;;; -*-Scheme-*- ;;; ;;; Demonstrate pipes, fork, exec. ;;; ;;; (calc-open) -- Open two pipes to/from UNIX dc command ;;; (calc expr) -- Send expression to dc, return result as a string ;;; (calc-close) -- Close pipes, wait for child process ;;; ;;; ;;; This program requires vanilla UNIX dc. It does not work with GNU dc, ;;; because GNU dc uses buffered output even if standard output points to ;;; a pipe. This means that GNU dc does not produce any output until the ;;; pipe is closed; the call to read-string therefore just hangs. (require 'unix) (define calc-from-dc) ; input port: standard output of dc command (define calc-to-dc) ; output port: standard input of dc command (define calc-dc-pid) ; process-ID of child process running dc (define calc-dc-command "/usr/bin/dc") (define (calc-open) (let* ((from (unix-pipe)) (to (unix-pipe)) (redirect-fd (lambda (a b) (unix-dup a b) (unix-close a)))) (set! calc-dc-pid (unix-fork)) (if (zero? calc-dc-pid) (begin (unix-close (car from)) (unix-close (cdr to)) (redirect-fd (car to) 0) (redirect-fd (cdr from) 1) (unix-exec calc-dc-command '("dc"))) (begin (unix-close (cdr from)) (unix-close (car to)) (set! calc-to-dc (unix-filedescriptor->port (cdr to) "w")) (set! calc-from-dc (unix-filedescriptor->port (car from) "r")))))) (define (calc expr) (format calc-to-dc "~a~%" expr) (flush-output-port calc-to-dc) (read-string calc-from-dc)) (define (calc-close) (close-output-port calc-to-dc) (close-input-port calc-from-dc) (if (feature? 'unix:wait-process) (unix-wait-process calc-dc-pid) (unix-wait))) ;;; Test -- print sqrt(2): (calc-open) (display (calc "10k 2v p")) (newline) (calc-close)