github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/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 "container": "podman", 23 } 24 } 25 26 // Slice transforms the specified map of environment variables into a 27 // slice. If a value is non-empty, the key and value are joined with '='. 28 func Slice(m map[string]string) []string { 29 env := make([]string, 0, len(m)) 30 for k, v := range m { 31 var s string 32 if len(v) > 0 { 33 s = fmt.Sprintf("%s=%s", k, v) 34 } else { 35 s = k 36 } 37 env = append(env, s) 38 } 39 return env 40 } 41 42 // Join joins the two environment maps with override overriding base. 43 func Join(base map[string]string, override map[string]string) map[string]string { 44 if len(base) == 0 { 45 return override 46 } 47 for k, v := range override { 48 base[k] = v 49 } 50 return base 51 } 52 53 // ParseFile parses the specified path for environment variables and returns them 54 // as a map. 55 func ParseFile(path string) (_ map[string]string, err error) { 56 env := make(map[string]string) 57 defer func() { 58 if err != nil { 59 err = errors.Wrapf(err, "error parsing env file %q", path) 60 } 61 }() 62 63 fh, err := os.Open(path) 64 if err != nil { 65 return nil, err 66 } 67 defer fh.Close() 68 69 scanner := bufio.NewScanner(fh) 70 for scanner.Scan() { 71 // trim the line from all leading whitespace first 72 line := strings.TrimLeft(scanner.Text(), whiteSpaces) 73 // line is not empty, and not starting with '#' 74 if len(line) > 0 && !strings.HasPrefix(line, "#") { 75 if err := parseEnv(env, line); err != nil { 76 return nil, err 77 } 78 } 79 } 80 return env, scanner.Err() 81 } 82 83 func parseEnv(env map[string]string, line string) error { 84 data := strings.SplitN(line, "=", 2) 85 86 // catch invalid variables such as "=" or "=A" 87 if data[0] == "" { 88 return errors.Errorf("invalid environment variable: %q", line) 89 } 90 // trim the front of a variable, but nothing else 91 name := strings.TrimLeft(data[0], whiteSpaces) 92 if strings.ContainsAny(name, whiteSpaces) { 93 return errors.Errorf("name %q has white spaces, poorly formatted name", name) 94 } 95 96 if len(data) > 1 { 97 env[name] = data[1] 98 } else { 99 if strings.HasSuffix(name, "*") { 100 name = strings.TrimSuffix(name, "*") 101 for _, e := range os.Environ() { 102 part := strings.SplitN(e, "=", 2) 103 if len(part) < 2 { 104 continue 105 } 106 if strings.HasPrefix(part[0], name) { 107 env[part[0]] = part[1] 108 } 109 } 110 } else if val, ok := os.LookupEnv(name); ok { 111 // if only a pass-through variable is given, clean it up. 112 env[name] = val 113 } 114 } 115 return nil 116 }