Beispiel #1
0
// 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()
		}
	}()
}
Beispiel #2
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
}
Beispiel #3
0
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
	}
}
Beispiel #4
0
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
}
Beispiel #5
0
func GetState(fd int) (*State, error) {
	state, err := terminal.GetState(fd)
	if err != nil {
		return nil, err
	}

	currentState := State(*state)
	return &currentState, nil
}
Beispiel #6
0
func init() {
	if runtime.GOOS != "windows" {
		terminalState, _ := terminal.GetState(0)
		sigint := make(chan os.Signal, 1)
		signal.Notify(sigint, os.Interrupt)
		go func() {
			<-sigint
			terminal.Restore(0, terminalState)
			fmt.Println("")
			os.Exit(1)
		}()
	}
}
Beispiel #7
0
func Signals() {
	prev, err := terminal.GetState(int(os.Stdin.Fd()))
	if err != nil {
		prev = nil
	}

	s := make(chan os.Signal, 1)
	signal.Notify(s, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT)
	for _ = range s {
		terminal.Restore(int(os.Stdin.Fd()), prev)
		os.Exit(1)
	}
}
Beispiel #8
0
/* Read non-empty password from terminal */
func GetPass(prompt string) (pass string, err error) {
	var resp []byte

	fd, err := getTerminalFd()
	if err != nil {
		return
	}

	/* Store current terminal state in case the call gets interrupted by signal */
	oldState, err := terminal.GetState(fd)
	if err != nil {
		err = errors.Errorf("failed to get terminal state: %s\n", err)
		return
	}

	/*
	 * Install signal handler
	 * Unlike the ReadLine function, using a raw terminal state here does not help.
	 * If the prompt gets killed by a signal, the terminal state is not restored.
	 * Hence restore it in a signal handler
	 */
	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGINT)
	go func() {
		<-c
		terminal.Restore(fd, oldState)
		fmt.Fprintln(os.Stderr, "aborting")
		os.Exit(1)
	}()

	for i := 0; len(resp) == 0; i++ {
		if i > 0 {
			fmt.Printf("\rInvalid response - try again")
			time.Sleep(500 * time.Millisecond)
		}
		/* Clear line - see https://en.wikipedia.org/wiki/ANSI_escape_code */
		fmt.Printf("\r\033[2K%s: ", prompt)

		/* This function internally takes care of restoring terminal state. */
		resp, err = terminal.ReadPassword(fd)
		if err != nil {
			return
		}
		resp = bytes.TrimSpace(resp)
	}
	/* Restore signal handling */
	signal.Stop(c)
	signal.Reset(syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGINT)
	return string(resp), nil
}
Beispiel #9
0
// restoreTerminal installs a cleanup handler that restores the previous
// terminal state on exit.
func restoreTerminal() {
	if !stdoutIsTerminal() {
		return
	}

	fd := int(os.Stdout.Fd())
	state, err := terminal.GetState(fd)
	if err != nil {
		fmt.Fprintf(os.Stderr, "unable to get terminal state: %v\n", err)
		return
	}

	AddCleanupHandler(func() error {
		err := checkErrno(terminal.Restore(fd, state))
		if err != nil {
			fmt.Fprintf(os.Stderr, "unable to get restore terminal state: %#+v\n", err)
		}
		return err
	})
}
Beispiel #10
0
func (r *LightRenderer) Init() {
	delay := 100
	delayEnv := os.Getenv("ESCDELAY")
	if len(delayEnv) > 0 {
		num, err := strconv.Atoi(delayEnv)
		if err == nil && num >= 0 {
			delay = num
		}
	}
	r.escDelay = delay

	fd := r.fd()
	origState, err := terminal.GetState(fd)
	if err != nil {
		errorExit(err.Error())
	}
	r.origState = origState
	terminal.MakeRaw(fd)
	r.updateTerminalSize()
	initTheme(r.theme, r.defaultTheme(), r.forceBlack)

	_, x := r.findOffset()
	if x > 0 {
		r.upOneLine = true
		r.stderr("\n")
	}
	for i := 1; i < r.MaxY(); i++ {
		r.stderr("\n")
		r.csi("G")
	}

	if r.mouse {
		r.csi("?1000h")
	}
	r.csi(fmt.Sprintf("%dA", r.MaxY()-1))
	r.csi("G")
	// r.csi("s")
	if r.mouse {
		r.yoffset, _ = r.findOffset()
	}
}
Beispiel #11
0
func sshWithRestore(c *cli.Context, id, cmd string) (int, error) {
	fd := os.Stdin.Fd()
	isTerm := terminal.IsTerminal(int(fd))
	var h, w int

	if isTerm {
		stdinState, err := terminal.GetState(int(fd))
		if err != nil {
			return -1, err
		}

		h, w, err = terminal.GetSize(int(fd))
		if err != nil {
			return -1, err
		}

		defer terminal.Restore(int(fd), stdinState)
	}

	return rackClient(c).SSHInstance(id, cmd, h, w, isTerm, os.Stdin, os.Stdout)
}
Beispiel #12
0
func readPass(fd int) ([]byte, error) {
	// make sure an interrupt won't break the terminal
	sigint := make(chan os.Signal)
	state, err := terminal.GetState(fd)
	if err != nil {
		return nil, err
	}
	go func() {
		for _ = range sigint {
			terminal.Restore(fd, state)
			fmt.Println("^C")
			os.Exit(1)
		}
	}()
	signal.Notify(sigint, os.Interrupt)
	defer func() {
		signal.Stop(sigint)
		close(sigint)
	}()
	return terminal.ReadPassword(fd)
}
// Catch signals
func catchNotifications() {
	ignoreStdin := false
	state, err := terminal.GetState(int(os.Stdin.Fd()))
	if err != nil {
		// Stdin may be redirected, then just exit
		ignoreStdin = true
	}

	// Deal with SIGINT
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, os.Interrupt)

	var timer time.Time
	go func() {
		for sig := range sigChan {
			if ignoreStdin {
				fmt.Fprintln(os.Stderr, sig, "signal caught!")
				fmt.Fprintln(os.Stderr, "Exiting")
				os.Exit(0)
			} else {
				// 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()
			}
		}
	}()
}
Beispiel #14
0
func startTerminal(c *config) {
	fmt.Printf("Starting terminal mode.\n")
	fmt.Printf("Enter h for [h]elp.\n")
	fmt.Printf("Enter q for [q]uit.\n")
	done := make(chan bool)
	initState, err := terminal.GetState(0)
	protected := false
	if err != nil {
		fmt.Printf("error getting terminal state: %v\n", err.Error())
		return
	}

	go func() {
		terminal.MakeRaw(int(os.Stdin.Fd()))
		n := terminal.NewTerminal(os.Stdin, "> ")
		for {
			var ln string
			var err error
			if !protected {
				ln, err = n.ReadLine()
				if err != nil {
					done <- true
				}
			} else {
				ln, err = n.ReadPassword(">*")
				if err != nil {
					done <- true
				}
			}
			execute(done, &protected, c, ln)
		}
	}()
	select {
	case <-done:
		fmt.Printf("exiting...\n")
		terminal.Restore(0, initState)
		close(done)
	}
}
Beispiel #15
0
func getpass(prompt string) (pass string, err error) {

	tstate, err := terminal.GetState(0)
	if err != nil {
		return
	}

	sig := make(chan os.Signal, 1)
	signal.Notify(sig, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
	go func() {
		quit := false
		for _ = range sig {
			quit = true
			break
		}
		terminal.Restore(0, tstate)
		if quit {
			fmt.Println()
			os.Exit(2)
		}
	}()
	defer func() {
		signal.Stop(sig)
		close(sig)
	}()

	f := bufio.NewWriter(os.Stdout)
	f.Write([]byte(prompt))
	f.Flush()

	passbytes, err := terminal.ReadPassword(0)
	pass = string(passbytes)

	f.Write([]byte("\n"))
	f.Flush()

	return
}
Beispiel #16
0
func cmdExec(c *cli.Context) error {
	fd := os.Stdin.Fd()

	var h, w int

	if terminal.IsTerminal(int(fd)) {
		stdinState, err := terminal.GetState(int(fd))
		if err != nil {
			return stdcli.Error(err)
		}

		defer terminal.Restore(int(fd), stdinState)

		w, h, err = terminal.GetSize(int(fd))
		if err != nil {
			return stdcli.Error(err)
		}
	}

	_, app, err := stdcli.DirApp(c, ".")
	if err != nil {
		return stdcli.Error(err)
	}

	if len(c.Args()) < 2 {
		stdcli.Usage(c, "exec")
		return nil
	}

	ps := c.Args()[0]

	code, err := rackClient(c).ExecProcessAttached(app, ps, strings.Join(c.Args()[1:], " "), os.Stdin, os.Stdout, h, w)
	if err != nil {
		return stdcli.Error(err)
	}

	return stdcli.Errorf("", code)
}
Beispiel #17
0
func cmdExec(c *cli.Context) {
	fd := os.Stdin.Fd()
	stdinState, err := terminal.GetState(int(fd))
	defer terminal.Restore(int(fd), stdinState)

	_, app, err := stdcli.DirApp(c, ".")

	if err != nil {
		stdcli.Error(err)
		return
	}

	if len(c.Args()) < 2 {
		stdcli.Usage(c, "exec")
		return
	}

	w, h, err := terminal.GetSize(int(fd))

	if err != nil {
		stdcli.Error(err)
		return
	}

	ps := c.Args()[0]

	code, err := rackClient(c).ExecProcessAttached(app, ps, strings.Join(c.Args()[1:], " "), os.Stdin, os.Stdout, h, w)
	terminal.Restore(int(fd), stdinState)

	if err != nil {
		stdcli.Error(err)
		return
	}

	os.Exit(code)
}