2021-11-02 15:31:49 +08:00
|
|
|
//go:build !windows
|
2018-11-19 16:01:24 +08:00
|
|
|
// +build !windows
|
|
|
|
|
2018-01-07 02:46:00 +08:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"log"
|
|
|
|
"os/exec"
|
|
|
|
"syscall"
|
|
|
|
"unsafe"
|
|
|
|
|
2019-06-24 03:04:57 +08:00
|
|
|
"github.com/gliderlabs/ssh"
|
2018-01-07 02:46:00 +08:00
|
|
|
"github.com/kr/pty"
|
|
|
|
"github.com/urfave/cli"
|
|
|
|
)
|
|
|
|
|
|
|
|
// testServer is an hidden handler used for integration tests
|
|
|
|
func testServer(c *cli.Context) error {
|
|
|
|
ssh.Handle(func(s ssh.Session) {
|
|
|
|
helloMsg := struct {
|
|
|
|
User string
|
|
|
|
Environ []string
|
|
|
|
Command []string
|
|
|
|
}{
|
|
|
|
User: s.User(),
|
|
|
|
Environ: s.Environ(),
|
|
|
|
Command: s.Command(),
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := json.NewEncoder(s).Encode(&helloMsg); err != nil {
|
|
|
|
log.Fatalf("failed to write helloMsg: %v", err)
|
|
|
|
}
|
|
|
|
cmd := exec.Command(s.Command()[0], s.Command()[1:]...) // #nosec
|
|
|
|
if s.Command() == nil {
|
|
|
|
cmd = exec.Command("/bin/sh") // #nosec
|
|
|
|
}
|
|
|
|
ptyReq, winCh, isPty := s.Pty()
|
|
|
|
var cmdErr error
|
|
|
|
if isPty {
|
|
|
|
cmd.Env = append(cmd.Env, fmt.Sprintf("TERM=%s", ptyReq.Term))
|
|
|
|
f, err := pty.Start(cmd)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintf(s, "failed to run command: %v\n", err) // #nosec
|
|
|
|
_ = s.Exit(1) // #nosec
|
|
|
|
return
|
|
|
|
}
|
|
|
|
go func() {
|
|
|
|
for win := range winCh {
|
|
|
|
_, _, _ = syscall.Syscall(syscall.SYS_IOCTL, f.Fd(), uintptr(syscall.TIOCSWINSZ),
|
|
|
|
uintptr(unsafe.Pointer(&struct{ h, w, x, y uint16 }{uint16(win.Height), uint16(win.Width), 0, 0}))) // #nosec
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
go func() {
|
|
|
|
// stdin
|
|
|
|
_, _ = io.Copy(f, s) // #nosec
|
|
|
|
}()
|
|
|
|
// stdout
|
|
|
|
_, _ = io.Copy(s, f) // #nosec
|
|
|
|
cmdErr = cmd.Wait()
|
|
|
|
} else {
|
2021-03-27 00:26:10 +08:00
|
|
|
// cmd.Stdin = s
|
2018-01-07 02:46:00 +08:00
|
|
|
cmd.Stdout = s
|
|
|
|
cmd.Stderr = s
|
|
|
|
cmdErr = cmd.Run()
|
|
|
|
}
|
|
|
|
|
|
|
|
if cmdErr != nil {
|
|
|
|
if exitError, ok := cmdErr.(*exec.ExitError); ok {
|
|
|
|
_ = s.Exit(exitError.Sys().(syscall.WaitStatus).ExitStatus()) // #nosec
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ = s.Exit(cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()) // #nosec
|
|
|
|
})
|
|
|
|
|
|
|
|
log.Println("starting ssh server on port 2222...")
|
|
|
|
return ssh.ListenAndServe(":2222", nil)
|
|
|
|
}
|