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")) }
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 }
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]) } }
func suspend() { if oldTermState != nil { terminal.Restore(syscall.Stdin, oldTermState) } go resume() syscall.Kill(os.Getpid(), syscall.SIGTSTP) }
func getPassword() ([]byte, error) { signals := make(chan os.Signal, 1) passwords := make(chan password) signal.Notify(signals, os.Interrupt, os.Kill) defer signal.Stop(signals) state, err := terminal.GetState(2) if err != nil { return nil, err } defer terminal.Restore(2, state) go func() { fmt.Fprintf(os.Stderr, "Password: "******"\n") p, err := terminal.ReadPassword(2) passwords <- password{ Password: p, Err: err, } close(passwords) }() select { case <-signals: return nil, fmt.Errorf("Password entry cancelled") case password := <-passwords: return password.Password, password.Err } }
// Close methods restores terminal, and send struct to Done chan. func (s Shell) Close() { s.Write([]byte(fmt.Sprint("Bye!"))) t.Restore(0, s.State) go func() { s.Done <- struct{}{} }() }
func runAttached(c *cli.Context, app, ps, args, release string) (int, error) { fd := os.Stdin.Fd() var w, h int if terminal.IsTerminal(int(fd)) { stdinState, err := terminal.GetState(int(fd)) if err != nil { return -1, err } defer terminal.Restore(int(fd), stdinState) w, h, err = terminal.GetSize(int(fd)) if err != nil { return -1, err } } code, err := rackClient(c).RunProcessAttached(app, ps, args, release, h, w, os.Stdin, os.Stdout) if err != nil { return -1, err } return code, nil }
func (i *Interactive) suspend() { if i.oldTermState != nil { terminal.Restore(syscall.Stdin, i.oldTermState) } go i.resume() syscall.Kill(os.Getpid(), syscall.SIGTSTP) }
func (i *Interactive) exit() { if i.oldTermState != nil { terminal.Restore(syscall.Stdin, i.oldTermState) } fmt.Printf("\n") os.Exit(0) }
// Close cleans up mongod and mongo processes and closes fd for the terminal func (sh *QShell) Close() error { closeErr := sh.mongoStateHolder.close() if err := terminal.Restore(sh.stdinFd, sh.oldState); err != nil && closeErr == nil { closeErr = err } return closeErr }
// Catch signals func catchNotifications() { state, err := terminal.GetState(int(os.Stdin.Fd())) checkErr(err) // Deal with SIGINT sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, os.Interrupt) var timer time.Time go func() { for sig := range sigChan { // Prevent exiting on accidental signal send if time.Now().Sub(timer) < time.Second*signalTimeout { terminal.Restore(int(os.Stdin.Fd()), state) os.Exit(0) } fmt.Fprintln(os.Stderr, "") fmt.Fprintln(os.Stderr, "") fmt.Fprintln(os.Stderr, "") fmt.Fprintln(os.Stderr, sig, "signal caught!") fmt.Fprintf(os.Stderr, "Send signal again within %v seconds to exit\n", signalTimeout) fmt.Fprintln(os.Stderr, "") fmt.Fprintln(os.Stderr, "") fmt.Fprintln(os.Stderr, "") timer = time.Now() } }() }
func cleanAndExit(oldState *terminal.State) { fmt.Println() if oldState != nil { terminal.Restore(0, oldState) } os.Exit(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 }
func exit() { if oldTermState != nil { terminal.Restore(syscall.Stdin, oldTermState) } fmt.Printf("\n") os.Exit(0) }
func getPassword() (string, error) { stdin := int(syscall.Stdin) initialTermState, err := terminal.GetState(stdin) if err != nil { return "", err } c := make(chan os.Signal) signal.Notify(c, os.Interrupt, os.Kill) go func() { s := <-c terminal.Restore(stdin, initialTermState) switch sig := s.(type) { case syscall.Signal: if int(sig) == 2 { fmt.Println("^C") } } os.Exit(1) }() passBytes, err := terminal.ReadPassword(stdin) if err != nil { return "", err } signal.Stop(c) fmt.Print("\n") return string(passBytes), nil }
// 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 }
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 }
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 } }
func fatalf(format string, a ...interface{}) { if oldTermState != nil { terminal.Restore(syscall.Stdin, oldTermState) } fmt.Fprintf(os.Stderr, format, a...) fmt.Fprintf(os.Stderr, "\n") os.Exit(1) }
func handleKey(line string, pos int, key rune) (newLine string, newPos int, ok bool) { if key == '\x03' { fmt.Println() terminal.Restore(0, regularState) os.Exit(0) } return "", 0, false }
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 } } }
func Restore(fd int, state *terminal.State) error { err := terminal.Restore(fd, state) if err != nil { if err.Error() == "errno 0" { err = nil } } return nil }
func (c *cliUI) close() { if c.oldState != nil { terminal.Restore(0, c.oldState) } if c.term != nil { c.term.SetBracketedPasteMode(false) } }
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...") }
func AskPass(q string) string { print(q) oldState, err := terminal.MakeRaw(0) defer terminal.Restore(0, oldState) ExitfOn("Error on terminal.MakeRaw: %v\n", err) reset := CatchSignal(os.Interrupt, func() { terminal.Restore(0, oldState) }) pass, err := terminal.ReadPassword(0) ExitfOn("Error on terminal.ReadPassword: %v\n", err) reset() println() return string(pass) }
func Restore(fd int, state *terminal.State) error { err := terminal.Restore(fd, state) if err != nil { // errno 0 means everything is ok :) if err.Error() == "errno 0" { err = nil } } return nil }
// 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 }
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 }
// 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 }
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] }