Mercurial > hg > xemacs-beta
comparison lisp/process.el @ 428:3ecd8885ac67 r21-2-22
Import from CVS: tag r21-2-22
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:28:15 +0200 |
parents | |
children | 84b14dcb0985 |
comparison
equal
deleted
inserted
replaced
427:0a0253eac470 | 428:3ecd8885ac67 |
---|---|
1 ;;; process.el --- commands for subprocesses; split out of simple.el | |
2 | |
3 ;; Copyright (C) 1985-7, 1993,4, 1997 Free Software Foundation, Inc. | |
4 ;; Copyright (C) 1995 Ben Wing. | |
5 | |
6 ;; Author: Ben Wing | |
7 ;; Maintainer: XEmacs Development Team | |
8 ;; Keywords: internal, processes, dumped | |
9 | |
10 ;; This file is part of XEmacs. | |
11 | |
12 ;; XEmacs is free software; you can redistribute it and/or modify it | |
13 ;; under the terms of the GNU General Public License as published by | |
14 ;; the Free Software Foundation; either version 2, or (at your option) | |
15 ;; any later version. | |
16 | |
17 ;; XEmacs is distributed in the hope that it will be useful, but | |
18 ;; WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
20 ;; General Public License for more details. | |
21 | |
22 ;; You should have received a copy of the GNU General Public License | |
23 ;; along with XEmacs; see the file COPYING. If not, write to the | |
24 ;; Free Software Foundation, 59 Temple Place - Suite 330, | |
25 ;; Boston, MA 02111-1307, USA. | |
26 | |
27 ;;; Synched up with: FSF 19.30. | |
28 | |
29 ;;; Commentary: | |
30 | |
31 ;; This file is dumped with XEmacs. | |
32 | |
33 ;;; Code: | |
34 | |
35 | |
36 (defvar binary-process-output) | |
37 (defvar buffer-file-type) | |
38 | |
39 (defgroup processes nil | |
40 "Process, subshell, compilation, and job control support." | |
41 :group 'external | |
42 :group 'development) | |
43 | |
44 (defgroup processes-basics nil | |
45 "Basic stuff dealing with processes." | |
46 :group 'processes) | |
47 | |
48 (defgroup execute nil | |
49 "Executing external commands." | |
50 :group 'processes) | |
51 | |
52 | |
53 (defvar shell-command-switch "-c" | |
54 "Switch used to have the shell execute its command line argument.") | |
55 | |
56 (defun start-process-shell-command (name buffer &rest args) | |
57 "Start a program in a subprocess. Return the process object for it. | |
58 Args are NAME BUFFER COMMAND &rest COMMAND-ARGS. | |
59 NAME is name for process. It is modified if necessary to make it unique. | |
60 BUFFER is the buffer or (buffer-name) to associate with the process. | |
61 Process output goes at end of that buffer, unless you specify | |
62 an output stream or filter function to handle the output. | |
63 BUFFER may be also nil, meaning that this process is not associated | |
64 with any buffer | |
65 Third arg is command name, the name of a shell command. | |
66 Remaining arguments are the arguments for the command. | |
67 Wildcards and redirection are handled as usual in the shell." | |
68 ;; We used to use `exec' to replace the shell with the command, | |
69 ;; but that failed to handle (...) and semicolon, etc. | |
70 (start-process name buffer shell-file-name shell-command-switch | |
71 (mapconcat #'identity args " "))) | |
72 | |
73 (defun call-process (program &optional infile buffer displayp &rest args) | |
74 "Call PROGRAM synchronously in separate process. | |
75 The program's input comes from file INFILE (nil means `/dev/null'). | |
76 Insert output in BUFFER before point; t means current buffer; | |
77 nil for BUFFER means discard it; 0 means discard and don't wait. | |
78 BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case, | |
79 REAL-BUFFER says what to do with standard output, as above, | |
80 while STDERR-FILE says what to do with standard error in the child. | |
81 STDERR-FILE may be nil (discard standard error output), | |
82 t (mix it with ordinary output), or a file name string. | |
83 | |
84 Fourth arg DISPLAYP non-nil means redisplay buffer as output is inserted. | |
85 Remaining arguments are strings passed as command arguments to PROGRAM. | |
86 | |
87 If BUFFER is 0, `call-process' returns immediately with value nil. | |
88 Otherwise it waits for PROGRAM to terminate and returns a numeric exit status | |
89 or a signal description string. | |
90 If you quit, the process is killed with SIGINT, or SIGKILL if you | |
91 quit again." | |
92 (apply 'call-process-internal program infile buffer displayp args)) | |
93 | |
94 (defun call-process-region (start end program | |
95 &optional deletep buffer displayp | |
96 &rest args) | |
97 "Send text from START to END to a synchronous process running PROGRAM. | |
98 Delete the text if fourth arg DELETEP is non-nil. | |
99 | |
100 Insert output in BUFFER before point; t means current buffer; | |
101 nil for BUFFER means discard it; 0 means discard and don't wait. | |
102 BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case, | |
103 REAL-BUFFER says what to do with standard output, as above, | |
104 while STDERR-FILE says what to do with standard error in the child. | |
105 STDERR-FILE may be nil (discard standard error output), | |
106 t (mix it with ordinary output), or a file name string. | |
107 | |
108 Sixth arg DISPLAYP non-nil means redisplay buffer as output is inserted. | |
109 Remaining args are passed to PROGRAM at startup as command args. | |
110 | |
111 If BUFFER is 0, returns immediately with value nil. | |
112 Otherwise waits for PROGRAM to terminate | |
113 and returns a numeric exit status or a signal description string. | |
114 If you quit, the process is first killed with SIGINT, then with SIGKILL if | |
115 you quit again before the process exits." | |
116 (let ((temp | |
117 (make-temp-name | |
118 (concat (file-name-as-directory (temp-directory)) | |
119 (if (memq system-type '(ms-dos windows-nt)) "em" "emacs"))))) | |
120 (unwind-protect | |
121 (progn | |
122 (if (memq system-type '(ms-dos windows-nt)) | |
123 (let ((buffer-file-type binary-process-output)) | |
124 (write-region start end temp nil 'silent)) | |
125 (write-region start end temp nil 'silent)) | |
126 (if deletep (delete-region start end)) | |
127 (apply #'call-process program temp buffer displayp args)) | |
128 (ignore-file-errors (delete-file temp))))) | |
129 | |
130 | |
131 (defun shell-command (command &optional output-buffer) | |
132 "Execute string COMMAND in inferior shell; display output, if any. | |
133 | |
134 If COMMAND ends in ampersand, execute it asynchronously. | |
135 The output appears in the buffer `*Async Shell Command*'. | |
136 That buffer is in shell mode. | |
137 | |
138 Otherwise, COMMAND is executed synchronously. The output appears in the | |
139 buffer `*Shell Command Output*'. | |
140 If the output is one line, it is displayed in the echo area *as well*, | |
141 but it is nonetheless available in buffer `*Shell Command Output*', | |
142 even though that buffer is not automatically displayed. | |
143 If there is no output, or if output is inserted in the current buffer, | |
144 then `*Shell Command Output*' is deleted. | |
145 | |
146 The optional second argument OUTPUT-BUFFER, if non-nil, | |
147 says to put the output in some other buffer. | |
148 If OUTPUT-BUFFER is a buffer or buffer name, put the output there. | |
149 If OUTPUT-BUFFER is not a buffer and not nil, | |
150 insert output in current buffer. (This cannot be done asynchronously.) | |
151 In either case, the output is inserted after point (leaving mark after it)." | |
152 (interactive (list (read-shell-command "Shell command: ") | |
153 current-prefix-arg)) | |
154 (if (and output-buffer | |
155 (not (or (bufferp output-buffer) (stringp output-buffer)))) | |
156 (progn (barf-if-buffer-read-only) | |
157 (push-mark) | |
158 ;; We do not use -f for csh; we will not support broken use of | |
159 ;; .cshrcs. Even the BSD csh manual says to use | |
160 ;; "if ($?prompt) exit" before things which are not useful | |
161 ;; non-interactively. Besides, if someone wants their other | |
162 ;; aliases for shell commands then they can still have them. | |
163 (call-process shell-file-name nil t nil | |
164 shell-command-switch command) | |
165 (exchange-point-and-mark t)) | |
166 ;; Preserve the match data in case called from a program. | |
167 (save-match-data | |
168 (if (string-match "[ \t]*&[ \t]*$" command) | |
169 ;; Command ending with ampersand means asynchronous. | |
170 (progn | |
171 (background (substring command 0 (match-beginning 0)))) | |
172 (shell-command-on-region (point) (point) command output-buffer))))) | |
173 | |
174 ;; We have a sentinel to prevent insertion of a termination message | |
175 ;; in the buffer itself. | |
176 (defun shell-command-sentinel (process signal) | |
177 (if (memq (process-status process) '(exit signal)) | |
178 (message "%s: %s." | |
179 (car (cdr (cdr (process-command process)))) | |
180 (substring signal 0 -1)))) | |
181 | |
182 (defun shell-command-on-region (start end command | |
183 &optional output-buffer replace) | |
184 "Execute string COMMAND in inferior shell with region as input. | |
185 Normally display output (if any) in temp buffer `*Shell Command Output*'; | |
186 Prefix arg means replace the region with it. | |
187 | |
188 The noninteractive arguments are START, END, COMMAND, OUTPUT-BUFFER, REPLACE. | |
189 If REPLACE is non-nil, that means insert the output | |
190 in place of text from START to END, putting point and mark around it. | |
191 | |
192 If the output is one line, it is displayed in the echo area, | |
193 but it is nonetheless available in buffer `*Shell Command Output*' | |
194 even though that buffer is not automatically displayed. | |
195 If there is no output, or if output is inserted in the current buffer, | |
196 then `*Shell Command Output*' is deleted. | |
197 | |
198 If the optional fourth argument OUTPUT-BUFFER is non-nil, | |
199 that says to put the output in some other buffer. | |
200 If OUTPUT-BUFFER is a buffer or buffer name, put the output there. | |
201 If OUTPUT-BUFFER is not a buffer and not nil, | |
202 insert output in the current buffer. | |
203 In either case, the output is inserted after point (leaving mark after it)." | |
204 (interactive (let ((string | |
205 ;; Do this before calling region-beginning | |
206 ;; and region-end, in case subprocess output | |
207 ;; relocates them while we are in the minibuffer. | |
208 (read-shell-command "Shell command on region: "))) | |
209 ;; call-interactively recognizes region-beginning and | |
210 ;; region-end specially, leaving them in the history. | |
211 (list (region-beginning) (region-end) | |
212 string | |
213 current-prefix-arg | |
214 current-prefix-arg))) | |
215 (if (or replace | |
216 (and output-buffer | |
217 (not (or (bufferp output-buffer) (stringp output-buffer))))) | |
218 ;; Replace specified region with output from command. | |
219 (let ((swap (and replace (< start end)))) | |
220 ;; Don't muck with mark unless REPLACE says we should. | |
221 (goto-char start) | |
222 (and replace (push-mark)) | |
223 (call-process-region start end shell-file-name t t nil | |
224 shell-command-switch command) | |
225 (let ((shell-buffer (get-buffer "*Shell Command Output*"))) | |
226 (and shell-buffer (not (eq shell-buffer (current-buffer))) | |
227 (kill-buffer shell-buffer))) | |
228 ;; Don't muck with mark unless REPLACE says we should. | |
229 (and replace swap (exchange-point-and-mark t))) | |
230 ;; No prefix argument: put the output in a temp buffer, | |
231 ;; replacing its entire contents. | |
232 (let ((buffer (get-buffer-create | |
233 (or output-buffer "*Shell Command Output*"))) | |
234 (success nil) | |
235 (exit-status nil) | |
236 (directory default-directory)) | |
237 (unwind-protect | |
238 (if (eq buffer (current-buffer)) | |
239 ;; If the input is the same buffer as the output, | |
240 ;; delete everything but the specified region, | |
241 ;; then replace that region with the output. | |
242 (progn (setq buffer-read-only nil) | |
243 (delete-region (max start end) (point-max)) | |
244 (delete-region (point-min) (max start end)) | |
245 (setq exit-status | |
246 (call-process-region (point-min) (point-max) | |
247 shell-file-name t t nil | |
248 shell-command-switch command)) | |
249 (setq success t)) | |
250 ;; Clear the output buffer, | |
251 ;; then run the command with output there. | |
252 (save-excursion | |
253 (set-buffer buffer) | |
254 (setq buffer-read-only nil) | |
255 ;; XEmacs change | |
256 (setq default-directory directory) | |
257 (erase-buffer)) | |
258 (setq exit-status | |
259 (call-process-region start end shell-file-name | |
260 nil buffer nil | |
261 shell-command-switch command)) | |
262 (setq success t)) | |
263 ;; Report the amount of output. | |
264 (let ((lines (save-excursion | |
265 (set-buffer buffer) | |
266 (if (= (buffer-size) 0) | |
267 0 | |
268 (count-lines (point-min) (point-max)))))) | |
269 (cond ((= lines 0) | |
270 (if success | |
271 (display-message | |
272 'command | |
273 (if (eql exit-status 0) | |
274 "(Shell command succeeded with no output)" | |
275 "(Shell command failed with no output)"))) | |
276 (kill-buffer buffer)) | |
277 ((and success (= lines 1)) | |
278 (message "%s" | |
279 (save-excursion | |
280 (set-buffer buffer) | |
281 (goto-char (point-min)) | |
282 (buffer-substring (point) | |
283 (progn (end-of-line) | |
284 (point)))))) | |
285 (t | |
286 (set-window-start (display-buffer buffer) 1)))))))) | |
287 | |
288 | |
289 (defun start-process (name buffer program &rest program-args) | |
290 "Start a program in a subprocess. Return the process object for it. | |
291 Args are NAME BUFFER PROGRAM &rest PROGRAM-ARGS | |
292 NAME is name for process. It is modified if necessary to make it unique. | |
293 BUFFER is the buffer or (buffer-name) to associate with the process. | |
294 Process output goes at end of that buffer, unless you specify | |
295 an output stream or filter function to handle the output. | |
296 BUFFER may be also nil, meaning that this process is not associated | |
297 with any buffer | |
298 Third arg is program file name. It is searched for as in the shell. | |
299 Remaining arguments are strings to give program as arguments." | |
300 (apply 'start-process-internal name buffer program program-args)) | |
301 | |
302 (defun open-network-stream (name buffer host service &optional protocol) | |
303 "Open a TCP connection for a service to a host. | |
304 Returns a subprocess-object to represent the connection. | |
305 Input and output work as for subprocesses; `delete-process' closes it. | |
306 Args are NAME BUFFER HOST SERVICE. | |
307 NAME is name for process. It is modified if necessary to make it unique. | |
308 BUFFER is the buffer (or buffer-name) to associate with the process. | |
309 Process output goes at end of that buffer, unless you specify | |
310 an output stream or filter function to handle the output. | |
311 BUFFER may be also nil, meaning that this process is not associated | |
312 with any buffer | |
313 Third arg is name of the host to connect to, or its IP address. | |
314 Fourth arg SERVICE is name of the service desired, or an integer | |
315 specifying a port number to connect to. | |
316 Fifth argument PROTOCOL is a network protocol. Currently 'tcp | |
317 (Transmission Control Protocol) and 'udp (User Datagram Protocol) are | |
318 supported. When omitted, 'tcp is assumed. | |
319 | |
320 Ouput via `process-send-string' and input via buffer or filter (see | |
321 `set-process-filter') are stream-oriented. That means UDP datagrams are | |
322 not guaranteed to be sent and received in discrete packets. (But small | |
323 datagrams around 500 bytes that are not truncated by `process-send-string' | |
324 are usually fine.) Note further that UDP protocol does not guard against | |
325 lost packets." | |
326 (open-network-stream-internal name buffer host service protocol)) | |
327 | |
328 (defun shell-quote-argument (argument) | |
329 "Quote an argument for passing as argument to an inferior shell." | |
330 (if (eq system-type 'ms-dos) | |
331 ;; MS-DOS shells don't have quoting, so don't do any. | |
332 argument | |
333 (if (eq system-type 'windows-nt) | |
334 (concat "\"" argument "\"") | |
335 ;; Quote everything except POSIX filename characters. | |
336 ;; This should be safe enough even for really weird shells. | |
337 (let ((result "") (start 0) end) | |
338 (while (string-match "[^-0-9a-zA-Z_./]" argument start) | |
339 (setq end (match-beginning 0) | |
340 result (concat result (substring argument start end) | |
341 "\\" (substring argument end (1+ end))) | |
342 start (1+ end))) | |
343 (concat result (substring argument start)))))) | |
344 | |
345 (defun exec-to-string (command) | |
346 "Execute COMMAND as an external process and return the output of that | |
347 process as a string" | |
348 ;; by "William G. Dubuque" <wgd@zurich.ai.mit.edu> | |
349 (with-output-to-string | |
350 (call-process shell-file-name nil t nil shell-command-switch command))) | |
351 | |
352 (defalias 'shell-command-to-string 'exec-to-string) | |
353 | |
354 ;;; process.el ends here |