Commit 1ef14cb4 authored by Lars Magne Ingebrigtsen's avatar Lars Magne Ingebrigtsen
Browse files

Extend `call-process' to take the `(:file "file")' syntax to redirect

STDOUT to a file.
parent dcb79f20
2011-04-30 Lars Magne Ingebrigtsen <larsi@gnus.org>
* processes.texi (Synchronous Processes): Document the (:file
"/file-name") syntax for `call-process'.
2011-04-23 Juanma Barranquero <lekktu@gmail.com> 2011-04-23 Juanma Barranquero <lekktu@gmail.com>
* windows.texi (Choosing Window): Fix typo. * windows.texi (Choosing Window): Fix typo.
......
...@@ -299,6 +299,9 @@ function returns. ...@@ -299,6 +299,9 @@ function returns.
MS-DOS doesn't support asynchronous subprocesses, so this option doesn't MS-DOS doesn't support asynchronous subprocesses, so this option doesn't
work there. work there.
@item @code{(:file @var{file-name})}
Send the output to the file name specified.
@item @code{(@var{real-destination} @var{error-destination})} @item @code{(@var{real-destination} @var{error-destination})}
Keep the standard output stream separate from the standard error stream; Keep the standard output stream separate from the standard error stream;
deal with the ordinary output as specified by @var{real-destination}, deal with the ordinary output as specified by @var{real-destination},
......
2011-05-01 Lars Magne Ingebrigtsen <larsi@gnus.org>
* sysdep.c (interruptible_wait_for_termination): New function
which is like wait_for_termination, but allows keyboard
interruptions.
* callproc.c (Fcall_process): Add (:file "file") as an option for
the STDOUT buffer.
(Fcall_process_region): Ditto.
2011-04-30 Eli Zaretskii <eliz@gnu.org> 2011-04-30 Eli Zaretskii <eliz@gnu.org>
* dosfns.c (Fint86, Fdos_memget, Fdos_memput): Use `ASIZE (FOO)' * dosfns.c (Fint86, Fdos_memget, Fdos_memput): Use `ASIZE (FOO)'
......
...@@ -156,8 +156,9 @@ DEFUN ("call-process", Fcall_process, Scall_process, 1, MANY, 0, ...@@ -156,8 +156,9 @@ DEFUN ("call-process", Fcall_process, Scall_process, 1, MANY, 0,
doc: /* Call PROGRAM synchronously in separate process. doc: /* Call PROGRAM synchronously in separate process.
The remaining arguments are optional. The remaining arguments are optional.
The program's input comes from file INFILE (nil means `/dev/null'). The program's input comes from file INFILE (nil means `/dev/null').
Insert output in BUFFER before point; t means current buffer; Insert output in BUFFER before point; t means current buffer; nil for BUFFER
nil for BUFFER means discard it; 0 means discard and don't wait. 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.
BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case, BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case,
REAL-BUFFER says what to do with standard output, as above, REAL-BUFFER says what to do with standard output, as above,
while STDERR-FILE says what to do with standard error in the child. while STDERR-FILE says what to do with standard error in the child.
...@@ -196,14 +197,17 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) ...@@ -196,14 +197,17 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
/* File to use for stderr in the child. /* File to use for stderr in the child.
t means use same as standard output. */ t means use same as standard output. */
Lisp_Object error_file; Lisp_Object error_file;
Lisp_Object output_file = Qnil;
#ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */ #ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
char *outf, *tempfile; char *outf, *tempfile;
int outfilefd; int outfilefd;
#endif #endif
int fd_output = -1;
struct coding_system process_coding; /* coding-system of process output */ struct coding_system process_coding; /* coding-system of process output */
struct coding_system argument_coding; /* coding-system of arguments */ struct coding_system argument_coding; /* coding-system of arguments */
/* Set to the return value of Ffind_operation_coding_system. */ /* Set to the return value of Ffind_operation_coding_system. */
Lisp_Object coding_systems; Lisp_Object coding_systems;
int output_to_buffer = 1;
/* Qt denotes that Ffind_operation_coding_system is not yet called. */ /* Qt denotes that Ffind_operation_coding_system is not yet called. */
coding_systems = Qt; coding_systems = Qt;
...@@ -273,9 +277,12 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) ...@@ -273,9 +277,12 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
{ {
buffer = args[2]; buffer = args[2];
/* If BUFFER is a list, its meaning is /* If BUFFER is a list, its meaning is (BUFFER-FOR-STDOUT
(BUFFER-FOR-STDOUT FILE-FOR-STDERR). */ FILE-FOR-STDERR), unless the first element is :file, in which case see
if (CONSP (buffer)) the next paragraph. */
if (CONSP (buffer) &&
(! SYMBOLP (XCAR (buffer)) ||
strcmp (SSDATA (SYMBOL_NAME (XCAR (buffer))), ":file")))
{ {
if (CONSP (XCDR (buffer))) if (CONSP (XCDR (buffer)))
{ {
...@@ -291,6 +298,17 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) ...@@ -291,6 +298,17 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
buffer = XCAR (buffer); buffer = XCAR (buffer);
} }
/* If the buffer is (still) a list, it might be a (:file "file") spec. */
if (CONSP (buffer) &&
SYMBOLP (XCAR (buffer)) &&
! strcmp (SSDATA (SYMBOL_NAME (XCAR (buffer))), ":file"))
{
output_file = Fexpand_file_name (XCAR (XCDR (buffer)),
BVAR (current_buffer, directory));
CHECK_STRING (output_file);
buffer = Qnil;
}
if (!(EQ (buffer, Qnil) if (!(EQ (buffer, Qnil)
|| EQ (buffer, Qt) || EQ (buffer, Qt)
|| INTEGERP (buffer))) || INTEGERP (buffer)))
...@@ -318,11 +336,11 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) ...@@ -318,11 +336,11 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
protected by the caller, so all we really have to worry about is protected by the caller, so all we really have to worry about is
buffer. */ buffer. */
{ {
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
current_dir = BVAR (current_buffer, directory); current_dir = BVAR (current_buffer, directory);
GCPRO4 (infile, buffer, current_dir, error_file); GCPRO5 (infile, buffer, current_dir, error_file, output_file);
current_dir = Funhandled_file_name_directory (current_dir); current_dir = Funhandled_file_name_directory (current_dir);
if (NILP (current_dir)) if (NILP (current_dir))
...@@ -342,6 +360,8 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) ...@@ -342,6 +360,8 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
current_dir = ENCODE_FILE (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))
output_file = ENCODE_FILE (output_file);
UNGCPRO; UNGCPRO;
} }
...@@ -353,6 +373,26 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) ...@@ -353,6 +373,26 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
infile = DECODE_FILE (infile); infile = DECODE_FILE (infile);
report_file_error ("Opening process input file", Fcons (infile, Qnil)); report_file_error ("Opening process input file", Fcons (infile, Qnil));
} }
if (STRINGP (output_file))
{
#ifdef DOS_NT
fd_output = emacs_open (SSDATA (output_file),
O_WRONLY | O_TRUNC | O_CREAT | O_TEXT,
S_IREAD | S_IWRITE);
#else /* not DOS_NT */
fd_output = creat (SSDATA (output_file), 0666);
#endif /* not DOS_NT */
if (fd_output < 0)
{
output_file = DECODE_FILE (output_file);
report_file_error ("Opening process output file",
Fcons (output_file, Qnil));
}
if (STRINGP (error_file) || NILP (error_file))
output_to_buffer = 0;
}
/* Search for program; barf if not found. */ /* Search for program; barf if not found. */
{ {
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
...@@ -413,13 +453,18 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) ...@@ -413,13 +453,18 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
strcat (tempfile, "detmp.XXX"); strcat (tempfile, "detmp.XXX");
mktemp (tempfile); mktemp (tempfile);
outfilefd = creat (tempfile, S_IREAD | S_IWRITE); /* If we're redirecting STDOUT to a file, this is already opened. */
if (outfilefd < 0) if (fd_output < 0)
{ {
emacs_close (filefd); outfilefd = creat (tempfile, S_IREAD | S_IWRITE);
report_file_error ("Opening process output file", if (outfilefd < 0) {
Fcons (build_string (tempfile), Qnil)); emacs_close (filefd);
report_file_error ("Opening process output file",
Fcons (build_string (tempfile), Qnil));
}
} }
else
outfilefd = fd_output;
fd[0] = filefd; fd[0] = filefd;
fd[1] = outfilefd; fd[1] = outfilefd;
#endif /* MSDOS */ #endif /* MSDOS */
...@@ -450,6 +495,8 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) ...@@ -450,6 +495,8 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
struct sigaction sigpipe_action; struct sigaction sigpipe_action;
#endif #endif
if (fd_output >= 0)
fd1 = fd_output;
#if 0 /* Some systems don't have sigblock. */ #if 0 /* Some systems don't have sigblock. */
mask = sigblock (sigmask (SIGCHLD)); mask = sigblock (sigmask (SIGCHLD));
#endif #endif
...@@ -591,6 +638,8 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) ...@@ -591,6 +638,8 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
/* Close most of our fd's, but not fd[0] /* Close most of our fd's, but not fd[0]
since we will use that to read input from. */ since we will use that to read input from. */
emacs_close (filefd); emacs_close (filefd);
if (fd_output >= 0)
emacs_close (fd_output);
if (fd1 >= 0 && fd1 != fd_error) if (fd1 >= 0 && fd1 != fd_error)
emacs_close (fd1); emacs_close (fd1);
} }
...@@ -673,6 +722,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) ...@@ -673,6 +722,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
immediate_quit = 1; immediate_quit = 1;
QUIT; QUIT;
if (output_to_buffer)
{ {
register EMACS_INT nread; register EMACS_INT nread;
int first = 1; int first = 1;
...@@ -802,7 +852,10 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) ...@@ -802,7 +852,10 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
#ifndef MSDOS #ifndef MSDOS
/* Wait for it to terminate, unless it already has. */ /* Wait for it to terminate, unless it already has. */
wait_for_termination (pid); if (output_to_buffer)
wait_for_termination (pid);
else
interruptible_wait_for_termination (pid);
#endif #endif
immediate_quit = 0; immediate_quit = 0;
...@@ -850,8 +903,10 @@ DEFUN ("call-process-region", Fcall_process_region, Scall_process_region, ...@@ -850,8 +903,10 @@ DEFUN ("call-process-region", Fcall_process_region, Scall_process_region,
The remaining arguments are optional. The remaining arguments are optional.
Delete the text if fourth arg DELETE is non-nil. Delete the text if fourth arg DELETE is non-nil.
Insert output in BUFFER before point; t means current buffer; Insert output in BUFFER before point; t means current buffer; nil for
nil for BUFFER means discard it; 0 means discard and don't wait. 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.
BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case, BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case,
REAL-BUFFER says what to do with standard output, as above, REAL-BUFFER says what to do with standard output, as above,
while STDERR-FILE says what to do with standard error in the child. while STDERR-FILE says what to do with standard error in the child.
......
...@@ -3349,6 +3349,7 @@ extern void reset_sys_modes (struct tty_display_info *); ...@@ -3349,6 +3349,7 @@ extern void reset_sys_modes (struct tty_display_info *);
extern void init_all_sys_modes (void); extern void init_all_sys_modes (void);
extern void reset_all_sys_modes (void); extern void reset_all_sys_modes (void);
extern void wait_for_termination (int); extern void wait_for_termination (int);
extern void interruptible_wait_for_termination (int);
extern void flush_pending_output (int); extern void flush_pending_output (int);
extern void child_setup_tty (int); extern void child_setup_tty (int);
extern void setup_pty (int); extern void setup_pty (int);
......
...@@ -301,6 +301,19 @@ int wait_debugging EXTERNALLY_VISIBLE; ...@@ -301,6 +301,19 @@ int wait_debugging EXTERNALLY_VISIBLE;
void void
wait_for_termination (int pid) wait_for_termination (int pid)
{
wait_for_termination_1 (pid, 0);
}
/* Like the above, but allow keyboard interruption. */
void
interruptible_wait_for_termination (int pid)
{
wait_for_termination_1 (pid, 1);
}
void
wait_for_termination_1 (int pid, int interruptible)
{ {
while (1) while (1)
{ {
...@@ -339,6 +352,8 @@ wait_for_termination (int pid) ...@@ -339,6 +352,8 @@ wait_for_termination (int pid)
sigsuspend (&empty_mask); sigsuspend (&empty_mask);
#endif /* not WINDOWSNT */ #endif /* not WINDOWSNT */
#endif /* not BSD_SYSTEM, and not HPUX version >= 6 */ #endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
if (interruptible)
QUIT;
} }
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment