saveutil.c revision 5977a007
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 if (verbose) 76 printf("Reading session save file...\n"); 77 78 buf = NULL; 79 buflen = 0; 80 81 /* Read version # */ 82 getnextline(&buf, &buflen, f); 83 if((p = strchr(buf, '\n'))) *p = '\0'; 84 version_number = atoi (buf); 85 if (version_number > SAVEFILE_VERSION) 86 { 87 if (verbose) 88 printf("Unsupported version number of session save file.\n"); 89 *sm_id = NULL; 90 if (buf) 91 free (buf); 92 return 0; 93 } 94 95 /* Read SM's id */ 96 getnextline(&buf, &buflen, f); 97 if((p = strchr(buf, '\n'))) *p = '\0'; 98 *sm_id = XtNewString(buf); 99 100 /* Read number of clients running in the last session */ 101 if (version_number >= 2) 102 { 103 getnextline(&buf, &buflen, f); 104 if((p = strchr(buf, '\n'))) *p = '\0'; 105 num_clients_in_last_session = atoi (buf); 106 } 107 108 state = 0; 109 while(getnextline(&buf, &buflen, f)) { 110 if((p = strchr(buf, '\n'))) *p = '\0'; 111 for(p = buf; *p && isspace(*p); p++) /* LOOP */; 112 if(*p == '#') continue; 113 114 if(!*p) 115 { 116 if (version_number >= 3 && 117 ListCount (PendingList) == num_clients_in_last_session) 118 { 119 state = 5; 120 break; 121 } 122 else 123 { 124 state = 0; 125 continue; 126 } 127 } 128 129 if(!isspace(buf[0])) { 130 switch(state) { 131 case 0: 132 c = (PendingClient *)XtMalloc(sizeof *c); 133 if(!c) nomem(); 134 135 c->clientId = XtNewString(p); 136 c->clientHostname = NULL; /* set in next state */ 137 138 c->props = ListInit(); 139 if(!c->props) nomem(); 140 141 if(!ListAddLast(PendingList, (char *)c)) nomem(); 142 143 state = 1; 144 break; 145 146 case 1: 147 c->clientHostname = XtNewString(p); 148 state = 2; 149 break; 150 151 case 2: 152 case 4: 153 prop = (Prop *)XtMalloc(sizeof *prop); 154 if(!prop) nomem(); 155 156 prop->name = XtNewString(p); 157 prop->values = ListInit(); 158 if(!prop->values) nomem(); 159 160 prop->type = NULL; 161 162 if(!ListAddLast(c->props, (char *)prop)) nomem(); 163 164 state = 3; 165 break; 166 167 case 3: 168 prop->type = XtNewString(p); 169 state = 4; 170 break; 171 172 default: 173 fprintf(stderr, "state %d\n", state); 174 fprintf(stderr, 175 "Corrupt save file line ignored:\n%s\n", buf); 176 continue; 177 } 178 } else { 179 if (state != 4) { 180 fprintf(stderr, "Corrupt save file line ignored:\n%s\n", buf); 181 continue; 182 } 183 val = (PropValue *)XtMalloc(sizeof *val); 184 if(!val) nomem(); 185 186 if (strcmp (prop->type, SmCARD8) == 0) 187 { 188 val->length = 1; 189 val->value = (XtPointer) XtMalloc (1); 190 *((char *)(val->value)) = atoi (p); 191 } 192 else 193 { 194 val->length = strlen(p); 195 val->value = XtNewString(p); 196 } 197 198 if(!ListAddLast(prop->values, (char *)val)) nomem(); 199 } 200 } 201 202 /* Read commands for non-session aware clients */ 203 204 if (state == 5) 205 { 206 String strbuf; 207 int bufsize = 0; 208 209 getnextline(&buf, &buflen, f); 210 if((p = strchr(buf, '\n'))) *p = '\0'; 211 non_session_aware_count = atoi (buf); 212 213 if (non_session_aware_count > 0) 214 { 215 non_session_aware_clients = (char **) malloc ( 216 non_session_aware_count * sizeof (char *)); 217 218 for (i = 0; i < non_session_aware_count; i++) 219 { 220 getnextline(&buf, &buflen, f); 221 if((p = strchr(buf, '\n'))) *p = '\0'; 222 non_session_aware_clients[i] = (char *) malloc ( 223 strlen (buf) + 2); 224 strcpy (non_session_aware_clients[i], buf); 225 bufsize += (strlen (buf) + 1); 226 } 227 228 strbuf = (String) 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 String commands; 306 char *p, *c; 307 int count; 308 309 f = fopen (session_save_file, "w"); 310 311 if (!f) 312 { 313 char msg[256]; 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 fprintf (f, "%d\n", SAVEFILE_VERSION); 323 fprintf (f, "%s\n", sm_id); 324 325 count = 0; 326 for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) 327 { 328 client = (ClientRec *) cl->thing; 329 330 if (client->restartHint != SmRestartNever) 331 count++; 332 } 333 count += ListCount (RestartAnywayList); 334 335 fprintf (f, "%d\n", count); 336 if (count == 0) 337 fprintf (f, "\n"); 338 339 for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) 340 { 341 client = (ClientRec *) cl->thing; 342 343 if (client->restartHint == SmRestartNever) 344 continue; 345 346 SaveClient (f, client); 347 } 348 349 for (cl = ListFirst (RestartAnywayList); cl; cl = ListNext (cl)) 350 { 351 client = (ClientRec *) cl->thing; 352 353 SaveClient (f, client); 354 } 355 356 357 /* Save the non-session aware clients */ 358 359 XtVaGetValues (manualRestartCommands, 360 XtNstring, &commands, 361 NULL); 362 363 p = c = commands; 364 count = 0; 365 366 while (*p) 367 { 368 if (*p == '\n') 369 { 370 if (p != c) 371 count++; 372 c = p + 1; 373 } 374 p++; 375 } 376 if (p != c) 377 count++; 378 379 fprintf (f, "%d\n", count); 380 381 p = c = commands; 382 383 while (*p) 384 { 385 if (*p == '\n') 386 { 387 if (p != c) 388 { 389 *p = '\0'; 390 fprintf (f, "%s\n", c); 391 *p = '\n'; 392 } 393 c = p + 1; 394 } 395 p++; 396 } 397 398 if (p != c) 399 fprintf (f, "%s\n", c); 400 401 fclose (f); 402 } 403} 404 405 406 407Status 408DeleteSession(const char *session_name) 409{ 410 char *buf; 411 int buflen; 412 char *p; 413 const char *dir; 414 FILE *f; 415 int state; 416 int foundDiscard; 417 char filename[256]; 418 int version_number; 419 420 dir = getenv ("SM_SAVE_DIR"); 421 if (!dir) 422 { 423 dir = getenv ("HOME"); 424 if (!dir) 425 dir = "."; 426 } 427 428 snprintf (filename, sizeof(filename), "%s/.XSM-%s", dir, session_name); 429 430 f = fopen(filename, "r"); 431 if(!f) { 432 return (0); 433 } 434 435 buf = NULL; 436 buflen = 0; 437 438 /* Read version # */ 439 getnextline(&buf, &buflen, f); 440 if((p = strchr(buf, '\n'))) *p = '\0'; 441 version_number = atoi (buf); 442 if (version_number > SAVEFILE_VERSION) 443 { 444 if (verbose) 445 printf("Can't delete session save file - incompatible version.\n"); 446 if (buf) 447 free (buf); 448 return (0); 449 } 450 451 /* Skip SM's id */ 452 getnextline(&buf, &buflen, f); 453 454 /* Skip number of clients running in the last session */ 455 if (version_number >= 2) 456 getnextline(&buf, &buflen, f); 457 458 state = 0; 459 foundDiscard = 0; 460 while(getnextline(&buf, &buflen, f)) { 461 if((p = strchr(buf, '\n'))) *p = '\0'; 462 for(p = buf; *p && isspace(*p); p++) /* LOOP */; 463 if(*p == '#') continue; 464 465 if(!*p) { 466 state = 0; 467 foundDiscard = 0; 468 continue; 469 } 470 471 if(!isspace(buf[0])) { 472 switch(state) { 473 case 0: 474 state = 1; 475 break; 476 477 case 1: 478 state = 2; 479 break; 480 481 case 2: 482 case 4: 483 if (strcmp (p, SmDiscardCommand) == 0) 484 foundDiscard = 1; 485 state = 3; 486 break; 487 488 case 3: 489 state = 4; 490 break; 491 492 default: 493 continue; 494 } 495 } else { 496 if (state != 4) { 497 continue; 498 } 499 if (foundDiscard) 500 { 501 execute_system_command (p); /* Discard Command */ 502 foundDiscard = 0; 503 } 504 } 505 } 506 507 fclose(f); 508 509 if (buf) 510 free (buf); 511 512 return ((remove (filename) == -1) ? 0 : 1); 513} 514 515 516 517Bool 518getnextline(char **pbuf, int *plen, FILE *f) 519{ 520 int c; 521 int i; 522 523 i = 0; 524 while(1) { 525 if(i+2 > *plen) { 526 if(*plen) *plen *= 2; 527 else *plen = BUFSIZ; 528 if(*pbuf) *pbuf = (char *) realloc(*pbuf, *plen + 1); 529 else *pbuf = (char *) malloc(*plen + 1); 530 } 531 c = getc(f); 532 if(c == EOF) break; 533 (*pbuf)[i++] = c; 534 if(c == '\n') break; 535 } 536 (*pbuf)[i] = '\0'; 537 return i; 538} 539