|
|
1.1 ! root 1: #ifndef lint ! 2: static char *rcsid_xinit_c = "$XConsortium: xinit.c,v 11.32 88/10/05 09:27:45 jim Exp $"; ! 3: #endif /* lint */ ! 4: #include <X11/copyright.h> ! 5: ! 6: /* Copyright Massachusetts Institute of Technology 1986 */ ! 7: ! 8: #include <X11/Xos.h> ! 9: #include <X11/Xlib.h> ! 10: #include <stdio.h> ! 11: #include <ctype.h> ! 12: #include <signal.h> ! 13: #include <sys/resource.h> ! 14: #ifndef SYSV ! 15: #include <sys/wait.h> ! 16: #endif ! 17: #include <errno.h> ! 18: extern int sys_nerr; ! 19: #ifdef hpux ! 20: #include <sys/utsname.h> ! 21: #endif ! 22: #include <setjmp.h> ! 23: ! 24: extern char *getenv(); ! 25: extern char **environ; ! 26: char **newenviron = NULL; ! 27: ! 28: #ifndef SHELL ! 29: #define SHELL "sh" ! 30: #endif ! 31: ! 32: #ifdef macII ! 33: #define vfork() fork() ! 34: #endif /* macII */ ! 35: ! 36: #if defined(SYSV) && !defined(hpux) ! 37: #define vfork() fork() ! 38: #endif /* SYSV and not hpux */ ! 39: ! 40: char *bindir = BINDIR; ! 41: char *server_names[] = { ! 42: #ifdef vax /* Digital */ ! 43: "Xqvss Digital monochrome display on Microvax II or III series", ! 44: "Xqdss Digital color display on Microvax II or III series", ! 45: #endif ! 46: #ifdef sun /* Sun */ ! 47: "Xsun Sun monochrome and color displays on Sun 2, 3, or 4 series", ! 48: #endif ! 49: #ifdef hpux /* HP */ ! 50: "Xhp HP monochrome and colors displays on 9000/300 series", ! 51: #endif ! 52: #ifdef apollo /* Apollo */ ! 53: "Xapollo Apollo monochrome and color displays", ! 54: #endif ! 55: #ifdef ibm /* IBM */ ! 56: "Xibm IBM AED, APA, 8514a, megapel, VGA displays on PC/RT", ! 57: #endif ! 58: #ifdef macII /* MacII */ ! 59: "XmacII Apple monochrome display on Macintosh II", ! 60: #endif ! 61: #ifdef M4310 /* Tektronix Pegasus */ ! 62: "Xpeg Tektronix Pegasus display on 4310", ! 63: #endif ! 64: #if defined(vax) || defined(sun) /* Parallax */ ! 65: "Xplx Parallax color and video graphics controller", ! 66: #endif ! 67: NULL}; ! 68: ! 69: #ifndef XINITRC ! 70: #define XINITRC ".xinitrc" ! 71: #endif ! 72: char xinitrcbuf[256]; ! 73: ! 74: #ifndef XSERVERRC ! 75: #define XSERVERRC ".xserverrc" ! 76: #endif ! 77: char xserverrcbuf[256]; ! 78: ! 79: #define TRUE 1 ! 80: #define FALSE 0 ! 81: #define OK_EXIT 0 ! 82: #define ERR_EXIT 1 ! 83: #ifdef ISOCONN ! 84: char displayname[100] = ":X0"; ! 85: #else /* ISOCONN */ ! 86: char displayname[100] = "unix"; ! 87: #endif /* ISOCONN */ ! 88: char client_display[100]; ! 89: ! 90: #ifdef ISOCONN ! 91: char *default_server = "Xsun"; ! 92: char *default_display = ":X0"; /* choose most efficient */ ! 93: char *default_client[] = {"xt", NULL}; ! 94: #else /* ISOCONN */ ! 95: char *default_server = "X"; ! 96: char *default_display = ":0"; /* choose most efficient */ ! 97: char *default_client[] = {"xterm", "-geometry", "+1+1", "-n", "login", "-display perky:X0", NULL}; ! 98: #endif /* ISOCONN */ ! 99: char *serverargv[100]; ! 100: char *clientargv[100]; ! 101: char **server = serverargv + 2; /* make sure room for sh .xserverrc args */ ! 102: char **client = clientargv + 2; /* make sure room for sh .xinitrc args */ ! 103: char *displayNum; ! 104: char *program; ! 105: Display *xd; /* server connection */ ! 106: #ifndef SYSV ! 107: union wait status; ! 108: #endif /* SYSV */ ! 109: int serverpid = -1; ! 110: int clientpid = -1; ! 111: extern int errno; ! 112: ! 113: sigCatch(sig) ! 114: int sig; ! 115: { ! 116: signal(SIGQUIT, SIG_IGN); ! 117: signal(SIGINT, SIG_IGN); ! 118: Error("unexpected signal %d\r\n", sig); ! 119: shutdown(serverpid, clientpid); ! 120: exit(1); ! 121: } ! 122: ! 123: #ifdef SYSV ! 124: sigAlarm(sig) ! 125: int sig; ! 126: { ! 127: signal (sig, sigAlarm); ! 128: } ! 129: #endif /* SYSV */ ! 130: ! 131: static Execute (vec) ! 132: char **vec; /* has room from up above */ ! 133: { ! 134: execvp (vec[0], vec); ! 135: if (access (vec[0], R_OK) == 0) { ! 136: vec--; /* back it up to stuff shell in */ ! 137: vec[0] = SHELL; ! 138: execvp (vec[0], vec); ! 139: } ! 140: return; ! 141: } ! 142: ! 143: main(argc, argv) ! 144: int argc; ! 145: register char **argv; ! 146: { ! 147: register char **sptr = server; ! 148: register char **cptr = client; ! 149: register char **ptr; ! 150: int pid, i; ! 151: int client_given = 0, server_given = 0; ! 152: int client_args_given = 0, server_args_given = 0; ! 153: int start_of_client_args, start_of_server_args; ! 154: #ifdef ISOCONN ! 155: extern char *index(); ! 156: char *cd; ! 157: #endif /* ISOCONN */ ! 158: ! 159: program = *argv++; ! 160: argc--; ! 161: ! 162: #ifndef UNIXCONN ! 163: #ifdef hpux ! 164: /* Why not use gethostname()? Well, at least on my system, I've had to ! 165: * make an ugly kernel patch to get a name longer than 8 characters, and ! 166: * uname() lets me access to the whole string (it smashes release, you ! 167: * see), whereas gethostname() kindly truncates it for me. ! 168: */ ! 169: { ! 170: struct utsname name; ! 171: ! 172: uname(&name); ! 173: strcpy(displayname, name.nodename); ! 174: } ! 175: #else ! 176: gethostname(displayname, sizeof(displayname)); ! 177: #ifdef ISOCONN ! 178: if ((cd = index(displayname, '.')) != NULL) ! 179: *cd = '\0'; ! 180: #endif /* ISOCONN */ ! 181: #endif ! 182: #endif /* UNIXCONN */ ! 183: /* ! 184: * copy the client args. ! 185: */ ! 186: if (argc == 0 || ! 187: (**argv != '/' && **argv != '.' && !isalpha(**argv))) { ! 188: for (ptr = default_client; *ptr; ) ! 189: *cptr++ = *ptr++; ! 190: strcpy(client_display, displayname); ! 191: strcat(client_display, default_display); ! 192: *cptr++ = client_display; ! 193: #ifdef sun ! 194: /* ! 195: * If running on a sun, and if WINDOW_PARENT isn't defined, ! 196: * that means SunWindows isn't running, so we should pass ! 197: * the -C flag to xterm so that it sets up a console. ! 198: */ ! 199: if ( getenv("WINDOW_PARENT") == NULL ) ! 200: *cptr++ = "-C"; ! 201: #endif /* sun */ ! 202: } else { ! 203: client_given = 1; ! 204: } ! 205: start_of_client_args = (cptr - client); ! 206: while (argc && strcmp(*argv, "--")) { ! 207: client_args_given++; ! 208: *cptr++ = *argv++; ! 209: argc--; ! 210: } ! 211: *cptr = NULL; ! 212: if (argc) { ! 213: argv++; ! 214: argc--; ! 215: } ! 216: ! 217: /* ! 218: * Copy the server args. ! 219: */ ! 220: if (argc == 0 || ! 221: (**argv != '/' && **argv != '.' && !isalpha(**argv))) { ! 222: *sptr++ = default_server; ! 223: } else { ! 224: server_given = 1; ! 225: *sptr++ = *argv++; ! 226: argc--; ! 227: } ! 228: if (argc > 0 && (argv[0][0] == ':' && isdigit(argv[0][1]))) ! 229: displayNum = *argv; ! 230: else ! 231: displayNum = *sptr++ = default_display; ! 232: ! 233: start_of_server_args = (sptr - server); ! 234: while (--argc >= 0) { ! 235: server_args_given++; ! 236: *sptr++ = *argv++; ! 237: } ! 238: *sptr = NULL; ! 239: ! 240: ! 241: strcat(displayname, displayNum); ! 242: ! 243: /* ! 244: * if no client arguments given, check for a startup file and copy ! 245: * that into the argument list ! 246: */ ! 247: if (!client_given) { ! 248: char *cp; ! 249: Bool required = False; ! 250: ! 251: xinitrcbuf[0] = '\0'; ! 252: if ((cp = getenv ("XINITRC")) != NULL) { ! 253: strcpy (xinitrcbuf, cp); ! 254: required = True; ! 255: } else if ((cp = getenv ("HOME")) != NULL) { ! 256: (void) sprintf (xinitrcbuf, "%s/%s", cp, XINITRC); ! 257: } ! 258: if (xinitrcbuf[0]) { ! 259: if (access (xinitrcbuf, F_OK) == 0) { ! 260: client += start_of_client_args - 1; ! 261: client[0] = xinitrcbuf; ! 262: } else if (required) { ! 263: fprintf (stderr, ! 264: "%s: warning, no client init file \"%s\"\n", ! 265: program, xinitrcbuf); ! 266: } ! 267: } ! 268: } ! 269: ! 270: /* ! 271: * if no server arguments given, check for a startup file and copy ! 272: * that into the argument list ! 273: */ ! 274: if (!server_given) { ! 275: char *cp; ! 276: Bool required = False; ! 277: ! 278: xserverrcbuf[0] = '\0'; ! 279: if ((cp = getenv ("XSERVERRC")) != NULL) { ! 280: strcpy (xserverrcbuf, cp); ! 281: required = True; ! 282: } else if ((cp = getenv ("HOME")) != NULL) { ! 283: (void) sprintf (xserverrcbuf, "%s/%s", cp, XSERVERRC); ! 284: } ! 285: if (xserverrcbuf[0]) { ! 286: if (access (xserverrcbuf, F_OK) == 0) { ! 287: server += start_of_server_args - 1; ! 288: server[0] = xserverrcbuf; ! 289: } else if (required) { ! 290: fprintf (stderr, ! 291: "%s: warning, no server init file \"%s\"\n", ! 292: program, xserverrcbuf); ! 293: } ! 294: } ! 295: } ! 296: ! 297: ! 298: /* ! 299: * put the display name into the environment ! 300: */ ! 301: set_environment (); ! 302: ! 303: /* ! 304: * Start the server and client. ! 305: */ ! 306: signal(SIGQUIT, sigCatch); ! 307: signal(SIGINT, sigCatch); ! 308: #ifdef SYSV ! 309: signal(SIGALRM, sigAlarm); ! 310: #endif /* SYSV */ ! 311: if ((serverpid = startServer(server)) > 0 ! 312: && (clientpid = startClient(client)) > 0) { ! 313: pid = -1; ! 314: while (pid != clientpid && pid != serverpid) ! 315: pid = wait(NULL); ! 316: } ! 317: signal(SIGQUIT, SIG_IGN); ! 318: signal(SIGINT, SIG_IGN); ! 319: ! 320: shutdown(serverpid, clientpid); ! 321: ! 322: if (serverpid < 0 || clientpid < 0) ! 323: exit(ERR_EXIT); ! 324: exit(OK_EXIT); ! 325: } ! 326: ! 327: ! 328: /* ! 329: * waitforserver - wait for X server to start up ! 330: */ ! 331: ! 332: waitforserver(serverpid) ! 333: int serverpid; ! 334: { ! 335: int ncycles = 120; /* # of cycles to wait */ ! 336: int cycles; /* Wait cycle count */ ! 337: ! 338: #ifdef ISOCONN ! 339: sleep(2); ! 340: #endif ! 341: for (cycles = 0; cycles < ncycles; cycles++) { ! 342: if (xd = XOpenDisplay(displayname)) { ! 343: return(TRUE); ! 344: } ! 345: else { ! 346: #define MSG "X server to begin accepting connections" ! 347: if (!processTimeout (serverpid, 1, MSG)) ! 348: break; ! 349: #undef MSG ! 350: } ! 351: } ! 352: ! 353: fprintf (stderr, "giving up.\r\n"); ! 354: return(FALSE); ! 355: } ! 356: ! 357: /* ! 358: * return TRUE if we timeout waiting for pid to exit, FALSE otherwise. ! 359: */ ! 360: processTimeout(pid, timeout, string) ! 361: int pid, timeout; ! 362: char *string; ! 363: { ! 364: int i = 0, pidfound = -1; ! 365: static char *laststring; ! 366: ! 367: for (;;) { ! 368: #ifdef SYSV ! 369: alarm(1); ! 370: if ((pidfound = wait(NULL)) == pid) ! 371: break; ! 372: alarm(0); ! 373: #else /* SYSV */ ! 374: if ((pidfound = wait3(&status, WNOHANG, NULL)) == pid) ! 375: break; ! 376: #endif /* SYSV */ ! 377: if (timeout) { ! 378: if (i == 0 && string != laststring) ! 379: fprintf(stderr, "\r\nwaiting for %s ", string); ! 380: else ! 381: fprintf(stderr, "."); ! 382: fflush(stderr); ! 383: } ! 384: if (timeout) ! 385: sleep (1); ! 386: if (++i > timeout) ! 387: break; ! 388: } ! 389: laststring = string; ! 390: return( pid != pidfound ); ! 391: } ! 392: ! 393: Error(fmt, x0,x1,x2,x3,x4,x5,x6,x7,x8,x9) ! 394: char *fmt; ! 395: { ! 396: extern char *sys_errlist[]; ! 397: ! 398: fprintf(stderr, "%s: ", program); ! 399: if (errno > 0 && errno < sys_nerr) ! 400: fprintf (stderr, "%s (errno %d): ", sys_errlist[errno], errno); ! 401: fprintf(stderr, fmt, x0,x1,x2,x3,x4,x5,x6,x7,x8,x9); ! 402: } ! 403: ! 404: Fatal(fmt, x0,x1,x2,x3,x4,x5,x6,x7,x8,x9) ! 405: char *fmt; ! 406: { ! 407: Error(fmt, x0,x1,x2,x3,x4,x5,x6,x7,x8,x9); ! 408: exit(ERR_EXIT); ! 409: } ! 410: ! 411: startServer(server) ! 412: char *server[]; ! 413: { ! 414: int serverpid; ! 415: ! 416: serverpid = vfork(); ! 417: switch(serverpid) { ! 418: case 0: ! 419: close(0); ! 420: close(1); ! 421: ! 422: /* ! 423: * don't hang on read/write to control tty ! 424: */ ! 425: #ifdef SIGTTIN ! 426: (void) signal(SIGTTIN, SIG_IGN); ! 427: #endif ! 428: #ifdef SIGTTOU ! 429: (void) signal(SIGTTOU, SIG_IGN); ! 430: #endif ! 431: ! 432: /* ! 433: * prevent server from getting sighup from vhangup() ! 434: * if client is xterm -L ! 435: */ ! 436: setpgrp(0,getpid()); ! 437: ! 438: Execute (server); ! 439: Error ("no server \"%s\" in PATH\n", server[0]); ! 440: { ! 441: char **cpp; ! 442: ! 443: fprintf (stderr, ! 444: "\nUse the -- option, or make sure that %s is in your path and\n", ! 445: bindir); ! 446: fprintf (stderr, ! 447: "that \"%s\" is a program or a link to the right type of server\n", ! 448: server[0]); ! 449: fprintf (stderr, ! 450: "for your display. Possible server names include:\n\n"); ! 451: for (cpp = server_names; *cpp; cpp++) { ! 452: fprintf (stderr, " %s\n", *cpp); ! 453: } ! 454: fprintf (stderr, "\n"); ! 455: } ! 456: exit (ERR_EXIT); ! 457: ! 458: break; ! 459: case -1: ! 460: break; ! 461: default: ! 462: /* ! 463: * don't nice server ! 464: */ ! 465: #ifdef PRIO_PROCESS ! 466: setpriority( PRIO_PROCESS, serverpid, -1 ); ! 467: #endif ! 468: ! 469: errno = 0; ! 470: if (! processTimeout(serverpid, 0, "")) { ! 471: serverpid = -1; ! 472: break; ! 473: } ! 474: /* ! 475: * kludge to avoid race with TCP, giving server time to ! 476: * set his socket options before we try to open it ! 477: */ ! 478: sleep(5); ! 479: ! 480: if (waitforserver(serverpid) == 0) { ! 481: Error("unable to connect to X server\r\n"); ! 482: shutdown(serverpid, -1); ! 483: serverpid = -1; ! 484: } ! 485: break; ! 486: } ! 487: ! 488: return(serverpid); ! 489: } ! 490: ! 491: startClient(client) ! 492: char *client[]; ! 493: { ! 494: int clientpid; ! 495: ! 496: if ((clientpid = vfork()) == 0) { ! 497: setuid(getuid()); ! 498: setpgrp(0, getpid()); ! 499: environ = newenviron; ! 500: Execute (client); ! 501: Error ("no program named \"%s\" in PATH\r\n", client[0]); ! 502: fprintf (stderr, ! 503: "\nSpecify a program on the command line or make sure that %s\r\n", bindir); ! 504: fprintf (stderr, ! 505: "is in your path.\r\n"); ! 506: fprintf (stderr, "\n"); ! 507: exit (ERR_EXIT); ! 508: } ! 509: return (clientpid); ! 510: } ! 511: ! 512: #ifdef SYSV ! 513: #define killpg(pgrp, sig) kill(-(pgrp), sig) ! 514: #endif /* SYSV */ ! 515: ! 516: static jmp_buf close_env; ! 517: ! 518: static int ignorexio (dpy) ! 519: Display *dpy; ! 520: { ! 521: fprintf (stderr, "%s: connection to X server lost.\r\n", program); ! 522: longjmp (close_env, 1); ! 523: return; ! 524: } ! 525: ! 526: static ! 527: shutdown(serverpid, clientpid) ! 528: int serverpid, clientpid; ! 529: { ! 530: /* have kept display opened, so close it now */ ! 531: if (clientpid > 0) { ! 532: XSetIOErrorHandler (ignorexio); ! 533: if (! setjmp(close_env)) { ! 534: XCloseDisplay(xd); ! 535: } ! 536: ! 537: /* HUP all local clients to allow them to clean up */ ! 538: errno = 0; ! 539: if ((killpg(clientpid, SIGHUP) != 0) && ! 540: (errno != ESRCH)) ! 541: Error("can't send HUP to process group %d\r\n", ! 542: clientpid); ! 543: } ! 544: ! 545: if (serverpid < 0) ! 546: return; ! 547: errno = 0; ! 548: if (killpg(serverpid, SIGTERM) < 0) { ! 549: if (errno == EPERM) ! 550: Fatal("Can't kill X server\r\n"); ! 551: if (errno == ESRCH) ! 552: return; ! 553: } ! 554: if (! processTimeout(serverpid, 10, "X server to shut down")) { ! 555: fprintf (stderr, "\r\n"); ! 556: return; ! 557: } ! 558: ! 559: fprintf(stderr, ! 560: "\r\n%s: X server slow to shut down, sending KILL signal.\r\n", ! 561: program); ! 562: fflush(stderr); ! 563: errno = 0; ! 564: if (killpg(serverpid, SIGKILL) < 0) { ! 565: if (errno == ESRCH) ! 566: return; ! 567: } ! 568: if (processTimeout(serverpid, 3, "server to die")) { ! 569: fprintf (stderr, "\r\n"); ! 570: Fatal("Can't kill server\r\n"); ! 571: } ! 572: fprintf (stderr, "\r\n"); ! 573: return; ! 574: } ! 575: ! 576: ! 577: /* ! 578: * make a new copy of environment that has room for DISPLAY ! 579: */ ! 580: ! 581: set_environment () ! 582: { ! 583: int nenvvars; ! 584: char **newPtr, **oldPtr; ! 585: static char displaybuf[256]; ! 586: ! 587: /* count number of environment variables */ ! 588: for (oldPtr = environ; *oldPtr; oldPtr++) ; ! 589: ! 590: nenvvars = (oldPtr - environ); ! 591: newenviron = (char **) malloc ((nenvvars + 2) * sizeof(char **)); ! 592: if (!newenviron) { ! 593: fprintf (stderr, ! 594: "%s: unable to allocate %d pointers for environment\n", ! 595: program, nenvvars + 2); ! 596: exit (1); ! 597: } ! 598: ! 599: /* put DISPLAY=displayname as first element */ ! 600: strcpy (displaybuf, "DISPLAY="); ! 601: strcpy (displaybuf + 8, displayname); ! 602: newPtr = newenviron; ! 603: *newPtr++ = displaybuf; ! 604: ! 605: /* copy pointers to other variables */ ! 606: for (oldPtr = environ; *oldPtr; oldPtr++) { ! 607: if (strncmp (*oldPtr, "DISPLAY=", 8) != 0) { ! 608: *newPtr++ = *oldPtr; ! 609: } ! 610: } ! 611: *newPtr = NULL; ! 612: return; ! 613: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.