fix: return other errors from sh runner

makes it so that the sh runner function will return
command not found and not executable errors,
which makes them able to be handled via lua properly
insensitive-tab^2
TorchedSammy 2022-04-30 21:02:36 -04:00
parent c4eb3ad368
commit 4178b78341
Signed by: sammyette
GPG Key ID: 904FC49417B44DCD
1 changed files with 80 additions and 26 deletions

106
exec.go
View File

@ -25,8 +25,63 @@ import (
) )
var errNotExec = errors.New("not executable") var errNotExec = errors.New("not executable")
var errNotFound = errors.New("not found")
var runnerMode rt.Value = rt.StringValue("hybrid") var runnerMode rt.Value = rt.StringValue("hybrid")
type execError struct{
typ string
cmd string
code int
colon bool
err error
}
func (e execError) Error() string {
return fmt.Sprintf("%s: %s", e.cmd, e.typ)
}
func (e execError) sprint() error {
sep := " "
if e.colon {
sep = ": "
}
return fmt.Errorf("hilbish: %s%s%s", e.cmd, sep, e.err.Error())
}
func isExecError(err error) (execError, bool) {
if exErr, ok := err.(execError); ok {
return exErr, true
}
fields := strings.Split(err.Error(), ": ")
knownTypes := []string{
"not-found",
"not-executable",
}
if len(fields) > 1 && contains(knownTypes, fields[1]) {
var colon bool
var e error
switch fields[1] {
case "not-found":
e = errNotFound
case "not-executable":
colon = true
e = errNotExec
}
return execError{
cmd: fields[0],
typ: fields[1],
colon: colon,
err: e,
}, true
}
return execError{}, false
}
func runInput(input string, priv bool) { func runInput(input string, priv bool) {
running = true running = true
cmdString := aliases.Resolve(input) cmdString := aliases.Resolve(input)
@ -43,10 +98,6 @@ func runInput(input string, priv bool) {
return return
} }
input, exitCode, err = handleSh(input) input, exitCode, err = handleSh(input)
if err != nil {
fmt.Fprintln(os.Stderr, err)
}
cmdFinish(exitCode, input, priv)
case "hybridRev": case "hybridRev":
_, _, err = handleSh(input) _, _, err = handleSh(input)
if err == nil { if err == nil {
@ -54,27 +105,15 @@ func runInput(input string, priv bool) {
return return
} }
input, exitCode, err = handleLua(cmdString) input, exitCode, err = handleLua(cmdString)
if err != nil {
fmt.Fprintln(os.Stderr, err)
}
cmdFinish(exitCode, input, priv)
case "lua": case "lua":
input, exitCode, err = handleLua(cmdString) input, exitCode, err = handleLua(cmdString)
if err != nil {
fmt.Fprintln(os.Stderr, err)
}
cmdFinish(exitCode, input, priv)
case "sh": case "sh":
input, exitCode, err = handleSh(input) input, exitCode, err = handleSh(input)
if err != nil {
fmt.Fprintln(os.Stderr, err)
}
cmdFinish(exitCode, input, priv)
} }
} else { } else {
// can only be a string or function so // can only be a string or function so
term := rt.NewTerminationWith(l.MainThread().CurrentCont(), 3, false) term := rt.NewTerminationWith(l.MainThread().CurrentCont(), 3, false)
err := rt.Call(l.MainThread(), runnerMode, []rt.Value{rt.StringValue(cmdString)}, term) err = rt.Call(l.MainThread(), runnerMode, []rt.Value{rt.StringValue(cmdString)}, term)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)
cmdFinish(124, input, priv) cmdFinish(124, input, priv)
@ -85,7 +124,6 @@ func runInput(input string, priv bool) {
luaexitcode := term.Get(1) luaexitcode := term.Get(1)
runErr := term.Get(2) runErr := term.Get(2)
var exitCode uint8
if code, ok := luaexitcode.TryInt(); ok { if code, ok := luaexitcode.TryInt(); ok {
exitCode = uint8(code) exitCode = uint8(code)
} }
@ -94,12 +132,20 @@ func runInput(input string, priv bool) {
input = inp input = inp
} }
if runErr != rt.NilValue { if errStr, ok := runErr.TryString(); ok {
fmt.Fprintln(os.Stderr, runErr) err = fmt.Errorf("%s", errStr)
}
}
if err != nil {
if exErr, ok := isExecError(err); ok {
hooks.Em.Emit("command." + exErr.typ, exErr.cmd)
err = exErr.sprint()
}
fmt.Fprintln(os.Stderr, err)
} }
cmdFinish(exitCode, input, priv) cmdFinish(exitCode, input, priv)
} }
}
func handleLua(cmdString string) (string, uint8, error) { func handleLua(cmdString string) (string, uint8, error) {
// First try to load input, essentially compiling to bytecode // First try to load input, essentially compiling to bytecode
@ -255,12 +301,20 @@ func execHandle(bg bool) interp.ExecHandlerFunc {
err := lookpath(args[0]) err := lookpath(args[0])
if err == errNotExec { if err == errNotExec {
hooks.Em.Emit("command.no-perm", args[0]) return execError{
hooks.Em.Emit("command.not-executable", args[0]) typ: "not-executable",
return interp.NewExitStatus(126) cmd: args[0],
code: 126,
colon: true,
err: errNotExec,
}
} else if err != nil { } else if err != nil {
hooks.Em.Emit("command.not-found", args[0]) return execError{
return interp.NewExitStatus(127) typ: "not-found",
cmd: args[0],
code: 127,
err: errNotFound,
}
} }
killTimeout := 2 * time.Second killTimeout := 2 * time.Second