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