139 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// +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
 | 
						|
}
 |