From f02767f72b9a352932239a808defa10998bfbf39 Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Tue, 10 Jan 2017 16:49:00 -0500 Subject: [PATCH] Add sigar.ProcEnv for getting a process's environment This PR adds the ability to retrieve the environment variables used to start a process. It is implemented for Linux, OS X, and FreeBSD. Neither Windows nor OpenBSD are implemented at this time. Closes #61 --- CHANGELOG.md | 1 + README.md | 1 + sigar_darwin.go | 12 ++++++++++++ sigar_interface.go | 4 ++++ sigar_interface_test.go | 11 +++++++++++ sigar_linux_common.go | 28 ++++++++++++++++++++++++++++ sigar_openbsd.go | 4 ++++ sigar_windows.go | 4 ++++ 8 files changed, 65 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cc18f0cd..65b588962 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Added support to `github.com/gosigar/sys/windows` for querying and enabling privileges in a process token. - Added utility code for interfacing with linux NETLINK_INET_DIAG. #60 +- Added `ProcEnv` for getting a process's environment variables. #61 ### Changed - Changed several `OpenProcess` calls on Windows to request the lowest possible diff --git a/README.md b/README.md index c701aad71..2482620a8 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ The features vary by operating system. | LoadAverage | X | X | | X | X | | Mem | X | X | X | X | X | | ProcArgs | X | X | X | | X | +| ProcEnv | X | X | | | X | | ProcExe | X | X | | | X | | ProcFDUsage | X | | | | X | | ProcList | X | X | X | | X | diff --git a/sigar_darwin.go b/sigar_darwin.go index 3a9921cf6..d90c15eeb 100644 --- a/sigar_darwin.go +++ b/sigar_darwin.go @@ -326,6 +326,18 @@ func (self *ProcArgs) Get(pid int) error { return err } +func (self *ProcEnv) Get(pid int) error { + if self.Vars == nil { + self.Vars = map[string]string{} + } + + env := func(k, v string) { + self.Vars[k] = v + } + + return kern_procargs(pid, nil, nil, env) +} + func (self *ProcExe) Get(pid int) error { exe := func(arg string) { self.Name = arg diff --git a/sigar_interface.go b/sigar_interface.go index 9f0e4d771..6ab5afb37 100644 --- a/sigar_interface.go +++ b/sigar_interface.go @@ -160,6 +160,10 @@ type ProcArgs struct { List []string } +type ProcEnv struct { + Vars map[string]string +} + type ProcExe struct { Name string Cwd string diff --git a/sigar_interface_test.go b/sigar_interface_test.go index 77dc8b312..efaa3ae92 100644 --- a/sigar_interface_test.go +++ b/sigar_interface_test.go @@ -128,6 +128,17 @@ func TestProcArgs(t *testing.T) { } } +func TestProcEnv(t *testing.T) { + env := &ProcEnv{} + if assert.NoError(t, skipNotImplemented(t, env.Get(os.Getpid()), "windows", "openbsd")) { + assert.True(t, len(env.Vars) > 0, "env is empty") + + for k, v := range env.Vars { + assert.Equal(t, os.Getenv(k), v) + } + } +} + func TestProcExe(t *testing.T) { exe := ProcExe{} if assert.NoError(t, skipNotImplemented(t, exe.Get(os.Getppid()), "windows")) { diff --git a/sigar_linux_common.go b/sigar_linux_common.go index 24b096aeb..7753a7e79 100644 --- a/sigar_linux_common.go +++ b/sigar_linux_common.go @@ -305,6 +305,34 @@ func (self *ProcArgs) Get(pid int) error { return nil } +func (self *ProcEnv) Get(pid int) error { + contents, err := readProcFile(pid, "environ") + if err != nil { + return err + } + + if self.Vars == nil { + self.Vars = map[string]string{} + } + + pairs := bytes.Split(contents, []byte{0}) + for _, kv := range pairs { + parts := bytes.SplitN(kv, []byte{'='}, 2) + if len(parts) != 2 { + continue + } + + key := string(bytes.TrimSpace(parts[0])) + if key == "" { + continue + } + + self.Vars[key] = string(bytes.TrimSpace(parts[1])) + } + + return nil +} + func (self *ProcExe) Get(pid int) error { fields := map[string]*string{ "exe": &self.Name, diff --git a/sigar_openbsd.go b/sigar_openbsd.go index 68cbb61c7..847b6dfc6 100644 --- a/sigar_openbsd.go +++ b/sigar_openbsd.go @@ -357,6 +357,10 @@ func (self *ProcArgs) Get(pid int) error { return nil } +func (self *ProcEnv) Get(pid int) error { + return ErrNotImplemented{runtime.GOOS} +} + func (self *ProcState) Get(pid int) error { return nil } diff --git a/sigar_windows.go b/sigar_windows.go index d1d40bd52..c5f665d92 100644 --- a/sigar_windows.go +++ b/sigar_windows.go @@ -67,6 +67,10 @@ func (self *FDUsage) Get() error { return ErrNotImplemented{runtime.GOOS} } +func (self *ProcEnv) Get(pid int) error { + return ErrNotImplemented{runtime.GOOS} +} + func (self *ProcExe) Get(pid int) error { return ErrNotImplemented{runtime.GOOS} }