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