home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / clients / xdm / server.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-21  |  8.6 KB  |  407 lines

  1. /*
  2.  * xdm - display manager daemon
  3.  *
  4.  * $XConsortium: server.c,v 1.17 91/09/19 16:26:01 keith Exp $
  5.  *
  6.  * Copyright 1988 Massachusetts Institute of Technology
  7.  *
  8.  * Permission to use, copy, modify, and distribute this software and its
  9.  * documentation for any purpose and without fee is hereby granted, provided
  10.  * that the above copyright notice appear in all copies and that both that
  11.  * copyright notice and this permission notice appear in supporting
  12.  * documentation, and that the name of M.I.T. not be used in advertising or
  13.  * publicity pertaining to distribution of the software without specific,
  14.  * written prior permission.  M.I.T. makes no representations about the
  15.  * suitability of this software for any purpose.  It is provided "as is"
  16.  * without express or implied warranty.
  17.  *
  18.  * Author:  Keith Packard, MIT X Consortium
  19.  */
  20.  
  21. /*
  22.  * server.c - manage the X server
  23.  */
  24.  
  25. # include    "dm.h"
  26. # include    <X11/Xlib.h>
  27. # include    <X11/Xos.h>
  28. # include    <stdio.h>
  29. # include    <signal.h>
  30. # include    <errno.h>
  31.  
  32. static receivedUsr1;
  33.  
  34. extern int  errno;
  35. static serverPause ();
  36.  
  37. static Display    *dpy;
  38.  
  39. /* ARGSUSED */
  40. static SIGVAL
  41. CatchUsr1 (n)
  42.     int n;
  43. {
  44. #ifdef SIGNALS_RESET_WHEN_CAUGHT
  45.     (void) Signal (SIGUSR1, CatchUsr1);
  46. #endif
  47.     Debug ("display manager caught SIGUSR1\n");
  48.     ++receivedUsr1;
  49. }
  50.  
  51. static char *_SysErrorMsg (n)
  52.     int n;
  53. {
  54.     extern char *sys_errlist[];
  55.     extern int sys_nerr;
  56.     char *s = ((n >= 0 && n < sys_nerr) ? sys_errlist[n] : "unknown error");
  57.  
  58.     return (s ? s : "no such error");
  59. }
  60.  
  61. StartServerOnce (d)
  62. struct display    *d;
  63. {
  64.     char    **f;
  65.     char    **argv;
  66.     char    arg[1024];
  67.     char    **parseArgs ();
  68.     int        pid;
  69.  
  70.     Debug ("StartServer for %s\n", d->name);
  71.     receivedUsr1 = 0;
  72.     (void) Signal (SIGUSR1, CatchUsr1);
  73.     argv = d->argv;
  74.     switch (pid = fork ()) {
  75.     case 0:
  76.     CleanUpChild ();
  77.     if (d->authFile) {
  78.         sprintf (arg, "-auth %s", d->authFile);
  79.         argv = parseArgs (argv, arg);
  80.     }
  81.     if (!argv) {
  82.         LogError ("StartServer: no arguments\n");
  83.         sleep ((unsigned) d->openDelay);
  84.         exit (UNMANAGE_DISPLAY);
  85.     }
  86.     for (f = argv; *f; f++)
  87.         Debug ("'%s' ", *f);
  88.     Debug ("\n");
  89.     /*
  90.      * give the server SIGUSR1 ignored,
  91.      * it will notice that and send SIGUSR1
  92.      * when ready
  93.      */
  94.     (void) Signal (SIGUSR1, SIG_IGN);
  95.     (void) execv (argv[0], argv);
  96.     LogError ("server %s cannot be executed\n",
  97.             argv[0]);
  98.     sleep ((unsigned) d->openDelay);
  99.     exit (REMANAGE_DISPLAY);
  100.     case -1:
  101.     LogError ("fork failed, sleeping\n");
  102.     return 0;
  103.     default:
  104.     break;
  105.     }
  106.     Debug ("Server Started %d\n", pid);
  107.     d->serverPid = pid;
  108.     if (serverPause ((unsigned) d->openDelay, pid))
  109.     return FALSE;
  110.     return TRUE;
  111. }
  112.  
  113. StartServer (d)
  114. struct display *d;
  115. {
  116.     int    i;
  117.     int    ret = FALSE;
  118.  
  119.     i = 0;
  120.     while (d->serverAttempts == 0 || i < d->serverAttempts)
  121.     {
  122.     if ((ret = StartServerOnce (d)) == TRUE)
  123.         break;
  124.     sleep (d->openDelay);
  125.     i++;
  126.     }
  127.     return ret;
  128. }
  129.  
  130. /*
  131.  * sleep for t seconds, return 1 if the server is dead when
  132.  * the sleep finishes, 0 else
  133.  */
  134.  
  135. static Jmp_buf    pauseAbort;
  136. static int    serverPauseRet;
  137.  
  138. /* ARGSUSED */
  139. static SIGVAL
  140. serverPauseAbort (n)
  141.     int n;
  142. {
  143.     Longjmp (pauseAbort, 1);
  144. }
  145.  
  146. /* ARGSUSED */
  147. static SIGVAL
  148. serverPauseUsr1 (n)
  149.     int n;
  150. {
  151.     Debug ("display manager paused til SIGUSR1\n");
  152.     ++receivedUsr1;
  153.     Longjmp (pauseAbort, 1);
  154. }
  155.  
  156. static
  157. serverPause (t, serverPid)
  158. unsigned    t;
  159. int        serverPid;
  160. {
  161.     int        pid;
  162.  
  163.     serverPauseRet = 0;
  164.     if (!Setjmp (pauseAbort)) {
  165.     (void) Signal (SIGALRM, serverPauseAbort);
  166.     (void) Signal (SIGUSR1, serverPauseUsr1);
  167. #ifdef SYSV
  168.     if (receivedUsr1)
  169.         (void) alarm ((unsigned) 1);
  170.     else
  171.         (void) alarm (t);
  172. #else
  173.     if (!receivedUsr1)
  174.         (void) alarm (t);
  175.     else
  176.         Debug ("Already received USR1\n");
  177. #endif
  178.     for (;;) {
  179. #if defined(SYSV) && defined(X_NOT_POSIX)
  180.         pid = wait ((waitType *) 0);
  181. #else
  182.         if (!receivedUsr1)
  183.         pid = wait ((waitType *) 0);
  184.         else
  185. #ifndef X_NOT_POSIX
  186.         pid = waitpid (-1, (int *) 0, WNOHANG);
  187. #else
  188.         pid = wait3 ((waitType *) 0, WNOHANG,
  189.                  (struct rusage *) 0);
  190. #endif /* X_NOT_POSIX */
  191. #endif /* SYSV */
  192.         if (pid == serverPid ||
  193.         pid == -1 && errno == ECHILD)
  194.         {
  195.         Debug ("Server dead\n");
  196.         serverPauseRet = 1;
  197.         break;
  198.         }
  199. #if !defined(SYSV) || !defined(X_NOT_POSIX)
  200.         if (pid == 0) {
  201.         Debug ("Server alive and kicking\n");
  202.         break;
  203.         }
  204. #endif
  205.     }
  206.     }
  207.     (void) alarm ((unsigned) 0);
  208.     (void) Signal (SIGALRM, SIG_DFL);
  209.     (void) Signal (SIGUSR1, CatchUsr1);
  210.     if (serverPauseRet) {
  211.     Debug ("Server died\n");
  212.     LogError ("server unexpectedly died\n");
  213.     }
  214.     return serverPauseRet;
  215. }
  216.  
  217.  
  218. /*
  219.  * this code is complicated by some TCP failings.  On
  220.  * many systems, the connect will occasionally hang forever,
  221.  * this trouble is avoided by setting up a timeout to Longjmp
  222.  * out of the connect (possibly leaving piles of garbage around
  223.  * inside Xlib) and give up, terminating the server.
  224.  */
  225.  
  226. static Jmp_buf    openAbort;
  227.  
  228. /* ARGSUSED */
  229. static SIGVAL
  230. abortOpen (n)
  231.     int n;
  232. {
  233.     Longjmp (openAbort, 1);
  234. }
  235.  
  236. #ifdef XDMCP
  237.  
  238. #ifdef STREAMSCONN
  239. #include <tiuser.h>
  240. #endif
  241.  
  242. static
  243. GetRemoteAddress (d, fd)
  244.     struct display  *d;
  245.     int            fd;
  246. {
  247.     char    buf[512];
  248.     int        len = sizeof (buf);
  249. #ifdef STREAMSCONN
  250.     struct netbuf    netb;
  251. #endif
  252.  
  253.     if (d->peer)
  254.     free ((char *) d->peer);
  255. #ifdef STREAMSCONN
  256.     netb.maxlen = sizeof(buf);
  257.     netb.buf = buf;
  258.     t_getname(fd, &netb, REMOTENAME);
  259.     len = 8;
  260.     /* lucky for us, t_getname returns something that looks like a sockaddr */
  261. #else
  262.     getpeername (fd, (struct sockaddr *) buf, &len);
  263. #endif
  264.     d->peerlen = 0;
  265.     if (len)
  266.     {
  267.     d->peer = (XdmcpNetaddr) malloc (len);
  268.     if (d->peer)
  269.     {
  270.         bcopy (buf, (char *) d->peer, len);
  271.         d->peerlen = len;
  272.     }
  273.     }
  274.     Debug ("Got remote address %s %d\n", d->name, d->peerlen);
  275. }
  276.  
  277. #endif /* XDMCP */
  278.  
  279. static int
  280. openErrorHandler (dpy)
  281.     Display *dpy;
  282. {
  283.     LogError ("IO Error in XOpenDisplay\n");
  284.     exit (OPENFAILED_DISPLAY);
  285. }
  286.  
  287. int
  288. WaitForServer (d)
  289.     struct display  *d;
  290. {
  291.     int        i;
  292.  
  293.     for (i = 0; i < (d->openRepeat > 0 ? d->openRepeat : 1); i++) {
  294.         (void) Signal (SIGALRM, abortOpen);
  295.         (void) alarm ((unsigned) d->openTimeout);
  296.         if (!Setjmp (openAbort)) {
  297.         Debug ("Before XOpenDisplay(%s)\n", d->name);
  298.         errno = 0;
  299.         (void) XSetIOErrorHandler (openErrorHandler);
  300.         dpy = XOpenDisplay (d->name);
  301. #ifdef STREAMSCONN
  302.         {
  303.         /* For some reason, the next XOpenDisplay we do is
  304.            going to fail, so we might as well get that out
  305.            of the way.  There is something broken here. */
  306.         Display *bogusDpy = XOpenDisplay (d->name);
  307.         Debug ("bogus XOpenDisplay %s\n",
  308.                bogusDpy ? "succeeded" : "failed");
  309.         if (bogusDpy) XCloseDisplay(bogusDpy); /* just in case */
  310.         }
  311. #endif
  312.         (void) alarm ((unsigned) 0);
  313.         (void) Signal (SIGALRM, SIG_DFL);
  314.         (void) XSetIOErrorHandler ((int (*)()) 0);
  315.         Debug ("After XOpenDisplay(%s)\n", d->name);
  316.         if (dpy) {
  317. #ifdef XDMCP
  318.             if (d->displayType.location == Foreign)
  319.             GetRemoteAddress (d, ConnectionNumber (dpy));
  320. #endif
  321.             RegisterCloseOnFork (ConnectionNumber (dpy));
  322.         (void) fcntl (ConnectionNumber (dpy), F_SETFD, 0);
  323.             return 1;
  324.         } else {
  325.             Debug ("OpenDisplay failed %d (%s) on \"%s\"\n",
  326.                errno, _SysErrorMsg (errno), d->name);
  327.         }
  328.         Debug ("waiting for server to start %d\n", i);
  329.         sleep ((unsigned) d->openDelay);
  330.         } else {
  331.         Debug ("hung in open, aborting\n");
  332.         LogError ("Hung in XOpenDisplay(%s), aborting\n", d->name);
  333.         (void) Signal (SIGALRM, SIG_DFL);
  334.         break;
  335.         }
  336.     }
  337.     Debug ("giving up on server\n");
  338.     LogError ("server open failed for %s, giving up\n", d->name);
  339.     return 0;
  340. }
  341.  
  342. ResetServer (d)
  343.     struct display  *d;
  344. {
  345.     if (dpy && d->displayType.origin != FromXDMCP)
  346.     pseudoReset (dpy);
  347. }
  348.  
  349. static Jmp_buf    pingTime;
  350.  
  351. static void
  352. PingLost ()
  353. {
  354.     Longjmp (pingTime, 1);
  355. }
  356.  
  357. /* ARGSUSED */
  358. static int
  359. PingLostIOErr (dpy)
  360.     Display *dpy;
  361. {
  362.     PingLost();
  363. }
  364.  
  365. /* ARGSUSED */
  366. static SIGVAL
  367. PingLostSig (n)
  368.     int n;
  369. {
  370.     PingLost();
  371. }
  372.  
  373. PingServer (d, alternateDpy)
  374.     struct display  *d;
  375.     Display        *alternateDpy;
  376. {
  377.     int        (*oldError)();
  378.     SIGVAL  (*oldSig)();
  379.     int        oldAlarm;
  380.  
  381.     if (!alternateDpy)
  382.     alternateDpy = dpy;
  383.     oldError = XSetIOErrorHandler (PingLostIOErr);
  384.     oldAlarm = alarm (0);
  385.     oldSig = Signal (SIGALRM, PingLostSig);
  386.     (void) alarm (d->pingTimeout * 60);
  387.     if (!Setjmp (pingTime))
  388.     {
  389.     Debug ("Ping server\n");
  390.     XSync (alternateDpy, 0);
  391.     }
  392.     else
  393.     {
  394.     Debug ("Server dead\n");
  395.     (void) alarm (0);
  396.     (void) Signal (SIGALRM, SIG_DFL);
  397.     XSetIOErrorHandler (oldError);
  398.     return 0;
  399.     }
  400.     (void) alarm (0);
  401.     (void) Signal (SIGALRM, oldSig);
  402.     (void) alarm (oldAlarm);
  403.     Debug ("Server alive\n");
  404.     XSetIOErrorHandler (oldError);
  405.     return 1;
  406. }
  407.