diff options
Diffstat (limited to 'vendor/github.com/keybase/go-ps/process_openbsd.go')
-rw-r--r-- | vendor/github.com/keybase/go-ps/process_openbsd.go | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/vendor/github.com/keybase/go-ps/process_openbsd.go b/vendor/github.com/keybase/go-ps/process_openbsd.go new file mode 100644 index 0000000..51c446d --- /dev/null +++ b/vendor/github.com/keybase/go-ps/process_openbsd.go @@ -0,0 +1,302 @@ +// +build openbsd + +package ps + +import ( + "bytes" + "encoding/binary" + "fmt" + "syscall" + "unsafe" +) + +// copied from sys/sysctl.h +const ( + CTL_KERN = 1 + KERN_PROC = 66 + KERN_PROC_PID = 1 + KERN_PROC_ARGS = 55 + KERN_PROC_ARGV = 1 + KERN_PROC_ALL = 0 +) + +/* Generated via cgo: + +$ cat /tmp/gen_defs.go +// +build ignore +package ps +// #include <sys/types.h> +// #include <sys/sysctl.h> +import "C" + +type Kinfo_proc C.struct_kinfo_proc + +$ go tool cgo -godefs temp.go + +*/ + +type Kinfo_proc struct { + Ki_forw uint64 + Ki_back uint64 + Ki_paddr uint64 + Ki_addr uint64 + Ki_fd uint64 + Ki_stats uint64 + Ki_limit uint64 + Ki_vmspace uint64 + Ki_sigacts uint64 + Ki_sess uint64 + Ki_tsess uint64 + Ki_ru uint64 + Ki_eflag int32 + Ki_exitsig int32 + Ki_flag int32 + Ki_pid int32 + Ki_ppid int32 + Ki_sid int32 + Ki_x_pgid int32 + Ki_tpgid int32 + Ki_uid uint32 + Ki_ruid uint32 + Ki_gid uint32 + Ki_rgid uint32 + Ki_groups [16]uint32 + Ki_ngroups int16 + Ki_jobc int16 + Ki_tdev uint32 + Ki_estcpu uint32 + Ki_rtime_sec uint32 + Ki_rtime_usec uint32 + Ki_cpticks int32 + Ki_pctcpu uint32 + Ki_swtime uint32 + Ki_slptime uint32 + Ki_schedflags int32 + Ki_uticks uint64 + Ki_sticks uint64 + Ki_iticks uint64 + Ki_tracep uint64 + Ki_traceflag int32 + Ki_holdcnt int32 + Ki_siglist int32 + Ki_sigmask uint32 + Ki_sigignore uint32 + Ki_sigcatch uint32 + Ki_stat int8 + Ki_priority uint8 + Ki_usrpri uint8 + Ki_nice uint8 + Ki_xstat uint16 + Ki_acflag uint16 + //Ki_comm [24]int8 + Ki_comm [20]byte + Ki_wmesg [8]int8 + Ki_wchan uint64 + Ki_login [32]int8 + Ki_vm_rssize int32 + Ki_vm_tsize int32 + Ki_vm_dsize int32 + Ki_vm_ssize int32 + Ki_uvalid int64 + Ki_ustart_sec uint64 + Ki_ustart_usec uint32 + Ki_uutime_sec uint32 + Ki_uutime_usec uint32 + Ki_ustime_sec uint32 + Ki_ustime_usec uint32 + Ki_pad_cgo_0 [4]byte + Ki_uru_maxrss uint64 + Ki_uru_ixrss uint64 + Ki_uru_idrss uint64 + Ki_uru_isrss uint64 + Ki_uru_minflt uint64 + Ki_uru_majflt uint64 + Ki_uru_nswap uint64 + Ki_uru_inblock uint64 + Ki_uru_oublock uint64 + Ki_uru_msgsnd uint64 + Ki_uru_msgrcv uint64 + Ki_uru_nsignals uint64 + Ki_uru_nvcsw uint64 + Ki_uru_nivcsw uint64 + Ki_uctime_sec uint32 + Ki_uctime_usec uint32 + Ki_psflags int32 + Ki_spare int32 + Ki_svuid uint32 + Ki_svgid uint32 + Ki_emul [8]int8 + Ki_rlim_rss_cur uint64 + Ki_cpuid uint64 + Ki_vm_map_size uint64 + Ki_tid int32 + Ki_rtableid uint32 +} + +var proc_k_size = unsafe.Sizeof(Kinfo_proc{}) + +// UnixProcess is an implementation of Process that contains Unix-specific +// fields and information. +type UnixProcess struct { + pid int + ppid int + state rune + pgrp int + sid int + + binary string +} + +// Pid returns process id +func (p *UnixProcess) Pid() int { + return p.pid +} + +// PPid returns parent process id +func (p *UnixProcess) PPid() int { + return p.ppid +} + +// Executable returns process executable name +func (p *UnixProcess) Executable() string { + return p.binary +} + +// Path returns path to process executable +func (p *UnixProcess) Path() (string, error) { + // On OpenBSD we don't have the actual path of a binary, the next + // best thing we can do is walk $PATH to hopefully find the binary. + // More info here: https://github.com/kardianos/osext/commit/b4814f465fb1f92d46e37f7ef84d732ece7c3e3a + return "", fmt.Errorf("Unsupported") +} + +// Refresh reloads all the data associated with this process. +func (p *UnixProcess) Refresh() error { + mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PID, int32(p.pid), int32(proc_k_size), 1} + + buf, length, err := call_syscall(mib) + if err != nil { + return err + } + if length != uint64(proc_k_size) { + return err + } + + k, err := parse_kinfo_proc(buf) + if err != nil { + return err + } + + p.ppid, p.pgrp, p.sid, p.binary = copy_params(&k) + return nil +} + +func copy_params(k *Kinfo_proc) (int, int, int, string) { + n := -1 + for i, b := range k.Ki_comm { + if b == 0 { + break + } + n = i + 1 + } + comm := string(k.Ki_comm[:n]) + + return int(k.Ki_ppid), int(k.Ki_x_pgid), int(k.Ki_sid), comm +} + +func findProcess(pid int) (Process, error) { + mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PID, int32(pid), int32(proc_k_size), 1} + + _, _, err := call_syscall(mib) + if err != nil { + return nil, err + } + + return newUnixProcess(pid) +} + +func processes() ([]Process, error) { + results := make([]Process, 0, 50) + + mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0, int32(proc_k_size), 400} + buf, length, err := call_syscall(mib) + if err != nil { + return results, err + } + + // get kinfo_proc size + procinfo_len := int(proc_k_size) + count := int(length / uint64(proc_k_size)) + + // parse buf to procs + for i := 0; i < count; i++ { + b := buf[i*procinfo_len : i*procinfo_len+procinfo_len] + k, err := parse_kinfo_proc(b) + if err != nil { + continue + } + p, err := newUnixProcess(int(k.Ki_pid)) + if err != nil { + continue + } + p.ppid, p.pgrp, p.sid, p.binary = copy_params(&k) + + results = append(results, p) + } + + return results, nil +} + +func parse_kinfo_proc(buf []byte) (Kinfo_proc, error) { + var k Kinfo_proc + br := bytes.NewReader(buf) + err := binary.Read(br, binary.LittleEndian, &k) + if err != nil { + return k, err + } + + return k, nil +} + +func call_syscall(mib []int32) ([]byte, uint64, error) { + miblen := uint64(len(mib)) + + // get required buffer size + length := uint64(0) + _, _, err := syscall.RawSyscall6( + syscall.SYS___SYSCTL, + uintptr(unsafe.Pointer(&mib[0])), + uintptr(miblen), + 0, + uintptr(unsafe.Pointer(&length)), + 0, + 0) + if err != 0 { + b := make([]byte, 0) + return b, length, err + } + if length == 0 { + b := make([]byte, 0) + return b, length, err + } + // get proc info itself + buf := make([]byte, length) + _, _, err = syscall.RawSyscall6( + syscall.SYS___SYSCTL, + uintptr(unsafe.Pointer(&mib[0])), + uintptr(miblen), + uintptr(unsafe.Pointer(&buf[0])), + uintptr(unsafe.Pointer(&length)), + 0, + 0) + if err != 0 { + return buf, length, err + } + + return buf, length, nil +} + +func newUnixProcess(pid int) (*UnixProcess, error) { + p := &UnixProcess{pid: pid} + return p, p.Refresh() +} |