github.com/gwitmond/nulpunt@v0.0.0-20140409222138-65af2ff40594/gopath/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 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 }