source: trunk/athena/etc/xdm/xdm/server.c @ 6052

Revision 6052, 8.6 KB checked in by lwvanels, 33 years ago (diff)
Initial revision
Line 
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
32static receivedUsr1;
33
34extern int  errno;
35static serverPause ();
36
37static Display  *dpy;
38
39/* ARGSUSED */
40static SIGVAL
41CatchUsr1 (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
51static 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
61StartServerOnce (d)
62struct 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
113StartServer (d)
114struct 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
135static Jmp_buf  pauseAbort;
136static int      serverPauseRet;
137
138/* ARGSUSED */
139static SIGVAL
140serverPauseAbort (n)
141    int n;
142{
143    Longjmp (pauseAbort, 1);
144}
145
146/* ARGSUSED */
147static SIGVAL
148serverPauseUsr1 (n)
149    int n;
150{
151    Debug ("display manager paused til SIGUSR1\n");
152    ++receivedUsr1;
153    Longjmp (pauseAbort, 1);
154}
155
156static
157serverPause (t, serverPid)
158unsigned    t;
159int         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
226static Jmp_buf  openAbort;
227
228/* ARGSUSED */
229static SIGVAL
230abortOpen (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
242static
243GetRemoteAddress (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
279static int
280openErrorHandler (dpy)
281    Display *dpy;
282{
283    LogError ("IO Error in XOpenDisplay\n");
284    exit (OPENFAILED_DISPLAY);
285}
286
287int
288WaitForServer (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
342ResetServer (d)
343    struct display  *d;
344{
345    if (dpy && d->displayType.origin != FromXDMCP)
346        pseudoReset (dpy);
347}
348
349static Jmp_buf  pingTime;
350
351static void
352PingLost ()
353{
354    Longjmp (pingTime, 1);
355}
356
357/* ARGSUSED */
358static int
359PingLostIOErr (dpy)
360    Display *dpy;
361{
362    PingLost();
363}
364
365/* ARGSUSED */
366static SIGVAL
367PingLostSig (n)
368    int n;
369{
370    PingLost();
371}
372
373PingServer (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}
Note: See TracBrowser for help on using the repository browser.