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