title: How to process input and output streams in Steel Bank Common Lisp?
body: <p>I'm trying to figure out how to use the output stream of one program I start with <code>RUN-PROGRAM</code> so it can be used as the input of another program started with <code>RUN-PROGRAM</code> (i.e., the moral and perhaps literal equivalent of piping). I've tried using a number of combinations of the <code>:INPUT</code>, <code>:OUTPUT</code> and <code>:WAIT</code> keyword arguments, but nothing I've hit 
  upon has been productive so far. Any tips would be helpful; for example, how would I go about doing something like <code>ls | grep lisp</code> from the shell? </p>
  
  <p>One of my attempts is </p>
  
  <pre><code>(defun piping-test () 
    (let ((grep-process (run-program "/usr/bin/grep" '("lisp") 
                                    :input :stream 
                                    :output :stream))) 
      (unwind-protect 
          (with-open-stream (s (process-input grep-process)) 
            (let ((ls-process (run-program "/bin/ls" '() 
                                          :output s))) 
              (when ls-process 
                (unwind-protect 
                    (with-open-stream (o (process-output grep-process)) 
                     (loop 
                        :for line := (read-line o nil nil) 
                        :while line 
                        :collect line)) 
                 (process-close ls-process))))) 
       (when grep-process (process-close grep-process))))) 
  </code></pre>
  
  <p>Running this in a SLIME REPL causes everything to hang until I break 
  with <code>C-c C-c</code>, so it's pretty obviously not the right thing, but I'm 
  not sure how to change it so it is the right thing. </p>
  
  <p><strong>EDIT:</strong> Adding <code>:WAIT NIL</code> to both <code>RUN-PROGRAM</code> invocations, or to only the invocation for <code>grep</code>, doesn't do the trick. In that case, the function will hang, and breaking with <code>C-c C-c</code> gets a stack trace indicating that there's a local function (defined via <code>FLET</code>) called <code>SB-UNIX:SELECT</code> that has hung.</p>