github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/pkg/env/env.go (about) 1 // Package for processing environment variables. 2 package env 3 4 // TODO: we need to add tests for this package. 5 6 import ( 7 "bufio" 8 "fmt" 9 "os" 10 "strings" 11 12 "github.com/pkg/errors" 13 ) 14 15 const whiteSpaces = " \t" 16 17 // DefaultEnvVariables returns a default environment, with $PATH and $TERM set. 18 func DefaultEnvVariables() map[string]string { 19 return map[string]string{ 20 "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 21 "TERM": "xterm", 22 } 23 } 24 25 // Slice transforms the specified map of environment variables into a 26 // slice. If a value is non-empty, the key and value are joined with '='. 27 func Slice(m map[string]string) []string { 28 env := make([]string, len(m)) 29 for k, v := range m { 30 var s string 31 if len(v) > 0 { 32 s = fmt.Sprintf("%s=%s", k, v) 33 } else { 34 s = k 35 } 36 env = append(env, s) 37 } 38 return env 39 } 40 41 // Join joins the two environment maps with override overriding base. 42 func Join(base map[string]string, override map[string]string) map[string]string { 43 if len(base) == 0 { 44 return override 45 } 46 for k, v := range override { 47 base[k] = v 48 } 49 return base 50 } 51 52 // ParseFile parses the specified path for environment variables and returns them 53 // as a map. 54 func ParseFile(path string) (_ map[string]string, err error) { 55 env := make(map[string]string) 56 defer func() { 57 if err != nil { 58 err = errors.Wrapf(err, "error parsing env file %q", path) 59 } 60 }() 61 62 fh, err := os.Open(path) 63 if err != nil { 64 return nil, err 65 } 66 defer fh.Close() 67 68 scanner := bufio.NewScanner(fh) 69 for scanner.Scan() { 70 // trim the line from all leading whitespace first 71 line := strings.TrimLeft(scanner.Text(), whiteSpaces) 72 // line is not empty, and not starting with '#' 73 if len(line) > 0 && !strings.HasPrefix(line, "#") { 74 if err := parseEnv(env, line); err != nil { 75 return nil, err 76 } 77 } 78 } 79 return env, scanner.Err() 80 } 81 82 func parseEnv(env map[string]string, line string) error { 83 data := strings.SplitN(line, "=", 2) 84 85 // catch invalid variables such as "=" or "=A" 86 if data[0] == "" { 87 return errors.Errorf("invalid environment variable: %q", line) 88 } 89 // trim the front of a variable, but nothing else 90 name := strings.TrimLeft(data[0], whiteSpaces) 91 if strings.ContainsAny(name, whiteSpaces) { 92 return errors.Errorf("name %q has white spaces, poorly formatted name", name) 93 } 94 95 if len(data) > 1 { 96 env[name] = data[1] 97 } else { 98 if strings.HasSuffix(name, "*") { 99 name = strings.TrimSuffix(name, "*") 100 for _, e := range os.Environ() { 101 part := strings.SplitN(e, "=", 2) 102 if len(part) < 2 { 103 continue 104 } 105 if strings.HasPrefix(part[0], name) { 106 env[part[0]] = part[1] 107 } 108 } 109 } else if val, ok := os.LookupEnv(name); ok { 110 // if only a pass-through variable is given, clean it up. 111 env[name] = val 112 } 113 } 114 return nil 115 }