X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/1f41ee56ace98fe0d5f288c97ddb73870befed45..2bfa3d3e1fb347ba76bddf77f3e288049635821d:/src/callproc.c diff --git a/src/callproc.c b/src/callproc.c index 0d30fe549e..56bdc7de0e 100644 --- a/src/callproc.c +++ b/src/callproc.c @@ -1,6 +1,7 @@ /* Synchronous subprocess invocation for GNU Emacs. -Copyright (C) 1985-1988, 1993-1995, 1999-2013 Free Software Foundation, Inc. +Copyright (C) 1985-1988, 1993-1995, 1999-2014 Free Software Foundation, +Inc. This file is part of GNU Emacs. @@ -81,12 +82,7 @@ static Lisp_Object Vtemp_file_name_pattern; /* If nonzero, a process-ID that has not been reaped. */ static pid_t synch_process_pid; -/* If a string, the name of a temp file that has not been removed. */ -#ifdef MSDOS static Lisp_Object synch_process_tempfile; -#else -# define synch_process_tempfile make_number (0) -#endif /* Indexes of file descriptors that need closing on call_process_kill. */ enum @@ -102,27 +98,8 @@ enum CALLPROC_FDS }; -static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int, ptrdiff_t); +static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int *, Lisp_Object *); -/* Block SIGCHLD. */ - -void -block_child_signal (void) -{ - sigset_t blocked; - sigemptyset (&blocked); - sigaddset (&blocked, SIGCHLD); - pthread_sigmask (SIG_BLOCK, &blocked, 0); -} - -/* Unblock SIGCHLD. */ - -void -unblock_child_signal (void) -{ - 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. */ @@ -151,7 +128,7 @@ encode_current_directory (void) report_file_error ("Setting current directory", BVAR (current_buffer, directory)); - RETURN_UNGCPRO (dir); + return dir; } /* If P is reapable, record it as a deleted process and kill it. @@ -161,7 +138,9 @@ encode_current_directory (void) void record_kill_process (struct Lisp_Process *p, Lisp_Object tempfile) { - block_child_signal (); +#ifndef MSDOS + sigset_t oldset; + block_child_signal (&oldset); if (p->alive) { @@ -170,15 +149,18 @@ record_kill_process (struct Lisp_Process *p, Lisp_Object tempfile) kill (- p->pid, SIGKILL); } - unblock_child_signal (); + unblock_child_signal (&oldset); +#endif /* !MSDOS */ } /* Clean up files, file descriptors and processes created by Fcall_process. */ static void -delete_temp_file (Lisp_Object name) +delete_temp_file_ptr (Lisp_Object *name_ptr) { - unlink (SSDATA (name)); + Lisp_Object name = *name_ptr; + if (! NILP (name)) + unlink (SSDATA (name)); } static void @@ -199,7 +181,7 @@ call_process_kill (void *ptr) synch_process_pid = 0; } else if (STRINGP (synch_process_tempfile)) - delete_temp_file (synch_process_tempfile); + delete_temp_file_ptr (&synch_process_tempfile); } /* Clean up when exiting Fcall_process: restore the buffer, and @@ -210,6 +192,7 @@ call_process_cleanup (Lisp_Object buffer) { Fset_buffer (buffer); +#ifndef MSDOS if (synch_process_pid) { kill (-synch_process_pid, SIGINT); @@ -221,6 +204,7 @@ call_process_cleanup (Lisp_Object buffer) immediate_quit = 0; message1 ("Waiting for process to die...done"); } +#endif /* !MSDOS */ } #ifdef DOS_NT @@ -261,7 +245,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * Lisp_Object infile, encoded_infile; int filefd; struct gcpro gcpro1; - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); if (nargs >= 2 && ! NILP (args[1])) { @@ -277,9 +261,11 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * filefd = emacs_open (SSDATA (encoded_infile), O_RDONLY, 0); if (filefd < 0) report_file_error ("Opening process input file", infile); - record_unwind_protect_int (close_file_unwind, filefd); + record_unwind_protect_ptr (close_file_ptr_unwind, &filefd); UNGCPRO; - return unbind_to (count, call_process (nargs, args, filefd, -1)); + Lisp_Object tem0 = call_process (nargs, args, &filefd, NULL); + dynwind_end (); + return tem0; } /* Like Fcall_process (NARGS, ARGS), except use FILEFD as the input file. @@ -291,8 +277,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * At entry, the specpdl stack top entry must be close_file_unwind (FILEFD). */ static Lisp_Object -call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, - ptrdiff_t tempfile_index) +call_process (ptrdiff_t nargs, Lisp_Object *args, int *filefd, Lisp_Object *tempfile_ptr) { Lisp_Object buffer, current_dir, path; bool display_p; @@ -300,7 +285,6 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, int callproc_fd[CALLPROC_FDS]; int status; ptrdiff_t i; - ptrdiff_t count = SPECPDL_INDEX (); USE_SAFE_ALLOCA; char **new_argv; @@ -312,6 +296,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, char *tempfile = NULL; int pid; #else + sigset_t oldset; pid_t pid; #endif int child_errno; @@ -322,6 +307,8 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, Lisp_Object coding_systems; bool discard_output; + dynwind_begin (); + if (synch_process_pid) error ("call-process invoked recursively"); @@ -465,7 +452,8 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, int ok; GCPRO3 (buffer, current_dir, error_file); - ok = openp (Vexec_path, args[0], Vexec_suffixes, &path, make_number (X_OK), 0); + ok = openp (Vexec_path, args[0], Vexec_suffixes, &path, + make_number (X_OK), false); UNGCPRO; if (ok < 0) report_file_error ("Searching for program", args[0]); @@ -516,10 +504,10 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, char const *outf = tmpdir ? tmpdir : ""; tempfile = alloca (strlen (outf) + 20); strcpy (tempfile, outf); - dostounix_filename (tempfile, 0); + dostounix_filename (tempfile); if (*tempfile == '\0' || tempfile[strlen (tempfile) - 1] != '/') strcat (tempfile, "/"); - strcat (tempfile, "detmp.XXX"); + strcat (tempfile, "emXXXXXX"); mktemp (tempfile); if (!*tempfile) report_file_error ("Opening process output file", Qnil); @@ -581,12 +569,12 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, #ifdef MSDOS /* MW, July 1993 */ /* Note that on MSDOS `child_setup' actually returns the child process exit status, not its PID, so assign it to status below. */ - pid = child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir); + pid = child_setup (*filefd, fd_output, fd_error, new_argv, 0, current_dir); if (pid < 0) { child_errno = errno; - unbind_to (count, Qnil); + dynwind_end (); synchronize_system_messages_locale (); return code_convert_string_norecord (build_string (strerror (child_errno)), @@ -600,8 +588,8 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, emacs_close (callproc_fd[i]); callproc_fd[i] = -1; } - emacs_close (filefd); - clear_unwind_protect (count - 1); + emacs_close (*filefd); + *filefd = -1; if (tempfile) { @@ -627,10 +615,10 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, #ifndef MSDOS block_input (); - block_child_signal (); + block_child_signal (&oldset); #ifdef WINDOWSNT - pid = child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir); + pid = child_setup (*filefd, fd_output, fd_error, new_argv, 0, current_dir); #else /* not WINDOWSNT */ /* vfork, and prevent local vars from being clobbered by the vfork. */ @@ -639,11 +627,8 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, Lisp_Object volatile coding_systems_volatile = coding_systems; Lisp_Object volatile current_dir_volatile = current_dir; bool volatile display_p_volatile = display_p; - bool volatile sa_must_free_volatile = sa_must_free; int volatile fd_error_volatile = fd_error; - int volatile filefd_volatile = filefd; - ptrdiff_t volatile count_volatile = count; - ptrdiff_t volatile sa_count_volatile = sa_count; + int *volatile filefd_volatile = filefd; char **volatile new_argv_volatile = new_argv; int volatile callproc_fd_volatile[CALLPROC_FDS]; for (i = 0; i < CALLPROC_FDS; i++) @@ -655,11 +640,8 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, coding_systems = coding_systems_volatile; current_dir = current_dir_volatile; display_p = display_p_volatile; - sa_must_free = sa_must_free_volatile; fd_error = fd_error_volatile; filefd = filefd_volatile; - count = count_volatile; - sa_count = sa_count_volatile; new_argv = new_argv_volatile; for (i = 0; i < CALLPROC_FDS; i++) @@ -669,14 +651,18 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, if (pid == 0) { - unblock_child_signal (); + unblock_child_signal (&oldset); setsid (); /* Emacs ignores SIGPIPE, but the child should not. */ signal (SIGPIPE, SIG_DFL); + /* Likewise for SIGPROF. */ +#ifdef SIGPROF + signal (SIGPROF, SIG_DFL); +#endif - child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir); + child_setup (*filefd, fd_output, fd_error, new_argv, 0, current_dir); } #endif /* not WINDOWSNT */ @@ -689,23 +675,22 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, if (INTEGERP (buffer)) { - if (tempfile_index < 0) - record_deleted_pid (pid, Qnil); - else - { - eassert (1 < nargs); - record_deleted_pid (pid, args[1]); - clear_unwind_protect (tempfile_index); - } + if (tempfile_ptr) + { + record_deleted_pid (pid, *tempfile_ptr); + *tempfile_ptr = Qnil; + } + else + { + record_deleted_pid (pid, Qnil); + } synch_process_pid = 0; } } - unblock_child_signal (); + unblock_child_signal (&oldset); unblock_input (); -#endif /* not MSDOS */ - if (pid < 0) report_file_errno ("Doing vfork", Qnil, child_errno); @@ -717,11 +702,16 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, emacs_close (callproc_fd[i]); callproc_fd[i] = -1; } - emacs_close (filefd); - clear_unwind_protect (count - 1); + emacs_close (*filefd); + *filefd = -1; + +#endif /* not MSDOS */ if (INTEGERP (buffer)) - return unbind_to (count, Qnil); + { + dynwind_end (); + return Qnil; + } if (BUFFERP (buffer)) Fset_buffer (buffer); @@ -812,15 +802,18 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, /* Now NREAD is the total amount of data in the buffer. */ immediate_quit = 0; - if (NILP (BVAR (current_buffer, enable_multibyte_characters)) - && ! CODING_MAY_REQUIRE_DECODING (&process_coding)) + if (!nread) + ; + else if (NILP (BVAR (current_buffer, enable_multibyte_characters)) + && ! CODING_MAY_REQUIRE_DECODING (&process_coding)) insert_1_both (buf, nread, nread, 0, 1, 0); else { /* We have to decode the input. */ Lisp_Object curbuf; - ptrdiff_t count1 = SPECPDL_INDEX (); + dynwind_begin (); XSETBUFFER (curbuf, current_buffer); + /* FIXME: Call signal_after_change! */ prepare_to_modify_buffer (PT, PT, NULL); /* We cannot allow after-change-functions be run during decoding, because that might modify the @@ -830,7 +823,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, specbind (Qinhibit_modification_hooks, Qt); decode_coding_c_string (&process_coding, (unsigned char *) buf, nread, curbuf); - unbind_to (count1, Qnil); + dynwind_end (); if (display_on_the_fly && CODING_REQUIRE_DETECTION (&saved_coding) && ! CODING_REQUIRE_DETECTION (&process_coding)) @@ -905,7 +898,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, synch_process_pid = 0; SAFE_FREE (); - unbind_to (count, Qnil); + dynwind_end (); if (WIFSIGNALED (status)) { @@ -932,9 +925,9 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, Unwind-protect the file, so that the file descriptor will be closed and the file removed when the caller unwinds the specpdl stack. */ -static int +static void create_temp_file (ptrdiff_t nargs, Lisp_Object *args, - Lisp_Object *filename_string_ptr) + Lisp_Object *filename_string_ptr, int *fdp) { int fd; struct gcpro gcpro1; @@ -984,14 +977,14 @@ create_temp_file (ptrdiff_t nargs, Lisp_Object *args, GCPRO1 (filename_string); tempfile = SSDATA (filename_string); - count = SPECPDL_INDEX (); - record_unwind_protect_nothing (); fd = mkostemp (tempfile, O_CLOEXEC); if (fd < 0) report_file_error ("Failed to open temporary file using pattern", pattern); - set_unwind_protect (count, delete_temp_file, filename_string); - record_unwind_protect_int (close_file_unwind, fd); + *fdp = fd; + *filename_string_ptr = filename_string; + record_unwind_protect (delete_temp_file_ptr, filename_string_ptr); + record_unwind_protect_ptr (close_file_ptr_unwind, fdp); } start = args[0]; @@ -1016,7 +1009,7 @@ create_temp_file (ptrdiff_t nargs, Lisp_Object *args, val = complement_process_encoding_system (val); { - ptrdiff_t count1 = SPECPDL_INDEX (); + dynwind_begin (); specbind (intern ("coding-system-for-write"), val); /* POSIX lets mk[s]temp use "."; don't invoke jka-compr if we @@ -1024,7 +1017,7 @@ create_temp_file (ptrdiff_t nargs, Lisp_Object *args, specbind (intern ("file-name-handler-alist"), Qnil); write_region (start, end, filename_string, Qnil, Qlambda, Qnil, Qnil, fd); - unbind_to (count1, Qnil); + dynwind_end (); } if (lseek (fd, 0, SEEK_SET) < 0) @@ -1033,9 +1026,7 @@ create_temp_file (ptrdiff_t nargs, Lisp_Object *args, /* Note that Fcall_process takes care of binding coding-system-for-read. */ - *filename_string_ptr = filename_string; UNGCPRO; - return fd; } DEFUN ("call-process-region", Fcall_process_region, Scall_process_region, @@ -1067,7 +1058,7 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r { struct gcpro gcpro1; Lisp_Object infile, val; - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); Lisp_Object start = args[0]; Lisp_Object end = args[1]; bool empty_input; @@ -1086,14 +1077,14 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r } if (!empty_input) - fd = create_temp_file (nargs, args, &infile); + create_temp_file (nargs, args, &infile, &fd); else { infile = Qnil; fd = emacs_open (NULL_DEVICE, O_RDONLY, 0); if (fd < 0) report_file_error ("Opening null device", Qnil); - record_unwind_protect_int (close_file_unwind, fd); + record_unwind_protect_ptr (close_file_ptr_unwind, &fd); } GCPRO1 (infile); @@ -1113,8 +1104,9 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r } args[1] = infile; - val = call_process (nargs, args, fd, empty_input ? -1 : count); - RETURN_UNGCPRO (unbind_to (count, val)); + val = call_process (nargs, args, &fd, &infile); + dynwind_end (); + return val; } #ifndef WINDOWSNT @@ -1611,13 +1603,13 @@ init_callproc (void) srcdir = Fexpand_file_name (build_string ("../src/"), lispdir); - tem = Fexpand_file_name (build_string ("GNU"), Vdata_directory); + tem = Fexpand_file_name (build_string ("NEWS"), Vdata_directory); tem1 = Ffile_exists_p (tem); if (!NILP (Fequal (srcdir, Vinvocation_directory)) || NILP (tem1)) { Lisp_Object newdir; newdir = Fexpand_file_name (build_string ("../etc/"), lispdir); - tem = Fexpand_file_name (build_string ("GNU"), newdir); + tem = Fexpand_file_name (build_string ("NEWS"), newdir); tem1 = Ffile_exists_p (tem); if (!NILP (tem1)) Vdata_directory = newdir; @@ -1664,19 +1656,17 @@ set_initial_environment (void) void syms_of_callproc (void) { +#include "callproc.x" + #ifndef DOS_NT Vtemp_file_name_pattern = build_string ("emacsXXXXXX"); -#elif defined (WINDOWSNT) +#else /* DOS_NT */ Vtemp_file_name_pattern = build_string ("emXXXXXX"); -#else - Vtemp_file_name_pattern = build_string ("detmp.XXX"); #endif staticpro (&Vtemp_file_name_pattern); -#ifdef MSDOS synch_process_tempfile = make_number (0); staticpro (&synch_process_tempfile); -#endif DEFVAR_LISP ("shell-file-name", Vshell_file_name, doc: /* File name to load inferior shells from. @@ -1685,7 +1675,11 @@ default if SHELL is not set. */); DEFVAR_LISP ("exec-path", Vexec_path, doc: /* List of directories to search programs to run in subprocesses. -Each element is a string (directory name) or nil (try default directory). */); +Each element is a string (directory name) or nil (try default directory). + +By default the last element of this list is `exec-directory'. The +last element is not always used, for example in shell completion +(`shell-dynamic-complete-command'). */); DEFVAR_LISP ("exec-suffixes", Vexec_suffixes, doc: /* List of suffixes to try to find executable file names. @@ -1749,8 +1743,4 @@ use. See `setenv' and `getenv'. */); Vprocess_environment = Qnil; - - defsubr (&Scall_process); - defsubr (&Sgetenv_internal); - defsubr (&Scall_process_region); }