With the external-program package, I can code to call an external command line program easily. For example:
(external-program:run "ls" '("-l") :output *standard-output*)
What if I want to keep streaming (piping) input and reading output. (1) instead of run, I use start.
(setf *x* (external-program:start "cat" '() :output :stream :input :stream))
(2) I create a thread for reading the output and print it. Bordeaux-threads API looks quite similar to POSIX.
(setf *read-thread* (bordeaux-threads:make-thread (lambda () (loop for line = (read-line (external-program:process-output-stream *x*) nil) while line do (format t "OUT: ~A~%" line))) :name "titi"))
(3) I get an output stream for passing data to the external program.
(setf *out* (external-program:process-input-stream *x*))
(4) I write something to out and flash it.
(progn (loop for i from 1 to 10 do (format *out* "!!! ~A~%" i)) (force-output *out*))
At this step, you should see some output from the (2) step, which are:
OUT: !!! 1 OUT: !!! 2 ... OUT: !!! 10
You can keep playing with it.
(5) And finally I clean everything up.
(close *out*) (bordeaux-threads:join-thread *read-thread*)