saveutil.c revision 1a650d1e
1/* $Xorg: saveutil.c,v 1.5 2001/02/09 02:06:01 xorgcvs Exp $ */
2/******************************************************************************
3
4Copyright 1993, 1998  The Open Group
5
6Permission to use, copy, modify, distribute, and sell this software and its
7documentation for any purpose is hereby granted without fee, provided that
8the above copyright notice appear in all copies and that both that
9copyright notice and this permission notice appear in supporting
10documentation.
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall not be
23used in advertising or otherwise to promote the sale, use or other dealings
24in this Software without prior written authorization from The Open Group.
25******************************************************************************/
26/* $XFree86: xc/programs/xsm/saveutil.c,v 1.5 2001/01/17 23:46:31 dawes Exp $ */
27
28#include "xsm.h"
29#include "log.h"
30#include "saveutil.h"
31#include "info.h"
32
33static char 		 session_save_file[PATH_MAX];
34
35
36void
37set_session_save_file_name(char *session_name)
38{
39    char *p;
40
41    p = (char *) getenv ("SM_SAVE_DIR");
42    if (!p)
43    {
44	p = (char *) getenv ("HOME");
45	if (!p)
46	    p = ".";
47    }
48
49    snprintf (session_save_file, sizeof(session_save_file),
50	      "%s/.XSM-%s", p, session_name);
51}
52
53
54
55int
56ReadSave(char *session_name, char **sm_id)
57{
58    char		*buf;
59    int			buflen;
60    char		*p;
61    PendingClient	*c = NULL;
62    Prop		*prop = NULL;
63    PropValue		*val;
64    FILE		*f;
65    int			state, i;
66    int			version_number;
67
68    f = fopen(session_save_file, "r");
69    if(!f) {
70	if (verbose)
71	    printf("No session save file.\n");
72	*sm_id = NULL;
73	return 0;
74    }
75    if (verbose)
76	printf("Reading session save file...\n");
77
78    buf = NULL;
79    buflen = 0;
80
81    /* Read version # */
82    getnextline(&buf, &buflen, f);
83    if((p = strchr(buf, '\n'))) *p = '\0';
84    version_number = atoi (buf);
85    if (version_number > SAVEFILE_VERSION)
86    {
87	if (verbose)
88	    printf("Unsupported version number of session save file.\n");
89	*sm_id = NULL;
90	if (buf)
91	    free (buf);
92	return 0;
93    }
94
95    /* Read SM's id */
96    getnextline(&buf, &buflen, f);
97    if((p = strchr(buf, '\n'))) *p = '\0';
98    *sm_id = XtNewString(buf);
99
100    /* Read number of clients running in the last session */
101    if (version_number >= 2)
102    {
103	getnextline(&buf, &buflen, f);
104	if((p = strchr(buf, '\n'))) *p = '\0';
105	num_clients_in_last_session = atoi (buf);
106    }
107
108    state = 0;
109    while(getnextline(&buf, &buflen, f)) {
110	if((p = strchr(buf, '\n'))) *p = '\0';
111	for(p = buf; *p && isspace(*p); p++) /* LOOP */;
112	if(*p == '#') continue;
113
114	if(!*p)
115	{
116	    if (version_number >= 3 &&
117		ListCount (PendingList) == num_clients_in_last_session)
118	    {
119		state = 5;
120		break;
121	    }
122	    else
123	    {
124		state = 0;
125		continue;
126	    }
127	}
128
129	if(!isspace(buf[0])) {
130	    switch(state) {
131		case 0:
132		    c = (PendingClient *)XtMalloc(sizeof *c);
133		    if(!c) nomem();
134
135		    c->clientId = XtNewString(p);
136		    c->clientHostname = NULL;  /* set in next state */
137
138		    c->props = ListInit();
139		    if(!c->props) nomem();
140
141		    if(!ListAddLast(PendingList, (char *)c)) nomem();
142
143		    state = 1;
144		    break;
145
146		case 1:
147		    c->clientHostname = XtNewString(p);
148                    state = 2;
149                    break;
150
151		case 2:
152		case 4:
153		    prop = (Prop *)XtMalloc(sizeof *prop);
154		    if(!prop) nomem();
155
156		    prop->name = XtNewString(p);
157		    prop->values = ListInit();
158		    if(!prop->values) nomem();
159
160		    prop->type = NULL;
161
162		    if(!ListAddLast(c->props, (char *)prop)) nomem();
163
164		    state = 3;
165		    break;
166
167		case 3:
168		    prop->type = XtNewString(p);
169		    state = 4;
170		    break;
171
172		default:
173		    fprintf(stderr, "state %d\n", state);
174		    fprintf(stderr,
175			    "Corrupt save file line ignored:\n%s\n", buf);
176		    continue;
177	    }
178	} else {
179	    if (state != 4) {
180		fprintf(stderr, "Corrupt save file line ignored:\n%s\n", buf);
181		continue;
182	    }
183	    val = (PropValue *)XtMalloc(sizeof *val);
184	    if(!val) nomem();
185
186	    if (strcmp (prop->type, SmCARD8) == 0)
187	    {
188		val->length = 1;
189		val->value = (XtPointer) XtMalloc (1);
190		*((char *)(val->value)) = atoi (p);
191	    }
192	    else
193	    {
194		val->length = strlen(p);
195		val->value = XtNewString(p);
196	    }
197
198	    if(!ListAddLast(prop->values, (char *)val)) nomem();
199	}
200    }
201
202    /* Read commands for non-session aware clients */
203
204    if (state == 5)
205    {
206	String strbuf;
207	int bufsize = 0;
208
209	getnextline(&buf, &buflen, f);
210	if((p = strchr(buf, '\n'))) *p = '\0';
211	non_session_aware_count = atoi (buf);
212
213	if (non_session_aware_count > 0)
214	{
215	    non_session_aware_clients = (char **) malloc (
216	        non_session_aware_count * sizeof (char *));
217
218	    for (i = 0; i < non_session_aware_count; i++)
219	    {
220		getnextline(&buf, &buflen, f);
221		if((p = strchr(buf, '\n'))) *p = '\0';
222		non_session_aware_clients[i] = (char *) malloc (
223		    strlen (buf) + 2);
224		strcpy (non_session_aware_clients[i], buf);
225		bufsize += (strlen (buf) + 1);
226	    }
227
228	    strbuf = (String) malloc (bufsize + 1);
229	    strbuf[0] = '\0';
230
231	    for (i = 0; i < non_session_aware_count; i++)
232	    {
233		strcat (strbuf, non_session_aware_clients[i]);
234		strcat (strbuf, "\n");
235	    }
236
237	    XtVaSetValues (manualRestartCommands,
238	        XtNstring, strbuf,
239	        NULL);
240
241	    free ((char *) strbuf);
242	}
243    }
244
245    fclose(f);
246
247    if (buf)
248	free (buf);
249
250    return 1;
251}
252
253
254
255static void
256SaveClient(FILE *f, ClientRec *client)
257{
258    List *pl;
259
260    fprintf (f, "%s\n", client->clientId);
261    fprintf (f, "%s\n", client->clientHostname);
262
263    for (pl = ListFirst (client->props); pl; pl = ListNext (pl))
264    {
265	Prop *pprop = (Prop *) pl->thing;
266	List *pj, *vl;
267	PropValue *pval;
268
269	fprintf (f, "%s\n", pprop->name);
270	fprintf (f, "%s\n", pprop->type);
271
272	if (strcmp (pprop->type, SmCARD8) == 0)
273	{
274	    char *card8;
275	    int value;
276
277	    vl = ListFirst (pprop->values);
278	    pval = (PropValue *) vl->thing;
279
280	    card8 = pval->value;
281	    value = *card8;
282	    fprintf(f, "\t%d\n", value);
283	}
284	else
285	{
286	    for (pj = ListFirst (pprop->values); pj; pj = ListNext (pj))
287	    {
288		pval = (PropValue *) pj->thing;
289		fprintf (f, "\t%s\n", (char *)pval->value);
290	    }
291	}
292    }
293
294    fprintf (f, "\n");
295}
296
297
298
299void
300WriteSave(char *sm_id)
301{
302    ClientRec *client;
303    FILE *f;
304    List *cl;
305    String commands;
306    char *p, *c;
307    int count;
308
309    f = fopen (session_save_file, "w");
310
311    if (!f)
312    {
313	char msg[256];
314
315	snprintf (msg, sizeof(msg), "%s: Error creating session save file %s",
316		  Argv[0], session_save_file);
317	add_log_text (msg);
318	perror (msg);
319    }
320    else
321    {
322	fprintf (f, "%d\n", SAVEFILE_VERSION);
323	fprintf (f, "%s\n", sm_id);
324
325	count = 0;
326	for (cl = ListFirst (RunningList); cl; cl = ListNext (cl))
327	{
328	    client = (ClientRec *) cl->thing;
329
330	    if (client->restartHint != SmRestartNever)
331		count++;
332	}
333	count += ListCount (RestartAnywayList);
334
335	fprintf (f, "%d\n", count);
336	if (count == 0)
337	    fprintf (f, "\n");
338
339	for (cl = ListFirst (RunningList); cl; cl = ListNext (cl))
340	{
341	    client = (ClientRec *) cl->thing;
342
343	    if (client->restartHint == SmRestartNever)
344		continue;
345
346	    SaveClient (f, client);
347	}
348
349	for (cl = ListFirst (RestartAnywayList); cl; cl = ListNext (cl))
350	{
351	    client = (ClientRec *) cl->thing;
352
353	    SaveClient (f, client);
354	}
355
356
357	/* Save the non-session aware clients */
358
359	XtVaGetValues (manualRestartCommands,
360	    XtNstring, &commands,
361	    NULL);
362
363	p = c = commands;
364	count = 0;
365
366	while (*p)
367	{
368	    if (*p == '\n')
369	    {
370		if (p != c)
371		    count++;
372		c = p + 1;
373	    }
374	    p++;
375	}
376	if (p != c)
377	    count++;
378
379	fprintf (f, "%d\n", count);
380
381	p = c = commands;
382
383	while (*p)
384	{
385	    if (*p == '\n')
386	    {
387		if (p != c)
388		{
389		    *p = '\0';
390		    fprintf (f, "%s\n", c);
391		    *p = '\n';
392		}
393		c = p + 1;
394	    }
395	    p++;
396	}
397
398	if (p != c)
399	    fprintf (f, "%s\n", c);
400
401	fclose (f);
402    }
403}
404
405
406
407Status
408DeleteSession(char *session_name)
409{
410    char	*buf;
411    int		buflen;
412    char	*p, *dir;
413    FILE	*f;
414    int		state;
415    int		foundDiscard;
416    char	filename[256];
417    int		version_number;
418
419    dir = (char *) getenv ("SM_SAVE_DIR");
420    if (!dir)
421    {
422	dir = (char *) getenv ("HOME");
423	if (!dir)
424	    dir = ".";
425    }
426
427    snprintf (filename, sizeof(filename), "%s/.XSM-%s", dir, session_name);
428
429    f = fopen(filename, "r");
430    if(!f) {
431	return (0);
432    }
433
434    buf = NULL;
435    buflen = 0;
436
437    /* Read version # */
438    getnextline(&buf, &buflen, f);
439    if((p = strchr(buf, '\n'))) *p = '\0';
440    version_number = atoi (buf);
441    if (version_number > SAVEFILE_VERSION)
442    {
443	if (verbose)
444	    printf("Can't delete session save file - incompatible version.\n");
445	if (buf)
446	    free (buf);
447	return (0);
448    }
449
450    /* Skip SM's id */
451    getnextline(&buf, &buflen, f);
452
453    /* Skip number of clients running in the last session */
454    if (version_number >= 2)
455	getnextline(&buf, &buflen, f);
456
457    state = 0;
458    foundDiscard = 0;
459    while(getnextline(&buf, &buflen, f)) {
460	if((p = strchr(buf, '\n'))) *p = '\0';
461	for(p = buf; *p && isspace(*p); p++) /* LOOP */;
462	if(*p == '#') continue;
463
464	if(!*p) {
465	    state = 0;
466	    foundDiscard = 0;
467	    continue;
468	}
469
470	if(!isspace(buf[0])) {
471	    switch(state) {
472		case 0:
473		    state = 1;
474		    break;
475
476		case 1:
477                    state = 2;
478                    break;
479
480		case 2:
481		case 4:
482		    if (strcmp (p, SmDiscardCommand) == 0)
483			foundDiscard = 1;
484		    state = 3;
485		    break;
486
487		case 3:
488		    state = 4;
489		    break;
490
491		default:
492		    continue;
493	    }
494	} else {
495	    if (state != 4) {
496		continue;
497	    }
498	    if (foundDiscard)
499	    {
500		execute_system_command (p);	/* Discard Command */
501		foundDiscard = 0;
502	    }
503	}
504    }
505
506    fclose(f);
507
508    if (buf)
509	free (buf);
510
511    return ((remove (filename) == -1) ? 0 : 1);
512}
513
514
515
516Bool
517getnextline(char **pbuf, int *plen, FILE *f)
518{
519	int c;
520	int i;
521
522	i = 0;
523	while(1) {
524	    if(i+2 > *plen) {
525		if(*plen) *plen *= 2;
526		else *plen = BUFSIZ;
527		if(*pbuf) *pbuf = (char *) realloc(*pbuf, *plen + 1);
528		else *pbuf = (char *) malloc(*plen + 1);
529	    }
530	    c = getc(f);
531	    if(c == EOF) break;
532	    (*pbuf)[i++] = c;
533	    if(c == '\n') break;
534	}
535	(*pbuf)[i] = '\0';
536	return i;
537}
538