diff --git a/pkg/cmdrunner/cmdrunner.go b/pkg/cmdrunner/cmdrunner.go index 3f1d4b11b..551e82b5f 100644 --- a/pkg/cmdrunner/cmdrunner.go +++ b/pkg/cmdrunner/cmdrunner.go @@ -1,6 +1,7 @@ package cmdrunner import ( + "bytes" "context" "fmt" "path" @@ -71,6 +72,7 @@ var ValidCommands = []string{ "@cd", "@compgen", "@setenv", "@unset", + "@remote:show", } func HandleCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { @@ -105,6 +107,9 @@ func HandleCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstor case "unset": return UnSetCommand(ctx, pk) + case "remote": + return RemoteCommand(ctx, pk) + default: return nil, fmt.Errorf("invalid command '@%s', no handler", pk.MetaCmd) } @@ -502,6 +507,45 @@ func UnSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore return update, nil } +func RemoteCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { + if pk.MetaSubCmd == "show" { + ids, err := resolveIds(ctx, pk, R_Session|R_Window|R_Remote) + if err != nil { + return nil, err + } + curRemote := remote.GetRemoteById(ids.RemoteId) + if curRemote == nil { + return nil, fmt.Errorf("invalid remote [%s] (not found)", ids.RemoteName) + } + state := curRemote.GetRemoteState() + var buf bytes.Buffer + buf.WriteString(fmt.Sprintf(" %-15s %s\n", "type", state.RemoteType)) + buf.WriteString(fmt.Sprintf(" %-15s %s\n", "remoteid", state.RemoteId)) + buf.WriteString(fmt.Sprintf(" %-15s %s\n", "physicalid", state.PhysicalId)) + buf.WriteString(fmt.Sprintf(" %-15s %s\n", "alias", state.RemoteAlias)) + buf.WriteString(fmt.Sprintf(" %-15s %s\n", "canonicalname", state.RemoteCanonicalName)) + buf.WriteString(fmt.Sprintf(" %-15s %s\n", "status", state.Status)) + buf.WriteString(fmt.Sprintf(" %-15s %s\n", "connectmode", state.ConnectMode)) + if ids.RemoteState != nil { + buf.WriteString(fmt.Sprintf(" %-15s %s\n", "cwd", ids.RemoteState.Cwd)) + } + output := buf.String() + if strings.HasSuffix(output, "\n") { + output = output[0 : len(output)-1] + } + return sstore.InfoUpdate{ + Info: &sstore.InfoMsgType{ + InfoTitle: fmt.Sprintf("show remote '%s' info", ids.RemoteName), + InfoLines: strings.Split(output, "\n"), + }, + }, nil + } + if pk.MetaSubCmd != "" { + return nil, fmt.Errorf("invalid @remote subcommand: '%s'", pk.MetaSubCmd) + } + return nil, fmt.Errorf("@remote requires a subcommand: 'show'") +} + func makeSetVarsStr(setVars map[string]bool) string { varArr := make([]string, 0, len(setVars)) for varName, _ := range setVars { @@ -537,7 +581,7 @@ func SetEnvCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstor } update := sstore.InfoUpdate{ Info: &sstore.InfoMsgType{ - InfoTitle: fmt.Sprintf("[%s] environment", ids.RemoteName), + InfoTitle: fmt.Sprintf("environment for [%s] remote", ids.RemoteName), InfoLines: infoLines, }, } diff --git a/pkg/remote/remote.go b/pkg/remote/remote.go index 745dbfee8..a84c068cc 100644 --- a/pkg/remote/remote.go +++ b/pkg/remote/remote.go @@ -151,49 +151,56 @@ func unquoteDQBashString(str string) (string, bool) { return string(rtn), true } +func (proc *MShellProc) GetRemoteState() RemoteState { + proc.Lock.Lock() + defer proc.Lock.Unlock() + state := RemoteState{ + RemoteType: proc.Remote.RemoteType, + RemoteId: proc.Remote.RemoteId, + RemoteAlias: proc.Remote.RemoteAlias, + RemoteCanonicalName: proc.Remote.RemoteCanonicalName, + PhysicalId: proc.Remote.PhysicalId, + Status: proc.Status, + ConnectMode: proc.Remote.ConnectMode, + } + if proc.Err != nil { + state.ErrorStr = proc.Err.Error() + } + vars := make(map[string]string) + vars["user"] = proc.Remote.RemoteUser + vars["host"] = proc.Remote.RemoteHost + if proc.Remote.RemoteSudo { + vars["sudo"] = "1" + } + vars["alias"] = proc.Remote.RemoteAlias + vars["cname"] = proc.Remote.RemoteCanonicalName + vars["physicalid"] = proc.Remote.PhysicalId + vars["remoteid"] = proc.Remote.RemoteId + vars["status"] = proc.Status + vars["type"] = proc.Remote.RemoteType + if proc.ServerProc != nil && proc.ServerProc.InitPk != nil { + state.DefaultState = &sstore.RemoteState{ + Cwd: proc.ServerProc.InitPk.Cwd, + Env0: proc.ServerProc.InitPk.Env0, + } + vars["home"] = proc.ServerProc.InitPk.HomeDir + vars["remoteuser"] = proc.ServerProc.InitPk.User + vars["remotehost"] = proc.ServerProc.InitPk.HostName + if proc.Remote.SSHOpts == nil || proc.Remote.SSHOpts.SSHHost == "" { + vars["local"] = "1" + } + } + state.RemoteVars = vars + return state +} + func GetAllRemoteState() []RemoteState { GlobalStore.Lock.Lock() defer GlobalStore.Lock.Unlock() var rtn []RemoteState for _, proc := range GlobalStore.Map { - state := RemoteState{ - RemoteType: proc.Remote.RemoteType, - RemoteId: proc.Remote.RemoteId, - RemoteAlias: proc.Remote.RemoteAlias, - RemoteCanonicalName: proc.Remote.RemoteCanonicalName, - PhysicalId: proc.Remote.PhysicalId, - Status: proc.Status, - ConnectMode: proc.Remote.ConnectMode, - } - if proc.Err != nil { - state.ErrorStr = proc.Err.Error() - } - vars := make(map[string]string) - vars["user"] = proc.Remote.RemoteUser - vars["host"] = proc.Remote.RemoteHost - if proc.Remote.RemoteSudo { - vars["sudo"] = "1" - } - vars["alias"] = proc.Remote.RemoteAlias - vars["cname"] = proc.Remote.RemoteCanonicalName - vars["physicalid"] = proc.Remote.PhysicalId - vars["remoteid"] = proc.Remote.RemoteId - vars["status"] = proc.Status - vars["type"] = proc.Remote.RemoteType - if proc.ServerProc != nil && proc.ServerProc.InitPk != nil { - state.DefaultState = &sstore.RemoteState{ - Cwd: proc.ServerProc.InitPk.Cwd, - Env0: proc.ServerProc.InitPk.Env0, - } - vars["home"] = proc.ServerProc.InitPk.HomeDir - vars["remoteuser"] = proc.ServerProc.InitPk.User - vars["remotehost"] = proc.ServerProc.InitPk.HostName - if proc.Remote.SSHOpts == nil || proc.Remote.SSHOpts.SSHHost == "" { - vars["local"] = "1" - } - } - state.RemoteVars = vars + state := proc.GetRemoteState() rtn = append(rtn, state) } return rtn