save.c revision 576bae58
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 );
42576bae58Smrg#ifndef HAVE_MKSTEMP
4314c0a534Smrgstatic char * unique_filename ( char *path, char *prefix );
4414c0a534Smrg#else
4514c0a534Smrgstatic char * unique_filename ( char *path, char *prefix, int *pFd );
4614c0a534Smrg#endif
4714c0a534Smrg
4814c0a534Smrg
4914c0a534Smrgstatic int
5014c0a534Smrgwrite_byte (FILE *file, unsigned char b)
5114c0a534Smrg{
5214c0a534Smrg    if (fwrite ((char *) &b, 1, 1, file) != 1)
5314c0a534Smrg	return 0;
5414c0a534Smrg    return 1;
5514c0a534Smrg}
5614c0a534Smrg
5714c0a534Smrg
5814c0a534Smrgstatic int
5914c0a534Smrgwrite_short (FILE *file, unsigned short s)
6014c0a534Smrg{
6114c0a534Smrg    unsigned char   file_short[2];
6214c0a534Smrg
6314c0a534Smrg    file_short[0] = (s & (unsigned)0xff00) >> 8;
6414c0a534Smrg    file_short[1] = s & 0xff;
6514c0a534Smrg    if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
6614c0a534Smrg	return 0;
6714c0a534Smrg    return 1;
6814c0a534Smrg}
6914c0a534Smrg
7014c0a534Smrg
7114c0a534Smrgstatic int
72bf2eeab3Smrgwrite_counted_string(FILE *file, char *string)
7314c0a534Smrg{
7414c0a534Smrg    if (string)
7514c0a534Smrg    {
7614c0a534Smrg	unsigned char count = strlen (string);
7714c0a534Smrg
7814c0a534Smrg	if (write_byte (file, count) == 0)
7914c0a534Smrg	    return 0;
8014c0a534Smrg	if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
8114c0a534Smrg	    return 0;
8214c0a534Smrg    }
8314c0a534Smrg    else
8414c0a534Smrg    {
8514c0a534Smrg	if (write_byte (file, 0) == 0)
8614c0a534Smrg	    return 0;
8714c0a534Smrg    }
8814c0a534Smrg
8914c0a534Smrg    return 1;
9014c0a534Smrg}
9114c0a534Smrg
9214c0a534Smrg
9314c0a534Smrg
9414c0a534Smrgstatic int
95bf2eeab3Smrgread_byte(FILE *file, unsigned char *bp)
9614c0a534Smrg{
9714c0a534Smrg    if (fread ((char *) bp, 1, 1, file) != 1)
9814c0a534Smrg	return 0;
9914c0a534Smrg    return 1;
10014c0a534Smrg}
10114c0a534Smrg
10214c0a534Smrg
10314c0a534Smrgstatic int
104bf2eeab3Smrgread_short(FILE *file, unsigned short *shortp)
10514c0a534Smrg{
10614c0a534Smrg    unsigned char   file_short[2];
10714c0a534Smrg
10814c0a534Smrg    if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
10914c0a534Smrg	return 0;
11014c0a534Smrg    *shortp = file_short[0] * 256 + file_short[1];
11114c0a534Smrg    return 1;
11214c0a534Smrg}
11314c0a534Smrg
11414c0a534Smrg
11514c0a534Smrgstatic int
116bf2eeab3Smrgread_counted_string(FILE *file, char **stringp)
11714c0a534Smrg{
11814c0a534Smrg    unsigned char  len;
11914c0a534Smrg    char	   *data;
12014c0a534Smrg
12114c0a534Smrg    if (read_byte (file, &len) == 0)
12214c0a534Smrg	return 0;
12314c0a534Smrg    if (len == 0) {
124bf2eeab3Smrg	data = NULL;
12514c0a534Smrg    } else {
12614c0a534Smrg    	data = (char *) malloc ((unsigned) len + 1);
12714c0a534Smrg    	if (!data)
12814c0a534Smrg	    return 0;
12914c0a534Smrg    	if (fread (data, (int) sizeof (char), (int) len, file) != len) {
13014c0a534Smrg	    free (data);
13114c0a534Smrg	    return 0;
13214c0a534Smrg    	}
13314c0a534Smrg	data[len] = '\0';
13414c0a534Smrg    }
13514c0a534Smrg    *stringp = data;
13614c0a534Smrg    return 1;
13714c0a534Smrg}
13814c0a534Smrg
13914c0a534Smrg
14014c0a534Smrg
14114c0a534Smrg/*
14214c0a534Smrg * An entry in the .smproxy file looks like this:
14314c0a534Smrg *
14414c0a534Smrg * FIELD				BYTES
14514c0a534Smrg * -----                                ----
14614c0a534Smrg * client ID len			1
14714c0a534Smrg * client ID				LIST of bytes
14814c0a534Smrg * WM_CLASS "res name" length		1
14914c0a534Smrg * WM_CLASS "res name"			LIST of bytes
15014c0a534Smrg * WM_CLASS "res class" length          1
15114c0a534Smrg * WM_CLASS "res class"                 LIST of bytes
15214c0a534Smrg * WM_NAME length			1
15314c0a534Smrg * WM_NAME				LIST of bytes
15414c0a534Smrg * WM_COMMAND arg count			1
15514c0a534Smrg * For each arg in WM_COMMAND
15614c0a534Smrg *    arg length			1
15714c0a534Smrg *    arg				LIST of bytes
15814c0a534Smrg */
15914c0a534Smrg
16014c0a534Smrgint
161bf2eeab3SmrgWriteProxyFileEntry(FILE *proxyFile, WinInfo *theWindow)
16214c0a534Smrg{
16314c0a534Smrg    int i;
16414c0a534Smrg
16514c0a534Smrg    if (!write_counted_string (proxyFile, theWindow->client_id))
16614c0a534Smrg	return 0;
16714c0a534Smrg    if (!write_counted_string (proxyFile, theWindow->class.res_name))
16814c0a534Smrg	return 0;
16914c0a534Smrg    if (!write_counted_string (proxyFile, theWindow->class.res_class))
17014c0a534Smrg	return 0;
17114c0a534Smrg    if (!write_counted_string (proxyFile, theWindow->wm_name))
17214c0a534Smrg	return 0;
17314c0a534Smrg
17414c0a534Smrg    if (!theWindow->wm_command || theWindow->wm_command_count == 0)
17514c0a534Smrg    {
17614c0a534Smrg	if (!write_byte (proxyFile, 0))
17714c0a534Smrg	    return 0;
17814c0a534Smrg    }
17914c0a534Smrg    else
18014c0a534Smrg    {
18114c0a534Smrg	if (!write_byte (proxyFile, (char) theWindow->wm_command_count))
18214c0a534Smrg	    return 0;
18314c0a534Smrg	for (i = 0; i < theWindow->wm_command_count; i++)
18414c0a534Smrg	    if (!write_counted_string (proxyFile, theWindow->wm_command[i]))
18514c0a534Smrg		return 0;
18614c0a534Smrg    }
18714c0a534Smrg
18814c0a534Smrg    return 1;
18914c0a534Smrg}
19014c0a534Smrg
19114c0a534Smrg
19214c0a534Smrgint
193bf2eeab3SmrgReadProxyFileEntry(FILE *proxyFile, ProxyFileEntry **pentry)
19414c0a534Smrg{
19514c0a534Smrg    ProxyFileEntry *entry;
19614c0a534Smrg    unsigned char byte;
19714c0a534Smrg    int i;
19814c0a534Smrg
19914c0a534Smrg    *pentry = entry = (ProxyFileEntry *) malloc (
20014c0a534Smrg	sizeof (ProxyFileEntry));
20114c0a534Smrg    if (!*pentry)
20214c0a534Smrg	return 0;
20314c0a534Smrg
20414c0a534Smrg    entry->tag = 0;
20514c0a534Smrg    entry->client_id = NULL;
20614c0a534Smrg    entry->class.res_name = NULL;
20714c0a534Smrg    entry->class.res_class = NULL;
20814c0a534Smrg    entry->wm_name = NULL;
20914c0a534Smrg    entry->wm_command = NULL;
21014c0a534Smrg    entry->wm_command_count = 0;
21114c0a534Smrg
21214c0a534Smrg    if (!read_counted_string (proxyFile, &entry->client_id))
21314c0a534Smrg	goto give_up;
21414c0a534Smrg    if (!read_counted_string (proxyFile, &entry->class.res_name))
21514c0a534Smrg	goto give_up;
21614c0a534Smrg    if (!read_counted_string (proxyFile, &entry->class.res_class))
21714c0a534Smrg	goto give_up;
21814c0a534Smrg    if (!read_counted_string (proxyFile, &entry->wm_name))
21914c0a534Smrg	goto give_up;
22014c0a534Smrg
22114c0a534Smrg    if (!read_byte (proxyFile, &byte))
22214c0a534Smrg	goto give_up;
22314c0a534Smrg    entry->wm_command_count = byte;
22414c0a534Smrg
22514c0a534Smrg    if (entry->wm_command_count == 0)
22614c0a534Smrg	entry->wm_command = NULL;
22714c0a534Smrg    else
22814c0a534Smrg    {
22914c0a534Smrg	entry->wm_command = (char **) malloc (entry->wm_command_count *
23014c0a534Smrg	    sizeof (char *));
23114c0a534Smrg
23214c0a534Smrg	if (!entry->wm_command)
23314c0a534Smrg	    goto give_up;
23414c0a534Smrg
23514c0a534Smrg	for (i = 0; i < entry->wm_command_count; i++)
23614c0a534Smrg	    if (!read_counted_string (proxyFile, &entry->wm_command[i]))
23714c0a534Smrg		goto give_up;
23814c0a534Smrg    }
23914c0a534Smrg
24014c0a534Smrg    return 1;
24114c0a534Smrg
24214c0a534Smrggive_up:
24314c0a534Smrg
24414c0a534Smrg    if (entry->client_id)
24514c0a534Smrg	free (entry->client_id);
24614c0a534Smrg    if (entry->class.res_name)
24714c0a534Smrg	free (entry->class.res_name);
24814c0a534Smrg    if (entry->class.res_class)
24914c0a534Smrg	free (entry->class.res_class);
25014c0a534Smrg    if (entry->wm_name)
25114c0a534Smrg	free (entry->wm_name);
25214c0a534Smrg    if (entry->wm_command_count)
25314c0a534Smrg    {
25414c0a534Smrg	for (i = 0; i < entry->wm_command_count; i++)
25514c0a534Smrg	    if (entry->wm_command[i])
25614c0a534Smrg		free (entry->wm_command[i]);
25714c0a534Smrg    }
25814c0a534Smrg    if (entry->wm_command)
25914c0a534Smrg	free ((char *) entry->wm_command);
26014c0a534Smrg
26114c0a534Smrg    free ((char *) entry);
26214c0a534Smrg    *pentry = NULL;
26314c0a534Smrg
26414c0a534Smrg    return 0;
26514c0a534Smrg}
26614c0a534Smrg
26714c0a534Smrg
26814c0a534Smrgvoid
269bf2eeab3SmrgReadProxyFile(char *filename)
27014c0a534Smrg{
27114c0a534Smrg    FILE *proxyFile;
27214c0a534Smrg    ProxyFileEntry *entry;
27314c0a534Smrg    int done = 0;
27414c0a534Smrg    unsigned short version;
27514c0a534Smrg
27614c0a534Smrg    proxyFile = fopen (filename, "rb");
27714c0a534Smrg    if (!proxyFile)
27814c0a534Smrg	return;
27914c0a534Smrg
28014c0a534Smrg    if (!read_short (proxyFile, &version) ||
28114c0a534Smrg	version > SAVEFILE_VERSION)
28214c0a534Smrg    {
28314c0a534Smrg	done = 1;
28414c0a534Smrg    }
28514c0a534Smrg
28614c0a534Smrg    while (!done)
28714c0a534Smrg    {
28814c0a534Smrg	if (ReadProxyFileEntry (proxyFile, &entry))
28914c0a534Smrg	{
29014c0a534Smrg	    entry->next = proxyFileHead;
29114c0a534Smrg	    proxyFileHead = entry;
29214c0a534Smrg	}
29314c0a534Smrg	else
29414c0a534Smrg	    done = 1;
29514c0a534Smrg    }
29614c0a534Smrg
29714c0a534Smrg    fclose (proxyFile);
29814c0a534Smrg}
29914c0a534Smrg
30014c0a534Smrg
30114c0a534Smrg
302576bae58Smrg#ifndef HAVE_MKSTEMP
30314c0a534Smrgstatic char *
304bf2eeab3Smrgunique_filename(char *path, char *prefix)
30514c0a534Smrg#else
30614c0a534Smrgstatic char *
307bf2eeab3Smrgunique_filename(char *path, char *prefix, int *pFd)
30814c0a534Smrg#endif
30914c0a534Smrg{
310576bae58Smrg#ifndef HAVE_MKSTEMP
31114c0a534Smrg#ifndef X_NOT_POSIX
31214c0a534Smrg    return ((char *) tempnam (path, prefix));
31314c0a534Smrg#else
31414c0a534Smrg    char tempFile[PATH_MAX];
31514c0a534Smrg    char *tmp;
31614c0a534Smrg
31714c0a534Smrg    sprintf (tempFile, "%s/%sXXXXXX", path, prefix);
31814c0a534Smrg    tmp = (char *) mktemp (tempFile);
31914c0a534Smrg    if (tmp)
32014c0a534Smrg    {
32114c0a534Smrg	char *ptr = (char *) malloc (strlen (tmp) + 1);
32214c0a534Smrg	strcpy (ptr, tmp);
32314c0a534Smrg	return (ptr);
32414c0a534Smrg    }
32514c0a534Smrg    else
32614c0a534Smrg	return (NULL);
32714c0a534Smrg#endif
32814c0a534Smrg#else
32914c0a534Smrg    char tempFile[PATH_MAX];
33014c0a534Smrg    char *ptr;
33114c0a534Smrg
33214c0a534Smrg    sprintf (tempFile, "%s/%sXXXXXX", path, prefix);
33314c0a534Smrg    ptr = (char *)malloc(strlen(tempFile) + 1);
33414c0a534Smrg    if (ptr != NULL)
33514c0a534Smrg    {
33614c0a534Smrg	strcpy(ptr, tempFile);
33714c0a534Smrg	*pFd =  mkstemp(ptr);
33814c0a534Smrg    }
33914c0a534Smrg    return ptr;
34014c0a534Smrg#endif
34114c0a534Smrg}
34214c0a534Smrg
34314c0a534Smrg
34414c0a534Smrg
34514c0a534Smrgchar *
346bf2eeab3SmrgWriteProxyFile(void)
34714c0a534Smrg{
34814c0a534Smrg    FILE *proxyFile = NULL;
34914c0a534Smrg    char *filename = NULL;
350576bae58Smrg#ifdef HAVE_MKSTEMP
35114c0a534Smrg    int fd;
35214c0a534Smrg#endif
35314c0a534Smrg    char *path;
35414c0a534Smrg    WinInfo *winptr;
35514c0a534Smrg    Bool success = False;
35614c0a534Smrg
35714c0a534Smrg    path = getenv ("SM_SAVE_DIR");
35814c0a534Smrg    if (!path)
35914c0a534Smrg    {
36014c0a534Smrg	path = getenv ("HOME");
36114c0a534Smrg	if (!path)
36214c0a534Smrg	    path = ".";
36314c0a534Smrg    }
36414c0a534Smrg
365576bae58Smrg#ifndef HAVE_MKSTEMP
36614c0a534Smrg    if ((filename = unique_filename (path, ".prx")) == NULL)
36714c0a534Smrg	goto bad;
36814c0a534Smrg
36914c0a534Smrg    if (!(proxyFile = fopen (filename, "wb")))
37014c0a534Smrg	goto bad;
37114c0a534Smrg#else
37214c0a534Smrg    if ((filename = unique_filename (path, ".prx", &fd)) == NULL)
37314c0a534Smrg	goto bad;
37414c0a534Smrg
37514c0a534Smrg    if (!(proxyFile = fdopen(fd, "wb")))
37614c0a534Smrg	goto bad;
37714c0a534Smrg#endif
37814c0a534Smrg    if (!write_short (proxyFile, SAVEFILE_VERSION))
37914c0a534Smrg	goto bad;
38014c0a534Smrg
38114c0a534Smrg    success = True;
38214c0a534Smrg    winptr = win_head;
38314c0a534Smrg
38414c0a534Smrg    while (winptr && success)
38514c0a534Smrg    {
38614c0a534Smrg	if (winptr->client_id)
38714c0a534Smrg	    if (!WriteProxyFileEntry (proxyFile, winptr))
38814c0a534Smrg	    {
38914c0a534Smrg		success = False;
39014c0a534Smrg		break;
39114c0a534Smrg	    }
39214c0a534Smrg
39314c0a534Smrg	winptr = winptr->next;
39414c0a534Smrg    }
39514c0a534Smrg
39614c0a534Smrg bad:
39714c0a534Smrg
39814c0a534Smrg    if (proxyFile)
39914c0a534Smrg	fclose (proxyFile);
40014c0a534Smrg
40114c0a534Smrg    if (success)
40214c0a534Smrg	return (filename);
40314c0a534Smrg    else
40414c0a534Smrg    {
40514c0a534Smrg	if (filename)
40614c0a534Smrg	    free (filename);
40714c0a534Smrg	return (NULL);
40814c0a534Smrg    }
40914c0a534Smrg}
41014c0a534Smrg
41114c0a534Smrg
41214c0a534Smrg
41314c0a534Smrgchar *
414bf2eeab3SmrgLookupClientID(WinInfo *theWindow)
41514c0a534Smrg{
41614c0a534Smrg    ProxyFileEntry *ptr;
41714c0a534Smrg    int found = 0;
41814c0a534Smrg
41914c0a534Smrg    ptr = proxyFileHead;
42014c0a534Smrg    while (ptr && !found)
42114c0a534Smrg    {
42214c0a534Smrg	if (!ptr->tag &&
42314c0a534Smrg            strcmp (theWindow->class.res_name, ptr->class.res_name) == 0 &&
42414c0a534Smrg	    strcmp (theWindow->class.res_class, ptr->class.res_class) == 0 &&
42514c0a534Smrg	    strcmp (theWindow->wm_name, ptr->wm_name) == 0)
42614c0a534Smrg	{
42714c0a534Smrg	    int i;
42814c0a534Smrg
42914c0a534Smrg	    if (theWindow->wm_command_count == ptr->wm_command_count)
43014c0a534Smrg	    {
43114c0a534Smrg		for (i = 0; i < theWindow->wm_command_count; i++)
43214c0a534Smrg		    if (strcmp (theWindow->wm_command[i],
43314c0a534Smrg			ptr->wm_command[i]) != 0)
43414c0a534Smrg			break;
43514c0a534Smrg
43614c0a534Smrg		if (i == theWindow->wm_command_count)
43714c0a534Smrg		    found = 1;
43814c0a534Smrg	    }
43914c0a534Smrg	}
44014c0a534Smrg
44114c0a534Smrg	if (!found)
44214c0a534Smrg	    ptr = ptr->next;
44314c0a534Smrg    }
44414c0a534Smrg
44514c0a534Smrg    if (found)
44614c0a534Smrg    {
44714c0a534Smrg	ptr->tag = 1;
44814c0a534Smrg	return (ptr->client_id);
44914c0a534Smrg    }
45014c0a534Smrg    else
45114c0a534Smrg	return NULL;
45214c0a534Smrg}
453