Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

EnvVars.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2005 Novell, Inc. All rights reserved.
00003 *
00004 * Redistribution and use in source and binary forms, with or without
00005 * modification, are permitted provided that the following conditions are met:
00006 *
00007 *  - Redistributions of source code must retain the above copyright notice,
00008 *    this list of conditions and the following disclaimer.
00009 *
00010 *  - Redistributions in binary form must reproduce the above copyright notice,
00011 *    this list of conditions and the following disclaimer in the documentation
00012 *    and/or other materials provided with the distribution.
00013 *
00014 *  - Neither the name of Novell, Inc., nor the names of its
00015 *    contributors may be used to endorse or promote products derived from this
00016 *    software without specific prior written permission.
00017 *
00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 * ARE DISCLAIMED. IN NO EVENT SHALL Novell, Inc., OR THE 
00022 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00023 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
00024 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
00025 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00026 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
00027 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
00028 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 *******************************************************************************/
00030 
00035 #include "blocxx/BLOCXX_config.h"
00036 #include "blocxx/EnvVars.hpp"
00037 
00038 #include <algorithm>
00039 #include <cstring>
00040 
00041 #if defined(OW_DARWIN)
00042 // On MacOSX, environ is not defined in shared libraries.  It is only provided
00043 // for executables.  Since the linker must resolve all symbols at link time,
00044 // the normal extern declaration of environ won't work.  As a substitute, we
00045 // need to use this:
00046 #include <crt_externs.h>
00047 #define environ (*_NSGetEnviron())
00048 
00049 // For more details on the subject, follow one of these links:
00050 // http://lists.gnu.org/archive/html/bug-guile/2004-01/msg00013.html
00051 // http://lists.apple.com/archives/darwin-dev/2005/Mar/msg00132.html
00052 // http://www.metapkg.org/wiki/15 (under the linking problems)
00053 
00054 #else /* !DARWIN */
00055 // according to man environ:
00056 // This variable must be declared in the user program, but is
00057 // declared in the header file unistd.h in case the header files came from
00058 // libc4 or libc5, and in case they came from glibc and _GNU_SOURCE was
00059 // defined.
00060 extern char** environ;
00061 #endif
00062 
00063 namespace BLOCXX_NAMESPACE
00064 {
00065 
00066 namespace
00067 {
00068 
00069 void getKeyValue(
00070    const char *const strArg, 
00071    String& key, 
00072    String& value)
00073 {
00074    key.erase();
00075    value.erase();
00076 
00077    const char* p = ::strchr(strArg, '=');
00078    if(p)
00079    {
00080       key = String(strArg, size_t(p-strArg));
00081       value = p+1;
00082    }
00083 }
00084 
00085 inline bool isValidKey(const String &key)
00086 {
00087     //
00088     // SUSv3 specifies that the setenv() function shall fail,
00089     // if the environment variable name is NULL, empty or
00090     // contains a '=' character:
00091     //
00092     return key.length() && key.indexOf('=') == String::npos;
00093 }
00094 
00095 }  // End of anonymous namespace
00096 
00098 EnvVars::EnvVars(EEnvVarFlag flag)
00099    : m_envMap()
00100    , m_envp(0)
00101 {
00102    if(flag == E_CURRENT_ENVIRONMENT)
00103    {
00104       fillEnvMap(environ, m_envMap);
00105    }
00106 }
00107 
00109 EnvVars::EnvVars(const char* const envp[])
00110    : m_envMap()
00111    , m_envp(0)
00112 {
00113    fillEnvMap(envp, m_envMap);
00114 }
00115 
00117 EnvVars::~EnvVars()
00118 {
00119    deleteEnvp();
00120 }
00121 
00123 // STATIC
00124 void 
00125 EnvVars::fillEnvMap(EnvMap& envMap)
00126 {
00127    fillEnvMap(environ, envMap);
00128 }
00129 
00131 // STATIC
00132 void 
00133 EnvVars::fillEnvMap(const char* const envp[], EnvMap& envMap)
00134 {
00135    envMap.clear();
00136    String key, value;
00137    for(size_t i = 0; envp[i]; i++)
00138    {
00139       getKeyValue(envp[i], key, value);
00140       if(isValidKey(key))
00141       {
00142          envMap[key] = value;
00143       }
00144    }
00145 }
00146 
00148 void 
00149 EnvVars::deleteEnvp() const
00150 {
00151    if(m_envp)
00152    {
00153       int i;
00154    
00155       // Delete all char pointers env var array
00156       for(i = 0; m_envp[i]; i++)
00157       {
00158          // m_envp[i] may be null if deleteEnvp was called because an
00159          // exception was caught while trying to allocate the array
00160          // in getenvp()
00161          delete [] m_envp[i];
00162       }
00163 
00164       delete [] m_envp;    // Delete pointer array
00165       m_envp = 0;
00166    }
00167 }
00168 
00170 String 
00171 EnvVars::getValue(const String& key, 
00172    const String& notFoundRetVal) const
00173 {
00174    EnvMap::const_iterator it = m_envMap.find(key);
00175    return (it != m_envMap.end()) ? it->second : notFoundRetVal;
00176 }
00177 
00179 const char* const* 
00180 EnvVars::getenvp() const
00181 {
00182    if(!m_envp)
00183    {
00184       int i;
00185       m_envp = new char* [m_envMap.size()+1];
00186       std::fill(m_envp, m_envp+m_envMap.size()+1, (char*)0);
00187       try
00188       {
00189          EnvMap::const_iterator it = m_envMap.begin();
00190          for(i = 0; it != m_envMap.end(); i++, it++)
00191          {
00192             size_t klen = it->first.length();
00193             size_t vlen = it->second.length();
00194 
00195             m_envp[i] = new char[klen + vlen + 2];
00196             ::strcpy(m_envp[i], it->first.c_str());
00197             m_envp[i][klen] = '=';
00198             ::strcpy(m_envp[i]+klen+1, it->second.c_str());
00199          }
00200       }
00201       catch(...)
00202       {
00203          deleteEnvp();  // Delete what has been allocated thus far.
00204          throw;         // Re-throw this exception
00205       }
00206    }
00207 
00208    return m_envp;
00209 }
00210 
00212 bool 
00213 EnvVars::removeVar(const String& varName)
00214 {
00215    bool cc = false;
00216    EnvMap::iterator it = m_envMap.find(varName);
00217    if (it != m_envMap.end())
00218    {
00219       cc = true;
00220       deleteEnvp();
00221       m_envMap.erase(it);
00222    }
00223 
00224    return cc;
00225 }
00226 
00228 bool 
00229 EnvVars::addVar(const String& name, const String& value)
00230 {
00231    bool cc = false;
00232    if(isValidKey(name) && m_envMap.find(name) == m_envMap.end())
00233    {
00234       cc = true;
00235       deleteEnvp();
00236       m_envMap[name] = value;
00237    }
00238    return cc;
00239 }
00240 
00242 bool 
00243 EnvVars::setVar(const String& key, const String& value)
00244 {
00245    bool cc = false;
00246    if( isValidKey(key))
00247    {
00248       cc = true;
00249       deleteEnvp();
00250       m_envMap[key] = value;
00251    }
00252    return cc;
00253 }
00254 
00256 bool 
00257 EnvVars::setVar(const String& keyValue)
00258 {
00259    String key, value;
00260    getKeyValue(keyValue.c_str(), key, value);
00261    return setVar(key, value);
00262 }
00263 
00265 bool 
00266 EnvVars::updateVar(const String& name, const String& value)
00267 {
00268    bool cc = false;
00269    EnvMap::iterator it = m_envMap.find(name);
00270    if (it != m_envMap.end())
00271    {
00272       cc = true;
00273       deleteEnvp();
00274       it->second = value;
00275    }
00276 
00277    return cc;
00278 }
00279 
00280 }  // End of BLOCXX_NAMESPACE

Generated on Mon Sep 12 23:56:34 2005 for blocxx by  doxygen 1.4.4