494 lines
9.8 KiB
C
494 lines
9.8 KiB
C
/* $Xorg: save.c,v 1.4 2001/02/09 02:05:35 xorgcvs Exp $ */
|
||
/******************************************************************************
|
||
|
||
Copyright 1994, 1998 The Open Group
|
||
|
||
Permission to use, copy, modify, distribute, and sell this software and its
|
||
documentation for any purpose is hereby granted without fee, provided that
|
||
the above copyright notice appear in all copies and that both that
|
||
copyright notice and this permission notice appear in supporting
|
||
documentation.
|
||
|
||
The above copyright notice and this permission notice shall be included in
|
||
all copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
||
Except as contained in this notice, the name of The Open Group shall not be
|
||
used in advertising or otherwise to promote the sale, use or other dealings
|
||
in this Software without prior written authorization from The Open Group.
|
||
|
||
Author: Ralph Mor, X Consortium
|
||
******************************************************************************/
|
||
/* $XFree86: xc/programs/smproxy/save.c,v 1.7 2001/01/17 23:45:04 dawes Exp $ */
|
||
|
||
#include "smproxy.h"
|
||
#ifdef HAS_MKSTEMP
|
||
#include <unistd.h>
|
||
#endif
|
||
|
||
|
||
ProxyFileEntry *proxyFileHead = NULL;
|
||
|
||
extern WinInfo *win_head;
|
||
|
||
static int write_byte ( FILE *file, unsigned char b );
|
||
static int write_short ( FILE *file, unsigned short s );
|
||
static int write_counted_string ( FILE *file, char *string );
|
||
static int read_byte ( FILE *file, unsigned char *bp );
|
||
static int read_short ( FILE *file, unsigned short *shortp );
|
||
static int read_counted_string ( FILE *file, char **stringp );
|
||
#ifndef HAS_MKSTEMP
|
||
static char * unique_filename ( char *path, char *prefix );
|
||
#else
|
||
static char * unique_filename ( char *path, char *prefix, int *pFd );
|
||
#endif
|
||
|
||
|
||
static int
|
||
write_byte (FILE *file, unsigned char b)
|
||
{
|
||
if (fwrite ((char *) &b, 1, 1, file) != 1)
|
||
return 0;
|
||
return 1;
|
||
}
|
||
|
||
|
||
static int
|
||
write_short (FILE *file, unsigned short s)
|
||
{
|
||
unsigned char file_short[2];
|
||
|
||
file_short[0] = (s & (unsigned)0xff00) >> 8;
|
||
file_short[1] = s & 0xff;
|
||
if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
|
||
return 0;
|
||
return 1;
|
||
}
|
||
|
||
|
||
static int
|
||
write_counted_string (file, string)
|
||
|
||
FILE *file;
|
||
char *string;
|
||
|
||
{
|
||
if (string)
|
||
{
|
||
unsigned char count = strlen (string);
|
||
|
||
if (write_byte (file, count) == 0)
|
||
return 0;
|
||
if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
if (write_byte (file, 0) == 0)
|
||
return 0;
|
||
}
|
||
|
||
return 1;
|
||
}
|
||
|
||
|
||
|
||
static int
|
||
read_byte (file, bp)
|
||
|
||
FILE *file;
|
||
unsigned char *bp;
|
||
|
||
{
|
||
if (fread ((char *) bp, 1, 1, file) != 1)
|
||
return 0;
|
||
return 1;
|
||
}
|
||
|
||
|
||
static int
|
||
read_short (file, shortp)
|
||
|
||
FILE *file;
|
||
unsigned short *shortp;
|
||
|
||
{
|
||
unsigned char file_short[2];
|
||
|
||
if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
|
||
return 0;
|
||
*shortp = file_short[0] * 256 + file_short[1];
|
||
return 1;
|
||
}
|
||
|
||
|
||
static int
|
||
read_counted_string (file, stringp)
|
||
|
||
FILE *file;
|
||
char **stringp;
|
||
|
||
{
|
||
unsigned char len;
|
||
char *data;
|
||
|
||
if (read_byte (file, &len) == 0)
|
||
return 0;
|
||
if (len == 0) {
|
||
data = 0;
|
||
} else {
|
||
data = (char *) malloc ((unsigned) len + 1);
|
||
if (!data)
|
||
return 0;
|
||
if (fread (data, (int) sizeof (char), (int) len, file) != len) {
|
||
free (data);
|
||
return 0;
|
||
}
|
||
data[len] = '\0';
|
||
}
|
||
*stringp = data;
|
||
return 1;
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
* An entry in the .smproxy file looks like this:
|
||
*
|
||
* FIELD BYTES
|
||
* ----- ----
|
||
* client ID len 1
|
||
* client ID LIST of bytes
|
||
* WM_CLASS "res name" length 1
|
||
* WM_CLASS "res name" LIST of bytes
|
||
* WM_CLASS "res class" length 1
|
||
* WM_CLASS "res class" LIST of bytes
|
||
* WM_NAME length 1
|
||
* WM_NAME LIST of bytes
|
||
* WM_COMMAND arg count 1
|
||
* For each arg in WM_COMMAND
|
||
* arg length 1
|
||
* arg LIST of bytes
|
||
*/
|
||
|
||
int
|
||
WriteProxyFileEntry (proxyFile, theWindow)
|
||
|
||
FILE *proxyFile;
|
||
WinInfo *theWindow;
|
||
|
||
{
|
||
int i;
|
||
|
||
if (!write_counted_string (proxyFile, theWindow->client_id))
|
||
return 0;
|
||
if (!write_counted_string (proxyFile, theWindow->class.res_name))
|
||
return 0;
|
||
if (!write_counted_string (proxyFile, theWindow->class.res_class))
|
||
return 0;
|
||
if (!write_counted_string (proxyFile, theWindow->wm_name))
|
||
return 0;
|
||
|
||
if (!theWindow->wm_command || theWindow->wm_command_count == 0)
|
||
{
|
||
if (!write_byte (proxyFile, 0))
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
if (!write_byte (proxyFile, (char) theWindow->wm_command_count))
|
||
return 0;
|
||
for (i = 0; i < theWindow->wm_command_count; i++)
|
||
if (!write_counted_string (proxyFile, theWindow->wm_command[i]))
|
||
return 0;
|
||
}
|
||
|
||
return 1;
|
||
}
|
||
|
||
|
||
int
|
||
ReadProxyFileEntry (proxyFile, pentry)
|
||
|
||
FILE *proxyFile;
|
||
ProxyFileEntry **pentry;
|
||
|
||
{
|
||
ProxyFileEntry *entry;
|
||
unsigned char byte;
|
||
int i;
|
||
|
||
*pentry = entry = (ProxyFileEntry *) malloc (
|
||
sizeof (ProxyFileEntry));
|
||
if (!*pentry)
|
||
return 0;
|
||
|
||
entry->tag = 0;
|
||
entry->client_id = NULL;
|
||
entry->class.res_name = NULL;
|
||
entry->class.res_class = NULL;
|
||
entry->wm_name = NULL;
|
||
entry->wm_command = NULL;
|
||
entry->wm_command_count = 0;
|
||
|
||
if (!read_counted_string (proxyFile, &entry->client_id))
|
||
goto give_up;
|
||
if (!read_counted_string (proxyFile, &entry->class.res_name))
|
||
goto give_up;
|
||
if (!read_counted_string (proxyFile, &entry->class.res_class))
|
||
goto give_up;
|
||
if (!read_counted_string (proxyFile, &entry->wm_name))
|
||
goto give_up;
|
||
|
||
if (!read_byte (proxyFile, &byte))
|
||
goto give_up;
|
||
entry->wm_command_count = byte;
|
||
|
||
if (entry->wm_command_count == 0)
|
||
entry->wm_command = NULL;
|
||
else
|
||
{
|
||
entry->wm_command = (char **) malloc (entry->wm_command_count *
|
||
sizeof (char *));
|
||
|
||
if (!entry->wm_command)
|
||
goto give_up;
|
||
|
||
for (i = 0; i < entry->wm_command_count; i++)
|
||
if (!read_counted_string (proxyFile, &entry->wm_command[i]))
|
||
goto give_up;
|
||
}
|
||
|
||
return 1;
|
||
|
||
give_up:
|
||
|
||
if (entry->client_id)
|
||
free (entry->client_id);
|
||
if (entry->class.res_name)
|
||
free (entry->class.res_name);
|
||
if (entry->class.res_class)
|
||
free (entry->class.res_class);
|
||
if (entry->wm_name)
|
||
free (entry->wm_name);
|
||
if (entry->wm_command_count)
|
||
{
|
||
for (i = 0; i < entry->wm_command_count; i++)
|
||
if (entry->wm_command[i])
|
||
free (entry->wm_command[i]);
|
||
}
|
||
if (entry->wm_command)
|
||
free ((char *) entry->wm_command);
|
||
|
||
free ((char *) entry);
|
||
*pentry = NULL;
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
void
|
||
ReadProxyFile (filename)
|
||
|
||
char *filename;
|
||
|
||
{
|
||
FILE *proxyFile;
|
||
ProxyFileEntry *entry;
|
||
int done = 0;
|
||
unsigned short version;
|
||
|
||
proxyFile = fopen (filename, "rb");
|
||
if (!proxyFile)
|
||
return;
|
||
|
||
if (!read_short (proxyFile, &version) ||
|
||
version > SAVEFILE_VERSION)
|
||
{
|
||
done = 1;
|
||
}
|
||
|
||
while (!done)
|
||
{
|
||
if (ReadProxyFileEntry (proxyFile, &entry))
|
||
{
|
||
entry->next = proxyFileHead;
|
||
proxyFileHead = entry;
|
||
}
|
||
else
|
||
done = 1;
|
||
}
|
||
|
||
fclose (proxyFile);
|
||
}
|
||
|
||
|
||
|
||
#ifndef HAS_MKSTEMP
|
||
static char *
|
||
unique_filename (path, prefix)
|
||
char *path;
|
||
char *prefix;
|
||
#else
|
||
static char *
|
||
unique_filename (path, prefix, pFd)
|
||
char *path;
|
||
char *prefix;
|
||
int *pFd;
|
||
#endif
|
||
|
||
{
|
||
#ifndef HAS_MKSTEMP
|
||
#ifndef X_NOT_POSIX
|
||
return ((char *) tempnam (path, prefix));
|
||
#else
|
||
char tempFile[PATH_MAX];
|
||
char *tmp;
|
||
|
||
sprintf (tempFile, "%s/%sXXXXXX", path, prefix);
|
||
tmp = (char *) mktemp (tempFile);
|
||
if (tmp)
|
||
{
|
||
char *ptr = (char *) malloc (strlen (tmp) + 1);
|
||
strcpy (ptr, tmp);
|
||
return (ptr);
|
||
}
|
||
else
|
||
return (NULL);
|
||
#endif
|
||
#else
|
||
char tempFile[PATH_MAX];
|
||
char *ptr;
|
||
|
||
sprintf (tempFile, "%s/%sXXXXXX", path, prefix);
|
||
ptr = (char *)malloc(strlen(tempFile) + 1);
|
||
if (ptr != NULL)
|
||
{
|
||
strcpy(ptr, tempFile);
|
||
*pFd = mkstemp(ptr);
|
||
}
|
||
return ptr;
|
||
#endif
|
||
}
|
||
|
||
|
||
|
||
char *
|
||
WriteProxyFile ()
|
||
|
||
{
|
||
FILE *proxyFile = NULL;
|
||
char *filename = NULL;
|
||
#ifdef HAS_MKSTEMP
|
||
int fd;
|
||
#endif
|
||
char *path;
|
||
WinInfo *winptr;
|
||
Bool success = False;
|
||
|
||
path = getenv ("SM_SAVE_DIR");
|
||
if (!path)
|
||
{
|
||
path = getenv ("HOME");
|
||
if (!path)
|
||
path = ".";
|
||
}
|
||
|
||
#ifndef HAS_MKSTEMP
|
||
if ((filename = unique_filename (path, ".prx")) == NULL)
|
||
goto bad;
|
||
|
||
if (!(proxyFile = fopen (filename, "wb")))
|
||
goto bad;
|
||
#else
|
||
if ((filename = unique_filename (path, ".prx", &fd)) == NULL)
|
||
goto bad;
|
||
|
||
if (!(proxyFile = fdopen(fd, "wb")))
|
||
goto bad;
|
||
#endif
|
||
if (!write_short (proxyFile, SAVEFILE_VERSION))
|
||
goto bad;
|
||
|
||
success = True;
|
||
winptr = win_head;
|
||
|
||
while (winptr && success)
|
||
{
|
||
if (winptr->client_id)
|
||
if (!WriteProxyFileEntry (proxyFile, winptr))
|
||
{
|
||
success = False;
|
||
break;
|
||
}
|
||
|
||
winptr = winptr->next;
|
||
}
|
||
|
||
bad:
|
||
|
||
if (proxyFile)
|
||
fclose (proxyFile);
|
||
|
||
if (success)
|
||
return (filename);
|
||
else
|
||
{
|
||
if (filename)
|
||
free (filename);
|
||
return (NULL);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
char *
|
||
LookupClientID (theWindow)
|
||
|
||
WinInfo *theWindow;
|
||
|
||
{
|
||
ProxyFileEntry *ptr;
|
||
int found = 0;
|
||
|
||
ptr = proxyFileHead;
|
||
while (ptr && !found)
|
||
{
|
||
if (!ptr->tag &&
|
||
strcmp (theWindow->class.res_name, ptr->class.res_name) == 0 &&
|
||
strcmp (theWindow->class.res_class, ptr->class.res_class) == 0 &&
|
||
strcmp (theWindow->wm_name, ptr->wm_name) == 0)
|
||
{
|
||
int i;
|
||
|
||
if (theWindow->wm_command_count == ptr->wm_command_count)
|
||
{
|
||
for (i = 0; i < theWindow->wm_command_count; i++)
|
||
if (strcmp (theWindow->wm_command[i],
|
||
ptr->wm_command[i]) != 0)
|
||
break;
|
||
|
||
if (i == theWindow->wm_command_count)
|
||
found = 1;
|
||
}
|
||
}
|
||
|
||
if (!found)
|
||
ptr = ptr->next;
|
||
}
|
||
|
||
if (found)
|
||
{
|
||
ptr->tag = 1;
|
||
return (ptr->client_id);
|
||
}
|
||
else
|
||
return NULL;
|
||
}
|