Commit c365c355 authored by Paul Eggert's avatar Paul Eggert
Browse files

Don't let very long directory names overrun the stack.

Fix some related minor problems involving "//", vfork.
* callproc.c (encode_current_directory): New function.
(call_process): Don't append "/"; not needed.
* fileio.c (file_name_as_directory_slop): New constant.
(file_name_as_directory): Allow SRC to be longer than SRCLEN;
this can save the caller having to alloca.
(Ffile_name_as_directory, Fdirectory_file_name, Fexpand_file_name):
Use SAFE_ALLOCA, not alloca.
(directory_file_name, Fexpand_file_name): Leave leading "//"
alone, since it can be special even on POSIX platforms.
* callproc.c (call_process):
* process.c (Fformat_network_address):
* sysdep.c (sys_subshell):
Use encode_current_directory rather than rolling our own.
(create_process): No need to encode directory; caller does that now.
* process.h (encode_current_directory): New decl.
* sysdep.c (sys_subshell): Work even if vfork trashes saved_handlers.
Rework to avoid 'goto xyzzy;'.
parent bb35f42f
2013-08-23 Paul Eggert <eggert@cs.ucla.edu>
Don't let very long directory names overrun the stack.
Fix some related minor problems involving "//", vfork.
* callproc.c (encode_current_directory): New function.
(call_process): Don't append "/"; not needed.
* fileio.c (file_name_as_directory_slop): New constant.
(file_name_as_directory): Allow SRC to be longer than SRCLEN;
this can save the caller having to alloca.
(Ffile_name_as_directory, Fdirectory_file_name, Fexpand_file_name):
Use SAFE_ALLOCA, not alloca.
(directory_file_name, Fexpand_file_name): Leave leading "//"
alone, since it can be special even on POSIX platforms.
* callproc.c (call_process):
* process.c (Fformat_network_address):
* sysdep.c (sys_subshell):
Use encode_current_directory rather than rolling our own.
(create_process): No need to encode directory; caller does that now.
* process.h (encode_current_directory): New decl.
* sysdep.c (sys_subshell): Work even if vfork trashes saved_handlers.
Rework to avoid 'goto xyzzy;'.
2013-08-23 Eli Zaretskii <eliz@gnu.org> 2013-08-23 Eli Zaretskii <eliz@gnu.org>
* xdisp.c (handle_face_prop): If the default face was remapped use * xdisp.c (handle_face_prop): If the default face was remapped use
......
...@@ -123,6 +123,37 @@ unblock_child_signal (void) ...@@ -123,6 +123,37 @@ unblock_child_signal (void)
pthread_sigmask (SIG_SETMASK, &empty_mask, 0); pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
} }
/* Return the current buffer's working directory, or the home
directory if it's unreachable, as a string suitable for a system call.
Signal an error if the result would not be an accessible directory. */
Lisp_Object
encode_current_directory (void)
{
Lisp_Object dir;
struct gcpro gcpro1;
dir = BVAR (current_buffer, directory);
GCPRO1 (dir);
dir = Funhandled_file_name_directory (dir);
/* If the file name handler says that dir is unreachable, use
a sensible default. */
if (NILP (dir))
dir = build_string ("~");
dir = expand_and_dir_to_file (dir, Qnil);
if (STRING_MULTIBYTE (dir))
dir = ENCODE_FILE (dir);
if (! file_accessible_directory_p (SSDATA (dir)))
report_file_error ("Setting current directory",
BVAR (current_buffer, directory));
RETURN_UNGCPRO (dir);
}
/* If P is reapable, record it as a deleted process and kill it. /* If P is reapable, record it as a deleted process and kill it.
Do this in a critical section. Unless PID is wedged it will be Do this in a critical section. Unless PID is wedged it will be
reaped on receipt of the first SIGCHLD after the critical section. */ 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,24 +439,10 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
{ {
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
current_dir = BVAR (current_buffer, directory); current_dir = encode_current_directory ();
GCPRO4 (buffer, current_dir, error_file, output_file); GCPRO4 (buffer, current_dir, error_file, output_file);
current_dir = Funhandled_file_name_directory (current_dir);
if (NILP (current_dir))
/* If the file name handler says that current_dir is unreachable, use
a sensible default. */
current_dir = build_string ("~/");
current_dir = expand_and_dir_to_file (current_dir, Qnil);
current_dir = Ffile_name_as_directory (current_dir);
if (NILP (Ffile_accessible_directory_p (current_dir)))
report_file_error ("Setting current directory",
BVAR (current_buffer, directory));
if (STRING_MULTIBYTE (current_dir))
current_dir = ENCODE_FILE (current_dir);
if (STRINGP (error_file) && STRING_MULTIBYTE (error_file)) if (STRINGP (error_file) && STRING_MULTIBYTE (error_file))
error_file = ENCODE_FILE (error_file); error_file = ENCODE_FILE (error_file);
if (STRINGP (output_file) && STRING_MULTIBYTE (output_file)) 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,23 +1193,21 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
static variables as if the superior had done alloca and will be static variables as if the superior had done alloca and will be
cleaned up in the usual way. */ cleaned up in the usual way. */
{ {
register char *temp; char *temp;
size_t i; /* size_t, because ptrdiff_t might overflow here! */ ptrdiff_t i;
i = SBYTES (current_dir); i = SBYTES (current_dir);
#ifdef MSDOS #ifdef MSDOS
/* MSDOS must have all environment variables malloc'ed, because /* MSDOS must have all environment variables malloc'ed, because
low-level libc functions that launch subsidiary processes rely low-level libc functions that launch subsidiary processes rely
on that. */ on that. */
pwd_var = xmalloc (i + 6); pwd_var = xmalloc (i + 5);
#else #else
pwd_var = alloca (i + 6); pwd_var = alloca (i + 5);
#endif #endif
temp = pwd_var + 4; temp = pwd_var + 4;
memcpy (pwd_var, "PWD=", 4); memcpy (pwd_var, "PWD=", 4);
memcpy (temp, SDATA (current_dir), i); strcpy (temp, SSDATA (current_dir));
if (!IS_DIRECTORY_SEP (temp[i - 1])) temp[i++] = DIRECTORY_SEP;
temp[i] = 0;
#ifndef DOS_NT #ifndef DOS_NT
/* We can't signal an Elisp error here; we're in a vfork. Since /* We can't signal an Elisp error here; we're in a vfork. Since
......
...@@ -504,6 +504,10 @@ get a current directory to run processes in. */) ...@@ -504,6 +504,10 @@ get a current directory to run processes in. */)
return Ffile_name_directory (filename); return Ffile_name_directory (filename);
} }
/* Maximum number of bytes that DST will be longer than SRC
in file_name_as_directory. This occurs when SRCLEN == 0. */
enum { file_name_as_directory_slop = 2 };
/* Convert from file name SRC of length SRCLEN to directory name in /* Convert from file name SRC of length SRCLEN to directory name in
DST. MULTIBYTE non-zero means the file name in SRC is a multibyte DST. MULTIBYTE non-zero means the file name in SRC is a multibyte
string. On UNIX, just make sure there is a terminating /. Return 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,14 +525,10 @@ file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen,
return 2; return 2;
} }
strcpy (dst, src); memcpy (dst, src, srclen);
if (!IS_DIRECTORY_SEP (dst[srclen - 1])) if (!IS_DIRECTORY_SEP (dst[srclen - 1]))
{ dst[srclen++] = DIRECTORY_SEP;
dst[srclen] = DIRECTORY_SEP; dst[srclen] = 0;
dst[srclen + 1] = '\0';
srclen++;
}
#ifdef DOS_NT #ifdef DOS_NT
dostounix_filename (dst, multibyte); dostounix_filename (dst, multibyte);
#endif #endif
...@@ -547,7 +547,8 @@ For a Unix-syntax file name, just appends a slash. */) ...@@ -547,7 +547,8 @@ For a Unix-syntax file name, just appends a slash. */)
{ {
char *buf; char *buf;
ptrdiff_t length; ptrdiff_t length;
Lisp_Object handler; Lisp_Object handler, val;
USE_SAFE_ALLOCA;
CHECK_STRING (file); CHECK_STRING (file);
if (NILP (file)) if (NILP (file))
...@@ -569,10 +570,12 @@ For a Unix-syntax file name, just appends a slash. */) ...@@ -569,10 +570,12 @@ For a Unix-syntax file name, just appends a slash. */)
if (!NILP (Vw32_downcase_file_names)) if (!NILP (Vw32_downcase_file_names))
file = Fdowncase (file); file = Fdowncase (file);
#endif #endif
buf = alloca (SBYTES (file) + 10); buf = SAFE_ALLOCA (SBYTES (file) + file_name_as_directory_slop + 1);
length = file_name_as_directory (buf, SSDATA (file), SBYTES (file), length = file_name_as_directory (buf, SSDATA (file), SBYTES (file),
STRING_MULTIBYTE (file)); STRING_MULTIBYTE (file));
return make_specified_string (buf, -1, length, STRING_MULTIBYTE (file)); val = make_specified_string (buf, -1, length, STRING_MULTIBYTE (file));
SAFE_FREE ();
return val;
} }
/* Convert from directory name SRC of length SRCLEN to file name in /* Convert from directory name SRC of length SRCLEN to file name in
...@@ -584,18 +587,17 @@ static ptrdiff_t ...@@ -584,18 +587,17 @@ static ptrdiff_t
directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte) directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte)
{ {
/* Process as Unix format: just remove any final slash. /* Process as Unix format: just remove any final slash.
But leave "/" unchanged; do not change it to "". */ But leave "/" and "//" unchanged. */
strcpy (dst, src); while (srclen > 1
if (srclen > 1
&& IS_DIRECTORY_SEP (dst[srclen - 1])
#ifdef DOS_NT #ifdef DOS_NT
&& !IS_ANY_SEP (dst[srclen - 2]) && !IS_ANY_SEP (src[srclen - 2])
#endif #endif
) && IS_DIRECTORY_SEP (src[srclen - 1])
{ && ! (srclen == 2 && IS_DIRECTORY_SEP (src[0])))
dst[srclen - 1] = 0;
srclen--; srclen--;
}
memcpy (dst, src, srclen);
dst[srclen] = 0;
#ifdef DOS_NT #ifdef DOS_NT
dostounix_filename (dst, multibyte); dostounix_filename (dst, multibyte);
#endif #endif
...@@ -613,7 +615,8 @@ In Unix-syntax, this function just removes the final slash. */) ...@@ -613,7 +615,8 @@ In Unix-syntax, this function just removes the final slash. */)
{ {
char *buf; char *buf;
ptrdiff_t length; ptrdiff_t length;
Lisp_Object handler; Lisp_Object handler, val;
USE_SAFE_ALLOCA;
CHECK_STRING (directory); CHECK_STRING (directory);
...@@ -636,10 +639,12 @@ In Unix-syntax, this function just removes the final slash. */) ...@@ -636,10 +639,12 @@ In Unix-syntax, this function just removes the final slash. */)
if (!NILP (Vw32_downcase_file_names)) if (!NILP (Vw32_downcase_file_names))
directory = Fdowncase (directory); directory = Fdowncase (directory);
#endif #endif
buf = alloca (SBYTES (directory) + 20); buf = SAFE_ALLOCA (SBYTES (directory) + 1);
length = directory_file_name (buf, SSDATA (directory), SBYTES (directory), length = directory_file_name (buf, SSDATA (directory), SBYTES (directory),
STRING_MULTIBYTE (directory)); STRING_MULTIBYTE (directory));
return make_specified_string (buf, -1, length, STRING_MULTIBYTE (directory)); val = make_specified_string (buf, -1, length, STRING_MULTIBYTE (directory));
SAFE_FREE ();
return val;
} }
static const char make_temp_name_tbl[64] = static const char make_temp_name_tbl[64] =
...@@ -837,6 +842,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) ...@@ -837,6 +842,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
Lisp_Object handler, result, handled_name; Lisp_Object handler, result, handled_name;
bool multibyte; bool multibyte;
Lisp_Object hdir; Lisp_Object hdir;
USE_SAFE_ALLOCA;
CHECK_STRING (name); CHECK_STRING (name);
...@@ -1011,11 +1017,11 @@ filesystem tree, not (expand-file-name ".." dirname). */) ...@@ -1011,11 +1017,11 @@ filesystem tree, not (expand-file-name ".." dirname). */)
|| (p[2] == '.' && (IS_DIRECTORY_SEP (p[3]) || (p[2] == '.' && (IS_DIRECTORY_SEP (p[3])
|| p[3] == 0)))) || p[3] == 0))))
lose = 1; lose = 1;
/* We want to replace multiple `/' in a row with a single /* Replace multiple slashes with a single one, except
slash. */ leave leading "//" alone. */
else if (p > nm else if (IS_DIRECTORY_SEP (p[0])
&& IS_DIRECTORY_SEP (p[0]) && IS_DIRECTORY_SEP (p[1])
&& IS_DIRECTORY_SEP (p[1])) && (p != nm || IS_DIRECTORY_SEP (p[2])))
lose = 1; lose = 1;
p++; p++;
} }
...@@ -1098,10 +1104,11 @@ filesystem tree, not (expand-file-name ".." dirname). */) ...@@ -1098,10 +1104,11 @@ filesystem tree, not (expand-file-name ".." dirname). */)
else /* ~user/filename */ else /* ~user/filename */
{ {
char *o, *p; char *o, *p;
for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)); p++); for (p = nm; *p && !IS_DIRECTORY_SEP (*p); p++)
o = alloca (p - nm + 1); continue;
o = SAFE_ALLOCA (p - nm + 1);
memcpy (o, nm, p - nm); memcpy (o, nm, p - nm);
o [p - nm] = 0; o[p - nm] = 0;
block_input (); block_input ();
pw = getpwnam (o + 1); pw = getpwnam (o + 1);
...@@ -1217,7 +1224,8 @@ filesystem tree, not (expand-file-name ".." dirname). */) ...@@ -1217,7 +1224,8 @@ filesystem tree, not (expand-file-name ".." dirname). */)
if (!IS_DIRECTORY_SEP (nm[0])) if (!IS_DIRECTORY_SEP (nm[0]))
{ {
ptrdiff_t newlen = strlen (newdir); ptrdiff_t newlen = strlen (newdir);
char *tmp = alloca (newlen + strlen (nm) + 2); char *tmp = alloca (newlen + file_name_as_directory_slop
+ strlen (nm) + 1);
file_name_as_directory (tmp, newdir, newlen, multibyte); file_name_as_directory (tmp, newdir, newlen, multibyte);
strcat (tmp, nm); strcat (tmp, nm);
nm = tmp; nm = tmp;
...@@ -1271,31 +1279,18 @@ filesystem tree, not (expand-file-name ".." dirname). */) ...@@ -1271,31 +1279,18 @@ filesystem tree, not (expand-file-name ".." dirname). */)
if (newdir) if (newdir)
{ {
/* Get rid of any slash at the end of newdir, unless newdir is /* Ignore any slash at the end of newdir, unless newdir is
just / or // (an incomplete UNC name). */ just "/" or "//". */
length = strlen (newdir); length = strlen (newdir);
tlen = length + 1; while (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1])
if (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1]) && ! (length == 2 && IS_DIRECTORY_SEP (newdir[0])))
#ifdef WINDOWSNT
&& !(length == 2 && IS_DIRECTORY_SEP (newdir[0]))
#endif
)
{
char *temp = alloca (length);
memcpy (temp, newdir, length - 1);
temp[length - 1] = 0;
length--; length--;
newdir = temp;
}
} }
else else
{
length = 0; length = 0;
tlen = 0;
}
/* Now concatenate the directory and name to new space in the stack frame. */ /* Now concatenate the directory and name to new space in the stack frame. */
tlen += strlen (nm) + 1; tlen = length + file_name_as_directory_slop + strlen (nm) + 1;
#ifdef DOS_NT #ifdef DOS_NT
/* Reserve space for drive specifier and escape prefix, since either /* Reserve space for drive specifier and escape prefix, since either
or both may need to be inserted. (The Microsoft x86 compiler or both may need to be inserted. (The Microsoft x86 compiler
...@@ -1303,7 +1298,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) ...@@ -1303,7 +1298,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
target = alloca (tlen + 4); target = alloca (tlen + 4);
target += 4; target += 4;
#else /* not DOS_NT */ #else /* not DOS_NT */
target = alloca (tlen); target = SAFE_ALLOCA (tlen);
#endif /* not DOS_NT */ #endif /* not DOS_NT */
*target = 0; *target = 0;
...@@ -1320,7 +1315,10 @@ filesystem tree, not (expand-file-name ".." dirname). */) ...@@ -1320,7 +1315,10 @@ filesystem tree, not (expand-file-name ".." dirname). */)
if (!(drive && nm[0] && IS_DIRECTORY_SEP (newdir[0]) if (!(drive && nm[0] && IS_DIRECTORY_SEP (newdir[0])
&& newdir[1] == '\0')) && newdir[1] == '\0'))
#endif #endif
strcpy (target, newdir); {
memcpy (target, newdir, length);
target[length] = 0;
}
} }
else else
file_name_as_directory (target, newdir, length, multibyte); file_name_as_directory (target, newdir, length, multibyte);
...@@ -1380,8 +1378,9 @@ filesystem tree, not (expand-file-name ".." dirname). */) ...@@ -1380,8 +1378,9 @@ filesystem tree, not (expand-file-name ".." dirname). */)
++o; ++o;
p += 3; p += 3;
} }
else if (p > target && IS_DIRECTORY_SEP (p[1])) else if (IS_DIRECTORY_SEP (p[1])
/* Collapse multiple `/' in a row. */ && (p != target || IS_DIRECTORY_SEP (p[2])))
/* Collapse multiple "/", except leave leading "//" alone. */
p++; p++;
else else
{ {
...@@ -1429,11 +1428,12 @@ filesystem tree, not (expand-file-name ".." dirname). */) ...@@ -1429,11 +1428,12 @@ filesystem tree, not (expand-file-name ".." dirname). */)
{ {
handled_name = call3 (handler, Qexpand_file_name, handled_name = call3 (handler, Qexpand_file_name,
result, default_directory); result, default_directory);
if (STRINGP (handled_name)) if (! STRINGP (handled_name))
return handled_name;
error ("Invalid handler in `file-name-handler-alist'"); error ("Invalid handler in `file-name-handler-alist'");
result = handled_name;
} }
SAFE_FREE ();
return result; return result;
} }
......
...@@ -1408,22 +1408,9 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) ...@@ -1408,22 +1408,9 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
function. The argument list is protected by the caller, so all function. The argument list is protected by the caller, so all
we really have to worry about is buffer. */ we really have to worry about is buffer. */
{ {
struct gcpro gcpro1, gcpro2; struct gcpro gcpro1;
GCPRO1 (buffer);
current_dir = BVAR (current_buffer, directory); current_dir = encode_current_directory ();
GCPRO2 (buffer, current_dir);
current_dir = Funhandled_file_name_directory (current_dir);
if (NILP (current_dir))
/* If the file name handler says that current_dir is unreachable, use
a sensible default. */
current_dir = build_string ("~/");
current_dir = expand_and_dir_to_file (current_dir, Qnil);
if (NILP (Ffile_accessible_directory_p (current_dir)))
report_file_error ("Setting current directory",
BVAR (current_buffer, directory));
UNGCPRO; UNGCPRO;
} }
...@@ -1670,7 +1657,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) ...@@ -1670,7 +1657,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
bool pty_flag = 0; bool pty_flag = 0;
char pty_name[PTY_NAME_SIZE]; char pty_name[PTY_NAME_SIZE];
Lisp_Object lisp_pty_name = Qnil; Lisp_Object lisp_pty_name = Qnil;
Lisp_Object encoded_current_dir;
inchannel = outchannel = -1; inchannel = outchannel = -1;
...@@ -1735,15 +1721,13 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) ...@@ -1735,15 +1721,13 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
/* This may signal an error. */ /* This may signal an error. */
setup_process_coding_systems (process); setup_process_coding_systems (process);
encoded_current_dir = ENCODE_FILE (current_dir);
block_input (); block_input ();
block_child_signal (); block_child_signal ();
#ifndef WINDOWSNT #ifndef WINDOWSNT
/* vfork, and prevent local vars from being clobbered by the vfork. */ /* vfork, and prevent local vars from being clobbered by the vfork. */
{ {
Lisp_Object volatile encoded_current_dir_volatile = encoded_current_dir; Lisp_Object volatile current_dir_volatile = current_dir;
Lisp_Object volatile lisp_pty_name_volatile = lisp_pty_name; Lisp_Object volatile lisp_pty_name_volatile = lisp_pty_name;
char **volatile new_argv_volatile = new_argv; char **volatile new_argv_volatile = new_argv;
int volatile forkin_volatile = forkin; int volatile forkin_volatile = forkin;
...@@ -1752,7 +1736,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) ...@@ -1752,7 +1736,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
pid = vfork (); pid = vfork ();
encoded_current_dir = encoded_current_dir_volatile; current_dir = current_dir_volatile;
lisp_pty_name = lisp_pty_name_volatile; lisp_pty_name = lisp_pty_name_volatile;
new_argv = new_argv_volatile; new_argv = new_argv_volatile;
forkin = forkin_volatile; forkin = forkin_volatile;
...@@ -1864,11 +1848,9 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) ...@@ -1864,11 +1848,9 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
if (pty_flag) if (pty_flag)
child_setup_tty (xforkout); child_setup_tty (xforkout);
#ifdef WINDOWSNT #ifdef WINDOWSNT
pid = child_setup (xforkin, xforkout, xforkout, pid = child_setup (xforkin, xforkout, xforkout, new_argv, 1, current_dir);
new_argv, 1, encoded_current_dir);
#else /* not WINDOWSNT */ #else /* not WINDOWSNT */
child_setup (xforkin, xforkout, xforkout, child_setup (xforkin, xforkout, xforkout, new_argv, 1, current_dir);
new_argv, 1, encoded_current_dir);
#endif /* not WINDOWSNT */ #endif /* not WINDOWSNT */
} }
......
...@@ -218,6 +218,7 @@ enum ...@@ -218,6 +218,7 @@ enum
extern void block_child_signal (void); extern void block_child_signal (void);
extern void unblock_child_signal (void); extern void unblock_child_signal (void);
extern Lisp_Object encode_current_directory (void);
extern void record_kill_process (struct Lisp_Process *, Lisp_Object); extern void record_kill_process (struct Lisp_Process *, Lisp_Object);
/* Defined in sysdep.c. */ /* Defined in sysdep.c. */
......
...@@ -471,10 +471,20 @@ sys_subshell (void) ...@@ -471,10 +471,20 @@ sys_subshell (void)
pid_t pid; pid_t pid;
int status; int status;
struct save_signal saved_handlers[5]; struct save_signal saved_handlers[5];
Lisp_Object dir; char *str = SSDATA (encode_current_directory ());
unsigned char *volatile str_volatile = 0;
unsigned char *str; #ifdef DOS_NT
int len; pid = 0;
#else
{
char *volatile str_volatile = str;
pid = vfork ();
str = str_volatile;
}
#endif
if (pid < 0)
error ("Can't spawn subshell");
saved_handlers[0].code = SIGINT; saved_handlers[0].code = SIGINT;
saved_handlers[1].code = SIGQUIT; saved_handlers[1].code = SIGQUIT;
...@@ -486,31 +496,8 @@ sys_subshell (void) ...@@ -486,31 +496,8 @@ sys_subshell (void)
saved_handlers[3].code = 0; saved_handlers[3].code = 0;
#endif #endif
/* Mentioning current_buffer->buffer would mean including buffer.h,
which somehow wedges the hp compiler. So instead... */
dir = intern ("default-directory");
if (NILP (Fboundp (dir)))
goto xyzzy;
dir = Fsymbol_value (dir);
if (!STRINGP (dir))
goto xyzzy;
dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil);
str_volatile = str = alloca (SCHARS (dir) + 2);
len = SCHARS (dir);
memcpy (str, SDATA (dir), len);
if (str[len - 1] != '/') str[len++] = '/';