Home | History | Annotate | Download | only in exec
      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 darwin dragonfly freebsd linux nacl netbsd openbsd solaris
      6 
      7 package exec
      8 
      9 import (
     10 	"errors"
     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 os.ErrPermission
     28 }
     29 
     30 // LookPath searches for an executable binary named file
     31 // in the directories named by the PATH environment variable.
     32 // If file contains a slash, it is tried directly and the PATH is not consulted.
     33 // The result may be an absolute path or a path relative to the current directory.
     34 func LookPath(file string) (string, error) {
     35 	// NOTE(rsc): I wish we could use the Plan 9 behavior here
     36 	// (only bypass the path if file begins with / or ./ or ../)
     37 	// but that would not match all the Unix shells.
     38 
     39 	if strings.Contains(file, "/") {
     40 		err := findExecutable(file)
     41 		if err == nil {
     42 			return file, nil
     43 		}
     44 		return "", &Error{file, err}
     45 	}
     46 	path := os.Getenv("PATH")
     47 	for _, dir := range filepath.SplitList(path) {
     48 		if dir == "" {
     49 			// Unix shell semantics: path element "" means "."
     50 			dir = "."
     51 		}
     52 		path := filepath.Join(dir, file)
     53 		if err := findExecutable(path); err == nil {
     54 			return path, nil
     55 		}
     56 	}
     57 	return "", &Error{file, ErrNotFound}
     58 }
     59