2006-11-25 13:07:29 -07:00
|
|
|
|
/******************************************************************************
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "smproxy.h"
|
2010-10-31 12:09:33 -06:00
|
|
|
|
#ifdef HAVE_MKSTEMP
|
2006-11-25 13:07:29 -07:00
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
2009-10-23 14:31:39 -06:00
|
|
|
|
static ProxyFileEntry *proxyFileHead = NULL;
|
2006-11-25 13:07:29 -07:00
|
|
|
|
|
|
|
|
|
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 );
|
2015-05-10 03:56:05 -06:00
|
|
|
|
|
|
|
|
|
#ifndef HAVE_ASPRINTF
|
|
|
|
|
# include <stdarg.h>
|
|
|
|
|
|
|
|
|
|
/* sprintf variant found in newer libc's which allocates string to print to */
|
|
|
|
|
_X_HIDDEN int _X_ATTRIBUTE_PRINTF(2,3)
|
|
|
|
|
asprintf(char ** ret, const char *format, ...)
|
|
|
|
|
{
|
|
|
|
|
char buf[256];
|
|
|
|
|
int len;
|
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
|
len = vsnprintf(buf, sizeof(buf), format, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
|
|
if (len < 0)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
if (len < sizeof(buf))
|
|
|
|
|
{
|
|
|
|
|
*ret = strdup(buf);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
*ret = malloc(len + 1); /* snprintf doesn't count trailing '\0' */
|
|
|
|
|
if (*ret != NULL)
|
|
|
|
|
{
|
|
|
|
|
va_start(ap, format);
|
|
|
|
|
len = vsnprintf(*ret, len + 1, format, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
if (len < 0) {
|
|
|
|
|
free(*ret);
|
|
|
|
|
*ret = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*ret == NULL)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
return len;
|
|
|
|
|
}
|
2006-11-25 13:07:29 -07:00
|
|
|
|
#endif
|
|
|
|
|
|
2015-05-10 03:56:05 -06:00
|
|
|
|
|
2006-11-25 13:07:29 -07:00
|
|
|
|
|
|
|
|
|
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
|
2009-10-23 14:31:39 -06:00
|
|
|
|
write_counted_string(FILE *file, char *string)
|
2006-11-25 13:07:29 -07:00
|
|
|
|
{
|
|
|
|
|
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
|
2009-10-23 14:31:39 -06:00
|
|
|
|
read_byte(FILE *file, unsigned char *bp)
|
2006-11-25 13:07:29 -07:00
|
|
|
|
{
|
|
|
|
|
if (fread ((char *) bp, 1, 1, file) != 1)
|
|
|
|
|
return 0;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2009-10-23 14:31:39 -06:00
|
|
|
|
read_short(FILE *file, unsigned short *shortp)
|
2006-11-25 13:07:29 -07:00
|
|
|
|
{
|
|
|
|
|
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
|
2009-10-23 14:31:39 -06:00
|
|
|
|
read_counted_string(FILE *file, char **stringp)
|
2006-11-25 13:07:29 -07:00
|
|
|
|
{
|
|
|
|
|
unsigned char len;
|
|
|
|
|
char *data;
|
|
|
|
|
|
|
|
|
|
if (read_byte (file, &len) == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
if (len == 0) {
|
2009-10-23 14:31:39 -06:00
|
|
|
|
data = NULL;
|
2006-11-25 13:07:29 -07:00
|
|
|
|
} 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
|
2009-10-23 14:31:39 -06:00
|
|
|
|
WriteProxyFileEntry(FILE *proxyFile, WinInfo *theWindow)
|
2006-11-25 13:07:29 -07:00
|
|
|
|
{
|
|
|
|
|
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
|
2009-10-23 14:31:39 -06:00
|
|
|
|
ReadProxyFileEntry(FILE *proxyFile, ProxyFileEntry **pentry)
|
2006-11-25 13:07:29 -07:00
|
|
|
|
{
|
|
|
|
|
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)
|
2011-08-28 04:21:07 -06:00
|
|
|
|
{
|
|
|
|
|
if (entry->wm_command_count)
|
|
|
|
|
{
|
|
|
|
|
for (i = 0; i < entry->wm_command_count; i++)
|
|
|
|
|
if (entry->wm_command[i])
|
|
|
|
|
free (entry->wm_command[i]);
|
|
|
|
|
}
|
2006-11-25 13:07:29 -07:00
|
|
|
|
free ((char *) entry->wm_command);
|
2011-08-28 04:21:07 -06:00
|
|
|
|
}
|
|
|
|
|
|
2006-11-25 13:07:29 -07:00
|
|
|
|
free ((char *) entry);
|
|
|
|
|
*pentry = NULL;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2009-10-23 14:31:39 -06:00
|
|
|
|
ReadProxyFile(char *filename)
|
2006-11-25 13:07:29 -07:00
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char *
|
2015-05-10 03:56:05 -06:00
|
|
|
|
unique_filename(const char *path, const char *prefix, int *pFd)
|
2006-11-25 13:07:29 -07:00
|
|
|
|
{
|
2015-05-10 03:56:05 -06:00
|
|
|
|
char *tempFile = NULL;
|
|
|
|
|
int tempFd = 0;
|
|
|
|
|
|
|
|
|
|
#if defined(HAVE_MKSTEMP) || defined(HAVE_MKTEMP)
|
|
|
|
|
if (asprintf (&tempFile, "%s/%sXXXXXX", path, prefix) == -1)
|
|
|
|
|
return NULL;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_MKSTEMP
|
|
|
|
|
tempFd = mkstemp(tempFile);
|
2006-11-25 13:07:29 -07:00
|
|
|
|
#else
|
|
|
|
|
|
2015-05-10 03:56:05 -06:00
|
|
|
|
# ifdef HAVE_MKTEMP
|
|
|
|
|
if (mktemp(tempFile) == NULL)
|
|
|
|
|
tempFd = -1;
|
|
|
|
|
# else /* fallback to tempnam */
|
|
|
|
|
tempFile = tempnam (path, prefix);
|
|
|
|
|
# endif /* HAVE_MKTEMP */
|
|
|
|
|
|
|
|
|
|
if (tempFd != -1 && tempFile != NULL)
|
|
|
|
|
tempFd = open(tempFile, O_RDWR | O_CREAT | O_EXCL, 0600);
|
2006-11-25 13:07:29 -07:00
|
|
|
|
#endif
|
|
|
|
|
|
2015-05-10 03:56:05 -06:00
|
|
|
|
if (tempFd == -1) {
|
|
|
|
|
free(tempFile);
|
|
|
|
|
return (NULL);
|
2006-11-25 13:07:29 -07:00
|
|
|
|
}
|
2015-05-10 03:56:05 -06:00
|
|
|
|
|
|
|
|
|
*pFd = tempFd;
|
|
|
|
|
return tempFile;
|
|
|
|
|
|
2006-11-25 13:07:29 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char *
|
2009-10-23 14:31:39 -06:00
|
|
|
|
WriteProxyFile(void)
|
2006-11-25 13:07:29 -07:00
|
|
|
|
{
|
|
|
|
|
FILE *proxyFile = NULL;
|
|
|
|
|
char *filename = NULL;
|
2015-05-10 03:56:05 -06:00
|
|
|
|
int fd = -1;
|
|
|
|
|
const char *path;
|
2006-11-25 13:07:29 -07:00
|
|
|
|
WinInfo *winptr;
|
|
|
|
|
Bool success = False;
|
|
|
|
|
|
|
|
|
|
path = getenv ("SM_SAVE_DIR");
|
|
|
|
|
if (!path)
|
|
|
|
|
{
|
|
|
|
|
path = getenv ("HOME");
|
|
|
|
|
if (!path)
|
|
|
|
|
path = ".";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((filename = unique_filename (path, ".prx", &fd)) == NULL)
|
|
|
|
|
goto bad;
|
|
|
|
|
|
|
|
|
|
if (!(proxyFile = fdopen(fd, "wb")))
|
|
|
|
|
goto bad;
|
2015-05-10 03:56:05 -06:00
|
|
|
|
|
2006-11-25 13:07:29 -07:00
|
|
|
|
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);
|
2015-05-10 03:56:05 -06:00
|
|
|
|
else if (fd != -1)
|
|
|
|
|
close (fd);
|
2006-11-25 13:07:29 -07:00
|
|
|
|
|
|
|
|
|
if (success)
|
|
|
|
|
return (filename);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (filename)
|
|
|
|
|
free (filename);
|
|
|
|
|
return (NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char *
|
2009-10-23 14:31:39 -06:00
|
|
|
|
LookupClientID(WinInfo *theWindow)
|
2006-11-25 13:07:29 -07:00
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|