github.com/dara-project/godist@v0.0.0-20200823115410-e0c80c8f0c78/src/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 nacl netbsd openbsd solaris
     6  
     7  // Unix environment variables.
     8  
     9  package syscall
    10  
    11  import "dara"
    12  import "runtime"
    13  import "sync"
    14  
    15  var (
    16  	// envOnce guards initialization by copyenv, which populates env.
    17  	envOnce sync.Once
    18  
    19  	// envLock guards env and envs.
    20  	envLock sync.RWMutex
    21  
    22  	// env maps from an environment variable to its first occurrence in envs.
    23  	env map[string]int
    24  
    25  	// envs is provided by the runtime. elements are expected to
    26  	// be of the form "key=value". An empty string means deleted
    27  	// (or a duplicate to be ignored).
    28  	envs []string = runtime_envs()
    29  )
    30  
    31  func runtime_envs() []string // in package runtime
    32  
    33  // setenv_c and unsetenv_c are provided by the runtime but are no-ops
    34  // if cgo isn't loaded.
    35  func setenv_c(k, v string)
    36  func unsetenv_c(k string)
    37  
    38  func copyenv() {
    39  	env = make(map[string]int)
    40  	for i, s := range envs {
    41  		for j := 0; j < len(s); j++ {
    42  			if s[j] == '=' {
    43  				key := s[:j]
    44  				if _, ok := env[key]; !ok {
    45  					env[key] = i // first mention of key
    46  				} else {
    47  					// Clear duplicate keys. This permits Unsetenv to
    48  					// safely delete only the first item without
    49  					// worrying about unshadowing a later one,
    50  					// which might be a security problem.
    51  					envs[i] = ""
    52  				}
    53  				break
    54  			}
    55  		}
    56  	}
    57  }
    58  
    59  func Unsetenv(key string) error {
    60  	envOnce.Do(copyenv)
    61  
    62  	envLock.Lock()
    63  	defer envLock.Unlock()
    64  
    65  	if i, ok := env[key]; ok {
    66  		envs[i] = ""
    67  		delete(env, key)
    68  	}
    69  	unsetenv_c(key)
    70  	// DARA Instrumentation
    71  	if (runtime.Is_dara_profiling_on()) {
    72  		runtime.Dara_Debug_Print(func() { println("[UNSETENV] : " + key) })
    73  		argInfo := dara.GeneralType{Type: dara.STRING}
    74          copy(argInfo.String[:], key)
    75  		retInfo := dara.GeneralType{Type: dara.ERROR, Unsupported : dara.UNSUPPORTEDVAL}
    76  		syscallInfo := dara.GeneralSyscall{dara.DSYS_UNSETENV, 1, 1, [10]dara.GeneralType{argInfo}, [10]dara.GeneralType{retInfo}}
    77  		runtime.Report_Syscall_To_Scheduler(dara.DSYS_UNSETENV, syscallInfo)
    78  	}
    79  	return nil
    80  }
    81  
    82  func Getenv(key string) (value string, found bool) {
    83  	argInfo := dara.GeneralType{Type: dara.STRING}
    84      copy(argInfo.String[:], key)
    85  	envOnce.Do(copyenv)
    86  	if len(key) == 0 {
    87  		return "", false
    88  	}
    89  
    90  	envLock.RLock()
    91  	defer envLock.RUnlock()
    92  
    93  	i, ok := env[key]
    94  	if !ok {
    95  		// DARA Instrumentation
    96  		if (runtime.Is_dara_profiling_on()) {
    97  			runtime.Dara_Debug_Print(func() { println("[GETENV] : " + key) })
    98  			retInfo1 := dara.GeneralType{Type: dara.STRING}
    99  			retInfo2 := dara.GeneralType{Type: dara.BOOL, Bool:false}
   100  			syscallInfo := dara.GeneralSyscall{dara.DSYS_GETENV, 1, 2, [10]dara.GeneralType{argInfo}, [10]dara.GeneralType{retInfo1, retInfo2}}
   101  			runtime.Report_Syscall_To_Scheduler(dara.DSYS_GETENV, syscallInfo)
   102  		}
   103  		return "", false
   104  	}
   105  	s := envs[i]
   106  	for i := 0; i < len(s); i++ {
   107  		if s[i] == '=' {
   108  			// DARA Instrumentation
   109  			if (runtime.Is_dara_profiling_on()) {
   110  				runtime.Dara_Debug_Print(func() {println("[GETENV] : " + key)})
   111  				retInfo1 := dara.GeneralType{Type: dara.STRING}
   112                  copy(retInfo1.String[:], s[i+1:])
   113  				retInfo2 := dara.GeneralType{Type: dara.BOOL, Bool:false}
   114  				syscallInfo := dara.GeneralSyscall{dara.DSYS_GETENV, 1, 2, [10]dara.GeneralType{argInfo}, [10]dara.GeneralType{retInfo1, retInfo2}}
   115  				runtime.Report_Syscall_To_Scheduler(dara.DSYS_GETENV, syscallInfo)
   116  			}
   117  			return s[i+1:], true
   118  		}
   119  	}
   120  	// DARA Instrumentation
   121  	if (runtime.Is_dara_profiling_on()) {
   122  		runtime.Dara_Debug_Print(func() { println("[GETENV] : " + key) })
   123  		retInfo1 := dara.GeneralType{Type: dara.STRING}
   124  		retInfo2 := dara.GeneralType{Type: dara.BOOL, Bool:false}
   125  		syscallInfo := dara.GeneralSyscall{dara.DSYS_GETENV, 1, 2, [10]dara.GeneralType{argInfo}, [10]dara.GeneralType{retInfo1, retInfo2}}
   126  		runtime.Report_Syscall_To_Scheduler(dara.DSYS_GETENV, syscallInfo)
   127  	}
   128  	return "", false
   129  }
   130  
   131  func Setenv(key, value string) error {
   132  	// DARA Instrumentation
   133  	if (runtime.Is_dara_profiling_on()) {
   134  		runtime.Dara_Debug_Print(func() { println("[SETENV] : " + key +  " "  + value) })
   135  		argInfo1 := dara.GeneralType{Type: dara.STRING}
   136          copy(argInfo1.String[:], key)
   137  		argInfo2 := dara.GeneralType{Type: dara.STRING}
   138          copy(argInfo2.String[:], value)
   139  		retInfo := dara.GeneralType{Type: dara.ERROR, Unsupported : dara.UNSUPPORTEDVAL}
   140  		syscallInfo := dara.GeneralSyscall{dara.DSYS_GETENV, 2, 1, [10]dara.GeneralType{argInfo1, argInfo2}, [10]dara.GeneralType{retInfo}}
   141  		runtime.Report_Syscall_To_Scheduler(dara.DSYS_SETENV, syscallInfo)
   142  	}
   143  	envOnce.Do(copyenv)
   144  	if len(key) == 0 {
   145  		return EINVAL
   146  	}
   147  	for i := 0; i < len(key); i++ {
   148  		if key[i] == '=' || key[i] == 0 {
   149  			return EINVAL
   150  		}
   151  	}
   152  	for i := 0; i < len(value); i++ {
   153  		if value[i] == 0 {
   154  			return EINVAL
   155  		}
   156  	}
   157  
   158  	envLock.Lock()
   159  	defer envLock.Unlock()
   160  
   161  	i, ok := env[key]
   162  	kv := key + "=" + value
   163  	if ok {
   164  		envs[i] = kv
   165  	} else {
   166  		i = len(envs)
   167  		envs = append(envs, kv)
   168  	}
   169  	env[key] = i
   170  	setenv_c(key, value)
   171  	return nil
   172  }
   173  
   174  func Clearenv() {
   175  	envOnce.Do(copyenv) // prevent copyenv in Getenv/Setenv
   176  
   177  	envLock.Lock()
   178  	defer envLock.Unlock()
   179  
   180  	for k := range env {
   181  		unsetenv_c(k)
   182  	}
   183  	env = make(map[string]int)
   184  	envs = []string{}
   185  	// DARA Instrumentation
   186  	if (runtime.Is_dara_profiling_on()) {
   187  		runtime.Dara_Debug_Print(func() { println("[CLEARENV]") })
   188  		syscallInfo := dara.GeneralSyscall{dara.DSYS_CLEARENV, 0, 0, [10]dara.GeneralType{}, [10]dara.GeneralType{}}
   189  		runtime.Report_Syscall_To_Scheduler(dara.DSYS_CLEARENV, syscallInfo)
   190  	}
   191  }
   192  
   193  func Environ() []string {
   194  	envOnce.Do(copyenv)
   195  	envLock.RLock()
   196  	defer envLock.RUnlock()
   197  	a := make([]string, 0, len(envs))
   198  	for _, env := range envs {
   199  		if env != "" {
   200  			a = append(a, env)
   201  		}
   202  	}
   203  	// DARA Instrumentation
   204  	if (runtime.Is_dara_profiling_on()) {
   205  		runtime.Dara_Debug_Print(func() { println("[ENVIRON]") })
   206  		retInfo := dara.GeneralType{Type: dara.ARRAY, Integer: len(a)}
   207  		syscallInfo := dara.GeneralSyscall{dara.DSYS_ENVIRON, 0, 1, [10]dara.GeneralType{}, [10]dara.GeneralType{retInfo}}
   208  		runtime.Report_Syscall_To_Scheduler(dara.DSYS_ENVIRON, syscallInfo)
   209  	}
   210  	return a
   211  }