save.c revision 1a054510
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) 253 { 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 free ((char *) entry->wm_command); 261 } 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 HAVE_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 HAVE_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 HAVE_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 HAVE_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