diff --git a/pkg/cmdrunner/cmdrunner.go b/pkg/cmdrunner/cmdrunner.go index a7cc9b7cd..a56bca090 100644 --- a/pkg/cmdrunner/cmdrunner.go +++ b/pkg/cmdrunner/cmdrunner.go @@ -1197,8 +1197,8 @@ func crShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType, ids re baseDisplayName := msh.GetDisplayName() displayName := rptr.GetDisplayName(baseDisplayName) cwdStr := "-" - if ri.FeState.Cwd != "" { - cwdStr = ri.FeState.Cwd + if ri.FeState["cwd"] != "" { + cwdStr = ri.FeState["cwd"] } buf.WriteString(fmt.Sprintf("%-30s %-50s\n", displayName, cwdStr)) } @@ -1217,8 +1217,8 @@ func crShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType, ids re continue } cwdStr := "-" - if feState.Cwd != "" { - cwdStr = feState.Cwd + if feState["cwd"] != "" { + cwdStr = feState["cwd"] } buf.WriteString(fmt.Sprintf("%-30s %-50s (default)\n", msh.GetDisplayName(), cwdStr)) } @@ -1303,7 +1303,7 @@ func makeStaticCmd(ctx context.Context, metaCmd string, ids resolvedIds, cmdStr cmd.StatePtr = *ids.Remote.StatePtr } if ids.Remote.FeState != nil { - cmd.FeState = *ids.Remote.FeState + cmd.FeState = ids.Remote.FeState } err := sstore.CreateCmdPtyFile(ctx, cmd.ScreenId, cmd.CmdId, cmd.TermOpts.MaxPtySize) if err != nil { @@ -1455,7 +1455,7 @@ func doCompGen(ctx context.Context, pk *scpacket.FeCommandPacketType, prefix str cgPacket.ReqId = uuid.New().String() cgPacket.CompType = compType cgPacket.Prefix = prefix - cgPacket.Cwd = ids.Remote.FeState.Cwd + cgPacket.Cwd = ids.Remote.FeState["cwd"] resp, err := ids.Remote.MShell.PacketRpc(ctx, cgPacket) if err != nil { return nil, false, err @@ -1495,7 +1495,7 @@ func CompGenCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ssto rptr := ids.Remote.RemotePtr compCtx.RemotePtr = &rptr if ids.Remote.FeState != nil { - compCtx.Cwd = ids.Remote.FeState.Cwd + compCtx.Cwd = ids.Remote.FeState["cwd"] } } compCtx.ForDisplay = showComps @@ -1949,7 +1949,7 @@ func RemoteResetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) ( return nil, fmt.Errorf("invalid initpk received from remote (no remote state)") } feState := sstore.FeStateFromShellState(initPk.State) - remoteInst, err := sstore.UpdateRemoteState(ctx, ids.SessionId, ids.ScreenId, ids.Remote.RemotePtr, *feState, initPk.State, nil) + remoteInst, err := sstore.UpdateRemoteState(ctx, ids.SessionId, ids.ScreenId, ids.Remote.RemotePtr, feState, initPk.State, nil) if err != nil { return nil, err } @@ -2657,8 +2657,8 @@ func LineShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sst buf.WriteString(fmt.Sprintf(" %-15s %s\n", "cmdid", cmd.CmdId)) buf.WriteString(fmt.Sprintf(" %-15s %s\n", "remote", cmd.Remote.MakeFullRemoteRef())) buf.WriteString(fmt.Sprintf(" %-15s %s\n", "status", cmd.Status)) - if cmd.FeState.Cwd != "" { - buf.WriteString(fmt.Sprintf(" %-15s %s\n", "cwd", cmd.FeState.Cwd)) + if cmd.FeState["cwd"] != "" { + buf.WriteString(fmt.Sprintf(" %-15s %s\n", "cwd", cmd.FeState["cwd"])) } buf.WriteString(fmt.Sprintf(" %-15s %s\n", "termopts", formatTermOpts(cmd.TermOpts))) if cmd.TermOpts != cmd.OrigTermOpts { diff --git a/pkg/cmdrunner/resolver.go b/pkg/cmdrunner/resolver.go index cce62160b..ea83da113 100644 --- a/pkg/cmdrunner/resolver.go +++ b/pkg/cmdrunner/resolver.go @@ -34,7 +34,7 @@ type ResolvedRemote struct { RState remote.RemoteRuntimeState RemoteCopy *sstore.RemoteType StatePtr *sstore.ShellStatePtr - FeState *sstore.FeStateType + FeState map[string]string } type ResolveItem = sstore.ResolveItem @@ -481,7 +481,7 @@ func resolveRemoteFromPtr(ctx context.Context, rptr *sstore.RemotePtrType, sessi rtn.FeState = msh.GetDefaultFeState() } else { rtn.StatePtr = &sstore.ShellStatePtr{BaseHash: ri.StateBaseHash, DiffHashArr: ri.StateDiffHashArr} - rtn.FeState = &ri.FeState + rtn.FeState = ri.FeState } } } diff --git a/pkg/cmdrunner/shparse.go b/pkg/cmdrunner/shparse.go index fcd9c293c..4e6868af6 100644 --- a/pkg/cmdrunner/shparse.go +++ b/pkg/cmdrunner/shparse.go @@ -23,6 +23,7 @@ type BareMetaCmdDecl struct { var BareMetaCmds = []BareMetaCmdDecl{ BareMetaCmdDecl{"cr", "cr"}, + BareMetaCmdDecl{"connect", "cr"}, BareMetaCmdDecl{"clear", "clear"}, BareMetaCmdDecl{"reset", "reset"}, } @@ -155,6 +156,8 @@ func setBracketArgs(argMap map[string]string, bracketStr string) error { return nil } +var literalRtnStateCommands = []string{".", "source", "unset", "cd", "alias", "unalias", "deactivate"} + // detects: export, declare, ., source, X=1, unset func IsReturnStateCommand(cmdStr string) bool { cmdReader := strings.NewReader(cmdStr) @@ -171,7 +174,7 @@ func IsReturnStateCommand(cmdStr string) bool { if len(callExpr.Args) > 0 && len(callExpr.Args[0].Parts) > 0 { lit, ok := callExpr.Args[0].Parts[0].(*syntax.Lit) if ok { - if lit.Value == "." || lit.Value == "source" || lit.Value == "unset" || lit.Value == "cd" || lit.Value == "alias" || lit.Value == "unalias" { + if utilfn.ContainsStr(literalRtnStateCommands, lit.Value) { return true } } diff --git a/pkg/remote/remote.go b/pkg/remote/remote.go index 007ab4bb5..699f4e85b 100644 --- a/pkg/remote/remote.go +++ b/pkg/remote/remote.go @@ -132,7 +132,7 @@ type RemoteRuntimeState struct { RemoteAlias string `json:"remotealias,omitempty"` RemoteCanonicalName string `json:"remotecanonicalname"` RemoteVars map[string]string `json:"remotevars"` - DefaultFeState *sstore.FeStateType `json:"defaultfestate"` + DefaultFeState map[string]string `json:"defaultfestate"` Status string `json:"status"` ConnectTimeout int `json:"connecttimeout,omitempty"` ErrorStr string `json:"errorstr,omitempty"` @@ -177,7 +177,7 @@ func (msh *MShellProc) GetDefaultStatePtr() *sstore.ShellStatePtr { return &sstore.ShellStatePtr{BaseHash: msh.CurrentState} } -func (msh *MShellProc) GetDefaultFeState() *sstore.FeStateType { +func (msh *MShellProc) GetDefaultFeState() map[string]string { state := msh.GetDefaultState() return sstore.FeStateFromShellState(state) } @@ -1484,7 +1484,7 @@ func RunCommand(ctx context.Context, sessionId string, screenId string, remotePt CmdStr: runPacket.Command, RawCmdStr: runPacket.Command, Remote: remotePtr, - FeState: *sstore.FeStateFromShellState(currentState), + FeState: sstore.FeStateFromShellState(currentState), StatePtr: *statePtr, TermOpts: makeTermOpts(runPacket), Status: status, @@ -1652,7 +1652,7 @@ func (msh *MShellProc) handleCmdDonePacket(donePk *packet.CmdDonePacketType) { var statePtr *sstore.ShellStatePtr if donePk.FinalState != nil && rct != nil { feState := sstore.FeStateFromShellState(donePk.FinalState) - remoteInst, err := sstore.UpdateRemoteState(context.Background(), rct.SessionId, rct.ScreenId, rct.RemotePtr, *feState, donePk.FinalState, nil) + remoteInst, err := sstore.UpdateRemoteState(context.Background(), rct.SessionId, rct.ScreenId, rct.RemotePtr, feState, donePk.FinalState, nil) if err != nil { msh.WriteToPtyBuffer("*error trying to update remotestate: %v\n", err) // fall-through (nothing to do) @@ -1667,7 +1667,7 @@ func (msh *MShellProc) handleCmdDonePacket(donePk *packet.CmdDonePacketType) { msh.WriteToPtyBuffer("*error trying to update remotestate: %v\n", err) // fall-through (nothing to do) } else { - remoteInst, err := sstore.UpdateRemoteState(context.Background(), rct.SessionId, rct.ScreenId, rct.RemotePtr, *feState, nil, donePk.FinalStateDiff) + remoteInst, err := sstore.UpdateRemoteState(context.Background(), rct.SessionId, rct.ScreenId, rct.RemotePtr, feState, nil, donePk.FinalStateDiff) if err != nil { msh.WriteToPtyBuffer("*error trying to update remotestate: %v\n", err) // fall-through (nothing to do) @@ -1995,7 +1995,7 @@ func (msh *MShellProc) getFullState(stateDiff *packet.ShellStateDiff) (*packet.S } // internal func, first tries the StateMap, otherwise will fallback on sstore.GetFullState -func (msh *MShellProc) getFeStateFromDiff(stateDiff *packet.ShellStateDiff) (*sstore.FeStateType, error) { +func (msh *MShellProc) getFeStateFromDiff(stateDiff *packet.ShellStateDiff) (map[string]string, error) { baseState := msh.GetStateByHash(stateDiff.BaseHash) if baseState != nil && len(stateDiff.DiffHashArr) == 0 { newState, err := shexec.ApplyShellStateDiff(*baseState, *stateDiff) diff --git a/pkg/sstore/dbops.go b/pkg/sstore/dbops.go index 0748a310a..03b0e3b61 100644 --- a/pkg/sstore/dbops.go +++ b/pkg/sstore/dbops.go @@ -31,6 +31,8 @@ type SingleConnDBGetter struct { SingleConnLock *sync.Mutex } +type FeStateType map[string]string + type TxWrap = txwrap.TxWrap var dbWrap *SingleConnDBGetter diff --git a/pkg/sstore/sstore.go b/pkg/sstore/sstore.go index e3105f26d..d18ac79ee 100644 --- a/pkg/sstore/sstore.go +++ b/pkg/sstore/sstore.go @@ -22,6 +22,7 @@ import ( "github.com/sawka/txwrap" "github.com/scripthaus-dev/mshell/pkg/base" "github.com/scripthaus-dev/mshell/pkg/packet" + "github.com/scripthaus-dev/mshell/pkg/shexec" "github.com/scripthaus-dev/sh2-server/pkg/dbutil" "github.com/scripthaus-dev/sh2-server/pkg/scbase" @@ -563,15 +564,15 @@ func (ssptr *ShellStatePtr) IsEmpty() bool { } type RemoteInstance struct { - RIId string `json:"riid"` - Name string `json:"name"` - SessionId string `json:"sessionid"` - ScreenId string `json:"screenid"` - RemoteOwnerId string `json:"remoteownerid"` - RemoteId string `json:"remoteid"` - FeState FeStateType `json:"festate"` - StateBaseHash string `json:"-"` - StateDiffHashArr []string `json:"-"` + RIId string `json:"riid"` + Name string `json:"name"` + SessionId string `json:"sessionid"` + ScreenId string `json:"screenid"` + RemoteOwnerId string `json:"remoteownerid"` + RemoteId string `json:"remoteid"` + FeState map[string]string `json:"festate"` + StateBaseHash string `json:"-"` + StateDiffHashArr []string `json:"-"` // only for updates Remove bool `json:"remove,omitempty"` @@ -611,16 +612,22 @@ func (sd *StateDiff) ToMap() map[string]interface{} { return rtn } -type FeStateType struct { - Cwd string `json:"cwd"` - // maybe later we can add some vars -} - -func FeStateFromShellState(state *packet.ShellState) *FeStateType { +func FeStateFromShellState(state *packet.ShellState) map[string]string { if state == nil { return nil } - return &FeStateType{Cwd: state.Cwd} + rtn := make(map[string]string) + rtn["cwd"] = state.Cwd + envMap := shexec.EnvMapFromState(state) + if envMap["VIRTUAL_ENV"] != "" { + rtn["VIRTUAL_ENV"] = envMap["VIRTUAL_ENV"] + } + for key, val := range envMap { + if strings.HasPrefix(key, "PROMPTVAR_") { + rtn[key] = val + } + } + return rtn } func (ri *RemoteInstance) FromMap(m map[string]interface{}) bool { @@ -874,7 +881,7 @@ type CmdType struct { Remote RemotePtrType `json:"remote"` CmdStr string `json:"cmdstr"` RawCmdStr string `json:"rawcmdstr"` - FeState FeStateType `json:"festate"` + FeState map[string]string `json:"festate"` StatePtr ShellStatePtr `json:"state"` TermOpts TermOpts `json:"termopts"` OrigTermOpts TermOpts `json:"origtermopts"`