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