int runProgram() { //printf("runProgram()\n"); if (global.params.verbose) { fprintf(global.stdmsg, "%s", global.params.exefile); for (size_t i = 0; i < global.params.runargs_length; i++) fprintf(global.stdmsg, " %s", (char *)global.params.runargs[i]); fprintf(global.stdmsg, "\n"); } // Build argv[] Strings argv; argv.push(global.params.exefile); for (size_t i = 0; i < global.params.runargs_length; i++) { const char *a = global.params.runargs[i]; #if _WIN32 // BUG: what about " appearing in the string? if (strchr(a, ' ')) { char *b = (char *)mem.malloc(3 + strlen(a)); sprintf(b, "\"%s\"", a); a = b; } #endif argv.push(a); } argv.push(NULL); #if _WIN32 const char *ex = FileName::name(global.params.exefile); if (ex == global.params.exefile) ex = FileName::combine(".", ex); else ex = global.params.exefile; // spawnlp returns intptr_t in some systems, not int return spawnv(0,ex,argv.tdata()); #elif linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun pid_t childpid; int status; childpid = fork(); if (childpid == 0) { const char *fn = argv[0]; if (!FileName::absolute(fn)) { // Make it "./fn" fn = FileName::combine(".", fn); } execv(fn, (char **)argv.tdata()); perror(fn); // failed to execute return -1; } waitpid(childpid, &status, 0); if (WIFEXITED(status)) { status = WEXITSTATUS(status); //printf("--- errorlevel %d\n", status); } else if (WIFSIGNALED(status)) { printf("--- killed by signal %d\n", WTERMSIG(status)); status = 1; } return status; #else assert(0); #endif }
/* Set up in, out, err pipes and spawn a program, waiting or otherwise. */ HANDLE spawn ( const char *program, const char *const *argv, int in, int out, int err, int search, char *envp, char *ptyname, int wait, char *pwd ) { int stdout_backup, stdin_backup, stderr_backup, wait_mode; HANDLE hProcess; HANDLE hReturn; /* Duplicate and save the original stdin/out/err handles. */ stdout_backup = _dup ( _fileno ( stdout ) ); stdin_backup = _dup ( _fileno ( stdin ) ); stderr_backup = _dup ( _fileno ( stderr ) ); /* If we are not using stdin/out/err * then duplicate the new pipes to current stdin/out/err handles. * * Default std fds are used if in, out or err parameters * are -1. */ hReturn = (HANDLE)-1; hProcess = (HANDLE)-1; if ( ( out >= 0 ) && ( out != _fileno ( stdout ) ) ) { if ( _dup2 ( out, _fileno ( stdout ) ) != 0 ) goto error_exit; } if ( ( in >= 0 ) && ( in != _fileno ( stdin ) ) ) { if ( _dup2 ( in, _fileno ( stdin ) ) != 0 ) goto error_exit_out; } if ( ( err >= 0 ) && ( err != _fileno ( stderr ) ) ) { if ( _dup2 ( err, _fileno ( stderr ) ) != 0 ) goto error_exit_in; } /* Set the wait mode. */ if ( 0 == wait ) { wait_mode = P_NOWAIT; } else { wait_mode = P_WAIT; } /* Change working directory if supplied. */ if (pwd) { if (chdir(pwd) < 0) { goto error_exit; } } /* Spawn process given on the command line*/ if (search) hProcess = (HANDLE) spawnvp ( wait_mode, program, (char* const* )argv ); else hProcess = (HANDLE) spawnv ( wait_mode, program, (char* const* )argv ); /* Now that the process is launched, replace the original * in/out/err handles and close the backups. */ if ( _dup2 ( stderr_backup, _fileno ( stderr ) ) != 0 ) goto error_exit; error_exit_in: if ( _dup2 ( stdin_backup, _fileno ( stdin ) ) != 0 ) goto error_exit; error_exit_out: if ( _dup2 ( stdout_backup, _fileno ( stdout ) ) != 0 ) goto error_exit; hReturn = hProcess; error_exit: close ( stdout_backup ); close ( stdin_backup ); close ( stderr_backup ); return hReturn; }
int main( int argc, char * const argv[] ) { char myfile[ sizeof __FILE__ ]; int child = argc > 1; int handle; int status; int handle_out; long size; /*** Initialize ***/ strcpy( ProgramName, argv[0] ); /* store filename */ strlwr( ProgramName ); /* and lower case it */ strcpy( myfile, __FILE__ ); strlwr( myfile ); if( child ) { char *env_var; if( argc == 4 ) { /* Verify expected command line contents */ VERIFY( !strcmp( argv[1], ARG1 ) ); VERIFY( !strcmp( argv[2], ARG2 ) ); VERIFY( !strcmp( argv[3], ARG3 ) ); /* Verify expected environment contents */ env_var = getenv( VAR_NAME ); VERIFY( env_var ); VERIFY( !strcmp( env_var, VAR_TEXT ) ); if( NumErrors != 0 ) { return( EXIT_FAILURE ); } else { return( CHILD_RC ); } } else { if( argc == 2 ) { /* Verify expected command line contents */ VERIFY( !strcmp( argv[1], ARG_REDIR ) ); /* Write text to stdout */ printf( REDIR_TEXT ); if( NumErrors != 0 ) { return( EXIT_FAILURE ); } else { return( CHILD_RC ); } } else return( EXIT_FAILURE ); } } else { int rc; char **env; const char *path = NULL; const char *child_args[] = { ProgramName, ARG1, ARG2, ARG3, NULL }; const char *child_envp[] = { NULL, VAR_NAME "=" VAR_TEXT, "DOS4G=QUIET", NULL }; /* We need to pass PATH down to the child because DOS/4GW style stub * programs rely on it to function properly. */ env = environ; while( env ) { if( !strncmp( *env, "PATH=", 5 ) ) { path = *env; break; } ++env; } child_envp[0] = path; /* Test spawn functions */ rc = spawnle( P_WAIT, ProgramName, ProgramName, ARG1, ARG2, ARG3, NULL, child_envp ); VERIFY( rc == CHILD_RC ); rc = spawnlpe( P_WAIT, ProgramName, ProgramName, ARG1, ARG2, ARG3, NULL, child_envp ); VERIFY( rc == CHILD_RC ); rc = spawnve( P_WAIT, ProgramName, child_args, child_envp ); VERIFY( rc == CHILD_RC ); rc = spawnvpe( P_WAIT, ProgramName, child_args, child_envp ); VERIFY( rc == CHILD_RC ); /* Modify our environment that child will inherit */ VERIFY( !setenv( VAR_NAME, VAR_TEXT, 1 ) ); rc = spawnl( P_WAIT, ProgramName, ProgramName, ARG1, ARG2, ARG3, NULL ); VERIFY( rc == CHILD_RC ); rc = spawnlp( P_WAIT, ProgramName, ProgramName, ARG1, ARG2, ARG3, NULL ); VERIFY( rc == CHILD_RC ); rc = spawnv( P_WAIT, ProgramName, child_args ); VERIFY( rc == CHILD_RC ); rc = spawnvp( P_WAIT, ProgramName, child_args ); VERIFY( rc == CHILD_RC ); /* Check inherited output redirection */ handle_out = dup( STDOUT_FILENO ); handle = creat( "test.fil", S_IREAD|S_IWRITE ); VERIFY( handle != -1 ); status = dup2( handle, STDOUT_FILENO ); VERIFY( status != -1 ); status = close( handle ); VERIFY( status == 0 ); rc = spawnl( P_WAIT, ProgramName, ProgramName, ARG_REDIR, NULL ); VERIFY( rc == CHILD_RC ); status = dup2( handle_out, STDOUT_FILENO ); VERIFY( status != -1 ); handle = open( "test.fil", O_RDWR ); VERIFY( handle != -1 ); size = filelength( handle ); VERIFY( size == strlen( REDIR_TEXT ) ); status = close( handle ); VERIFY( status == 0 ); status = unlink( "test.fil" ); VERIFY( status == 0 ); signal_count = 0; signal_number = 0; /* Install SIGBREAK handler */ VERIFY( signal( SIGBREAK, break_handler ) == SIG_DFL ); /* Raise signal and verify results */ VERIFY( raise( SIGBREAK ) == 0 ); VERIFY( signal_count == 1 ); VERIFY( signal_number == SIGBREAK ); /* Raise again - nothing should have happened */ VERIFY( raise( SIGBREAK ) == 0 ); VERIFY( signal_count == 1 ); /*** Print a pass/fail message and quit ***/ if( NumErrors != 0 ) { printf( "%s: FAILURE (%d errors).\n", ProgramName, NumErrors ); return( EXIT_FAILURE ); } printf( "Tests completed (%s).\n", ProgramName ); } return( 0 ); }
int main(int argc, char **argv) { char python_bin[PATH_MAX + 1], argv0_bin[PATH_MAX + 1], *p, *q; char prog_py[PATH_MAX + 1]; const char *moreargv[ARGV_MAX + 1]; int i; (void)argc; p = argv[0]; q = NULL; while (*p != '\0') { if (*p++ == FILE_SEP) q = p; } if (q == NULL) { // Try to find argv[0] on $PATH. p = argv[0]; strncpy(argv0_bin, p, sizeof argv0_bin); q = NULL; while (*p != '\0') { if (*p++ == '.') q = p; } if (q == NULL) { argv0_bin[sizeof argv0_bin - 5] = '\0'; strcat(argv0_bin, ".exe"); } else { argv0_bin[sizeof argv0_bin - 1] = '\0'; } find_on_path(argv0_bin, python_bin); } else { // Put dirname(argv[0]) to python_bin. p = argv[0]; --q; if (q - p > PATH_MAX) { q = p + PATH_MAX; } strncpy(python_bin, p, q - p); python_bin[q - p] = '\0'; } if (python_bin[0] == '\0') { python_bin[0] = '.'; python_bin[1] = '\0'; } strcpy(prog_py, python_bin); i = strlen(python_bin); if (i + strlen(python_exe) > PATH_MAX) { i = PATH_MAX - strlen(python_exe); } python_bin[i] = FILE_SEP; strcpy(python_bin + i + 1, python_exe); i = strlen(prog_py); if (i + strlen(pdfsizeopt_py) > PATH_MAX) { i = PATH_MAX - strlen(pdfsizeopt_py); } prog_py[i] = FILE_SEP; strcpy(prog_py + i + 1, pdfsizeopt_py); moreargv[0] = "python26"; moreargv[1] = prog_py; for (i = 1; argv[i] != NULL; ++i) { moreargv[i + 1] = argv[i]; } moreargv[i + 1] = NULL; // execv(...) and P_OVERLAY don't work well in wine-1.2.2 and Windows XP, // because they make this process return before the started process finishes. i = spawnv(P_WAIT, python_bin, moreargv); if (i < 0) { fprintf(stderr, "error: could not start %s: %s\n", python_bin, strerror(errno)); return 120; } return i; }