summaryrefslogtreecommitdiff
path: root/vendor/github.com/mitchellh/go-ps/process_darwin.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/mitchellh/go-ps/process_darwin.go')
-rw-r--r--vendor/github.com/mitchellh/go-ps/process_darwin.go138
1 files changed, 138 insertions, 0 deletions
diff --git a/vendor/github.com/mitchellh/go-ps/process_darwin.go b/vendor/github.com/mitchellh/go-ps/process_darwin.go
new file mode 100644
index 0000000..5ee87fb
--- /dev/null
+++ b/vendor/github.com/mitchellh/go-ps/process_darwin.go
@@ -0,0 +1,138 @@
+// +build darwin
+
+package ps
+
+import (
+ "bytes"
+ "encoding/binary"
+ "syscall"
+ "unsafe"
+)
+
+type DarwinProcess struct {
+ pid int
+ ppid int
+ binary string
+}
+
+func (p *DarwinProcess) Pid() int {
+ return p.pid
+}
+
+func (p *DarwinProcess) PPid() int {
+ return p.ppid
+}
+
+func (p *DarwinProcess) Executable() string {
+ return p.binary
+}
+
+func findProcess(pid int) (Process, error) {
+ ps, err := processes()
+ if err != nil {
+ return nil, err
+ }
+
+ for _, p := range ps {
+ if p.Pid() == pid {
+ return p, nil
+ }
+ }
+
+ return nil, nil
+}
+
+func processes() ([]Process, error) {
+ buf, err := darwinSyscall()
+ if err != nil {
+ return nil, err
+ }
+
+ procs := make([]*kinfoProc, 0, 50)
+ k := 0
+ for i := _KINFO_STRUCT_SIZE; i < buf.Len(); i += _KINFO_STRUCT_SIZE {
+ proc := &kinfoProc{}
+ err = binary.Read(bytes.NewBuffer(buf.Bytes()[k:i]), binary.LittleEndian, proc)
+ if err != nil {
+ return nil, err
+ }
+
+ k = i
+ procs = append(procs, proc)
+ }
+
+ darwinProcs := make([]Process, len(procs))
+ for i, p := range procs {
+ darwinProcs[i] = &DarwinProcess{
+ pid: int(p.Pid),
+ ppid: int(p.PPid),
+ binary: darwinCstring(p.Comm),
+ }
+ }
+
+ return darwinProcs, nil
+}
+
+func darwinCstring(s [16]byte) string {
+ i := 0
+ for _, b := range s {
+ if b != 0 {
+ i++
+ } else {
+ break
+ }
+ }
+
+ return string(s[:i])
+}
+
+func darwinSyscall() (*bytes.Buffer, error) {
+ mib := [4]int32{_CTRL_KERN, _KERN_PROC, _KERN_PROC_ALL, 0}
+ size := uintptr(0)
+
+ _, _, errno := syscall.Syscall6(
+ syscall.SYS___SYSCTL,
+ uintptr(unsafe.Pointer(&mib[0])),
+ 4,
+ 0,
+ uintptr(unsafe.Pointer(&size)),
+ 0,
+ 0)
+
+ if errno != 0 {
+ return nil, errno
+ }
+
+ bs := make([]byte, size)
+ _, _, errno = syscall.Syscall6(
+ syscall.SYS___SYSCTL,
+ uintptr(unsafe.Pointer(&mib[0])),
+ 4,
+ uintptr(unsafe.Pointer(&bs[0])),
+ uintptr(unsafe.Pointer(&size)),
+ 0,
+ 0)
+
+ if errno != 0 {
+ return nil, errno
+ }
+
+ return bytes.NewBuffer(bs[0:size]), nil
+}
+
+const (
+ _CTRL_KERN = 1
+ _KERN_PROC = 14
+ _KERN_PROC_ALL = 0
+ _KINFO_STRUCT_SIZE = 648
+)
+
+type kinfoProc struct {
+ _ [40]byte
+ Pid int32
+ _ [199]byte
+ Comm [16]byte
+ _ [301]byte
+ PPid int32
+ _ [84]byte
+}