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