diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-01-17 12:40:45 +0100 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-01-17 12:40:45 +0100 |
commit | 3e45412327a2654a77944249962b3652e6142299 (patch) | |
tree | bc3bf69452afa055423cbe0c5cfa8ca357df6ccf /src/pkg/os/env.go | |
parent | c533680039762cacbc37db8dc7eed074c3e497be (diff) | |
download | golang-upstream/2011.01.12.tar.gz |
Imported Upstream version 2011.01.12upstream/2011.01.12
Diffstat (limited to 'src/pkg/os/env.go')
-rw-r--r-- | src/pkg/os/env.go | 119 |
1 files changed, 53 insertions, 66 deletions
diff --git a/src/pkg/os/env.go b/src/pkg/os/env.go index bdd2ac293..3a6d79dd0 100644 --- a/src/pkg/os/env.go +++ b/src/pkg/os/env.go @@ -1,86 +1,73 @@ -// Copyright 2009 The Go Authors. All rights reserved. +// 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. -// Environment variables. +// General environment variables. package os -import ( - "once" -) - -// ENOENV is the Error indicating that an environment variable does not exist. -var ENOENV = NewError("no such environment variable") - -var env map[string]string - - -func copyenv() { - env = make(map[string]string) - for _, s := range Envs { - for j := 0; j < len(s); j++ { - if s[j] == '=' { - env[s[0:j]] = s[j+1:] - break - } +// Expand replaces ${var} or $var in the string based on the mapping function. +// Invocations of undefined variables are replaced with the empty string. +func Expand(s string, mapping func(string) string) string { + buf := make([]byte, 0, 2*len(s)) + // ${} 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) { + buf = append(buf, []byte(s[i:j])...) + name, w := getShellName(s[j+1:]) + buf = append(buf, []byte(mapping(name))...) + j += w + i = j + 1 } } + return string(buf) + s[i:] } -// Getenverror retrieves the value of the environment variable named by the key. -// It returns the value and an error, if any. -func Getenverror(key string) (value string, err Error) { - once.Do(copyenv) - - if len(key) == 0 { - return "", EINVAL - } - v, ok := env[key] - if !ok { - return "", ENOENV - } - return v, nil -} - -// 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. -func Getenv(key string) string { - v, _ := Getenverror(key) - return v +// ShellExpand replaces ${var} or $var in the string according to the values +// of the operating system's environment variables. References to undefined +// variables are replaced by the empty string. +func ShellExpand(s string) string { + return Expand(s, Getenv) } -// Setenv sets the value of the environment variable named by the key. -// It returns an Error, if any. -func Setenv(key, value string) Error { - once.Do(copyenv) - - if len(key) == 0 { - return EINVAL +// isSpellSpecialVar 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 } - env[key] = value - return nil + return false } -// Clearenv deletes all environment variables. -func Clearenv() { - once.Do(copyenv) // prevent copyenv in Getenv/Setenv - env = make(map[string]string) +// 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' } -// Environ returns an array of strings representing the environment, -// in the form "key=value". -func Environ() []string { - once.Do(copyenv) - a := make([]string, len(env)) - i := 0 - for k, v := range env { - // check i < len(a) for safety, - // in case env is changing underfoot. - if i < len(a) { - a[i] = k + "=" + v - i++ +// getName 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] == '}' { + return s[1:i], i + 1 + } } + return "", 1 // Bad syntax; just eat the brace. + 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 a[0:i] + return s[:i], i } |