diff options
Diffstat (limited to 'os/osglue.c')
-rw-r--r-- | os/osglue.c | 384 |
1 files changed, 384 insertions, 0 deletions
diff --git a/os/osglue.c b/os/osglue.c new file mode 100644 index 0000000..d0dd8cc --- /dev/null +++ b/os/osglue.c @@ -0,0 +1,384 @@ +/* $Xorg: osglue.c,v 1.4 2001/02/09 02:05:44 xorgcvs Exp $ */ +/* +Copyright 1987, 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. + * Copyright 1990, 1991 Network Computing Devices; + * Portions Copyright 1987 by Digital Equipment Corporation + * + * 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, and that the names of Network Computing Devices, + * or Digital not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Network Computing Devices, or Digital + * make no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * NETWORK COMPUTING DEVICES, AND DIGITAL DISCLAIM ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, OR DIGITAL BE + * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $NCDId: @(#)osglue.c,v 4.6 1991/07/09 14:07:30 lemke Exp $ + * + */ + +/* + * this is miscellaneous OS specific stuff. + * + * Catalogue support, alternate servers, and cloneing + */ + +#include <X11/Xtrans.h> +#include "osstruct.h" +#include <stdio.h> +#define XK_LATIN1 +#include <X11/keysymdef.h> + +Bool drone_server = FALSE; +extern Bool CloneSelf; +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; + +/* + * XXX + * + * Catalogue support is absolutely minimal. Some guts are here, but + * we don't actually do anything with them so the only one exported is + * 'all'. Be warned that other parts of the server may incorrectly + * assume the catalogue list is global, and will therefore need fixing. + * + */ + +static char *catalogue_name = "all"; + +static Bool /* stolen from R4 Match() */ +pattern_match(pat, plen, string) + 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) { + /* we just skipped an asterisk */ + 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(pattern, patlen, maxnames, catalogues, len) + 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++; /* for length */ + count++; + } + } +bail: + *len = size; + *catalogues = catlist; + return count; +} + +/* + * check if catalogue list is valid + */ + +int +ValidateCatalogues(num, cats) + 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 bad entry index */ + return FSBadName; + } + c += len; + } + return FSSuccess; +} + +int +SetAlternateServers(list) + 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) { + /* XXX -- leak */ + return FSBadAlloc; + } + memmove( a->name, st, a->namelen); + a->subset = FALSE; /* XXX */ + a++; + t++; + st = t; + a->namelen = 0; + } else { + a->namelen++; + t++; + } + } + a->name = (char *) fsalloc(a->namelen); + if (!a->name) { + /* XXX -- leak */ + return FSBadAlloc; + } + memmove( a->name, st, a->namelen); + a->subset = FALSE; /* XXX */ + + 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(svrs) + AlternateServerPtr *svrs; +{ + *svrs = alt_servers; + return num_alts; +} + +/* + * here's some fun stuff. in order to cleanly handle becoming overloaded, + * this allows us to clone ourselves. the parent keeps the Listen + * socket open, and sends it to itself. the child stops listening, + * and becomes a drone, hanging out till it loses all its clients. + */ +int +CloneMyself() +{ + int child; + char old_listen_arg[256]; + char *arg_ptr = old_listen_arg; + int i, j; + int lastfdesc; + char portnum[20]; + extern int ListenPort; + + assert(!drone_server); /* a drone shouldn't hit this */ + + if (!CloneSelf) + return -1; + + old_listen_arg[0] = '\0'; + +#ifdef XNO_SYSCONF /* should only be on FreeBSD 1.x and NetBSD 0.x */ +#undef _SC_OPEN_MAX +#endif +#ifdef _SC_OPEN_MAX + lastfdesc = sysconf(_SC_OPEN_MAX) - 1; +#else +#ifdef hpux + lastfdesc = _NFILE - 1; +#else + lastfdesc = getdtablesize() - 1; +#endif +#endif + + NoticeF("attempting clone...\n"); + child = fork(); + if (child == -1) { + /* failed to fork */ + ErrorF("Clone failed to fork()\n"); + return -1; + } + /* + * Note: they still share the same process group, and killing the parent + * will take out all the kids as well. this is considered a feature (at + * least until i'm convinced otherwise) + */ + if (child == 0) { + StopListening(); + NoticeF("Clone: child becoming drone\n"); + drone_server = TRUE; + return 1; + } else { /* parent */ + NoticeF("Clone: parent revitalizing as %s\n", progname); + CloseErrors(); + /* XXX should we close stdio as well? */ + 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, + NULL); + + InitErrors(); /* reopen errors, since we don't want to lose + * this */ + Error("Clone failed"); + FatalError("Failed to clone self\n"); + } + /* NOTREACHED */ +} |