summaryrefslogtreecommitdiff
path: root/src/callproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/callproc.c')
-rw-r--r--src/callproc.c211
1 files changed, 111 insertions, 100 deletions
diff --git a/src/callproc.c b/src/callproc.c
index 30f9dc58d46..91f29bd589b 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -123,8 +123,8 @@ record_kill_process (struct Lisp_Process *p)
/* Clean up when exiting call_process_cleanup. */
-static Lisp_Object
-call_process_kill (Lisp_Object ignored)
+static void
+call_process_kill (void)
{
if (synch_process_fd >= 0)
emacs_close (synch_process_fd);
@@ -136,15 +136,13 @@ call_process_kill (Lisp_Object ignored)
proc.pid = synch_process_pid;
record_kill_process (&proc);
}
-
- return Qnil;
}
/* Clean up when exiting Fcall_process.
On MSDOS, delete the temporary file on any kind of termination.
On Unix, kill the process and any children on termination by signal. */
-static Lisp_Object
+static void
call_process_cleanup (Lisp_Object arg)
{
#ifdef MSDOS
@@ -162,7 +160,7 @@ call_process_cleanup (Lisp_Object arg)
{
ptrdiff_t count = SPECPDL_INDEX ();
kill (-synch_process_pid, SIGINT);
- record_unwind_protect (call_process_kill, make_number (0));
+ record_unwind_protect_void (call_process_kill);
message1 ("Waiting for process to die...(type C-g again to kill it instantly)");
immediate_quit = 1;
QUIT;
@@ -183,8 +181,6 @@ call_process_cleanup (Lisp_Object arg)
if (!(strcmp (SDATA (file), NULL_DEVICE) == 0 || SREF (file, 0) == '\0'))
unlink (SDATA (file));
#endif
-
- return Qnil;
}
#ifdef DOS_NT
@@ -392,7 +388,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
if (NILP (Ffile_accessible_directory_p (current_dir)))
report_file_error ("Setting current directory",
- Fcons (BVAR (current_buffer, directory), Qnil));
+ BVAR (current_buffer, directory));
if (STRING_MULTIBYTE (infile))
infile = ENCODE_FILE (infile);
@@ -409,8 +405,11 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
filefd = emacs_open (SSDATA (infile), O_RDONLY, 0);
if (filefd < 0)
- report_file_error ("Opening process input file",
- Fcons (DECODE_FILE (infile), Qnil));
+ {
+ int open_errno = errno;
+ report_file_errno ("Opening process input file", DECODE_FILE (infile),
+ open_errno);
+ }
if (STRINGP (output_file))
{
@@ -422,7 +421,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
int open_errno = errno;
output_file = DECODE_FILE (output_file);
report_file_errno ("Opening process output file",
- Fcons (output_file, Qnil), open_errno);
+ output_file, open_errno);
}
if (STRINGP (error_file) || NILP (error_file))
output_to_buffer = 0;
@@ -440,8 +439,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
{
int openp_errno = errno;
emacs_close (filefd);
- report_file_errno ("Searching for program",
- Fcons (args[0], Qnil), openp_errno);
+ report_file_errno ("Searching for program", args[0], openp_errno);
}
}
@@ -506,7 +504,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
int open_errno = errno;
emacs_close (filefd);
report_file_errno ("Opening process output file",
- Fcons (build_string (tempfile), Qnil), open_errno);
+ build_string (tempfile), open_errno);
}
}
else
@@ -524,7 +522,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
{
#ifndef MSDOS
int fd[2];
- if (pipe2 (fd, O_CLOEXEC) != 0)
+ if (emacs_pipe (fd) != 0)
{
int pipe_errno = errno;
emacs_close (filefd);
@@ -563,8 +561,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
error_file = build_string (NULL_DEVICE);
else if (STRINGP (error_file))
error_file = DECODE_FILE (error_file);
- report_file_errno ("Cannot redirect stderr",
- Fcons (error_file, Qnil), open_errno);
+ report_file_errno ("Cannot redirect stderr", error_file, open_errno);
}
#ifdef MSDOS /* MW, July 1993 */
@@ -596,8 +593,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
unlink (tempfile);
emacs_close (filefd);
report_file_errno ("Cannot re-open temporary file",
- Fcons (build_string (tempfile), Qnil),
- open_errno);
+ build_string (tempfile), open_errno);
}
}
else
@@ -935,7 +931,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
return make_number (WEXITSTATUS (status));
}
-static Lisp_Object
+static void
delete_temp_file (Lisp_Object name)
{
/* Suppress jka-compr handling, etc. */
@@ -957,44 +953,18 @@ delete_temp_file (Lisp_Object name)
internal_delete_file (name);
#endif
unbind_to (count, Qnil);
- return Qnil;
}
-DEFUN ("call-process-region", Fcall_process_region, Scall_process_region,
- 3, MANY, 0,
- doc: /* Send text from START to END to a synchronous process running PROGRAM.
-The remaining arguments are optional.
-Delete the text if fourth arg DELETE is non-nil.
-
-Insert output in BUFFER before point; t means current buffer; nil for
- BUFFER means discard it; 0 means discard and don't wait; and `(:file
- FILE)', where FILE is a file name string, means that it should be
- written to that file (if the file already exists it is overwritten).
-BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case,
-REAL-BUFFER says what to do with standard output, as above,
-while STDERR-FILE says what to do with standard error in the child.
-STDERR-FILE may be nil (discard standard error output),
-t (mix it with ordinary output), or a file name string.
-
-Sixth arg DISPLAY non-nil means redisplay buffer as output is inserted.
-Remaining args are passed to PROGRAM at startup as command args.
+/* Create a temporary file suitable for storing the input data of
+ call-process-region. NARGS and ARGS are the same as for
+ call-process-region. */
-If BUFFER is 0, `call-process-region' returns immediately with value nil.
-Otherwise it waits for PROGRAM to terminate
-and returns a numeric exit status or a signal description string.
-If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.
-
-usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &rest ARGS) */)
- (ptrdiff_t nargs, Lisp_Object *args)
+static Lisp_Object
+create_temp_file (ptrdiff_t nargs, Lisp_Object *args)
{
struct gcpro gcpro1;
Lisp_Object filename_string;
- register Lisp_Object start, end;
- ptrdiff_t count = SPECPDL_INDEX ();
- /* Qt denotes we have not yet called Ffind_operation_coding_system. */
- Lisp_Object coding_systems;
- Lisp_Object val, *args2;
- ptrdiff_t i;
+ Lisp_Object val, start, end;
Lisp_Object tmpdir;
if (STRINGP (Vtemporary_file_directory))
@@ -1016,9 +986,7 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
}
{
- USE_SAFE_ALLOCA;
Lisp_Object pattern = Fexpand_file_name (Vtemp_file_name_pattern, tmpdir);
- Lisp_Object encoded_tem;
char *tempfile;
#ifdef WINDOWSNT
@@ -1036,39 +1004,30 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
}
#endif
- encoded_tem = ENCODE_FILE (pattern);
- tempfile = SAFE_ALLOCA (SBYTES (encoded_tem) + 1);
- memcpy (tempfile, SDATA (encoded_tem), SBYTES (encoded_tem) + 1);
- coding_systems = Qt;
+ filename_string = Fcopy_sequence (ENCODE_FILE (pattern));
+ GCPRO1 (filename_string);
+ tempfile = SSDATA (filename_string);
-#if defined HAVE_MKOSTEMP || defined HAVE_MKSTEMP
{
- int fd, open_errno;
+ int fd;
- block_input ();
-# ifdef HAVE_MKOSTEMP
+#ifdef HAVE_MKOSTEMP
fd = mkostemp (tempfile, O_CLOEXEC);
-# else
+#elif defined HAVE_MKSTEMP
fd = mkstemp (tempfile);
-# endif
- open_errno = errno;
- unblock_input ();
+#else
+ errno = EEXIST;
+ mktemp (tempfile);
+ /* INT_MAX denotes success, because close (INT_MAX) does nothing. */
+ fd = *tempfile ? INT_MAX : -1;
+#endif
if (fd < 0)
- report_file_errno ("Failed to open temporary file",
- Fcons (build_string (tempfile), Qnil), open_errno);
+ report_file_error ("Failed to open temporary file using pattern",
+ pattern);
emacs_close (fd);
}
-#else
- errno = EEXIST;
- mktemp (tempfile);
- if (!*tempfile)
- report_file_error ("Failed to open temporary file using pattern",
- Fcons (pattern, Qnil));
-#endif
- filename_string = build_string (tempfile);
- GCPRO1 (filename_string);
- SAFE_FREE ();
+ record_unwind_protect (delete_temp_file, filename_string);
}
start = args[0];
@@ -1080,10 +1039,12 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
val = Qraw_text;
else
{
+ Lisp_Object coding_systems;
+ Lisp_Object *args2;
USE_SAFE_ALLOCA;
SAFE_NALLOCA (args2, 1, nargs + 1);
args2[0] = Qcall_process_region;
- for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
+ memcpy (args2 + 1, args, nargs * sizeof *args);
coding_systems = Ffind_operation_coding_system (nargs + 1, args2);
val = CONSP (coding_systems) ? XCDR (coding_systems) : Qnil;
SAFE_FREE ();
@@ -1105,7 +1066,57 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
/* Note that Fcall_process takes care of binding
coding-system-for-read. */
- record_unwind_protect (delete_temp_file, filename_string);
+ RETURN_UNGCPRO (filename_string);
+}
+
+DEFUN ("call-process-region", Fcall_process_region, Scall_process_region,
+ 3, MANY, 0,
+ doc: /* Send text from START to END to a synchronous process running PROGRAM.
+The remaining arguments are optional.
+Delete the text if fourth arg DELETE is non-nil.
+
+Insert output in BUFFER before point; t means current buffer; nil for
+ BUFFER means discard it; 0 means discard and don't wait; and `(:file
+ FILE)', where FILE is a file name string, means that it should be
+ written to that file (if the file already exists it is overwritten).
+BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case,
+REAL-BUFFER says what to do with standard output, as above,
+while STDERR-FILE says what to do with standard error in the child.
+STDERR-FILE may be nil (discard standard error output),
+t (mix it with ordinary output), or a file name string.
+
+Sixth arg DISPLAY non-nil means redisplay buffer as output is inserted.
+Remaining args are passed to PROGRAM at startup as command args.
+
+If BUFFER is 0, `call-process-region' returns immediately with value nil.
+Otherwise it waits for PROGRAM to terminate
+and returns a numeric exit status or a signal description string.
+If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.
+
+usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &rest ARGS) */)
+ (ptrdiff_t nargs, Lisp_Object *args)
+{
+ struct gcpro gcpro1;
+ Lisp_Object infile;
+ ptrdiff_t count = SPECPDL_INDEX ();
+ Lisp_Object start = args[0];
+ Lisp_Object end = args[1];
+ bool empty_input;
+
+ if (STRINGP (start))
+ empty_input = SCHARS (start) == 0;
+ else if (NILP (start))
+ empty_input = BEG == Z;
+ else
+ {
+ validate_region (&args[0], &args[1]);
+ start = args[0];
+ end = args[1];
+ empty_input = XINT (start) == XINT (end);
+ }
+
+ infile = empty_input ? Qnil : create_temp_file (nargs, args);
+ GCPRO1 (infile);
if (nargs > 3 && !NILP (args[3]))
Fdelete_region (start, end);
@@ -1120,7 +1131,7 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
args[0] = args[2];
nargs = 2;
}
- args[1] = filename_string;
+ args[1] = infile;
RETURN_UNGCPRO (unbind_to (count, Fcall_process (nargs, args)));
}
@@ -1185,9 +1196,11 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
#ifdef WINDOWSNT
int cpid;
HANDLE handles[3];
-#endif /* WINDOWSNT */
+#else
+ int exec_errno;
pid_t pid = getpid ();
+#endif /* WINDOWSNT */
/* Note that use of alloca is always safe here. It's obvious for systems
that do not have true vfork or that have true (stack) alloca.
@@ -1346,32 +1359,27 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
}
#ifndef MSDOS
- emacs_close (0);
- emacs_close (1);
- emacs_close (2);
-
- /* Redirect file descriptors and clear FD_CLOEXEC on the redirected ones. */
+ /* Redirect file descriptors and clear the close-on-exec flag on the
+ redirected ones. IN, OUT, and ERR are close-on-exec so they
+ need not be closed explicitly. */
dup2 (in, 0);
dup2 (out, 1);
dup2 (err, 2);
- emacs_close (in);
- if (out != in)
- emacs_close (out);
- if (err != in && err != out)
- emacs_close (err);
-
setpgid (0, 0);
tcsetpgrp (0, pid);
execve (new_argv[0], new_argv, env);
+ exec_errno = errno;
- /* Don't output the program name here, as it can be arbitrarily long,
- and a long write from a vforked child to its parent can cause a
- deadlock. */
- emacs_perror ("child process");
+ /* Avoid deadlock if the child's perror writes to a full pipe; the
+ pipe's reader is the parent, but with vfork the parent can't
+ run until the child exits. Truncate the diagnostic instead. */
+ fcntl (STDERR_FILENO, F_SETFL, O_NONBLOCK);
- _exit (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
+ errno = exec_errno;
+ emacs_perror (new_argv[0]);
+ _exit (exec_errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
#else /* MSDOS */
pid = run_msdos_command (new_argv, pwd_var + 4, in, out, err, env);
@@ -1386,7 +1394,8 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
#ifndef WINDOWSNT
/* Move the file descriptor FD so that its number is not less than MINFD.
- If the file descriptor is moved at all, the original is freed. */
+ If the file descriptor is moved at all, the original is closed on MSDOS,
+ but not elsewhere as the caller will close it anyway. */
static int
relocate_fd (int fd, int minfd)
{
@@ -1400,7 +1409,9 @@ relocate_fd (int fd, int minfd)
emacs_perror ("while setting up child");
_exit (EXIT_CANCELED);
}
+#ifdef MSDOS
emacs_close (fd);
+#endif
return new;
}
}