mirror of
https://git.in.rschanz.org/ryan77627/guix.git
synced 2024-12-27 06:42:14 -05:00
syscalls: Add 'tcgetattr' and 'tcsetattr' bindings.
* guix/build/syscalls.scm (bits->symbols-body, define-bits) (local-flags): New macros. (TCSANOW, TCSADRAIN, TCSAFLUSH): New variables. (<termios>): New record type. (%termios): New C structure. (tcgetattr, tcsetattr): New procedures. * tests/syscalls.scm ("tcgetattr ENOTTY", "tcgetattr") ("tcsetattr"): New tests.
This commit is contained in:
parent
ba369abe58
commit
29d457c209
2 changed files with 156 additions and 0 deletions
|
@ -100,6 +100,22 @@ (define-module (guix build syscalls)
|
||||||
interface-broadcast-address
|
interface-broadcast-address
|
||||||
network-interfaces
|
network-interfaces
|
||||||
|
|
||||||
|
termios?
|
||||||
|
termios-input-flags
|
||||||
|
termios-output-flags
|
||||||
|
termios-control-flags
|
||||||
|
termios-local-flags
|
||||||
|
termios-line-discipline
|
||||||
|
termios-control-chars
|
||||||
|
termios-input-speed
|
||||||
|
termios-output-speed
|
||||||
|
local-flags
|
||||||
|
TCSANOW
|
||||||
|
TCSADRAIN
|
||||||
|
TCSAFLUSH
|
||||||
|
tcgetattr
|
||||||
|
tcsetattr
|
||||||
|
|
||||||
window-size?
|
window-size?
|
||||||
window-size-rows
|
window-size-rows
|
||||||
window-size-columns
|
window-size-columns
|
||||||
|
@ -996,6 +1012,121 @@ (define free-ifaddrs
|
||||||
;;; Terminals.
|
;;; Terminals.
|
||||||
;;;
|
;;;
|
||||||
|
|
||||||
|
(define-syntax bits->symbols-body
|
||||||
|
(syntax-rules ()
|
||||||
|
((_ bits () ())
|
||||||
|
'())
|
||||||
|
((_ bits (name names ...) (value values ...))
|
||||||
|
(let ((result (bits->symbols-body bits (names ...) (values ...))))
|
||||||
|
(if (zero? (logand bits value))
|
||||||
|
result
|
||||||
|
(cons 'name result))))))
|
||||||
|
|
||||||
|
(define-syntax define-bits
|
||||||
|
(syntax-rules (define)
|
||||||
|
"Define the given numerical constants under CONSTRUCTOR, such that
|
||||||
|
(CONSTRUCTOR NAME) returns VALUE. Define BITS->SYMBOLS as a procedure that,
|
||||||
|
given an integer, returns the list of names of the constants that are or'd."
|
||||||
|
((_ constructor bits->symbols (define names values) ...)
|
||||||
|
(begin
|
||||||
|
(define-syntax constructor
|
||||||
|
(syntax-rules (names ...)
|
||||||
|
((_ names) values) ...
|
||||||
|
((_ several (... ...))
|
||||||
|
(logior (constructor several) (... ...)))))
|
||||||
|
(define (bits->symbols bits)
|
||||||
|
(bits->symbols-body bits (names ...) (values ...)))
|
||||||
|
(define names values) ...))))
|
||||||
|
|
||||||
|
;; 'local-flags' bits from <bits/termios.h>
|
||||||
|
(define-bits local-flags
|
||||||
|
local-flags->symbols
|
||||||
|
(define ISIG #o0000001)
|
||||||
|
(define ICANON #o0000002)
|
||||||
|
(define XCASE #o0000004)
|
||||||
|
(define ECHO #o0000010)
|
||||||
|
(define ECHOE #o0000020)
|
||||||
|
(define ECHOK #o0000040)
|
||||||
|
(define ECHONL #o0000100)
|
||||||
|
(define NOFLSH #o0000200)
|
||||||
|
(define TOSTOP #o0000400)
|
||||||
|
(define ECHOCTL #o0001000)
|
||||||
|
(define ECHOPRT #o0002000)
|
||||||
|
(define ECHOKE #o0004000)
|
||||||
|
(define FLUSHO #o0010000)
|
||||||
|
(define PENDIN #o0040000)
|
||||||
|
(define IEXTEN #o0100000)
|
||||||
|
(define EXTPROC #o0200000))
|
||||||
|
|
||||||
|
;; "Actions" values for 'tcsetattr'.
|
||||||
|
(define TCSANOW 0)
|
||||||
|
(define TCSADRAIN 1)
|
||||||
|
(define TCSAFLUSH 2)
|
||||||
|
|
||||||
|
(define-record-type <termios>
|
||||||
|
(termios input-flags output-flags control-flags local-flags
|
||||||
|
line-discipline control-chars
|
||||||
|
input-speed output-speed)
|
||||||
|
termios?
|
||||||
|
(input-flags termios-input-flags)
|
||||||
|
(output-flags termios-output-flags)
|
||||||
|
(control-flags termios-control-flags)
|
||||||
|
(local-flags termios-local-flags)
|
||||||
|
(line-discipline termios-line-discipline)
|
||||||
|
(control-chars termios-control-chars)
|
||||||
|
(input-speed termios-input-speed)
|
||||||
|
(output-speed termios-output-speed))
|
||||||
|
|
||||||
|
(define-c-struct %termios ;<bits/termios.h>
|
||||||
|
sizeof-termios
|
||||||
|
termios
|
||||||
|
read-termios
|
||||||
|
write-termios!
|
||||||
|
(input-flags unsigned-int)
|
||||||
|
(output-flags unsigned-int)
|
||||||
|
(control-flags unsigned-int)
|
||||||
|
(local-flags unsigned-int)
|
||||||
|
(line-discipline uint8)
|
||||||
|
(control-chars (array uint8 32))
|
||||||
|
(input-speed unsigned-int)
|
||||||
|
(output-speed unsigned-int))
|
||||||
|
|
||||||
|
(define tcgetattr
|
||||||
|
(let ((proc (syscall->procedure int "tcgetattr" (list int '*))))
|
||||||
|
(lambda (fd)
|
||||||
|
"Return the <termios> structure for the tty at FD."
|
||||||
|
(let* ((bv (make-bytevector sizeof-termios))
|
||||||
|
(ret (proc fd (bytevector->pointer bv)))
|
||||||
|
(err (errno)))
|
||||||
|
(if (zero? ret)
|
||||||
|
(read-termios bv)
|
||||||
|
(throw 'system-error "tcgetattr" "~A"
|
||||||
|
(list (strerror err))
|
||||||
|
(list err)))))))
|
||||||
|
|
||||||
|
(define tcsetattr
|
||||||
|
(let ((proc (syscall->procedure int "tcsetattr" (list int int '*))))
|
||||||
|
(lambda (fd actions termios)
|
||||||
|
"Use TERMIOS for the tty at FD. ACTIONS is one of 'TCSANOW',
|
||||||
|
'TCSADRAIN', or 'TCSAFLUSH'; see tcsetattr(3) for details."
|
||||||
|
(define bv
|
||||||
|
(make-bytevector sizeof-termios))
|
||||||
|
|
||||||
|
(let-syntax ((match/write (syntax-rules ()
|
||||||
|
((_ fields ...)
|
||||||
|
(match termios
|
||||||
|
(($ <termios> fields ...)
|
||||||
|
(write-termios! bv 0 fields ...)))))))
|
||||||
|
(match/write input-flags output-flags control-flags local-flags
|
||||||
|
line-discipline control-chars input-speed output-speed))
|
||||||
|
|
||||||
|
(let ((ret (proc fd actions (bytevector->pointer bv)))
|
||||||
|
(err (errno)))
|
||||||
|
(unless (zero? ret)
|
||||||
|
(throw 'system-error "tcgetattr" "~A"
|
||||||
|
(list (strerror err))
|
||||||
|
(list err)))))))
|
||||||
|
|
||||||
(define-syntax TIOCGWINSZ ;<asm-generic/ioctls.h>
|
(define-syntax TIOCGWINSZ ;<asm-generic/ioctls.h>
|
||||||
(identifier-syntax #x5413))
|
(identifier-syntax #x5413))
|
||||||
|
|
||||||
|
|
|
@ -259,6 +259,31 @@ (define perform-container-tests?
|
||||||
(#f #f)
|
(#f #f)
|
||||||
(lo (interface-address lo)))))))
|
(lo (interface-address lo)))))))
|
||||||
|
|
||||||
|
(test-equal "tcgetattr ENOTTY"
|
||||||
|
ENOTTY
|
||||||
|
(catch 'system-error
|
||||||
|
(lambda ()
|
||||||
|
(call-with-input-file "/dev/null"
|
||||||
|
(lambda (port)
|
||||||
|
(tcgetattr (fileno port)))))
|
||||||
|
(compose system-error-errno list)))
|
||||||
|
|
||||||
|
(test-skip (if (and (file-exists? "/proc/self/fd/0")
|
||||||
|
(string-prefix? "/dev/pts/" (readlink "/proc/self/fd/0")))
|
||||||
|
0
|
||||||
|
2))
|
||||||
|
|
||||||
|
(test-assert "tcgetattr"
|
||||||
|
(let ((termios (tcgetattr 0)))
|
||||||
|
(and (termios? termios)
|
||||||
|
(> (termios-input-speed termios) 0)
|
||||||
|
(> (termios-output-speed termios) 0))))
|
||||||
|
|
||||||
|
(test-assert "tcsetattr"
|
||||||
|
(let ((first (tcgetattr 0)))
|
||||||
|
(tcsetattr 0 TCSANOW first)
|
||||||
|
(equal? first (tcgetattr 0))))
|
||||||
|
|
||||||
(test-assert "terminal-window-size ENOTTY"
|
(test-assert "terminal-window-size ENOTTY"
|
||||||
(call-with-input-file "/dev/null"
|
(call-with-input-file "/dev/null"
|
||||||
(lambda (port)
|
(lambda (port)
|
||||||
|
|
Loading…
Reference in a new issue