github.com/kula/etcd@v0.2.1-0.20131226070625-e96234382ac0/third_party/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 startUpcwd, getwdError = 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  	_, _, err := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
    31  	if err != 0 {
    32  		return "", err
    33  	}
    34  	if n == 0 { // shouldn't happen
    35  		return "", nil
    36  	}
    37  	buf := make([]byte, n)
    38  	_, _, err = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&n)), 0, 0)
    39  	if err != 0 {
    40  		return "", err
    41  	}
    42  	if n == 0 { // 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 strpath string
    52  	if buf[0] != '/' {
    53  		var e error
    54  		if strpath, e = getAbs(buf); e != nil {
    55  			return strpath, e
    56  		}
    57  	} else {
    58  		strpath = string(buf)
    59  	}
    60  	// darwin KERN_PROCARGS may return the path to a symlink rather than the
    61  	// actual executable
    62  	if runtime.GOOS == "darwin" {
    63  		if strpath, err := filepath.EvalSymlinks(strpath); err != nil {
    64  			return strpath, err
    65  		}
    66  	}
    67  	return strpath, nil
    68  }
    69  
    70  func getAbs(buf []byte) (string, error) {
    71  	if getwdError != nil {
    72  		return string(buf), getwdError
    73  	} else {
    74  		if buf[0] == '.' {
    75  			buf = buf[1:]
    76  		}
    77  		if startUpcwd[len(startUpcwd)-1] != '/' && buf[0] != '/' {
    78  			return startUpcwd + "/" + string(buf), nil
    79  		}
    80  		return startUpcwd + string(buf), nil
    81  	}
    82  }