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