X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Frun-program.lisp;h=97d6d5503a24868008655d8fb24eabc365de8edc;hb=e6f4c7523aa628ece995ee01879d3fb90eed6d9f;hp=daebefececc054af3f29c39b275db704ca8c82a4;hpb=33b3b129c1c895c9583494dc75455f56c83ad748;p=sbcl.git diff --git a/src/code/run-program.lisp b/src/code/run-program.lisp index daebefe..97d6d55 100644 --- a/src/code/run-program.lisp +++ b/src/code/run-program.lisp @@ -386,14 +386,16 @@ status slot." ;; First try to use the Unix98 pty api. (let* ((master-name (coerce (format nil "/dev/ptmx") 'base-string)) (master-fd (sb-unix:unix-open master-name - sb-unix:o_rdwr + (logior sb-unix:o_rdwr + sb-unix:o_noctty) #o666))) (when master-fd (grantpt master-fd) (unlockpt master-fd) (let* ((slave-name (ptsname master-fd)) (slave-fd (sb-unix:unix-open slave-name - sb-unix:o_rdwr + (logior sb-unix:o_rdwr + sb-unix:o_noctty) #o666))) (when slave-fd (return-from find-a-pty @@ -408,13 +410,15 @@ status slot." (let* ((master-name (coerce (format nil "/dev/pty~C~X" char digit) 'base-string)) (master-fd (sb-unix:unix-open master-name - sb-unix:o_rdwr + (logior sb-unix:o_rdwr + sb-unix:o_noctty) #o666))) (when master-fd (let* ((slave-name (coerce (format nil "/dev/tty~C~X" char digit) 'base-string)) (slave-fd (sb-unix:unix-open slave-name - sb-unix:o_rdwr + (logior sb-unix:o_rdwr + sb-unix:o_noctty) #o666))) (when slave-fd (return-from find-a-pty @@ -496,7 +500,7 @@ status slot." ;; Copy string. (sb-kernel:copy-ub8-to-system-area octets 0 string-sap 0 size) ;; NULL-terminate it - (setf (sap-ref-32 string-sap size) 0) + (sb-kernel:system-area-ub8-fill 0 string-sap size 4) ;; Put the pointer in the vector. (setf (sap-ref-sap vec-sap vec-index-offset) string-sap) ;; Advance string-sap for the next string. @@ -507,14 +511,18 @@ status slot." (setf (sap-ref-sap vec-sap vec-index-offset) (int-sap 0)) (values vec-sap (sap+ vec-sap bytes-per-word) total-bytes))) -(defmacro with-c-strvec ((var str-list) &body body) - (with-unique-names (sap size) - `(multiple-value-bind (,sap ,var ,size) - (string-list-to-c-strvec ,str-list) - (unwind-protect - (progn - ,@body) - (sb-sys:deallocate-system-memory ,sap ,size))))) +(defmacro with-c-strvec ((var str-list &key null) &body body) + (once-only ((null null)) + (with-unique-names (sap size) + `(multiple-value-bind (,sap ,var ,size) + (if ,null + (values nil (sb-sys:int-sap 0)) + (string-list-to-c-strvec ,str-list)) + (unwind-protect + (progn + ,@body) + (unless ,null + (sb-sys:deallocate-system-memory ,sap ,size))))))) (sb-alien:define-alien-routine spawn #-win32 sb-alien:int @@ -576,9 +584,8 @@ status slot." &key #-win32 (env nil env-p) #-win32 (environment - (if env-p - (unix-environment-sbcl-from-cmucl env) - (posix-environ)) + (when env-p + (unix-environment-sbcl-from-cmucl env)) environment-p) (wait t) search @@ -729,6 +736,8 @@ Users Manual for details about the PROCESS structure."#-win32" ;; hard-coded symbols here. (values stdout output-stream) (get-descriptor-for ,@args)))) + (unless ,fd + (return-from run-program)) ,@body)) (with-open-pty (((pty-name pty-stream) (pty cookie)) &body body) @@ -740,9 +749,13 @@ Users Manual for details about the PROCESS structure."#-win32" (with-args-vec ((vec args) &body body) `(with-c-strvec (,vec ,args) ,@body)) - (with-environment-vec ((vec env) &body body) + (with-environment-vec ((vec) &body body) #+win32 `(let (,vec) ,@body) - #-win32 `(with-c-strvec (,vec ,env) ,@body))) + #-win32 + `(with-c-strvec + (,vec environment + :null (not (or environment environment-p))) + ,@body))) (with-fd-and-stream-for ((stdin input-stream) :input input cookie :direction :input @@ -766,34 +779,40 @@ Users Manual for details about the PROCESS structure."#-win32" (let (child) (with-active-processes-lock () (with-args-vec (args-vec simple-args) - (with-environment-vec (environment-vec environment) + (with-environment-vec (environment-vec) (setq child (without-gcing (spawn progname args-vec stdin stdout stderr (if search 1 0) environment-vec pty-name - (if wait 1 0)))) - (unless (= child -1) - (setf proc - (apply - #'make-process - :pid child - :input input-stream - :output output-stream - :error error-stream - :status-hook status-hook - :cookie cookie - #-win32 (list :pty pty-stream - :%status :running) - #+win32 (if wait - (list :%status :exited - :exit-code child) - (list :%status :running)))) - (push proc *active-processes*))))) + (if wait 1 0)))))) + (unless (minusp child) + (setf proc + (apply + #'make-process + :pid child + :input input-stream + :output output-stream + :error error-stream + :status-hook status-hook + :cookie cookie + #-win32 (list :pty pty-stream + :%status :running) + #+win32 (if wait + (list :%status :exited + :exit-code child) + (list :%status :running)))) + (push proc *active-processes*))) ;; Report the error outside the lock. - (when (= child -1) - (error "couldn't fork child process: ~A" - (strerror))))))))) + #+win32 + (when (minusp child) + (error "Couldn't execute ~S: ~A" progname (strerror))) + #-win32 + (case child + (-2 + (error "Couldn't execute ~S: ~A" progname (strerror))) + (-1 + (error "Couldn't fork child process: ~A" (strerror)))))))))) (dolist (fd *close-in-parent*) (sb-unix:unix-close fd)) (unless proc @@ -924,6 +943,12 @@ Users Manual for details about the PROCESS structure."#-win32" (get-stream-fd-and-external-format (two-way-stream-output-stream stream) direction)))))) +(defun get-temporary-directory () + #-win32 (or (sb-ext:posix-getenv "TMPDIR") + "/tmp") + #+win32 (or (sb-ext:posix-getenv "TEMP") + "C:/Temp")) + ;;; Find a file descriptor to use for object given the direction. ;;; Returns the descriptor. If object is :STREAM, returns the created @@ -942,10 +967,14 @@ Users Manual for details about the PROCESS structure."#-win32" ;; run afoul of disk quotas or to choke on small /tmp file systems. (flet ((make-temp-fd () (multiple-value-bind (fd name/errno) - (sb-unix:sb-mkstemp "/tmp/.run-program-XXXXXX" #o0600) + (sb-unix:sb-mkstemp (format nil "~a/.run-program-XXXXXX" + (get-temporary-directory)) + #o0600) (unless fd (error "could not open a temporary file: ~A" (strerror name/errno))) + ;; Can't unlink an opened file on Windows + #-win32 (unless (sb-unix:unix-unlink name/errno) (sb-unix:unix-close fd) (error "failed to unlink ~A" name/errno)) @@ -1004,15 +1033,16 @@ Users Manual for details about the PROCESS structure."#-win32" ;; validation there. (with-open-stream (file (apply #'open object :allow-other-keys t keys)) - (multiple-value-bind - (fd errno) - (sb-unix:unix-dup (sb-sys:fd-stream-fd file)) - (cond (fd - (push fd *close-in-parent*) - (values fd nil)) - (t - (error "couldn't duplicate file descriptor: ~A" - (strerror errno))))))) + (when file + (multiple-value-bind + (fd errno) + (sb-unix:unix-dup (sb-sys:fd-stream-fd file)) + (cond (fd + (push fd *close-in-parent*) + (values fd nil)) + (t + (error "couldn't duplicate file descriptor: ~A" + (strerror errno)))))))) ((streamp object) (ecase direction (:input