github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/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 var buf []byte 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 if buf == nil { 23 buf = make([]byte, 0, 2*len(s)) 24 } 25 buf = append(buf, s[i:j]...) 26 name, w := getShellName(s[j+1:]) 27 if name == "" && w > 0 { 28 // Encountered invalid syntax; eat the 29 // characters. 30 } else if name == "" { 31 // Valid syntax, but $ was not followed by a 32 // name. Leave the dollar character untouched. 33 buf = append(buf, s[j]) 34 } else { 35 buf = append(buf, mapping(name)...) 36 } 37 j += w 38 i = j + 1 39 } 40 } 41 if buf == nil { 42 return s 43 } 44 return string(buf) + s[i:] 45 } 46 47 // ExpandEnv replaces ${var} or $var in the string according to the values 48 // of the current environment variables. References to undefined 49 // variables are replaced by the empty string. 50 func ExpandEnv(s string) string { 51 return Expand(s, Getenv) 52 } 53 54 // isShellSpecialVar reports whether the character identifies a special 55 // shell variable such as $*. 56 func isShellSpecialVar(c uint8) bool { 57 switch c { 58 case '*', '#', '$', '@', '!', '?', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': 59 return true 60 } 61 return false 62 } 63 64 // isAlphaNum reports whether the byte is an ASCII letter, number, or underscore 65 func isAlphaNum(c uint8) bool { 66 return c == '_' || '0' <= c && c <= '9' || 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' 67 } 68 69 // getShellName returns the name that begins the string and the number of bytes 70 // consumed to extract it. If the name is enclosed in {}, it's part of a ${} 71 // expansion and two more bytes are needed than the length of the name. 72 func getShellName(s string) (string, int) { 73 switch { 74 case s[0] == '{': 75 if len(s) > 2 && isShellSpecialVar(s[1]) && s[2] == '}' { 76 return s[1:2], 3 77 } 78 // Scan to closing brace 79 for i := 1; i < len(s); i++ { 80 if s[i] == '}' { 81 if i == 1 { 82 return "", 2 // Bad syntax; eat "${}" 83 } 84 return s[1:i], i + 1 85 } 86 } 87 return "", 1 // Bad syntax; eat "${" 88 case isShellSpecialVar(s[0]): 89 return s[0:1], 1 90 } 91 // Scan alphanumerics. 92 var i int 93 for i = 0; i < len(s) && isAlphaNum(s[i]); i++ { 94 } 95 return s[:i], i 96 } 97 98 // Getenv retrieves the value of the environment variable named by the key. 99 // It returns the value, which will be empty if the variable is not present. 100 // To distinguish between an empty value and an unset value, use LookupEnv. 101 func Getenv(key string) string { 102 testlog.Getenv(key) 103 v, _ := syscall.Getenv(key) 104 return v 105 } 106 107 // LookupEnv retrieves the value of the environment variable named 108 // by the key. If the variable is present in the environment the 109 // value (which may be empty) is returned and the boolean is true. 110 // Otherwise the returned value will be empty and the boolean will 111 // be false. 112 func LookupEnv(key string) (string, bool) { 113 testlog.Getenv(key) 114 return syscall.Getenv(key) 115 } 116 117 // Setenv sets the value of the environment variable named by the key. 118 // It returns an error, if any. 119 func Setenv(key, value string) error { 120 err := syscall.Setenv(key, value) 121 if err != nil { 122 return NewSyscallError("setenv", err) 123 } 124 return nil 125 } 126 127 // Unsetenv unsets a single environment variable. 128 func Unsetenv(key string) error { 129 return syscall.Unsetenv(key) 130 } 131 132 // Clearenv deletes all environment variables. 133 func Clearenv() { 134 syscall.Clearenv() 135 } 136 137 // Environ returns a copy of strings representing the environment, 138 // in the form "key=value". 139 func Environ() []string { 140 return syscall.Environ() 141 }