save.c revision 14c0a534
1/* $Xorg: save.c,v 1.4 2001/02/09 02:05:35 xorgcvs Exp $ */ 2/****************************************************************************** 3 4Copyright 1994, 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 26Author: Ralph Mor, X Consortium 27******************************************************************************/ 28/* $XFree86: xc/programs/smproxy/save.c,v 1.7 2001/01/17 23:45:04 dawes Exp $ */ 29 30#include "smproxy.h" 31#ifdef HAS_MKSTEMP 32#include <unistd.h> 33#endif 34 35 36ProxyFileEntry *proxyFileHead = NULL; 37 38extern WinInfo *win_head; 39 40static int write_byte ( FILE *file, unsigned char b ); 41static int write_short ( FILE *file, unsigned short s ); 42static int write_counted_string ( FILE *file, char *string ); 43static int read_byte ( FILE *file, unsigned char *bp ); 44static int read_short ( FILE *file, unsigned short *shortp ); 45static int read_counted_string ( FILE *file, char **stringp ); 46#ifndef HAS_MKSTEMP 47static char * unique_filename ( char *path, char *prefix ); 48#else 49static char * unique_filename ( char *path, char *prefix, int *pFd ); 50#endif 51 52 53static int 54write_byte (FILE *file, unsigned char b) 55{ 56 if (fwrite ((char *) &b, 1, 1, file) != 1) 57 return 0; 58 return 1; 59} 60 61 62static int 63write_short (FILE *file, unsigned short s) 64{ 65 unsigned char file_short[2]; 66 67 file_short[0] = (s & (unsigned)0xff00) >> 8; 68 file_short[1] = s & 0xff; 69 if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1) 70 return 0; 71 return 1; 72} 73 74 75static int 76write_counted_string (file, string) 77 78FILE *file; 79char *string; 80 81{ 82 if (string) 83 { 84 unsigned char count = strlen (string); 85 86 if (write_byte (file, count) == 0) 87 return 0; 88 if (fwrite (string, (int) sizeof (char), (int) count, file) != count) 89 return 0; 90 } 91 else 92 { 93 if (write_byte (file, 0) == 0) 94 return 0; 95 } 96 97 return 1; 98} 99 100 101 102static int 103read_byte (file, bp) 104 105FILE *file; 106unsigned char *bp; 107 108{ 109 if (fread ((char *) bp, 1, 1, file) != 1) 110 return 0; 111 return 1; 112} 113 114 115static int 116read_short (file, shortp) 117 118FILE *file; 119unsigned short *shortp; 120 121{ 122 unsigned char file_short[2]; 123 124 if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1) 125 return 0; 126 *shortp = file_short[0] * 256 + file_short[1]; 127 return 1; 128} 129 130 131static int 132read_counted_string (file, stringp) 133 134FILE *file; 135char **stringp; 136 137{ 138 unsigned char len; 139 char *data; 140 141 if (read_byte (file, &len) == 0) 142 return 0; 143 if (len == 0) { 144 data = 0; 145 } else { 146 data = (char *) malloc ((unsigned) len + 1); 147 if (!data) 148 return 0; 149 if (fread (data, (int) sizeof (char), (int) len, file) != len) { 150 free (data); 151 return 0; 152 } 153 data[len] = '\0'; 154 } 155 *stringp = data; 156 return 1; 157} 158 159 160 161/* 162 * An entry in the .smproxy file looks like this: 163 * 164 * FIELD BYTES 165 * ----- ---- 166 * client ID len 1 167 * client ID LIST of bytes 168 * WM_CLASS "res name" length 1 169 * WM_CLASS "res name" LIST of bytes 170 * WM_CLASS "res class" length 1 171 * WM_CLASS "res class" LIST of bytes 172 * WM_NAME length 1 173 * WM_NAME LIST of bytes 174 * WM_COMMAND arg count 1 175 * For each arg in WM_COMMAND 176 * arg length 1 177 * arg LIST of bytes 178 */ 179 180int 181WriteProxyFileEntry (proxyFile, theWindow) 182 183FILE *proxyFile; 184WinInfo *theWindow; 185 186{ 187 int i; 188 189 if (!write_counted_string (proxyFile, theWindow->client_id)) 190 return 0; 191 if (!write_counted_string (proxyFile, theWindow->class.res_name)) 192 return 0; 193 if (!write_counted_string (proxyFile, theWindow->class.res_class)) 194 return 0; 195 if (!write_counted_string (proxyFile, theWindow->wm_name)) 196 return 0; 197 198 if (!theWindow->wm_command || theWindow->wm_command_count == 0) 199 { 200 if (!write_byte (proxyFile, 0)) 201 return 0; 202 } 203 else 204 { 205 if (!write_byte (proxyFile, (char) theWindow->wm_command_count)) 206 return 0; 207 for (i = 0; i < theWindow->wm_command_count; i++) 208 if (!write_counted_string (proxyFile, theWindow->wm_command[i])) 209 return 0; 210 } 211 212 return 1; 213} 214 215 216int 217ReadProxyFileEntry (proxyFile, pentry) 218 219FILE *proxyFile; 220ProxyFileEntry **pentry; 221 222{ 223 ProxyFileEntry *entry; 224 unsigned char byte; 225 int i; 226 227 *pentry = entry = (ProxyFileEntry *) malloc ( 228 sizeof (ProxyFileEntry)); 229 if (!*pentry) 230 return 0; 231 232 entry->tag = 0; 233 entry->client_id = NULL; 234 entry->class.res_name = NULL; 235 entry->class.res_class = NULL; 236 entry->wm_name = NULL; 237 entry->wm_command = NULL; 238 entry->wm_command_count = 0; 239 240 if (!read_counted_string (proxyFile, &entry->client_id)) 241 goto give_up; 242 if (!read_counted_string (proxyFile, &entry->class.res_name)) 243 goto give_up; 244 if (!read_counted_string (proxyFile, &entry->class.res_class)) 245 goto give_up; 246 if (!read_counted_string (proxyFile, &entry->wm_name)) 247 goto give_up; 248 249 if (!read_byte (proxyFile, &byte)) 250 goto give_up; 251 entry->wm_command_count = byte; 252 253 if (entry->wm_command_count == 0) 254 entry->wm_command = NULL; 255 else 256 { 257 entry->wm_command = (char **) malloc (entry->wm_command_count * 258 sizeof (char *)); 259 260 if (!entry->wm_command) 261 goto give_up; 262 263 for (i = 0; i < entry->wm_command_count; i++) 264 if (!read_counted_string (proxyFile, &entry->wm_command[i])) 265 goto give_up; 266 } 267 268 return 1; 269 270give_up: 271 272 if (entry->client_id) 273 free (entry->client_id); 274 if (entry->class.res_name) 275 free (entry->class.res_name); 276 if (entry->class.res_class) 277 free (entry->class.res_class); 278 if (entry->wm_name) 279 free (entry->wm_name); 280 if (entry->wm_command_count) 281 { 282 for (i = 0; i < entry->wm_command_count; i++) 283 if (entry->wm_command[i]) 284 free (entry->wm_command[i]); 285 } 286 if (entry->wm_command) 287 free ((char *) entry->wm_command); 288 289 free ((char *) entry); 290 *pentry = NULL; 291 292 return 0; 293} 294 295 296void 297ReadProxyFile (filename) 298 299char *filename; 300 301{ 302 FILE *proxyFile; 303 ProxyFileEntry *entry; 304 int done = 0; 305 unsigned short version; 306 307 proxyFile = fopen (filename, "rb"); 308 if (!proxyFile) 309 return; 310 311 if (!read_short (proxyFile, &version) || 312 version > SAVEFILE_VERSION) 313 { 314 done = 1; 315 } 316 317 while (!done) 318 { 319 if (ReadProxyFileEntry (proxyFile, &entry)) 320 { 321 entry->next = proxyFileHead; 322 proxyFileHead = entry; 323 } 324 else 325 done = 1; 326 } 327 328 fclose (proxyFile); 329} 330 331 332 333#ifndef HAS_MKSTEMP 334static char * 335unique_filename (path, prefix) 336char *path; 337char *prefix; 338#else 339static char * 340unique_filename (path, prefix, pFd) 341char *path; 342char *prefix; 343int *pFd; 344#endif 345 346{ 347#ifndef HAS_MKSTEMP 348#ifndef X_NOT_POSIX 349 return ((char *) tempnam (path, prefix)); 350#else 351 char tempFile[PATH_MAX]; 352 char *tmp; 353 354 sprintf (tempFile, "%s/%sXXXXXX", path, prefix); 355 tmp = (char *) mktemp (tempFile); 356 if (tmp) 357 { 358 char *ptr = (char *) malloc (strlen (tmp) + 1); 359 strcpy (ptr, tmp); 360 return (ptr); 361 } 362 else 363 return (NULL); 364#endif 365#else 366 char tempFile[PATH_MAX]; 367 char *ptr; 368 369 sprintf (tempFile, "%s/%sXXXXXX", path, prefix); 370 ptr = (char *)malloc(strlen(tempFile) + 1); 371 if (ptr != NULL) 372 { 373 strcpy(ptr, tempFile); 374 *pFd = mkstemp(ptr); 375 } 376 return ptr; 377#endif 378} 379 380 381 382char * 383WriteProxyFile () 384 385{ 386 FILE *proxyFile = NULL; 387 char *filename = NULL; 388#ifdef HAS_MKSTEMP 389 int fd; 390#endif 391 char *path; 392 WinInfo *winptr; 393 Bool success = False; 394 395 path = getenv ("SM_SAVE_DIR"); 396 if (!path) 397 { 398 path = getenv ("HOME"); 399 if (!path) 400 path = "."; 401 } 402 403#ifndef HAS_MKSTEMP 404 if ((filename = unique_filename (path, ".prx")) == NULL) 405 goto bad; 406 407 if (!(proxyFile = fopen (filename, "wb"))) 408 goto bad; 409#else 410 if ((filename = unique_filename (path, ".prx", &fd)) == NULL) 411 goto bad; 412 413 if (!(proxyFile = fdopen(fd, "wb"))) 414 goto bad; 415#endif 416 if (!write_short (proxyFile, SAVEFILE_VERSION)) 417 goto bad; 418 419 success = True; 420 winptr = win_head; 421 422 while (winptr && success) 423 { 424 if (winptr->client_id) 425 if (!WriteProxyFileEntry (proxyFile, winptr)) 426 { 427 success = False; 428 break; 429 } 430 431 winptr = winptr->next; 432 } 433 434 bad: 435 436 if (proxyFile) 437 fclose (proxyFile); 438 439 if (success) 440 return (filename); 441 else 442 { 443 if (filename) 444 free (filename); 445 return (NULL); 446 } 447} 448 449 450 451char * 452LookupClientID (theWindow) 453 454WinInfo *theWindow; 455 456{ 457 ProxyFileEntry *ptr; 458 int found = 0; 459 460 ptr = proxyFileHead; 461 while (ptr && !found) 462 { 463 if (!ptr->tag && 464 strcmp (theWindow->class.res_name, ptr->class.res_name) == 0 && 465 strcmp (theWindow->class.res_class, ptr->class.res_class) == 0 && 466 strcmp (theWindow->wm_name, ptr->wm_name) == 0) 467 { 468 int i; 469 470 if (theWindow->wm_command_count == ptr->wm_command_count) 471 { 472 for (i = 0; i < theWindow->wm_command_count; i++) 473 if (strcmp (theWindow->wm_command[i], 474 ptr->wm_command[i]) != 0) 475 break; 476 477 if (i == theWindow->wm_command_count) 478 found = 1; 479 } 480 } 481 482 if (!found) 483 ptr = ptr->next; 484 } 485 486 if (found) 487 { 488 ptr->tag = 1; 489 return (ptr->client_id); 490 } 491 else 492 return NULL; 493} 494