Permalink
Browse files

ProcArgs - get process arguments

Change-Id: I3563d3f4813f8097bc4d55293d322cd838413499
  • Loading branch information...
1 parent 05d8279 commit ffca5cfefc77761e3114e30683fbd42421989856 @dougm dougm committed Aug 9, 2012
Showing with 137 additions and 0 deletions.
  1. +4 −0 sigar.go
  2. +94 −0 sigar_darwin.go
  3. +23 −0 sigar_linux.go
  4. +12 −0 sigar_test.go
  5. +4 −0 sigar_util.go
View
@@ -86,3 +86,7 @@ type ProcTime struct {
Sys uint64
Total uint64
}
+
+type ProcArgs struct {
+ List []string
+}
View
@@ -17,6 +17,7 @@ import (
"bytes"
"encoding/binary"
"fmt"
+ "io"
"syscall"
"time"
"unsafe"
@@ -217,6 +218,99 @@ func (self *ProcTime) Get(pid int) error {
return nil
}
+func (self *ProcArgs) Get(pid int) error {
+ var args []string
+
+ argv := func(arg string) {
+ args = append(args, arg)
+ }
+
+ err := kern_procargs(pid, nil, argv, nil)
+
+ self.List = args
+
+ return err
+}
+
+// wrapper around sysctl KERN_PROCARGS2
+// callbacks params are optional,
+// up to the caller as to which pieces of data they want
+func kern_procargs(pid int,
+ exe func(string),
+ argv func(string),
+ env func(string, string)) error {
+
+ mib := []C.int{C.CTL_KERN, C.KERN_PROCARGS2, C.int(pid)}
+ argmax := uintptr(C.ARG_MAX)
+ buf := make([]byte, argmax)
+ err := sysctl(mib, &buf[0], &argmax, nil, 0)
+ if err != nil {
+ return nil
+ }
+
+ bbuf := bytes.NewBuffer(buf)
+ bbuf.Truncate(int(argmax))
+
+ var argc int32
+ binary.Read(bbuf, binary.LittleEndian, &argc)
+
+ path, err := bbuf.ReadBytes(0)
+ if exe != nil {
+ exe(string(chop(path)))
+ }
+
+ // skip trailing \0's
+ for {
+ c, _ := bbuf.ReadByte()
+ if c != 0 {
+ bbuf.UnreadByte()
+ break // start of argv[0]
+ }
+ }
+
+ for i := 0; i < int(argc); i++ {
+ arg, err := bbuf.ReadBytes(0)
+ if err == io.EOF {
+ break
+ }
+ if argv != nil {
+ argv(string(chop(arg)))
+ }
+ }
+
+ if env == nil {
+ return nil
+ }
+
+ delim := []byte{61} // "="
+
+ for {
+ line, err := bbuf.ReadBytes(0)
+ if err == io.EOF || line[0] == 0 {
+ break
+ }
+ pair := bytes.SplitN(chop(line), delim, 2)
+ env(string(pair[0]), string(pair[1]))
+ }
+
+ return nil
+}
+
+// XXX copied from zsyscall_darwin_amd64.go
+func sysctl(mib []C.int, old *byte, oldlen *uintptr,
+ new *byte, newlen uintptr) (err error) {
+ var p0 unsafe.Pointer
+ p0 = unsafe.Pointer(&mib[0])
+ _, _, e1 := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(p0),
+ uintptr(len(mib)),
+ uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)),
+ uintptr(unsafe.Pointer(new)), uintptr(newlen))
+ if e1 != 0 {
+ err = e1
+ }
+ return
+}
+
func vm_info(vmstat *C.vm_statistics_data_t) error {
var count C.mach_msg_type_number_t = C.HOST_VM_INFO_COUNT
View
@@ -233,6 +233,29 @@ func (self *ProcTime) Get(pid int) error {
return nil
}
+func (self *ProcArgs) Get(pid int) error {
+ contents, err := readProcFile(pid, "cmdline")
+ if err != nil {
+ return err
+ }
+
+ bbuf := bytes.NewBuffer(contents)
+
+ var args []string
+
+ for {
+ arg, err := bbuf.ReadBytes(0)
+ if err == io.EOF {
+ break
+ }
+ args = append(args, string(chop(arg)))
+ }
+
+ self.List = args
+
+ return nil
+}
+
func parseMeminfo(table map[string]*uint64) error {
return readFile(procd+"meminfo", func(line string) bool {
fields := strings.Split(line, ":")
View
@@ -142,3 +142,15 @@ func TestProcTime(t *testing.T) {
t.Error("Invalid ProcTime.Get('%d')", invalidPid)
}
}
+
+func TestProcArgs(t *testing.T) {
+ args := ProcArgs{}
+ err := args.Get(os.Getppid())
+ if err != nil {
+ t.Error(err)
+ }
+
+ if len(args.List) < 2 {
+ t.Errorf("invalid ProcArgs %s", args.List)
+ }
+}
View
@@ -16,3 +16,7 @@ func bytePtrToString(ptr *int8) string {
return string(bytes[0:n])
}
+
+func chop(buf []byte) []byte {
+ return buf[0 : len(buf)-1]
+}

0 comments on commit ffca5cf

Please sign in to comment.