diff options
Diffstat (limited to 'kdm/backend/process.c')
-rw-r--r-- | kdm/backend/process.c | 762 |
1 files changed, 0 insertions, 762 deletions
diff --git a/kdm/backend/process.c b/kdm/backend/process.c deleted file mode 100644 index f9d34fe7f..000000000 --- a/kdm/backend/process.c +++ /dev/null @@ -1,762 +0,0 @@ -/* - -Copyright 1988, 1998 The Open Group -Copyright 2001-2004 Oswald Buddenhagen <ossi@kde.org> - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of a copyright holder shall -not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization -from the copyright holder. - -*/ - -/* - * xdm - display manager daemon - * Author: Keith Packard, MIT X Consortium - * - * subdaemon and external process management and communication - */ - -#include "dm.h" -#include "dm_error.h" - -#include <ctype.h> -#include <stdio.h> -#include <stdarg.h> -#include <signal.h> -#include <unistd.h> -#ifdef _POSIX_PRIORITY_SCHEDULING -# include <sched.h> -#endif - -extern char **environ; - - -SIGFUNC Signal( int sig, SIGFUNC handler ) -{ -#ifndef __EMX__ - struct sigaction sigact, osigact; - sigact.sa_handler = handler; - sigemptyset( &sigact.sa_mask ); -# ifdef SA_RESTART - sigact.sa_flags = SA_RESTART; -# else - sigact.sa_flags = 0; -# endif - sigaction( sig, &sigact, &osigact ); - return osigact.sa_handler; -#else - return signal( sig, handler ); -#endif -} - - -void -TerminateProcess( int pid, int sig ) -{ - kill( pid, sig ); -#ifdef SIGCONT - kill( pid, SIGCONT ); -#endif -} - - -static FD_TYPE CloseMask; -static int max = -1; - -void -RegisterCloseOnFork( int fd ) -{ - FD_SET( fd, &CloseMask ); - if (fd > max) - max = fd; -} - -void -ClearCloseOnFork( int fd ) -{ - FD_CLR( fd, &CloseMask ); -} - -void -CloseNClearCloseOnFork( int fd ) -{ - close( fd ); - FD_CLR( fd, &CloseMask ); -} - -static void -CloseOnFork( void ) -{ - int fd; - - for (fd = 0; fd <= max; fd++) - if (FD_ISSET( fd, &CloseMask )) - close( fd ); - FD_ZERO( &CloseMask ); - max = -1; -} - -int -Fork() -{ - int pid; - - sigset_t ss, oss; - sigfillset( &ss ); - sigprocmask( SIG_SETMASK, &ss, &oss ); - - if (!(pid = fork())) { -#ifdef SIGCHLD - (void)Signal( SIGCHLD, SIG_DFL ); -#endif - (void)Signal( SIGTERM, SIG_DFL ); - (void)Signal( SIGINT, SIG_IGN ); /* for -nodaemon */ - (void)Signal( SIGPIPE, SIG_DFL ); - (void)Signal( SIGALRM, SIG_DFL ); - (void)Signal( SIGHUP, SIG_DFL ); - sigemptyset( &ss ); - sigprocmask( SIG_SETMASK, &ss, NULL ); - CloseOnFork(); - return 0; - } - - sigprocmask( SIG_SETMASK, &oss, 0 ); - - return pid; -} - -int -Wait4( int pid ) -{ - waitType result; - - while (waitpid( pid, &result, 0 ) < 0) - if (errno != EINTR) { - Debug( "Wait4(%d) failed: %m\n", pid ); - return 0; - } - return waitVal( result ); -} - - -void -execute( char **argv, char **env ) -{ - Debug( "execute: %[s ; %[s\n", argv, env ); - execve( argv[0], argv, env ); - /* - * In case this is a shell script which hasn't been - * made executable (or this is a SYSV box), do - * a reasonable thing - */ - if (errno != ENOENT) { - char **newargv; - FILE *f; - int nu; - char program[1024]; - - /* - * emulate BSD kernel behaviour -- read - * the first line; check if it starts - * with "#!", in which case it uses - * the rest of the line as the name of - * program to run. Else use "/bin/sh". - */ - if (!(f = fopen( argv[0], "r" ))) - return; - if (!fGets( program, sizeof(program), f )) { - fclose( f ); - return; - } - fclose( f ); - if (!strncmp( program, "#!", 2 )) - newargv = parseArgs( 0, program + 2 ); - else - newargv = addStrArr( 0, "/bin/sh", 7 ); - if (!newargv) - return; - nu = arrLen( newargv ); - if (!(argv = xCopyStrArr( nu, argv ))) - return; - memcpy( argv, newargv, sizeof(char *) * nu ); - Debug( "shell script execution: %[s\n", argv ); - execve( argv[0], argv, env ); - } -} - -int -runAndWait( char **args, char **env ) -{ - int pid, ret; - - switch (pid = Fork()) { - case 0: - execute( args, env ); - LogError( "Can't execute %\"s: %m\n", args[0] ); - exit( 127 ); - case -1: - LogError( "Can't fork to execute %\"s: %m\n", args[0] ); - return 1; - } - ret = Wait4( pid ); - return waitVal( ret ); -} - -FILE * -pOpen( char **what, char m, int *pid ) -{ - int dp[2]; - - if (pipe( dp )) - return 0; - switch ((*pid = Fork())) { - case 0: - if (m == 'r') - dup2( dp[1], 1 ); - else - dup2( dp[0], 0 ); - close( dp[0] ); - close( dp[1] ); - execute( what, environ ); - LogError( "Can't execute %\"s: %m\n", what[0] ); - exit( 127 ); - case -1: - close( dp[0] ); - close( dp[1] ); - LogError( "Can't fork to execute %\"s: %m\n", what[0] ); - return 0; - } - if (m == 'r') { - close( dp[1] ); - return fdopen( dp[0], "r" ); - } else { - close( dp[0] ); - return fdopen( dp[1], "w" ); - } -} - -int -pClose( FILE *f, int pid ) -{ - fclose( f ); - return Wait4( pid ); -} - -char * -locate( const char *exe ) -{ - int len; - char *path, *name, *thenam, nambuf[PATH_MAX+1]; - char *pathe; - - if (!(path = getenv( "PATH" ))) { - LogError( "Can't execute %'s: $PATH not set.\n", exe ); - return 0; - } - len = strlen( exe ); - name = nambuf + PATH_MAX - len; - memcpy( name, exe, len + 1 ); - *--name = '/'; - do { - if (!(pathe = strchr( path, ':' ))) - pathe = path + strlen( path ); - len = pathe - path; - if (len && !(len == 1 && *path == '.')) { - thenam = name - len; - if (thenam >= nambuf) { - memcpy( thenam, path, len ); - if (!access( thenam, X_OK )) { - StrDup( &name, thenam ); - return name; - } - } - } - path = pathe; - } while (*path++ != '\0'); - LogError( "Can't execute %'s: not in $PATH.\n", exe ); - return 0; -} - - -static GTalk *curtalk; - -void -GSet( GTalk *tlk ) -{ - curtalk = tlk; -} - -int -GFork( GPipe *pajp, const char *pname, char *cname, - GPipe *ogp, char *cgname ) -{ - int opipe[2], ipipe[2], ogpipe[2], igpipe[2], pid; - - if (pipe( opipe )) - goto badp1; - if (pipe( ipipe )) - goto badp2; - if (ogp) { - if (pipe( ogpipe )) - goto badp3; - if (pipe( igpipe )) { - close( ogpipe[0] ); - close( ogpipe[1] ); - badp3: - close( ipipe[0] ); - close( ipipe[1] ); - badp2: - close( opipe[0] ); - close( opipe[1] ); - badp1: - LogError( "Cannot start %s, pipe() failed", cname ); - if (cname) - free( cname ); - return -1; - } - } - RegisterCloseOnFork( opipe[1] ); - RegisterCloseOnFork( ipipe[0] ); - if (ogp) { - RegisterCloseOnFork( ogpipe[1] ); - RegisterCloseOnFork( igpipe[0] ); - } - switch (pid = Fork()) { - case -1: - close( opipe[0] ); - close( ipipe[1] ); - CloseNClearCloseOnFork( opipe[1] ); - CloseNClearCloseOnFork( ipipe[0] ); - if (ogp) { - close( ogpipe[0] ); - close( igpipe[1] ); - CloseNClearCloseOnFork( ogpipe[1] ); - CloseNClearCloseOnFork( igpipe[0] ); - } - LogError( "Cannot start %s, fork() failed\n", cname ); - if (cname) - free( cname ); - return -1; - case 0: - pajp->wfd = ipipe[1]; - RegisterCloseOnFork( ipipe[1] ); - pajp->rfd = opipe[0]; - RegisterCloseOnFork( opipe[0] ); - pajp->who = (char *)pname; - if (ogp) { - ogp->wfd = igpipe[1]; - RegisterCloseOnFork( igpipe[1] ); - ogp->rfd = ogpipe[0]; - RegisterCloseOnFork( ogpipe[0] ); - ogp->who = (char *)pname; - } - break; - default: - close( opipe[0] ); - close( ipipe[1] ); - pajp->rfd = ipipe[0]; - pajp->wfd = opipe[1]; - pajp->who = cname; - if (ogp) { - close( ogpipe[0] ); - close( igpipe[1] ); - ogp->rfd = igpipe[0]; - ogp->wfd = ogpipe[1]; - ogp->who = cgname; - } - break; - } - return pid; -} - -int -GOpen( GProc *proc, char **argv, const char *what, char **env, char *cname, - GPipe *gp ) -{ - char **margv; - int pip[2]; - char coninfo[32]; - -/* ### GSet (proc->pipe); */ - if (proc->pid) { - LogError( "%s already running\n", cname ); - if (cname) - free( cname ); - return -1; - } - if (!(margv = xCopyStrArr( 1, argv ))) { - if (cname) - free( cname ); - return -1; - } - if (!StrApp( margv, progpath, what, (char *)0 )) { - free( margv ); - if (cname) - free( cname ); - return -1; - } - if (pipe( pip )) { - LogError( "Cannot start %s, pipe() failed\n", cname ); - if (cname) - free( cname ); - goto fail; - } - if (gp) { - ClearCloseOnFork( gp->rfd ); - ClearCloseOnFork( gp->wfd ); - } - proc->pid = GFork( &proc->pipe, 0, cname, 0, 0 ); - if (proc->pid) { - close( pip[1] ); - if (gp) { - RegisterCloseOnFork( gp->rfd ); - RegisterCloseOnFork( gp->wfd ); - } - } - switch (proc->pid) { - case -1: - fail1: - close( pip[0] ); - fail: - free( margv[0] ); - free( margv ); - return -1; - case 0: - (void)Signal( SIGPIPE, SIG_IGN ); - close( pip[0] ); - fcntl( pip[1], F_SETFD, FD_CLOEXEC ); - if (gp) - sprintf( coninfo, "CONINFO=%d %d %d %d", - proc->pipe.rfd, proc->pipe.wfd, gp->rfd, gp->wfd ); - else - sprintf( coninfo, "CONINFO=%d %d", - proc->pipe.rfd, proc->pipe.wfd ); - env = putEnv( coninfo, env ); - if (debugLevel & DEBUG_VALGRIND) { - char **nmargv = xCopyStrArr( 1, margv ); - nmargv[0] = locate( "valgrind" ); - execute( nmargv, env ); - } else if (debugLevel & DEBUG_STRACE) { - char **nmargv = xCopyStrArr( 1, margv ); - nmargv[0] = locate( "strace" ); - execute( nmargv, env ); - } else - execute( margv, env ); - write( pip[1], "", 1 ); - exit( 1 ); - default: - (void)Signal( SIGPIPE, SIG_IGN ); - if (Reader( pip[0], coninfo, 1 )) { - Wait4( proc->pid ); - LogError( "Cannot execute %\"s (%s)\n", margv[0], cname ); - GClosen (&proc->pipe); - goto fail1; - } - close( pip[0] ); - Debug( "started %s (%\"s), pid %d\n", cname, margv[0], proc->pid ); - free( margv[0] ); - free( margv ); - GSendInt( debugLevel ); - return 0; - } -} - -static void -iGClosen( GPipe *pajp ) -{ - CloseNClearCloseOnFork( pajp->rfd ); - CloseNClearCloseOnFork( pajp->wfd ); - pajp->rfd = pajp->wfd = -1; -} - -void -GClosen (GPipe *pajp) -{ - iGClosen( pajp ); - if (pajp->who) - free( pajp->who ); - pajp->who = 0; -} - -int -GClose (GProc *proc, GPipe *gp, int force) -{ - int ret; - - if (!proc->pid) { - Debug( "whoops, GClose while helper not running\n" ); - return 0; - } - iGClosen( &proc->pipe ); - if (gp) - GClosen (gp); - if (force) - TerminateProcess( proc->pid, SIGTERM ); - ret = Wait4( proc->pid ); - proc->pid = 0; - if (WaitSig( ret ) ? WaitSig( ret ) != SIGTERM : - (WaitCode( ret ) < EX_NORMAL || WaitCode( ret ) > EX_MAX)) - LogError( "Abnormal termination of %s, code %d, signal %d\n", - proc->pipe.who, WaitCode( ret ), WaitSig( ret ) ); - Debug( "closed %s\n", proc->pipe.who ); - if (proc->pipe.who) - free( proc->pipe.who ); - proc->pipe.who = 0; - return ret; -} - -static void ATTR_NORETURN -GErr( void ) -{ - Longjmp( curtalk->errjmp, 1 ); -} - -static void -GRead( void *buf, int len ) -{ - if (Reader( curtalk->pipe->rfd, buf, len ) != len) { - LogError( "Cannot read from %s\n", curtalk->pipe->who ); - GErr(); - } -} - -static void -GWrite( const void *buf, int len ) -{ - if (Writer( curtalk->pipe->wfd, buf, len ) != len) { - LogError( "Cannot write to %s\n", curtalk->pipe->who ); - GErr(); - } -#ifdef _POSIX_PRIORITY_SCHEDULING - if ((debugLevel & DEBUG_HLPCON)) - sched_yield(); -#endif -} - -void -GSendInt( int val ) -{ - GDebug( "sending int %d (%#x) to %s\n", val, val, curtalk->pipe->who ); - GWrite( &val, sizeof(val) ); -} - -int -GRecvInt() -{ - int val; - - GDebug( "receiving int from %s ...\n", curtalk->pipe->who ); - GRead( &val, sizeof(val) ); - GDebug( " -> %d (%#x)\n", val, val ); - return val; -} - -int -GRecvCmd( int *cmd ) -{ - GDebug( "receiving command from %s ...\n", curtalk->pipe->who ); - if (Reader( curtalk->pipe->rfd, cmd, sizeof(*cmd) ) == sizeof(*cmd)) { - GDebug( " -> %d\n", *cmd ); - return 1; - } - GDebug( " -> no data\n" ); - return 0; -} - -void -GSendArr( int len, const char *data ) -{ - GDebug( "sending array[%d] %02[*{hhx to %s\n", - len, len, data, curtalk->pipe->who ); - GWrite( &len, sizeof(len) ); - GWrite( data, len ); -} - -static char * -iGRecvArr( int *rlen ) -{ - int len; - char *buf; - - GRead( &len, sizeof(len) ); - *rlen = len; - GDebug( " -> %d bytes\n", len ); - if (!len) - return (char *)0; - if (!(buf = Malloc( len ))) - GErr(); - GRead( buf, len ); - return buf; -} - -char * -GRecvArr( int *rlen ) -{ - char *buf; - - GDebug( "receiving array from %s ...\n", curtalk->pipe->who ); - buf = iGRecvArr( rlen ); - GDebug( " -> %02[*{hhx\n", *rlen, buf ); - return buf; -} - -static int -iGRecvArrBuf( char *buf ) -{ - int len; - - GRead( &len, sizeof(len) ); - GDebug( " -> %d bytes\n", len ); - if (len) - GRead( buf, len ); - return len; -} - -int -GRecvArrBuf( char *buf ) -{ - int len; - - GDebug( "receiving already allocated array from %s ...\n", - curtalk->pipe->who ); - len = iGRecvArrBuf( buf ); - GDebug( " -> %02[*{hhx\n", len, buf ); - return len; -} - -int -GRecvStrBuf( char *buf ) -{ - int len; - - GDebug( "receiving already allocated string from %s ...\n", - curtalk->pipe->who ); - len = iGRecvArrBuf( buf ); - GDebug( " -> %\".*s\n", len, buf ); - return len; -} - -void -GSendStr( const char *buf ) -{ - int len; - - GDebug( "sending string %\"s to %s\n", buf, curtalk->pipe->who ); - if (buf) { - len = strlen( buf ) + 1; - GWrite( &len, sizeof(len) ); - GWrite( buf, len ); - } else - GWrite( &buf, sizeof(int) ); -} - -void -GSendNStr( const char *buf, int len ) -{ - int tlen = len + 1; - GDebug( "sending string %\".*s to %s\n", len, buf, curtalk->pipe->who ); - GWrite( &tlen, sizeof(tlen) ); - GWrite( buf, len ); - GWrite( "", 1 ); -} - -void -GSendStrN( const char *buf, int len ) -{ - if (buf) - GSendNStr( buf, StrNLen( buf, len ) ); - else - GSendStr( buf ); -} - -char * -GRecvStr() -{ - int len; - char *buf; - - GDebug( "receiving string from %s ...\n", curtalk->pipe->who ); - buf = iGRecvArr( &len ); - GDebug( " -> %\".*s\n", len, buf ); - return buf; -} - -static void -iGSendStrArr( int num, char **data ) -{ - char **cdata; - - GWrite( &num, sizeof(num) ); - for (cdata = data; --num >= 0; cdata++) - GSendStr( *cdata ); -} - -/* -void -GSendStrArr (int num, char **data) -{ - GDebug( "sending string array[%d] to %s\n", num, curtalk->pipe->who ); - iGSendStrArr( num, data ); -} -*/ - -char ** -GRecvStrArr( int *rnum ) -{ - int num; - char **argv, **cargv; - - GDebug( "receiving string array from %s ...\n", curtalk->pipe->who ); - GRead( &num, sizeof(num) ); - GDebug( " -> %d strings\n", num ); - *rnum = num; - if (!num) - return (char **)0; - if (!(argv = Malloc( num * sizeof(char *) ))) - GErr(); - for (cargv = argv; --num >= 0; cargv++) - *cargv = GRecvStr(); - return argv; -} - -void -GSendArgv( char **argv ) -{ - int num; - - if (argv) { - for (num = 0; argv[num]; num++); - GDebug( "sending argv[%d] to %s ...\n", num, curtalk->pipe->who ); - iGSendStrArr( num + 1, argv ); - } else { - GDebug( "sending NULL argv to %s\n", curtalk->pipe->who ); - GWrite( &argv, sizeof(int) ); - } -} - -char ** -GRecvArgv() -{ - int num; - - return GRecvStrArr( &num ); -} - |