save.c revision bf2eeab3
114c0a534Smrg/* $Xorg: save.c,v 1.4 2001/02/09 02:05:35 xorgcvs Exp $ */
214c0a534Smrg/******************************************************************************
314c0a534Smrg
414c0a534SmrgCopyright 1994, 1998  The Open Group
514c0a534Smrg
614c0a534SmrgPermission to use, copy, modify, distribute, and sell this software and its
714c0a534Smrgdocumentation for any purpose is hereby granted without fee, provided that
814c0a534Smrgthe above copyright notice appear in all copies and that both that
914c0a534Smrgcopyright notice and this permission notice appear in supporting
1014c0a534Smrgdocumentation.
1114c0a534Smrg
1214c0a534SmrgThe above copyright notice and this permission notice shall be included in
1314c0a534Smrgall copies or substantial portions of the Software.
1414c0a534Smrg
1514c0a534SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1614c0a534SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1714c0a534SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1814c0a534SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1914c0a534SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2014c0a534SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2114c0a534Smrg
2214c0a534SmrgExcept as contained in this notice, the name of The Open Group shall not be
2314c0a534Smrgused in advertising or otherwise to promote the sale, use or other dealings
2414c0a534Smrgin this Software without prior written authorization from The Open Group.
2514c0a534Smrg
2614c0a534SmrgAuthor:  Ralph Mor, X Consortium
2714c0a534Smrg******************************************************************************/
2814c0a534Smrg/* $XFree86: xc/programs/smproxy/save.c,v 1.7 2001/01/17 23:45:04 dawes Exp $ */
2914c0a534Smrg
3014c0a534Smrg#include "smproxy.h"
3114c0a534Smrg#ifdef HAS_MKSTEMP
3214c0a534Smrg#include <unistd.h>
3314c0a534Smrg#endif
3414c0a534Smrg
3514c0a534Smrg
36bf2eeab3Smrgstatic ProxyFileEntry *proxyFileHead = NULL;
3714c0a534Smrg
3814c0a534Smrgstatic int write_byte ( FILE *file, unsigned char b );
3914c0a534Smrgstatic int write_short ( FILE *file, unsigned short s );
4014c0a534Smrgstatic int write_counted_string ( FILE *file, char *string );
4114c0a534Smrgstatic int read_byte ( FILE *file, unsigned char *bp );
4214c0a534Smrgstatic int read_short ( FILE *file, unsigned short *shortp );
4314c0a534Smrgstatic int read_counted_string ( FILE *file, char **stringp );
4414c0a534Smrg#ifndef HAS_MKSTEMP
4514c0a534Smrgstatic char * unique_filename ( char *path, char *prefix );
4614c0a534Smrg#else
4714c0a534Smrgstatic char * unique_filename ( char *path, char *prefix, int *pFd );
4814c0a534Smrg#endif
4914c0a534Smrg
5014c0a534Smrg
5114c0a534Smrgstatic int
5214c0a534Smrgwrite_byte (FILE *file, unsigned char b)
5314c0a534Smrg{
5414c0a534Smrg    if (fwrite ((char *) &b, 1, 1, file) != 1)
5514c0a534Smrg	return 0;
5614c0a534Smrg    return 1;
5714c0a534Smrg}
5814c0a534Smrg
5914c0a534Smrg
6014c0a534Smrgstatic int
6114c0a534Smrgwrite_short (FILE *file, unsigned short s)
6214c0a534Smrg{
6314c0a534Smrg    unsigned char   file_short[2];
6414c0a534Smrg
6514c0a534Smrg    file_short[0] = (s & (unsigned)0xff00) >> 8;
6614c0a534Smrg    file_short[1] = s & 0xff;
6714c0a534Smrg    if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
6814c0a534Smrg	return 0;
6914c0a534Smrg    return 1;
7014c0a534Smrg}
7114c0a534Smrg
7214c0a534Smrg
7314c0a534Smrgstatic int
74bf2eeab3Smrgwrite_counted_string(FILE *file, char *string)
7514c0a534Smrg{
7614c0a534Smrg    if (string)
7714c0a534Smrg    {
7814c0a534Smrg	unsigned char count = strlen (string);
7914c0a534Smrg
8014c0a534Smrg	if (write_byte (file, count) == 0)
8114c0a534Smrg	    return 0;
8214c0a534Smrg	if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
8314c0a534Smrg	    return 0;
8414c0a534Smrg    }
8514c0a534Smrg    else
8614c0a534Smrg    {
8714c0a534Smrg	if (write_byte (file, 0) == 0)
8814c0a534Smrg	    return 0;
8914c0a534Smrg    }
9014c0a534Smrg
9114c0a534Smrg    return 1;
9214c0a534Smrg}
9314c0a534Smrg
9414c0a534Smrg
9514c0a534Smrg
9614c0a534Smrgstatic int
97bf2eeab3Smrgread_byte(FILE *file, unsigned char *bp)
9814c0a534Smrg{
9914c0a534Smrg    if (fread ((char *) bp, 1, 1, file) != 1)
10014c0a534Smrg	return 0;
10114c0a534Smrg    return 1;
10214c0a534Smrg}
10314c0a534Smrg
10414c0a534Smrg
10514c0a534Smrgstatic int
106bf2eeab3Smrgread_short(FILE *file, unsigned short *shortp)
10714c0a534Smrg{
10814c0a534Smrg    unsigned char   file_short[2];
10914c0a534Smrg
11014c0a534Smrg    if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
11114c0a534Smrg	return 0;
11214c0a534Smrg    *shortp = file_short[0] * 256 + file_short[1];
11314c0a534Smrg    return 1;
11414c0a534Smrg}
11514c0a534Smrg
11614c0a534Smrg
11714c0a534Smrgstatic int
118bf2eeab3Smrgread_counted_string(FILE *file, char **stringp)
11914c0a534Smrg{
12014c0a534Smrg    unsigned char  len;
12114c0a534Smrg    char	   *data;
12214c0a534Smrg
12314c0a534Smrg    if (read_byte (file, &len) == 0)
12414c0a534Smrg	return 0;
12514c0a534Smrg    if (len == 0) {
126bf2eeab3Smrg	data = NULL;
12714c0a534Smrg    } else {
12814c0a534Smrg    	data = (char *) malloc ((unsigned) len + 1);
12914c0a534Smrg    	if (!data)
13014c0a534Smrg	    return 0;
13114c0a534Smrg    	if (fread (data, (int) sizeof (char), (int) len, file) != len) {
13214c0a534Smrg	    free (data);
13314c0a534Smrg	    return 0;
13414c0a534Smrg    	}
13514c0a534Smrg	data[len] = '\0';
13614c0a534Smrg    }
13714c0a534Smrg    *stringp = data;
13814c0a534Smrg    return 1;
13914c0a534Smrg}
14014c0a534Smrg
14114c0a534Smrg
14214c0a534Smrg
14314c0a534Smrg/*
14414c0a534Smrg * An entry in the .smproxy file looks like this:
14514c0a534Smrg *
14614c0a534Smrg * FIELD				BYTES
14714c0a534Smrg * -----                                ----
14814c0a534Smrg * client ID len			1
14914c0a534Smrg * client ID				LIST of bytes
15014c0a534Smrg * WM_CLASS "res name" length		1
15114c0a534Smrg * WM_CLASS "res name"			LIST of bytes
15214c0a534Smrg * WM_CLASS "res class" length          1
15314c0a534Smrg * WM_CLASS "res class"                 LIST of bytes
15414c0a534Smrg * WM_NAME length			1
15514c0a534Smrg * WM_NAME				LIST of bytes
15614c0a534Smrg * WM_COMMAND arg count			1
15714c0a534Smrg * For each arg in WM_COMMAND
15814c0a534Smrg *    arg length			1
15914c0a534Smrg *    arg				LIST of bytes
16014c0a534Smrg */
16114c0a534Smrg
16214c0a534Smrgint
163bf2eeab3SmrgWriteProxyFileEntry(FILE *proxyFile, WinInfo *theWindow)
16414c0a534Smrg{
16514c0a534Smrg    int i;
16614c0a534Smrg
16714c0a534Smrg    if (!write_counted_string (proxyFile, theWindow->client_id))
16814c0a534Smrg	return 0;
16914c0a534Smrg    if (!write_counted_string (proxyFile, theWindow->class.res_name))
17014c0a534Smrg	return 0;
17114c0a534Smrg    if (!write_counted_string (proxyFile, theWindow->class.res_class))
17214c0a534Smrg	return 0;
17314c0a534Smrg    if (!write_counted_string (proxyFile, theWindow->wm_name))
17414c0a534Smrg	return 0;
17514c0a534Smrg
17614c0a534Smrg    if (!theWindow->wm_command || theWindow->wm_command_count == 0)
17714c0a534Smrg    {
17814c0a534Smrg	if (!write_byte (proxyFile, 0))
17914c0a534Smrg	    return 0;
18014c0a534Smrg    }
18114c0a534Smrg    else
18214c0a534Smrg    {
18314c0a534Smrg	if (!write_byte (proxyFile, (char) theWindow->wm_command_count))
18414c0a534Smrg	    return 0;
18514c0a534Smrg	for (i = 0; i < theWindow->wm_command_count; i++)
18614c0a534Smrg	    if (!write_counted_string (proxyFile, theWindow->wm_command[i]))
18714c0a534Smrg		return 0;
18814c0a534Smrg    }
18914c0a534Smrg
19014c0a534Smrg    return 1;
19114c0a534Smrg}
19214c0a534Smrg
19314c0a534Smrg
19414c0a534Smrgint
195bf2eeab3SmrgReadProxyFileEntry(FILE *proxyFile, ProxyFileEntry **pentry)
19614c0a534Smrg{
19714c0a534Smrg    ProxyFileEntry *entry;
19814c0a534Smrg    unsigned char byte;
19914c0a534Smrg    int i;
20014c0a534Smrg
20114c0a534Smrg    *pentry = entry = (ProxyFileEntry *) malloc (
20214c0a534Smrg	sizeof (ProxyFileEntry));
20314c0a534Smrg    if (!*pentry)
20414c0a534Smrg	return 0;
20514c0a534Smrg
20614c0a534Smrg    entry->tag = 0;
20714c0a534Smrg    entry->client_id = NULL;
20814c0a534Smrg    entry->class.res_name = NULL;
20914c0a534Smrg    entry->class.res_class = NULL;
21014c0a534Smrg    entry->wm_name = NULL;
21114c0a534Smrg    entry->wm_command = NULL;
21214c0a534Smrg    entry->wm_command_count = 0;
21314c0a534Smrg
21414c0a534Smrg    if (!read_counted_string (proxyFile, &entry->client_id))
21514c0a534Smrg	goto give_up;
21614c0a534Smrg    if (!read_counted_string (proxyFile, &entry->class.res_name))
21714c0a534Smrg	goto give_up;
21814c0a534Smrg    if (!read_counted_string (proxyFile, &entry->class.res_class))
21914c0a534Smrg	goto give_up;
22014c0a534Smrg    if (!read_counted_string (proxyFile, &entry->wm_name))
22114c0a534Smrg	goto give_up;
22214c0a534Smrg
22314c0a534Smrg    if (!read_byte (proxyFile, &byte))
22414c0a534Smrg	goto give_up;
22514c0a534Smrg    entry->wm_command_count = byte;
22614c0a534Smrg
22714c0a534Smrg    if (entry->wm_command_count == 0)
22814c0a534Smrg	entry->wm_command = NULL;
22914c0a534Smrg    else
23014c0a534Smrg    {
23114c0a534Smrg	entry->wm_command = (char **) malloc (entry->wm_command_count *
23214c0a534Smrg	    sizeof (char *));
23314c0a534Smrg
23414c0a534Smrg	if (!entry->wm_command)
23514c0a534Smrg	    goto give_up;
23614c0a534Smrg
23714c0a534Smrg	for (i = 0; i < entry->wm_command_count; i++)
23814c0a534Smrg	    if (!read_counted_string (proxyFile, &entry->wm_command[i]))
23914c0a534Smrg		goto give_up;
24014c0a534Smrg    }
24114c0a534Smrg
24214c0a534Smrg    return 1;
24314c0a534Smrg
24414c0a534Smrggive_up:
24514c0a534Smrg
24614c0a534Smrg    if (entry->client_id)
24714c0a534Smrg	free (entry->client_id);
24814c0a534Smrg    if (entry->class.res_name)
24914c0a534Smrg	free (entry->class.res_name);
25014c0a534Smrg    if (entry->class.res_class)
25114c0a534Smrg	free (entry->class.res_class);
25214c0a534Smrg    if (entry->wm_name)
25314c0a534Smrg	free (entry->wm_name);
25414c0a534Smrg    if (entry->wm_command_count)
25514c0a534Smrg    {
25614c0a534Smrg	for (i = 0; i < entry->wm_command_count; i++)
25714c0a534Smrg	    if (entry->wm_command[i])
25814c0a534Smrg		free (entry->wm_command[i]);
25914c0a534Smrg    }
26014c0a534Smrg    if (entry->wm_command)
26114c0a534Smrg	free ((char *) entry->wm_command);
26214c0a534Smrg
26314c0a534Smrg    free ((char *) entry);
26414c0a534Smrg    *pentry = NULL;
26514c0a534Smrg
26614c0a534Smrg    return 0;
26714c0a534Smrg}
26814c0a534Smrg
26914c0a534Smrg
27014c0a534Smrgvoid
271bf2eeab3SmrgReadProxyFile(char *filename)
27214c0a534Smrg{
27314c0a534Smrg    FILE *proxyFile;
27414c0a534Smrg    ProxyFileEntry *entry;
27514c0a534Smrg    int done = 0;
27614c0a534Smrg    unsigned short version;
27714c0a534Smrg
27814c0a534Smrg    proxyFile = fopen (filename, "rb");
27914c0a534Smrg    if (!proxyFile)
28014c0a534Smrg	return;
28114c0a534Smrg
28214c0a534Smrg    if (!read_short (proxyFile, &version) ||
28314c0a534Smrg	version > SAVEFILE_VERSION)
28414c0a534Smrg    {
28514c0a534Smrg	done = 1;
28614c0a534Smrg    }
28714c0a534Smrg
28814c0a534Smrg    while (!done)
28914c0a534Smrg    {
29014c0a534Smrg	if (ReadProxyFileEntry (proxyFile, &entry))
29114c0a534Smrg	{
29214c0a534Smrg	    entry->next = proxyFileHead;
29314c0a534Smrg	    proxyFileHead = entry;
29414c0a534Smrg	}
29514c0a534Smrg	else
29614c0a534Smrg	    done = 1;
29714c0a534Smrg    }
29814c0a534Smrg
29914c0a534Smrg    fclose (proxyFile);
30014c0a534Smrg}
30114c0a534Smrg
30214c0a534Smrg
30314c0a534Smrg
30414c0a534Smrg#ifndef HAS_MKSTEMP
30514c0a534Smrgstatic char *
306bf2eeab3Smrgunique_filename(char *path, char *prefix)
30714c0a534Smrg#else
30814c0a534Smrgstatic char *
309bf2eeab3Smrgunique_filename(char *path, char *prefix, int *pFd)
31014c0a534Smrg#endif
31114c0a534Smrg{
31214c0a534Smrg#ifndef HAS_MKSTEMP
31314c0a534Smrg#ifndef X_NOT_POSIX
31414c0a534Smrg    return ((char *) tempnam (path, prefix));
31514c0a534Smrg#else
31614c0a534Smrg    char tempFile[PATH_MAX];
31714c0a534Smrg    char *tmp;
31814c0a534Smrg
31914c0a534Smrg    sprintf (tempFile, "%s/%sXXXXXX", path, prefix);
32014c0a534Smrg    tmp = (char *) mktemp (tempFile);
32114c0a534Smrg    if (tmp)
32214c0a534Smrg    {
32314c0a534Smrg	char *ptr = (char *) malloc (strlen (tmp) + 1);
32414c0a534Smrg	strcpy (ptr, tmp);
32514c0a534Smrg	return (ptr);
32614c0a534Smrg    }
32714c0a534Smrg    else
32814c0a534Smrg	return (NULL);
32914c0a534Smrg#endif
33014c0a534Smrg#else
33114c0a534Smrg    char tempFile[PATH_MAX];
33214c0a534Smrg    char *ptr;
33314c0a534Smrg
33414c0a534Smrg    sprintf (tempFile, "%s/%sXXXXXX", path, prefix);
33514c0a534Smrg    ptr = (char *)malloc(strlen(tempFile) + 1);
33614c0a534Smrg    if (ptr != NULL)
33714c0a534Smrg    {
33814c0a534Smrg	strcpy(ptr, tempFile);
33914c0a534Smrg	*pFd =  mkstemp(ptr);
34014c0a534Smrg    }
34114c0a534Smrg    return ptr;
34214c0a534Smrg#endif
34314c0a534Smrg}
34414c0a534Smrg
34514c0a534Smrg
34614c0a534Smrg
34714c0a534Smrgchar *
348bf2eeab3SmrgWriteProxyFile(void)
34914c0a534Smrg{
35014c0a534Smrg    FILE *proxyFile = NULL;
35114c0a534Smrg    char *filename = NULL;
35214c0a534Smrg#ifdef HAS_MKSTEMP
35314c0a534Smrg    int fd;
35414c0a534Smrg#endif
35514c0a534Smrg    char *path;
35614c0a534Smrg    WinInfo *winptr;
35714c0a534Smrg    Bool success = False;
35814c0a534Smrg
35914c0a534Smrg    path = getenv ("SM_SAVE_DIR");
36014c0a534Smrg    if (!path)
36114c0a534Smrg    {
36214c0a534Smrg	path = getenv ("HOME");
36314c0a534Smrg	if (!path)
36414c0a534Smrg	    path = ".";
36514c0a534Smrg    }
36614c0a534Smrg
36714c0a534Smrg#ifndef HAS_MKSTEMP
36814c0a534Smrg    if ((filename = unique_filename (path, ".prx")) == NULL)
36914c0a534Smrg	goto bad;
37014c0a534Smrg
37114c0a534Smrg    if (!(proxyFile = fopen (filename, "wb")))
37214c0a534Smrg	goto bad;
37314c0a534Smrg#else
37414c0a534Smrg    if ((filename = unique_filename (path, ".prx", &fd)) == NULL)
37514c0a534Smrg	goto bad;
37614c0a534Smrg
37714c0a534Smrg    if (!(proxyFile = fdopen(fd, "wb")))
37814c0a534Smrg	goto bad;
37914c0a534Smrg#endif
38014c0a534Smrg    if (!write_short (proxyFile, SAVEFILE_VERSION))
38114c0a534Smrg	goto bad;
38214c0a534Smrg
38314c0a534Smrg    success = True;
38414c0a534Smrg    winptr = win_head;
38514c0a534Smrg
38614c0a534Smrg    while (winptr && success)
38714c0a534Smrg    {
38814c0a534Smrg	if (winptr->client_id)
38914c0a534Smrg	    if (!WriteProxyFileEntry (proxyFile, winptr))
39014c0a534Smrg	    {
39114c0a534Smrg		success = False;
39214c0a534Smrg		break;
39314c0a534Smrg	    }
39414c0a534Smrg
39514c0a534Smrg	winptr = winptr->next;
39614c0a534Smrg    }
39714c0a534Smrg
39814c0a534Smrg bad:
39914c0a534Smrg
40014c0a534Smrg    if (proxyFile)
40114c0a534Smrg	fclose (proxyFile);
40214c0a534Smrg
40314c0a534Smrg    if (success)
40414c0a534Smrg	return (filename);
40514c0a534Smrg    else
40614c0a534Smrg    {
40714c0a534Smrg	if (filename)
40814c0a534Smrg	    free (filename);
40914c0a534Smrg	return (NULL);
41014c0a534Smrg    }
41114c0a534Smrg}
41214c0a534Smrg
41314c0a534Smrg
41414c0a534Smrg
41514c0a534Smrgchar *
416bf2eeab3SmrgLookupClientID(WinInfo *theWindow)
41714c0a534Smrg{
41814c0a534Smrg    ProxyFileEntry *ptr;
41914c0a534Smrg    int found = 0;
42014c0a534Smrg
42114c0a534Smrg    ptr = proxyFileHead;
42214c0a534Smrg    while (ptr && !found)
42314c0a534Smrg    {
42414c0a534Smrg	if (!ptr->tag &&
42514c0a534Smrg            strcmp (theWindow->class.res_name, ptr->class.res_name) == 0 &&
42614c0a534Smrg	    strcmp (theWindow->class.res_class, ptr->class.res_class) == 0 &&
42714c0a534Smrg	    strcmp (theWindow->wm_name, ptr->wm_name) == 0)
42814c0a534Smrg	{
42914c0a534Smrg	    int i;
43014c0a534Smrg
43114c0a534Smrg	    if (theWindow->wm_command_count == ptr->wm_command_count)
43214c0a534Smrg	    {
43314c0a534Smrg		for (i = 0; i < theWindow->wm_command_count; i++)
43414c0a534Smrg		    if (strcmp (theWindow->wm_command[i],
43514c0a534Smrg			ptr->wm_command[i]) != 0)
43614c0a534Smrg			break;
43714c0a534Smrg
43814c0a534Smrg		if (i == theWindow->wm_command_count)
43914c0a534Smrg		    found = 1;
44014c0a534Smrg	    }
44114c0a534Smrg	}
44214c0a534Smrg
44314c0a534Smrg	if (!found)
44414c0a534Smrg	    ptr = ptr->next;
44514c0a534Smrg    }
44614c0a534Smrg
44714c0a534Smrg    if (found)
44814c0a534Smrg    {
44914c0a534Smrg	ptr->tag = 1;
45014c0a534Smrg	return (ptr->client_id);
45114c0a534Smrg    }
45214c0a534Smrg    else
45314c0a534Smrg	return NULL;
45414c0a534Smrg}
455