b8a43951a90dae4c9128507b3de58c82cc7c2235
[ghc-hetmet.git] / rts / win32 / GetEnv.c
1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team 2011
4  *
5  * Access to the process environment variables
6  *
7  * ---------------------------------------------------------------------------*/
8
9 #include "Rts.h"
10 #include "GetEnv.h"
11
12 #include <windows.h>
13
14 /* Windows does it differently, though arguably the most sanely.
15  * GetEnvironmentStrings() returns a pointer to a block of
16  * environment vars with a double null terminator:
17  *   Var1=Value1\0
18  *   Var2=Value2\0
19  *   ...
20  *   VarN=ValueN\0\0 
21  * But because everyone else (ie POSIX) uses a vector of strings, we convert
22  * to that format. Fortunately this is just a matter of making an array of
23  * offsets into the environment block.
24  *
25  * Note that we have to call FreeEnvironmentStrings() at the end.
26  *
27  */
28 void getProgEnvv(int *out_envc, char **out_envv[]) {
29     int envc, i;
30     char *env;
31     char *envp;
32     char **envv;
33
34     /* For now, use the 'A'nsi not 'W'ide variant.
35        Note: corresponding Free below must use the same 'A'/'W' variant. */
36     env = GetEnvironmentStringsA();
37
38     envc = 0;
39     for (envp = env; *envp != 0; envp += strlen(envp) + 1) {
40         envc++;
41     }
42
43     envv = stgMallocBytes(sizeof(char*) * (envc+1));
44
45     i = 0;
46     for (envp = env; *envp != NULL; envp += strlen(envp) + 1) {
47         envv[i] = envp;
48         i++;
49     }
50     /* stash whole env in last+1 entry */
51     envv[envc] = env;
52
53     *out_envc = envc;
54     *out_envv = envv;
55 }
56
57 void freeProgEnvv(int envc, char *envv[]) {
58     /* we stashed the win32 env block in the last+1 entry */
59     FreeEnvironmentStringsA(envv[envc]);
60     stgFree(envv);
61 }