Home | History | Annotate | Download | only in exec
      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