diff options
Diffstat (limited to 'src/callproc.c')
| -rw-r--r-- | src/callproc.c | 53 | 
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))  | 
