X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fexecute.c;h=a6911d97b36e4cc4b4296e4cf8b19f63046fcc26;hb=5709a7204dfd9a4fedf2cdbaa341bc6c540dadf3;hp=57664feacd0d482bba2b60a6ca410bd23625e189;hpb=ac5d57a6683bc6f146b28d2c84e1fdbf80877e06;p=gnulib.git diff --git a/lib/execute.c b/lib/execute.c index 57664feac..a6911d97b 100644 --- a/lib/execute.c +++ b/lib/execute.c @@ -1,11 +1,11 @@ /* Creation of autonomous subprocesses. - Copyright (C) 2001-2004, 2006-2007 Free Software Foundation, Inc. + Copyright (C) 2001-2004, 2006-2009 Free Software Foundation, Inc. Written by Bruno Haible , 2001. - This program is free software; you can redistribute it and/or modify + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -13,8 +13,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ #include @@ -30,7 +29,6 @@ #include #include "error.h" -#include "exit.h" #include "fatal-signal.h" #include "wait-process.h" #include "gettext.h" @@ -46,30 +44,10 @@ #else /* Unix API. */ -# if HAVE_POSIX_SPAWN -# include -# else -# if HAVE_VFORK_H -# include -# endif -# endif +# include #endif -#if ! HAVE_ENVIRON_DECL -extern char **environ; -#endif - -#ifndef STDIN_FILENO -# define STDIN_FILENO 0 -#endif -#ifndef STDOUT_FILENO -# define STDOUT_FILENO 1 -#endif -#ifndef STDERR_FILENO -# define STDERR_FILENO 2 -#endif - /* The results of open() in this file are not used with fchdir, therefore save some unnecessary work in fchdir.c. */ #undef open @@ -123,7 +101,8 @@ execute (const char *progname, const char *prog_path, char **prog_argv, bool ignore_sigpipe, bool null_stdin, bool null_stdout, bool null_stderr, - bool slave_process, bool exit_on_error) + bool slave_process, bool exit_on_error, + int *termsigp) { #if defined _MSC_VER || defined __MINGW32__ @@ -135,6 +114,7 @@ execute (const char *progname, int nullinfd; int nulloutfd; + /* FIXME: Need to free memory allocated by prepare_spawn. */ prog_argv = prepare_spawn (prog_argv); /* Save standard file handles of parent process. */ @@ -165,7 +145,27 @@ execute (const char *progname, && ((null_stdout && nulloutfd == STDOUT_FILENO) || (null_stderr && nulloutfd == STDERR_FILENO) || close (nulloutfd) >= 0)))) - exitcode = spawnvp (P_WAIT, prog_path, prog_argv); + /* Use spawnvpe and pass the environment explicitly. This is needed if + the program has modified the environment using putenv() or [un]setenv(). + On Windows, programs have two environments, one in the "environment + block" of the process and managed through SetEnvironmentVariable(), and + one inside the process, in the location retrieved by the 'environ' + macro. When using spawnvp() without 'e', the child process inherits a + copy of the environment block - ignoring the effects of putenv() and + [un]setenv(). */ + { + exitcode = spawnvpe (P_WAIT, prog_path, (const char **) prog_argv, + (const char **) environ); + if (exitcode < 0 && errno == ENOEXEC) + { + /* prog is not an native executable. Try to execute it as a + shell script. Note that prepare_spawn() has already prepended + a hidden element "sh.exe" to prog_argv. */ + --prog_argv; + exitcode = spawnvpe (P_WAIT, prog_argv[0], (const char **) prog_argv, + (const char **) environ); + } + } if (nulloutfd >= 0) close (nulloutfd); if (nullinfd >= 0) @@ -179,6 +179,9 @@ execute (const char *progname, if (null_stdin) dup2 (orig_stdin, STDIN_FILENO), close (orig_stdin); + if (termsigp != NULL) + *termsigp = 0; + if (exitcode == -1) { if (exit_on_error || !null_stderr) @@ -197,7 +200,6 @@ execute (const char *progname, subprocess to exit with return code 127. It is implementation dependent which error is reported which way. We treat both cases as equivalent. */ -#if HAVE_POSIX_SPAWN sigset_t blocked_signals; posix_spawn_file_actions_t actions; bool actions_allocated; @@ -205,11 +207,7 @@ execute (const char *progname, bool attrs_allocated; int err; pid_t child; -#else - int child; -#endif -#if HAVE_POSIX_SPAWN if (slave_process) { sigprocmask (SIG_SETMASK, NULL, &blocked_signals); @@ -257,6 +255,8 @@ execute (const char *progname, posix_spawnattr_destroy (&attrs); if (slave_process) unblock_fatal_signals (); + if (termsigp != NULL) + *termsigp = 0; if (exit_on_error || !null_stderr) error (exit_on_error ? EXIT_FAILURE : 0, err, _("%s subprocess failed"), progname); @@ -265,46 +265,6 @@ execute (const char *progname, posix_spawn_file_actions_destroy (&actions); if (attrs_allocated) posix_spawnattr_destroy (&attrs); -#else - if (slave_process) - block_fatal_signals (); - /* Use vfork() instead of fork() for efficiency. */ - if ((child = vfork ()) == 0) - { - /* Child process code. */ - int nullinfd; - int nulloutfd; - - if ((!null_stdin - || ((nullinfd = open ("/dev/null", O_RDONLY, 0)) >= 0 - && (nullinfd == STDIN_FILENO - || (dup2 (nullinfd, STDIN_FILENO) >= 0 - && close (nullinfd) >= 0)))) - && (!(null_stdout || null_stderr) - || ((nulloutfd = open ("/dev/null", O_RDWR, 0)) >= 0 - && (!null_stdout - || nulloutfd == STDOUT_FILENO - || dup2 (nulloutfd, STDOUT_FILENO) >= 0) - && (!null_stderr - || nulloutfd == STDERR_FILENO - || dup2 (nulloutfd, STDERR_FILENO) >= 0) - && ((null_stdout && nulloutfd == STDOUT_FILENO) - || (null_stderr && nulloutfd == STDERR_FILENO) - || close (nulloutfd) >= 0))) - && (!slave_process || (unblock_fatal_signals (), true))) - execvp (prog_path, prog_argv); - _exit (127); - } - if (child == -1) - { - if (slave_process) - unblock_fatal_signals (); - if (exit_on_error || !null_stderr) - error (exit_on_error ? EXIT_FAILURE : 0, errno, - _("%s subprocess failed"), progname); - return 127; - } -#endif if (slave_process) { register_slave_subprocess (child); @@ -312,7 +272,7 @@ execute (const char *progname, } return wait_subprocess (child, progname, ignore_sigpipe, null_stderr, - slave_process, exit_on_error); + slave_process, exit_on_error, termsigp); #endif }