/* vim: ts=4 sw=4 sts=4 ff=unix fenc=utf-8 :
 * =====================================================================
 *  sc_env.c
 *  Copyright (c)  2003 - 2011  sys0tem
 *  LICENSE :
 *	LGPL (GNU Lesser General Public License - Version 3,29 June 2007)
 *	http://www.gnu.org/copyleft/lesser.html
 *	or
 *	EPL (Eclipse Public License - v1.0)
 *	http://www.eclipse.org/legal/epl-v10.html
 * =====================================================================
 */
#include <string.h>

#include <sc_os.h>
#include <sc_error.h>
#include <sc_env.h>

#if (SC_isWindows)
#include <windows.h>
#endif
#define SC_ENV_BUFFER_MAX (4096)


/**
 * 指定された name の環境変数を取得します。
 * name に = が含まれている場合、= の前までを
 * キーとして環境変数を検索します。
 *
 * @param name 環境変数名
 * @return 値
 */
char* SC_getenv(const char* name)
{
	char keyName[SC_ENV_BUFFER_MAX];
	int  ptr = 0;

	/* = の前までをキーとする		*/
	while ((name[ptr] != '\0') && (ptr < (SC_ENV_BUFFER_MAX - 1)))
	{
		if (name[ptr] == '=')
		{
			break;
		}
		keyName[ptr] = name[ptr];
		ptr++;
	}
	keyName[ptr] = '\0';

#if (SC_isWindows)
	{
		DWORD ret;
		static char buff[SC_ENV_BUFFER_MAX];

		ret = GetEnvironmentVariable(keyName, (LPSTR) buff, sizeof(buff));
		if (ret == 0)
		{
			return NULL;
		}
		return buff;
	}
#else
	return getenv(keyName);
#endif
}

/**
 * nameが存在しない場合、環境変数 name に値 value を設定し、
 * 環境に追加します。name が環境変数に存在する場合、
 * overwriteが true ならばその値を value に変更します。
 * false ならば name の値を変更せず true を返します。
 * name に '=' 文字が含まれている場合、
 * エラー番号に SC_EINVALを設定し、エラーを返します。
 *
 * @param name      環境変数名
 * @param value     値
 * @param overwrite true/false (上書きする/しない)
 * @return true/false (成功/失敗)
 */
bool SC_setenv(const char* name, const char* value, bool overwrite)
{
#if (SC_isWindows)
	DWORD ret;
	LPSTR buff[1];
	/* = が含まれている場合はエラー	*/
	const char* ptr = name;
	while (*ptr != '\0')
	{
		if (*ptr == '=')
		{
			SC_setError(SC_EINVAL);
			return false;
		}
		ptr++;
	}

	/* name が既に存在するかチェック	*/
	ret = GetEnvironmentVariable(name, (LPSTR) buff, 1);
	if ((!overwrite) && (ret != 0))
	{	/* 上書きしない場合、既に環境変数にある->true */
		if (ret != 0)
		{	/* 既に環境変数に存在する	*/
			return true;
		}
	}

	/* 環境変数を設定する				*/
	ret = SetEnvironmentVariable(name, value);
	if (ret != 0)
	{	/* 成功	*/
		return true;
	}
	return false;
#else
	int ret = setenv(name, value, overwrite);
	if (ret == 0)
	{	/* 成功	*/
		return true;
	}
	return false;
#endif
}


/**
 * 変数 name を環境から削除します。
 *
 * @param name 環境変数名
 * @return true/false (成功/失敗)
 */
bool SC_unsetenv(const char* name)
{
#if (SC_isWindows)
	BOOL ret = SetEnvironmentVariable(name, NULL);
	if (ret != 0)
	{	/* 成功	*/
		return true;
	}
	return false;
#else
	int ret = unsetenv(name);
	if (ret == 0)
	{	/* 成功	*/
		return true;
	}
	return false;
#endif
}

