// makeRaw puts the terminal connected to the given file descriptor into raw // mode and returns the previous state of the terminal so that it can be // restored. // Source: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c func makeRaw(fd int) (*unix.Termios, error) { oldTermiosPtr, err := unix.IoctlGetTermios(int(fd), unix.TCGETS) if err != nil { return nil, err } oldTermios := *oldTermiosPtr newTermios := oldTermios newTermios.Lflag &^= syscall.ECHO | syscall.ECHOE | syscall.ECHOK | syscall.ECHONL if err := unix.IoctlSetTermios(fd, unix.TCSETS, &newTermios); err != nil { return nil, err } return oldTermiosPtr, nil }
// makeRaw puts the terminal connected to the given file descriptor into raw // mode and returns the previous state of the terminal so that it can be // restored. // Source: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c func makeRaw(fd uintptr) (*terminalState, error) { oldTermiosPtr, err := unix.IoctlGetTermios(int(fd), unix.TCGETS) if err != nil { return nil, err } oldTermios := *oldTermiosPtr newTermios := oldTermios newTermios.Lflag &^= syscall.ECHO | syscall.ECHOE | syscall.ECHOK | syscall.ECHONL if err := unix.IoctlSetTermios(int(fd), unix.TCSETS, &newTermios); err != nil { return nil, err } return &terminalState{ state: oldTermiosPtr, }, nil }
// ReadPassword reads a line of input from a terminal without local echo. This // is commonly used for inputting passwords and other sensitive data. The slice // returned does not include the \n. // see also: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c func ReadPassword(fd int) ([]byte, error) { val, err := unix.IoctlGetTermios(fd, unix.TCGETS) if err != nil { return nil, err } oldState := *val newState := oldState newState.Lflag &^= syscall.ECHO newState.Lflag |= syscall.ICANON | syscall.ISIG newState.Iflag |= syscall.ICRNL err = unix.IoctlSetTermios(fd, unix.TCSETS, &newState) if err != nil { return nil, err } // XXX what about resetting the terminal after a signal like Control-C? // XXX or is ISIG sufficient? defer func() { unix.IoctlSetTermios(fd, unix.TCSETS, &oldState) }() var buf [16]byte var ret []byte for { n, err := syscall.Read(fd, buf[:]) if err != nil { return nil, err } if n == 0 { if len(ret) == 0 { return nil, io.EOF } break } if buf[n-1] == '\n' { n-- } ret = append(ret, buf[:n]...) if n < len(buf) { break } } return ret, nil }
// ReadPassword reads a line of input from a terminal without local echo. This // is commonly used for inputting passwords and other sensitive data. The slice // returned does not include the \n. func ReadPassword(fd int) ([]byte, error) { // see also: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c val, err := unix.IoctlGetTermios(fd, unix.TCGETS) if err != nil { return nil, err } oldState := *val newState := oldState newState.Lflag &^= syscall.ECHO newState.Lflag |= syscall.ICANON | syscall.ISIG newState.Iflag |= syscall.ICRNL err = unix.IoctlSetTermios(fd, unix.TCSETS, &newState) if err != nil { return nil, err } defer unix.IoctlSetTermios(fd, unix.TCSETS, &oldState) var buf [16]byte var ret []byte for { n, err := syscall.Read(fd, buf[:]) if err != nil { return nil, err } if n == 0 { if len(ret) == 0 { return nil, io.EOF } break } if buf[n-1] == '\n' { n-- } ret = append(ret, buf[:n]...) if n < len(buf) { break } } return ret, nil }
// IsTerminal returns true if the given file descriptor is a terminal. func IsTerminal() bool { _, err := unix.IoctlGetTermios(int(os.Stdout.Fd()), unix.TCGETA) return err == nil }
// Tcgetattr gets the current serial port settings. func Tcgetattr(fd uintptr, argp *syscall.Termios) error { termios, err := unix.IoctlGetTermios(int(fd), unix.TCGETS) *argp = syscall.Termios(*termios) return err }
// IsTty returns true if the given file descriptor is a terminal. func IsTty(fd uintptr) bool { _, err := unix.IoctlGetTermios(int(fd), unix.TCGETA) return err == nil }