aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoakim Verona2013-08-23 20:12:26 +0200
committerJoakim Verona2013-08-23 20:12:26 +0200
commitaedb3873bb150227acd4b9496127a2e250d9da66 (patch)
treece857f619470ef47e1ddbe5f9ad92320fd20b8bb
parent0fd8418c4004d593b9f37c55ed5b9c5ca221c72b (diff)
parentc365c3558065fca4c11c3f46605d1045763485ab (diff)
downloademacs-aedb3873bb150227acd4b9496127a2e250d9da66.tar.gz
emacs-aedb3873bb150227acd4b9496127a2e250d9da66.zip
merge from trunk
-rw-r--r--src/ChangeLog22
-rw-r--r--src/callproc.c59
-rw-r--r--src/fileio.c118
-rw-r--r--src/process.c32
-rw-r--r--src/process.h1
-rw-r--r--src/sysdep.c48
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 @@
12013-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
12013-08-23 Eli Zaretskii <eliz@gnu.org> 232013-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
130Lisp_Object
131encode_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. */
509enum { 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
584directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte) 587directory_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
645static const char make_temp_name_tbl[64] = 650static 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
219extern void block_child_signal (void); 219extern void block_child_signal (void);
220extern void unblock_child_signal (void); 220extern void unblock_child_signal (void);
221extern Lisp_Object encode_current_directory (void);
221extern void record_kill_process (struct Lisp_Process *, Lisp_Object); 222extern 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);