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