github.com/rogpeppe/go-internal@v1.12.1-0.20240509064211-c8567cf8e95f/internal/os/execpath/lp_plan9.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package execpath 6 7 import ( 8 "os" 9 "path/filepath" 10 "strings" 11 ) 12 13 func findExecutable(file string) error { 14 d, err := os.Stat(file) 15 if err != nil { 16 return err 17 } 18 if m := d.Mode(); !m.IsDir() && m&0111 != 0 { 19 return nil 20 } 21 return os.ErrPermission 22 } 23 24 // Look searches for an executable named file, using getenv to look up 25 // environment variables. If getenv is nil, os.Getenv will be used. If file 26 // contains a slash, it is tried directly and getenv will not be called. The 27 // result may be an absolute path or a path relative to the current directory. 28 func Look(file string, getenv func(string) string) (string, error) { 29 if getenv == nil { 30 getenv = os.Getenv 31 } 32 33 // skip the path lookup for these prefixes 34 skip := []string{"/", "#", "./", "../"} 35 36 for _, p := range skip { 37 if strings.HasPrefix(file, p) { 38 err := findExecutable(file) 39 if err == nil { 40 return file, nil 41 } 42 return "", &Error{file, err} 43 } 44 } 45 46 path := getenv("path") 47 for _, dir := range filepath.SplitList(path) { 48 path := filepath.Join(dir, file) 49 if err := findExecutable(path); err == nil { 50 return path, nil 51 } 52 } 53 return "", &Error{file, ErrNotFound} 54 }