Skip to content

Instantly share code, notes, and snippets.

@erkin
Last active October 5, 2020 02:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erkin/21f09b7c8d150314fc56a3d2d188f7ed to your computer and use it in GitHub Desktop.
Save erkin/21f09b7c8d150314fc56a3d2d188f7ed to your computer and use it in GitHub Desktop.
getpass in Chez Scheme
;;; Chez Scheme clone of Python `getpass'
;;; Based on github.com/smitchell556/get-pass
(library (get-pass)
(export get-pass)
(import (chezscheme))
;;; FFI portion
;;; See termios(3) for more info
(define-ftype termios
(struct
(c_iflag unsigned)
(c_oflag unsigned)
(c_cflag unsigned)
(c_lflag unsigned)
(c_cc (array 32 unsigned))
(c_ispeed unsigned)
(c_ospeed unsigned)))
(define tcgetattr
(foreign-procedure
"tcgetattr" (int (* termios)) int))
(define tcsetattr
(foreign-procedure
"tcsetattr" (int int (* termios)) int))
(define echo 8) ; Echo input to output
(define tcsanow 0) ; Apply changes right away
(define tcsadrain 1) ; Apply changes after output is written
;; Turn off the ECHO bit on the local modes field of the termios struct
(define (echo-off! t)
(ftype-set! termios (c_lflag) t
(bitwise-and
(ftype-ref termios (c_lflag) t)
(bitwise-not echo))))
;; Turn on the ECHO bit
(define (echo-on! t)
(ftype-set! termios (c_lflag) t
(bitwise-ior
(ftype-ref termios (c_lflag) t)
echo)))
(define (get-pass prompt in out)
(display prompt out)
(flush-output-port out)
(let ((fd (port-file-descriptor in)) ; Get the input port's fd
(t #f)) ; termios struct pointer
(dynamic-wind
(lambda ()
;; Allocate a termios struct
(set! t (make-ftype-pointer
termios (foreign-alloc (ftype-sizeof termios))))
;; Fill t with fd's terminal properties
(tcgetattr fd t)
;; Disable the ECHO bit on t
(echo-off! t)
;; Push t back to fd, effective once the port is flushed
(tcsetattr fd tcsadrain t))
;; Read line and return it
(lambda () (get-line in))
(lambda ()
;; Enable the ECHO bit on t
(echo-on! t)
;; Push t to fd again, effective immediately
(tcsetattr fd tcsanow t)
;; Free the termios struct
(foreign-free (ftype-pointer-address t))
;; Line break if necessary
(fresh-line out))))))
;;; Usage example:
(import (get-pass))
(load-shared-object "libc.so.6")
(display (string-append "The password entered was: "
(get-pass "Password: " (current-input-port) (current-output-port))))
(newline)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment