* detect kill ssh session * include sftp session in the count of ssh sessions * log session type in the agent
87 lines
1.7 KiB
Go
87 lines
1.7 KiB
Go
package terminal
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/ActiveState/termtest/conpty"
|
|
"github.com/gliderlabs/ssh"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
"syscall"
|
|
)
|
|
|
|
var PtySpawner = Spawner(func(sshSession ssh.Session, env []string, name string, args ...string) (Process, error) {
|
|
_, winCh, isPty := sshSession.Pty()
|
|
if !isPty {
|
|
return nil, fmt.Errorf("ssh session is not a pty")
|
|
}
|
|
|
|
cpty, err := conpty.New(80, 25)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
pid, _, err := cpty.Spawn(
|
|
name,
|
|
args,
|
|
&syscall.ProcAttr{
|
|
Env: env,
|
|
},
|
|
)
|
|
if err != nil {
|
|
cpty.Close()
|
|
return nil, err
|
|
}
|
|
log.Printf("New process with pid %d spawned\n", pid)
|
|
process, err := os.FindProcess(pid)
|
|
if err != nil {
|
|
cpty.Close()
|
|
return nil, fmt.Errorf("Failed to find process: %v", err)
|
|
}
|
|
|
|
go func() {
|
|
for win := range winCh {
|
|
err = cpty.Resize(uint16(win.Width), uint16(win.Height))
|
|
if err != nil {
|
|
log.Printf("Failed to resize terminal to %d x %d", win.Width, win.Height)
|
|
}
|
|
}
|
|
}()
|
|
return ptyProcess{
|
|
cpty: cpty,
|
|
process: process,
|
|
}, nil
|
|
})
|
|
|
|
type ptyProcess struct {
|
|
cpty *conpty.ConPty
|
|
process *os.Process
|
|
}
|
|
|
|
func (proc ptyProcess) Read(p []byte) (n int, err error) {
|
|
return proc.cpty.OutPipe().Read(p)
|
|
}
|
|
func (proc ptyProcess) Write(p []byte) (n int, err error) {
|
|
uintn, err := proc.cpty.Write(p)
|
|
return int(uintn), err
|
|
}
|
|
|
|
func (p ptyProcess) Pipe() io.ReadWriter {
|
|
return p
|
|
}
|
|
|
|
func (p ptyProcess) Kill() error {
|
|
return p.process.Kill()
|
|
}
|
|
|
|
func (p ptyProcess) Wait() error {
|
|
defer p.cpty.Close()
|
|
ps, err := p.process.Wait()
|
|
if err != nil {
|
|
return fmt.Errorf("Error waiting for process: %v", err)
|
|
}
|
|
if ps.ExitCode() != 0 {
|
|
return fmt.Errorf("exit code was: %d\n", ps.ExitCode())
|
|
}
|
|
return nil
|
|
}
|