diff options
| author | Joakim Verona | 2013-08-23 20:12:26 +0200 |
|---|---|---|
| committer | Joakim Verona | 2013-08-23 20:12:26 +0200 |
| commit | aedb3873bb150227acd4b9496127a2e250d9da66 (patch) | |
| tree | ce857f619470ef47e1ddbe5f9ad92320fd20b8bb | |
| parent | 0fd8418c4004d593b9f37c55ed5b9c5ca221c72b (diff) | |
| parent | c365c3558065fca4c11c3f46605d1045763485ab (diff) | |
| download | emacs-aedb3873bb150227acd4b9496127a2e250d9da66.tar.gz emacs-aedb3873bb150227acd4b9496127a2e250d9da66.zip | |
merge from trunk
| -rw-r--r-- | src/ChangeLog | 22 | ||||
| -rw-r--r-- | src/callproc.c | 59 | ||||
| -rw-r--r-- | src/fileio.c | 118 | ||||
| -rw-r--r-- | src/process.c | 32 | ||||
| -rw-r--r-- | src/process.h | 1 | ||||
| -rw-r--r-- | src/sysdep.c | 48 |
6 files changed, 142 insertions, 138 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index bee477c745a..73fdb0221ce 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,25 @@ | |||
| 1 | 2013-08-23 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Don't let very long directory names overrun the stack. | ||
| 4 | Fix some related minor problems involving "//", vfork. | ||
| 5 | * callproc.c (encode_current_directory): New function. | ||
| 6 | (call_process): Don't append "/"; not needed. | ||
| 7 | * fileio.c (file_name_as_directory_slop): New constant. | ||
| 8 | (file_name_as_directory): Allow SRC to be longer than SRCLEN; | ||
| 9 | this can save the caller having to alloca. | ||
| 10 | (Ffile_name_as_directory, Fdirectory_file_name, Fexpand_file_name): | ||
| 11 | Use SAFE_ALLOCA, not alloca. | ||
| 12 | (directory_file_name, Fexpand_file_name): Leave leading "//" | ||
| 13 | alone, since it can be special even on POSIX platforms. | ||
| 14 | * callproc.c (call_process): | ||
| 15 | * process.c (Fformat_network_address): | ||
| 16 | * sysdep.c (sys_subshell): | ||
| 17 | Use encode_current_directory rather than rolling our own. | ||
| 18 | (create_process): No need to encode directory; caller does that now. | ||
| 19 | * process.h (encode_current_directory): New decl. | ||
| 20 | * sysdep.c (sys_subshell): Work even if vfork trashes saved_handlers. | ||
| 21 | Rework to avoid 'goto xyzzy;'. | ||
| 22 | |||
| 1 | 2013-08-23 Eli Zaretskii <eliz@gnu.org> | 23 | 2013-08-23 Eli Zaretskii <eliz@gnu.org> |
| 2 | 24 | ||
| 3 | * xdisp.c (handle_face_prop): If the default face was remapped use | 25 | * xdisp.c (handle_face_prop): If the default face was remapped use |
diff --git a/src/callproc.c b/src/callproc.c index fca4216b5f7..d4b4a26ec3a 100644 --- a/src/callproc.c +++ b/src/callproc.c | |||
| @@ -123,6 +123,37 @@ unblock_child_signal (void) | |||
| 123 | pthread_sigmask (SIG_SETMASK, &empty_mask, 0); | 123 | pthread_sigmask (SIG_SETMASK, &empty_mask, 0); |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | /* Return the current buffer's working directory, or the home | ||
| 127 | directory if it's unreachable, as a string suitable for a system call. | ||
| 128 | Signal an error if the result would not be an accessible directory. */ | ||
| 129 | |||
| 130 | Lisp_Object | ||
| 131 | encode_current_directory (void) | ||
| 132 | { | ||
| 133 | Lisp_Object dir; | ||
| 134 | struct gcpro gcpro1; | ||
| 135 | |||
| 136 | dir = BVAR (current_buffer, directory); | ||
| 137 | GCPRO1 (dir); | ||
| 138 | |||
| 139 | dir = Funhandled_file_name_directory (dir); | ||
| 140 | |||
| 141 | /* If the file name handler says that dir is unreachable, use | ||
| 142 | a sensible default. */ | ||
| 143 | if (NILP (dir)) | ||
| 144 | dir = build_string ("~"); | ||
| 145 | |||
| 146 | dir = expand_and_dir_to_file (dir, Qnil); | ||
| 147 | |||
| 148 | if (STRING_MULTIBYTE (dir)) | ||
| 149 | dir = ENCODE_FILE (dir); | ||
| 150 | if (! file_accessible_directory_p (SSDATA (dir))) | ||
| 151 | report_file_error ("Setting current directory", | ||
| 152 | BVAR (current_buffer, directory)); | ||
| 153 | |||
| 154 | RETURN_UNGCPRO (dir); | ||
| 155 | } | ||
| 156 | |||
| 126 | /* If P is reapable, record it as a deleted process and kill it. | 157 | /* If P is reapable, record it as a deleted process and kill it. |
| 127 | Do this in a critical section. Unless PID is wedged it will be | 158 | Do this in a critical section. Unless PID is wedged it will be |
| 128 | reaped on receipt of the first SIGCHLD after the critical section. */ | 159 | reaped on receipt of the first SIGCHLD after the critical section. */ |
| @@ -408,24 +439,10 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, | |||
| 408 | { | 439 | { |
| 409 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | 440 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; |
| 410 | 441 | ||
| 411 | current_dir = BVAR (current_buffer, directory); | 442 | current_dir = encode_current_directory (); |
| 412 | 443 | ||
| 413 | GCPRO4 (buffer, current_dir, error_file, output_file); | 444 | GCPRO4 (buffer, current_dir, error_file, output_file); |
| 414 | 445 | ||
| 415 | current_dir = Funhandled_file_name_directory (current_dir); | ||
| 416 | if (NILP (current_dir)) | ||
| 417 | /* If the file name handler says that current_dir is unreachable, use | ||
| 418 | a sensible default. */ | ||
| 419 | current_dir = build_string ("~/"); | ||
| 420 | current_dir = expand_and_dir_to_file (current_dir, Qnil); | ||
| 421 | current_dir = Ffile_name_as_directory (current_dir); | ||
| 422 | |||
| 423 | if (NILP (Ffile_accessible_directory_p (current_dir))) | ||
| 424 | report_file_error ("Setting current directory", | ||
| 425 | BVAR (current_buffer, directory)); | ||
| 426 | |||
| 427 | if (STRING_MULTIBYTE (current_dir)) | ||
| 428 | current_dir = ENCODE_FILE (current_dir); | ||
| 429 | if (STRINGP (error_file) && STRING_MULTIBYTE (error_file)) | 446 | if (STRINGP (error_file) && STRING_MULTIBYTE (error_file)) |
| 430 | error_file = ENCODE_FILE (error_file); | 447 | error_file = ENCODE_FILE (error_file); |
| 431 | if (STRINGP (output_file) && STRING_MULTIBYTE (output_file)) | 448 | if (STRINGP (output_file) && STRING_MULTIBYTE (output_file)) |
| @@ -1176,23 +1193,21 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, | |||
| 1176 | static variables as if the superior had done alloca and will be | 1193 | static variables as if the superior had done alloca and will be |
| 1177 | cleaned up in the usual way. */ | 1194 | cleaned up in the usual way. */ |
| 1178 | { | 1195 | { |
| 1179 | register char *temp; | 1196 | char *temp; |
| 1180 | size_t i; /* size_t, because ptrdiff_t might overflow here! */ | 1197 | ptrdiff_t i; |
| 1181 | 1198 | ||
| 1182 | i = SBYTES (current_dir); | 1199 | i = SBYTES (current_dir); |
| 1183 | #ifdef MSDOS | 1200 | #ifdef MSDOS |
| 1184 | /* MSDOS must have all environment variables malloc'ed, because | 1201 | /* MSDOS must have all environment variables malloc'ed, because |
| 1185 | low-level libc functions that launch subsidiary processes rely | 1202 | low-level libc functions that launch subsidiary processes rely |
| 1186 | on that. */ | 1203 | on that. */ |
| 1187 | pwd_var = xmalloc (i + 6); | 1204 | pwd_var = xmalloc (i + 5); |
| 1188 | #else | 1205 | #else |
| 1189 | pwd_var = alloca (i + 6); | 1206 | pwd_var = alloca (i + 5); |
| 1190 | #endif | 1207 | #endif |
| 1191 | temp = pwd_var + 4; | 1208 | temp = pwd_var + 4; |
| 1192 | memcpy (pwd_var, "PWD=", 4); | 1209 | memcpy (pwd_var, "PWD=", 4); |
| 1193 | memcpy (temp, SDATA (current_dir), i); | 1210 | strcpy (temp, SSDATA (current_dir)); |
| 1194 | if (!IS_DIRECTORY_SEP (temp[i - 1])) temp[i++] = DIRECTORY_SEP; | ||
| 1195 | temp[i] = 0; | ||
| 1196 | 1211 | ||
| 1197 | #ifndef DOS_NT | 1212 | #ifndef DOS_NT |
| 1198 | /* We can't signal an Elisp error here; we're in a vfork. Since | 1213 | /* We can't signal an Elisp error here; we're in a vfork. Since |
diff --git a/src/fileio.c b/src/fileio.c index 08caf102266..7cad8d29da2 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -504,6 +504,10 @@ get a current directory to run processes in. */) | |||
| 504 | return Ffile_name_directory (filename); | 504 | return Ffile_name_directory (filename); |
| 505 | } | 505 | } |
| 506 | 506 | ||
| 507 | /* Maximum number of bytes that DST will be longer than SRC | ||
| 508 | in file_name_as_directory. This occurs when SRCLEN == 0. */ | ||
| 509 | enum { file_name_as_directory_slop = 2 }; | ||
| 510 | |||
| 507 | /* Convert from file name SRC of length SRCLEN to directory name in | 511 | /* Convert from file name SRC of length SRCLEN to directory name in |
| 508 | DST. MULTIBYTE non-zero means the file name in SRC is a multibyte | 512 | DST. MULTIBYTE non-zero means the file name in SRC is a multibyte |
| 509 | string. On UNIX, just make sure there is a terminating /. Return | 513 | string. On UNIX, just make sure there is a terminating /. Return |
| @@ -521,14 +525,10 @@ file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen, | |||
| 521 | return 2; | 525 | return 2; |
| 522 | } | 526 | } |
| 523 | 527 | ||
| 524 | strcpy (dst, src); | 528 | memcpy (dst, src, srclen); |
| 525 | |||
| 526 | if (!IS_DIRECTORY_SEP (dst[srclen - 1])) | 529 | if (!IS_DIRECTORY_SEP (dst[srclen - 1])) |
| 527 | { | 530 | dst[srclen++] = DIRECTORY_SEP; |
| 528 | dst[srclen] = DIRECTORY_SEP; | 531 | dst[srclen] = 0; |
| 529 | dst[srclen + 1] = '\0'; | ||
| 530 | srclen++; | ||
| 531 | } | ||
| 532 | #ifdef DOS_NT | 532 | #ifdef DOS_NT |
| 533 | dostounix_filename (dst, multibyte); | 533 | dostounix_filename (dst, multibyte); |
| 534 | #endif | 534 | #endif |
| @@ -547,7 +547,8 @@ For a Unix-syntax file name, just appends a slash. */) | |||
| 547 | { | 547 | { |
| 548 | char *buf; | 548 | char *buf; |
| 549 | ptrdiff_t length; | 549 | ptrdiff_t length; |
| 550 | Lisp_Object handler; | 550 | Lisp_Object handler, val; |
| 551 | USE_SAFE_ALLOCA; | ||
| 551 | 552 | ||
| 552 | CHECK_STRING (file); | 553 | CHECK_STRING (file); |
| 553 | if (NILP (file)) | 554 | if (NILP (file)) |
| @@ -569,10 +570,12 @@ For a Unix-syntax file name, just appends a slash. */) | |||
| 569 | if (!NILP (Vw32_downcase_file_names)) | 570 | if (!NILP (Vw32_downcase_file_names)) |
| 570 | file = Fdowncase (file); | 571 | file = Fdowncase (file); |
| 571 | #endif | 572 | #endif |
| 572 | buf = alloca (SBYTES (file) + 10); | 573 | buf = SAFE_ALLOCA (SBYTES (file) + file_name_as_directory_slop + 1); |
| 573 | length = file_name_as_directory (buf, SSDATA (file), SBYTES (file), | 574 | length = file_name_as_directory (buf, SSDATA (file), SBYTES (file), |
| 574 | STRING_MULTIBYTE (file)); | 575 | STRING_MULTIBYTE (file)); |
| 575 | return make_specified_string (buf, -1, length, STRING_MULTIBYTE (file)); | 576 | val = make_specified_string (buf, -1, length, STRING_MULTIBYTE (file)); |
| 577 | SAFE_FREE (); | ||
| 578 | return val; | ||
| 576 | } | 579 | } |
| 577 | 580 | ||
| 578 | /* Convert from directory name SRC of length SRCLEN to file name in | 581 | /* Convert from directory name SRC of length SRCLEN to file name in |
| @@ -584,18 +587,17 @@ static ptrdiff_t | |||
| 584 | directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte) | 587 | directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte) |
| 585 | { | 588 | { |
| 586 | /* Process as Unix format: just remove any final slash. | 589 | /* Process as Unix format: just remove any final slash. |
| 587 | But leave "/" unchanged; do not change it to "". */ | 590 | But leave "/" and "//" unchanged. */ |
| 588 | strcpy (dst, src); | 591 | while (srclen > 1 |
| 589 | if (srclen > 1 | ||
| 590 | && IS_DIRECTORY_SEP (dst[srclen - 1]) | ||
| 591 | #ifdef DOS_NT | 592 | #ifdef DOS_NT |
| 592 | && !IS_ANY_SEP (dst[srclen - 2]) | 593 | && !IS_ANY_SEP (src[srclen - 2]) |
| 593 | #endif | 594 | #endif |
| 594 | ) | 595 | && IS_DIRECTORY_SEP (src[srclen - 1]) |
| 595 | { | 596 | && ! (srclen == 2 && IS_DIRECTORY_SEP (src[0]))) |
| 596 | dst[srclen - 1] = 0; | 597 | srclen--; |
| 597 | srclen--; | 598 | |
| 598 | } | 599 | memcpy (dst, src, srclen); |
| 600 | dst[srclen] = 0; | ||
| 599 | #ifdef DOS_NT | 601 | #ifdef DOS_NT |
| 600 | dostounix_filename (dst, multibyte); | 602 | dostounix_filename (dst, multibyte); |
| 601 | #endif | 603 | #endif |
| @@ -613,7 +615,8 @@ In Unix-syntax, this function just removes the final slash. */) | |||
| 613 | { | 615 | { |
| 614 | char *buf; | 616 | char *buf; |
| 615 | ptrdiff_t length; | 617 | ptrdiff_t length; |
| 616 | Lisp_Object handler; | 618 | Lisp_Object handler, val; |
| 619 | USE_SAFE_ALLOCA; | ||
| 617 | 620 | ||
| 618 | CHECK_STRING (directory); | 621 | CHECK_STRING (directory); |
| 619 | 622 | ||
| @@ -636,10 +639,12 @@ In Unix-syntax, this function just removes the final slash. */) | |||
| 636 | if (!NILP (Vw32_downcase_file_names)) | 639 | if (!NILP (Vw32_downcase_file_names)) |
| 637 | directory = Fdowncase (directory); | 640 | directory = Fdowncase (directory); |
| 638 | #endif | 641 | #endif |
| 639 | buf = alloca (SBYTES (directory) + 20); | 642 | buf = SAFE_ALLOCA (SBYTES (directory) + 1); |
| 640 | length = directory_file_name (buf, SSDATA (directory), SBYTES (directory), | 643 | length = directory_file_name (buf, SSDATA (directory), SBYTES (directory), |
| 641 | STRING_MULTIBYTE (directory)); | 644 | STRING_MULTIBYTE (directory)); |
| 642 | return make_specified_string (buf, -1, length, STRING_MULTIBYTE (directory)); | 645 | val = make_specified_string (buf, -1, length, STRING_MULTIBYTE (directory)); |
| 646 | SAFE_FREE (); | ||
| 647 | return val; | ||
| 643 | } | 648 | } |
| 644 | 649 | ||
| 645 | static const char make_temp_name_tbl[64] = | 650 | static const char make_temp_name_tbl[64] = |
| @@ -837,6 +842,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) | |||
| 837 | Lisp_Object handler, result, handled_name; | 842 | Lisp_Object handler, result, handled_name; |
| 838 | bool multibyte; | 843 | bool multibyte; |
| 839 | Lisp_Object hdir; | 844 | Lisp_Object hdir; |
| 845 | USE_SAFE_ALLOCA; | ||
| 840 | 846 | ||
| 841 | CHECK_STRING (name); | 847 | CHECK_STRING (name); |
| 842 | 848 | ||
| @@ -1011,11 +1017,11 @@ filesystem tree, not (expand-file-name ".." dirname). */) | |||
| 1011 | || (p[2] == '.' && (IS_DIRECTORY_SEP (p[3]) | 1017 | || (p[2] == '.' && (IS_DIRECTORY_SEP (p[3]) |
| 1012 | || p[3] == 0)))) | 1018 | || p[3] == 0)))) |
| 1013 | lose = 1; | 1019 | lose = 1; |
| 1014 | /* We want to replace multiple `/' in a row with a single | 1020 | /* Replace multiple slashes with a single one, except |
| 1015 | slash. */ | 1021 | leave leading "//" alone. */ |
| 1016 | else if (p > nm | 1022 | else if (IS_DIRECTORY_SEP (p[0]) |
| 1017 | && IS_DIRECTORY_SEP (p[0]) | 1023 | && IS_DIRECTORY_SEP (p[1]) |
| 1018 | && IS_DIRECTORY_SEP (p[1])) | 1024 | && (p != nm || IS_DIRECTORY_SEP (p[2]))) |
| 1019 | lose = 1; | 1025 | lose = 1; |
| 1020 | p++; | 1026 | p++; |
| 1021 | } | 1027 | } |
| @@ -1098,10 +1104,11 @@ filesystem tree, not (expand-file-name ".." dirname). */) | |||
| 1098 | else /* ~user/filename */ | 1104 | else /* ~user/filename */ |
| 1099 | { | 1105 | { |
| 1100 | char *o, *p; | 1106 | char *o, *p; |
| 1101 | for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)); p++); | 1107 | for (p = nm; *p && !IS_DIRECTORY_SEP (*p); p++) |
| 1102 | o = alloca (p - nm + 1); | 1108 | continue; |
| 1109 | o = SAFE_ALLOCA (p - nm + 1); | ||
| 1103 | memcpy (o, nm, p - nm); | 1110 | memcpy (o, nm, p - nm); |
| 1104 | o [p - nm] = 0; | 1111 | o[p - nm] = 0; |
| 1105 | 1112 | ||
| 1106 | block_input (); | 1113 | block_input (); |
| 1107 | pw = getpwnam (o + 1); | 1114 | pw = getpwnam (o + 1); |
| @@ -1217,7 +1224,8 @@ filesystem tree, not (expand-file-name ".." dirname). */) | |||
| 1217 | if (!IS_DIRECTORY_SEP (nm[0])) | 1224 | if (!IS_DIRECTORY_SEP (nm[0])) |
| 1218 | { | 1225 | { |
| 1219 | ptrdiff_t newlen = strlen (newdir); | 1226 | ptrdiff_t newlen = strlen (newdir); |
| 1220 | char *tmp = alloca (newlen + strlen (nm) + 2); | 1227 | char *tmp = alloca (newlen + file_name_as_directory_slop |
| 1228 | + strlen (nm) + 1); | ||
| 1221 | file_name_as_directory (tmp, newdir, newlen, multibyte); | 1229 | file_name_as_directory (tmp, newdir, newlen, multibyte); |
| 1222 | strcat (tmp, nm); | 1230 | strcat (tmp, nm); |
| 1223 | nm = tmp; | 1231 | nm = tmp; |
| @@ -1271,31 +1279,18 @@ filesystem tree, not (expand-file-name ".." dirname). */) | |||
| 1271 | 1279 | ||
| 1272 | if (newdir) | 1280 | if (newdir) |
| 1273 | { | 1281 | { |
| 1274 | /* Get rid of any slash at the end of newdir, unless newdir is | 1282 | /* Ignore any slash at the end of newdir, unless newdir is |
| 1275 | just / or // (an incomplete UNC name). */ | 1283 | just "/" or "//". */ |
| 1276 | length = strlen (newdir); | 1284 | length = strlen (newdir); |
| 1277 | tlen = length + 1; | 1285 | while (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1]) |
| 1278 | if (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1]) | 1286 | && ! (length == 2 && IS_DIRECTORY_SEP (newdir[0]))) |
| 1279 | #ifdef WINDOWSNT | 1287 | length--; |
| 1280 | && !(length == 2 && IS_DIRECTORY_SEP (newdir[0])) | ||
| 1281 | #endif | ||
| 1282 | ) | ||
| 1283 | { | ||
| 1284 | char *temp = alloca (length); | ||
| 1285 | memcpy (temp, newdir, length - 1); | ||
| 1286 | temp[length - 1] = 0; | ||
| 1287 | length--; | ||
| 1288 | newdir = temp; | ||
| 1289 | } | ||
| 1290 | } | 1288 | } |
| 1291 | else | 1289 | else |
| 1292 | { | 1290 | length = 0; |
| 1293 | length = 0; | ||
| 1294 | tlen = 0; | ||
| 1295 | } | ||
| 1296 | 1291 | ||
| 1297 | /* Now concatenate the directory and name to new space in the stack frame. */ | 1292 | /* Now concatenate the directory and name to new space in the stack frame. */ |
| 1298 | tlen += strlen (nm) + 1; | 1293 | tlen = length + file_name_as_directory_slop + strlen (nm) + 1; |
| 1299 | #ifdef DOS_NT | 1294 | #ifdef DOS_NT |
| 1300 | /* Reserve space for drive specifier and escape prefix, since either | 1295 | /* Reserve space for drive specifier and escape prefix, since either |
| 1301 | or both may need to be inserted. (The Microsoft x86 compiler | 1296 | or both may need to be inserted. (The Microsoft x86 compiler |
| @@ -1303,7 +1298,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) | |||
| 1303 | target = alloca (tlen + 4); | 1298 | target = alloca (tlen + 4); |
| 1304 | target += 4; | 1299 | target += 4; |
| 1305 | #else /* not DOS_NT */ | 1300 | #else /* not DOS_NT */ |
| 1306 | target = alloca (tlen); | 1301 | target = SAFE_ALLOCA (tlen); |
| 1307 | #endif /* not DOS_NT */ | 1302 | #endif /* not DOS_NT */ |
| 1308 | *target = 0; | 1303 | *target = 0; |
| 1309 | 1304 | ||
| @@ -1320,7 +1315,10 @@ filesystem tree, not (expand-file-name ".." dirname). */) | |||
| 1320 | if (!(drive && nm[0] && IS_DIRECTORY_SEP (newdir[0]) | 1315 | if (!(drive && nm[0] && IS_DIRECTORY_SEP (newdir[0]) |
| 1321 | && newdir[1] == '\0')) | 1316 | && newdir[1] == '\0')) |
| 1322 | #endif | 1317 | #endif |
| 1323 | strcpy (target, newdir); | 1318 | { |
| 1319 | memcpy (target, newdir, length); | ||
| 1320 | target[length] = 0; | ||
| 1321 | } | ||
| 1324 | } | 1322 | } |
| 1325 | else | 1323 | else |
| 1326 | file_name_as_directory (target, newdir, length, multibyte); | 1324 | file_name_as_directory (target, newdir, length, multibyte); |
| @@ -1380,8 +1378,9 @@ filesystem tree, not (expand-file-name ".." dirname). */) | |||
| 1380 | ++o; | 1378 | ++o; |
| 1381 | p += 3; | 1379 | p += 3; |
| 1382 | } | 1380 | } |
| 1383 | else if (p > target && IS_DIRECTORY_SEP (p[1])) | 1381 | else if (IS_DIRECTORY_SEP (p[1]) |
| 1384 | /* Collapse multiple `/' in a row. */ | 1382 | && (p != target || IS_DIRECTORY_SEP (p[2]))) |
| 1383 | /* Collapse multiple "/", except leave leading "//" alone. */ | ||
| 1385 | p++; | 1384 | p++; |
| 1386 | else | 1385 | else |
| 1387 | { | 1386 | { |
| @@ -1429,11 +1428,12 @@ filesystem tree, not (expand-file-name ".." dirname). */) | |||
| 1429 | { | 1428 | { |
| 1430 | handled_name = call3 (handler, Qexpand_file_name, | 1429 | handled_name = call3 (handler, Qexpand_file_name, |
| 1431 | result, default_directory); | 1430 | result, default_directory); |
| 1432 | if (STRINGP (handled_name)) | 1431 | if (! STRINGP (handled_name)) |
| 1433 | return handled_name; | 1432 | error ("Invalid handler in `file-name-handler-alist'"); |
| 1434 | error ("Invalid handler in `file-name-handler-alist'"); | 1433 | result = handled_name; |
| 1435 | } | 1434 | } |
| 1436 | 1435 | ||
| 1436 | SAFE_FREE (); | ||
| 1437 | return result; | 1437 | return result; |
| 1438 | } | 1438 | } |
| 1439 | 1439 | ||
diff --git a/src/process.c b/src/process.c index 75cb590fc57..ea1129ffbb8 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -1408,22 +1408,9 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) | |||
| 1408 | function. The argument list is protected by the caller, so all | 1408 | function. The argument list is protected by the caller, so all |
| 1409 | we really have to worry about is buffer. */ | 1409 | we really have to worry about is buffer. */ |
| 1410 | { | 1410 | { |
| 1411 | struct gcpro gcpro1, gcpro2; | 1411 | struct gcpro gcpro1; |
| 1412 | 1412 | GCPRO1 (buffer); | |
| 1413 | current_dir = BVAR (current_buffer, directory); | 1413 | current_dir = encode_current_directory (); |
| 1414 | |||
| 1415 | GCPRO2 (buffer, current_dir); | ||
| 1416 | |||
| 1417 | current_dir = Funhandled_file_name_directory (current_dir); | ||
| 1418 | if (NILP (current_dir)) | ||
| 1419 | /* If the file name handler says that current_dir is unreachable, use | ||
| 1420 | a sensible default. */ | ||
| 1421 | current_dir = build_string ("~/"); | ||
| 1422 | current_dir = expand_and_dir_to_file (current_dir, Qnil); | ||
| 1423 | if (NILP (Ffile_accessible_directory_p (current_dir))) | ||
| 1424 | report_file_error ("Setting current directory", | ||
| 1425 | BVAR (current_buffer, directory)); | ||
| 1426 | |||
| 1427 | UNGCPRO; | 1414 | UNGCPRO; |
| 1428 | } | 1415 | } |
| 1429 | 1416 | ||
| @@ -1670,7 +1657,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1670 | bool pty_flag = 0; | 1657 | bool pty_flag = 0; |
| 1671 | char pty_name[PTY_NAME_SIZE]; | 1658 | char pty_name[PTY_NAME_SIZE]; |
| 1672 | Lisp_Object lisp_pty_name = Qnil; | 1659 | Lisp_Object lisp_pty_name = Qnil; |
| 1673 | Lisp_Object encoded_current_dir; | ||
| 1674 | 1660 | ||
| 1675 | inchannel = outchannel = -1; | 1661 | inchannel = outchannel = -1; |
| 1676 | 1662 | ||
| @@ -1735,15 +1721,13 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1735 | /* This may signal an error. */ | 1721 | /* This may signal an error. */ |
| 1736 | setup_process_coding_systems (process); | 1722 | setup_process_coding_systems (process); |
| 1737 | 1723 | ||
| 1738 | encoded_current_dir = ENCODE_FILE (current_dir); | ||
| 1739 | |||
| 1740 | block_input (); | 1724 | block_input (); |
| 1741 | block_child_signal (); | 1725 | block_child_signal (); |
| 1742 | 1726 | ||
| 1743 | #ifndef WINDOWSNT | 1727 | #ifndef WINDOWSNT |
| 1744 | /* vfork, and prevent local vars from being clobbered by the vfork. */ | 1728 | /* vfork, and prevent local vars from being clobbered by the vfork. */ |
| 1745 | { | 1729 | { |
| 1746 | Lisp_Object volatile encoded_current_dir_volatile = encoded_current_dir; | 1730 | Lisp_Object volatile current_dir_volatile = current_dir; |
| 1747 | Lisp_Object volatile lisp_pty_name_volatile = lisp_pty_name; | 1731 | Lisp_Object volatile lisp_pty_name_volatile = lisp_pty_name; |
| 1748 | char **volatile new_argv_volatile = new_argv; | 1732 | char **volatile new_argv_volatile = new_argv; |
| 1749 | int volatile forkin_volatile = forkin; | 1733 | int volatile forkin_volatile = forkin; |
| @@ -1752,7 +1736,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1752 | 1736 | ||
| 1753 | pid = vfork (); | 1737 | pid = vfork (); |
| 1754 | 1738 | ||
| 1755 | encoded_current_dir = encoded_current_dir_volatile; | 1739 | current_dir = current_dir_volatile; |
| 1756 | lisp_pty_name = lisp_pty_name_volatile; | 1740 | lisp_pty_name = lisp_pty_name_volatile; |
| 1757 | new_argv = new_argv_volatile; | 1741 | new_argv = new_argv_volatile; |
| 1758 | forkin = forkin_volatile; | 1742 | forkin = forkin_volatile; |
| @@ -1864,11 +1848,9 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1864 | if (pty_flag) | 1848 | if (pty_flag) |
| 1865 | child_setup_tty (xforkout); | 1849 | child_setup_tty (xforkout); |
| 1866 | #ifdef WINDOWSNT | 1850 | #ifdef WINDOWSNT |
| 1867 | pid = child_setup (xforkin, xforkout, xforkout, | 1851 | pid = child_setup (xforkin, xforkout, xforkout, new_argv, 1, current_dir); |
| 1868 | new_argv, 1, encoded_current_dir); | ||
| 1869 | #else /* not WINDOWSNT */ | 1852 | #else /* not WINDOWSNT */ |
| 1870 | child_setup (xforkin, xforkout, xforkout, | 1853 | child_setup (xforkin, xforkout, xforkout, new_argv, 1, current_dir); |
| 1871 | new_argv, 1, encoded_current_dir); | ||
| 1872 | #endif /* not WINDOWSNT */ | 1854 | #endif /* not WINDOWSNT */ |
| 1873 | } | 1855 | } |
| 1874 | 1856 | ||
diff --git a/src/process.h b/src/process.h index b312f7f2425..6aff95686a2 100644 --- a/src/process.h +++ b/src/process.h | |||
| @@ -218,6 +218,7 @@ enum | |||
| 218 | 218 | ||
| 219 | extern void block_child_signal (void); | 219 | extern void block_child_signal (void); |
| 220 | extern void unblock_child_signal (void); | 220 | extern void unblock_child_signal (void); |
| 221 | extern Lisp_Object encode_current_directory (void); | ||
| 221 | extern void record_kill_process (struct Lisp_Process *, Lisp_Object); | 222 | extern void record_kill_process (struct Lisp_Process *, Lisp_Object); |
| 222 | 223 | ||
| 223 | /* Defined in sysdep.c. */ | 224 | /* Defined in sysdep.c. */ |
diff --git a/src/sysdep.c b/src/sysdep.c index 78e3d908cfe..c6d5f9942ab 100644 --- a/src/sysdep.c +++ b/src/sysdep.c | |||
| @@ -471,10 +471,20 @@ sys_subshell (void) | |||
| 471 | pid_t pid; | 471 | pid_t pid; |
| 472 | int status; | 472 | int status; |
| 473 | struct save_signal saved_handlers[5]; | 473 | struct save_signal saved_handlers[5]; |
| 474 | Lisp_Object dir; | 474 | char *str = SSDATA (encode_current_directory ()); |
| 475 | unsigned char *volatile str_volatile = 0; | 475 | |
| 476 | unsigned char *str; | 476 | #ifdef DOS_NT |
| 477 | int len; | 477 | pid = 0; |
| 478 | #else | ||
| 479 | { | ||
| 480 | char *volatile str_volatile = str; | ||
| 481 | pid = vfork (); | ||
| 482 | str = str_volatile; | ||
| 483 | } | ||
| 484 | #endif | ||
| 485 | |||
| 486 | if (pid < 0) | ||
| 487 | error ("Can't spawn subshell"); | ||
| 478 | 488 | ||
| 479 | saved_handlers[0].code = SIGINT; | 489 | saved_handlers[0].code = SIGINT; |
| 480 | saved_handlers[1].code = SIGQUIT; | 490 | saved_handlers[1].code = SIGQUIT; |
| @@ -486,31 +496,8 @@ sys_subshell (void) | |||
| 486 | saved_handlers[3].code = 0; | 496 | saved_handlers[3].code = 0; |
| 487 | #endif | 497 | #endif |
| 488 | 498 | ||
| 489 | /* Mentioning current_buffer->buffer would mean including buffer.h, | ||
| 490 | which somehow wedges the hp compiler. So instead... */ | ||
| 491 | |||
| 492 | dir = intern ("default-directory"); | ||
| 493 | if (NILP (Fboundp (dir))) | ||
| 494 | goto xyzzy; | ||
| 495 | dir = Fsymbol_value (dir); | ||
| 496 | if (!STRINGP (dir)) | ||
| 497 | goto xyzzy; | ||
| 498 | |||
| 499 | dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil); | ||
| 500 | str_volatile = str = alloca (SCHARS (dir) + 2); | ||
| 501 | len = SCHARS (dir); | ||
| 502 | memcpy (str, SDATA (dir), len); | ||
| 503 | if (str[len - 1] != '/') str[len++] = '/'; | ||
| 504 | str[len] = 0; | ||
| 505 | xyzzy: | ||
| 506 | |||
| 507 | #ifdef DOS_NT | 499 | #ifdef DOS_NT |
| 508 | pid = 0; | ||
| 509 | save_signal_handlers (saved_handlers); | 500 | save_signal_handlers (saved_handlers); |
| 510 | #else | ||
| 511 | pid = vfork (); | ||
| 512 | if (pid == -1) | ||
| 513 | error ("Can't spawn subshell"); | ||
| 514 | #endif | 501 | #endif |
| 515 | 502 | ||
| 516 | if (pid == 0) | 503 | if (pid == 0) |
| @@ -528,11 +515,10 @@ sys_subshell (void) | |||
| 528 | sh = "sh"; | 515 | sh = "sh"; |
| 529 | 516 | ||
| 530 | /* Use our buffer's default directory for the subshell. */ | 517 | /* Use our buffer's default directory for the subshell. */ |
| 531 | str = str_volatile; | 518 | if (chdir (str) != 0) |
| 532 | if (str && chdir ((char *) str) != 0) | ||
| 533 | { | 519 | { |
| 534 | #ifndef DOS_NT | 520 | #ifndef DOS_NT |
| 535 | emacs_perror ((char *) str); | 521 | emacs_perror (str); |
| 536 | _exit (EXIT_CANCELED); | 522 | _exit (EXIT_CANCELED); |
| 537 | #endif | 523 | #endif |
| 538 | } | 524 | } |
| @@ -546,8 +532,6 @@ sys_subshell (void) | |||
| 546 | if (epwd) | 532 | if (epwd) |
| 547 | { | 533 | { |
| 548 | strcpy (old_pwd, epwd); | 534 | strcpy (old_pwd, epwd); |
| 549 | if (str[len - 1] == '/') | ||
| 550 | str[len - 1] = '\0'; | ||
| 551 | setenv ("PWD", str, 1); | 535 | setenv ("PWD", str, 1); |
| 552 | } | 536 | } |
| 553 | st = system (sh); | 537 | st = system (sh); |