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