#include <config.h>
-#include <signal.h>
#include <errno.h>
#include <stdio.h>
-#include <setjmp.h>
#include <sys/types.h>
#include <unistd.h>
#include "process.h"
#include "syssignal.h"
#include "systty.h"
+#include "syswait.h"
#include "blockinput.h"
#include "frame.h"
#include "termhooks.h"
#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;
+\f
+/* 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
+}
-\f
-/* 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;
}
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;
#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;
/* 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++)
&& 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;
}
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 */
}
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);
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
#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);
}
}
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)
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);
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;
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)
#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));
}
\f
static Lisp_Object
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;
{
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));
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);
add_env (char **env, char **new_env, char *string)
{
char **ep;
- int ok = 1;
+ bool ok = 1;
if (string == NULL)
return new_env;
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
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;
/* 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);
}
/* 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"))
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);
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]));
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: ";
}
#endif /* not WINDOWSNT */
-static int
+static bool
getenv_internal_1 (const char *var, ptrdiff_t varlen, char **value,
ptrdiff_t *valuelen, Lisp_Object env)
{
return 0;
}
-static int
+static bool
getenv_internal (const char *var, ptrdiff_t varlen, char **value,
ptrdiff_t *valuelen, Lisp_Object frame)
{
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);
}
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))
{
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)
#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");
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
}