diff options
| author | Joakim Verona | 2013-08-12 12:29:06 +0200 |
|---|---|---|
| committer | Joakim Verona | 2013-08-12 12:29:06 +0200 |
| commit | 5ff84f8a17c73bf63cc7532e14149380d9f83b3f (patch) | |
| tree | 501ac3b99a49aaa25adedc516bb4ea7a34c22a5c /src | |
| parent | c39e73975f7371a6458cd63967d39ba77a1e871a (diff) | |
| parent | 7a67e06b99a85ae700a7ccc75468397d53af59ed (diff) | |
| download | emacs-5ff84f8a17c73bf63cc7532e14149380d9f83b3f.tar.gz emacs-5ff84f8a17c73bf63cc7532e14149380d9f83b3f.zip | |
merge from trunk
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 104 | ||||
| -rw-r--r-- | src/callproc.c | 762 | ||||
| -rw-r--r-- | src/decompress.c | 100 | ||||
| -rw-r--r-- | src/eval.c | 10 | ||||
| -rw-r--r-- | src/fileio.c | 74 | ||||
| -rw-r--r-- | src/frame.h | 8 | ||||
| -rw-r--r-- | src/lisp.h | 6 | ||||
| -rw-r--r-- | src/process.c | 225 | ||||
| -rw-r--r-- | src/process.h | 15 | ||||
| -rw-r--r-- | src/syswait.h | 3 | ||||
| -rw-r--r-- | src/window.c | 35 | ||||
| -rw-r--r-- | src/window.h | 6 | ||||
| -rw-r--r-- | src/xdisp.c | 43 |
13 files changed, 772 insertions, 619 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 1780bf4e797..679b82ba63c 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,107 @@ | |||
| 1 | 2013-08-12 Dmitry Antipov <dmantipov@yandex.ru> | ||
| 2 | |||
| 3 | Avoid looping over all frame windows to freeze and unfreeze. | ||
| 4 | * window.h (struct window): Drop frozen_window_start_p. | ||
| 5 | (freeze_window_starts): Drop prototype. | ||
| 6 | * frame.h (struct frame): New frozen_window_starts flag. | ||
| 7 | (FRAME_WINDOWS_FROZEN): New macro. | ||
| 8 | * window.c (freeze_window_start, freeze_window_starts): | ||
| 9 | Remove. | ||
| 10 | (select_window, replace_window): Adjust users. | ||
| 11 | * xdisp.c (resize_mini_window): Use FRAME_WINDOWS_FROZEN. | ||
| 12 | (window_frozen_p): New function. | ||
| 13 | (redisplay_window): Use it. | ||
| 14 | |||
| 15 | 2013-08-12 Paul Eggert <eggert@cs.ucla.edu> | ||
| 16 | |||
| 17 | Fix some fd issues when running subprocesses (Bug#15035). | ||
| 18 | Fix bugs that can leak files or file descriptors on errors. | ||
| 19 | Don't unlink open temp files, as that's hard for users to diagnose | ||
| 20 | when things go awry (e.g., temp disk exhausted). | ||
| 21 | Don't bother to lock temp files. Check for invalid recursion. | ||
| 22 | * callproc.c (synch_process_fd): Remove. All uses removed. | ||
| 23 | (synch_process_tempfile): New var or macro. | ||
| 24 | (CALLPROC_STDOUT, CALLPROC_STDERR, CALLPROC_PIPEREAD, CALLPROC_FDS): | ||
| 25 | New constants. | ||
| 26 | (record_kill_process): New arg, the temp name. All callers changed. | ||
| 27 | (delete_temp_file): Now just a simple wrapper around unlink. | ||
| 28 | (call_process_kill): New arg, the call_process_fd array. | ||
| 29 | Close them all. Clear synch_process_pid. Remove the temp file, | ||
| 30 | or arrange for it to be removed. | ||
| 31 | (call_process_cleanup) [MSDOS]: Arg no longer contains file name; | ||
| 32 | that's been moved to synch_process_tempfile. Caller changed. | ||
| 33 | Do not remove the tempfile; that's now call_process_kill's | ||
| 34 | responsibility. | ||
| 35 | (call_process_cleanup) [!MSDOS]: Do not record unwind-protect for | ||
| 36 | call_process_kill; the caller now does that. | ||
| 37 | (call_process_cleanup): Do not close the process fd; that's now | ||
| 38 | call_process_kill's responsibility. | ||
| 39 | (Fcall_process): Implement via new function call_process, which | ||
| 40 | has most of the old body of Fcall_process, but with a different API. | ||
| 41 | (call_process): New function that does not open or close filefd if | ||
| 42 | it is nonnegative. Record which fds need to be closed, and let | ||
| 43 | call_process_kill close (and remove the tempfile, on MSDOS) on error. | ||
| 44 | Signal an error if invoked recursively (could be done via a hook). | ||
| 45 | Simplify creation of the tempfile in the MSDOS case. | ||
| 46 | Don't create the output file until after checking for the executable. | ||
| 47 | Report any failure to open /dev/null. | ||
| 48 | Don't open /dev/null for writing twice; once is enough. | ||
| 49 | Don't create pipe if all output is being discarded or sent to file. | ||
| 50 | Don't worry about setting up the coding system or reading from the | ||
| 51 | pipe if all output is being discarded. | ||
| 52 | Hoist fd_error local into top level, to lessen block nesting. | ||
| 53 | Don't record deleted pid here; now done by Fcall_process_region. | ||
| 54 | (Fcall_process) [MSDOS]: Report mktemp failure immediately, | ||
| 55 | and note its success in synch_process_tempfile. | ||
| 56 | Do not leak resources when child_setup fails. | ||
| 57 | (Fcall_process) [!MSDOS && !WINDOWSNT]: Remove duplicate assignment | ||
| 58 | to child_errno. Remove unnecessary close of fd0; it's close-on-exec. | ||
| 59 | (create_temp_file): Now returns open fd, with an additional | ||
| 60 | Lisp_Object * argument to return the name. All callers changed. | ||
| 61 | Do not close the file; rewind it instead, and leave it open for | ||
| 62 | the caller. Do not lock the temp file. Unwind-protect the file | ||
| 63 | and the file-descriptor. | ||
| 64 | (Fcall_process_region): If the input is /dev/null, unwind-protect it. | ||
| 65 | If an asynchrounous process, record it here, not in call_process. | ||
| 66 | (syms_of_callproc) [MSDOS]: Initialize synch_process_tempfile. | ||
| 67 | * eval.c (set_unwind_protect): New function. | ||
| 68 | * fileio.c (write_region): New function, generalized from the | ||
| 69 | old Fwrite_region. Do not lock temp files. | ||
| 70 | (Fwrite_region): Use it. | ||
| 71 | * lisp.h (set_unwind_protect, write_region): New decls. | ||
| 72 | * process.c: Include <verify.h>. | ||
| 73 | (make_process): Mark fds as initially closed. | ||
| 74 | (deleted_pid_list): Now a list of pid-filename pairs. | ||
| 75 | All uses changed. | ||
| 76 | (close_process_fd): New function. | ||
| 77 | (SUBPROCESS_STDIN, WRITE_TO_SUBPROCESS, READ_FROM_SUBPROCESS) | ||
| 78 | (SUBPROCESS_STDOUT, READ_FROM_EXEC_MONITOR, EXEC_MONITOR_OUTPUT): | ||
| 79 | New constants. Verify that their number matches PROCESS_OPEN_FDS. | ||
| 80 | (create_process, create_pty, Fmake_serial_process) | ||
| 81 | (server_accept_connection): Record which fds need to be closed, | ||
| 82 | and let deactivate_process close them. | ||
| 83 | (Fmake_network_process): Do not discard the unwind-protect | ||
| 84 | until it's safe to do so. | ||
| 85 | (deactivate_process): Close the fds opened by create_process etc. | ||
| 86 | (Fprocess_send_eof): Adjust to new way of recording open fds. | ||
| 87 | Report an error if /dev/null can't be opened, instead of aborting. | ||
| 88 | * process.h (PROCESS_OPEN_FDS): New constant. | ||
| 89 | (struct Lisp_Process): New member open_fds. | ||
| 90 | (record_kill_process, record_deleted_pid): Adjust signatures. | ||
| 91 | (record_deleted_pid): Move decl here ... | ||
| 92 | * syswait.h (record_deleted_pid): ... from here. | ||
| 93 | |||
| 94 | 2013-08-11 Paul Eggert <eggert@cs.ucla.edu> | ||
| 95 | |||
| 96 | * decompress.c: Fix bugs with large buffers and weird inputs. | ||
| 97 | Tune a bit. Reindent as per usual Emacs style. | ||
| 98 | (BUFFER_SIZE): Remove. | ||
| 99 | (Fdecompress_gzipped_region): Do not mishandle input buffers with | ||
| 100 | more than UINT_MAX bytes. Decompress into the gap instead of into | ||
| 101 | an auto buffer, as this should avoid copying. Return nil if | ||
| 102 | 'inflate' returns Z_NEED_DICT, as we have no dictionary. Do not | ||
| 103 | set immediate_quit; we shouldn't trust zlib code that much. | ||
| 104 | |||
| 1 | 2013-08-11 Lars Magne Ingebrigtsen <larsi@gnus.org> | 105 | 2013-08-11 Lars Magne Ingebrigtsen <larsi@gnus.org> |
| 2 | 106 | ||
| 3 | * decompress.c (Fdecompress_gzipped_region): Respect all zlib | 107 | * decompress.c (Fdecompress_gzipped_region): Respect all zlib |
diff --git a/src/callproc.c b/src/callproc.c index 54bc5cd9dc0..2a9162cb5cc 100644 --- a/src/callproc.c +++ b/src/callproc.c | |||
| @@ -68,9 +68,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 68 | /* Pattern used by call-process-region to make temp files. */ | 68 | /* Pattern used by call-process-region to make temp files. */ |
| 69 | static Lisp_Object Vtemp_file_name_pattern; | 69 | static Lisp_Object Vtemp_file_name_pattern; |
| 70 | 70 | ||
| 71 | /* The next two variables are valid only while record-unwind-protect | 71 | /* The next two variables are used while record-unwind-protect is in place |
| 72 | is in place during call-process for a synchronous subprocess. At | 72 | during call-process for a subprocess for which record_deleted_pid has |
| 73 | other times, their contents are irrelevant. Doing this via static | 73 | not yet been called. At other times, synch_process_pid is zero and |
| 74 | synch_process_tempfile's contents are irrelevant. Doing this via static | ||
| 74 | C variables is more convenient than putting them into the arguments | 75 | C variables is more convenient than putting them into the arguments |
| 75 | of record-unwind-protect, as they need to be updated at randomish | 76 | of record-unwind-protect, as they need to be updated at randomish |
| 76 | times in the code, and Lisp cannot always store these values as | 77 | times in the code, and Lisp cannot always store these values as |
| @@ -80,8 +81,28 @@ static Lisp_Object Vtemp_file_name_pattern; | |||
| 80 | /* If nonzero, a process-ID that has not been reaped. */ | 81 | /* If nonzero, a process-ID that has not been reaped. */ |
| 81 | static pid_t synch_process_pid; | 82 | static pid_t synch_process_pid; |
| 82 | 83 | ||
| 83 | /* If nonnegative, a file descriptor that has not been closed. */ | 84 | /* If a string, the name of a temp file that has not been removed. */ |
| 84 | static int synch_process_fd; | 85 | #ifdef MSDOS |
| 86 | static Lisp_Object synch_process_tempfile; | ||
| 87 | #else | ||
| 88 | # define synch_process_tempfile make_number (0) | ||
| 89 | #endif | ||
| 90 | |||
| 91 | /* Indexes of file descriptors that need closing on call_process_kill. */ | ||
| 92 | enum | ||
| 93 | { | ||
| 94 | /* The subsidiary process's stdout and stderr. stdin is handled | ||
| 95 | separately, in either Fcall_process_region or create_temp_file. */ | ||
| 96 | CALLPROC_STDOUT, CALLPROC_STDERR, | ||
| 97 | |||
| 98 | /* How to read from a pipe (or substitute) from the subsidiary process. */ | ||
| 99 | CALLPROC_PIPEREAD, | ||
| 100 | |||
| 101 | /* A bound on the number of file descriptors. */ | ||
| 102 | CALLPROC_FDS | ||
| 103 | }; | ||
| 104 | |||
| 105 | static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int); | ||
| 85 | 106 | ||
| 86 | /* Block SIGCHLD. */ | 107 | /* Block SIGCHLD. */ |
| 87 | 108 | ||
| @@ -107,80 +128,68 @@ unblock_child_signal (void) | |||
| 107 | reaped on receipt of the first SIGCHLD after the critical section. */ | 128 | reaped on receipt of the first SIGCHLD after the critical section. */ |
| 108 | 129 | ||
| 109 | void | 130 | void |
| 110 | record_kill_process (struct Lisp_Process *p) | 131 | record_kill_process (struct Lisp_Process *p, Lisp_Object tempfile) |
| 111 | { | 132 | { |
| 112 | block_child_signal (); | 133 | block_child_signal (); |
| 113 | 134 | ||
| 114 | if (p->alive) | 135 | if (p->alive) |
| 115 | { | 136 | { |
| 137 | record_deleted_pid (p->pid, tempfile); | ||
| 116 | p->alive = 0; | 138 | p->alive = 0; |
| 117 | record_deleted_pid (p->pid); | ||
| 118 | kill (- p->pid, SIGKILL); | 139 | kill (- p->pid, SIGKILL); |
| 119 | } | 140 | } |
| 120 | 141 | ||
| 121 | unblock_child_signal (); | 142 | unblock_child_signal (); |
| 122 | } | 143 | } |
| 123 | 144 | ||
| 124 | /* Clean up when exiting call_process_cleanup. */ | 145 | /* Clean up files, file descriptors and processes created by Fcall_process. */ |
| 146 | |||
| 147 | static void | ||
| 148 | delete_temp_file (Lisp_Object name) | ||
| 149 | { | ||
| 150 | unlink (SSDATA (name)); | ||
| 151 | } | ||
| 125 | 152 | ||
| 126 | static void | 153 | static void |
| 127 | call_process_kill (void) | 154 | call_process_kill (void *ptr) |
| 128 | { | 155 | { |
| 129 | if (synch_process_fd >= 0) | 156 | int *callproc_fd = ptr; |
| 130 | emacs_close (synch_process_fd); | 157 | int i; |
| 158 | for (i = 0; i < CALLPROC_FDS; i++) | ||
| 159 | if (0 <= callproc_fd[i]) | ||
| 160 | emacs_close (callproc_fd[i]); | ||
| 131 | 161 | ||
| 132 | if (synch_process_pid) | 162 | if (synch_process_pid) |
| 133 | { | 163 | { |
| 134 | struct Lisp_Process proc; | 164 | struct Lisp_Process proc; |
| 135 | proc.alive = 1; | 165 | proc.alive = 1; |
| 136 | proc.pid = synch_process_pid; | 166 | proc.pid = synch_process_pid; |
| 137 | record_kill_process (&proc); | 167 | record_kill_process (&proc, synch_process_tempfile); |
| 168 | synch_process_pid = 0; | ||
| 138 | } | 169 | } |
| 170 | else if (STRINGP (synch_process_tempfile)) | ||
| 171 | delete_temp_file (synch_process_tempfile); | ||
| 139 | } | 172 | } |
| 140 | 173 | ||
| 141 | /* Clean up when exiting Fcall_process. | 174 | /* Clean up when exiting Fcall_process: restore the buffer, and |
| 142 | On MSDOS, delete the temporary file on any kind of termination. | 175 | kill the subsidiary process group if the process still exists. */ |
| 143 | On Unix, kill the process and any children on termination by signal. */ | ||
| 144 | 176 | ||
| 145 | static void | 177 | static void |
| 146 | call_process_cleanup (Lisp_Object arg) | 178 | call_process_cleanup (Lisp_Object buffer) |
| 147 | { | 179 | { |
| 148 | #ifdef MSDOS | ||
| 149 | Lisp_Object buffer = Fcar (arg); | ||
| 150 | Lisp_Object file = Fcdr (arg); | ||
| 151 | #else | ||
| 152 | Lisp_Object buffer = arg; | ||
| 153 | #endif | ||
| 154 | |||
| 155 | Fset_buffer (buffer); | 180 | Fset_buffer (buffer); |
| 156 | 181 | ||
| 157 | #ifndef MSDOS | ||
| 158 | /* If the process still exists, kill its process group. */ | ||
| 159 | if (synch_process_pid) | 182 | if (synch_process_pid) |
| 160 | { | 183 | { |
| 161 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 162 | kill (-synch_process_pid, SIGINT); | 184 | kill (-synch_process_pid, SIGINT); |
| 163 | record_unwind_protect_void (call_process_kill); | ||
| 164 | message1 ("Waiting for process to die...(type C-g again to kill it instantly)"); | 185 | message1 ("Waiting for process to die...(type C-g again to kill it instantly)"); |
| 165 | immediate_quit = 1; | 186 | immediate_quit = 1; |
| 166 | QUIT; | 187 | QUIT; |
| 167 | wait_for_termination (synch_process_pid, 0, 1); | 188 | wait_for_termination (synch_process_pid, 0, 1); |
| 168 | synch_process_pid = 0; | 189 | synch_process_pid = 0; |
| 169 | immediate_quit = 0; | 190 | immediate_quit = 0; |
| 170 | specpdl_ptr = specpdl + count; /* Discard the unwind protect. */ | ||
| 171 | message1 ("Waiting for process to die...done"); | 191 | message1 ("Waiting for process to die...done"); |
| 172 | } | 192 | } |
| 173 | #endif | ||
| 174 | |||
| 175 | if (synch_process_fd >= 0) | ||
| 176 | emacs_close (synch_process_fd); | ||
| 177 | |||
| 178 | #ifdef MSDOS | ||
| 179 | /* FILE is "" when we didn't actually create a temporary file in | ||
| 180 | call-process. */ | ||
| 181 | if (!(strcmp (SDATA (file), NULL_DEVICE) == 0 || SREF (file, 0) == '\0')) | ||
| 182 | unlink (SDATA (file)); | ||
| 183 | #endif | ||
| 184 | } | 193 | } |
| 185 | 194 | ||
| 186 | #ifdef DOS_NT | 195 | #ifdef DOS_NT |
| @@ -218,10 +227,42 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you quit again. | |||
| 218 | usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) */) | 227 | usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) */) |
| 219 | (ptrdiff_t nargs, Lisp_Object *args) | 228 | (ptrdiff_t nargs, Lisp_Object *args) |
| 220 | { | 229 | { |
| 221 | Lisp_Object infile, buffer, current_dir, path; | 230 | Lisp_Object infile, encoded_infile; |
| 231 | int filefd; | ||
| 232 | struct gcpro gcpro1; | ||
| 233 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 234 | |||
| 235 | if (nargs >= 2 && ! NILP (args[1])) | ||
| 236 | { | ||
| 237 | infile = Fexpand_file_name (args[1], BVAR (current_buffer, directory)); | ||
| 238 | CHECK_STRING (infile); | ||
| 239 | } | ||
| 240 | else | ||
| 241 | infile = build_string (NULL_DEVICE); | ||
| 242 | |||
| 243 | GCPRO1 (infile); | ||
| 244 | encoded_infile = STRING_MULTIBYTE (infile) ? ENCODE_FILE (infile) : infile; | ||
| 245 | |||
| 246 | filefd = emacs_open (SSDATA (encoded_infile), O_RDONLY, 0); | ||
| 247 | if (filefd < 0) | ||
| 248 | report_file_error ("Opening process input file", infile); | ||
| 249 | record_unwind_protect_int (close_file_unwind, filefd); | ||
| 250 | UNGCPRO; | ||
| 251 | return unbind_to (count, call_process (nargs, args, filefd)); | ||
| 252 | } | ||
| 253 | |||
| 254 | /* Like Fcall_process (NARGS, ARGS), except use FILEFD as the input file. | ||
| 255 | At entry, the specpdl stack top entry must be close_file_unwind (FILEFD). */ | ||
| 256 | |||
| 257 | static Lisp_Object | ||
| 258 | call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd) | ||
| 259 | { | ||
| 260 | Lisp_Object buffer, current_dir, path; | ||
| 222 | bool display_p; | 261 | bool display_p; |
| 223 | int fd0, fd1, filefd; | 262 | int fd0; |
| 263 | int callproc_fd[CALLPROC_FDS]; | ||
| 224 | int status; | 264 | int status; |
| 265 | ptrdiff_t i; | ||
| 225 | ptrdiff_t count = SPECPDL_INDEX (); | 266 | ptrdiff_t count = SPECPDL_INDEX (); |
| 226 | USE_SAFE_ALLOCA; | 267 | USE_SAFE_ALLOCA; |
| 227 | 268 | ||
| @@ -231,19 +272,21 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * | |||
| 231 | Lisp_Object error_file; | 272 | Lisp_Object error_file; |
| 232 | Lisp_Object output_file = Qnil; | 273 | Lisp_Object output_file = Qnil; |
| 233 | #ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */ | 274 | #ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */ |
| 234 | char *outf, *tempfile = NULL; | 275 | char *tempfile = NULL; |
| 235 | int outfilefd; | ||
| 236 | int pid; | 276 | int pid; |
| 237 | #else | 277 | #else |
| 238 | pid_t pid; | 278 | pid_t pid; |
| 239 | #endif | 279 | #endif |
| 240 | int child_errno; | 280 | int child_errno; |
| 241 | int fd_output = -1; | 281 | int fd_output, fd_error; |
| 242 | struct coding_system process_coding; /* coding-system of process output */ | 282 | struct coding_system process_coding; /* coding-system of process output */ |
| 243 | struct coding_system argument_coding; /* coding-system of arguments */ | 283 | struct coding_system argument_coding; /* coding-system of arguments */ |
| 244 | /* Set to the return value of Ffind_operation_coding_system. */ | 284 | /* Set to the return value of Ffind_operation_coding_system. */ |
| 245 | Lisp_Object coding_systems; | 285 | Lisp_Object coding_systems; |
| 246 | bool output_to_buffer = 1; | 286 | bool discard_output; |
| 287 | |||
| 288 | if (synch_process_pid) | ||
| 289 | error ("call-process invoked recursively"); | ||
| 247 | 290 | ||
| 248 | /* Qt denotes that Ffind_operation_coding_system is not yet called. */ | 291 | /* Qt denotes that Ffind_operation_coding_system is not yet called. */ |
| 249 | coding_systems = Qt; | 292 | coding_systems = Qt; |
| @@ -262,7 +305,6 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * | |||
| 262 | /* Decide the coding-system for giving arguments. */ | 305 | /* Decide the coding-system for giving arguments. */ |
| 263 | { | 306 | { |
| 264 | Lisp_Object val, *args2; | 307 | Lisp_Object val, *args2; |
| 265 | ptrdiff_t i; | ||
| 266 | 308 | ||
| 267 | /* If arguments are supplied, we may have to encode them. */ | 309 | /* If arguments are supplied, we may have to encode them. */ |
| 268 | if (nargs >= 5) | 310 | if (nargs >= 5) |
| @@ -301,24 +343,16 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * | |||
| 301 | } | 343 | } |
| 302 | } | 344 | } |
| 303 | 345 | ||
| 304 | if (nargs >= 2 && ! NILP (args[1])) | 346 | if (nargs < 3) |
| 305 | { | 347 | buffer = Qnil; |
| 306 | infile = Fexpand_file_name (args[1], BVAR (current_buffer, directory)); | ||
| 307 | CHECK_STRING (infile); | ||
| 308 | } | ||
| 309 | else | 348 | else |
| 310 | infile = build_string (NULL_DEVICE); | ||
| 311 | |||
| 312 | if (nargs >= 3) | ||
| 313 | { | 349 | { |
| 314 | buffer = args[2]; | 350 | buffer = args[2]; |
| 315 | 351 | ||
| 316 | /* If BUFFER is a list, its meaning is (BUFFER-FOR-STDOUT | 352 | /* If BUFFER is a list, its meaning is (BUFFER-FOR-STDOUT |
| 317 | FILE-FOR-STDERR), unless the first element is :file, in which case see | 353 | FILE-FOR-STDERR), unless the first element is :file, in which case see |
| 318 | the next paragraph. */ | 354 | the next paragraph. */ |
| 319 | if (CONSP (buffer) | 355 | if (CONSP (buffer) && !EQ (XCAR (buffer), QCfile)) |
| 320 | && (! SYMBOLP (XCAR (buffer)) | ||
| 321 | || strcmp (SSDATA (SYMBOL_NAME (XCAR (buffer))), ":file"))) | ||
| 322 | { | 356 | { |
| 323 | if (CONSP (XCDR (buffer))) | 357 | if (CONSP (XCDR (buffer))) |
| 324 | { | 358 | { |
| @@ -335,9 +369,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * | |||
| 335 | } | 369 | } |
| 336 | 370 | ||
| 337 | /* If the buffer is (still) a list, it might be a (:file "file") spec. */ | 371 | /* If the buffer is (still) a list, it might be a (:file "file") spec. */ |
| 338 | if (CONSP (buffer) | 372 | if (CONSP (buffer) && EQ (XCAR (buffer), QCfile)) |
| 339 | && SYMBOLP (XCAR (buffer)) | ||
| 340 | && ! strcmp (SSDATA (SYMBOL_NAME (XCAR (buffer))), ":file")) | ||
| 341 | { | 373 | { |
| 342 | output_file = Fexpand_file_name (XCAR (XCDR (buffer)), | 374 | output_file = Fexpand_file_name (XCAR (XCDR (buffer)), |
| 343 | BVAR (current_buffer, directory)); | 375 | BVAR (current_buffer, directory)); |
| @@ -345,9 +377,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * | |||
| 345 | buffer = Qnil; | 377 | buffer = Qnil; |
| 346 | } | 378 | } |
| 347 | 379 | ||
| 348 | if (!(EQ (buffer, Qnil) | 380 | if (! (NILP (buffer) || EQ (buffer, Qt) || INTEGERP (buffer))) |
| 349 | || EQ (buffer, Qt) | ||
| 350 | || INTEGERP (buffer))) | ||
| 351 | { | 381 | { |
| 352 | Lisp_Object spec_buffer; | 382 | Lisp_Object spec_buffer; |
| 353 | spec_buffer = buffer; | 383 | spec_buffer = buffer; |
| @@ -358,8 +388,6 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * | |||
| 358 | CHECK_BUFFER (buffer); | 388 | CHECK_BUFFER (buffer); |
| 359 | } | 389 | } |
| 360 | } | 390 | } |
| 361 | else | ||
| 362 | buffer = Qnil; | ||
| 363 | 391 | ||
| 364 | /* Make sure that the child will be able to chdir to the current | 392 | /* Make sure that the child will be able to chdir to the current |
| 365 | buffer's current directory, or its unhandled equivalent. We | 393 | buffer's current directory, or its unhandled equivalent. We |
| @@ -372,11 +400,11 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * | |||
| 372 | protected by the caller, so all we really have to worry about is | 400 | protected by the caller, so all we really have to worry about is |
| 373 | buffer. */ | 401 | buffer. */ |
| 374 | { | 402 | { |
| 375 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; | 403 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; |
| 376 | 404 | ||
| 377 | current_dir = BVAR (current_buffer, directory); | 405 | current_dir = BVAR (current_buffer, directory); |
| 378 | 406 | ||
| 379 | GCPRO5 (infile, buffer, current_dir, error_file, output_file); | 407 | GCPRO4 (buffer, current_dir, error_file, output_file); |
| 380 | 408 | ||
| 381 | current_dir = Funhandled_file_name_directory (current_dir); | 409 | current_dir = Funhandled_file_name_directory (current_dir); |
| 382 | if (NILP (current_dir)) | 410 | if (NILP (current_dir)) |
| @@ -390,8 +418,6 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * | |||
| 390 | report_file_error ("Setting current directory", | 418 | report_file_error ("Setting current directory", |
| 391 | BVAR (current_buffer, directory)); | 419 | BVAR (current_buffer, directory)); |
| 392 | 420 | ||
| 393 | if (STRING_MULTIBYTE (infile)) | ||
| 394 | infile = ENCODE_FILE (infile); | ||
| 395 | if (STRING_MULTIBYTE (current_dir)) | 421 | if (STRING_MULTIBYTE (current_dir)) |
| 396 | current_dir = ENCODE_FILE (current_dir); | 422 | current_dir = ENCODE_FILE (current_dir); |
| 397 | if (STRINGP (error_file) && STRING_MULTIBYTE (error_file)) | 423 | if (STRINGP (error_file) && STRING_MULTIBYTE (error_file)) |
| @@ -403,44 +429,23 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * | |||
| 403 | 429 | ||
| 404 | display_p = INTERACTIVE && nargs >= 4 && !NILP (args[3]); | 430 | display_p = INTERACTIVE && nargs >= 4 && !NILP (args[3]); |
| 405 | 431 | ||
| 406 | filefd = emacs_open (SSDATA (infile), O_RDONLY, 0); | 432 | for (i = 0; i < CALLPROC_FDS; i++) |
| 407 | if (filefd < 0) | 433 | callproc_fd[i] = -1; |
| 408 | { | 434 | #ifdef MSDOS |
| 409 | int open_errno = errno; | 435 | synch_process_tempfile = make_number (0); |
| 410 | report_file_errno ("Opening process input file", DECODE_FILE (infile), | 436 | #endif |
| 411 | open_errno); | 437 | record_unwind_protect_ptr (call_process_kill, callproc_fd); |
| 412 | } | ||
| 413 | |||
| 414 | if (STRINGP (output_file)) | ||
| 415 | { | ||
| 416 | fd_output = emacs_open (SSDATA (output_file), | ||
| 417 | O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, | ||
| 418 | default_output_mode); | ||
| 419 | if (fd_output < 0) | ||
| 420 | { | ||
| 421 | int open_errno = errno; | ||
| 422 | output_file = DECODE_FILE (output_file); | ||
| 423 | report_file_errno ("Opening process output file", | ||
| 424 | output_file, open_errno); | ||
| 425 | } | ||
| 426 | if (STRINGP (error_file) || NILP (error_file)) | ||
| 427 | output_to_buffer = 0; | ||
| 428 | } | ||
| 429 | 438 | ||
| 430 | /* Search for program; barf if not found. */ | 439 | /* Search for program; barf if not found. */ |
| 431 | { | 440 | { |
| 432 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | 441 | struct gcpro gcpro1, gcpro2, gcpro3; |
| 433 | int ok; | 442 | int ok; |
| 434 | 443 | ||
| 435 | GCPRO4 (infile, buffer, current_dir, error_file); | 444 | GCPRO3 (buffer, current_dir, error_file); |
| 436 | ok = openp (Vexec_path, args[0], Vexec_suffixes, &path, make_number (X_OK)); | 445 | ok = openp (Vexec_path, args[0], Vexec_suffixes, &path, make_number (X_OK)); |
| 437 | UNGCPRO; | 446 | UNGCPRO; |
| 438 | if (ok < 0) | 447 | if (ok < 0) |
| 439 | { | 448 | report_file_error ("Searching for program", args[0]); |
| 440 | int openp_errno = errno; | ||
| 441 | emacs_close (filefd); | ||
| 442 | report_file_errno ("Searching for program", args[0], openp_errno); | ||
| 443 | } | ||
| 444 | } | 449 | } |
| 445 | 450 | ||
| 446 | /* If program file name starts with /: for quoting a magic name, | 451 | /* If program file name starts with /: for quoting a magic name, |
| @@ -452,9 +457,9 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * | |||
| 452 | new_argv = SAFE_ALLOCA ((nargs > 4 ? nargs - 2 : 2) * sizeof *new_argv); | 457 | new_argv = SAFE_ALLOCA ((nargs > 4 ? nargs - 2 : 2) * sizeof *new_argv); |
| 453 | 458 | ||
| 454 | { | 459 | { |
| 455 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; | 460 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; |
| 456 | 461 | ||
| 457 | GCPRO5 (infile, buffer, current_dir, path, error_file); | 462 | GCPRO4 (buffer, current_dir, path, error_file); |
| 458 | if (nargs > 4) | 463 | if (nargs > 4) |
| 459 | { | 464 | { |
| 460 | ptrdiff_t i; | 465 | ptrdiff_t i; |
| @@ -479,254 +484,213 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * | |||
| 479 | UNGCPRO; | 484 | UNGCPRO; |
| 480 | } | 485 | } |
| 481 | 486 | ||
| 482 | #ifdef MSDOS /* MW, July 1993 */ | 487 | discard_output = INTEGERP (buffer) || (NILP (buffer) && NILP (output_file)); |
| 483 | 488 | ||
| 484 | /* If we're redirecting STDOUT to a file, that file is already open | 489 | #ifdef MSDOS |
| 485 | on fd_output. */ | 490 | if (! discard_output && ! STRINGP (output_file)) |
| 486 | if (fd_output < 0) | ||
| 487 | { | 491 | { |
| 488 | if ((outf = egetenv ("TMPDIR"))) | 492 | char const *tmpdir = egetenv ("TMPDIR"); |
| 489 | strcpy (tempfile = alloca (strlen (outf) + 20), outf); | 493 | char const *outf = tmpdir ? tmpdir : ""; |
| 490 | else | 494 | tempfile = alloca (strlen (outf) + 20); |
| 491 | { | 495 | strcpy (tempfile, outf); |
| 492 | tempfile = alloca (20); | ||
| 493 | *tempfile = '\0'; | ||
| 494 | } | ||
| 495 | dostounix_filename (tempfile, 0); | 496 | dostounix_filename (tempfile, 0); |
| 496 | if (*tempfile == '\0' || tempfile[strlen (tempfile) - 1] != '/') | 497 | if (*tempfile == '\0' || tempfile[strlen (tempfile) - 1] != '/') |
| 497 | strcat (tempfile, "/"); | 498 | strcat (tempfile, "/"); |
| 498 | strcat (tempfile, "detmp.XXX"); | 499 | strcat (tempfile, "detmp.XXX"); |
| 499 | mktemp (tempfile); | 500 | mktemp (tempfile); |
| 500 | outfilefd = emacs_open (tempfile, O_WRONLY | O_CREAT | O_TRUNC, | 501 | if (!*tempfile) |
| 501 | S_IREAD | S_IWRITE); | 502 | report_file_error ("Opening process output file", Qnil); |
| 502 | if (outfilefd < 0) | 503 | output_file = build_string (tempfile); |
| 504 | synch_process_tempfile = output_file; | ||
| 505 | } | ||
| 506 | #endif | ||
| 507 | |||
| 508 | if (discard_output) | ||
| 509 | { | ||
| 510 | fd_output = emacs_open (NULL_DEVICE, O_WRONLY, 0); | ||
| 511 | if (fd_output < 0) | ||
| 512 | report_file_error ("Opening null device", Qnil); | ||
| 513 | } | ||
| 514 | else if (STRINGP (output_file)) | ||
| 515 | { | ||
| 516 | fd_output = emacs_open (SSDATA (output_file), | ||
| 517 | O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, | ||
| 518 | default_output_mode); | ||
| 519 | if (fd_output < 0) | ||
| 503 | { | 520 | { |
| 504 | int open_errno = errno; | 521 | int open_errno = errno; |
| 505 | emacs_close (filefd); | 522 | output_file = DECODE_FILE (output_file); |
| 506 | report_file_errno ("Opening process output file", | 523 | report_file_errno ("Opening process output file", |
| 507 | build_string (tempfile), open_errno); | 524 | output_file, open_errno); |
| 508 | } | 525 | } |
| 509 | } | 526 | } |
| 510 | else | 527 | else |
| 511 | outfilefd = fd_output; | ||
| 512 | fd0 = filefd; | ||
| 513 | fd1 = outfilefd; | ||
| 514 | #endif /* MSDOS */ | ||
| 515 | |||
| 516 | if (INTEGERP (buffer)) | ||
| 517 | { | ||
| 518 | fd0 = -1; | ||
| 519 | fd1 = emacs_open (NULL_DEVICE, O_WRONLY, 0); | ||
| 520 | } | ||
| 521 | else | ||
| 522 | { | 528 | { |
| 523 | #ifndef MSDOS | ||
| 524 | int fd[2]; | 529 | int fd[2]; |
| 525 | if (emacs_pipe (fd) != 0) | 530 | if (emacs_pipe (fd) != 0) |
| 526 | { | 531 | report_file_error ("Creating process pipe", Qnil); |
| 527 | int pipe_errno = errno; | 532 | callproc_fd[CALLPROC_PIPEREAD] = fd[0]; |
| 528 | emacs_close (filefd); | 533 | fd_output = fd[1]; |
| 529 | report_file_errno ("Creating process pipe", Qnil, pipe_errno); | ||
| 530 | } | ||
| 531 | fd0 = fd[0]; | ||
| 532 | fd1 = fd[1]; | ||
| 533 | #endif | ||
| 534 | } | 534 | } |
| 535 | callproc_fd[CALLPROC_STDOUT] = fd_output; | ||
| 535 | 536 | ||
| 536 | { | 537 | fd_error = fd_output; |
| 537 | int fd_error = fd1; | ||
| 538 | 538 | ||
| 539 | if (fd_output >= 0) | 539 | if (STRINGP (error_file) || (NILP (error_file) && !discard_output)) |
| 540 | fd1 = fd_output; | 540 | { |
| 541 | 541 | fd_error = emacs_open ((STRINGP (error_file) | |
| 542 | if (NILP (error_file)) | 542 | ? SSDATA (error_file) |
| 543 | fd_error = emacs_open (NULL_DEVICE, O_WRONLY, 0); | 543 | : NULL_DEVICE), |
| 544 | else if (STRINGP (error_file)) | ||
| 545 | fd_error = emacs_open (SSDATA (error_file), | ||
| 546 | O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, | 544 | O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, |
| 547 | default_output_mode); | 545 | default_output_mode); |
| 548 | 546 | if (fd_error < 0) | |
| 549 | if (fd_error < 0) | 547 | { |
| 550 | { | 548 | int open_errno = errno; |
| 551 | int open_errno = errno; | 549 | report_file_errno ("Cannot redirect stderr", |
| 552 | emacs_close (filefd); | 550 | (STRINGP (error_file) |
| 553 | if (fd0 != filefd) | 551 | ? DECODE_FILE (error_file) |
| 554 | emacs_close (fd0); | 552 | : build_string (NULL_DEVICE)), |
| 555 | if (fd1 >= 0) | 553 | open_errno); |
| 556 | emacs_close (fd1); | 554 | } |
| 557 | #ifdef MSDOS | 555 | callproc_fd[CALLPROC_STDERR] = fd_error; |
| 558 | unlink (tempfile); | 556 | } |
| 559 | #endif | ||
| 560 | if (NILP (error_file)) | ||
| 561 | error_file = build_string (NULL_DEVICE); | ||
| 562 | else if (STRINGP (error_file)) | ||
| 563 | error_file = DECODE_FILE (error_file); | ||
| 564 | report_file_errno ("Cannot redirect stderr", error_file, open_errno); | ||
| 565 | } | ||
| 566 | 557 | ||
| 567 | #ifdef MSDOS /* MW, July 1993 */ | 558 | #ifdef MSDOS /* MW, July 1993 */ |
| 568 | /* Note that on MSDOS `child_setup' actually returns the child process | 559 | /* Note that on MSDOS `child_setup' actually returns the child process |
| 569 | exit status, not its PID, so assign it to status below. */ | 560 | exit status, not its PID, so assign it to status below. */ |
| 570 | pid = child_setup (filefd, outfilefd, fd_error, new_argv, 0, current_dir); | 561 | pid = child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir); |
| 571 | child_errno = errno; | 562 | |
| 572 | 563 | if (pid < 0) | |
| 573 | emacs_close (outfilefd); | 564 | { |
| 574 | if (fd_error != outfilefd) | 565 | child_errno = errno; |
| 575 | emacs_close (fd_error); | 566 | unbind_to (count, Qnil); |
| 576 | if (pid < 0) | 567 | synchronize_system_messages_locale (); |
| 577 | { | 568 | return |
| 578 | synchronize_system_messages_locale (); | 569 | code_convert_string_norecord (build_string (strerror (child_errno)), |
| 579 | return | 570 | Vlocale_coding_system, 0); |
| 580 | code_convert_string_norecord (build_string (strerror (child_errno)), | 571 | } |
| 581 | Vlocale_coding_system, 0); | 572 | status = pid; |
| 582 | } | 573 | |
| 583 | status = pid; | 574 | for (i = 0; i < CALLPROC_FDS; i++) |
| 584 | fd1 = -1; /* No harm in closing that one! */ | 575 | if (0 <= callproc_fd[i]) |
| 585 | if (tempfile) | ||
| 586 | { | 576 | { |
| 587 | /* Since CRLF is converted to LF within `decode_coding', we | 577 | emacs_close (callproc_fd[i]); |
| 588 | can always open a file with binary mode. */ | 578 | callproc_fd[i] = -1; |
| 589 | fd0 = emacs_open (tempfile, O_RDONLY | O_BINARY, 0); | ||
| 590 | if (fd0 < 0) | ||
| 591 | { | ||
| 592 | int open_errno = errno; | ||
| 593 | unlink (tempfile); | ||
| 594 | emacs_close (filefd); | ||
| 595 | report_file_errno ("Cannot re-open temporary file", | ||
| 596 | build_string (tempfile), open_errno); | ||
| 597 | } | ||
| 598 | } | 579 | } |
| 599 | else | 580 | emacs_close (filefd); |
| 600 | fd0 = -1; /* We are not going to read from tempfile. */ | 581 | clear_unwind_protect (count - 1); |
| 582 | |||
| 583 | if (tempfile) | ||
| 584 | { | ||
| 585 | /* Since CRLF is converted to LF within `decode_coding', we | ||
| 586 | can always open a file with binary mode. */ | ||
| 587 | callproc_fd[CALLPROC_PIPEREAD] = emacs_open (tempfile, | ||
| 588 | O_RDONLY | O_BINARY, 0); | ||
| 589 | if (callproc_fd[CALLPROC_PIPEREAD] < 0) | ||
| 590 | { | ||
| 591 | int open_errno = errno; | ||
| 592 | report_file_errno ("Cannot re-open temporary file", | ||
| 593 | build_string (tempfile), open_errno); | ||
| 594 | } | ||
| 595 | } | ||
| 596 | |||
| 601 | #endif /* MSDOS */ | 597 | #endif /* MSDOS */ |
| 602 | 598 | ||
| 603 | /* Do the unwind-protect now, even though the pid is not known, so | 599 | /* Do the unwind-protect now, even though the pid is not known, so |
| 604 | that no storage allocation is done in the critical section. | 600 | that no storage allocation is done in the critical section. |
| 605 | The actual PID will be filled in during the critical section. */ | 601 | The actual PID will be filled in during the critical section. */ |
| 606 | synch_process_pid = 0; | 602 | record_unwind_protect (call_process_cleanup, Fcurrent_buffer ()); |
| 607 | synch_process_fd = fd0; | ||
| 608 | 603 | ||
| 609 | #ifdef MSDOS | 604 | #ifndef MSDOS |
| 610 | /* MSDOS needs different cleanup information. */ | ||
| 611 | record_unwind_protect (call_process_cleanup, | ||
| 612 | Fcons (Fcurrent_buffer (), | ||
| 613 | build_string (tempfile ? tempfile : ""))); | ||
| 614 | #else | ||
| 615 | record_unwind_protect (call_process_cleanup, Fcurrent_buffer ()); | ||
| 616 | 605 | ||
| 617 | block_input (); | 606 | block_input (); |
| 618 | block_child_signal (); | 607 | block_child_signal (); |
| 619 | 608 | ||
| 620 | #ifdef WINDOWSNT | 609 | #ifdef WINDOWSNT |
| 621 | pid = child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir); | 610 | pid = child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir); |
| 622 | /* We need to record the input file of this child, for when we are | ||
| 623 | called from call-process-region to create an async subprocess. | ||
| 624 | That's because call-process-region's unwind procedure will | ||
| 625 | attempt to delete the temporary input file, which will fail | ||
| 626 | because that file is still in use. Recording it with the child | ||
| 627 | will allow us to delete the file when the subprocess exits. | ||
| 628 | The second part of this is in delete_temp_file, q.v. */ | ||
| 629 | if (pid > 0 && INTEGERP (buffer) && nargs >= 2 && !NILP (args[1])) | ||
| 630 | record_infile (pid, xstrdup (SSDATA (infile))); | ||
| 631 | #else /* not WINDOWSNT */ | 611 | #else /* not WINDOWSNT */ |
| 632 | 612 | ||
| 633 | /* vfork, and prevent local vars from being clobbered by the vfork. */ | 613 | /* vfork, and prevent local vars from being clobbered by the vfork. */ |
| 634 | { | 614 | { |
| 635 | Lisp_Object volatile buffer_volatile = buffer; | 615 | Lisp_Object volatile buffer_volatile = buffer; |
| 636 | Lisp_Object volatile coding_systems_volatile = coding_systems; | 616 | Lisp_Object volatile coding_systems_volatile = coding_systems; |
| 637 | Lisp_Object volatile current_dir_volatile = current_dir; | 617 | Lisp_Object volatile current_dir_volatile = current_dir; |
| 638 | bool volatile display_p_volatile = display_p; | 618 | bool volatile display_p_volatile = display_p; |
| 639 | bool volatile output_to_buffer_volatile = output_to_buffer; | 619 | bool volatile sa_must_free_volatile = sa_must_free; |
| 640 | bool volatile sa_must_free_volatile = sa_must_free; | 620 | int volatile fd_error_volatile = fd_error; |
| 641 | int volatile fd1_volatile = fd1; | 621 | int volatile filefd_volatile = filefd; |
| 642 | int volatile fd_error_volatile = fd_error; | 622 | ptrdiff_t volatile count_volatile = count; |
| 643 | int volatile fd_output_volatile = fd_output; | 623 | ptrdiff_t volatile sa_count_volatile = sa_count; |
| 644 | int volatile filefd_volatile = filefd; | 624 | char **volatile new_argv_volatile = new_argv; |
| 645 | ptrdiff_t volatile count_volatile = count; | 625 | int volatile callproc_fd_volatile[CALLPROC_FDS]; |
| 646 | ptrdiff_t volatile sa_count_volatile = sa_count; | 626 | for (i = 0; i < CALLPROC_FDS; i++) |
| 647 | char **volatile new_argv_volatile = new_argv; | 627 | callproc_fd_volatile[i] = callproc_fd[i]; |
| 648 | 628 | ||
| 649 | pid = vfork (); | 629 | pid = vfork (); |
| 650 | child_errno = errno; | 630 | |
| 651 | 631 | buffer = buffer_volatile; | |
| 652 | buffer = buffer_volatile; | 632 | coding_systems = coding_systems_volatile; |
| 653 | coding_systems = coding_systems_volatile; | 633 | current_dir = current_dir_volatile; |
| 654 | current_dir = current_dir_volatile; | 634 | display_p = display_p_volatile; |
| 655 | display_p = display_p_volatile; | 635 | sa_must_free = sa_must_free_volatile; |
| 656 | output_to_buffer = output_to_buffer_volatile; | 636 | fd_error = fd_error_volatile; |
| 657 | sa_must_free = sa_must_free_volatile; | 637 | filefd = filefd_volatile; |
| 658 | fd1 = fd1_volatile; | 638 | count = count_volatile; |
| 659 | fd_error = fd_error_volatile; | 639 | sa_count = sa_count_volatile; |
| 660 | fd_output = fd_output_volatile; | 640 | new_argv = new_argv_volatile; |
| 661 | filefd = filefd_volatile; | 641 | |
| 662 | count = count_volatile; | 642 | for (i = 0; i < CALLPROC_FDS; i++) |
| 663 | sa_count = sa_count_volatile; | 643 | callproc_fd[i] = callproc_fd_volatile[i]; |
| 664 | new_argv = new_argv_volatile; | 644 | fd_output = callproc_fd[CALLPROC_STDOUT]; |
| 665 | 645 | } | |
| 666 | fd0 = synch_process_fd; | ||
| 667 | } | ||
| 668 | |||
| 669 | if (pid == 0) | ||
| 670 | { | ||
| 671 | unblock_child_signal (); | ||
| 672 | 646 | ||
| 673 | if (fd0 >= 0) | 647 | if (pid == 0) |
| 674 | emacs_close (fd0); | 648 | { |
| 649 | unblock_child_signal (); | ||
| 675 | 650 | ||
| 676 | setsid (); | 651 | setsid (); |
| 677 | 652 | ||
| 678 | /* Emacs ignores SIGPIPE, but the child should not. */ | 653 | /* Emacs ignores SIGPIPE, but the child should not. */ |
| 679 | signal (SIGPIPE, SIG_DFL); | 654 | signal (SIGPIPE, SIG_DFL); |
| 680 | 655 | ||
| 681 | child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir); | 656 | child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir); |
| 682 | } | 657 | } |
| 683 | 658 | ||
| 684 | #endif /* not WINDOWSNT */ | 659 | #endif /* not WINDOWSNT */ |
| 685 | 660 | ||
| 686 | child_errno = errno; | 661 | child_errno = errno; |
| 687 | 662 | ||
| 688 | if (pid > 0) | 663 | if (pid > 0) |
| 689 | { | 664 | synch_process_pid = pid; |
| 690 | if (INTEGERP (buffer)) | ||
| 691 | record_deleted_pid (pid); | ||
| 692 | else | ||
| 693 | synch_process_pid = pid; | ||
| 694 | } | ||
| 695 | 665 | ||
| 696 | unblock_child_signal (); | 666 | unblock_child_signal (); |
| 697 | unblock_input (); | 667 | unblock_input (); |
| 698 | 668 | ||
| 699 | /* The MSDOS case did this already. */ | ||
| 700 | if (fd_error >= 0) | ||
| 701 | emacs_close (fd_error); | ||
| 702 | #endif /* not MSDOS */ | 669 | #endif /* not MSDOS */ |
| 703 | 670 | ||
| 704 | /* Close most of our file descriptors, but not fd0 | ||
| 705 | since we will use that to read input from. */ | ||
| 706 | emacs_close (filefd); | ||
| 707 | if (fd_output >= 0) | ||
| 708 | emacs_close (fd_output); | ||
| 709 | if (fd1 >= 0 && fd1 != fd_error) | ||
| 710 | emacs_close (fd1); | ||
| 711 | } | ||
| 712 | |||
| 713 | if (pid < 0) | 671 | if (pid < 0) |
| 714 | report_file_errno ("Doing vfork", Qnil, child_errno); | 672 | report_file_errno ("Doing vfork", Qnil, child_errno); |
| 715 | 673 | ||
| 674 | /* Close our file descriptors, except for callproc_fd[CALLPROC_PIPEREAD] | ||
| 675 | since we will use that to read input from. */ | ||
| 676 | for (i = 0; i < CALLPROC_FDS; i++) | ||
| 677 | if (i != CALLPROC_PIPEREAD && 0 <= callproc_fd[i]) | ||
| 678 | { | ||
| 679 | emacs_close (callproc_fd[i]); | ||
| 680 | callproc_fd[i] = -1; | ||
| 681 | } | ||
| 682 | emacs_close (filefd); | ||
| 683 | clear_unwind_protect (count - 1); | ||
| 684 | |||
| 716 | if (INTEGERP (buffer)) | 685 | if (INTEGERP (buffer)) |
| 717 | return unbind_to (count, Qnil); | 686 | return unbind_to (count, Qnil); |
| 718 | 687 | ||
| 719 | if (BUFFERP (buffer)) | 688 | if (BUFFERP (buffer)) |
| 720 | Fset_buffer (buffer); | 689 | Fset_buffer (buffer); |
| 721 | 690 | ||
| 722 | if (NILP (buffer)) | 691 | fd0 = callproc_fd[CALLPROC_PIPEREAD]; |
| 723 | { | 692 | |
| 724 | /* If BUFFER is nil, we must read process output once and then | 693 | if (0 <= fd0) |
| 725 | discard it, so setup coding system but with nil. */ | ||
| 726 | setup_coding_system (Qnil, &process_coding); | ||
| 727 | process_coding.dst_multibyte = 0; | ||
| 728 | } | ||
| 729 | else | ||
| 730 | { | 694 | { |
| 731 | Lisp_Object val, *args2; | 695 | Lisp_Object val, *args2; |
| 732 | 696 | ||
| @@ -762,13 +726,13 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * | |||
| 762 | setup_coding_system (val, &process_coding); | 726 | setup_coding_system (val, &process_coding); |
| 763 | process_coding.dst_multibyte | 727 | process_coding.dst_multibyte |
| 764 | = ! NILP (BVAR (current_buffer, enable_multibyte_characters)); | 728 | = ! NILP (BVAR (current_buffer, enable_multibyte_characters)); |
| 729 | process_coding.src_multibyte = 0; | ||
| 765 | } | 730 | } |
| 766 | process_coding.src_multibyte = 0; | ||
| 767 | 731 | ||
| 768 | immediate_quit = 1; | 732 | immediate_quit = 1; |
| 769 | QUIT; | 733 | QUIT; |
| 770 | 734 | ||
| 771 | if (output_to_buffer) | 735 | if (0 <= fd0) |
| 772 | { | 736 | { |
| 773 | enum { CALLPROC_BUFFER_SIZE_MIN = 16 * 1024 }; | 737 | enum { CALLPROC_BUFFER_SIZE_MIN = 16 * 1024 }; |
| 774 | enum { CALLPROC_BUFFER_SIZE_MAX = 4 * CALLPROC_BUFFER_SIZE_MIN }; | 738 | enum { CALLPROC_BUFFER_SIZE_MAX = 4 * CALLPROC_BUFFER_SIZE_MIN }; |
| @@ -779,9 +743,8 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * | |||
| 779 | EMACS_INT total_read = 0; | 743 | EMACS_INT total_read = 0; |
| 780 | int carryover = 0; | 744 | int carryover = 0; |
| 781 | bool display_on_the_fly = display_p; | 745 | bool display_on_the_fly = display_p; |
| 782 | struct coding_system saved_coding; | 746 | struct coding_system saved_coding = process_coding; |
| 783 | 747 | ||
| 784 | saved_coding = process_coding; | ||
| 785 | while (1) | 748 | while (1) |
| 786 | { | 749 | { |
| 787 | /* Repeatedly read until we've filled as much as possible | 750 | /* Repeatedly read until we've filled as much as possible |
| @@ -812,58 +775,54 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * | |||
| 812 | /* Now NREAD is the total amount of data in the buffer. */ | 775 | /* Now NREAD is the total amount of data in the buffer. */ |
| 813 | immediate_quit = 0; | 776 | immediate_quit = 0; |
| 814 | 777 | ||
| 815 | if (!NILP (buffer)) | 778 | if (NILP (BVAR (current_buffer, enable_multibyte_characters)) |
| 816 | { | 779 | && ! CODING_MAY_REQUIRE_DECODING (&process_coding)) |
| 817 | if (NILP (BVAR (current_buffer, enable_multibyte_characters)) | 780 | insert_1_both (buf, nread, nread, 0, 1, 0); |
| 818 | && ! CODING_MAY_REQUIRE_DECODING (&process_coding)) | 781 | else |
| 819 | insert_1_both (buf, nread, nread, 0, 1, 0); | 782 | { /* We have to decode the input. */ |
| 820 | else | 783 | Lisp_Object curbuf; |
| 821 | { /* We have to decode the input. */ | 784 | ptrdiff_t count1 = SPECPDL_INDEX (); |
| 822 | Lisp_Object curbuf; | 785 | |
| 823 | ptrdiff_t count1 = SPECPDL_INDEX (); | 786 | XSETBUFFER (curbuf, current_buffer); |
| 824 | 787 | /* We cannot allow after-change-functions be run | |
| 825 | XSETBUFFER (curbuf, current_buffer); | 788 | during decoding, because that might modify the |
| 826 | /* We cannot allow after-change-functions be run | 789 | buffer, while we rely on process_coding.produced to |
| 827 | during decoding, because that might modify the | 790 | faithfully reflect inserted text until we |
| 828 | buffer, while we rely on process_coding.produced to | 791 | TEMP_SET_PT_BOTH below. */ |
| 829 | faithfully reflect inserted text until we | 792 | specbind (Qinhibit_modification_hooks, Qt); |
| 830 | TEMP_SET_PT_BOTH below. */ | 793 | decode_coding_c_string (&process_coding, |
| 831 | specbind (Qinhibit_modification_hooks, Qt); | 794 | (unsigned char *) buf, nread, curbuf); |
| 832 | decode_coding_c_string (&process_coding, | 795 | unbind_to (count1, Qnil); |
| 833 | (unsigned char *) buf, nread, curbuf); | 796 | if (display_on_the_fly |
| 834 | unbind_to (count1, Qnil); | 797 | && CODING_REQUIRE_DETECTION (&saved_coding) |
| 835 | if (display_on_the_fly | 798 | && ! CODING_REQUIRE_DETECTION (&process_coding)) |
| 836 | && CODING_REQUIRE_DETECTION (&saved_coding) | 799 | { |
| 837 | && ! CODING_REQUIRE_DETECTION (&process_coding)) | 800 | /* We have detected some coding system, but the |
| 838 | { | 801 | detection may have been via insufficient data. |
| 839 | /* We have detected some coding system. But, | 802 | So give up displaying on the fly. */ |
| 840 | there's a possibility that the detection was | 803 | if (process_coding.produced > 0) |
| 841 | done by insufficient data. So, we give up | 804 | del_range_2 (process_coding.dst_pos, |
| 842 | displaying on the fly. */ | 805 | process_coding.dst_pos_byte, |
| 843 | if (process_coding.produced > 0) | 806 | (process_coding.dst_pos |
| 844 | del_range_2 (process_coding.dst_pos, | 807 | + process_coding.produced_char), |
| 845 | process_coding.dst_pos_byte, | 808 | (process_coding.dst_pos_byte |
| 846 | process_coding.dst_pos | 809 | + process_coding.produced), |
| 847 | + process_coding.produced_char, | 810 | 0); |
| 848 | process_coding.dst_pos_byte | 811 | display_on_the_fly = 0; |
| 849 | + process_coding.produced, 0); | 812 | process_coding = saved_coding; |
| 850 | display_on_the_fly = 0; | 813 | carryover = nread; |
| 851 | process_coding = saved_coding; | 814 | /* Make the above condition always fail in the future. */ |
| 852 | carryover = nread; | 815 | saved_coding.common_flags |
| 853 | /* This is to make the above condition always | 816 | &= ~CODING_REQUIRE_DETECTION_MASK; |
| 854 | fails in the future. */ | 817 | continue; |
| 855 | saved_coding.common_flags | ||
| 856 | &= ~CODING_REQUIRE_DETECTION_MASK; | ||
| 857 | continue; | ||
| 858 | } | ||
| 859 | |||
| 860 | TEMP_SET_PT_BOTH (PT + process_coding.produced_char, | ||
| 861 | PT_BYTE + process_coding.produced); | ||
| 862 | carryover = process_coding.carryover_bytes; | ||
| 863 | if (carryover > 0) | ||
| 864 | memcpy (buf, process_coding.carryover, | ||
| 865 | process_coding.carryover_bytes); | ||
| 866 | } | 818 | } |
| 819 | |||
| 820 | TEMP_SET_PT_BOTH (PT + process_coding.produced_char, | ||
| 821 | PT_BYTE + process_coding.produced); | ||
| 822 | carryover = process_coding.carryover_bytes; | ||
| 823 | if (carryover > 0) | ||
| 824 | memcpy (buf, process_coding.carryover, | ||
| 825 | process_coding.carryover_bytes); | ||
| 867 | } | 826 | } |
| 868 | 827 | ||
| 869 | if (process_coding.mode & CODING_MODE_LAST_BLOCK) | 828 | if (process_coding.mode & CODING_MODE_LAST_BLOCK) |
| @@ -882,7 +841,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * | |||
| 882 | first = 0; | 841 | first = 0; |
| 883 | redisplay_preserve_echo_area (1); | 842 | redisplay_preserve_echo_area (1); |
| 884 | /* This variable might have been set to 0 for code | 843 | /* This variable might have been set to 0 for code |
| 885 | detection. In that case, we set it back to 1 because | 844 | detection. In that case, set it back to 1 because |
| 886 | we should have already detected a coding system. */ | 845 | we should have already detected a coding system. */ |
| 887 | display_on_the_fly = 1; | 846 | display_on_the_fly = 1; |
| 888 | } | 847 | } |
| @@ -901,7 +860,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * | |||
| 901 | 860 | ||
| 902 | #ifndef MSDOS | 861 | #ifndef MSDOS |
| 903 | /* Wait for it to terminate, unless it already has. */ | 862 | /* Wait for it to terminate, unless it already has. */ |
| 904 | wait_for_termination (pid, &status, !output_to_buffer); | 863 | wait_for_termination (pid, &status, fd0 < 0); |
| 905 | #endif | 864 | #endif |
| 906 | 865 | ||
| 907 | immediate_quit = 0; | 866 | immediate_quit = 0; |
| @@ -931,37 +890,18 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * | |||
| 931 | return make_number (WEXITSTATUS (status)); | 890 | return make_number (WEXITSTATUS (status)); |
| 932 | } | 891 | } |
| 933 | 892 | ||
| 934 | static void | ||
| 935 | delete_temp_file (Lisp_Object name) | ||
| 936 | { | ||
| 937 | /* Suppress jka-compr handling, etc. */ | ||
| 938 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 939 | specbind (intern ("file-name-handler-alist"), Qnil); | ||
| 940 | #ifdef WINDOWSNT | ||
| 941 | /* If this is called when the subprocess didn't exit yet, the | ||
| 942 | attempt to delete its input file will fail. In that case, we | ||
| 943 | schedule the file for deletion when the subprocess exits. This | ||
| 944 | is the 2nd part of handling this situation; see the call to | ||
| 945 | record_infile in call-process above, for the first part. */ | ||
| 946 | if (!internal_delete_file (name)) | ||
| 947 | { | ||
| 948 | Lisp_Object encoded_file = ENCODE_FILE (name); | ||
| 949 | |||
| 950 | record_pending_deletion (SSDATA (encoded_file)); | ||
| 951 | } | ||
| 952 | #else | ||
| 953 | internal_delete_file (name); | ||
| 954 | #endif | ||
| 955 | unbind_to (count, Qnil); | ||
| 956 | } | ||
| 957 | |||
| 958 | /* Create a temporary file suitable for storing the input data of | 893 | /* Create a temporary file suitable for storing the input data of |
| 959 | call-process-region. NARGS and ARGS are the same as for | 894 | call-process-region. NARGS and ARGS are the same as for |
| 960 | call-process-region. */ | 895 | call-process-region. Store into *FILENAME_STRING_PTR a Lisp string |
| 896 | naming the file, and return a file descriptor for reading. | ||
| 897 | Unwind-protect the file, so that the file descriptor will be closed | ||
| 898 | and the file removed when the caller unwinds the specpdl stack. */ | ||
| 961 | 899 | ||
| 962 | static Lisp_Object | 900 | static int |
| 963 | create_temp_file (ptrdiff_t nargs, Lisp_Object *args) | 901 | create_temp_file (ptrdiff_t nargs, Lisp_Object *args, |
| 902 | Lisp_Object *filename_string_ptr) | ||
| 964 | { | 903 | { |
| 904 | int fd; | ||
| 965 | struct gcpro gcpro1; | 905 | struct gcpro gcpro1; |
| 966 | Lisp_Object filename_string; | 906 | Lisp_Object filename_string; |
| 967 | Lisp_Object val, start, end; | 907 | Lisp_Object val, start, end; |
| @@ -988,6 +928,7 @@ create_temp_file (ptrdiff_t nargs, Lisp_Object *args) | |||
| 988 | { | 928 | { |
| 989 | Lisp_Object pattern = Fexpand_file_name (Vtemp_file_name_pattern, tmpdir); | 929 | Lisp_Object pattern = Fexpand_file_name (Vtemp_file_name_pattern, tmpdir); |
| 990 | char *tempfile; | 930 | char *tempfile; |
| 931 | ptrdiff_t count; | ||
| 991 | 932 | ||
| 992 | #ifdef WINDOWSNT | 933 | #ifdef WINDOWSNT |
| 993 | /* Cannot use the result of Fexpand_file_name, because it | 934 | /* Cannot use the result of Fexpand_file_name, because it |
| @@ -1008,15 +949,14 @@ create_temp_file (ptrdiff_t nargs, Lisp_Object *args) | |||
| 1008 | GCPRO1 (filename_string); | 949 | GCPRO1 (filename_string); |
| 1009 | tempfile = SSDATA (filename_string); | 950 | tempfile = SSDATA (filename_string); |
| 1010 | 951 | ||
| 1011 | { | 952 | count = SPECPDL_INDEX (); |
| 1012 | int fd = mkostemp (tempfile, O_CLOEXEC); | 953 | record_unwind_protect_nothing (); |
| 1013 | if (fd < 0) | 954 | fd = mkostemp (tempfile, O_CLOEXEC); |
| 1014 | report_file_error ("Failed to open temporary file using pattern", | 955 | if (fd < 0) |
| 1015 | pattern); | 956 | report_file_error ("Failed to open temporary file using pattern", |
| 1016 | emacs_close (fd); | 957 | pattern); |
| 1017 | } | 958 | set_unwind_protect (count, delete_temp_file, filename_string); |
| 1018 | 959 | record_unwind_protect_int (close_file_unwind, fd); | |
| 1019 | record_unwind_protect (delete_temp_file, filename_string); | ||
| 1020 | } | 960 | } |
| 1021 | 961 | ||
| 1022 | start = args[0]; | 962 | start = args[0]; |
| @@ -1047,15 +987,20 @@ create_temp_file (ptrdiff_t nargs, Lisp_Object *args) | |||
| 1047 | /* POSIX lets mk[s]temp use "."; don't invoke jka-compr if we | 987 | /* POSIX lets mk[s]temp use "."; don't invoke jka-compr if we |
| 1048 | happen to get a ".Z" suffix. */ | 988 | happen to get a ".Z" suffix. */ |
| 1049 | specbind (intern ("file-name-handler-alist"), Qnil); | 989 | specbind (intern ("file-name-handler-alist"), Qnil); |
| 1050 | Fwrite_region (start, end, filename_string, Qnil, Qlambda, Qnil, Qnil); | 990 | write_region (start, end, filename_string, Qnil, Qlambda, Qnil, Qnil, fd); |
| 1051 | 991 | ||
| 1052 | unbind_to (count1, Qnil); | 992 | unbind_to (count1, Qnil); |
| 1053 | } | 993 | } |
| 1054 | 994 | ||
| 995 | if (lseek (fd, 0, SEEK_SET) < 0) | ||
| 996 | report_file_error ("Setting file position", filename_string); | ||
| 997 | |||
| 1055 | /* Note that Fcall_process takes care of binding | 998 | /* Note that Fcall_process takes care of binding |
| 1056 | coding-system-for-read. */ | 999 | coding-system-for-read. */ |
| 1057 | 1000 | ||
| 1058 | RETURN_UNGCPRO (filename_string); | 1001 | *filename_string_ptr = filename_string; |
| 1002 | UNGCPRO; | ||
| 1003 | return fd; | ||
| 1059 | } | 1004 | } |
| 1060 | 1005 | ||
| 1061 | DEFUN ("call-process-region", Fcall_process_region, Scall_process_region, | 1006 | DEFUN ("call-process-region", Fcall_process_region, Scall_process_region, |
| @@ -1085,12 +1030,13 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you quit again. | |||
| 1085 | usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &rest ARGS) */) | 1030 | usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &rest ARGS) */) |
| 1086 | (ptrdiff_t nargs, Lisp_Object *args) | 1031 | (ptrdiff_t nargs, Lisp_Object *args) |
| 1087 | { | 1032 | { |
| 1088 | struct gcpro gcpro1; | 1033 | struct gcpro gcpro1, gcpro2; |
| 1089 | Lisp_Object infile; | 1034 | Lisp_Object infile, val; |
| 1090 | ptrdiff_t count = SPECPDL_INDEX (); | 1035 | ptrdiff_t count = SPECPDL_INDEX (); |
| 1091 | Lisp_Object start = args[0]; | 1036 | Lisp_Object start = args[0]; |
| 1092 | Lisp_Object end = args[1]; | 1037 | Lisp_Object end = args[1]; |
| 1093 | bool empty_input; | 1038 | bool empty_input; |
| 1039 | int fd; | ||
| 1094 | 1040 | ||
| 1095 | if (STRINGP (start)) | 1041 | if (STRINGP (start)) |
| 1096 | empty_input = SCHARS (start) == 0; | 1042 | empty_input = SCHARS (start) == 0; |
| @@ -1104,8 +1050,19 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r | |||
| 1104 | empty_input = XINT (start) == XINT (end); | 1050 | empty_input = XINT (start) == XINT (end); |
| 1105 | } | 1051 | } |
| 1106 | 1052 | ||
| 1107 | infile = empty_input ? Qnil : create_temp_file (nargs, args); | 1053 | if (!empty_input) |
| 1108 | GCPRO1 (infile); | 1054 | fd = create_temp_file (nargs, args, &infile); |
| 1055 | else | ||
| 1056 | { | ||
| 1057 | infile = Qnil; | ||
| 1058 | fd = emacs_open (NULL_DEVICE, O_RDONLY, 0); | ||
| 1059 | if (fd < 0) | ||
| 1060 | report_file_error ("Opening null device", Qnil); | ||
| 1061 | record_unwind_protect_int (close_file_unwind, fd); | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | val = infile; | ||
| 1065 | GCPRO2 (infile, val); | ||
| 1109 | 1066 | ||
| 1110 | if (nargs > 3 && !NILP (args[3])) | 1067 | if (nargs > 3 && !NILP (args[3])) |
| 1111 | Fdelete_region (start, end); | 1068 | Fdelete_region (start, end); |
| @@ -1122,7 +1079,17 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r | |||
| 1122 | } | 1079 | } |
| 1123 | args[1] = infile; | 1080 | args[1] = infile; |
| 1124 | 1081 | ||
| 1125 | RETURN_UNGCPRO (unbind_to (count, Fcall_process (nargs, args))); | 1082 | val = call_process (nargs, args, fd); |
| 1083 | |||
| 1084 | if (!empty_input && 4 < nargs | ||
| 1085 | && (INTEGERP (CONSP (args[4]) ? XCAR (args[4]) : args[4]))) | ||
| 1086 | { | ||
| 1087 | record_deleted_pid (synch_process_pid, infile); | ||
| 1088 | synch_process_pid = 0; | ||
| 1089 | clear_unwind_protect (count); | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | RETURN_UNGCPRO (unbind_to (count, val)); | ||
| 1126 | } | 1093 | } |
| 1127 | 1094 | ||
| 1128 | #ifndef WINDOWSNT | 1095 | #ifndef WINDOWSNT |
| @@ -1683,6 +1650,11 @@ syms_of_callproc (void) | |||
| 1683 | #endif | 1650 | #endif |
| 1684 | staticpro (&Vtemp_file_name_pattern); | 1651 | staticpro (&Vtemp_file_name_pattern); |
| 1685 | 1652 | ||
| 1653 | #ifdef MSDOS | ||
| 1654 | synch_process_tempfile = make_number (0); | ||
| 1655 | staticpro (&synch_process_tempfile); | ||
| 1656 | #endif | ||
| 1657 | |||
| 1686 | DEFVAR_LISP ("shell-file-name", Vshell_file_name, | 1658 | DEFVAR_LISP ("shell-file-name", Vshell_file_name, |
| 1687 | doc: /* File name to load inferior shells from. | 1659 | doc: /* File name to load inferior shells from. |
| 1688 | Initialized from the SHELL environment variable, or to a system-dependent | 1660 | Initialized from the SHELL environment variable, or to a system-dependent |
diff --git a/src/decompress.c b/src/decompress.c index a6323a843e9..866f4f51516 100644 --- a/src/decompress.c +++ b/src/decompress.c | |||
| @@ -27,48 +27,48 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 27 | #include "buffer.h" | 27 | #include "buffer.h" |
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | #define BUFFER_SIZE 16384 | 30 | struct decompress_unwind_data |
| 31 | 31 | { | |
| 32 | struct decompress_unwind_data { | ||
| 33 | ptrdiff_t old_point, start; | 32 | ptrdiff_t old_point, start; |
| 34 | z_stream *stream; | 33 | z_stream *stream; |
| 35 | }; | 34 | }; |
| 36 | 35 | ||
| 37 | static void | 36 | static void |
| 38 | unwind_decompress (void *ddata) { | 37 | unwind_decompress (void *ddata) |
| 38 | { | ||
| 39 | struct decompress_unwind_data *data = ddata; | 39 | struct decompress_unwind_data *data = ddata; |
| 40 | inflateEnd (data->stream); | 40 | inflateEnd (data->stream); |
| 41 | /* Delete any uncompressed data already inserted and restore | 41 | |
| 42 | point. */ | 42 | /* Delete any uncompressed data already inserted and restore point. */ |
| 43 | if (data->start) { | 43 | if (data->start) |
| 44 | del_range (data->start, PT); | 44 | { |
| 45 | SET_PT (data->old_point); | 45 | del_range (data->start, PT); |
| 46 | } | 46 | SET_PT (data->old_point); |
| 47 | } | ||
| 47 | } | 48 | } |
| 48 | 49 | ||
| 49 | DEFUN ("decompress-gzipped-region", Fdecompress_gzipped_region, | 50 | DEFUN ("decompress-gzipped-region", Fdecompress_gzipped_region, |
| 50 | Sdecompress_gzipped_region, | 51 | Sdecompress_gzipped_region, |
| 51 | 2, 2, 0, | 52 | 2, 2, 0, |
| 52 | doc: /* Decompress a gzip-compressed region. | 53 | doc: /* Decompress a gzip-compressed region. |
| 53 | The text in the region will be replaced by the decompressed data. | 54 | Replace the text in the region by the decompressed data. |
| 54 | On failure, nil is returned and the data is left in place. | 55 | On failure, return nil and leave the data in place. |
| 55 | This function can only be called in unibyte buffers.*/) | 56 | This function can be called only in unibyte buffers. */) |
| 56 | (Lisp_Object start, Lisp_Object end) | 57 | (Lisp_Object start, Lisp_Object end) |
| 57 | { | 58 | { |
| 58 | ptrdiff_t istart, iend, point = PT; | 59 | ptrdiff_t istart, iend, pos_byte; |
| 59 | z_stream stream; | 60 | z_stream stream; |
| 60 | int decompressed; | 61 | int inflate_status; |
| 61 | char out[16384]; | ||
| 62 | struct decompress_unwind_data unwind_data; | 62 | struct decompress_unwind_data unwind_data; |
| 63 | ptrdiff_t count = SPECPDL_INDEX (); | 63 | ptrdiff_t count = SPECPDL_INDEX (); |
| 64 | 64 | ||
| 65 | validate_region (&start, &end); | 65 | validate_region (&start, &end); |
| 66 | 66 | ||
| 67 | if (! NILP (BVAR (current_buffer, enable_multibyte_characters))) | 67 | if (! NILP (BVAR (current_buffer, enable_multibyte_characters))) |
| 68 | error ("This function can only be called in unibyte buffers"); | 68 | error ("This function can be called only in unibyte buffers"); |
| 69 | 69 | ||
| 70 | /* This is a unibyte buffer, so character positions and bytes are | 70 | /* This is a unibyte buffer, so character positions and bytes are |
| 71 | the same. */ | 71 | the same. */ |
| 72 | istart = XINT (start); | 72 | istart = XINT (start); |
| 73 | iend = XINT (end); | 73 | iend = XINT (end); |
| 74 | move_gap_both (iend, iend); | 74 | move_gap_both (iend, iend); |
| @@ -79,49 +79,55 @@ This function can only be called in unibyte buffers.*/) | |||
| 79 | stream.avail_in = 0; | 79 | stream.avail_in = 0; |
| 80 | stream.next_in = Z_NULL; | 80 | stream.next_in = Z_NULL; |
| 81 | 81 | ||
| 82 | /* This magic number apparently means "this is gzip". */ | 82 | /* This magic number apparently means "this is gzip". */ |
| 83 | if (inflateInit2 (&stream, 16 + MAX_WBITS) != Z_OK) | 83 | if (inflateInit2 (&stream, 16 + MAX_WBITS) != Z_OK) |
| 84 | return Qnil; | 84 | return Qnil; |
| 85 | 85 | ||
| 86 | /* We're inserting the decompressed data at the end of the | ||
| 87 | compressed data. */ | ||
| 88 | SET_PT (iend); | ||
| 89 | |||
| 90 | stream.avail_in = iend - istart; | ||
| 91 | stream.next_in = (char *) BYTE_POS_ADDR (istart); | ||
| 92 | |||
| 93 | unwind_data.start = iend; | 86 | unwind_data.start = iend; |
| 94 | unwind_data.stream = &stream; | 87 | unwind_data.stream = &stream; |
| 95 | unwind_data.old_point = point; | 88 | unwind_data.old_point = PT; |
| 89 | |||
| 96 | record_unwind_protect_ptr (unwind_decompress, &unwind_data); | 90 | record_unwind_protect_ptr (unwind_decompress, &unwind_data); |
| 97 | 91 | ||
| 98 | immediate_quit = 1; | 92 | /* Insert the decompressed data at the end of the compressed data. */ |
| 99 | 93 | SET_PT (iend); | |
| 100 | /* Run inflate() on input until the output buffer isn't full. */ | ||
| 101 | do { | ||
| 102 | int result; | ||
| 103 | stream.avail_out = BUFFER_SIZE; | ||
| 104 | stream.next_out = out; | ||
| 105 | result = inflate (&stream, Z_NO_FLUSH); | ||
| 106 | if (result < 0) { | ||
| 107 | unbind_to (count, Qnil); | ||
| 108 | return Qnil; | ||
| 109 | } | ||
| 110 | 94 | ||
| 111 | decompressed = BUFFER_SIZE - stream.avail_out; | 95 | pos_byte = istart; |
| 112 | insert_1_both (out, decompressed, decompressed, 0, 0, 0); | 96 | |
| 113 | QUIT; | 97 | /* Keep calling 'inflate' until it reports an error or end-of-input. */ |
| 114 | } while (stream.avail_out == 0); | 98 | do |
| 99 | { | ||
| 100 | /* Maximum number of bytes that one 'inflate' call should read and write. | ||
| 101 | zlib requires that these values not exceed UINT_MAX. | ||
| 102 | Do not make avail_out too large, as that might unduly delay C-g. */ | ||
| 103 | ptrdiff_t avail_in = min (iend - pos_byte, UINT_MAX); | ||
| 104 | ptrdiff_t avail_out = min (1 << 14, UINT_MAX); | ||
| 105 | |||
| 106 | ptrdiff_t decompressed; | ||
| 107 | |||
| 108 | if (GAP_SIZE < avail_out) | ||
| 109 | make_gap (avail_out - GAP_SIZE); | ||
| 110 | stream.next_in = BYTE_POS_ADDR (pos_byte); | ||
| 111 | stream.avail_in = avail_in; | ||
| 112 | stream.next_out = GPT_ADDR; | ||
| 113 | stream.avail_out = avail_out; | ||
| 114 | inflate_status = inflate (&stream, Z_NO_FLUSH); | ||
| 115 | pos_byte += avail_in - stream.avail_in; | ||
| 116 | decompressed = avail_out - stream.avail_out; | ||
| 117 | insert_from_gap (decompressed, decompressed, 0); | ||
| 118 | QUIT; | ||
| 119 | } | ||
| 120 | while (inflate_status == Z_OK); | ||
| 115 | 121 | ||
| 116 | immediate_quit = 0; | 122 | if (inflate_status != Z_STREAM_END) |
| 123 | return unbind_to (count, Qnil); | ||
| 117 | 124 | ||
| 118 | unwind_data.start = 0; | 125 | unwind_data.start = 0; |
| 119 | unbind_to (count, Qnil); | ||
| 120 | 126 | ||
| 121 | /* Delete the compressed data. */ | 127 | /* Delete the compressed data. */ |
| 122 | del_range (istart, iend); | 128 | del_range (istart, iend); |
| 123 | 129 | ||
| 124 | return Qt; | 130 | return unbind_to (count, Qt); |
| 125 | } | 131 | } |
| 126 | 132 | ||
| 127 | 133 | ||
diff --git a/src/eval.c b/src/eval.c index 8ee259110f4..566be0c2a83 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -3302,6 +3302,16 @@ clear_unwind_protect (ptrdiff_t count) | |||
| 3302 | previous value without invoking it. */ | 3302 | previous value without invoking it. */ |
| 3303 | 3303 | ||
| 3304 | void | 3304 | void |
| 3305 | set_unwind_protect (ptrdiff_t count, void (*func) (Lisp_Object), | ||
| 3306 | Lisp_Object arg) | ||
| 3307 | { | ||
| 3308 | union specbinding *p = specpdl + count; | ||
| 3309 | p->unwind.kind = SPECPDL_UNWIND; | ||
| 3310 | p->unwind.func = func; | ||
| 3311 | p->unwind.arg = arg; | ||
| 3312 | } | ||
| 3313 | |||
| 3314 | void | ||
| 3305 | set_unwind_protect_ptr (ptrdiff_t count, void (*func) (void *), void *arg) | 3315 | set_unwind_protect_ptr (ptrdiff_t count, void (*func) (void *), void *arg) |
| 3306 | { | 3316 | { |
| 3307 | union specbinding *p = specpdl + count; | 3317 | union specbinding *p = specpdl + count; |
diff --git a/src/fileio.c b/src/fileio.c index 6b24e592bb3..6ec5f78c2cf 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -4746,25 +4746,39 @@ This does code conversion according to the value of | |||
| 4746 | 4746 | ||
| 4747 | This calls `write-region-annotate-functions' at the start, and | 4747 | This calls `write-region-annotate-functions' at the start, and |
| 4748 | `write-region-post-annotation-function' at the end. */) | 4748 | `write-region-post-annotation-function' at the end. */) |
| 4749 | (Lisp_Object start, Lisp_Object end, Lisp_Object filename, Lisp_Object append, Lisp_Object visit, Lisp_Object lockname, Lisp_Object mustbenew) | 4749 | (Lisp_Object start, Lisp_Object end, Lisp_Object filename, Lisp_Object append, |
| 4750 | Lisp_Object visit, Lisp_Object lockname, Lisp_Object mustbenew) | ||
| 4751 | { | ||
| 4752 | return write_region (start, end, filename, append, visit, lockname, mustbenew, | ||
| 4753 | -1); | ||
| 4754 | } | ||
| 4755 | |||
| 4756 | /* Like Fwrite_region, except that if DESC is nonnegative, it is a file | ||
| 4757 | descriptor for FILENAME, so do not open or close FILENAME. */ | ||
| 4758 | |||
| 4759 | Lisp_Object | ||
| 4760 | write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename, | ||
| 4761 | Lisp_Object append, Lisp_Object visit, Lisp_Object lockname, | ||
| 4762 | Lisp_Object mustbenew, int desc) | ||
| 4750 | { | 4763 | { |
| 4751 | int desc; | ||
| 4752 | int open_flags; | 4764 | int open_flags; |
| 4753 | int mode; | 4765 | int mode; |
| 4754 | off_t offset IF_LINT (= 0); | 4766 | off_t offset IF_LINT (= 0); |
| 4767 | bool open_and_close_file = desc < 0; | ||
| 4755 | bool ok; | 4768 | bool ok; |
| 4756 | int save_errno = 0; | 4769 | int save_errno = 0; |
| 4757 | const char *fn; | 4770 | const char *fn; |
| 4758 | struct stat st; | 4771 | struct stat st; |
| 4759 | EMACS_TIME modtime; | 4772 | EMACS_TIME modtime; |
| 4760 | ptrdiff_t count = SPECPDL_INDEX (); | 4773 | ptrdiff_t count = SPECPDL_INDEX (); |
| 4761 | ptrdiff_t count1; | 4774 | ptrdiff_t count1 IF_LINT (= 0); |
| 4762 | Lisp_Object handler; | 4775 | Lisp_Object handler; |
| 4763 | Lisp_Object visit_file; | 4776 | Lisp_Object visit_file; |
| 4764 | Lisp_Object annotations; | 4777 | Lisp_Object annotations; |
| 4765 | Lisp_Object encoded_filename; | 4778 | Lisp_Object encoded_filename; |
| 4766 | bool visiting = (EQ (visit, Qt) || STRINGP (visit)); | 4779 | bool visiting = (EQ (visit, Qt) || STRINGP (visit)); |
| 4767 | bool quietly = !NILP (visit); | 4780 | bool quietly = !NILP (visit); |
| 4781 | bool file_locked = 0; | ||
| 4768 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; | 4782 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; |
| 4769 | struct buffer *given_buffer; | 4783 | struct buffer *given_buffer; |
| 4770 | struct coding_system coding; | 4784 | struct coding_system coding; |
| @@ -4832,7 +4846,6 @@ This calls `write-region-annotate-functions' at the start, and | |||
| 4832 | record_unwind_protect (build_annotations_unwind, | 4846 | record_unwind_protect (build_annotations_unwind, |
| 4833 | Vwrite_region_annotation_buffers); | 4847 | Vwrite_region_annotation_buffers); |
| 4834 | Vwrite_region_annotation_buffers = list1 (Fcurrent_buffer ()); | 4848 | Vwrite_region_annotation_buffers = list1 (Fcurrent_buffer ()); |
| 4835 | count1 = SPECPDL_INDEX (); | ||
| 4836 | 4849 | ||
| 4837 | given_buffer = current_buffer; | 4850 | given_buffer = current_buffer; |
| 4838 | 4851 | ||
| @@ -4871,8 +4884,11 @@ This calls `write-region-annotate-functions' at the start, and | |||
| 4871 | coding.mode |= CODING_MODE_SELECTIVE_DISPLAY; | 4884 | coding.mode |= CODING_MODE_SELECTIVE_DISPLAY; |
| 4872 | 4885 | ||
| 4873 | #ifdef CLASH_DETECTION | 4886 | #ifdef CLASH_DETECTION |
| 4874 | if (!auto_saving) | 4887 | if (open_and_close_file && !auto_saving) |
| 4875 | lock_file (lockname); | 4888 | { |
| 4889 | lock_file (lockname); | ||
| 4890 | file_locked = 1; | ||
| 4891 | } | ||
| 4876 | #endif /* CLASH_DETECTION */ | 4892 | #endif /* CLASH_DETECTION */ |
| 4877 | 4893 | ||
| 4878 | encoded_filename = ENCODE_FILE (filename); | 4894 | encoded_filename = ENCODE_FILE (filename); |
| @@ -4889,19 +4905,23 @@ This calls `write-region-annotate-functions' at the start, and | |||
| 4889 | mode = auto_saving ? auto_save_mode_bits : 0666; | 4905 | mode = auto_saving ? auto_save_mode_bits : 0666; |
| 4890 | #endif | 4906 | #endif |
| 4891 | 4907 | ||
| 4892 | desc = emacs_open (fn, open_flags, mode); | 4908 | if (open_and_close_file) |
| 4893 | |||
| 4894 | if (desc < 0) | ||
| 4895 | { | 4909 | { |
| 4896 | int open_errno = errno; | 4910 | desc = emacs_open (fn, open_flags, mode); |
| 4911 | if (desc < 0) | ||
| 4912 | { | ||
| 4913 | int open_errno = errno; | ||
| 4897 | #ifdef CLASH_DETECTION | 4914 | #ifdef CLASH_DETECTION |
| 4898 | if (!auto_saving) unlock_file (lockname); | 4915 | if (file_locked) |
| 4916 | unlock_file (lockname); | ||
| 4899 | #endif /* CLASH_DETECTION */ | 4917 | #endif /* CLASH_DETECTION */ |
| 4900 | UNGCPRO; | 4918 | UNGCPRO; |
| 4901 | report_file_errno ("Opening output file", filename, open_errno); | 4919 | report_file_errno ("Opening output file", filename, open_errno); |
| 4902 | } | 4920 | } |
| 4903 | 4921 | ||
| 4904 | record_unwind_protect_int (close_file_unwind, desc); | 4922 | count1 = SPECPDL_INDEX (); |
| 4923 | record_unwind_protect_int (close_file_unwind, desc); | ||
| 4924 | } | ||
| 4905 | 4925 | ||
| 4906 | if (NUMBERP (append)) | 4926 | if (NUMBERP (append)) |
| 4907 | { | 4927 | { |
| @@ -4910,7 +4930,8 @@ This calls `write-region-annotate-functions' at the start, and | |||
| 4910 | { | 4930 | { |
| 4911 | int lseek_errno = errno; | 4931 | int lseek_errno = errno; |
| 4912 | #ifdef CLASH_DETECTION | 4932 | #ifdef CLASH_DETECTION |
| 4913 | if (!auto_saving) unlock_file (lockname); | 4933 | if (file_locked) |
| 4934 | unlock_file (lockname); | ||
| 4914 | #endif /* CLASH_DETECTION */ | 4935 | #endif /* CLASH_DETECTION */ |
| 4915 | UNGCPRO; | 4936 | UNGCPRO; |
| 4916 | report_file_errno ("Lseek error", filename, lseek_errno); | 4937 | report_file_errno ("Lseek error", filename, lseek_errno); |
| @@ -4945,9 +4966,9 @@ This calls `write-region-annotate-functions' at the start, and | |||
| 4945 | 4966 | ||
| 4946 | immediate_quit = 0; | 4967 | immediate_quit = 0; |
| 4947 | 4968 | ||
| 4948 | /* fsync is not crucial for auto-save files, since they might lose | 4969 | /* fsync is not crucial for temporary files. Nor for auto-save |
| 4949 | some work anyway. */ | 4970 | files, since they might lose some work anyway. */ |
| 4950 | if (!auto_saving && !write_region_inhibit_fsync) | 4971 | if (open_and_close_file && !auto_saving && !write_region_inhibit_fsync) |
| 4951 | { | 4972 | { |
| 4952 | /* Transfer data and metadata to disk, retrying if interrupted. | 4973 | /* Transfer data and metadata to disk, retrying if interrupted. |
| 4953 | fsync can report a write failure here, e.g., due to disk full | 4974 | fsync can report a write failure here, e.g., due to disk full |
| @@ -4971,12 +4992,15 @@ This calls `write-region-annotate-functions' at the start, and | |||
| 4971 | ok = 0, save_errno = errno; | 4992 | ok = 0, save_errno = errno; |
| 4972 | } | 4993 | } |
| 4973 | 4994 | ||
| 4974 | /* NFS can report a write failure now. */ | 4995 | if (open_and_close_file) |
| 4975 | if (emacs_close (desc) < 0) | 4996 | { |
| 4976 | ok = 0, save_errno = errno; | 4997 | /* NFS can report a write failure now. */ |
| 4998 | if (emacs_close (desc) < 0) | ||
| 4999 | ok = 0, save_errno = errno; | ||
| 4977 | 5000 | ||
| 4978 | /* Discard the unwind protect for close_file_unwind. */ | 5001 | /* Discard the unwind protect for close_file_unwind. */ |
| 4979 | specpdl_ptr = specpdl + count1; | 5002 | specpdl_ptr = specpdl + count1; |
| 5003 | } | ||
| 4980 | 5004 | ||
| 4981 | /* Some file systems have a bug where st_mtime is not updated | 5005 | /* Some file systems have a bug where st_mtime is not updated |
| 4982 | properly after a write. For example, CIFS might not see the | 5006 | properly after a write. For example, CIFS might not see the |
| @@ -5052,7 +5076,7 @@ This calls `write-region-annotate-functions' at the start, and | |||
| 5052 | unbind_to (count, Qnil); | 5076 | unbind_to (count, Qnil); |
| 5053 | 5077 | ||
| 5054 | #ifdef CLASH_DETECTION | 5078 | #ifdef CLASH_DETECTION |
| 5055 | if (!auto_saving) | 5079 | if (file_locked) |
| 5056 | unlock_file (lockname); | 5080 | unlock_file (lockname); |
| 5057 | #endif /* CLASH_DETECTION */ | 5081 | #endif /* CLASH_DETECTION */ |
| 5058 | 5082 | ||
diff --git a/src/frame.h b/src/frame.h index 33e4bb71d7a..e44003b15ca 100644 --- a/src/frame.h +++ b/src/frame.h | |||
| @@ -410,6 +410,10 @@ struct frame | |||
| 410 | /* Nonzero means that the pointer is invisible. */ | 410 | /* Nonzero means that the pointer is invisible. */ |
| 411 | unsigned pointer_invisible :1; | 411 | unsigned pointer_invisible :1; |
| 412 | 412 | ||
| 413 | /* Nonzero means that all windows except mini-window and | ||
| 414 | selected window on this frame have frozen window starts. */ | ||
| 415 | unsigned frozen_window_starts : 1; | ||
| 416 | |||
| 413 | /* Nonzero if we should actually display the scroll bars on this frame. */ | 417 | /* Nonzero if we should actually display the scroll bars on this frame. */ |
| 414 | enum vertical_scroll_bar_type vertical_scroll_bar_type; | 418 | enum vertical_scroll_bar_type vertical_scroll_bar_type; |
| 415 | 419 | ||
| @@ -761,6 +765,10 @@ default_pixels_per_inch_y (void) | |||
| 761 | /* Not really implemented. */ | 765 | /* Not really implemented. */ |
| 762 | #define FRAME_WANTS_MODELINE_P(f) (f)->wants_modeline | 766 | #define FRAME_WANTS_MODELINE_P(f) (f)->wants_modeline |
| 763 | 767 | ||
| 768 | /* Nonzero if all windows except selected window and mini window | ||
| 769 | are frozen on frame F. */ | ||
| 770 | #define FRAME_WINDOWS_FROZEN(f) (f)->frozen_window_starts | ||
| 771 | |||
| 764 | /* Nonzero if a size change has been requested for frame F | 772 | /* Nonzero if a size change has been requested for frame F |
| 765 | but not yet really put into effect. This can be true temporarily | 773 | but not yet really put into effect. This can be true temporarily |
| 766 | when an X event comes in at a bad time. */ | 774 | when an X event comes in at a bad time. */ |
diff --git a/src/lisp.h b/src/lisp.h index 13cb9fbcbb7..981ab3f6f0b 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -3751,11 +3751,12 @@ extern Lisp_Object internal_condition_case_n | |||
| 3751 | Lisp_Object, Lisp_Object (*) (Lisp_Object, ptrdiff_t, Lisp_Object *)); | 3751 | Lisp_Object, Lisp_Object (*) (Lisp_Object, ptrdiff_t, Lisp_Object *)); |
| 3752 | extern void specbind (Lisp_Object, Lisp_Object); | 3752 | extern void specbind (Lisp_Object, Lisp_Object); |
| 3753 | extern void record_unwind_protect (void (*) (Lisp_Object), Lisp_Object); | 3753 | extern void record_unwind_protect (void (*) (Lisp_Object), Lisp_Object); |
| 3754 | extern void record_unwind_protect_int (void (*) (int), int); | ||
| 3755 | extern void record_unwind_protect_ptr (void (*) (void *), void *); | 3754 | extern void record_unwind_protect_ptr (void (*) (void *), void *); |
| 3755 | extern void record_unwind_protect_int (void (*) (int), int); | ||
| 3756 | extern void record_unwind_protect_void (void (*) (void)); | 3756 | extern void record_unwind_protect_void (void (*) (void)); |
| 3757 | extern void record_unwind_protect_nothing (void); | 3757 | extern void record_unwind_protect_nothing (void); |
| 3758 | extern void clear_unwind_protect (ptrdiff_t); | 3758 | extern void clear_unwind_protect (ptrdiff_t); |
| 3759 | extern void set_unwind_protect (ptrdiff_t, void (*) (Lisp_Object), Lisp_Object); | ||
| 3759 | extern void set_unwind_protect_ptr (ptrdiff_t, void (*) (void *), void *); | 3760 | extern void set_unwind_protect_ptr (ptrdiff_t, void (*) (void *), void *); |
| 3760 | extern Lisp_Object unbind_to (ptrdiff_t, Lisp_Object); | 3761 | extern Lisp_Object unbind_to (ptrdiff_t, Lisp_Object); |
| 3761 | extern _Noreturn void error (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2); | 3762 | extern _Noreturn void error (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2); |
| @@ -3835,6 +3836,9 @@ extern Lisp_Object Qfile_directory_p; | |||
| 3835 | extern Lisp_Object Qinsert_file_contents; | 3836 | extern Lisp_Object Qinsert_file_contents; |
| 3836 | extern Lisp_Object Qfile_name_history; | 3837 | extern Lisp_Object Qfile_name_history; |
| 3837 | extern Lisp_Object expand_and_dir_to_file (Lisp_Object, Lisp_Object); | 3838 | extern Lisp_Object expand_and_dir_to_file (Lisp_Object, Lisp_Object); |
| 3839 | extern Lisp_Object write_region (Lisp_Object, Lisp_Object, Lisp_Object, | ||
| 3840 | Lisp_Object, Lisp_Object, Lisp_Object, | ||
| 3841 | Lisp_Object, int); | ||
| 3838 | EXFUN (Fread_file_name, 6); /* Not a normal DEFUN. */ | 3842 | EXFUN (Fread_file_name, 6); /* Not a normal DEFUN. */ |
| 3839 | extern void close_file_unwind (int); | 3843 | extern void close_file_unwind (int); |
| 3840 | extern void fclose_unwind (void *); | 3844 | extern void fclose_unwind (void *); |
diff --git a/src/process.c b/src/process.c index 99c707ff97b..a2bcffe5160 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -92,6 +92,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 92 | 92 | ||
| 93 | #include <c-ctype.h> | 93 | #include <c-ctype.h> |
| 94 | #include <sig2str.h> | 94 | #include <sig2str.h> |
| 95 | #include <verify.h> | ||
| 95 | 96 | ||
| 96 | #endif /* subprocesses */ | 97 | #endif /* subprocesses */ |
| 97 | 98 | ||
| @@ -722,6 +723,8 @@ make_process (Lisp_Object name) | |||
| 722 | non-Lisp data, so do it only for slots which should not be zero. */ | 723 | non-Lisp data, so do it only for slots which should not be zero. */ |
| 723 | p->infd = -1; | 724 | p->infd = -1; |
| 724 | p->outfd = -1; | 725 | p->outfd = -1; |
| 726 | for (i = 0; i < PROCESS_OPEN_FDS; i++) | ||
| 727 | p->open_fd[i] = -1; | ||
| 725 | 728 | ||
| 726 | #ifdef HAVE_GNUTLS | 729 | #ifdef HAVE_GNUTLS |
| 727 | p->gnutls_initstage = GNUTLS_STAGE_EMPTY; | 730 | p->gnutls_initstage = GNUTLS_STAGE_EMPTY; |
| @@ -818,13 +821,17 @@ get_process (register Lisp_Object name) | |||
| 818 | treated by the SIGCHLD handler and waitpid has been invoked on them; | 821 | treated by the SIGCHLD handler and waitpid has been invoked on them; |
| 819 | otherwise they might fill up the kernel's process table. | 822 | otherwise they might fill up the kernel's process table. |
| 820 | 823 | ||
| 821 | Some processes created by call-process are also put onto this list. */ | 824 | Some processes created by call-process are also put onto this list. |
| 825 | |||
| 826 | Members of this list are (process-ID . filename) pairs. The | ||
| 827 | process-ID is a number; the filename, if a string, is a file that | ||
| 828 | needs to be removed after the process exits. */ | ||
| 822 | static Lisp_Object deleted_pid_list; | 829 | static Lisp_Object deleted_pid_list; |
| 823 | 830 | ||
| 824 | void | 831 | void |
| 825 | record_deleted_pid (pid_t pid) | 832 | record_deleted_pid (pid_t pid, Lisp_Object filename) |
| 826 | { | 833 | { |
| 827 | deleted_pid_list = Fcons (make_fixnum_or_float (pid), | 834 | deleted_pid_list = Fcons (Fcons (make_fixnum_or_float (pid), filename), |
| 828 | /* GC treated elements set to nil. */ | 835 | /* GC treated elements set to nil. */ |
| 829 | Fdelq (Qnil, deleted_pid_list)); | 836 | Fdelq (Qnil, deleted_pid_list)); |
| 830 | 837 | ||
| @@ -852,7 +859,7 @@ nil, indicating the current buffer's process. */) | |||
| 852 | else | 859 | else |
| 853 | { | 860 | { |
| 854 | if (p->alive) | 861 | if (p->alive) |
| 855 | record_kill_process (p); | 862 | record_kill_process (p, Qnil); |
| 856 | 863 | ||
| 857 | if (p->infd >= 0) | 864 | if (p->infd >= 0) |
| 858 | { | 865 | { |
| @@ -1605,17 +1612,45 @@ start_process_unwind (Lisp_Object proc) | |||
| 1605 | remove_process (proc); | 1612 | remove_process (proc); |
| 1606 | } | 1613 | } |
| 1607 | 1614 | ||
| 1615 | /* If *FD_ADDR is nonnegative, close it, and mark it as closed. */ | ||
| 1616 | |||
| 1617 | static void | ||
| 1618 | close_process_fd (int *fd_addr) | ||
| 1619 | { | ||
| 1620 | int fd = *fd_addr; | ||
| 1621 | if (0 <= fd) | ||
| 1622 | { | ||
| 1623 | *fd_addr = -1; | ||
| 1624 | emacs_close (fd); | ||
| 1625 | } | ||
| 1626 | } | ||
| 1627 | |||
| 1628 | /* Indexes of file descriptors in open_fds. */ | ||
| 1629 | enum | ||
| 1630 | { | ||
| 1631 | /* The pipe from Emacs to its subprocess. */ | ||
| 1632 | SUBPROCESS_STDIN, | ||
| 1633 | WRITE_TO_SUBPROCESS, | ||
| 1634 | |||
| 1635 | /* The main pipe from the subprocess to Emacs. */ | ||
| 1636 | READ_FROM_SUBPROCESS, | ||
| 1637 | SUBPROCESS_STDOUT, | ||
| 1638 | |||
| 1639 | /* The pipe from the subprocess to Emacs that is closed when the | ||
| 1640 | subprocess execs. */ | ||
| 1641 | READ_FROM_EXEC_MONITOR, | ||
| 1642 | EXEC_MONITOR_OUTPUT | ||
| 1643 | }; | ||
| 1644 | |||
| 1645 | verify (PROCESS_OPEN_FDS == EXEC_MONITOR_OUTPUT + 1); | ||
| 1608 | 1646 | ||
| 1609 | static void | 1647 | static void |
| 1610 | create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | 1648 | create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) |
| 1611 | { | 1649 | { |
| 1650 | struct Lisp_Process *p = XPROCESS (process); | ||
| 1612 | int inchannel, outchannel; | 1651 | int inchannel, outchannel; |
| 1613 | pid_t pid; | 1652 | pid_t pid; |
| 1614 | int vfork_errno; | 1653 | int vfork_errno; |
| 1615 | int sv[2]; | ||
| 1616 | #ifndef WINDOWSNT | ||
| 1617 | int wait_child_setup[2]; | ||
| 1618 | #endif | ||
| 1619 | int forkin, forkout; | 1654 | int forkin, forkout; |
| 1620 | bool pty_flag = 0; | 1655 | bool pty_flag = 0; |
| 1621 | char pty_name[PTY_NAME_SIZE]; | 1656 | char pty_name[PTY_NAME_SIZE]; |
| @@ -1629,6 +1664,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1629 | 1664 | ||
| 1630 | if (inchannel >= 0) | 1665 | if (inchannel >= 0) |
| 1631 | { | 1666 | { |
| 1667 | p->open_fd[READ_FROM_SUBPROCESS] = inchannel; | ||
| 1632 | #if ! defined (USG) || defined (USG_SUBTTY_WORKS) | 1668 | #if ! defined (USG) || defined (USG_SUBTTY_WORKS) |
| 1633 | /* On most USG systems it does not work to open the pty's tty here, | 1669 | /* On most USG systems it does not work to open the pty's tty here, |
| 1634 | then close it and reopen it in the child. */ | 1670 | then close it and reopen it in the child. */ |
| @@ -1637,6 +1673,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1637 | forkout = forkin = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0); | 1673 | forkout = forkin = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0); |
| 1638 | if (forkin < 0) | 1674 | if (forkin < 0) |
| 1639 | report_file_error ("Opening pty", Qnil); | 1675 | report_file_error ("Opening pty", Qnil); |
| 1676 | p->open_fd[SUBPROCESS_STDIN] = forkin; | ||
| 1640 | #else | 1677 | #else |
| 1641 | forkin = forkout = -1; | 1678 | forkin = forkout = -1; |
| 1642 | #endif /* not USG, or USG_SUBTTY_WORKS */ | 1679 | #endif /* not USG, or USG_SUBTTY_WORKS */ |
| @@ -1645,23 +1682,17 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1645 | } | 1682 | } |
| 1646 | else | 1683 | else |
| 1647 | { | 1684 | { |
| 1648 | if (emacs_pipe (sv) != 0) | 1685 | if (emacs_pipe (p->open_fd + SUBPROCESS_STDIN) != 0 |
| 1686 | || emacs_pipe (p->open_fd + READ_FROM_SUBPROCESS) != 0) | ||
| 1649 | report_file_error ("Creating pipe", Qnil); | 1687 | report_file_error ("Creating pipe", Qnil); |
| 1650 | inchannel = sv[0]; | 1688 | forkin = p->open_fd[SUBPROCESS_STDIN]; |
| 1651 | forkout = sv[1]; | 1689 | outchannel = p->open_fd[WRITE_TO_SUBPROCESS]; |
| 1652 | if (emacs_pipe (sv) != 0) | 1690 | inchannel = p->open_fd[READ_FROM_SUBPROCESS]; |
| 1653 | { | 1691 | forkout = p->open_fd[SUBPROCESS_STDOUT]; |
| 1654 | int pipe_errno = errno; | ||
| 1655 | emacs_close (inchannel); | ||
| 1656 | emacs_close (forkout); | ||
| 1657 | report_file_errno ("Creating pipe", Qnil, pipe_errno); | ||
| 1658 | } | ||
| 1659 | outchannel = sv[1]; | ||
| 1660 | forkin = sv[0]; | ||
| 1661 | } | 1692 | } |
| 1662 | 1693 | ||
| 1663 | #ifndef WINDOWSNT | 1694 | #ifndef WINDOWSNT |
| 1664 | if (emacs_pipe (wait_child_setup) != 0) | 1695 | if (emacs_pipe (p->open_fd + READ_FROM_EXEC_MONITOR) != 0) |
| 1665 | report_file_error ("Creating pipe", Qnil); | 1696 | report_file_error ("Creating pipe", Qnil); |
| 1666 | #endif | 1697 | #endif |
| 1667 | 1698 | ||
| @@ -1670,16 +1701,16 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1670 | 1701 | ||
| 1671 | /* Record this as an active process, with its channels. */ | 1702 | /* Record this as an active process, with its channels. */ |
| 1672 | chan_process[inchannel] = process; | 1703 | chan_process[inchannel] = process; |
| 1673 | XPROCESS (process)->infd = inchannel; | 1704 | p->infd = inchannel; |
| 1674 | XPROCESS (process)->outfd = outchannel; | 1705 | p->outfd = outchannel; |
| 1675 | 1706 | ||
| 1676 | /* Previously we recorded the tty descriptor used in the subprocess. | 1707 | /* Previously we recorded the tty descriptor used in the subprocess. |
| 1677 | It was only used for getting the foreground tty process, so now | 1708 | It was only used for getting the foreground tty process, so now |
| 1678 | we just reopen the device (see emacs_get_tty_pgrp) as this is | 1709 | we just reopen the device (see emacs_get_tty_pgrp) as this is |
| 1679 | more portable (see USG_SUBTTY_WORKS above). */ | 1710 | more portable (see USG_SUBTTY_WORKS above). */ |
| 1680 | 1711 | ||
| 1681 | XPROCESS (process)->pty_flag = pty_flag; | 1712 | p->pty_flag = pty_flag; |
| 1682 | pset_status (XPROCESS (process), Qrun); | 1713 | pset_status (p, Qrun); |
| 1683 | 1714 | ||
| 1684 | FD_SET (inchannel, &input_wait_mask); | 1715 | FD_SET (inchannel, &input_wait_mask); |
| 1685 | FD_SET (inchannel, &non_keyboard_wait_mask); | 1716 | FD_SET (inchannel, &non_keyboard_wait_mask); |
| @@ -1699,25 +1730,21 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1699 | { | 1730 | { |
| 1700 | Lisp_Object volatile encoded_current_dir_volatile = encoded_current_dir; | 1731 | Lisp_Object volatile encoded_current_dir_volatile = encoded_current_dir; |
| 1701 | Lisp_Object volatile lisp_pty_name_volatile = lisp_pty_name; | 1732 | Lisp_Object volatile lisp_pty_name_volatile = lisp_pty_name; |
| 1702 | Lisp_Object volatile process_volatile = process; | ||
| 1703 | char **volatile new_argv_volatile = new_argv; | 1733 | char **volatile new_argv_volatile = new_argv; |
| 1704 | int volatile forkin_volatile = forkin; | 1734 | int volatile forkin_volatile = forkin; |
| 1705 | int volatile forkout_volatile = forkout; | 1735 | int volatile forkout_volatile = forkout; |
| 1706 | int volatile wait_child_setup_0_volatile = wait_child_setup[0]; | 1736 | struct Lisp_Process *p_volatile = p; |
| 1707 | int volatile wait_child_setup_1_volatile = wait_child_setup[1]; | ||
| 1708 | 1737 | ||
| 1709 | pid = vfork (); | 1738 | pid = vfork (); |
| 1710 | 1739 | ||
| 1711 | encoded_current_dir = encoded_current_dir_volatile; | 1740 | encoded_current_dir = encoded_current_dir_volatile; |
| 1712 | lisp_pty_name = lisp_pty_name_volatile; | 1741 | lisp_pty_name = lisp_pty_name_volatile; |
| 1713 | process = process_volatile; | ||
| 1714 | new_argv = new_argv_volatile; | 1742 | new_argv = new_argv_volatile; |
| 1715 | forkin = forkin_volatile; | 1743 | forkin = forkin_volatile; |
| 1716 | forkout = forkout_volatile; | 1744 | forkout = forkout_volatile; |
| 1717 | wait_child_setup[0] = wait_child_setup_0_volatile; | 1745 | p = p_volatile; |
| 1718 | wait_child_setup[1] = wait_child_setup_1_volatile; | ||
| 1719 | 1746 | ||
| 1720 | pty_flag = XPROCESS (process)->pty_flag; | 1747 | pty_flag = p->pty_flag; |
| 1721 | } | 1748 | } |
| 1722 | 1749 | ||
| 1723 | if (pid == 0) | 1750 | if (pid == 0) |
| @@ -1833,42 +1860,42 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1833 | /* Back in the parent process. */ | 1860 | /* Back in the parent process. */ |
| 1834 | 1861 | ||
| 1835 | vfork_errno = errno; | 1862 | vfork_errno = errno; |
| 1836 | XPROCESS (process)->pid = pid; | 1863 | p->pid = pid; |
| 1837 | if (pid >= 0) | 1864 | if (pid >= 0) |
| 1838 | XPROCESS (process)->alive = 1; | 1865 | p->alive = 1; |
| 1839 | 1866 | ||
| 1840 | /* Stop blocking in the parent. */ | 1867 | /* Stop blocking in the parent. */ |
| 1841 | unblock_child_signal (); | 1868 | unblock_child_signal (); |
| 1842 | unblock_input (); | 1869 | unblock_input (); |
| 1843 | 1870 | ||
| 1844 | if (forkin >= 0) | ||
| 1845 | emacs_close (forkin); | ||
| 1846 | if (forkin != forkout && forkout >= 0) | ||
| 1847 | emacs_close (forkout); | ||
| 1848 | |||
| 1849 | if (pid < 0) | 1871 | if (pid < 0) |
| 1850 | report_file_errno ("Doing vfork", Qnil, vfork_errno); | 1872 | report_file_errno ("Doing vfork", Qnil, vfork_errno); |
| 1851 | else | 1873 | else |
| 1852 | { | 1874 | { |
| 1853 | /* vfork succeeded. */ | 1875 | /* vfork succeeded. */ |
| 1854 | 1876 | ||
| 1877 | /* Close the pipe ends that the child uses, or the child's pty. */ | ||
| 1878 | close_process_fd (&p->open_fd[SUBPROCESS_STDIN]); | ||
| 1879 | close_process_fd (&p->open_fd[SUBPROCESS_STDOUT]); | ||
| 1880 | |||
| 1855 | #ifdef WINDOWSNT | 1881 | #ifdef WINDOWSNT |
| 1856 | register_child (pid, inchannel); | 1882 | register_child (pid, inchannel); |
| 1857 | #endif /* WINDOWSNT */ | 1883 | #endif /* WINDOWSNT */ |
| 1858 | 1884 | ||
| 1859 | pset_tty_name (XPROCESS (process), lisp_pty_name); | 1885 | pset_tty_name (p, lisp_pty_name); |
| 1860 | 1886 | ||
| 1861 | #ifndef WINDOWSNT | 1887 | #ifndef WINDOWSNT |
| 1862 | /* Wait for child_setup to complete in case that vfork is | 1888 | /* Wait for child_setup to complete in case that vfork is |
| 1863 | actually defined as fork. The descriptor wait_child_setup[1] | 1889 | actually defined as fork. The descriptor |
| 1890 | XPROCESS (proc)->open_fd[EXEC_MOINTOR_OUTPUT] | ||
| 1864 | of a pipe is closed at the child side either by close-on-exec | 1891 | of a pipe is closed at the child side either by close-on-exec |
| 1865 | on successful execve or the _exit call in child_setup. */ | 1892 | on successful execve or the _exit call in child_setup. */ |
| 1866 | { | 1893 | { |
| 1867 | char dummy; | 1894 | char dummy; |
| 1868 | 1895 | ||
| 1869 | emacs_close (wait_child_setup[1]); | 1896 | close_process_fd (&p->open_fd[EXEC_MONITOR_OUTPUT]); |
| 1870 | emacs_read (wait_child_setup[0], &dummy, 1); | 1897 | emacs_read (p->open_fd[READ_FROM_EXEC_MONITOR], &dummy, 1); |
| 1871 | emacs_close (wait_child_setup[0]); | 1898 | close_process_fd (&p->open_fd[READ_FROM_EXEC_MONITOR]); |
| 1872 | } | 1899 | } |
| 1873 | #endif | 1900 | #endif |
| 1874 | } | 1901 | } |
| @@ -1877,16 +1904,13 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1877 | static void | 1904 | static void |
| 1878 | create_pty (Lisp_Object process) | 1905 | create_pty (Lisp_Object process) |
| 1879 | { | 1906 | { |
| 1907 | struct Lisp_Process *p = XPROCESS (process); | ||
| 1880 | char pty_name[PTY_NAME_SIZE]; | 1908 | char pty_name[PTY_NAME_SIZE]; |
| 1881 | int inchannel, outchannel; | 1909 | int pty_fd = NILP (Vprocess_connection_type) ? -1 : allocate_pty (pty_name); |
| 1882 | 1910 | ||
| 1883 | inchannel = outchannel = -1; | 1911 | if (pty_fd >= 0) |
| 1884 | |||
| 1885 | if (!NILP (Vprocess_connection_type)) | ||
| 1886 | outchannel = inchannel = allocate_pty (pty_name); | ||
| 1887 | |||
| 1888 | if (inchannel >= 0) | ||
| 1889 | { | 1912 | { |
| 1913 | p->open_fd[SUBPROCESS_STDIN] = pty_fd; | ||
| 1890 | #if ! defined (USG) || defined (USG_SUBTTY_WORKS) | 1914 | #if ! defined (USG) || defined (USG_SUBTTY_WORKS) |
| 1891 | /* On most USG systems it does not work to open the pty's tty here, | 1915 | /* On most USG systems it does not work to open the pty's tty here, |
| 1892 | then close it and reopen it in the child. */ | 1916 | then close it and reopen it in the child. */ |
| @@ -1895,6 +1919,7 @@ create_pty (Lisp_Object process) | |||
| 1895 | int forkout = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0); | 1919 | int forkout = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0); |
| 1896 | if (forkout < 0) | 1920 | if (forkout < 0) |
| 1897 | report_file_error ("Opening pty", Qnil); | 1921 | report_file_error ("Opening pty", Qnil); |
| 1922 | p->open_fd[WRITE_TO_SUBPROCESS] = forkout; | ||
| 1898 | #if defined (DONT_REOPEN_PTY) | 1923 | #if defined (DONT_REOPEN_PTY) |
| 1899 | /* In the case that vfork is defined as fork, the parent process | 1924 | /* In the case that vfork is defined as fork, the parent process |
| 1900 | (Emacs) may send some data before the child process completes | 1925 | (Emacs) may send some data before the child process completes |
| @@ -1903,33 +1928,32 @@ create_pty (Lisp_Object process) | |||
| 1903 | #endif /* DONT_REOPEN_PTY */ | 1928 | #endif /* DONT_REOPEN_PTY */ |
| 1904 | #endif /* not USG, or USG_SUBTTY_WORKS */ | 1929 | #endif /* not USG, or USG_SUBTTY_WORKS */ |
| 1905 | 1930 | ||
| 1906 | fcntl (inchannel, F_SETFL, O_NONBLOCK); | 1931 | fcntl (pty_fd, F_SETFL, O_NONBLOCK); |
| 1907 | fcntl (outchannel, F_SETFL, O_NONBLOCK); | ||
| 1908 | 1932 | ||
| 1909 | /* Record this as an active process, with its channels. | 1933 | /* Record this as an active process, with its channels. |
| 1910 | As a result, child_setup will close Emacs's side of the pipes. */ | 1934 | As a result, child_setup will close Emacs's side of the pipes. */ |
| 1911 | chan_process[inchannel] = process; | 1935 | chan_process[pty_fd] = process; |
| 1912 | XPROCESS (process)->infd = inchannel; | 1936 | p->infd = pty_fd; |
| 1913 | XPROCESS (process)->outfd = outchannel; | 1937 | p->outfd = pty_fd; |
| 1914 | 1938 | ||
| 1915 | /* Previously we recorded the tty descriptor used in the subprocess. | 1939 | /* Previously we recorded the tty descriptor used in the subprocess. |
| 1916 | It was only used for getting the foreground tty process, so now | 1940 | It was only used for getting the foreground tty process, so now |
| 1917 | we just reopen the device (see emacs_get_tty_pgrp) as this is | 1941 | we just reopen the device (see emacs_get_tty_pgrp) as this is |
| 1918 | more portable (see USG_SUBTTY_WORKS above). */ | 1942 | more portable (see USG_SUBTTY_WORKS above). */ |
| 1919 | 1943 | ||
| 1920 | XPROCESS (process)->pty_flag = 1; | 1944 | p->pty_flag = 1; |
| 1921 | pset_status (XPROCESS (process), Qrun); | 1945 | pset_status (p, Qrun); |
| 1922 | setup_process_coding_systems (process); | 1946 | setup_process_coding_systems (process); |
| 1923 | 1947 | ||
| 1924 | FD_SET (inchannel, &input_wait_mask); | 1948 | FD_SET (pty_fd, &input_wait_mask); |
| 1925 | FD_SET (inchannel, &non_keyboard_wait_mask); | 1949 | FD_SET (pty_fd, &non_keyboard_wait_mask); |
| 1926 | if (inchannel > max_process_desc) | 1950 | if (pty_fd > max_process_desc) |
| 1927 | max_process_desc = inchannel; | 1951 | max_process_desc = pty_fd; |
| 1928 | 1952 | ||
| 1929 | pset_tty_name (XPROCESS (process), build_string (pty_name)); | 1953 | pset_tty_name (p, build_string (pty_name)); |
| 1930 | } | 1954 | } |
| 1931 | 1955 | ||
| 1932 | XPROCESS (process)->pid = -2; | 1956 | p->pid = -2; |
| 1933 | } | 1957 | } |
| 1934 | 1958 | ||
| 1935 | 1959 | ||
| @@ -2535,6 +2559,7 @@ usage: (make-serial-process &rest ARGS) */) | |||
| 2535 | p = XPROCESS (proc); | 2559 | p = XPROCESS (proc); |
| 2536 | 2560 | ||
| 2537 | fd = serial_open (port); | 2561 | fd = serial_open (port); |
| 2562 | p->open_fd[SUBPROCESS_STDIN] = fd; | ||
| 2538 | p->infd = fd; | 2563 | p->infd = fd; |
| 2539 | p->outfd = fd; | 2564 | p->outfd = fd; |
| 2540 | if (fd > max_process_desc) | 2565 | if (fd > max_process_desc) |
| @@ -3297,12 +3322,6 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3297 | } | 3322 | } |
| 3298 | #endif | 3323 | #endif |
| 3299 | 3324 | ||
| 3300 | /* Discard the unwind protect for closing S, if any. */ | ||
| 3301 | specpdl_ptr = specpdl + count1; | ||
| 3302 | |||
| 3303 | /* Unwind bind_polling_period and request_sigio. */ | ||
| 3304 | unbind_to (count, Qnil); | ||
| 3305 | |||
| 3306 | if (s < 0) | 3325 | if (s < 0) |
| 3307 | { | 3326 | { |
| 3308 | /* If non-blocking got this far - and failed - assume non-blocking is | 3327 | /* If non-blocking got this far - and failed - assume non-blocking is |
| @@ -3344,8 +3363,17 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3344 | if ((tem = Fplist_get (contact, QCstop), !NILP (tem))) | 3363 | if ((tem = Fplist_get (contact, QCstop), !NILP (tem))) |
| 3345 | pset_command (p, Qt); | 3364 | pset_command (p, Qt); |
| 3346 | p->pid = 0; | 3365 | p->pid = 0; |
| 3366 | |||
| 3367 | p->open_fd[SUBPROCESS_STDIN] = inch; | ||
| 3347 | p->infd = inch; | 3368 | p->infd = inch; |
| 3348 | p->outfd = outch; | 3369 | p->outfd = outch; |
| 3370 | |||
| 3371 | /* Discard the unwind protect for closing S, if any. */ | ||
| 3372 | specpdl_ptr = specpdl + count1; | ||
| 3373 | |||
| 3374 | /* Unwind bind_polling_period and request_sigio. */ | ||
| 3375 | unbind_to (count, Qnil); | ||
| 3376 | |||
| 3349 | if (is_server && socktype != SOCK_DGRAM) | 3377 | if (is_server && socktype != SOCK_DGRAM) |
| 3350 | pset_status (p, Qlisten); | 3378 | pset_status (p, Qlisten); |
| 3351 | 3379 | ||
| @@ -3784,17 +3812,15 @@ FLAGS is the current flags of the interface. */) | |||
| 3784 | static void | 3812 | static void |
| 3785 | deactivate_process (Lisp_Object proc) | 3813 | deactivate_process (Lisp_Object proc) |
| 3786 | { | 3814 | { |
| 3787 | register int inchannel, outchannel; | 3815 | int inchannel; |
| 3788 | register struct Lisp_Process *p = XPROCESS (proc); | 3816 | struct Lisp_Process *p = XPROCESS (proc); |
| 3817 | int i; | ||
| 3789 | 3818 | ||
| 3790 | #ifdef HAVE_GNUTLS | 3819 | #ifdef HAVE_GNUTLS |
| 3791 | /* Delete GnuTLS structures in PROC, if any. */ | 3820 | /* Delete GnuTLS structures in PROC, if any. */ |
| 3792 | emacs_gnutls_deinit (proc); | 3821 | emacs_gnutls_deinit (proc); |
| 3793 | #endif /* HAVE_GNUTLS */ | 3822 | #endif /* HAVE_GNUTLS */ |
| 3794 | 3823 | ||
| 3795 | inchannel = p->infd; | ||
| 3796 | outchannel = p->outfd; | ||
| 3797 | |||
| 3798 | #ifdef ADAPTIVE_READ_BUFFERING | 3824 | #ifdef ADAPTIVE_READ_BUFFERING |
| 3799 | if (p->read_output_delay > 0) | 3825 | if (p->read_output_delay > 0) |
| 3800 | { | 3826 | { |
| @@ -3805,16 +3831,17 @@ deactivate_process (Lisp_Object proc) | |||
| 3805 | } | 3831 | } |
| 3806 | #endif | 3832 | #endif |
| 3807 | 3833 | ||
| 3834 | inchannel = p->infd; | ||
| 3835 | |||
| 3836 | /* Beware SIGCHLD hereabouts. */ | ||
| 3837 | if (inchannel >= 0) | ||
| 3838 | flush_pending_output (inchannel); | ||
| 3839 | |||
| 3840 | for (i = 0; i < PROCESS_OPEN_FDS; i++) | ||
| 3841 | close_process_fd (&p->open_fd[i]); | ||
| 3842 | |||
| 3808 | if (inchannel >= 0) | 3843 | if (inchannel >= 0) |
| 3809 | { | 3844 | { |
| 3810 | /* Beware SIGCHLD hereabouts. */ | ||
| 3811 | flush_pending_output (inchannel); | ||
| 3812 | emacs_close (inchannel); | ||
| 3813 | if (outchannel >= 0 && outchannel != inchannel) | ||
| 3814 | emacs_close (outchannel); | ||
| 3815 | |||
| 3816 | p->infd = -1; | ||
| 3817 | p->outfd = -1; | ||
| 3818 | #ifdef DATAGRAM_SOCKETS | 3845 | #ifdef DATAGRAM_SOCKETS |
| 3819 | if (DATAGRAM_CHAN_P (inchannel)) | 3846 | if (DATAGRAM_CHAN_P (inchannel)) |
| 3820 | { | 3847 | { |
| @@ -4095,6 +4122,7 @@ server_accept_connection (Lisp_Object server, int channel) | |||
| 4095 | /* Discard the unwind protect for closing S. */ | 4122 | /* Discard the unwind protect for closing S. */ |
| 4096 | specpdl_ptr = specpdl + count; | 4123 | specpdl_ptr = specpdl + count; |
| 4097 | 4124 | ||
| 4125 | p->open_fd[SUBPROCESS_STDIN] = s; | ||
| 4098 | p->infd = s; | 4126 | p->infd = s; |
| 4099 | p->outfd = s; | 4127 | p->outfd = s; |
| 4100 | pset_status (p, Qrun); | 4128 | pset_status (p, Qrun); |
| @@ -6014,7 +6042,8 @@ process has been transmitted to the serial port. */) | |||
| 6014 | } | 6042 | } |
| 6015 | else | 6043 | else |
| 6016 | { | 6044 | { |
| 6017 | int old_outfd, new_outfd; | 6045 | int old_outfd = XPROCESS (proc)->outfd; |
| 6046 | int new_outfd; | ||
| 6018 | 6047 | ||
| 6019 | #ifdef HAVE_SHUTDOWN | 6048 | #ifdef HAVE_SHUTDOWN |
| 6020 | /* If this is a network connection, or socketpair is used | 6049 | /* If this is a network connection, or socketpair is used |
| @@ -6022,18 +6051,15 @@ process has been transmitted to the serial port. */) | |||
| 6022 | (In some old system, shutdown to socketpair doesn't work. | 6051 | (In some old system, shutdown to socketpair doesn't work. |
| 6023 | Then we just can't win.) */ | 6052 | Then we just can't win.) */ |
| 6024 | if (EQ (XPROCESS (proc)->type, Qnetwork) | 6053 | if (EQ (XPROCESS (proc)->type, Qnetwork) |
| 6025 | || XPROCESS (proc)->outfd == XPROCESS (proc)->infd) | 6054 | || XPROCESS (proc)->infd == old_outfd) |
| 6026 | shutdown (XPROCESS (proc)->outfd, 1); | 6055 | shutdown (old_outfd, 1); |
| 6027 | /* In case of socketpair, outfd == infd, so don't close it. */ | 6056 | #endif |
| 6028 | if (XPROCESS (proc)->outfd != XPROCESS (proc)->infd) | 6057 | close_process_fd (&XPROCESS (proc)->open_fd[WRITE_TO_SUBPROCESS]); |
| 6029 | emacs_close (XPROCESS (proc)->outfd); | ||
| 6030 | #else /* not HAVE_SHUTDOWN */ | ||
| 6031 | emacs_close (XPROCESS (proc)->outfd); | ||
| 6032 | #endif /* not HAVE_SHUTDOWN */ | ||
| 6033 | new_outfd = emacs_open (NULL_DEVICE, O_WRONLY, 0); | 6058 | new_outfd = emacs_open (NULL_DEVICE, O_WRONLY, 0); |
| 6034 | if (new_outfd < 0) | 6059 | if (new_outfd < 0) |
| 6035 | emacs_abort (); | 6060 | report_file_error ("Opening null device", Qnil); |
| 6036 | old_outfd = XPROCESS (proc)->outfd; | 6061 | XPROCESS (proc)->open_fd[WRITE_TO_SUBPROCESS] = new_outfd; |
| 6062 | XPROCESS (proc)->outfd = new_outfd; | ||
| 6037 | 6063 | ||
| 6038 | if (!proc_encode_coding_system[new_outfd]) | 6064 | if (!proc_encode_coding_system[new_outfd]) |
| 6039 | proc_encode_coding_system[new_outfd] | 6065 | proc_encode_coding_system[new_outfd] |
| @@ -6042,8 +6068,6 @@ process has been transmitted to the serial port. */) | |||
| 6042 | = *proc_encode_coding_system[old_outfd]; | 6068 | = *proc_encode_coding_system[old_outfd]; |
| 6043 | memset (proc_encode_coding_system[old_outfd], 0, | 6069 | memset (proc_encode_coding_system[old_outfd], 0, |
| 6044 | sizeof (struct coding_system)); | 6070 | sizeof (struct coding_system)); |
| 6045 | |||
| 6046 | XPROCESS (proc)->outfd = new_outfd; | ||
| 6047 | } | 6071 | } |
| 6048 | return process; | 6072 | return process; |
| 6049 | } | 6073 | } |
| @@ -6120,7 +6144,8 @@ handle_child_signal (int sig) | |||
| 6120 | bool all_pids_are_fixnums | 6144 | bool all_pids_are_fixnums |
| 6121 | = (MOST_NEGATIVE_FIXNUM <= TYPE_MINIMUM (pid_t) | 6145 | = (MOST_NEGATIVE_FIXNUM <= TYPE_MINIMUM (pid_t) |
| 6122 | && TYPE_MAXIMUM (pid_t) <= MOST_POSITIVE_FIXNUM); | 6146 | && TYPE_MAXIMUM (pid_t) <= MOST_POSITIVE_FIXNUM); |
| 6123 | Lisp_Object xpid = XCAR (tail); | 6147 | Lisp_Object head = XCAR (tail); |
| 6148 | Lisp_Object xpid = XCAR (head); | ||
| 6124 | if (all_pids_are_fixnums ? INTEGERP (xpid) : NUMBERP (xpid)) | 6149 | if (all_pids_are_fixnums ? INTEGERP (xpid) : NUMBERP (xpid)) |
| 6125 | { | 6150 | { |
| 6126 | pid_t deleted_pid; | 6151 | pid_t deleted_pid; |
| @@ -6129,7 +6154,11 @@ handle_child_signal (int sig) | |||
| 6129 | else | 6154 | else |
| 6130 | deleted_pid = XFLOAT_DATA (xpid); | 6155 | deleted_pid = XFLOAT_DATA (xpid); |
| 6131 | if (child_status_changed (deleted_pid, 0, 0)) | 6156 | if (child_status_changed (deleted_pid, 0, 0)) |
| 6132 | XSETCAR (tail, Qnil); | 6157 | { |
| 6158 | if (STRINGP (XCDR (head))) | ||
| 6159 | unlink (SSDATA (XCDR (head))); | ||
| 6160 | XSETCAR (tail, Qnil); | ||
| 6161 | } | ||
| 6133 | } | 6162 | } |
| 6134 | } | 6163 | } |
| 6135 | 6164 | ||
diff --git a/src/process.h b/src/process.h index 8ae33aebf39..b312f7f2425 100644 --- a/src/process.h +++ b/src/process.h | |||
| @@ -31,6 +31,11 @@ INLINE_HEADER_BEGIN | |||
| 31 | # define PROCESS_INLINE INLINE | 31 | # define PROCESS_INLINE INLINE |
| 32 | #endif | 32 | #endif |
| 33 | 33 | ||
| 34 | /* Bound on number of file descriptors opened on behalf of a process, | ||
| 35 | that need to be closed. */ | ||
| 36 | |||
| 37 | enum { PROCESS_OPEN_FDS = 6 }; | ||
| 38 | |||
| 34 | /* This structure records information about a subprocess | 39 | /* This structure records information about a subprocess |
| 35 | or network connection. */ | 40 | or network connection. */ |
| 36 | 41 | ||
| @@ -115,6 +120,9 @@ struct Lisp_Process | |||
| 115 | int infd; | 120 | int infd; |
| 116 | /* Descriptor by which we write to this process */ | 121 | /* Descriptor by which we write to this process */ |
| 117 | int outfd; | 122 | int outfd; |
| 123 | /* Descriptors that were created for this process and that need | ||
| 124 | closing. Unused entries are negative. */ | ||
| 125 | int open_fd[PROCESS_OPEN_FDS]; | ||
| 118 | /* Event-count of last event in which this process changed status. */ | 126 | /* Event-count of last event in which this process changed status. */ |
| 119 | EMACS_INT tick; | 127 | EMACS_INT tick; |
| 120 | /* Event-count of last such event reported. */ | 128 | /* Event-count of last such event reported. */ |
| @@ -210,13 +218,16 @@ enum | |||
| 210 | 218 | ||
| 211 | extern void block_child_signal (void); | 219 | extern void block_child_signal (void); |
| 212 | extern void unblock_child_signal (void); | 220 | extern void unblock_child_signal (void); |
| 213 | extern void record_kill_process (struct Lisp_Process *); | 221 | extern void record_kill_process (struct Lisp_Process *, Lisp_Object); |
| 214 | 222 | ||
| 215 | /* Defined in process.c. */ | 223 | /* Defined in sysdep.c. */ |
| 216 | 224 | ||
| 217 | extern Lisp_Object list_system_processes (void); | 225 | extern Lisp_Object list_system_processes (void); |
| 218 | extern Lisp_Object system_process_attributes (Lisp_Object); | 226 | extern Lisp_Object system_process_attributes (Lisp_Object); |
| 219 | 227 | ||
| 228 | /* Defined in process.c. */ | ||
| 229 | |||
| 230 | extern void record_deleted_pid (pid_t, Lisp_Object); | ||
| 220 | extern void hold_keyboard_input (void); | 231 | extern void hold_keyboard_input (void); |
| 221 | extern void unhold_keyboard_input (void); | 232 | extern void unhold_keyboard_input (void); |
| 222 | extern bool kbd_on_hold_p (void); | 233 | extern bool kbd_on_hold_p (void); |
diff --git a/src/syswait.h b/src/syswait.h index 03e5cb5fe2e..4ae9129d7ed 100644 --- a/src/syswait.h +++ b/src/syswait.h | |||
| @@ -52,9 +52,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 52 | #define WTERMSIG(status) ((status) & 0x7f) | 52 | #define WTERMSIG(status) ((status) & 0x7f) |
| 53 | #endif | 53 | #endif |
| 54 | 54 | ||
| 55 | /* Defined in process.c. */ | ||
| 56 | extern void record_deleted_pid (pid_t); | ||
| 57 | |||
| 58 | /* Defined in sysdep.c. */ | 55 | /* Defined in sysdep.c. */ |
| 59 | extern void wait_for_termination (pid_t, int *, bool); | 56 | extern void wait_for_termination (pid_t, int *, bool); |
| 60 | extern pid_t child_status_changed (pid_t, int *, int); | 57 | extern pid_t child_status_changed (pid_t, int *, int); |
diff --git a/src/window.c b/src/window.c index 921ea86b3d2..82639b6d8ce 100644 --- a/src/window.c +++ b/src/window.c | |||
| @@ -72,7 +72,6 @@ static int get_leaf_windows (struct window *, struct window **, int); | |||
| 72 | static void window_scroll (Lisp_Object, EMACS_INT, bool, int); | 72 | static void window_scroll (Lisp_Object, EMACS_INT, bool, int); |
| 73 | static void window_scroll_pixel_based (Lisp_Object, int, bool, int); | 73 | static void window_scroll_pixel_based (Lisp_Object, int, bool, int); |
| 74 | static void window_scroll_line_based (Lisp_Object, int, bool, int); | 74 | static void window_scroll_line_based (Lisp_Object, int, bool, int); |
| 75 | static int freeze_window_start (struct window *, void *); | ||
| 76 | static Lisp_Object window_list (void); | 75 | static Lisp_Object window_list (void); |
| 77 | static int add_window_to_list (struct window *, void *); | 76 | static int add_window_to_list (struct window *, void *); |
| 78 | static Lisp_Object next_window (Lisp_Object, Lisp_Object, | 77 | static Lisp_Object next_window (Lisp_Object, Lisp_Object, |
| @@ -502,7 +501,6 @@ select_window (Lisp_Object window, Lisp_Object norecord, int inhibit_point_swap) | |||
| 502 | CHECK_LIVE_WINDOW (window); | 501 | CHECK_LIVE_WINDOW (window); |
| 503 | 502 | ||
| 504 | w = XWINDOW (window); | 503 | w = XWINDOW (window); |
| 505 | w->frozen_window_start_p = 0; | ||
| 506 | 504 | ||
| 507 | /* Make the selected window's buffer current. */ | 505 | /* Make the selected window's buffer current. */ |
| 508 | Fset_buffer (w->contents); | 506 | Fset_buffer (w->contents); |
| @@ -2058,7 +2056,6 @@ replace_window (Lisp_Object old, Lisp_Object new, int setflag) | |||
| 2058 | wset_window_end_vpos (n, make_number (0)); | 2056 | wset_window_end_vpos (n, make_number (0)); |
| 2059 | wset_window_end_pos (n, make_number (0)); | 2057 | wset_window_end_pos (n, make_number (0)); |
| 2060 | n->window_end_valid = 0; | 2058 | n->window_end_valid = 0; |
| 2061 | n->frozen_window_start_p = 0; | ||
| 2062 | } | 2059 | } |
| 2063 | 2060 | ||
| 2064 | tem = o->next; | 2061 | tem = o->next; |
| @@ -6459,38 +6456,6 @@ foreach_window_1 (struct window *w, int (*fn) (struct window *, void *), void *u | |||
| 6459 | return cont; | 6456 | return cont; |
| 6460 | } | 6457 | } |
| 6461 | 6458 | ||
| 6462 | |||
| 6463 | /* Freeze or unfreeze the window start of W unless it is a | ||
| 6464 | mini-window or the selected window. FREEZE_P non-null means freeze | ||
| 6465 | the window start. */ | ||
| 6466 | |||
| 6467 | static int | ||
| 6468 | freeze_window_start (struct window *w, void *freeze_p) | ||
| 6469 | { | ||
| 6470 | if (MINI_WINDOW_P (w) | ||
| 6471 | || (WINDOWP (selected_window) /* Can be nil in corner cases. */ | ||
| 6472 | && (w == XWINDOW (selected_window) | ||
| 6473 | || (MINI_WINDOW_P (XWINDOW (selected_window)) | ||
| 6474 | && ! NILP (Vminibuf_scroll_window) | ||
| 6475 | && w == XWINDOW (Vminibuf_scroll_window))))) | ||
| 6476 | freeze_p = NULL; | ||
| 6477 | |||
| 6478 | w->frozen_window_start_p = freeze_p != NULL; | ||
| 6479 | return 1; | ||
| 6480 | } | ||
| 6481 | |||
| 6482 | |||
| 6483 | /* Freeze or unfreeze the window starts of all leaf windows on frame | ||
| 6484 | F, except the selected window and a mini-window. FREEZE_P non-zero | ||
| 6485 | means freeze the window start. */ | ||
| 6486 | |||
| 6487 | void | ||
| 6488 | freeze_window_starts (struct frame *f, bool freeze_p) | ||
| 6489 | { | ||
| 6490 | foreach_window (f, freeze_window_start, freeze_p ? f : 0); | ||
| 6491 | } | ||
| 6492 | |||
| 6493 | |||
| 6494 | /*********************************************************************** | 6459 | /*********************************************************************** |
| 6495 | Initialization | 6460 | Initialization |
| 6496 | ***********************************************************************/ | 6461 | ***********************************************************************/ |
diff --git a/src/window.h b/src/window.h index 24949e1e287..260a672d93a 100644 --- a/src/window.h +++ b/src/window.h | |||
| @@ -316,11 +316,6 @@ struct window | |||
| 316 | Currently only used for menu bar windows of frames. */ | 316 | Currently only used for menu bar windows of frames. */ |
| 317 | unsigned pseudo_window_p : 1; | 317 | unsigned pseudo_window_p : 1; |
| 318 | 318 | ||
| 319 | /* 1 means the window start of this window is frozen and may not | ||
| 320 | be changed during redisplay. If point is not in the window, | ||
| 321 | accept that. */ | ||
| 322 | unsigned frozen_window_start_p : 1; | ||
| 323 | |||
| 324 | /* Non-zero means fringes are drawn outside display margins. | 319 | /* Non-zero means fringes are drawn outside display margins. |
| 325 | Otherwise draw them between margin areas and text. */ | 320 | Otherwise draw them between margin areas and text. */ |
| 326 | unsigned fringes_outside_margins : 1; | 321 | unsigned fringes_outside_margins : 1; |
| @@ -888,7 +883,6 @@ extern Lisp_Object window_from_coordinates (struct frame *, int, int, | |||
| 888 | extern void resize_frame_windows (struct frame *, int, bool); | 883 | extern void resize_frame_windows (struct frame *, int, bool); |
| 889 | extern void restore_window_configuration (Lisp_Object); | 884 | extern void restore_window_configuration (Lisp_Object); |
| 890 | extern void delete_all_child_windows (Lisp_Object); | 885 | extern void delete_all_child_windows (Lisp_Object); |
| 891 | extern void freeze_window_starts (struct frame *, bool); | ||
| 892 | extern void grow_mini_window (struct window *, int); | 886 | extern void grow_mini_window (struct window *, int); |
| 893 | extern void shrink_mini_window (struct window *); | 887 | extern void shrink_mini_window (struct window *); |
| 894 | extern int window_relative_x_coord (struct window *, enum window_part, int); | 888 | extern int window_relative_x_coord (struct window *, enum window_part, int); |
diff --git a/src/xdisp.c b/src/xdisp.c index 9f734981ce9..42b7977687e 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -10516,7 +10516,8 @@ resize_mini_window (struct window *w, int exact_p) | |||
| 10516 | if (height > WINDOW_TOTAL_LINES (w)) | 10516 | if (height > WINDOW_TOTAL_LINES (w)) |
| 10517 | { | 10517 | { |
| 10518 | int old_height = WINDOW_TOTAL_LINES (w); | 10518 | int old_height = WINDOW_TOTAL_LINES (w); |
| 10519 | freeze_window_starts (f, 1); | 10519 | |
| 10520 | FRAME_WINDOWS_FROZEN (f) = 1; | ||
| 10520 | grow_mini_window (w, height - WINDOW_TOTAL_LINES (w)); | 10521 | grow_mini_window (w, height - WINDOW_TOTAL_LINES (w)); |
| 10521 | window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height; | 10522 | window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height; |
| 10522 | } | 10523 | } |
| @@ -10524,7 +10525,8 @@ resize_mini_window (struct window *w, int exact_p) | |||
| 10524 | && (exact_p || BEGV == ZV)) | 10525 | && (exact_p || BEGV == ZV)) |
| 10525 | { | 10526 | { |
| 10526 | int old_height = WINDOW_TOTAL_LINES (w); | 10527 | int old_height = WINDOW_TOTAL_LINES (w); |
| 10527 | freeze_window_starts (f, 0); | 10528 | |
| 10529 | FRAME_WINDOWS_FROZEN (f) = 0; | ||
| 10528 | shrink_mini_window (w); | 10530 | shrink_mini_window (w); |
| 10529 | window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height; | 10531 | window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height; |
| 10530 | } | 10532 | } |
| @@ -10535,19 +10537,21 @@ resize_mini_window (struct window *w, int exact_p) | |||
| 10535 | if (height > WINDOW_TOTAL_LINES (w)) | 10537 | if (height > WINDOW_TOTAL_LINES (w)) |
| 10536 | { | 10538 | { |
| 10537 | int old_height = WINDOW_TOTAL_LINES (w); | 10539 | int old_height = WINDOW_TOTAL_LINES (w); |
| 10538 | freeze_window_starts (f, 1); | 10540 | |
| 10541 | FRAME_WINDOWS_FROZEN (f) = 1; | ||
| 10539 | grow_mini_window (w, height - WINDOW_TOTAL_LINES (w)); | 10542 | grow_mini_window (w, height - WINDOW_TOTAL_LINES (w)); |
| 10540 | window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height; | 10543 | window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height; |
| 10541 | } | 10544 | } |
| 10542 | else if (height < WINDOW_TOTAL_LINES (w)) | 10545 | else if (height < WINDOW_TOTAL_LINES (w)) |
| 10543 | { | 10546 | { |
| 10544 | int old_height = WINDOW_TOTAL_LINES (w); | 10547 | int old_height = WINDOW_TOTAL_LINES (w); |
| 10545 | freeze_window_starts (f, 0); | 10548 | |
| 10549 | FRAME_WINDOWS_FROZEN (f) = 0; | ||
| 10546 | shrink_mini_window (w); | 10550 | shrink_mini_window (w); |
| 10547 | 10551 | ||
| 10548 | if (height) | 10552 | if (height) |
| 10549 | { | 10553 | { |
| 10550 | freeze_window_starts (f, 1); | 10554 | FRAME_WINDOWS_FROZEN (f) = 1; |
| 10551 | grow_mini_window (w, height - WINDOW_TOTAL_LINES (w)); | 10555 | grow_mini_window (w, height - WINDOW_TOTAL_LINES (w)); |
| 10552 | } | 10556 | } |
| 10553 | 10557 | ||
| @@ -10930,6 +10934,31 @@ mode_line_update_needed (struct window *w) | |||
| 10930 | && (w->column_number_displayed != current_column ())); | 10934 | && (w->column_number_displayed != current_column ())); |
| 10931 | } | 10935 | } |
| 10932 | 10936 | ||
| 10937 | /* Nonzero if window start of W is frozen and may not be changed during | ||
| 10938 | redisplay. */ | ||
| 10939 | |||
| 10940 | static bool | ||
| 10941 | window_frozen_p (struct window *w) | ||
| 10942 | { | ||
| 10943 | if (FRAME_WINDOWS_FROZEN (XFRAME (WINDOW_FRAME (w)))) | ||
| 10944 | { | ||
| 10945 | Lisp_Object window; | ||
| 10946 | |||
| 10947 | XSETWINDOW (window, w); | ||
| 10948 | if (MINI_WINDOW_P (w)) | ||
| 10949 | return 0; | ||
| 10950 | else if (EQ (window, selected_window)) | ||
| 10951 | return 0; | ||
| 10952 | else if (MINI_WINDOW_P (XWINDOW (selected_window)) | ||
| 10953 | && EQ (window, Vminibuf_scroll_window)) | ||
| 10954 | /* This special window can't be frozen too. */ | ||
| 10955 | return 0; | ||
| 10956 | else | ||
| 10957 | return 1; | ||
| 10958 | } | ||
| 10959 | return 0; | ||
| 10960 | } | ||
| 10961 | |||
| 10933 | /*********************************************************************** | 10962 | /*********************************************************************** |
| 10934 | Mode Lines and Frame Titles | 10963 | Mode Lines and Frame Titles |
| 10935 | ***********************************************************************/ | 10964 | ***********************************************************************/ |
| @@ -15573,7 +15602,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) | |||
| 15573 | 15602 | ||
| 15574 | /* Handle case where place to start displaying has been specified, | 15603 | /* Handle case where place to start displaying has been specified, |
| 15575 | unless the specified location is outside the accessible range. */ | 15604 | unless the specified location is outside the accessible range. */ |
| 15576 | if (w->force_start || w->frozen_window_start_p) | 15605 | if (w->force_start || window_frozen_p (w)) |
| 15577 | { | 15606 | { |
| 15578 | /* We set this later on if we have to adjust point. */ | 15607 | /* We set this later on if we have to adjust point. */ |
| 15579 | int new_vpos = -1; | 15608 | int new_vpos = -1; |
| @@ -15618,7 +15647,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) | |||
| 15618 | goto need_larger_matrices; | 15647 | goto need_larger_matrices; |
| 15619 | } | 15648 | } |
| 15620 | 15649 | ||
| 15621 | if (w->cursor.vpos < 0 && !w->frozen_window_start_p) | 15650 | if (w->cursor.vpos < 0 && !window_frozen_p (w)) |
| 15622 | { | 15651 | { |
| 15623 | /* If point does not appear, try to move point so it does | 15652 | /* If point does not appear, try to move point so it does |
| 15624 | appear. The desired matrix has been built above, so we | 15653 | appear. The desired matrix has been built above, so we |