d2/lib/xexec/xexec.go

58 lines
1.2 KiB
Go
Raw Normal View History

package xexec
import (
"errors"
"io/fs"
"os"
"path/filepath"
"strings"
)
// findExecutable is from package exec
func findExecutable(file string) error {
d, err := os.Stat(file)
if err != nil {
return err
}
if m := d.Mode(); !m.IsDir() && m&0111 != 0 {
return nil
}
return fs.ErrPermission
}
// SearchPath searches for all executables that have prefix in their names in
// the directories named by the PATH environment variable.
func SearchPath(prefix string) ([]string, error) {
var matches []string
envPath := os.Getenv("PATH")
dirSet := make(map[string]struct{})
for _, dir := range filepath.SplitList(envPath) {
if dir == "" {
// From exec package:
// Unix shell semantics: path element "" means "."
dir = "."
}
if _, ok := dirSet[dir]; ok {
continue
}
dirSet[dir] = struct{}{}
files, err := os.ReadDir(dir)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
continue
}
return nil, err
}
for _, f := range files {
if strings.HasPrefix(f.Name(), prefix) {
match := filepath.Join(dir, f.Name())
if err := findExecutable(match); err == nil {
matches = append(matches, match)
}
}
}
}
return matches, nil
}