diff options
Diffstat (limited to 'src/callproc.c')
-rw-r--r-- | src/callproc.c | 102 |
1 files changed, 33 insertions, 69 deletions
diff --git a/src/callproc.c b/src/callproc.c index 76b5caa4465..f0fe5c66611 100644 --- a/src/callproc.c +++ b/src/callproc.c @@ -22,6 +22,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <config.h> #include <errno.h> #include <stdio.h> +#include <stdlib.h> #include <sys/types.h> #include <unistd.h> @@ -31,7 +32,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "lisp.h" #ifdef WINDOWSNT -#define NOMINMAX #include <sys/socket.h> /* for fcntl */ #include <windows.h> #include "w32.h" @@ -292,7 +292,6 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, Lisp_Object output_file = Qnil; #ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */ char *tempfile = NULL; - int pid; #else sigset_t oldset; pid_t pid; @@ -537,11 +536,9 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, } #ifdef MSDOS /* MW, July 1993 */ - /* Note that on MSDOS `child_setup' actually returns the child process - exit status, not its PID, so assign it to status below. */ - pid = child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir); + status = child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir); - if (pid < 0) + if (status < 0) { child_errno = errno; unbind_to (count, Qnil); @@ -550,7 +547,6 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, code_convert_string_norecord (build_string (strerror (child_errno)), Vlocale_coding_system, 0); } - status = pid; for (i = 0; i < CALLPROC_FDS; i++) if (0 <= callproc_fd[i]) @@ -565,8 +561,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, { /* Since CRLF is converted to LF within `decode_coding', we can always open a file with binary mode. */ - callproc_fd[CALLPROC_PIPEREAD] = emacs_open (tempfile, - O_RDONLY | O_BINARY, 0); + callproc_fd[CALLPROC_PIPEREAD] = emacs_open (tempfile, O_RDONLY, 0); if (callproc_fd[CALLPROC_PIPEREAD] < 0) { int open_errno = errno; @@ -1085,10 +1080,6 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r return unbind_to (count, val); } -#ifndef WINDOWSNT -static int relocate_fd (int fd, int minfd); -#endif - static char ** add_env (char **env, char **new_env, char *string) { @@ -1167,9 +1158,13 @@ exec_failed (char const *name, int err) CURRENT_DIR is an elisp string giving the path of the current directory the subprocess should have. Since we can't really signal a decent error from within the child, this should be verified as an - executable directory by the parent. */ + executable directory by the parent. -int + On GNUish hosts, either exec or return an error number. + On MS-Windows, either return a pid or signal an error. + On MS-DOS, either return an exit status or signal an error. */ + +CHILD_SETUP_TYPE child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, Lisp_Object current_dir) { @@ -1307,7 +1302,7 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, #ifdef WINDOWSNT prepare_standard_handles (in, out, err, handles); - set_process_dir (SDATA (current_dir)); + set_process_dir (SSDATA (current_dir)); /* Spawn the child. (See w32proc.c:sys_spawnve). */ cpid = spawnve (_P_NOWAIT, new_argv[0], new_argv, env); reset_standard_handles (in, out, err, handles); @@ -1317,43 +1312,23 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, return cpid; #else /* not WINDOWSNT */ - /* Make sure that in, out, and err are not actually already in - descriptors zero, one, or two; this could happen if Emacs is - started with its standard in, out, or error closed, as might - happen under X. */ - { - int oin = in, oout = out; - - /* We have to avoid relocating the same descriptor twice! */ - - in = relocate_fd (in, 3); - if (out == oin) - out = in; - else - out = relocate_fd (out, 3); +#ifndef MSDOS - if (err == oin) - err = in; - else if (err == oout) - err = out; - else - err = relocate_fd (err, 3); - } + restore_nofile_limit (); -#ifndef MSDOS /* Redirect file descriptors and clear the close-on-exec flag on the redirected ones. IN, OUT, and ERR are close-on-exec so they need not be closed explicitly. */ - dup2 (in, 0); - dup2 (out, 1); - dup2 (err, 2); + dup2 (in, STDIN_FILENO); + dup2 (out, STDOUT_FILENO); + dup2 (err, STDERR_FILENO); setpgid (0, 0); tcsetpgrp (0, pid); - execve (new_argv[0], new_argv, env); - exec_failed (new_argv[0], errno); + int errnum = emacs_exec_file (new_argv[0], new_argv, env); + exec_failed (new_argv[0], errnum); #else /* MSDOS */ pid = run_msdos_command (new_argv, pwd_var + 4, in, out, err, env); @@ -1366,31 +1341,6 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, #endif /* not WINDOWSNT */ } -#ifndef WINDOWSNT -/* Move the file descriptor FD so that its number is not less than MINFD. - If the file descriptor is moved at all, the original is closed on MSDOS, - but not elsewhere as the caller will close it anyway. */ -static int -relocate_fd (int fd, int minfd) -{ - if (fd >= minfd) - return fd; - else - { - int new = fcntl (fd, F_DUPFD_CLOEXEC, minfd); - if (new == -1) - { - emacs_perror ("while setting up child"); - _exit (EXIT_CANCELED); - } -#ifdef MSDOS - emacs_close (fd); -#endif - return new; - } -} -#endif /* not WINDOWSNT */ - static bool getenv_internal_1 (const char *var, ptrdiff_t varlen, char **value, ptrdiff_t *valuelen, Lisp_Object env) @@ -1402,7 +1352,7 @@ getenv_internal_1 (const char *var, ptrdiff_t varlen, char **value, && SBYTES (entry) >= varlen #ifdef WINDOWSNT /* NT environment variables are case insensitive. */ - && ! strnicmp (SDATA (entry), var, varlen) + && ! strnicmp (SSDATA (entry), var, varlen) #else /* not WINDOWSNT */ && ! memcmp (SDATA (entry), var, varlen) #endif /* not WINDOWSNT */ @@ -1435,6 +1385,20 @@ getenv_internal (const char *var, ptrdiff_t varlen, char **value, Vprocess_environment)) return *value ? 1 : 0; + /* On Windows we make some modifications to Emacs' environment + without recording them in Vprocess_environment. */ +#ifdef WINDOWSNT + { + char* tmpval = getenv (var); + if (tmpval) + { + *value = tmpval; + *valuelen = strlen (tmpval); + return 1; + } + } +#endif + /* For DISPLAY try to get the values from the frame or the initial env. */ if (strcmp (var, "DISPLAY") == 0) { |