| // Copyright 2010 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // General environment variables. |
| |
| package os |
| |
| import ( |
| "internal/testlog" |
| "syscall" |
| ) |
| |
| // Expand replaces ${var} or $var in the string based on the mapping function. |
| // For example, os.ExpandEnv(s) is equivalent to os.Expand(s, os.Getenv). |
| func Expand(s string, mapping func(string) string) string { |
| var buf []byte |
| // ${} is all ASCII, so bytes are fine for this operation. |
| i := 0 |
| for j := 0; j < len(s); j++ { |
| if s[j] == '$' && j+1 < len(s) { |
| if buf == nil { |
| buf = make([]byte, 0, 2*len(s)) |
| } |
| buf = append(buf, s[i:j]...) |
| name, w := getShellName(s[j+1:]) |
| if name == "" && w > 0 { |
| // Encountered invalid syntax; eat the |
| // characters. |
| } else if name == "" { |
| // Valid syntax, but $ was not followed by a |
| // name. Leave the dollar character untouched. |
| buf = append(buf, s[j]) |
| } else { |
| buf = append(buf, mapping(name)...) |
| } |
| j += w |
| i = j + 1 |
| } |
| } |
| if buf == nil { |
| return s |
| } |
| return string(buf) + s[i:] |
| } |
| |
| // ExpandEnv replaces ${var} or $var in the string according to the values |
| // of the current environment variables. References to undefined |
| // variables are replaced by the empty string. |
| func ExpandEnv(s string) string { |
| return Expand(s, Getenv) |
| } |
| |
| // isShellSpecialVar reports whether the character identifies a special |
| // shell variable such as $*. |
| func isShellSpecialVar(c uint8) bool { |
| switch c { |
| case '*', '#', '$', '@', '!', '?', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': |
| return true |
| } |
| return false |
| } |
| |
| // isAlphaNum reports whether the byte is an ASCII letter, number, or underscore |
| func isAlphaNum(c uint8) bool { |
| return c == '_' || '0' <= c && c <= '9' || 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' |
| } |
| |
| // getShellName returns the name that begins the string and the number of bytes |
| // consumed to extract it. If the name is enclosed in {}, it's part of a ${} |
| // expansion and two more bytes are needed than the length of the name. |
| func getShellName(s string) (string, int) { |
| switch { |
| case s[0] == '{': |
| if len(s) > 2 && isShellSpecialVar(s[1]) && s[2] == '}' { |
| return s[1:2], 3 |
| } |
| // Scan to closing brace |
| for i := 1; i < len(s); i++ { |
| if s[i] == '}' { |
| if i == 1 { |
| return "", 2 // Bad syntax; eat "${}" |
| } |
| return s[1:i], i + 1 |
| } |
| } |
| return "", 1 // Bad syntax; eat "${" |
| case isShellSpecialVar(s[0]): |
| return s[0:1], 1 |
| } |
| // Scan alphanumerics. |
| var i int |
| for i = 0; i < len(s) && isAlphaNum(s[i]); i++ { |
| } |
| return s[:i], i |
| } |
| |
| // Getenv retrieves the value of the environment variable named by the key. |
| // It returns the value, which will be empty if the variable is not present. |
| // To distinguish between an empty value and an unset value, use LookupEnv. |
| func Getenv(key string) string { |
| testlog.Getenv(key) |
| v, _ := syscall.Getenv(key) |
| return v |
| } |
| |
| // LookupEnv retrieves the value of the environment variable named |
| // by the key. If the variable is present in the environment the |
| // value (which may be empty) is returned and the boolean is true. |
| // Otherwise the returned value will be empty and the boolean will |
| // be false. |
| func LookupEnv(key string) (string, bool) { |
| testlog.Getenv(key) |
| return syscall.Getenv(key) |
| } |
| |
| // Setenv sets the value of the environment variable named by the key. |
| // It returns an error, if any. |
| func Setenv(key, value string) error { |
| err := syscall.Setenv(key, value) |
| if err != nil { |
| return NewSyscallError("setenv", err) |
| } |
| return nil |
| } |
| |
| // Unsetenv unsets a single environment variable. |
| func Unsetenv(key string) error { |
| return syscall.Unsetenv(key) |
| } |
| |
| // Clearenv deletes all environment variables. |
| func Clearenv() { |
| syscall.Clearenv() |
| } |
| |
| // Environ returns a copy of strings representing the environment, |
| // in the form "key=value". |
| func Environ() []string { |
| return syscall.Environ() |
| } |