3 Copyright 1988, 1998 The Open Group
4 Copyright 2001-2004 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 * subdaemon and external process management and communication
39 #if defined(SINGLE_PIPE) && !defined(__FreeBSD__)
40 # include "dm_socket.h"
48 #ifdef _POSIX_PRIORITY_SCHEDULING
53 SIGFUNC
Signal( int sig
, SIGFUNC handler
)
56 struct sigaction sigact
, osigact
;
57 sigact
.sa_handler
= handler
;
58 sigemptyset( &sigact
.sa_mask
);
60 sigact
.sa_flags
= SA_RESTART
;
64 sigaction( sig
, &sigact
, &osigact
);
65 return osigact
.sa_handler
;
67 return signal( sig
, handler
);
73 terminateProcess( int pid
, int sig
)
82 static fd_set closeMask
;
86 registerCloseOnFork( int fd
)
88 FD_SET( fd
, &closeMask
);
94 clearCloseOnFork( int fd
)
96 FD_CLR( fd
, &closeMask
);
100 closeNclearCloseOnFork( int fd
)
103 FD_CLR( fd
, &closeMask
);
111 for (fd
= 0; fd
<= max
; fd
++)
112 if (FD_ISSET( fd
, &closeMask
))
114 FD_ZERO( &closeMask
);
119 Fork( volatile int *pidr
)
125 sigprocmask( SIG_SETMASK
, &ss
, &oss
);
127 if (!(pid
= fork())) {
129 (void)Signal( SIGCHLD
, SIG_DFL
);
131 (void)Signal( SIGTERM
, SIG_DFL
);
132 (void)Signal( SIGINT
, SIG_IGN
); /* for -nodaemon */
133 (void)Signal( SIGPIPE
, SIG_DFL
);
134 (void)Signal( SIGALRM
, SIG_DFL
);
135 (void)Signal( SIGHUP
, SIG_DFL
);
137 sigprocmask( SIG_SETMASK
, &ss
, NULL
);
143 sigprocmask( SIG_SETMASK
, &oss
, 0 );
149 cldCatcher( int n ATTR_UNUSED
)
154 Wait4( volatile int *pid
)
158 struct sigaction osa
;
161 sigprocmask( SIG_SETMASK
, &ss
, &oss
);
162 sigaction( SIGCHLD
, 0, &osa
);
163 if (osa
.sa_handler
== SIG_DFL
)
164 Signal( SIGCHLD
, cldCatcher
);
166 switch (waitpid( *pid
, &result
, WNOHANG
)) {
171 debug( "Wait4(%d) failed: %m\n", *pid
);
176 if (osa
.sa_handler
== SIG_DFL
)
177 Signal( SIGCHLD
, SIG_DFL
);
178 sigprocmask( SIG_SETMASK
, &oss
, 0 );
179 return wcFromWait( result
);
186 execute( char **argv
, char **env
)
188 debug( "execute: %[s ; %[s\n", argv
, env
);
189 execve( argv
[0], argv
, env
);
191 * In case this is a shell script which hasn't been
192 * made executable (or this is a SYSV box), do
195 if (errno
!= ENOENT
) {
202 * emulate BSD kernel behaviour -- read
203 * the first line; check if it starts
204 * with "#!", in which case it uses
205 * the rest of the line as the name of
206 * program to run. Else use "/bin/sh".
208 if (!(f
= fopen( argv
[0], "r" )))
210 if (!fGets( program
, sizeof(program
), f
)) {
215 if (!strncmp( program
, "#!", 2 ))
216 newargv
= parseArgs( 0, program
+ 2 );
218 newargv
= addStrArr( 0, "/bin/sh", 7 );
221 nu
= arrLen( newargv
);
222 if (!(argv
= xCopyStrArr( nu
, argv
)))
224 memcpy( argv
, newargv
, sizeof(char *) * nu
);
225 debug( "shell script execution: %[s\n", argv
);
226 execve( argv
[0], argv
, env
);
231 runAndWait( char **args
, char **env
)
235 switch (Fork( &pid
)) {
237 execute( args
, env
);
238 logError( "Cannot execute %\"s: %m\n", args
[0] );
241 logError( "Cannot fork to execute %\"s: %m\n", args
[0] );
242 return wcCompose( 0, 0, 127 );
245 return wcFromWait( ret
);
249 pOpen( char **what
, char m
, volatile int *pid
)
255 switch (Fork( pid
)) {
263 execute( what
, environ
);
264 logError( "Cannot execute %\"s: %m\n", what
[0] );
269 logError( "Cannot fork to execute %\"s: %m\n", what
[0] );
274 return fdopen( dp
[0], "r" );
277 return fdopen( dp
[1], "w" );
282 pClose( FILE *f
, volatile int *pid
)
289 locate( const char *exe
)
292 char *path
, *pathe
, *name
, *thenam
, nambuf
[PATH_MAX
+1];
294 if (!(path
= getenv( "PATH" ))) {
295 logError( "Cannot execute %'s: $PATH not set.\n", exe
);
299 name
= nambuf
+ PATH_MAX
- len
;
300 memcpy( name
, exe
, len
+ 1 );
303 if (!(pathe
= strchr( path
, ':' )))
304 pathe
= path
+ strlen( path
);
306 if (len
&& !(len
== 1 && *path
== '.')) {
308 if (thenam
>= nambuf
) {
309 memcpy( thenam
, path
, len
);
310 if (!access( thenam
, X_OK
)) {
311 strDup( &name
, thenam
);
317 } while (*path
++ != '\0');
318 logError( "Cannot execute %'s: not in $PATH.\n", exe
);
323 static GTalk
*curtalk
;
332 gCloseOnExec( GPipe
*pajp
)
334 fcntl( pajp
->fd
.r
, F_SETFD
, FD_CLOEXEC
);
336 fcntl( pajp
->fd
.w
, F_SETFD
, FD_CLOEXEC
);
340 #if !defined(SINGLE_PIPE) || defined(__FreeBSD__)
341 # define make_pipe(h) pipe( h )
343 # define make_pipe(h) socketpair( AF_UNIX, SOCK_STREAM, 0, h )
347 gFork( GPipe
*pajp
, const char *pname
, char *cname
,
348 GPipe
*ogp
, char *cgname
,
352 int opipe
[2], ogpipe
[2];
354 int ipipe
[2], igpipe
[2];
358 if (make_pipe( opipe
))
365 if (make_pipe( ogpipe
))
382 logError( "Cannot start %s, pipe() failed", cname
);
388 registerCloseOnFork( opipe
[1] );
390 registerCloseOnFork( ipipe
[0] );
393 registerCloseOnFork( ogpipe
[1] );
395 registerCloseOnFork( igpipe
[0] );
399 clearCloseOnFork( gp
->fd
.r
);
401 clearCloseOnFork( gp
->fd
.w
);
404 if ((pid
= Fork( pidr
))) {
406 registerCloseOnFork( gp
->fd
.r
);
408 registerCloseOnFork( gp
->fd
.w
);
424 closeNclearCloseOnFork( opipe
[1] );
426 closeNclearCloseOnFork( ipipe
[0] );
429 closeNclearCloseOnFork( ogpipe
[1] );
431 closeNclearCloseOnFork( igpipe
[0] );
434 logError( "Cannot start %s, fork() failed\n", cname
);
440 pajp
->fd
.w
= ipipe
[1];
441 registerCloseOnFork( ipipe
[1] );
443 pajp
->fd
.r
= opipe
[0];
444 registerCloseOnFork( opipe
[0] );
445 pajp
->who
= (char *)pname
;
448 ogp
->fd
.w
= igpipe
[1];
449 registerCloseOnFork( igpipe
[1] );
451 ogp
->fd
.r
= ogpipe
[0];
452 registerCloseOnFork( ogpipe
[0] );
453 ogp
->who
= (char *)pname
;
459 pajp
->fd
.w
= opipe
[1];
461 pajp
->fd
.r
= ipipe
[0];
465 ogp
->fd
.w
= ogpipe
[1];
467 ogp
->fd
.r
= igpipe
[0];
476 gOpen( GProc
*proc
, char **argv
, const char *what
, char **env
, char *cname
,
484 logError( "%s already running\n", cname
);
489 if (!(margv
= xCopyStrArr( 1, argv
))) {
494 #if KDM_LIBEXEC_STRIP == -1
495 if (!strApp( margv
, KDM_LIBEXEC_SUFFIX
, progname
, what
, (char *)0 ))
496 #elif KDM_LIBEXEC_STRIP == 0
497 if (!strApp( margv
, progpath
, what
, (char *)0 ))
499 if (!strApp( margv
, progpath
, "/" KDM_LIBEXEC_SUFFIX
, progname
, what
, (char *)0 ))
508 logError( "Cannot start %s, pipe() failed\n", cname
);
513 switch (gFork( &proc
->pipe
, 0, cname
, 0, 0, gp
, &proc
->pid
)) {
523 (void)Signal( SIGPIPE
, SIG_IGN
);
525 fcntl( pip
[1], F_SETFD
, FD_CLOEXEC
);
527 sprintf( coninfo
, "CONINFO=%d %d %d %d",
528 proc
->pipe
.fd
.r
, proc
->pipe
.fd
.w
, gp
->fd
.r
, gp
->fd
.w
);
530 sprintf( coninfo
, "CONINFO=%d %d",
531 proc
->pipe
.fd
.r
, proc
->pipe
.fd
.w
);
532 env
= putEnv( coninfo
, env
);
533 if (debugLevel
& DEBUG_VALGRIND
) {
534 char **nmargv
= xCopyStrArr( 1, margv
);
535 nmargv
[0] = locate( "valgrind" );
536 execute( nmargv
, env
);
537 } else if (debugLevel
& DEBUG_STRACE
) {
538 char **nmargv
= xCopyStrArr( 1, margv
);
539 nmargv
[0] = locate( "strace" );
540 execute( nmargv
, env
);
542 execute( margv
, env
);
543 write( pip
[1], "", 1 );
546 (void)Signal( SIGPIPE
, SIG_IGN
);
548 if (reader( pip
[0], coninfo
, 1 )) {
550 logError( "Cannot execute %\"s (%s)\n", margv
[0], cname
);
551 gClosen( &proc
->pipe
);
555 debug( "started %s (%\"s), pid %d\n", cname
, margv
[0], proc
->pid
);
558 gSendInt( debugLevel
);
564 _gClosen( GPipe
*pajp
)
566 closeNclearCloseOnFork( pajp
->fd
.r
);
568 closeNclearCloseOnFork( pajp
->fd
.w
);
575 gClosen( GPipe
*pajp
)
584 gClose( GProc
*proc
, GPipe
*gp
, int force
)
588 if (proc
->pid
<= 0) {
589 debug( "whoops, gClose while helper not running\n" );
592 _gClosen( &proc
->pipe
);
596 terminateProcess( proc
->pid
, SIGTERM
);
597 ret
= Wait4( &proc
->pid
);
598 if (wcSig( ret
) ? wcSig( ret
) != SIGTERM
:
599 (wcCode( ret
) < EX_NORMAL
|| wcCode( ret
) > EX_MAX
))
600 logError( "Abnormal termination of %s, code %d, signal %d\n",
601 proc
->pipe
.who
, wcCode( ret
), wcSig( ret
) );
602 debug( "closed %s\n", proc
->pipe
.who
);
604 free( proc
->pipe
.who
);
609 static void ATTR_NORETURN
612 Longjmp( curtalk
->errjmp
, 1 );
616 gRead( void *buf
, int len
)
618 if (reader( curtalk
->pipe
->fd
.r
, buf
, len
) != len
) {
619 logError( "Cannot read from %s\n", curtalk
->pipe
->who
);
625 gWrite( const void *buf
, int len
)
627 if (writer( curtalk
->pipe
->fd
.w
, buf
, len
) != len
) {
628 logError( "Cannot write to %s\n", curtalk
->pipe
->who
);
631 #ifdef _POSIX_PRIORITY_SCHEDULING
632 if ((debugLevel
& DEBUG_HLPCON
))
640 gDebug( "sending int %d (%#x) to %s\n", val
, val
, curtalk
->pipe
->who
);
641 gWrite( &val
, sizeof(val
) );
649 gDebug( "receiving int from %s ...\n", curtalk
->pipe
->who
);
650 gRead( &val
, sizeof(val
) );
651 gDebug( " -> %d (%#x)\n", val
, val
);
658 gDebug( "receiving command from %s ...\n", curtalk
->pipe
->who
);
659 if (reader( curtalk
->pipe
->fd
.r
, cmd
, sizeof(*cmd
) ) == sizeof(*cmd
)) {
660 gDebug( " -> %d\n", *cmd
);
663 gDebug( " -> no data\n" );
668 gSendArr( int len
, const char *data
)
670 gDebug( "sending array[%d] %02[*{hhx to %s\n",
671 len
, len
, data
, curtalk
->pipe
->who
);
672 gWrite( &len
, sizeof(len
) );
677 _gRecvArr( int *rlen
)
682 gRead( &len
, sizeof(len
) );
684 gDebug( " -> %d bytes\n", len
);
685 if (!len
|| len
> 0x10000)
687 if (!(buf
= Malloc( len
)))
694 gRecvArr( int *rlen
)
698 gDebug( "receiving array from %s ...\n", curtalk
->pipe
->who
);
699 buf
= _gRecvArr( rlen
);
700 gDebug( " -> %02[*{hhx\n", *rlen
, buf
);
705 _gRecvArrBuf( char *buf
)
709 gRead( &len
, sizeof(len
) );
710 gDebug( " -> %d bytes\n", len
);
711 if (len
&& len
< 0x10000)
717 gRecvArrBuf( char *buf
)
721 gDebug( "receiving already allocated array from %s ...\n",
722 curtalk
->pipe
->who
);
723 len
= _gRecvArrBuf( buf
);
724 gDebug( " -> %02[*{hhx\n", len
, buf
);
729 gRecvStrBuf( char *buf
)
733 gDebug( "receiving already allocated string from %s ...\n",
734 curtalk
->pipe
->who
);
735 len
= _gRecvArrBuf( buf
);
736 gDebug( " -> %\".*s\n", len
, buf
);
741 gSendStr( const char *buf
)
745 gDebug( "sending string %\"s to %s\n", buf
, curtalk
->pipe
->who
);
747 len
= strlen( buf
) + 1;
748 gWrite( &len
, sizeof(len
) );
751 gWrite( &buf
, sizeof(int) );
755 gSendNStr( const char *buf
, int len
)
758 gDebug( "sending string %\".*s to %s\n", len
, buf
, curtalk
->pipe
->who
);
759 gWrite( &tlen
, sizeof(tlen
) );
765 gSendStrN( const char *buf
, int len
)
768 gSendNStr( buf
, strnlen( buf
, len
) );
779 gDebug( "receiving string from %s ...\n", curtalk
->pipe
->who
);
780 buf
= _gRecvArr( &len
);
781 gDebug( " -> %\".*s\n", len
, buf
);
786 _gSendStrArr( int num
, char **data
)
790 gWrite( &num
, sizeof(num
) );
791 for (cdata
= data
; --num
>= 0; cdata
++)
797 gSendStrArr (int num, char **data)
799 gDebug( "sending string array[%d] to %s\n", num, curtalk->pipe->who );
800 _gSendStrArr( num, data );
805 gRecvStrArr( int *rnum
)
808 char **argv
, **cargv
;
810 gDebug( "receiving string array from %s ...\n", curtalk
->pipe
->who
);
811 gRead( &num
, sizeof(num
) );
812 gDebug( " -> %d strings\n", num
);
816 if (!(argv
= Malloc( num
* sizeof(char *) )))
818 for (cargv
= argv
; --num
>= 0; cargv
++)
824 gSendArgv( char **argv
)
829 for (num
= 0; argv
[num
]; num
++);
830 gDebug( "sending argv[%d] to %s ...\n", num
, curtalk
->pipe
->who
);
831 _gSendStrArr( num
+ 1, argv
);
833 gDebug( "sending NULL argv to %s\n", curtalk
->pipe
->who
);
834 gWrite( &argv
, sizeof(int) );
843 return gRecvStrArr( &num
);