17cc577a4SJonathan Peyton /*
2de4749b7SJonathan Peyton  * kmp_environment.cpp -- Handle environment variables OS-independently.
37cc577a4SJonathan Peyton  */
47cc577a4SJonathan Peyton 
57cc577a4SJonathan Peyton //===----------------------------------------------------------------------===//
67cc577a4SJonathan Peyton //
757b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
857b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
957b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
107cc577a4SJonathan Peyton //
117cc577a4SJonathan Peyton //===----------------------------------------------------------------------===//
127cc577a4SJonathan Peyton 
133041982dSJonathan Peyton /* We use GetEnvironmentVariable for Windows* OS instead of getenv because the
143041982dSJonathan Peyton    act of loading a DLL on Windows* OS makes any user-set environment variables
153041982dSJonathan Peyton    (i.e. with putenv()) unavailable.  getenv() apparently gets a clean copy of
163041982dSJonathan Peyton    the env variables as they existed at the start of the run. JH 12/23/2002
173041982dSJonathan Peyton 
187cc577a4SJonathan Peyton    On Windows* OS, there are two environments (at least, see below):
197cc577a4SJonathan Peyton 
203041982dSJonathan Peyton    1. Environment maintained by Windows* OS on IA-32 architecture. Accessible
213041982dSJonathan Peyton       through GetEnvironmentVariable(), SetEnvironmentVariable(), and
223041982dSJonathan Peyton       GetEnvironmentStrings().
237cc577a4SJonathan Peyton 
247cc577a4SJonathan Peyton    2. Environment maintained by C RTL. Accessible through getenv(), putenv().
257cc577a4SJonathan Peyton 
263041982dSJonathan Peyton    putenv() function updates both C and Windows* OS on IA-32 architecture.
273041982dSJonathan Peyton    getenv() function search for variables in C RTL environment only.
283041982dSJonathan Peyton    Windows* OS on IA-32 architecture functions work *only* with Windows* OS on
293041982dSJonathan Peyton    IA-32 architecture.
307cc577a4SJonathan Peyton 
313041982dSJonathan Peyton    Windows* OS on IA-32 architecture maintained by OS, so there is always only
323041982dSJonathan Peyton    one Windows* OS on IA-32 architecture per process. Changes in Windows* OS on
333041982dSJonathan Peyton    IA-32 architecture are process-visible.
347cc577a4SJonathan Peyton 
353041982dSJonathan Peyton    C environment maintained by C RTL. Multiple copies of C RTL may be present
363041982dSJonathan Peyton    in the process, and each C RTL maintains its own environment. :-(
377cc577a4SJonathan Peyton 
387cc577a4SJonathan Peyton    Thus, proper way to work with environment on Windows* OS is:
397cc577a4SJonathan Peyton 
403041982dSJonathan Peyton    1. Set variables with putenv() function -- both C and Windows* OS on IA-32
413041982dSJonathan Peyton       architecture are being updated. Windows* OS on IA-32 architecture may be
423041982dSJonathan Peyton       considered primary target, while updating C RTL environment is free bonus.
437cc577a4SJonathan Peyton 
447cc577a4SJonathan Peyton    2. Get variables with GetEnvironmentVariable() -- getenv() does not
457cc577a4SJonathan Peyton       search Windows* OS on IA-32 architecture, and can not see variables
467cc577a4SJonathan Peyton       set with SetEnvironmentVariable().
477cc577a4SJonathan Peyton 
487cc577a4SJonathan Peyton    2007-04-05 -- lev
497cc577a4SJonathan Peyton */
507cc577a4SJonathan Peyton 
517cc577a4SJonathan Peyton #include "kmp_environment.h"
527cc577a4SJonathan Peyton 
537cc577a4SJonathan Peyton #include "kmp.h" //
547cc577a4SJonathan Peyton #include "kmp_i18n.h"
553041982dSJonathan Peyton #include "kmp_os.h" // KMP_OS_*.
563041982dSJonathan Peyton #include "kmp_str.h" // __kmp_str_*().
577cc577a4SJonathan Peyton 
587cc577a4SJonathan Peyton #if KMP_OS_UNIX
597cc577a4SJonathan Peyton #include <stdlib.h> // getenv, setenv, unsetenv.
607cc577a4SJonathan Peyton #include <string.h> // strlen, strcpy.
617cc577a4SJonathan Peyton #if KMP_OS_DARWIN
627cc577a4SJonathan Peyton #include <crt_externs.h>
637cc577a4SJonathan Peyton #define environ (*_NSGetEnviron())
647cc577a4SJonathan Peyton #else
657cc577a4SJonathan Peyton extern char **environ;
667cc577a4SJonathan Peyton #endif
677cc577a4SJonathan Peyton #elif KMP_OS_WINDOWS
683041982dSJonathan Peyton #include <windows.h> // GetEnvironmentVariable, SetEnvironmentVariable,
693041982dSJonathan Peyton // GetLastError.
707cc577a4SJonathan Peyton #else
717cc577a4SJonathan Peyton #error Unknown or unsupported OS.
727cc577a4SJonathan Peyton #endif
737cc577a4SJonathan Peyton 
747cc577a4SJonathan Peyton // TODO: Eliminate direct memory allocations, use string operations instead.
757cc577a4SJonathan Peyton 
allocate(size_t size)763041982dSJonathan Peyton static inline void *allocate(size_t size) {
777cc577a4SJonathan Peyton   void *ptr = KMP_INTERNAL_MALLOC(size);
787cc577a4SJonathan Peyton   if (ptr == NULL) {
797cc577a4SJonathan Peyton     KMP_FATAL(MemoryAllocFailed);
80bd3a7633SJonathan Peyton   }
817cc577a4SJonathan Peyton   return ptr;
827cc577a4SJonathan Peyton } // allocate
837cc577a4SJonathan Peyton 
__kmp_env_get(char const * name)843041982dSJonathan Peyton char *__kmp_env_get(char const *name) {
857cc577a4SJonathan Peyton 
867cc577a4SJonathan Peyton   char *result = NULL;
877cc577a4SJonathan Peyton 
887cc577a4SJonathan Peyton #if KMP_OS_UNIX
897cc577a4SJonathan Peyton   char const *value = getenv(name);
907cc577a4SJonathan Peyton   if (value != NULL) {
917cc577a4SJonathan Peyton     size_t len = KMP_STRLEN(value) + 1;
927cc577a4SJonathan Peyton     result = (char *)KMP_INTERNAL_MALLOC(len);
937cc577a4SJonathan Peyton     if (result == NULL) {
947cc577a4SJonathan Peyton       KMP_FATAL(MemoryAllocFailed);
95bd3a7633SJonathan Peyton     }
967cc577a4SJonathan Peyton     KMP_STRNCPY_S(result, len, value, len);
97bd3a7633SJonathan Peyton   }
987cc577a4SJonathan Peyton #elif KMP_OS_WINDOWS
993041982dSJonathan Peyton   /* We use GetEnvironmentVariable for Windows* OS instead of getenv because the
1003041982dSJonathan Peyton      act of loading a DLL on Windows* OS makes any user-set environment
1013041982dSJonathan Peyton      variables (i.e. with putenv()) unavailable. getenv() apparently gets a
1023041982dSJonathan Peyton      clean copy of the env variables as they existed at the start of the run.
1033041982dSJonathan Peyton      JH 12/23/2002 */
1047cc577a4SJonathan Peyton   DWORD rc;
1057cc577a4SJonathan Peyton   rc = GetEnvironmentVariable(name, NULL, 0);
1067cc577a4SJonathan Peyton   if (!rc) {
1077cc577a4SJonathan Peyton     DWORD error = GetLastError();
1087cc577a4SJonathan Peyton     if (error != ERROR_ENVVAR_NOT_FOUND) {
1096a393f75SJonathan Peyton       __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
110bd3a7633SJonathan Peyton     }
1117cc577a4SJonathan Peyton     // Variable is not found, it's ok, just continue.
1127cc577a4SJonathan Peyton   } else {
1137cc577a4SJonathan Peyton     DWORD len = rc;
1147cc577a4SJonathan Peyton     result = (char *)KMP_INTERNAL_MALLOC(len);
1157cc577a4SJonathan Peyton     if (result == NULL) {
1167cc577a4SJonathan Peyton       KMP_FATAL(MemoryAllocFailed);
117bd3a7633SJonathan Peyton     }
1187cc577a4SJonathan Peyton     rc = GetEnvironmentVariable(name, result, len);
1197cc577a4SJonathan Peyton     if (!rc) {
1207cc577a4SJonathan Peyton       // GetEnvironmentVariable() may return 0 if variable is empty.
1217cc577a4SJonathan Peyton       // In such a case GetLastError() returns ERROR_SUCCESS.
1227cc577a4SJonathan Peyton       DWORD error = GetLastError();
1237cc577a4SJonathan Peyton       if (error != ERROR_SUCCESS) {
1247cc577a4SJonathan Peyton         // Unexpected error. The variable should be in the environment,
1257cc577a4SJonathan Peyton         // and buffer should be large enough.
1266a393f75SJonathan Peyton         __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error),
1273041982dSJonathan Peyton                     __kmp_msg_null);
1287cc577a4SJonathan Peyton         KMP_INTERNAL_FREE((void *)result);
1297cc577a4SJonathan Peyton         result = NULL;
130bd3a7633SJonathan Peyton       }
131bd3a7633SJonathan Peyton     }
132bd3a7633SJonathan Peyton   }
1337cc577a4SJonathan Peyton #else
1347cc577a4SJonathan Peyton #error Unknown or unsupported OS.
1357cc577a4SJonathan Peyton #endif
1367cc577a4SJonathan Peyton 
1377cc577a4SJonathan Peyton   return result;
1387cc577a4SJonathan Peyton 
1397cc577a4SJonathan Peyton } // func __kmp_env_get
1407cc577a4SJonathan Peyton 
1417cc577a4SJonathan Peyton // TODO: Find and replace all regular free() with __kmp_env_free().
1427cc577a4SJonathan Peyton 
__kmp_env_free(char const ** value)1433041982dSJonathan Peyton void __kmp_env_free(char const **value) {
1447cc577a4SJonathan Peyton 
1457cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(value != NULL);
146c47afcd9SAndrey Churbanov   KMP_INTERNAL_FREE(CCAST(char *, *value));
1477cc577a4SJonathan Peyton   *value = NULL;
1487cc577a4SJonathan Peyton 
1497cc577a4SJonathan Peyton } // func __kmp_env_free
1507cc577a4SJonathan Peyton 
__kmp_env_exists(char const * name)1513041982dSJonathan Peyton int __kmp_env_exists(char const *name) {
1527cc577a4SJonathan Peyton 
1537cc577a4SJonathan Peyton #if KMP_OS_UNIX
1547cc577a4SJonathan Peyton   char const *value = getenv(name);
1557cc577a4SJonathan Peyton   return ((value == NULL) ? (0) : (1));
1567cc577a4SJonathan Peyton #elif KMP_OS_WINDOWS
1577cc577a4SJonathan Peyton   DWORD rc;
1587cc577a4SJonathan Peyton   rc = GetEnvironmentVariable(name, NULL, 0);
1597cc577a4SJonathan Peyton   if (rc == 0) {
1607cc577a4SJonathan Peyton     DWORD error = GetLastError();
1617cc577a4SJonathan Peyton     if (error != ERROR_ENVVAR_NOT_FOUND) {
1626a393f75SJonathan Peyton       __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
163bd3a7633SJonathan Peyton     }
1647cc577a4SJonathan Peyton     return 0;
165bd3a7633SJonathan Peyton   }
1667cc577a4SJonathan Peyton   return 1;
1677cc577a4SJonathan Peyton #else
1687cc577a4SJonathan Peyton #error Unknown or unsupported OS.
1697cc577a4SJonathan Peyton #endif
1707cc577a4SJonathan Peyton 
1717cc577a4SJonathan Peyton } // func __kmp_env_exists
1727cc577a4SJonathan Peyton 
__kmp_env_set(char const * name,char const * value,int overwrite)1733041982dSJonathan Peyton void __kmp_env_set(char const *name, char const *value, int overwrite) {
1747cc577a4SJonathan Peyton 
1757cc577a4SJonathan Peyton #if KMP_OS_UNIX
1767cc577a4SJonathan Peyton   int rc = setenv(name, value, overwrite);
1777cc577a4SJonathan Peyton   if (rc != 0) {
1787cc577a4SJonathan Peyton     // Dead code. I tried to put too many variables into Linux* OS
1797cc577a4SJonathan Peyton     // environment on IA-32 architecture. When application consumes
1807cc577a4SJonathan Peyton     // more than ~2.5 GB of memory, entire system feels bad. Sometimes
1817cc577a4SJonathan Peyton     // application is killed (by OS?), sometimes system stops
1827cc577a4SJonathan Peyton     // responding... But this error message never appears. --ln
1836a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(CantSetEnvVar, name), KMP_HNT(NotEnoughMemory),
1846a393f75SJonathan Peyton                 __kmp_msg_null);
185bd3a7633SJonathan Peyton   }
1867cc577a4SJonathan Peyton #elif KMP_OS_WINDOWS
1877cc577a4SJonathan Peyton   BOOL rc;
1887cc577a4SJonathan Peyton   if (!overwrite) {
1897cc577a4SJonathan Peyton     rc = GetEnvironmentVariable(name, NULL, 0);
1907cc577a4SJonathan Peyton     if (rc) {
1917cc577a4SJonathan Peyton       // Variable exists, do not overwrite.
1927cc577a4SJonathan Peyton       return;
193bd3a7633SJonathan Peyton     }
1947cc577a4SJonathan Peyton     DWORD error = GetLastError();
1957cc577a4SJonathan Peyton     if (error != ERROR_ENVVAR_NOT_FOUND) {
1966a393f75SJonathan Peyton       __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
197bd3a7633SJonathan Peyton     }
198bd3a7633SJonathan Peyton   }
1997cc577a4SJonathan Peyton   rc = SetEnvironmentVariable(name, value);
2007cc577a4SJonathan Peyton   if (!rc) {
2017cc577a4SJonathan Peyton     DWORD error = GetLastError();
2026a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(CantSetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
203bd3a7633SJonathan Peyton   }
2047cc577a4SJonathan Peyton #else
2057cc577a4SJonathan Peyton #error Unknown or unsupported OS.
2067cc577a4SJonathan Peyton #endif
2077cc577a4SJonathan Peyton 
2087cc577a4SJonathan Peyton } // func __kmp_env_set
2097cc577a4SJonathan Peyton 
__kmp_env_unset(char const * name)2103041982dSJonathan Peyton void __kmp_env_unset(char const *name) {
2117cc577a4SJonathan Peyton 
2127cc577a4SJonathan Peyton #if KMP_OS_UNIX
2137cc577a4SJonathan Peyton   unsetenv(name);
2147cc577a4SJonathan Peyton #elif KMP_OS_WINDOWS
2157cc577a4SJonathan Peyton   BOOL rc = SetEnvironmentVariable(name, NULL);
2167cc577a4SJonathan Peyton   if (!rc) {
2177cc577a4SJonathan Peyton     DWORD error = GetLastError();
2186a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(CantSetEnvVar, name), KMP_ERR(error), __kmp_msg_null);
219bd3a7633SJonathan Peyton   }
2207cc577a4SJonathan Peyton #else
2217cc577a4SJonathan Peyton #error Unknown or unsupported OS.
2227cc577a4SJonathan Peyton #endif
2237cc577a4SJonathan Peyton 
2247cc577a4SJonathan Peyton } // func __kmp_env_unset
2257cc577a4SJonathan Peyton 
2263041982dSJonathan Peyton /* Intel OpenMP RTL string representation of environment: just a string of
2273041982dSJonathan Peyton    characters, variables are separated with vertical bars, e. g.:
2287cc577a4SJonathan Peyton 
2297cc577a4SJonathan Peyton         "KMP_WARNINGS=0|KMP_AFFINITY=compact|"
2307cc577a4SJonathan Peyton 
2317cc577a4SJonathan Peyton     Empty variables are allowed and ignored:
2327cc577a4SJonathan Peyton 
2337cc577a4SJonathan Peyton         "||KMP_WARNINGS=1||"
2347cc577a4SJonathan Peyton */
2357cc577a4SJonathan Peyton 
2363041982dSJonathan Peyton static void
___kmp_env_blk_parse_string(kmp_env_blk_t * block,char const * env)2373041982dSJonathan Peyton ___kmp_env_blk_parse_string(kmp_env_blk_t *block, // M: Env block to fill.
2387cc577a4SJonathan Peyton                             char const *env // I: String to parse.
2397cc577a4SJonathan Peyton ) {
2407cc577a4SJonathan Peyton 
2417cc577a4SJonathan Peyton   char const chr_delimiter = '|';
2427cc577a4SJonathan Peyton   char const str_delimiter[] = {chr_delimiter, 0};
2437cc577a4SJonathan Peyton 
2447cc577a4SJonathan Peyton   char *bulk = NULL;
2457cc577a4SJonathan Peyton   kmp_env_var_t *vars = NULL;
2467cc577a4SJonathan Peyton   int count = 0; // Number of used elements in vars array.
2477cc577a4SJonathan Peyton   int delimiters = 0; // Number of delimiters in input string.
2487cc577a4SJonathan Peyton 
2497cc577a4SJonathan Peyton   // Copy original string, we will modify the copy.
2507cc577a4SJonathan Peyton   bulk = __kmp_str_format("%s", env);
2517cc577a4SJonathan Peyton 
2523041982dSJonathan Peyton   // Loop thru all the vars in environment block. Count delimiters (maximum
2533041982dSJonathan Peyton   // number of variables is number of delimiters plus one).
2547cc577a4SJonathan Peyton   {
2557cc577a4SJonathan Peyton     char const *ptr = bulk;
2567cc577a4SJonathan Peyton     for (;;) {
2577cc577a4SJonathan Peyton       ptr = strchr(ptr, chr_delimiter);
2587cc577a4SJonathan Peyton       if (ptr == NULL) {
2597cc577a4SJonathan Peyton         break;
260bd3a7633SJonathan Peyton       }
2617cc577a4SJonathan Peyton       ++delimiters;
2627cc577a4SJonathan Peyton       ptr += 1;
263bd3a7633SJonathan Peyton     }
2647cc577a4SJonathan Peyton   }
2657cc577a4SJonathan Peyton 
2667cc577a4SJonathan Peyton   // Allocate vars array.
2677cc577a4SJonathan Peyton   vars = (kmp_env_var_t *)allocate((delimiters + 1) * sizeof(kmp_env_var_t));
2687cc577a4SJonathan Peyton 
2697cc577a4SJonathan Peyton   // Loop thru all the variables.
2707cc577a4SJonathan Peyton   {
2717cc577a4SJonathan Peyton     char *var; // Pointer to variable (both name and value).
2727cc577a4SJonathan Peyton     char *name; // Pointer to name of variable.
2737cc577a4SJonathan Peyton     char *value; // Pointer to value.
2747cc577a4SJonathan Peyton     char *buf; // Buffer for __kmp_str_token() function.
2757cc577a4SJonathan Peyton     var = __kmp_str_token(bulk, str_delimiter, &buf); // Get the first var.
2767cc577a4SJonathan Peyton     while (var != NULL) {
2777cc577a4SJonathan Peyton       // Save found variable in vars array.
2787cc577a4SJonathan Peyton       __kmp_str_split(var, '=', &name, &value);
2797cc577a4SJonathan Peyton       KMP_DEBUG_ASSERT(count < delimiters + 1);
2807cc577a4SJonathan Peyton       vars[count].name = name;
2817cc577a4SJonathan Peyton       vars[count].value = value;
2827cc577a4SJonathan Peyton       ++count;
2837cc577a4SJonathan Peyton       // Get the next var.
2847cc577a4SJonathan Peyton       var = __kmp_str_token(NULL, str_delimiter, &buf);
285bd3a7633SJonathan Peyton     }
2867cc577a4SJonathan Peyton   }
2877cc577a4SJonathan Peyton 
2887cc577a4SJonathan Peyton   // Fill out result.
2897cc577a4SJonathan Peyton   block->bulk = bulk;
2907cc577a4SJonathan Peyton   block->vars = vars;
2917cc577a4SJonathan Peyton   block->count = count;
292bd3a7633SJonathan Peyton }
2937cc577a4SJonathan Peyton 
2943041982dSJonathan Peyton /* Windows* OS (actually, DOS) environment block is a piece of memory with
2953041982dSJonathan Peyton    environment variables. Each variable is terminated with zero byte, entire
2963041982dSJonathan Peyton    block is terminated with one extra zero byte, so we have two zero bytes at
2973041982dSJonathan Peyton    the end of environment block, e. g.:
2987cc577a4SJonathan Peyton 
2997cc577a4SJonathan Peyton         "HOME=C:\\users\\lev\x00OS=Windows_NT\x00\x00"
3007cc577a4SJonathan Peyton 
3017cc577a4SJonathan Peyton     It is not clear how empty environment is represented. "\x00\x00"?
3027cc577a4SJonathan Peyton */
3037cc577a4SJonathan Peyton 
3047cc577a4SJonathan Peyton #if KMP_OS_WINDOWS
___kmp_env_blk_parse_windows(kmp_env_blk_t * block,char const * env)3053041982dSJonathan Peyton static void ___kmp_env_blk_parse_windows(
3067cc577a4SJonathan Peyton     kmp_env_blk_t *block, // M: Env block to fill.
3077cc577a4SJonathan Peyton     char const *env // I: Pointer to Windows* OS (DOS) environment block.
3087cc577a4SJonathan Peyton ) {
3097cc577a4SJonathan Peyton 
3107cc577a4SJonathan Peyton   char *bulk = NULL;
3117cc577a4SJonathan Peyton   kmp_env_var_t *vars = NULL;
3127cc577a4SJonathan Peyton   int count = 0; // Number of used elements in vars array.
3137cc577a4SJonathan Peyton   int size = 0; // Size of bulk.
3147cc577a4SJonathan Peyton 
3157cc577a4SJonathan Peyton   char *name; // Pointer to name of variable.
3167cc577a4SJonathan Peyton   char *value; // Pointer to value.
3177cc577a4SJonathan Peyton 
3187cc577a4SJonathan Peyton   if (env != NULL) {
3197cc577a4SJonathan Peyton 
3203041982dSJonathan Peyton     // Loop thru all the vars in environment block. Count variables, find size
3213041982dSJonathan Peyton     // of block.
3227cc577a4SJonathan Peyton     {
3237cc577a4SJonathan Peyton       char const *var; // Pointer to beginning of var.
3247cc577a4SJonathan Peyton       int len; // Length of variable.
3257cc577a4SJonathan Peyton       count = 0;
3263041982dSJonathan Peyton       var =
3273041982dSJonathan Peyton           env; // The first variable starts and beginning of environment block.
3287cc577a4SJonathan Peyton       len = KMP_STRLEN(var);
3297cc577a4SJonathan Peyton       while (len != 0) {
3307cc577a4SJonathan Peyton         ++count;
3317cc577a4SJonathan Peyton         size = size + len + 1;
3323041982dSJonathan Peyton         var = var + len +
3333041982dSJonathan Peyton               1; // Move pointer to the beginning of the next variable.
3347cc577a4SJonathan Peyton         len = KMP_STRLEN(var);
335bd3a7633SJonathan Peyton       }
3363041982dSJonathan Peyton       size =
3373041982dSJonathan Peyton           size + 1; // Total size of env block, including terminating zero byte.
3387cc577a4SJonathan Peyton     }
3397cc577a4SJonathan Peyton 
3407cc577a4SJonathan Peyton     // Copy original block to bulk, we will modify bulk, not original block.
3417cc577a4SJonathan Peyton     bulk = (char *)allocate(size);
3427cc577a4SJonathan Peyton     KMP_MEMCPY_S(bulk, size, env, size);
3437cc577a4SJonathan Peyton     // Allocate vars array.
3447cc577a4SJonathan Peyton     vars = (kmp_env_var_t *)allocate(count * sizeof(kmp_env_var_t));
3457cc577a4SJonathan Peyton 
3467cc577a4SJonathan Peyton     // Loop thru all the vars, now in bulk.
3477cc577a4SJonathan Peyton     {
3487cc577a4SJonathan Peyton       char *var; // Pointer to beginning of var.
3497cc577a4SJonathan Peyton       int len; // Length of variable.
3507cc577a4SJonathan Peyton       count = 0;
3517cc577a4SJonathan Peyton       var = bulk;
3527cc577a4SJonathan Peyton       len = KMP_STRLEN(var);
3537cc577a4SJonathan Peyton       while (len != 0) {
3547cc577a4SJonathan Peyton         // Save variable in vars array.
3557cc577a4SJonathan Peyton         __kmp_str_split(var, '=', &name, &value);
3567cc577a4SJonathan Peyton         vars[count].name = name;
3577cc577a4SJonathan Peyton         vars[count].value = value;
3587cc577a4SJonathan Peyton         ++count;
3597cc577a4SJonathan Peyton         // Get the next var.
3607cc577a4SJonathan Peyton         var = var + len + 1;
3617cc577a4SJonathan Peyton         len = KMP_STRLEN(var);
3627cc577a4SJonathan Peyton       }
363bd3a7633SJonathan Peyton     }
364bd3a7633SJonathan Peyton   }
3657cc577a4SJonathan Peyton 
3667cc577a4SJonathan Peyton   // Fill out result.
3677cc577a4SJonathan Peyton   block->bulk = bulk;
3687cc577a4SJonathan Peyton   block->vars = vars;
3697cc577a4SJonathan Peyton   block->count = count;
370bd3a7633SJonathan Peyton }
3717cc577a4SJonathan Peyton #endif
3727cc577a4SJonathan Peyton 
3733041982dSJonathan Peyton /* Unix environment block is a array of pointers to variables, last pointer in
3743041982dSJonathan Peyton    array is NULL:
3757cc577a4SJonathan Peyton 
3767cc577a4SJonathan Peyton         { "HOME=/home/lev", "TERM=xterm", NULL }
3777cc577a4SJonathan Peyton */
3787cc577a4SJonathan Peyton 
37916428a8dSMartin Storsjö #if KMP_OS_UNIX
3803041982dSJonathan Peyton static void
___kmp_env_blk_parse_unix(kmp_env_blk_t * block,char ** env)3813041982dSJonathan Peyton ___kmp_env_blk_parse_unix(kmp_env_blk_t *block, // M: Env block to fill.
3827cc577a4SJonathan Peyton                           char **env // I: Unix environment to parse.
3837cc577a4SJonathan Peyton ) {
3847cc577a4SJonathan Peyton   char *bulk = NULL;
3857cc577a4SJonathan Peyton   kmp_env_var_t *vars = NULL;
3867cc577a4SJonathan Peyton   int count = 0;
3876b316febSTerry Wilmarth   size_t size = 0; // Size of bulk.
3887cc577a4SJonathan Peyton 
3897cc577a4SJonathan Peyton   // Count number of variables and length of required bulk.
3907cc577a4SJonathan Peyton   {
3917cc577a4SJonathan Peyton     while (env[count] != NULL) {
3927cc577a4SJonathan Peyton       size += KMP_STRLEN(env[count]) + 1;
3937cc577a4SJonathan Peyton       ++count;
394bd3a7633SJonathan Peyton     }
3957cc577a4SJonathan Peyton   }
3967cc577a4SJonathan Peyton 
3977cc577a4SJonathan Peyton   // Allocate memory.
3987cc577a4SJonathan Peyton   bulk = (char *)allocate(size);
3997cc577a4SJonathan Peyton   vars = (kmp_env_var_t *)allocate(count * sizeof(kmp_env_var_t));
4007cc577a4SJonathan Peyton 
4017cc577a4SJonathan Peyton   // Loop thru all the vars.
4027cc577a4SJonathan Peyton   {
4037cc577a4SJonathan Peyton     char *var; // Pointer to beginning of var.
4047cc577a4SJonathan Peyton     char *name; // Pointer to name of variable.
4057cc577a4SJonathan Peyton     char *value; // Pointer to value.
4066b316febSTerry Wilmarth     size_t len; // Length of variable.
4077cc577a4SJonathan Peyton     int i;
4087cc577a4SJonathan Peyton     var = bulk;
4097cc577a4SJonathan Peyton     for (i = 0; i < count; ++i) {
4107cc577a4SJonathan Peyton       // Copy variable to bulk.
4117cc577a4SJonathan Peyton       len = KMP_STRLEN(env[i]);
4127cc577a4SJonathan Peyton       KMP_MEMCPY_S(var, size, env[i], len + 1);
4137cc577a4SJonathan Peyton       // Save found variable in vars array.
4147cc577a4SJonathan Peyton       __kmp_str_split(var, '=', &name, &value);
4157cc577a4SJonathan Peyton       vars[i].name = name;
4167cc577a4SJonathan Peyton       vars[i].value = value;
4177cc577a4SJonathan Peyton       // Move pointer.
4187cc577a4SJonathan Peyton       var += len + 1;
419bd3a7633SJonathan Peyton     }
4207cc577a4SJonathan Peyton   }
4217cc577a4SJonathan Peyton 
4227cc577a4SJonathan Peyton   // Fill out result.
4237cc577a4SJonathan Peyton   block->bulk = bulk;
4247cc577a4SJonathan Peyton   block->vars = vars;
4257cc577a4SJonathan Peyton   block->count = count;
426bd3a7633SJonathan Peyton }
42716428a8dSMartin Storsjö #endif
4287cc577a4SJonathan Peyton 
__kmp_env_blk_init(kmp_env_blk_t * block,char const * bulk)4293041982dSJonathan Peyton void __kmp_env_blk_init(kmp_env_blk_t *block, // M: Block to initialize.
4307cc577a4SJonathan Peyton                         char const *bulk // I: Initialization string, or NULL.
4317cc577a4SJonathan Peyton ) {
4327cc577a4SJonathan Peyton 
4337cc577a4SJonathan Peyton   if (bulk != NULL) {
4347cc577a4SJonathan Peyton     ___kmp_env_blk_parse_string(block, bulk);
4357cc577a4SJonathan Peyton   } else {
4367cc577a4SJonathan Peyton #if KMP_OS_UNIX
4377cc577a4SJonathan Peyton     ___kmp_env_blk_parse_unix(block, environ);
4387cc577a4SJonathan Peyton #elif KMP_OS_WINDOWS
4397cc577a4SJonathan Peyton     {
4407cc577a4SJonathan Peyton       char *mem = GetEnvironmentStrings();
4417cc577a4SJonathan Peyton       if (mem == NULL) {
4427cc577a4SJonathan Peyton         DWORD error = GetLastError();
4436a393f75SJonathan Peyton         __kmp_fatal(KMP_MSG(CantGetEnvironment), KMP_ERR(error),
4443041982dSJonathan Peyton                     __kmp_msg_null);
445bd3a7633SJonathan Peyton       }
4467cc577a4SJonathan Peyton       ___kmp_env_blk_parse_windows(block, mem);
4477cc577a4SJonathan Peyton       FreeEnvironmentStrings(mem);
4487cc577a4SJonathan Peyton     }
4497cc577a4SJonathan Peyton #else
4507cc577a4SJonathan Peyton #error Unknown or unsupported OS.
4517cc577a4SJonathan Peyton #endif
452bd3a7633SJonathan Peyton   }
4537cc577a4SJonathan Peyton 
4547cc577a4SJonathan Peyton } // __kmp_env_blk_init
4557cc577a4SJonathan Peyton 
___kmp_env_var_cmp(kmp_env_var_t const * lhs,kmp_env_var_t const * rhs)4563041982dSJonathan Peyton static int ___kmp_env_var_cmp( // Comparison function for qsort().
4573041982dSJonathan Peyton     kmp_env_var_t const *lhs, kmp_env_var_t const *rhs) {
4587cc577a4SJonathan Peyton   return strcmp(lhs->name, rhs->name);
4597cc577a4SJonathan Peyton }
4607cc577a4SJonathan Peyton 
__kmp_env_blk_sort(kmp_env_blk_t * block)4613041982dSJonathan Peyton void __kmp_env_blk_sort(
4627cc577a4SJonathan Peyton     kmp_env_blk_t *block // M: Block of environment variables to sort.
4637cc577a4SJonathan Peyton ) {
4647cc577a4SJonathan Peyton 
465c47afcd9SAndrey Churbanov   qsort(CCAST(kmp_env_var_t *, block->vars), block->count,
466c47afcd9SAndrey Churbanov         sizeof(kmp_env_var_t),
4673041982dSJonathan Peyton         (int (*)(void const *, void const *)) & ___kmp_env_var_cmp);
4687cc577a4SJonathan Peyton 
4697cc577a4SJonathan Peyton } // __kmp_env_block_sort
4707cc577a4SJonathan Peyton 
__kmp_env_blk_free(kmp_env_blk_t * block)4713041982dSJonathan Peyton void __kmp_env_blk_free(
4727cc577a4SJonathan Peyton     kmp_env_blk_t *block // M: Block of environment variables to free.
4737cc577a4SJonathan Peyton ) {
4747cc577a4SJonathan Peyton 
475c47afcd9SAndrey Churbanov   KMP_INTERNAL_FREE(CCAST(kmp_env_var_t *, block->vars));
4767cc577a4SJonathan Peyton   __kmp_str_free(&(block->bulk));
4777cc577a4SJonathan Peyton 
4787cc577a4SJonathan Peyton   block->count = 0;
4797cc577a4SJonathan Peyton   block->vars = NULL;
4807cc577a4SJonathan Peyton 
4817cc577a4SJonathan Peyton } // __kmp_env_blk_free
4827cc577a4SJonathan Peyton 
4837cc577a4SJonathan Peyton char const * // R: Value of variable or NULL if variable does not exist.
__kmp_env_blk_var(kmp_env_blk_t * block,char const * name)484*309b00a4SShilei Tian __kmp_env_blk_var(kmp_env_blk_t *block, // I: Block of environment variables.
4857cc577a4SJonathan Peyton                   char const *name // I: Name of variable to find.
4867cc577a4SJonathan Peyton ) {
4877cc577a4SJonathan Peyton 
4887cc577a4SJonathan Peyton   int i;
4897cc577a4SJonathan Peyton   for (i = 0; i < block->count; ++i) {
4907cc577a4SJonathan Peyton     if (strcmp(block->vars[i].name, name) == 0) {
4917cc577a4SJonathan Peyton       return block->vars[i].value;
492bd3a7633SJonathan Peyton     }
493bd3a7633SJonathan Peyton   }
4947cc577a4SJonathan Peyton   return NULL;
4957cc577a4SJonathan Peyton 
4967cc577a4SJonathan Peyton } // __kmp_env_block_var
4977cc577a4SJonathan Peyton 
4987cc577a4SJonathan Peyton // end of file //
499