saveutil.c revision 2bc08f26
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    fcntl(fileno(f), F_SETFD, FD_CLOEXEC);
76    if (verbose)
77	printf("Reading session save file...\n");
78
79    buf = NULL;
80    buflen = 0;
81
82    /* Read version # */
83    getnextline(&buf, &buflen, f);
84    if((p = strchr(buf, '\n'))) *p = '\0';
85    version_number = atoi (buf);
86    if (version_number > SAVEFILE_VERSION)
87    {
88	if (verbose)
89	    printf("Unsupported version number of session save file.\n");
90	*sm_id = NULL;
91	if (buf)
92	    free (buf);
93	return 0;
94    }
95
96    /* Read SM's id */
97    getnextline(&buf, &buflen, f);
98    if((p = strchr(buf, '\n'))) *p = '\0';
99    *sm_id = XtNewString(buf);
100
101    /* Read number of clients running in the last session */
102    if (version_number >= 2)
103    {
104	getnextline(&buf, &buflen, f);
105	if((p = strchr(buf, '\n'))) *p = '\0';
106	num_clients_in_last_session = atoi (buf);
107    }
108
109    state = 0;
110    while(getnextline(&buf, &buflen, f)) {
111	if((p = strchr(buf, '\n'))) *p = '\0';
112	for(p = buf; *p && isspace(*p); p++) /* LOOP */;
113	if(*p == '#') continue;
114
115	if(!*p)
116	{
117	    if (version_number >= 3 &&
118		ListCount (PendingList) == num_clients_in_last_session)
119	    {
120		state = 5;
121		break;
122	    }
123	    else
124	    {
125		state = 0;
126		continue;
127	    }
128	}
129
130	if(!isspace(buf[0])) {
131	    switch(state) {
132		case 0:
133		    c = (PendingClient *)XtMalloc(sizeof *c);
134		    if(!c) nomem();
135
136		    c->clientId = XtNewString(p);
137		    c->clientHostname = NULL;  /* set in next state */
138
139		    c->props = ListInit();
140		    if(!c->props) nomem();
141
142		    if(!ListAddLast(PendingList, (char *)c)) nomem();
143
144		    state = 1;
145		    break;
146
147		case 1:
148		    c->clientHostname = XtNewString(p);
149                    state = 2;
150                    break;
151
152		case 2:
153		case 4:
154		    prop = (Prop *)XtMalloc(sizeof *prop);
155		    if(!prop) nomem();
156
157		    prop->name = XtNewString(p);
158		    prop->values = ListInit();
159		    if(!prop->values) nomem();
160
161		    prop->type = NULL;
162
163		    if(!ListAddLast(c->props, (char *)prop)) nomem();
164
165		    state = 3;
166		    break;
167
168		case 3:
169		    prop->type = XtNewString(p);
170		    state = 4;
171		    break;
172
173		default:
174		    fprintf(stderr, "state %d\n", state);
175		    fprintf(stderr,
176			    "Corrupt save file line ignored:\n%s\n", buf);
177		    continue;
178	    }
179	} else {
180	    if (state != 4) {
181		fprintf(stderr, "Corrupt save file line ignored:\n%s\n", buf);
182		continue;
183	    }
184	    val = (PropValue *)XtMalloc(sizeof *val);
185	    if(!val) nomem();
186
187	    if (strcmp (prop->type, SmCARD8) == 0)
188	    {
189		val->length = 1;
190		val->value = (XtPointer) XtMalloc (1);
191		*((char *)(val->value)) = atoi (p);
192	    }
193	    else
194	    {
195		val->length = strlen(p);
196		val->value = XtNewString(p);
197	    }
198
199	    if(!ListAddLast(prop->values, (char *)val)) nomem();
200	}
201    }
202
203    /* Read commands for non-session aware clients */
204
205    if (state == 5)
206    {
207	String strbuf;
208	int bufsize = 0;
209
210	getnextline(&buf, &buflen, f);
211	if((p = strchr(buf, '\n'))) *p = '\0';
212	non_session_aware_count = atoi (buf);
213
214	if (non_session_aware_count > 0)
215	{
216	    non_session_aware_clients = (char **) malloc (
217	        non_session_aware_count * sizeof (char *));
218
219	    for (i = 0; i < non_session_aware_count; i++)
220	    {
221		getnextline(&buf, &buflen, f);
222		if((p = strchr(buf, '\n'))) *p = '\0';
223		non_session_aware_clients[i] = (char *) malloc (
224		    strlen (buf) + 2);
225		strcpy (non_session_aware_clients[i], buf);
226		bufsize += (strlen (buf) + 1);
227	    }
228
229	    strbuf = (String) malloc (bufsize + 1);
230	    strbuf[0] = '\0';
231
232	    for (i = 0; i < non_session_aware_count; i++)
233	    {
234		strcat (strbuf, non_session_aware_clients[i]);
235		strcat (strbuf, "\n");
236	    }
237
238	    XtVaSetValues (manualRestartCommands,
239	        XtNstring, strbuf,
240	        NULL);
241
242	    free ((char *) strbuf);
243	}
244    }
245
246    fclose(f);
247
248    if (buf)
249	free (buf);
250
251    return 1;
252}
253
254
255
256static void
257SaveClient(FILE *f, ClientRec *client)
258{
259    List *pl;
260
261    fprintf (f, "%s\n", client->clientId);
262    fprintf (f, "%s\n", client->clientHostname);
263
264    for (pl = ListFirst (client->props); pl; pl = ListNext (pl))
265    {
266	Prop *pprop = (Prop *) pl->thing;
267	List *pj, *vl;
268	PropValue *pval;
269
270	fprintf (f, "%s\n", pprop->name);
271	fprintf (f, "%s\n", pprop->type);
272
273	if (strcmp (pprop->type, SmCARD8) == 0)
274	{
275	    char *card8;
276	    int value;
277
278	    vl = ListFirst (pprop->values);
279	    pval = (PropValue *) vl->thing;
280
281	    card8 = pval->value;
282	    value = *card8;
283	    fprintf(f, "\t%d\n", value);
284	}
285	else
286	{
287	    for (pj = ListFirst (pprop->values); pj; pj = ListNext (pj))
288	    {
289		pval = (PropValue *) pj->thing;
290		fprintf (f, "\t%s\n", (char *)pval->value);
291	    }
292	}
293    }
294
295    fprintf (f, "\n");
296}
297
298
299
300void
301WriteSave(const char *sm_id)
302{
303    ClientRec *client;
304    FILE *f;
305    List *cl;
306    String commands;
307    char *p, *c;
308    int count;
309
310    f = fopen (session_save_file, "w");
311
312    if (!f)
313    {
314	char msg[256];
315
316	snprintf (msg, sizeof(msg), "%s: Error creating session save file %s",
317		  Argv[0], session_save_file);
318	add_log_text (msg);
319	perror (msg);
320    }
321    else
322    {
323	fcntl(fileno(f), F_SETFD, FD_CLOEXEC);
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(const char *session_name)
411{
412    char	*buf;
413    int		buflen;
414    char	*p;
415    const char	*dir;
416    FILE	*f;
417    int		state;
418    int		foundDiscard;
419    char	filename[256];
420    int		version_number;
421
422    dir = getenv ("SM_SAVE_DIR");
423    if (!dir)
424    {
425	dir = getenv ("HOME");
426	if (!dir)
427	    dir = ".";
428    }
429
430    snprintf (filename, sizeof(filename), "%s/.XSM-%s", dir, session_name);
431
432    f = fopen(filename, "r");
433    if(!f) {
434	return (0);
435    }
436    fcntl(fileno(f), F_SETFD, FD_CLOEXEC);
437
438    buf = NULL;
439    buflen = 0;
440
441    /* Read version # */
442    getnextline(&buf, &buflen, f);
443    if((p = strchr(buf, '\n'))) *p = '\0';
444    version_number = atoi (buf);
445    if (version_number > SAVEFILE_VERSION)
446    {
447	if (verbose)
448	    printf("Can't delete session save file - incompatible version.\n");
449	if (buf)
450	    free (buf);
451	return (0);
452    }
453
454    /* Skip SM's id */
455    getnextline(&buf, &buflen, f);
456
457    /* Skip number of clients running in the last session */
458    if (version_number >= 2)
459	getnextline(&buf, &buflen, f);
460
461    state = 0;
462    foundDiscard = 0;
463    while(getnextline(&buf, &buflen, f)) {
464	if((p = strchr(buf, '\n'))) *p = '\0';
465	for(p = buf; *p && isspace(*p); p++) /* LOOP */;
466	if(*p == '#') continue;
467
468	if(!*p) {
469	    state = 0;
470	    foundDiscard = 0;
471	    continue;
472	}
473
474	if(!isspace(buf[0])) {
475	    switch(state) {
476		case 0:
477		    state = 1;
478		    break;
479
480		case 1:
481                    state = 2;
482                    break;
483
484		case 2:
485		case 4:
486		    if (strcmp (p, SmDiscardCommand) == 0)
487			foundDiscard = 1;
488		    state = 3;
489		    break;
490
491		case 3:
492		    state = 4;
493		    break;
494
495		default:
496		    continue;
497	    }
498	} else {
499	    if (state != 4) {
500		continue;
501	    }
502	    if (foundDiscard)
503	    {
504		execute_system_command (p);	/* Discard Command */
505		foundDiscard = 0;
506	    }
507	}
508    }
509
510    fclose(f);
511
512    if (buf)
513	free (buf);
514
515    return ((remove (filename) == -1) ? 0 : 1);
516}
517
518
519
520Bool
521getnextline(char **pbuf, int *plen, FILE *f)
522{
523	int c;
524	int i;
525
526	i = 0;
527	while(1) {
528	    if(i+2 > *plen) {
529		if(*plen) *plen *= 2;
530		else *plen = BUFSIZ;
531		if(*pbuf) *pbuf = (char *) realloc(*pbuf, *plen + 1);
532		else *pbuf = (char *) malloc(*plen + 1);
533	    }
534	    c = getc(f);
535	    if(c == EOF) break;
536	    (*pbuf)[i++] = c;
537	    if(c == '\n') break;
538	}
539	(*pbuf)[i] = '\0';
540	return i;
541}
542