diff --git a/exec.go b/exec.go index f1b7c88..1b4df4f 100644 --- a/exec.go +++ b/exec.go @@ -2,6 +2,7 @@ package main import ( "context" + "errors" "fmt" "os" "path/filepath" @@ -17,6 +18,8 @@ import ( "mvdan.cc/sh/v3/syntax" ) +var errNotExec = errors.New("not executable") + func runInput(input, origInput string) { running = true cmdString := aliases.Resolve(input) @@ -136,8 +139,8 @@ func execCommand(cmd, old string) error { return interp.NewExitStatus(exitcode) } - err := lookpath(args[0]) - if err == os.ErrPermission { + err, execName := lookpath(args[0]) + if err == errNotExec { hooks.Em.Emit("command.no-perm", args[0]) return interp.NewExitStatus(126) } else if err != nil { @@ -145,6 +148,8 @@ func execCommand(cmd, old string) error { return interp.NewExitStatus(127) } + args[0] = execName // windows, thanks + return interp.DefaultExecHandler(2 * time.Second)(ctx, args) } runner, _ := interp.New( @@ -156,37 +161,24 @@ func execCommand(cmd, old string) error { return err } -// custom lookpath function so we know if a command is found *and* has execute permission -func lookpath(file string) error { +func lookpath(file string) (error, string) { // custom lookpath function so we know if a command is found *and* is executable skip := []string{"./", "/", "../", "~/"} for _, s := range skip { if strings.HasPrefix(file, s) { - err := findExecutable(file) - return err + return findExecutable(file) } } for _, dir := range filepath.SplitList(os.Getenv("PATH")) { path := filepath.Join(dir, file) - err := findExecutable(path) - if err == os.ErrPermission { - return err + err, execName := findExecutable(path) + if err == errNotExec { + return err, "" } else if err == nil { - return nil + return nil, execName } } - return os.ErrNotExist -} - -func findExecutable(name string) error { - f, err := os.Stat(name) - if err != nil { - return err - } - if m := f.Mode(); !m.IsDir() && m & 0111 != 0 { - return nil - } - return os.ErrPermission + return os.ErrNotExist, "" } func splitInput(input string) ([]string, string) { diff --git a/execfile_unix.go b/execfile_unix.go new file mode 100644 index 0000000..e4ab109 --- /dev/null +++ b/execfile_unix.go @@ -0,0 +1,19 @@ +// +build linux darwin + +package main + +import ( + "path/filepath" + "os" +) + +func findExecutable(path string) (error, string) { + f, err := os.Stat(path) + if err != nil { + return err, "" + } + if m := f.Mode(); !m.IsDir() && m & 0111 != 0 { + return nil, filepath.Base(path) + } + return errNotExec, "" +} diff --git a/execfile_windows.go b/execfile_windows.go new file mode 100644 index 0000000..b94782a --- /dev/null +++ b/execfile_windows.go @@ -0,0 +1,26 @@ +// +build windows + +package main + +import ( + "path/filepath" + "os" +) + +func findExecutable(path string) (error, string) { + nameExt := filepath.Ext(path) + + if nameExt == "" { + for _, ext := range filepath.SplitList(os.Getenv("PATHEXT")) { + _, err := os.Stat(path + ext) + if err != nil { + return nil, filepath.Base(path + ext) + } + } + } else { + _, err := os.Stat(path) + return err, "" + } + + return errNotExec, "" +}