2023-10-17 06:31:13 +02:00
|
|
|
// Copyright 2023, Command Line Inc.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
2022-06-10 09:35:24 +02:00
|
|
|
package shexec
|
|
|
|
|
|
|
|
import (
|
2022-08-23 00:59:03 +02:00
|
|
|
"bytes"
|
2022-07-07 03:59:46 +02:00
|
|
|
"context"
|
2022-06-29 06:57:30 +02:00
|
|
|
"encoding/base64"
|
2022-06-10 09:35:24 +02:00
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
2022-06-29 23:29:38 +02:00
|
|
|
"os/signal"
|
2022-07-02 02:37:37 +02:00
|
|
|
"os/user"
|
2023-10-26 00:20:25 +02:00
|
|
|
"path"
|
2022-09-22 08:26:53 +02:00
|
|
|
"runtime"
|
2022-12-21 06:58:24 +01:00
|
|
|
"strconv"
|
2022-06-10 09:35:24 +02:00
|
|
|
"strings"
|
2022-10-22 23:45:31 +02:00
|
|
|
"sync"
|
2022-06-10 09:35:24 +02:00
|
|
|
"syscall"
|
|
|
|
"time"
|
|
|
|
|
2022-06-27 23:57:01 +02:00
|
|
|
"github.com/alessio/shellescape"
|
2023-10-26 00:20:25 +02:00
|
|
|
"github.com/creack/pty"
|
|
|
|
"github.com/google/uuid"
|
2023-10-16 22:25:53 +02:00
|
|
|
"github.com/wavetermdev/waveterm/waveshell/pkg/base"
|
|
|
|
"github.com/wavetermdev/waveterm/waveshell/pkg/cirfile"
|
|
|
|
"github.com/wavetermdev/waveterm/waveshell/pkg/mpio"
|
|
|
|
"github.com/wavetermdev/waveterm/waveshell/pkg/packet"
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
"github.com/wavetermdev/waveterm/waveshell/pkg/shellapi"
|
|
|
|
"github.com/wavetermdev/waveterm/waveshell/pkg/shellenv"
|
|
|
|
"github.com/wavetermdev/waveterm/waveshell/pkg/shellutil"
|
2024-03-06 20:38:27 +01:00
|
|
|
"github.com/wavetermdev/waveterm/waveshell/pkg/wlog"
|
2022-09-26 22:02:34 +02:00
|
|
|
"golang.org/x/mod/semver"
|
2022-07-02 02:37:37 +02:00
|
|
|
"golang.org/x/sys/unix"
|
2022-06-10 09:35:24 +02:00
|
|
|
)
|
|
|
|
|
2022-09-04 08:26:57 +02:00
|
|
|
const MinTermRows = 2
|
|
|
|
const MinTermCols = 10
|
|
|
|
const MaxTermRows = 1024
|
|
|
|
const MaxTermCols = 1024
|
2022-06-24 03:23:30 +02:00
|
|
|
const MaxFdNum = 1023
|
|
|
|
const FirstExtraFilesFdNum = 3
|
2022-08-20 00:28:32 +02:00
|
|
|
const DefaultMaxPtySize = 1024 * 1024
|
2022-09-04 08:38:35 +02:00
|
|
|
const MinMaxPtySize = 16 * 1024
|
|
|
|
const MaxMaxPtySize = 100 * 1024 * 1024
|
2023-01-31 21:14:41 +01:00
|
|
|
const MaxRunDataSize = 1024 * 1024
|
|
|
|
const MaxTotalRunDataSize = 10 * MaxRunDataSize
|
2023-10-05 18:50:35 +02:00
|
|
|
const ShellVarName = "SHELL"
|
2023-11-10 03:29:11 +01:00
|
|
|
const SigKillWaitTime = 2 * time.Second
|
2023-11-10 03:57:39 +01:00
|
|
|
const RtnStateFdNum = 20
|
|
|
|
const ReturnStateReadWaitTime = 2 * time.Second
|
2024-01-20 22:17:43 +01:00
|
|
|
const ForceDebugRcFile = false
|
2024-03-06 20:38:27 +01:00
|
|
|
const ForceDebugReturnState = false
|
2022-06-21 02:51:28 +02:00
|
|
|
|
2022-09-26 22:02:34 +02:00
|
|
|
const ClientCommandFmt = `
|
2022-06-27 23:57:01 +02:00
|
|
|
PATH=$PATH:~/.mshell;
|
2022-06-28 07:39:16 +02:00
|
|
|
which mshell > /dev/null;
|
2022-06-27 23:57:01 +02:00
|
|
|
if [[ "$?" -ne 0 ]]
|
|
|
|
then
|
2022-09-22 08:26:53 +02:00
|
|
|
printf "\n##N{\"type\": \"init\", \"notfound\": true, \"uname\": \"%s|%s\"}\n" "$(uname -s)" "$(uname -m)"
|
2022-06-27 23:57:01 +02:00
|
|
|
else
|
2022-09-26 22:02:34 +02:00
|
|
|
mshell-[%VERSION%] --single
|
2022-06-27 23:57:01 +02:00
|
|
|
fi
|
|
|
|
`
|
2022-06-26 10:41:58 +02:00
|
|
|
|
2022-09-26 22:02:34 +02:00
|
|
|
func MakeClientCommandStr() string {
|
|
|
|
return strings.ReplaceAll(ClientCommandFmt, "[%VERSION%]", semver.MajorMinor(base.MShellVersion))
|
|
|
|
}
|
|
|
|
|
|
|
|
const InstallCommandFmt = `
|
2022-09-22 08:26:53 +02:00
|
|
|
printf "\n##N{\"type\": \"init\", \"notfound\": true, \"uname\": \"%s|%s\"}\n" "$(uname -s)" "$(uname -m)";
|
2022-06-28 07:39:16 +02:00
|
|
|
mkdir -p ~/.mshell/;
|
2022-09-22 08:51:16 +02:00
|
|
|
cat > ~/.mshell/mshell.temp;
|
|
|
|
if [[ -s ~/.mshell/mshell.temp ]]
|
|
|
|
then
|
2022-09-26 22:02:34 +02:00
|
|
|
mv ~/.mshell/mshell.temp ~/.mshell/mshell-[%VERSION%];
|
|
|
|
chmod a+x ~/.mshell/mshell-[%VERSION%];
|
|
|
|
~/.mshell/mshell-[%VERSION%] --single --version
|
2022-09-22 08:51:16 +02:00
|
|
|
fi
|
2022-06-28 07:39:16 +02:00
|
|
|
`
|
|
|
|
|
2022-09-26 22:02:34 +02:00
|
|
|
func MakeInstallCommandStr() string {
|
|
|
|
return strings.ReplaceAll(InstallCommandFmt, "[%VERSION%]", semver.MajorMinor(base.MShellVersion))
|
|
|
|
}
|
|
|
|
|
2022-11-02 05:19:42 +01:00
|
|
|
type MShellBinaryReaderFn func(version string, goos string, goarch string) (io.ReadCloser, error)
|
|
|
|
|
2022-10-22 23:45:31 +02:00
|
|
|
type ReturnStateBuf struct {
|
2024-03-20 00:38:38 +01:00
|
|
|
Lock *sync.Mutex
|
|
|
|
Buf []byte
|
|
|
|
Done bool
|
|
|
|
Err error
|
|
|
|
Reader *os.File
|
|
|
|
FdNum int
|
|
|
|
EndBytes []byte
|
|
|
|
DoneCh chan bool
|
2022-10-22 23:45:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func MakeReturnStateBuf() *ReturnStateBuf {
|
|
|
|
return &ReturnStateBuf{Lock: &sync.Mutex{}, DoneCh: make(chan bool)}
|
|
|
|
}
|
|
|
|
|
2022-06-10 09:35:24 +02:00
|
|
|
type ShExecType struct {
|
2022-12-06 07:26:13 +01:00
|
|
|
Lock *sync.Mutex // only locks "Exited" field
|
2022-07-02 02:37:37 +02:00
|
|
|
StartTs time.Time
|
|
|
|
CK base.CommandKey
|
|
|
|
FileNames *base.CommandFileNames
|
|
|
|
Cmd *exec.Cmd
|
|
|
|
CmdPty *os.File
|
2022-08-20 00:28:32 +02:00
|
|
|
MaxPtySize int64
|
2022-07-02 02:37:37 +02:00
|
|
|
Multiplexer *mpio.Multiplexer
|
|
|
|
Detached bool
|
|
|
|
DetachedOutput *packet.PacketSender
|
|
|
|
RunnerOutFd *os.File
|
2022-09-07 01:40:41 +02:00
|
|
|
MsgSender *packet.PacketSender // where to send out-of-band messages back to calling proceess
|
2022-10-22 23:45:31 +02:00
|
|
|
ReturnState *ReturnStateBuf
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
Exited bool // locked via Lock
|
|
|
|
TmpRcFileName string // file *or* directory holding temporary rc file(s)
|
|
|
|
SAPI shellapi.ShellApi
|
2022-06-23 21:48:45 +02:00
|
|
|
}
|
|
|
|
|
2022-06-29 02:20:01 +02:00
|
|
|
type StdContext struct{}
|
|
|
|
|
|
|
|
func (StdContext) GetWriter(fdNum int) io.WriteCloser {
|
|
|
|
if fdNum == 0 {
|
|
|
|
return os.Stdin
|
|
|
|
}
|
|
|
|
if fdNum == 1 {
|
|
|
|
return os.Stdout
|
|
|
|
}
|
|
|
|
if fdNum == 2 {
|
|
|
|
return os.Stderr
|
|
|
|
}
|
|
|
|
fd := os.NewFile(uintptr(fdNum), fmt.Sprintf("/dev/fd/%d", fdNum))
|
|
|
|
return fd
|
|
|
|
}
|
|
|
|
|
|
|
|
func (StdContext) GetReader(fdNum int) io.ReadCloser {
|
|
|
|
if fdNum == 0 {
|
|
|
|
return os.Stdin
|
|
|
|
}
|
|
|
|
if fdNum == 1 {
|
|
|
|
return os.Stdout
|
|
|
|
}
|
|
|
|
if fdNum == 2 {
|
|
|
|
return os.Stdout
|
|
|
|
}
|
|
|
|
fd := os.NewFile(uintptr(fdNum), fmt.Sprintf("/dev/fd/%d", fdNum))
|
|
|
|
return fd
|
|
|
|
}
|
|
|
|
|
|
|
|
type FdContext interface {
|
|
|
|
GetWriter(fdNum int) io.WriteCloser
|
|
|
|
GetReader(fdNum int) io.ReadCloser
|
|
|
|
}
|
|
|
|
|
2022-09-07 01:40:41 +02:00
|
|
|
type ShExecUPR struct {
|
|
|
|
ShExec *ShExecType
|
|
|
|
UPR packet.UnknownPacketReporter
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *ShExecType) processSpecialInputPacket(pk *packet.SpecialInputPacketType) error {
|
2022-12-21 06:58:24 +01:00
|
|
|
base.Logf("processSpecialInputPacket: %#v\n", pk)
|
2022-09-07 01:40:41 +02:00
|
|
|
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 != "" {
|
2022-12-21 06:58:24 +01:00
|
|
|
var signal syscall.Signal
|
|
|
|
sigNumInt, err := strconv.Atoi(pk.SigName)
|
|
|
|
if err == nil {
|
|
|
|
signal = syscall.Signal(sigNumInt)
|
|
|
|
} else {
|
|
|
|
signal = unix.SignalNum(pk.SigName)
|
|
|
|
}
|
|
|
|
if signal == 0 {
|
2022-09-07 01:40:41 +02:00
|
|
|
return fmt.Errorf("error signal %q not found, cannot send", pk.SigName)
|
|
|
|
}
|
2022-12-21 06:58:24 +01:00
|
|
|
s.SendSignal(syscall.Signal(signal))
|
2022-09-07 01:40:41 +02:00
|
|
|
}
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
func MakeShExec(ck base.CommandKey, upr packet.UnknownPacketReporter, sapi shellapi.ShellApi) *ShExecType {
|
2022-06-23 21:48:45 +02:00
|
|
|
return &ShExecType{
|
2022-12-06 07:26:13 +01:00
|
|
|
Lock: &sync.Mutex{},
|
2022-06-24 19:24:02 +02:00
|
|
|
StartTs: time.Now(),
|
2022-06-27 21:03:47 +02:00
|
|
|
CK: ck,
|
2022-06-29 04:01:33 +02:00
|
|
|
Multiplexer: mpio.MakeMultiplexer(ck, upr),
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
SAPI: sapi,
|
2022-06-23 21:48:45 +02:00
|
|
|
}
|
2022-06-10 09:35:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *ShExecType) Close() {
|
2022-06-23 21:48:45 +02:00
|
|
|
if c.CmdPty != nil {
|
|
|
|
c.CmdPty.Close()
|
|
|
|
}
|
2022-06-24 19:24:02 +02:00
|
|
|
c.Multiplexer.Close()
|
2022-07-02 02:37:37 +02:00
|
|
|
if c.DetachedOutput != nil {
|
|
|
|
c.DetachedOutput.Close()
|
|
|
|
c.DetachedOutput.WaitForDone()
|
|
|
|
}
|
|
|
|
if c.RunnerOutFd != nil {
|
|
|
|
c.RunnerOutFd.Close()
|
|
|
|
}
|
2022-10-22 23:45:31 +02:00
|
|
|
if c.ReturnState != nil {
|
|
|
|
c.ReturnState.Reader.Close()
|
|
|
|
}
|
2023-10-26 00:20:25 +02:00
|
|
|
if c.TmpRcFileName != "" {
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
// TmpRcFileName can be a file or a directory
|
|
|
|
os.RemoveAll(c.TmpRcFileName)
|
2023-10-26 00:20:25 +02:00
|
|
|
}
|
2022-06-23 21:48:45 +02:00
|
|
|
}
|
|
|
|
|
2022-07-06 08:14:14 +02:00
|
|
|
func (c *ShExecType) MakeCmdStartPacket(reqId string) *packet.CmdStartPacketType {
|
|
|
|
startPacket := packet.MakeCmdStartPacket(reqId)
|
2022-06-23 21:48:45 +02:00
|
|
|
startPacket.Ts = time.Now().UnixMilli()
|
2022-06-27 21:03:47 +02:00
|
|
|
startPacket.CK = c.CK
|
2022-06-23 21:48:45 +02:00
|
|
|
startPacket.Pid = c.Cmd.Process.Pid
|
|
|
|
startPacket.MShellPid = os.Getpid()
|
|
|
|
return startPacket
|
2022-06-10 09:35:24 +02:00
|
|
|
}
|
|
|
|
|
2022-06-29 23:29:38 +02:00
|
|
|
// returns (pr, err)
|
|
|
|
func MakeSimpleStaticWriterPipe(data []byte) (*os.File, error) {
|
|
|
|
pr, pw, err := os.Pipe()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
go func() {
|
|
|
|
defer pw.Close()
|
|
|
|
pw.Write(data)
|
|
|
|
}()
|
|
|
|
return pr, err
|
|
|
|
}
|
|
|
|
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
func MakeRunnerExec(ck base.CommandKey) (*exec.Cmd, error) {
|
|
|
|
msPath, err := base.GetMShellPath()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
ecmd := exec.Command(msPath, string(ck))
|
|
|
|
return ecmd, nil
|
|
|
|
}
|
|
|
|
|
2022-06-29 23:29:38 +02:00
|
|
|
func MakeDetachedExecCmd(pk *packet.RunPacketType, cmdTty *os.File) (*exec.Cmd, error) {
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
sapi, err := shellapi.MakeShellApi(pk.ShellType)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-10-17 08:46:59 +02:00
|
|
|
state := pk.State
|
|
|
|
if state == nil {
|
|
|
|
state = &packet.ShellState{}
|
|
|
|
}
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
ecmd := exec.Command(sapi.GetLocalShellPath(), "-c", pk.Command)
|
2022-10-17 08:46:59 +02:00
|
|
|
if !pk.StateComplete {
|
2022-08-23 01:24:53 +02:00
|
|
|
ecmd.Env = os.Environ()
|
|
|
|
}
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
shellutil.UpdateCmdEnv(ecmd, shellenv.EnvMapFromState(state))
|
|
|
|
shellutil.UpdateCmdEnv(ecmd, shellutil.MShellEnvVars(getTermType(pk)))
|
2022-10-17 08:46:59 +02:00
|
|
|
if state.Cwd != "" {
|
|
|
|
ecmd.Dir = base.ExpandHomeDir(state.Cwd)
|
2022-06-10 09:35:24 +02:00
|
|
|
}
|
2022-07-06 20:21:15 +02:00
|
|
|
if HasDupStdin(pk.Fds) {
|
|
|
|
return nil, fmt.Errorf("cannot detach command with dup stdin")
|
2022-06-29 23:29:38 +02:00
|
|
|
}
|
2022-07-06 20:21:15 +02:00
|
|
|
ecmd.Stdin = cmdTty
|
2022-06-10 09:35:24 +02:00
|
|
|
ecmd.Stdout = cmdTty
|
|
|
|
ecmd.Stderr = cmdTty
|
|
|
|
ecmd.SysProcAttr = &syscall.SysProcAttr{
|
|
|
|
Setsid: true,
|
|
|
|
Setctty: true,
|
|
|
|
}
|
2022-06-29 23:29:38 +02:00
|
|
|
extraFiles := make([]*os.File, 0, MaxFdNum+1)
|
2022-07-06 20:21:15 +02:00
|
|
|
if len(pk.Fds) > 0 {
|
|
|
|
return nil, fmt.Errorf("invalid fd %d passed to detached command", pk.Fds[0].FdNum)
|
2022-06-29 23:29:38 +02:00
|
|
|
}
|
|
|
|
for _, runData := range pk.RunData {
|
|
|
|
if runData.FdNum >= len(extraFiles) {
|
|
|
|
extraFiles = extraFiles[:runData.FdNum+1]
|
|
|
|
}
|
|
|
|
var err error
|
|
|
|
extraFiles[runData.FdNum], err = MakeSimpleStaticWriterPipe(runData.Data)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if len(extraFiles) > FirstExtraFilesFdNum {
|
|
|
|
ecmd.ExtraFiles = extraFiles[FirstExtraFilesFdNum:]
|
|
|
|
}
|
|
|
|
return ecmd, nil
|
2022-06-10 09:35:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// this will never return (unless there is an error creating/opening the file), as fifoFile will never EOF
|
|
|
|
func MakeAndCopyStdinFifo(dst *os.File, fifoName string) error {
|
|
|
|
os.Remove(fifoName)
|
|
|
|
err := syscall.Mkfifo(fifoName, 0600) // only read/write from user for security
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("cannot make stdin-fifo '%s': %v", fifoName, err)
|
|
|
|
}
|
|
|
|
// rw is non-blocking, will keep the fifo "open" for the blocking reader
|
|
|
|
rwfd, err := os.OpenFile(fifoName, os.O_RDWR, 0600)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("cannot open stdin-fifo(1) '%s': %v", fifoName, err)
|
|
|
|
}
|
|
|
|
defer rwfd.Close()
|
|
|
|
fifoReader, err := os.Open(fifoName) // blocking open/reads (open won't block because of rwfd)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("cannot open stdin-fifo(2) '%s': %w", fifoName, err)
|
|
|
|
}
|
|
|
|
defer fifoReader.Close()
|
|
|
|
io.Copy(dst, fifoReader)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func ValidateRunPacket(pk *packet.RunPacketType) error {
|
|
|
|
if pk.Type != packet.RunPacketStr {
|
|
|
|
return fmt.Errorf("run packet has wrong type: %s", pk.Type)
|
|
|
|
}
|
2022-06-23 21:48:45 +02:00
|
|
|
if pk.Detached {
|
2022-06-27 21:03:47 +02:00
|
|
|
err := pk.CK.Validate("run packet")
|
2022-06-23 21:48:45 +02:00
|
|
|
if err != nil {
|
2022-06-27 21:03:47 +02:00
|
|
|
return err
|
2022-06-23 21:48:45 +02:00
|
|
|
}
|
2022-06-28 03:42:56 +02:00
|
|
|
for _, rfd := range pk.Fds {
|
|
|
|
if rfd.Write {
|
|
|
|
return fmt.Errorf("cannot detach command with writable remote files fd=%d", rfd.FdNum)
|
|
|
|
}
|
2022-07-06 20:21:15 +02:00
|
|
|
if rfd.Read && rfd.DupStdin {
|
|
|
|
return fmt.Errorf("cannot detach command with dup stdin fd=%d", rfd.FdNum)
|
|
|
|
}
|
|
|
|
if rfd.Read {
|
2022-06-29 06:57:30 +02:00
|
|
|
return fmt.Errorf("cannot detach command with readable remote files fd=%d", rfd.FdNum)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
totalRunData := 0
|
|
|
|
for _, rd := range pk.RunData {
|
2023-01-31 21:14:41 +01:00
|
|
|
if rd.DataLen > MaxRunDataSize {
|
2022-06-29 06:57:30 +02:00
|
|
|
return fmt.Errorf("cannot detach command, constant rundata input too large fd=%d, len=%d, max=%d", rd.FdNum, rd.DataLen, mpio.ReadBufSize)
|
2022-06-28 03:42:56 +02:00
|
|
|
}
|
2022-06-29 06:57:30 +02:00
|
|
|
totalRunData += rd.DataLen
|
|
|
|
}
|
2023-01-31 21:14:41 +01:00
|
|
|
if totalRunData > MaxTotalRunDataSize {
|
2022-06-29 06:57:30 +02:00
|
|
|
return fmt.Errorf("cannot detach command, constant rundata input too large len=%d, max=%d", totalRunData, mpio.MaxTotalRunDataSize)
|
2022-06-28 03:42:56 +02:00
|
|
|
}
|
2022-06-10 09:35:24 +02:00
|
|
|
}
|
2024-03-07 01:37:54 +01:00
|
|
|
if pk.State != nil {
|
|
|
|
pkCwd := pk.State.Cwd
|
|
|
|
if pkCwd == "" {
|
|
|
|
pkCwd = "~"
|
|
|
|
}
|
|
|
|
realCwd := base.ExpandHomeDir(pkCwd)
|
2022-06-25 08:42:00 +02:00
|
|
|
dirInfo, err := os.Stat(realCwd)
|
2022-06-10 09:35:24 +02:00
|
|
|
if err != nil {
|
2024-03-07 01:37:54 +01:00
|
|
|
return base.CodedErrorf(packet.EC_InvalidCwd, "invalid cwd '%s' for command: %v", realCwd, err)
|
2022-06-10 09:35:24 +02:00
|
|
|
}
|
|
|
|
if !dirInfo.IsDir() {
|
2024-03-07 01:37:54 +01:00
|
|
|
return base.CodedErrorf(packet.EC_InvalidCwd, "invalid cwd '%s' for command, not a directory", realCwd)
|
2022-06-10 09:35:24 +02:00
|
|
|
}
|
|
|
|
}
|
2022-06-29 06:57:30 +02:00
|
|
|
for _, runData := range pk.RunData {
|
|
|
|
if runData.DataLen != len(runData.Data) {
|
|
|
|
return fmt.Errorf("rundata length mismatch, fd=%d, datalen=%d, expected=%d", runData.FdNum, len(runData.Data), runData.DataLen)
|
|
|
|
}
|
|
|
|
}
|
2022-07-06 20:21:15 +02:00
|
|
|
if pk.UsePty && HasDupStdin(pk.Fds) {
|
|
|
|
return fmt.Errorf("cannot use pty with command that has dup stdin")
|
|
|
|
}
|
2022-06-10 09:35:24 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-06-21 02:51:28 +02:00
|
|
|
func GetWinsize(p *packet.RunPacketType) *pty.Winsize {
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
rows := shellutil.DefaultTermRows
|
|
|
|
cols := shellutil.DefaultTermCols
|
2022-07-06 23:06:58 +02:00
|
|
|
if p.TermOpts != nil {
|
2022-09-04 08:26:57 +02:00
|
|
|
rows = base.BoundInt(p.TermOpts.Rows, MinTermRows, MaxTermRows)
|
|
|
|
cols = base.BoundInt(p.TermOpts.Cols, MinTermCols, MaxTermCols)
|
2022-06-21 02:51:28 +02:00
|
|
|
}
|
|
|
|
return &pty.Winsize{Rows: uint16(rows), Cols: uint16(cols)}
|
|
|
|
}
|
|
|
|
|
2022-06-29 00:04:08 +02:00
|
|
|
type SSHOpts struct {
|
2022-09-14 02:10:18 +02:00
|
|
|
SSHHost string
|
|
|
|
SSHOptsStr string
|
|
|
|
SSHIdentity string
|
|
|
|
SSHUser string
|
2022-10-01 02:22:57 +02:00
|
|
|
SSHPort int
|
2022-09-14 02:10:18 +02:00
|
|
|
SSHErrorsToTty bool
|
2022-10-01 02:22:57 +02:00
|
|
|
BatchMode bool
|
2022-06-28 07:39:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type InstallOpts struct {
|
2022-06-29 00:04:08 +02:00
|
|
|
SSHOpts SSHOpts
|
2022-06-28 07:39:16 +02:00
|
|
|
ArchStr string
|
|
|
|
OptName string
|
2022-06-28 08:14:53 +02:00
|
|
|
Detect bool
|
2022-09-26 22:02:34 +02:00
|
|
|
CmdPty *os.File
|
2022-06-28 07:39:16 +02:00
|
|
|
}
|
|
|
|
|
2022-06-24 22:25:09 +02:00
|
|
|
type ClientOpts struct {
|
2022-06-29 06:57:30 +02:00
|
|
|
SSHOpts SSHOpts
|
|
|
|
Command string
|
|
|
|
Fds []packet.RemoteFd
|
|
|
|
Cwd string
|
|
|
|
Debug bool
|
|
|
|
Sudo bool
|
|
|
|
SudoWithPass bool
|
|
|
|
SudoPw string
|
|
|
|
Detach bool
|
2022-07-06 20:21:15 +02:00
|
|
|
UsePty bool
|
2022-06-24 22:25:09 +02:00
|
|
|
}
|
|
|
|
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
func MakeMShellSingleCmd() (*exec.Cmd, error) {
|
|
|
|
execFile, err := os.Executable()
|
2022-07-07 03:59:46 +02:00
|
|
|
if err != nil {
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
return nil, fmt.Errorf("cannot find local mshell executable: %w", err)
|
2022-07-07 03:59:46 +02:00
|
|
|
}
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
ecmd := exec.Command(execFile, "--single-from-server")
|
2022-07-07 03:59:46 +02:00
|
|
|
return ecmd, nil
|
|
|
|
}
|
|
|
|
|
2024-02-29 20:37:03 +01:00
|
|
|
func MakeLocalExecCmd(cmdStr string, sapi shellapi.ShellApi) *exec.Cmd {
|
|
|
|
homeDir, _ := os.UserHomeDir() // ignore error
|
|
|
|
if homeDir == "" {
|
|
|
|
homeDir = "/"
|
|
|
|
}
|
|
|
|
ecmd := exec.Command(sapi.GetLocalShellPath(), "-c", cmdStr)
|
|
|
|
ecmd.Dir = homeDir
|
|
|
|
return ecmd
|
|
|
|
}
|
|
|
|
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
func (opts SSHOpts) MakeSSHExecCmd(remoteCommand string, sapi shellapi.ShellApi) *exec.Cmd {
|
2022-06-29 00:04:08 +02:00
|
|
|
remoteCommand = strings.TrimSpace(remoteCommand)
|
|
|
|
if opts.SSHHost == "" {
|
2022-08-24 11:11:49 +02:00
|
|
|
homeDir, _ := os.UserHomeDir() // ignore error
|
|
|
|
if homeDir == "" {
|
|
|
|
homeDir = "/"
|
|
|
|
}
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
ecmd := exec.Command(sapi.GetLocalShellPath(), "-c", remoteCommand)
|
2022-08-24 11:11:49 +02:00
|
|
|
ecmd.Dir = homeDir
|
2022-06-28 00:10:17 +02:00
|
|
|
return ecmd
|
|
|
|
} else {
|
|
|
|
var moreSSHOpts []string
|
2022-06-29 00:04:08 +02:00
|
|
|
if opts.SSHIdentity != "" {
|
|
|
|
identityOpt := fmt.Sprintf("-i %s", shellescape.Quote(opts.SSHIdentity))
|
2022-06-28 00:10:17 +02:00
|
|
|
moreSSHOpts = append(moreSSHOpts, identityOpt)
|
|
|
|
}
|
2022-06-29 00:04:08 +02:00
|
|
|
if opts.SSHUser != "" {
|
|
|
|
userOpt := fmt.Sprintf("-l %s", shellescape.Quote(opts.SSHUser))
|
2022-06-28 00:10:17 +02:00
|
|
|
moreSSHOpts = append(moreSSHOpts, userOpt)
|
|
|
|
}
|
2022-10-01 02:22:57 +02:00
|
|
|
if opts.SSHPort != 0 {
|
|
|
|
portOpt := fmt.Sprintf("-p %d", opts.SSHPort)
|
|
|
|
moreSSHOpts = append(moreSSHOpts, portOpt)
|
|
|
|
}
|
2022-09-14 02:10:18 +02:00
|
|
|
if opts.SSHErrorsToTty {
|
2022-10-01 02:22:57 +02:00
|
|
|
errFdStr := "-E /dev/tty"
|
|
|
|
moreSSHOpts = append(moreSSHOpts, errFdStr)
|
|
|
|
}
|
|
|
|
if opts.BatchMode {
|
|
|
|
batchOpt := "-o 'BatchMode=yes'"
|
|
|
|
moreSSHOpts = append(moreSSHOpts, batchOpt)
|
2022-09-14 02:10:18 +02:00
|
|
|
}
|
2022-10-01 02:22:57 +02:00
|
|
|
// note that SSHOptsStr is *not* escaped
|
|
|
|
sshCmd := fmt.Sprintf("ssh %s %s %s %s", strings.Join(moreSSHOpts, " "), opts.SSHOptsStr, shellescape.Quote(opts.SSHHost), shellescape.Quote(remoteCommand))
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
ecmd := exec.Command(sapi.GetRemoteShellPath(), "-c", sshCmd)
|
2022-06-28 00:10:17 +02:00
|
|
|
return ecmd
|
|
|
|
}
|
2022-06-27 23:57:01 +02:00
|
|
|
}
|
|
|
|
|
2022-06-29 00:04:08 +02:00
|
|
|
func (opts SSHOpts) MakeMShellSSHOpts() string {
|
2022-06-28 07:39:16 +02:00
|
|
|
var moreSSHOpts []string
|
2022-06-29 00:04:08 +02:00
|
|
|
if opts.SSHIdentity != "" {
|
|
|
|
identityOpt := fmt.Sprintf("-i %s", shellescape.Quote(opts.SSHIdentity))
|
2022-06-28 07:39:16 +02:00
|
|
|
moreSSHOpts = append(moreSSHOpts, identityOpt)
|
|
|
|
}
|
2022-06-29 00:04:08 +02:00
|
|
|
if opts.SSHUser != "" {
|
|
|
|
userOpt := fmt.Sprintf("-l %s", shellescape.Quote(opts.SSHUser))
|
2022-06-28 07:39:16 +02:00
|
|
|
moreSSHOpts = append(moreSSHOpts, userOpt)
|
|
|
|
}
|
2022-10-01 02:22:57 +02:00
|
|
|
if opts.SSHPort != 0 {
|
|
|
|
portOpt := fmt.Sprintf("-p %d", opts.SSHPort)
|
|
|
|
moreSSHOpts = append(moreSSHOpts, portOpt)
|
|
|
|
}
|
2022-06-29 00:04:08 +02:00
|
|
|
if opts.SSHOptsStr != "" {
|
|
|
|
optsOpt := fmt.Sprintf("--ssh-opts %s", shellescape.Quote(opts.SSHOptsStr))
|
2022-06-28 03:42:56 +02:00
|
|
|
moreSSHOpts = append(moreSSHOpts, optsOpt)
|
|
|
|
}
|
2022-06-29 00:04:08 +02:00
|
|
|
if opts.SSHHost != "" {
|
|
|
|
sshArg := fmt.Sprintf("--ssh %s", shellescape.Quote(opts.SSHHost))
|
2022-06-28 03:42:56 +02:00
|
|
|
moreSSHOpts = append(moreSSHOpts, sshArg)
|
|
|
|
}
|
2022-06-29 00:04:08 +02:00
|
|
|
return strings.Join(moreSSHOpts, " ")
|
2022-06-28 03:42:56 +02:00
|
|
|
}
|
|
|
|
|
2022-07-06 23:06:58 +02:00
|
|
|
func GetTerminalSize() (int, int, error) {
|
|
|
|
fd, err := os.Open("/dev/tty")
|
|
|
|
if err != nil {
|
|
|
|
return 0, 0, err
|
|
|
|
}
|
|
|
|
defer fd.Close()
|
|
|
|
return pty.Getsize(fd)
|
|
|
|
}
|
|
|
|
|
2022-06-29 06:57:30 +02:00
|
|
|
func AddRunData(pk *packet.RunPacketType, data string, dataType string) (int, error) {
|
2023-01-31 21:14:41 +01:00
|
|
|
if len(data) > MaxRunDataSize {
|
|
|
|
return 0, fmt.Errorf("%s too large, exceeds read buffer size size:%d", dataType, len(data))
|
2022-06-29 06:57:30 +02:00
|
|
|
}
|
|
|
|
fdNum, err := NextFreeFdNum(pk)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
runData := packet.RunDataType{FdNum: fdNum, DataLen: len(data), Data: []byte(data)}
|
|
|
|
pk.RunData = append(pk.RunData, runData)
|
|
|
|
return fdNum, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func NextFreeFdNum(pk *packet.RunPacketType) (int, error) {
|
2022-06-26 10:41:58 +02:00
|
|
|
fdMap := make(map[int]bool)
|
2022-06-29 06:57:30 +02:00
|
|
|
for _, fd := range pk.Fds {
|
2022-06-26 10:41:58 +02:00
|
|
|
fdMap[fd.FdNum] = true
|
|
|
|
}
|
2022-06-29 06:57:30 +02:00
|
|
|
for _, rd := range pk.RunData {
|
|
|
|
fdMap[rd.FdNum] = true
|
|
|
|
}
|
2022-06-26 10:41:58 +02:00
|
|
|
for i := 3; i <= MaxFdNum; i++ {
|
|
|
|
if !fdMap[i] {
|
|
|
|
return i, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0, fmt.Errorf("reached maximum number of fds, all fds between 3-%d are in use", MaxFdNum)
|
|
|
|
}
|
|
|
|
|
2022-06-29 06:57:30 +02:00
|
|
|
func MaxFdNumInPacket(pk *packet.RunPacketType) int {
|
2022-06-26 10:41:58 +02:00
|
|
|
maxFdNum := 3
|
2022-06-29 06:57:30 +02:00
|
|
|
for _, fd := range pk.Fds {
|
2022-06-26 10:41:58 +02:00
|
|
|
if fd.FdNum > maxFdNum {
|
|
|
|
maxFdNum = fd.FdNum
|
|
|
|
}
|
|
|
|
}
|
2022-06-29 06:57:30 +02:00
|
|
|
for _, rd := range pk.RunData {
|
|
|
|
if rd.FdNum > maxFdNum {
|
|
|
|
maxFdNum = rd.FdNum
|
|
|
|
}
|
|
|
|
}
|
2022-06-26 10:41:58 +02:00
|
|
|
return maxFdNum
|
2022-06-24 22:25:09 +02:00
|
|
|
}
|
|
|
|
|
2022-06-25 08:42:00 +02:00
|
|
|
func ValidateRemoteFds(rfds []packet.RemoteFd) error {
|
|
|
|
dupMap := make(map[int]bool)
|
|
|
|
for _, rfd := range rfds {
|
|
|
|
if rfd.FdNum < 0 {
|
|
|
|
return fmt.Errorf("mshell negative fd numbers fd=%d", rfd.FdNum)
|
|
|
|
}
|
|
|
|
if rfd.FdNum < FirstExtraFilesFdNum {
|
|
|
|
return fmt.Errorf("mshell does not support re-opening fd=%d (0, 1, and 2, are always open)", rfd.FdNum)
|
|
|
|
}
|
|
|
|
if rfd.FdNum > MaxFdNum {
|
|
|
|
return fmt.Errorf("mshell does not support opening fd numbers above %d", MaxFdNum)
|
|
|
|
}
|
|
|
|
if dupMap[rfd.FdNum] {
|
|
|
|
return fmt.Errorf("mshell got duplicate entries for fd=%d", rfd.FdNum)
|
|
|
|
}
|
|
|
|
if rfd.Read && rfd.Write {
|
|
|
|
return fmt.Errorf("mshell does not support opening fd numbers for reading and writing, fd=%d", rfd.FdNum)
|
|
|
|
}
|
|
|
|
if !rfd.Read && !rfd.Write {
|
|
|
|
return fmt.Errorf("invalid fd=%d, neither reading or writing mode specified", rfd.FdNum)
|
|
|
|
}
|
|
|
|
dupMap[rfd.FdNum] = true
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-11-02 05:19:42 +01:00
|
|
|
func sendMShellBinary(input io.WriteCloser, mshellStream io.Reader) {
|
2022-06-28 08:14:53 +02:00
|
|
|
go func() {
|
|
|
|
defer input.Close()
|
2022-11-02 05:19:42 +01:00
|
|
|
io.Copy(input, mshellStream)
|
2022-06-28 08:14:53 +02:00
|
|
|
}()
|
|
|
|
}
|
|
|
|
|
2024-02-29 20:37:03 +01:00
|
|
|
func RunInstallFromCmd(ctx context.Context, ecmd ConnInterface, tryDetect bool, mshellStream io.Reader, mshellReaderFn MShellBinaryReaderFn, msgFn func(string)) error {
|
2022-06-28 07:39:16 +02:00
|
|
|
inputWriter, err := ecmd.StdinPipe()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("creating stdin pipe: %v", err)
|
|
|
|
}
|
|
|
|
stdoutReader, err := ecmd.StdoutPipe()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("creating stdout pipe: %v", err)
|
|
|
|
}
|
|
|
|
stderrReader, err := ecmd.StderrPipe()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("creating stderr pipe: %v", err)
|
|
|
|
}
|
|
|
|
go func() {
|
|
|
|
io.Copy(os.Stderr, stderrReader)
|
|
|
|
}()
|
2022-11-02 05:19:42 +01:00
|
|
|
if mshellStream != nil {
|
|
|
|
sendMShellBinary(inputWriter, mshellStream)
|
2022-06-28 07:39:16 +02:00
|
|
|
}
|
2023-12-18 21:42:40 +01:00
|
|
|
packetParser := packet.MakePacketParser(stdoutReader, nil)
|
2022-06-28 07:39:16 +02:00
|
|
|
err = ecmd.Start()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("running ssh command: %w", err)
|
|
|
|
}
|
2022-06-28 08:14:53 +02:00
|
|
|
firstInit := true
|
2022-09-27 08:23:32 +02:00
|
|
|
for {
|
|
|
|
var pk packet.PacketType
|
|
|
|
select {
|
|
|
|
case pk = <-packetParser.MainCh:
|
|
|
|
case <-ctx.Done():
|
|
|
|
return ctx.Err()
|
|
|
|
}
|
2023-02-01 09:44:31 +01:00
|
|
|
if pk == nil {
|
|
|
|
return fmt.Errorf("no response packet received from client")
|
|
|
|
}
|
2022-06-28 08:14:53 +02:00
|
|
|
if pk.GetType() == packet.InitPacketStr && firstInit {
|
|
|
|
firstInit = false
|
|
|
|
initPacket := pk.(*packet.InitPacketType)
|
|
|
|
if !tryDetect {
|
|
|
|
continue // ignore
|
|
|
|
}
|
|
|
|
tryDetect = false
|
|
|
|
if initPacket.UName == "" {
|
|
|
|
return fmt.Errorf("cannot detect arch, no uname received from remote server")
|
|
|
|
}
|
|
|
|
goos, goarch, err := DetectGoArch(initPacket.UName)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("arch cannot be detected (might be incompatible with mshell): %w", err)
|
|
|
|
}
|
2022-09-26 22:02:34 +02:00
|
|
|
msgStr := fmt.Sprintf("mshell detected remote architecture as '%s.%s'\n", goos, goarch)
|
|
|
|
msgFn(msgStr)
|
2022-11-02 05:19:42 +01:00
|
|
|
detectedMSS, err := mshellReaderFn(base.MShellVersion, goos, goarch)
|
2022-09-26 22:02:34 +02:00
|
|
|
if err != nil {
|
2022-11-02 05:19:42 +01:00
|
|
|
return err
|
2022-09-26 22:02:34 +02:00
|
|
|
}
|
2022-11-02 05:19:42 +01:00
|
|
|
defer detectedMSS.Close()
|
|
|
|
sendMShellBinary(inputWriter, detectedMSS)
|
2022-06-28 08:14:53 +02:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
if pk.GetType() == packet.InitPacketStr && !firstInit {
|
2022-06-28 07:39:16 +02:00
|
|
|
initPacket := pk.(*packet.InitPacketType)
|
|
|
|
if initPacket.Version == base.MShellVersion {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return fmt.Errorf("invalid version '%s' received from client, expecting '%s'", initPacket.Version, base.MShellVersion)
|
|
|
|
}
|
|
|
|
if pk.GetType() == packet.RawPacketStr {
|
|
|
|
rawPk := pk.(*packet.RawPacketType)
|
2022-09-27 08:23:32 +02:00
|
|
|
msgFn(fmt.Sprintf("%s\n", rawPk.Data))
|
2022-06-28 07:39:16 +02:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
return fmt.Errorf("invalid response packet '%s' received from client", pk.GetType())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-29 02:20:01 +02:00
|
|
|
func HasDupStdin(fds []packet.RemoteFd) bool {
|
|
|
|
for _, rfd := range fds {
|
|
|
|
if rfd.Read && rfd.DupStdin {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2022-06-29 06:57:30 +02:00
|
|
|
func min(v1 int, v2 int) int {
|
|
|
|
if v1 <= v2 {
|
|
|
|
return v1
|
|
|
|
}
|
|
|
|
return v2
|
|
|
|
}
|
|
|
|
|
2022-07-07 03:59:46 +02:00
|
|
|
func SendRunPacketAndRunData(ctx context.Context, sender *packet.PacketSender, runPacket *packet.RunPacketType) error {
|
|
|
|
err := sender.SendPacketCtx(ctx, runPacket)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-06-29 23:29:38 +02:00
|
|
|
if len(runPacket.RunData) == 0 {
|
2022-07-07 03:59:46 +02:00
|
|
|
return nil
|
2022-06-29 23:29:38 +02:00
|
|
|
}
|
2022-06-29 06:57:30 +02:00
|
|
|
for _, runData := range runPacket.RunData {
|
|
|
|
sendBuf := runData.Data
|
|
|
|
for len(sendBuf) > 0 {
|
|
|
|
chunkSize := min(len(sendBuf), mpio.MaxSingleWriteSize)
|
|
|
|
chunk := sendBuf[0:chunkSize]
|
|
|
|
dataPk := packet.MakeDataPacket()
|
|
|
|
dataPk.CK = runPacket.CK
|
|
|
|
dataPk.FdNum = runData.FdNum
|
|
|
|
dataPk.Data64 = base64.StdEncoding.EncodeToString(chunk)
|
|
|
|
dataPk.Eof = (len(chunk) == len(sendBuf))
|
|
|
|
sendBuf = sendBuf[chunkSize:]
|
2022-07-07 03:59:46 +02:00
|
|
|
err = sender.SendPacketCtx(ctx, dataPk)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-06-29 06:57:30 +02:00
|
|
|
}
|
|
|
|
}
|
2022-07-07 03:59:46 +02:00
|
|
|
err = sender.SendPacketCtx(ctx, packet.MakeDataEndPacket(runPacket.CK))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
2022-06-29 06:57:30 +02:00
|
|
|
}
|
|
|
|
|
2022-06-28 08:14:53 +02:00
|
|
|
func DetectGoArch(uname string) (string, string, error) {
|
2022-06-28 03:42:56 +02:00
|
|
|
fields := strings.SplitN(uname, "|", 2)
|
|
|
|
if len(fields) != 2 {
|
|
|
|
return "", "", fmt.Errorf("invalid uname string returned")
|
|
|
|
}
|
|
|
|
osVal := strings.TrimSpace(strings.ToLower(fields[0]))
|
|
|
|
archVal := strings.TrimSpace(strings.ToLower(fields[1]))
|
|
|
|
if osVal != "darwin" && osVal != "linux" {
|
|
|
|
return "", "", fmt.Errorf("invalid uname OS '%s', mshell only supports OS X (darwin) and linux", osVal)
|
|
|
|
}
|
|
|
|
goos := osVal
|
|
|
|
goarch := ""
|
|
|
|
if archVal == "x86_64" || archVal == "i686" || archVal == "amd64" {
|
|
|
|
goarch = "amd64"
|
2022-09-22 08:26:53 +02:00
|
|
|
} else if archVal == "aarch64" || archVal == "arm64" {
|
2022-06-28 03:42:56 +02:00
|
|
|
goarch = "arm64"
|
|
|
|
}
|
|
|
|
if goarch == "" {
|
|
|
|
return "", "", fmt.Errorf("invalid uname machine type '%s', mshell only supports aarch64 (amd64) and x86_64 (amd64)", archVal)
|
|
|
|
}
|
2022-06-28 07:39:16 +02:00
|
|
|
if !base.ValidGoArch(goos, goarch) {
|
|
|
|
return "", "", fmt.Errorf("invalid arch detected %s.%s", goos, goarch)
|
|
|
|
}
|
2022-06-28 03:42:56 +02:00
|
|
|
return goos, goarch, nil
|
|
|
|
}
|
|
|
|
|
2022-06-27 21:14:07 +02:00
|
|
|
func (cmd *ShExecType) RunRemoteIOAndWait(packetParser *packet.PacketParser, sender *packet.PacketSender) {
|
2022-06-25 08:42:00 +02:00
|
|
|
defer cmd.Close()
|
2022-10-22 23:45:31 +02:00
|
|
|
if cmd.ReturnState != nil {
|
|
|
|
go cmd.ReturnState.Run()
|
|
|
|
}
|
2022-06-27 21:14:07 +02:00
|
|
|
cmd.Multiplexer.RunIOAndWait(packetParser, sender, true, false, false)
|
2022-06-23 21:48:45 +02:00
|
|
|
donePacket := cmd.WaitForCommand()
|
|
|
|
sender.SendPacket(donePacket)
|
|
|
|
}
|
|
|
|
|
2022-07-06 23:06:58 +02:00
|
|
|
func getTermType(pk *packet.RunPacketType) string {
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
termType := shellutil.DefaultTermType
|
2022-07-06 23:06:58 +02:00
|
|
|
if pk.TermOpts != nil && pk.TermOpts.Term != "" {
|
|
|
|
termType = pk.TermOpts.Term
|
|
|
|
}
|
|
|
|
return termType
|
|
|
|
}
|
|
|
|
|
2022-12-21 06:58:24 +01:00
|
|
|
func (s *ShExecType) SendSignal(sig syscall.Signal) {
|
2023-11-10 03:29:11 +01:00
|
|
|
base.Logf("signal start %v\n", sig)
|
|
|
|
if sig == syscall.SIGKILL {
|
|
|
|
// SIGKILL is special, it also needs to kill waveshell if it's hanging
|
|
|
|
go func() {
|
|
|
|
wsPid := syscall.Getpid()
|
|
|
|
base.Logf("special sigkill handling waveshell-pid:%d\n", wsPid)
|
|
|
|
time.Sleep(SigKillWaitTime)
|
|
|
|
base.Logf("running self-sigkill %d\n", wsPid)
|
|
|
|
syscall.Kill(wsPid, syscall.SIGKILL)
|
|
|
|
}()
|
|
|
|
}
|
2022-12-06 07:26:13 +01:00
|
|
|
if s.Cmd == nil || s.Cmd.Process == nil || s.IsExited() {
|
2023-11-10 03:29:11 +01:00
|
|
|
base.Logf("signal, no cmd or exited (exited:%v)\n", s.IsExited())
|
2022-12-06 07:26:13 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
pgroup := false
|
|
|
|
if s.Cmd.SysProcAttr != nil && (s.Cmd.SysProcAttr.Setsid || s.Cmd.SysProcAttr.Setpgid) {
|
|
|
|
pgroup = true
|
|
|
|
}
|
|
|
|
pid := s.Cmd.Process.Pid
|
|
|
|
if pgroup {
|
2022-12-21 06:58:24 +01:00
|
|
|
base.Logf("send signal %s to %d (pgroup)\n", sig, -pid)
|
|
|
|
syscall.Kill(-pid, sig)
|
2022-12-06 07:26:13 +01:00
|
|
|
} else {
|
2022-12-21 06:58:24 +01:00
|
|
|
base.Logf("send signal %s to %d (normal)\n", sig, pid)
|
|
|
|
syscall.Kill(pid, sig)
|
2022-12-06 07:26:13 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-22 23:45:31 +02:00
|
|
|
func RunCommandSimple(pk *packet.RunPacketType, sender *packet.PacketSender, fromServer bool) (rtnShExec *ShExecType, rtnErr error) {
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
sapi, err := shellapi.MakeShellApi(pk.ShellType)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-10-17 08:46:59 +02:00
|
|
|
state := pk.State
|
|
|
|
if state == nil {
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
return nil, fmt.Errorf("invalid run packet, no state")
|
2022-10-17 08:46:59 +02:00
|
|
|
}
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
cmd := MakeShExec(pk.CK, nil, sapi)
|
2022-10-22 23:45:31 +02:00
|
|
|
defer func() {
|
|
|
|
// on error, call cmd.Close()
|
|
|
|
if rtnErr != nil {
|
|
|
|
cmd.Close()
|
|
|
|
}
|
|
|
|
}()
|
2022-09-06 21:57:54 +02:00
|
|
|
if fromServer {
|
2022-09-07 01:40:41 +02:00
|
|
|
msgUpr := packet.MessageUPR{CK: pk.CK, Sender: sender}
|
|
|
|
upr := ShExecUPR{ShExec: cmd, UPR: msgUpr}
|
|
|
|
cmd.Multiplexer.UPR = upr
|
|
|
|
cmd.MsgSender = sender
|
2022-09-06 21:57:54 +02:00
|
|
|
}
|
2022-10-22 23:45:31 +02:00
|
|
|
var rtnStateWriter *os.File
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
rcFileStr := sapi.MakeRcFileStr(pk)
|
2022-10-22 23:45:31 +02:00
|
|
|
if pk.ReturnState {
|
|
|
|
pr, pw, err := os.Pipe()
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("cannot create returnstate pipe: %v", err)
|
|
|
|
}
|
|
|
|
cmd.ReturnState = MakeReturnStateBuf()
|
|
|
|
cmd.ReturnState.Reader = pr
|
2023-11-10 03:57:39 +01:00
|
|
|
cmd.ReturnState.FdNum = RtnStateFdNum
|
2022-10-22 23:45:31 +02:00
|
|
|
rtnStateWriter = pw
|
|
|
|
defer pw.Close()
|
2024-03-20 00:38:38 +01:00
|
|
|
trapCmdStr, endBytes := sapi.MakeExitTrap(cmd.ReturnState.FdNum)
|
|
|
|
cmd.ReturnState.EndBytes = endBytes
|
2022-10-22 23:45:31 +02:00
|
|
|
rcFileStr += trapCmdStr
|
|
|
|
}
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
shellVarMap := shellenv.ShellVarMapFromState(state)
|
2024-01-20 22:17:43 +01:00
|
|
|
if base.HasDebugFlag(shellVarMap, base.DebugFlag_LogRcFile) || ForceDebugRcFile {
|
2024-03-06 20:38:27 +01:00
|
|
|
wlog.Logf("debugrc file %q\n", base.GetDebugRcFileName())
|
2023-08-14 21:23:33 +02:00
|
|
|
debugRcFileName := base.GetDebugRcFileName()
|
|
|
|
err := os.WriteFile(debugRcFileName, []byte(rcFileStr), 0600)
|
|
|
|
if err != nil {
|
|
|
|
base.Logf("error writing %s: %v\n", debugRcFileName, err)
|
|
|
|
}
|
|
|
|
}
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
var isOldBashVersion bool
|
|
|
|
if sapi.GetShellType() == packet.ShellType_bash {
|
|
|
|
bashVersion := sapi.GetLocalMajorVersion()
|
|
|
|
isOldBashVersion = (semver.Compare(bashVersion, "v4") < 0)
|
|
|
|
}
|
2023-10-26 00:20:25 +02:00
|
|
|
var rcFileName string
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
var zdotdir string
|
2023-10-26 00:20:25 +02:00
|
|
|
if isOldBashVersion {
|
|
|
|
rcFileDir, err := base.EnsureRcFilesDir()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
rcFileName = path.Join(rcFileDir, uuid.New().String())
|
|
|
|
err = os.WriteFile(rcFileName, []byte(rcFileStr), 0600)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("could not write temp rcfile: %w", err)
|
|
|
|
}
|
|
|
|
cmd.TmpRcFileName = rcFileName
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
} else if sapi.GetShellType() == packet.ShellType_zsh {
|
|
|
|
rcFileDir, err := base.EnsureRcFilesDir()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
zdotdir = path.Join(rcFileDir, uuid.New().String())
|
|
|
|
os.Mkdir(zdotdir, 0700)
|
|
|
|
rcFileName = path.Join(zdotdir, ".zshenv")
|
|
|
|
err = os.WriteFile(rcFileName, []byte(rcFileStr), 0600)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("could not write temp rcfile: %w", err)
|
|
|
|
}
|
|
|
|
cmd.TmpRcFileName = zdotdir
|
2023-10-26 00:20:25 +02:00
|
|
|
} else {
|
|
|
|
rcFileFdNum, err := AddRunData(pk, rcFileStr, "rcfile")
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
rcFileName = fmt.Sprintf("/dev/fd/%d", rcFileFdNum)
|
2022-10-17 08:46:59 +02:00
|
|
|
}
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
if cmd.TmpRcFileName != "" {
|
|
|
|
go func() {
|
|
|
|
// cmd.Close() will also remove rcFileName
|
|
|
|
// adding this to also try to proactively clean up after 2-seconds.
|
|
|
|
time.Sleep(2 * time.Second)
|
|
|
|
os.Remove(cmd.TmpRcFileName)
|
|
|
|
}()
|
2022-08-30 09:23:03 +02:00
|
|
|
}
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
cmd.Cmd = sapi.MakeShExecCommand(pk.Command, rcFileName, pk.UsePty)
|
2022-10-17 08:46:59 +02:00
|
|
|
if !pk.StateComplete {
|
2022-08-23 01:24:53 +02:00
|
|
|
cmd.Cmd.Env = os.Environ()
|
|
|
|
}
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
shellutil.UpdateCmdEnv(cmd.Cmd, shellenv.EnvMapFromState(state))
|
|
|
|
if sapi.GetShellType() == packet.ShellType_zsh {
|
|
|
|
shellutil.UpdateCmdEnv(cmd.Cmd, map[string]string{"ZDOTDIR": zdotdir})
|
|
|
|
}
|
2024-03-07 01:37:54 +01:00
|
|
|
if state.Cwd == "" {
|
|
|
|
cmd.Cmd.Dir = base.ExpandHomeDir("~")
|
|
|
|
} else if state.Cwd != "" {
|
2022-10-17 08:46:59 +02:00
|
|
|
cmd.Cmd.Dir = base.ExpandHomeDir(state.Cwd)
|
2022-06-25 08:42:00 +02:00
|
|
|
}
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
err = ValidateRemoteFds(pk.Fds)
|
2022-06-25 08:42:00 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2022-06-23 21:48:45 +02:00
|
|
|
}
|
2022-07-06 20:21:15 +02:00
|
|
|
var cmdPty *os.File
|
|
|
|
var cmdTty *os.File
|
|
|
|
if pk.UsePty {
|
|
|
|
cmdPty, cmdTty, err = pty.Open()
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("opening new pty: %w", err)
|
|
|
|
}
|
|
|
|
pty.Setsize(cmdPty, GetWinsize(pk))
|
|
|
|
defer func() {
|
|
|
|
cmdTty.Close()
|
|
|
|
}()
|
|
|
|
cmd.CmdPty = cmdPty
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
shellutil.UpdateCmdEnv(cmd.Cmd, shellutil.MShellEnvVars(getTermType(pk)))
|
2022-07-06 20:21:15 +02:00
|
|
|
}
|
|
|
|
if cmdTty != nil {
|
|
|
|
cmd.Cmd.Stdin = cmdTty
|
|
|
|
cmd.Cmd.Stdout = cmdTty
|
|
|
|
cmd.Cmd.Stderr = cmdTty
|
|
|
|
cmd.Cmd.SysProcAttr = &syscall.SysProcAttr{
|
|
|
|
Setsid: true,
|
|
|
|
Setctty: true,
|
|
|
|
}
|
2023-04-18 00:13:03 +02:00
|
|
|
cmd.Multiplexer.MakeRawFdWriter(0, cmdPty, false, "simple")
|
2022-07-06 21:16:37 +02:00
|
|
|
cmd.Multiplexer.MakeRawFdReader(1, cmdPty, false, true)
|
2022-07-06 20:21:15 +02:00
|
|
|
nullFd, err := os.Open("/dev/null")
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("cannot open /dev/null: %w", err)
|
|
|
|
}
|
2022-07-06 21:16:37 +02:00
|
|
|
cmd.Multiplexer.MakeRawFdReader(2, nullFd, true, false)
|
2022-07-06 20:21:15 +02:00
|
|
|
} else {
|
2023-04-18 00:13:03 +02:00
|
|
|
cmd.Cmd.Stdin, err = cmd.Multiplexer.MakeWriterPipe(0, "simple")
|
2022-07-06 20:21:15 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
cmd.Cmd.Stdout, err = cmd.Multiplexer.MakeReaderPipe(1)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
cmd.Cmd.Stderr, err = cmd.Multiplexer.MakeReaderPipe(2)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-06-23 21:48:45 +02:00
|
|
|
}
|
2022-06-24 03:23:30 +02:00
|
|
|
extraFiles := make([]*os.File, 0, MaxFdNum+1)
|
2022-06-29 06:57:30 +02:00
|
|
|
for _, runData := range pk.RunData {
|
|
|
|
if runData.FdNum >= len(extraFiles) {
|
|
|
|
extraFiles = extraFiles[:runData.FdNum+1]
|
|
|
|
}
|
2023-04-18 00:13:03 +02:00
|
|
|
extraFiles[runData.FdNum], err = cmd.Multiplexer.MakeStaticWriterPipe(runData.FdNum, runData.Data, MaxRunDataSize, "simple-rundata")
|
2022-06-29 06:57:30 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
2022-06-24 03:23:30 +02:00
|
|
|
for _, rfd := range pk.Fds {
|
|
|
|
if rfd.FdNum >= len(extraFiles) {
|
|
|
|
extraFiles = extraFiles[:rfd.FdNum+1]
|
|
|
|
}
|
|
|
|
if rfd.Read {
|
|
|
|
// client file is open for reading, so we make a writer pipe
|
2023-04-18 00:13:03 +02:00
|
|
|
extraFiles[rfd.FdNum], err = cmd.Multiplexer.MakeWriterPipe(rfd.FdNum, "simple")
|
2022-06-24 03:23:30 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if rfd.Write {
|
|
|
|
// client file is open for writing, so we make a reader pipe
|
2022-06-24 19:24:02 +02:00
|
|
|
extraFiles[rfd.FdNum], err = cmd.Multiplexer.MakeReaderPipe(rfd.FdNum)
|
2022-06-24 03:23:30 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-10-22 23:45:31 +02:00
|
|
|
if cmd.ReturnState != nil {
|
|
|
|
if cmd.ReturnState.FdNum >= len(extraFiles) {
|
|
|
|
extraFiles = extraFiles[:cmd.ReturnState.FdNum+1]
|
|
|
|
}
|
|
|
|
extraFiles[cmd.ReturnState.FdNum] = rtnStateWriter
|
|
|
|
}
|
2022-06-24 03:23:30 +02:00
|
|
|
if len(extraFiles) > FirstExtraFilesFdNum {
|
|
|
|
cmd.Cmd.ExtraFiles = extraFiles[FirstExtraFilesFdNum:]
|
|
|
|
}
|
2022-06-23 21:48:45 +02:00
|
|
|
err = cmd.Cmd.Start()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return cmd, nil
|
|
|
|
}
|
|
|
|
|
2022-10-22 23:45:31 +02:00
|
|
|
// TODO limit size of read state buffer
|
|
|
|
func (rs *ReturnStateBuf) Run() {
|
|
|
|
buf := make([]byte, 1024)
|
|
|
|
defer func() {
|
|
|
|
rs.Lock.Lock()
|
|
|
|
defer rs.Lock.Unlock()
|
|
|
|
rs.Reader.Close()
|
|
|
|
rs.Done = true
|
|
|
|
close(rs.DoneCh)
|
|
|
|
}()
|
|
|
|
for {
|
|
|
|
n, readErr := rs.Reader.Read(buf)
|
|
|
|
if readErr == io.EOF {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if readErr != nil {
|
|
|
|
rs.Lock.Lock()
|
|
|
|
rs.Err = readErr
|
|
|
|
rs.Lock.Unlock()
|
|
|
|
break
|
|
|
|
}
|
|
|
|
rs.Lock.Lock()
|
|
|
|
rs.Buf = append(rs.Buf, buf[0:n]...)
|
2024-03-20 00:38:38 +01:00
|
|
|
if bytes.HasSuffix(rs.Buf, rs.EndBytes) {
|
|
|
|
rs.Buf = rs.Buf[:len(rs.Buf)-len(rs.EndBytes)]
|
|
|
|
rs.Lock.Unlock()
|
|
|
|
break
|
|
|
|
}
|
2022-10-22 23:45:31 +02:00
|
|
|
rs.Lock.Unlock()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-29 23:29:38 +02:00
|
|
|
// in detached run mode, we don't want mshell to die from signals
|
|
|
|
// since we want mshell to persist even if the mshell --server is terminated
|
|
|
|
func SetupSignalsForDetach() {
|
|
|
|
sigCh := make(chan os.Signal, 1)
|
2022-12-06 07:26:13 +01:00
|
|
|
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGPIPE)
|
2022-06-29 23:29:38 +02:00
|
|
|
go func() {
|
|
|
|
for range sigCh {
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
|
2022-12-06 07:26:13 +01:00
|
|
|
// in detached run mode, we don't want mshell to die from signals
|
|
|
|
// since we want mshell to persist even if the mshell --server is terminated
|
|
|
|
func IgnoreSigPipe() {
|
|
|
|
sigCh := make(chan os.Signal, 1)
|
|
|
|
signal.Notify(sigCh, syscall.SIGPIPE)
|
|
|
|
go func() {
|
|
|
|
for sig := range sigCh {
|
|
|
|
base.Logf("ignoring signal %v\n", sig)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
|
2022-08-20 00:28:32 +02:00
|
|
|
func copyToCirFile(dest *cirfile.File, src io.Reader) error {
|
|
|
|
buf := make([]byte, 64*1024)
|
|
|
|
for {
|
|
|
|
var appendErr error
|
|
|
|
nr, readErr := src.Read(buf)
|
|
|
|
if nr > 0 {
|
|
|
|
appendErr = dest.AppendData(context.Background(), buf[0:nr])
|
|
|
|
}
|
|
|
|
if readErr != nil && readErr != io.EOF {
|
|
|
|
return readErr
|
|
|
|
}
|
|
|
|
if appendErr != nil {
|
|
|
|
return appendErr
|
|
|
|
}
|
|
|
|
if readErr == io.EOF {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-15 07:58:09 +01:00
|
|
|
func GetCmdExitCode(cmd *exec.Cmd, err error) int {
|
|
|
|
if cmd == nil || cmd.ProcessState == nil {
|
|
|
|
return GetExitCode(err)
|
|
|
|
}
|
|
|
|
status, ok := cmd.ProcessState.Sys().(syscall.WaitStatus)
|
|
|
|
if !ok {
|
|
|
|
return cmd.ProcessState.ExitCode()
|
|
|
|
}
|
|
|
|
signaled := status.Signaled()
|
|
|
|
if signaled {
|
|
|
|
signal := status.Signal()
|
|
|
|
return 128 + int(signal)
|
|
|
|
}
|
|
|
|
exitStatus := status.ExitStatus()
|
|
|
|
return exitStatus
|
|
|
|
}
|
|
|
|
|
2022-06-16 01:29:39 +02:00
|
|
|
func GetExitCode(err error) int {
|
|
|
|
if err == nil {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
if exitErr, ok := err.(*exec.ExitError); ok {
|
|
|
|
return exitErr.ExitCode()
|
|
|
|
} else {
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-06 07:26:13 +01:00
|
|
|
func (c *ShExecType) ProcWait() error {
|
|
|
|
exitErr := c.Cmd.Wait()
|
|
|
|
c.Lock.Lock()
|
|
|
|
c.Exited = true
|
|
|
|
c.Lock.Unlock()
|
|
|
|
return exitErr
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *ShExecType) IsExited() bool {
|
|
|
|
c.Lock.Lock()
|
|
|
|
defer c.Lock.Unlock()
|
|
|
|
return c.Exited
|
|
|
|
}
|
|
|
|
|
2024-03-15 07:58:09 +01:00
|
|
|
// called in waveshell --single mode (returns the real cmddone packet)
|
2022-06-23 21:48:45 +02:00
|
|
|
func (c *ShExecType) WaitForCommand() *packet.CmdDonePacketType {
|
2022-10-22 23:45:31 +02:00
|
|
|
donePacket := packet.MakeCmdDonePacket(c.CK)
|
2022-12-06 07:26:13 +01:00
|
|
|
exitErr := c.ProcWait()
|
2022-10-22 23:45:31 +02:00
|
|
|
if c.ReturnState != nil {
|
2023-11-10 03:57:39 +01:00
|
|
|
// processing ReturnState *should* be fast. strange bug while running [[[ eval $(ssh-agent -s) ]]]
|
|
|
|
// where the process exits, but the ReturnState.Reader does not return EOF! Limit this to 2 seconds
|
|
|
|
go func() {
|
|
|
|
time.Sleep(ReturnStateReadWaitTime)
|
|
|
|
c.ReturnState.Reader.Close()
|
|
|
|
}()
|
2022-10-22 23:45:31 +02:00
|
|
|
<-c.ReturnState.DoneCh
|
2024-03-06 20:38:27 +01:00
|
|
|
if ForceDebugReturnState {
|
|
|
|
wlog.Logf("debug returnstate file %q\n", base.GetDebugReturnStateFileName())
|
|
|
|
os.WriteFile(base.GetDebugReturnStateFileName(), c.ReturnState.Buf, 0666)
|
|
|
|
}
|
2024-03-20 00:38:38 +01:00
|
|
|
state, _, _ := c.SAPI.ParseShellStateOutput(c.ReturnState.Buf) // TODO what to do with error?
|
2022-10-22 23:45:31 +02:00
|
|
|
donePacket.FinalState = state
|
|
|
|
}
|
2022-06-11 06:37:21 +02:00
|
|
|
endTs := time.Now()
|
|
|
|
cmdDuration := endTs.Sub(c.StartTs)
|
|
|
|
donePacket.Ts = endTs.UnixMilli()
|
2024-03-15 07:58:09 +01:00
|
|
|
donePacket.ExitCode = GetCmdExitCode(c.Cmd, exitErr)
|
2022-06-11 06:37:21 +02:00
|
|
|
donePacket.DurationMs = int64(cmdDuration / time.Millisecond)
|
2022-06-23 21:48:45 +02:00
|
|
|
if c.FileNames != nil {
|
|
|
|
os.Remove(c.FileNames.StdinFifo) // best effort (no need to check error)
|
|
|
|
}
|
2022-06-11 06:37:21 +02:00
|
|
|
return donePacket
|
2022-06-10 09:35:24 +02:00
|
|
|
}
|
2022-07-02 02:37:37 +02:00
|
|
|
|
|
|
|
func MakeInitPacket() *packet.InitPacketType {
|
|
|
|
initPacket := packet.MakeInitPacket()
|
|
|
|
initPacket.Version = base.MShellVersion
|
2023-04-13 06:45:45 +02:00
|
|
|
initPacket.BuildTime = base.BuildTime
|
2022-07-02 02:37:37 +02:00
|
|
|
initPacket.HomeDir = base.GetHomeDir()
|
|
|
|
initPacket.MShellHomeDir = base.GetMShellHomeDir()
|
|
|
|
if user, _ := user.Current(); user != nil {
|
|
|
|
initPacket.User = user.Username
|
|
|
|
}
|
2022-07-07 22:25:42 +02:00
|
|
|
initPacket.HostName, _ = os.Hostname()
|
2022-09-22 08:26:53 +02:00
|
|
|
initPacket.UName = fmt.Sprintf("%s|%s", runtime.GOOS, runtime.GOARCH)
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
initPacket.Shell = shellapi.DetectLocalShellType()
|
2022-07-02 02:37:37 +02:00
|
|
|
return initPacket
|
|
|
|
}
|
|
|
|
|
zsh support (#227)
adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature.
Commits:
* refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions
* checkpoint
* work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec)
* more refactoring
* create shellapi interface to abstract bash specific functionality
* more refactoring, move bash shell state parsing to shellapi
* move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell
* get shellType passed through to server/single paths for waveshell
* add a local shelltype detector
* mock out a zshapi
* move shelltype through more of the code
* get a command to run via zsh
* zsh can now switch directories. poc, needs cleanup
* working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv)
* switch to use []byte for vardecl serialization + diffs
* progress on zsh environment. still have issues reconciling init environment with trap environment
* fix typeset argument parsing
* parse promptvars, more zsh specific ignores
* fix bug with promptvar not getting set (wrong check in FeState func)
* add sdk (issue #188) to list of rtnstate commands
* more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base.
* must return a value
* zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1.
* force zmodload of zsh/parameter
* starting work on zsh functions
* need a v1 of mapdiff as well (to handle null chars)
* pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt
* reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values)
* fixes, working on functions, issue with line endings
* zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output.
* write uuid tempdir, cleanup with tmprcfilename code
* hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh
* make sure key order is constant so shell hashes are consistent
* fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash
* add log packet and new shellstate packets
* switch to shellstate map that's also keyed by shelltype
* add shelltype to remoteinstance
* remove shell argument from waveshell
* added new shelltype statemap to remote.go (msh), deal with fallout
* move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states
* change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells
* add shellpref field to remote table. use to drive the default shell choice for new tabs
* show shelltag on cmdinput, pass through ri and remote (defaultshellstate)
* bump mshell version to v0.4
* better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match)
* better error handling, check shellstate compatibility during run (on waveshell server)
* add extra separator for bash shellstate processing to deal with spurious output from rc files
* special migration for v30 -- flag invalid bash shell states and show special button in UI to fix
* format
* remove zsh-decls (unused)
* remove test code
* remove debug print
* fix typo
2024-01-17 01:11:04 +01:00
|
|
|
func MakeServerInitPacket() (*packet.InitPacketType, error) {
|
|
|
|
var err error
|
|
|
|
initPacket := MakeInitPacket()
|
2022-07-02 02:37:37 +02:00
|
|
|
initPacket.RemoteId, err = base.GetRemoteId()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return initPacket, nil
|
|
|
|
}
|
2022-08-23 00:59:03 +02:00
|
|
|
|
2022-08-23 02:27:55 +02:00
|
|
|
func ParseEnv0(env []byte) map[string]string {
|
2022-08-23 00:59:03 +02:00
|
|
|
envLines := bytes.Split(env, []byte{0})
|
|
|
|
rtn := make(map[string]string)
|
|
|
|
for _, envLine := range envLines {
|
|
|
|
if len(envLine) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
eqIdx := bytes.Index(envLine, []byte{'='})
|
|
|
|
if eqIdx == -1 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
varName := string(envLine[0:eqIdx])
|
|
|
|
varVal := string(envLine[eqIdx+1:])
|
|
|
|
rtn[varName] = varVal
|
|
|
|
}
|
|
|
|
return rtn
|
|
|
|
}
|
|
|
|
|
2022-08-23 02:27:55 +02:00
|
|
|
func MakeEnv0(envMap map[string]string) []byte {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
for envName, envVal := range envMap {
|
|
|
|
buf.WriteString(envName)
|
|
|
|
buf.WriteByte('=')
|
|
|
|
buf.WriteString(envVal)
|
|
|
|
buf.WriteByte(0)
|
|
|
|
}
|
|
|
|
return buf.Bytes()
|
|
|
|
}
|
|
|
|
|
2022-08-23 00:59:03 +02:00
|
|
|
func getStderr(err error) string {
|
|
|
|
exitErr, ok := err.(*exec.ExitError)
|
|
|
|
if !ok {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
if len(exitErr.Stderr) == 0 {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
lines := strings.SplitN(string(exitErr.Stderr), "\n", 2)
|
|
|
|
if len(lines[0]) > 100 {
|
|
|
|
return lines[0][0:100]
|
|
|
|
}
|
|
|
|
return lines[0]
|
|
|
|
}
|