blob: 661efb88f6286588d3b56126103200ebdf983ba5 [file] [log] [blame]
/************************************************************************
*
* environ.cpp - definitions of testsuite helpers
*
* $Id$
*
************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 2001-2006 Rogue Wave Software.
*
**************************************************************************/
// expand _TEST_EXPORT macros
#define _RWSTD_TEST_SRC
#include <environ.h>
#include <assert.h> // for assert
#include <stdlib.h> // for getenv, malloc, putenv
#include <string.h> // for strchr, strlen, ...
extern "C" {
// char** environ;
#ifndef _RWSTD_NO_PUTENV_CONST_CHAR
_RWSTD_DLLIMPORT int putenv (const char*) _LIBC_THROWS ();
#else // if defined (_RWSTD_NO_PUTENV_CONST_CHAR)
_RWSTD_DLLIMPORT int putenv (char*) _LIBC_THROWS ();
#endif // _RWSTD_NO_PUTENV_CONST_CHAR
#ifdef _RWSTD_NO_UNSETENV
# ifndef _RWSTD_NO_UNSETENV_IN_LIBC
_RWSTD_DLLIMPORT int unsetenv (const char*) _LIBC_THROWS ();
# undef _RWSTD_NO_UNSETENV
# endif // _RWSTD_NO_UNSETENV_IN_LIBC
#endif // _RWSTD_NO_UNSETENV
} // extern "C"
// sets (or unsets) one or more sep-separated environment variables
_TEST_EXPORT int
rw_putenv (const char* str, int sep /* = -1 */)
{
int nset = 0;
int ret = 0;
if (!str) {
str = getenv ("RW_PUTENV");
if (str)
sep = *str++;
else
return 0;
}
// set separator to NUL if it's invalid
if (sep < 0 || int (_RWSTD_UCHAR_MAX) < sep)
sep = 0;
for (const char *pvar = str; pvar && *pvar; ++nset) {
// look for separator (or the terminating NUL by default)
const char *pend = strchr (pvar, sep);
if (0 == pend)
pend = pvar + strlen (pvar);
const size_t varlen = pend - pvar;
char* const envvar = (char*)malloc (pend - pvar + 1);
if (0 == envvar)
return -1;
memcpy (envvar, pvar, varlen);
envvar [varlen] = '\0';
// look for the first equals sign
const char* const equals = strchr (envvar, '=');
char *var = 0;
if (equals) {
// add the variable to the environment or modify it if
// it's already defined
// Note: calling Solaris 7 putenv() during program startup
// (i.e., from ctors of namespace-scope objects) prevents
// getenv() from finding that variable at program runtime
ret = putenv (envvar);
// determine wheteher putenv() made copy of the variable
// or if it simply used the pointer passed to it; if the
// former, deallocate the buffer dynamically allocated
// above
char namebuf [256];
assert (size_t (equals - envvar) < sizeof namebuf);
memcpy (namebuf, envvar, equals - envvar);
namebuf [equals - envvar] = '\0';
var = getenv (namebuf);
if (equals + 1 != var)
free (envvar);
}
else if ((var = getenv (envvar))) {
// try to remove variable from the environment
#ifndef _RWSTD_NO_UNSETENV
# if defined (_RWSTD_OS_FREEBSD) || defined (_RWSTD_OS_DARWIN)
// FreeBSD (and Darwin) declares void unsetenv(const char*)
// http://www.freebsd.org/cgi/man.cgi?query=unsetenv&sektion=3
unsetenv (envvar);
ret = 0;
# else // !FreeBSD ...
ret = unsetenv (envvar);
# endif // FreeBSD ...
#else // ifdef _RWSTD_NO_UNSETENV
ret = putenv (envvar);
#endif // _RWSTD_NO_UNSETENV
if (0 == ret) {
// see if the variable has been removed
var = getenv (envvar);
if (var) {
// if not, zero-out the first byte of its name
// FIXME: make this more robust, e.g., by calling
// unsetenv() when provided or by manipulating
// the environment directly
*(var - 1 - varlen) = '\0';
#if 0 // disabled
char **penv = environ;
if (penv) {
while (*penv && *penv != (var - 1 - varlen))
++penv;
while (*penv)
*penv = penv [1];
}
#endif // 0/1
}
}
free (envvar);
}
pvar = pend + !!*pend;
}
if (1 == nset)
return ret;
return nset;
}