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