Mercurial > hg > xemacs-beta
comparison lisp/process.el @ 209:41ff10fd062f r20-4b3
Import from CVS: tag r20-4b3
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:04:58 +0200 |
parents | |
children | 0e522484dd2a |
comparison
equal
deleted
inserted
replaced
208:f427b8ec4379 | 209:41ff10fd062f |
---|---|
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 shell-command-switch "-c" | |
37 "Switch used to have the shell execute its command line argument.") | |
38 | |
39 (defun start-process-shell-command (name buffer &rest args) | |
40 "Start a program in a subprocess. Return the process object for it. | |
41 Args are NAME BUFFER COMMAND &rest COMMAND-ARGS. | |
42 NAME is name for process. It is modified if necessary to make it unique. | |
43 BUFFER is the buffer or (buffer-name) to associate with the process. | |
44 Process output goes at end of that buffer, unless you specify | |
45 an output stream or filter function to handle the output. | |
46 BUFFER may be also nil, meaning that this process is not associated | |
47 with any buffer | |
48 Third arg is command name, the name of a shell command. | |
49 Remaining arguments are the arguments for the command. | |
50 Wildcards and redirection are handled as usual in the shell." | |
51 (cond | |
52 ((eq system-type 'vax-vms) | |
53 (apply 'start-process name buffer args)) | |
54 ;; We used to use `exec' to replace the shell with the command, | |
55 ;; but that failed to handle (...) and semicolon, etc. | |
56 (t | |
57 (start-process name buffer shell-file-name shell-command-switch | |
58 (mapconcat 'identity args " "))))) | |
59 | |
60 (defun call-process (program &optional infile buffer displayp &rest args) | |
61 "Call PROGRAM synchronously in separate process. | |
62 The program's input comes from file INFILE (nil means `/dev/null'). | |
63 Insert output in BUFFER before point; t means current buffer; | |
64 nil for BUFFER means discard it; 0 means discard and don't wait. | |
65 BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case, | |
66 REAL-BUFFER says what to do with standard output, as above, | |
67 while STDERR-FILE says what to do with standard error in the child. | |
68 STDERR-FILE may be nil (discard standard error output), | |
69 t (mix it with ordinary output), or a file name string. | |
70 | |
71 Fourth arg DISPLAYP non-nil means redisplay buffer as output is inserted. | |
72 Remaining arguments are strings passed as command arguments to PROGRAM. | |
73 | |
74 If BUFFER is 0, `call-process' returns immediately with value nil. | |
75 Otherwise it waits for PROGRAM to terminate and returns a numeric exit status | |
76 or a signal description string. | |
77 If you quit, the process is killed with SIGINT, or SIGKILL if you | |
78 quit again." | |
79 (apply 'call-process-internal program infile buffer displayp args)) | |
80 | |
81 (defun call-process-region (start end program | |
82 &optional deletep buffer displayp | |
83 &rest args) | |
84 "Send text from START to END to a synchronous process running PROGRAM. | |
85 Delete the text if fourth arg DELETEP is non-nil. | |
86 | |
87 Insert output in BUFFER before point; t means current buffer; | |
88 nil for BUFFER means discard it; 0 means discard and don't wait. | |
89 BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case, | |
90 REAL-BUFFER says what to do with standard output, as above, | |
91 while STDERR-FILE says what to do with standard error in the child. | |
92 STDERR-FILE may be nil (discard standard error output), | |
93 t (mix it with ordinary output), or a file name string. | |
94 | |
95 Sixth arg DISPLAYP non-nil means redisplay buffer as output is inserted. | |
96 Remaining args are passed to PROGRAM at startup as command args. | |
97 | |
98 If BUFFER is 0, returns immediately with value nil. | |
99 Otherwise waits for PROGRAM to terminate | |
100 and returns a numeric exit status or a signal description string. | |
101 If you quit, the process is first killed with SIGINT, then with SIGKILL if | |
102 you quit again before the process exits." | |
103 (let ((temp (cond ((eq system-type 'vax-vms) | |
104 (make-temp-name "tmp:emacs")) | |
105 ((or (eq system-type 'ms-dos) | |
106 (eq system-type 'windows-nt)) | |
107 (make-temp-name | |
108 (concat (file-name-as-directory | |
109 (or (getenv "TMP") | |
110 (getenv "TEMP") | |
111 "")) | |
112 "em"))) | |
113 (t | |
114 (make-temp-name "/tmp/emacs"))))) | |
115 (unwind-protect | |
116 (progn | |
117 (if (or (eq system-type 'ms-dos) | |
118 (eq system-type 'windows-nt)) | |
119 (let ((buffer-file-type binary-process-output)) | |
120 (write-region start end temp nil 'silent)) | |
121 (write-region start end temp nil 'silent)) | |
122 (if deletep (delete-region start end)) | |
123 (apply #'call-process program temp buffer displayp args)) | |
124 (condition-case () | |
125 (delete-file temp) | |
126 (file-error nil))))) | |
127 | |
128 | |
129 (defun shell-command (command &optional output-buffer) | |
130 "Execute string COMMAND in inferior shell; display output, if any. | |
131 | |
132 If COMMAND ends in ampersand, execute it asynchronously. | |
133 The output appears in the buffer `*Async Shell Command*'. | |
134 That buffer is in shell mode. | |
135 | |
136 Otherwise, COMMAND is executed synchronously. The output appears in the | |
137 buffer `*Shell Command Output*'. | |
138 If the output is one line, it is displayed in the echo area *as well*, | |
139 but it is nonetheless available in buffer `*Shell Command Output*', | |
140 even though that buffer is not automatically displayed. | |
141 If there is no output, or if output is inserted in the current buffer, | |
142 then `*Shell Command Output*' is deleted. | |
143 | |
144 The optional second argument OUTPUT-BUFFER, if non-nil, | |
145 says to put the output in some other buffer. | |
146 If OUTPUT-BUFFER is a buffer or buffer name, put the output there. | |
147 If OUTPUT-BUFFER is not a buffer and not nil, | |
148 insert output in current buffer. (This cannot be done asynchronously.) | |
149 In either case, the output is inserted after point (leaving mark after it)." | |
150 (interactive (list (read-shell-command "Shell command: ") | |
151 current-prefix-arg)) | |
152 (if (and output-buffer | |
153 (not (or (bufferp output-buffer) (stringp output-buffer)))) | |
154 (progn (barf-if-buffer-read-only) | |
155 (push-mark) | |
156 ;; We do not use -f for csh; we will not support broken use of | |
157 ;; .cshrcs. Even the BSD csh manual says to use | |
158 ;; "if ($?prompt) exit" before things which are not useful | |
159 ;; non-interactively. Besides, if someone wants their other | |
160 ;; aliases for shell commands then they can still have them. | |
161 (call-process shell-file-name nil t nil | |
162 shell-command-switch command) | |
163 (exchange-point-and-mark t)) | |
164 ;; Preserve the match data in case called from a program. | |
165 (save-match-data | |
166 (if (string-match "[ \t]*&[ \t]*$" command) | |
167 ;; Command ending with ampersand means asynchronous. | |
168 (progn | |
169 (background (substring command 0 (match-beginning 0)))) | |
170 (shell-command-on-region (point) (point) command output-buffer))))) | |
171 | |
172 ;; We have a sentinel to prevent insertion of a termination message | |
173 ;; in the buffer itself. | |
174 (defun shell-command-sentinel (process signal) | |
175 (if (memq (process-status process) '(exit signal)) | |
176 (message "%s: %s." | |
177 (car (cdr (cdr (process-command process)))) | |
178 (substring signal 0 -1)))) | |
179 | |
180 (defun shell-command-on-region (start end command | |
181 &optional output-buffer replace) | |
182 "Execute string COMMAND in inferior shell with region as input. | |
183 Normally display output (if any) in temp buffer `*Shell Command Output*'; | |
184 Prefix arg means replace the region with it. | |
185 | |
186 The noninteractive arguments are START, END, COMMAND, OUTPUT-BUFFER, REPLACE. | |
187 If REPLACE is non-nil, that means insert the output | |
188 in place of text from START to END, putting point and mark around it. | |
189 | |
190 If the output is one line, it is displayed in the echo area, | |
191 but it is nonetheless available in buffer `*Shell Command Output*' | |
192 even though that buffer is not automatically displayed. | |
193 If there is no output, or if output is inserted in the current buffer, | |
194 then `*Shell Command Output*' is deleted. | |
195 | |
196 If the optional fourth argument OUTPUT-BUFFER is non-nil, | |
197 that says to put the output in some other buffer. | |
198 If OUTPUT-BUFFER is a buffer or buffer name, put the output there. | |
199 If OUTPUT-BUFFER is not a buffer and not nil, | |
200 insert output in the current buffer. | |
201 In either case, the output is inserted after point (leaving mark after it)." | |
202 (interactive (let ((string | |
203 ;; Do this before calling region-beginning | |
204 ;; and region-end, in case subprocess output | |
205 ;; relocates them while we are in the minibuffer. | |
206 (read-shell-command "Shell command on region: "))) | |
207 ;; call-interactively recognizes region-beginning and | |
208 ;; region-end specially, leaving them in the history. | |
209 (list (region-beginning) (region-end) | |
210 string | |
211 current-prefix-arg | |
212 current-prefix-arg))) | |
213 (if (or replace | |
214 (and output-buffer | |
215 (not (or (bufferp output-buffer) (stringp output-buffer))))) | |
216 ;; Replace specified region with output from command. | |
217 (let ((swap (and replace (< start end)))) | |
218 ;; Don't muck with mark unless REPLACE says we should. | |
219 (goto-char start) | |
220 (and replace (push-mark)) | |
221 (call-process-region start end shell-file-name t t nil | |
222 shell-command-switch command) | |
223 (let ((shell-buffer (get-buffer "*Shell Command Output*"))) | |
224 (and shell-buffer (not (eq shell-buffer (current-buffer))) | |
225 (kill-buffer shell-buffer))) | |
226 ;; Don't muck with mark unless REPLACE says we should. | |
227 (and replace swap (exchange-point-and-mark t))) | |
228 ;; No prefix argument: put the output in a temp buffer, | |
229 ;; replacing its entire contents. | |
230 (let ((buffer (get-buffer-create | |
231 (or output-buffer "*Shell Command Output*"))) | |
232 (success nil) | |
233 (directory default-directory)) | |
234 (unwind-protect | |
235 (if (eq buffer (current-buffer)) | |
236 ;; If the input is the same buffer as the output, | |
237 ;; delete everything but the specified region, | |
238 ;; then replace that region with the output. | |
239 (progn (setq buffer-read-only nil) | |
240 (delete-region (max start end) (point-max)) | |
241 (delete-region (point-min) (max start end)) | |
242 (call-process-region (point-min) (point-max) | |
243 shell-file-name t t nil | |
244 shell-command-switch command) | |
245 (setq success t)) | |
246 ;; Clear the output buffer, | |
247 ;; then run the command with output there. | |
248 (save-excursion | |
249 (set-buffer buffer) | |
250 (setq buffer-read-only nil) | |
251 ;; XEmacs change | |
252 (setq default-directory directory) | |
253 (erase-buffer)) | |
254 (call-process-region start end shell-file-name | |
255 nil buffer nil | |
256 shell-command-switch command) | |
257 (setq success t)) | |
258 ;; Report the amount of output. | |
259 (let ((lines (save-excursion | |
260 (set-buffer buffer) | |
261 (if (= (buffer-size) 0) | |
262 0 | |
263 (count-lines (point-min) (point-max)))))) | |
264 (cond ((= lines 0) | |
265 (if success | |
266 (display-message | |
267 'command | |
268 "(Shell command completed with no output)")) | |
269 (kill-buffer buffer)) | |
270 ((and success (= lines 1)) | |
271 (message "%s" | |
272 (save-excursion | |
273 (set-buffer buffer) | |
274 (goto-char (point-min)) | |
275 (buffer-substring (point) | |
276 (progn (end-of-line) | |
277 (point)))))) | |
278 (t | |
279 (set-window-start (display-buffer buffer) 1)))))))) | |
280 | |
281 | |
282 (defun start-process (name buffer program &rest program-args) | |
283 "Start a program in a subprocess. Return the process object for it. | |
284 Args are NAME BUFFER PROGRAM &rest PROGRAM-ARGS | |
285 NAME is name for process. It is modified if necessary to make it unique. | |
286 BUFFER is the buffer or (buffer-name) to associate with the process. | |
287 Process output goes at end of that buffer, unless you specify | |
288 an output stream or filter function to handle the output. | |
289 BUFFER may be also nil, meaning that this process is not associated | |
290 with any buffer | |
291 Third arg is program file name. It is searched for as in the shell. | |
292 Remaining arguments are strings to give program as arguments. | |
293 INCODE and OUTCODE specify the coding-system objects used in input/output | |
294 from/to the process." | |
295 (apply 'start-process-internal name buffer program program-args)) | |
296 | |
297 (defun open-network-stream (name buffer host service) | |
298 "Open a TCP connection for a service to a host. | |
299 Returns a subprocess-object to represent the connection. | |
300 Input and output work as for subprocesses; `delete-process' closes it. | |
301 Args are NAME BUFFER HOST SERVICE. | |
302 NAME is name for process. It is modified if necessary to make it unique. | |
303 BUFFER is the buffer (or buffer-name) to associate with the process. | |
304 Process output goes at end of that buffer, unless you specify | |
305 an output stream or filter function to handle the output. | |
306 BUFFER may be also nil, meaning that this process is not associated | |
307 with any buffer | |
308 Third arg is name of the host to connect to, or its IP address. | |
309 Fourth arg SERVICE is name of the service desired, or an integer | |
310 specifying a port number to connect to." | |
311 (open-network-stream-internal name buffer host service)) | |
312 | |
313 (defun shell-quote-argument (argument) | |
314 "Quote an argument for passing as argument to an inferior shell." | |
315 (if (eq system-type 'ms-dos) | |
316 ;; MS-DOS shells don't have quoting, so don't do any. | |
317 argument | |
318 (if (eq system-type 'windows-nt) | |
319 (concat "\"" argument "\"") | |
320 ;; Quote everything except POSIX filename characters. | |
321 ;; This should be safe enough even for really weird shells. | |
322 (let ((result "") (start 0) end) | |
323 (while (string-match "[^-0-9a-zA-Z_./]" argument start) | |
324 (setq end (match-beginning 0) | |
325 result (concat result (substring argument start end) | |
326 "\\" (substring argument end (1+ end))) | |
327 start (1+ end))) | |
328 (concat result (substring argument start)))))) | |
329 | |
330 (defun exec-to-string (command) | |
331 "Execute COMMAND as an external process and return the output of that | |
332 process as a string" | |
333 ;; by "William G. Dubuque" <wgd@zurich.ai.mit.edu> | |
334 (with-output-to-string | |
335 (call-process shell-file-name nil t nil "-c" command))) | |
336 | |
337 (defalias 'shell-command-to-string 'exec-to-string) | |
338 | |
339 ;;; process.el ends here |