save.c revision 576bae58
1/****************************************************************************** 2 3Copyright 1994, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from The Open Group. 24 25Author: Ralph Mor, X Consortium 26******************************************************************************/ 27 28#include "smproxy.h" 29#ifdef HAVE_MKSTEMP 30#include <unistd.h> 31#endif 32 33 34static ProxyFileEntry *proxyFileHead = NULL; 35 36static int write_byte ( FILE *file, unsigned char b ); 37static int write_short ( FILE *file, unsigned short s ); 38static int write_counted_string ( FILE *file, char *string ); 39static int read_byte ( FILE *file, unsigned char *bp ); 40static int read_short ( FILE *file, unsigned short *shortp ); 41static int read_counted_string ( FILE *file, char **stringp ); 42#ifndef HAVE_MKSTEMP 43static char * unique_filename ( char *path, char *prefix ); 44#else 45static char * unique_filename ( char *path, char *prefix, int *pFd ); 46#endif 47 48 49static int 50write_byte (FILE *file, unsigned char b) 51{ 52 if (fwrite ((char *) &b, 1, 1, file) != 1) 53 return 0; 54 return 1; 55} 56 57 58static int 59write_short (FILE *file, unsigned short s) 60{ 61 unsigned char file_short[2]; 62 63 file_short[0] = (s & (unsigned)0xff00) >> 8; 64 file_short[1] = s & 0xff; 65 if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1) 66 return 0; 67 return 1; 68} 69 70 71static int 72write_counted_string(FILE *file, char *string) 73{ 74 if (string) 75 { 76 unsigned char count = strlen (string); 77 78 if (write_byte (file, count) == 0) 79 return 0; 80 if (fwrite (string, (int) sizeof (char), (int) count, file) != count) 81 return 0; 82 } 83 else 84 { 85 if (write_byte (file, 0) == 0) 86 return 0; 87 } 88 89 return 1; 90} 91 92 93 94static int 95read_byte(FILE *file, unsigned char *bp) 96{ 97 if (fread ((char *) bp, 1, 1, file) != 1) 98 return 0; 99 return 1; 100} 101 102 103static int 104read_short(FILE *file, unsigned short *shortp) 105{ 106 unsigned char file_short[2]; 107 108 if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1) 109 return 0; 110 *shortp = file_short[0] * 256 + file_short[1]; 111 return 1; 112} 113 114 115static int 116read_counted_string(FILE *file, char **stringp) 117{ 118 unsigned char len; 119 char *data; 120 121 if (read_byte (file, &len) == 0) 122 return 0; 123 if (len == 0) { 124 data = NULL; 125 } else { 126 data = (char *) malloc ((unsigned) len + 1); 127 if (!data) 128 return 0; 129 if (fread (data, (int) sizeof (char), (int) len, file) != len) { 130 free (data); 131 return 0; 132 } 133 data[len] = '\0'; 134 } 135 *stringp = data; 136 return 1; 137} 138 139 140 141/* 142 * An entry in the .smproxy file looks like this: 143 * 144 * FIELD BYTES 145 * ----- ---- 146 * client ID len 1 147 * client ID LIST of bytes 148 * WM_CLASS "res name" length 1 149 * WM_CLASS "res name" LIST of bytes 150 * WM_CLASS "res class" length 1 151 * WM_CLASS "res class" LIST of bytes 152 * WM_NAME length 1 153 * WM_NAME LIST of bytes 154 * WM_COMMAND arg count 1 155 * For each arg in WM_COMMAND 156 * arg length 1 157 * arg LIST of bytes 158 */ 159 160int 161WriteProxyFileEntry(FILE *proxyFile, WinInfo *theWindow) 162{ 163 int i; 164 165 if (!write_counted_string (proxyFile, theWindow->client_id)) 166 return 0; 167 if (!write_counted_string (proxyFile, theWindow->class.res_name)) 168 return 0; 169 if (!write_counted_string (proxyFile, theWindow->class.res_class)) 170 return 0; 171 if (!write_counted_string (proxyFile, theWindow->wm_name)) 172 return 0; 173 174 if (!theWindow->wm_command || theWindow->wm_command_count == 0) 175 { 176 if (!write_byte (proxyFile, 0)) 177 return 0; 178 } 179 else 180 { 181 if (!write_byte (proxyFile, (char) theWindow->wm_command_count)) 182 return 0; 183 for (i = 0; i < theWindow->wm_command_count; i++) 184 if (!write_counted_string (proxyFile, theWindow->wm_command[i])) 185 return 0; 186 } 187 188 return 1; 189} 190 191 192int 193ReadProxyFileEntry(FILE *proxyFile, ProxyFileEntry **pentry) 194{ 195 ProxyFileEntry *entry; 196 unsigned char byte; 197 int i; 198 199 *pentry = entry = (ProxyFileEntry *) malloc ( 200 sizeof (ProxyFileEntry)); 201 if (!*pentry) 202 return 0; 203 204 entry->tag = 0; 205 entry->client_id = NULL; 206 entry->class.res_name = NULL; 207 entry->class.res_class = NULL; 208 entry->wm_name = NULL; 209 entry->wm_command = NULL; 210 entry->wm_command_count = 0; 211 212 if (!read_counted_string (proxyFile, &entry->client_id)) 213 goto give_up; 214 if (!read_counted_string (proxyFile, &entry->class.res_name)) 215 goto give_up; 216 if (!read_counted_string (proxyFile, &entry->class.res_class)) 217 goto give_up; 218 if (!read_counted_string (proxyFile, &entry->wm_name)) 219 goto give_up; 220 221 if (!read_byte (proxyFile, &byte)) 222 goto give_up; 223 entry->wm_command_count = byte; 224 225 if (entry->wm_command_count == 0) 226 entry->wm_command = NULL; 227 else 228 { 229 entry->wm_command = (char **) malloc (entry->wm_command_count * 230 sizeof (char *)); 231 232 if (!entry->wm_command) 233 goto give_up; 234 235 for (i = 0; i < entry->wm_command_count; i++) 236 if (!read_counted_string (proxyFile, &entry->wm_command[i])) 237 goto give_up; 238 } 239 240 return 1; 241 242give_up: 243 244 if (entry->client_id) 245 free (entry->client_id); 246 if (entry->class.res_name) 247 free (entry->class.res_name); 248 if (entry->class.res_class) 249 free (entry->class.res_class); 250 if (entry->wm_name) 251 free (entry->wm_name); 252 if (entry->wm_command_count) 253 { 254 for (i = 0; i < entry->wm_command_count; i++) 255 if (entry->wm_command[i]) 256 free (entry->wm_command[i]); 257 } 258 if (entry->wm_command) 259 free ((char *) entry->wm_command); 260 261 free ((char *) entry); 262 *pentry = NULL; 263 264 return 0; 265} 266 267 268void 269ReadProxyFile(char *filename) 270{ 271 FILE *proxyFile; 272 ProxyFileEntry *entry; 273 int done = 0; 274 unsigned short version; 275 276 proxyFile = fopen (filename, "rb"); 277 if (!proxyFile) 278 return; 279 280 if (!read_short (proxyFile, &version) || 281 version > SAVEFILE_VERSION) 282 { 283 done = 1; 284 } 285 286 while (!done) 287 { 288 if (ReadProxyFileEntry (proxyFile, &entry)) 289 { 290 entry->next = proxyFileHead; 291 proxyFileHead = entry; 292 } 293 else 294 done = 1; 295 } 296 297 fclose (proxyFile); 298} 299 300 301 302#ifndef HAVE_MKSTEMP 303static char * 304unique_filename(char *path, char *prefix) 305#else 306static char * 307unique_filename(char *path, char *prefix, int *pFd) 308#endif 309{ 310#ifndef HAVE_MKSTEMP 311#ifndef X_NOT_POSIX 312 return ((char *) tempnam (path, prefix)); 313#else 314 char tempFile[PATH_MAX]; 315 char *tmp; 316 317 sprintf (tempFile, "%s/%sXXXXXX", path, prefix); 318 tmp = (char *) mktemp (tempFile); 319 if (tmp) 320 { 321 char *ptr = (char *) malloc (strlen (tmp) + 1); 322 strcpy (ptr, tmp); 323 return (ptr); 324 } 325 else 326 return (NULL); 327#endif 328#else 329 char tempFile[PATH_MAX]; 330 char *ptr; 331 332 sprintf (tempFile, "%s/%sXXXXXX", path, prefix); 333 ptr = (char *)malloc(strlen(tempFile) + 1); 334 if (ptr != NULL) 335 { 336 strcpy(ptr, tempFile); 337 *pFd = mkstemp(ptr); 338 } 339 return ptr; 340#endif 341} 342 343 344 345char * 346WriteProxyFile(void) 347{ 348 FILE *proxyFile = NULL; 349 char *filename = NULL; 350#ifdef HAVE_MKSTEMP 351 int fd; 352#endif 353 char *path; 354 WinInfo *winptr; 355 Bool success = False; 356 357 path = getenv ("SM_SAVE_DIR"); 358 if (!path) 359 { 360 path = getenv ("HOME"); 361 if (!path) 362 path = "."; 363 } 364 365#ifndef HAVE_MKSTEMP 366 if ((filename = unique_filename (path, ".prx")) == NULL) 367 goto bad; 368 369 if (!(proxyFile = fopen (filename, "wb"))) 370 goto bad; 371#else 372 if ((filename = unique_filename (path, ".prx", &fd)) == NULL) 373 goto bad; 374 375 if (!(proxyFile = fdopen(fd, "wb"))) 376 goto bad; 377#endif 378 if (!write_short (proxyFile, SAVEFILE_VERSION)) 379 goto bad; 380 381 success = True; 382 winptr = win_head; 383 384 while (winptr && success) 385 { 386 if (winptr->client_id) 387 if (!WriteProxyFileEntry (proxyFile, winptr)) 388 { 389 success = False; 390 break; 391 } 392 393 winptr = winptr->next; 394 } 395 396 bad: 397 398 if (proxyFile) 399 fclose (proxyFile); 400 401 if (success) 402 return (filename); 403 else 404 { 405 if (filename) 406 free (filename); 407 return (NULL); 408 } 409} 410 411 412 413char * 414LookupClientID(WinInfo *theWindow) 415{ 416 ProxyFileEntry *ptr; 417 int found = 0; 418 419 ptr = proxyFileHead; 420 while (ptr && !found) 421 { 422 if (!ptr->tag && 423 strcmp (theWindow->class.res_name, ptr->class.res_name) == 0 && 424 strcmp (theWindow->class.res_class, ptr->class.res_class) == 0 && 425 strcmp (theWindow->wm_name, ptr->wm_name) == 0) 426 { 427 int i; 428 429 if (theWindow->wm_command_count == ptr->wm_command_count) 430 { 431 for (i = 0; i < theWindow->wm_command_count; i++) 432 if (strcmp (theWindow->wm_command[i], 433 ptr->wm_command[i]) != 0) 434 break; 435 436 if (i == theWindow->wm_command_count) 437 found = 1; 438 } 439 } 440 441 if (!found) 442 ptr = ptr->next; 443 } 444 445 if (found) 446 { 447 ptr->tag = 1; 448 return (ptr->client_id); 449 } 450 else 451 return NULL; 452} 453