/*
 *	app.c
 *
 *	env.exe - UNIXコマンド「env」互換ツール
 *	Copyright (C) 2015-2016 Naoyuki Sawa
 *
 *	* Mon Sep 28 21:55:38 JST 2015 Naoyuki Sawa
 *	- 1st リリース。
 *	- Win32用「env」コマンドは、UnxUtils(http://sourceforge.net/projects/unxutils/)にも含まれていますが、
 *	  使って見たところ正常に動作しないようなので、自分で作った物です。
 *	- UnxUtils版の「env」は、子プロセスの起動に_execvp()を使っているのが間違いです。
 *	  正しくは_spawnvp()を使って、env.exeが子プロセスの終了を待つべきです。
 *	* Sun Feb 21 21:02:01 JST 2016 Naoyuki Sawa
 *	- 「Boehm GC」をマルチスレッド対応にした事,及び,それに伴ってclipbpe.cモジュールを修正した事に伴い、当ツールもプロジェクト設定の変更を行ってリビルドしました。
 *	  詳細は、/clip/tool/gc/README.TXT と /clip/clipbpe.c の2015/11/03のコメントを参照して下さい。
 *	- libclipのライブラリ化の伴い、以下の変更を行いました。
 *	  ・extclip.hとextclip.cを削除しました。extclip.hとextclip.cはlibclipに含まれるようになったからです。
 *	  ・"CLiP Files"を削除しました。CLiPライブラリの各モジュールはlibclipに含まれるようになったからです。
 *	  当ツールの動作には変更有りません。
 */
#include "app.h"
#define VERSION		"20160221"	//最終更新日
/****************************************************************************
 *	ローカル関数宣言
 ****************************************************************************/
static int subr(int argc, char* argv[]);
__declspec(noreturn) static void usage();
/****************************************************************************
 *	main
 ****************************************************************************/
int main(int argc, char* argv[]) {
	int exitCode;
//	putenv("GC_LOG_FILE=CON");//ログ出力先を指定する。
//	GC_set_find_leak(1);//メモリリーク検出を開始する。
	exitCode = subr(argc, argv);
//	CHECK_LEAKS();//メモリリークを検出する。
//	cputs("ok");
//	getch();
	return exitCode;
}
/****************************************************************************
 *	ローカル関数
 ****************************************************************************/
static int subr(int argc, char* argv[]) {
	int opt, exitCode;
	char* s;
	opterr = 0;	//オプションエラーは当プログラム内で処理するので、getopt()内でのエラー表示は不要。
	while((opt = getopt(argc, argv, "hu:")) != -1) {
		switch(opt) {
		default:
		case 'h':
			usage();
			break;
		case 'u':
			//環境変数を削除します。
			s = strdup_printf("%s=", optarg);
			_putenv(s);
			free(s);
			break;
		}
	}
	while(optind < argc) {
		//'='が含まれていなければ、'COMMAND'と見なして抜けます。
		if(!strchr(argv[optind], '=')) { break; }
		//環境変数を追加,又は,変更します。
		// - 「NAME=」と指定された場合は、環境変数を削除します。
		_putenv(argv[optind]);
		optind++;
	}
	if(optind < argc) {
		//'COMMAND'が指定されていなければ、子プロセスを実行し、終了するまで待ちます。
		// - _execvp()ではダメです。
		//   cmd.exeがenv.exeが終了したと判断して子プロセスが実行中のままコマンドプロンプトに戻ってしまいます。
		//   _spawnvp()を使って子プロセスの終了を待つのが正しいです。
		exitCode = _spawnvp(_P_WAIT, argv[optind], &argv[optind]);
		if(exitCode == -1) { die("%sを実行できません。(%s)", argv[optind], strerror(errno)); }
	} else {
		//'COMMAND'が指定されていなければ、環境の一覧を表示します。
		s = strjoinv("\n", _environ);
		puts(s);
		free(s);
		exitCode = EXIT_SUCCESS;
	}
	return exitCode;
}
/*--------------------------------------------------------------------------*/
__declspec(noreturn) static void usage() {
	fprintf(stderr, "env.exe - UNIXコマンド「env」互換ツール (%s)\n", VERSION);
	fprintf(stderr, "Copyright (C) 2015-2016 Naoyuki Sawa\n");
	fprintf(stderr, "\n");
	fprintf(stderr, "USAGE:\n");
	fprintf(stderr, "  env.exe [OPTION ...] [--] [NAME=VALUE ...] [COMMAND [ARG ...]]\n");
	fprintf(stderr, "\n");
	fprintf(stderr, "OPTIONS:\n");
	fprintf(stderr, "  -u変数名 環境変数を削除します。\n");
	fprintf(stderr, "  -h       使い方を表示します。\n");
	fprintf(stderr, "\n");
	fprintf(stderr, "NOTE:\n");
	fprintf(stderr, "  Win32用「env」コマンドは、UnxUtils(http://sourceforge.net/projects/unxutils/)にも含まれていますが、\n");
	fprintf(stderr, "  使って見たところ正常に動作しないようなので、自分で作った物です。\n");
	fprintf(stderr, "  本物の「env」やUnxUtils版の「-i」オプションは、使用頻度が低いと思うので当実装では未対応としました。\n");
	fprintf(stderr, "\n");
	fprintf(stderr, "EXAMPLE:\n");
	fprintf(stderr, "  ①env.exe REGTBL_BIN=RegTbl.bin MkRegTbl.bat RegTbl.txt\n");
	fprintf(stderr, "    環境変数REGTBL_BINにRegTbl.binを設定して、MkRegTbl.batを実行します。\n");
	fprintf(stderr, "  ②env.exe -uREGTBL_BIN MkRegTbl.bat RegTbl.txt\n");
	fprintf(stderr, "    環境変数REGTBL_BINを確実に削除して、MkRegTbl.batを実行します。\n");
	fprintf(stderr, "  ③env.exe REGTBL_BIN=RegTbl.bin\n");
	fprintf(stderr, "    環境変数の変更を適用した結果として得られた、環境の一覧を表示します。\n");
	exit(EXIT_FAILURE);
}
