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