blob: 51bc3cf4558901c52727195f9a5ea5d6ce6027f1 [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//
Chandler Carruth57b08b02019-01-19 10:56:40 +00007// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
8// See https://llvm.org/LICENSE.txt for license information.
9// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Jim Cownie5e8470a2013-09-27 10:38:44 +000010//
11//===----------------------------------------------------------------------===//
12
Jonathan Peyton30419822017-05-12 18:01:32 +000013/* We use GetEnvironmentVariable for Windows* OS instead of getenv because the
14 act of loading a DLL on Windows* OS makes any user-set environment variables
15 (i.e. with putenv()) unavailable. getenv() apparently gets a clean copy of
16 the env variables as they existed at the start of the run. JH 12/23/2002
Jim Cownie5e8470a2013-09-27 10:38:44 +000017
Jonathan Peyton30419822017-05-12 18:01:32 +000018 On Windows* OS, there are two environments (at least, see below):
Jim Cownie5e8470a2013-09-27 10:38:44 +000019
Jonathan Peyton30419822017-05-12 18:01:32 +000020 1. Environment maintained by Windows* OS on IA-32 architecture. Accessible
21 through GetEnvironmentVariable(), SetEnvironmentVariable(), and
22 GetEnvironmentStrings().
Jim Cownie5e8470a2013-09-27 10:38:44 +000023
Jonathan Peyton30419822017-05-12 18:01:32 +000024 2. Environment maintained by C RTL. Accessible through getenv(), putenv().
Jim Cownie5e8470a2013-09-27 10:38:44 +000025
Jonathan Peyton30419822017-05-12 18:01:32 +000026 putenv() function updates both C and Windows* OS on IA-32 architecture.
27 getenv() function search for variables in C RTL environment only.
28 Windows* OS on IA-32 architecture functions work *only* with Windows* OS on
29 IA-32 architecture.
Jim Cownie5e8470a2013-09-27 10:38:44 +000030
Jonathan Peyton30419822017-05-12 18:01:32 +000031 Windows* OS on IA-32 architecture maintained by OS, so there is always only
32 one Windows* OS on IA-32 architecture per process. Changes in Windows* OS on
33 IA-32 architecture are process-visible.
Jim Cownie5e8470a2013-09-27 10:38:44 +000034
Jonathan Peyton30419822017-05-12 18:01:32 +000035 C environment maintained by C RTL. Multiple copies of C RTL may be present
36 in the process, and each C RTL maintains its own environment. :-(
Jim Cownie5e8470a2013-09-27 10:38:44 +000037
Jonathan Peyton30419822017-05-12 18:01:32 +000038 Thus, proper way to work with environment on Windows* OS is:
Jim Cownie5e8470a2013-09-27 10:38:44 +000039
Jonathan Peyton30419822017-05-12 18:01:32 +000040 1. Set variables with putenv() function -- both C and Windows* OS on IA-32
41 architecture are being updated. Windows* OS on IA-32 architecture may be
42 considered primary target, while updating C RTL environment is free bonus.
Jim Cownie5e8470a2013-09-27 10:38:44 +000043
Jonathan Peyton30419822017-05-12 18:01:32 +000044 2. Get variables with GetEnvironmentVariable() -- getenv() does not
45 search Windows* OS on IA-32 architecture, and can not see variables
46 set with SetEnvironmentVariable().
47
48 2007-04-05 -- lev
Jim Cownie5e8470a2013-09-27 10:38:44 +000049*/
50
51#include "kmp_environment.h"
52
Jonathan Peyton30419822017-05-12 18:01:32 +000053#include "kmp.h" //
Jim Cownie5e8470a2013-09-27 10:38:44 +000054#include "kmp_i18n.h"
Jonathan Peyton30419822017-05-12 18:01:32 +000055#include "kmp_os.h" // KMP_OS_*.
56#include "kmp_str.h" // __kmp_str_*().
Jim Cownie5e8470a2013-09-27 10:38:44 +000057
58#if KMP_OS_UNIX
Jonathan Peyton30419822017-05-12 18:01:32 +000059#include <stdlib.h> // getenv, setenv, unsetenv.
60#include <string.h> // strlen, strcpy.
61#if KMP_OS_DARWIN
62#include <crt_externs.h>
63#define environ (*_NSGetEnviron())
Jim Cownie5e8470a2013-09-27 10:38:44 +000064#else
Jonathan Peyton30419822017-05-12 18:01:32 +000065extern char **environ;
Jim Cownie5e8470a2013-09-27 10:38:44 +000066#endif
Jonathan Peyton30419822017-05-12 18:01:32 +000067#elif KMP_OS_WINDOWS
68#include <windows.h> // GetEnvironmentVariable, SetEnvironmentVariable,
69// GetLastError.
70#else
71#error Unknown or unsupported OS.
72#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +000073
74// TODO: Eliminate direct memory allocations, use string operations instead.
75
Jonathan Peyton30419822017-05-12 18:01:32 +000076static inline void *allocate(size_t size) {
77 void *ptr = KMP_INTERNAL_MALLOC(size);
78 if (ptr == NULL) {
79 KMP_FATAL(MemoryAllocFailed);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +000080 }
Jonathan Peyton30419822017-05-12 18:01:32 +000081 return ptr;
Jim Cownie5e8470a2013-09-27 10:38:44 +000082} // allocate
83
Jonathan Peyton30419822017-05-12 18:01:32 +000084char *__kmp_env_get(char const *name) {
Jim Cownie5e8470a2013-09-27 10:38:44 +000085
Jonathan Peyton30419822017-05-12 18:01:32 +000086 char *result = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +000087
Jonathan Peyton30419822017-05-12 18:01:32 +000088#if KMP_OS_UNIX
89 char const *value = getenv(name);
90 if (value != NULL) {
91 size_t len = KMP_STRLEN(value) + 1;
92 result = (char *)KMP_INTERNAL_MALLOC(len);
93 if (result == NULL) {
94 KMP_FATAL(MemoryAllocFailed);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +000095 }
Jonathan Peyton30419822017-05-12 18:01:32 +000096 KMP_STRNCPY_S(result, len, value, len);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +000097 }
Jonathan Peyton30419822017-05-12 18:01:32 +000098#elif KMP_OS_WINDOWS
99 /* We use GetEnvironmentVariable for Windows* OS instead of getenv because the
100 act of loading a DLL on Windows* OS makes any user-set environment
101 variables (i.e. with putenv()) unavailable. getenv() apparently gets a
102 clean copy of the env variables as they existed at the start of the run.
103 JH 12/23/2002 */
104 DWORD rc;
105 rc = GetEnvironmentVariable(name, NULL, 0);
106 if (!rc) {
107 DWORD error = GetLastError();
108 if (error != ERROR_ENVVAR_NOT_FOUND) {
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000109 __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000110 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000111 // Variable is not found, it's ok, just continue.
112 } else {
113 DWORD len = rc;
114 result = (char *)KMP_INTERNAL_MALLOC(len);
115 if (result == NULL) {
116 KMP_FATAL(MemoryAllocFailed);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000117 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000118 rc = GetEnvironmentVariable(name, result, len);
119 if (!rc) {
120 // GetEnvironmentVariable() may return 0 if variable is empty.
121 // In such a case GetLastError() returns ERROR_SUCCESS.
122 DWORD error = GetLastError();
123 if (error != ERROR_SUCCESS) {
124 // Unexpected error. The variable should be in the environment,
125 // and buffer should be large enough.
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000126 __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error),
127 __kmp_msg_null);
Jonathan Peyton30419822017-05-12 18:01:32 +0000128 KMP_INTERNAL_FREE((void *)result);
129 result = NULL;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000130 }
131 }
132 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000133#else
134#error Unknown or unsupported OS.
135#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +0000136
Jonathan Peyton30419822017-05-12 18:01:32 +0000137 return result;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000138
139} // func __kmp_env_get
140
Jim Cownie5e8470a2013-09-27 10:38:44 +0000141// TODO: Find and replace all regular free() with __kmp_env_free().
142
Jonathan Peyton30419822017-05-12 18:01:32 +0000143void __kmp_env_free(char const **value) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000144
Jonathan Peyton30419822017-05-12 18:01:32 +0000145 KMP_DEBUG_ASSERT(value != NULL);
Andrey Churbanovc47afcd2017-07-03 11:24:08 +0000146 KMP_INTERNAL_FREE(CCAST(char *, *value));
Jonathan Peyton30419822017-05-12 18:01:32 +0000147 *value = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000148
149} // func __kmp_env_free
150
Jonathan Peyton30419822017-05-12 18:01:32 +0000151int __kmp_env_exists(char const *name) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000152
Jonathan Peyton30419822017-05-12 18:01:32 +0000153#if KMP_OS_UNIX
154 char const *value = getenv(name);
155 return ((value == NULL) ? (0) : (1));
156#elif KMP_OS_WINDOWS
157 DWORD rc;
158 rc = GetEnvironmentVariable(name, NULL, 0);
159 if (rc == 0) {
160 DWORD error = GetLastError();
161 if (error != ERROR_ENVVAR_NOT_FOUND) {
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000162 __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000163 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000164 return 0;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000165 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000166 return 1;
167#else
168#error Unknown or unsupported OS.
169#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +0000170
171} // func __kmp_env_exists
172
Jonathan Peyton30419822017-05-12 18:01:32 +0000173void __kmp_env_set(char const *name, char const *value, int overwrite) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000174
Jonathan Peyton30419822017-05-12 18:01:32 +0000175#if KMP_OS_UNIX
176 int rc = setenv(name, value, overwrite);
177 if (rc != 0) {
178 // Dead code. I tried to put too many variables into Linux* OS
179 // environment on IA-32 architecture. When application consumes
180 // more than ~2.5 GB of memory, entire system feels bad. Sometimes
181 // application is killed (by OS?), sometimes system stops
182 // responding... But this error message never appears. --ln
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000183 __kmp_fatal(KMP_MSG(CantSetEnvVar, name), KMP_HNT(NotEnoughMemory),
184 __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000185 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000186#elif KMP_OS_WINDOWS
187 BOOL rc;
188 if (!overwrite) {
189 rc = GetEnvironmentVariable(name, NULL, 0);
190 if (rc) {
191 // Variable exists, do not overwrite.
192 return;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000193 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000194 DWORD error = GetLastError();
195 if (error != ERROR_ENVVAR_NOT_FOUND) {
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000196 __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000197 }
198 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000199 rc = SetEnvironmentVariable(name, value);
200 if (!rc) {
201 DWORD error = GetLastError();
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000202 __kmp_fatal(KMP_MSG(CantSetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000203 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000204#else
205#error Unknown or unsupported OS.
206#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +0000207
208} // func __kmp_env_set
209
Jonathan Peyton30419822017-05-12 18:01:32 +0000210void __kmp_env_unset(char const *name) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000211
Jonathan Peyton30419822017-05-12 18:01:32 +0000212#if KMP_OS_UNIX
213 unsetenv(name);
214#elif KMP_OS_WINDOWS
215 BOOL rc = SetEnvironmentVariable(name, NULL);
216 if (!rc) {
217 DWORD error = GetLastError();
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000218 __kmp_fatal(KMP_MSG(CantSetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000219 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000220#else
221#error Unknown or unsupported OS.
222#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +0000223
224} // func __kmp_env_unset
225
Jonathan Peyton30419822017-05-12 18:01:32 +0000226/* Intel OpenMP RTL string representation of environment: just a string of
227 characters, variables are separated with vertical bars, e. g.:
Jim Cownie5e8470a2013-09-27 10:38:44 +0000228
229 "KMP_WARNINGS=0|KMP_AFFINITY=compact|"
230
231 Empty variables are allowed and ignored:
232
233 "||KMP_WARNINGS=1||"
Jim Cownie5e8470a2013-09-27 10:38:44 +0000234*/
235
Jonathan Peyton30419822017-05-12 18:01:32 +0000236static void
237___kmp_env_blk_parse_string(kmp_env_blk_t *block, // M: Env block to fill.
238 char const *env // I: String to parse.
239 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000240
Jonathan Peyton30419822017-05-12 18:01:32 +0000241 char const chr_delimiter = '|';
242 char const str_delimiter[] = {chr_delimiter, 0};
Jim Cownie5e8470a2013-09-27 10:38:44 +0000243
Jonathan Peyton30419822017-05-12 18:01:32 +0000244 char *bulk = NULL;
245 kmp_env_var_t *vars = NULL;
246 int count = 0; // Number of used elements in vars array.
247 int delimiters = 0; // Number of delimiters in input string.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000248
Jonathan Peyton30419822017-05-12 18:01:32 +0000249 // Copy original string, we will modify the copy.
250 bulk = __kmp_str_format("%s", env);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000251
Jonathan Peyton30419822017-05-12 18:01:32 +0000252 // Loop thru all the vars in environment block. Count delimiters (maximum
253 // number of variables is number of delimiters plus one).
254 {
255 char const *ptr = bulk;
256 for (;;) {
257 ptr = strchr(ptr, chr_delimiter);
258 if (ptr == NULL) {
259 break;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000260 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000261 ++delimiters;
262 ptr += 1;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000263 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000264 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000265
Jonathan Peyton30419822017-05-12 18:01:32 +0000266 // Allocate vars array.
267 vars = (kmp_env_var_t *)allocate((delimiters + 1) * sizeof(kmp_env_var_t));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000268
Jonathan Peyton30419822017-05-12 18:01:32 +0000269 // Loop thru all the variables.
270 {
271 char *var; // Pointer to variable (both name and value).
272 char *name; // Pointer to name of variable.
273 char *value; // Pointer to value.
274 char *buf; // Buffer for __kmp_str_token() function.
275 var = __kmp_str_token(bulk, str_delimiter, &buf); // Get the first var.
276 while (var != NULL) {
277 // Save found variable in vars array.
278 __kmp_str_split(var, '=', &name, &value);
279 KMP_DEBUG_ASSERT(count < delimiters + 1);
280 vars[count].name = name;
281 vars[count].value = value;
282 ++count;
283 // Get the next var.
284 var = __kmp_str_token(NULL, str_delimiter, &buf);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000285 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000286 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000287
Jonathan Peyton30419822017-05-12 18:01:32 +0000288 // Fill out result.
289 block->bulk = bulk;
290 block->vars = vars;
291 block->count = count;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000292}
Jim Cownie5e8470a2013-09-27 10:38:44 +0000293
Jonathan Peyton30419822017-05-12 18:01:32 +0000294/* Windows* OS (actually, DOS) environment block is a piece of memory with
295 environment variables. Each variable is terminated with zero byte, entire
296 block is terminated with one extra zero byte, so we have two zero bytes at
297 the end of environment block, e. g.:
Jim Cownie5e8470a2013-09-27 10:38:44 +0000298
299 "HOME=C:\\users\\lev\x00OS=Windows_NT\x00\x00"
300
301 It is not clear how empty environment is represented. "\x00\x00"?
302*/
303
Jonathan Peyton2321d572015-06-08 19:25:25 +0000304#if KMP_OS_WINDOWS
Jonathan Peyton30419822017-05-12 18:01:32 +0000305static void ___kmp_env_blk_parse_windows(
306 kmp_env_blk_t *block, // M: Env block to fill.
307 char const *env // I: Pointer to Windows* OS (DOS) environment block.
308 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000309
Jonathan Peyton30419822017-05-12 18:01:32 +0000310 char *bulk = NULL;
311 kmp_env_var_t *vars = NULL;
312 int count = 0; // Number of used elements in vars array.
313 int size = 0; // Size of bulk.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000314
Jonathan Peyton30419822017-05-12 18:01:32 +0000315 char *name; // Pointer to name of variable.
316 char *value; // Pointer to value.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000317
Jonathan Peyton30419822017-05-12 18:01:32 +0000318 if (env != NULL) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000319
Jonathan Peyton30419822017-05-12 18:01:32 +0000320 // Loop thru all the vars in environment block. Count variables, find size
321 // of block.
322 {
323 char const *var; // Pointer to beginning of var.
324 int len; // Length of variable.
325 count = 0;
326 var =
327 env; // The first variable starts and beginning of environment block.
328 len = KMP_STRLEN(var);
329 while (len != 0) {
330 ++count;
331 size = size + len + 1;
332 var = var + len +
333 1; // Move pointer to the beginning of the next variable.
334 len = KMP_STRLEN(var);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000335 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000336 size =
337 size + 1; // Total size of env block, including terminating zero byte.
338 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000339
Jonathan Peyton30419822017-05-12 18:01:32 +0000340 // Copy original block to bulk, we will modify bulk, not original block.
341 bulk = (char *)allocate(size);
342 KMP_MEMCPY_S(bulk, size, env, size);
343 // Allocate vars array.
344 vars = (kmp_env_var_t *)allocate(count * sizeof(kmp_env_var_t));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000345
Jonathan Peyton30419822017-05-12 18:01:32 +0000346 // Loop thru all the vars, now in bulk.
347 {
348 char *var; // Pointer to beginning of var.
349 int len; // Length of variable.
350 count = 0;
351 var = bulk;
352 len = KMP_STRLEN(var);
353 while (len != 0) {
354 // Save variable in vars array.
355 __kmp_str_split(var, '=', &name, &value);
356 vars[count].name = name;
357 vars[count].value = value;
358 ++count;
359 // Get the next var.
360 var = var + len + 1;
361 len = KMP_STRLEN(var);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000362 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000363 }
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000364 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000365
Jonathan Peyton30419822017-05-12 18:01:32 +0000366 // Fill out result.
367 block->bulk = bulk;
368 block->vars = vars;
369 block->count = count;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000370}
Jonathan Peyton2321d572015-06-08 19:25:25 +0000371#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +0000372
Jonathan Peyton30419822017-05-12 18:01:32 +0000373/* Unix environment block is a array of pointers to variables, last pointer in
374 array is NULL:
Jim Cownie5e8470a2013-09-27 10:38:44 +0000375
376 { "HOME=/home/lev", "TERM=xterm", NULL }
377*/
378
Jonathan Peyton30419822017-05-12 18:01:32 +0000379static void
380___kmp_env_blk_parse_unix(kmp_env_blk_t *block, // M: Env block to fill.
381 char **env // I: Unix environment to parse.
382 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000383
Jonathan Peyton30419822017-05-12 18:01:32 +0000384 char *bulk = NULL;
385 kmp_env_var_t *vars = NULL;
386 int count = 0;
387 int size = 0; // Size of bulk.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000388
Jonathan Peyton30419822017-05-12 18:01:32 +0000389 // Count number of variables and length of required bulk.
390 {
391 count = 0;
392 size = 0;
393 while (env[count] != NULL) {
394 size += KMP_STRLEN(env[count]) + 1;
395 ++count;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000396 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000397 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000398
Jonathan Peyton30419822017-05-12 18:01:32 +0000399 // Allocate memory.
400 bulk = (char *)allocate(size);
401 vars = (kmp_env_var_t *)allocate(count * sizeof(kmp_env_var_t));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000402
Jonathan Peyton30419822017-05-12 18:01:32 +0000403 // Loop thru all the vars.
404 {
405 char *var; // Pointer to beginning of var.
406 char *name; // Pointer to name of variable.
407 char *value; // Pointer to value.
408 int len; // Length of variable.
409 int i;
410 var = bulk;
411 for (i = 0; i < count; ++i) {
412 // Copy variable to bulk.
413 len = KMP_STRLEN(env[i]);
414 KMP_MEMCPY_S(var, size, env[i], len + 1);
415 // Save found variable in vars array.
416 __kmp_str_split(var, '=', &name, &value);
417 vars[i].name = name;
418 vars[i].value = value;
419 // Move pointer.
420 var += len + 1;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000421 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000422 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000423
Jonathan Peyton30419822017-05-12 18:01:32 +0000424 // Fill out result.
425 block->bulk = bulk;
426 block->vars = vars;
427 block->count = count;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000428}
Jim Cownie5e8470a2013-09-27 10:38:44 +0000429
Jonathan Peyton30419822017-05-12 18:01:32 +0000430void __kmp_env_blk_init(kmp_env_blk_t *block, // M: Block to initialize.
431 char const *bulk // I: Initialization string, or NULL.
432 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000433
Jonathan Peyton30419822017-05-12 18:01:32 +0000434 if (bulk != NULL) {
435 ___kmp_env_blk_parse_string(block, bulk);
436 } else {
437#if KMP_OS_UNIX
438 ___kmp_env_blk_parse_unix(block, environ);
439#elif KMP_OS_WINDOWS
440 {
441 char *mem = GetEnvironmentStrings();
442 if (mem == NULL) {
443 DWORD error = GetLastError();
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000444 __kmp_fatal(KMP_MSG(CantGetEnvironment), KMP_ERR(error),
445 __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000446 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000447 ___kmp_env_blk_parse_windows(block, mem);
448 FreeEnvironmentStrings(mem);
449 }
450#else
451#error Unknown or unsupported OS.
452#endif
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000453 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000454
455} // __kmp_env_blk_init
456
Jonathan Peyton30419822017-05-12 18:01:32 +0000457static int ___kmp_env_var_cmp( // Comparison function for qsort().
458 kmp_env_var_t const *lhs, kmp_env_var_t const *rhs) {
459 return strcmp(lhs->name, rhs->name);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000460}
461
Jonathan Peyton30419822017-05-12 18:01:32 +0000462void __kmp_env_blk_sort(
463 kmp_env_blk_t *block // M: Block of environment variables to sort.
464 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000465
Andrey Churbanovc47afcd2017-07-03 11:24:08 +0000466 qsort(CCAST(kmp_env_var_t *, block->vars), block->count,
467 sizeof(kmp_env_var_t),
Jonathan Peyton30419822017-05-12 18:01:32 +0000468 (int (*)(void const *, void const *)) & ___kmp_env_var_cmp);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000469
470} // __kmp_env_block_sort
471
Jonathan Peyton30419822017-05-12 18:01:32 +0000472void __kmp_env_blk_free(
473 kmp_env_blk_t *block // M: Block of environment variables to free.
474 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000475
Andrey Churbanovc47afcd2017-07-03 11:24:08 +0000476 KMP_INTERNAL_FREE(CCAST(kmp_env_var_t *, block->vars));
Jonathan Peyton30419822017-05-12 18:01:32 +0000477 __kmp_str_free(&(block->bulk));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000478
Jonathan Peyton30419822017-05-12 18:01:32 +0000479 block->count = 0;
480 block->vars = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000481
482} // __kmp_env_blk_free
483
Jonathan Peyton30419822017-05-12 18:01:32 +0000484char const * // R: Value of variable or NULL if variable does not exist.
485 __kmp_env_blk_var(
486 kmp_env_blk_t *block, // I: Block of environment variables.
487 char const *name // I: Name of variable to find.
488 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000489
Jonathan Peyton30419822017-05-12 18:01:32 +0000490 int i;
491 for (i = 0; i < block->count; ++i) {
492 if (strcmp(block->vars[i].name, name) == 0) {
493 return block->vars[i].value;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000494 }
495 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000496 return NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000497
498} // __kmp_env_block_var
499
Jim Cownie5e8470a2013-09-27 10:38:44 +0000500// end of file //