big update to handle cmd returnstate (still need to process new state with donepacket)

This commit is contained in:
sawka
2022-10-27 00:33:50 -07:00
parent d50ed6ca6c
commit 0060c8ffc2
7 changed files with 148 additions and 171 deletions
+31
View File
@@ -182,6 +182,36 @@ func HandleGetWindow(w http.ResponseWriter, r *http.Request) {
return return
} }
func HandleRtnState(w http.ResponseWriter, r *http.Request) {
qvals := r.URL.Query()
sessionId := qvals.Get("sessionid")
cmdId := qvals.Get("cmdid")
if sessionId == "" || cmdId == "" {
w.WriteHeader(500)
w.Write([]byte(fmt.Sprintf("must specify sessionid and cmdid")))
return
}
if _, err := uuid.Parse(sessionId); err != nil {
w.WriteHeader(500)
w.Write([]byte(fmt.Sprintf("invalid sessionid: %v", err)))
return
}
if _, err := uuid.Parse(cmdId); err != nil {
w.WriteHeader(500)
w.Write([]byte(fmt.Sprintf("invalid cmdid: %v", err)))
return
}
data, err := cmdrunner.GetRtnStateDiff(r.Context(), sessionId, cmdId)
if err != nil {
w.WriteHeader(500)
w.Write([]byte(fmt.Sprintf("cannot get rtnstate diff: %v", err)))
return
}
w.WriteHeader(http.StatusOK)
w.Write(data)
return
}
func HandleRemotePty(w http.ResponseWriter, r *http.Request) { func HandleRemotePty(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin")) w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin"))
w.Header().Set("Access-Control-Allow-Credentials", "true") w.Header().Set("Access-Control-Allow-Credentials", "true")
@@ -393,6 +423,7 @@ func main() {
gr := mux.NewRouter() gr := mux.NewRouter()
gr.HandleFunc("/api/ptyout", HandleGetPtyOut) gr.HandleFunc("/api/ptyout", HandleGetPtyOut)
gr.HandleFunc("/api/remote-pty", HandleRemotePty) gr.HandleFunc("/api/remote-pty", HandleRemotePty)
gr.HandleFunc("/api/rtnstate", HandleRtnState)
gr.HandleFunc("/api/get-window", HandleGetWindow) gr.HandleFunc("/api/get-window", HandleGetWindow)
gr.HandleFunc("/api/run-command", HandleRunCommand).Methods("GET", "POST", "OPTIONS") gr.HandleFunc("/api/run-command", HandleRunCommand).Methods("GET", "POST", "OPTIONS")
gr.HandleFunc("/api/get-client-data", HandleGetClientData) gr.HandleFunc("/api/get-client-data", HandleGetClientData)
+2 -1
View File
@@ -79,6 +79,7 @@ CREATE TABLE line (
text text NOT NULL, text text NOT NULL,
cmdid varchar(36) NOT NULL, cmdid varchar(36) NOT NULL,
ephemeral boolean NOT NULL, ephemeral boolean NOT NULL,
contentheight int NOT NULL,
PRIMARY KEY (sessionid, windowid, lineid) PRIMARY KEY (sessionid, windowid, lineid)
); );
@@ -116,7 +117,7 @@ CREATE TABLE cmd (
startpk json NOT NULL, startpk json NOT NULL,
donepk json NOT NULL, donepk json NOT NULL,
runout json NOT NULL, runout json NOT NULL,
usedrows int NOT NULL, rtnstate bool NOT NULL,
PRIMARY KEY (sessionid, cmdid) PRIMARY KEY (sessionid, cmdid)
); );
+33 -133
View File
@@ -39,7 +39,7 @@ var ColorNames = []string{"black", "red", "green", "yellow", "blue", "magenta",
var RemoteColorNames = []string{"red", "green", "yellow", "blue", "magenta", "cyan", "white", "orange"} var RemoteColorNames = []string{"red", "green", "yellow", "blue", "magenta", "cyan", "white", "orange"}
var RemoteSetArgs = []string{"alias", "connectmode", "key", "password", "autoinstall", "color"} var RemoteSetArgs = []string{"alias", "connectmode", "key", "password", "autoinstall", "color"}
var WindowCmds = []string{"run", "comment", "cd", "cr", "setenv", "unset", "clear", "sw", "alias", "unalias", "function", "source", "reset"} var WindowCmds = []string{"run", "comment", "cd", "cr", "clear", "sw", "alias", "unalias", "function", "reset"}
var NoHistCmds = []string{"compgen", "line", "history"} var NoHistCmds = []string{"compgen", "line", "history"}
var GlobalCmds = []string{"session", "screen", "remote"} var GlobalCmds = []string{"session", "screen", "remote"}
@@ -72,11 +72,9 @@ func init() {
registerCmdFn("run", RunCommand) registerCmdFn("run", RunCommand)
registerCmdFn("eval", EvalCommand) registerCmdFn("eval", EvalCommand)
registerCmdFn("comment", CommentCommand) registerCmdFn("comment", CommentCommand)
registerCmdFn("cd", CdCommand) // registerCmdFn("cd", CdCommand)
registerCmdFn("cr", CrCommand) registerCmdFn("cr", CrCommand)
registerCmdFn("compgen", CompGenCommand) registerCmdFn("compgen", CompGenCommand)
registerCmdFn("setenv", SetEnvCommand)
registerCmdFn("unset", UnSetCommand)
registerCmdFn("clear", ClearCommand) registerCmdFn("clear", ClearCommand)
registerCmdFn("reset", ResetCommand) registerCmdFn("reset", ResetCommand)
@@ -114,8 +112,6 @@ func init() {
registerCmdFn("line:show", LineShowCommand) registerCmdFn("line:show", LineShowCommand)
registerCmdFn("history", HistoryCommand) registerCmdFn("history", HistoryCommand)
registerCmdFn("source", SourceCommand)
} }
func getValidCommands() []string { func getValidCommands() []string {
@@ -239,40 +235,6 @@ func getUITermOpts(uiContext *scpacket.UIContextType) *packet.TermOpts {
return termOpts return termOpts
} }
func SourceCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_Window|R_RemoteConnected)
if err != nil {
return nil, fmt.Errorf("/source error: %w", err)
}
if len(pk.Args) != 1 {
return nil, fmt.Errorf("/source takes one argument (the file to source)")
}
cmdId := scbase.GenSCUUID()
runPacket := packet.MakeRunPacket()
runPacket.ReqId = uuid.New().String()
runPacket.CK = base.MakeCommandKey(ids.SessionId, cmdId)
runPacket.State = ids.Remote.RemoteState
runPacket.StateComplete = true
runPacket.UsePty = true
runPacket.TermOpts = getUITermOpts(pk.UIContext)
runPacket.Command = strings.TrimSpace(fmt.Sprintf("source %s", shellescape.Quote(pk.Args[0])))
runPacket.ReturnState = true
cmd, callback, err := remote.RunCommand(ctx, cmdId, ids.Remote.RemotePtr, ids.Remote.RemoteState, runPacket)
if callback != nil {
defer callback()
}
if err != nil {
return nil, err
}
update, err := addLineForCmd(ctx, "/source", true, ids, cmd)
if err != nil {
return nil, err
}
update.Interactive = pk.Interactive
sstore.MainBus.SendUpdate(ids.SessionId, update)
return nil, nil
}
func RunCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { func RunCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_Window|R_RemoteConnected) ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_Window|R_RemoteConnected)
if err != nil { if err != nil {
@@ -280,6 +242,7 @@ func RunCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.U
} }
cmdId := scbase.GenSCUUID() cmdId := scbase.GenSCUUID()
cmdStr := firstArg(pk) cmdStr := firstArg(pk)
isRtnStateCmd := IsReturnStateCommand(cmdStr)
runPacket := packet.MakeRunPacket() runPacket := packet.MakeRunPacket()
runPacket.ReqId = uuid.New().String() runPacket.ReqId = uuid.New().String()
runPacket.CK = base.MakeCommandKey(ids.SessionId, cmdId) runPacket.CK = base.MakeCommandKey(ids.SessionId, cmdId)
@@ -288,6 +251,7 @@ func RunCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.U
runPacket.UsePty = true runPacket.UsePty = true
runPacket.TermOpts = getUITermOpts(pk.UIContext) runPacket.TermOpts = getUITermOpts(pk.UIContext)
runPacket.Command = strings.TrimSpace(cmdStr) runPacket.Command = strings.TrimSpace(cmdStr)
runPacket.ReturnState = resolveBool(pk.Kwargs["rtnstate"], isRtnStateCmd)
cmd, callback, err := remote.RunCommand(ctx, cmdId, ids.Remote.RemotePtr, ids.Remote.RemoteState, runPacket) cmd, callback, err := remote.RunCommand(ctx, cmdId, ids.Remote.RemotePtr, ids.Remote.RemoteState, runPacket)
if callback != nil { if callback != nil {
defer callback() defer callback()
@@ -522,43 +486,6 @@ func SwSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore
return sstore.ModelUpdate{ScreenWindows: []*sstore.ScreenWindowType{sw}}, nil return sstore.ModelUpdate{ScreenWindows: []*sstore.ScreenWindowType{sw}}, nil
} }
func UnSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
ids, err := resolveUiIds(ctx, pk, R_Session|R_Window|R_RemoteConnected)
if err != nil {
return nil, fmt.Errorf("cannot unset: %v", err)
}
declMap := shexec.DeclMapFromState(ids.Remote.RemoteState)
unsetVars := make(map[string]bool)
for _, argStr := range pk.Args {
eqIdx := strings.Index(argStr, "=")
if eqIdx != -1 {
return nil, fmt.Errorf("invalid argument to setenv, '%s' (cannot contain equal sign)", argStr)
}
delete(declMap, argStr)
unsetVars[argStr] = true
}
if len(unsetVars) == 0 {
return nil, fmt.Errorf("no variables provided to unset")
}
state := *ids.Remote.RemoteState
state.ShellVars = shexec.SerializeDeclMap(declMap)
remoteInst, err := sstore.UpdateRemoteState(ctx, ids.SessionId, ids.WindowId, ids.Remote.RemotePtr, state)
if err != nil {
return nil, err
}
var cmdOutput bytes.Buffer
displayStateUpdate(&cmdOutput, *ids.Remote.RemoteState, remoteInst.State)
cmd, err := makeStaticCmd(ctx, "unset", ids, pk.GetRawStr(), cmdOutput.Bytes())
update, err := addLineForCmd(ctx, "/unset", false, ids, cmd)
if err != nil {
// TODO tricky error since the command was a success, but we can't show the output
return nil, err
}
update.Interactive = pk.Interactive
update.Sessions = sstore.MakeSessionsUpdateForRemote(ids.SessionId, remoteInst)
return update, nil
}
func RemoteInstallCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { func RemoteInstallCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
ids, err := resolveUiIds(ctx, pk, R_Session|R_Window|R_Remote) ids, err := resolveUiIds(ctx, pk, R_Session|R_Window|R_Remote)
if err != nil { if err != nil {
@@ -939,56 +866,6 @@ func RemoteCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstor
return nil, fmt.Errorf("/remote requires a subcommand: %s", formatStrs([]string{"show"}, "or", false)) return nil, fmt.Errorf("/remote requires a subcommand: %s", formatStrs([]string{"show"}, "or", false))
} }
func SetEnvCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
ids, err := resolveUiIds(ctx, pk, R_Session|R_Window|R_RemoteConnected)
if err != nil {
return nil, fmt.Errorf("cannot setenv: %v", err)
}
declMap := shexec.DeclMapFromState(ids.Remote.RemoteState)
if len(pk.Args) == 0 {
var infoLines []string
for _, decl := range declMap {
line := fmt.Sprintf("%s=%s", decl.Name, shellescape.Quote(decl.Value))
infoLines = append(infoLines, line)
}
update := sstore.ModelUpdate{
Info: &sstore.InfoMsgType{
InfoTitle: fmt.Sprintf("environment for remote [%s]", ids.Remote.DisplayName),
InfoLines: infoLines,
},
}
return update, nil
}
setVars := make(map[string]bool)
for _, argStr := range pk.Args {
eqIdx := strings.Index(argStr, "=")
if eqIdx == -1 {
return nil, fmt.Errorf("invalid argument to setenv, '%s' (no equal sign)", argStr)
}
envName := argStr[:eqIdx]
envVal := argStr[eqIdx+1:]
declMap[envName] = &shexec.DeclareDeclType{Args: "x", Name: envName, Value: envVal}
setVars[envName] = true
}
state := *ids.Remote.RemoteState
state.ShellVars = shexec.SerializeDeclMap(declMap)
remoteInst, err := sstore.UpdateRemoteState(ctx, ids.SessionId, ids.WindowId, ids.Remote.RemotePtr, state)
if err != nil {
return nil, err
}
var cmdOutput bytes.Buffer
displayStateUpdate(&cmdOutput, *ids.Remote.RemoteState, remoteInst.State)
cmd, err := makeStaticCmd(ctx, "setenv", ids, pk.GetRawStr(), cmdOutput.Bytes())
update, err := addLineForCmd(ctx, "/setenv", false, ids, cmd)
if err != nil {
// TODO tricky error since the command was a success, but we can't show the output
return nil, err
}
update.Interactive = pk.Interactive
update.Sessions = sstore.MakeSessionsUpdateForRemote(ids.SessionId, remoteInst)
return update, nil
}
func CrCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { func CrCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
ids, err := resolveUiIds(ctx, pk, R_Session|R_Window) ids, err := resolveUiIds(ctx, pk, R_Session|R_Window)
if err != nil { if err != nil {
@@ -1814,21 +1691,25 @@ func formatTextTable(totalCols int, data [][]string, colMeta []ColMeta) []string
func displayStateUpdate(buf *bytes.Buffer, oldState packet.ShellState, newState packet.ShellState) { func displayStateUpdate(buf *bytes.Buffer, oldState packet.ShellState, newState packet.ShellState) {
if newState.Cwd != oldState.Cwd { if newState.Cwd != oldState.Cwd {
buf.WriteString(fmt.Sprintf("cwd %s\r\n", newState.Cwd)) buf.WriteString(fmt.Sprintf("cwd %s\n", newState.Cwd))
} }
if !bytes.Equal(newState.ShellVars, oldState.ShellVars) { if !bytes.Equal(newState.ShellVars, oldState.ShellVars) {
newEnvMap := shexec.DeclMapFromState(&newState) newEnvMap := shexec.DeclMapFromState(&newState)
oldEnvMap := shexec.DeclMapFromState(&oldState) oldEnvMap := shexec.DeclMapFromState(&oldState)
for key, newVal := range newEnvMap { for key, newVal := range newEnvMap {
oldVal, found := oldEnvMap[key] oldVal, found := oldEnvMap[key]
if !found || oldVal.Value != newVal.Value { if !found || ((oldVal.Value != newVal.Value) || (oldVal.IsExport() != newVal.IsExport())) {
buf.WriteString(fmt.Sprintf("%s=%s\r\n", key, shellescape.Quote(newVal.Value))) var exportStr string
if newVal.IsExport() {
exportStr = "export "
}
buf.WriteString(fmt.Sprintf("%s%s=%s\n", exportStr, key, ShellQuote(newVal.Value, false, 50)))
} }
} }
for key, _ := range oldEnvMap { for key, _ := range oldEnvMap {
_, found := newEnvMap[key] _, found := newEnvMap[key]
if !found { if !found {
buf.WriteString(fmt.Sprintf("unset %s\r\n", key)) buf.WriteString(fmt.Sprintf("unset %s\n", key))
} }
} }
} }
@@ -1844,7 +1725,7 @@ func displayStateUpdate(buf *bytes.Buffer, oldState packet.ShellState, newState
for aliasName, _ := range oldAliasMap { for aliasName, _ := range oldAliasMap {
_, found := newAliasMap[aliasName] _, found := newAliasMap[aliasName]
if !found { if !found {
buf.WriteString(fmt.Sprintf("unalias %s\r\n", shellescape.Quote(aliasName))) buf.WriteString(fmt.Sprintf("unalias %s\n", shellescape.Quote(aliasName)))
} }
} }
} }
@@ -1860,8 +1741,27 @@ func displayStateUpdate(buf *bytes.Buffer, oldState packet.ShellState, newState
for funcName, _ := range oldFuncMap { for funcName, _ := range oldFuncMap {
_, found := newFuncMap[funcName] _, found := newFuncMap[funcName]
if !found { if !found {
buf.WriteString(fmt.Sprintf("unset -f %s\r\n", shellescape.Quote(funcName))) buf.WriteString(fmt.Sprintf("unset -f %s\n", shellescape.Quote(funcName)))
} }
} }
} }
} }
func GetRtnStateDiff(ctx context.Context, sessionId string, cmdId string) ([]byte, error) {
cmd, err := sstore.GetCmdById(ctx, sessionId, cmdId)
if err != nil {
return nil, err
}
if cmd == nil {
return nil, nil
}
if !cmd.RtnState {
return nil, nil
}
if cmd.DonePk == nil || cmd.DonePk.FinalState == nil {
return nil, nil
}
var outputBytes bytes.Buffer
displayStateUpdate(&outputBytes, cmd.RemoteState, *cmd.DonePk.FinalState)
return outputBytes.Bytes(), nil
}
+53 -13
View File
@@ -59,14 +59,8 @@ type BareMetaCmdDecl struct {
} }
var BareMetaCmds = []BareMetaCmdDecl{ var BareMetaCmds = []BareMetaCmdDecl{
BareMetaCmdDecl{"cd", "cd"},
BareMetaCmdDecl{"cr", "cr"}, BareMetaCmdDecl{"cr", "cr"},
BareMetaCmdDecl{"setenv", "setenv"},
BareMetaCmdDecl{"export", "setenv"},
BareMetaCmdDecl{"unset", "unset"},
BareMetaCmdDecl{"clear", "clear"}, BareMetaCmdDecl{"clear", "clear"},
BareMetaCmdDecl{".", "source"},
BareMetaCmdDecl{"source", "source"},
BareMetaCmdDecl{"reset", "reset"}, BareMetaCmdDecl{"reset", "reset"},
} }
@@ -123,7 +117,7 @@ func onlyRawArgs(metaCmd string, metaSubCmd string) bool {
} }
// minimum maxlen=6 // minimum maxlen=6
func ForceQuote(val string, maxLen int) string { func ShellQuote(val string, forceQuote bool, maxLen int) string {
if maxLen < 6 { if maxLen < 6 {
maxLen = 6 maxLen = 6
} }
@@ -134,10 +128,17 @@ func ForceQuote(val string, maxLen int) string {
} }
return rtn return rtn
} }
if len(rtn) > maxLen-2 { if forceQuote {
return "\"" + rtn[0:maxLen-5] + "...\"" if len(rtn) > maxLen-2 {
return "\"" + rtn[0:maxLen-5] + "...\""
}
return "\"" + rtn + "\""
} else {
if len(rtn) > maxLen {
return rtn[0:maxLen-3] + "..."
}
return rtn
} }
return "\"" + rtn + "\""
} }
func setBracketArgs(argMap map[string]string, bracketStr string) error { func setBracketArgs(argMap map[string]string, bracketStr string) error {
@@ -163,7 +164,7 @@ func setBracketArgs(argMap map[string]string, bracketStr string) error {
varVal = litStr[eqIdx+1:] varVal = litStr[eqIdx+1:]
} }
if !shexec.IsValidBashIdentifier(varName) { if !shexec.IsValidBashIdentifier(varName) {
wordErr = fmt.Errorf("invalid identifier %s in bracket args", ForceQuote(varName, 20)) wordErr = fmt.Errorf("invalid identifier %s in bracket args", ShellQuote(varName, true, 20))
return false return false
} }
if varVal == "" { if varVal == "" {
@@ -181,6 +182,35 @@ func setBracketArgs(argMap map[string]string, bracketStr string) error {
return nil return nil
} }
// detects: export, declare, ., source, X=1, unset
func IsReturnStateCommand(cmdStr string) bool {
cmdReader := strings.NewReader(cmdStr)
parser := syntax.NewParser(syntax.Variant(syntax.LangBash))
file, err := parser.Parse(cmdReader, "cmd")
if err != nil {
return false
}
for _, stmt := range file.Stmts {
if callExpr, ok := stmt.Cmd.(*syntax.CallExpr); ok {
if len(callExpr.Assigns) > 0 && len(callExpr.Args) == 0 {
return true
}
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" {
return true
}
}
}
} else if _, ok := stmt.Cmd.(*syntax.DeclClause); ok {
return true
}
}
return false
}
func EvalBracketArgs(origCmdStr string) (map[string]string, string, error) { func EvalBracketArgs(origCmdStr string) (map[string]string, string, error) {
rtn := make(map[string]string) rtn := make(map[string]string)
if strings.HasPrefix(origCmdStr, " ") { if strings.HasPrefix(origCmdStr, " ") {
@@ -210,7 +240,11 @@ func EvalMetaCommand(ctx context.Context, origPk *scpacket.FeCommandPacketType)
if strings.TrimSpace(origPk.Args[0]) == "" { if strings.TrimSpace(origPk.Args[0]) == "" {
return nil, fmt.Errorf("empty command") return nil, fmt.Errorf("empty command")
} }
metaCmd, metaSubCmd, commandArgs := parseMetaCmd(origPk.Args[0]) bracketArgs, cmdStr, err := EvalBracketArgs(origPk.Args[0])
if err != nil {
return nil, err
}
metaCmd, metaSubCmd, commandArgs := parseMetaCmd(cmdStr)
rtnPk := scpacket.MakeFeCommandPacket() rtnPk := scpacket.MakeFeCommandPacket()
rtnPk.MetaCmd = metaCmd rtnPk.MetaCmd = metaCmd
rtnPk.MetaSubCmd = metaSubCmd rtnPk.MetaSubCmd = metaSubCmd
@@ -220,6 +254,9 @@ func EvalMetaCommand(ctx context.Context, origPk *scpacket.FeCommandPacketType)
for key, val := range origPk.Kwargs { for key, val := range origPk.Kwargs {
rtnPk.Kwargs[key] = val rtnPk.Kwargs[key] = val
} }
for key, val := range bracketArgs {
rtnPk.Kwargs[key] = val
}
if onlyRawArgs(metaCmd, metaSubCmd) { if onlyRawArgs(metaCmd, metaSubCmd) {
// don't evaluate arguments for /run or /comment // don't evaluate arguments for /run or /comment
rtnPk.Args = []string{commandArgs} rtnPk.Args = []string{commandArgs}
@@ -228,7 +265,7 @@ func EvalMetaCommand(ctx context.Context, origPk *scpacket.FeCommandPacketType)
commandReader := strings.NewReader(commandArgs) commandReader := strings.NewReader(commandArgs)
parser := syntax.NewParser(syntax.Variant(syntax.LangBash)) parser := syntax.NewParser(syntax.Variant(syntax.LangBash))
var words []*syntax.Word var words []*syntax.Word
err := parser.Words(commandReader, func(w *syntax.Word) bool { err = parser.Words(commandReader, func(w *syntax.Word) bool {
words = append(words, w) words = append(words, w)
return true return true
}) })
@@ -338,6 +375,9 @@ func ParseFuncs(funcs string) (map[string]string, error) {
fmt.Printf("stmt-err: %v\n", err) fmt.Printf("stmt-err: %v\n", err)
continue continue
} }
if strings.HasPrefix(funcName, "_scripthaus_") {
continue
}
if funcName != "" { if funcName != "" {
rtn[funcName] = funcVal rtn[funcName] = funcVal
} }
+1
View File
@@ -1106,6 +1106,7 @@ func RunCommand(ctx context.Context, cmdId string, remotePtr sstore.RemotePtrTyp
StartPk: startPk, StartPk: startPk,
DonePk: nil, DonePk: nil,
RunOut: nil, RunOut: nil,
RtnState: runPacket.ReturnState,
} }
err = sstore.CreateCmdPtyFile(ctx, cmd.SessionId, cmd.CmdId, cmd.TermOpts.MaxPtySize) err = sstore.CreateCmdPtyFile(ctx, cmd.SessionId, cmd.CmdId, cmd.TermOpts.MaxPtySize)
if err != nil { if err != nil {
+4 -4
View File
@@ -623,8 +623,8 @@ func InsertLine(ctx context.Context, line *LineType, cmd *CmdType) error {
query = `SELECT nextlinenum FROM window WHERE sessionid = ? AND windowid = ?` query = `SELECT nextlinenum FROM window WHERE sessionid = ? AND windowid = ?`
nextLineNum := tx.GetInt(query, line.SessionId, line.WindowId) nextLineNum := tx.GetInt(query, line.SessionId, line.WindowId)
line.LineNum = int64(nextLineNum) line.LineNum = int64(nextLineNum)
query = `INSERT INTO line ( sessionid, windowid, userid, lineid, ts, linenum, linenumtemp, linelocal, linetype, text, cmdid, ephemeral) query = `INSERT INTO line ( sessionid, windowid, userid, lineid, ts, linenum, linenumtemp, linelocal, linetype, text, cmdid, ephemeral, contentheight)
VALUES (:sessionid,:windowid,:userid,:lineid,:ts,:linenum,:linenumtemp,:linelocal,:linetype,:text,:cmdid,:ephemeral)` VALUES (:sessionid,:windowid,:userid,:lineid,:ts,:linenum,:linenumtemp,:linelocal,:linetype,:text,:cmdid,:ephemeral,:contentheight)`
tx.NamedExecWrap(query, line) tx.NamedExecWrap(query, line)
query = `UPDATE window SET nextlinenum = ? WHERE sessionid = ? AND windowid = ?` query = `UPDATE window SET nextlinenum = ? WHERE sessionid = ? AND windowid = ?`
tx.ExecWrap(query, nextLineNum+1, line.SessionId, line.WindowId) tx.ExecWrap(query, nextLineNum+1, line.SessionId, line.WindowId)
@@ -632,8 +632,8 @@ func InsertLine(ctx context.Context, line *LineType, cmd *CmdType) error {
cmd.OrigTermOpts = cmd.TermOpts cmd.OrigTermOpts = cmd.TermOpts
cmdMap := cmd.ToMap() cmdMap := cmd.ToMap()
query = ` query = `
INSERT INTO cmd ( sessionid, cmdid, remoteownerid, remoteid, remotename, cmdstr, remotestate, termopts, origtermopts, status, startpk, donepk, runout, usedrows) INSERT INTO cmd ( sessionid, cmdid, remoteownerid, remoteid, remotename, cmdstr, remotestate, termopts, origtermopts, status, startpk, donepk, rtnstate, runout)
VALUES (:sessionid,:cmdid,:remoteownerid,:remoteid,:remotename,:cmdstr,:remotestate,:termopts,:origtermopts,:status,:startpk,:donepk,:runout,:usedrows) VALUES (:sessionid,:cmdid,:remoteownerid,:remoteid,:remotename,:cmdstr,:remotestate,:termopts,:origtermopts,:status,:startpk,:donepk,:rtnstate,:runout)
` `
tx.NamedExecWrap(query, cmdMap) tx.NamedExecWrap(query, cmdMap)
} }
+24 -20
View File
@@ -28,6 +28,7 @@ import (
const LineTypeCmd = "cmd" const LineTypeCmd = "cmd"
const LineTypeText = "text" const LineTypeText = "text"
const LineNoHeight = -1
const DBFileName = "sh2.db" const DBFileName = "sh2.db"
const DefaultSessionName = "default" const DefaultSessionName = "default"
@@ -496,19 +497,20 @@ func RIFromMap(m map[string]interface{}) *RemoteInstance {
} }
type LineType struct { type LineType struct {
SessionId string `json:"sessionid"` SessionId string `json:"sessionid"`
WindowId string `json:"windowid"` WindowId string `json:"windowid"`
UserId string `json:"userid"` UserId string `json:"userid"`
LineId string `json:"lineid"` LineId string `json:"lineid"`
Ts int64 `json:"ts"` Ts int64 `json:"ts"`
LineNum int64 `json:"linenum"` LineNum int64 `json:"linenum"`
LineNumTemp bool `json:"linenumtemp,omitempty"` LineNumTemp bool `json:"linenumtemp,omitempty"`
LineLocal bool `json:"linelocal"` LineLocal bool `json:"linelocal"`
LineType string `json:"linetype"` LineType string `json:"linetype"`
Text string `json:"text,omitempty"` Text string `json:"text,omitempty"`
CmdId string `json:"cmdid,omitempty"` CmdId string `json:"cmdid,omitempty"`
Ephemeral bool `json:"ephemeral,omitempty"` Ephemeral bool `json:"ephemeral,omitempty"`
Remove bool `json:"remove,omitempty"` Remove bool `json:"remove,omitempty"`
ContentHeight int64 `json:"contentheight,omitempty"`
} }
type ResolveItem struct { type ResolveItem struct {
@@ -575,11 +577,11 @@ type CmdType struct {
TermOpts TermOpts `json:"termopts"` TermOpts TermOpts `json:"termopts"`
OrigTermOpts TermOpts `json:"origtermopts"` OrigTermOpts TermOpts `json:"origtermopts"`
Status string `json:"status"` Status string `json:"status"`
StartPk *packet.CmdStartPacketType `json:"startpk"` StartPk *packet.CmdStartPacketType `json:"startpk,omitempty"`
DonePk *packet.CmdDonePacketType `json:"donepk"` DonePk *packet.CmdDonePacketType `json:"donepk,omitempty"`
UsedRows int64 `json:"usedrows"` RunOut []packet.PacketType `json:"runout,omitempty"`
RunOut []packet.PacketType `json:"runout"` RtnState bool `json:"rtnstate,omitempty"`
Remove bool `json:"remove"` Remove bool `json:"remove,omitempty"`
} }
func (r *RemoteType) ToMap() map[string]interface{} { func (r *RemoteType) ToMap() map[string]interface{} {
@@ -644,7 +646,7 @@ func (cmd *CmdType) ToMap() map[string]interface{} {
rtn["startpk"] = quickJson(cmd.StartPk) rtn["startpk"] = quickJson(cmd.StartPk)
rtn["donepk"] = quickJson(cmd.DonePk) rtn["donepk"] = quickJson(cmd.DonePk)
rtn["runout"] = quickJson(cmd.RunOut) rtn["runout"] = quickJson(cmd.RunOut)
rtn["usedrows"] = cmd.UsedRows rtn["rtnstate"] = cmd.RtnState
return rtn return rtn
} }
@@ -666,7 +668,7 @@ func CmdFromMap(m map[string]interface{}) *CmdType {
quickSetJson(&cmd.StartPk, m, "startpk") quickSetJson(&cmd.StartPk, m, "startpk")
quickSetJson(&cmd.DonePk, m, "donepk") quickSetJson(&cmd.DonePk, m, "donepk")
quickSetJson(&cmd.RunOut, m, "runout") quickSetJson(&cmd.RunOut, m, "runout")
quickSetInt64(&cmd.UsedRows, m, "usedrows") quickSetBool(&cmd.RtnState, m, "rtnstate")
return &cmd return &cmd
} }
@@ -680,6 +682,7 @@ func makeNewLineCmd(sessionId string, windowId string, userId string, cmdId stri
rtn.LineLocal = true rtn.LineLocal = true
rtn.LineType = LineTypeCmd rtn.LineType = LineTypeCmd
rtn.CmdId = cmdId rtn.CmdId = cmdId
rtn.ContentHeight = LineNoHeight
return rtn return rtn
} }
@@ -693,6 +696,7 @@ func makeNewLineText(sessionId string, windowId string, userId string, text stri
rtn.LineLocal = true rtn.LineLocal = true
rtn.LineType = LineTypeText rtn.LineType = LineTypeText
rtn.Text = text rtn.Text = text
rtn.ContentHeight = LineNoHeight
return rtn return rtn
} }