github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/os/exec/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 exec 6 7 import ( 8 "errors" 9 "internal/godebug" 10 "io/fs" 11 "os" 12 "path/filepath" 13 "strings" 14 ) 15 16 // ErrNotFound is the error resulting if a path search failed to find an executable file. 17 var ErrNotFound = errors.New("executable file not found in $path") 18 19 func findExecutable(file string) error { 20 d, err := os.Stat(file) 21 if err != nil { 22 return err 23 } 24 if m := d.Mode(); !m.IsDir() && m&0111 != 0 { 25 return nil 26 } 27 return fs.ErrPermission 28 } 29 30 // LookPath searches for an executable named file in the 31 // directories named by the path environment variable. 32 // If file begins with "/", "#", "./", or "../", it is tried 33 // directly and the path is not consulted. 34 // On success, the result is an absolute path. 35 // 36 // In older versions of Go, LookPath could return a path relative to the current directory. 37 // As of Go 1.19, LookPath will instead return that path along with an error satisfying 38 // errors.Is(err, ErrDot). See the package documentation for more details. 39 func LookPath(file string) (string, error) { 40 // skip the path lookup for these prefixes 41 skip := []string{"/", "#", "./", "../"} 42 43 for _, p := range skip { 44 if strings.HasPrefix(file, p) { 45 err := findExecutable(file) 46 if err == nil { 47 return file, nil 48 } 49 return "", &Error{file, err} 50 } 51 } 52 53 path := os.Getenv("path") 54 for _, dir := range filepath.SplitList(path) { 55 path := filepath.Join(dir, file) 56 if err := findExecutable(path); err == nil { 57 if !filepath.IsAbs(path) && godebug.Get("execerrdot") != "0" { 58 return path, &Error{file, ErrDot} 59 } 60 return path, nil 61 } 62 } 63 return "", &Error{file, ErrNotFound} 64 }