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