views:

225

answers:

1

Hi,

In my application, I need direct access to the _environ variable because I must have something like the glibc unsetenv (you cannot have that with setenv or putenv).

This is the code I need to use:

//////////////////////
// unsetenv for WIN32, taken from libc source
int unsetenv(const char *name)
{
  size_t len;
  char **ep;

  if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
    {
      return -1;
    }

  len = strlen (name);

  ep = _environ;
  while (*ep != NULL)
    if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
      {
    /* Found it.  Remove this pointer by moving later ones back.  */
    char **dp = ep;

    do
      dp[0] = dp[1];
    while (*dp++);
    /* Continue the loop in case NAME appears again.  */
      }
    else
      ++ep;

  return 0;
}

It has worked fine until we got some problems with manifests on some systems, so we tried to use the static version of the runtime library (/MT flag).

Now, I am getting this error:

unresolved external symbol __environ

I read here and at many other places that this variable has become obsolete and deprecated. I wonder about the possible solution. I also cannot use the _wenviron variable because we want to support Windows 98.

In the project settings, I explicitely set it to use MBCS (i.e., not Unicode). I am a bit stumbled here. Is there anything else I must set?

Just for testing, I also tried the Unicode version. I.e. this code:

int unsetenv(const wchar_t *name)
{
  size_t len;
  wchar_t **ep;

  if (name == NULL || *name == '\0' || wcschr (name, '=') != NULL)
    {
      return -1;
    }

  len = wcslen (name);

  ep = _wenviron;
  while (*ep != NULL)
    if (!wcsncmp (*ep, name, len) && (*ep)[len] == '=')
      {
    /* Found it.  Remove this pointer by moving later ones back.  */
    wchar_t **dp = ep;

    do
      dp[0] = dp[1];
    while (*dp++);
    /* Continue the loop in case NAME appears again.  */
      }
    else
      ++ep;

  return 0;
}

I wonder a bit why that even compiled because I explicitly have set it to use MBCS and not Unicode. But maybe that means something else. (Can somebody enlighten me here?)

Anyway, this results in these errors:

1>AuxLib.obj : error LNK2001: unresolved external symbol __wenviron
1>ExtractInfo.obj : error LNK2001: unresolved external symbol __environ

AuxLib.obj is the file with this unsetenv(). So one error more than before.

A: 

I'm not sure I understand, what's wrong with getenv_s()? It is the function equivalent of the global variable __environ. It is multibyte, not unicode, so it should work fine on all platforms targetted by the VS 2005 compiler. the "_s" means "safe", meaning the operation was re-designed to reduce exploitability by hackers via buffer overflows, etc.

David Gladfelter
I must that code above to work. That code will overwrite the memory where _environ is pointing to. There is no MSVC function I know about which can do that.
Albert
The OP is trying to delete an environment variable from the globally-shared libc variable. I don't know of a library function that performs that operation for the OP, and it would be nice as it could do so in a thread-safe manner.
Heath Hunnicutt
Sorry, I see that now. From what I've seen, the only reliable way to delete an environment variable is to use the Win32 function SetEnvironmentVariable and pass a NULL for the value. This API is only supported on Windows 2000 and above.
David Gladfelter
And what can I do if I want to have it working on Win98 and above?
Albert
According to the VS 2008 documentation, the requirements for SetEnvironmentVariable are:Client: Requires Windows Vista, Windows XP, Windows 2000 Professional, Windows NT Workstation, Windows Me, Windows 98, or Windows 95.MSDN probably is reflecting discontinued support for Windows 98.
MSN
Ah thanks for the information. That would then solve at least this code part. But it seems I got some more similar problems in other files (where I don't even have the source code, only a binary lib-file).
Albert