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