save.c revision 24047306
114c0a534Smrg/****************************************************************************** 214c0a534Smrg 314c0a534SmrgCopyright 1994, 1998 The Open Group 414c0a534Smrg 514c0a534SmrgPermission to use, copy, modify, distribute, and sell this software and its 614c0a534Smrgdocumentation for any purpose is hereby granted without fee, provided that 714c0a534Smrgthe above copyright notice appear in all copies and that both that 814c0a534Smrgcopyright notice and this permission notice appear in supporting 914c0a534Smrgdocumentation. 1014c0a534Smrg 1114c0a534SmrgThe above copyright notice and this permission notice shall be included in 1214c0a534Smrgall copies or substantial portions of the Software. 1314c0a534Smrg 1414c0a534SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1514c0a534SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1614c0a534SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1714c0a534SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 1814c0a534SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1914c0a534SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2014c0a534Smrg 2114c0a534SmrgExcept as contained in this notice, the name of The Open Group shall not be 2214c0a534Smrgused in advertising or otherwise to promote the sale, use or other dealings 2314c0a534Smrgin this Software without prior written authorization from The Open Group. 2414c0a534Smrg 2514c0a534SmrgAuthor: Ralph Mor, X Consortium 2614c0a534Smrg******************************************************************************/ 2714c0a534Smrg 2814c0a534Smrg#include "smproxy.h" 29576bae58Smrg#ifdef HAVE_MKSTEMP 3014c0a534Smrg#include <unistd.h> 3114c0a534Smrg#endif 3214c0a534Smrg 3314c0a534Smrg 34bf2eeab3Smrgstatic ProxyFileEntry *proxyFileHead = NULL; 3514c0a534Smrg 3614c0a534Smrgstatic int write_byte ( FILE *file, unsigned char b ); 3714c0a534Smrgstatic int write_short ( FILE *file, unsigned short s ); 3814c0a534Smrgstatic int write_counted_string ( FILE *file, char *string ); 3914c0a534Smrgstatic int read_byte ( FILE *file, unsigned char *bp ); 4014c0a534Smrgstatic int read_short ( FILE *file, unsigned short *shortp ); 4114c0a534Smrgstatic int read_counted_string ( FILE *file, char **stringp ); 4224047306Smrg 4324047306Smrg#ifndef HAVE_ASPRINTF 4424047306Smrg# include <stdarg.h> 4524047306Smrg 4624047306Smrg/* sprintf variant found in newer libc's which allocates string to print to */ 4724047306Smrg_X_HIDDEN int _X_ATTRIBUTE_PRINTF(2,3) 4824047306Smrgasprintf(char ** ret, const char *format, ...) 4924047306Smrg{ 5024047306Smrg char buf[256]; 5124047306Smrg int len; 5224047306Smrg va_list ap; 5324047306Smrg 5424047306Smrg va_start(ap, format); 5524047306Smrg len = vsnprintf(buf, sizeof(buf), format, ap); 5624047306Smrg va_end(ap); 5724047306Smrg 5824047306Smrg if (len < 0) 5924047306Smrg return -1; 6024047306Smrg 6124047306Smrg if (len < sizeof(buf)) 6224047306Smrg { 6324047306Smrg *ret = strdup(buf); 6424047306Smrg } 6524047306Smrg else 6624047306Smrg { 6724047306Smrg *ret = malloc(len + 1); /* snprintf doesn't count trailing '\0' */ 6824047306Smrg if (*ret != NULL) 6924047306Smrg { 7024047306Smrg va_start(ap, format); 7124047306Smrg len = vsnprintf(*ret, len + 1, format, ap); 7224047306Smrg va_end(ap); 7324047306Smrg if (len < 0) { 7424047306Smrg free(*ret); 7524047306Smrg *ret = NULL; 7624047306Smrg } 7724047306Smrg } 7824047306Smrg } 7924047306Smrg 8024047306Smrg if (*ret == NULL) 8124047306Smrg return -1; 8224047306Smrg 8324047306Smrg return len; 8424047306Smrg} 8514c0a534Smrg#endif 8614c0a534Smrg 8724047306Smrg 8814c0a534Smrg 8914c0a534Smrgstatic int 9014c0a534Smrgwrite_byte (FILE *file, unsigned char b) 9114c0a534Smrg{ 9214c0a534Smrg if (fwrite ((char *) &b, 1, 1, file) != 1) 9314c0a534Smrg return 0; 9414c0a534Smrg return 1; 9514c0a534Smrg} 9614c0a534Smrg 9714c0a534Smrg 9814c0a534Smrgstatic int 9914c0a534Smrgwrite_short (FILE *file, unsigned short s) 10014c0a534Smrg{ 10114c0a534Smrg unsigned char file_short[2]; 10214c0a534Smrg 10314c0a534Smrg file_short[0] = (s & (unsigned)0xff00) >> 8; 10414c0a534Smrg file_short[1] = s & 0xff; 10514c0a534Smrg if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1) 10614c0a534Smrg return 0; 10714c0a534Smrg return 1; 10814c0a534Smrg} 10914c0a534Smrg 11014c0a534Smrg 11114c0a534Smrgstatic int 112bf2eeab3Smrgwrite_counted_string(FILE *file, char *string) 11314c0a534Smrg{ 11414c0a534Smrg if (string) 11514c0a534Smrg { 11614c0a534Smrg unsigned char count = strlen (string); 11714c0a534Smrg 11814c0a534Smrg if (write_byte (file, count) == 0) 11914c0a534Smrg return 0; 12014c0a534Smrg if (fwrite (string, (int) sizeof (char), (int) count, file) != count) 12114c0a534Smrg return 0; 12214c0a534Smrg } 12314c0a534Smrg else 12414c0a534Smrg { 12514c0a534Smrg if (write_byte (file, 0) == 0) 12614c0a534Smrg return 0; 12714c0a534Smrg } 12814c0a534Smrg 12914c0a534Smrg return 1; 13014c0a534Smrg} 13114c0a534Smrg 13214c0a534Smrg 13314c0a534Smrg 13414c0a534Smrgstatic int 135bf2eeab3Smrgread_byte(FILE *file, unsigned char *bp) 13614c0a534Smrg{ 13714c0a534Smrg if (fread ((char *) bp, 1, 1, file) != 1) 13814c0a534Smrg return 0; 13914c0a534Smrg return 1; 14014c0a534Smrg} 14114c0a534Smrg 14214c0a534Smrg 14314c0a534Smrgstatic int 144bf2eeab3Smrgread_short(FILE *file, unsigned short *shortp) 14514c0a534Smrg{ 14614c0a534Smrg unsigned char file_short[2]; 14714c0a534Smrg 14814c0a534Smrg if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1) 14914c0a534Smrg return 0; 15014c0a534Smrg *shortp = file_short[0] * 256 + file_short[1]; 15114c0a534Smrg return 1; 15214c0a534Smrg} 15314c0a534Smrg 15414c0a534Smrg 15514c0a534Smrgstatic int 156bf2eeab3Smrgread_counted_string(FILE *file, char **stringp) 15714c0a534Smrg{ 15814c0a534Smrg unsigned char len; 15914c0a534Smrg char *data; 16014c0a534Smrg 16114c0a534Smrg if (read_byte (file, &len) == 0) 16214c0a534Smrg return 0; 16314c0a534Smrg if (len == 0) { 164bf2eeab3Smrg data = NULL; 16514c0a534Smrg } else { 16614c0a534Smrg data = (char *) malloc ((unsigned) len + 1); 16714c0a534Smrg if (!data) 16814c0a534Smrg return 0; 16914c0a534Smrg if (fread (data, (int) sizeof (char), (int) len, file) != len) { 17014c0a534Smrg free (data); 17114c0a534Smrg return 0; 17214c0a534Smrg } 17314c0a534Smrg data[len] = '\0'; 17414c0a534Smrg } 17514c0a534Smrg *stringp = data; 17614c0a534Smrg return 1; 17714c0a534Smrg} 17814c0a534Smrg 17914c0a534Smrg 18014c0a534Smrg 18114c0a534Smrg/* 18214c0a534Smrg * An entry in the .smproxy file looks like this: 18314c0a534Smrg * 18414c0a534Smrg * FIELD BYTES 18514c0a534Smrg * ----- ---- 18614c0a534Smrg * client ID len 1 18714c0a534Smrg * client ID LIST of bytes 18814c0a534Smrg * WM_CLASS "res name" length 1 18914c0a534Smrg * WM_CLASS "res name" LIST of bytes 19014c0a534Smrg * WM_CLASS "res class" length 1 19114c0a534Smrg * WM_CLASS "res class" LIST of bytes 19214c0a534Smrg * WM_NAME length 1 19314c0a534Smrg * WM_NAME LIST of bytes 19414c0a534Smrg * WM_COMMAND arg count 1 19514c0a534Smrg * For each arg in WM_COMMAND 19614c0a534Smrg * arg length 1 19714c0a534Smrg * arg LIST of bytes 19814c0a534Smrg */ 19914c0a534Smrg 20014c0a534Smrgint 201bf2eeab3SmrgWriteProxyFileEntry(FILE *proxyFile, WinInfo *theWindow) 20214c0a534Smrg{ 20314c0a534Smrg int i; 20414c0a534Smrg 20514c0a534Smrg if (!write_counted_string (proxyFile, theWindow->client_id)) 20614c0a534Smrg return 0; 20714c0a534Smrg if (!write_counted_string (proxyFile, theWindow->class.res_name)) 20814c0a534Smrg return 0; 20914c0a534Smrg if (!write_counted_string (proxyFile, theWindow->class.res_class)) 21014c0a534Smrg return 0; 21114c0a534Smrg if (!write_counted_string (proxyFile, theWindow->wm_name)) 21214c0a534Smrg return 0; 21314c0a534Smrg 21414c0a534Smrg if (!theWindow->wm_command || theWindow->wm_command_count == 0) 21514c0a534Smrg { 21614c0a534Smrg if (!write_byte (proxyFile, 0)) 21714c0a534Smrg return 0; 21814c0a534Smrg } 21914c0a534Smrg else 22014c0a534Smrg { 22114c0a534Smrg if (!write_byte (proxyFile, (char) theWindow->wm_command_count)) 22214c0a534Smrg return 0; 22314c0a534Smrg for (i = 0; i < theWindow->wm_command_count; i++) 22414c0a534Smrg if (!write_counted_string (proxyFile, theWindow->wm_command[i])) 22514c0a534Smrg return 0; 22614c0a534Smrg } 22714c0a534Smrg 22814c0a534Smrg return 1; 22914c0a534Smrg} 23014c0a534Smrg 23114c0a534Smrg 23214c0a534Smrgint 233bf2eeab3SmrgReadProxyFileEntry(FILE *proxyFile, ProxyFileEntry **pentry) 23414c0a534Smrg{ 23514c0a534Smrg ProxyFileEntry *entry; 23614c0a534Smrg unsigned char byte; 23714c0a534Smrg int i; 23814c0a534Smrg 23914c0a534Smrg *pentry = entry = (ProxyFileEntry *) malloc ( 24014c0a534Smrg sizeof (ProxyFileEntry)); 24114c0a534Smrg if (!*pentry) 24214c0a534Smrg return 0; 24314c0a534Smrg 24414c0a534Smrg entry->tag = 0; 24514c0a534Smrg entry->client_id = NULL; 24614c0a534Smrg entry->class.res_name = NULL; 24714c0a534Smrg entry->class.res_class = NULL; 24814c0a534Smrg entry->wm_name = NULL; 24914c0a534Smrg entry->wm_command = NULL; 25014c0a534Smrg entry->wm_command_count = 0; 25114c0a534Smrg 25214c0a534Smrg if (!read_counted_string (proxyFile, &entry->client_id)) 25314c0a534Smrg goto give_up; 25414c0a534Smrg if (!read_counted_string (proxyFile, &entry->class.res_name)) 25514c0a534Smrg goto give_up; 25614c0a534Smrg if (!read_counted_string (proxyFile, &entry->class.res_class)) 25714c0a534Smrg goto give_up; 25814c0a534Smrg if (!read_counted_string (proxyFile, &entry->wm_name)) 25914c0a534Smrg goto give_up; 26014c0a534Smrg 26114c0a534Smrg if (!read_byte (proxyFile, &byte)) 26214c0a534Smrg goto give_up; 26314c0a534Smrg entry->wm_command_count = byte; 26414c0a534Smrg 26514c0a534Smrg if (entry->wm_command_count == 0) 26614c0a534Smrg entry->wm_command = NULL; 26714c0a534Smrg else 26814c0a534Smrg { 26914c0a534Smrg entry->wm_command = (char **) malloc (entry->wm_command_count * 27014c0a534Smrg sizeof (char *)); 27114c0a534Smrg 27214c0a534Smrg if (!entry->wm_command) 27314c0a534Smrg goto give_up; 27414c0a534Smrg 27514c0a534Smrg for (i = 0; i < entry->wm_command_count; i++) 27614c0a534Smrg if (!read_counted_string (proxyFile, &entry->wm_command[i])) 27714c0a534Smrg goto give_up; 27814c0a534Smrg } 27914c0a534Smrg 28014c0a534Smrg return 1; 28114c0a534Smrg 28214c0a534Smrggive_up: 28314c0a534Smrg 28414c0a534Smrg if (entry->client_id) 28514c0a534Smrg free (entry->client_id); 28614c0a534Smrg if (entry->class.res_name) 28714c0a534Smrg free (entry->class.res_name); 28814c0a534Smrg if (entry->class.res_class) 28914c0a534Smrg free (entry->class.res_class); 29014c0a534Smrg if (entry->wm_name) 29114c0a534Smrg free (entry->wm_name); 29214c0a534Smrg if (entry->wm_command) 2931a054510Smrg { 2941a054510Smrg if (entry->wm_command_count) 2951a054510Smrg { 2961a054510Smrg for (i = 0; i < entry->wm_command_count; i++) 2971a054510Smrg if (entry->wm_command[i]) 2981a054510Smrg free (entry->wm_command[i]); 2991a054510Smrg } 30014c0a534Smrg free ((char *) entry->wm_command); 3011a054510Smrg } 3021a054510Smrg 30314c0a534Smrg free ((char *) entry); 30414c0a534Smrg *pentry = NULL; 30514c0a534Smrg 30614c0a534Smrg return 0; 30714c0a534Smrg} 30814c0a534Smrg 30914c0a534Smrg 31014c0a534Smrgvoid 311bf2eeab3SmrgReadProxyFile(char *filename) 31214c0a534Smrg{ 31314c0a534Smrg FILE *proxyFile; 31414c0a534Smrg ProxyFileEntry *entry; 31514c0a534Smrg int done = 0; 31614c0a534Smrg unsigned short version; 31714c0a534Smrg 31814c0a534Smrg proxyFile = fopen (filename, "rb"); 31914c0a534Smrg if (!proxyFile) 32014c0a534Smrg return; 32114c0a534Smrg 32214c0a534Smrg if (!read_short (proxyFile, &version) || 32314c0a534Smrg version > SAVEFILE_VERSION) 32414c0a534Smrg { 32514c0a534Smrg done = 1; 32614c0a534Smrg } 32714c0a534Smrg 32814c0a534Smrg while (!done) 32914c0a534Smrg { 33014c0a534Smrg if (ReadProxyFileEntry (proxyFile, &entry)) 33114c0a534Smrg { 33214c0a534Smrg entry->next = proxyFileHead; 33314c0a534Smrg proxyFileHead = entry; 33414c0a534Smrg } 33514c0a534Smrg else 33614c0a534Smrg done = 1; 33714c0a534Smrg } 33814c0a534Smrg 33914c0a534Smrg fclose (proxyFile); 34014c0a534Smrg} 34114c0a534Smrg 34214c0a534Smrg 34314c0a534Smrg 34414c0a534Smrgstatic char * 34524047306Smrgunique_filename(const char *path, const char *prefix, int *pFd) 34614c0a534Smrg{ 34724047306Smrg char *tempFile = NULL; 34824047306Smrg int tempFd = 0; 34924047306Smrg 35024047306Smrg#if defined(HAVE_MKSTEMP) || defined(HAVE_MKTEMP) 35124047306Smrg if (asprintf (&tempFile, "%s/%sXXXXXX", path, prefix) == -1) 35224047306Smrg return NULL; 35324047306Smrg#endif 35424047306Smrg 35524047306Smrg#ifdef HAVE_MKSTEMP 35624047306Smrg tempFd = mkstemp(tempFile); 35714c0a534Smrg#else 35814c0a534Smrg 35924047306Smrg# ifdef HAVE_MKTEMP 36024047306Smrg if (mktemp(tempFile) == NULL) 36124047306Smrg tempFd = -1; 36224047306Smrg# else /* fallback to tempnam */ 36324047306Smrg tempFile = tempnam (path, prefix); 36424047306Smrg# endif /* HAVE_MKTEMP */ 36524047306Smrg 36624047306Smrg if (tempFd != -1 && tempFile != NULL) 36724047306Smrg tempFd = open(tempFile, O_RDWR | O_CREAT | O_EXCL, 0600); 36814c0a534Smrg#endif 36914c0a534Smrg 37024047306Smrg if (tempFd == -1) { 37124047306Smrg free(tempFile); 37224047306Smrg return (NULL); 37314c0a534Smrg } 37424047306Smrg 37524047306Smrg *pFd = tempFd; 37624047306Smrg return tempFile; 37724047306Smrg 37814c0a534Smrg} 37914c0a534Smrg 38014c0a534Smrg 38114c0a534Smrg 38214c0a534Smrgchar * 383bf2eeab3SmrgWriteProxyFile(void) 38414c0a534Smrg{ 38514c0a534Smrg FILE *proxyFile = NULL; 38614c0a534Smrg char *filename = NULL; 38724047306Smrg int fd = -1; 38824047306Smrg const char *path; 38914c0a534Smrg WinInfo *winptr; 39014c0a534Smrg Bool success = False; 39114c0a534Smrg 39214c0a534Smrg path = getenv ("SM_SAVE_DIR"); 39314c0a534Smrg if (!path) 39414c0a534Smrg { 39514c0a534Smrg path = getenv ("HOME"); 39614c0a534Smrg if (!path) 39714c0a534Smrg path = "."; 39814c0a534Smrg } 39914c0a534Smrg 40014c0a534Smrg if ((filename = unique_filename (path, ".prx", &fd)) == NULL) 40114c0a534Smrg goto bad; 40214c0a534Smrg 40314c0a534Smrg if (!(proxyFile = fdopen(fd, "wb"))) 40414c0a534Smrg goto bad; 40524047306Smrg 40614c0a534Smrg if (!write_short (proxyFile, SAVEFILE_VERSION)) 40714c0a534Smrg goto bad; 40814c0a534Smrg 40914c0a534Smrg success = True; 41014c0a534Smrg winptr = win_head; 41114c0a534Smrg 41214c0a534Smrg while (winptr && success) 41314c0a534Smrg { 41414c0a534Smrg if (winptr->client_id) 41514c0a534Smrg if (!WriteProxyFileEntry (proxyFile, winptr)) 41614c0a534Smrg { 41714c0a534Smrg success = False; 41814c0a534Smrg break; 41914c0a534Smrg } 42014c0a534Smrg 42114c0a534Smrg winptr = winptr->next; 42214c0a534Smrg } 42314c0a534Smrg 42414c0a534Smrg bad: 42514c0a534Smrg 42614c0a534Smrg if (proxyFile) 42714c0a534Smrg fclose (proxyFile); 42824047306Smrg else if (fd != -1) 42924047306Smrg close (fd); 43014c0a534Smrg 43114c0a534Smrg if (success) 43214c0a534Smrg return (filename); 43314c0a534Smrg else 43414c0a534Smrg { 43514c0a534Smrg if (filename) 43614c0a534Smrg free (filename); 43714c0a534Smrg return (NULL); 43814c0a534Smrg } 43914c0a534Smrg} 44014c0a534Smrg 44114c0a534Smrg 44214c0a534Smrg 44314c0a534Smrgchar * 444bf2eeab3SmrgLookupClientID(WinInfo *theWindow) 44514c0a534Smrg{ 44614c0a534Smrg ProxyFileEntry *ptr; 44714c0a534Smrg int found = 0; 44814c0a534Smrg 44914c0a534Smrg ptr = proxyFileHead; 45014c0a534Smrg while (ptr && !found) 45114c0a534Smrg { 45214c0a534Smrg if (!ptr->tag && 45314c0a534Smrg strcmp (theWindow->class.res_name, ptr->class.res_name) == 0 && 45414c0a534Smrg strcmp (theWindow->class.res_class, ptr->class.res_class) == 0 && 45514c0a534Smrg strcmp (theWindow->wm_name, ptr->wm_name) == 0) 45614c0a534Smrg { 45714c0a534Smrg int i; 45814c0a534Smrg 45914c0a534Smrg if (theWindow->wm_command_count == ptr->wm_command_count) 46014c0a534Smrg { 46114c0a534Smrg for (i = 0; i < theWindow->wm_command_count; i++) 46214c0a534Smrg if (strcmp (theWindow->wm_command[i], 46314c0a534Smrg ptr->wm_command[i]) != 0) 46414c0a534Smrg break; 46514c0a534Smrg 46614c0a534Smrg if (i == theWindow->wm_command_count) 46714c0a534Smrg found = 1; 46814c0a534Smrg } 46914c0a534Smrg } 47014c0a534Smrg 47114c0a534Smrg if (!found) 47214c0a534Smrg ptr = ptr->next; 47314c0a534Smrg } 47414c0a534Smrg 47514c0a534Smrg if (found) 47614c0a534Smrg { 47714c0a534Smrg ptr->tag = 1; 47814c0a534Smrg return (ptr->client_id); 47914c0a534Smrg } 48014c0a534Smrg else 48114c0a534Smrg return NULL; 48214c0a534Smrg} 483