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