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 char *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] = malloc (strlen (buf) + 2); 224 strcpy (non_session_aware_clients[i], buf); 225 bufsize += (strlen (buf) + 1); 226 } 227 228 strbuf = 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 char *commands; 306 char *p, *c; 307 int count; 308 309 f = fopen (session_save_file, "w"); 310 311 if (!f) 312 { 313 char msg[36 + sizeof(session_save_file)]; 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 fcntl(fileno(f), F_SETFD, FD_CLOEXEC); 323 fprintf (f, "%d\n", SAVEFILE_VERSION); 324 fprintf (f, "%s\n", sm_id); 325 326 count = 0; 327 for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) 328 { 329 client = (ClientRec *) cl->thing; 330 331 if (client->restartHint != SmRestartNever) 332 count++; 333 } 334 count += ListCount (RestartAnywayList); 335 336 fprintf (f, "%d\n", count); 337 if (count == 0) 338 fprintf (f, "\n"); 339 340 for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) 341 { 342 client = (ClientRec *) cl->thing; 343 344 if (client->restartHint == SmRestartNever) 345 continue; 346 347 SaveClient (f, client); 348 } 349 350 for (cl = ListFirst (RestartAnywayList); cl; cl = ListNext (cl)) 351 { 352 client = (ClientRec *) cl->thing; 353 354 SaveClient (f, client); 355 } 356 357 358 /* Save the non-session aware clients */ 359 360 XtVaGetValues (manualRestartCommands, 361 XtNstring, &commands, 362 NULL); 363 364 p = c = commands; 365 count = 0; 366 367 while (*p) 368 { 369 if (*p == '\n') 370 { 371 if (p != c) 372 count++; 373 c = p + 1; 374 } 375 p++; 376 } 377 if (p != c) 378 count++; 379 380 fprintf (f, "%d\n", count); 381 382 p = c = commands; 383 384 while (*p) 385 { 386 if (*p == '\n') 387 { 388 if (p != c) 389 { 390 *p = '\0'; 391 fprintf (f, "%s\n", c); 392 *p = '\n'; 393 } 394 c = p + 1; 395 } 396 p++; 397 } 398 399 if (p != c) 400 fprintf (f, "%s\n", c); 401 402 fclose (f); 403 } 404} 405 406 407 408Status 409DeleteSession(const char *session_name) 410{ 411 char *buf; 412 int buflen; 413 char *p; 414 const char *dir; 415 FILE *f; 416 int state; 417 int foundDiscard; 418 char filename[256]; 419 int version_number; 420 421 dir = getenv ("SM_SAVE_DIR"); 422 if (!dir) 423 { 424 dir = getenv ("HOME"); 425 if (!dir) 426 dir = "."; 427 } 428 429 snprintf (filename, sizeof(filename), "%s/.XSM-%s", dir, session_name); 430 431 f = fopen(filename, "r"); 432 if(!f) { 433 return (0); 434 } 435 fcntl(fileno(f), F_SETFD, FD_CLOEXEC); 436 437 buf = NULL; 438 buflen = 0; 439 440 /* Read version # */ 441 getnextline(&buf, &buflen, f); 442 if((p = strchr(buf, '\n'))) *p = '\0'; 443 version_number = atoi (buf); 444 if (version_number > SAVEFILE_VERSION) 445 { 446 if (verbose) 447 printf("Can't delete session save file - incompatible version.\n"); 448 if (buf) 449 free (buf); 450 return (0); 451 } 452 453 /* Skip SM's id */ 454 getnextline(&buf, &buflen, f); 455 456 /* Skip number of clients running in the last session */ 457 if (version_number >= 2) 458 getnextline(&buf, &buflen, f); 459 460 state = 0; 461 foundDiscard = 0; 462 while(getnextline(&buf, &buflen, f)) { 463 if((p = strchr(buf, '\n'))) *p = '\0'; 464 for(p = buf; *p && isspace(*p); p++) /* LOOP */; 465 if(*p == '#') continue; 466 467 if(!*p) { 468 state = 0; 469 foundDiscard = 0; 470 continue; 471 } 472 473 if(!isspace(buf[0])) { 474 switch(state) { 475 case 0: 476 state = 1; 477 break; 478 479 case 1: 480 state = 2; 481 break; 482 483 case 2: 484 case 4: 485 if (strcmp (p, SmDiscardCommand) == 0) 486 foundDiscard = 1; 487 state = 3; 488 break; 489 490 case 3: 491 state = 4; 492 break; 493 494 default: 495 continue; 496 } 497 } else { 498 if (state != 4) { 499 continue; 500 } 501 if (foundDiscard) 502 { 503 execute_system_command (p); /* Discard Command */ 504 foundDiscard = 0; 505 } 506 } 507 } 508 509 fclose(f); 510 511 if (buf) 512 free (buf); 513 514 return ((remove (filename) == -1) ? 0 : 1); 515} 516 517 518 519Bool 520getnextline(char **pbuf, int *plen, FILE *f) 521{ 522 int c; 523 int i; 524 525 i = 0; 526 while(1) { 527 if(i+2 > *plen) { 528 if(*plen) *plen *= 2; 529 else *plen = BUFSIZ; 530 if(*pbuf) *pbuf = (char *) realloc(*pbuf, *plen + 1); 531 else *pbuf = (char *) malloc(*plen + 1); 532 } 533 c = getc(f); 534 if(c == EOF) break; 535 (*pbuf)[i++] = c; 536 if(c == '\n') break; 537 } 538 (*pbuf)[i] = '\0'; 539 return i; 540} 541