github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/syscall/env_unix.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  // +build darwin dragonfly freebsd linux netbsd openbsd
     6  
     7  // Unix environment variables.
     8  
     9  package syscall
    10  
    11  import "sync"
    12  
    13  var (
    14  	// envOnce guards initialization by copyenv, which populates env.
    15  	envOnce sync.Once
    16  
    17  	// envLock guards env and envs.
    18  	envLock sync.RWMutex
    19  
    20  	// env maps from an environment variable to its first occurrence in envs.
    21  	env map[string]int
    22  
    23  	// envs is provided by the runtime. elements are expected to be
    24  	// of the form "key=value".
    25  	envs []string
    26  )
    27  
    28  // setenv_c is provided by the runtime, but is a no-op if cgo isn't
    29  // loaded.
    30  func setenv_c(k, v string)
    31  
    32  func copyenv() {
    33  	env = make(map[string]int)
    34  	for i, s := range envs {
    35  		for j := 0; j < len(s); j++ {
    36  			if s[j] == '=' {
    37  				key := s[:j]
    38  				if _, ok := env[key]; !ok {
    39  					env[key] = i
    40  				}
    41  				break
    42  			}
    43  		}
    44  	}
    45  }
    46  
    47  func Getenv(key string) (value string, found bool) {
    48  	envOnce.Do(copyenv)
    49  	if len(key) == 0 {
    50  		return "", false
    51  	}
    52  
    53  	envLock.RLock()
    54  	defer envLock.RUnlock()
    55  
    56  	i, ok := env[key]
    57  	if !ok {
    58  		return "", false
    59  	}
    60  	s := envs[i]
    61  	for i := 0; i < len(s); i++ {
    62  		if s[i] == '=' {
    63  			return s[i+1:], true
    64  		}
    65  	}
    66  	return "", false
    67  }
    68  
    69  func Setenv(key, value string) error {
    70  	envOnce.Do(copyenv)
    71  	if len(key) == 0 {
    72  		return EINVAL
    73  	}
    74  	for i := 0; i < len(key); i++ {
    75  		if key[i] == '=' || key[i] == 0 {
    76  			return EINVAL
    77  		}
    78  	}
    79  	for i := 0; i < len(value); i++ {
    80  		if value[i] == 0 {
    81  			return EINVAL
    82  		}
    83  	}
    84  
    85  	envLock.Lock()
    86  	defer envLock.Unlock()
    87  
    88  	i, ok := env[key]
    89  	kv := key + "=" + value
    90  	if ok {
    91  		envs[i] = kv
    92  	} else {
    93  		i = len(envs)
    94  		envs = append(envs, kv)
    95  	}
    96  	env[key] = i
    97  	setenv_c(key, value)
    98  	return nil
    99  }
   100  
   101  func Clearenv() {
   102  	envOnce.Do(copyenv) // prevent copyenv in Getenv/Setenv
   103  
   104  	envLock.Lock()
   105  	defer envLock.Unlock()
   106  
   107  	env = make(map[string]int)
   108  	envs = []string{}
   109  	// TODO(bradfitz): pass through to C
   110  }
   111  
   112  func Environ() []string {
   113  	envOnce.Do(copyenv)
   114  	envLock.RLock()
   115  	defer envLock.RUnlock()
   116  	a := make([]string, len(envs))
   117  	copy(a, envs)
   118  	return a
   119  }