github.com/neugram/ng@v0.0.0-20180309130942-d472ff93d872/eval/shell/exec_bsd.go (about) 1 // Copyright 2015 The Neugram 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 6 7 package shell 8 9 import ( 10 "bytes" 11 "errors" 12 "fmt" 13 "os" 14 "path/filepath" 15 "runtime" 16 "syscall" 17 "unsafe" 18 ) 19 20 // executable returns the path to the executable of this process. 21 func executable() (string, error) { 22 pid := int32(os.Getpid()) 23 24 // TODO: other BSDs have different sysctls. 25 const CTL_KERN = 1 26 var cfg [4]int32 27 if runtime.GOOS == "darwin" { 28 const KERN_PROCARGS = 38 // <sys/sysctl.h> 29 cfg = [4]int32{CTL_KERN, KERN_PROCARGS, pid, -1} 30 } else { 31 panic(fmt.Sprintf("executable: unsupported GOOS: %q", runtime.GOOS)) 32 } 33 34 // Get the size of the process args, then take the first of 35 // the NUL-separated list. 36 var n uintptr 37 np := unsafe.Pointer(&n) 38 _, _, errno := syscall.Syscall6( 39 syscall.SYS___SYSCTL, 40 uintptr(unsafe.Pointer(&cfg[0])), 41 4, 0, uintptr(np), 0, 0, 42 ) 43 if errno != 0 { 44 return "", errno 45 } 46 if n == 0 { 47 return "", errors.New("shell executable: sysctl returned zero size") 48 } 49 buf := make([]byte, n) 50 _, _, errno = syscall.Syscall6( 51 syscall.SYS___SYSCTL, 52 uintptr(unsafe.Pointer(&cfg[0])), 53 4, uintptr(unsafe.Pointer(&buf[0])), uintptr(np), 0, 0, 54 ) 55 if errno != 0 { 56 return "", errno 57 } 58 if i := bytes.IndexByte(buf, 0); i > 0 { 59 buf = buf[:i] 60 } 61 path := string(buf) 62 if !filepath.IsAbs(path) { 63 path = filepath.Join(initialCwd, string(buf)) 64 } 65 return path, nil 66 }