3

It seems there is NO ANSI standard way to execute an external program and get its output as the following SBCL special code does:

(defmacro with-input-from-program ((stream program program-args environment)
                               &body body)
"Creates an new process of the specified by PROGRAM using
 PROGRAM-ARGS as a list of the arguments to the program. Binds the
 stream variable to an input stream from which the output of the
 process can be read and executes body as an implicit progn."
#+sbcl
(let ((process (gensym)))
    `(let ((,process (sb-ext::run-program ,program
                                      ,program-args
                                      :output :stream
                                      :environment ,environment
                                      :wait nil)))
   (when ,process
     (unwind-protect
          (let ((,stream (sb-ext:process-output ,process)))
            ,@body)
       (sb-ext:process-wait ,process)
       (sb-ext:process-close ,process))))))

The following CCL code reports "ERROR: value # is not of the expected type (AND CCL::BINARY-STREAM INPUT-STREAM)"

 #+clozure
 (let ((process (gensym)))
  `(let ((,process (ccl:run-program "/bin/sh" (list "-c" (namestring ,program))
                                    :input nil :output :stream :error :stream
                                    :wait nil)))
   (when ,process
     (unwind-protect
          (let ((,stream (ccl::external-process-output-stream ,process)))     
            ,@body)
       ;(ccl:process-wait (ccl:process-whostate ,process) nil)
       (close (ccl::external-process-output-stream ,process))
       (close (ccl::external-process-error-stream ,process))))))

I know little CCL. I want to know how i can modify this code to support CCL ?

Any suggestion is appreciated !

z_axis
  • 8,272
  • 7
  • 41
  • 61
  • I tried your code using CCL 64 on Linux Mint 12 64bit with `(with-input-from-program (stream "ls" "" nil) (loop for k = (read-line stream nil nil) then (read-line stream nil nil) while k do (print k)))` and it did what I expected (list the files in the current directory). Maybe you should provide the code that generated the error you mention? – Miron Brezuleanu Feb 06 '12 at 12:32
  • 1
    Trying `(with-input-from-program (stream "ls" "" nil) (read-byte stream))` with your macro (also CCL 64, Mint 12 64bit) fails with the message you provided. So the explanation seems to be that you're trying to read bytes from a character stream. – Miron Brezuleanu Feb 06 '12 at 12:46

2 Answers2

4

Apparently trivial-shell:shell-command doesn't allow exactly what you want (it executes the external command synchronously and returns the whole output).

You could look into CCL's run-program. See:

Community
  • 1
  • 1
Miron Brezuleanu
  • 2,989
  • 2
  • 22
  • 33
1

You should use trivial-shell.

Trivial shell is a simple platform independent interface to the underlying Operating System.

Daimrod
  • 4,902
  • 23
  • 25