summaryrefslogtreecommitdiff
path: root/vendor/github.com/keybase/go-ps
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/keybase/go-ps')
-rw-r--r--vendor/github.com/keybase/go-ps/.gitignore1
-rw-r--r--vendor/github.com/keybase/go-ps/.pre-commit-config.yaml10
-rw-r--r--vendor/github.com/keybase/go-ps/.travis.yml11
-rw-r--r--vendor/github.com/keybase/go-ps/LICENSE.md44
-rw-r--r--vendor/github.com/keybase/go-ps/README.md31
-rw-r--r--vendor/github.com/keybase/go-ps/appveyor.yml31
-rw-r--r--vendor/github.com/keybase/go-ps/darwincgo/empty.go1
-rw-r--r--vendor/github.com/keybase/go-ps/darwincgo/process_darwin.c87
-rw-r--r--vendor/github.com/keybase/go-ps/darwincgo/process_darwin.go84
-rw-r--r--vendor/github.com/keybase/go-ps/process.go75
-rw-r--r--vendor/github.com/keybase/go-ps/process_darwin.go31
-rw-r--r--vendor/github.com/keybase/go-ps/process_freebsd.go269
-rw-r--r--vendor/github.com/keybase/go-ps/process_openbsd.go302
-rw-r--r--vendor/github.com/keybase/go-ps/process_unix.go144
-rw-r--r--vendor/github.com/keybase/go-ps/process_windows.go196
15 files changed, 1317 insertions, 0 deletions
diff --git a/vendor/github.com/keybase/go-ps/.gitignore b/vendor/github.com/keybase/go-ps/.gitignore
new file mode 100644
index 0000000..a977916
--- /dev/null
+++ b/vendor/github.com/keybase/go-ps/.gitignore
@@ -0,0 +1 @@
+.vagrant/
diff --git a/vendor/github.com/keybase/go-ps/.pre-commit-config.yaml b/vendor/github.com/keybase/go-ps/.pre-commit-config.yaml
new file mode 100644
index 0000000..b87b62d
--- /dev/null
+++ b/vendor/github.com/keybase/go-ps/.pre-commit-config.yaml
@@ -0,0 +1,10 @@
+- repo: https://github.com/gabriel/pre-commit-golang
+ sha: c02a81d85a5295886022b8106c367518e6c3760e
+ hooks:
+ - id: go-fmt
+ - id: go-metalinter
+ args:
+ - --deadline=60s
+ - --vendor
+ - --cyclo-over=20
+ - --dupl-threshold=100
diff --git a/vendor/github.com/keybase/go-ps/.travis.yml b/vendor/github.com/keybase/go-ps/.travis.yml
new file mode 100644
index 0000000..f5b919d
--- /dev/null
+++ b/vendor/github.com/keybase/go-ps/.travis.yml
@@ -0,0 +1,11 @@
+language: go
+go:
+ - tip
+os:
+ - linux
+ - osx
+before_install:
+ - go get github.com/mattn/goveralls
+ - go get golang.org/x/tools/cmd/cover
+script:
+ - $HOME/gopath/bin/goveralls -service=travis-ci
diff --git a/vendor/github.com/keybase/go-ps/LICENSE.md b/vendor/github.com/keybase/go-ps/LICENSE.md
new file mode 100644
index 0000000..83eb91b
--- /dev/null
+++ b/vendor/github.com/keybase/go-ps/LICENSE.md
@@ -0,0 +1,44 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Mitchell Hashimoto
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+
+The MIT License (MIT)
+
+Copyright (c) 2015 Keybase
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/keybase/go-ps/README.md b/vendor/github.com/keybase/go-ps/README.md
new file mode 100644
index 0000000..3d5762a
--- /dev/null
+++ b/vendor/github.com/keybase/go-ps/README.md
@@ -0,0 +1,31 @@
+# Process List Library for Go
+
+[![Build Status](https://travis-ci.org/keybase/go-ps.svg?branch=master)](https://travis-ci.org/keybase/go-ps)
+[![Build Status](https://ci.appveyor.com/api/projects/status/github/keybase/go-ps?branch=master&svg=true)](https://ci.appveyor.com/project/keybase/go-ps)
+[![Coverage Status](https://coveralls.io/repos/github/keybase/go-ps/badge.svg?branch=master)](https://coveralls.io/github/keybase/go-ps?branch=master)
+[![GoDoc](https://godoc.org/github.com/keybase/go-ps?status.svg)](https://godoc.org/github.com/keybase/go-ps)
+
+
+go-ps is a library for Go that implements OS-specific APIs to list and
+manipulate processes in a platform-safe way. The library can find and
+list processes on Linux, Mac OS X, and Windows.
+
+If you're new to Go, this library has a good amount of advanced Go educational
+value as well. It uses some advanced features of Go: build tags, accessing
+DLL methods for Windows, cgo for Darwin, etc.
+
+How it works:
+
+ * **Darwin** uses `sysctl` and `proc_listpids` (for the path) to retrieve the process table, via cgo.
+ * **Unix** uses the procfs at `/proc` to inspect the process tree.
+ * **Windows** uses the Windows API, and methods such as
+ `CreateToolhelp32Snapshot` to get a point-in-time snapshot of
+ the process table.
+
+## Installation
+
+Install using standard `go get`:
+
+```
+$ go get github.com/keybase/go-ps
+```
diff --git a/vendor/github.com/keybase/go-ps/appveyor.yml b/vendor/github.com/keybase/go-ps/appveyor.yml
new file mode 100644
index 0000000..59a98ac
--- /dev/null
+++ b/vendor/github.com/keybase/go-ps/appveyor.yml
@@ -0,0 +1,31 @@
+# environment variables
+environment:
+ global:
+ GOPATH: c:\work\
+
+# clone path
+clone_folder: c:\work\src\github.com\keybase\go-ps
+
+# build platform, i.e. x86, x64, Any CPU. This setting is optional.
+#platform: Any CPU
+
+# scripts to run before build
+before_build:
+
+# scripts to run after build
+after_build:
+
+# to run your custom scripts instead of automatic MSBuild
+build_script:
+ - go version
+ - go build
+ - go get github.com/stretchr/testify/assert
+ - go get github.com/stretchr/testify/require
+ - go test -short -v
+ - go test -short -race -v
+
+# to disable automatic tests
+test: off
+
+# to disable deployment
+deploy: off
diff --git a/vendor/github.com/keybase/go-ps/darwincgo/empty.go b/vendor/github.com/keybase/go-ps/darwincgo/empty.go
new file mode 100644
index 0000000..bc315c6
--- /dev/null
+++ b/vendor/github.com/keybase/go-ps/darwincgo/empty.go
@@ -0,0 +1 @@
+package darwincgo
diff --git a/vendor/github.com/keybase/go-ps/darwincgo/process_darwin.c b/vendor/github.com/keybase/go-ps/darwincgo/process_darwin.c
new file mode 100644
index 0000000..610a8ef
--- /dev/null
+++ b/vendor/github.com/keybase/go-ps/darwincgo/process_darwin.c
@@ -0,0 +1,87 @@
+// +build darwin
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <strings.h>
+#include <libproc.h>
+#include <unistd.h>
+#include <sys/sysctl.h>
+
+// This is declared in process_darwin.go
+extern void goDarwinAppendProc(pid_t, pid_t, char *);
+extern void goDarwinSetPath(pid_t, char *);
+
+// darwinProcesses loads the process table and calls the exported Go function to
+// insert the data back into the Go space.
+//
+// This function is implemented in C because while it would technically
+// be possible to do this all in Go, I didn't want to go spelunking through
+// header files to get all the structures properly. It is much easier to just
+// call it in C and be done with it.
+int darwinProcesses() {
+ int err = 0;
+ int i = 0;
+ static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
+ size_t length = 0;
+ struct kinfo_proc *result = NULL;
+ size_t resultCount = 0;
+
+ // Get the length first
+ err = sysctl((int*)name, (sizeof(name) / sizeof(*name)) - 1,
+ NULL, &length, NULL, 0);
+ if (err != 0) {
+ goto ERREXIT;
+ }
+
+ // Allocate the appropriate sized buffer to read the process list
+ result = malloc(length);
+
+ // Call sysctl again with our buffer to fill it with the process list
+ err = sysctl((int*)name, (sizeof(name) / sizeof(*name)) - 1,
+ result, &length,
+ NULL, 0);
+ if (err != 0) {
+ goto ERREXIT;
+ }
+
+ resultCount = length / sizeof(struct kinfo_proc);
+ for (i = 0; i < resultCount; i++) {
+ struct kinfo_proc *single = &result[i];
+ goDarwinAppendProc(
+ single->kp_proc.p_pid,
+ single->kp_eproc.e_ppid,
+ single->kp_proc.p_comm);
+ }
+
+ERREXIT:
+ if (result != NULL) {
+ free(result);
+ }
+
+ if (err != 0) {
+ return errno;
+ }
+ return 0;
+}
+
+// darwinProcessPaths looks up paths for process pids
+void darwinProcessPaths() {
+ int pid_buf_size = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
+ int pid_count = pid_buf_size / sizeof(pid_t);
+
+ pid_t* pids = malloc(pid_buf_size);
+ bzero(pids, pid_buf_size);
+
+ proc_listpids(PROC_ALL_PIDS, 0, pids, pid_buf_size);
+ char path_buffer[PROC_PIDPATHINFO_MAXSIZE];
+
+ for (int i=0; i < pid_count; i++) {
+ if (pids[i] == 0) break;
+ bzero(path_buffer, PROC_PIDPATHINFO_MAXSIZE);
+ if (proc_pidpath(pids[i], path_buffer, sizeof(path_buffer)) > 0) {
+ goDarwinSetPath(pids[i], path_buffer);
+ }
+ }
+ free(pids);
+}
diff --git a/vendor/github.com/keybase/go-ps/darwincgo/process_darwin.go b/vendor/github.com/keybase/go-ps/darwincgo/process_darwin.go
new file mode 100644
index 0000000..ab9edf4
--- /dev/null
+++ b/vendor/github.com/keybase/go-ps/darwincgo/process_darwin.go
@@ -0,0 +1,84 @@
+// +build darwin
+
+package darwincgo
+
+/*
+#include <stdio.h>
+#include <errno.h>
+#include <libproc.h>
+extern int darwinProcesses();
+extern void darwinProcessPaths();
+*/
+import "C"
+
+import (
+ "path/filepath"
+ "sync"
+)
+
+// This lock is what verifies that C calling back into Go is only
+// modifying data once at a time.
+var darwinLock sync.Mutex
+var darwinProcsByPID map[int]*DarwinProcess
+
+// DarwinProcess is process definition for OS X
+type DarwinProcess struct {
+ pid int
+ ppid int
+ path string
+}
+
+// Pid returns process id
+func (p *DarwinProcess) Pid() int {
+ return p.pid
+}
+
+// PPid returns parent process id
+func (p *DarwinProcess) PPid() int {
+ return p.ppid
+}
+
+// Executable returns process executable name
+func (p *DarwinProcess) Executable() string {
+ path, _ := p.Path()
+ return filepath.Base(path)
+}
+
+// Path returns path to process executable
+func (p *DarwinProcess) Path() (string, error) {
+ return p.path, nil
+}
+
+//export goDarwinAppendProc
+func goDarwinAppendProc(pid C.pid_t, ppid C.pid_t, comm *C.char) {
+ proc := &DarwinProcess{
+ pid: int(pid),
+ ppid: int(ppid),
+ }
+ darwinProcsByPID[proc.pid] = proc
+}
+
+//export goDarwinSetPath
+func goDarwinSetPath(pid C.pid_t, comm *C.char) {
+ if proc, ok := darwinProcsByPID[int(pid)]; ok && proc != nil {
+ proc.path = C.GoString(comm)
+ }
+}
+
+// ProcessMap returns a map of processes for the main library package.
+func ProcessMap() (map[int]*DarwinProcess, error) {
+ darwinLock.Lock()
+ defer darwinLock.Unlock()
+ darwinProcsByPID = make(map[int]*DarwinProcess)
+
+ // To ignore deadcode warnings for exported functions
+ _ = goDarwinAppendProc
+ _ = goDarwinSetPath
+
+ // TODO: Investigate why darwinProcesses returns error even if process list
+ // succeeds
+ C.darwinProcesses()
+ C.darwinProcessPaths()
+
+ return darwinProcsByPID, nil
+}
diff --git a/vendor/github.com/keybase/go-ps/process.go b/vendor/github.com/keybase/go-ps/process.go
new file mode 100644
index 0000000..042cd1b
--- /dev/null
+++ b/vendor/github.com/keybase/go-ps/process.go
@@ -0,0 +1,75 @@
+// Package ps provides an API for finding and listing processes in a
+// platform-agnostic way.
+//
+// NOTE: If you're reading these docs online via GoDocs or some other system,
+// you might only see the Unix docs. This project makes heavy use of
+// platform-specific implementations. We recommend reading the source if you
+// are interested.
+package ps
+
+import "fmt"
+
+// Process is the generic interface that is implemented on every platform
+// and provides common operations for processes.
+type Process interface {
+ // Pid is the process ID for this process.
+ Pid() int
+
+ // PPid is the parent process ID for this process.
+ PPid() int
+
+ // Executable name running this process. This is not a path to the
+ // executable.
+ Executable() string
+
+ // Path is full path to the executable. The path may be unavailable if the
+ // exectuable was deleted from the system while it was still running.
+ Path() (string, error)
+}
+
+type processesFn func() ([]Process, error)
+
+// Processes returns all processes.
+//
+// This of course will be a point-in-time snapshot of when this method was
+// called. Some operating systems don't provide snapshot capability of the
+// process table, in which case the process table returned might contain
+// ephemeral entities that happened to be running when this was called.
+func Processes() ([]Process, error) {
+ return processes()
+}
+
+// FindProcess looks up a single process by pid.
+// This may require a full process listing depending on the platform, so
+// consider using os.FindProcess instead.
+// Process will be nil and error will be nil if a matching process is not found.
+func FindProcess(pid int) (Process, error) {
+ return findProcess(pid)
+}
+
+type matchFn func(Process) bool
+
+// findProcessesWithFn finds processes using match function.
+// If max is != 0, then we will return that max number of processes.
+func findProcessesWithFn(processesFn processesFn, matchFn matchFn, max int) ([]Process, error) {
+ processes, err := processesFn()
+ if err != nil {
+ return nil, fmt.Errorf("Error listing processes: %s", err)
+ }
+ if processes == nil {
+ return nil, nil
+ }
+ procs := []Process{}
+ for _, p := range processes {
+ if matchFn(p) {
+ procs = append(procs, p)
+ }
+ if max != 0 && len(procs) >= max {
+ break
+ }
+ }
+ return procs, nil
+}
+
+// Avoid linting error
+var _ = findProcessesWithFn
diff --git a/vendor/github.com/keybase/go-ps/process_darwin.go b/vendor/github.com/keybase/go-ps/process_darwin.go
new file mode 100644
index 0000000..02cfa79
--- /dev/null
+++ b/vendor/github.com/keybase/go-ps/process_darwin.go
@@ -0,0 +1,31 @@
+// +build darwin
+
+package ps
+
+import (
+ "github.com/keybase/go-ps/darwincgo"
+)
+
+func findProcess(pid int) (Process, error) {
+ m, err := darwincgo.ProcessMap()
+ if err != nil {
+ return nil, err
+ }
+ p := m[pid]
+ if p == nil {
+ return nil, nil
+ }
+ return p, nil
+}
+
+func processes() ([]Process, error) {
+ m, err := darwincgo.ProcessMap()
+ if err != nil {
+ return nil, err
+ }
+ ps := make([]Process, 0, len(m))
+ for _, dp := range m {
+ ps = append(ps, dp)
+ }
+ return ps, nil
+}
diff --git a/vendor/github.com/keybase/go-ps/process_freebsd.go b/vendor/github.com/keybase/go-ps/process_freebsd.go
new file mode 100644
index 0000000..33942c8
--- /dev/null
+++ b/vendor/github.com/keybase/go-ps/process_freebsd.go
@@ -0,0 +1,269 @@
+// +build freebsd,amd64
+
+package ps
+
+import (
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "syscall"
+ "unsafe"
+)
+
+// copied from sys/sysctl.h
+const (
+ CTL_KERN = 1 // "high kernel": proc, limits
+ KERN_PROC = 14 // struct: process entries
+ KERN_PROC_PID = 1 // by process id
+ KERN_PROC_PROC = 8 // only return procs
+ KERN_PROC_PATHNAME = 12 // path to executable
+)
+
+// copied from sys/user.h
+type Kinfo_proc struct {
+ Ki_structsize int32
+ Ki_layout int32
+ Ki_args int64
+ Ki_paddr int64
+ Ki_addr int64
+ Ki_tracep int64
+ Ki_textvp int64
+ Ki_fd int64
+ Ki_vmspace int64
+ Ki_wchan int64
+ Ki_pid int32
+ Ki_ppid int32
+ Ki_pgid int32
+ Ki_tpgid int32
+ Ki_sid int32
+ Ki_tsid int32
+ Ki_jobc [2]byte
+ Ki_spare_short1 [2]byte
+ Ki_tdev int32
+ Ki_siglist [16]byte
+ Ki_sigmask [16]byte
+ Ki_sigignore [16]byte
+ Ki_sigcatch [16]byte
+ Ki_uid int32
+ Ki_ruid int32
+ Ki_svuid int32
+ Ki_rgid int32
+ Ki_svgid int32
+ Ki_ngroups [2]byte
+ Ki_spare_short2 [2]byte
+ Ki_groups [64]byte
+ Ki_size int64
+ Ki_rssize int64
+ Ki_swrss int64
+ Ki_tsize int64
+ Ki_dsize int64
+ Ki_ssize int64
+ Ki_xstat [2]byte
+ Ki_acflag [2]byte
+ Ki_pctcpu int32
+ Ki_estcpu int32
+ Ki_slptime int32
+ Ki_swtime int32
+ Ki_cow int32
+ Ki_runtime int64
+ Ki_start [16]byte
+ Ki_childtime [16]byte
+ Ki_flag int64
+ Ki_kiflag int64
+ Ki_traceflag int32
+ Ki_stat [1]byte
+ Ki_nice [1]byte
+ Ki_lock [1]byte
+ Ki_rqindex [1]byte
+ Ki_oncpu [1]byte
+ Ki_lastcpu [1]byte
+ Ki_ocomm [17]byte
+ Ki_wmesg [9]byte
+ Ki_login [18]byte
+ Ki_lockname [9]byte
+ Ki_comm [20]byte
+ Ki_emul [17]byte
+ Ki_sparestrings [68]byte
+ Ki_spareints [36]byte
+ Ki_cr_flags int32
+ Ki_jid int32
+ Ki_numthreads int32
+ Ki_tid int32
+ Ki_pri int32
+ Ki_rusage [144]byte
+ Ki_rusage_ch [144]byte
+ Ki_pcb int64
+ Ki_kstack int64
+ Ki_udata int64
+ Ki_tdaddr int64
+ Ki_spareptrs [48]byte
+ Ki_spareint64s [96]byte
+ Ki_sflag int64
+ Ki_tdflags int64
+}
+
+// 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) {
+ 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)}
+
+ buf, length, err := call_syscall(mib)
+ if err != nil {
+ return err
+ }
+ proc_k := Kinfo_proc{}
+ if length != uint64(unsafe.Sizeof(proc_k)) {
+ 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_pgid), int(k.Ki_sid), comm
+}
+
+func findProcess(pid int) (Process, error) {
+ mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, int32(pid)}
+
+ _, _, 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_PROC, 0}
+ buf, length, err := call_syscall(mib)
+ if err != nil {
+ return results, err
+ }
+
+ // get kinfo_proc size
+ k := Kinfo_proc{}
+ procinfo_len := int(unsafe.Sizeof(k))
+ count := int(length / uint64(procinfo_len))
+
+ // 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()
+}
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()
+}
diff --git a/vendor/github.com/keybase/go-ps/process_unix.go b/vendor/github.com/keybase/go-ps/process_unix.go
new file mode 100644
index 0000000..8c89b7e
--- /dev/null
+++ b/vendor/github.com/keybase/go-ps/process_unix.go
@@ -0,0 +1,144 @@
+// +build linux netbsd
+
+package ps
+
+import (
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strconv"
+ "strings"
+)
+
+// 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 // binary name might be truncated
+}
+
+// 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 {
+ path, err := p.Path()
+ if err != nil {
+ // Fall back to binary name which might be truncated
+ return p.binary
+ }
+ return filepath.Base(path)
+}
+
+// Path returns path to process executable
+func (p *UnixProcess) Path() (string, error) {
+ return filepath.EvalSymlinks(fmt.Sprintf("/proc/%d/exe", p.pid))
+}
+
+// Refresh reloads all the data associated with this process.
+func (p *UnixProcess) Refresh() error {
+ statPath := fmt.Sprintf("/proc/%d/stat", p.pid)
+ dataBytes, err := ioutil.ReadFile(statPath)
+ if err != nil {
+ return err
+ }
+
+ // First, parse out the image name
+ data := string(dataBytes)
+ binStart := strings.IndexRune(data, '(') + 1
+ binEnd := strings.IndexRune(data[binStart:], ')')
+ p.binary = data[binStart : binStart+binEnd]
+
+ // Move past the image name and start parsing the rest
+ // The name here might not be the full name
+ data = data[binStart+binEnd+2:]
+ _, err = fmt.Sscanf(data,
+ "%c %d %d %d",
+ &p.state,
+ &p.ppid,
+ &p.pgrp,
+ &p.sid)
+
+ return err
+}
+
+func findProcess(pid int) (Process, error) {
+ dir := fmt.Sprintf("/proc/%d", pid)
+ _, err := os.Stat(dir)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return nil, nil
+ }
+
+ return nil, err
+ }
+
+ return newUnixProcess(pid)
+}
+
+func processes() ([]Process, error) {
+ d, err := os.Open("/proc")
+ if err != nil {
+ return nil, err
+ }
+ defer d.Close()
+
+ results := make([]Process, 0, 50)
+ for {
+ fis, err := d.Readdir(10)
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ for _, fi := range fis {
+ // We only care about directories, since all pids are dirs
+ if !fi.IsDir() {
+ continue
+ }
+
+ // We only care if the name starts with a numeric
+ name := fi.Name()
+ if name[0] < '0' || name[0] > '9' {
+ continue
+ }
+
+ // From this point forward, any errors we just ignore, because
+ // it might simply be that the process doesn't exist anymore.
+ pid, err := strconv.ParseInt(name, 10, 0)
+ if err != nil {
+ continue
+ }
+
+ p, err := newUnixProcess(int(pid))
+ if err != nil {
+ continue
+ }
+
+ results = append(results, p)
+ }
+ }
+
+ return results, nil
+}
+
+func newUnixProcess(pid int) (*UnixProcess, error) {
+ p := &UnixProcess{pid: pid}
+ return p, p.Refresh()
+}
diff --git a/vendor/github.com/keybase/go-ps/process_windows.go b/vendor/github.com/keybase/go-ps/process_windows.go
new file mode 100644
index 0000000..e4d89e3
--- /dev/null
+++ b/vendor/github.com/keybase/go-ps/process_windows.go
@@ -0,0 +1,196 @@
+// +build windows
+
+package ps
+
+import (
+ "fmt"
+ "syscall"
+ "unsafe"
+)
+
+// Windows API functions
+var (
+ modKernel32 = syscall.NewLazyDLL("kernel32.dll")
+ procCloseHandle = modKernel32.NewProc("CloseHandle")
+ procCreateToolhelp32Snapshot = modKernel32.NewProc("CreateToolhelp32Snapshot")
+ procProcess32First = modKernel32.NewProc("Process32FirstW")
+ procProcess32Next = modKernel32.NewProc("Process32NextW")
+ procModule32First = modKernel32.NewProc("Module32FirstW")
+ procModule32Next = modKernel32.NewProc("Module32NextW")
+)
+
+// Some constants from the Windows API
+const (
+ ERROR_NO_MORE_FILES = 0x12
+ MAX_PATH = 260
+ MAX_MODULE_NAME32 = 255
+)
+
+type PROCESSENTRY32 struct {
+ Size uint32
+ CntUsage uint32
+ ProcessID uint32
+ DefaultHeapID uintptr
+ ModuleID uint32
+ CntThreads uint32
+ ParentProcessID uint32
+ PriorityClassBase int32
+ Flags uint32
+ ExeFile [MAX_PATH]uint16
+}
+
+// WindowsProcess is an implementation of Process for Windows.
+type WindowsProcess struct {
+ pid int
+ ppid int
+ exe string
+}
+
+// Pid returns process id
+func (p *WindowsProcess) Pid() int {
+ return p.pid
+}
+
+// PPid returns parent process id
+func (p *WindowsProcess) PPid() int {
+ return p.ppid
+}
+
+// Executable returns process executable name
+func (p *WindowsProcess) Executable() string {
+ return p.exe
+}
+
+// Path returns path to process executable
+func (p *WindowsProcess) Path() (string, error) {
+ processModules, err := modules(p.pid)
+ if err != nil {
+ return "", err
+ }
+ if len(processModules) == 0 {
+ return "", fmt.Errorf("No modules found for process")
+ }
+ return processModules[0].path, nil
+}
+
+func ptrToString(c []uint16) string {
+ i := 0
+ for {
+ if c[i] == 0 {
+ return syscall.UTF16ToString(c[:i])
+ }
+ i++
+ }
+}
+
+func newWindowsProcess(e *PROCESSENTRY32) *WindowsProcess {
+ return &WindowsProcess{
+ pid: int(e.ProcessID),
+ ppid: int(e.ParentProcessID),
+ exe: ptrToString(e.ExeFile[:]),
+ }
+}
+
+func findProcess(pid int) (Process, error) {
+ return findProcessWithFn(processes, pid)
+}
+
+func findProcessWithFn(processesFn processesFn, pid int) (Process, error) {
+ ps, err := processesFn()
+ if err != nil {
+ return nil, fmt.Errorf("Error listing processes: %s", err)
+ }
+
+ for _, p := range ps {
+ if p.Pid() == pid {
+ return p, nil
+ }
+ }
+
+ return nil, nil
+}
+
+func processes() ([]Process, error) {
+ handle, _, _ := procCreateToolhelp32Snapshot.Call(
+ 0x00000002,
+ 0)
+ if handle < 0 {
+ return nil, syscall.GetLastError()
+ }
+ defer procCloseHandle.Call(handle)
+
+ var entry PROCESSENTRY32
+ entry.Size = uint32(unsafe.Sizeof(entry))
+ ret, _, _ := procProcess32First.Call(handle, uintptr(unsafe.Pointer(&entry)))
+ if ret == 0 {
+ return nil, fmt.Errorf("Error retrieving process info.")
+ }
+
+ results := make([]Process, 0, 50)
+ for {
+ results = append(results, newWindowsProcess(&entry))
+
+ ret, _, _ := procProcess32Next.Call(handle, uintptr(unsafe.Pointer(&entry)))
+ if ret == 0 {
+ break
+ }
+ }
+
+ return results, nil
+}
+
+// MODULEENTRY32 is the Windows API structure that contains a modules's
+// information.
+type MODULEENTRY32 struct {
+ Size uint32
+ ModuleID uint32
+ ProcessID uint32
+ GlblcntUsage uint32
+ ProccntUsage uint32
+ ModBaseAddr *uint8
+ ModBaseSize uint32
+ HModule uintptr
+ SzModule [MAX_MODULE_NAME32 + 1]uint16
+ SzExePath [MAX_PATH]uint16
+}
+
+type windowsModule struct {
+ name string
+ path string
+}
+
+func newWindowsModule(e *MODULEENTRY32) windowsModule {
+ return windowsModule{
+ name: ptrToString(e.SzModule[:]),
+ path: ptrToString(e.SzExePath[:]),
+ }
+}
+
+func modules(pid int) ([]windowsModule, error) {
+ handle, _, _ := procCreateToolhelp32Snapshot.Call(
+ 0x00000008, // TH32CS_SNAPMODULE
+ uintptr(uint32(pid)))
+ if handle < 0 {
+ return nil, syscall.GetLastError()
+ }
+ defer procCloseHandle.Call(handle)
+
+ var entry MODULEENTRY32
+ entry.Size = uint32(unsafe.Sizeof(entry))
+ ret, _, _ := procModule32First.Call(handle, uintptr(unsafe.Pointer(&entry)))
+ if ret == 0 {
+ return nil, fmt.Errorf("Error retrieving module info")
+ }
+
+ results := make([]windowsModule, 0, 50)
+ for {
+ results = append(results, newWindowsModule(&entry))
+
+ ret, _, _ := procModule32Next.Call(handle, uintptr(unsafe.Pointer(&entry)))
+ if ret == 0 {
+ break
+ }
+ }
+
+ return results, nil
+}