[racket] Duplicating output from a system call

From: Neil Van Dyke (neil at neilvandyke.org)
Date: Fri May 17 01:01:12 EDT 2013

If you change the "process*" call in the below program to run your 
command, and run this program in DrRacket with "View -> Show Log", 
hopefully you see the output from your command promptly.

#lang racket/base

(require racket/system)

(apply (lambda (stdout-in
          (let* ((buf-size  4096)
                 (buf-bytes (make-bytes buf-size)))
            (let loop ()
              (let ((evt (sync/enable-break stdout-in stderr-in)))
                ;; ...
                (let ((read-result (read-bytes-avail! buf-bytes evt)))
                  (cond ((eof-object? read-result)
                         (log-error "EOF!")
                         ;; ...
                        ;; ...
                         (log-error "OUTPUT: ~S" (subbytes buf-bytes 0 
            ;; ...
            (close-output-port stdin-out)
            (close-input-port  stdout-in)
            (close-input-port  stderr-in)))
        (process* "/bin/sh"
                  "while true ; do echo -n abc ; sleep 3 ; done"))

(I wrote the code this particular way, using a bytes buffer, because 
it's a good starting point for doing fancier things, such as if you're 
trying to recognize particular output and handle it specially, or if 
you're interacting with the process.  This is as far as I can help, 
though.  Depending on the entirety of what you want to do with the 
output, getting this right can easily take hours and end up looking like 
systems programming.  Or you can look at doing it with first-class 
continuations, which should be more elegant, but continuations hurt 
people's brains initially, and i'm not sure how performance would compare.)

Neil V.

Posted on the users mailing list.