github.com/BIG5Concepts/forego@v0.16.1/Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_sysctl.go (about)

     1  // Copyright 2012 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 freebsd
     6  
     7  package osext
     8  
     9  import (
    10  	"os"
    11  	"path/filepath"
    12  	"runtime"
    13  	"syscall"
    14  	"unsafe"
    15  )
    16  
    17  var initCwd, initCwdErr = os.Getwd()
    18  
    19  func executable() (string, error) {
    20  	var mib [4]int32
    21  	switch runtime.GOOS {
    22  	case "freebsd":
    23  		mib = [4]int32{1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1}
    24  	case "darwin":
    25  		mib = [4]int32{1 /* CTL_KERN */, 38 /* KERN_PROCARGS */, int32(os.Getpid()), -1}
    26  	}
    27  
    28  	n := uintptr(0)
    29  	// Get length.
    30  	_, _, errNum := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
    31  	if errNum != 0 {
    32  		return "", errNum
    33  	}
    34  	if n == 0 { // This shouldn't happen.
    35  		return "", nil
    36  	}
    37  	buf := make([]byte, n)
    38  	_, _, errNum = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&n)), 0, 0)
    39  	if errNum != 0 {
    40  		return "", errNum
    41  	}
    42  	if n == 0 { // This shouldn't happen.
    43  		return "", nil
    44  	}
    45  	for i, v := range buf {
    46  		if v == 0 {
    47  			buf = buf[:i]
    48  			break
    49  		}
    50  	}
    51  	var err error
    52  	execPath := string(buf)
    53  	// execPath will not be empty due to above checks.
    54  	// Try to get the absolute path if the execPath is not rooted.
    55  	if execPath[0] != '/' {
    56  		execPath, err = getAbs(execPath)
    57  		if err != nil {
    58  			return execPath, err
    59  		}
    60  	}
    61  	// For darwin KERN_PROCARGS may return the path to a symlink rather than the
    62  	// actual executable.
    63  	if runtime.GOOS == "darwin" {
    64  		if execPath, err = filepath.EvalSymlinks(execPath); err != nil {
    65  			return execPath, err
    66  		}
    67  	}
    68  	return execPath, nil
    69  }
    70  
    71  func getAbs(execPath string) (string, error) {
    72  	if initCwdErr != nil {
    73  		return execPath, initCwdErr
    74  	}
    75  	// The execPath may begin with a "../" or a "./" so clean it first.
    76  	// Join the two paths, trailing and starting slashes undetermined, so use
    77  	// the generic Join function.
    78  	return filepath.Join(initCwd, filepath.Clean(execPath)), nil
    79  }