예제 #1
0
파일: terminal.go 프로젝트: decred/dcrd
func startTerminal(c *config) {
	var clear, protected bool

	fmt.Println("Starting terminal mode.")
	fmt.Println("Enter h for [h]elp.")
	fmt.Println("Enter l for [l]ist of commands.")
	fmt.Println("Enter q for [q]uit.")

	termState, err := terminal.MakeRaw(int(os.Stdin.Fd()))
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to set raw mode on STDIN: %v\n",
			err)
		return
	}
	n := terminal.NewTerminal(os.Stdin, "> ")
	n.SetSize(int(^uint(0)>>1), 0)

	var ln string
	for {
		if !protected {
			ln, err = n.ReadLine()
		} else {
			ln, err = n.ReadPassword(">*")
		}
		terminal.Restore(int(os.Stdin.Fd()), termState)
		if err != nil {
			break
		}

		quit := execute(&protected, c, ln, &clear)
		if quit {
			break
		}

		if clear {
			fmt.Println("Clearing history...")
			termState, err = terminal.MakeRaw(int(os.Stdin.Fd()))
			if err != nil {
				fmt.Fprintf(os.Stderr, "Failed to set raw "+
					"mode on STDIN: %v\n", err)
				break
			}
			n = terminal.NewTerminal(os.Stdin, "> ")
			n.SetSize(int(^uint(0)>>1), 0)
			clear = false
		} else {
			termState, err = terminal.MakeRaw(int(os.Stdin.Fd()))
			if err != nil {
				fmt.Fprintf(os.Stderr, "Failed to set raw "+
					"mode on STDIN: %v\n", err)
				break
			}
		}
	}
	fmt.Println("exiting...")
}
예제 #2
0
파일: main.go 프로젝트: echlebek/erickson
func askConfig() (cfg, error) {
	stdinState, err := terminal.MakeRaw(syscall.Stdin)
	if err != nil {
		return cfg{}, err
	}
	defer terminal.Restore(syscall.Stdin, stdinState)
	stdoutState, err := terminal.MakeRaw(syscall.Stdout)
	if err != nil {
		return cfg{}, err
	}
	defer terminal.Restore(syscall.Stdout, stdoutState)
	t := struct {
		io.Reader
		io.Writer
	}{os.Stdin, os.Stdout}

	term := terminal.NewTerminal(t, "")

	msg := "Configure git-erickson for first time use.\nErickson server URL: "
	if _, err := term.Write([]byte(msg)); err != nil {
		return cfg{}, err
	}

	url, err := term.ReadLine()
	if err != nil {
		return cfg{}, err
	}

	cmd := exec.Command("git", "config", "--global", "erickson.url", string(url))
	if err := cmd.Run(); err != nil {
		return cfg{}, err
	}

	if _, err := term.Write([]byte("Erickson username: "******"git", "config", "--global", "erickson.username", string(username))
	if err := cmd.Run(); err != nil {
		return cfg{}, err
	}

	return cfg{url: url, username: username}, nil
}
예제 #3
0
파일: ui.go 프로젝트: PMaynard/coyim
// NewCLI creates a new cliUI instance
func NewCLI(version string) UI {
	oldState, err := terminal.MakeRaw(0)
	if err != nil {
		panic(err.Error())
	}

	term := terminal.NewTerminal(os.Stdin, "")
	updateTerminalSize(term)
	term.SetBracketedPasteMode(true)

	resizeChan := make(chan os.Signal)
	go func() {
		for _ = range resizeChan {
			updateTerminalSize(term)
		}
	}()
	signal.Notify(resizeChan, syscall.SIGWINCH)

	return &cliUI{
		term:      term,
		oldState:  oldState,
		terminate: make(chan bool),
		input: &input{
			term:        term,
			uidComplete: new(priorityList),
		},
		RosterEditor: RosterEditor{
			PendingRosterChan: make(chan *RosterEdit),
		},
		events:   make(chan interface{}),
		commands: make(chan interface{}, 5),
	}
}
예제 #4
0
파일: processes.go 프로젝트: harryross/rack
func copyWithExit(w io.Writer, r io.Reader, ch chan int) {
	buf := make([]byte, 1024)
	isTerminalRaw := false

	for {
		n, err := r.Read(buf)

		if err == io.EOF {
			ch <- 1
			return
		}

		if err != nil {
			break
		}

		if !isTerminalRaw {
			terminal.MakeRaw(int(os.Stdin.Fd()))
			isTerminalRaw = true
		}

		if s := string(buf[0:n]); strings.HasPrefix(s, "F1E49A85-0AD7-4AEF-A618-C249C6E6568D:") {
			code, _ := strconv.Atoi(s[37:])
			ch <- code
			return
		}

		_, err = w.Write(buf[0:n])

		if err != nil {
			break
		}
	}
}
예제 #5
0
func makeRaw(fd uintptr) (*terminalState, error) {
	state, err := terminal.MakeRaw(int(fd))

	return &terminalState{
		state: state,
	}, err
}
예제 #6
0
// promptForPassword prompts the user for a password twice, returning
// the read bytes if they match, or an error.
// It turns out getting non-echo stdin is tricky and not portable at all.
// terminal seems a decent solution, although it does not work on windows.
func promptForPassword() ([]byte, error) {
	// Use a raw terminal.
	oldState, err := terminal.MakeRaw(0)
	if err != nil {
		return nil, err
	}
	defer func() {
		_ = terminal.Restore(0, oldState)
	}()

	fmt.Print("Enter password: "******"\nConfirm password: "******"\n")
	if !bytes.Equal(one, two) {
		return nil, util.Errorf("password mismatch")
	}
	return []byte(one), nil
}
예제 #7
0
파일: uninstall.go 프로젝트: colonelmo/helm
// promptConfirm prompts a user to confirm (or deny) something.
//
// True is returned iff the prompt is confirmed.
// Errors are reported to the log, and return false.
//
// Valid confirmations:
// 	y, yes, true, t, aye-aye
//
// Valid denials:
//	n, no, f, false
//
// Any other prompt response will return false, and issue a warning to the
// user.
func promptConfirm(msg string) bool {
	oldState, err := terminal.MakeRaw(0)
	if err != nil {
		log.Err("Could not get terminal: %s", err)
		return false
	}
	defer terminal.Restore(0, oldState)

	f := readerWriter(log.Stdin, log.Stdout)
	t := terminal.NewTerminal(f, msg+" (y/N) ")
	res, err := t.ReadLine()
	if err != nil {
		log.Err("Could not read line: %s", err)
		return false
	}
	res = strings.ToLower(res)
	switch res {
	case "yes", "y", "true", "t", "aye-aye":
		return true
	case "no", "n", "false", "f":
		return false
	}
	log.Warn("Did not understand answer %q, assuming No", res)
	return false
}
예제 #8
0
파일: attach_linux.go 프로젝트: vmware/vic
func rawConnectionFromSerial() (net.Conn, error) {
	log.Info("opening ttyS0 for backchannel")
	f, err := os.OpenFile(pathPrefix+"/ttyS0", os.O_RDWR|os.O_SYNC|syscall.O_NOCTTY, backchannelMode)
	if err != nil {
		detail := fmt.Errorf("failed to open serial port for backchannel: %s", err)
		log.Error(detail)
		return nil, detail
	}

	// set the provided FDs to raw if it's a termial
	// 0 is the uninitialized value for Fd
	if f.Fd() != 0 && terminal.IsTerminal(int(f.Fd())) {
		log.Debug("setting terminal to raw mode")
		s, err := terminal.MakeRaw(int(f.Fd()))
		if err != nil {
			return nil, err
		}

		log.Infof("s = %#v", s)
	}

	var conn net.Conn

	log.Infof("creating raw connection from ttyS0 (fd=%d)", f.Fd())

	conn, err = serial.NewFileConn(f)
	return conn, err
}
예제 #9
0
파일: light.go 프로젝트: junegunn/fzf
func (r *LightRenderer) Resume() bool {
	terminal.MakeRaw(r.fd())
	r.csi("?1049l")
	r.flush()
	// Should redraw
	return true
}
예제 #10
0
func copyWithExit(w io.Writer, r io.Reader, ch chan int) {
	buf := make([]byte, 1024)
	isTerminalRaw := false

	for {
		n, err := r.Read(buf)

		if err == io.EOF {
			ch <- 1
			return
		}

		if err != nil {
			break
		}

		if !isTerminalRaw {
			terminal.MakeRaw(int(os.Stdin.Fd()))
			isTerminalRaw = true
		}

		if s := string(buf[0:n]); strings.HasPrefix(s, StatusCodePrefix) {
			code, _ := strconv.Atoi(strings.TrimSpace(s[37:]))
			ch <- code
			return
		}

		_, err = w.Write(buf[0:n])

		if err != nil {
			break
		}
	}
}
예제 #11
0
func client(user, passwd, ip string) {
	config := &ssh.ClientConfig{
		User: user,
		Auth: []ssh.AuthMethod{
			ssh.Password(passwd),
		},
	}
	client, err := ssh.Dial("tcp", ip, config)
	if err != nil {
		fmt.Println("建立连接: ", err)
		return
	}
	defer client.Close()
	session, err := client.NewSession()
	if err != nil {
		fmt.Println("创建Session出错: ", err)
		return
	}
	defer session.Close()

	fd := int(os.Stdin.Fd())
	oldState, err := terminal.MakeRaw(fd)
	if err != nil {
		fmt.Println("创建文件描述符: ", err)
		return
	}

	session.Stdout = os.Stdout
	session.Stderr = os.Stderr
	session.Stdin = os.Stdin

	termWidth, termHeight, err := terminal.GetSize(fd)
	if err != nil {
		fmt.Println("获取窗口宽高: ", err)
		return
	}
	defer terminal.Restore(fd, oldState)

	modes := ssh.TerminalModes{
		ssh.ECHO:          1,
		ssh.TTY_OP_ISPEED: 14400,
		ssh.TTY_OP_OSPEED: 14400,
	}

	if err := session.RequestPty("xterm-256color", termHeight, termWidth, modes); err != nil {
		fmt.Println("创建终端出错: ", err)
		return
	}
	err = session.Shell()
	if err != nil {
		fmt.Println("执行Shell出错: ", err)
		return
	}
	err = session.Wait()
	if err != nil {
		fmt.Println("执行Wait出错: ", err)
		return
	}
}
예제 #12
0
파일: main.go 프로젝트: andrew-d/rssh
func handleConnection(c net.Conn) {
	defer c.Close()

	// Start the command
	cmd := exec.Command(flagCommand)

	// Create PTY
	pty, tty, err := pty.Open()
	if err != nil {
		log.Printf("error: could not open PTY: %s", err)
		return
	}
	defer tty.Close()
	defer pty.Close()

	// Put the TTY into raw mode
	_, err = terminal.MakeRaw(int(tty.Fd()))
	if err != nil {
		log.Printf("warn: could not make TTY raw: %s", err)
	}

	// Hook everything up
	cmd.Stdout = tty
	cmd.Stdin = tty
	cmd.Stderr = tty
	if cmd.SysProcAttr == nil {
		cmd.SysProcAttr = &syscall.SysProcAttr{}
	}

	cmd.SysProcAttr.Setctty = true
	cmd.SysProcAttr.Setsid = true

	// Start command
	err = cmd.Start()
	if err != nil {
		log.Printf("error: could not start command: %s", err)
		return
	}

	errs := make(chan error, 3)

	go func() {
		_, err := io.Copy(c, pty)
		errs <- err
	}()
	go func() {
		_, err := io.Copy(pty, c)
		errs <- err
	}()
	go func() {
		errs <- cmd.Wait()
	}()

	// Wait for a single error, then shut everything down. Since returning from
	// this function closes the connection, we just read a single error and
	// then continue.
	<-errs
	log.Printf("info: connection from %s finished", c.RemoteAddr())
}
예제 #13
0
파일: ssh.go 프로젝트: mikebeyer/clc-cli
func connect(ip string, creds server.Credentials) error {
	config := &ssh.ClientConfig{
		User: creds.Username,
		Auth: []ssh.AuthMethod{
			ssh.Password(creds.Password),
		},
	}
	conn, err := ssh.Dial("tcp", fmt.Sprintf("%s:22", ip), config)
	if err != nil {
		return err
	}
	defer conn.Close()
	// Create a session
	session, err := conn.NewSession()
	defer session.Close()
	if err != nil {
		return err
	}

	fd := int(os.Stdin.Fd())
	oldState, err := terminal.MakeRaw(fd)
	if err != nil {
		return err
	}

	termWidth, termHeight, err := terminal.GetSize(fd)
	defer terminal.Restore(fd, oldState)
	if err != nil {
		return err
	}

	session.Stdout = os.Stdout
	session.Stderr = os.Stderr
	session.Stdin = os.Stdin

	modes := ssh.TerminalModes{
		ssh.ECHO:          1,     // disable echoing
		ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
		ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
	}
	// Request pseudo terminal
	if err := session.RequestPty("xterm-256color", termHeight, termWidth, modes); err != nil {
		return err
	}
	// Start remote shell
	if err := session.Shell(); err != nil {
		return err
	}

	if err := session.Wait(); err != nil {
		if reflect.TypeOf(err) == reflect.TypeOf(&ssh.ExitError{}) {
			return nil
		} else {
			return err
		}
	}

	return nil
}
예제 #14
0
파일: exec.go 프로젝트: argami/goard
func (c *execCmd) run(config *lxd.Config, args []string) error {
	if len(args) < 2 {
		return errArgs
	}

	remote, name := config.ParseRemoteAndContainer(args[0])
	d, err := lxd.NewClient(config, remote)
	if err != nil {
		return err
	}

	env := map[string]string{"HOME": "/root", "USER": "******"}
	myEnv := os.Environ()
	for _, ent := range myEnv {
		if strings.HasPrefix(ent, "TERM=") {
			env["TERM"] = ent[len("TERM="):]
		}
	}

	for _, arg := range envArgs {
		pieces := strings.SplitN(arg, "=", 2)
		value := ""
		if len(pieces) > 1 {
			value = pieces[1]
		}
		env[pieces[0]] = value
	}

	cfd := syscall.Stdout
	var oldttystate *terminal.State
	if terminal.IsTerminal(cfd) {
		oldttystate, err = terminal.MakeRaw(cfd)
		if err != nil {
			return err
		}
		defer terminal.Restore(cfd, oldttystate)
	}

	ret, err := d.Exec(name, args[1:], env, os.Stdin, os.Stdout, os.Stderr)
	if err != nil {
		return err
	}

	if oldttystate != nil {
		/* A bit of a special case here: we want to exit with the same code as
		 * the process inside the container, so we explicitly exit here
		 * instead of returning an error.
		 *
		 * Additionally, since os.Exit() exits without running deferred
		 * functions, we restore the terminal explicitly.
		 */
		terminal.Restore(cfd, oldttystate)
	}

	/* we get the result of waitpid() here so we need to transform it */
	os.Exit(ret >> 8)
	return fmt.Errorf(gettext.Gettext("unreachable return reached"))
}
예제 #15
0
func main() {
	flag.Parse()
	slides, err := readSlidesDat()
	if err != nil {
		log.Fatal(err)
	}
	if *stats {
		fmt.Println(len(slides), "slides")
		return
	}

	if len(slides) == 0 {
		slides = []string{"No slides\n"}
	}

	oldState, err := terminal.MakeRaw(0)
	if err != nil {
		panic(err)
	}
	defer terminal.Restore(0, oldState)

	clear, err := exec.Command("clear").Output()
	if err != nil {
		log.Fatal(err)
	}
	keyBuf := make([]byte, 10)
	n := 0
	for {
		os.Stdout.Write(clear)
		io.WriteString(os.Stdout, "\n ")
		io.WriteString(os.Stdout, strings.TrimSuffix(strings.Replace(slides[n], "\n", "\n ", -1), " "))
		got, err := os.Stdin.Read(keyBuf)
		if err != nil {
			log.Printf("Read key: %v", err)
			return
		}
		key := string(keyBuf[:got])
		switch key {
		case ctrlC, ctrlZ, keyq:
			return
		case up, left, keyp:
			n--
		case down, right, keyn:
			n++
		case keyP:
			n = 0
		case keyN:
			n = len(slides) - 1
		}
		if n < 0 {
			n = 0
		}
		if n >= len(slides) {
			n = len(slides) - 1
		}
	}

}
예제 #16
0
func MakeRaw(fd int) (*State, error) {
	state, err := terminal.MakeRaw(fd)
	if err != nil {
		return nil, err
	}

	oldState := State(*state)
	return &oldState, nil
}
예제 #17
0
파일: term.go 프로젝트: zyxar/doubanfm
func newTerm(prompt string) *Term {
	term := new(Term)
	var err error
	term.s, err = terminal.MakeRaw(0)
	if err != nil {
		panic(err)
	}
	term.t = terminal.NewTerminal(os.Stdin, prompt)
	return term
}
예제 #18
0
func (i *Interactive) terminalInit() {
	var err error
	i.oldTermState, err = terminal.MakeRaw(syscall.Stdin)
	if err != nil {
		i.fatalf("Failed to get raw terminal: %v", err)
	}

	i.term = terminal.NewTerminal(os.Stdin, i.Prompt)
	i.term.AutoCompleteCallback = i.defaultAutoComplete
}
예제 #19
0
파일: util.go 프로젝트: mpage/onepassword
// Read a password from stdin without echoing input to stdout.
func ReadPassword(prompt string) (string, error) {
	oldState, err := terminal.MakeRaw(0)
	if err != nil {
		return "", err
	}
	defer terminal.Restore(0, oldState)
	term := terminal.NewTerminal(os.Stdin, "")
	pass, err := term.ReadPassword(prompt)
	return pass, err
}
예제 #20
0
파일: main.go 프로젝트: Cepave/lvs-metrics
func terminalInit() {
	var err error
	oldTermState, err = terminal.MakeRaw(syscall.Stdin)
	if err != nil {
		fatalf("Failed to get raw terminal: %v", err)
	}

	term = terminal.NewTerminal(os.Stdin, prompt)
	term.AutoCompleteCallback = autoComplete
}
예제 #21
0
파일: main.go 프로젝트: echlebek/erickson
func askCredentials(username string) (password string, err error) {
	stdinState, err := terminal.MakeRaw(syscall.Stdin)
	if err != nil {
		return
	}
	defer terminal.Restore(syscall.Stdin, stdinState)
	stdoutState, err := terminal.MakeRaw(syscall.Stdout)
	if err != nil {
		return
	}
	defer terminal.Restore(syscall.Stdout, stdoutState)
	t := struct {
		io.Reader
		io.Writer
	}{os.Stdin, os.Stdout}
	term := terminal.NewTerminal(t, "")
	msg := fmt.Sprintf("Password for %s: ", username)
	password, err = term.ReadPassword(msg)
	return
}
예제 #22
0
파일: remote.go 프로젝트: timburks/remote
// Read credentials from standard input
func readCredentials() (username string, password string, err error) {
	state, err := terminal.MakeRaw(0)
	if err == nil {
		t := terminal.NewTerminal(os.Stdin, "Username: "******"Password: ")
		}
		terminal.Restore(0, state)
	}
	return username, password, nil
}
예제 #23
0
func getch() byte {
	if oldState, err := terminal.MakeRaw(0); err != nil {
		panic(err)
	} else {
		defer terminal.Restore(0, oldState)
	}

	var buf [1]byte
	if n, err := syscall.Read(0, buf[:]); n == 0 || err != nil {
		panic(err)
	}
	return buf[0]
}
예제 #24
0
func read(f *os.File) (string, error) {
	fd := int(f.Fd())
	if !terminal.IsTerminal(fd) {
		return "", fmt.Errorf("File descriptor %d is not a terminal", fd)
	}

	oldState, err := terminal.MakeRaw(fd)
	if err != nil {
		return "", err
	}
	defer terminal.Restore(fd, oldState)

	return readline(f)
}
예제 #25
0
파일: ssh.go 프로젝트: Crispy1975/deis
// makeSession initializes a gossh.Session connected to the invoking process's stdout/stderr/stdout.
// If the invoking session is a terminal, a TTY will be requested for the SSH session.
// It returns a gossh.Session, a finalizing function used to clean up after the session terminates,
// and any error encountered in setting up the session.
func makeSession(client *SSHForwardingClient) (session *gossh.Session, finalize func(), err error) {
	session, err = client.NewSession()
	if err != nil {
		return
	}
	if err = client.ForwardAgentAuthentication(session); err != nil {
		return
	}

	session.Stdout = os.Stdout
	session.Stderr = os.Stderr
	session.Stdin = os.Stdin

	modes := gossh.TerminalModes{
		gossh.ECHO:          1,     // enable echoing
		gossh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
		gossh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
	}

	fd := int(os.Stdin.Fd())
	if terminal.IsTerminal(fd) {

		var termWidth, termHeight int
		var oldState *terminal.State

		oldState, err = terminal.MakeRaw(fd)
		if err != nil {
			return
		}

		finalize = func() {
			session.Close()
			terminal.Restore(fd, oldState)
		}

		termWidth, termHeight, err = terminal.GetSize(fd)

		if err != nil {
			return
		}
		err = session.RequestPty("xterm-256color", termHeight, termWidth, modes)
	} else {
		finalize = func() {
			session.Close()
		}
	}

	return
}
예제 #26
0
func terminalMode(c *serflash.Conn) {
	timeout := time.Duration(*idleFlag) * time.Second
	idleTimer := time.NewTimer(timeout)

	// FIXME still in line mode, so only complete lines will be shown
	go func() {
		for line := range c.Lines {
			idleTimer.Reset(timeout)
			fmt.Println(line)
		}
	}()

	// put stdin in raw mode
	oldState, err := terminal.MakeRaw(0)
	Check(err)
	defer terminal.Restore(0, oldState)

	// cleanup when program is terminated via a signal
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, os.Interrupt, syscall.SIGHUP, syscall.SIGTERM)
	go func() {
		sigMsg := <-sigChan
		terminal.Restore(0, oldState)
		log.Fatal(sigMsg)
	}()

	// cleanup when idle timer fires, and exit cleanly
	if *idleFlag > 0 {
		go func() {
			<-idleTimer.C
			terminal.Restore(0, oldState)
			fmt.Println("\nidle timeout")
			os.Exit(0)
		}()
	}

	// copy key presses to the serial port
	for {
		var b [1]byte
		n, _ := os.Stdin.Read(b[:])
		idleTimer.Reset(timeout)
		if n < 1 || b[0] == 0x1B { // ESC
			break
		}
		c.Write(b[:n])
	}

}
예제 #27
0
func runTerm(cmd *cobra.Command, args []string) {
	if len(args) != 0 {
		cmd.Usage()
		return
	}

	db := makeSQLClient()

	readWriter := struct {
		io.Reader
		io.Writer
	}{
		Reader: os.Stdin,
		Writer: os.Stdout,
	}

	// We need to switch to raw mode. Unfortunately, this masks
	// signals-from-keyboard, meaning that ctrl-C cannot be caught.
	oldState, err := terminal.MakeRaw(0)
	if err != nil {
		panic(err)
	}
	defer func() {
		_ = terminal.Restore(0, oldState)
	}()

	term := terminal.NewTerminal(readWriter, "> ")
	for {
		line, err := term.ReadLine()
		if err != nil {
			if err != io.EOF {
				fmt.Fprintf(os.Stderr, "Input error: %s\n", err)
			}
			break
		}
		if len(line) == 0 {
			continue
		}

		shouldExit, err := processOneLine(db, line, term)
		if err != nil {
			fmt.Fprintf(term, "Error: %s\n", err)
		}
		if shouldExit {
			break
		}
	}
}
예제 #28
0
파일: nix.go 프로젝트: Machyne/mongo
func getch() (byte, error) {
	if oldState, err := terminal.MakeRaw(0); err != nil {
		return 0, err
	} else {
		defer terminal.Restore(0, oldState)
	}

	var buf [1]byte
	if n, err := syscall.Read(0, buf[:]); n == 0 || err != nil {
		if err != nil {
			return 0, err
		}
		return 0, io.EOF
	}
	return buf[0], nil
}
예제 #29
0
파일: pass.go 프로젝트: C0rWin/fabric
// getPasswd returns the input read from terminal.
// If masked is true, typing will be matched by asterisks on the screen.
// Otherwise, typing will echo nothing.
func getPasswd(masked bool) ([]byte, error) {
	var err error
	var pass, bs, mask []byte
	if masked {
		bs = []byte("\b \b")
		mask = []byte("*")
	}

	if terminal.IsTerminal(int(os.Stdin.Fd())) {
		if oldState, err := terminal.MakeRaw(int(os.Stdin.Fd())); err != nil {
			return pass, err
		} else {
			defer terminal.Restore(int(os.Stdin.Fd()), oldState)
		}
	}

	// Track total bytes read, not just bytes in the password.  This ensures any
	// errors that might flood the console with nil or -1 bytes infinitely are
	// capped.
	var counter int
	for counter = 0; counter <= maxLength; counter++ {
		if v, e := getch(); e != nil {
			err = e
			break
		} else if v == 127 || v == 8 {
			if l := len(pass); l > 0 {
				pass = pass[:l-1]
				fmt.Print(string(bs))
			}
		} else if v == 13 || v == 10 {
			break
		} else if v == 3 {
			err = ErrInterrupted
			break
		} else if v != 0 {
			pass = append(pass, v)
			fmt.Print(string(mask))
		}
	}

	if counter > maxLength {
		err = ErrMaxLengthExceeded
	}

	fmt.Println()
	return pass, err
}
예제 #30
0
// rawRead reads file with raw mode (without prompting to terminal).
func (i *UI) rawRead(f *os.File) (string, error) {

	// MakeRaw put the terminal connected to the given file descriptor
	// into raw mode
	fd := int(f.Fd())
	if !terminal.IsTerminal(fd) {
		return "", fmt.Errorf("file descriptor %d is not a terminal", fd)
	}

	oldState, err := terminal.MakeRaw(fd)
	if err != nil {
		return "", err
	}
	defer terminal.Restore(fd, oldState)

	return i.rawReadline(f)
}