summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/vendor/github.com/bgentry/speakeasy/speakeasy_unix.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/vendor/github.com/bgentry/speakeasy/speakeasy_unix.go')
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/vendor/github.com/bgentry/speakeasy/speakeasy_unix.go93
1 files changed, 93 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/vendor/github.com/bgentry/speakeasy/speakeasy_unix.go b/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/vendor/github.com/bgentry/speakeasy/speakeasy_unix.go
new file mode 100644
index 000000000..d99fda191
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/vendor/github.com/bgentry/speakeasy/speakeasy_unix.go
@@ -0,0 +1,93 @@
+// based on https://code.google.com/p/gopass
+// Author: johnsiilver@gmail.com (John Doak)
+//
+// Original code is based on code by RogerV in the golang-nuts thread:
+// https://groups.google.com/group/golang-nuts/browse_thread/thread/40cc41e9d9fc9247
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package speakeasy
+
+import (
+ "fmt"
+ "os"
+ "os/signal"
+ "strings"
+ "syscall"
+)
+
+const sttyArg0 = "/bin/stty"
+
+var (
+ sttyArgvEOff = []string{"stty", "-echo"}
+ sttyArgvEOn = []string{"stty", "echo"}
+)
+
+// getPassword gets input hidden from the terminal from a user. This is
+// accomplished by turning off terminal echo, reading input from the user and
+// finally turning on terminal echo.
+func getPassword() (password string, err error) {
+ sig := make(chan os.Signal, 10)
+ brk := make(chan bool)
+
+ // File descriptors for stdin, stdout, and stderr.
+ fd := []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()}
+
+ // Setup notifications of termination signals to channel sig, create a process to
+ // watch for these signals so we can turn back on echo if need be.
+ signal.Notify(sig, syscall.SIGHUP, syscall.SIGINT, syscall.SIGKILL, syscall.SIGQUIT,
+ syscall.SIGTERM)
+ go catchSignal(fd, sig, brk)
+
+ // Turn off the terminal echo.
+ pid, err := echoOff(fd)
+ if err != nil {
+ return "", err
+ }
+
+ // Turn on the terminal echo and stop listening for signals.
+ defer signal.Stop(sig)
+ defer close(brk)
+ defer echoOn(fd)
+
+ syscall.Wait4(pid, nil, 0, nil)
+
+ line, err := readline()
+ if err == nil {
+ password = strings.TrimSpace(line)
+ } else {
+ err = fmt.Errorf("failed during password entry: %s", err)
+ }
+
+ return password, err
+}
+
+// echoOff turns off the terminal echo.
+func echoOff(fd []uintptr) (int, error) {
+ pid, err := syscall.ForkExec(sttyArg0, sttyArgvEOff, &syscall.ProcAttr{Dir: "", Files: fd})
+ if err != nil {
+ return 0, fmt.Errorf("failed turning off console echo for password entry:\n\t%s", err)
+ }
+ return pid, nil
+}
+
+// echoOn turns back on the terminal echo.
+func echoOn(fd []uintptr) {
+ // Turn on the terminal echo.
+ pid, e := syscall.ForkExec(sttyArg0, sttyArgvEOn, &syscall.ProcAttr{Dir: "", Files: fd})
+ if e == nil {
+ syscall.Wait4(pid, nil, 0, nil)
+ }
+}
+
+// catchSignal tries to catch SIGKILL, SIGQUIT and SIGINT so that we can turn
+// terminal echo back on before the program ends. Otherwise the user is left
+// with echo off on their terminal.
+func catchSignal(fd []uintptr, sig chan os.Signal, brk chan bool) {
+ select {
+ case <-sig:
+ echoOn(fd)
+ os.Exit(-1)
+ case <-brk:
+ }
+}