saveutil.c revision 5977a007
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(const char *session_name)
38{
39    const char *p;
40
41    p = getenv ("SM_SAVE_DIR");
42    if (!p)
43    {
44	p = 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(const 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(const 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(const char *session_name)
409{
410    char	*buf;
411    int		buflen;
412    char	*p;
413    const char	*dir;
414    FILE	*f;
415    int		state;
416    int		foundDiscard;
417    char	filename[256];
418    int		version_number;
419
420    dir = getenv ("SM_SAVE_DIR");
421    if (!dir)
422    {
423	dir = getenv ("HOME");
424	if (!dir)
425	    dir = ".";
426    }
427
428    snprintf (filename, sizeof(filename), "%s/.XSM-%s", dir, session_name);
429
430    f = fopen(filename, "r");
431    if(!f) {
432	return (0);
433    }
434
435    buf = NULL;
436    buflen = 0;
437
438    /* Read version # */
439    getnextline(&buf, &buflen, f);
440    if((p = strchr(buf, '\n'))) *p = '\0';
441    version_number = atoi (buf);
442    if (version_number > SAVEFILE_VERSION)
443    {
444	if (verbose)
445	    printf("Can't delete session save file - incompatible version.\n");
446	if (buf)
447	    free (buf);
448	return (0);
449    }
450
451    /* Skip SM's id */
452    getnextline(&buf, &buflen, f);
453
454    /* Skip number of clients running in the last session */
455    if (version_number >= 2)
456	getnextline(&buf, &buflen, f);
457
458    state = 0;
459    foundDiscard = 0;
460    while(getnextline(&buf, &buflen, f)) {
461	if((p = strchr(buf, '\n'))) *p = '\0';
462	for(p = buf; *p && isspace(*p); p++) /* LOOP */;
463	if(*p == '#') continue;
464
465	if(!*p) {
466	    state = 0;
467	    foundDiscard = 0;
468	    continue;
469	}
470
471	if(!isspace(buf[0])) {
472	    switch(state) {
473		case 0:
474		    state = 1;
475		    break;
476
477		case 1:
478                    state = 2;
479                    break;
480
481		case 2:
482		case 4:
483		    if (strcmp (p, SmDiscardCommand) == 0)
484			foundDiscard = 1;
485		    state = 3;
486		    break;
487
488		case 3:
489		    state = 4;
490		    break;
491
492		default:
493		    continue;
494	    }
495	} else {
496	    if (state != 4) {
497		continue;
498	    }
499	    if (foundDiscard)
500	    {
501		execute_system_command (p);	/* Discard Command */
502		foundDiscard = 0;
503	    }
504	}
505    }
506
507    fclose(f);
508
509    if (buf)
510	free (buf);
511
512    return ((remove (filename) == -1) ? 0 : 1);
513}
514
515
516
517Bool
518getnextline(char **pbuf, int *plen, FILE *f)
519{
520	int c;
521	int i;
522
523	i = 0;
524	while(1) {
525	    if(i+2 > *plen) {
526		if(*plen) *plen *= 2;
527		else *plen = BUFSIZ;
528		if(*pbuf) *pbuf = (char *) realloc(*pbuf, *plen + 1);
529		else *pbuf = (char *) malloc(*plen + 1);
530	    }
531	    c = getc(f);
532	    if(c == EOF) break;
533	    (*pbuf)[i++] = c;
534	    if(c == '\n') break;
535	}
536	(*pbuf)[i] = '\0';
537	return i;
538}
539