blob: efbe84e10b3fa44a20cc2b49ac13fe5b933a7bf3 [file] [log] [blame]
Jim Cownie5e8470a2013-09-27 10:38:44 +00001/*
Jonathan Peytonde4749b2016-12-14 23:01:24 +00002 * kmp_environment.cpp -- Handle environment variables OS-independently.
Jim Cownie5e8470a2013-09-27 10:38:44 +00003 */
4
5
6//===----------------------------------------------------------------------===//
7//
8// The LLVM Compiler Infrastructure
9//
10// This file is dual licensed under the MIT and the University of Illinois Open
11// Source Licenses. See LICENSE.txt for details.
12//
13//===----------------------------------------------------------------------===//
14
15
Jonathan Peyton30419822017-05-12 18:01:32 +000016/* We use GetEnvironmentVariable for Windows* OS instead of getenv because the
17 act of loading a DLL on Windows* OS makes any user-set environment variables
18 (i.e. with putenv()) unavailable. getenv() apparently gets a clean copy of
19 the env variables as they existed at the start of the run. JH 12/23/2002
Jim Cownie5e8470a2013-09-27 10:38:44 +000020
Jonathan Peyton30419822017-05-12 18:01:32 +000021 On Windows* OS, there are two environments (at least, see below):
Jim Cownie5e8470a2013-09-27 10:38:44 +000022
Jonathan Peyton30419822017-05-12 18:01:32 +000023 1. Environment maintained by Windows* OS on IA-32 architecture. Accessible
24 through GetEnvironmentVariable(), SetEnvironmentVariable(), and
25 GetEnvironmentStrings().
Jim Cownie5e8470a2013-09-27 10:38:44 +000026
Jonathan Peyton30419822017-05-12 18:01:32 +000027 2. Environment maintained by C RTL. Accessible through getenv(), putenv().
Jim Cownie5e8470a2013-09-27 10:38:44 +000028
Jonathan Peyton30419822017-05-12 18:01:32 +000029 putenv() function updates both C and Windows* OS on IA-32 architecture.
30 getenv() function search for variables in C RTL environment only.
31 Windows* OS on IA-32 architecture functions work *only* with Windows* OS on
32 IA-32 architecture.
Jim Cownie5e8470a2013-09-27 10:38:44 +000033
Jonathan Peyton30419822017-05-12 18:01:32 +000034 Windows* OS on IA-32 architecture maintained by OS, so there is always only
35 one Windows* OS on IA-32 architecture per process. Changes in Windows* OS on
36 IA-32 architecture are process-visible.
Jim Cownie5e8470a2013-09-27 10:38:44 +000037
Jonathan Peyton30419822017-05-12 18:01:32 +000038 C environment maintained by C RTL. Multiple copies of C RTL may be present
39 in the process, and each C RTL maintains its own environment. :-(
Jim Cownie5e8470a2013-09-27 10:38:44 +000040
Jonathan Peyton30419822017-05-12 18:01:32 +000041 Thus, proper way to work with environment on Windows* OS is:
Jim Cownie5e8470a2013-09-27 10:38:44 +000042
Jonathan Peyton30419822017-05-12 18:01:32 +000043 1. Set variables with putenv() function -- both C and Windows* OS on IA-32
44 architecture are being updated. Windows* OS on IA-32 architecture may be
45 considered primary target, while updating C RTL environment is free bonus.
Jim Cownie5e8470a2013-09-27 10:38:44 +000046
Jonathan Peyton30419822017-05-12 18:01:32 +000047 2. Get variables with GetEnvironmentVariable() -- getenv() does not
48 search Windows* OS on IA-32 architecture, and can not see variables
49 set with SetEnvironmentVariable().
50
51 2007-04-05 -- lev
Jim Cownie5e8470a2013-09-27 10:38:44 +000052*/
53
54#include "kmp_environment.h"
55
Jonathan Peyton30419822017-05-12 18:01:32 +000056#include "kmp.h" //
Jim Cownie5e8470a2013-09-27 10:38:44 +000057#include "kmp_i18n.h"
Jonathan Peyton30419822017-05-12 18:01:32 +000058#include "kmp_os.h" // KMP_OS_*.
59#include "kmp_str.h" // __kmp_str_*().
Jim Cownie5e8470a2013-09-27 10:38:44 +000060
61#if KMP_OS_UNIX
Jonathan Peyton30419822017-05-12 18:01:32 +000062#include <stdlib.h> // getenv, setenv, unsetenv.
63#include <string.h> // strlen, strcpy.
64#if KMP_OS_DARWIN
65#include <crt_externs.h>
66#define environ (*_NSGetEnviron())
Jim Cownie5e8470a2013-09-27 10:38:44 +000067#else
Jonathan Peyton30419822017-05-12 18:01:32 +000068extern char **environ;
Jim Cownie5e8470a2013-09-27 10:38:44 +000069#endif
Jonathan Peyton30419822017-05-12 18:01:32 +000070#elif KMP_OS_WINDOWS
71#include <windows.h> // GetEnvironmentVariable, SetEnvironmentVariable,
72// GetLastError.
73#else
74#error Unknown or unsupported OS.
75#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +000076
77// TODO: Eliminate direct memory allocations, use string operations instead.
78
Jonathan Peyton30419822017-05-12 18:01:32 +000079static inline void *allocate(size_t size) {
80 void *ptr = KMP_INTERNAL_MALLOC(size);
81 if (ptr == NULL) {
82 KMP_FATAL(MemoryAllocFailed);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +000083 }
Jonathan Peyton30419822017-05-12 18:01:32 +000084 return ptr;
Jim Cownie5e8470a2013-09-27 10:38:44 +000085} // allocate
86
Jonathan Peyton30419822017-05-12 18:01:32 +000087char *__kmp_env_get(char const *name) {
Jim Cownie5e8470a2013-09-27 10:38:44 +000088
Jonathan Peyton30419822017-05-12 18:01:32 +000089 char *result = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +000090
Jonathan Peyton30419822017-05-12 18:01:32 +000091#if KMP_OS_UNIX
92 char const *value = getenv(name);
93 if (value != NULL) {
94 size_t len = KMP_STRLEN(value) + 1;
95 result = (char *)KMP_INTERNAL_MALLOC(len);
96 if (result == NULL) {
97 KMP_FATAL(MemoryAllocFailed);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +000098 }
Jonathan Peyton30419822017-05-12 18:01:32 +000099 KMP_STRNCPY_S(result, len, value, len);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000100 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000101#elif KMP_OS_WINDOWS
102 /* We use GetEnvironmentVariable for Windows* OS instead of getenv because the
103 act of loading a DLL on Windows* OS makes any user-set environment
104 variables (i.e. with putenv()) unavailable. getenv() apparently gets a
105 clean copy of the env variables as they existed at the start of the run.
106 JH 12/23/2002 */
107 DWORD rc;
108 rc = GetEnvironmentVariable(name, NULL, 0);
109 if (!rc) {
110 DWORD error = GetLastError();
111 if (error != ERROR_ENVVAR_NOT_FOUND) {
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000112 __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000113 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000114 // Variable is not found, it's ok, just continue.
115 } else {
116 DWORD len = rc;
117 result = (char *)KMP_INTERNAL_MALLOC(len);
118 if (result == NULL) {
119 KMP_FATAL(MemoryAllocFailed);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000120 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000121 rc = GetEnvironmentVariable(name, result, len);
122 if (!rc) {
123 // GetEnvironmentVariable() may return 0 if variable is empty.
124 // In such a case GetLastError() returns ERROR_SUCCESS.
125 DWORD error = GetLastError();
126 if (error != ERROR_SUCCESS) {
127 // Unexpected error. The variable should be in the environment,
128 // and buffer should be large enough.
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000129 __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error),
130 __kmp_msg_null);
Jonathan Peyton30419822017-05-12 18:01:32 +0000131 KMP_INTERNAL_FREE((void *)result);
132 result = NULL;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000133 }
134 }
135 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000136#else
137#error Unknown or unsupported OS.
138#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +0000139
Jonathan Peyton30419822017-05-12 18:01:32 +0000140 return result;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000141
142} // func __kmp_env_get
143
Jim Cownie5e8470a2013-09-27 10:38:44 +0000144// TODO: Find and replace all regular free() with __kmp_env_free().
145
Jonathan Peyton30419822017-05-12 18:01:32 +0000146void __kmp_env_free(char const **value) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000147
Jonathan Peyton30419822017-05-12 18:01:32 +0000148 KMP_DEBUG_ASSERT(value != NULL);
Andrey Churbanovc47afcd2017-07-03 11:24:08 +0000149 KMP_INTERNAL_FREE(CCAST(char *, *value));
Jonathan Peyton30419822017-05-12 18:01:32 +0000150 *value = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000151
152} // func __kmp_env_free
153
Jonathan Peyton30419822017-05-12 18:01:32 +0000154int __kmp_env_exists(char const *name) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000155
Jonathan Peyton30419822017-05-12 18:01:32 +0000156#if KMP_OS_UNIX
157 char const *value = getenv(name);
158 return ((value == NULL) ? (0) : (1));
159#elif KMP_OS_WINDOWS
160 DWORD rc;
161 rc = GetEnvironmentVariable(name, NULL, 0);
162 if (rc == 0) {
163 DWORD error = GetLastError();
164 if (error != ERROR_ENVVAR_NOT_FOUND) {
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000165 __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000166 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000167 return 0;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000168 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000169 return 1;
170#else
171#error Unknown or unsupported OS.
172#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +0000173
174} // func __kmp_env_exists
175
Jonathan Peyton30419822017-05-12 18:01:32 +0000176void __kmp_env_set(char const *name, char const *value, int overwrite) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000177
Jonathan Peyton30419822017-05-12 18:01:32 +0000178#if KMP_OS_UNIX
179 int rc = setenv(name, value, overwrite);
180 if (rc != 0) {
181 // Dead code. I tried to put too many variables into Linux* OS
182 // environment on IA-32 architecture. When application consumes
183 // more than ~2.5 GB of memory, entire system feels bad. Sometimes
184 // application is killed (by OS?), sometimes system stops
185 // responding... But this error message never appears. --ln
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000186 __kmp_fatal(KMP_MSG(CantSetEnvVar, name), KMP_HNT(NotEnoughMemory),
187 __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000188 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000189#elif KMP_OS_WINDOWS
190 BOOL rc;
191 if (!overwrite) {
192 rc = GetEnvironmentVariable(name, NULL, 0);
193 if (rc) {
194 // Variable exists, do not overwrite.
195 return;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000196 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000197 DWORD error = GetLastError();
198 if (error != ERROR_ENVVAR_NOT_FOUND) {
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000199 __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000200 }
201 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000202 rc = SetEnvironmentVariable(name, value);
203 if (!rc) {
204 DWORD error = GetLastError();
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000205 __kmp_fatal(KMP_MSG(CantSetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000206 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000207#else
208#error Unknown or unsupported OS.
209#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +0000210
211} // func __kmp_env_set
212
Jonathan Peyton30419822017-05-12 18:01:32 +0000213void __kmp_env_unset(char const *name) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000214
Jonathan Peyton30419822017-05-12 18:01:32 +0000215#if KMP_OS_UNIX
216 unsetenv(name);
217#elif KMP_OS_WINDOWS
218 BOOL rc = SetEnvironmentVariable(name, NULL);
219 if (!rc) {
220 DWORD error = GetLastError();
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000221 __kmp_fatal(KMP_MSG(CantSetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000222 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000223#else
224#error Unknown or unsupported OS.
225#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +0000226
227} // func __kmp_env_unset
228
Jonathan Peyton30419822017-05-12 18:01:32 +0000229/* Intel OpenMP RTL string representation of environment: just a string of
230 characters, variables are separated with vertical bars, e. g.:
Jim Cownie5e8470a2013-09-27 10:38:44 +0000231
232 "KMP_WARNINGS=0|KMP_AFFINITY=compact|"
233
234 Empty variables are allowed and ignored:
235
236 "||KMP_WARNINGS=1||"
Jim Cownie5e8470a2013-09-27 10:38:44 +0000237*/
238
Jonathan Peyton30419822017-05-12 18:01:32 +0000239static void
240___kmp_env_blk_parse_string(kmp_env_blk_t *block, // M: Env block to fill.
241 char const *env // I: String to parse.
242 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000243
Jonathan Peyton30419822017-05-12 18:01:32 +0000244 char const chr_delimiter = '|';
245 char const str_delimiter[] = {chr_delimiter, 0};
Jim Cownie5e8470a2013-09-27 10:38:44 +0000246
Jonathan Peyton30419822017-05-12 18:01:32 +0000247 char *bulk = NULL;
248 kmp_env_var_t *vars = NULL;
249 int count = 0; // Number of used elements in vars array.
250 int delimiters = 0; // Number of delimiters in input string.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000251
Jonathan Peyton30419822017-05-12 18:01:32 +0000252 // Copy original string, we will modify the copy.
253 bulk = __kmp_str_format("%s", env);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000254
Jonathan Peyton30419822017-05-12 18:01:32 +0000255 // Loop thru all the vars in environment block. Count delimiters (maximum
256 // number of variables is number of delimiters plus one).
257 {
258 char const *ptr = bulk;
259 for (;;) {
260 ptr = strchr(ptr, chr_delimiter);
261 if (ptr == NULL) {
262 break;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000263 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000264 ++delimiters;
265 ptr += 1;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000266 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000267 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000268
Jonathan Peyton30419822017-05-12 18:01:32 +0000269 // Allocate vars array.
270 vars = (kmp_env_var_t *)allocate((delimiters + 1) * sizeof(kmp_env_var_t));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000271
Jonathan Peyton30419822017-05-12 18:01:32 +0000272 // Loop thru all the variables.
273 {
274 char *var; // Pointer to variable (both name and value).
275 char *name; // Pointer to name of variable.
276 char *value; // Pointer to value.
277 char *buf; // Buffer for __kmp_str_token() function.
278 var = __kmp_str_token(bulk, str_delimiter, &buf); // Get the first var.
279 while (var != NULL) {
280 // Save found variable in vars array.
281 __kmp_str_split(var, '=', &name, &value);
282 KMP_DEBUG_ASSERT(count < delimiters + 1);
283 vars[count].name = name;
284 vars[count].value = value;
285 ++count;
286 // Get the next var.
287 var = __kmp_str_token(NULL, str_delimiter, &buf);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000288 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000289 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000290
Jonathan Peyton30419822017-05-12 18:01:32 +0000291 // Fill out result.
292 block->bulk = bulk;
293 block->vars = vars;
294 block->count = count;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000295}
Jim Cownie5e8470a2013-09-27 10:38:44 +0000296
Jonathan Peyton30419822017-05-12 18:01:32 +0000297/* Windows* OS (actually, DOS) environment block is a piece of memory with
298 environment variables. Each variable is terminated with zero byte, entire
299 block is terminated with one extra zero byte, so we have two zero bytes at
300 the end of environment block, e. g.:
Jim Cownie5e8470a2013-09-27 10:38:44 +0000301
302 "HOME=C:\\users\\lev\x00OS=Windows_NT\x00\x00"
303
304 It is not clear how empty environment is represented. "\x00\x00"?
305*/
306
Jonathan Peyton2321d572015-06-08 19:25:25 +0000307#if KMP_OS_WINDOWS
Jonathan Peyton30419822017-05-12 18:01:32 +0000308static void ___kmp_env_blk_parse_windows(
309 kmp_env_blk_t *block, // M: Env block to fill.
310 char const *env // I: Pointer to Windows* OS (DOS) environment block.
311 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000312
Jonathan Peyton30419822017-05-12 18:01:32 +0000313 char *bulk = NULL;
314 kmp_env_var_t *vars = NULL;
315 int count = 0; // Number of used elements in vars array.
316 int size = 0; // Size of bulk.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000317
Jonathan Peyton30419822017-05-12 18:01:32 +0000318 char *name; // Pointer to name of variable.
319 char *value; // Pointer to value.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000320
Jonathan Peyton30419822017-05-12 18:01:32 +0000321 if (env != NULL) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000322
Jonathan Peyton30419822017-05-12 18:01:32 +0000323 // Loop thru all the vars in environment block. Count variables, find size
324 // of block.
325 {
326 char const *var; // Pointer to beginning of var.
327 int len; // Length of variable.
328 count = 0;
329 var =
330 env; // The first variable starts and beginning of environment block.
331 len = KMP_STRLEN(var);
332 while (len != 0) {
333 ++count;
334 size = size + len + 1;
335 var = var + len +
336 1; // Move pointer to the beginning of the next variable.
337 len = KMP_STRLEN(var);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000338 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000339 size =
340 size + 1; // Total size of env block, including terminating zero byte.
341 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000342
Jonathan Peyton30419822017-05-12 18:01:32 +0000343 // Copy original block to bulk, we will modify bulk, not original block.
344 bulk = (char *)allocate(size);
345 KMP_MEMCPY_S(bulk, size, env, size);
346 // Allocate vars array.
347 vars = (kmp_env_var_t *)allocate(count * sizeof(kmp_env_var_t));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000348
Jonathan Peyton30419822017-05-12 18:01:32 +0000349 // Loop thru all the vars, now in bulk.
350 {
351 char *var; // Pointer to beginning of var.
352 int len; // Length of variable.
353 count = 0;
354 var = bulk;
355 len = KMP_STRLEN(var);
356 while (len != 0) {
357 // Save variable in vars array.
358 __kmp_str_split(var, '=', &name, &value);
359 vars[count].name = name;
360 vars[count].value = value;
361 ++count;
362 // Get the next var.
363 var = var + len + 1;
364 len = KMP_STRLEN(var);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000365 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000366 }
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000367 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000368
Jonathan Peyton30419822017-05-12 18:01:32 +0000369 // Fill out result.
370 block->bulk = bulk;
371 block->vars = vars;
372 block->count = count;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000373}
Jonathan Peyton2321d572015-06-08 19:25:25 +0000374#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +0000375
Jonathan Peyton30419822017-05-12 18:01:32 +0000376/* Unix environment block is a array of pointers to variables, last pointer in
377 array is NULL:
Jim Cownie5e8470a2013-09-27 10:38:44 +0000378
379 { "HOME=/home/lev", "TERM=xterm", NULL }
380*/
381
Jonathan Peyton30419822017-05-12 18:01:32 +0000382static void
383___kmp_env_blk_parse_unix(kmp_env_blk_t *block, // M: Env block to fill.
384 char **env // I: Unix environment to parse.
385 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000386
Jonathan Peyton30419822017-05-12 18:01:32 +0000387 char *bulk = NULL;
388 kmp_env_var_t *vars = NULL;
389 int count = 0;
390 int size = 0; // Size of bulk.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000391
Jonathan Peyton30419822017-05-12 18:01:32 +0000392 // Count number of variables and length of required bulk.
393 {
394 count = 0;
395 size = 0;
396 while (env[count] != NULL) {
397 size += KMP_STRLEN(env[count]) + 1;
398 ++count;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000399 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000400 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000401
Jonathan Peyton30419822017-05-12 18:01:32 +0000402 // Allocate memory.
403 bulk = (char *)allocate(size);
404 vars = (kmp_env_var_t *)allocate(count * sizeof(kmp_env_var_t));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000405
Jonathan Peyton30419822017-05-12 18:01:32 +0000406 // Loop thru all the vars.
407 {
408 char *var; // Pointer to beginning of var.
409 char *name; // Pointer to name of variable.
410 char *value; // Pointer to value.
411 int len; // Length of variable.
412 int i;
413 var = bulk;
414 for (i = 0; i < count; ++i) {
415 // Copy variable to bulk.
416 len = KMP_STRLEN(env[i]);
417 KMP_MEMCPY_S(var, size, env[i], len + 1);
418 // Save found variable in vars array.
419 __kmp_str_split(var, '=', &name, &value);
420 vars[i].name = name;
421 vars[i].value = value;
422 // Move pointer.
423 var += len + 1;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000424 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000425 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000426
Jonathan Peyton30419822017-05-12 18:01:32 +0000427 // Fill out result.
428 block->bulk = bulk;
429 block->vars = vars;
430 block->count = count;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000431}
Jim Cownie5e8470a2013-09-27 10:38:44 +0000432
Jonathan Peyton30419822017-05-12 18:01:32 +0000433void __kmp_env_blk_init(kmp_env_blk_t *block, // M: Block to initialize.
434 char const *bulk // I: Initialization string, or NULL.
435 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000436
Jonathan Peyton30419822017-05-12 18:01:32 +0000437 if (bulk != NULL) {
438 ___kmp_env_blk_parse_string(block, bulk);
439 } else {
440#if KMP_OS_UNIX
441 ___kmp_env_blk_parse_unix(block, environ);
442#elif KMP_OS_WINDOWS
443 {
444 char *mem = GetEnvironmentStrings();
445 if (mem == NULL) {
446 DWORD error = GetLastError();
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000447 __kmp_fatal(KMP_MSG(CantGetEnvironment), KMP_ERR(error),
448 __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000449 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000450 ___kmp_env_blk_parse_windows(block, mem);
451 FreeEnvironmentStrings(mem);
452 }
453#else
454#error Unknown or unsupported OS.
455#endif
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000456 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000457
458} // __kmp_env_blk_init
459
Jonathan Peyton30419822017-05-12 18:01:32 +0000460static int ___kmp_env_var_cmp( // Comparison function for qsort().
461 kmp_env_var_t const *lhs, kmp_env_var_t const *rhs) {
462 return strcmp(lhs->name, rhs->name);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000463}
464
Jonathan Peyton30419822017-05-12 18:01:32 +0000465void __kmp_env_blk_sort(
466 kmp_env_blk_t *block // M: Block of environment variables to sort.
467 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000468
Andrey Churbanovc47afcd2017-07-03 11:24:08 +0000469 qsort(CCAST(kmp_env_var_t *, block->vars), block->count,
470 sizeof(kmp_env_var_t),
Jonathan Peyton30419822017-05-12 18:01:32 +0000471 (int (*)(void const *, void const *)) & ___kmp_env_var_cmp);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000472
473} // __kmp_env_block_sort
474
Jonathan Peyton30419822017-05-12 18:01:32 +0000475void __kmp_env_blk_free(
476 kmp_env_blk_t *block // M: Block of environment variables to free.
477 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000478
Andrey Churbanovc47afcd2017-07-03 11:24:08 +0000479 KMP_INTERNAL_FREE(CCAST(kmp_env_var_t *, block->vars));
Jonathan Peyton30419822017-05-12 18:01:32 +0000480 __kmp_str_free(&(block->bulk));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000481
Jonathan Peyton30419822017-05-12 18:01:32 +0000482 block->count = 0;
483 block->vars = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000484
485} // __kmp_env_blk_free
486
Jonathan Peyton30419822017-05-12 18:01:32 +0000487char const * // R: Value of variable or NULL if variable does not exist.
488 __kmp_env_blk_var(
489 kmp_env_blk_t *block, // I: Block of environment variables.
490 char const *name // I: Name of variable to find.
491 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000492
Jonathan Peyton30419822017-05-12 18:01:32 +0000493 int i;
494 for (i = 0; i < block->count; ++i) {
495 if (strcmp(block->vars[i].name, name) == 0) {
496 return block->vars[i].value;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000497 }
498 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000499 return NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000500
501} // __kmp_env_block_var
502
Jim Cownie5e8470a2013-09-27 10:38:44 +0000503// end of file //