Newer
Older
libkc / modules / src / kc_env.c
/**
 * @file  kc_env.c
 * @brief 環境変数 モジュール
 * @copyright  2003 - 2023  Nomura Kei
 */
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <kc.h>
#include <kc_env.h>

// Windows 環境変数の最大長は 327676
#define KC_ENV_BUFFER_MAX (32767)

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

	char *tmp_ptr = strstr(name, "=");
	if (tmp_ptr)
	{ // = が含まれる。
		size_t len = (size_t)(tmp_ptr - name);
		if (len < KC_ENV_BUFFER_MAX)
		{
			tmp_ptr = NULL;
			strncpy(tmp_buff, name, len);
		}
		else
		{
			tmp_ptr = (char *)malloc(len + 1);
			strncpy(tmp_ptr, name, len + 1);
			tmp_ptr[len] = '\0';
			key_name = tmp_ptr;
		}
	}
	else
	{
		key_name = name;
	}

	char *result = NULL;
#if (KC_IS_WINDOWS)
	static char buff[KC_ENV_BUFFER_MAX];
	DWORD ret = GetEnvironmentVariable(key_name, buff, sizeof(buff));
	if (ret != 0)
	{
		result = buff;
	}
#else
	result = getenv(key_name);
#endif
	// malloc でメモリを確保している場合、解放する。
	// ※確保していない場合、tmp_ptr = NULL のため、free(NULL) となり副作用なし
	free(tmp_ptr);
	return result;
}

/**
 * 指定された name の環境変数が存在しない場合、
 * 環境変数 name に指定された値 value を設定します。
 * overwrite が true ならばその値を value に変更します。
 * false ならば name の値を変更せず、true を返します。
 * name に '=' 文字が含まれている場合、設定に失敗し、false を返します。
 *
 * @param name 環境変数名
 * @param value 設定する環境変数の値
 * @param overwrite true/false (上書きする/しない)
 * @return true/false (設定成功/失敗)
 */
bool KcEnv_set(const char *name, const char *value, bool overwrite)
{
#if (KC_IS_WINDOWS)
	// = が含まれている場合はエラー
	char *ptr = strstr(name, "=");
	if (ptr == NULL)
	{
		char buff[1];
		DWORD ret = GetEnvironmentVariable(name, buff, 1);
		if ((!overwrite) && (ret != 0))
		{ // 上書きなし && 既に環境変数に存在するので true を返す。
			return true;
		}

		// 環境変数設定
		ret = SetEnvironmentVariable(name, value);
		return (ret != 0);
	}
	else
	{
		errno = EINVAL;
		return false;
	}
#else
	int ret = setenv(name, value, overwrite);
	return (ret == 0);
#endif
}

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