mirror of https://gogs.blitter.com/RLabs/xs
				
				
				
			Fixes for MSYS2 and CYGWIN term mode; removed mintty_wrapper.sh
This commit is contained in:
		
							parent
							
								
									12409319e7
								
							
						
					
					
						commit
						e5b6422d70
					
				
							
								
								
									
										9
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										9
									
								
								Makefile
								
								
								
								
							| 
						 | 
					@ -108,10 +108,8 @@ reinstall: uninstall install
 | 
				
			||||||
install:
 | 
					install:
 | 
				
			||||||
	echo "WIN_MSYS:" $(WIN_MSYS)
 | 
						echo "WIN_MSYS:" $(WIN_MSYS)
 | 
				
			||||||
ifdef WIN_MSYS
 | 
					ifdef WIN_MSYS
 | 
				
			||||||
	cp xs/mintty_wrapper.sh $(INSTPREFIX)/bin/xs
 | 
						cp xs/xs $(INSTPREFIX)/bin/xs
 | 
				
			||||||
	cp xs/mintty_wrapper.sh $(INSTPREFIX)/bin/xc
 | 
						cp xs/xs $(INSTPREFIX)/bin/xc
 | 
				
			||||||
	cp xs/xs $(INSTPREFIX)/bin/_xs
 | 
					 | 
				
			||||||
	cp xs/xs $(INSTPREFIX)/bin/_xc
 | 
					 | 
				
			||||||
	echo "Install of xsd server for Windows not yet supported"
 | 
						echo "Install of xsd server for Windows not yet supported"
 | 
				
			||||||
else
 | 
					else
 | 
				
			||||||
	cp xs/xs $(INSTPREFIX)/bin
 | 
						cp xs/xs $(INSTPREFIX)/bin
 | 
				
			||||||
| 
						 | 
					@ -120,8 +118,7 @@ else
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uninstall:
 | 
					uninstall:
 | 
				
			||||||
	rm -f $(INSTPREFIX)/bin/xs $(INSTPREFIX)/bin/xc \
 | 
						rm -f $(INSTPREFIX)/bin/xs $(INSTPREFIX)/bin/xc
 | 
				
			||||||
	$(INSTPREFIX)/bin/_xs $(INSTPREFIX)/bin/_xc
 | 
					 | 
				
			||||||
ifndef $(WIN_MSYS)
 | 
					ifndef $(WIN_MSYS)
 | 
				
			||||||
	rm -f $(INSTPREFIX)/sbin/xsd
 | 
						rm -f $(INSTPREFIX)/sbin/xsd
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ package xs
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	unix "golang.org/x/sys/unix"
 | 
						unix "golang.org/x/sys/unix"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -30,7 +31,8 @@ type State struct {
 | 
				
			||||||
// MakeRaw put the terminal connected to the given file descriptor into raw
 | 
					// MakeRaw put the terminal connected to the given file descriptor into raw
 | 
				
			||||||
// mode and returns the previous state of the terminal so that it can be
 | 
					// mode and returns the previous state of the terminal so that it can be
 | 
				
			||||||
// restored.
 | 
					// restored.
 | 
				
			||||||
func MakeRaw(fd uintptr) (*State, error) {
 | 
					func MakeRaw(f *os.File) (*State, error) {
 | 
				
			||||||
 | 
						fd := f.Fd()
 | 
				
			||||||
	termios, err := unix.IoctlGetTermios(int(fd), ioctlReadTermios)
 | 
						termios, err := unix.IoctlGetTermios(int(fd), ioctlReadTermios)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
| 
						 | 
					@ -56,8 +58,8 @@ func MakeRaw(fd uintptr) (*State, error) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetState returns the current state of a terminal which may be useful to
 | 
					// GetState returns the current state of a terminal which may be useful to
 | 
				
			||||||
// restore the terminal after a signal.
 | 
					// restore the terminal after a signal.
 | 
				
			||||||
func GetState(fd uintptr) (*State, error) {
 | 
					func GetState(f *os.File) (*State, error) {
 | 
				
			||||||
	termios, err := unix.IoctlGetTermios(int(fd), ioctlReadTermios)
 | 
						termios, err := unix.IoctlGetTermios(int(f.Fd()), ioctlReadTermios)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -67,9 +69,9 @@ func GetState(fd uintptr) (*State, error) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Restore restores the terminal connected to the given file descriptor to a
 | 
					// Restore restores the terminal connected to the given file descriptor to a
 | 
				
			||||||
// previous state.
 | 
					// previous state.
 | 
				
			||||||
func Restore(fd uintptr, state *State) error {
 | 
					func Restore(f *os.File, state *State) error {
 | 
				
			||||||
	if state != nil {
 | 
						if state != nil {
 | 
				
			||||||
		return unix.IoctlSetTermios(int(fd), ioctlWriteTermios, &state.termios)
 | 
							return unix.IoctlSetTermios(int(f.Fd()), ioctlWriteTermios, &state.termios)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		return errors.New("nil State")
 | 
							return errors.New("nil State")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -78,7 +80,8 @@ func Restore(fd uintptr, state *State) error {
 | 
				
			||||||
// ReadPassword reads a line of input from a terminal without local echo.  This
 | 
					// ReadPassword reads a line of input from a terminal without local echo.  This
 | 
				
			||||||
// is commonly used for inputting passwords and other sensitive data. The slice
 | 
					// is commonly used for inputting passwords and other sensitive data. The slice
 | 
				
			||||||
// returned does not include the \n.
 | 
					// returned does not include the \n.
 | 
				
			||||||
func ReadPassword(fd uintptr) ([]byte, error) {
 | 
					func ReadPassword(f *os.File) ([]byte, error) {
 | 
				
			||||||
 | 
						fd := f.Fd()
 | 
				
			||||||
	termios, err := unix.IoctlGetTermios(int(fd), ioctlReadTermios)
 | 
						termios, err := unix.IoctlGetTermios(int(fd), ioctlReadTermios)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,4 @@
 | 
				
			||||||
 | 
					//go:build windows
 | 
				
			||||||
// +build windows
 | 
					// +build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Note the terminal manipulation functions herein are mostly stubs. They
 | 
					// Note the terminal manipulation functions herein are mostly stubs. They
 | 
				
			||||||
| 
						 | 
					@ -15,10 +16,12 @@
 | 
				
			||||||
package xs
 | 
					package xs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"io"
 | 
						"bufio"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
	"os/exec"
 | 
						"os/exec"
 | 
				
			||||||
 | 
						"os/signal"
 | 
				
			||||||
	"golang.org/x/sys/windows"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type State struct {
 | 
					type State struct {
 | 
				
			||||||
| 
						 | 
					@ -27,67 +30,84 @@ type State struct {
 | 
				
			||||||
// MakeRaw put the terminal connected to the given file descriptor into raw
 | 
					// MakeRaw put the terminal connected to the given file descriptor into raw
 | 
				
			||||||
// mode and returns the previous state of the terminal so that it can be
 | 
					// mode and returns the previous state of the terminal so that it can be
 | 
				
			||||||
// restored.
 | 
					// restored.
 | 
				
			||||||
func MakeRaw(fd uintptr) (*State, error) {
 | 
					func MakeRaw(f *os.File) (*State, error) {
 | 
				
			||||||
	// This doesn't really work. The exec.Command() runs a sub-shell
 | 
						cmd := exec.Command("stty", "-echo", "raw")
 | 
				
			||||||
	// so the stty mods don't affect the client process.
 | 
						cmd.Stdin = f
 | 
				
			||||||
	cmd := exec.Command("stty", "-echo raw")
 | 
						err := cmd.Run()
 | 
				
			||||||
	cmd.Run()
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatal(err)
 | 
				
			||||||
 | 
							return &State{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// MSYS2/CYGWIN: wintty needs CTRL-C caught
 | 
				
			||||||
 | 
						// ----------------------------------------
 | 
				
			||||||
 | 
						c := make(chan os.Signal, 1)
 | 
				
			||||||
 | 
						signal.Notify(c, os.Interrupt, os.Kill)
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							for sig := range c {
 | 
				
			||||||
 | 
								_ = sig
 | 
				
			||||||
 | 
								//fmt.Println(sig)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						// ----------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &State{}, nil
 | 
						return &State{}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetState returns the current state of a terminal which may be useful to
 | 
					// GetState returns the current state of a terminal which may be useful to
 | 
				
			||||||
// restore the terminal after a signal.
 | 
					// restore the terminal after a signal.
 | 
				
			||||||
func GetState(fd uintptr) (*State, error) {
 | 
					func GetState(f *os.File) (*State, error) {
 | 
				
			||||||
	return &State{}, nil
 | 
						return &State{}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Restore restores the terminal connected to the given file descriptor to a
 | 
					// Restore restores the terminal connected to the given file descriptor to a
 | 
				
			||||||
// previous state.
 | 
					// previous state.
 | 
				
			||||||
func Restore(fd uintptr, state *State) error {
 | 
					func Restore(f *os.File, state *State) error {
 | 
				
			||||||
	cmd := exec.Command("stty", "echo cooked")
 | 
						cmd := exec.Command("stty", "sane")
 | 
				
			||||||
	cmd.Run()
 | 
						cmd.Stdin = f
 | 
				
			||||||
 | 
						err := cmd.Run()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatal(err)
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ReadPassword reads a line of input from a terminal without local echo.  This
 | 
					// ReadPassword reads a line of input from a terminal without local echo.  This
 | 
				
			||||||
// is commonly used for inputting passwords and other sensitive data. The slice
 | 
					// is commonly used for inputting passwords and other sensitive data. The slice
 | 
				
			||||||
// returned does not include the \n.
 | 
					// returned does not include the \n.
 | 
				
			||||||
func ReadPassword(fd uintptr) ([]byte, error) {
 | 
					func ReadPassword(f *os.File) (pw []byte, err error) {
 | 
				
			||||||
	return readPasswordLine(passwordReader(fd))
 | 
						sttycmd, err := exec.LookPath("stty")
 | 
				
			||||||
}
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
// passwordReader is an io.Reader that reads from a specific file descriptor.
 | 
						} else {
 | 
				
			||||||
type passwordReader windows.Handle
 | 
							//fmt.Printf("stty found at: %v\n", sttycmd)
 | 
				
			||||||
 | 
							cmdOff := exec.Command(sttycmd, "-echo")
 | 
				
			||||||
func (r passwordReader) Read(buf []byte) (int, error) {
 | 
							cmdOff.Stdin = f    //os.Stdin
 | 
				
			||||||
	return windows.Read(windows.Handle(r), buf)
 | 
							cmdOff.Stdout = nil //os.Stdout
 | 
				
			||||||
}
 | 
							cmdOff.Stderr = nil //os.Stderr
 | 
				
			||||||
 | 
							err = cmdOff.Run()
 | 
				
			||||||
// readPasswordLine reads from reader until it finds \n or io.EOF.
 | 
					 | 
				
			||||||
// The slice returned does not include the \n.
 | 
					 | 
				
			||||||
// readPasswordLine also ignores any \r it finds.
 | 
					 | 
				
			||||||
func readPasswordLine(reader io.Reader) ([]byte, error) {
 | 
					 | 
				
			||||||
	var buf [1]byte
 | 
					 | 
				
			||||||
	var ret []byte
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for {
 | 
					 | 
				
			||||||
		n, err := reader.Read(buf[:])
 | 
					 | 
				
			||||||
		if n > 0 {
 | 
					 | 
				
			||||||
			switch buf[0] {
 | 
					 | 
				
			||||||
			case '\n':
 | 
					 | 
				
			||||||
				return ret, nil
 | 
					 | 
				
			||||||
			case '\r':
 | 
					 | 
				
			||||||
				// remove \r from passwords on Windows
 | 
					 | 
				
			||||||
			default:
 | 
					 | 
				
			||||||
				ret = append(ret, buf[0])
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			if err == io.EOF && len(ret) > 0 {
 | 
								return nil, err
 | 
				
			||||||
				return ret, nil
 | 
							}
 | 
				
			||||||
			}
 | 
					
 | 
				
			||||||
			return ret, err
 | 
							//fmt.Printf("Enter password:")
 | 
				
			||||||
 | 
							scanner := bufio.NewScanner(os.Stdin)
 | 
				
			||||||
 | 
							scanner.Scan()
 | 
				
			||||||
 | 
							err = scanner.Err()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							pw = scanner.Bytes()
 | 
				
			||||||
 | 
							fmt.Println()
 | 
				
			||||||
 | 
							cmdOn := exec.Command(sttycmd, "echo")
 | 
				
			||||||
 | 
							cmdOn.Stdin = f    //os.Stdin
 | 
				
			||||||
 | 
							cmdOn.Stdout = nil //os.Stdout
 | 
				
			||||||
 | 
							cmdOn.Stderr = nil //os.Stderr
 | 
				
			||||||
 | 
							err = cmdOn.Run()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,39 +0,0 @@
 | 
				
			||||||
#!/bin/bash
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
## This wrapper may be used within the MSYS/mintty Windows
 | 
					 | 
				
			||||||
## shell environment to have a functioning xs client with
 | 
					 | 
				
			||||||
## working 'raw' mode and hidden password entry.
 | 
					 | 
				
			||||||
##
 | 
					 | 
				
			||||||
## mintty uses named pipes and ptys to get a more POSIX-like
 | 
					 | 
				
			||||||
## terminal (incl. VT/ANSI codes) rather than the dumb Windows
 | 
					 | 
				
			||||||
## console interface; however Go on Windows does not have functioning
 | 
					 | 
				
			||||||
## MSYS/mintty code to set raw, echo etc. modes.
 | 
					 | 
				
			||||||
##
 | 
					 | 
				
			||||||
## Someday it would be preferable to put native Windows term mode
 | 
					 | 
				
			||||||
## code into the client build, but this is 'good enough' for now
 | 
					 | 
				
			||||||
## (with the exception of tty rows/cols not being set based on
 | 
					 | 
				
			||||||
##  info from the server).
 | 
					 | 
				
			||||||
##
 | 
					 | 
				
			||||||
## INSTALLATION
 | 
					 | 
				
			||||||
## --
 | 
					 | 
				
			||||||
## Build the client, put it somewhere in your $PATH with this
 | 
					 | 
				
			||||||
## wrapper and edit the name of the client binary
 | 
					 | 
				
			||||||
## eg.,
 | 
					 | 
				
			||||||
## $ cp hkexsh.exe /usr/bin/.hkexsh.exe
 | 
					 | 
				
			||||||
## $ cp mintty_wrapper.sh /usr/bin/hkexsh
 | 
					 | 
				
			||||||
####
 | 
					 | 
				
			||||||
trap cleanup EXIT ERR
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
cleanup() {
 | 
					 | 
				
			||||||
  stty sane
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
me="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if [ ${1}x == "-hx" ]; then
 | 
					 | 
				
			||||||
  _${me} -h
 | 
					 | 
				
			||||||
else
 | 
					 | 
				
			||||||
  stty -echo raw icrnl
 | 
					 | 
				
			||||||
  _${me} $@
 | 
					 | 
				
			||||||
fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										45
									
								
								xs/xs.go
								
								
								
								
							
							
						
						
									
										45
									
								
								xs/xs.go
								
								
								
								
							| 
						 | 
					@ -35,7 +35,7 @@ import (
 | 
				
			||||||
	"blitter.com/go/xs/logger"
 | 
						"blitter.com/go/xs/logger"
 | 
				
			||||||
	"blitter.com/go/xs/spinsult"
 | 
						"blitter.com/go/xs/spinsult"
 | 
				
			||||||
	"blitter.com/go/xs/xsnet"
 | 
						"blitter.com/go/xs/xsnet"
 | 
				
			||||||
	isatty "github.com/mattn/go-isatty"
 | 
						//isatty "github.com/mattn/go-isatty"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
| 
						 | 
					@ -990,29 +990,13 @@ func main() { //nolint: funlen, gocyclo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// === Shell terminal mode (Shell vs. Copy) setup
 | 
						// === Shell terminal mode (Shell vs. Copy) setup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Set stdin in raw mode if it's an interactive session
 | 
					 | 
				
			||||||
	// TODO: send flag to server side indicating this
 | 
					 | 
				
			||||||
	//  affects shell command used
 | 
					 | 
				
			||||||
	var oldState *xs.State
 | 
					 | 
				
			||||||
	defer conn.Close()
 | 
						defer conn.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// === From this point on, conn is a secure encrypted channel
 | 
						// === From this point on, conn is a secure encrypted channel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if shellMode {
 | 
						// === BEGIN Login phase
 | 
				
			||||||
		if isatty.IsTerminal(os.Stdin.Fd()) {
 | 
					 | 
				
			||||||
			oldState, err = xs.MakeRaw(os.Stdin.Fd())
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				panic(err)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			// #gv:s/label=\"main\$1\"/label=\"deferRestore\"/
 | 
					 | 
				
			||||||
			// TODO:.gv:main:1:deferRestore
 | 
					 | 
				
			||||||
			defer restoreTermState(oldState)
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			log.Println("NOT A TTY")
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// === Login phase
 | 
						var oldState *xs.State
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Start login timeout here and disconnect if user/pass phase stalls
 | 
						// Start login timeout here and disconnect if user/pass phase stalls
 | 
				
			||||||
	// iloginImpatience := time.AfterFunc(20*time.Second, func() {
 | 
						// iloginImpatience := time.AfterFunc(20*time.Second, func() {
 | 
				
			||||||
| 
						 | 
					@ -1029,7 +1013,7 @@ func main() { //nolint: funlen, gocyclo
 | 
				
			||||||
			// No auth token, prompt for password
 | 
								// No auth token, prompt for password
 | 
				
			||||||
			fmt.Printf("Gimme cookie:")
 | 
								fmt.Printf("Gimme cookie:")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ab, e := xs.ReadPassword(os.Stdin.Fd())
 | 
							ab, e := xs.ReadPassword(os.Stdin)
 | 
				
			||||||
		if !gopt {
 | 
							if !gopt {
 | 
				
			||||||
			fmt.Printf("\r\n")
 | 
								fmt.Printf("\r\n")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -1044,6 +1028,25 @@ func main() { //nolint: funlen, gocyclo
 | 
				
			||||||
	// Security scrub
 | 
						// Security scrub
 | 
				
			||||||
	runtime.GC()
 | 
						runtime.GC()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// === END Login phase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// === Terminal mode adjustment for session
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if shellMode {
 | 
				
			||||||
 | 
							if true { //isatty.IsTerminal(os.Stdin.Fd()) {
 | 
				
			||||||
 | 
								oldState, err = xs.MakeRaw(os.Stdin)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									panic(err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								// #gv:s/label=\"main\$1\"/label=\"deferRestore\"/
 | 
				
			||||||
 | 
								// TODO:.gv:main:1:deferRestore
 | 
				
			||||||
 | 
								defer restoreTermState(oldState)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								log.Println("NOT A TTY")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// === Session param and TERM setup
 | 
						// === Session param and TERM setup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Set up session params and send over to server
 | 
						// Set up session params and send over to server
 | 
				
			||||||
| 
						 | 
					@ -1147,7 +1150,7 @@ func localUserName(u *user.User) string {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func restoreTermState(oldState *xs.State) {
 | 
					func restoreTermState(oldState *xs.State) {
 | 
				
			||||||
	_ = xs.Restore(os.Stdin.Fd(), oldState)
 | 
						_ = xs.Restore(os.Stdin, oldState)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// exitWithStatus wraps os.Exit() plus does any required pprof housekeeping
 | 
					// exitWithStatus wraps os.Exit() plus does any required pprof housekeeping
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,7 +39,6 @@ import (
 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
	"syscall"
 | 
					 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hkex "blitter.com/go/herradurakex"
 | 
						hkex "blitter.com/go/herradurakex"
 | 
				
			||||||
| 
						 | 
					@ -1762,7 +1761,9 @@ func (hc *Conn) keepaliveHelper() {
 | 
				
			||||||
				hc.ShutdownKeepAlive()
 | 
									hc.ShutdownKeepAlive()
 | 
				
			||||||
				if hc.Pproc != 0 {
 | 
									if hc.Pproc != 0 {
 | 
				
			||||||
					//fmt.Printf("[pid %d needs to be killed]\n", hc.Pproc)
 | 
										//fmt.Printf("[pid %d needs to be killed]\n", hc.Pproc)
 | 
				
			||||||
					syscall.Kill(hc.Pproc, syscall.SIGABRT) //nolint:errcheck
 | 
										//syscall.Kill(hc.Pproc, syscall.SIGABRT) //nolint:errcheck
 | 
				
			||||||
 | 
										//exec.Command("taskkill", "/f", "/pid", strconv.Itoa(hc.Pproc)).Run()
 | 
				
			||||||
 | 
										hc.kill()
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				break
 | 
									break
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,13 @@
 | 
				
			||||||
 | 
					//go:build linux
 | 
				
			||||||
 | 
					// +build linux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package xsnet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (hc *Conn) kill() {
 | 
				
			||||||
 | 
						syscall.Kill(hc.Pproc, syscall.SIGABRT) //nolint:errcheck
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,13 @@
 | 
				
			||||||
 | 
					//go:build windows
 | 
				
			||||||
 | 
					// +build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package xsnet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"os/exec"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (hc *Conn) kill() {
 | 
				
			||||||
 | 
						exec.Command("taskkill", "/f", "/pid", strconv.Itoa(hc.Pproc)).Run()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue