Re: g_setenv g_unsetenv
- From: George <jirka 5z com>
- To: Tim Janik <timj gtk org>
- Cc: Gtk+ Developers <gtk-devel-list gnome org>
- Subject: Re: g_setenv g_unsetenv
- Date: Thu, 7 Sep 2000 17:56:32 -0700
OK, here's a patch. It does a putenv dance for everything and doesn't
twiddle 'environ'. I've also added some test code to testglib.c. There is
also some Win32 code which I did according to MS docs, but not sure if it's
correct as I couldn't even compile it of course. Now in case we're not on
Win32 and putenv is not available, the functions are no-ops. Unsetenv of
course only works if putenv can remove variables. Also note that
g_setenv ("FOO", "", TRUE); on a sunbox is equivalent to g_unsetenv ("FOO");
due to the way putenv works there (apparently). Somewhere putenv ("VAR")
removes variables, somewhere it's putenv ("VAR="). But POSIX says nothing of
the sort. In fact according to POSIX I couldn't find a good way to unset a
variable. Well in the worst case the VAR will not be removed but set to
an empty string, which is the next best thing.
George
--
George <jirka 5z com>
Originality is undetected plagiarism.
-- Dean W. R. Inge
Index: configure.in
===================================================================
RCS file: /cvs/gnome/glib/configure.in,v
retrieving revision 1.140
diff -u -p -r1.140 configure.in
--- configure.in 2000/09/06 15:01:03 1.140
+++ configure.in 2000/09/08 00:52:30
@@ -221,7 +221,7 @@ AC_HEADER_STDC
# Checks for library functions.
AC_FUNC_VPRINTF
-AC_CHECK_FUNCS(atexit on_exit)
+AC_CHECK_FUNCS(atexit on_exit setenv unsetenv putenv)
AC_CHECK_SIZEOF(char)
AC_CHECK_SIZEOF(short)
Index: glib.h
===================================================================
RCS file: /cvs/gnome/glib/glib.h,v
retrieving revision 1.196
diff -u -p -r1.196 glib.h
--- glib.h 2000/09/07 23:08:25 1.196
+++ glib.h 2000/09/08 00:52:31
@@ -1788,6 +1788,20 @@ gchar* g_path_get_dirname (const gchar *
/* return the environment string for the variable. The returned memory
* must not be freed. */
gchar* g_getenv (const gchar *variable);
+/* Set an environment variable. if 'overwrite' is false and
+ * variable already exists, then nothing happens, returns 0
+ * on success, -1 on error. Note that it may call putenv
+ * and leak memory if setenv doesn't exist on a system.
+ * Thus you should never use this in a loop or anywhere
+ * where leaks are a problem. */
+gint g_setenv (const gchar *variable,
+ const gchar *value,
+ gboolean overwrite);
+/* Unset an environment variable. This function may not
+ * be 100% reliable on systems with no unsetenv and a
+ * broken putenv implementation. It could also leak
+ * memory on such broken systems. */
+void g_unsetenv (const gchar *variable);
/* we use a GLib function as a replacement for ATEXIT, so
* the programmer is not required to check the return value
Index: gutils.c
===================================================================
RCS file: /cvs/gnome/glib/gutils.c,v
retrieving revision 1.67
diff -u -p -r1.67 gutils.c
--- gutils.c 2000/09/07 23:08:25 1.67
+++ gutils.c 2000/09/08 00:52:32
@@ -540,6 +540,130 @@ g_getenv (const gchar *variable)
#endif
}
+G_LOCK_DEFINE_STATIC (g_setenv_global);
+
+/* Setting environment, much hairier if setenv is not present. */
+gint
+g_setenv (const gchar *variable, const gchar *value, gboolean overwrite)
+{
+ g_return_val_if_fail (variable != NULL, -1);
+ g_return_val_if_fail (value != NULL, -1);
+
+#if defined(HAVE_SETENV)
+ return setenv (variable, value, overwrite);
+#elif defined(G_OS_WIN32)
+ {
+ gboolean return_value;
+
+ G_LOCK (g_setenv_global);
+
+ if ( ! overwrite &&
+ g_getenv (variable) != NULL)
+ {
+ G_UNLOCK (g_setenv_global);
+ return 0;
+ }
+
+ return_value = SetEnvironmentVariable (variable, value);
+
+ G_UNLOCK (g_setenv_global);
+
+ return return_value ? 0 : -1;
+#elif defined(HAVE_PUTENV)
+ {
+ gchar *string;
+ gint return_value;
+
+ G_LOCK (g_setenv_global);
+
+ if ( ! overwrite &&
+ g_getenv (variable) != NULL)
+ {
+ G_UNLOCK (g_setenv_global);
+ return 0;
+ }
+
+ /* A leak. But there is absolutely no apparent
+ * way to get around this other then an incredible
+ * mess with the environ variable */
+ string = g_strconcat (variable, "=", value, NULL);
+ return_value = putenv (string);
+
+ /* If things went bad, we can safely free the string
+ * as it's not in the environment */
+ if (return_value < 0)
+ g_free (string);
+
+ G_UNLOCK (g_setenv_global);
+
+ return return_value;
+ }
+#else
+ /* no putenv, no setenv, no nuthin' */
+ return -1;
+#endif
+}
+
+void
+g_unsetenv (const gchar *variable)
+{
+ g_return_if_fail (variable != NULL);
+
+#if defined(HAVE_UNSETENV)
+ unsetenv (variable);
+#elif defined(G_OS_WIN32)
+ SetEnvironmentVariable (variable, NULL);
+#elif defined(HAVE_PUTENV)
+ {
+ char *string;
+
+ /* Things "could" go mucho wrong if variable
+ * includes a '=' */
+ g_return_if_fail (strchr (variable, '=') == NULL);
+
+ G_LOCK (g_setenv_global);
+
+ /* To avoid unneccesary leaks, etc,
+ * check if it's even there */
+ if (g_getenv (variable) == NULL)
+ {
+ G_UNLOCK (g_setenv_global);
+ return;
+ }
+
+ /* Possible leak. If neither putenv ("VAR")
+ * nor putenv ("VAR=") kill the environ variable,
+ * then our string would end up in the
+ * environment itself */
+ string = g_strdup (variable);
+ if (putenv (string) < 0)
+ {
+ g_free (string);
+ string = g_strconcat (variable, "=", NULL);
+ if (putenv (string) < 0)
+ {
+ /* We can safely free the string as
+ * things just plain went wrong */
+ g_free (string);
+ string = NULL;
+ }
+ }
+
+ /* if the variable is not in the evnironment,
+ * then putenv worked and got rid of it. And
+ * we can safely free string */
+ if (string != NULL &&
+ g_getenv (variable) == NULL)
+ g_free (string);
+
+ G_UNLOCK (g_setenv_global);
+ }
+#else
+ /* no putenv, no unsetenv, no nuthin' */
+ return;
+#endif
+}
+
G_LOCK_DEFINE_STATIC (g_utils_global);
Index: testglib.c
===================================================================
RCS file: /cvs/gnome/glib/testglib.c,v
retrieving revision 1.38
diff -u -p -r1.38 testglib.c
--- testglib.c 2000/09/07 23:08:25 1.38
+++ testglib.c 2000/09/08 00:52:32
@@ -398,6 +398,32 @@ main (int argc,
if (n_dirname_checks)
g_print ("ok\n");
+ {
+ gboolean env_ok = TRUE;
+
+ g_print ("checking g_setenv/g_unsetenv...");
+ if (g_setenv ("GLIB_TESTING", "FOO", TRUE) < 0)
+ {
+ g_print ("\nfailed to set GLIB_TESTING to \"FOO\"\n");
+ env_ok = FALSE;
+ }
+ if (g_getenv ("GLIB_TESTING") == NULL ||
+ strcmp (g_getenv ("GLIB_TESTING"), "FOO") != 0)
+ {
+ g_print ("\nfailed, GLIB_TESTING is not set or not set to \"FOO\"\n");
+ env_ok = FALSE;
+ }
+ g_unsetenv ("GLIB_TESTING");
+ if (g_getenv ("GLIB_TESTING") != NULL)
+ {
+ g_print ("\nfailed, unsetenv failed\n");
+ env_ok = FALSE;
+ }
+
+ if (env_ok)
+ g_print ("ok\n");
+ }
+
g_print ("checking doubly linked lists...");
list = NULL;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]