Changeset 14853
- Timestamp:
- 09/02/16 21:31:09 (7 years ago)
- Location:
- trunk/abcl/src/org/armedbear/lisp
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/abcl/src/org/armedbear/lisp/Extensions.java
r14404 r14853 276 276 try 277 277 { 278 File file = File.createTempFile("abcl", null, null);278 File file = File.createTempFile("abcl", "", null); 279 279 if (file != null) 280 280 return new Pathname(file.getPath()); -
trunk/abcl/src/org/armedbear/lisp/run-program.lisp
r14732 r14853 36 36 (export '(run-program process process-p process-input process-output 37 37 process-error process-alive-p process-wait process-exit-code 38 process-kill ))39 40 ;;; Vaguely inspired by sb-ext:run-program in SBCL. 41 ;;; 42 ;;; See <http://www.sbcl.org/manual/Running-external-programs.html>. 38 process-kill process-pid)) 39 40 ;;; Vaguely inspired by sb-ext:run-program in SBCL. 41 ;;; 42 ;;; See <http://www.sbcl.org/manual/Running-external-programs.html>. 43 43 ;;; 44 44 ;;; This implementation uses the JVM facilities for running external 45 45 ;;; processes. 46 46 ;;; <http://download.oracle.com/javase/6/docs/api/java/lang/ProcessBuilder.html>. 47 (defun run-program (program args &key environment (wait t) clear-environment) 47 (defun run-program (program args &key environment (wait t) clear-environment 48 (input :stream) (output :stream) (error :stream) 49 if-input-does-not-exist (if-output-exists :error) 50 (if-error-exists :error) directory) 48 51 "Run PROGRAM with ARGS in with ENVIRONMENT variables. 49 52 … … 54 57 Creates a new process running the the PROGRAM. 55 58 56 ARGS are a list of strings to be passed to the program as arguments. 59 ARGS are a list of strings to be passed to the program as arguments. 57 60 58 61 For no arguments, use nil which means that just the name of the … … 78 81 The &key arguments have the following meanings: 79 82 80 :environment 83 :environment 81 84 An alist of STRINGs (name . value) describing new 82 85 environment values that replace existing ones. 83 86 84 :clear-env 87 :clear-environment 85 88 If non-NIL, the current environment is cleared before the 86 89 values supplied by :environment are inserted. 87 90 88 :wait 91 :wait 89 92 If non-NIL, which is the default, wait until the created process 90 93 finishes. If NIL, continue running Lisp until the program 91 94 finishes. 95 96 :input 97 If T, I/O is inherited from the Java process. If NIL, /dev/null is used 98 (nul on Windows). If a PATHNAME designator other than a stream is 99 supplied, input will be read from that file. If set to :STREAM, a stream 100 will be available via PROCESS-INPUT to read from. Defaults to :STREAM. 101 102 :if-input-does-not-exist 103 If :input points to a non-existing file, this may be set to :ERROR in 104 order to signal an error, :CREATE to create and read from an empty file, 105 or NIL to immediately NIL instead of creating the process. 106 Defaults to NIL. 107 108 :output 109 If T, I/O is inherited from the Java process. If NIL, /dev/null is used 110 (nul on Windows). If a PATHNAME designator other than a stream is 111 supplied, output will be redirect to that file. If set to :STREAM, a 112 stream will be available via PROCESS-OUTPUT to write to. 113 Defaults to :STREAM. 114 115 :if-output-exists 116 If :output points to a non-existing file, this may be set to :ERROR in 117 order to signal an error, :SUPERSEDE to supersede the existing file, 118 :APPEND to append to it instead, or NIL to immediately NIL instead of 119 creating the process. Defaults to :ERROR. 120 121 :error 122 Same as :output, but can also be :output, in which case the error stream 123 is redirected to wherever the standard output stream goes. 124 Defaults to :STREAM. 125 126 :if-error-exists 127 Same as :if-output-exists, but for the :error target. 128 129 :directory 130 If set will become the working directory for the new process, otherwise 131 the working directory will be unchanged from the current Java process. 132 Defaults to NIL. 92 133 " 93 134 (let* ((program-namestring (namestring (pathname program))) 94 95 135 (process-builder (%make-process-builder program-namestring args))) 96 136 (let ((env-map (%process-builder-environment process-builder))) 97 137 (when clear-environment 98 (%process-builder-env-clear env-map)) 138 (%process-builder-env-clear env-map)) 99 139 (when environment 100 140 (dolist (entry environment) … … 102 142 (princ-to-string (car entry)) 103 143 (princ-to-string (cdr entry)))))) 104 (let ((process (make-process (%process-builder-start process-builder)))) 105 (when wait (process-wait process)) 106 process))) 144 (let ((input-stream-p (eq input :stream)) 145 (output-stream-p (eq output :stream)) 146 (error-stream-p (eq error :stream))) 147 (unless output-stream-p 148 (unless (setup-output-redirection process-builder output NIL if-output-exists) 149 (return-from run-program))) 150 (if (eq error :output) 151 (java:jcall "redirectErrorStream" process-builder T) 152 (unless error-stream-p 153 (unless (setup-output-redirection process-builder error T if-error-exists) 154 (return-from run-program)))) 155 (unless input-stream-p 156 (unless (setup-input-redirection process-builder input if-input-does-not-exist) 157 (return-from run-program))) 158 (when directory 159 (java:jcall "directory" process-builder (java:jnew "java.io.File" (namestring directory)))) 160 (let ((process (make-process (%process-builder-start process-builder) 161 input-stream-p output-stream-p error-stream-p))) 162 (when wait (process-wait process)) 163 process)))) 164 165 (defconstant +inherit+ 166 (java:jfield "java.lang.ProcessBuilder$Redirect" "INHERIT")) 167 168 (defun coerce-to-file (value) 169 (java:jnew 170 "java.io.File" 171 (if value 172 (namestring value) 173 #+unix "/dev/null" 174 #+windows "nul" 175 #-(or unix windows) (error "Don't know how to set up null stream on this platform.")))) 176 177 (defun setup-input-redirection (process-builder value if-does-not-exist) 178 (let ((redirect (if (eq value T) 179 +inherit+ 180 (let ((file (coerce-to-file value))) 181 (when value 182 (if (eq if-does-not-exist :create) 183 (open value :direction :probe :if-does-not-exist :create) 184 (unless (probe-file value) 185 (ecase if-does-not-exist 186 (:error (error "Input file ~S does not exist." value)) 187 ((NIL) (return-from setup-input-redirection)))))) 188 (java:jstatic "from" "java.lang.ProcessBuilder$Redirect" file))))) 189 (java:jcall "redirectInput" process-builder redirect)) 190 T) 191 192 (defun setup-output-redirection (process-builder value errorp if-does-exist) 193 (let ((redirect (if (eq value T) 194 +inherit+ 195 (let ((file (coerce-to-file value)) 196 appendp) 197 (when (and value (probe-file value)) 198 (ecase if-does-exist 199 (:error (error "Output file ~S does already exist." value)) 200 (:supersede (rename-file (make-temp-file) value)) 201 (:append (setf appendp T)) 202 ((NIL) (return-from setup-output-redirection)))) 203 (if appendp 204 (java:jstatic "appendTo" "java.lang.ProcessBuilder$Redirect" file) 205 (java:jstatic "to" "java.lang.ProcessBuilder$Redirect" file)))))) 206 (if errorp 207 (java:jcall "redirectError" process-builder redirect) 208 (java:jcall "redirectOutput" process-builder redirect))) 209 T) 107 210 108 211 ;;; The process structure. 109 212 (defstruct (process (:constructor %make-process (jprocess))) 110 jprocess input outputerror)111 112 (defun make-process (proc )213 jprocess %input %output %error) 214 215 (defun make-process (proc inputp outputp errorp) 113 216 (let ((process (%make-process proc))) 114 (setf (process-input process) (%make-process-input-stream proc)) 115 (setf (process-output process) (%make-process-output-stream proc)) 116 (setf (process-error process) (%make-process-error-stream proc)) 217 (when inputp 218 (setf (%process-input process) (%make-process-input-stream proc))) 219 (when outputp 220 (setf (%process-output process) (%make-process-output-stream proc))) 221 (when errorp 222 (setf (%process-error process) (%make-process-error-stream proc))) 117 223 process)) 224 225 (defun process-input (process) 226 (%process-input process)) 227 228 (defun process-output (process) 229 (%process-output process)) 230 231 (defun process-error (process) 232 (%process-error process)) 118 233 119 234 (defun process-alive-p (process) … … 132 247 "Kills the process." 133 248 (%process-kill (process-jprocess process))) 249 250 (defun process-pid (process) 251 "Return the process ID." 252 (%process-pid (process-jprocess process))) 134 253 135 254 ;;; Low-level functions. For now they're just a refactoring of the … … 177 296 (ignore-errors (java:jcall "exitValue" jprocess))) 178 297 298 #+unix 299 (defconstant +pid-field+ 300 (let ((field (java:jcall "getDeclaredField" (java:jclass "java.lang.UNIXProcess") "pid"))) 301 (java:jcall "setAccessible" field java:+true+) 302 field)) 303 304 (defun %process-pid (jprocess) 305 #+unix (java:jcall "get" +pid-field+ jprocess) 306 #-unix (error "Can't retrieve PID on this platform.")) 307 179 308 (defun %process-kill (jprocess) 180 309 (java:jcall "destroy" jprocess))
Note: See TracChangeset
for help on using the changeset viewer.