Mercurial > hg > octave-lojdl > gnulib-hg
comparison lib/putenv.c @ 17347:cec099cbf54f
putenv: port better to native Windows
* lib/putenv.c [(_WIN32 || __WIN32__) && ! __CYGWIN__]:
Define WIN32_LEAN_AND_MEAN and include <windows.h>.
(_unsetenv): Use _putenv if available.
(putenv): Temporarily set NAME=' ' rather than NAME='x' as that's
a bit less likely to cause damage.
(putenv) [(_WIN32 || __WIN32__) && ! __CYGWIN__]:
Fix the wrong value with SetEnvironmentVariable.
(putenv) [!HAVE__PUTENV]: Simplify and match the HAVE__PUTENV
code better.
author | Paul Eggert <eggert@cs.ucla.edu> |
---|---|
date | Mon, 18 Feb 2013 19:38:13 -0800 |
parents | a72ac603a92f |
children | a154fccd3b21 |
comparison
equal
deleted
inserted
replaced
17346:e27f620a8d36 | 17347:cec099cbf54f |
---|---|
32 #endif | 32 #endif |
33 | 33 |
34 #include <string.h> | 34 #include <string.h> |
35 #include <unistd.h> | 35 #include <unistd.h> |
36 | 36 |
37 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ | |
38 # define WIN32_LEAN_AND_MEAN | |
39 # include <windows.h> | |
40 #endif | |
41 | |
37 #if _LIBC | 42 #if _LIBC |
38 # if HAVE_GNU_LD | 43 # if HAVE_GNU_LD |
39 # define environ __environ | 44 # define environ __environ |
40 # else | 45 # else |
41 extern char **environ; | 46 extern char **environ; |
65 return -1; | 70 return -1; |
66 } | 71 } |
67 | 72 |
68 len = strlen (name); | 73 len = strlen (name); |
69 | 74 |
75 #if HAVE__PUTENV | |
76 { | |
77 int putenv_result, putenv_errno; | |
78 char *name_ = malloc (len + 2); | |
79 memcpy (name_, name, len); | |
80 name_[len] = '='; | |
81 name_[len + 1] = 0; | |
82 putenv_result = _putenv (name_); | |
83 putenv_errno = errno; | |
84 free (name_); | |
85 __set_errno (putenv_errno); | |
86 return putenv_result; | |
87 } | |
88 #else | |
89 | |
70 LOCK; | 90 LOCK; |
71 | 91 |
72 ep = environ; | 92 ep = environ; |
73 while (*ep != NULL) | 93 while (*ep != NULL) |
74 if (!strncmp (*ep, name, len) && (*ep)[len] == '=') | 94 if (!strncmp (*ep, name, len) && (*ep)[len] == '=') |
85 ++ep; | 105 ++ep; |
86 | 106 |
87 UNLOCK; | 107 UNLOCK; |
88 | 108 |
89 return 0; | 109 return 0; |
110 #endif | |
90 } | 111 } |
91 | 112 |
92 | 113 |
93 /* Put STRING, which is of the form "NAME=VALUE", in the environment. | 114 /* Put STRING, which is of the form "NAME=VALUE", in the environment. |
94 If STRING contains no '=', then remove STRING from the environment. */ | 115 If STRING contains no '=', then remove STRING from the environment. */ |
95 int | 116 int |
96 putenv (char *string) | 117 putenv (char *string) |
97 { | 118 { |
98 const char *const name_end = strchr (string, '='); | 119 const char *name_end = strchr (string, '='); |
99 register size_t size; | 120 char **ep; |
100 register char **ep; | |
101 | 121 |
102 if (name_end == NULL) | 122 if (name_end == NULL) |
103 { | 123 { |
104 /* Remove the variable from the environment. */ | 124 /* Remove the variable from the environment. */ |
105 return _unsetenv (string); | 125 return _unsetenv (string); |
106 } | 126 } |
107 | 127 |
108 size = 0; | |
109 for (ep = environ; *ep != NULL; ++ep) | |
110 if (!strncmp (*ep, string, name_end - string) && | |
111 (*ep)[name_end - string] == '=') | |
112 break; | |
113 else | |
114 ++size; | |
115 | |
116 if (*ep == NULL) | |
117 { | |
118 #if HAVE__PUTENV | 128 #if HAVE__PUTENV |
119 /* Rely on _putenv to allocate the new environment. If other | 129 /* Rely on _putenv to allocate the new environment. If other |
120 parts of the application use _putenv, the !HAVE__PUTENV code | 130 parts of the application use _putenv, the !HAVE__PUTENV code |
121 would fight over who owns the environ vector, causing a crash. */ | 131 would fight over who owns the environ vector, causing a crash. */ |
122 if (name_end[1]) | 132 if (name_end[1]) |
123 return _putenv (string); | 133 return _putenv (string); |
124 else | 134 else |
125 { | 135 { |
126 /* _putenv ("NAME=") unsets NAME, so invoke _putenv ("NAME=x") | 136 /* _putenv ("NAME=") unsets NAME, so invoke _putenv ("NAME= ") |
127 to allocate the environ vector and then replace the new | 137 to allocate the environ vector and then replace the new |
128 entry with "NAME=". */ | 138 entry with "NAME=". */ |
129 int putenv_result, putenv_errno; | 139 int putenv_result, putenv_errno; |
130 char *name_x = malloc (name_end - string + sizeof "=x"); | 140 char *name_x = malloc (name_end - string + sizeof "= "); |
131 if (!name_x) | 141 if (!name_x) |
132 return -1; | 142 return -1; |
133 memcpy (name_x, string, name_end - string + 1); | 143 memcpy (name_x, string, name_end - string + 1); |
134 name_x[name_end - string + 1] = 'x'; | 144 name_x[name_end - string + 1] = ' '; |
135 name_x[name_end - string + 2] = 0; | 145 name_x[name_end - string + 2] = 0; |
136 putenv_result = _putenv (name_x); | 146 putenv_result = _putenv (name_x); |
137 putenv_errno = errno; | 147 putenv_errno = errno; |
138 for (ep = environ; *ep; ep++) | 148 for (ep = environ; *ep; ep++) |
139 if (*ep == name_x) | 149 if (strcmp (*ep, name_x) == 0) |
140 { | 150 { |
141 *ep = string; | 151 *ep = string; |
142 break; | 152 break; |
143 } | 153 } |
154 # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ | |
155 if (putenv_result == 0) | |
156 { | |
157 /* _putenv propagated "NAME= " into the subprocess environment; | |
158 fix that by calling SetEnvironmentVariable directly. */ | |
159 name_x[name_end - string] = 0; | |
160 putenv_result = SetEnvironmentVariable (name_x, "") ? 0 : -1; | |
161 putenv_errno = ENOMEM; /* ENOMEM is the only way to fail. */ | |
162 } | |
163 # endif | |
144 free (name_x); | 164 free (name_x); |
145 __set_errno (putenv_errno); | 165 __set_errno (putenv_errno); |
146 return putenv_result; | 166 return putenv_result; |
147 } | 167 } |
148 #else | 168 #else |
169 for (ep = environ; *ep; ep++) | |
170 if (strncmp (*ep, string, name_end - string) == 0 | |
171 && (*ep)[name_end - string] == '=') | |
172 break; | |
173 | |
174 if (*ep) | |
175 *ep = string; | |
176 else | |
177 { | |
149 static char **last_environ = NULL; | 178 static char **last_environ = NULL; |
150 char **new_environ = (char **) malloc ((size + 2) * sizeof (char *)); | 179 size_t size = ep - environ; |
151 if (new_environ == NULL) | 180 char **new_environ = malloc ((size + 2) * sizeof *new_environ); |
181 if (! new_environ) | |
152 return -1; | 182 return -1; |
153 (void) memcpy ((void *) new_environ, (void *) environ, | 183 new_environ[0] = string; |
154 size * sizeof (char *)); | 184 memcpy (new_environ + 1, environ, (size + 1) * sizeof *new_environ); |
155 new_environ[size] = (char *) string; | |
156 new_environ[size + 1] = NULL; | |
157 free (last_environ); | 185 free (last_environ); |
158 last_environ = new_environ; | 186 last_environ = new_environ; |
159 environ = new_environ; | 187 environ = new_environ; |
188 } | |
160 #endif | 189 #endif |
161 } | |
162 else | |
163 *ep = string; | |
164 | 190 |
165 return 0; | 191 return 0; |
166 } | 192 } |