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 = parseArgs( argv, args )) ||
60
!(argv = addStrArr( argv, d->name, -1 )))
64
!(argv = addStrArr( argv, vtstr,
65
sprintf( vtstr, "vt%d", d->serverVT ) )))
72
startServerOnce( void )
74
struct display *d = startingServer;
77
debug( "startServerOnce for %s, try %d\n", d->name, ++d->startTries );
78
d->serverStatus = starting;
79
switch (Fork( &d->serverPid )) {
81
argv = prepareServerArgv( d, d->serverArgsLocal );
83
if (!(argv = addStrArr( argv, "-auth", 5 )) ||
84
!(argv = addStrArr( argv, d->authFile, -1 )))
87
debug( "exec %\"[s\n", argv );
89
* give the server SIGUSR1 ignored,
90
* it will notice that and send SIGUSR1
93
(void)Signal( SIGUSR1, SIG_IGN );
94
(void)execv( argv[0], argv );
95
logError( "X server %\"s cannot be executed\n", argv[0] );
98
logError( "X server fork failed\n" );
102
debug( "X server forked, pid %d\n", d->serverPid );
103
serverTimeout = d->serverTimeout + now;
109
startServer( struct display *d )
117
abortStartServer( struct display *d )
119
if (startingServer == d)
121
if (d->serverStatus != ignore)
123
d->serverStatus = ignore;
124
serverTimeout = TO_INF;
125
debug( "aborting X server start\n" );
134
struct display *d = startingServer;
135
d->serverStatus = ignore;
136
serverTimeout = TO_INF;
137
debug( "X server ready, starting session\n" );
144
struct display *d = startingServer;
145
if (!d->serverAttempts || d->startTries < d->serverAttempts) {
146
d->serverStatus = pausing;
147
serverTimeout = d->openDelay + now;
149
d->serverStatus = ignore;
150
serverTimeout = TO_INF;
152
logError( "X server for display %s can't be started,"
153
" session disabled\n", d->name );
161
struct display *d = startingServer;
162
switch (d->serverStatus) {
165
break; /* cannot happen */
167
logError( "X server startup timeout, terminating\n" );
168
kill( d->serverPid, d->termSignal );
169
d->serverStatus = d->termSignal == SIGKILL ? killed : terminated;
170
serverTimeout = d->serverTimeout + now;
173
logInfo( "X server termination timeout, killing\n" );
174
kill( d->serverPid, SIGKILL );
175
d->serverStatus = killed;
176
serverTimeout = 10 + now;
179
logInfo( "X server is stuck in D state; leaving it alone\n" );
192
* this code is complicated by some TCP failings. On
193
* many systems, the connect will occasionally hang forever,
194
* this trouble is avoided by setting up a timeout to Longjmp
195
* out of the connect (possibly leaving piles of garbage around
196
* inside Xlib) and give up, terminating the server.
199
static Jmp_buf openAbort;
203
abortOpen( int n ATTR_UNUSED )
205
Longjmp( openAbort, 1 );
215
getRemoteAddress( struct display *d, int fd )
218
int len = sizeof(buf);
223
XdmcpDisposeARRAY8( &d->peer );
225
netb.maxlen = sizeof(buf);
227
t_getname( fd, &netb, REMOTENAME );
229
/* lucky for us, t_getname returns something that looks like a sockaddr */
231
getpeername( fd, (struct sockaddr *)buf, (void *)&len );
233
if (len && XdmcpAllocARRAY8( &d->peer, len ))
234
memmove( (char *)d->peer.data, buf, len );
235
debug( "got remote address %s %d\n", d->name, d->peer.length );
241
openErrorHandler( Display *dspl ATTR_UNUSED )
243
logError( "IO Error in XOpenDisplay\n" );
244
exit( EX_OPENFAILED_DPY );
250
waitForServer( struct display *d )
257
(void)Signal( SIGALRM, abortOpen );
258
(void)alarm( (unsigned)d->openTimeout );
259
if (!Setjmp( openAbort )) {
260
debug( "before XOpenDisplay(%s)\n", d->name );
262
(void)XSetIOErrorHandler( openErrorHandler );
263
dpy = XOpenDisplay( d->name );
266
/* For some reason, the next XOpenDisplay we do is
267
going to fail, so we might as well get that out
268
of the way. There is something broken here. */
269
Display *bogusDpy = XOpenDisplay( d->name );
270
debug( "bogus XOpenDisplay %s\n",
271
bogusDpy ? "succeeded" : "failed" );
272
if (bogusDpy) XCloseDisplay( bogusDpy ); /* just in case */
275
(void)alarm( (unsigned)0 );
276
(void)Signal( SIGALRM, SIG_DFL );
277
(void)XSetIOErrorHandler( (int (*)( Display * )) 0 );
278
debug( "after XOpenDisplay(%s)\n", d->name );
281
if ((d->displayType & d_location) == dForeign)
282
getRemoteAddress( d, ConnectionNumber( dpy ) );
284
registerCloseOnFork( ConnectionNumber( dpy ) );
287
debug( "OpenDisplay(%s) attempt %d failed: %m\n", d->name, i + 1 );
288
sleep( (unsigned)d->openDelay );
290
logError( "Hung in XOpenDisplay(%s), aborting\n", d->name );
291
(void)Signal( SIGALRM, SIG_DFL );
294
} while (++i < d->openRepeat);
295
logError( "Cannot connect to %s, giving up\n", d->name );
296
exit( EX_OPENFAILED_DPY );
301
resetServer( struct display *d )
303
if (dpy && (d->displayType & d_origin) != dFromXDMCP)
308
static Jmp_buf pingTime;
313
Longjmp( pingTime, 1 );
318
pingLostIOErr( Display *dspl ATTR_UNUSED )
326
pingLostSig( int n ATTR_UNUSED )
332
pingServer( struct display *d )
334
int (*oldError)( Display * );
335
void (*oldSig)( int );
338
oldError = XSetIOErrorHandler( pingLostIOErr );
339
oldAlarm = alarm( 0 );
340
oldSig = Signal( SIGALRM, pingLostSig );
341
(void)alarm( d->pingTimeout * 60 );
342
if (!Setjmp( pingTime )) {
343
debug( "ping X server\n" );
346
debug( "X server dead\n" );
348
(void)Signal( SIGALRM, SIG_DFL );
349
XSetIOErrorHandler( oldError );
353
(void)Signal( SIGALRM, oldSig );
354
(void)alarm( oldAlarm );
355
debug( "X server alive\n" );
356
XSetIOErrorHandler( oldError );