summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ChangeLog11
-rw-r--r--src/callproc.c86
2 files changed, 59 insertions, 38 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index efa404afc2f..da15a612a19 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,14 @@
+2012-11-28 Paul Eggert <eggert@cs.ucla.edu>
+
+ * callproc.c (Fcall_process): Fix vfork portability problems.
+ Do not assume that fd[0], count, filefd, and save_environ survive
+ vfork. Fix bug whereby wrong errno value could be reported for
+ pipe failure. Some minor cleanups, too, as follows. Move buf and
+ bufsize to the context where they're needed. Change new_argv to
+ be of type char **, as this is more convenient and avoids casts.
+ (CALLPROC_BUFFER_SIZE_MIN, CALLPROC_BUFFER_SIZE_MAX):
+ Now local constants, not macros.
+
2012-11-18 Kenichi Handa <handa@gnu.org>
* font.c (font_unparse_xlfd): Fix previous change. Keep "const"
diff --git a/src/callproc.c b/src/callproc.c
index c9a504746b3..bba1c043b4c 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -183,16 +183,11 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
{
Lisp_Object infile, buffer, current_dir, path, cleanup_info_tail;
bool display_p;
- int fd[2];
- int filefd;
-#define CALLPROC_BUFFER_SIZE_MIN (16 * 1024)
-#define CALLPROC_BUFFER_SIZE_MAX (4 * CALLPROC_BUFFER_SIZE_MIN)
- char buf[CALLPROC_BUFFER_SIZE_MAX];
- int bufsize = CALLPROC_BUFFER_SIZE_MIN;
+ int fd0, fd1, filefd;
ptrdiff_t count = SPECPDL_INDEX ();
USE_SAFE_ALLOCA;
- register const unsigned char **new_argv;
+ char **new_argv;
/* File to use for stderr in the child.
t means use same as standard output. */
Lisp_Object error_file;
@@ -432,12 +427,12 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
}
UNGCPRO;
for (i = 4; i < nargs; i++)
- new_argv[i - 3] = SDATA (args[i]);
+ new_argv[i - 3] = SSDATA (args[i]);
new_argv[i - 3] = 0;
}
else
new_argv[1] = 0;
- new_argv[0] = SDATA (path);
+ new_argv[0] = SSDATA (path);
#ifdef MSDOS /* MW, July 1993 */
@@ -466,29 +461,35 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
}
else
outfilefd = fd_output;
- fd[0] = filefd;
- fd[1] = outfilefd;
+ fd0 = filefd;
+ fd1 = outfilefd;
#endif /* MSDOS */
if (INTEGERP (buffer))
- fd[1] = emacs_open (NULL_DEVICE, O_WRONLY, 0), fd[0] = -1;
+ {
+ fd0 = -1;
+ fd1 = emacs_open (NULL_DEVICE, O_WRONLY, 0);
+ }
else
{
#ifndef MSDOS
- errno = 0;
+ int fd[2];
if (pipe (fd) == -1)
{
+ int pipe_errno = errno;
emacs_close (filefd);
+ errno = pipe_errno;
report_file_error ("Creating process pipe", Qnil);
}
+ fd0 = fd[0];
+ fd1 = fd[1];
#endif
}
{
/* child_setup must clobber environ in systems with true vfork.
Protect it from permanent change. */
- register char **save_environ = environ;
- register int fd1 = fd[1];
+ char **save_environ = environ;
int fd_error = fd1;
if (fd_output >= 0)
@@ -520,8 +521,8 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
if (fd_error < 0)
{
emacs_close (filefd);
- if (fd[0] != filefd)
- emacs_close (fd[0]);
+ if (fd0 != filefd)
+ emacs_close (fd0);
if (fd1 >= 0)
emacs_close (fd1);
#ifdef MSDOS
@@ -538,8 +539,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
/* Note that on MSDOS `child_setup' actually returns the child process
exit status, not its PID, so we assign it to `synch_process_retcode'
below. */
- pid = child_setup (filefd, outfilefd, fd_error, (char **) new_argv,
- 0, current_dir);
+ pid = child_setup (filefd, outfilefd, fd_error, new_argv, 0, current_dir);
/* Record that the synchronous process exited and note its
termination status. */
@@ -559,8 +559,8 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
{
/* Since CRLF is converted to LF within `decode_coding', we
can always open a file with binary mode. */
- fd[0] = emacs_open (tempfile, O_RDONLY | O_BINARY, 0);
- if (fd[0] < 0)
+ fd0 = emacs_open (tempfile, O_RDONLY | O_BINARY, 0);
+ if (fd0 < 0)
{
unlink (tempfile);
emacs_close (filefd);
@@ -569,11 +569,10 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
}
}
else
- fd[0] = -1; /* We are not going to read from tempfile. */
+ fd0 = -1; /* We are not going to read from tempfile. */
#else /* not MSDOS */
#ifdef WINDOWSNT
- pid = child_setup (filefd, fd1, fd_error, (char **) new_argv,
- 0, current_dir);
+ pid = child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir);
#else /* not WINDOWSNT */
block_input ();
@@ -586,11 +585,15 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
bool volatile display_p_volatile = display_p;
bool volatile output_to_buffer_volatile = output_to_buffer;
bool volatile sa_must_free_volatile = sa_must_free;
+ int volatile fd0_volatile = fd0;
int volatile fd1_volatile = fd1;
int volatile fd_error_volatile = fd_error;
int volatile fd_output_volatile = fd_output;
+ int volatile filefd_volatile = filefd;
+ ptrdiff_t volatile count_volatile = count;
ptrdiff_t volatile sa_count_volatile = sa_count;
- unsigned char const **volatile new_argv_volatile = new_argv;
+ char **volatile new_argv_volatile = new_argv;
+ char **volatile new_save_environ = save_environ;
pid = vfork ();
@@ -598,27 +601,30 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
coding_systems = coding_systems_volatile;
current_dir = current_dir_volatile;
display_p = display_p_volatile;
+ output_to_buffer = output_to_buffer_volatile;
+ sa_must_free = sa_must_free_volatile;
+ fd0 = fd0_volatile;
fd1 = fd1_volatile;
fd_error = fd_error_volatile;
fd_output = fd_output_volatile;
- output_to_buffer = output_to_buffer_volatile;
- sa_must_free = sa_must_free_volatile;
+ filefd = filefd_volatile;
+ count = count_volatile;
sa_count = sa_count_volatile;
new_argv = new_argv_volatile;
+ save_environ = new_save_environ;
}
if (pid == 0)
{
- if (fd[0] >= 0)
- emacs_close (fd[0]);
+ if (fd0 >= 0)
+ emacs_close (fd0);
setsid ();
/* Emacs ignores SIGPIPE, but the child should not. */
signal (SIGPIPE, SIG_DFL);
- child_setup (filefd, fd1, fd_error, (char **) new_argv,
- 0, current_dir);
+ child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir);
}
unblock_input ();
@@ -632,7 +638,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
environ = save_environ;
- /* Close most of our fd's, but not fd[0]
+ /* Close most of our file descriptors, but not fd0
since we will use that to read input from. */
emacs_close (filefd);
if (fd_output >= 0)
@@ -643,15 +649,15 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
if (pid < 0)
{
- if (fd[0] >= 0)
- emacs_close (fd[0]);
+ if (fd0 >= 0)
+ emacs_close (fd0);
report_file_error ("Doing vfork", Qnil);
}
if (INTEGERP (buffer))
{
- if (fd[0] >= 0)
- emacs_close (fd[0]);
+ if (fd0 >= 0)
+ emacs_close (fd0);
return Qnil;
}
@@ -666,7 +672,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
#endif /* not MSDOS */
record_unwind_protect (call_process_cleanup,
Fcons (Fcurrent_buffer (),
- Fcons (INTEGER_TO_CONS (fd[0]),
+ Fcons (INTEGER_TO_CONS (fd0),
cleanup_info_tail)));
if (BUFFERP (buffer))
@@ -723,6 +729,10 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
if (output_to_buffer)
{
+ enum { CALLPROC_BUFFER_SIZE_MIN = 16 * 1024 };
+ enum { CALLPROC_BUFFER_SIZE_MAX = 4 * CALLPROC_BUFFER_SIZE_MIN };
+ char buf[CALLPROC_BUFFER_SIZE_MAX];
+ int bufsize = CALLPROC_BUFFER_SIZE_MIN;
int nread;
bool first = 1;
EMACS_INT total_read = 0;
@@ -739,7 +749,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
nread = carryover;
while (nread < bufsize - 1024)
{
- int this_read = emacs_read (fd[0], buf + nread,
+ int this_read = emacs_read (fd0, buf + nread,
bufsize - nread);
if (this_read < 0)