summaryrefslogtreecommitdiffstats
path: root/xpa/xlaunch.c
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2018-01-23 16:53:51 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2018-01-23 16:53:51 (GMT)
commit51e1f85047b34f095ed69a3024d696997d2667c8 (patch)
treea8d46838982aa78a35653c10d0b7370d751d6181 /xpa/xlaunch.c
parent0c198f7902ee997dd8ec3631e8ff1c385257014d (diff)
downloadblt-51e1f85047b34f095ed69a3024d696997d2667c8.zip
blt-51e1f85047b34f095ed69a3024d696997d2667c8.tar.gz
blt-51e1f85047b34f095ed69a3024d696997d2667c8.tar.bz2
upgrade xpa
Diffstat (limited to 'xpa/xlaunch.c')
-rw-r--r--xpa/xlaunch.c657
1 files changed, 0 insertions, 657 deletions
diff --git a/xpa/xlaunch.c b/xpa/xlaunch.c
deleted file mode 100644
index 9f064d1..0000000
--- a/xpa/xlaunch.c
+++ /dev/null
@@ -1,657 +0,0 @@
-/*
- * Copyright (c) 1999-2007 Smithsonian Astrophysical Observatory
- */
-
-#include <xlaunch.h>
-
-/*
- *----------------------------------------------------------------------------
- *
- *
- * Private Routines and Data
- *
- *
- *----------------------------------------------------------------------------
- */
-
-static pid_t pid=0;
-
-#if HAVE_MINGW32==0
-
-/* wait for child process to start, using waitpid() */
-#ifdef ANSI_FUNC
-static int launch_pipes(int *pipes, int flag)
-#else
-static int launch_pipes(pipes, flag)
- int *pipes;
- int flag;
-#endif
-{
- int i;
- char tbuf[SZ_LINE];
- if( pipes ){
- for(i=0; i<4; i++){
- pipes[i] = -1;
- }
- if( (pipe(&pipes[0]) < 0) || (pipe(&pipes[2]) < 0) ) return -1;
- if( flag ){
-#if HAVE_SETENV
- snprintf(tbuf, SZ_LINE-1, "%d,%d,%d,%d",
- pipes[0], pipes[1], pipes[2], pipes[3]);
- setenv("LAUNCH_PIPES", tbuf, 1);
-#else
- snprintf(tbuf, SZ_LINE-1, "LAUNCH_PIPES=%d,%d,%d,%d",
- pipes[0], pipes[1], pipes[2], pipes[3]);
- putenv(xstrdup(tbuf));
-#endif
- }
- }
- return 0;
-}
-
-#ifdef ANSI_FUNC
-static int cleanup_pipes(int *pipes)
-#else
-static int cleanup_pipes(pipes)
- int *pipes;
-#endif
-{
- if( pipes ){
- /* close child pipes */
- close(pipes[1]);
- close(pipes[2]);
- /* move parent write into slot 1 */
- pipes[1] = pipes[3];
- /* set unused pipes to impossible value */
- pipes[2] = -1;
- pipes[3] = -1;
- }
- return 0;
-}
-
-#if LAUNCH_USE_WAITPID
-/* wait for child process to start, using waitpid() */
-#ifdef ANSI_FUNC
-static int launch_waitstart(pid_t pid)
-#else
-static int launch_waitstart(pid)
- pid_t pid;
-#endif
-{
- int i, got;
- int status=0;
- struct timeval tv;
- /* wait up to LAUNCH_WAIT_TRIES millisec to make sure the child started,
- but if we get an error, we can exit immediately */
- for(i=0; i<LAUNCH_WAIT_TRIES; i++){
- errno = 0;
- got=waitpid(pid, &status, WNOHANG);
- /* look for error termination */
- if( (got < 0) || ((got == 0) && xerrno) ){
- got = -1;
- /* make sure status shows error */
- if( status == 0 )
- status = -1;
- break;
- }
- /* look for normal termination */
- else if( got > 0 ){
- break;
- }
- /* no termination, sleep and wait some more */
- else{
- tv.tv_sec = 0;
- tv.tv_usec = LAUNCH_WAIT_MSEC;
- xselect(1, NULL, NULL, NULL, &tv);
- }
- }
- /* no termination means the child is still running */
- if( got == 0 ) status = 0;
- /* return the news */
- return status;
-}
-#endif
-
-/*
- * standard unix version of launch:
- * adapted from the system() code in:
- * W. Richard Stevens
- * "Advanced Programming in the Unix Environment"
- * Addison-Wesley Publishing Co, 1992
- * p. 314
- */
-#ifdef ANSI_FUNC
-static int launch_fork_exec(char *cmdstring, int attach,
- char **stdfiles, int *pipes)
-#else
- static int launch_fork_exec(cmdstring, attach, stdfiles, pipes)
- char *cmdstring;
- int attach;
- char **stdfiles;
- int *pipes;
-#endif
-{
- int status;
- int tpipes[4];
- struct sigaction ignore, saveintr, savequit;
- sigset_t chldmask, savemask;
-#if LAUNCH_USE_PIPE
- int fd[2];
-#endif
-
- /* return false if no command is specified */
- if( !cmdstring || !*cmdstring ) return -1;
-
- ignore.sa_handler = SIG_IGN; /* ignore SIGINT and SIGQUIT */
- sigemptyset(&ignore.sa_mask);
- ignore.sa_flags = 0;
- if (sigaction(SIGINT, &ignore, &saveintr) < 0)
- return -1;
- if (sigaction(SIGQUIT, &ignore, &savequit) < 0)
- return -1;
-
- sigemptyset(&chldmask); /* now block SIGCHLD */
- sigaddset(&chldmask, SIGCHLD);
- if (sigprocmask(SIG_BLOCK, &chldmask, &savemask) < 0)
- return -1;
-
-#if LAUNCH_USE_PIPE
- /* open a pipe so parent can hear if the child fails to exec */
- if( !attach ){
- if( pipe(fd) < 0 )
- return -1;
- xfcntl(fd[0], F_SETFD, FD_CLOEXEC);
- xfcntl(fd[1], F_SETFD, FD_CLOEXEC);
- }
-#endif
-
- /* create temp ipc pipes if necessary */
- if( pipes ){
- if( launch_pipes(tpipes, 0) < 0 ) return -1;
- }
-
- /* start new process */
- if( (pid = fork()) < 0 ){
-#if LAUNCH_USE_PIPE
- if( !attach ){
- close(fd[0]);
- close(fd[1]);
- }
-#endif
- if( pipes ){
- close(tpipes[0]);
- close(tpipes[1]);
- close(tpipes[2]);
- close(tpipes[3]);
- }
- status = -1; /* ERROR: probably out of processes */
- } else if( pid == 0 ){ /* child */
- int i, j, len;
- char *argv[LAUNCH_ARGS+1];
- char *path=NULL;
- char *s=NULL, *t=NULL;
-
- /* reset pipes, if necessary */
- if( pipes ){
- /* close parent's read/write pipes */
- close(tpipes[0]);
- close(tpipes[3]);
- /* change child's stdin/stdout to use the passed pipes to parent */
- dup2(tpipes[2], 0); close(tpipes[2]);
- dup2(tpipes[1], 1); close(tpipes[1]);
- }
-
- /* close and reopen stdio files, if necessary */
- if( stdfiles ){
- for(i=0; i<3; i++){
- if( stdfiles[i] ){
- close(i);
- switch(i){
- case 0:
- if( open(stdfiles[i], O_RDONLY) < 0){
- _exit(-1);
- }
- break;
- case 1:
- if( open(stdfiles[i], O_CREAT|O_WRONLY|O_TRUNC, 0600) < 0){
- _exit(-1);
- }
- break;
- case 2:
- /* if stderr is the same as stdout, just dup */
- if( stdfiles[1] && !strcmp(stdfiles[1], stdfiles[i]) ){
- dup(1);
- }
- else{
- if( open(stdfiles[i], O_CREAT|O_WRONLY|O_TRUNC, 0600) < 0){
- _exit(-1);
- }
- }
- break;
- }
- }
- }
- }
-
- /* restore previous signal actions & reset signal mask, but only if
- parent is waiting for completion (i.e., we are "attached") */
- if( attach ){
- sigaction(SIGINT, &saveintr, NULL);
- sigaction(SIGQUIT, &savequit, NULL);
- sigprocmask(SIG_SETMASK, &savemask, NULL);
- }
-#if LAUNCH_USE_PIPE
- /* child closes reader -- only writes status */
- else{
- close(fd[0]);
- }
-#endif
-
- /* package up the arguments for new process */
- t = (char *)xstrdup(cmdstring);
- for(i=0, s=(char *)strtok(t, " \t"); s;
- i++, s=(char *)strtok(NULL," \t")){
- if( i < LAUNCH_ARGS ){
- /* save argument */
- argv[i] = xstrdup(s);
- /* change back special char to spaces, if necessary */
- len = strlen(argv[i]);
- for(j=0; j<len; j++){
- if( argv[i][j] == LAUNCH_SPACE){
- argv[i][j] = ' ';
- }
- }
- argv[i+1] = NULL;
- /* save program name */
- if( i == 0 ) path = argv[i];
- }
- }
- if( t ) xfree(t);
-#ifndef HAVE_CYGWIN
- /* this call is broken in cygwin */
- /* for unattached processes, start a new session (with new process id),
- so that we do not inherit signals from parent (particularly SIGTERM) */
- if( !attach )
- setsid();
-#endif
- /* start up the new program */
- if( execvp(path, argv) ){
- status = 127;
-#if LAUNCH_USE_PIPE
- if( !attach ){
- write(fd[1], &status, 4);
- close(fd[1]);
- }
-#endif
- _exit(status); /* exec error */
- }
- } else { /* parent */
- /* wait for program termination from attached process */
- if( attach ){
- while( waitpid(pid, &status, 0) < 0 ){
- if( xerrno != EINTR ){
- status = -1; /* error other than EINTR from waitpid() */
- break;
- }
- }
- }
- else{
-#if LAUNCH_USE_WAITPID
- status = launch_waitstart(pid);
-#endif
-#if LAUNCH_USE_PIPE
- close(fd[1]);
- if( read(fd[0], &status, 4) == 0 ){
- status = 0;
- }
- close(fd[0]);
-#endif
- }
- }
-
- /* cleanup temp ipc pipes and move into user space */
- if( pipes ){
- cleanup_pipes(tpipes);
- pipes[0] = tpipes[0];
- pipes[1] = tpipes[1];
- }
-
- /* restore previous signal actions & reset signal mask */
- if( sigaction(SIGINT, &saveintr, NULL) < 0 ) return -1;
- if( sigaction(SIGQUIT, &savequit, NULL) < 0 ) return -1;
- if( sigprocmask(SIG_SETMASK, &savemask, NULL) < 0 ) return -1;
-
- /* return the news */
- return status;
-}
-
-#endif
-
-#if HAVE_POSIX_SPAWN
-
-#if defined(HAVE__NSGETENVIRON) && defined(HAVE_CRT_EXTERNS_H)
-#include <crt_externs.h>
-#define environ (*_NSGetEnviron())
-#else
-extern char **environ;
-#endif
-
-/* spawn calls POSIX posix_spawn */
-#ifdef ANSI_FUNC
-static int launch_posix_spawn(char *cmdstring, int attach,
- char **stdfiles, int *pipes)
-#else
- static int launch_posix_spawn(cmdstring, attach, stdfiles, pipes)
- char *cmdstring;
- int attach;
- char **stdfiles;
- int *pipes;
-#endif
-{
- int i, j, len;
- int status=0;
- int got=0;
- int tpipes[4];
- char *argv[LAUNCH_ARGS+1];
- char *path=NULL;
- char *s=NULL, *t=NULL;
- posix_spawn_file_actions_t act;
- posix_spawn_file_actions_t *pact=NULL;
-
- /* return false if no command is specified */
- if( !cmdstring || !*cmdstring )
- return -1;
-
- /* create temp ipc pipes if necessary */
- if( pipes ){
- if( launch_pipes(tpipes, 1) < 0 ) return -1;
- }
-
- /* package up the arguments for new process */
- t = (char *)xstrdup(cmdstring);
- for(i=0, s=(char *)strtok(t, " \t"); s;
- i++, s=(char *)strtok(NULL," \t")){
- if( i < LAUNCH_ARGS ){
- /* save argument */
- argv[i] = xstrdup(s);
- /* change back special char to spaces, if necessary */
- len = strlen(argv[i]);
- for(j=0; j<len; j++){
- if( argv[i][j] == LAUNCH_SPACE){
- argv[i][j] = ' ';
- }
- }
- /* last arg is always a NULL */
- argv[i+1] = NULL;
- /* save program name */
- if( i == 0 ) path = argv[i];
- /* inc arg count */
- got++;
- }
- }
- if( t ) xfree(t);
- /* arrange stdfiles files, if necessary */
- if( stdfiles ){
- if( posix_spawn_file_actions_init(&act) != 0)
- return -1;
- /* stdin */
- if(stdfiles[0] &&
- posix_spawn_file_actions_addopen(&act, 0, stdfiles[0], O_RDONLY, 0))
- return -1;
- /* stdout */
- if(stdfiles[1] &&
- posix_spawn_file_actions_addopen(&act, 1, stdfiles[1], O_CREAT|O_WRONLY|O_TRUNC, 0600))
- return -1;
- /* stderr */
- if(stdfiles[2] &&
- posix_spawn_file_actions_addopen(&act, 2, stdfiles[2], O_CREAT|O_WRONLY|O_TRUNC, 0600))
- return -1;
- pact = &act;
- }
- /* start the new process */
- if( (status = posix_spawnp(&pid, path, pact, NULL, argv, environ)) )
- return status;
- /* wait for program termination from attached process */
- if( attach ){
- while( waitpid(pid, &status, 0) < 0 ){
- if( xerrno != EINTR ){
- status = -1; /* error other than EINTR from waitpid() */
- break;
- }
- }
- }
-#if BIG_DELAY_WHEN_USING_THIS
- /* wait for child process to start */
- else{
- status = launch_waitstart(pid);
- }
-#endif
- /* clean up */
- if( stdfiles ) posix_spawn_file_actions_destroy(&act);
- /* cleanup temp ipc pipes and move into user space */
- if( pipes ){
- cleanup_pipes(tpipes);
- pipes[0] = tpipes[0];
- pipes[1] = tpipes[1];
- }
- for(i=0; i<got; i++){
- if( argv[i] ) xfree((char *)argv[i]);
- }
- /* return status */
- return status;
-}
-
-#endif
-
-#if HAVE_SPAWNVP
-
-#ifdef ANSI_FUNC
-static int launch_spawnvp(char *cmdstring, int attach,
- char **stdfiles, int *pipes)
-#else
- static int launch_spawnvp(cmdstring, attach, stdfiles, pipes)
- char *cmdstring;
- int attach;
- char **stdfiles;
- int *pipes;
-#endif
-{
- int i, j;
- int len;
- int got;
- int status;
- int tpipes[4];
- char *argv[LAUNCH_ARGS+1];
- char *path=NULL;
- char *s=NULL, *t=NULL;
- struct timeval tv;
-
- /* return false if no command is specified */
- if( !cmdstring || !*cmdstring ) return -1;
-
- /* for now, we can't support stdfiles */
- if( stdfiles ) return -1;
-
- /* create temp ipc pipes if necessary */
- if( pipes ){
-#if HAVE_MINGW32==0
- if( launch_pipes(tpipes, 1) < 0 ) return -1;
-#else
- fprintf(stderr, "ERROR: launch_pipes() not available in mingw\n");
- exit(1);
-#endif
- }
-
-
- /* package up the arguments for new process */
- t = (char *)xstrdup(cmdstring);
- for(i=0, got=0, s=(char *)strtok(t, " \t"); s;
- i++, s=(char *)strtok(NULL," \t")){
- if( i < LAUNCH_ARGS ){
- /* save argument */
- argv[i] = xstrdup(s);
- /* change back special char to spaces, if necessary */
- len = strlen(argv[i]);
- for(j=0; j<len; j++){
- if( argv[i][j] == LAUNCH_SPACE){
- argv[i][j] = ' ';
- }
- }
- /* last arg is always a NULL */
- argv[i+1] = NULL;
- /* save program name */
- if( i == 0 ) path = (char *)argv[i];
- /* inc arg count */
- got++;
- }
- }
- if( t ) xfree(t);
- if( attach )
- i = _P_WAIT;
- else
- i = _P_NOWAIT;
- if((status = spawnvp(i, path, (void *)argv)) != -1){
- status = 0;
- /* wait for child to start */
- tv.tv_sec = 0;
- tv.tv_usec = LAUNCH_WAIT_MSEC;
- xselect(1, NULL, NULL, NULL, &tv);
- }
- /* clean up */
- for(i=0; i<got; i++){
- if( argv[i] ) xfree((char *)argv[i]);
- }
- /* cleanup temp ipc pipes and move into user space */
- if( pipes ){
-#if HAVE_MINGW32==0
- cleanup_pipes(tpipes);
- pipes[0] = tpipes[0];
- pipes[1] = tpipes[1];
-#else
- fprintf(stderr, "ERROR: launch_pipes() not available in mingw\n");
- exit(1);
-#endif
- }
- return status;
-}
-
-#endif
-
-/*
- *----------------------------------------------------------------------------
- *
- *
- * Public Routines and Data
- *
- *
- *----------------------------------------------------------------------------
- */
-
-/*
- *
- * LaunchPid() -- return pid of last launched process
- *
- */
-#ifdef ANSI_FUNC
-pid_t LaunchPid(void)
-#else
-pid_t LaunchPid()
-#endif
-{
- return pid;
-}
-
-#ifdef ANSI_FUNC
-int Launch(char *cmdstring, int attach, char **stdfiles, int *pipes)
-#else
-int Launch(cmdstring, attach, stdfiles, piles)
- char *cmdstring;
- int attach;
- char **stdfiles;
- int *pipes;
-#endif
-{
- static int which_launch=0;
- static int which_debug=0;
- char *s=NULL;
-
- /* return false if no command is specified */
- if( !cmdstring || !*cmdstring ) return -1;
-
- /* sanity check: don't specify stdfiles and pipes simultaneously */
- if( stdfiles && pipes ){
- fprintf(stderr,
- "ERROR: stdfiles and pipes are mutually exclusive in Launch()\n");
- return -1;
- }
-
- /* if pipes are specified, we don't attach */
- if( pipes ) attach = 0;
-
- /* determine launch method */
- if( !which_launch ){
- which_launch = LAUNCH_DEFAULT_WHICH;
- if( (s=getenv("LAUNCH_ROUTINE")) ){
- /* fork_exec */
- if( !strncasecmp(s, "f", 1) ){
- which_launch = 1;
- if( *s == 'F' ) which_debug = 1;
- }
- /* posix_spawn */
- else if( !strncasecmp(s, "p", 1) ){
- which_launch = 2;
- if( *s == 'P' ) which_debug = 1;
- }
- /* spawnvp */
- else if( !strncasecmp(s, "s", 1) ){
- which_launch = 3;
- if( *s == 'S' ) which_debug = 1;
- }
- else if( *s == 'V' ) {
- which_debug = 1;
- }
- }
- }
- /* call the correct launch method */
- switch(which_launch){
- case 1:
-#if HAVE_MINGW32==0
- if( which_debug ) fprintf(stderr, "launch_fork_exec: %s\n", cmdstring);
- return launch_fork_exec(cmdstring, attach, stdfiles, pipes);
-#else
- fprintf(stderr, "ERROR: fork_exec() not available on this host\n");
- exit(1);
-#endif
- break;
- case 2:
-#if HAVE_POSIX_SPAWN
- if( which_debug ) fprintf(stderr, "launch_posix_spawn: %s\n", cmdstring);
- return launch_posix_spawn(cmdstring, attach, stdfiles, pipes);
-#else
- fprintf(stderr, "ERROR: posix_spawn() not available on this host\n");
- exit(1);
-#endif
- break;
- case 3:
-#if HAVE_SPAWNVP
- if( which_debug ) fprintf(stderr, "launch_spawnvp: %s\n", cmdstring);
- return launch_spawnvp(cmdstring, attach, stdfiles, pipes);
-#else
- fprintf(stderr, "ERROR: spawnvp() not available on this host\n");
- exit(1);
-#endif
- break;
- default:
-#if HAVE_MINGW32==0
- if( which_debug ) fprintf(stderr, "launch_fork_exec: %s\n", cmdstring);
- return launch_fork_exec(cmdstring, attach, stdfiles, pipes);
-#else
- fprintf(stderr, "ERROR: no launch techniques available on this host\n");
- exit(1);
-#endif
- break;
- }
- /* can't happen */
- return -1;
-}
-