1 /** 2 * Functions for modifying environment variables. 3 * 4 * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved 5 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 6 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/env.d, env.d) 7 * Documentation: https://dlang.org/phobos/dmd_env.html 8 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/env.d 9 */ 10 11 module dmd.env; 12 13 import core.stdc.string; 14 import core.sys.posix.stdlib; 15 import dmd.globals; 16 import dmd.root.array; 17 import dmd.root.rmem; 18 import dmd.root.string; 19 20 version (Windows) 21 private extern (C) int putenv(const char*) nothrow; 22 23 /** 24 Construct a variable from `name` and `value` and put it in the environment while saving 25 the previous value of the environment variable into a global list so it can be restored later. 26 Params: 27 name = the name of the variable 28 value = the value of the variable 29 Returns: 30 true on error, false on success 31 */ 32 bool putenvRestorable(const(char)[] name, const(char)[] value) nothrow 33 { 34 saveEnvVar(name); 35 const nameValue = allocNameValue(name, value); 36 const result = putenv(cast(char*)nameValue.ptr); 37 version (Windows) 38 mem.xfree(cast(void*)nameValue.ptr); 39 else 40 { 41 if (result) 42 mem.xfree(cast(void*)nameValue.ptr); 43 } 44 return result ? true : false; 45 } 46 47 /** 48 Allocate a new variable via xmalloc that can be added to the global environment. The 49 resulting string will be null-terminated immediately after the end of the array. 50 Params: 51 name = name of the variable 52 value = value of the variable 53 Returns: 54 a newly allocated variable that can be added to the global environment 55 */ 56 string allocNameValue(const(char)[] name, const(char)[] value) nothrow 57 { 58 const length = name.length + 1 + value.length; 59 auto str = (cast(char*)mem.xmalloc(length + 1))[0 .. length]; 60 str[0 .. name.length] = name[]; 61 str[name.length] = '='; 62 str[name.length + 1 .. length] = value[]; 63 str.ptr[length] = '\0'; 64 return cast(string)str; 65 } 66 67 /// Holds the original values of environment variables when they are overwritten. 68 private __gshared string[string] envNameValues; 69 70 /// Restore the original environment. 71 void restoreEnvVars() 72 { 73 foreach (var; envNameValues.values) 74 { 75 if (putenv(cast(char*)var.ptr)) 76 assert(0); 77 } 78 } 79 80 /// Save the environment variable `name` if not saved already. 81 void saveEnvVar(const(char)[] name) nothrow 82 { 83 if (!(name in envNameValues)) 84 { 85 envNameValues[name.idup] = allocNameValue(name, name.toCStringThen!(n => getenv(n.ptr)).toDString); 86 } 87 }