summaryrefslogtreecommitdiff
path: root/src/callproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/callproc.c')
-rw-r--r--src/callproc.c53
1 files changed, 30 insertions, 23 deletions
diff --git a/src/callproc.c b/src/callproc.c
index e8b61b9f01f..0636571b26c 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -466,7 +466,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
&& SREF (path, 1) == ':')
path = Fsubstring (path, make_number (2), Qnil);
- new_argv = SAFE_ALLOCA ((nargs > 4 ? nargs - 2 : 2) * sizeof *new_argv);
+ SAFE_NALLOCA (new_argv, 1, nargs < 4 ? 2 : nargs - 2);
{
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
@@ -1151,6 +1151,25 @@ add_env (char **env, char **new_env, char *string)
return new_env;
}
+#ifndef DOS_NT
+
+/* 'exec' failed inside a child running NAME, with error number ERR.
+ Report the error and exit the child. */
+
+static _Noreturn void
+exec_failed (char const *name, int err)
+{
+ /* Avoid deadlock if the child's perror writes to a full pipe; the
+ pipe's reader is the parent, but with vfork the parent can't
+ run until the child exits. Truncate the diagnostic instead. */
+ fcntl (STDERR_FILENO, F_SETFL, O_NONBLOCK);
+
+ errno = err;
+ emacs_perror (name);
+ _exit (err == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
+}
+#endif
+
/* This is the last thing run in a newly forked inferior
either synchronous or asynchronous.
Copy descriptors IN, OUT and ERR as descriptors 0, 1 and 2.
@@ -1174,8 +1193,6 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
int cpid;
HANDLE handles[3];
#else
- int exec_errno;
-
pid_t pid = getpid ();
#endif /* WINDOWSNT */
@@ -1196,6 +1213,8 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
on that. */
pwd_var = xmalloc (i + 5);
#else
+ if (MAX_ALLOCA - 5 < i)
+ exec_failed (new_argv[0], ENOMEM);
pwd_var = alloca (i + 5);
#endif
temp = pwd_var + 4;
@@ -1262,6 +1281,8 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
}
/* new_length + 2 to include PWD and terminating 0. */
+ if (MAX_ALLOCA / sizeof *env - 2 < new_length)
+ exec_failed (new_argv[0], ENOMEM);
env = new_env = alloca ((new_length + 2) * sizeof *env);
/* If we have a PWD envvar, pass one down,
but with corrected value. */
@@ -1270,6 +1291,8 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
if (STRINGP (display))
{
+ if (MAX_ALLOCA - sizeof "DISPLAY=" < SBYTES (display))
+ exec_failed (new_argv[0], ENOMEM);
char *vdata = alloca (sizeof "DISPLAY=" + SBYTES (display));
strcpy (vdata, "DISPLAY=");
strcat (vdata, SSDATA (display));
@@ -1345,16 +1368,7 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
tcsetpgrp (0, pid);
execve (new_argv[0], new_argv, env);
- exec_errno = errno;
-
- /* Avoid deadlock if the child's perror writes to a full pipe; the
- pipe's reader is the parent, but with vfork the parent can't
- run until the child exits. Truncate the diagnostic instead. */
- fcntl (STDERR_FILENO, F_SETFL, O_NONBLOCK);
-
- errno = exec_errno;
- emacs_perror (new_argv[0]);
- _exit (exec_errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
+ exec_failed (new_argv[0], errno);
#else /* MSDOS */
pid = run_msdos_command (new_argv, pwd_var + 4, in, out, err, env);
@@ -1543,20 +1557,13 @@ init_callproc_1 (void)
void
init_callproc (void)
{
- char *data_dir = egetenv ("EMACSDATA");
+ bool data_dir = egetenv ("EMACSDATA") != 0;
- register char * sh;
+ 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);
- }
- }
+ data_dir == ns_etc_directory () != 0;
#endif
if (!NILP (Vinstallation_directory))