github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/os/exec/lp_unix.go (about) 1 // Copyright 2010 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 // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris 6 7 package exec 8 9 import ( 10 "errors" 11 "io/fs" 12 "os" 13 "path/filepath" 14 "strings" 15 ) 16 17 // ErrNotFound is the error resulting if a path search failed to find an executable file. 18 var ErrNotFound = errors.New("executable file not found in $PATH") 19 20 func findExecutable(file string) error { 21 d, err := os.Stat(file) 22 if err != nil { 23 return err 24 } 25 if m := d.Mode(); !m.IsDir() && m&0111 != 0 { 26 return nil 27 } 28 return fs.ErrPermission 29 } 30 31 // LookPath searches for an executable named file in the 32 // directories named by the PATH environment variable. 33 // If file contains a slash, it is tried directly and the PATH is not consulted. 34 // The result may be an absolute path or a path relative to the current directory. 35 func LookPath(file string) (string, error) { 36 // NOTE(rsc): I wish we could use the Plan 9 behavior here 37 // (only bypass the path if file begins with / or ./ or ../) 38 // but that would not match all the Unix shells. 39 40 if strings.Contains(file, "/") { 41 err := findExecutable(file) 42 if err == nil { 43 return file, nil 44 } 45 return "", &Error{file, err} 46 } 47 path := os.Getenv("PATH") 48 for _, dir := range filepath.SplitList(path) { 49 if dir == "" { 50 // Unix shell semantics: path element "" means "." 51 dir = "." 52 } 53 path := filepath.Join(dir, file) 54 if err := findExecutable(path); err == nil { 55 return path, nil 56 } 57 } 58 return "", &Error{file, ErrNotFound} 59 }