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, | |||
| 466 | && SREF (path, 1) == ':') | 466 | && SREF (path, 1) == ':') |
| 467 | path = Fsubstring (path, make_number (2), Qnil); | 467 | path = Fsubstring (path, make_number (2), Qnil); |
| 468 | 468 | ||
| 469 | new_argv = SAFE_ALLOCA ((nargs > 4 ? nargs - 2 : 2) * sizeof *new_argv); | 469 | SAFE_NALLOCA (new_argv, 1, nargs < 4 ? 2 : nargs - 2); |
| 470 | 470 | ||
| 471 | { | 471 | { |
| 472 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | 472 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; |
| @@ -1151,6 +1151,25 @@ add_env (char **env, char **new_env, char *string) | |||
| 1151 | return new_env; | 1151 | return new_env; |
| 1152 | } | 1152 | } |
| 1153 | 1153 | ||
| 1154 | #ifndef DOS_NT | ||
| 1155 | |||
| 1156 | /* 'exec' failed inside a child running NAME, with error number ERR. | ||
| 1157 | Report the error and exit the child. */ | ||
| 1158 | |||
| 1159 | static _Noreturn void | ||
| 1160 | exec_failed (char const *name, int err) | ||
| 1161 | { | ||
| 1162 | /* Avoid deadlock if the child's perror writes to a full pipe; the | ||
| 1163 | pipe's reader is the parent, but with vfork the parent can't | ||
| 1164 | run until the child exits. Truncate the diagnostic instead. */ | ||
| 1165 | fcntl (STDERR_FILENO, F_SETFL, O_NONBLOCK); | ||
| 1166 | |||
| 1167 | errno = err; | ||
| 1168 | emacs_perror (name); | ||
| 1169 | _exit (err == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE); | ||
| 1170 | } | ||
| 1171 | #endif | ||
| 1172 | |||
| 1154 | /* This is the last thing run in a newly forked inferior | 1173 | /* This is the last thing run in a newly forked inferior |
| 1155 | either synchronous or asynchronous. | 1174 | either synchronous or asynchronous. |
| 1156 | Copy descriptors IN, OUT and ERR as descriptors 0, 1 and 2. | 1175 | 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, | |||
| 1174 | int cpid; | 1193 | int cpid; |
| 1175 | HANDLE handles[3]; | 1194 | HANDLE handles[3]; |
| 1176 | #else | 1195 | #else |
| 1177 | int exec_errno; | ||
| 1178 | |||
| 1179 | pid_t pid = getpid (); | 1196 | pid_t pid = getpid (); |
| 1180 | #endif /* WINDOWSNT */ | 1197 | #endif /* WINDOWSNT */ |
| 1181 | 1198 | ||
| @@ -1196,6 +1213,8 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, | |||
| 1196 | on that. */ | 1213 | on that. */ |
| 1197 | pwd_var = xmalloc (i + 5); | 1214 | pwd_var = xmalloc (i + 5); |
| 1198 | #else | 1215 | #else |
| 1216 | if (MAX_ALLOCA - 5 < i) | ||
| 1217 | exec_failed (new_argv[0], ENOMEM); | ||
| 1199 | pwd_var = alloca (i + 5); | 1218 | pwd_var = alloca (i + 5); |
| 1200 | #endif | 1219 | #endif |
| 1201 | temp = pwd_var + 4; | 1220 | temp = pwd_var + 4; |
| @@ -1262,6 +1281,8 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, | |||
| 1262 | } | 1281 | } |
| 1263 | 1282 | ||
| 1264 | /* new_length + 2 to include PWD and terminating 0. */ | 1283 | /* new_length + 2 to include PWD and terminating 0. */ |
| 1284 | if (MAX_ALLOCA / sizeof *env - 2 < new_length) | ||
| 1285 | exec_failed (new_argv[0], ENOMEM); | ||
| 1265 | env = new_env = alloca ((new_length + 2) * sizeof *env); | 1286 | env = new_env = alloca ((new_length + 2) * sizeof *env); |
| 1266 | /* If we have a PWD envvar, pass one down, | 1287 | /* If we have a PWD envvar, pass one down, |
| 1267 | but with corrected value. */ | 1288 | but with corrected value. */ |
| @@ -1270,6 +1291,8 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, | |||
| 1270 | 1291 | ||
| 1271 | if (STRINGP (display)) | 1292 | if (STRINGP (display)) |
| 1272 | { | 1293 | { |
| 1294 | if (MAX_ALLOCA - sizeof "DISPLAY=" < SBYTES (display)) | ||
| 1295 | exec_failed (new_argv[0], ENOMEM); | ||
| 1273 | char *vdata = alloca (sizeof "DISPLAY=" + SBYTES (display)); | 1296 | char *vdata = alloca (sizeof "DISPLAY=" + SBYTES (display)); |
| 1274 | strcpy (vdata, "DISPLAY="); | 1297 | strcpy (vdata, "DISPLAY="); |
| 1275 | strcat (vdata, SSDATA (display)); | 1298 | strcat (vdata, SSDATA (display)); |
| @@ -1345,16 +1368,7 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, | |||
| 1345 | tcsetpgrp (0, pid); | 1368 | tcsetpgrp (0, pid); |
| 1346 | 1369 | ||
| 1347 | execve (new_argv[0], new_argv, env); | 1370 | execve (new_argv[0], new_argv, env); |
| 1348 | exec_errno = errno; | 1371 | exec_failed (new_argv[0], errno); |
| 1349 | |||
| 1350 | /* Avoid deadlock if the child's perror writes to a full pipe; the | ||
| 1351 | pipe's reader is the parent, but with vfork the parent can't | ||
| 1352 | run until the child exits. Truncate the diagnostic instead. */ | ||
| 1353 | fcntl (STDERR_FILENO, F_SETFL, O_NONBLOCK); | ||
| 1354 | |||
| 1355 | errno = exec_errno; | ||
| 1356 | emacs_perror (new_argv[0]); | ||
| 1357 | _exit (exec_errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE); | ||
| 1358 | 1372 | ||
| 1359 | #else /* MSDOS */ | 1373 | #else /* MSDOS */ |
| 1360 | pid = run_msdos_command (new_argv, pwd_var + 4, in, out, err, env); | 1374 | pid = run_msdos_command (new_argv, pwd_var + 4, in, out, err, env); |
| @@ -1543,20 +1557,13 @@ init_callproc_1 (void) | |||
| 1543 | void | 1557 | void |
| 1544 | init_callproc (void) | 1558 | init_callproc (void) |
| 1545 | { | 1559 | { |
| 1546 | char *data_dir = egetenv ("EMACSDATA"); | 1560 | bool data_dir = egetenv ("EMACSDATA") != 0; |
| 1547 | 1561 | ||
| 1548 | register char * sh; | 1562 | char *sh; |
| 1549 | Lisp_Object tempdir; | 1563 | Lisp_Object tempdir; |
| 1550 | #ifdef HAVE_NS | 1564 | #ifdef HAVE_NS |
| 1551 | if (data_dir == 0) | 1565 | if (data_dir == 0) |
| 1552 | { | 1566 | data_dir == ns_etc_directory () != 0; |
| 1553 | const char *etc_dir = ns_etc_directory (); | ||
| 1554 | if (etc_dir) | ||
| 1555 | { | ||
| 1556 | data_dir = alloca (strlen (etc_dir) + 1); | ||
| 1557 | strcpy (data_dir, etc_dir); | ||
| 1558 | } | ||
| 1559 | } | ||
| 1560 | #endif | 1567 | #endif |
| 1561 | 1568 | ||
| 1562 | if (!NILP (Vinstallation_directory)) | 1569 | if (!NILP (Vinstallation_directory)) |