github.com/c9s/go@v0.0.0-20180120015821-984e81f64e0c/src/os/env.go (about) 1 // Copyright 2010 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // General environment variables. 6 7 package os 8 9 import ( 10 "internal/testlog" 11 "syscall" 12 ) 13 14 // Expand replaces ${var} or $var in the string based on the mapping function. 15 // For example, os.ExpandEnv(s) is equivalent to os.Expand(s, os.Getenv). 16 func Expand(s string, mapping func(string) string) string { 17 buf := make([]byte, 0, 2*len(s)) 18 // ${} is all ASCII, so bytes are fine for this operation. 19 i := 0 20 for j := 0; j < len(s); j++ { 21 if s[j] == '$' && j+1 < len(s) { 22 buf = append(buf, s[i:j]...) 23 name, w := getShellName(s[j+1:]) 24 buf = append(buf, mapping(name)...) 25 j += w 26 i = j + 1 27 } 28 } 29 return string(buf) + s[i:] 30 } 31 32 // ExpandEnv replaces ${var} or $var in the string according to the values 33 // of the current environment variables. References to undefined 34 // variables are replaced by the empty string. 35 func ExpandEnv(s string) string { 36 return Expand(s, Getenv) 37 } 38 39 // isShellSpecialVar reports whether the character identifies a special 40 // shell variable such as $*. 41 func isShellSpecialVar(c uint8) bool { 42 switch c { 43 case '*', '#', '$', '@', '!', '?', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': 44 return true 45 } 46 return false 47 } 48 49 // isAlphaNum reports whether the byte is an ASCII letter, number, or underscore 50 func isAlphaNum(c uint8) bool { 51 return c == '_' || '0' <= c && c <= '9' || 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' 52 } 53 54 // getShellName returns the name that begins the string and the number of bytes 55 // consumed to extract it. If the name is enclosed in {}, it's part of a ${} 56 // expansion and two more bytes are needed than the length of the name. 57 func getShellName(s string) (string, int) { 58 switch { 59 case s[0] == '{': 60 if len(s) > 2 && isShellSpecialVar(s[1]) && s[2] == '}' { 61 return s[1:2], 3 62 } 63 // Scan to closing brace 64 for i := 1; i < len(s); i++ { 65 if s[i] == '}' { 66 return s[1:i], i + 1 67 } 68 } 69 return "", 1 // Bad syntax; just eat the brace. 70 case isShellSpecialVar(s[0]): 71 return s[0:1], 1 72 } 73 // Scan alphanumerics. 74 var i int 75 for i = 0; i < len(s) && isAlphaNum(s[i]); i++ { 76 } 77 return s[:i], i 78 } 79 80 // Getenv retrieves the value of the environment variable named by the key. 81 // It returns the value, which will be empty if the variable is not present. 82 // To distinguish between an empty value and an unset value, use LookupEnv. 83 func Getenv(key string) string { 84 testlog.Getenv(key) 85 v, _ := syscall.Getenv(key) 86 return v 87 } 88 89 // LookupEnv retrieves the value of the environment variable named 90 // by the key. If the variable is present in the environment the 91 // value (which may be empty) is returned and the boolean is true. 92 // Otherwise the returned value will be empty and the boolean will 93 // be false. 94 func LookupEnv(key string) (string, bool) { 95 testlog.Getenv(key) 96 return syscall.Getenv(key) 97 } 98 99 // Setenv sets the value of the environment variable named by the key. 100 // It returns an error, if any. 101 func Setenv(key, value string) error { 102 err := syscall.Setenv(key, value) 103 if err != nil { 104 return NewSyscallError("setenv", err) 105 } 106 return nil 107 } 108 109 // Unsetenv unsets a single environment variable. 110 func Unsetenv(key string) error { 111 return syscall.Unsetenv(key) 112 } 113 114 // Clearenv deletes all environment variables. 115 func Clearenv() { 116 syscall.Clearenv() 117 } 118 119 // Environ returns a copy of strings representing the environment, 120 // in the form "key=value". 121 func Environ() []string { 122 return syscall.Environ() 123 }