LCOV - code coverage report
Current view: top level - glib/glib - genviron.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 77 77 100.0 %
Date: 2024-04-16 05:15:53 Functions: 11 11 100.0 %
Branches: 32 34 94.1 %

           Branch data     Line data    Source code
       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                 :      79846 : 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   [ +  +  +  + ]:      79846 :     return strncmp (env, variable, len) == 0 && env[len] == '=';
      59                 :            : #endif
      60                 :            : }
      61                 :            : 
      62                 :            : static gint
      63                 :        432 : g_environ_find (gchar       **envp,
      64                 :            :                 const gchar  *variable)
      65                 :            : {
      66                 :            :   gsize len;
      67                 :            :   gint i;
      68                 :            : 
      69         [ +  + ]:        432 :   if (envp == NULL)
      70                 :          3 :     return -1;
      71                 :            : 
      72                 :        429 :   len = strlen (variable);
      73                 :            : 
      74         [ +  + ]:      61873 :   for (i = 0; envp[i]; i++)
      75                 :            :     {
      76         [ +  + ]:      61770 :       if (g_environ_matches (envp[i], variable, len))
      77                 :        326 :         return i;
      78                 :            :     }
      79                 :            : 
      80                 :        103 :   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                 :        155 : g_environ_getenv (gchar       **envp,
     102                 :            :                   const gchar  *variable)
     103                 :            : {
     104                 :            :   gint index;
     105                 :            : 
     106                 :        155 :   g_return_val_if_fail (variable != NULL, NULL);
     107                 :            : 
     108                 :        154 :   index = g_environ_find (envp, variable);
     109         [ +  + ]:        154 :   if (index != -1)
     110                 :        142 :     return envp[index] + strlen (variable) + 1;
     111                 :            :   else
     112                 :         12 :     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                 :        281 : g_environ_setenv (gchar       **envp,
     136                 :            :                   const gchar  *variable,
     137                 :            :                   const gchar  *value,
     138                 :            :                   gboolean      overwrite)
     139                 :            : {
     140                 :            :   gint index;
     141                 :            : 
     142                 :        281 :   g_return_val_if_fail (variable != NULL, NULL);
     143                 :        280 :   g_return_val_if_fail (strchr (variable, '=') == NULL, NULL);
     144                 :        279 :   g_return_val_if_fail (value != NULL, NULL);
     145                 :            : 
     146                 :        278 :   index = g_environ_find (envp, variable);
     147         [ +  + ]:        278 :   if (index != -1)
     148                 :            :     {
     149         [ +  + ]:        184 :       if (overwrite)
     150                 :            :         {
     151                 :        182 :           g_free (envp[index]);
     152                 :        182 :           envp[index] = g_strdup_printf ("%s=%s", variable, value);
     153                 :            :         }
     154                 :            :     }
     155                 :            :   else
     156                 :            :     {
     157                 :            :       gint length;
     158                 :            : 
     159         [ +  + ]:         94 :       length = envp ? g_strv_length (envp) : 0;
     160                 :         94 :       envp = g_renew (gchar *, envp, length + 2);
     161                 :         94 :       envp[length] = g_strdup_printf ("%s=%s", variable, value);
     162                 :         94 :       envp[length + 1] = NULL;
     163                 :            :     }
     164                 :            : 
     165                 :        278 :   return envp;
     166                 :            : }
     167                 :            : 
     168                 :            : static gchar **
     169                 :        108 : g_environ_unsetenv_internal (gchar        **envp,
     170                 :            :                              const gchar   *variable,
     171                 :            :                              gboolean       free_value)
     172                 :            : {
     173                 :            :   gsize len;
     174                 :            :   gchar **e, **f;
     175                 :            : 
     176                 :        108 :   len = strlen (variable);
     177                 :            : 
     178                 :            :   /* Note that we remove *all* environment entries for
     179                 :            :    * the variable name, not just the first.
     180                 :            :    */
     181                 :        108 :   e = f = envp;
     182         [ +  + ]:      18184 :   while (*e != NULL)
     183                 :            :     {
     184         [ +  + ]:      18076 :       if (!g_environ_matches (*e, variable, len))
     185                 :            :         {
     186                 :      18017 :           *f = *e;
     187                 :      18017 :           f++;
     188                 :            :         }
     189                 :            :       else
     190                 :            :         {
     191         [ +  - ]:         59 :           if (free_value)
     192                 :         59 :             g_free (*e);
     193                 :            :         }
     194                 :            : 
     195                 :      18076 :       e++;
     196                 :            :     }
     197                 :        108 :   *f = NULL;
     198                 :            : 
     199                 :        108 :   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                 :        110 : g_environ_unsetenv (gchar       **envp,
     221                 :            :                     const gchar  *variable)
     222                 :            : {
     223                 :        110 :   g_return_val_if_fail (variable != NULL, NULL);
     224                 :        109 :   g_return_val_if_fail (strchr (variable, '=') == NULL, NULL);
     225                 :            : 
     226         [ +  + ]:        109 :   if (envp == NULL)
     227                 :          1 :     return NULL;
     228                 :            : 
     229                 :        108 :   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                 :      42284 : g_getenv (const gchar *variable)
     254                 :            : {
     255                 :      42284 :   g_return_val_if_fail (variable != NULL, NULL);
     256                 :            : 
     257                 :      42284 :   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                 :       1255 : 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                 :       1255 :   g_return_val_if_fail (variable != NULL, FALSE);
     302                 :       1254 :   g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE);
     303                 :       1253 :   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         [ +  + ]:       1252 :   if (g_thread_n_created () > 0)
     309                 :        258 :     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                 :       1252 :   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                 :       1252 :   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                 :        729 : g_unsetenv (const gchar *variable)
     364                 :            : {
     365                 :        729 :   g_return_if_fail (variable != NULL);
     366                 :        728 :   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         [ +  + ]:        727 :   if (g_thread_n_created () > 0)
     372                 :        479 :     g_debug ("unsetenv() is not thread-safe and should not be used after threads are created");
     373                 :            : #endif
     374                 :            : 
     375                 :            : #ifdef HAVE_UNSETENV
     376                 :        727 :   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                 :          1 : g_listenv (void)
     405                 :            : {
     406                 :            :   gchar **result, *eq;
     407                 :            :   gint len, i, j;
     408                 :            : 
     409                 :          1 :   len = g_strv_length (environ);
     410                 :          1 :   result = g_new0 (gchar *, len + 1);
     411                 :            : 
     412                 :          1 :   j = 0;
     413         [ +  + ]:        165 :   for (i = 0; i < len; i++)
     414                 :            :     {
     415                 :        164 :       eq = strchr (environ[i], '=');
     416         [ +  - ]:        164 :       if (eq)
     417                 :        164 :         result[j++] = g_strndup (environ[i], eq - environ[i]);
     418                 :            :     }
     419                 :            : 
     420                 :          1 :   result[j] = NULL;
     421                 :            : 
     422                 :          1 :   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                 :        172 : g_get_environ (void)
     446                 :            : {
     447                 :        172 :   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: */

Generated by: LCOV version 1.14