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  }