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