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 "os" 10 "path/filepath" 11 "strings" 12 ) 13 14 // ErrNotFound is the error resulting if a path search failed to find an executable file. 15 var ErrNotFound = errors.New("executable file not found in $path") 16 17 func findExecutable(file string) error { 18 d, err := os.Stat(file) 19 if err != nil { 20 return err 21 } 22 if m := d.Mode(); !m.IsDir() && m&0111 != 0 { 23 return nil 24 } 25 return os.ErrPermission 26 } 27 28 // LookPath searches for an executable binary named file 29 // in the directories named by the path environment variable. 30 // If file begins with "/", "#", "./", or "../", it is tried 31 // directly and the path is not consulted. 32 // The result may be an absolute path or a path relative to the current directory. 33 func LookPath(file string) (string, error) { 34 // skip the path lookup for these prefixes 35 skip := []string{"/", "#", "./", "../"} 36 37 for _, p := range skip { 38 if strings.HasPrefix(file, p) { 39 err := findExecutable(file) 40 if err == nil { 41 return file, nil 42 } 43 return "", &Error{file, err} 44 } 45 } 46 47 path := os.Getenv("path") 48 for _, dir := range filepath.SplitList(path) { 49 path := filepath.Join(dir, file) 50 if err := findExecutable(path); err == nil { 51 return path, nil 52 } 53 } 54 return "", &Error{file, ErrNotFound} 55 } 56