mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-02-26 03:24:03 +01:00
handle term resize / SIGWINCH, move from mpio to shexec (used UnknownPacketReporter). change signum to signame for cross-system compatibility
This commit is contained in:
parent
670f54a5b4
commit
ec143de8b4
@ -12,9 +12,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/creack/pty"
|
||||
"github.com/scripthaus-dev/mshell/pkg/base"
|
||||
"github.com/scripthaus-dev/mshell/pkg/packet"
|
||||
)
|
||||
@ -31,8 +29,6 @@ type Multiplexer struct {
|
||||
FdWriters map[int]*FdWriter // synchronized
|
||||
RunData map[int]*FdReader // synchronized
|
||||
CloseAfterStart []*os.File // synchronized
|
||||
PtyFd *os.File
|
||||
CmdProc *os.Process
|
||||
|
||||
Sender *packet.PacketSender
|
||||
Input *packet.PacketParser
|
||||
@ -55,12 +51,6 @@ func MakeMultiplexer(ck base.CommandKey, upr packet.UnknownPacketReporter) *Mult
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Multiplexer) SetPtyFd(ptyFd *os.File) {
|
||||
m.Lock.Lock()
|
||||
defer m.Lock.Unlock()
|
||||
m.PtyFd = ptyFd
|
||||
}
|
||||
|
||||
func (m *Multiplexer) Close() {
|
||||
m.Lock.Lock()
|
||||
defer m.Lock.Unlock()
|
||||
@ -230,36 +220,11 @@ func (m *Multiplexer) runPacketInputLoop() *packet.CmdDonePacketType {
|
||||
donePacket := pk.(*packet.CmdDonePacketType)
|
||||
return donePacket
|
||||
}
|
||||
if pk.GetType() == packet.SpecialInputPacketStr {
|
||||
inputPacket := pk.(*packet.SpecialInputPacketType)
|
||||
m.processSpecialInputPacket(inputPacket)
|
||||
}
|
||||
m.UPR.UnknownPacket(pk)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Multiplexer) processSpecialInputPacket(pk *packet.SpecialInputPacketType) {
|
||||
m.Lock.Lock()
|
||||
ptyFd := m.PtyFd
|
||||
cmdProc := m.CmdProc
|
||||
m.Lock.Unlock()
|
||||
if ptyFd == nil {
|
||||
// no pty, maybe send a message back to server, but the server always starts with a pty, so this shouldn't be an issue
|
||||
return
|
||||
}
|
||||
if pk.WinSize != nil {
|
||||
winSize := &pty.Winsize{
|
||||
//Rows: base.BoundInt(pk.WinSize.Rows, shexec.MinTermRows, shexec.MaxTermRows),
|
||||
//Cols: base.BoundInt(pk.Winsize.Cols, shexec.MinTermCols, shexec.MaxTermCols),
|
||||
}
|
||||
pty.Setsize(ptyFd, winSize)
|
||||
if cmdProc != nil {
|
||||
cmdProc.Signal(syscall.SIGWINCH)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Multiplexer) processDataPacket(dataPacket *packet.DataPacketType) error {
|
||||
realData, err := base64.StdEncoding.DecodeString(dataPacket.Data64)
|
||||
if err != nil {
|
||||
|
@ -248,7 +248,7 @@ type WinSize struct {
|
||||
type SpecialInputPacketType struct {
|
||||
Type string `json:"type"`
|
||||
CK base.CommandKey `json:"ck"`
|
||||
SigNum int `json:"signum,omitempty"`
|
||||
SigName string `json:"signame,omitempty"` // passed to unix.SignalNum (needs 'SIG' prefix, e.g. "SIGTERM")
|
||||
WinSize *WinSize `json:"winsize,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,6 @@ import (
|
||||
"os/signal"
|
||||
"os/user"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@ -70,7 +69,6 @@ const RunSudoCommandFmt = `sudo -n -C %d bash /dev/fd/%d`
|
||||
const RunSudoPasswordCommandFmt = `cat /dev/fd/%d | sudo -k -S -C %d bash -c "echo '[from-mshell]'; exec %d>&-; bash /dev/fd/%d < /dev/fd/%d"`
|
||||
|
||||
type ShExecType struct {
|
||||
Lock *sync.Mutex
|
||||
StartTs time.Time
|
||||
CK base.CommandKey
|
||||
FileNames *base.CommandFileNames
|
||||
@ -81,6 +79,7 @@ type ShExecType struct {
|
||||
Detached bool
|
||||
DetachedOutput *packet.PacketSender
|
||||
RunnerOutFd *os.File
|
||||
MsgSender *packet.PacketSender // where to send out-of-band messages back to calling proceess
|
||||
}
|
||||
|
||||
type StdContext struct{}
|
||||
@ -118,9 +117,50 @@ type FdContext interface {
|
||||
GetReader(fdNum int) io.ReadCloser
|
||||
}
|
||||
|
||||
type ShExecUPR struct {
|
||||
ShExec *ShExecType
|
||||
UPR packet.UnknownPacketReporter
|
||||
}
|
||||
|
||||
func (s *ShExecType) processSpecialInputPacket(pk *packet.SpecialInputPacketType) error {
|
||||
if pk.WinSize != nil {
|
||||
if s.CmdPty == nil {
|
||||
return fmt.Errorf("cannot change winsize, cmd was not started with a pty")
|
||||
}
|
||||
winSize := &pty.Winsize{
|
||||
Rows: uint16(base.BoundInt(pk.WinSize.Rows, MinTermRows, MaxTermRows)),
|
||||
Cols: uint16(base.BoundInt(pk.WinSize.Cols, MinTermCols, MaxTermCols)),
|
||||
}
|
||||
pty.Setsize(s.CmdPty, winSize)
|
||||
s.Cmd.Process.Signal(syscall.SIGWINCH)
|
||||
}
|
||||
if pk.SigName != "" {
|
||||
sigNum := unix.SignalNum(pk.SigName)
|
||||
if sigNum == 0 {
|
||||
return fmt.Errorf("error signal %q not found, cannot send", pk.SigName)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s ShExecUPR) UnknownPacket(pk packet.PacketType) {
|
||||
if pk.GetType() == packet.SpecialInputPacketStr {
|
||||
inputPacket := pk.(*packet.SpecialInputPacketType)
|
||||
err := s.ShExec.processSpecialInputPacket(inputPacket)
|
||||
if err != nil && s.ShExec.MsgSender != nil {
|
||||
msg := packet.MakeMessagePacket(err.Error())
|
||||
msg.CK = s.ShExec.CK
|
||||
s.ShExec.MsgSender.SendPacket(msg)
|
||||
}
|
||||
return
|
||||
}
|
||||
if s.UPR != nil {
|
||||
s.UPR.UnknownPacket(pk)
|
||||
}
|
||||
}
|
||||
|
||||
func MakeShExec(ck base.CommandKey, upr packet.UnknownPacketReporter) *ShExecType {
|
||||
return &ShExecType{
|
||||
Lock: &sync.Mutex{},
|
||||
StartTs: time.Now(),
|
||||
CK: ck,
|
||||
Multiplexer: mpio.MakeMultiplexer(ck, upr),
|
||||
@ -835,11 +875,13 @@ func getTermType(pk *packet.RunPacketType) string {
|
||||
}
|
||||
|
||||
func RunCommandSimple(pk *packet.RunPacketType, sender *packet.PacketSender, fromServer bool) (*ShExecType, error) {
|
||||
var upr packet.UnknownPacketReporter
|
||||
cmd := MakeShExec(pk.CK, nil)
|
||||
if fromServer {
|
||||
upr = packet.MessageUPR{CK: pk.CK, Sender: sender}
|
||||
msgUpr := packet.MessageUPR{CK: pk.CK, Sender: sender}
|
||||
upr := ShExecUPR{ShExec: cmd, UPR: msgUpr}
|
||||
cmd.Multiplexer.UPR = upr
|
||||
cmd.MsgSender = sender
|
||||
}
|
||||
cmd := MakeShExec(pk.CK, upr)
|
||||
if pk.UsePty {
|
||||
cmd.Cmd = exec.Command("bash", "-i", "-c", pk.Command)
|
||||
} else {
|
||||
@ -869,7 +911,6 @@ func RunCommandSimple(pk *packet.RunPacketType, sender *packet.PacketSender, fro
|
||||
cmdTty.Close()
|
||||
}()
|
||||
cmd.CmdPty = cmdPty
|
||||
cmd.Multiplexer.SetPtyFd(cmdPty)
|
||||
UpdateCmdEnv(cmd.Cmd, map[string]string{"TERM": getTermType(pk)})
|
||||
}
|
||||
if cmdTty != nil {
|
||||
@ -1051,7 +1092,6 @@ func RunCommandDetached(pk *packet.RunPacketType, sender *packet.PacketSender) (
|
||||
cmd.CmdPty = cmdPty
|
||||
cmd.Detached = true
|
||||
cmd.MaxPtySize = DefaultMaxPtySize
|
||||
cmd.Multiplexer.SetPtyFd(cmdPty)
|
||||
if pk.TermOpts != nil && pk.TermOpts.MaxPtySize > 0 {
|
||||
cmd.MaxPtySize = base.BoundInt64(pk.TermOpts.MaxPtySize, MinMaxPtySize, MaxMaxPtySize)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user