diff options
Diffstat (limited to 'src/callproc.c')
| -rw-r--r-- | src/callproc.c | 87 |
1 files changed, 56 insertions, 31 deletions
diff --git a/src/callproc.c b/src/callproc.c index 2f68ea6f328..e3dcc7bbcca 100644 --- a/src/callproc.c +++ b/src/callproc.c | |||
| @@ -129,7 +129,7 @@ encode_current_directory (void) | |||
| 129 | 129 | ||
| 130 | if (STRING_MULTIBYTE (dir)) | 130 | if (STRING_MULTIBYTE (dir)) |
| 131 | dir = ENCODE_FILE (dir); | 131 | dir = ENCODE_FILE (dir); |
| 132 | if (! file_accessible_directory_p (SSDATA (dir))) | 132 | if (! file_accessible_directory_p (dir)) |
| 133 | report_file_error ("Setting current directory", | 133 | report_file_error ("Setting current directory", |
| 134 | BVAR (current_buffer, directory)); | 134 | BVAR (current_buffer, directory)); |
| 135 | 135 | ||
| @@ -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; |
| @@ -632,6 +632,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, | |||
| 632 | int volatile fd_error_volatile = fd_error; | 632 | int volatile fd_error_volatile = fd_error; |
| 633 | int volatile filefd_volatile = filefd; | 633 | int volatile filefd_volatile = filefd; |
| 634 | ptrdiff_t volatile count_volatile = count; | 634 | ptrdiff_t volatile count_volatile = count; |
| 635 | ptrdiff_t volatile sa_avail_volatile = sa_avail; | ||
| 635 | ptrdiff_t volatile sa_count_volatile = sa_count; | 636 | ptrdiff_t volatile sa_count_volatile = sa_count; |
| 636 | char **volatile new_argv_volatile = new_argv; | 637 | char **volatile new_argv_volatile = new_argv; |
| 637 | int volatile callproc_fd_volatile[CALLPROC_FDS]; | 638 | int volatile callproc_fd_volatile[CALLPROC_FDS]; |
| @@ -648,6 +649,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, | |||
| 648 | fd_error = fd_error_volatile; | 649 | fd_error = fd_error_volatile; |
| 649 | filefd = filefd_volatile; | 650 | filefd = filefd_volatile; |
| 650 | count = count_volatile; | 651 | count = count_volatile; |
| 652 | sa_avail = sa_avail_volatile; | ||
| 651 | sa_count = sa_count_volatile; | 653 | sa_count = sa_count_volatile; |
| 652 | new_argv = new_argv_volatile; | 654 | new_argv = new_argv_volatile; |
| 653 | 655 | ||
| @@ -1151,6 +1153,39 @@ add_env (char **env, char **new_env, char *string) | |||
| 1151 | return new_env; | 1153 | return new_env; |
| 1152 | } | 1154 | } |
| 1153 | 1155 | ||
| 1156 | #ifndef DOS_NT | ||
| 1157 | |||
| 1158 | /* 'exec' failed inside a child running NAME, with error number ERR. | ||
| 1159 | Possibly a vforked child needed to allocate a large vector on the | ||
| 1160 | stack; such a child cannot fall back on malloc because that might | ||
| 1161 | mess up the allocator's data structures in the parent. | ||
| 1162 | Report the error and exit the child. */ | ||
| 1163 | |||
| 1164 | static _Noreturn void | ||
| 1165 | exec_failed (char const *name, int err) | ||
| 1166 | { | ||
| 1167 | /* Avoid deadlock if the child's perror writes to a full pipe; the | ||
| 1168 | pipe's reader is the parent, but with vfork the parent can't | ||
| 1169 | run until the child exits. Truncate the diagnostic instead. */ | ||
| 1170 | fcntl (STDERR_FILENO, F_SETFL, O_NONBLOCK); | ||
| 1171 | |||
| 1172 | errno = err; | ||
| 1173 | emacs_perror (name); | ||
| 1174 | _exit (err == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE); | ||
| 1175 | } | ||
| 1176 | |||
| 1177 | #else | ||
| 1178 | |||
| 1179 | /* Do nothing. There is no need to fail, as DOS_NT platforms do not | ||
| 1180 | fork and exec, and handle alloca exhaustion in a different way. */ | ||
| 1181 | |||
| 1182 | static void | ||
| 1183 | exec_failed (char const *name, int err) | ||
| 1184 | { | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | #endif | ||
| 1188 | |||
| 1154 | /* This is the last thing run in a newly forked inferior | 1189 | /* This is the last thing run in a newly forked inferior |
| 1155 | either synchronous or asynchronous. | 1190 | either synchronous or asynchronous. |
| 1156 | Copy descriptors IN, OUT and ERR as descriptors 0, 1 and 2. | 1191 | Copy descriptors IN, OUT and ERR as descriptors 0, 1 and 2. |
| @@ -1174,8 +1209,6 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, | |||
| 1174 | int cpid; | 1209 | int cpid; |
| 1175 | HANDLE handles[3]; | 1210 | HANDLE handles[3]; |
| 1176 | #else | 1211 | #else |
| 1177 | int exec_errno; | ||
| 1178 | |||
| 1179 | pid_t pid = getpid (); | 1212 | pid_t pid = getpid (); |
| 1180 | #endif /* WINDOWSNT */ | 1213 | #endif /* WINDOWSNT */ |
| 1181 | 1214 | ||
| @@ -1196,11 +1229,13 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, | |||
| 1196 | on that. */ | 1229 | on that. */ |
| 1197 | pwd_var = xmalloc (i + 5); | 1230 | pwd_var = xmalloc (i + 5); |
| 1198 | #else | 1231 | #else |
| 1232 | if (MAX_ALLOCA - 5 < i) | ||
| 1233 | exec_failed (new_argv[0], ENOMEM); | ||
| 1199 | pwd_var = alloca (i + 5); | 1234 | pwd_var = alloca (i + 5); |
| 1200 | #endif | 1235 | #endif |
| 1201 | temp = pwd_var + 4; | 1236 | temp = pwd_var + 4; |
| 1202 | memcpy (pwd_var, "PWD=", 4); | 1237 | memcpy (pwd_var, "PWD=", 4); |
| 1203 | strcpy (temp, SSDATA (current_dir)); | 1238 | lispstpcpy (temp, current_dir); |
| 1204 | 1239 | ||
| 1205 | #ifndef DOS_NT | 1240 | #ifndef DOS_NT |
| 1206 | /* We can't signal an Elisp error here; we're in a vfork. Since | 1241 | /* We can't signal an Elisp error here; we're in a vfork. Since |
| @@ -1262,6 +1297,8 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, | |||
| 1262 | } | 1297 | } |
| 1263 | 1298 | ||
| 1264 | /* new_length + 2 to include PWD and terminating 0. */ | 1299 | /* new_length + 2 to include PWD and terminating 0. */ |
| 1300 | if (MAX_ALLOCA / sizeof *env - 2 < new_length) | ||
| 1301 | exec_failed (new_argv[0], ENOMEM); | ||
| 1265 | env = new_env = alloca ((new_length + 2) * sizeof *env); | 1302 | env = new_env = alloca ((new_length + 2) * sizeof *env); |
| 1266 | /* If we have a PWD envvar, pass one down, | 1303 | /* If we have a PWD envvar, pass one down, |
| 1267 | but with corrected value. */ | 1304 | but with corrected value. */ |
| @@ -1270,7 +1307,11 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, | |||
| 1270 | 1307 | ||
| 1271 | if (STRINGP (display)) | 1308 | if (STRINGP (display)) |
| 1272 | { | 1309 | { |
| 1273 | char *vdata = alloca (sizeof "DISPLAY=" + SBYTES (display)); | 1310 | char *vdata; |
| 1311 | |||
| 1312 | if (MAX_ALLOCA - sizeof "DISPLAY=" < SBYTES (display)) | ||
| 1313 | exec_failed (new_argv[0], ENOMEM); | ||
| 1314 | vdata = alloca (sizeof "DISPLAY=" + SBYTES (display)); | ||
| 1274 | strcpy (vdata, "DISPLAY="); | 1315 | strcpy (vdata, "DISPLAY="); |
| 1275 | strcat (vdata, SSDATA (display)); | 1316 | strcat (vdata, SSDATA (display)); |
| 1276 | new_env = add_env (env, new_env, vdata); | 1317 | new_env = add_env (env, new_env, vdata); |
| @@ -1345,16 +1386,7 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, | |||
| 1345 | tcsetpgrp (0, pid); | 1386 | tcsetpgrp (0, pid); |
| 1346 | 1387 | ||
| 1347 | execve (new_argv[0], new_argv, env); | 1388 | execve (new_argv[0], new_argv, env); |
| 1348 | exec_errno = errno; | 1389 | 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 | 1390 | ||
| 1359 | #else /* MSDOS */ | 1391 | #else /* MSDOS */ |
| 1360 | pid = run_msdos_command (new_argv, pwd_var + 4, in, out, err, env); | 1392 | pid = run_msdos_command (new_argv, pwd_var + 4, in, out, err, env); |
| @@ -1488,14 +1520,14 @@ If optional parameter ENV is a list, then search this list instead of | |||
| 1488 | } | 1520 | } |
| 1489 | 1521 | ||
| 1490 | /* A version of getenv that consults the Lisp environment lists, | 1522 | /* A version of getenv that consults the Lisp environment lists, |
| 1491 | easily callable from C. */ | 1523 | easily callable from C. This is usually called from egetenv. */ |
| 1492 | char * | 1524 | char * |
| 1493 | egetenv (const char *var) | 1525 | egetenv_internal (const char *var, ptrdiff_t len) |
| 1494 | { | 1526 | { |
| 1495 | char *value; | 1527 | char *value; |
| 1496 | ptrdiff_t valuelen; | 1528 | ptrdiff_t valuelen; |
| 1497 | 1529 | ||
| 1498 | if (getenv_internal (var, strlen (var), &value, &valuelen, Qnil)) | 1530 | if (getenv_internal (var, len, &value, &valuelen, Qnil)) |
| 1499 | return value; | 1531 | return value; |
| 1500 | else | 1532 | else |
| 1501 | return 0; | 1533 | return 0; |
| @@ -1543,20 +1575,13 @@ init_callproc_1 (void) | |||
| 1543 | void | 1575 | void |
| 1544 | init_callproc (void) | 1576 | init_callproc (void) |
| 1545 | { | 1577 | { |
| 1546 | char *data_dir = egetenv ("EMACSDATA"); | 1578 | bool data_dir = egetenv ("EMACSDATA") != 0; |
| 1547 | 1579 | ||
| 1548 | register char * sh; | 1580 | char *sh; |
| 1549 | Lisp_Object tempdir; | 1581 | Lisp_Object tempdir; |
| 1550 | #ifdef HAVE_NS | 1582 | #ifdef HAVE_NS |
| 1551 | if (data_dir == 0) | 1583 | if (data_dir == 0) |
| 1552 | { | 1584 | 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 | 1585 | #endif |
| 1561 | 1586 | ||
| 1562 | if (!NILP (Vinstallation_directory)) | 1587 | if (!NILP (Vinstallation_directory)) |
| @@ -1625,12 +1650,12 @@ init_callproc (void) | |||
| 1625 | #endif | 1650 | #endif |
| 1626 | { | 1651 | { |
| 1627 | tempdir = Fdirectory_file_name (Vexec_directory); | 1652 | tempdir = Fdirectory_file_name (Vexec_directory); |
| 1628 | if (! file_accessible_directory_p (SSDATA (tempdir))) | 1653 | if (! file_accessible_directory_p (tempdir)) |
| 1629 | dir_warning ("arch-dependent data dir", Vexec_directory); | 1654 | dir_warning ("arch-dependent data dir", Vexec_directory); |
| 1630 | } | 1655 | } |
| 1631 | 1656 | ||
| 1632 | tempdir = Fdirectory_file_name (Vdata_directory); | 1657 | tempdir = Fdirectory_file_name (Vdata_directory); |
| 1633 | if (! file_accessible_directory_p (SSDATA (tempdir))) | 1658 | if (! file_accessible_directory_p (tempdir)) |
| 1634 | dir_warning ("arch-independent data dir", Vdata_directory); | 1659 | dir_warning ("arch-independent data dir", Vdata_directory); |
| 1635 | 1660 | ||
| 1636 | sh = getenv ("SHELL"); | 1661 | sh = getenv ("SHELL"); |