...

Source file src/os/executable_path.go

Documentation: os

		 1  // Copyright 2017 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  //go:build aix || openbsd
		 6  // +build aix openbsd
		 7  
		 8  package os
		 9  
		10  // We query the working directory at init, to use it later to search for the
		11  // executable file
		12  // errWd will be checked later, if we need to use initWd
		13  var initWd, errWd = Getwd()
		14  
		15  func executable() (string, error) {
		16  	var exePath string
		17  	if len(Args) == 0 || Args[0] == "" {
		18  		return "", ErrNotExist
		19  	}
		20  	if IsPathSeparator(Args[0][0]) {
		21  		// Args[0] is an absolute path, so it is the executable.
		22  		// Note that we only need to worry about Unix paths here.
		23  		exePath = Args[0]
		24  	} else {
		25  		for i := 1; i < len(Args[0]); i++ {
		26  			if IsPathSeparator(Args[0][i]) {
		27  				// Args[0] is a relative path: prepend the
		28  				// initial working directory.
		29  				if errWd != nil {
		30  					return "", errWd
		31  				}
		32  				exePath = initWd + string(PathSeparator) + Args[0]
		33  				break
		34  			}
		35  		}
		36  	}
		37  	if exePath != "" {
		38  		if err := isExecutable(exePath); err != nil {
		39  			return "", err
		40  		}
		41  		return exePath, nil
		42  	}
		43  	// Search for executable in $PATH.
		44  	for _, dir := range splitPathList(Getenv("PATH")) {
		45  		if len(dir) == 0 {
		46  			dir = "."
		47  		}
		48  		if !IsPathSeparator(dir[0]) {
		49  			if errWd != nil {
		50  				return "", errWd
		51  			}
		52  			dir = initWd + string(PathSeparator) + dir
		53  		}
		54  		exePath = dir + string(PathSeparator) + Args[0]
		55  		switch isExecutable(exePath) {
		56  		case nil:
		57  			return exePath, nil
		58  		case ErrPermission:
		59  			return "", ErrPermission
		60  		}
		61  	}
		62  	return "", ErrNotExist
		63  }
		64  
		65  // isExecutable returns an error if a given file is not an executable.
		66  func isExecutable(path string) error {
		67  	stat, err := Stat(path)
		68  	if err != nil {
		69  		return err
		70  	}
		71  	mode := stat.Mode()
		72  	if !mode.IsRegular() {
		73  		return ErrPermission
		74  	}
		75  	if (mode & 0111) == 0 {
		76  		return ErrPermission
		77  	}
		78  	return nil
		79  }
		80  
		81  // splitPathList splits a path list.
		82  // This is based on genSplit from strings/strings.go
		83  func splitPathList(pathList string) []string {
		84  	if pathList == "" {
		85  		return nil
		86  	}
		87  	n := 1
		88  	for i := 0; i < len(pathList); i++ {
		89  		if pathList[i] == PathListSeparator {
		90  			n++
		91  		}
		92  	}
		93  	start := 0
		94  	a := make([]string, n)
		95  	na := 0
		96  	for i := 0; i+1 <= len(pathList) && na+1 < n; i++ {
		97  		if pathList[i] == PathListSeparator {
		98  			a[na] = pathList[start:i]
		99  			na++
	 100  			start = i + 1
	 101  		}
	 102  	}
	 103  	a[na] = pathList[start:]
	 104  	return a[:na+1]
	 105  }
	 106  

View as plain text