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 	"strings"
     11 )
     12 
     13 // ErrNotFound is the error resulting if a path search failed to find an executable file.
     14 var ErrNotFound = errors.New("executable file not found in $path")
     15 
     16 func findExecutable(file string) error {
     17 	d, err := os.Stat(file)
     18 	if err != nil {
     19 		return err
     20 	}
     21 	if m := d.Mode(); !m.IsDir() && m&0111 != 0 {
     22 		return nil
     23 	}
     24 	return os.ErrPermission
     25 }
     26 
     27 // LookPath searches for an executable binary named file
     28 // in the directories named by the path environment variable.
     29 // If file begins with "/", "#", "./", or "../", it is tried
     30 // directly and the path is not consulted.
     31 // The result may be an absolute path or a path relative to the current directory.
     32 func LookPath(file string) (string, error) {
     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 := os.Getenv("path")
     47 	for _, dir := range strings.Split(path, "\000") {
     48 		if err := findExecutable(dir + "/" + file); err == nil {
     49 			return dir + "/" + file, nil
     50 		}
     51 	}
     52 	return "", &Error{file, ErrNotFound}
     53 }
     54