#include <X11/Xtrans.h>
#include "osstruct.h"
#include <stdio.h>
#include <stdlib.h>
#define XK_LATIN1
#include <X11/keysymdef.h>
#ifdef __UNIXOS2__
#define _NFILE 256
#endif
Bool drone_server = FALSE;
extern char *progname;
extern char *configfilename;
static int num_alts;
static AlternateServerPtr alt_servers = (AlternateServerPtr) 0;
extern XtransConnInfo *ListenTransConns;
extern int *ListenTransFds;
extern int ListenTransCount;
static char *catalogue_name = "all";
static Bool
pattern_match(char *pat, int plen, char *string)
{
register int i,
l;
int j,
m,
res;
register char cp,
cs;
int head,
tail;
head = 0;
tail = plen;
res = -1;
for (i = 0; i < head; i++) {
cp = pat[i];
if (cp == XK_question) {
if (!string[i])
return res;
res = 0;
} else if (cp != string[i])
return res;
}
if (head == plen)
return (string[head] ? res : 1);
l = head;
while (++i < tail) {
j = i;
m = l;
while ((cp = pat[i]) != XK_asterisk) {
if (!(cs = string[l]))
return 0;
if ((cp != cs) && (cp != XK_question)) {
m++;
cp = pat[j];
if (cp == XK_asterisk) {
if (!string[m])
return 0;
} else {
while ((cs = string[m]) != cp) {
if (!cs)
return 0;
m++;
}
}
l = m;
i = j;
}
l++;
i++;
}
}
m = strlen(&string[l]);
j = plen - tail;
if (m < j)
return 0;
l = (l + m) - j;
while ((cp = pat[i])) {
if ((cp != string[l]) && (cp != XK_question))
return 0;
l++;
i++;
}
return 1;
}
int
ListCatalogues(char *pattern, int patlen, int maxnames,
char **catalogues, int *len)
{
int count = 0;
char *catlist = NULL;
int size = 0;
if (maxnames) {
if (pattern_match(pattern, patlen, catalogue_name)) {
size = strlen(catalogue_name);
catlist = (char *) fsalloc(size + 1);
if (!catlist)
goto bail;
*catlist = size;
memmove( &catlist[1], catalogue_name, size);
size++;
count++;
}
}
bail:
*len = size;
*catalogues = catlist;
return count;
}
int
ValidateCatalogues(int *num, char *cats)
{
char *c = cats;
int i,
len;
for (i = 0; i < *num; i++) {
len = *c++;
if (strncmp(c, catalogue_name, len)) {
*num = i;
return FSBadName;
}
c += len;
}
return FSSuccess;
}
int
SetAlternateServers(char *list)
{
char *t,
*st;
AlternateServerPtr alts,
a;
int num,
i;
t = list;
num = 1;
while (*t) {
if (*t == ',')
num++;
t++;
}
a = alts = (AlternateServerPtr) fsalloc(sizeof(AlternateServerRec) * num);
if (!alts)
return FSBadAlloc;
st = t = list;
a->namelen = 0;
while (*t) {
if (*t == ',') {
a->name = (char *) fsalloc(a->namelen);
if (!a->name) {
return FSBadAlloc;
}
memmove( a->name, st, a->namelen);
a->subset = FALSE;
a++;
t++;
st = t;
a->namelen = 0;
} else {
a->namelen++;
t++;
}
}
a->name = (char *) fsalloc(a->namelen);
if (!a->name) {
return FSBadAlloc;
}
memmove( a->name, st, a->namelen);
a->subset = FALSE;
for (i = 0; i < num_alts; i++) {
fsfree((char *) alt_servers[i].name);
}
fsfree((char *) alt_servers);
num_alts = num;
alt_servers = alts;
return FSSuccess;
}
int
ListAlternateServers(AlternateServerPtr *svrs)
{
*svrs = alt_servers;
return num_alts;
}
int
CloneMyself(void)
{
int child;
char old_listen_arg[256];
char *arg_ptr = old_listen_arg;
int i, j;
int lastfdesc;
char portnum[20];
assert(!drone_server);
if (!CloneSelf)
return -1;
#ifdef __UNIXOS2__
NoticeF("cloning of font server not supported under OS/2!\n");
return(-1);
#endif
old_listen_arg[0] = '\0';
#ifdef XNO_SYSCONF
#undef _SC_OPEN_MAX
#endif
#ifdef _SC_OPEN_MAX
lastfdesc = sysconf(_SC_OPEN_MAX) - 1;
#else
#if defined(hpux) || defined(__UNIXOS2__)
lastfdesc = _NFILE - 1;
#else
lastfdesc = getdtablesize() - 1;
#endif
#endif
NoticeF("attempting clone...\n");
chdir("/");
child = fork();
if (child == -1) {
ErrorF("clone failed to fork()\n");
return -1;
}
if (child == 0) {
StopListening();
NoticeF("clone: child becoming drone\n");
drone_server = TRUE;
return 1;
} else {
NoticeF("clone: parent revitalizing as %s\n", progname);
CloseErrors();
for (i = 3; i < lastfdesc; i++)
{
for (j = 0; j < ListenTransCount; j++)
if (ListenTransFds[j] == i)
break;
if (j >= ListenTransCount)
(void) close(i);
}
for (i = 0; i < ListenTransCount; i++)
{
int trans_id, fd;
char *port;
if (!_FontTransGetReopenInfo (ListenTransConns[i],
&trans_id, &fd, &port))
continue;
sprintf (arg_ptr, "%d/%d/%s", trans_id, fd, port);
arg_ptr += strlen (arg_ptr);
free (port);
if (i < ListenTransCount - 1)
{
strcat (arg_ptr, ",");
arg_ptr++;
}
}
sprintf (portnum, "%d", ListenPort);
if (*old_listen_arg != '\0')
execlp(progname, progname,
"-ls", old_listen_arg,
"-cf", configfilename,
"-port", portnum,
(void *)NULL);
InitErrors();
Error("clone failed");
FatalError("failed to clone self\n");
}
return 0;
}