3
Copyright 1988, 1998 The Open Group
4
Copyright 2001,2003,2005 Oswald Buddenhagen <ossi@kde.org>
6
Permission to use, copy, modify, distribute, and sell this software and its
7
documentation for any purpose is hereby granted without fee, provided that
8
the above copyright notice appear in all copies and that both that
9
copyright notice and this permission notice appear in supporting
12
The above copyright notice and this permission notice shall be included
13
in all copies or substantial portions of the Software.
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21
OTHER DEALINGS IN THE SOFTWARE.
23
Except as contained in this notice, the name of a copyright holder shall
24
not be used in advertising or otherwise to promote the sale, use or
25
other dealings in this Software without prior written authorization
26
from the copyright holder.
31
* xdm - display manager daemon
32
* Author: Keith Packard, MIT X Consortium
34
* server.c - manage the X server
39
#include "dm_socket.h"
47
struct display *startingServer;
48
time_t serverTimeout = TO_INF;
51
prepareServerArgv(struct display *d, const char *args)
58
if (!(argv = parseArgs(0, d->serverCmd)) ||
59
!(argv = addStrArr(argv, d->name, -1)))
63
!(argv = addStrArr(argv, vtstr,
64
sprintf(vtstr, "vt%d", d->serverVT))))
67
if (!(argv = parseArgs(argv, args)))
70
if (!changeUser(d->serverUID, d->authFile))
79
struct display *d = startingServer;
82
debug("startServerOnce for %s, try %d\n", d->name, ++d->startTries);
83
d->serverStatus = starting;
84
switch (Fork(&d->serverPid)) {
86
argv = prepareServerArgv(d, d->serverArgsLocal);
88
if (!(argv = addStrArr(argv, "-auth", 5)) ||
89
!(argv = addStrArr(argv, d->authFile, -1)))
92
debug("exec %\"[s\n", argv);
94
* give the server SIGUSR1 ignored,
95
* it will notice that and send SIGUSR1
98
(void)Signal(SIGUSR1, SIG_IGN);
99
(void)execv(argv[0], argv);
100
logError("X server %\"s cannot be executed\n", argv[0]);
103
logError("X server fork failed\n");
107
debug("X server forked, pid %d\n", d->serverPid);
108
serverTimeout = d->serverTimeout + now;
114
startServer(struct display *d)
122
abortStartServer(struct display *d)
124
if (startingServer == d) {
125
if (d->serverStatus != ignore) {
126
d->serverStatus = ignore;
127
serverTimeout = TO_INF;
128
debug("aborting X server start\n");
137
struct display *d = startingServer;
138
d->serverStatus = ignore;
139
serverTimeout = TO_INF;
140
debug("X server ready, starting session\n");
147
struct display *d = startingServer;
148
if (!d->serverAttempts || d->startTries < d->serverAttempts) {
149
d->serverStatus = pausing;
150
serverTimeout = d->openDelay + now;
152
d->serverStatus = ignore;
153
serverTimeout = TO_INF;
155
logError("X server for display %s cannot be started,"
156
" session disabled\n", d->name);
164
struct display *d = startingServer;
165
switch (d->serverStatus) {
168
break; /* cannot happen */
170
logError("X server startup timeout, terminating\n");
171
kill(d->serverPid, SIGTERM);
172
d->serverStatus = terminated;
173
serverTimeout = d->serverTimeout + now;
176
logInfo("X server termination timeout, killing\n");
177
kill(d->serverPid, SIGKILL);
178
d->serverStatus = killed;
179
serverTimeout = 10 + now;
182
logInfo("X server is stuck in D state; leaving it alone\n");
195
* this code is complicated by some TCP failings. On
196
* many systems, the connect will occasionally hang forever,
197
* this trouble is avoided by setting up a timeout to Longjmp
198
* out of the connect (possibly leaving piles of garbage around
199
* inside Xlib) and give up, terminating the server.
202
static Jmp_buf openAbort;
206
abortOpen(int n ATTR_UNUSED)
208
Longjmp(openAbort, 1);
218
getRemoteAddress(struct display *d, int fd)
221
int len = sizeof(buf);
226
XdmcpDisposeARRAY8(&d->peer);
228
netb.maxlen = sizeof(buf);
230
t_getname(fd, &netb, REMOTENAME);
232
/* lucky for us, t_getname returns something that looks like a sockaddr */
234
getpeername(fd, (struct sockaddr *)buf, (void *)&len);
236
if (len && XdmcpAllocARRAY8(&d->peer, len))
237
memmove(d->peer.data, buf, len);
238
debug("got remote address %s %d\n", d->name, d->peer.length);
244
openErrorHandler(Display *dspl)
246
logError("IO Error in XOpenDisplay(%s)\n", DisplayString(dspl));
247
exit(EX_OPENFAILED_DPY);
253
waitForServer(struct display *d)
260
(void)Signal(SIGALRM, abortOpen);
261
(void)alarm((unsigned)d->openTimeout);
262
if (!Setjmp(openAbort)) {
263
debug("before XOpenDisplay(%s)\n", d->name);
265
(void)XSetIOErrorHandler(openErrorHandler);
266
dpy = XOpenDisplay(d->name);
269
/* For some reason, the next XOpenDisplay we do is
270
going to fail, so we might as well get that out
271
of the way. There is something broken here. */
272
Display *bogusDpy = XOpenDisplay(d->name);
273
debug("bogus XOpenDisplay %s\n",
274
bogusDpy ? "succeeded" : "failed");
276
XCloseDisplay(bogusDpy); /* just in case */
279
(void)alarm((unsigned)0);
280
(void)Signal(SIGALRM, SIG_DFL);
281
(void)XSetIOErrorHandler((int (*)(Display *)) 0);
282
debug("after XOpenDisplay(%s)\n", d->name);
285
if ((d->displayType & d_location) == dForeign)
286
getRemoteAddress(d, ConnectionNumber(dpy));
288
registerCloseOnFork(ConnectionNumber(dpy));
291
debug("OpenDisplay(%s) attempt %d failed: %m\n", d->name, i + 1);
292
sleep((unsigned)d->openDelay);
294
logError("Hung in XOpenDisplay(%s), aborting\n", d->name);
295
(void)Signal(SIGALRM, SIG_DFL);
298
} while (++i < d->openRepeat);
299
logError("Cannot connect to %s, giving up\n", d->name);
300
exit(EX_OPENFAILED_DPY);
305
resetServer(struct display *d)
307
if (dpy && (d->displayType & d_origin) != dFromXDMCP)
312
static Jmp_buf pingTime;
317
Longjmp(pingTime, 1);
322
pingLostIOErr(Display *dspl ATTR_UNUSED)
330
pingLostSig(int n ATTR_UNUSED)
336
pingServer(struct display *d)
338
int (*oldError)(Display *);
342
oldError = XSetIOErrorHandler(pingLostIOErr);
344
oldSig = Signal(SIGALRM, pingLostSig);
345
(void)alarm(d->pingTimeout * 60);
346
if (!Setjmp(pingTime)) {
347
debug("ping X server\n");
350
debug("X server dead\n");
352
(void)Signal(SIGALRM, SIG_DFL);
353
XSetIOErrorHandler(oldError);
357
(void)Signal(SIGALRM, oldSig);
358
(void)alarm(oldAlarm);
359
debug("X server alive\n");
360
XSetIOErrorHandler(oldError);