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