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