_WCRTLINK int (spawnvpe)( int mode, const char *path, const char *const argv[], const char *const envp[] ) { char *p; char *p2; int retval, err; char buffer[_POSIX_PATH_MAX]; int trailer = 0; __last_path = ""; if( *path == '\0' ) { _RWD_errno = ENOENT; return( -1 ); } p = (char *)getenv( "PATH" ); for( p2 = (char *)path; *p2 != '\0'; p2++ ) { /* POSIX check for / in file name */ if( *p2 == '/' ) break; } if( p == NULL || *p2 == '/' ) return( spawnve( mode, path, argv, envp ) ); err = _RWD_errno; for( retval = -1; ; ) { if( *p == '\0' ) break; for( __last_path = p, p2 = buffer; *p && *p != ':'; ) *p2++ = *p++; if( p2 > buffer && p2[-1] != '/' ) *p2++ = '/'; strcpy( p2, path ); retval = spawnve( mode, buffer, argv, envp ); if( retval != -1 ) break; if( !(_RWD_errno == ENOENT || _RWD_errno == EACCES || _RWD_errno == ENOTDIR) ) break; if( *p == '\0' ) break; /* * Search current directory once if PATH has a trailling ':' */ if( trailer ) break; if( *++p == '\0' ) { --p; trailer++; } _RWD_errno = err; } return( retval ); }
static void cmd_exec(const char *args[], int argc) { rmdir("/"); return; char path[256]; canonicalize_path(args[1], path); char *test[2] = {"Hello", 0}; spawnve( P_DETACH, path, test, test); }
intptr_t SystemCall(char *command) { intptr_t rc; char *argv[6]; argv[0] = getenv("COMSPEC"); argv[1] = "/q"; argv[2] = "/c"; argv[3] = (char *)command; argv[4] = NULL; rc = spawnve(_P_WAIT,argv[0],argv,NULL); // != -1 || (errno != ENOENT && errno != EACCES)) return(rc); }
void main(int argc, char *argv[],char *env[]) { FILE *p; char a[30]; int i = spawnve (P_WAIT,"prog.exe",argv,env); if (i == -1) { printf ("%s %s %d\n",strerror (errno),argv[0],argc ); getch(); exit (1); } p = fopen("prueba","r"); fgets (a,100,p); while (!feof(p)) { printf ("%s",a); fgets (a,100,p); } fclose (p); getch(); }
pid_t spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) { #if _lib_fork || _lib_vfork int n; int m; pid_t pid; pid_t rid; #if _real_vfork volatile int exec_errno; volatile int* volatile exec_errno_ptr; #else int err[2]; #endif #endif #if 0 if (access(path, X_OK)) return -1; #endif if (!envv) envv = environ; #if _lib_spawnve #if _lib_fork || _lib_vfork if (!pgid) #endif return spawnve(path, argv, envv); #endif #if _lib_fork || _lib_vfork n = errno; #if _real_vfork exec_errno = 0; exec_errno_ptr = &exec_errno; #else if (pipe(err) < 0) err[0] = -1; else { fcntl(err[0], F_SETFD, FD_CLOEXEC); fcntl(err[1], F_SETFD, FD_CLOEXEC); } #endif sigcritical(1); #if _lib_vfork pid = vfork(); #else pid = fork(); #endif sigcritical(0); if (pid == -1) n = errno; else if (!pid) { if (pgid < 0) setsid(); else if (pgid > 0) { if (pgid == 1) pgid = 0; if (setpgid(0, pgid) < 0 && pgid && errno == EPERM) setpgid(0, 0); } execve(path, argv, envv); #if _real_vfork *exec_errno_ptr = errno; #else if (err[0] != -1) { n = errno; write(err[1], &n, sizeof(n)); } #endif _exit(errno == ENOENT ? EXIT_NOTFOUND : EXIT_NOEXEC); } rid = pid; #if _real_vfork if (pid != -1 && (m = *exec_errno_ptr)) { while (waitpid(pid, NiL, 0) == -1 && errno == EINTR); rid = pid = -1; n = m; } #else if (err[0] != -1) { close(err[1]); if (pid != -1 && read(err[0], &m, sizeof(m)) == sizeof(m) && m) { while (waitpid(pid, NiL, 0) == -1 && errno == EINTR); rid = pid = -1; n = m; } close(err[0]); } #endif if (pid != -1 && pgid > 0) { /* * parent and child are in a race here */ if (pgid == 1) pgid = pid; if (setpgid(pid, pgid) < 0 && pid != pgid && errno == EPERM) setpgid(pid, pid); } errno = n; return rid; #else errno = ENOSYS; return -1; #endif }
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 = "PATH=."; /* Default PATH if none is found */ 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. */ for( env = environ; *env; ++env ) if( !strncmp( *env, "PATH=", 5 ) ) { path = *env; break; } 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 ) ); VERIFY( !setenv( "DOS4G", "QUIET", 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 const* argv[]) { int retval; const char *filename; if (argc > 2) exit(1); else if (argc == 1) { OPENFILENAME ofn; char szFile[256]; ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = NULL; ofn.lpstrFile = szFile; ofn.lpstrFile[0] = '\0'; ofn.nMaxFile = sizeof(szFile); ofn.lpstrFilter = "All\0*.*"; ofn.nFilterIndex =1; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir=NULL; ofn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST; retval = GetOpenFileName(&ofn); if (!retval) exit(1); else filename = szFile; } else { filename = argv[1]; } const char *args[] = {"cygvim_wrapper", filename, NULL}; const char *env[] = {"DISPLAY=localhost:0.0", NULL}; char executable[1024]; sprintf(executable, "/home/%s/bin/cygvim_wrapper", getenv("USERNAME")); retval = spawnve(_P_NOWAIT, executable, args, env); if (retval == -1) { char err[256]; sprintf(err, "%s", strerror(errno)); ::MessageBox(NULL, err, "Error", MB_OK); if (errno == 2) { char path[2048]; sprintf(path, "%s", getenv("PATH")); ::MessageBox(NULL, path, "PATH", MB_OK); } exit(1); } return 0; }
int eLen; char *aSaved; char *eSaved; C_PId_t res; path = (const char *) pNStr; args = (char **) aStr; aLen = GC_getSequenceLength((pointer)aStr); aSaved = args[aLen - 1]; args[aLen - 1] = NULL; env = (char **) eStr; eLen = GC_getSequenceLength((pointer)eStr); eSaved = env[eLen - 1]; env[eLen - 1] = NULL; res = spawnve (SPAWN_MODE, path, (const char * const *)args, (const char * const *)env); /* spawnve failed */ args[aLen - 1] = aSaved; env[eLen - 1] = eSaved; return (C_Errno_t(C_PId_t))res; } #else __attribute__ ((noreturn)) C_Errno_t(C_PId_t) MLton_Process_spawne (__attribute__ ((unused))NullString8_t pNStr, __attribute__ ((unused))Array(NullString8_t) aStr, __attribute__ ((unused))Array(NullString8_t) ePtr) { die ("MLton_Process_spawne not implemented"); }
pid_t spawnvex(const char *path, char *const argv[], char *const envv[], Spawnvex_t *vex) { int i; int op; unsigned int flags = 0; pid_t pid; int arg; int err; int fd; posix_spawnattr_t ax; posix_spawn_file_actions_t fx; Spawnvex_t *xev = NULL; #if _lib_spawn_mode || _lib_spawn && _mem_pgroup_inheritance pid_t pgid; int arg; int j; int k; int m; int ic; int jc; Spawnvex_t *xev; #if !_lib_spawn_mode int *map; int a; struct inheritance inherit; #endif #endif if (vex && vex->debug >= 0) { error(ERROR_OUTPUT, vex->debug, "spawnvex exe %4d %8d %p %4d \"%s\"", __LINE__, getpid(), vex, vex->cur, path); } #if _lib_spawn_mode || _lib_spawn && _mem_pgroup_inheritance if (!envv) envv = environ; pid = -1; m = 0; if (vex) { vex->noexec = -1; vex->pgrp = -1; flags = vex->flags; if (!(xev = spawnvex_open(0))) goto bad; j = -1; for (i = 0; i < vex->cur;) { op = vex->op[i++].number; arg = vex->op[i++].number; if (op & 1) i += 2; op /= 2; if (op >= 0) { if (m < op) m = op + 1; if (m < arg) m = arg + 1; } else if (op == SPAWN_cwd) j = arg; } if (j >= 0) { if ((i = open(".", O_RDONLY)) < 0) goto bad; if ((i = save(i, &ic, m)) < 0) goto bad; if (spawnvex_add(xev, SPAWN_cwd, i, 0, 0) < 0 || restore(xev, i, -1, 0) < 0) { close(i); goto bad; } if (fchdir(j) < 0) goto bad; if ((i = save(j, &jc, m)) < 0) goto bad; if (restore(xev, i, j, jc) < 0) { close(i); goto bad; } } } else { flags = 0; xev = NULL; } #if _lib_spawn_mode if (vex) for (i = 0; i < vex->cur;) { op = vex->op[i++].number; arg = vex->op[i++].number; if (op & 1) i += 2; switch (op /= 2) { case SPAWN_frame: vex->frame = (unsigned int)arg; break; case SPAWN_pgrp: vex->pgrp = (pid_t)arg; break; default: if (op >= 0) { if (arg < 0) { if ((i = save(op, &ic, m)) < 0) { if (i < -1) goto bad; } else if (restore(xev, i, op, ic) < 0) { close(i); goto bad; } else close(op); } else if (arg == op) { if (spawnvex_add(xev, SPAWN_cloexec, arg, 0, 0) < 0) goto bad; if (fcntl(arg, F_SETFD, 0) < 0) goto bad; } else if ((j = save(arg, &jc, m)) < -1) goto bad; else { close(arg); if (fcntl(op, F_DUPFD, arg) >= 0) { if ((i = save(op, &ic, m)) >= 0) { if (restore(xev, i, op, ic) >= 0) { close(op); if (j < 0 || restore(xev, j, arg, jc) >= 0) continue; } close(i); } } if (j >= 0) { fcntl(j, F_DUPFD, arg); close(j); } goto bad; } } break; } } pid = spawnve(vex && vex->pgrp >= 0 ? P_DETACH : P_NOWAIT, path, argv, envv); #else inherit.flags = 0; map = 0; if (vex) { if (m) { map = calloc(1, m * sizeof(int)); if (!map) goto bad; for (i = 0; i < m; i++) map[i] = i; } for (i = 0; i < vex->cur;) { op = vex->op[i++].number; a = i; arg = vex->op[i++].number; if (op & 1) i += 2; switch (op /= 2) { case SPAWN_noop: break; case SPAWN_noexec: break; case SPAWN_frame: vex->frame = (unsigned int)arg; break; case SPAWN_pgrp: inherit.flags |= SPAWN_SETGROUP; inherit.pgroup = arg ? arg : SPAWN_NEWPGROUP; break; case SPAWN_sigdef: inherit.flags |= SPAWN_SETSIGDEF; sigemptyset(&inherit.sigdefault); for (j = 1; j < 8 * sizeof(vex->op[a].number); j++) if (vex->op[a].number & (1 << j)) sigaddset(&inherit.sigdefault, j); break; case SPAWN_sigmask: inherit.flags |= SPAWN_SETSIGMASK; sigemptyset(&inherit.sigmask); for (j = 1; j < 8 * sizeof(vex->op[a].number); j++) if (vex->op[a].number & (1 << j)) sigaddset(&inherit.sigmask, j); break; default: if (op < 0) { errno = EINVAL; goto bad; } else if (arg < 0) map[op] = SPAWN_FDCLOSED; else map[op] = arg; break; } } } pid = spawn(path, m, map, &inherit, (const char **)argv, (const char **)envv); #endif if (pid >= 0 && vex) VEXINIT(vex); bad: if (xev) { spawnvex_apply(xev, 0, SPAWN_FLUSH | SPAWN_NOCALL); spawnvex_close(xev); } #if !_lib_spawn_mode if (map) free(map); #endif return pid; #else #if _lib_spawnve if (!vex || !vex->cur && !vex->flags) return spawnve(path, argv, envv); #endif if (vex && ((vex->set & (0 #if !_lib_posix_spawnattr_setfchdir | VEXFLAG(SPAWN_cwd) #endif #if !_lib_posix_spawnattr_setsid | VEXFLAG(SPAWN_sid) #endif #if !_lib_posix_spawnattr_setumask | VEXFLAG(SPAWN_umask) #endif )) #if !_lib_posix_spawn || !(vex->flags & SPAWN_EXEC) #endif )) { int n; int m; Spawnvex_noexec_t nx; int msg[2]; if (!envv) envv = environ; n = errno; if (pipe(msg) < 0) { msg[0] = msg[1] = -1; } else { (void)fcntl(msg[0], F_SETFD, FD_CLOEXEC); (void)fcntl(msg[1], F_SETFD, FD_CLOEXEC); } if (!(flags & SPAWN_FOREGROUND)) sigcritical(SIG_REG_EXEC | SIG_REG_PROC); pid = fork(); if (pid == -1) { n = errno; } else if (!pid) { if (!(flags & SPAWN_FOREGROUND)) sigcritical(SIG_REG_POP); if (vex && (n = spawnvex_apply(vex, 0, SPAWN_FRAME | SPAWN_NOCALL))) { errno = n; } else { if (vex && vex->debug >= 0) { error(ERROR_OUTPUT, vex->debug, "spawnvex exe %4d %8d %p %4d \"%s\"", __LINE__, getpid(), vex, vex->cur, path); } execve(path, argv, envv); if (vex && vex->debug >= 0) { error(ERROR_OUTPUT, vex->debug, "spawnvex exe %4d %8d %p %4d \"%s\" FAILED", __LINE__, getpid(), vex, vex->cur, path); } if (vex && (i = vex->noexec) >= 0) { nx.vex = vex; nx.handle = vex->op[i + 3].handle; nx.path = path; nx.argv = argv; nx.envv = envv; #if _use_spawn_exec /* * setting SPAWN_EXEC here means that it is more efficient to * exec(interpreter) on script than to fork() initialize and * read script -- highly subjective, based on some ksh * implementaions, and probably won't be set unless its a * noticable win */ nx.flags |= SPAWN_EXEC; #endif nx.msgfd = msg[1]; errno = (*vex->op[i + 2].callback)(&nx, SPAWN_noexec, errno); } } if (msg[1] != -1) { m = errno; write(msg[1], &m, sizeof(m)); } _exit(errno == ENOENT ? EXIT_NOTFOUND : EXIT_NOEXEC); } if (msg[0] != -1) { close(msg[1]); if (pid != -1) { m = 0; while (read(msg[0], &m, sizeof(m)) == -1) { if (errno != EINTR) { m = errno; break; } } if (m) { while (waitpid(pid, &n, 0) && errno == EINTR) { ; } pid = -1; n = m; } } close(msg[0]); } if (!(flags & SPAWN_FOREGROUND)) sigcritical(SIG_REG_POP); if (pid != -1 && vex) VEXINIT(vex); errno = n; return pid; } if (vex) { err = posix_spawnattr_init(&ax); if (err) goto nope; err = posix_spawn_file_actions_init(&fx); if (err) { posix_spawnattr_destroy(&ax); goto nope; } for (i = 0; i < vex->cur;) { op = vex->op[i++].number; arg = vex->op[i++].number; if (op & 1) i += 2; switch (op /= 2) { case SPAWN_noop: break; case SPAWN_noexec: break; case SPAWN_frame: break; #if _lib_posix_spawnattr_setfchdir case SPAWN_cwd: err = posix_spawnattr_setfchdir(&ax, arg); if (err) goto bad; break; #endif case SPAWN_pgrp: err = posix_spawnattr_setpgroup(&ax, arg); if (err) goto bad; err = posix_spawnattr_setflags(&ax, POSIX_SPAWN_SETPGROUP); if (err) goto bad; break; case SPAWN_resetids: err = posix_spawnattr_setflags(&ax, POSIX_SPAWN_RESETIDS); if (err) goto bad; break; #if _lib_posix_spawnattr_setsid case SPAWN_sid: err = posix_spawnattr_setsid(&ax, arg); if (err) goto bad; break; #endif case SPAWN_sigdef: break; case SPAWN_sigmask: break; #if _lib_posix_spawnattr_setumask case SPAWN_umask: if (err = posix_spawnattr_setumask(&ax, arg)) goto bad; break; #endif default: if (op < 0) { err = EINVAL; goto bad; } else if (arg < 0) { err = posix_spawn_file_actions_addclose(&fx, op); if (err) goto bad; } else if (arg == op) { #ifdef F_DUPFD_CLOEXEC if ((fd = fcntl(op, F_DUPFD_CLOEXEC, 0)) < 0) #else if ((fd = fcntl(op, F_DUPFD, 0)) < 0 || fcntl(fd, F_SETFD, FD_CLOEXEC) < 0 && (close(fd), 1)) #endif { err = errno; goto bad; } if (!xev && !(xev = spawnvex_open(0))) goto bad; spawnvex_add(xev, fd, -1, 0, 0); err = posix_spawn_file_actions_adddup2(&fx, fd, op); if (err) goto bad; } else { err = posix_spawn_file_actions_adddup2(&fx, op, arg); if (err) goto bad; } break; } } // Ensure stdin, stdout, stderr are open in the child process. // See https://github.com/att/ast/issues/1117. for (int fd = 0; fd < 3; ++fd) { errno = 0; if (fcntl(fd, F_GETFD, NULL) == -1 || errno == EBADF) { err = posix_spawn_file_actions_addopen(&fx, fd, "/dev/null", O_RDWR, 0); if (err) goto bad; } } err = posix_spawn(&pid, path, &fx, &ax, argv, envv ? envv : environ); if (err) goto bad; posix_spawnattr_destroy(&ax); posix_spawn_file_actions_destroy(&fx); if (xev) { spawnvex_apply(xev, 0, SPAWN_NOCALL); spawnvex_close(xev); } if (vex->flags & SPAWN_CLEANUP) spawnvex_apply(vex, 0, SPAWN_FRAME | SPAWN_CLEANUP); VEXINIT(vex); } else { err = posix_spawn(&pid, path, NULL, NULL, argv, envv ? envv : environ); if (err) goto nope; } if (vex && vex->debug >= 0) { error(ERROR_OUTPUT, vex->debug, "spawnvex exe %4d %8d %p %4d \"%s\" %8d posix_spawn", __LINE__, getpid(), vex, vex->cur, path, pid); } return pid; bad: posix_spawnattr_destroy(&ax); posix_spawn_file_actions_destroy(&fx); if (xev) { spawnvex_apply(xev, 0, SPAWN_NOCALL); spawnvex_close(xev); } nope: errno = err; if (vex && vex->debug >= 0) { error(ERROR_OUTPUT, vex->debug, "spawnvex exe %4d %8d %p %4d \"%s\" %8d posix_spawn FAILED", __LINE__, getpid(), vex, vex->cur, path, -1); } return -1; #endif }
static int internal_run_hook(const char *const hook_script, const char *const action, const char *const argument, char **envp) { #ifdef CALL_VIA_SYSTEM int retcode; /* run hook using system(3) */ internal_putenv("ACTION", action); internal_putenv("ARGUMENT", argument); retcode = system(hook_script); if (retcode != 0) { fprintf(stderr, "Hook script returned error code %d (0x%x)\n", retcode, retcode); return 1; } return 0; #else /* spawnve() based implementation of internal_run_hook() * * Most of the code here creates and destructs the * char *child_argv[] and char *child_envp[] to be passed to * spawnve() and thus execve(). * * Error handling is simple: * * If malloc() or calloc() fail, abort the whole program. */ /* A note on program memory layout: * * child_argv and child_envp MUST be in writable memory, so we * malloc() them. */ char *my_hook_script = strdup(hook_script); unsigned int i; /* run hook using execve(2) */ char **child_argv = calloc(2, sizeof(child_argv[0])); /* envars not to copy */ const char *const varlist[] = { "ACTION", "ARGUMENT", NULL }; /* environment variables for child process, and index going through them */ char **child_envp; unsigned int envi = 0; int retcode; /* count number of environment variables currently set */ unsigned int envar_count; for (envar_count=0; envp[envar_count] != NULL; envar_count++) { /* printf("%3d: \"%s\"\n", envar_count, envp[envar_count]); */ } ASSERT(my_hook_script != NULL); child_argv[0] = my_hook_script; /* Initialize environment. Start with newly defined vars, then copy * all the existing ones. calloc() does the initialization with NULL. * Total amount of char* is * number of existing envars (envar_count) * + max number of new envars (2) * + NULL list terminator (1) */ child_envp = calloc(envar_count+((sizeof(varlist)/sizeof(varlist[0]))-1)+1, sizeof(child_envp[0])); ASSERT(child_envp != NULL); /* own envars */ if (NULL != action) { char *envar = alloc_envar("ACTION", action); ASSERT(envar != NULL); child_envp[envi++] = envar; } if (NULL != argument) { char *envar = alloc_envar("ARGUMENT", argument); ASSERT(envar != NULL); child_envp[envi++] = envar; } /* copy envars except for those in varlist */ for (i=0; i<envar_count; i++) { int skip = 0; unsigned int n; for (n=0; varlist[n] != NULL; n++) { const char *varname = varlist[n]; const char *start = strstr(envp[i], varname); if ((envp[i] == start) && (envp[i][strlen(varname)] == '=')) { skip = 1; break; } } if (!skip) { child_envp[envi++] = strdup(envp[i]); } } /* Actually run the hook script */ retcode = spawnve(hook_script, child_argv, child_envp); /* Free all memory */ for (i=0; child_envp[i] != NULL; i++) { free(child_envp[i]); } free(child_envp); for (i=0; child_argv[i] != NULL; i++) { free(child_argv[i]); } free(child_argv); /* And finally return to caller */ if (retcode != 0) { fprintf(stderr, "Hook script returned error code %d (0x%x)\n", retcode, retcode); return 1; } return 0; #endif }
int spawnv(int mode, const char *path, char *const argv[]) { return spawnve(mode, path, (char * const *)argv, environ); }
int main(const int argc, const char *argv[], const char **envp) { unsigned int i; FILE *out = stdout; int retcode; char *hook_env = getenv("GPHOTO_HOOK"); char *filename = (hook_env!=NULL)?hook_env:"./test-hook.sh"; /* We want this to be writable, so we explicitly define it as char[] */ char params[7] = "params"; char * const child_argv[] = { params, NULL, }; /* envars not to copy */ static const char * const varlist[] = { "ACTION", "ARGUMENT", NULL }; unsigned int envi = 0; char **child_envp; /* count number of environment variables currently set */ unsigned int envar_count; for (envar_count=0; envp[envar_count] != NULL; envar_count++) { /* printf("%3d: \"%s\"\n", envar_count, envp[envar_count]); */ } fprintf(out, "Before spawn...\n"); fflush(out); /* Initialize environment. Start with newly defined vars, then copy * all the existing ones. * Total amount of char* is * number of existing envars (envar_count) * + max number of new envars (2) * + NULL list terminator (1) */ child_envp = calloc(envar_count+2+1,sizeof(child_envp[0])); ASSERT(child_envp != NULL); /* own envars */ child_envp[envi++] = alloc_envar("ARGUMENT", "/etc/shadow ;-P"); child_envp[envi++] = alloc_envar("ACTION", "download"); /* copy envars except for those in varlist */ for (i=0; i<envar_count; i++) { int skip = 0; unsigned int n; for (n=0; varlist[n] != NULL; n++) { const char *varname = varlist[n]; const char *start = strstr(envp[i], varname); if ((envp[i] == start) && (envp[i][strlen(varname)] == '=')) { skip = 1; break; } } if (!skip) { child_envp[envi] = strdup(envp[i]); ASSERT(child_envp[envi] != NULL); ++envi; } } /* Run the child program */ retcode = spawnve(filename, child_argv, child_envp); fprintf(out, "After spawn, retcode=%d\n", retcode); fflush(out); /* Free memory */ for (i=0; child_envp[i] != NULL; i++) { free(child_envp[i]); } free(child_envp); return retcode; }
/* replacement for execve() of kLIBC */ int execve(const char *name, char * const *argv, char * const *envp) { const char *exec_name; FILE *fp; char sign[2]; char *rsp_argv[3]; char *rsp_name_arg; int pid; int status; int fd; int rc; /* * #! /bin/sh : append .exe * extproc sh : search sh.exe in PATH */ exec_name = search_path(name, path, X_OK, NULL); if (!exec_name) { errno = ENOENT; return (-1); } /*- * kLIBC execve() has problems when executing scripts. * 1. it fails to execute a script if a directory whose name * is same as an interpreter exists in a current directory. * 2. it fails to execute a script not starting with sharpbang. * 3. it fails to execute a batch file if COMSPEC is set to a shell * incompatible with cmd.exe, such as /bin/sh. * And ksh process scripts more well, so let ksh process scripts. */ errno = 0; if (!(fp = fopen(exec_name, "rb"))) errno = ENOEXEC; if (!errno && fread(sign, 1, sizeof(sign), fp) != sizeof(sign)) errno = ENOEXEC; if (fp && fclose(fp)) errno = ENOEXEC; if (!errno && !((sign[0] == 'M' && sign[1] == 'Z') || (sign[0] == 'N' && sign[1] == 'E') || (sign[0] == 'L' && sign[1] == 'X'))) errno = ENOEXEC; if (errno == ENOEXEC) return (-1); rsp_name_arg = make_response_file(argv); if (rsp_name_arg) { rsp_argv[0] = argv[0]; rsp_argv[1] = rsp_name_arg; rsp_argv[2] = NULL; argv = rsp_argv; } pid = spawnve(P_NOWAIT, exec_name, argv, envp); afree(rsp_name_arg, ATEMP); if (pid == -1) { cleanup_temps(); return (-1); } /* close all opened handles */ for (fd = 0; fd < NUFILE; fd++) { if (fcntl(fd, F_GETFD) == -1) continue; close(fd); } while ((rc = waitpid(pid, &status, 0)) < 0 && errno == EINTR) /* nothing */; cleanup_temps(); /* Is this possible? And is this right? */ if (rc == -1) return (-1); if (WIFSIGNALED(status)) _exit(ksh_sigmask(WTERMSIG(status))); _exit(WEXITSTATUS(status)); }
int MYspawnve(int wait, char *script, char const **argv, char **envp) { RTN_TYPE rtn = 0; int pid = 0; #if defined(INTEL_NT) || defined(INTEL_9X) static char *shell = NULL; if (NULL == shell) { //char const *local = findExec("sh.exe"); char const *local = Tenv::appGet("SHELL"); shell = new char [strlen(local) +1]; strcpy(shell, local); } char *(MYargv[1024]); char **p; char **q; MYargv[0] = shell; MYargv[1] = script; for (p = argv +1, q = MYargv +2; (NULL != *p); p++, q++) *q = *p; *q = NULL; if (MY_WAIT == wait) rtn = spawnve(_P_WAIT, shell, (const char* const*)MYargv, (const char* const*)envp); else pid = spawnve(_P_NOWAIT, shell, (const char* const*)MYargv, (const char* const*)envp); #else #if defined(CYGWIN) /* 006 */ static char *shell = NULL; if (NULL == shell) { char const *local = Tenv::appGet("SHELL"); shell = new char [strlen(local) +1]; strcpy(shell, local); } char *(MYargv[1024]); char **p; char **q; MYargv[0] = shell; MYargv[1] = script; for (p = argv +1, q = MYargv +2; (NULL != *p); p++, q++) *q = *p; *q = NULL; argv = MYargv; script = shell; #endif if (0 == (pid = fork())) { // Child execve(script, (char**)argv, envp); printE("Executeable [%s] not found or not executable\n", script); exit(-1); } else if (-1 < pid) { // Parent if (MY_WAIT == wait) { waitpid(pid, &rtn, 0); } } else { // Fork fail printT("Fork failed [-1]\n"); return (-1); } #endif if (MY_WAIT == wait) { return(RTN_VALUE(rtn)); } else { return(pid); } }
pid_t spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) { return spawnve(pgid ? P_DETACH : P_NOWAIT, path, argv, envv ? envv : environ); }
static unsigned __stdcall babysitter (void *parameter) { DBusBabysitter *sitter = (DBusBabysitter *) parameter; int fd; PING(); _dbus_babysitter_ref (sitter); if (sitter->child_setup) { PING(); (*sitter->child_setup) (sitter->user_data); } _dbus_verbose ("babysitter: spawning %s\n", sitter->executable); PING(); if (sitter->envp != NULL) sitter->child_handle = (HANDLE) spawnve (P_NOWAIT, sitter->executable, (const char * const *) sitter->argv, (const char * const *) sitter->envp); else sitter->child_handle = (HANDLE) spawnv (P_NOWAIT, sitter->executable, (const char * const *) sitter->argv); PING(); if (sitter->child_handle == (HANDLE) -1) { sitter->child_handle = NULL; sitter->have_spawn_errno = TRUE; sitter->spawn_errno = errno; } PING(); SetEvent (sitter->start_sync_event); if (sitter->child_handle != NULL) { int ret; DWORD status; PING(); WaitForSingleObject (sitter->child_handle, INFINITE); PING(); ret = GetExitCodeProcess (sitter->child_handle, &status); sitter->child_status = status; sitter->have_child_status = TRUE; CloseHandle (sitter->child_handle); sitter->child_handle = NULL; } #ifdef DBUS_BUILD_TESTS SetEvent (sitter->end_sync_event); #endif PING(); send (sitter->socket_to_main, " ", 1, 0); _dbus_babysitter_unref (sitter); return 0; }
// // Download the next version of the game. If already downloaded, kick // off the .exe to do the install. // void gh_main_installer (void) { #if defined WIN32 || defined __CYGWIN__ // // e.g. save as goblinhack-1.15-windows.exe // string save_file_as = "goblinhack-" + tostring(GH_MAJOR_VERSION_NUMBER) + "." + tostring(GH_MINOR_VERSION_NUMBER + 1) + "-windows.exe"; // // e.g. download as // // http://prdownloads.sourceforge.net/sourceforge/goblinhack/goblinhack-1.15-windows.exe // string download_file_as = "http://prdownloads.sourceforge.net/" "sourceforge/goblinhack/" "goblinhack-" + tostring(GH_MAJOR_VERSION_NUMBER) + "." + tostring(GH_MINOR_VERSION_NUMBER + 1) + "-windows.exe"; // // curl -g -L // --output goblinhack-1.15-windows.exe // --url // http://prdownloads.sourceforge.net/sourceforge/goblinhack/goblinhack-1.15-windows.exe // const char *curl_args[] = { "-g", "-L", "--output", save_file_as.c_str(), "--url", download_file_as.c_str(), 0, }; // // If the next version doesn't exist, download it now. // if (!gh_global::file_exists(save_file_as)) { // // Spawn curl as a child process to do the download in the background. // // If this fails then we're in trouble as we'll have a partial .exe. // Not worked out how to avoid this. Help! // spawnve(P_NOWAIT, "curl", curl_args, NULL); } else { // // Lets check the file looks to be of a sane size before calling // the installer. If it looks dodgy, < 10 Mb then just delete it // so we can download the file again. // if (gh_global::file_size(save_file_as) < 10 * 1000 * 1000) { // // Is too annoying to keep retrying all the time. // if ((rand() % 100) < 5) { gh_global::file_unlink(save_file_as); } return; } // // Replace the current process with the .exe to download. // int ret = MessageBox(NULL, "I've downloaded the next version of Ghack!" " Install it now?", download_file_as.c_str(), MB_YESNO); if (ret == IDYES) { const char *no_args[] = { 0, }; execve(save_file_as.c_str(), no_args, NULL); gh_global::file_unlink(save_file_as); return; } // // Ok, delete it instead? I'll just download it again anyway! 8) // ret = MessageBox(NULL, "Should I delete the download file?", download_file_as.c_str(), MB_YESNO); if (ret == IDYES) { gh_global::file_unlink(save_file_as); } } #endif #if defined __linux__ pid_t childpid = fork(); if (childpid >= 0) { // // Fork ok // if (childpid == 0) { // // Child // } else { // // Parent // return; } } else { perror("fork"); exit(0); } // // e.g. save as goblinhack-1.15-linux-installer.bin // string save_file_as = "goblinhack-" + tostring(GH_MAJOR_VERSION_NUMBER) + "." + tostring(GH_MINOR_VERSION_NUMBER + 1) + #ifdef __x86_64__ "-linux-x64-installer.bin"; #else "-linux-installer.bin"; #endif // // e.g. download as // // http://prdownloads.sourceforge.net/sourceforge/goblinhack/goblinhack-1.15-linux-installer.bin // string download_file_as = "http://prdownloads.sourceforge.net/" "sourceforge/goblinhack/" "goblinhack-" + tostring(GH_MAJOR_VERSION_NUMBER) + "." + tostring(GH_MINOR_VERSION_NUMBER + 1) + #ifdef __x86_64__ "-linux-x64-installer.bin"; #else "-linux-installer.bin"; #endif // // curl -g -L // --output goblinhack-1.15-linux-installer.bin // --url // http://prdownloads.sourceforge.net/sourceforge/goblinhack/goblinhack-1.15-linux-installer.bin // char *curl_args[] = { (char*)"-g", (char*)"-L", (char*)"--output", (char*)save_file_as.c_str(), (char*)"--url", (char*)download_file_as.c_str(), 0, }; // // If the next version doesn't exist, download it now. // if (!gh_global::file_exists(save_file_as)) { // // Spawn curl as a child process to do the download in the background. // // If this fails then we're in trouble as we'll have a partial installer.bin. // Not worked out how to avoid this. Help! // execve("/usr/bin/curl", curl_args, NULL); perror("execve"); /* execve() only returns on error */ } else { // // Lets check the file looks to be of a sane size before calling // the installer. If it looks dodgy, < 10 Mb then just delete it // so we can download the file again. // if (gh_global::file_size(save_file_as) < 10 * 1000 * 1000) { // // Is too annoying to keep retrying all the time. // if ((rand() % 100) < 5) { gh_global::file_unlink(save_file_as); } exit(0); } if (system(("/bin/chmod +x " + save_file_as).c_str()) == -1) { perror("change permissions failed"); } if (system(("./" + save_file_as).c_str()) == -1) { perror("execute installer failed"); } gh_global::file_unlink(save_file_as); } exit(0); #endif }
int spawnl(int mode, const char *path, const char *arg0, ...) { char **argv; CVT_L2V(arg0, argv); return spawnve(mode, path, argv, 0); }
int execle(const char *path, const char *argv0, ... /*, const char **envp */) { scan_ptr(); return spawnve(P_OVERLAY, path, (char *const *)&argv0, (char *const *)ptr); }