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 cannot 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
);