github.com/rigado/snapd@v2.42.5-go-mod+incompatible/osutil/env.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2016 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package osutil
    21  
    22  import (
    23  	"fmt"
    24  	"os"
    25  	"strconv"
    26  	"strings"
    27  )
    28  
    29  // GetenvBool returns whether the given key may be considered "set" in the
    30  // environment (i.e. it is set to one of "1", "true", etc).
    31  //
    32  // An optional second argument can be provided, which determines how to
    33  // treat missing or unparsable values; default is to treat them as false.
    34  func GetenvBool(key string, dflt ...bool) bool {
    35  	if val := strings.TrimSpace(os.Getenv(key)); val != "" {
    36  		if b, err := strconv.ParseBool(val); err == nil {
    37  			return b
    38  		}
    39  	}
    40  
    41  	if len(dflt) > 0 {
    42  		return dflt[0]
    43  	}
    44  
    45  	return false
    46  }
    47  
    48  // GetenvInt64 interprets the value of the given environment variable
    49  // as an int64 and returns the corresponding value. The base can be
    50  // implied via the prefix (0x for 16, 0 for 8; otherwise 10).
    51  //
    52  // An optional second argument can be provided, which determines how to
    53  // treat missing or unparsable values; default is to treat them as 0.
    54  func GetenvInt64(key string, dflt ...int64) int64 {
    55  	if val := strings.TrimSpace(os.Getenv(key)); val != "" {
    56  		if b, err := strconv.ParseInt(val, 0, 64); err == nil {
    57  			return b
    58  		}
    59  	}
    60  
    61  	if len(dflt) > 0 {
    62  		return dflt[0]
    63  	}
    64  
    65  	return 0
    66  }
    67  
    68  // EnvMap takes a list of "key=value" strings and transforms them into
    69  // a map.
    70  func EnvMap(env []string) map[string]string {
    71  	out := make(map[string]string, len(env))
    72  	for _, kv := range env {
    73  		l := strings.SplitN(kv, "=", 2)
    74  		if len(l) == 2 {
    75  			out[l[0]] = l[1]
    76  		}
    77  	}
    78  	return out
    79  }
    80  
    81  // SubstituteEnv takes a list of environment strings like:
    82  // - K1=BAR
    83  // - K2=$K1
    84  // - K3=${K2}
    85  // and substitutes them top-down from the given environment
    86  // and from the os environment.
    87  //
    88  // Input strings that do not have the form "k=v" will be dropped
    89  // from the output.
    90  //
    91  // The result will be a list of environment strings in the same
    92  // order as the input.
    93  func SubstituteEnv(env []string) []string {
    94  	envMap := map[string]string{}
    95  	out := make([]string, 0, len(env))
    96  
    97  	for _, s := range env {
    98  		l := strings.SplitN(s, "=", 2)
    99  		if len(l) < 2 {
   100  			continue
   101  		}
   102  		k := l[0]
   103  		v := l[1]
   104  		v = os.Expand(v, func(k string) string {
   105  			if s, ok := envMap[k]; ok {
   106  				return s
   107  			}
   108  			return os.Getenv(k)
   109  		})
   110  		out = append(out, fmt.Sprintf("%s=%s", k, v))
   111  		envMap[k] = v
   112  	}
   113  
   114  	return out
   115  }