(define-library (chibi pty) (import (scheme base) (chibi filesystem) (chibi process) (chibi string) (chibi stty) (only (chibi) fileno?)) (export open-pty fork-pty login-tty open-pty-process call-with-pty-process-io) (include-shared "pty") (begin (define (winsize-arg o) (cond ((and (pair? o) (integer? (car o))) (unless (and (pair? (cdr o)) (integer? (cadr o))) (error "open-pty expects integer width and height" o)) (make-winsize (car o) (cadr o))) ((and (pair? o) (pair? (cdr o))) (cadr o)) (else #f))) (define (open-pty . o) (let ((termios (and (pair? o) (car o))) (winsize (winsize-arg (if (pair? o) (cdr o) '())))) (openpty termios winsize))) (define (fork-pty . o) (let ((termios (and (pair? o) (car o))) (winsize (winsize-arg (if (pair? o) (cdr o) '())))) (forkpty termios winsize))) (define (open-pty-process command . o) (let* ((command (if (and (string? command) (string-find? command #\space)) (string-split command) command)) (pty (apply fork-pty o))) (cond ((not (and (pair? pty) (integer? (car pty)) (not (negative? (car pty))) (pair? (cdr pty)) (fileno? (cadr pty)))) (error "failed to fork-pty" pty)) ((zero? (car pty)) ; child (execute (car command) command)) (else ; parent pty)))) (define (call-with-pty-process-io command proc . o) (unless (procedure? proc) (error "call-with-pty-process-io expected procedure" proc)) (let ((pty (apply open-pty-process command o))) (if (and (pair? pty) (integer? (car pty)) (not (negative? (car pty))) (fileno? (cadr pty))) (let* ((pid (car pty)) (fd (cadr pty)) (name (and (pair? (cddr pty)) (car (cddr pty)))) (in (open-input-file-descriptor fd)) (out (open-output-file-descriptor fd)) (res (proc pid in out name))) (close-input-port in) (close-output-port out) (close-file-descriptor fd) res) (error "couldn't open-pty-process" command o pty))))))