// 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 }
func read(f *os.File) (string, error) { fd := int(f.Fd()) if !isTerminal(fd) { return "", fmt.Errorf("File descriptor %d is not a terminal", fd) } oldState, err := makeRaw(fd) if err != nil { return "", err } defer unix.IoctlSetTermios(fd, unix.TCSETS, oldState) return readline(f) }
// 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 }
func restore(fd uintptr, oldState *terminalState) error { return unix.IoctlSetTermios(int(fd), unix.TCSETS, oldState.state) }
// Tcsetattr sets the current serial port settings. func Tcsetattr(fd, action uintptr, argp *syscall.Termios) error { return unix.IoctlSetTermios(int(fd), int(action), (*unix.Termios)(argp)) }