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       else
202         g_free (*e);
203
204       e++;
205     }
206   *f = NULL;
207
208   return envp;
209 }
210
211 /* UNIX implemention {{{1 */
212 #ifndef G_OS_WIN32
213
214 /**
215  * g_getenv:
216  * @variable: the environment variable to get, in the GLib file name
217  *     encoding
218  *
219  * Returns the value of an environment variable.
220  *
221  * The name and value are in the GLib file name encoding. On UNIX,
222  * this means the actual bytes which might or might not be in some
223  * consistent character set and encoding. On Windows, it is in UTF-8.
224  * On Windows, in case the environment variable's value contains
225  * references to other environment variables, they are expanded.
226  *
227  * Return value: the value of the environment variable, or %NULL if
228  *     the environment variable is not found. The returned string
229  *     may be overwritten by the next call to g_getenv(), g_setenv()
230  *     or g_unsetenv().
231  */
232 const gchar *
233 g_getenv (const gchar *variable)
234 {
235   g_return_val_if_fail (variable != NULL, NULL);
236
237   return getenv (variable);
238 }
239
240 /**
241  * g_setenv:
242  * @variable: the environment variable to set, must not contain '='.
243  * @value: the value for to set the variable to.
244  * @overwrite: whether to change the variable if it already exists.
245  *
246  * Sets an environment variable. Both the variable's name and value
247  * should be in the GLib file name encoding. On UNIX, this means that
248  * they can be arbitrary byte strings. On Windows, they should be in
249  * UTF-8.
250  *
251  * Note that on some systems, when variables are overwritten, the memory
252  * used for the previous variables and its value isn't reclaimed.
253  *
254  * <warning><para>
255  * Environment variable handling in UNIX is not thread-safe, and your
256  * program may crash if one thread calls g_setenv() while another
257  * thread is calling getenv(). (And note that many functions, such as
258  * gettext(), call getenv() internally.) This function is only safe to
259  * use at the very start of your program, before creating any other
260  * threads (or creating objects that create worker threads of their
261  * own).
262  * </para><para>
263  * If you need to set up the environment for a child process, you can
264  * use g_get_environ() to get an environment array, modify that with
265  * g_environ_setenv() and g_environ_unsetenv(), and then pass that
266  * array directly to execvpe(), g_spawn_async(), or the like.
267  * </para></warning>
268  *
269  * Returns: %FALSE if the environment variable couldn't be set.
270  *
271  * Since: 2.4
272  */
273 gboolean
274 g_setenv (const gchar *variable,
275           const gchar *value,
276           gboolean     overwrite)
277 {
278   gint result;
279 #ifndef HAVE_SETENV
280   gchar *string;
281 #endif
282
283   g_return_val_if_fail (variable != NULL, FALSE);
284   g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE);
285
286 #ifdef HAVE_SETENV
287   result = setenv (variable, value, overwrite);
288 #else
289   if (!overwrite && getenv (variable) != NULL)
290     return TRUE;
291
292   /* This results in a leak when you overwrite existing
293    * settings. It would be fairly easy to fix this by keeping
294    * our own parallel array or hash table.
295    */
296   string = g_strconcat (variable, "=", value, NULL);
297   result = putenv (string);
298 #endif
299   return result == 0;
300 }
301
302 #ifdef HAVE__NSGETENVIRON
303 #define environ (*_NSGetEnviron())
304 #else
305 /* According to the Single Unix Specification, environ is not
306  * in any system header, although unistd.h often declares it.
307  */
308 extern char **environ;
309 #endif
310
311 /**
312  * g_unsetenv:
313  * @variable: the environment variable to remove, must not contain '='
314  *
315  * Removes an environment variable from the environment.
316  *
317  * Note that on some systems, when variables are overwritten, the
318  * memory used for the previous variables and its value isn't reclaimed.
319  *
320  * <warning><para>
321  * Environment variable handling in UNIX is not thread-safe, and your
322  * program may crash if one thread calls g_unsetenv() while another
323  * thread is calling getenv(). (And note that many functions, such as
324  * gettext(), call getenv() internally.) This function is only safe
325  * to use at the very start of your program, before creating any other
326  * threads (or creating objects that create worker threads of their
327  * own).
328  * </para><para>
329  * If you need to set up the environment for a child process, you can
330  * use g_get_environ() to get an environment array, modify that with
331  * g_environ_setenv() and g_environ_unsetenv(), and then pass that
332  * array directly to execvpe(), g_spawn_async(), or the like.
333  * </para></warning>
334  *
335  * Since: 2.4
336  */
337 void
338 g_unsetenv (const gchar *variable)
339 {
340 #ifdef HAVE_UNSETENV
341   g_return_if_fail (variable != NULL);
342   g_return_if_fail (strchr (variable, '=') == NULL);
343
344   unsetenv (variable);
345 #else /* !HAVE_UNSETENV */
346   g_return_if_fail (variable != NULL);
347   g_return_if_fail (strchr (variable, '=') == NULL);
348
349   /* Mess directly with the environ array.
350    * This seems to be the only portable way to do this.
351    */
352   g_environ_unsetenv (environ, variable);
353 #endif /* !HAVE_UNSETENV */
354 }
355
356 /**
357  * g_listenv:
358  *
359  * Gets the names of all variables set in the environment.
360  *
361  * Programs that want to be portable to Windows should typically use
362  * this function and g_getenv() instead of using the environ array
363  * from the C library directly. On Windows, the strings in the environ
364  * array are in system codepage encoding, while in most of the typical
365  * use cases for environment variables in GLib-using programs you want
366  * the UTF-8 encoding that this function and g_getenv() provide.
367  *
368  * Returns: (array zero-terminated=1) (transfer full): a %NULL-terminated
369  *     list of strings which must be freed with g_strfreev().
370  *
371  * Since: 2.8
372  */
373 gchar **
374 g_listenv (void)
375 {
376   gchar **result, *eq;
377   gint len, i, j;
378
379   len = g_strv_length (environ);
380   result = g_new0 (gchar *, len + 1);
381
382   j = 0;
383   for (i = 0; i < len; i++)
384     {
385       eq = strchr (environ[i], '=');
386       if (eq)
387         result[j++] = g_strndup (environ[i], eq - environ[i]);
388     }
389
390   result[j] = NULL;
391
392   return result;
393 }
394
395 /**
396  * g_get_environ:
397  *
398  * Gets the list of environment variables for the current process.
399  *
400  * The list is %NULL terminated and each item in the list is of the
401  * form 'NAME=VALUE'.
402  *
403  * This is equivalent to direct access to the 'environ' global variable,
404  * except portable.
405  *
406  * The return value is freshly allocated and it should be freed with
407  * g_strfreev() when it is no longer needed.
408  *
409  * Returns: (array zero-terminated=1) (transfer full): the list of
410  *     environment variables
411  *
412  * Since: 2.28
413  */
414 gchar **
415 g_get_environ (void)
416 {
417   return g_strdupv (environ);
418 }
419
420 /* Win32 implementation {{{1 */
421 #else   /* G_OS_WIN32 */
422
423 const gchar *
424 g_getenv (const gchar *variable)
425 {
426   GQuark quark;
427   gchar *value;
428   wchar_t dummy[2], *wname, *wvalue;
429   int len;
430
431   g_return_val_if_fail (variable != NULL, NULL);
432   g_return_val_if_fail (g_utf8_validate (variable, -1, NULL), NULL);
433
434   /* On Windows NT, it is relatively typical that environment
435    * variables contain references to other environment variables. If
436    * so, use ExpandEnvironmentStrings(). (In an ideal world, such
437    * environment variables would be stored in the Registry as
438    * REG_EXPAND_SZ type values, and would then get automatically
439    * expanded before a program sees them. But there is broken software
440    * that stores environment variables as REG_SZ values even if they
441    * contain references to other environment variables.)
442    */
443
444   wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
445
446   len = GetEnvironmentVariableW (wname, dummy, 2);
447
448   if (len == 0)
449     {
450       g_free (wname);
451       return NULL;
452     }
453   else if (len == 1)
454     len = 2;
455
456   wvalue = g_new (wchar_t, len);
457
458   if (GetEnvironmentVariableW (wname, wvalue, len) != len - 1)
459     {
460       g_free (wname);
461       g_free (wvalue);
462       return NULL;
463     }
464
465   if (wcschr (wvalue, L'%') != NULL)
466     {
467       wchar_t *tem = wvalue;
468
469       len = ExpandEnvironmentStringsW (wvalue, dummy, 2);
470
471       if (len > 0)
472         {
473           wvalue = g_new (wchar_t, len);
474
475           if (ExpandEnvironmentStringsW (tem, wvalue, len) != len)
476             {
477               g_free (wvalue);
478               wvalue = tem;
479             }
480           else
481             g_free (tem);
482         }
483     }
484
485   value = g_utf16_to_utf8 (wvalue, -1, NULL, NULL, NULL);
486
487   g_free (wname);
488   g_free (wvalue);
489
490   quark = g_quark_from_string (value);
491   g_free (value);
492
493   return g_quark_to_string (quark);
494 }
495
496 gboolean
497 g_setenv (const gchar *variable,
498           const gchar *value,
499           gboolean     overwrite)
500 {
501   gboolean retval;
502   wchar_t *wname, *wvalue, *wassignment;
503   gchar *tem;
504
505   g_return_val_if_fail (variable != NULL, FALSE);
506   g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE);
507   g_return_val_if_fail (g_utf8_validate (variable, -1, NULL), FALSE);
508   g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE);
509
510   if (!overwrite && g_getenv (variable) != NULL)
511     return TRUE;
512
513   /* We want to (if possible) set both the environment variable copy
514    * kept by the C runtime and the one kept by the system.
515    *
516    * We can't use only the C runtime's putenv or _wputenv() as that
517    * won't work for arbitrary Unicode strings in a "non-Unicode" app
518    * (with main() and not wmain()). In a "main()" app the C runtime
519    * initializes the C runtime's environment table by converting the
520    * real (wide char) environment variables to system codepage, thus
521    * breaking those that aren't representable in the system codepage.
522    *
523    * As the C runtime's putenv() will also set the system copy, we do
524    * the putenv() first, then call SetEnvironmentValueW ourselves.
525    */
526
527   wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
528   wvalue = g_utf8_to_utf16 (value, -1, NULL, NULL, NULL);
529   tem = g_strconcat (variable, "=", value, NULL);
530   wassignment = g_utf8_to_utf16 (tem, -1, NULL, NULL, NULL);
531
532   g_free (tem);
533   _wputenv (wassignment);
534   g_free (wassignment);
535
536   retval = (SetEnvironmentVariableW (wname, wvalue) != 0);
537
538   g_free (wname);
539   g_free (wvalue);
540
541   return retval;
542 }
543
544 void
545 g_unsetenv (const gchar *variable)
546 {
547   wchar_t *wname, *wassignment;
548   gchar *tem;
549
550   g_return_if_fail (variable != NULL);
551   g_return_if_fail (strchr (variable, '=') == NULL);
552   g_return_if_fail (g_utf8_validate (variable, -1, NULL));
553
554   wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
555   tem = g_strconcat (variable, "=", NULL);
556   wassignment = g_utf8_to_utf16 (tem, -1, NULL, NULL, NULL);
557
558   g_free (tem);
559   _wputenv (wassignment);
560   g_free (wassignment);
561
562   SetEnvironmentVariableW (wname, NULL);
563
564   g_free (wname);
565 }
566
567 gchar **
568 g_listenv (void)
569 {
570   gchar **result, *eq;
571   gint len = 0, j;
572   wchar_t *p, *q;
573
574   p = (wchar_t *) GetEnvironmentStringsW ();
575   if (p != NULL)
576     {
577       q = p;
578       while (*q)
579         {
580           q += wcslen (q) + 1;
581           len++;
582         }
583     }
584   result = g_new0 (gchar *, len + 1);
585
586   j = 0;
587   q = p;
588   while (*q)
589     {
590       result[j] = g_utf16_to_utf8 (q, -1, NULL, NULL, NULL);
591       if (result[j] != NULL)
592         {
593           eq = strchr (result[j], '=');
594           if (eq && eq > result[j])
595             {
596               *eq = '\0';
597               j++;
598             }
599           else
600             g_free (result[j]);
601         }
602       q += wcslen (q) + 1;
603     }
604   result[j] = NULL;
605   FreeEnvironmentStringsW (p);
606
607   return result;
608 }
609
610 gchar **
611 g_get_environ (void)
612 {
613   gunichar2 *strings;
614   gchar **result;
615   gint i, n;
616
617   strings = GetEnvironmentStringsW ();
618   for (n = 0; strings[n]; n += wcslen (strings + n) + 1);
619   result = g_new (char *, n + 1);
620   for (i = 0; strings[i]; i += wcslen (strings + i) + 1)
621     result[i] = g_utf16_to_utf8 (strings + i, -1, NULL, NULL, NULL);
622   FreeEnvironmentStringsW (strings);
623   result[i] = NULL;
624
625   return result;
626 }
627
628 /* Win32 binary compatibility versions {{{1 */
629 #ifndef _WIN64
630
631 #undef g_getenv
632
633 const gchar *
634 g_getenv (const gchar *variable)
635 {
636   gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL);
637   const gchar *utf8_value = g_getenv_utf8 (utf8_variable);
638   gchar *value;
639   GQuark quark;
640
641   g_free (utf8_variable);
642   if (!utf8_value)
643     return NULL;
644   value = g_locale_from_utf8 (utf8_value, -1, NULL, NULL, NULL);
645   quark = g_quark_from_string (value);
646   g_free (value);
647
648   return g_quark_to_string (quark);
649 }
650
651 #undef g_setenv
652
653 gboolean
654 g_setenv (const gchar *variable,
655           const gchar *value,
656           gboolean     overwrite)
657 {
658   gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL);
659   gchar *utf8_value = g_locale_to_utf8 (value, -1, NULL, NULL, NULL);
660   gboolean retval = g_setenv_utf8 (utf8_variable, utf8_value, overwrite);
661
662   g_free (utf8_variable);
663   g_free (utf8_value);
664
665   return retval;
666 }
667
668 #undef g_unsetenv
669
670 void
671 g_unsetenv (const gchar *variable)
672 {
673   gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL);
674
675   g_unsetenv_utf8 (utf8_variable);
676
677   g_free (utf8_variable);
678 }
679
680 #endif  /* _WIN64 */
681
682 #endif  /* G_OS_WIN32 */
683
684 /* Epilogue {{{1 */
685 /* vim: set foldmethod=marker: */