(write-string line strm)
(write-char #\newline strm))))))
+(defun read-stream-to-string (in)
+ (with-output-to-string (out)
+ (let ((eof (gensym)))
+ (do ((line (read-line in nil eof)
+ (read-line in nil eof)))
+ ((eq line eof))
+ (format out "~A~%" line)))))
+
(defun read-file-to-string (file)
"Opens a reads a file. Returns the contents as a single string"
(with-output-to-string (out)
(with-open-file (in file :direction :input)
- (let ((eof (gensym)))
- (do ((line (read-line in nil eof)
- (read-line in nil eof)))
- ((eq line eof))
- (format out "~A~%" line))))))
-
+ (read-stream-to-string in))))
+
+(defun read-stream-to-strings (in)
+ (let ((lines '())
+ (eof (gensym)))
+ (do ((line (read-line in nil eof)
+ (read-line in nil eof)))
+ ((eq line eof))
+ (push line lines)))
+ (nreverse lines))
+
(defun read-file-to-strings (file)
"Opens a reads a file. Returns the contents as a list of strings"
- (let ((lines '()))
- (with-open-file (in file :direction :input)
- (let ((eof (gensym)))
- (do ((line (read-line in nil eof)
- (read-line in nil eof)))
- ((eq line eof))
- (push line lines)))
- (nreverse lines))))
+ (with-open-file (in file :direction :input)
+ (read-stream-to-strings in)))
(defun file-subst (old new file1 file2)
(with-open-file (in file1 :direction :input)
returns (VALUES string-output error-output exit-status)"
(let ((command (apply #'format nil control-string args)))
#+sbcl
- (sb-impl::process-exit-code
- (sb-ext:run-program
- "/bin/sh"
- (list "-c" command)
- :input nil :output nil))
+ (let ((process (sb-ext:run-program
+ "/bin/sh"
+ (list "-c" command)
+ :input nil :output :stream :error :stream)))
+ (values
+ (sb-impl::process-output process)
+ (sb-impl::process-error process)
+ (sb-impl::process-exit-code process)))
#+(or cmu scl)
- (ext:process-exit-code
- (ext:run-program
- "/bin/sh"
- (list "-c" command)
- :input nil :output nil))
-
+ (let ((process (ext:run-program
+ "/bin/sh"
+ (list "-c" command)
+ :input nil :output :stream :error :stream)))
+ (values
+ (ext::process-output process)
+ (ext::process-error process)
+ (ext::process-exit-code process)))
#+allegro
(multiple-value-bind (output error status)
- (excl.osi:command-output command)
+ (excl.osi:command-output command :whole t)
(values output error status))
#+lispworks
- (system:call-system-showing-output
- command
- :shell-type "/bin/sh"
- :output-stream output)
+ ;; BUG: Lispworks combines output and error streams
+ (let ((output (make-output-string-stream)))
+ (unwind-protect
+ (let ((status
+ (system:call-system-showing-output
+ command
+ :shell-type "/bin/sh"
+ :output-stream output)))
+ (values (get-output-string output) nil status))
+ (close output)))
- #+clisp ;XXX not exactly *verbose-out*, I know
- (ext:run-shell-command command :output :terminal :wait t)
+ #+clisp
+ ;; BUG: CLisp doesn't allow output to user-specified stream
+ (values
+ nil
+ nil
+ (ext:run-shell-command command :output :terminal :wait t))
#+openmcl
- (nth-value 1
- (ccl:external-process-status
- (ccl:run-program "/bin/sh" (list "-c" command)
- :input nil :output nil
- :wait t)))
-
+ (let* ((process (ccl:run-program
+ "/bin/sh"
+ (list "-c" command)
+ :input nil :output :stream :error :stream
+ :wait t))
+ (output (read-stream-to-string (ccl::external-process-output-stream process)))
+ (error (read-stream-to-string (ccl::external-process-error-stream process))))
+ (close (ccl::external-process-output-stream process))
+ (close (ccl::external-process-error-stream process))
+ (values output
+ error
+ (nth-value 1 (ccl::external-process-status process))))
+
#-(or openmcl clisp lispworks allegro scl cmu sbcl)
- (error "RUN-SHELL-PROGRAM not implemented for this Lisp")
+ (error "COMMAND-OUTPUT not implemented for this Lisp")
))