This program implements a simple program interface to the UNIX dc desktop calculator command. The procedure calc-open starts the dc command and establishes two pipes to/from the child process; the procedure calc sends its argument (a dc expression as a string) as input to dc; calc-close closes the pipes and waits for the subprocess to terminate.
(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 "/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) (unix-wait-process calc-dc-pid)) ;;; Test -- print sqrt(2): (calc-open) (display (calc "10k 2v p")) (newline) (calc-close)
The following procedure copies a file; the arguments are the source and target file names. The second argument may name a directory, in this case the file is copied into the directory. The target file must not yet exist. copy-file preserves the access mode of the source file.
(require 'unix) (define copy-buffer-size 8192) (define (copy-file from to) (let ((from-stat (unix-stat from)) (to-stat (unix-errval (unix-stat to)))) (if (eq? (stat-type from-stat) 'directory) ; complain if "from" (error 'copy-file "~s is a directory" from)) ; is a directory (if (and (not (unix-error? to-stat)) ; destination exists (eq? (stat-type to-stat) 'directory)) ; and is a directory? (set! to (format #f "~a/~a" to from))) (let* ((to-fd (unix-open to '(write create exclusive) (stat-mode from-stat))) (from-fd (unix-open from '(read))) (buf (make-string copy-buffer-size))) (let loop ((num-chars (unix-read-string-fill! from-fd buf))) (if (positive? num-chars) (begin (unix-write to-fd buf num-chars) (loop (unix-read-string-fill! from-fd buf))))) (unix-close from-fd) (unix-close to-fd))))
lock-vi starts the vi editor with the specified file name. It provides exclusive access to the file during the editing session by applying a write lock to the file and removing it when the editor finishes. A message is displayed periodically if the lock is held by somebody else.
(require 'unix) (define (lock-vi file) (let* ((fd (unix-open file '(read write))) (lock ((record-constructor lock-record) #t 'set 0 0))) (let loop () (if (not (unix-set-lock fd lock #f)) (begin (format #t "Someone else is editing ~s...~%" file) (unix-sleep 10) (loop)))) (unix-system (format #f "vi ~a" file)) (unix-remove-lock fd lock)))
pipe-size attempts to determine the capacity of a pipe. It creates a pipe, places the write end of the pipe into non-blocking I/O mode and writes into the pipe until it is full, counting the characters successfully written.
(require 'unix) (define (pipe-size) (let* ((pipe (unix-pipe)) (flags (unix-filedescriptor-flags (cdr pipe))) (len 32) ; assumes capacity is multiple of len (noise (make-string len))) ;; enable non-blocking I/O for write side of pipe: (unix-filedescriptor-flags (cdr pipe) (cons 'ndelay flags)) (unwind-protect (let loop ((size 0)) (if (unix-error? (unix-errval (unix-write (cdr pipe) noise))) (if (memq (unix-errno) '(eagain ewouldblock)) size (error 'pipe-size "~E")) (loop (+ size 32)))) (unix-close (car pipe)) (unix-close (cdr pipe)))))