2 * kmp_environment.cpp -- Handle environment variables OS-independently.
5 //===----------------------------------------------------------------------===//
7 // The LLVM Compiler Infrastructure
9 // This file is dual licensed under the MIT and the University of Illinois Open
10 // Source Licenses. See LICENSE.txt for details.
12 //===----------------------------------------------------------------------===//
14 /* We use GetEnvironmentVariable for Windows* OS instead of getenv because the
15 act of loading a DLL on Windows* OS makes any user-set environment variables
16 (i.e. with putenv()) unavailable. getenv() apparently gets a clean copy of
17 the env variables as they existed at the start of the run. JH 12/23/2002
19 On Windows* OS, there are two environments (at least, see below):
21 1. Environment maintained by Windows* OS on IA-32 architecture. Accessible
22 through GetEnvironmentVariable(), SetEnvironmentVariable(), and
23 GetEnvironmentStrings().
25 2. Environment maintained by C RTL. Accessible through getenv(), putenv().
27 putenv() function updates both C and Windows* OS on IA-32 architecture.
28 getenv() function search for variables in C RTL environment only.
29 Windows* OS on IA-32 architecture functions work *only* with Windows* OS on
32 Windows* OS on IA-32 architecture maintained by OS, so there is always only
33 one Windows* OS on IA-32 architecture per process. Changes in Windows* OS on
34 IA-32 architecture are process-visible.
36 C environment maintained by C RTL. Multiple copies of C RTL may be present
37 in the process, and each C RTL maintains its own environment. :-(
39 Thus, proper way to work with environment on Windows* OS is:
41 1. Set variables with putenv() function -- both C and Windows* OS on IA-32
42 architecture are being updated. Windows* OS on IA-32 architecture may be
43 considered primary target, while updating C RTL environment is free bonus.
45 2. Get variables with GetEnvironmentVariable() -- getenv() does not
46 search Windows* OS on IA-32 architecture, and can not see variables
47 set with SetEnvironmentVariable().
52 #include "kmp_environment.h"
56 #include "kmp_os.h" // KMP_OS_*.
57 #include "kmp_str.h" // __kmp_str_*().
60 #include <stdlib.h> // getenv, setenv, unsetenv.
61 #include <string.h> // strlen, strcpy.
63 #include <crt_externs.h>
64 #define environ (*_NSGetEnviron())
66 extern char **environ;
69 #include <windows.h> // GetEnvironmentVariable, SetEnvironmentVariable,
72 #error Unknown or unsupported OS.
75 // TODO: Eliminate direct memory allocations, use string operations instead.
77 static inline void *allocate(size_t size) {
78 void *ptr = KMP_INTERNAL_MALLOC(size);
80 KMP_FATAL(MemoryAllocFailed);
85 char *__kmp_env_get(char const *name) {
90 char const *value = getenv(name);
92 size_t len = KMP_STRLEN(value) + 1;
93 result = (char *)KMP_INTERNAL_MALLOC(len);
95 KMP_FATAL(MemoryAllocFailed);
97 KMP_STRNCPY_S(result, len, value, len);
100 /* We use GetEnvironmentVariable for Windows* OS instead of getenv because the
101 act of loading a DLL on Windows* OS makes any user-set environment
102 variables (i.e. with putenv()) unavailable. getenv() apparently gets a
103 clean copy of the env variables as they existed at the start of the run.
106 rc = GetEnvironmentVariable(name, NULL, 0);
108 DWORD error = GetLastError();
109 if (error != ERROR_ENVVAR_NOT_FOUND) {
110 __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
112 // Variable is not found, it's ok, just continue.
115 result = (char *)KMP_INTERNAL_MALLOC(len);
116 if (result == NULL) {
117 KMP_FATAL(MemoryAllocFailed);
119 rc = GetEnvironmentVariable(name, result, len);
121 // GetEnvironmentVariable() may return 0 if variable is empty.
122 // In such a case GetLastError() returns ERROR_SUCCESS.
123 DWORD error = GetLastError();
124 if (error != ERROR_SUCCESS) {
125 // Unexpected error. The variable should be in the environment,
126 // and buffer should be large enough.
127 __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error),
129 KMP_INTERNAL_FREE((void *)result);
135 #error Unknown or unsupported OS.
140 } // func __kmp_env_get
142 // TODO: Find and replace all regular free() with __kmp_env_free().
144 void __kmp_env_free(char const **value) {
146 KMP_DEBUG_ASSERT(value != NULL);
147 KMP_INTERNAL_FREE(CCAST(char *, *value));
150 } // func __kmp_env_free
152 int __kmp_env_exists(char const *name) {
155 char const *value = getenv(name);
156 return ((value == NULL) ? (0) : (1));
159 rc = GetEnvironmentVariable(name, NULL, 0);
161 DWORD error = GetLastError();
162 if (error != ERROR_ENVVAR_NOT_FOUND) {
163 __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
169 #error Unknown or unsupported OS.
172 } // func __kmp_env_exists
174 void __kmp_env_set(char const *name, char const *value, int overwrite) {
177 int rc = setenv(name, value, overwrite);
179 // Dead code. I tried to put too many variables into Linux* OS
180 // environment on IA-32 architecture. When application consumes
181 // more than ~2.5 GB of memory, entire system feels bad. Sometimes
182 // application is killed (by OS?), sometimes system stops
183 // responding... But this error message never appears. --ln
184 __kmp_fatal(KMP_MSG(CantSetEnvVar, name), KMP_HNT(NotEnoughMemory),
190 rc = GetEnvironmentVariable(name, NULL, 0);
192 // Variable exists, do not overwrite.
195 DWORD error = GetLastError();
196 if (error != ERROR_ENVVAR_NOT_FOUND) {
197 __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
200 rc = SetEnvironmentVariable(name, value);
202 DWORD error = GetLastError();
203 __kmp_fatal(KMP_MSG(CantSetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
206 #error Unknown or unsupported OS.
209 } // func __kmp_env_set
211 void __kmp_env_unset(char const *name) {
216 BOOL rc = SetEnvironmentVariable(name, NULL);
218 DWORD error = GetLastError();
219 __kmp_fatal(KMP_MSG(CantSetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
222 #error Unknown or unsupported OS.
225 } // func __kmp_env_unset
227 /* Intel OpenMP RTL string representation of environment: just a string of
228 characters, variables are separated with vertical bars, e. g.:
230 "KMP_WARNINGS=0|KMP_AFFINITY=compact|"
232 Empty variables are allowed and ignored:
238 ___kmp_env_blk_parse_string(kmp_env_blk_t *block, // M: Env block to fill.
239 char const *env // I: String to parse.
242 char const chr_delimiter = '|';
243 char const str_delimiter[] = {chr_delimiter, 0};
246 kmp_env_var_t *vars = NULL;
247 int count = 0; // Number of used elements in vars array.
248 int delimiters = 0; // Number of delimiters in input string.
250 // Copy original string, we will modify the copy.
251 bulk = __kmp_str_format("%s", env);
253 // Loop thru all the vars in environment block. Count delimiters (maximum
254 // number of variables is number of delimiters plus one).
256 char const *ptr = bulk;
258 ptr = strchr(ptr, chr_delimiter);
267 // Allocate vars array.
268 vars = (kmp_env_var_t *)allocate((delimiters + 1) * sizeof(kmp_env_var_t));
270 // Loop thru all the variables.
272 char *var; // Pointer to variable (both name and value).
273 char *name; // Pointer to name of variable.
274 char *value; // Pointer to value.
275 char *buf; // Buffer for __kmp_str_token() function.
276 var = __kmp_str_token(bulk, str_delimiter, &buf); // Get the first var.
277 while (var != NULL) {
278 // Save found variable in vars array.
279 __kmp_str_split(var, '=', &name, &value);
280 KMP_DEBUG_ASSERT(count < delimiters + 1);
281 vars[count].name = name;
282 vars[count].value = value;
285 var = __kmp_str_token(NULL, str_delimiter, &buf);
292 block->count = count;
295 /* Windows* OS (actually, DOS) environment block is a piece of memory with
296 environment variables. Each variable is terminated with zero byte, entire
297 block is terminated with one extra zero byte, so we have two zero bytes at
298 the end of environment block, e. g.:
300 "HOME=C:\\users\\lev\x00OS=Windows_NT\x00\x00"
302 It is not clear how empty environment is represented. "\x00\x00"?
306 static void ___kmp_env_blk_parse_windows(
307 kmp_env_blk_t *block, // M: Env block to fill.
308 char const *env // I: Pointer to Windows* OS (DOS) environment block.
312 kmp_env_var_t *vars = NULL;
313 int count = 0; // Number of used elements in vars array.
314 int size = 0; // Size of bulk.
316 char *name; // Pointer to name of variable.
317 char *value; // Pointer to value.
321 // Loop thru all the vars in environment block. Count variables, find size
324 char const *var; // Pointer to beginning of var.
325 int len; // Length of variable.
328 env; // The first variable starts and beginning of environment block.
329 len = KMP_STRLEN(var);
332 size = size + len + 1;
334 1; // Move pointer to the beginning of the next variable.
335 len = KMP_STRLEN(var);
338 size + 1; // Total size of env block, including terminating zero byte.
341 // Copy original block to bulk, we will modify bulk, not original block.
342 bulk = (char *)allocate(size);
343 KMP_MEMCPY_S(bulk, size, env, size);
344 // Allocate vars array.
345 vars = (kmp_env_var_t *)allocate(count * sizeof(kmp_env_var_t));
347 // Loop thru all the vars, now in bulk.
349 char *var; // Pointer to beginning of var.
350 int len; // Length of variable.
353 len = KMP_STRLEN(var);
355 // Save variable in vars array.
356 __kmp_str_split(var, '=', &name, &value);
357 vars[count].name = name;
358 vars[count].value = value;
362 len = KMP_STRLEN(var);
370 block->count = count;
374 /* Unix environment block is a array of pointers to variables, last pointer in
377 { "HOME=/home/lev", "TERM=xterm", NULL }
381 ___kmp_env_blk_parse_unix(kmp_env_blk_t *block, // M: Env block to fill.
382 char **env // I: Unix environment to parse.
386 kmp_env_var_t *vars = NULL;
388 int size = 0; // Size of bulk.
390 // Count number of variables and length of required bulk.
394 while (env[count] != NULL) {
395 size += KMP_STRLEN(env[count]) + 1;
401 bulk = (char *)allocate(size);
402 vars = (kmp_env_var_t *)allocate(count * sizeof(kmp_env_var_t));
404 // Loop thru all the vars.
406 char *var; // Pointer to beginning of var.
407 char *name; // Pointer to name of variable.
408 char *value; // Pointer to value.
409 int len; // Length of variable.
412 for (i = 0; i < count; ++i) {
413 // Copy variable to bulk.
414 len = KMP_STRLEN(env[i]);
415 KMP_MEMCPY_S(var, size, env[i], len + 1);
416 // Save found variable in vars array.
417 __kmp_str_split(var, '=', &name, &value);
419 vars[i].value = value;
428 block->count = count;
431 void __kmp_env_blk_init(kmp_env_blk_t *block, // M: Block to initialize.
432 char const *bulk // I: Initialization string, or NULL.
436 ___kmp_env_blk_parse_string(block, bulk);
439 ___kmp_env_blk_parse_unix(block, environ);
442 char *mem = GetEnvironmentStrings();
444 DWORD error = GetLastError();
445 __kmp_fatal(KMP_MSG(CantGetEnvironment), KMP_ERR(error),
448 ___kmp_env_blk_parse_windows(block, mem);
449 FreeEnvironmentStrings(mem);
452 #error Unknown or unsupported OS.
456 } // __kmp_env_blk_init
458 static int ___kmp_env_var_cmp( // Comparison function for qsort().
459 kmp_env_var_t const *lhs, kmp_env_var_t const *rhs) {
460 return strcmp(lhs->name, rhs->name);
463 void __kmp_env_blk_sort(
464 kmp_env_blk_t *block // M: Block of environment variables to sort.
467 qsort(CCAST(kmp_env_var_t *, block->vars), block->count,
468 sizeof(kmp_env_var_t),
469 (int (*)(void const *, void const *)) & ___kmp_env_var_cmp);
471 } // __kmp_env_block_sort
473 void __kmp_env_blk_free(
474 kmp_env_blk_t *block // M: Block of environment variables to free.
477 KMP_INTERNAL_FREE(CCAST(kmp_env_var_t *, block->vars));
478 __kmp_str_free(&(block->bulk));
483 } // __kmp_env_blk_free
485 char const * // R: Value of variable or NULL if variable does not exist.
487 kmp_env_blk_t *block, // I: Block of environment variables.
488 char const *name // I: Name of variable to find.
492 for (i = 0; i < block->count; ++i) {
493 if (strcmp(block->vars[i].name, name) == 0) {
494 return block->vars[i].value;
499 } // __kmp_env_block_var