...
Run Format

Source file src/os/executable_path.go

Documentation: os

  // Copyright 2017 The Go Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style
  // license that can be found in the LICENSE file.
  
  // +build openbsd
  
  package os
  
  // We query the working directory at init, to use it later to search for the
  // executable file
  // errWd will be checked later, if we need to use initWd
  var initWd, errWd = Getwd()
  
  func executable() (string, error) {
  	var exePath string
  	if len(Args) == 0 || Args[0] == "" {
  		return "", ErrNotExist
  	}
  	if IsPathSeparator(Args[0][0]) {
  		// Args[0] is an absolute path, so it is the executable.
  		// Note that we only need to worry about Unix paths here.
  		exePath = Args[0]
  	} else {
  		for i := 1; i < len(Args[0]); i++ {
  			if IsPathSeparator(Args[0][i]) {
  				// Args[0] is a relative path: prepend the
  				// initial working directory.
  				if errWd != nil {
  					return "", errWd
  				}
  				exePath = initWd + string(PathSeparator) + Args[0]
  				break
  			}
  		}
  	}
  	if exePath != "" {
  		if err := isExecutable(exePath); err != nil {
  			return "", err
  		}
  		return exePath, nil
  	}
  	// Search for executable in $PATH.
  	for _, dir := range splitPathList(Getenv("PATH")) {
  		if len(dir) == 0 {
  			dir = "."
  		}
  		if !IsPathSeparator(dir[0]) {
  			if errWd != nil {
  				return "", errWd
  			}
  			dir = initWd + string(PathSeparator) + dir
  		}
  		exePath = dir + string(PathSeparator) + Args[0]
  		switch isExecutable(exePath) {
  		case nil:
  			return exePath, nil
  		case ErrPermission:
  			return "", ErrPermission
  		}
  	}
  	return "", ErrNotExist
  }
  
  // isExecutable returns an error if a given file is not an executable.
  func isExecutable(path string) error {
  	stat, err := Stat(path)
  	if err != nil {
  		return err
  	}
  	mode := stat.Mode()
  	if !mode.IsRegular() {
  		return ErrPermission
  	}
  	if (mode & 0111) == 0 {
  		return ErrPermission
  	}
  	return nil
  }
  
  // splitPathList splits a path list.
  // This is based on genSplit from strings/strings.go
  func splitPathList(pathList string) []string {
  	if pathList == "" {
  		return nil
  	}
  	n := 1
  	for i := 0; i < len(pathList); i++ {
  		if pathList[i] == PathListSeparator {
  			n++
  		}
  	}
  	start := 0
  	a := make([]string, n)
  	na := 0
  	for i := 0; i+1 <= len(pathList) && na+1 < n; i++ {
  		if pathList[i] == PathListSeparator {
  			a[na] = pathList[start:i]
  			na++
  			start = i + 1
  		}
  	}
  	a[na] = pathList[start:]
  	return a[:na+1]
  }
  

View as plain text