github.com/markusbkk/elvish@v0.0.0-20231204143114-91dc52438621/pkg/cli/term/setup_unix.go (about) 1 //go:build !windows && !plan9 2 // +build !windows,!plan9 3 4 package term 5 6 import ( 7 "fmt" 8 "os" 9 10 "golang.org/x/sys/unix" 11 "github.com/markusbkk/elvish/pkg/diag" 12 "github.com/markusbkk/elvish/pkg/sys/eunix" 13 ) 14 15 func setup(in, out *os.File) (func() error, error) { 16 // On Unix, use input file for changing termios. All fds pointing to the 17 // same terminal are equivalent. 18 19 fd := int(in.Fd()) 20 term, err := eunix.TermiosForFd(fd) 21 if err != nil { 22 return nil, fmt.Errorf("can't get terminal attribute: %s", err) 23 } 24 25 savedTermios := term.Copy() 26 27 term.SetICanon(false) 28 term.SetIExten(false) 29 term.SetEcho(false) 30 term.SetVMin(1) 31 term.SetVTime(0) 32 33 // Enforcing crnl translation on readline. Assuming user won't set 34 // inlcr or -onlcr, otherwise we have to hardcode all of them here. 35 term.SetICRNL(true) 36 37 err = term.ApplyToFd(fd) 38 if err != nil { 39 return nil, fmt.Errorf("can't set up terminal attribute: %s", err) 40 } 41 42 var errSetupVT error 43 err = setupVT(out) 44 if err != nil { 45 errSetupVT = fmt.Errorf("can't setup VT: %s", err) 46 } 47 48 restore := func() error { 49 return diag.Errors(savedTermios.ApplyToFd(fd), restoreVT(out)) 50 } 51 52 return restore, errSetupVT 53 } 54 55 func setupGlobal() func() { 56 return func() {} 57 } 58 59 func sanitize(in, out *os.File) { 60 // Some programs use non-blocking IO but do not correctly clear the 61 // non-blocking flags after exiting, so we always clear the flag. See #822 62 // for an example. 63 unix.SetNonblock(int(in.Fd()), false) 64 unix.SetNonblock(int(out.Fd()), false) 65 }