go_sysutils/funcs.go

265 lines
4.7 KiB
Go

package sysutils
import (
`bytes`
`errors`
`fmt`
`io/ioutil`
`os`
`runtime`
`strconv`
`strings`
`r00t2.io/sysutils/paths`
)
/*
EnvMapper contains the environment variables as grouped by their basic type.
If a variable's type cannot be determined, it's placed in Strings.
If a variable's type is a list, it will be an []interface{} as each item may be a different variable type.
It essentially is the same as EnvMap except with the types split out for convenience.
*/
type EnvMapper struct {
Booleans map[string]bool `json:"bools"`
Numbers map[string]int `json:"nums"`
Strings map[string]string `json:"strings"`
Lists map[string][]interface{} `json:"lists"`
}
// GetEnvMapper returns a pointer to a populated EnvMapper.
func GetEnvMapper() (e *EnvMapper, err error) {
var em map[string]interface{}
var env EnvMapper
env = EnvMapper{
Booleans: nil,
Numbers: nil,
Strings: nil,
Lists: nil,
}
for k, v := range em {
switch t := v.(type) {
case bool:
if env.Booleans == nil {
env.Booleans = make(map[string]bool, 0)
}
env.Booleans[k] = t
continue
case int:
if env.Numbers == nil {
env.Numbers = make(map[string]int, 0)
}
env.Numbers[k] = t
continue
case []interface{}:
if env.Lists == nil {
env.Lists = make(map[string][]interface{}, 0)
}
env.Lists[k] = t
case string: // the "default" since everything could probably be typeswitched to a string otherwise.
if env.Strings == nil {
env.Strings = make(map[string]string, 0)
}
env.Strings[k] = t
}
}
*e = env
return
}
/*
EnvMap returns a map of environment variables.
The variable is an interface due to it attempting to use a variable's value to its "true" native type.
If a type cannot be determined, it will be treated a string.
*/
func EnvMap() (envs map[string]interface{}, err error) {
var ems map[string]string
if ems, err = EnvMapString(); err != nil {
return
}
for k, v := range ems {
// Is int?
if i, ok := getNum(v); ok {
envs[k] = i
continue
}
// Is bool?
if b, ok := getBool(v); ok {
envs[k] = b
continue
}
// Is array?
if a, ok := getArr(v); ok {
envs[k] = a
continue
}
// It's a string (probably).
envs[k] = v
}
return
}
// EnvMapString is like EnvMap, but all values are treated as strings.
func EnvMapString() (envs map[string]string, err error) {
var envArray []string
envs = make(map[string]string, 0)
envArray = os.Environ()
for _, e := range envArray {
var k, v string
var kv []string
kv = strings.SplitN(e, "=", 2)
k = kv[0]
if len(kv) == 2 {
v = kv[1]
} else {
v = ""
}
envs[k] = v
}
return
}
// UTILITY FUNCS
// getBool attempts to convert a string value to a boolean.
func getBool(s string) (b bool, ok bool) {
switch s2 := strings.ToLower(strings.TrimSpace(s)); s2 {
case "true", "yes", "y":
b = true
ok = true
case "false", "no", "n":
b = false
ok = true
}
return
}
// getNum attempts to convert a string value to an int.
func getNum(s string) (n int, ok bool) {
var err error
if n, err = strconv.Atoi(s); err == nil {
ok = true
}
return
}
// getArr attempts to convert a string value to an array of interface{}.
func getArr(s string) (a []interface{}, ok bool) {
var arrS []string
if arrS, ok = getArrStr(s); !ok {
return
}
a = make([]interface{}, len(arrS))
for idx, i := range arrS {
if b, ok := getBool(i); ok {
a[idx] = b
} else if n, ok := getNum(i); ok {
a[idx] = n
} else if l, ok := getArr(i); ok {
a[idx] = l
} else {
a[idx] = i
}
}
return
}
// getArrStr attempts to convert a string value to an array of strings.
func getArrStr(s string) (a []string, ok bool) {
var sep string = ":"
if runtime.GOOS == "windows" {
sep = ";"
}
a = strings.Split(s, sep)
l := len(s)
if l <= 1 {
return
}
ok = true
return
}
/*
GetEnvPid will only work on *NIX-like systems with procfs.
It gets the environment variables of a given process' PID.
*/
func GetEnvPid(pid uint32) (env map[string]string, err error) {
var envBytes []byte
var envArr [][]byte
var procPath string
var exists bool
env = make(map[string]string, 0)
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 = ioutil.ReadFile(procPath); err != nil {
return
}
envArr = bytes.Split(envBytes, []byte{0x0})
for _, b := range envArr {
// s := strings.TrimSpace(string(b))
s := string(b)
e := strings.SplitN(s, "=", 2)
for _, i := range e {
if len(i) != 2 {
env[string(i[0])] = ""
continue
}
env[string(i[0])] = string(i[1])
}
}
return
}