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
52
extern char **environ;
55
SIGFUNC Signal( int sig, SIGFUNC handler )
58
struct sigaction sigact, osigact;
59
sigact.sa_handler = handler;
60
sigemptyset( &sigact.sa_mask );
62
sigact.sa_flags = SA_RESTART;
66
sigaction( sig, &sigact, &osigact );
67
return osigact.sa_handler;
69
return signal( sig, handler );
75
terminateProcess( int pid, int sig )
84
static fd_set closeMask;
88
registerCloseOnFork( int fd )
90
FD_SET( fd, &closeMask );
96
clearCloseOnFork( int fd )
98
FD_CLR( fd, &closeMask );
102
closeNclearCloseOnFork( int fd )
105
FD_CLR( fd, &closeMask );
113
for (fd = 0; fd <= max; fd++)
114
if (FD_ISSET( fd, &closeMask ))
116
FD_ZERO( &closeMask );
121
Fork( volatile int *pidr )
127
sigprocmask( SIG_SETMASK, &ss, &oss );
129
if (!(pid = fork())) {
131
(void)Signal( SIGCHLD, SIG_DFL );
133
(void)Signal( SIGTERM, SIG_DFL );
134
(void)Signal( SIGINT, SIG_IGN ); /* for -nodaemon */
135
(void)Signal( SIGPIPE, SIG_DFL );
136
(void)Signal( SIGALRM, SIG_DFL );
137
(void)Signal( SIGHUP, SIG_DFL );
139
sigprocmask( SIG_SETMASK, &ss, NULL );
145
sigprocmask( SIG_SETMASK, &oss, 0 );
151
cldCatcher( int n ATTR_UNUSED )
156
Wait4( volatile int *pid )
160
struct sigaction osa;
163
sigprocmask( SIG_SETMASK, &ss, &oss );
164
sigaction( SIGCHLD, 0, &osa );
165
if (osa.sa_handler == SIG_DFL)
166
Signal( SIGCHLD, cldCatcher );
168
switch (waitpid( *pid, &result, WNOHANG )) {
173
debug( "Wait4(%d) failed: %m\n", *pid );
178
if (osa.sa_handler == SIG_DFL)
179
Signal( SIGCHLD, SIG_DFL );
180
sigprocmask( SIG_SETMASK, &oss, 0 );
181
return wcFromWait( result );
188
execute( char **argv, char **env )
190
debug( "execute: %[s ; %[s\n", argv, env );
191
execve( argv[0], argv, env );
193
* In case this is a shell script which hasn't been
194
* made executable (or this is a SYSV box), do
197
if (errno != ENOENT) {
204
* emulate BSD kernel behaviour -- read
205
* the first line; check if it starts
206
* with "#!", in which case it uses
207
* the rest of the line as the name of
208
* program to run. Else use "/bin/sh".
210
if (!(f = fopen( argv[0], "r" )))
212
if (!fGets( program, sizeof(program), f )) {
217
if (!strncmp( program, "#!", 2 ))
218
newargv = parseArgs( 0, program + 2 );
220
newargv = addStrArr( 0, "/bin/sh", 7 );
223
nu = arrLen( newargv );
224
if (!(argv = xCopyStrArr( nu, argv )))
226
memcpy( argv, newargv, sizeof(char *) * nu );
227
debug( "shell script execution: %[s\n", argv );
228
execve( argv[0], argv, env );
233
runAndWait( char **args, char **env )
237
switch (Fork( &pid )) {
239
execute( args, env );
240
logError( "Can't execute %\"s: %m\n", args[0] );
243
logError( "Can't fork to execute %\"s: %m\n", args[0] );
244
return wcCompose( 0, 0, 127 );
247
return wcFromWait( ret );
251
pOpen( char **what, char m, volatile int *pid )
257
switch (Fork( pid )) {
265
execute( what, environ );
266
logError( "Can't execute %\"s: %m\n", what[0] );
271
logError( "Can't fork to execute %\"s: %m\n", what[0] );
276
return fdopen( dp[0], "r" );
279
return fdopen( dp[1], "w" );
284
pClose( FILE *f, volatile int *pid )
291
locate( const char *exe )
294
char *path, *pathe, *name, *thenam, nambuf[PATH_MAX+1];
296
if (!(path = getenv( "PATH" ))) {
297
logError( "Can't execute %'s: $PATH not set.\n", exe );
301
name = nambuf + PATH_MAX - len;
302
memcpy( name, exe, len + 1 );
305
if (!(pathe = strchr( path, ':' )))
306
pathe = path + strlen( path );
308
if (len && !(len == 1 && *path == '.')) {
310
if (thenam >= nambuf) {
311
memcpy( thenam, path, len );
312
if (!access( thenam, X_OK )) {
313
strDup( &name, thenam );
319
} while (*path++ != '\0');
320
logError( "Can't execute %'s: not in $PATH.\n", exe );
325
static GTalk *curtalk;
334
gCloseOnExec( GPipe *pajp )
336
fcntl( pajp->fd.r, F_SETFD, FD_CLOEXEC );
338
fcntl( pajp->fd.w, F_SETFD, FD_CLOEXEC );
342
#if !defined(SINGLE_PIPE) || defined(__FreeBSD__)
343
# define make_pipe(h) pipe( h )
345
# define make_pipe(h) socketpair( AF_UNIX, SOCK_STREAM, 0, h )
349
gFork( GPipe *pajp, const char *pname, char *cname,
350
GPipe *ogp, char *cgname,
354
int opipe[2], ogpipe[2];
356
int ipipe[2], igpipe[2];
360
if (make_pipe( opipe ))
367
if (make_pipe( ogpipe ))
384
logError( "Cannot start %s, pipe() failed", cname );
390
registerCloseOnFork( opipe[1] );
392
registerCloseOnFork( ipipe[0] );
395
registerCloseOnFork( ogpipe[1] );
397
registerCloseOnFork( igpipe[0] );
401
clearCloseOnFork( gp->fd.r );
403
clearCloseOnFork( gp->fd.w );
406
if ((pid = Fork( pidr ))) {
408
registerCloseOnFork( gp->fd.r );
410
registerCloseOnFork( gp->fd.w );
426
closeNclearCloseOnFork( opipe[1] );
428
closeNclearCloseOnFork( ipipe[0] );
431
closeNclearCloseOnFork( ogpipe[1] );
433
closeNclearCloseOnFork( igpipe[0] );
436
logError( "Cannot start %s, fork() failed\n", cname );
442
pajp->fd.w = ipipe[1];
443
registerCloseOnFork( ipipe[1] );
445
pajp->fd.r = opipe[0];
446
registerCloseOnFork( opipe[0] );
447
pajp->who = (char *)pname;
450
ogp->fd.w = igpipe[1];
451
registerCloseOnFork( igpipe[1] );
453
ogp->fd.r = ogpipe[0];
454
registerCloseOnFork( ogpipe[0] );
455
ogp->who = (char *)pname;
461
pajp->fd.w = opipe[1];
463
pajp->fd.r = ipipe[0];
467
ogp->fd.w = ogpipe[1];
469
ogp->fd.r = igpipe[0];
478
gOpen( GProc *proc, char **argv, const char *what, char **env, char *cname,
486
logError( "%s already running\n", cname );
491
if (!(margv = xCopyStrArr( 1, argv ))) {
496
if (!strApp( margv, progpath, what, (char *)0 )) {
503
logError( "Cannot start %s, pipe() failed\n", cname );
508
switch (gFork( &proc->pipe, 0, cname, 0, 0, gp, &proc->pid )) {
518
(void)Signal( SIGPIPE, SIG_IGN );
520
fcntl( pip[1], F_SETFD, FD_CLOEXEC );
522
sprintf( coninfo, "CONINFO=%d %d %d %d",
523
proc->pipe.fd.r, proc->pipe.fd.w, gp->fd.r, gp->fd.w );
525
sprintf( coninfo, "CONINFO=%d %d",
526
proc->pipe.fd.r, proc->pipe.fd.w );
527
env = putEnv( coninfo, env );
528
if (debugLevel & DEBUG_VALGRIND) {
529
char **nmargv = xCopyStrArr( 1, margv );
530
nmargv[0] = locate( "valgrind" );
531
execute( nmargv, env );
532
} else if (debugLevel & DEBUG_STRACE) {
533
char **nmargv = xCopyStrArr( 1, margv );
534
nmargv[0] = locate( "strace" );
535
execute( nmargv, env );
537
execute( margv, env );
538
write( pip[1], "", 1 );
541
(void)Signal( SIGPIPE, SIG_IGN );
543
if (reader( pip[0], coninfo, 1 )) {
545
logError( "Cannot execute %\"s (%s)\n", margv[0], cname );
546
gClosen( &proc->pipe );
550
debug( "started %s (%\"s), pid %d\n", cname, margv[0], proc->pid );
553
gSendInt( debugLevel );
559
_gClosen( GPipe *pajp )
561
closeNclearCloseOnFork( pajp->fd.r );
563
closeNclearCloseOnFork( pajp->fd.w );
570
gClosen( GPipe *pajp )
579
gClose( GProc *proc, GPipe *gp, int force )
583
if (proc->pid <= 0) {
584
debug( "whoops, gClose while helper not running\n" );
587
_gClosen( &proc->pipe );
591
terminateProcess( proc->pid, SIGTERM );
592
ret = Wait4( &proc->pid );
593
if (wcSig( ret ) ? wcSig( ret ) != SIGTERM :
594
(wcCode( ret ) < EX_NORMAL || wcCode( ret ) > EX_MAX))
595
logError( "Abnormal termination of %s, code %d, signal %d\n",
596
proc->pipe.who, wcCode( ret ), wcSig( ret ) );
597
debug( "closed %s\n", proc->pipe.who );
599
free( proc->pipe.who );
604
static void ATTR_NORETURN
607
Longjmp( curtalk->errjmp, 1 );
611
gRead( void *buf, int len )
613
if (reader( curtalk->pipe->fd.r, buf, len ) != len) {
614
logError( "Cannot read from %s\n", curtalk->pipe->who );
620
gWrite( const void *buf, int len )
622
if (writer( curtalk->pipe->fd.w, buf, len ) != len) {
623
logError( "Cannot write to %s\n", curtalk->pipe->who );
626
#ifdef _POSIX_PRIORITY_SCHEDULING
627
if ((debugLevel & DEBUG_HLPCON))
635
gDebug( "sending int %d (%#x) to %s\n", val, val, curtalk->pipe->who );
636
gWrite( &val, sizeof(val) );
644
gDebug( "receiving int from %s ...\n", curtalk->pipe->who );
645
gRead( &val, sizeof(val) );
646
gDebug( " -> %d (%#x)\n", val, val );
653
gDebug( "receiving command from %s ...\n", curtalk->pipe->who );
654
if (reader( curtalk->pipe->fd.r, cmd, sizeof(*cmd) ) == sizeof(*cmd)) {
655
gDebug( " -> %d\n", *cmd );
658
gDebug( " -> no data\n" );
663
gSendArr( int len, const char *data )
665
gDebug( "sending array[%d] %02[*{hhx to %s\n",
666
len, len, data, curtalk->pipe->who );
667
gWrite( &len, sizeof(len) );
672
_gRecvArr( int *rlen )
677
gRead( &len, sizeof(len) );
679
gDebug( " -> %d bytes\n", len );
680
if (!len || len > 0x10000)
682
if (!(buf = Malloc( len )))
689
gRecvArr( int *rlen )
693
gDebug( "receiving array from %s ...\n", curtalk->pipe->who );
694
buf = _gRecvArr( rlen );
695
gDebug( " -> %02[*{hhx\n", *rlen, buf );
700
_gRecvArrBuf( char *buf )
704
gRead( &len, sizeof(len) );
705
gDebug( " -> %d bytes\n", len );
706
if (len && len < 0x10000)
712
gRecvArrBuf( char *buf )
716
gDebug( "receiving already allocated array from %s ...\n",
717
curtalk->pipe->who );
718
len = _gRecvArrBuf( buf );
719
gDebug( " -> %02[*{hhx\n", len, buf );
724
gRecvStrBuf( char *buf )
728
gDebug( "receiving already allocated string from %s ...\n",
729
curtalk->pipe->who );
730
len = _gRecvArrBuf( buf );
731
gDebug( " -> %\".*s\n", len, buf );
736
gSendStr( const char *buf )
740
gDebug( "sending string %\"s to %s\n", buf, curtalk->pipe->who );
742
len = strlen( buf ) + 1;
743
gWrite( &len, sizeof(len) );
746
gWrite( &buf, sizeof(int) );
750
gSendNStr( const char *buf, int len )
753
gDebug( "sending string %\".*s to %s\n", len, buf, curtalk->pipe->who );
754
gWrite( &tlen, sizeof(tlen) );
760
gSendStrN( const char *buf, int len )
763
gSendNStr( buf, strnlen( buf, len ) );
774
gDebug( "receiving string from %s ...\n", curtalk->pipe->who );
775
buf = _gRecvArr( &len );
776
gDebug( " -> %\".*s\n", len, buf );
781
_gSendStrArr( int num, char **data )
785
gWrite( &num, sizeof(num) );
786
for (cdata = data; --num >= 0; cdata++)
792
gSendStrArr (int num, char **data)
794
gDebug( "sending string array[%d] to %s\n", num, curtalk->pipe->who );
795
_gSendStrArr( num, data );
800
gRecvStrArr( int *rnum )
803
char **argv, **cargv;
805
gDebug( "receiving string array from %s ...\n", curtalk->pipe->who );
806
gRead( &num, sizeof(num) );
807
gDebug( " -> %d strings\n", num );
811
if (!(argv = Malloc( num * sizeof(char *) )))
813
for (cargv = argv; --num >= 0; cargv++)
819
gSendArgv( char **argv )
824
for (num = 0; argv[num]; num++);
825
gDebug( "sending argv[%d] to %s ...\n", num, curtalk->pipe->who );
826
_gSendStrArr( num + 1, argv );
828
gDebug( "sending NULL argv to %s\n", curtalk->pipe->who );
829
gWrite( &argv, sizeof(int) );
838
return gRecvStrArr( &num );