Re: g_setenv g_unsetenv

George <jirka 5z com> writes:

> On Wed, Sep 06, 2000 at 12:37:39PM +0200, Tim Janik wrote:
> > > I think this should go into glib and I'd be willing to write it.  Now the
> > > question is, would it be accepted?
> > 
> > i'd love to see portable versions for this.
> Here's what I have after about an hour of research.  First after looking and
> seeing that while putenv is on most systems, it works somewhat differently, I
> started implementing a scheme that something like "screen" uses.  That is on
> first g_putenv (or whatever it would be named), the entire environment is
> copied onto the heap.  Then we can do good memory management upon it.  Then
> it hit me.  If another part of the program did a putenv, we'd get majorly
> screwed, so I think that approach is too fragile.  Another approach might be
> keeping some bookkeeping information, however, I'm not sure that the cost of
> this is actually worth plugging the leaks which are not too bad.  So I
> decided that on systems without setenv, g_setenv would just leak each time
> you do it, that's the only sane / portable way to get this to work
> apparently.  The other problem is unsetenv.  Different systems with putenv
> seem to handle it differently, namely either putenv("name") or
> putenv("name="), if they handle the case at all.  It's however quite easy to
> implement unsetenv by hand by just twiddling the "environ" global (which
> should be standard C as far as I know).  In fact as far as I could tell, the
> only ANSI-C parts are the environ, and getenv.  So apparently there could be
> systems out there that do not have setenv nor putenv. 

putenv is POSIX so I think we can assume it on all Unixish platforms.

Also, I think twiddling environ is dangerous, neither ANSI nor POSIX
nor anything else guarantees that modifying environ will result in
those changes propogating to child processes. I think a configure
check should be able to determine if putenv("name=") or putenv
("name") is the right thing.

> So I intend to write
> support for those as well.  Well here's my current stab at it (doesn't
> include windows stuff as apparently it would need to use some windows
> specific functions, but as far as I could tell those should be in the spirit
> of setenv, also this is not tested at all, just posted here as food for
> thought):
> gint
> g_setenv (const gchar *name, const gchar *value, gboolean overwrite)
> {
> #if defined(HAVE_SETENV)
>   return setenv (name, value, overwrite);
> #elif defined(G_OS_WIN32)
>   /* FOO */

Should probably not even define the function in this case, I think.

> #else
>   gchar *string;
>   if ( ! overwrite &&
>       g_getenv (name) != NULL)
>     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 (name, '=', value, NULL);

You mean "=", not '='

>   return putenv (string);
> #endif
> }
> /* We will need this for unsetenv if there
>  * is no unsetenv */
> #if !defined(HAVE_SETENV) && !defined(G_OS_WIN32)
> extern gchar **environ;
> #endif
> void
> g_unsetenv (const gchar *name)
> {
> #if defined(HAVE_SETENV)
>   unsetenv (name);
> #elif defined(G_OS_WIN32)
>   /* FOO */
> #else
>   gint i;
>   gint len;
>   len = strlen (name);
>   /* Mess directly with the environ array, apparently
>    * this seems to be the only portable way to do this */

As I said above, I'd suggest using putenv if available.

>   for (i = 0; environ[i] != NULL; i++)
>     {
>       if (strncmp (environ[i], name, len) == 0 &&
> 	  environ[i][len + 1] == '=')
> 	break;
>     }
>   while (environ[i] != NULL)
>     {
>       environ[i] = environ[i + 1];
>       i++;
>     }
> #endif
> }
> Now the question is, how far should this be taken.  Do we want book keeping?
> Or do we just accept memleaks.  Note that bookkeeping will never be perfect
> if intermixed with normal setenv, putenv calls, and may be more expensive
> then the memleaks.

Well you can never guarantee that some library out there won't call
setenv() or putenv(), it's probably safer not to leak.

 - Maciej

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]