-/**
- * g_setenv:
- * @variable: the environment variable to set, must not contain '='.
- * @value: the value for to set the variable to.
- * @overwrite: whether to change the variable if it already exists.
- *
- * Sets an environment variable. Both the variable's name and value
- * should be in the GLib file name encoding. On UNIX, this means that
- * they can be any sequence of bytes. On Windows, they should be in
- * UTF-8.
- *
- * Note that on some systems, when variables are overwritten, the memory
- * used for the previous variables and its value isn't reclaimed.
- *
- * Returns: %FALSE if the environment variable couldn't be set.
- *
- * Since: 2.4
- */
-gboolean
-g_setenv (const gchar *variable,
- const gchar *value,
- gboolean overwrite)
-{
-#ifndef G_OS_WIN32
-
- gint result;
-#ifndef HAVE_SETENV
- gchar *string;
-#endif
-
- g_return_val_if_fail (variable != NULL, FALSE);
- g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE);
-
-#ifdef HAVE_SETENV
- result = setenv (variable, value, overwrite);
-#else
- if (!overwrite && getenv (variable) != NULL)
- return TRUE;
-
- /* This results in a leak when you overwrite existing
- * settings. It would be fairly easy to fix this by keeping
- * our own parallel array or hash table.
- */
- string = g_strconcat (variable, "=", value, NULL);
- result = putenv (string);
-#endif
- return result == 0;
-
-#else /* G_OS_WIN32 */
-
- gboolean retval;
- wchar_t *wname, *wvalue, *wassignment;
- gchar *tem;
-
- g_return_val_if_fail (variable != NULL, FALSE);
- g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE);
- g_return_val_if_fail (g_utf8_validate (variable, -1, NULL), FALSE);
- g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE);
-
- if (!overwrite && g_getenv (variable) != NULL)
- return TRUE;
-
- /* We want to (if possible) set both the environment variable copy
- * kept by the C runtime and the one kept by the system.
- *
- * We can't use only the C runtime's putenv or _wputenv() as that
- * won't work for arbitrary Unicode strings in a "non-Unicode" app
- * (with main() and not wmain()). In a "main()" app the C runtime
- * initializes the C runtime's environment table by converting the
- * real (wide char) environment variables to system codepage, thus
- * breaking those that aren't representable in the system codepage.
- *
- * As the C runtime's putenv() will also set the system copy, we do
- * the putenv() first, then call SetEnvironmentValueW ourselves.
- */
-
- wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
- wvalue = g_utf8_to_utf16 (value, -1, NULL, NULL, NULL);
- tem = g_strconcat (variable, "=", value, NULL);
- wassignment = g_utf8_to_utf16 (tem, -1, NULL, NULL, NULL);
-
- g_free (tem);
- _wputenv (wassignment);
- g_free (wassignment);
-
- retval = (SetEnvironmentVariableW (wname, wvalue) != 0);
-
- g_free (wname);
- g_free (wvalue);
-
- return retval;
-
-#endif /* G_OS_WIN32 */
-}
-
-#ifdef HAVE__NSGETENVIRON
-#define environ (*_NSGetEnviron())
-#elif !defined(G_OS_WIN32)
-
-/* According to the Single Unix Specification, environ is not in
- * any system header, although unistd.h often declares it.
- */
-extern char **environ;
-#endif
-
-/**
- * g_unsetenv:
- * @variable: the environment variable to remove, must not contain '='.
- *
- * Removes an environment variable from the environment.
- *
- * Note that on some systems, when variables are overwritten, the memory
- * used for the previous variables and its value isn't reclaimed.
- * Furthermore, this function can't be guaranteed to operate in a
- * threadsafe way.
- *
- * Since: 2.4
- **/
-void
-g_unsetenv (const gchar *variable)
-{
-#ifndef G_OS_WIN32
-
-#ifdef HAVE_UNSETENV
- g_return_if_fail (variable != NULL);
- g_return_if_fail (strchr (variable, '=') == NULL);
-
- unsetenv (variable);
-#else /* !HAVE_UNSETENV */
- int len;
- gchar **e, **f;
-
- g_return_if_fail (variable != NULL);
- g_return_if_fail (strchr (variable, '=') == NULL);
-
- len = strlen (variable);
-
- /* Mess directly with the environ array.
- * This seems to be the only portable way to do this.
- *
- * Note that we remove *all* environment entries for
- * the variable name, not just the first.
- */
- e = f = environ;
- while (*e != NULL)
- {
- if (strncmp (*e, variable, len) != 0 || (*e)[len] != '=')
- {
- *f = *e;
- f++;
- }
- e++;
- }
- *f = NULL;
-#endif /* !HAVE_UNSETENV */
-
-#else /* G_OS_WIN32 */
-
- wchar_t *wname, *wassignment;
- gchar *tem;
-
- g_return_if_fail (variable != NULL);
- g_return_if_fail (strchr (variable, '=') == NULL);
- g_return_if_fail (g_utf8_validate (variable, -1, NULL));
-
- wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
- tem = g_strconcat (variable, "=", NULL);
- wassignment = g_utf8_to_utf16 (tem, -1, NULL, NULL, NULL);
-
- g_free (tem);
- _wputenv (wassignment);
- g_free (wassignment);
-
- SetEnvironmentVariableW (wname, NULL);
-
- g_free (wname);
-
-#endif /* G_OS_WIN32 */
-}
-
-/**
- * g_listenv:
- *
- * Gets the names of all variables set in the environment.
- *
- * Returns: a %NULL-terminated list of strings which must be freed
- * with g_strfreev().
- *
- * Programs that want to be portable to Windows should typically use
- * this function and g_getenv() instead of using the environ array
- * from the C library directly. On Windows, the strings in the environ
- * array are in system codepage encoding, while in most of the typical
- * use cases for environment variables in GLib-using programs you want
- * the UTF-8 encoding that this function and g_getenv() provide.
- *
- * Since: 2.8
- */
-gchar **
-g_listenv (void)
-{
-#ifndef G_OS_WIN32
- gchar **result, *eq;
- gint len, i, j;
-
- len = g_strv_length (environ);
- result = g_new0 (gchar *, len + 1);
-
- j = 0;
- for (i = 0; i < len; i++)
- {
- eq = strchr (environ[i], '=');
- if (eq)
- result[j++] = g_strndup (environ[i], eq - environ[i]);
- }
-
- result[j] = NULL;
-
- return result;
-#else
- gchar **result, *eq;
- gint len = 0, j;
- wchar_t *p, *q;
-
- p = (wchar_t *) GetEnvironmentStringsW ();
- if (p != NULL)
- {
- q = p;
- while (*q)
- {
- q += wcslen (q) + 1;
- len++;
- }
- }
- result = g_new0 (gchar *, len + 1);
-
- j = 0;
- q = p;
- while (*q)
- {
- result[j] = g_utf16_to_utf8 (q, -1, NULL, NULL, NULL);
- if (result[j] != NULL)
- {
- eq = strchr (result[j], '=');
- if (eq && eq > result[j])
- {
- *eq = '\0';
- j++;
- }
- else
- g_free (result[j]);
- }
- q += wcslen (q) + 1;
- }
- result[j] = NULL;
- FreeEnvironmentStringsW (p);
-
- return result;
-#endif
-}
-
-G_LOCK_DEFINE_STATIC (g_utils_global);
-
-static gchar *g_tmp_dir = NULL;
-static gchar *g_user_name = NULL;
-static gchar *g_real_name = NULL;
-static gchar *g_home_dir = NULL;
-static gchar *g_host_name = NULL;
-
-#ifdef G_OS_WIN32
-/* System codepage versions of the above, kept at file level so that they,
- * too, are produced only once.
- */
-static gchar *g_tmp_dir_cp = NULL;
-static gchar *g_user_name_cp = NULL;
-static gchar *g_real_name_cp = NULL;
-static gchar *g_home_dir_cp = NULL;
-#endif
-
-static gchar *g_user_data_dir = NULL;
-static gchar **g_system_data_dirs = NULL;
-static gchar *g_user_cache_dir = NULL;
-static gchar *g_user_config_dir = NULL;
-static gchar **g_system_config_dirs = NULL;
-
-static gchar **g_user_special_dirs = NULL;
-
-/* fifteen minutes of fame for everybody */
-#define G_USER_DIRS_EXPIRE 15 * 60
-
-#ifdef G_OS_WIN32
-
-static gchar *
-get_special_folder (int csidl)
-{
- wchar_t path[MAX_PATH+1];
- HRESULT hr;
- LPITEMIDLIST pidl = NULL;
- BOOL b;
- gchar *retval = NULL;
-
- hr = SHGetSpecialFolderLocation (NULL, csidl, &pidl);
- if (hr == S_OK)
- {
- b = SHGetPathFromIDListW (pidl, path);
- if (b)
- retval = g_utf16_to_utf8 (path, -1, NULL, NULL, NULL);
- CoTaskMemFree (pidl);
- }
- return retval;
-}
-
-static char *
-get_windows_directory_root (void)
-{
- wchar_t wwindowsdir[MAX_PATH];
-
- if (GetWindowsDirectoryW (wwindowsdir, G_N_ELEMENTS (wwindowsdir)))
- {
- /* Usually X:\Windows, but in terminal server environments
- * might be an UNC path, AFAIK.
- */
- char *windowsdir = g_utf16_to_utf8 (wwindowsdir, -1, NULL, NULL, NULL);
- char *p;
-
- if (windowsdir == NULL)
- return g_strdup ("C:\\");
-
- p = (char *) g_path_skip_root (windowsdir);
- if (G_IS_DIR_SEPARATOR (p[-1]) && p[-2] != ':')
- p--;
- *p = '\0';
- return windowsdir;
- }
- else
- return g_strdup ("C:\\");
-}
-
-#endif
-
-/* HOLDS: g_utils_global_lock */
-static void
-g_get_any_init_do (void)
-{
- gchar hostname[100];
-
- g_tmp_dir = g_strdup (g_getenv ("TMPDIR"));
- if (!g_tmp_dir)
- g_tmp_dir = g_strdup (g_getenv ("TMP"));
- if (!g_tmp_dir)
- g_tmp_dir = g_strdup (g_getenv ("TEMP"));
-
-#ifdef G_OS_WIN32
- if (!g_tmp_dir)
- g_tmp_dir = get_windows_directory_root ();
-#else
-#ifdef P_tmpdir
- if (!g_tmp_dir)
- {
- gsize k;
- g_tmp_dir = g_strdup (P_tmpdir);
- k = strlen (g_tmp_dir);
- if (k > 1 && G_IS_DIR_SEPARATOR (g_tmp_dir[k - 1]))
- g_tmp_dir[k - 1] = '\0';
- }
-#endif
-
- if (!g_tmp_dir)
- {
- g_tmp_dir = g_strdup ("/tmp");
- }
-#endif /* !G_OS_WIN32 */
-
-#ifdef G_OS_WIN32
- /* We check $HOME first for Win32, though it is a last resort for Unix
- * where we prefer the results of getpwuid().
- */
- g_home_dir = g_strdup (g_getenv ("HOME"));
-
- /* Only believe HOME if it is an absolute path and exists */
- if (g_home_dir)
- {
- if (!(g_path_is_absolute (g_home_dir) &&
- g_file_test (g_home_dir, G_FILE_TEST_IS_DIR)))
- {
- g_free (g_home_dir);
- g_home_dir = NULL;
- }
- }
-
- /* In case HOME is Unix-style (it happens), convert it to
- * Windows style.
- */
- if (g_home_dir)
- {
- gchar *p;
- while ((p = strchr (g_home_dir, '/')) != NULL)
- *p = '\\';
- }
-
- if (!g_home_dir)
- {
- /* USERPROFILE is probably the closest equivalent to $HOME? */
- if (g_getenv ("USERPROFILE") != NULL)
- g_home_dir = g_strdup (g_getenv ("USERPROFILE"));
- }
-
- if (!g_home_dir)
- g_home_dir = get_special_folder (CSIDL_PROFILE);
-
- if (!g_home_dir)
- g_home_dir = get_windows_directory_root ();
-#endif /* G_OS_WIN32 */
-
-#ifdef HAVE_PWD_H
- {
- struct passwd *pw = NULL;
- gpointer buffer = NULL;
- gint error;
- gchar *logname;
-
-# if defined (HAVE_POSIX_GETPWUID_R) || defined (HAVE_NONPOSIX_GETPWUID_R)
- struct passwd pwd;
-# ifdef _SC_GETPW_R_SIZE_MAX
- /* This reurns the maximum length */
- glong bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
-
- if (bufsize < 0)
- bufsize = 64;
-# else /* _SC_GETPW_R_SIZE_MAX */
- glong bufsize = 64;
-# endif /* _SC_GETPW_R_SIZE_MAX */
-
- logname = (gchar *) g_getenv ("LOGNAME");
-
- do
- {
- g_free (buffer);
- /* we allocate 6 extra bytes to work around a bug in
- * Mac OS < 10.3. See #156446
- */
- buffer = g_malloc (bufsize + 6);
- errno = 0;
-
-# ifdef HAVE_POSIX_GETPWUID_R
- if (logname) {
- error = getpwnam_r (logname, &pwd, buffer, bufsize, &pw);
- if (!pw || (pw->pw_uid != getuid ())) {
- /* LOGNAME is lying, fall back to looking up the uid */
- error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
- }
- } else {
- error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
- }
- error = error < 0 ? errno : error;
-# else /* HAVE_NONPOSIX_GETPWUID_R */
- /* HPUX 11 falls into the HAVE_POSIX_GETPWUID_R case */
-# if defined(_AIX) || defined(__hpux)
- error = getpwuid_r (getuid (), &pwd, buffer, bufsize);
- pw = error == 0 ? &pwd : NULL;
-# else /* !_AIX */
- if (logname) {
- pw = getpwnam_r (logname, &pwd, buffer, bufsize);
- if (!pw || (pw->pw_uid != getuid ())) {
- /* LOGNAME is lying, fall back to looking up the uid */
- pw = getpwuid_r (getuid (), &pwd, buffer, bufsize);
- }
- } else {
- pw = getpwuid_r (getuid (), &pwd, buffer, bufsize);
- }
- error = pw ? 0 : errno;
-# endif /* !_AIX */
-# endif /* HAVE_NONPOSIX_GETPWUID_R */
-
- if (!pw)
- {
- /* we bail out prematurely if the user id can't be found
- * (should be pretty rare case actually), or if the buffer
- * should be sufficiently big and lookups are still not
- * successfull.
- */
- if (error == 0 || error == ENOENT)
- {
- g_warning ("getpwuid_r(): failed due to unknown user id (%lu)",
- (gulong) getuid ());
- break;
- }
- if (bufsize > 32 * 1024)
- {
- g_warning ("getpwuid_r(): failed due to: %s.",
- g_strerror (error));
- break;
- }
-
- bufsize *= 2;
- }
- }
- while (!pw);
-# endif /* HAVE_POSIX_GETPWUID_R || HAVE_NONPOSIX_GETPWUID_R */
-
- if (!pw)
- {
- setpwent ();
- pw = getpwuid (getuid ());
- endpwent ();
- }
- if (pw)
- {
- g_user_name = g_strdup (pw->pw_name);
-
- if (pw->pw_gecos && *pw->pw_gecos != '\0')
- {
- gchar **gecos_fields;
- gchar **name_parts;
-
- /* split the gecos field and substitute '&' */
- gecos_fields = g_strsplit (pw->pw_gecos, ",", 0);
- name_parts = g_strsplit (gecos_fields[0], "&", 0);
- pw->pw_name[0] = g_ascii_toupper (pw->pw_name[0]);
- g_real_name = g_strjoinv (pw->pw_name, name_parts);
- g_strfreev (gecos_fields);
- g_strfreev (name_parts);
- }
-
- if (!g_home_dir)
- g_home_dir = g_strdup (pw->pw_dir);
- }
- g_free (buffer);
- }
-
-#else /* !HAVE_PWD_H */
-
-#ifdef G_OS_WIN32
- {
- guint len = UNLEN+1;
- wchar_t buffer[UNLEN+1];
-
- if (GetUserNameW (buffer, (LPDWORD) &len))
- {
- g_user_name = g_utf16_to_utf8 (buffer, -1, NULL, NULL, NULL);
- g_real_name = g_strdup (g_user_name);
- }
- }
-#endif /* G_OS_WIN32 */
-
-#endif /* !HAVE_PWD_H */
-
-#ifndef G_OS_WIN32
- if (!g_home_dir)
- g_home_dir = g_strdup (g_getenv ("HOME"));
-#endif
-
-#ifdef __EMX__
- /* change '\\' in %HOME% to '/' */
- g_strdelimit (g_home_dir, "\\",'/');
-#endif
- if (!g_user_name)
- g_user_name = g_strdup ("somebody");
- if (!g_real_name)
- g_real_name = g_strdup ("Unknown");
-
- {
-#ifndef G_OS_WIN32
- gboolean hostname_fail = (gethostname (hostname, sizeof (hostname)) == -1);
-#else
- DWORD size = sizeof (hostname);
- gboolean hostname_fail = (!GetComputerName (hostname, &size));
-#endif
- g_host_name = g_strdup (hostname_fail ? "localhost" : hostname);
- }
-
-#ifdef G_OS_WIN32
- g_tmp_dir_cp = g_locale_from_utf8 (g_tmp_dir, -1, NULL, NULL, NULL);
- g_user_name_cp = g_locale_from_utf8 (g_user_name, -1, NULL, NULL, NULL);
- g_real_name_cp = g_locale_from_utf8 (g_real_name, -1, NULL, NULL, NULL);
-
- if (!g_tmp_dir_cp)
- g_tmp_dir_cp = g_strdup ("\\");
- if (!g_user_name_cp)
- g_user_name_cp = g_strdup ("somebody");
- if (!g_real_name_cp)
- g_real_name_cp = g_strdup ("Unknown");
-
- /* home_dir might be NULL, unlike tmp_dir, user_name and
- * real_name.
- */
- if (g_home_dir)
- g_home_dir_cp = g_locale_from_utf8 (g_home_dir, -1, NULL, NULL, NULL);
- else
- g_home_dir_cp = NULL;
-#endif /* G_OS_WIN32 */
-}
-
-static inline void
-g_get_any_init (void)
-{
- if (!g_tmp_dir)
- g_get_any_init_do ();
-}
-
-static inline void
-g_get_any_init_locked (void)
-{
- G_LOCK (g_utils_global);
- g_get_any_init ();
- G_UNLOCK (g_utils_global);
-}
-
-
-/**
- * g_get_user_name:
- *
- * Gets the user name of the current user. The encoding of the returned
- * string is system-defined. On UNIX, it might be the preferred file name
- * encoding, or something else, and there is no guarantee that it is even
- * consistent on a machine. On Windows, it is always UTF-8.
- *
- * Returns: the user name of the current user.
- */
-G_CONST_RETURN gchar*
-g_get_user_name (void)
-{
- g_get_any_init_locked ();
- return g_user_name;
-}
-
-/**
- * g_get_real_name:
- *
- * Gets the real name of the user. This usually comes from the user's entry
- * in the <filename>passwd</filename> file. The encoding of the returned
- * string is system-defined. (On Windows, it is, however, always UTF-8.)
- * If the real user name cannot be determined, the string "Unknown" is
- * returned.
- *
- * Returns: the user's real name.
- */
-G_CONST_RETURN gchar*
-g_get_real_name (void)
-{
- g_get_any_init_locked ();
- return g_real_name;
-}