3 Commits

3 changed files with 177 additions and 26 deletions

12
TODO
View File

@@ -2,12 +2,24 @@
-- incorporate with https://github.com/tredoe/osutil ? -- incorporate with https://github.com/tredoe/osutil ?
-- cli flag to dump flat hashes too -- cli flag to dump flat hashes too
--- https://github.com/hlandau/passlib --- https://github.com/hlandau/passlib
-- incoprporated separately; https://git.r00t2.io/r00t2/PWGen (import r00t2.io/pwgen)
- unit tests - unit tests
- constants/vars for errors - constants/vars for errors
- func and struct to return segregated system-level env vars vs. user env vars (mostly usable on windows) (see envs/.TODO.go.UNFINISHED) - func and struct to return segregated system-level env vars vs. user env vars (mostly usable on windows) (see envs/.TODO.go.UNFINISHED)
-- https://www3.ntu.edu.sg/home/ehchua/programming/howto/Environment_Variables.html
-- windows:
--- https://docs.microsoft.com/en-us/windows/deployment/usmt/usmt-recognized-environment-variables
--- https://pureinfotech.com/list-environment-variables-windows-10/
--- https://gist.github.com/RebeccaWhit3/5dad8627b8227142e1bea432db3f8824
--- https://ss64.com/nt/syntax-variables.html
-- linux/XDG:
--- https://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html
--- https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
-- macOS:
--- https://ss64.com/osx/syntax-env_vars.html
- validator for windows usernames, domains, etc. (for *NIX, https://unix.stackexchange.com/a/435120/284004) - validator for windows usernames, domains, etc. (for *NIX, https://unix.stackexchange.com/a/435120/284004)
-- https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/naming-conventions-for-computer-domain-site-ou -- https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/naming-conventions-for-computer-domain-site-ou

View File

@@ -61,6 +61,59 @@ func GetEnvMapNative() (envMap map[string]interface{}) {
return return
} }
/*
GetFirst gets the first instance if populated/set occurrence of varNames.
For example, if you have three potential env vars, FOO, FOOBAR, FOOBARBAZ,
and want to follow the logic flow of:
1.) Check if FOO is set. If not,
2.) Check if FOOBAR is set. If not,
3.) Check if FOOBARBAZ is set.
Then this would be specified as:
GetFirst([]string{"FOO", "FOOBAR", "FOOBARBAZ"})
If val is "" and ok is true, this means that one of the specified variable names IS
set but is set to an empty value. If ok is false, none of the specified variables
are set.
It is a thin wrapper around GetFirstWithRef.
*/
func GetFirst(varNames []string) (val string, ok bool) {
val, ok, _ = GetFirstWithRef(varNames)
return
}
/*
GetFirstWithRef behaves exactly like GetFirst, but with an additional returned value, idx,
which specifies the index in varNames in which a set variable was found. e.g. if:
GetFirstWithRef([]string{"FOO", "FOOBAR", "FOOBAZ"})
is called and FOO is not set but FOOBAR is, idx will be 1.
If ok is false, idx will always be -1 and should be ignored.
*/
func GetFirstWithRef(varNames []string) (val string, ok bool, idx int) {
idx = -1
for i, vn := range varNames {
if HasEnv(vn) {
ok = true
idx = i
val = os.Getenv(vn)
return
}
}
return
}
/* /*
GetPidEnvMap will only work on *NIX-like systems with procfs. GetPidEnvMap will only work on *NIX-like systems with procfs.
It gets the environment variables of a given process' PID. It gets the environment variables of a given process' PID.
@@ -118,3 +171,17 @@ func GetPidEnvMapNative(pid uint32) (envMap map[string]interface{}, err error) {
return return
} }
/*
HasEnv is much like os.LookupEnv, but only returns a boolean for
if the environment variable key exists or not.
This is useful anywhere you may need to set a boolean in a func call
depending on the *presence* of an env var or not.
*/
func HasEnv(key string) (envIsSet bool) {
_, envIsSet = os.LookupEnv(key)
return
}

View File

@@ -20,13 +20,12 @@ package paths
import ( import (
"errors" "errors"
`fmt` "fmt"
`io/fs` "io/fs"
"os" "os"
"os/user" "os/user"
"path/filepath" "path/filepath"
`strings` "strings"
// "syscall" // "syscall"
) )
@@ -83,10 +82,81 @@ func ExpandHome(path *string) (err error) {
return return
} }
/*
GetFirst is the file equivalent of envs.GetFirst.
It iterates through paths, normalizing them along the way
(so abstracted paths such as ~/foo/bar.txt and relative paths
such as bar/baz.txt will still work), and returns the content
of the first found existing file. If the first found path
is a directory, content will be nil but isDir will be true
(as will ok).
If no path exists, ok will be false.
As always, results are not guaranteed due to permissions, etc.
potentially returning an inaccurate result.
This is a thin wrapper around GetFirstWithRef.
*/
func GetFirst(paths []string) (content []byte, isDir, ok bool) {
content, isDir, ok, _ = GetFirstWithRef(paths)
return
}
/*
GetFirstWithRef is the file equivalent of envs.GetFirstWithRef.
It behaves exactly like GetFirst, but with an additional returned value, idx,
which specifies the index in paths in which a path was found.
As always, results are not guaranteed due to permissions, etc.
potentially returning an inaccurate result.
*/
func GetFirstWithRef(paths []string) (content []byte, isDir, ok bool, idx int) {
var locPaths []string
var exists bool
var stat os.FileInfo
var err error
idx = -1
// We have to be a little less cavalier about this.
if paths == nil {
return
}
locPaths = make([]string, len(paths))
locPaths = paths[:] // Create an explicit copy so we don't modify paths.
for i, p := range locPaths {
if exists, stat, err = RealPathExistsStat(&p); err != nil {
err = nil
continue
}
if !exists {
continue
}
isDir = stat.IsDir()
if !isDir {
if content, err = os.ReadFile(p); err != nil {
continue
}
}
ok = true
idx = i
return
}
return
}
/* /*
MakeDirIfNotExist will create a directory at a given path if it doesn't exist. MakeDirIfNotExist will create a directory at a given path if it doesn't exist.
See also the documentation for RealPath. See also the documentation for RealPath.
This is a bit more sane option than os.MkdirAll as it will normalize paths a little better.
*/ */
func MakeDirIfNotExist(path string) (err error) { func MakeDirIfNotExist(path string) (err error) {
@@ -113,6 +183,8 @@ func MakeDirIfNotExist(path string) (err error) {
if !stat.Mode().IsDir() { if !stat.Mode().IsDir() {
err = errors.New(fmt.Sprintf("path %v exists but is not a directory", locPath)) err = errors.New(fmt.Sprintf("path %v exists but is not a directory", locPath))
return return
} else {
return
} }
// This should probably never happen. Probably. // This should probably never happen. Probably.