X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fspawni.c;h=048d9cfca0083746f368e8ad21a6a7046ceb2450;hb=32d1664e8e930d8fa6a29db4caac4d21623e42c8;hp=0d0d418cb7f4b0529e95510abb5272bd7dcaea7d;hpb=07c1f7b3d60a2d8433bddf1a85c33bc2ba4f59ff;p=gnulib.git diff --git a/lib/spawni.c b/lib/spawni.c index 0d0d418cb..048d9cfca 100644 --- a/lib/spawni.c +++ b/lib/spawni.c @@ -1,5 +1,5 @@ /* Guts of POSIX spawn interface. Generic POSIX.1 version. - Copyright (C) 2000-2005, 2006, 2008 Free Software Foundation, Inc. + Copyright (C) 2000-2006, 2008-2010 Free Software Foundation, Inc. This file is part of the GNU C Library. This program is free software: you can redistribute it and/or modify @@ -86,7 +86,23 @@ was wanted there is no way to signal an error using one of the available methods. The committee chose to signal an error by a normal program exit with the exit code 127. */ -#define SPAWN_ERROR 127 +#define SPAWN_ERROR 127 + + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + +/* Native Woe32 API. */ +int +__spawni (pid_t *pid, const char *file, + const posix_spawn_file_actions_t *file_actions, + const posix_spawnattr_t *attrp, char *const argv[], + char *const envp[], int use_path) +{ + /* Not yet implemented. */ + return ENOSYS; +} + +#else /* The file is accessible but it is not an executable file. Invoke @@ -107,8 +123,8 @@ script_execute (const char *file, char *const argv[], char *const envp[]) new_argv[1] = (char *) file; while (argc > 1) { - new_argv[argc] = argv[argc - 1]; - --argc; + new_argv[argc] = argv[argc - 1]; + --argc; } /* Execute the shell. */ @@ -121,9 +137,9 @@ script_execute (const char *file, char *const argv[], char *const envp[]) Before running the process perform the actions described in FILE-ACTIONS. */ int __spawni (pid_t *pid, const char *file, - const posix_spawn_file_actions_t *file_actions, - const posix_spawnattr_t *attrp, char *const argv[], - char *const envp[], int use_path) + const posix_spawn_file_actions_t *file_actions, + const posix_spawnattr_t *attrp, char *const argv[], + char *const envp[], int use_path) { pid_t new_pid; char *path, *p, *name; @@ -133,17 +149,21 @@ __spawni (pid_t *pid, const char *file, /* Do this once. */ short int flags = attrp == NULL ? 0 : attrp->_flags; + /* Avoid gcc warning + "variable 'flags' might be clobbered by 'longjmp' or 'vfork'" */ + (void) &flags; + /* Generate the new process. */ #if HAVE_VFORK if ((flags & POSIX_SPAWN_USEVFORK) != 0 /* If no major work is done, allow using vfork. Note that we - might perform the path searching. But this would be done by - a call to execvp(), too, and such a call must be OK according - to POSIX. */ + might perform the path searching. But this would be done by + a call to execvp(), too, and such a call must be OK according + to POSIX. */ || ((flags & (POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF - | POSIX_SPAWN_SETSCHEDPARAM | POSIX_SPAWN_SETSCHEDULER - | POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_RESETIDS)) == 0 - && file_actions == NULL)) + | POSIX_SPAWN_SETSCHEDPARAM | POSIX_SPAWN_SETSCHEDULER + | POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_RESETIDS)) == 0 + && file_actions == NULL)) new_pid = vfork (); else #endif @@ -152,11 +172,11 @@ __spawni (pid_t *pid, const char *file, if (new_pid != 0) { if (new_pid < 0) - return errno; + return errno; /* The call was successful. Store the PID if necessary. */ if (pid != NULL) - *pid = new_pid; + *pid = new_pid; return 0; } @@ -170,9 +190,9 @@ __spawni (pid_t *pid, const char *file, if ((flags & POSIX_SPAWN_SETSIGDEF) != 0) { /* We have to iterate over all signals. This could possibly be - done better but it requires system specific solutions since - the sigset_t data type can be very different on different - architectures. */ + done better but it requires system specific solutions since + the sigset_t data type can be very different on different + architectures. */ int sig; struct sigaction sa; @@ -180,9 +200,9 @@ __spawni (pid_t *pid, const char *file, sa.sa_handler = SIG_DFL; for (sig = 1; sig <= NSIG; ++sig) - if (sigismember (&attrp->_sd, sig) != 0 - && sigaction (sig, &sa, NULL) != 0) - _exit (SPAWN_ERROR); + if (sigismember (&attrp->_sd, sig) != 0 + && sigaction (sig, &sa, NULL) != 0) + _exit (SPAWN_ERROR); } @@ -192,14 +212,14 @@ __spawni (pid_t *pid, const char *file, == POSIX_SPAWN_SETSCHEDPARAM) { if (sched_setparam (0, &attrp->_sp) == -1) - _exit (SPAWN_ERROR); + _exit (SPAWN_ERROR); } else if ((flags & POSIX_SPAWN_SETSCHEDULER) != 0) { if (sched_setscheduler (0, attrp->_policy, - (flags & POSIX_SPAWN_SETSCHEDPARAM) != 0 - ? &attrp->_sp : NULL) == -1) - _exit (SPAWN_ERROR); + (flags & POSIX_SPAWN_SETSCHEDPARAM) != 0 + ? &attrp->_sp : NULL) == -1) + _exit (SPAWN_ERROR); } #endif @@ -211,7 +231,7 @@ __spawni (pid_t *pid, const char *file, /* Set the effective user and group IDs. */ if ((flags & POSIX_SPAWN_RESETIDS) != 0 && (local_seteuid (getuid ()) != 0 - || local_setegid (getgid ()) != 0)) + || local_setegid (getgid ()) != 0)) _exit (SPAWN_ERROR); /* Execute the file actions. */ @@ -220,52 +240,52 @@ __spawni (pid_t *pid, const char *file, int cnt; for (cnt = 0; cnt < file_actions->_used; ++cnt) - { - struct __spawn_action *action = &file_actions->_actions[cnt]; - - switch (action->tag) - { - case spawn_do_close: - if (close_not_cancel (action->action.close_action.fd) != 0) - /* Signal the error. */ - _exit (SPAWN_ERROR); - break; - - case spawn_do_open: - { - int new_fd = open_not_cancel (action->action.open_action.path, - action->action.open_action.oflag - | O_LARGEFILE, - action->action.open_action.mode); - - if (new_fd == -1) - /* The `open' call failed. */ - _exit (SPAWN_ERROR); - - /* Make sure the desired file descriptor is used. */ - if (new_fd != action->action.open_action.fd) - { - if (dup2 (new_fd, action->action.open_action.fd) - != action->action.open_action.fd) - /* The `dup2' call failed. */ - _exit (SPAWN_ERROR); - - if (close_not_cancel (new_fd) != 0) - /* The `close' call failed. */ - _exit (SPAWN_ERROR); - } - } - break; - - case spawn_do_dup2: - if (dup2 (action->action.dup2_action.fd, - action->action.dup2_action.newfd) - != action->action.dup2_action.newfd) - /* The `dup2' call failed. */ - _exit (SPAWN_ERROR); - break; - } - } + { + struct __spawn_action *action = &file_actions->_actions[cnt]; + + switch (action->tag) + { + case spawn_do_close: + if (close_not_cancel (action->action.close_action.fd) != 0) + /* Signal the error. */ + _exit (SPAWN_ERROR); + break; + + case spawn_do_open: + { + int new_fd = open_not_cancel (action->action.open_action.path, + action->action.open_action.oflag + | O_LARGEFILE, + action->action.open_action.mode); + + if (new_fd == -1) + /* The `open' call failed. */ + _exit (SPAWN_ERROR); + + /* Make sure the desired file descriptor is used. */ + if (new_fd != action->action.open_action.fd) + { + if (dup2 (new_fd, action->action.open_action.fd) + != action->action.open_action.fd) + /* The `dup2' call failed. */ + _exit (SPAWN_ERROR); + + if (close_not_cancel (new_fd) != 0) + /* The `close' call failed. */ + _exit (SPAWN_ERROR); + } + } + break; + + case spawn_do_dup2: + if (dup2 (action->action.dup2_action.fd, + action->action.dup2_action.newfd) + != action->action.dup2_action.newfd) + /* The `dup2' call failed. */ + _exit (SPAWN_ERROR); + break; + } + } } if (! use_path || strchr (file, '/') != NULL) @@ -274,7 +294,7 @@ __spawni (pid_t *pid, const char *file, execve (file, argv, envp); if (errno == ENOEXEC) - script_execute (file, argv, envp); + script_execute (file, argv, envp); /* Oh, oh. `execve' returns. This is bad. */ _exit (SPAWN_ERROR); @@ -286,8 +306,8 @@ __spawni (pid_t *pid, const char *file, { #if HAVE_CONFSTR /* There is no `PATH' in the environment. - The default search path is the current directory - followed by the path `confstr' returns for `_CS_PATH'. */ + The default search path is the current directory + followed by the path `confstr' returns for `_CS_PATH'. */ len = confstr (_CS_PATH, (char *) NULL, 0); path = (char *) alloca (1 + len); path[0] = ':'; @@ -315,38 +335,40 @@ __spawni (pid_t *pid, const char *file, p = strchrnul (path, ':'); if (p == path) - /* Two adjacent colons, or a colon at the beginning or the end - of `PATH' means to search the current directory. */ - startp = name + 1; + /* Two adjacent colons, or a colon at the beginning or the end + of `PATH' means to search the current directory. */ + startp = name + 1; else - startp = (char *) memcpy (name - (p - path), path, p - path); + startp = (char *) memcpy (name - (p - path), path, p - path); /* Try to execute this name. If it works, execv will not return. */ execve (startp, argv, envp); if (errno == ENOEXEC) - script_execute (startp, argv, envp); + script_execute (startp, argv, envp); switch (errno) - { - case EACCES: - case ENOENT: - case ESTALE: - case ENOTDIR: - /* Those errors indicate the file is missing or not executable - by us, in which case we want to just try the next path - directory. */ - break; - - default: - /* Some other error means we found an executable file, but - something went wrong executing it; return the error to our - caller. */ - _exit (SPAWN_ERROR); - } + { + case EACCES: + case ENOENT: + case ESTALE: + case ENOTDIR: + /* Those errors indicate the file is missing or not executable + by us, in which case we want to just try the next path + directory. */ + break; + + default: + /* Some other error means we found an executable file, but + something went wrong executing it; return the error to our + caller. */ + _exit (SPAWN_ERROR); + } } while (*p++ != '\0'); /* Return with an error. */ _exit (SPAWN_ERROR); } + +#endif