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