github.com/sdibtacm/sandbox@v0.0.0-20200320120712-60470cf803dc/exec/lookpath.go (about)

     1  //+build linux
     2  
     3  package exec
     4  
     5  import (
     6  	"errors"
     7  	"os"
     8  	"path/filepath"
     9  	"strconv"
    10  	"strings"
    11  )
    12  
    13  type LpError struct {
    14  	// Name is the file name for which the error occurred.
    15  	Name string
    16  	// Err is the underlying error.
    17  	Err error
    18  }
    19  
    20  func (e *LpError) Error() string {
    21  	return "exec: " + strconv.Quote(e.Name) + ": " + e.Err.Error()
    22  }
    23  
    24  // Copyright 2010 The Go Authors. All rights reserved.
    25  // Use of this source code is governed by a BSD-style
    26  // license that can be found in the LICENSE file.
    27  
    28  // ErrNotFound is the error resulting if a path search failed to find an executable file.
    29  var ErrNotFound = errors.New("executable file not found in $PATH")
    30  
    31  func executable(file string) error {
    32  	d, err := os.Stat(file)
    33  	if err != nil {
    34  		return err
    35  	}
    36  	if m := d.Mode(); !m.IsDir() && m&0111 != 0 {
    37  		return nil
    38  	}
    39  	return os.ErrPermission
    40  }
    41  
    42  // LookPath searches for an executable named file in the
    43  // directories named by the PATH environment variable.
    44  // If file contains a slash, it is tried directly and the PATH is not consulted.
    45  // The result may be an absolute path or a path relative to the current directory.
    46  func LookPath(file string) (string, error) {
    47  	// NOTE(rsc): I wish we could use the Plan 9 behavior here
    48  	// (only bypass the path if file begins with / or ./ or ../)
    49  	// but that would not match all the Unix shells.
    50  
    51  	if strings.Contains(file, "/") {
    52  		err := executable(file)
    53  		if err == nil {
    54  			return file, nil
    55  		}
    56  		return "", &LpError{file, err}
    57  	}
    58  	path := os.Getenv("PATH")
    59  	for _, dir := range filepath.SplitList(path) {
    60  		if dir == "" {
    61  			// Unix shell semantics: path element "" means "."
    62  			dir = "."
    63  		}
    64  		path := filepath.Join(dir, file)
    65  		if err := executable(path); err == nil {
    66  			return path, nil
    67  		}
    68  	}
    69  	return "", &LpError{file, ErrNotFound}
    70  }