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