X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/41b7f8bc6c4511ab6fcf7f6b1f9e7fdcd8592821..d8ad4d3ff9dcea9c581d72e1e9ec292ea18673b1:/src/callproc.c diff --git a/src/callproc.c b/src/callproc.c index 804af1e9ab..6153bc1b6c 100644 --- a/src/callproc.c +++ b/src/callproc.c @@ -19,10 +19,8 @@ along with GNU Emacs. If not, see . */ #include -#include #include #include -#include #include #include @@ -53,6 +51,7 @@ along with GNU Emacs. If not, see . */ #include "process.h" #include "syssignal.h" #include "systty.h" +#include "syswait.h" #include "blockinput.h" #include "frame.h" #include "termhooks.h" @@ -61,104 +60,117 @@ along with GNU Emacs. If not, see . */ #include "msdos.h" #endif -#ifndef USE_CRT_DLL -extern char **environ; -#endif - -#ifdef HAVE_SETPGID -#if !defined (USG) -#undef setpgrp -#define setpgrp setpgid -#endif +#ifdef HAVE_NS +#include "nsterm.h" #endif /* Pattern used by call-process-region to make temp files. */ static Lisp_Object Vtemp_file_name_pattern; -/* True if we are about to fork off a synchronous process or if we - are waiting for it. */ -int synch_process_alive; +/* The next two variables are valid only while record-unwind-protect + is in place during call-process for a synchronous subprocess. At + other times, their contents are irrelevant. Doing this via static + C variables is more convenient than putting them into the arguments + of record-unwind-protect, as they need to be updated at randomish + times in the code, and Lisp cannot always store these values as + Emacs integers. It's safe to use static variables here, as the + code is never invoked reentrantly. */ -/* Nonzero => this is a string explaining death of synchronous subprocess. */ -const char *synch_process_death; +/* If nonzero, a process-ID that has not been reaped. */ +static pid_t synch_process_pid; -/* Nonzero => this is the signal number that terminated the subprocess. */ -int synch_process_termsig; +/* If nonnegative, a file descriptor that has not been closed. */ +static int synch_process_fd; + +/* Block SIGCHLD. */ -/* If synch_process_death is zero, - this is exit code of synchronous subprocess. */ -int synch_process_retcode; +static void +block_child_signal (void) +{ +#ifdef SIGCHLD + sigset_t blocked; + sigemptyset (&blocked); + sigaddset (&blocked, SIGCHLD); + pthread_sigmask (SIG_BLOCK, &blocked, 0); +#endif +} - -/* Clean up when exiting Fcall_process. - On MSDOS, delete the temporary file on any kind of termination. - On Unix, kill the process and any children on termination by signal. */ +/* Unblock SIGCHLD. */ -/* Nonzero if this is termination due to exit. */ -static int call_process_exited; +static void +unblock_child_signal (void) +{ +#ifdef SIGCHLD + pthread_sigmask (SIG_SETMASK, &empty_mask, 0); +#endif +} -static Lisp_Object Fgetenv_internal (Lisp_Object, Lisp_Object); +/* Clean up when exiting call_process_cleanup. */ static Lisp_Object -call_process_kill (Lisp_Object fdpid) +call_process_kill (Lisp_Object ignored) { - int fd; - pid_t pid; - CONS_TO_INTEGER (Fcar (fdpid), int, fd); - CONS_TO_INTEGER (Fcdr (fdpid), pid_t, pid); - emacs_close (fd); - EMACS_KILLPG (pid, SIGKILL); - synch_process_alive = 0; + if (0 <= synch_process_fd) + emacs_close (synch_process_fd); + + /* If PID is reapable, kill it and record it as a deleted process. + Do this in a critical section. Unless PID is wedged it will be + reaped on receipt of the first SIGCHLD after the critical section. */ + if (synch_process_pid) + { + block_child_signal (); + record_deleted_pid (synch_process_pid); + EMACS_KILLPG (synch_process_pid, SIGKILL); + unblock_child_signal (); + } + return Qnil; } +/* Clean up when exiting Fcall_process. + On MSDOS, delete the temporary file on any kind of termination. + On Unix, kill the process and any children on termination by signal. */ + static Lisp_Object call_process_cleanup (Lisp_Object arg) { - Lisp_Object fdpid = Fcdr (arg); - int fd; -#if defined (MSDOS) - Lisp_Object file; +#ifdef MSDOS + Lisp_Object buffer = Fcar (arg); + Lisp_Object file = Fcdr (arg); #else - pid_t pid; + Lisp_Object buffer = arg; #endif - Fset_buffer (Fcar (arg)); - CONS_TO_INTEGER (Fcar (fdpid), int, fd); - -#if defined (MSDOS) - /* for MSDOS fdpid is really (fd . tempfile) */ - file = Fcdr (fdpid); - /* FD is -1 and FILE is "" when we didn't actually create a - temporary file in call-process. */ - if (fd >= 0) - emacs_close (fd); - if (!(strcmp (SDATA (file), NULL_DEVICE) == 0 || SREF (file, 0) == '\0')) - unlink (SDATA (file)); -#else /* not MSDOS */ - CONS_TO_INTEGER (Fcdr (fdpid), pid_t, pid); - - if (call_process_exited) - { - emacs_close (fd); - return Qnil; - } + Fset_buffer (buffer); - if (EMACS_KILLPG (pid, SIGINT) == 0) +#ifndef MSDOS + /* If the process still exists, kill its process group. */ + if (synch_process_pid) { ptrdiff_t count = SPECPDL_INDEX (); - record_unwind_protect (call_process_kill, fdpid); + EMACS_KILLPG (synch_process_pid, SIGINT); + record_unwind_protect (call_process_kill, make_number (0)); message1 ("Waiting for process to die...(type C-g again to kill it instantly)"); immediate_quit = 1; QUIT; - wait_for_termination (pid); + wait_for_termination (synch_process_pid, 0, 1); + synch_process_pid = 0; immediate_quit = 0; specpdl_ptr = specpdl + count; /* Discard the unwind protect. */ message1 ("Waiting for process to die...done"); } - synch_process_alive = 0; - emacs_close (fd); -#endif /* not MSDOS */ +#endif + + if (0 <= synch_process_fd) + emacs_close (synch_process_fd); + +#ifdef MSDOS + /* FILE is "" when we didn't actually create a temporary file in + call-process. */ + if (!(strcmp (SDATA (file), NULL_DEVICE) == 0 || SREF (file, 0) == '\0')) + unlink (SDATA (file)); +#endif + return Qnil; } @@ -191,18 +203,14 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you quit again. usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) (ptrdiff_t nargs, Lisp_Object *args) { - Lisp_Object infile, buffer, current_dir, path, cleanup_info_tail; - int display_p; - int fd[2]; - int filefd; -#define CALLPROC_BUFFER_SIZE_MIN (16 * 1024) -#define CALLPROC_BUFFER_SIZE_MAX (4 * CALLPROC_BUFFER_SIZE_MIN) - char buf[CALLPROC_BUFFER_SIZE_MAX]; - int bufsize = CALLPROC_BUFFER_SIZE_MIN; + Lisp_Object infile, buffer, current_dir, path; + bool display_p; + int fd0, fd1, filefd; + int status; ptrdiff_t count = SPECPDL_INDEX (); USE_SAFE_ALLOCA; - register const unsigned char **new_argv; + char **new_argv; /* File to use for stderr in the child. t means use same as standard output. */ Lisp_Object error_file; @@ -214,12 +222,13 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) #else pid_t pid; #endif + int child_errno; int fd_output = -1; struct coding_system process_coding; /* coding-system of process output */ struct coding_system argument_coding; /* coding-system of arguments */ /* Set to the return value of Ffind_operation_coding_system. */ Lisp_Object coding_systems; - int output_to_buffer = 1; + bool output_to_buffer = 1; /* Qt denotes that Ffind_operation_coding_system is not yet called. */ coding_systems = Qt; @@ -243,7 +252,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) /* If arguments are supplied, we may have to encode them. */ if (nargs >= 5) { - int must_encode = 0; + bool must_encode = 0; Lisp_Object coding_attrs; for (i = 4; i < nargs; i++) @@ -425,8 +434,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) && SREF (path, 1) == ':') path = Fsubstring (path, make_number (2), Qnil); - SAFE_ALLOCA (new_argv, const unsigned char **, - (nargs > 4 ? nargs - 2 : 2) * sizeof *new_argv); + new_argv = SAFE_ALLOCA ((nargs > 4 ? nargs - 2 : 2) * sizeof *new_argv); if (nargs > 4) { ptrdiff_t i; @@ -443,12 +451,12 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) } UNGCPRO; for (i = 4; i < nargs; i++) - new_argv[i - 3] = SDATA (args[i]); + new_argv[i - 3] = SSDATA (args[i]); new_argv[i - 3] = 0; } else new_argv[1] = 0; - new_argv[0] = SDATA (path); + new_argv[0] = SSDATA (path); #ifdef MSDOS /* MW, July 1993 */ @@ -477,51 +485,36 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) } else outfilefd = fd_output; - fd[0] = filefd; - fd[1] = outfilefd; + fd0 = filefd; + fd1 = outfilefd; #endif /* MSDOS */ if (INTEGERP (buffer)) - fd[1] = emacs_open (NULL_DEVICE, O_WRONLY, 0), fd[0] = -1; + { + fd0 = -1; + fd1 = emacs_open (NULL_DEVICE, O_WRONLY, 0); + } else { #ifndef MSDOS - errno = 0; + int fd[2]; if (pipe (fd) == -1) { + int pipe_errno = errno; emacs_close (filefd); + errno = pipe_errno; report_file_error ("Creating process pipe", Qnil); } + fd0 = fd[0]; + fd1 = fd[1]; #endif } { - /* child_setup must clobber environ in systems with true vfork. - Protect it from permanent change. */ - register char **save_environ = environ; - register int fd1 = fd[1]; int fd_error = fd1; -#ifdef HAVE_WORKING_VFORK - sigset_t procmask; - sigset_t blocked; - struct sigaction sigpipe_action; -#endif if (fd_output >= 0) fd1 = fd_output; -#if 0 /* Some systems don't have sigblock. */ - mask = sigblock (sigmask (SIGCHLD)); -#endif - - /* Record that we're about to create a synchronous process. */ - synch_process_alive = 1; - - /* These vars record information from process termination. - Clear them now before process can possibly terminate, - to avoid timing error if process terminates soon. */ - synch_process_death = 0; - synch_process_retcode = 0; - synch_process_termsig = 0; if (NILP (error_file)) fd_error = emacs_open (NULL_DEVICE, O_WRONLY, 0); @@ -539,8 +532,8 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) if (fd_error < 0) { emacs_close (filefd); - if (fd[0] != filefd) - emacs_close (fd[0]); + if (fd0 != filefd) + emacs_close (fd0); if (fd1 >= 0) emacs_close (fd1); #ifdef MSDOS @@ -555,31 +548,28 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) #ifdef MSDOS /* MW, July 1993 */ /* Note that on MSDOS `child_setup' actually returns the child process - exit status, not its PID, so we assign it to `synch_process_retcode' - below. */ - pid = child_setup (filefd, outfilefd, fd_error, (char **) new_argv, - 0, current_dir); - - /* Record that the synchronous process exited and note its - termination status. */ - synch_process_alive = 0; - synch_process_retcode = pid; - if (synch_process_retcode < 0) /* means it couldn't be exec'ed */ - { - synchronize_system_messages_locale (); - synch_process_death = strerror (errno); - } + exit status, not its PID, so assign it to status below. */ + pid = child_setup (filefd, outfilefd, fd_error, new_argv, 0, current_dir); + child_errno = errno; emacs_close (outfilefd); if (fd_error != outfilefd) emacs_close (fd_error); + if (pid < 0) + { + synchronize_system_messages_locale (); + return + code_convert_string_norecord (build_string (strerror (child_errno)), + Vlocale_coding_system, 0); + } + status = pid; fd1 = -1; /* No harm in closing that one! */ if (tempfile) { /* Since CRLF is converted to LF within `decode_coding', we can always open a file with binary mode. */ - fd[0] = emacs_open (tempfile, O_RDONLY | O_BINARY, 0); - if (fd[0] < 0) + fd0 = emacs_open (tempfile, O_RDONLY | O_BINARY, 0); + if (fd0 < 0) { unlink (tempfile); emacs_close (filefd); @@ -588,97 +578,102 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) } } else - fd[0] = -1; /* We are not going to read from tempfile. */ -#else /* not MSDOS */ -#ifdef WINDOWSNT - pid = child_setup (filefd, fd1, fd_error, (char **) new_argv, - 0, current_dir); -#else /* not WINDOWSNT */ + fd0 = -1; /* We are not going to read from tempfile. */ +#endif /* MSDOS */ -#ifdef HAVE_WORKING_VFORK - /* On many hosts (e.g. Solaris 2.4), if a vforked child calls `signal', - this sets the parent's signal handlers as well as the child's. - So delay all interrupts whose handlers the child might munge, - and record the current handlers so they can be restored later. */ - sigemptyset (&blocked); - sigaddset (&blocked, SIGPIPE); - sigaction (SIGPIPE, 0, &sigpipe_action); - pthread_sigmask (SIG_BLOCK, &blocked, &procmask); -#endif + /* Do the unwind-protect now, even though the pid is not known, so + that no storage allocation is done in the critical section. + The actual PID will be filled in during the critical section. */ + synch_process_pid = 0; + synch_process_fd = fd0; - BLOCK_INPUT; +#ifdef MSDOS + /* MSDOS needs different cleanup information. */ + record_unwind_protect (call_process_cleanup, + Fcons (Fcurrent_buffer (), + build_string (tempfile ? tempfile : ""))); +#else + record_unwind_protect (call_process_cleanup, Fcurrent_buffer ()); + + block_input (); + block_child_signal (); + +#ifdef WINDOWSNT + pid = child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir); +#else /* not WINDOWSNT */ /* vfork, and prevent local vars from being clobbered by the vfork. */ { Lisp_Object volatile buffer_volatile = buffer; Lisp_Object volatile coding_systems_volatile = coding_systems; Lisp_Object volatile current_dir_volatile = current_dir; - int volatile display_p_volatile = display_p; + bool volatile display_p_volatile = display_p; + bool volatile output_to_buffer_volatile = output_to_buffer; + bool volatile sa_must_free_volatile = sa_must_free; int volatile fd1_volatile = fd1; int volatile fd_error_volatile = fd_error; int volatile fd_output_volatile = fd_output; - int volatile output_to_buffer_volatile = output_to_buffer; - int volatile sa_must_free_volatile = sa_must_free; + int volatile filefd_volatile = filefd; + ptrdiff_t volatile count_volatile = count; ptrdiff_t volatile sa_count_volatile = sa_count; - unsigned char const **volatile new_argv_volatile = new_argv; + char **volatile new_argv_volatile = new_argv; pid = vfork (); + child_errno = errno; buffer = buffer_volatile; coding_systems = coding_systems_volatile; current_dir = current_dir_volatile; display_p = display_p_volatile; + output_to_buffer = output_to_buffer_volatile; + sa_must_free = sa_must_free_volatile; fd1 = fd1_volatile; fd_error = fd_error_volatile; fd_output = fd_output_volatile; - output_to_buffer = output_to_buffer_volatile; - sa_must_free = sa_must_free_volatile; + filefd = filefd_volatile; + count = count_volatile; sa_count = sa_count_volatile; new_argv = new_argv_volatile; + + fd0 = synch_process_fd; } if (pid == 0) { - if (fd[0] >= 0) - emacs_close (fd[0]); -#ifdef HAVE_SETSID + unblock_child_signal (); + + if (fd0 >= 0) + emacs_close (fd0); + setsid (); -#endif -#if defined (USG) - setpgrp (); -#else - setpgrp (pid, pid); -#endif /* USG */ - /* GConf causes us to ignore SIGPIPE, make sure it is restored - in the child. */ + /* Emacs ignores SIGPIPE, but the child should not. */ signal (SIGPIPE, SIG_DFL); -#ifdef HAVE_WORKING_VFORK - pthread_sigmask (SIG_SETMASK, &procmask, 0); -#endif - child_setup (filefd, fd1, fd_error, (char **) new_argv, - 0, current_dir); + child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir); } - UNBLOCK_INPUT; +#endif /* not WINDOWSNT */ -#ifdef HAVE_WORKING_VFORK - /* Restore the signal state. */ - sigaction (SIGPIPE, &sigpipe_action, 0); - pthread_sigmask (SIG_SETMASK, &procmask, 0); -#endif + child_errno = errno; -#endif /* not WINDOWSNT */ + if (0 < pid) + { + if (INTEGERP (buffer)) + record_deleted_pid (pid); + else + synch_process_pid = pid; + } + + unblock_child_signal (); + unblock_input (); /* The MSDOS case did this already. */ if (fd_error >= 0) emacs_close (fd_error); #endif /* not MSDOS */ - environ = save_environ; - - /* Close most of our fd's, but not fd[0] + /* Close most of our file descriptors, but not fd0 since we will use that to read input from. */ emacs_close (filefd); if (fd_output >= 0) @@ -689,31 +684,12 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) if (pid < 0) { - if (fd[0] >= 0) - emacs_close (fd[0]); + errno = child_errno; report_file_error ("Doing vfork", Qnil); } if (INTEGERP (buffer)) - { - if (fd[0] >= 0) - emacs_close (fd[0]); - return Qnil; - } - - /* Enable sending signal if user quits below. */ - call_process_exited = 0; - -#if defined (MSDOS) - /* MSDOS needs different cleanup information. */ - cleanup_info_tail = build_string (tempfile ? tempfile : ""); -#else - cleanup_info_tail = INTEGER_TO_CONS (pid); -#endif /* not MSDOS */ - record_unwind_protect (call_process_cleanup, - Fcons (Fcurrent_buffer (), - Fcons (INTEGER_TO_CONS (fd[0]), - cleanup_info_tail))); + return unbind_to (count, Qnil); if (BUFFERP (buffer)) Fset_buffer (buffer); @@ -769,11 +745,15 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) if (output_to_buffer) { - register int nread; - int first = 1; + enum { CALLPROC_BUFFER_SIZE_MIN = 16 * 1024 }; + enum { CALLPROC_BUFFER_SIZE_MAX = 4 * CALLPROC_BUFFER_SIZE_MIN }; + char buf[CALLPROC_BUFFER_SIZE_MAX]; + int bufsize = CALLPROC_BUFFER_SIZE_MIN; + int nread; + bool first = 1; EMACS_INT total_read = 0; int carryover = 0; - int display_on_the_fly = display_p; + bool display_on_the_fly = display_p; struct coding_system saved_coding; saved_coding = process_coding; @@ -785,7 +765,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) nread = carryover; while (nread < bufsize - 1024) { - int this_read = emacs_read (fd[0], buf + nread, + int this_read = emacs_read (fd0, buf + nread, bufsize - nread); if (this_read < 0) @@ -896,38 +876,34 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) #ifndef MSDOS /* Wait for it to terminate, unless it already has. */ - if (output_to_buffer) - wait_for_termination (pid); - else - interruptible_wait_for_termination (pid); + wait_for_termination (pid, &status, !output_to_buffer); #endif immediate_quit = 0; /* Don't kill any children that the subprocess may have left behind when exiting. */ - call_process_exited = 1; + synch_process_pid = 0; SAFE_FREE (); unbind_to (count, Qnil); - if (synch_process_termsig) + if (WIFSIGNALED (status)) { const char *signame; synchronize_system_messages_locale (); - signame = strsignal (synch_process_termsig); + signame = strsignal (WTERMSIG (status)); if (signame == 0) signame = "unknown"; - synch_process_death = signame; + return code_convert_string_norecord (build_string (signame), + Vlocale_coding_system, 0); } - if (synch_process_death) - return code_convert_string_norecord (build_string (synch_process_death), - Vlocale_coding_system, 0); - return make_number (synch_process_retcode); + eassert (WIFEXITED (status)); + return make_number (WEXITSTATUS (status)); } static Lisp_Object @@ -976,8 +952,7 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r Lisp_Object coding_systems; Lisp_Object val, *args2; ptrdiff_t i; - char *tempfile; - Lisp_Object tmpdir, pattern; + Lisp_Object tmpdir; if (STRINGP (Vtemporary_file_directory)) tmpdir = Vtemporary_file_directory; @@ -1001,18 +976,19 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r { USE_SAFE_ALLOCA; - pattern = Fexpand_file_name (Vtemp_file_name_pattern, tmpdir); - SAFE_ALLOCA (tempfile, char *, SBYTES (pattern) + 1); - memcpy (tempfile, SDATA (pattern), SBYTES (pattern) + 1); + Lisp_Object pattern = Fexpand_file_name (Vtemp_file_name_pattern, tmpdir); + Lisp_Object encoded_tem = ENCODE_FILE (pattern); + char *tempfile = SAFE_ALLOCA (SBYTES (encoded_tem) + 1); + memcpy (tempfile, SDATA (encoded_tem), SBYTES (encoded_tem) + 1); coding_systems = Qt; #ifdef HAVE_MKSTEMP { int fd; - BLOCK_INPUT; + block_input (); fd = mkstemp (tempfile); - UNBLOCK_INPUT; + unblock_input (); if (fd == -1) report_file_error ("Failed to open temporary file", Fcons (build_string (tempfile), Qnil)); @@ -1020,7 +996,15 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r close (fd); } #else + errno = 0; mktemp (tempfile); + if (!*tempfile) + { + if (!errno) + errno = EEXIST; + report_file_error ("Failed to open temporary file using pattern", + Fcons (pattern, Qnil)); + } #endif filename_string = build_string (tempfile); @@ -1090,7 +1074,7 @@ static char ** add_env (char **env, char **new_env, char *string) { char **ep; - int ok = 1; + bool ok = 1; if (string == NULL) return new_env; @@ -1126,12 +1110,7 @@ add_env (char **env, char **new_env, char *string) Initialize inferior's priority, pgrp, connected dir and environment. then exec another program based on new_argv. - This function may change environ for the superior process. - Therefore, the superior process must save and restore the value - of environ around the vfork and the call to this function. - - SET_PGRP is nonzero if we should put the subprocess into a separate - process group. + If SET_PGRP, put the subprocess into a separate process group. CURRENT_DIR is an elisp string giving the path of the current directory the subprocess should have. Since we can't really signal @@ -1139,7 +1118,8 @@ add_env (char **env, char **new_env, char *string) executable directory by the parent. */ int -child_setup (int in, int out, int err, register char **new_argv, int set_pgrp, Lisp_Object current_dir) +child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, + Lisp_Object current_dir) { char **env; char *pwd_var; @@ -1174,9 +1154,9 @@ child_setup (int in, int out, int err, register char **new_argv, int set_pgrp, L /* MSDOS must have all environment variables malloc'ed, because low-level libc functions that launch subsidiary processes rely on that. */ - pwd_var = (char *) xmalloc (i + 6); + pwd_var = xmalloc (i + 6); #else - pwd_var = (char *) alloca (i + 6); + pwd_var = alloca (i + 6); #endif temp = pwd_var + 4; memcpy (pwd_var, "PWD=", 4); @@ -1244,7 +1224,7 @@ child_setup (int in, int out, int err, register char **new_argv, int set_pgrp, L } /* new_length + 2 to include PWD and terminating 0. */ - env = new_env = (char **) alloca ((new_length + 2) * sizeof (char *)); + env = new_env = alloca ((new_length + 2) * sizeof *env); /* If we have a PWD envvar, pass one down, but with corrected value. */ if (egetenv ("PWD")) @@ -1252,7 +1232,7 @@ child_setup (int in, int out, int err, register char **new_argv, int set_pgrp, L if (STRINGP (display)) { - char *vdata = (char *) alloca (sizeof "DISPLAY=" + SBYTES (display)); + char *vdata = alloca (sizeof "DISPLAY=" + SBYTES (display)); strcpy (vdata, "DISPLAY="); strcat (vdata, SSDATA (display)); new_env = add_env (env, new_env, vdata); @@ -1329,22 +1309,10 @@ child_setup (int in, int out, int err, register char **new_argv, int set_pgrp, L if (err != in && err != out) emacs_close (err); -#if defined (USG) -#ifndef SETPGRP_RELEASES_CTTY - setpgrp (); /* No arguments but equivalent in this case */ -#endif -#else /* not USG */ - setpgrp (pid, pid); -#endif /* not USG */ - - /* setpgrp_of_tty is incorrect here; it uses input_fd. */ + setpgid (0, 0); tcsetpgrp (0, pid); - /* execvp does not accept an environment arg so the only way - to pass this environment is to set environ. Our caller - is responsible for restoring the ambient value of environ. */ - environ = env; - execvp (new_argv[0], new_argv); + execve (new_argv[0], new_argv, env); emacs_write (1, "Can't exec program: ", 20); emacs_write (1, new_argv[0], strlen (new_argv[0])); @@ -1372,16 +1340,7 @@ relocate_fd (int fd, int minfd) return fd; else { - int new; -#ifdef F_DUPFD - new = fcntl (fd, F_DUPFD, minfd); -#else - new = dup (fd); - if (new != -1) - /* Note that we hold the original FD open while we recurse, - to guarantee we'll get a new FD if we need it. */ - new = relocate_fd (new, minfd); -#endif + int new = fcntl (fd, F_DUPFD, minfd); if (new == -1) { const char *message_1 = "Error while setting up child: "; @@ -1398,7 +1357,7 @@ relocate_fd (int fd, int minfd) } #endif /* not WINDOWSNT */ -static int +static bool getenv_internal_1 (const char *var, ptrdiff_t varlen, char **value, ptrdiff_t *valuelen, Lisp_Object env) { @@ -1433,7 +1392,7 @@ getenv_internal_1 (const char *var, ptrdiff_t varlen, char **value, return 0; } -static int +static bool getenv_internal (const char *var, ptrdiff_t varlen, char **value, ptrdiff_t *valuelen, Lisp_Object frame) { @@ -1513,20 +1472,34 @@ egetenv (const char *var) void init_callproc_1 (void) { - char *data_dir = egetenv ("EMACSDATA"); - char *doc_dir = egetenv ("EMACSDOC"); +#ifdef HAVE_NS + const char *etc_dir = ns_etc_directory (); + const char *path_exec = ns_exec_path (); +#endif - Vdata_directory - = Ffile_name_as_directory (build_string (data_dir ? data_dir - : PATH_DATA)); - Vdoc_directory - = Ffile_name_as_directory (build_string (doc_dir ? doc_dir - : PATH_DOC)); + Vdata_directory = decode_env_path ("EMACSDATA", +#ifdef HAVE_NS + etc_dir ? etc_dir : +#endif + PATH_DATA); + Vdata_directory = Ffile_name_as_directory (Fcar (Vdata_directory)); + + Vdoc_directory = decode_env_path ("EMACSDOC", +#ifdef HAVE_NS + etc_dir ? etc_dir : +#endif + PATH_DOC); + Vdoc_directory = Ffile_name_as_directory (Fcar (Vdoc_directory)); /* Check the EMACSPATH environment variable, defaulting to the PATH_EXEC path from epaths.h. */ - Vexec_path = decode_env_path ("EMACSPATH", PATH_EXEC); + Vexec_path = decode_env_path ("EMACSPATH", +#ifdef HAVE_NS + path_exec ? path_exec : +#endif + PATH_EXEC); Vexec_directory = Ffile_name_as_directory (Fcar (Vexec_path)); + /* FIXME? For ns, path_exec should go at the front? */ Vexec_path = nconc2 (decode_env_path ("PATH", ""), Vexec_path); } @@ -1539,6 +1512,17 @@ init_callproc (void) register char * sh; Lisp_Object tempdir; +#ifdef HAVE_NS + if (data_dir == 0) + { + const char *etc_dir = ns_etc_directory (); + if (etc_dir) + { + data_dir = alloca (strlen (etc_dir) + 1); + strcpy (data_dir, etc_dir); + } + } +#endif if (!NILP (Vinstallation_directory)) { @@ -1546,17 +1530,24 @@ init_callproc (void) Lisp_Object tem; tem = Fexpand_file_name (build_string ("lib-src"), Vinstallation_directory); -#ifndef DOS_NT +#ifndef MSDOS /* MSDOS uses wrapped binaries, so don't do this. */ if (NILP (Fmember (tem, Vexec_path))) { - Vexec_path = decode_env_path ("EMACSPATH", PATH_EXEC); +#ifdef HAVE_NS + const char *path_exec = ns_exec_path (); +#endif + Vexec_path = decode_env_path ("EMACSPATH", +#ifdef HAVE_NS + path_exec ? path_exec : +#endif + PATH_EXEC); Vexec_path = Fcons (tem, Vexec_path); Vexec_path = nconc2 (decode_env_path ("PATH", ""), Vexec_path); } Vexec_directory = Ffile_name_as_directory (tem); -#endif /* not DOS_NT */ +#endif /* not MSDOS */ /* Maybe use ../etc as well as ../lib-src. */ if (data_dir == 0) @@ -1599,15 +1590,13 @@ init_callproc (void) #endif { tempdir = Fdirectory_file_name (Vexec_directory); - if (access (SSDATA (tempdir), 0) < 0) - dir_warning ("Warning: arch-dependent data dir (%s) does not exist.\n", - Vexec_directory); + if (! file_accessible_directory_p (SSDATA (tempdir))) + dir_warning ("arch-dependent data dir", Vexec_directory); } tempdir = Fdirectory_file_name (Vdata_directory); - if (access (SSDATA (tempdir), 0) < 0) - dir_warning ("Warning: arch-independent data dir (%s) does not exist.\n", - Vdata_directory); + if (! file_accessible_directory_p (SSDATA (tempdir))) + dir_warning ("arch-independent data dir", Vdata_directory); sh = (char *) getenv ("SHELL"); Vshell_file_name = build_string (sh ? sh : "/bin/sh"); @@ -1616,7 +1605,7 @@ init_callproc (void) Vshared_game_score_directory = Qnil; #else Vshared_game_score_directory = build_string (PATH_GAME); - if (NILP (Ffile_directory_p (Vshared_game_score_directory))) + if (NILP (Ffile_accessible_directory_p (Vshared_game_score_directory))) Vshared_game_score_directory = Qnil; #endif }