github.com/bilus/oya@v0.0.3-0.20190301162104-da4acbd394c6/cmd/internal/secrets.go (about) 1 package internal 2 3 import ( 4 "io" 5 "log" 6 "os" 7 "os/exec" 8 "os/signal" 9 "syscall" 10 11 "github.com/bilus/oya/pkg/secrets" 12 "github.com/kr/pty" 13 "golang.org/x/crypto/ssh/terminal" 14 ) 15 16 func SecretsView(workDir string, stdout, stderr io.Writer) error { 17 output, err := secrets.Decrypt(workDir) 18 if err != nil { 19 return err 20 } 21 stdout.Write(output) 22 return nil 23 } 24 25 func SecretsEdit(workDir string, stdout, stderr io.Writer) error { 26 viewCmd := secrets.ViewCmd(workDir) 27 if err := terminalRun(viewCmd); err != nil { 28 return err 29 } 30 return nil 31 } 32 33 func SecretsEncrypt(workDir string, stdout, stderr io.Writer) error { 34 if err := secrets.Encrypt(workDir); err != nil { 35 return err 36 } 37 return nil 38 } 39 40 func terminalRun(cmd *exec.Cmd) error { 41 // Start the command with a pty. 42 ptmx, err := pty.Start(cmd) 43 if err != nil { 44 return err 45 } 46 // Make sure to close the pty at the end. 47 defer func() { _ = ptmx.Close() }() // Best effort. 48 49 // Handle pty size. 50 ch := make(chan os.Signal, 1) 51 defer close(ch) 52 signal.Notify(ch, syscall.SIGWINCH) 53 go func() { 54 for range ch { 55 if err := pty.InheritSize(os.Stdin, ptmx); err != nil { 56 log.Printf("error resizing pty: %s", err) 57 } 58 } 59 }() 60 ch <- syscall.SIGWINCH // Initial resize. 61 62 // Set stdin in raw mode. 63 oldState, err := terminal.MakeRaw(int(os.Stdin.Fd())) 64 if err != nil { 65 return err 66 } 67 defer func() { _ = terminal.Restore(int(os.Stdin.Fd()), oldState) }() // Best effort. 68 69 // Copy stdin to the pty and the pty to stdout. 70 go func() { 71 _, err = io.Copy(ptmx, os.Stdin) 72 if err != nil { 73 log.Printf("error %s", err) 74 } 75 }() 76 77 _, err = io.Copy(os.Stdout, ptmx) 78 if err != nil { 79 return err 80 } 81 82 return nil 83 }