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