/* =============================================================================
* scpp_env.cpp
* Copyright (c) 2003 - 2011 Nomura Kei
* LICENSE :
* LGPL (GNU Lesser General General Public License - Version 3,29 June 2007)
* http://www.gnu.org/copyleft/lesser.html
* =============================================================================
*
* 環境変数操作
*
* 環境変数の値を取得/設定/削除します
*
*/
#include <iostream>
#include <cstdlib>
#include <scpp_os.hpp>
#include <scpp_errno.hpp>
#include <scpp_env.hpp>
namespace scpp
{
namespace Env
{
/// 環境変数用一時バッファサイズ (現状, Windows でのみ使用される)
const int SCPP_ENV_BUFFER_MAX = 4096;
/**
* 指定された name の環境変数を取得します.
* name に = が含まれる場合, = の前までをキーとして環境変数を検索します.
*
* 使用例)
* @code
* // sample.cpp
* #include <iostream>
* #include <scpp_env.hpp>
*
* int main(int argc, char* argv[])
* {
* std::string envVal;
* bool ret = scpp::env::getEnv(&envVal, "LANG");
* if (ret)
* {
* std::cout << "LANG=" << envVal << std::endl;
* }
* return 0;
* }
* -----
* $ g++ `scpp-config --cflags` -o sample sample.cpp `scpp-config --libs`
* $ LANG=C
* $ ./sample
* LANG=C
* @endcode
*
* @param buf 環境変数の値格納用文字バッファ
* @param name 環境変数
*/
bool getEnv(std::string* buf, const std::string& name)
{
// = より前までを nameKey に設定
std::string::size_type index = name.find("=");
std::string nameKey = (index == std::string::npos) ? name : name.substr(0, index);
#if (SCPP_IS_WINDOWS)
// for Windows
char tmpBuf[SCPP_ENV_BUFFER_MAX];
DWORD ret = GetEnvironmentVariable(nameKey.c_str(), (LPSTR) tmpBuf, sizeof(tmpBuf));
if (ret != 0)
{
*buf = tmpBuf;
return true;
}
*buf = "";
return false;
#else
// for not Windows
char* tmpBuf = getenv(nameKey.c_str());
if (tmpBuf != 0)
{
*buf = tmpBuf;
return true;
}
*buf = "";
return false;
#endif
}
/**
* 環境変数設定.
*
* name が存在しない場合, 環境変数 name に値 value を設定し,
* 環境に追加します. name が環境変数に存在する場合,
* overwrite が true ならば, その値を value に変更します.
* false ならば name の値を変更せず true を返します.
*
* name に '=' 文字が含まれている場合,
* エラー番号に SCPP_EINVAL を設定し, エラーを返します.
*
* 使用例)
* @code
* // sample.cpp
* #include <iostream>
* #include <scpp_env.hpp>
*
* int main(int argc, char* argv[])
* {
* bool ret = scpp::env::setEnv("LANG", "C");
* if (ret)
* {
* std::string envVal;
* scpp::env::getEnv(&envVal, "LANG", true);
* std::cout << "LANG=" << envVal << std::endl;
* }
* return 0;
* }
* -----
* $ g++ `scpp-config --cflags` -o sample sample.cpp `scpp-config --libs`
* $ ./sample
* LANG=C
* @endcode
*
* @param name 環境変数名
* @param value 値
* @param overwrite true/false (上書きする/しない)
* @return true/false (設定成功/失敗)
*/
bool setEnv(const std::string& name, const std::string& value, bool overwrite)
{
#if (SCPP_IS_WINDOWS)
// for Windows
std::string::size_type index = name.find("=");
if (index != std::string::npos)
{ // = が含まれる
Errno::setError(SCPP_EINVAL);
return false;
}
// name が既に存在するか確認
LPSTR buf[1];
DWORD ret = GetEnvironmentVariable(name.c_str(), (LPSTR) buf, 1);
if ((!overwrite) && (ret != 0))
{ // 上書きしない場合, 既に環境変数にある -> true
return true;
}
// 環境変数を設定する
ret = SetEnvironmentVariable(name.c_str(), value.c_str());
return (ret != 0);
#else
// for Windows 以外
// = が含まれている場合, setenv 内でエラーになる
int ret = setenv(name.c_str(), value.c_str(), overwrite);
return (ret == 0);
#endif
}
/**
* 環境変数 name を環境から削除します.
*
* @param name 環境変数名
* @return true/false (削除成功/失敗)
*/
bool unsetEnv(const std::string& name)
{
#if (SCPP_IS_WINDOWS)
// for Windows
BOOL ret = SetEnvironmentVariable(name.c_str(), 0);
return (ret != 0);
#else
// for Windows 以外
int ret = unsetenv(name.c_str());
return (ret == 0);
#endif
}
} // namespace Env
} // namespace scpp