Path: csiph.com!news.nrbbs.org!border-4.nntp.ord.giganews.com!nntp.giganews.com!local-2.nntp.ord.giganews.com!Xl.tags.giganews.com!local-4.nntp.ord.giganews.com!news.giganews.com.POSTED!not-for-mail NNTP-Posting-Date: Fri, 07 Aug 2026 00:12:04 +0000 From: steve g Newsgroups: comp.lang.lisp Subject: :sbcl-posix and termios Date: Thu, 06 Aug 2026 20:12:03 -0400 Message-ID: <87ecga94bw.fsf@gmail.com> User-Agent: Gnus/5.13 (Gnus v5.13) Cancel-Lock: sha1:W41Whk2CSSLlJy/Tf0AcZhOPTSk= MIME-Version: 1.0 Content-Type: text/plain Lines: 437 X-Usenet-Provider: http://www.giganews.com X-Trace: sv3-jKJjfW9ZXQKdMwP28deafJU8z4QY2h8nxLouYhh1GHDT4PmH6iMjCs9tJ/PEl++swWM/qLYnv22K4XG!CxNCRdxIPewSQQOBtIHyeH2C30ijeEhjwsZSkl3aw+pdFUI= X-Complaints-To: abuse@giganews.com X-DMCA-Notifications: http://www.giganews.com/info/dmca.html X-Abuse-and-DMCA-Info: Please be sure to forward a copy of ALL headers X-Abuse-and-DMCA-Info: Otherwise we will be unable to process your complaint properly X-Postfilter: 1.3.40 Xref: csiph.com comp.lang.lisp:61317 I have been going crazy over this (over the years...) I remeber that the Linux OS would put a pad of 0 bytes into the terminfo struct. Really mean :) I've enclosed a postscript because I like the colors better. TINFO> (setq xyz (make-instance 'sb-posix:termios)) # TINFO> xyz # TINFO> (sb-posix:termios-iflags xyz) ; Evaluation aborted on #. TINFO> (sb-posix:termios-iflag xyz) ; Evaluation aborted on #. TINFO> (sb-posix:termios-oflag xyz) ; Evaluation aborted on #. TINFO> (sb-posix::termios-oflag xyz) ; Evaluation aborted on #. TINFO> (sb-posix:termios-lflag xyz) ; Evaluation aborted on #. TINFO> (current-tidevice) #S(TIDEVICE :NAME "New Device" :STREAM-OUTPUT # :STREAM-INPUT # :OFD 8 :IFD 9 :ROWS 31 :COLS 193 :BAUD-RATE-INPUT 9600 :BAUD-RATE-OUTPUT 9600 :UPC 1042 :OBUFSIZE 1066 :TERMIOS-OLD # :TERMIOS-NEW # :CLOSED NIL) TINFO> (termios-old (current-tidevice)) ; Evaluation aborted on #. TINFO> (tidevice-termios-old (current-tidevice)) # TINFO> (posix:iflag (tidevice-termios-old (current-tidevice))) ; Evaluation aborted on #. TINFO> (sb-posix:iflag (tidevice-termios-old (current-tidevice))) ; Evaluation aborted on #. TINFO> (import :sb-posix) T TINFO> (sb-posix:iflag (tidevice-termios-old (current-tidevice))) ; Evaluation aborted on #. TINFO> (sb-posix::iflag (tidevice-termios-old (current-tidevice))) ; Evaluation aborted on #. TINFO> Should I just move terminfo to a shared library? The following is the code I have that does work. (defun tidevice-open (tty) (let ((curdev (current-tidevice))) ;; This should raise a condition (if (null tty) (setq tty "/dev/pts/1")) (setq tty (namestring tty)) (let* ((ofd (sb-posix:open tty sb-posix::o-wronly (logior sb-posix::o-noctty sb-posix::o-nonblock Sb-POSIX::O-DIRECT SB-POSIX::O-NDELAY ))) (ifd (sb-posix:open tty sb-posix::o-rdonly (logior sb-posix::o-noctty sb-posix::o-nonblock) )) ;; this needs to be fixed for input (output (sb-sys:make-fd-stream ofd :name "Device Output" :auto-close t :output t :input nil :buffering :none :element-type 'character :external-format :ascii)) (input (sb-sys:make-fd-stream ifd :name "Device Input" :auto-close t :buffering :none :output nil :input t :element-type '(unsigned-byte 8) :timeout 1.25 ))) (setf (tidevice-stream-input curdev) input) (setf (tidevice-stream-output curdev) output) (setf (tidevice-ofd curdev) ofd) (setf (tidevice-ifd curdev) ifd) (setf (tidevice-closed curdev) nil) ;; FIXME: check the input (sb-posix:tcgetattr ifd (tidevice-termios-old curdev)) (sb-posix:tcgetattr ifd (tidevice-termios-new curdev)) ;; device shardware (let ((rows (get-window-size-rows ofd)) (cols (get-window-size-columns ofd)) (baud-input (get-input-baud-rate (tidevice-termios-new curdev))) (baud-output (get-output-baud-rate (tidevice-termios-new curdev)))) ;; device size (setf (tidevice-rows curdev) rows) (setf (tidevice-cols curdev) cols) ;; set baud (setf (tidevice-baud-rate-output curdev) baud-output (tidevice-baud-rate-input curdev) baud-input) ;; set upc mmUPC and buffer size (setf (tidevice-upc curdev) (baud-get-upc baud-input baud-DIVIDEND)) (setf (tidevice-obufsize curdev) (baud-get-bufsize baud-TIMES (tidevice-upc curdev))) )))) ;;;; This code does not work anymore. I might be using a older version. I really want to clean this up but I still think doing it in C is the best option - I'd rather just use sbcl. (deftype termios-mode-p () `(member :CBREAK :CBREAK-ON :CANONICAL :QIFLUSH-OFF :QIFLUSH-ON :ECHO-ON :ECHO-OFF :CR-TO-NL :NL-TO-CR :ASCII :META-ON :ESC-ON :PACKET :RESET :CLOSE :ESC) ) (defun tty-device-termios-set (&optional (mode :packet)) "Set terminal attributes for fildes in <*current-screen> based on mode. :CLOSE Close termios. :RESET Reset current termios with open time termios. :CBREAK Noncanonical Mode (Example libc). :CBREAk-OFF Cannon mode normal. :RAW Enables raw mode. :QIFLUSH-OFF Enabling flushing of buffers on INTR QUIT or SUSP (QIFLUSH Mode) disabled :QIFLUSH :QIFLUSH-ON Disable flushing of buffers on INTR QUIT or SUSP (QIFLUSH Mode) enabled :CRNL :CR-to-N Enabling Carriage Return to New line Mode. :NLCR :NL-to-CR Disabling Carriage Return to New line Mode. :SIGNAL-ON Enabled editing interupts :SIGNAL-OFF Disable editinhg interrupts :META-ON :ESC-ON Meta Mode enabled :ESC-OFF :META-OFF Meta Mode disabled. :ASCII ASCII Mode enabled. :PACKET my favorite mix. :ECHO-ON Enable echo. :ECHO-OFF Disable echo (for reading passwords, etc). When using GNU/Linux they keyboard is also set via ioctl to the accoodating mode." (let* ((curscr (current-screen)) (termios (screen-termios-new curscr))) (sb-posix::tcsetattr (screen-ofd curscr) SB-POSIX::TCSANOW termios) (sb-posix::tcsetattr (screen-ifd curscr) SB-POSIX::TCSANOW termios) ;; curs_inopts (3x) (ccase mode (:close (terminfo::debugging-motion-macros "Closing IO") (finish-output (screen-output curscr)) (clear-input (screen-input curscr)) (sb-posix::tcsetattr (screen-ofd curscr) SB-POSIX::TCSANOW termios) (sb-posix::tcsetattr (screen-ifd curscr) SB-POSIX::TCSANOW termios) (sb-posix:close (screen-ifd curscr)) (sb-posix:close (screen-ofd curscr)) ;; (attr-reset (screen-attr-flag curscr)) ;; (stat-reset (screen-stat-flag curscr)) (return-from tty-device-termios-set mode)) (:reset (terminfo::debugging-motion-macros "Restting IO to UNICODE") (let ((oldtermios (screen-termios-old curscr))) (setf (sb-posix:termios-iflag termios) (sb-posix:termios-iflag oldtermios)) (setf (sb-posix:termios-oflag termios) (sb-posix:termios-oflag oldtermios)) (setf (sb-posix:termios-cflag termios) (sb-posix:termios-cflag oldtermios)) (setf (sb-posix:termios-Lflag termios) (sb-posix:termios-Lflag oldtermios)) (setf (aref (sb-posix:termios-cc termios) sb-posix:vmin) (aref (sb-posix:termios-cc oldtermios) sb-posix:vmin)) (setf (aref (sb-posix:termios-cc termios) sb-posix:vtime) (aref (sb-posix:termios-cc oldtermios) sb-posix:vtime)) (sb-posix:tcflush (screen-ofd curscr) sb-posix:tcsanow ) (sb-posix:tcflush (screen-ifd curscr) sb-posix:tcsanow ) (terminfo::set-keyboard-mode (screen-ifd curscr) terminfo::K_UNICODE)) ;; (attr-reset (screen-attr-flag curscr)) ;; (stat-reset (screen-stat-flag curscr))) ) ((:CBREAK :NONCANONICAL) (terminfo::debugging-motion-macros "CBREAK Mode enabled") (terminfo::set-keyboard-mode (screen-ifd curscr) terminfo::K_MEDIUMRAW) (terminfo::debugging-motion-macros "Set keyboard into Medium Raw") ;; set cannon mode (setf (sb-posix:termios-Lflag termios) (logior (sb-posix::termios-Lflag termios) sb-posix::icanon)) ;; set nl/cr (setf (sb-posix::termios-iflag termios) (logior (sb-posix::termios-iflag termios) sb-posix::icrnl)) ;; turn off input is UTF8 mode when available (when (boundp 'terminfo::IUTF8) (setf (sb-posix::termios-iflag termios) (logior (sb-posix:termios-iflag termios) terminfo::IUTF8))) (setf (aref (sb-posix:termios-cc termios) sb-posix:vmin) 1) (setf (aref (sb-posix:termios-cc termios) sb-posix:vtime) 1) ) ((:CBREAK-OFF :CANNON-OFF) (terminfo::debugging-motion-macros "CBREAK Mode disabled") (terminfo::set-keyboard-mode (screen-ifd curscr) terminfo::K_UNICODE) ;; set non-cannon mode, no echo, no flush on signal ;; set cannon mode, no echo, no flush on signal (setf (sb-posix:termios-Lflag termios) (logand (sb-posix:termios-Lflag termios) (lognot sb-posix:icanon))) ;; set read time/bytes (setf (aref (sb-posix:termios-cc termios) sb-posix:vmin) 4) (setf (aref (sb-posix:termios-cc termios) sb-posix:vtime) 1) ;; set ignore nl/cr (setf (sb-posix::termios-iflag termios) (logior (sb-posix:termios-iflag termios) sb-posix:icrnl)) ;; turn on input to UTF8 mode when available (when (boundp 'terminfo::IUTF8) (setf (sb-posix::termios-iflag termios) (logior (sb-posix:termios-iflag termios) terminfo::IUTF8))) ) (:RAW ;; use with caution (terminfo::debugging-motion-macros "RAW Mode enabled") (terminfo::set-keyboard-mode (screen-ifd curscr) terminfo::K_RAW) (setf (sb-posix:termios-Lflag termios) (logior (sb-posix:termios-Lflag termios) (logior sb-posix:ISIG sb-posix:ICANON))) (setf (sb-posix::termios-iflag termios) (logior (sb-posix:termios-iflag termios) (logior sb-posix:ISIG sb-posix:ICANON sb-posix:IEXTEN)))) ((:QIFLUSH :QIFLUSH-ON) (terminfo::debugging-motion-macros "Disable flushing of buffers on INTR QUIT or SUSP (QIFLUSH Mode) enabled") (setf (sb-posix:termios-Lflag termios) (logand (sb-posix:termios-Lflag termios) (lognot sb-posix:noflsh)))) (:QIFLUSH-OFF (terminfo::debugging-motion-macros "Enabling flushing of buffers on INTR QUIT or SUSP (QIFLUSH Mode disabled)") (setf (sb-posix:termios-Lflag termios) (logior (sb-posix:termios-Lflag termios) sb-posix:noflsh))) ((:CRNL :CR-TO-NL) (terminfo::debugging-motion-macros "Enabling Carriage Return to New line Mode.") ;; ignore carriage returns (when (logand (sb-posix:termios-iflag termios) sb-posix:INLCR) (setf (sb-posix::termios-iflag termios) (logior (sb-posix:termios-iflag termios) sb-posix:INLCR))) (setf (sb-posix:termios-iflag termios) (logand (sb-posix::termios-iflag termios) (lognot sb-posix:IGNCR))) (setf (sb-posix:termios-oflag termios) (logand (sb-posix:termios-oflag termios) (lognot sb-posix:OCRNL)))) ((:NLCR :NL-to-CR) (terminfo::debugging-motion-macros "Disabling Carriage Return to New line Mode.") ;; if ignore CR is set, unset it (when (logand (sb-posix::termios-iflag termios) sb-posix:INLCR) ;; turn off ignore cr when set (setf (sb-posix:termios-iflag termios) (logior (sb-posix:termios-iflag termios) sb-posix:IGNCR))) (setf (sb-posix::termios-iflag termios) (logand (sb-posix:termios-iflag termios) (lognot sb-posix:IGNCR))) (setf (sb-posix:termios-oflag termios) (logand (sb-posix:termios-oflag termios) (lognot sb-posix:IGNCR)))) ((:META-ON :ESC-ON) (terminfo::debugging-motion-macros "Meta Mode enabled.") (setf (sb-posix:termios-cflag termios) (logand (sb-posix:termios-cflag termios) (lognot sb-POSIX:CS8)))) ((:ESC-OFF :META-OFF) (terminfo::debugging-motion-macros "Meta Mode disabled.") (setf (sb-posix:termios-cflag termios) (logior (sb-posix:termios-cflag termios) sb-posix:CS8))) (:ASCII (terminfo::debugging-motion-macros "ASCII Mode enabled") (setf (sb-posix:termios-Lflag termios) (logand (sb-posix:termios-Lflag termios) (lognot sb-posix::icanon ))) (setf (sb-posix:termios-Lflag termios) (logior (sb-posix::termios-Lflag termios) (logior sb-posix:echo terminfo::ECHOCTL))) (setf (aref (sb-posix:termios-cc termios) sb-posix:vmin) 1) (setf (aref (sb-posix:termios-cc termios) sb-posix:vtime) 0) (terminfo::set-keyboard-mode (screen-ifd curscr) terminfo::K_XLATE)) (:SIGNAL-OFF (setf (sb-posix:termios-lflag termios) (logand (sb-posix:termios-Lflag termios) (lognot (logior sb-posix:isig)))) (terminfo::debugging-motion-macros "Editing signals disabled")) (:SIGNAL-ON (setf (sb-posix:termios-lflag termios) (logior (sb-posix:termios-Lflag termios) sb-posix:isig)) (terminfo::debugging-motion-macros "Editing signals enabled")) (:PACKET #| Best for packet mode/no signals Old Flags New Flags ------------------------ i_flags; 25862 => 25606 O_flags; 5 => 5 C_flags; 1215 => 1215 L_flags; 35387 => 35377 |# ;; ioctl KDSKBMODE: set to unicode/medium-raw input (terminfo::debugging-motion-macros "Packet Mode enabled") (setf (sb-posix:termios-lflag termios) (logand (sb-posix:termios-Lflag termios) (lognot (logior ;; sb-posix:isig sb-posix:icanon sb-posix:echo terminfo::echoctl)))) ;; size of byte 8 (setf (sb-posix:termios-cflag termios) (logand (sb-posix:termios-cflag termios) sb-posix:CS8)) (setf (aref (sb-posix:termios-cc termios) sb-posix:vmin) 1) (setf (aref (sb-posix:termios-cc termios) sb-posix:vtime) 1) (sb-posix:tcflush (screen-ifd curscr) sb-posix:tcsanow ) (sb-posix:tcflush (screen-ofd curscr) sb-posix:tcsanow ) (terminfo::set-keyboard-mode (screen-ifd curscr) terminfo::K_MEDIUMRAW) ) (:ECHO-ON (setf (sb-posix:termios-Lflag termios) (logior (sb-posix:termios-Lflag termios) sb-posix:echo)) (terminfo::debugging-motion-macros "Echo Mode enabled")) (:ECHO-OFF (terminfo::debugging-motion-macros "Echo Mode disabled") (setf (sb-posix:termios-Lflag termios) (logand (sb-posix:termios-Lflag termios) (lognot sb-posix:echo)))) ) ;; flush the streams before filedescriptors (clear-input (screen-input curscr)) (force-output (screen-output curscr)) (sb-posix::tcsetattr (screen-ofd curscr) sb-posix:tcsaflush termios) (sb-posix::tcsetattr (screen-ifd curscr) sb-posix:tcsaflush termios))) (defvar *termios-print-string* (mapconcat #'identity '( "Old Flags New Flags" "------------------------" "i_flags; ~d => ~d" "O_flags; ~d => ~d" "C_flags; ~d => ~d" "L_flags; ~d => ~d") (string #\Newline) )) (defun tty-device-termios-display (&optional (stream t)) "Print the current bits in a terminfo structure." (let ((oldtermios (screen-termios-old (current-screen))) (newtermios (screen-termios-new (current-screen)))) (format stream *termios-print-string* (sb-posix:termios-iflag oldtermios) (sb-posix:termios-iflag newtermios) (sb-posix:termios-oflag oldtermios) (sb-posix:termios-oflag newtermios) (sb-posix:termios-cflag oldtermios) (sb-posix:termios-cflag newtermios) (sb-posix:termios-lflag oldtermios) (sb-posix:termios-lflag newtermios)))) TINFO> (tty-device-termios-display t) => The slot SB-POSIX::IFLAG is unbound in the object #. [Condition of type UNBOUND-SLOT] ;;; Inspection results. TINFO> (current-tidevice) #S(TIDEVICE :NAME "New Device" :STREAM-OUTPUT # :STREAM-INPUT # :OFD 8 :IFD 9 :ROWS 31 :COLS 193 :BAUD-RATE-INPUT 9600 :BAUD-RATE-OUTPUT 9600 :UPC 1042 :OBUFSIZE 1066 :TERMIOS-OLD # :TERMIOS-NEW # :CLOSED NIL) TINFO> (termios-old (current-tidevice)) ; Evaluation aborted on #. TINFO> (tidevice-termios-old (current-tidevice)) # TINFO> (posix:iflag (tidevice-termios-old (current-tidevice))) ; Evaluation aborted on #. TINFO> (sb-posix:iflag (tidevice-termios-old (current-tidevice))) ; Evaluation aborted on #. TINFO> (import :sb-posix) T TINFO> (sb-posix:iflag (tidevice-termios-old (current-tidevice))) ; Evaluation aborted on #. TINFO> (sb-posix::iflag (tidevice-termios-old (current-tidevice))) ; Evaluation aborted on #. TINFO> ; No value TINFO> ; No value TINFO> ; No value TINFO> (tty-device-termios-display t) ; Evaluation aborted on #. TINFO> ; No value TINFO> (inspect (current-tidevice)) The object is a STRUCTURE-OBJECT of type TIDEVICE. 0. NAME: New Device 1. STREAM-OUTPUT: # 2. STREAM-INPUT: # 3. OFD: 8 4. IFD: 9 5. ROWS: 31 6. COLS: 193 7. BAUD-RATE-INPUT: 9600 8. BAUD-RATE-OUTPUT: 9600 9. UPC: 1042 10. OBUFSIZE: 1066 11. TERMIOS-OLD: # 12. TERMIOS-NEW: # 13. CLOSED: NIL > 11 The object is a STANDARD-OBJECT of type SB-POSIX:TERMIOS. 0. IFLAG: 17408 1. OFLAG: 5 2. CFLAG: 983231 3. LFLAG: 35377 4. CC: #(3 28 127 21 4 0 1 0 17 19 26 0 18 0 23 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) 5. REMAINING-FIELDS: #(0 0 0 0 0 150 0 0 0 150 0 0) > q any help would be useful. sorry for the postscript my email does not like me today.