/src/glib/glib/genviron.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* GLIB - Library of useful routines for C programming |
2 | | * Copyright (C) 1995-1998 Peter Mattis, Spencer Kimball and Josh MacDonald |
3 | | * |
4 | | * This library is free software; you can redistribute it and/or |
5 | | * modify it under the terms of the GNU Lesser General Public |
6 | | * License as published by the Free Software Foundation; either |
7 | | * version 2.1 of the License, or (at your option) any later version. |
8 | | * |
9 | | * This library is distributed in the hope that it will be useful, |
10 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | | * Lesser General Public License for more details. |
13 | | * |
14 | | * You should have received a copy of the GNU Lesser General Public |
15 | | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
16 | | */ |
17 | | |
18 | | /* |
19 | | * Modified by the GLib Team and others 1997-2000. See the AUTHORS |
20 | | * file for a list of people on the GLib Team. See the ChangeLog |
21 | | * files for a list of changes. These files are distributed with |
22 | | * GLib at ftp://ftp.gtk.org/pub/gtk/. |
23 | | */ |
24 | | |
25 | | #include "config.h" |
26 | | |
27 | | #include "genviron.h" |
28 | | |
29 | | #include <stdlib.h> |
30 | | #include <string.h> |
31 | | #ifdef HAVE_CRT_EXTERNS_H |
32 | | #include <crt_externs.h> /* for _NSGetEnviron */ |
33 | | #endif |
34 | | #ifdef G_OS_WIN32 |
35 | | #include <windows.h> |
36 | | #endif |
37 | | |
38 | | #include "glib-private.h" |
39 | | #include "gmem.h" |
40 | | #include "gmessages.h" |
41 | | #include "gstrfuncs.h" |
42 | | #include "gunicode.h" |
43 | | #include "gconvert.h" |
44 | | #include "gquark.h" |
45 | | #include "gthreadprivate.h" |
46 | | |
47 | | /* Environ array functions {{{1 */ |
48 | | static gboolean |
49 | | g_environ_matches (const gchar *env, const gchar *variable, gsize len) |
50 | 0 | { |
51 | | #ifdef G_OS_WIN32 |
52 | | /* TODO handle Unicode environment variable names */ |
53 | | /* Like filesystem paths, environment variables are case-insensitive. */ |
54 | | return g_ascii_strncasecmp (env, variable, len) == 0 && env[len] == '='; |
55 | | #else |
56 | 0 | return strncmp (env, variable, len) == 0 && env[len] == '='; |
57 | 0 | #endif |
58 | 0 | } |
59 | | |
60 | | static gint |
61 | | g_environ_find (gchar **envp, |
62 | | const gchar *variable) |
63 | 0 | { |
64 | 0 | gsize len; |
65 | 0 | gint i; |
66 | |
|
67 | 0 | if (envp == NULL) |
68 | 0 | return -1; |
69 | | |
70 | 0 | len = strlen (variable); |
71 | |
|
72 | 0 | for (i = 0; envp[i]; i++) |
73 | 0 | { |
74 | 0 | if (g_environ_matches (envp[i], variable, len)) |
75 | 0 | return i; |
76 | 0 | } |
77 | | |
78 | 0 | return -1; |
79 | 0 | } |
80 | | |
81 | | /** |
82 | | * g_environ_getenv: |
83 | | * @envp: (nullable) (array zero-terminated=1) (transfer none) (element-type filename): |
84 | | * an environment list (eg, as returned from g_get_environ()), or %NULL |
85 | | * for an empty environment list |
86 | | * @variable: (type filename): the environment variable to get |
87 | | * |
88 | | * Returns the value of the environment variable @variable in the |
89 | | * provided list @envp. |
90 | | * |
91 | | * Returns: (type filename): the value of the environment variable, or %NULL if |
92 | | * the environment variable is not set in @envp. The returned |
93 | | * string is owned by @envp, and will be freed if @variable is |
94 | | * set or unset again. |
95 | | * |
96 | | * Since: 2.32 |
97 | | */ |
98 | | const gchar * |
99 | | g_environ_getenv (gchar **envp, |
100 | | const gchar *variable) |
101 | 0 | { |
102 | 0 | gint index; |
103 | |
|
104 | 0 | g_return_val_if_fail (variable != NULL, NULL); |
105 | | |
106 | 0 | index = g_environ_find (envp, variable); |
107 | 0 | if (index != -1) |
108 | 0 | return envp[index] + strlen (variable) + 1; |
109 | 0 | else |
110 | 0 | return NULL; |
111 | 0 | } |
112 | | |
113 | | /** |
114 | | * g_environ_setenv: |
115 | | * @envp: (nullable) (array zero-terminated=1) (element-type filename) (transfer full): |
116 | | * an environment list that can be freed using g_strfreev() (e.g., as |
117 | | * returned from g_get_environ()), or %NULL for an empty |
118 | | * environment list |
119 | | * @variable: (type filename): the environment variable to set, must not |
120 | | * contain '=' |
121 | | * @value: (type filename): the value for to set the variable to |
122 | | * @overwrite: whether to change the variable if it already exists |
123 | | * |
124 | | * Sets the environment variable @variable in the provided list |
125 | | * @envp to @value. |
126 | | * |
127 | | * Returns: (array zero-terminated=1) (element-type filename) (transfer full): |
128 | | * the updated environment list. Free it using g_strfreev(). |
129 | | * |
130 | | * Since: 2.32 |
131 | | */ |
132 | | gchar ** |
133 | | g_environ_setenv (gchar **envp, |
134 | | const gchar *variable, |
135 | | const gchar *value, |
136 | | gboolean overwrite) |
137 | 0 | { |
138 | 0 | gint index; |
139 | |
|
140 | 0 | g_return_val_if_fail (variable != NULL, NULL); |
141 | 0 | g_return_val_if_fail (strchr (variable, '=') == NULL, NULL); |
142 | 0 | g_return_val_if_fail (value != NULL, NULL); |
143 | | |
144 | 0 | index = g_environ_find (envp, variable); |
145 | 0 | if (index != -1) |
146 | 0 | { |
147 | 0 | if (overwrite) |
148 | 0 | { |
149 | 0 | g_free (envp[index]); |
150 | 0 | envp[index] = g_strdup_printf ("%s=%s", variable, value); |
151 | 0 | } |
152 | 0 | } |
153 | 0 | else |
154 | 0 | { |
155 | 0 | gint length; |
156 | |
|
157 | 0 | length = envp ? g_strv_length (envp) : 0; |
158 | 0 | envp = g_renew (gchar *, envp, length + 2); |
159 | 0 | envp[length] = g_strdup_printf ("%s=%s", variable, value); |
160 | 0 | envp[length + 1] = NULL; |
161 | 0 | } |
162 | |
|
163 | 0 | return envp; |
164 | 0 | } |
165 | | |
166 | | static gchar ** |
167 | | g_environ_unsetenv_internal (gchar **envp, |
168 | | const gchar *variable, |
169 | | gboolean free_value) |
170 | 0 | { |
171 | 0 | gsize len; |
172 | 0 | gchar **e, **f; |
173 | |
|
174 | 0 | len = strlen (variable); |
175 | | |
176 | | /* Note that we remove *all* environment entries for |
177 | | * the variable name, not just the first. |
178 | | */ |
179 | 0 | e = f = envp; |
180 | 0 | while (*e != NULL) |
181 | 0 | { |
182 | 0 | if (!g_environ_matches (*e, variable, len)) |
183 | 0 | { |
184 | 0 | *f = *e; |
185 | 0 | f++; |
186 | 0 | } |
187 | 0 | else |
188 | 0 | { |
189 | 0 | if (free_value) |
190 | 0 | g_free (*e); |
191 | 0 | } |
192 | |
|
193 | 0 | e++; |
194 | 0 | } |
195 | 0 | *f = NULL; |
196 | |
|
197 | 0 | return envp; |
198 | 0 | } |
199 | | |
200 | | |
201 | | /** |
202 | | * g_environ_unsetenv: |
203 | | * @envp: (nullable) (array zero-terminated=1) (element-type filename) (transfer full): |
204 | | * an environment list that can be freed using g_strfreev() (e.g., as |
205 | | * returned from g_get_environ()), or %NULL for an empty environment list |
206 | | * @variable: (type filename): the environment variable to remove, must not |
207 | | * contain '=' |
208 | | * |
209 | | * Removes the environment variable @variable from the provided |
210 | | * environment @envp. |
211 | | * |
212 | | * Returns: (array zero-terminated=1) (element-type filename) (transfer full): |
213 | | * the updated environment list. Free it using g_strfreev(). |
214 | | * |
215 | | * Since: 2.32 |
216 | | */ |
217 | | gchar ** |
218 | | g_environ_unsetenv (gchar **envp, |
219 | | const gchar *variable) |
220 | 0 | { |
221 | 0 | g_return_val_if_fail (variable != NULL, NULL); |
222 | 0 | g_return_val_if_fail (strchr (variable, '=') == NULL, NULL); |
223 | | |
224 | 0 | if (envp == NULL) |
225 | 0 | return NULL; |
226 | | |
227 | 0 | return g_environ_unsetenv_internal (envp, variable, TRUE); |
228 | 0 | } |
229 | | |
230 | | /* UNIX implementation {{{1 */ |
231 | | #ifndef G_OS_WIN32 |
232 | | |
233 | | /** |
234 | | * g_getenv: |
235 | | * @variable: (type filename): the environment variable to get |
236 | | * |
237 | | * Returns the value of an environment variable. |
238 | | * |
239 | | * On UNIX, the name and value are byte strings which might or might not |
240 | | * be in some consistent character set and encoding. On Windows, they are |
241 | | * in UTF-8. |
242 | | * On Windows, in case the environment variable's value contains |
243 | | * references to other environment variables, they are expanded. |
244 | | * |
245 | | * Returns: (type filename): the value of the environment variable, or %NULL if |
246 | | * the environment variable is not found. The returned string |
247 | | * may be overwritten by the next call to g_getenv(), g_setenv() |
248 | | * or g_unsetenv(). |
249 | | */ |
250 | | const gchar * |
251 | | g_getenv (const gchar *variable) |
252 | 25.7M | { |
253 | 25.7M | g_return_val_if_fail (variable != NULL, NULL); |
254 | | |
255 | 25.7M | return getenv (variable); |
256 | 25.7M | } |
257 | | |
258 | | /** |
259 | | * g_setenv: |
260 | | * @variable: (type filename): the environment variable to set, must not |
261 | | * contain '='. |
262 | | * @value: (type filename): the value for to set the variable to. |
263 | | * @overwrite: whether to change the variable if it already exists. |
264 | | * |
265 | | * Sets an environment variable. On UNIX, both the variable's name and |
266 | | * value can be arbitrary byte strings, except that the variable's name |
267 | | * cannot contain '='. On Windows, they should be in UTF-8. |
268 | | * |
269 | | * Note that on some systems, when variables are overwritten, the memory |
270 | | * used for the previous variables and its value isn't reclaimed. |
271 | | * |
272 | | * You should be mindful of the fact that environment variable handling |
273 | | * in UNIX is not thread-safe, and your program may crash if one thread |
274 | | * calls g_setenv() while another thread is calling getenv(). (And note |
275 | | * that many functions, such as gettext(), call getenv() internally.) |
276 | | * This function is only safe to use at the very start of your program, |
277 | | * before creating any other threads (or creating objects that create |
278 | | * worker threads of their own). |
279 | | * |
280 | | * If you need to set up the environment for a child process, you can |
281 | | * use g_get_environ() to get an environment array, modify that with |
282 | | * g_environ_setenv() and g_environ_unsetenv(), and then pass that |
283 | | * array directly to execvpe(), g_spawn_async(), or the like. |
284 | | * |
285 | | * Returns: %FALSE if the environment variable couldn't be set. |
286 | | * |
287 | | * Since: 2.4 |
288 | | */ |
289 | | gboolean |
290 | | g_setenv (const gchar *variable, |
291 | | const gchar *value, |
292 | | gboolean overwrite) |
293 | 91.7k | { |
294 | 91.7k | gint result; |
295 | | #ifndef HAVE_SETENV |
296 | | gchar *string; |
297 | | #endif |
298 | | |
299 | 91.7k | g_return_val_if_fail (variable != NULL, FALSE); |
300 | 91.7k | g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE); |
301 | 91.7k | g_return_val_if_fail (value != NULL, FALSE); |
302 | | |
303 | 91.7k | #ifndef G_DISABLE_CHECKS |
304 | | /* FIXME: This will be upgraded to a g_warning() in a future release of GLib. |
305 | | * See https://gitlab.gnome.org/GNOME/glib/issues/715 */ |
306 | 91.7k | if (g_thread_n_created () > 0) |
307 | 0 | g_debug ("setenv()/putenv() are not thread-safe and should not be used after threads are created"); |
308 | 91.7k | #endif |
309 | | |
310 | 91.7k | #ifdef HAVE_SETENV |
311 | 91.7k | result = setenv (variable, value, overwrite); |
312 | | #else |
313 | | if (!overwrite && getenv (variable) != NULL) |
314 | | return TRUE; |
315 | | |
316 | | /* This results in a leak when you overwrite existing |
317 | | * settings. It would be fairly easy to fix this by keeping |
318 | | * our own parallel array or hash table. |
319 | | */ |
320 | | string = g_strconcat (variable, "=", value, NULL); |
321 | | result = putenv (string); |
322 | | #endif |
323 | 91.7k | return result == 0; |
324 | 91.7k | } |
325 | | |
326 | | #ifdef HAVE__NSGETENVIRON |
327 | | #define environ (*_NSGetEnviron()) |
328 | | #else |
329 | | /* According to the Single Unix Specification, environ is not |
330 | | * in any system header, although unistd.h often declares it. |
331 | | */ |
332 | | extern char **environ; |
333 | | #endif |
334 | | |
335 | | /** |
336 | | * g_unsetenv: |
337 | | * @variable: (type filename): the environment variable to remove, must |
338 | | * not contain '=' |
339 | | * |
340 | | * Removes an environment variable from the environment. |
341 | | * |
342 | | * Note that on some systems, when variables are overwritten, the |
343 | | * memory used for the previous variables and its value isn't reclaimed. |
344 | | * |
345 | | * You should be mindful of the fact that environment variable handling |
346 | | * in UNIX is not thread-safe, and your program may crash if one thread |
347 | | * calls g_unsetenv() while another thread is calling getenv(). (And note |
348 | | * that many functions, such as gettext(), call getenv() internally.) This |
349 | | * function is only safe to use at the very start of your program, before |
350 | | * creating any other threads (or creating objects that create worker |
351 | | * threads of their own). |
352 | | * |
353 | | * If you need to set up the environment for a child process, you can |
354 | | * use g_get_environ() to get an environment array, modify that with |
355 | | * g_environ_setenv() and g_environ_unsetenv(), and then pass that |
356 | | * array directly to execvpe(), g_spawn_async(), or the like. |
357 | | * |
358 | | * Since: 2.4 |
359 | | */ |
360 | | void |
361 | | g_unsetenv (const gchar *variable) |
362 | 0 | { |
363 | 0 | g_return_if_fail (variable != NULL); |
364 | 0 | g_return_if_fail (strchr (variable, '=') == NULL); |
365 | | |
366 | 0 | #ifndef G_DISABLE_CHECKS |
367 | | /* FIXME: This will be upgraded to a g_warning() in a future release of GLib. |
368 | | * See https://gitlab.gnome.org/GNOME/glib/issues/715 */ |
369 | 0 | if (g_thread_n_created () > 0) |
370 | 0 | g_debug ("unsetenv() is not thread-safe and should not be used after threads are created"); |
371 | 0 | #endif |
372 | |
|
373 | 0 | #ifdef HAVE_UNSETENV |
374 | 0 | unsetenv (variable); |
375 | | #else /* !HAVE_UNSETENV */ |
376 | | /* Mess directly with the environ array. |
377 | | * This seems to be the only portable way to do this. |
378 | | */ |
379 | | g_environ_unsetenv_internal (environ, variable, FALSE); |
380 | | #endif /* !HAVE_UNSETENV */ |
381 | 0 | } |
382 | | |
383 | | /** |
384 | | * g_listenv: |
385 | | * |
386 | | * Gets the names of all variables set in the environment. |
387 | | * |
388 | | * Programs that want to be portable to Windows should typically use |
389 | | * this function and g_getenv() instead of using the environ array |
390 | | * from the C library directly. On Windows, the strings in the environ |
391 | | * array are in system codepage encoding, while in most of the typical |
392 | | * use cases for environment variables in GLib-using programs you want |
393 | | * the UTF-8 encoding that this function and g_getenv() provide. |
394 | | * |
395 | | * Returns: (array zero-terminated=1) (element-type filename) (transfer full): |
396 | | * a %NULL-terminated list of strings which must be freed with |
397 | | * g_strfreev(). |
398 | | * |
399 | | * Since: 2.8 |
400 | | */ |
401 | | gchar ** |
402 | | g_listenv (void) |
403 | 0 | { |
404 | 0 | gchar **result, *eq; |
405 | 0 | gint len, i, j; |
406 | |
|
407 | 0 | len = g_strv_length (environ); |
408 | 0 | result = g_new0 (gchar *, len + 1); |
409 | |
|
410 | 0 | j = 0; |
411 | 0 | for (i = 0; i < len; i++) |
412 | 0 | { |
413 | 0 | eq = strchr (environ[i], '='); |
414 | 0 | if (eq) |
415 | 0 | result[j++] = g_strndup (environ[i], eq - environ[i]); |
416 | 0 | } |
417 | |
|
418 | 0 | result[j] = NULL; |
419 | |
|
420 | 0 | return result; |
421 | 0 | } |
422 | | |
423 | | /** |
424 | | * g_get_environ: |
425 | | * |
426 | | * Gets the list of environment variables for the current process. |
427 | | * |
428 | | * The list is %NULL terminated and each item in the list is of the |
429 | | * form 'NAME=VALUE'. |
430 | | * |
431 | | * This is equivalent to direct access to the 'environ' global variable, |
432 | | * except portable. |
433 | | * |
434 | | * The return value is freshly allocated and it should be freed with |
435 | | * g_strfreev() when it is no longer needed. |
436 | | * |
437 | | * Returns: (array zero-terminated=1) (element-type filename) (transfer full): |
438 | | * the list of environment variables |
439 | | * |
440 | | * Since: 2.28 |
441 | | */ |
442 | | gchar ** |
443 | | g_get_environ (void) |
444 | 0 | { |
445 | 0 | return g_strdupv (environ); |
446 | 0 | } |
447 | | |
448 | | /* Win32 implementation {{{1 */ |
449 | | #else /* G_OS_WIN32 */ |
450 | | |
451 | | const gchar * |
452 | | g_getenv (const gchar *variable) |
453 | | { |
454 | | GQuark quark; |
455 | | gchar *value; |
456 | | wchar_t dummy[2], *wname, *wvalue; |
457 | | int len; |
458 | | |
459 | | g_return_val_if_fail (variable != NULL, NULL); |
460 | | g_return_val_if_fail (g_utf8_validate (variable, -1, NULL), NULL); |
461 | | |
462 | | /* On Windows NT, it is relatively typical that environment |
463 | | * variables contain references to other environment variables. If |
464 | | * so, use ExpandEnvironmentStrings(). (In an ideal world, such |
465 | | * environment variables would be stored in the Registry as |
466 | | * REG_EXPAND_SZ type values, and would then get automatically |
467 | | * expanded before a program sees them. But there is broken software |
468 | | * that stores environment variables as REG_SZ values even if they |
469 | | * contain references to other environment variables.) |
470 | | */ |
471 | | |
472 | | wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL); |
473 | | |
474 | | len = GetEnvironmentVariableW (wname, dummy, 2); |
475 | | |
476 | | if (len == 0) |
477 | | { |
478 | | g_free (wname); |
479 | | if (GetLastError () == ERROR_ENVVAR_NOT_FOUND) |
480 | | return NULL; |
481 | | |
482 | | quark = g_quark_from_static_string (""); |
483 | | return g_quark_to_string (quark); |
484 | | } |
485 | | else if (len == 1) |
486 | | len = 2; |
487 | | |
488 | | wvalue = g_new (wchar_t, len); |
489 | | |
490 | | if (GetEnvironmentVariableW (wname, wvalue, len) != len - 1) |
491 | | { |
492 | | g_free (wname); |
493 | | g_free (wvalue); |
494 | | return NULL; |
495 | | } |
496 | | |
497 | | if (wcschr (wvalue, L'%') != NULL) |
498 | | { |
499 | | wchar_t *tem = wvalue; |
500 | | |
501 | | len = ExpandEnvironmentStringsW (wvalue, dummy, 2); |
502 | | |
503 | | if (len > 0) |
504 | | { |
505 | | wvalue = g_new (wchar_t, len); |
506 | | |
507 | | if (ExpandEnvironmentStringsW (tem, wvalue, len) != len) |
508 | | { |
509 | | g_free (wvalue); |
510 | | wvalue = tem; |
511 | | } |
512 | | else |
513 | | g_free (tem); |
514 | | } |
515 | | } |
516 | | |
517 | | value = g_utf16_to_utf8 (wvalue, -1, NULL, NULL, NULL); |
518 | | |
519 | | g_free (wname); |
520 | | g_free (wvalue); |
521 | | |
522 | | quark = g_quark_from_string (value); |
523 | | g_free (value); |
524 | | |
525 | | return g_quark_to_string (quark); |
526 | | } |
527 | | |
528 | | gboolean |
529 | | g_setenv (const gchar *variable, |
530 | | const gchar *value, |
531 | | gboolean overwrite) |
532 | | { |
533 | | gboolean retval; |
534 | | wchar_t *wname, *wvalue, *wassignment; |
535 | | gchar *tem; |
536 | | |
537 | | g_return_val_if_fail (variable != NULL, FALSE); |
538 | | g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE); |
539 | | g_return_val_if_fail (value != NULL, FALSE); |
540 | | g_return_val_if_fail (g_utf8_validate (variable, -1, NULL), FALSE); |
541 | | g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE); |
542 | | |
543 | | if (!overwrite && g_getenv (variable) != NULL) |
544 | | return TRUE; |
545 | | |
546 | | /* We want to (if possible) set both the environment variable copy |
547 | | * kept by the C runtime and the one kept by the system. |
548 | | * |
549 | | * We can't use only the C runtime's putenv or _wputenv() as that |
550 | | * won't work for arbitrary Unicode strings in a "non-Unicode" app |
551 | | * (with main() and not wmain()). In a "main()" app the C runtime |
552 | | * initializes the C runtime's environment table by converting the |
553 | | * real (wide char) environment variables to system codepage, thus |
554 | | * breaking those that aren't representable in the system codepage. |
555 | | * |
556 | | * As the C runtime's putenv() will also set the system copy, we do |
557 | | * the putenv() first, then call SetEnvironmentValueW ourselves. |
558 | | */ |
559 | | |
560 | | wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL); |
561 | | wvalue = g_utf8_to_utf16 (value, -1, NULL, NULL, NULL); |
562 | | tem = g_strconcat (variable, "=", value, NULL); |
563 | | wassignment = g_utf8_to_utf16 (tem, -1, NULL, NULL, NULL); |
564 | | |
565 | | g_free (tem); |
566 | | _wputenv (wassignment); |
567 | | g_free (wassignment); |
568 | | |
569 | | retval = (SetEnvironmentVariableW (wname, wvalue) != 0); |
570 | | |
571 | | g_free (wname); |
572 | | g_free (wvalue); |
573 | | |
574 | | return retval; |
575 | | } |
576 | | |
577 | | void |
578 | | g_unsetenv (const gchar *variable) |
579 | | { |
580 | | wchar_t *wname, *wassignment; |
581 | | gchar *tem; |
582 | | |
583 | | g_return_if_fail (variable != NULL); |
584 | | g_return_if_fail (strchr (variable, '=') == NULL); |
585 | | g_return_if_fail (g_utf8_validate (variable, -1, NULL)); |
586 | | |
587 | | wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL); |
588 | | tem = g_strconcat (variable, "=", NULL); |
589 | | wassignment = g_utf8_to_utf16 (tem, -1, NULL, NULL, NULL); |
590 | | |
591 | | g_free (tem); |
592 | | _wputenv (wassignment); |
593 | | g_free (wassignment); |
594 | | |
595 | | SetEnvironmentVariableW (wname, NULL); |
596 | | |
597 | | g_free (wname); |
598 | | } |
599 | | |
600 | | gchar ** |
601 | | g_listenv (void) |
602 | | { |
603 | | gchar **result, *eq; |
604 | | gint len = 0, j; |
605 | | wchar_t *p, *q; |
606 | | |
607 | | p = (wchar_t *) GetEnvironmentStringsW (); |
608 | | if (p != NULL) |
609 | | { |
610 | | q = p; |
611 | | while (*q) |
612 | | { |
613 | | q += wcslen (q) + 1; |
614 | | len++; |
615 | | } |
616 | | } |
617 | | result = g_new0 (gchar *, len + 1); |
618 | | |
619 | | j = 0; |
620 | | q = p; |
621 | | while (*q) |
622 | | { |
623 | | result[j] = g_utf16_to_utf8 (q, -1, NULL, NULL, NULL); |
624 | | if (result[j] != NULL) |
625 | | { |
626 | | eq = strchr (result[j], '='); |
627 | | if (eq && eq > result[j]) |
628 | | { |
629 | | *eq = '\0'; |
630 | | j++; |
631 | | } |
632 | | else |
633 | | g_free (result[j]); |
634 | | } |
635 | | q += wcslen (q) + 1; |
636 | | } |
637 | | result[j] = NULL; |
638 | | FreeEnvironmentStringsW (p); |
639 | | |
640 | | return result; |
641 | | } |
642 | | |
643 | | gchar ** |
644 | | g_get_environ (void) |
645 | | { |
646 | | gunichar2 *strings; |
647 | | gchar **result; |
648 | | gint i, n; |
649 | | |
650 | | strings = GetEnvironmentStringsW (); |
651 | | for (n = 0, i = 0; strings[n]; i++) |
652 | | n += wcslen (strings + n) + 1; |
653 | | |
654 | | result = g_new (char *, i + 1); |
655 | | for (n = 0, i = 0; strings[n]; i++) |
656 | | { |
657 | | result[i] = g_utf16_to_utf8 (strings + n, -1, NULL, NULL, NULL); |
658 | | n += wcslen (strings + n) + 1; |
659 | | } |
660 | | FreeEnvironmentStringsW (strings); |
661 | | result[i] = NULL; |
662 | | |
663 | | return result; |
664 | | } |
665 | | |
666 | | #endif /* G_OS_WIN32 */ |
667 | | |
668 | | #ifdef G_OS_WIN32 |
669 | | |
670 | | /* Binary compatibility versions. Not for newly compiled code. */ |
671 | | |
672 | | _GLIB_EXTERN const gchar *g_getenv_utf8 (const gchar *variable); |
673 | | _GLIB_EXTERN gboolean g_setenv_utf8 (const gchar *variable, |
674 | | const gchar *value, |
675 | | gboolean overwrite); |
676 | | _GLIB_EXTERN void g_unsetenv_utf8 (const gchar *variable); |
677 | | |
678 | | const gchar * |
679 | | g_getenv_utf8 (const gchar *variable) |
680 | | { |
681 | | return g_getenv (variable); |
682 | | } |
683 | | |
684 | | gboolean |
685 | | g_setenv_utf8 (const gchar *variable, |
686 | | const gchar *value, |
687 | | gboolean overwrite) |
688 | | { |
689 | | return g_setenv (variable, value, overwrite); |
690 | | } |
691 | | |
692 | | void |
693 | | g_unsetenv_utf8 (const gchar *variable) |
694 | | { |
695 | | g_unsetenv (variable); |
696 | | } |
697 | | |
698 | | #endif |
699 | | |
700 | | /* Epilogue {{{1 */ |
701 | | /* vim: set foldmethod=marker: */ |