FCGI_Accept versus setenv, unsetenv, and putenv

Mark Brown (mbrown@OpenMarket.com)
Mon, 13 May 1996 16:15:07 -0400

Message-Id: <199605132015.QAA17833@breckenridge.openmarket.com>
To: fastcgi-developers@OpenMarket.com
Subject: FCGI_Accept versus setenv, unsetenv, and putenv
Date: Mon, 13 May 1996 16:15:07 -0400
From: Mark Brown <mbrown@OpenMarket.com>

The fcgi_stdio library is not designed for use with setenv(2),
unsetenv(2), and putenv(2).

FCGI_Accept assigns a new value to environ.  It also retains
a copy of this value.  On the next call to FCGI_Accept,
this storage pointed to by this value is freed.

If you call setenv, unsetenv, or putenv, it is pretty unlikely
that the right thing will happen when FCGI_Accept goes to free
"its" storage.

You can argue that this is a crock, that FCGI_Accept should
retain a list of the variables it has bound and then unsetenv
each one on the next call.  That might be better.  But it doesn't
work that way today.

If you want to use setenv and its friends, here is one
way to go:

  Wrap FCGI_Accept like this:

  extern char **environ;
  static char **reqEnv;

  static int My_FCGI_Accept(void) {
      char **tmp = environ;
      int status = FCGI_Accept();
      reqEnv = environ;
      environ = tmp;
      return status;

The net effect of this is to give you a version of FCGI_Accept
that doesn't modify environ, and returns the request
environment in the variable reqEnv.

Now you are free to use setenv, unsetenv, and putenv to your heart's
content.  But you can't access the *request* environment with getenv
unless you putenv each element of the request environment first.
You can use FCGX_GetParam to access reqEnv directly, or write
your own.

The storage pointed to by reqEnv belongs to FCGI_Accept;
don't retain any pointers to it, and don't free() it.  Beware of
storage leaks; if you do a putenv during a request, most likely you
should do a corresponding unsetenv at the end of the request.
I recommend the use of Purify on this sort of code!