osglue.c revision bbe1b32b
1/* $Xorg: osglue.c,v 1.4 2001/02/09 02:05:44 xorgcvs Exp $ */
2/*
3Copyright 1987, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24 * Copyright 1990, 1991 Network Computing Devices;
25 * Portions Copyright 1987 by Digital Equipment Corporation
26 *
27 * Permission to use, copy, modify, distribute, and sell this software and its
28 * documentation for any purpose is hereby granted without fee, provided that
29 * the above copyright notice appear in all copies and that both that
30 * copyright notice and this permission notice appear in supporting
31 * documentation, and that the names of Network Computing Devices,
32 * or Digital not be used in advertising or
33 * publicity pertaining to distribution of the software without specific,
34 * written prior permission.  Network Computing Devices, or Digital
35 * make no representations about the
36 * suitability of this software for any purpose.  It is provided "as is"
37 * without express or implied warranty.
38 *
39 * NETWORK COMPUTING DEVICES, AND DIGITAL DISCLAIM ALL WARRANTIES WITH
40 * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
41 * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, OR DIGITAL BE
42 * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
43 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
44 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
45 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
46 *
47 * $NCDXorg: @(#)osglue.c,v 4.6 1991/07/09 14:07:30 lemke Exp $
48 *
49 */
50/* $XFree86: xc/programs/xfs/os/osglue.c,v 3.18 2002/10/15 01:45:03 dawes Exp $ */
51
52/*
53 * this is miscellaneous OS specific stuff.
54 *
55 * Catalogue support, alternate servers, and cloneing
56 */
57
58#include <X11/Xtrans/Xtrans.h>
59#include "osstruct.h"
60#include <stdio.h>
61#include <stdlib.h>
62#define  XK_LATIN1
63#include <X11/keysymdef.h>
64#ifdef __UNIXOS2__
65#define _NFILE 256
66#endif
67
68Bool        drone_server = FALSE;
69extern char *progname;
70extern char *configfilename;
71
72static int  num_alts;
73static AlternateServerPtr alt_servers = (AlternateServerPtr) 0;
74
75extern XtransConnInfo 	*ListenTransConns;
76extern int	       	*ListenTransFds;
77extern int		ListenTransCount;
78
79/*
80 * XXX
81 *
82 * Catalogue support is absolutely minimal.  Some guts are here, but
83 * we don't actually do anything with them so the only one exported is
84 * 'all'.  Be warned that other parts of the server may incorrectly
85 * assume the catalogue list is global, and will therefore need fixing.
86 *
87 */
88
89static char *catalogue_name = "all";
90
91static Bool			/* stolen from R4 Match() */
92pattern_match(char *pat, int plen, char *string)
93{
94    register int i,
95                l;
96    int         j,
97                m,
98                res;
99    register char cp,
100                cs;
101    int         head,
102                tail;
103
104    head = 0;
105    tail = plen;
106
107    res = -1;
108    for (i = 0; i < head; i++) {
109	cp = pat[i];
110	if (cp == XK_question) {
111	    if (!string[i])
112		return res;
113	    res = 0;
114	} else if (cp != string[i])
115	    return res;
116    }
117    if (head == plen)
118	return (string[head] ? res : 1);
119    l = head;
120    while (++i < tail) {
121	/* we just skipped an asterisk */
122	j = i;
123	m = l;
124	while ((cp = pat[i]) != XK_asterisk) {
125	    if (!(cs = string[l]))
126		return 0;
127	    if ((cp != cs) && (cp != XK_question)) {
128		m++;
129		cp = pat[j];
130		if (cp == XK_asterisk) {
131		    if (!string[m])
132			return 0;
133		} else {
134		    while ((cs = string[m]) != cp) {
135			if (!cs)
136			    return 0;
137			m++;
138		    }
139		}
140		l = m;
141		i = j;
142	    }
143	    l++;
144	    i++;
145	}
146    }
147    m = strlen(&string[l]);
148    j = plen - tail;
149    if (m < j)
150	return 0;
151    l = (l + m) - j;
152    while ((cp = pat[i])) {
153	if ((cp != string[l]) && (cp != XK_question))
154	    return 0;
155	l++;
156	i++;
157    }
158    return 1;
159}
160
161int
162ListCatalogues(char *pattern, int patlen, int maxnames,
163	       char **catalogues, int *len)
164{
165    int         count = 0;
166    char       *catlist = NULL;
167    int         size = 0;
168
169    if (maxnames) {
170	if (pattern_match(pattern, patlen, catalogue_name)) {
171	    size = strlen(catalogue_name);
172	    catlist = (char *) fsalloc(size + 1);
173	    if (!catlist)
174		goto bail;
175	    *catlist = size;
176	    memmove( &catlist[1], catalogue_name, size);
177	    size++;		/* for length */
178	    count++;
179	}
180    }
181bail:
182    *len = size;
183    *catalogues = catlist;
184    return count;
185}
186
187/*
188 * check if catalogue list is valid
189 */
190
191int
192ValidateCatalogues(int *num, char *cats)
193{
194    char       *c = cats;
195    int         i,
196                len;
197
198    for (i = 0; i < *num; i++) {
199	len = *c++;
200	if (strncmp(c, catalogue_name, len)) {
201	    *num = i;		/* return bad entry index */
202	    return FSBadName;
203	}
204	c += len;
205    }
206    return FSSuccess;
207}
208
209int
210SetAlternateServers(char *list)
211{
212    char       *t,
213               *st;
214    AlternateServerPtr alts,
215                a;
216    int         num,
217                i;
218
219    t = list;
220    num = 1;
221    while (*t) {
222	if (*t == ',')
223	    num++;
224	t++;
225    }
226
227    a = alts = (AlternateServerPtr) fsalloc(sizeof(AlternateServerRec) * num);
228    if (!alts)
229	return FSBadAlloc;
230
231    st = t = list;
232    a->namelen = 0;
233    while (*t) {
234	if (*t == ',') {
235	    a->name = (char *) fsalloc(a->namelen);
236	    if (!a->name) {
237		/* XXX  -- leak */
238		return FSBadAlloc;
239	    }
240	    memmove( a->name, st, a->namelen);
241	    a->subset = FALSE;	/* XXX */
242	    a++;
243	    t++;
244	    st = t;
245	    a->namelen = 0;
246	} else {
247	    a->namelen++;
248	    t++;
249	}
250    }
251    a->name = (char *) fsalloc(a->namelen);
252    if (!a->name) {
253	/* XXX  -- leak */
254	return FSBadAlloc;
255    }
256    memmove( a->name, st, a->namelen);
257    a->subset = FALSE;		/* XXX */
258
259    for (i = 0; i < num_alts; i++) {
260	fsfree((char *) alt_servers[i].name);
261    }
262    fsfree((char *) alt_servers);
263    num_alts = num;
264    alt_servers = alts;
265    return FSSuccess;
266}
267
268int
269ListAlternateServers(AlternateServerPtr *svrs)
270{
271    *svrs = alt_servers;
272    return num_alts;
273}
274
275/*
276 * here's some fun stuff.  in order to cleanly handle becoming overloaded,
277 * this allows us to clone ourselves.  the parent keeps the Listen
278 * socket open, and sends it to itself.  the child stops listening,
279 * and becomes a drone, hanging out till it loses all its clients.
280 */
281
282int
283CloneMyself(void)
284{
285    int         child;
286    char        old_listen_arg[256];
287    char	*arg_ptr = old_listen_arg;
288    int         i, j;
289    int         lastfdesc;
290    char	portnum[20];
291
292    assert(!drone_server);	/* a drone shouldn't hit this */
293
294    if (!CloneSelf)
295	return -1;
296
297#ifdef __UNIXOS2__
298    NoticeF("cloning of font server not supported under OS/2!\n");
299    return(-1);
300#endif
301
302    old_listen_arg[0] = '\0';
303
304#ifdef XNO_SYSCONF	/* should only be on FreeBSD 1.x and NetBSD 0.x */
305#undef _SC_OPEN_MAX
306#endif
307#ifdef _SC_OPEN_MAX
308    lastfdesc = sysconf(_SC_OPEN_MAX) - 1;
309#else
310#if defined(hpux) || defined(__UNIXOS2__)
311    lastfdesc = _NFILE - 1;
312#else
313    lastfdesc = getdtablesize() - 1;
314#endif				/* hpux */
315#endif
316
317    NoticeF("attempting clone...\n");
318    chdir("/");
319    child = fork();
320    if (child == -1) {
321	/* failed to fork */
322	ErrorF("clone failed to fork()\n");
323	return -1;
324    }
325    /*
326     * Note:  they still share the same process group, and killing the parent
327     * will take out all the kids as well.  this is considered a feature (at
328     * least until i'm convinced otherwise)
329     */
330    if (child == 0) {
331	StopListening();
332	NoticeF("clone: child becoming drone\n");
333	drone_server = TRUE;
334	return 1;
335    } else {			/* parent */
336	NoticeF("clone: parent revitalizing as %s\n", progname);
337	CloseErrors();
338	/* XXX should we close stdio as well? */
339	for (i = 3; i < lastfdesc; i++)
340	{
341	    for (j = 0; j < ListenTransCount; j++)
342		if (ListenTransFds[j] == i)
343		    break;
344
345	    if (j >= ListenTransCount)
346		(void) close(i);
347	}
348
349	for (i = 0; i < ListenTransCount; i++)
350	{
351	    int trans_id, fd;
352	    char *port;
353
354	    if (!_FontTransGetReopenInfo (ListenTransConns[i],
355		&trans_id, &fd, &port))
356		continue;
357
358	    sprintf (arg_ptr, "%d/%d/%s", trans_id, fd, port);
359	    arg_ptr += strlen (arg_ptr);
360	    free (port);
361
362	    if (i < ListenTransCount - 1)
363	    {
364		strcat (arg_ptr, ",");
365		arg_ptr++;
366	    }
367	}
368
369	sprintf (portnum, "%d", ListenPort);
370	if (*old_listen_arg != '\0')
371	    execlp(progname, progname,
372		   "-ls", old_listen_arg,
373		   "-cf", configfilename,
374		   "-port", portnum,
375		   (void *)NULL);
376
377	InitErrors();		/* reopen errors, since we don't want to lose
378				 * this */
379	Error("clone failed");
380	FatalError("failed to clone self\n");
381    }
382    /* NOTREACHED */
383    return 0;
384}
385