blob: 22c2941133e1bc5b021bcbc5f2a8d7797c7419d7 [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
Jim Cownie5e8470a2013-09-27 10:38:44 +00005//===----------------------------------------------------------------------===//
6//
7// The LLVM Compiler Infrastructure
8//
9// This file is dual licensed under the MIT and the University of Illinois Open
10// Source Licenses. See LICENSE.txt for details.
11//
12//===----------------------------------------------------------------------===//
13
Jonathan Peyton30419822017-05-12 18:01:32 +000014/* 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
Jim Cownie5e8470a2013-09-27 10:38:44 +000018
Jonathan Peyton30419822017-05-12 18:01:32 +000019 On Windows* OS, there are two environments (at least, see below):
Jim Cownie5e8470a2013-09-27 10:38:44 +000020
Jonathan Peyton30419822017-05-12 18:01:32 +000021 1. Environment maintained by Windows* OS on IA-32 architecture. Accessible
22 through GetEnvironmentVariable(), SetEnvironmentVariable(), and
23 GetEnvironmentStrings().
Jim Cownie5e8470a2013-09-27 10:38:44 +000024
Jonathan Peyton30419822017-05-12 18:01:32 +000025 2. Environment maintained by C RTL. Accessible through getenv(), putenv().
Jim Cownie5e8470a2013-09-27 10:38:44 +000026
Jonathan Peyton30419822017-05-12 18:01:32 +000027 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
30 IA-32 architecture.
Jim Cownie5e8470a2013-09-27 10:38:44 +000031
Jonathan Peyton30419822017-05-12 18:01:32 +000032 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.
Jim Cownie5e8470a2013-09-27 10:38:44 +000035
Jonathan Peyton30419822017-05-12 18:01:32 +000036 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. :-(
Jim Cownie5e8470a2013-09-27 10:38:44 +000038
Jonathan Peyton30419822017-05-12 18:01:32 +000039 Thus, proper way to work with environment on Windows* OS is:
Jim Cownie5e8470a2013-09-27 10:38:44 +000040
Jonathan Peyton30419822017-05-12 18:01:32 +000041 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.
Jim Cownie5e8470a2013-09-27 10:38:44 +000044
Jonathan Peyton30419822017-05-12 18:01:32 +000045 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().
48
49 2007-04-05 -- lev
Jim Cownie5e8470a2013-09-27 10:38:44 +000050*/
51
52#include "kmp_environment.h"
53
Jonathan Peyton30419822017-05-12 18:01:32 +000054#include "kmp.h" //
Jim Cownie5e8470a2013-09-27 10:38:44 +000055#include "kmp_i18n.h"
Jonathan Peyton30419822017-05-12 18:01:32 +000056#include "kmp_os.h" // KMP_OS_*.
57#include "kmp_str.h" // __kmp_str_*().
Jim Cownie5e8470a2013-09-27 10:38:44 +000058
59#if KMP_OS_UNIX
Jonathan Peyton30419822017-05-12 18:01:32 +000060#include <stdlib.h> // getenv, setenv, unsetenv.
61#include <string.h> // strlen, strcpy.
62#if KMP_OS_DARWIN
63#include <crt_externs.h>
64#define environ (*_NSGetEnviron())
Jim Cownie5e8470a2013-09-27 10:38:44 +000065#else
Jonathan Peyton30419822017-05-12 18:01:32 +000066extern char **environ;
Jim Cownie5e8470a2013-09-27 10:38:44 +000067#endif
Jonathan Peyton30419822017-05-12 18:01:32 +000068#elif KMP_OS_WINDOWS
69#include <windows.h> // GetEnvironmentVariable, SetEnvironmentVariable,
70// GetLastError.
71#else
72#error Unknown or unsupported OS.
73#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +000074
75// TODO: Eliminate direct memory allocations, use string operations instead.
76
Jonathan Peyton30419822017-05-12 18:01:32 +000077static inline void *allocate(size_t size) {
78 void *ptr = KMP_INTERNAL_MALLOC(size);
79 if (ptr == NULL) {
80 KMP_FATAL(MemoryAllocFailed);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +000081 }
Jonathan Peyton30419822017-05-12 18:01:32 +000082 return ptr;
Jim Cownie5e8470a2013-09-27 10:38:44 +000083} // allocate
84
Jonathan Peyton30419822017-05-12 18:01:32 +000085char *__kmp_env_get(char const *name) {
Jim Cownie5e8470a2013-09-27 10:38:44 +000086
Jonathan Peyton30419822017-05-12 18:01:32 +000087 char *result = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +000088
Jonathan Peyton30419822017-05-12 18:01:32 +000089#if KMP_OS_UNIX
90 char const *value = getenv(name);
91 if (value != NULL) {
92 size_t len = KMP_STRLEN(value) + 1;
93 result = (char *)KMP_INTERNAL_MALLOC(len);
94 if (result == NULL) {
95 KMP_FATAL(MemoryAllocFailed);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +000096 }
Jonathan Peyton30419822017-05-12 18:01:32 +000097 KMP_STRNCPY_S(result, len, value, len);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +000098 }
Jonathan Peyton30419822017-05-12 18:01:32 +000099#elif KMP_OS_WINDOWS
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.
104 JH 12/23/2002 */
105 DWORD rc;
106 rc = GetEnvironmentVariable(name, NULL, 0);
107 if (!rc) {
108 DWORD error = GetLastError();
109 if (error != ERROR_ENVVAR_NOT_FOUND) {
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000110 __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000111 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000112 // Variable is not found, it's ok, just continue.
113 } else {
114 DWORD len = rc;
115 result = (char *)KMP_INTERNAL_MALLOC(len);
116 if (result == NULL) {
117 KMP_FATAL(MemoryAllocFailed);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000118 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000119 rc = GetEnvironmentVariable(name, result, len);
120 if (!rc) {
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.
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000127 __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error),
128 __kmp_msg_null);
Jonathan Peyton30419822017-05-12 18:01:32 +0000129 KMP_INTERNAL_FREE((void *)result);
130 result = NULL;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000131 }
132 }
133 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000134#else
135#error Unknown or unsupported OS.
136#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +0000137
Jonathan Peyton30419822017-05-12 18:01:32 +0000138 return result;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000139
140} // func __kmp_env_get
141
Jim Cownie5e8470a2013-09-27 10:38:44 +0000142// TODO: Find and replace all regular free() with __kmp_env_free().
143
Jonathan Peyton30419822017-05-12 18:01:32 +0000144void __kmp_env_free(char const **value) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000145
Jonathan Peyton30419822017-05-12 18:01:32 +0000146 KMP_DEBUG_ASSERT(value != NULL);
Andrey Churbanovc47afcd2017-07-03 11:24:08 +0000147 KMP_INTERNAL_FREE(CCAST(char *, *value));
Jonathan Peyton30419822017-05-12 18:01:32 +0000148 *value = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000149
150} // func __kmp_env_free
151
Jonathan Peyton30419822017-05-12 18:01:32 +0000152int __kmp_env_exists(char const *name) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000153
Jonathan Peyton30419822017-05-12 18:01:32 +0000154#if KMP_OS_UNIX
155 char const *value = getenv(name);
156 return ((value == NULL) ? (0) : (1));
157#elif KMP_OS_WINDOWS
158 DWORD rc;
159 rc = GetEnvironmentVariable(name, NULL, 0);
160 if (rc == 0) {
161 DWORD error = GetLastError();
162 if (error != ERROR_ENVVAR_NOT_FOUND) {
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000163 __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000164 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000165 return 0;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000166 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000167 return 1;
168#else
169#error Unknown or unsupported OS.
170#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +0000171
172} // func __kmp_env_exists
173
Jonathan Peyton30419822017-05-12 18:01:32 +0000174void __kmp_env_set(char const *name, char const *value, int overwrite) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000175
Jonathan Peyton30419822017-05-12 18:01:32 +0000176#if KMP_OS_UNIX
177 int rc = setenv(name, value, overwrite);
178 if (rc != 0) {
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
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000184 __kmp_fatal(KMP_MSG(CantSetEnvVar, name), KMP_HNT(NotEnoughMemory),
185 __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000186 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000187#elif KMP_OS_WINDOWS
188 BOOL rc;
189 if (!overwrite) {
190 rc = GetEnvironmentVariable(name, NULL, 0);
191 if (rc) {
192 // Variable exists, do not overwrite.
193 return;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000194 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000195 DWORD error = GetLastError();
196 if (error != ERROR_ENVVAR_NOT_FOUND) {
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000197 __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000198 }
199 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000200 rc = SetEnvironmentVariable(name, value);
201 if (!rc) {
202 DWORD error = GetLastError();
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000203 __kmp_fatal(KMP_MSG(CantSetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000204 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000205#else
206#error Unknown or unsupported OS.
207#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +0000208
209} // func __kmp_env_set
210
Jonathan Peyton30419822017-05-12 18:01:32 +0000211void __kmp_env_unset(char const *name) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000212
Jonathan Peyton30419822017-05-12 18:01:32 +0000213#if KMP_OS_UNIX
214 unsetenv(name);
215#elif KMP_OS_WINDOWS
216 BOOL rc = SetEnvironmentVariable(name, NULL);
217 if (!rc) {
218 DWORD error = GetLastError();
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000219 __kmp_fatal(KMP_MSG(CantSetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000220 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000221#else
222#error Unknown or unsupported OS.
223#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +0000224
225} // func __kmp_env_unset
226
Jonathan Peyton30419822017-05-12 18:01:32 +0000227/* Intel OpenMP RTL string representation of environment: just a string of
228 characters, variables are separated with vertical bars, e. g.:
Jim Cownie5e8470a2013-09-27 10:38:44 +0000229
230 "KMP_WARNINGS=0|KMP_AFFINITY=compact|"
231
232 Empty variables are allowed and ignored:
233
234 "||KMP_WARNINGS=1||"
Jim Cownie5e8470a2013-09-27 10:38:44 +0000235*/
236
Jonathan Peyton30419822017-05-12 18:01:32 +0000237static void
238___kmp_env_blk_parse_string(kmp_env_blk_t *block, // M: Env block to fill.
239 char const *env // I: String to parse.
240 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000241
Jonathan Peyton30419822017-05-12 18:01:32 +0000242 char const chr_delimiter = '|';
243 char const str_delimiter[] = {chr_delimiter, 0};
Jim Cownie5e8470a2013-09-27 10:38:44 +0000244
Jonathan Peyton30419822017-05-12 18:01:32 +0000245 char *bulk = NULL;
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.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000249
Jonathan Peyton30419822017-05-12 18:01:32 +0000250 // Copy original string, we will modify the copy.
251 bulk = __kmp_str_format("%s", env);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000252
Jonathan Peyton30419822017-05-12 18:01:32 +0000253 // Loop thru all the vars in environment block. Count delimiters (maximum
254 // number of variables is number of delimiters plus one).
255 {
256 char const *ptr = bulk;
257 for (;;) {
258 ptr = strchr(ptr, chr_delimiter);
259 if (ptr == NULL) {
260 break;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000261 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000262 ++delimiters;
263 ptr += 1;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000264 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000265 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000266
Jonathan Peyton30419822017-05-12 18:01:32 +0000267 // Allocate vars array.
268 vars = (kmp_env_var_t *)allocate((delimiters + 1) * sizeof(kmp_env_var_t));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000269
Jonathan Peyton30419822017-05-12 18:01:32 +0000270 // Loop thru all the variables.
271 {
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;
283 ++count;
284 // Get the next var.
285 var = __kmp_str_token(NULL, str_delimiter, &buf);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000286 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000287 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000288
Jonathan Peyton30419822017-05-12 18:01:32 +0000289 // Fill out result.
290 block->bulk = bulk;
291 block->vars = vars;
292 block->count = count;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000293}
Jim Cownie5e8470a2013-09-27 10:38:44 +0000294
Jonathan Peyton30419822017-05-12 18:01:32 +0000295/* 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.:
Jim Cownie5e8470a2013-09-27 10:38:44 +0000299
300 "HOME=C:\\users\\lev\x00OS=Windows_NT\x00\x00"
301
302 It is not clear how empty environment is represented. "\x00\x00"?
303*/
304
Jonathan Peyton2321d572015-06-08 19:25:25 +0000305#if KMP_OS_WINDOWS
Jonathan Peyton30419822017-05-12 18:01:32 +0000306static 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.
309 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000310
Jonathan Peyton30419822017-05-12 18:01:32 +0000311 char *bulk = NULL;
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.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000315
Jonathan Peyton30419822017-05-12 18:01:32 +0000316 char *name; // Pointer to name of variable.
317 char *value; // Pointer to value.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000318
Jonathan Peyton30419822017-05-12 18:01:32 +0000319 if (env != NULL) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000320
Jonathan Peyton30419822017-05-12 18:01:32 +0000321 // Loop thru all the vars in environment block. Count variables, find size
322 // of block.
323 {
324 char const *var; // Pointer to beginning of var.
325 int len; // Length of variable.
326 count = 0;
327 var =
328 env; // The first variable starts and beginning of environment block.
329 len = KMP_STRLEN(var);
330 while (len != 0) {
331 ++count;
332 size = size + len + 1;
333 var = var + len +
334 1; // Move pointer to the beginning of the next variable.
335 len = KMP_STRLEN(var);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000336 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000337 size =
338 size + 1; // Total size of env block, including terminating zero byte.
339 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000340
Jonathan Peyton30419822017-05-12 18:01:32 +0000341 // 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));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000346
Jonathan Peyton30419822017-05-12 18:01:32 +0000347 // Loop thru all the vars, now in bulk.
348 {
349 char *var; // Pointer to beginning of var.
350 int len; // Length of variable.
351 count = 0;
352 var = bulk;
353 len = KMP_STRLEN(var);
354 while (len != 0) {
355 // Save variable in vars array.
356 __kmp_str_split(var, '=', &name, &value);
357 vars[count].name = name;
358 vars[count].value = value;
359 ++count;
360 // Get the next var.
361 var = var + len + 1;
362 len = KMP_STRLEN(var);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000363 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000364 }
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000365 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000366
Jonathan Peyton30419822017-05-12 18:01:32 +0000367 // Fill out result.
368 block->bulk = bulk;
369 block->vars = vars;
370 block->count = count;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000371}
Jonathan Peyton2321d572015-06-08 19:25:25 +0000372#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +0000373
Jonathan Peyton30419822017-05-12 18:01:32 +0000374/* Unix environment block is a array of pointers to variables, last pointer in
375 array is NULL:
Jim Cownie5e8470a2013-09-27 10:38:44 +0000376
377 { "HOME=/home/lev", "TERM=xterm", NULL }
378*/
379
Jonathan Peyton30419822017-05-12 18:01:32 +0000380static void
381___kmp_env_blk_parse_unix(kmp_env_blk_t *block, // M: Env block to fill.
382 char **env // I: Unix environment to parse.
383 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000384
Jonathan Peyton30419822017-05-12 18:01:32 +0000385 char *bulk = NULL;
386 kmp_env_var_t *vars = NULL;
387 int count = 0;
388 int size = 0; // Size of bulk.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000389
Jonathan Peyton30419822017-05-12 18:01:32 +0000390 // Count number of variables and length of required bulk.
391 {
392 count = 0;
393 size = 0;
394 while (env[count] != NULL) {
395 size += KMP_STRLEN(env[count]) + 1;
396 ++count;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000397 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000398 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000399
Jonathan Peyton30419822017-05-12 18:01:32 +0000400 // Allocate memory.
401 bulk = (char *)allocate(size);
402 vars = (kmp_env_var_t *)allocate(count * sizeof(kmp_env_var_t));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000403
Jonathan Peyton30419822017-05-12 18:01:32 +0000404 // Loop thru all the vars.
405 {
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.
410 int i;
411 var = bulk;
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);
418 vars[i].name = name;
419 vars[i].value = value;
420 // Move pointer.
421 var += len + 1;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000422 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000423 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000424
Jonathan Peyton30419822017-05-12 18:01:32 +0000425 // Fill out result.
426 block->bulk = bulk;
427 block->vars = vars;
428 block->count = count;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000429}
Jim Cownie5e8470a2013-09-27 10:38:44 +0000430
Jonathan Peyton30419822017-05-12 18:01:32 +0000431void __kmp_env_blk_init(kmp_env_blk_t *block, // M: Block to initialize.
432 char const *bulk // I: Initialization string, or NULL.
433 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000434
Jonathan Peyton30419822017-05-12 18:01:32 +0000435 if (bulk != NULL) {
436 ___kmp_env_blk_parse_string(block, bulk);
437 } else {
438#if KMP_OS_UNIX
439 ___kmp_env_blk_parse_unix(block, environ);
440#elif KMP_OS_WINDOWS
441 {
442 char *mem = GetEnvironmentStrings();
443 if (mem == NULL) {
444 DWORD error = GetLastError();
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000445 __kmp_fatal(KMP_MSG(CantGetEnvironment), KMP_ERR(error),
446 __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000447 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000448 ___kmp_env_blk_parse_windows(block, mem);
449 FreeEnvironmentStrings(mem);
450 }
451#else
452#error Unknown or unsupported OS.
453#endif
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000454 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000455
456} // __kmp_env_blk_init
457
Jonathan Peyton30419822017-05-12 18:01:32 +0000458static 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);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000461}
462
Jonathan Peyton30419822017-05-12 18:01:32 +0000463void __kmp_env_blk_sort(
464 kmp_env_blk_t *block // M: Block of environment variables to sort.
465 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000466
Andrey Churbanovc47afcd2017-07-03 11:24:08 +0000467 qsort(CCAST(kmp_env_var_t *, block->vars), block->count,
468 sizeof(kmp_env_var_t),
Jonathan Peyton30419822017-05-12 18:01:32 +0000469 (int (*)(void const *, void const *)) & ___kmp_env_var_cmp);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000470
471} // __kmp_env_block_sort
472
Jonathan Peyton30419822017-05-12 18:01:32 +0000473void __kmp_env_blk_free(
474 kmp_env_blk_t *block // M: Block of environment variables to free.
475 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000476
Andrey Churbanovc47afcd2017-07-03 11:24:08 +0000477 KMP_INTERNAL_FREE(CCAST(kmp_env_var_t *, block->vars));
Jonathan Peyton30419822017-05-12 18:01:32 +0000478 __kmp_str_free(&(block->bulk));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000479
Jonathan Peyton30419822017-05-12 18:01:32 +0000480 block->count = 0;
481 block->vars = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000482
483} // __kmp_env_blk_free
484
Jonathan Peyton30419822017-05-12 18:01:32 +0000485char const * // R: Value of variable or NULL if variable does not exist.
486 __kmp_env_blk_var(
487 kmp_env_blk_t *block, // I: Block of environment variables.
488 char const *name // I: Name of variable to find.
489 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000490
Jonathan Peyton30419822017-05-12 18:01:32 +0000491 int i;
492 for (i = 0; i < block->count; ++i) {
493 if (strcmp(block->vars[i].name, name) == 0) {
494 return block->vars[i].value;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000495 }
496 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000497 return NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000498
499} // __kmp_env_block_var
500
Jim Cownie5e8470a2013-09-27 10:38:44 +0000501// end of file //