OSDN Git Service

Update a number of broken links in comments.
[pg-rex/syncrep.git] / src / port / win32env.c
1 /*-------------------------------------------------------------------------
2  *
3  * win32env.c
4  *        putenv() and unsetenv() for win32, that updates both process
5  *        environment and the cached versions in (potentially multiple)
6  *        MSVCRT.
7  *
8  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
9  * Portions Copyright (c) 1994, Regents of the University of California
10  *
11  *
12  * IDENTIFICATION
13  *        $PostgreSQL: pgsql/src/port/win32env.c,v 1.8 2010/02/26 02:01:38 momjian Exp $
14  *
15  *-------------------------------------------------------------------------
16  */
17
18 #include "c.h"
19
20 int
21 pgwin32_putenv(const char *envval)
22 {
23         char       *envcpy;
24         char       *cp;
25
26         /*
27          * Each version of MSVCRT has its own _putenv() call in the runtime
28          * library.
29          *
30          * mingw always uses MSVCRT.DLL, but if we are in a Visual C++
31          * environment, attempt to update the environment in all MSVCRT modules
32          * that are currently loaded, to work properly with any third party
33          * libraries linked against a different MSVCRT but still relying on
34          * environment variables.
35          *
36          * Also separately update the system environment that gets inherited by
37          * subprocesses.
38          */
39 #ifdef _MSC_VER
40         typedef int (_cdecl * PUTENVPROC) (const char *);
41         static struct
42         {
43                 char       *modulename;
44                 HMODULE         hmodule;
45                 PUTENVPROC      putenvFunc;
46         }                       rtmodules[] =
47         {
48                 {
49                         "msvcrt", 0, NULL
50                 },                                              /* Visual Studio 6.0 / mingw */
51                 {
52                         "msvcr70", 0, NULL
53                 },                                              /* Visual Studio 2002 */
54                 {
55                         "msvcr71", 0, NULL
56                 },                                              /* Visual Studio 2003 */
57                 {
58                         "msvcr80", 0, NULL
59                 },                                              /* Visual Studio 2005 */
60                 {
61                         "msvcr90", 0, NULL
62                 },                                              /* Visual Studio 2008 */
63                 {
64                         NULL, 0, NULL
65                 }
66         };
67         int                     i;
68
69         for (i = 0; rtmodules[i].modulename; i++)
70         {
71                 if (rtmodules[i].putenvFunc == NULL)
72                 {
73                         if (rtmodules[i].hmodule == 0)
74                         {
75                                 /* Not attempted before, so try to find this DLL */
76                                 rtmodules[i].hmodule = GetModuleHandle(rtmodules[i].modulename);
77                                 if (rtmodules[i].hmodule == NULL)
78                                 {
79                                         /*
80                                          * Set to INVALID_HANDLE_VALUE so we know we have tried
81                                          * this one before, and won't try again.
82                                          */
83                                         rtmodules[i].hmodule = INVALID_HANDLE_VALUE;
84                                         continue;
85                                 }
86                                 else
87                                 {
88                                         rtmodules[i].putenvFunc = (PUTENVPROC) GetProcAddress(rtmodules[i].hmodule, "_putenv");
89                                         if (rtmodules[i].putenvFunc == NULL)
90                                         {
91                                                 CloseHandle(rtmodules[i].hmodule);
92                                                 rtmodules[i].hmodule = INVALID_HANDLE_VALUE;
93                                                 continue;
94                                         }
95                                 }
96                         }
97                         else
98                         {
99                                 /*
100                                  * Module loaded, but we did not find the function last time.
101                                  * We're not going to find it this time either...
102                                  */
103                                 continue;
104                         }
105                 }
106                 /* At this point, putenvFunc is set or we have exited the loop */
107                 rtmodules[i].putenvFunc(envval);
108         }
109 #endif   /* _MSC_VER */
110
111         /*
112          * Update the process environment - to make modifications visible to child
113          * processes.
114          *
115          * Need a copy of the string so we can modify it.
116          */
117         envcpy = strdup(envval);
118         cp = strchr(envcpy, '=');
119         if (cp == NULL)
120                 return -1;
121         *cp = '\0';
122         cp++;
123         if (strlen(cp))
124         {
125                 /*
126                  * Only call SetEnvironmentVariable() when we are adding a variable,
127                  * not when removing it. Calling it on both crashes on at least
128                  * certain versions of MingW.
129                  */
130                 if (!SetEnvironmentVariable(envcpy, cp))
131                 {
132                         free(envcpy);
133                         return -1;
134                 }
135         }
136         free(envcpy);
137
138         /* Finally, update our "own" cache */
139         return _putenv(envval);
140 }
141
142 void
143 pgwin32_unsetenv(const char *name)
144 {
145         char       *envbuf;
146
147         envbuf = (char *) malloc(strlen(name) + 2);
148         if (!envbuf)
149                 return;
150
151         sprintf(envbuf, "%s=", name);
152         pgwin32_putenv(envbuf);
153         free(envbuf);
154 }