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