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