brent saner 803be548cf
v1.15.0
* IDState cleaned up. Should work on all *NIXes now.
* Can now get IDState of arbitrary PID.
* Shuffled some env stuff around.
2025-11-07 23:11:47 -05:00

161 lines
3.0 KiB
Go

package internal
import (
`bytes`
`errors`
`fmt`
`os`
"runtime"
"strconv"
"strings"
`r00t2.io/sysutils/paths`
)
// EnvListToMap splits a []string of env var keypairs to a map.
func EnvListToMap(envs []string) (envMap map[string]string) {
var kv []string
var k, v string
envMap = make(map[string]string)
for _, ev := range envs {
kv = strings.SplitN(ev, "=", 2)
// I *think* SplitN does this for me, but...
if len(kv) == 1 {
kv = append(kv, "")
}
k = kv[0]
v = kv[1]
envMap[k] = v
}
return
}
// GetPathEnv returns a slice of the PATH variable's items.
func GetPathEnv() (pathList []string, err error) {
var pathVar string = GetPathEnvName()
pathList = make([]string, 0)
for _, p := range strings.Split(os.Getenv(pathVar), string(os.PathListSeparator)) {
if err = paths.RealPath(&p); err != nil {
return
}
pathList = append(pathList, p)
}
return
}
/*
GetPidEnvMap will only work on *NIX-like systems with procfs.
It gets the environment variables of a given process' PID.
*/
func GetPidEnvMap(pid uint32) (envMap map[string]string, err error) {
var envBytes []byte
var envList []string
var envArr [][]byte
var procPath string
var exists bool
envMap = make(map[string]string)
procPath = fmt.Sprintf("/proc/%v/environ", pid)
if exists, err = paths.RealPathExists(&procPath); err != nil {
return
}
if !exists {
err = errors.New(fmt.Sprintf("information for pid %v does not exist", pid))
return
}
if envBytes, err = os.ReadFile(procPath); err != nil {
return
}
envArr = bytes.Split(envBytes, []byte{0x0})
envList = make([]string, len(envArr))
for idx, b := range envArr {
envList[idx] = string(b)
}
envMap = EnvListToMap(envList)
return
}
// GetPathEnvName gets the OS-specific path environment variable name.
func GetPathEnvName() (envVarName string) {
var ok bool
if envVarName, ok = pathEnvVarName[runtime.GOOS]; !ok {
// *NIX/the default.
envVarName = "PATH"
}
return
}
// NativizeEnvMap returns a native-typed env map from a string version.
func NativizeEnvMap(stringMap map[string]string) (envMap map[string]interface{}) {
var pathVar string = GetPathEnvName()
var err error
envMap = make(map[string]interface{})
for k, v := range stringMap {
// Check for PATH/Path - we handle this uniquely.
if k == pathVar {
if envMap[k], err = GetPathEnv(); err != nil {
envMap[k] = v
err = nil
}
continue
}
// It might be...
// a float
if reMaybeFloat.MatchString(v) {
if envMap[k], err = strconv.ParseFloat(v, 64); err == nil {
continue
}
err = nil
}
// an int
if reMaybeInt.MatchString(v) {
if envMap[k], err = strconv.Atoi(v); err == nil {
continue
}
err = nil
}
// a uint
if envMap[k], err = strconv.ParseUint(v, 10, 64); err == nil {
continue
} else {
err = nil
}
// a boolean
if envMap[k], err = strconv.ParseBool(v); err == nil {
continue
} else {
err = nil
}
// ok so... guess it's a string, then.
envMap[k] = v
}
return
}