commit | b6e1bdd4a4f88614e0c6e5e8089c7abed98aae17 | [log] [tgz] |
---|---|---|
author | Drew DeVault <sir@cmpwn.com> | Sun Mar 31 21:15:51 2019 -0600 |
committer | Keith Rarick <kr@xph.us> | Sun Mar 31 20:15:51 2019 -0700 |
tree | ee5da698ebbe3ccac3130dcfc83b599ffedcb380 | |
parent | 521317be5ebc228a0f0ede099fa2a0b5ece22e49 [diff] |
Set Ctty in SysProcAttr (#75)
Pty is a Go package for using unix pseudo-terminals.
go get github.com/kr/pty
package main import ( "github.com/kr/pty" "io" "os" "os/exec" ) func main() { c := exec.Command("grep", "--color=auto", "bar") f, err := pty.Start(c) if err != nil { panic(err) } go func() { f.Write([]byte("foo\n")) f.Write([]byte("bar\n")) f.Write([]byte("baz\n")) f.Write([]byte{4}) // EOT }() io.Copy(os.Stdout, f) }
package main import ( "io" "log" "os" "os/exec" "os/signal" "syscall" "github.com/kr/pty" "golang.org/x/crypto/ssh/terminal" ) func test() error { // Create arbitrary command. c := exec.Command("bash") // Start the command with a pty. ptmx, err := pty.Start(c) if err != nil { return err } // Make sure to close the pty at the end. defer func() { _ = ptmx.Close() }() // Best effort. // Handle pty size. ch := make(chan os.Signal, 1) signal.Notify(ch, syscall.SIGWINCH) go func() { for range ch { if err := pty.InheritSize(os.Stdin, ptmx); err != nil { log.Printf("error resizing pty: %s", err) } } }() ch <- syscall.SIGWINCH // Initial resize. // Set stdin in raw mode. oldState, err := terminal.MakeRaw(int(os.Stdin.Fd())) if err != nil { panic(err) } defer func() { _ = terminal.Restore(int(os.Stdin.Fd()), oldState) }() // Best effort. // Copy stdin to the pty and the pty to stdout. go func() { _, _ = io.Copy(ptmx, os.Stdin) }() _, _ = io.Copy(os.Stdout, ptmx) return nil } func main() { if err := test(); err != nil { log.Fatal(err) } }