* tar xzf utvpn-src-unix-v101-7101-public-2010.06.27.tar.gz
[lab.git] / utvpn / utvpn-unix-v101-7101-public / src / Cedar / Console.c
diff --git a/utvpn/utvpn-unix-v101-7101-public/src/Cedar/Console.c b/utvpn/utvpn-unix-v101-7101-public/src/Cedar/Console.c
new file mode 100644 (file)
index 0000000..53c9cab
--- /dev/null
@@ -0,0 +1,2411 @@
+// SoftEther UT-VPN SourceCode\r
+// \r
+// Copyright (C) 2004-2010 SoftEther Corporation.\r
+// Copyright (C) 2004-2010 University of Tsukuba, Japan.\r
+// Copyright (C) 2003-2010 Daiyuu Nobori.\r
+// All Rights Reserved.\r
+// \r
+// http://utvpn.tsukuba.ac.jp/\r
+// \r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// version 2 as published by the Free Software Foundation.\r
+// \r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+// GNU General Public License for more details.\r
+// \r
+// You should have received a copy of the GNU General Public License version 2\r
+// along with this program; if not, write to the Free Software\r
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
+// \r
+// このファイルは GPL バージョン 2 ライセンスで公開されています。\r
+// 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布\r
+// することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示\r
+// を除去することはできません。改変した著作物を配布する場合は、改変実施者の\r
+// 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。\r
+// \r
+// この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の\r
+// ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )\r
+// および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって\r
+// ホストされています。\r
+// 本プログラムの配布者は、本プログラムを、業としての利用以外のため、\r
+// および、試験または研究のために利用が行われることを想定して配布\r
+// しています。\r
+// SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に\r
+// あります。\r
+// 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード\r
+// の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して\r
+// いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して\r
+// ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース\r
+// に組み込みさせていただきます。\r
+// \r
+// GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する\r
+// 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。\r
+// \r
+// 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社\r
+// (SoftEther Corporation) およびその他の著作権保持者が保有しています。\r
+// ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの\r
+// 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意\r
+// ください。\r
+// \r
+// お願い: どのような通信ソフトウェアにも通常は必ず未発見の\r
+// セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、\r
+// UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの\r
+// 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社\r
+// および脆弱性情報の届出を受け付ける公的機関まで通報いただき、\r
+// 公益保護にご協力いただきますようお願い申し上げます。\r
+// \r
+// ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を\r
+// 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客\r
+// を保護するための努力を行います。\r
+// \r
+// ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/\r
+// 日本国内の脆弱性情報届出受付公的機関:\r
+//         独立行政法人 情報処理推進機構\r
+//         http://www.ipa.go.jp/security/vuln/report/\r
+// \r
+// 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。\r
+// 連絡先: http://www.softether.co.jp/jp/contact/\r
+\r
+// -----------------------------------------------\r
+// [ChangeLog]\r
+// 2010.05.20\r
+//  新規リリース by SoftEther\r
+// -----------------------------------------------\r
+\r
+// Console.c\r
+// コンソール サービス\r
+\r
+#include "CedarPch.h"\r
+\r
+\r
+// コマンドのヘルプを表示する\r
+void PrintCmdHelp(CONSOLE *c, char *cmd_name, TOKEN_LIST *param_list)\r
+{\r
+       wchar_t tmp[MAX_SIZE];\r
+       wchar_t *buf;\r
+       UINT buf_size;\r
+       wchar_t *description, *args, *help;\r
+       UNI_TOKEN_LIST *t;\r
+       UINT width;\r
+       UINT i;\r
+       char *space;\r
+       // 引数チェック\r
+       if (c == NULL || cmd_name == NULL || param_list == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       width = GetConsoleWidth(c) - 2;\r
+\r
+       buf_size = sizeof(wchar_t) * (width + 32);\r
+       buf = Malloc(buf_size);\r
+\r
+       GetCommandHelpStr(cmd_name, &description, &args, &help);\r
+\r
+       space = MakeCharArray(' ', 2);\r
+\r
+       // タイトル\r
+       UniFormat(tmp, sizeof(tmp), _UU("CMD_HELP_TITLE"), cmd_name);\r
+       c->Write(c, tmp);\r
+       c->Write(c, L"");\r
+\r
+       // 目的\r
+       c->Write(c, _UU("CMD_HELP_DESCRIPTION"));\r
+       t = SeparateStringByWidth(description, width - 2);\r
+       for (i = 0;i < t->NumTokens;i++)\r
+       {\r
+               UniFormat(buf, buf_size, L"%S%s", space, t->Token[i]);\r
+               c->Write(c, buf);\r
+       }\r
+       UniFreeToken(t);\r
+       c->Write(c, L"");\r
+\r
+       // 説明\r
+       c->Write(c, _UU("CMD_HELP_HELP"));\r
+       t = SeparateStringByWidth(help, width - 2);\r
+       for (i = 0;i < t->NumTokens;i++)\r
+       {\r
+               UniFormat(buf, buf_size, L"%S%s", space, t->Token[i]);\r
+               c->Write(c, buf);\r
+       }\r
+       UniFreeToken(t);\r
+       c->Write(c, L"");\r
+\r
+       // 使用方法\r
+       c->Write(c, _UU("CMD_HELP_USAGE"));\r
+       t = SeparateStringByWidth(args, width - 2);\r
+       for (i = 0;i < t->NumTokens;i++)\r
+       {\r
+               UniFormat(buf, buf_size, L"%S%s", space, t->Token[i]);\r
+               c->Write(c, buf);\r
+       }\r
+       UniFreeToken(t);\r
+\r
+       // 引数\r
+       if (param_list->NumTokens >= 1)\r
+       {\r
+               c->Write(c, L"");\r
+               c->Write(c, _UU("CMD_HELP_ARGS"));\r
+               PrintCandidateHelp(c, cmd_name, param_list, 2);\r
+       }\r
+\r
+       Free(space);\r
+\r
+       Free(buf);\r
+}\r
+\r
+// SafeStr であるかどうかの評価\r
+bool CmdEvalSafe(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       wchar_t *p = (param == NULL) ? _UU("CMD_EVAL_SAFE") : (wchar_t *)param;\r
+\r
+       if (IsSafeUniStr(str))\r
+       {\r
+               return true;\r
+       }\r
+\r
+       c->Write(c, p);\r
+\r
+       return false;\r
+}\r
+\r
+// 文字列入力プロンプト\r
+wchar_t *CmdPrompt(CONSOLE *c, void *param)\r
+{\r
+       wchar_t *p = (param == NULL) ? _UU("CMD_PROMPT") : (wchar_t *)param;\r
+\r
+       return c->ReadLine(c, p, true);\r
+}\r
+\r
+// 指定されたファイルが存在するかどうか評価\r
+bool CmdEvalIsFile(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       char tmp[MAX_PATH];\r
+       // 引数チェック\r
+       if (c == NULL || str == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       UniToStr(tmp, sizeof(tmp), str);\r
+\r
+       if (IsEmptyStr(tmp))\r
+       {\r
+               c->Write(c, _UU("CMD_FILE_NAME_EMPTY"));\r
+               return false;\r
+       }\r
+\r
+       if (IsFileExists(tmp) == false)\r
+       {\r
+               wchar_t tmp2[MAX_SIZE];\r
+\r
+               UniFormat(tmp2, sizeof(tmp2), _UU("CMD_FILE_NOT_FOUND"), tmp);\r
+               c->Write(c, tmp2);\r
+\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+// 整数の評価\r
+bool CmdEvalInt1(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       wchar_t *p = (param == NULL) ? _UU("CMD_EVAL_INT") : (wchar_t *)param;\r
+\r
+       if (UniToInt(str) == 0)\r
+       {\r
+               c->Write(c, p);\r
+\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+// 空白を指定できないパラメータの評価\r
+bool CmdEvalNotEmpty(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       wchar_t *p = (param == NULL) ? _UU("CMD_EVAL_NOT_EMPTY") : (wchar_t *)param;\r
+\r
+       if (UniIsEmptyStr(str) == false)\r
+       {\r
+               return true;\r
+       }\r
+\r
+       c->Write(c, p);\r
+\r
+       return false;\r
+}\r
+\r
+// パラメータの最小 / 最大値評価関数\r
+bool CmdEvalMinMax(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       CMD_EVAL_MIN_MAX *e;\r
+       wchar_t *tag;\r
+       UINT v;\r
+       // 引数チェック\r
+       if (param == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       e = (CMD_EVAL_MIN_MAX *)param;\r
+\r
+       if (e->StrName == NULL)\r
+       {\r
+               tag = _UU("CMD_EVAL_MIN_MAX");\r
+       }\r
+       else\r
+       {\r
+               tag = _UU(e->StrName);\r
+       }\r
+\r
+       v = UniToInt(str);\r
+\r
+       if (v >= e->MinValue && v <= e->MaxValue)\r
+       {\r
+               return true;\r
+       }\r
+       else\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+\r
+               UniFormat(tmp, sizeof(tmp), tag, e->MinValue, e->MaxValue);\r
+               c->Write(c, tmp);\r
+\r
+               return false;\r
+       }\r
+}\r
+\r
+// コマンドのヘルプ文字列を取得する\r
+void GetCommandHelpStr(char *command_name, wchar_t **description, wchar_t **args, wchar_t **help)\r
+{\r
+       char tmp1[128], tmp2[128], tmp3[128];\r
+\r
+       Format(tmp1, sizeof(tmp1), "CMD_%s", command_name);\r
+       Format(tmp2, sizeof(tmp2), "CMD_%s_ARGS", command_name);\r
+       Format(tmp3, sizeof(tmp3), "CMD_%s_HELP", command_name);\r
+\r
+       if (description != NULL)\r
+       {\r
+               *description = _UU(tmp1);\r
+               if (UniIsEmptyStr(*description))\r
+               {\r
+                       *description = _UU("CMD_UNKNOWM");\r
+               }\r
+       }\r
+\r
+       if (args != NULL)\r
+       {\r
+               *args = _UU(tmp2);\r
+               if (UniIsEmptyStr(*args))\r
+               {\r
+                       *args = _UU("CMD_UNKNOWN_ARGS");\r
+               }\r
+       }\r
+\r
+       if (help != NULL)\r
+       {\r
+               *help = _UU(tmp3);\r
+               if (UniIsEmptyStr(*help))\r
+               {\r
+                       *help = _UU("CMD_UNKNOWN_HELP");\r
+               }\r
+       }\r
+}\r
+\r
+// パラメータのヘルプ文字列を取得する\r
+void GetCommandParamHelpStr(char *command_name, char *param_name, wchar_t **description)\r
+{\r
+       char tmp[160];\r
+       if (description == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Format(tmp, sizeof(tmp), "CMD_%s_%s", command_name, param_name);\r
+\r
+       *description = _UU(tmp);\r
+\r
+       if (UniIsEmptyStr(*description))\r
+       {\r
+               *description = _UU("CMD_UNKNOWN_PARAM");\r
+       }\r
+}\r
+\r
+// 文字列比較関数\r
+int CompareCandidateStr(void *p1, void *p2)\r
+{\r
+       char *s1, *s2;\r
+       if (p1 == NULL || p2 == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+       s1 = *(char **)p1;\r
+       s2 = *(char **)p2;\r
+       if (s1 == NULL || s2 == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       if (s1[0] == '[' && s2[0] != '[')\r
+       {\r
+               return -1;\r
+       }\r
+       else if (s2[0] == '[' && s1[0] != '[')\r
+       {\r
+               return 1;\r
+       }\r
+\r
+       return StrCmp(s1, s2);\r
+}\r
+\r
+// 候補一覧のヘルプを表示する\r
+void PrintCandidateHelp(CONSOLE *c, char *cmd_name, TOKEN_LIST *candidate_list, UINT left_space)\r
+{\r
+       UINT console_width;\r
+       UINT max_keyword_width;\r
+       LIST *o;\r
+       UINT i;\r
+       wchar_t *tmpbuf;\r
+       UINT tmpbuf_size;\r
+       char *left_space_array;\r
+       char *max_space_array;\r
+       // 引数チェック\r
+       if (c == NULL || candidate_list == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 画面の横幅の取得\r
+       console_width = GetConsoleWidth(c) - 1;\r
+\r
+       tmpbuf_size = sizeof(wchar_t) * (console_width + 32);\r
+       tmpbuf = Malloc(tmpbuf_size);\r
+\r
+       left_space_array = MakeCharArray(' ', left_space);\r
+\r
+       // コマンド名はソートしてリスト化する\r
+       // パラメータ名はソートしない\r
+       o = NewListFast(cmd_name == NULL ? CompareCandidateStr : NULL);\r
+\r
+       max_keyword_width = 0;\r
+\r
+       for (i = 0;i < candidate_list->NumTokens;i++)\r
+       {\r
+               UINT keyword_width;\r
+\r
+               // 各キーワードの横幅を取得する\r
+               Insert(o, candidate_list->Token[i]);\r
+\r
+               keyword_width = StrWidth(candidate_list->Token[i]);\r
+               if (cmd_name != NULL)\r
+               {\r
+                       if (candidate_list->Token[i][0] != '[')\r
+                       {\r
+                               keyword_width += 1;\r
+                       }\r
+                       else\r
+                       {\r
+                               keyword_width -= 2;\r
+                       }\r
+               }\r
+\r
+               max_keyword_width = MAX(max_keyword_width, keyword_width);\r
+       }\r
+\r
+       max_space_array = MakeCharArray(' ', max_keyword_width);\r
+\r
+       // 候補を表示する\r
+       for (i = 0;i < LIST_NUM(o);i++)\r
+       {\r
+               char tmp[128];\r
+               char *name = LIST_DATA(o, i);\r
+               UNI_TOKEN_LIST *t;\r
+               wchar_t *help;\r
+               UINT j;\r
+               UINT keyword_start_width = left_space;\r
+               UINT descript_start_width = left_space + max_keyword_width + 1;\r
+               UINT descript_width;\r
+               char *space;\r
+\r
+               if (console_width >= (descript_start_width + 5))\r
+               {\r
+                       descript_width = console_width - descript_start_width - 3;\r
+               }\r
+               else\r
+               {\r
+                       descript_width = 2;\r
+               }\r
+\r
+               // 名前を生成する\r
+               if (cmd_name != NULL && name[0] != '[')\r
+               {\r
+                       // パラメータの場合は先頭に "/" を付ける\r
+                       Format(tmp, sizeof(tmp), "/%s", name);\r
+               }\r
+               else\r
+               {\r
+                       // コマンド名の場合はそのままの文字を使用する\r
+                       if (cmd_name == NULL)\r
+                       {\r
+                               StrCpy(tmp, sizeof(tmp), name);\r
+                       }\r
+                       else\r
+                       {\r
+                               StrCpy(tmp, sizeof(tmp), name + 1);\r
+                               if (StrLen(tmp) >= 1)\r
+                               {\r
+                                       tmp[StrLen(tmp) - 1] = 0;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               // ヘルプ文字を取得する\r
+               if (cmd_name == NULL)\r
+               {\r
+                       GetCommandHelpStr(name, &help, NULL, NULL);\r
+               }\r
+               else\r
+               {\r
+                       GetCommandParamHelpStr(cmd_name, name, &help);\r
+               }\r
+\r
+               space = MakeCharArray(' ', max_keyword_width - StrWidth(name) - (cmd_name == NULL ? 0 : (name[0] != '[' ? 1 : -2)));\r
+\r
+               t = SeparateStringByWidth(help, descript_width);\r
+\r
+               for (j = 0;j < t->NumTokens;j++)\r
+               {\r
+                       if (j == 0)\r
+                       {\r
+                               UniFormat(tmpbuf, tmpbuf_size, L"%S%S%S - %s",\r
+                                       left_space_array, tmp, space, t->Token[j]);\r
+                       }\r
+                       else\r
+                       {\r
+                               UniFormat(tmpbuf, tmpbuf_size, L"%S%S   %s",\r
+                                       left_space_array, max_space_array, t->Token[j]);\r
+                       }\r
+\r
+                       c->Write(c, tmpbuf);\r
+               }\r
+\r
+               Free(space);\r
+\r
+               UniFreeToken(t);\r
+       }\r
+\r
+       ReleaseList(o);\r
+\r
+       Free(max_space_array);\r
+       Free(tmpbuf);\r
+       Free(left_space_array);\r
+}\r
+\r
+// 文字列を指定された横幅で分割する\r
+UNI_TOKEN_LIST *SeparateStringByWidth(wchar_t *str, UINT width)\r
+{\r
+       UINT wp;\r
+       wchar_t *tmp;\r
+       UINT len, i;\r
+       LIST *o;\r
+       UNI_TOKEN_LIST *ret;\r
+       // 引数チェック\r
+       if (str == NULL)\r
+       {\r
+               return UniNullToken();\r
+       }\r
+       if (width == 0)\r
+       {\r
+               width = 1;\r
+       }\r
+\r
+       o = NewListFast(NULL);\r
+\r
+       len = UniStrLen(str);\r
+       tmp = ZeroMalloc(sizeof(wchar_t) * (len + 32));\r
+       wp = 0;\r
+\r
+       for (i = 0;i < (len + 1);i++)\r
+       {\r
+               wchar_t c = str[i];\r
+\r
+               switch (c)\r
+               {\r
+               case 0:\r
+               case L'\r':\r
+               case L'\n':\r
+                       if (c == L'\r')\r
+                       {\r
+                               if (str[i + 1] == L'\n')\r
+                               {\r
+                                       i++;\r
+                               }\r
+                       }\r
+\r
+                       tmp[wp++] = 0;\r
+                       wp = 0;\r
+\r
+                       Insert(o, UniCopyStr(tmp));\r
+                       break;\r
+\r
+               default:\r
+                       tmp[wp++] = c;\r
+                       tmp[wp] = 0;\r
+                       if (UniStrWidth(tmp) >= width)\r
+                       {\r
+                               tmp[wp++] = 0;\r
+                               wp = 0;\r
+\r
+                               Insert(o, UniCopyStr(tmp));\r
+                       }\r
+                       break;\r
+               }\r
+       }\r
+\r
+       if (LIST_NUM(o) == 0)\r
+       {\r
+               Insert(o, CopyUniStr(L""));\r
+       }\r
+\r
+       ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));\r
+       ret->NumTokens = LIST_NUM(o);\r
+       ret->Token = ZeroMalloc(sizeof(wchar_t *) * ret->NumTokens);\r
+\r
+       for (i = 0;i < LIST_NUM(o);i++)\r
+       {\r
+               wchar_t *s = LIST_DATA(o, i);\r
+\r
+               ret->Token[i] = s;\r
+       }\r
+\r
+       ReleaseList(o);\r
+       Free(tmp);\r
+\r
+       return ret;\r
+}\r
+\r
+// 指定した文字列が help を示すかどうかをチェック\r
+bool IsHelpStr(char *str)\r
+{\r
+       // 引数チェック\r
+       if (str == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (StrCmpi(str, "help") == 0 || StrCmpi(str, "?") == 0 ||\r
+               StrCmpi(str, "man") == 0 || StrCmpi(str, "/man") == 0 ||\r
+               StrCmpi(str, "-man") == 0 || StrCmpi(str, "--man") == 0 ||\r
+               StrCmpi(str, "/help") == 0 || StrCmpi(str, "/?") == 0 ||\r
+               StrCmpi(str, "-help") == 0 || StrCmpi(str, "-?") == 0 ||\r
+               StrCmpi(str, "/h") == 0 || StrCmpi(str, "--help") == 0 ||\r
+               StrCmpi(str, "--?") == 0)\r
+       {\r
+               return true;\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+// コマンドの実行\r
+bool DispatchNextCmd(CONSOLE *c, char *prompt, CMD cmd[], UINT num_cmd, void *param)\r
+{\r
+       return DispatchNextCmdEx(c, NULL, prompt, cmd, num_cmd, param);\r
+}\r
+bool DispatchNextCmdEx(CONSOLE *c, wchar_t *exec_command, char *prompt, CMD cmd[], UINT num_cmd, void *param)\r
+{\r
+       wchar_t *str;\r
+       wchar_t *tmp;\r
+       char *cmd_name;\r
+       bool b_exit = false;\r
+       wchar_t *cmd_param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       TOKEN_LIST *t;\r
+       TOKEN_LIST *candidate;\r
+       bool no_end_crlf = false;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (c == NULL || (num_cmd >= 1 && cmd == NULL))\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (exec_command == NULL)\r
+       {\r
+               // プロンプトを表示\r
+RETRY:\r
+               tmp = CopyStrToUni(prompt);\r
+               str = c->ReadLine(c, tmp, false);\r
+               Free(tmp);\r
+\r
+               if (str != NULL && IsEmptyUniStr(str))\r
+               {\r
+                       Free(str);\r
+                       goto RETRY;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               // exec_command を使用\r
+               if (UniStartWith(exec_command, L"utvpncmd") == false)\r
+               {\r
+                       if (prompt != NULL)\r
+                       {\r
+                               if (c->ConsoleType != CONSOLE_CSV)\r
+                               {\r
+                                       UniFormat(tmp, sizeof(tmp), L"%S%s", prompt, exec_command);\r
+                                       c->Write(c, tmp);\r
+                               }\r
+                       }\r
+               }\r
+               str = CopyUniStr(exec_command);\r
+       }\r
+\r
+       if (str == NULL)\r
+       {\r
+               // ユーザーキャンセル\r
+               return false;\r
+       }\r
+\r
+       UniTrimCrlf(str);\r
+       UniTrim(str);\r
+\r
+       if (UniIsEmptyStr(str))\r
+       {\r
+               // 何もしない\r
+               Free(str);\r
+               return true;\r
+       }\r
+\r
+       // コマンド名とパラメータに分ける\r
+       if (SeparateCommandAndParam(str, &cmd_name, &cmd_param) == false)\r
+       {\r
+               // 何もしない\r
+               Free(str);\r
+               return true;\r
+       }\r
+\r
+       if (StrLen(cmd_name) >= 2 && cmd_name[0] == '?' && cmd_name[1] != '?')\r
+       {\r
+               char tmp[MAX_SIZE];\r
+               wchar_t *s;\r
+\r
+               StrCpy(tmp, sizeof(tmp), cmd_name + 1);\r
+               StrCpy(cmd_name, 0, tmp);\r
+\r
+               s = UniCopyStr(L"/?");\r
+               Free(cmd_param);\r
+\r
+               cmd_param = s;\r
+       }\r
+\r
+       if (StrLen(cmd_name) >= 2 && EndWith(cmd_name, "?") && cmd_name[StrLen(cmd_name) - 2] != '?')\r
+       {\r
+               wchar_t *s;\r
+\r
+               cmd_name[StrLen(cmd_name) - 1] = 0;\r
+\r
+               s = UniCopyStr(L"/?");\r
+               Free(cmd_param);\r
+\r
+               cmd_param = s;\r
+       }\r
+\r
+       // コマンドの候補を取得する\r
+       t = ZeroMalloc(sizeof(TOKEN_LIST));\r
+       t->NumTokens = num_cmd;\r
+       t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);\r
+       for (i = 0;i < t->NumTokens;i++)\r
+       {\r
+               t->Token[i] = CopyStr(cmd[i].Name);\r
+       }\r
+\r
+       if (IsHelpStr(cmd_name))\r
+       {\r
+               if (UniIsEmptyStr(cmd_param))\r
+               {\r
+                       wchar_t tmp[MAX_SIZE];\r
+\r
+                       // 使用できるコマンド一覧を表示する\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CMD_HELP_1"), t->NumTokens);\r
+                       c->Write(c, tmp);\r
+\r
+                       PrintCandidateHelp(c, NULL, t, 1);\r
+\r
+                       c->Write(c, L"");\r
+                       c->Write(c, _UU("CMD_HELP_2"));\r
+               }\r
+               else\r
+               {\r
+                       char *cmd_name;\r
+\r
+                       // 指定したコマンドのヘルプを表示する\r
+                       if (SeparateCommandAndParam(cmd_param, &cmd_name, NULL))\r
+                       {\r
+                               bool b = true;\r
+\r
+                               if (IsHelpStr(cmd_name))\r
+                               {\r
+                                       b = false;\r
+                               }\r
+\r
+                               if (b)\r
+                               {\r
+                                       wchar_t str[MAX_SIZE];\r
+\r
+                                       UniFormat(str, sizeof(str), L"%S /help", cmd_name);\r
+                                       DispatchNextCmdEx(c, str, NULL, cmd, num_cmd, param);\r
+                                       no_end_crlf = true;\r
+                               }\r
+\r
+                               Free(cmd_name);\r
+                       }\r
+               }\r
+       }\r
+       else if (StrCmpi(cmd_name, "exit") == 0 || StrCmpi(cmd_name, "quit") == 0)\r
+       {\r
+               // 終了\r
+               b_exit = true;\r
+       }\r
+       else\r
+       {\r
+               candidate = GetRealnameCandidate(cmd_name, t);\r
+\r
+               if (candidate == NULL || candidate->NumTokens == 0)\r
+               {\r
+                       wchar_t tmp[MAX_SIZE];\r
+\r
+                       // 候補無し\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CON_UNKNOWN_CMD"), cmd_name);\r
+                       c->Write(c, tmp);\r
+\r
+                       c->RetCode = ERR_BAD_COMMAND_OR_PARAM;\r
+               }\r
+               else if (candidate->NumTokens >= 2)\r
+               {\r
+                       wchar_t tmp[MAX_SIZE];\r
+\r
+                       // 候補が複数ある\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CON_AMBIGIOUS_CMD"), cmd_name);\r
+                       c->Write(c, tmp);\r
+                       c->Write(c, _UU("CON_AMBIGIOUS_CMD_1"));\r
+                       PrintCandidateHelp(c, NULL, candidate, 1);\r
+                       c->Write(c, _UU("CON_AMBIGIOUS_CMD_2"));\r
+\r
+                       c->RetCode = ERR_BAD_COMMAND_OR_PARAM;\r
+               }\r
+               else\r
+               {\r
+                       char *real_cmd_name;\r
+                       UINT i;\r
+\r
+                       // 1 つに定まった\r
+                       real_cmd_name = candidate->Token[0];\r
+\r
+                       for (i = 0;i < num_cmd;i++)\r
+                       {\r
+                               if (StrCmpi(cmd[i].Name, real_cmd_name) == 0)\r
+                               {\r
+                                       if (cmd[i].Proc != NULL)\r
+                                       {\r
+                                               // CSV モードでなければコマンドの説明を表示する\r
+                                               if(c->ConsoleType != CONSOLE_CSV)\r
+                                               {\r
+                                                       wchar_t tmp[256];\r
+                                                       wchar_t *note;\r
+\r
+                                                       GetCommandHelpStr(cmd[i].Name, &note, NULL, NULL);\r
+                                                       UniFormat(tmp, sizeof(tmp), _UU("CMD_EXEC_MSG_NAME"), cmd[i].Name, note);\r
+                                                       c->Write(c, tmp);\r
+                                               }\r
+\r
+                                               // コマンドのプロシージャを呼び出す\r
+                                               ret = cmd[i].Proc(c, cmd[i].Name, cmd_param, param);\r
+\r
+                                               if (ret == INFINITE)\r
+                                               {\r
+                                                       // 終了コマンド\r
+                                                       b_exit = true;\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       c->RetCode = ret;\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+\r
+               FreeToken(candidate);\r
+       }\r
+\r
+       FreeToken(t);\r
+       Free(str);\r
+       Free(cmd_name);\r
+       Free(cmd_param);\r
+\r
+       if (no_end_crlf == false)\r
+       {\r
+               //c->Write(c, L"");\r
+       }\r
+\r
+       if (b_exit)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+// 現在のコンソールの横幅を取得する\r
+UINT GetConsoleWidth(CONSOLE *c)\r
+{\r
+       UINT size;\r
+\r
+       size = c->GetWidth(c);\r
+\r
+       if (size == 0)\r
+       {\r
+               size = 80;\r
+       }\r
+\r
+       if (size < 32)\r
+       {\r
+               size = 32;\r
+       }\r
+\r
+       if (size > 65536)\r
+       {\r
+               size = 65535;\r
+       }\r
+\r
+       return size;\r
+}\r
+\r
+// コマンドラインをコマンドとパラメータの 2 つに分離する\r
+bool SeparateCommandAndParam(wchar_t *src, char **cmd, wchar_t **param)\r
+{\r
+       UINT i, len, wp;\r
+       wchar_t *tmp;\r
+       wchar_t *src_tmp;\r
+       // 引数チェック\r
+       if (src == NULL)\r
+       {\r
+               return false;\r
+       }\r
+       if (cmd != NULL)\r
+       {\r
+               *cmd = NULL;\r
+       }\r
+       if (param != NULL)\r
+       {\r
+               *param = NULL;\r
+       }\r
+\r
+       src_tmp = UniCopyStr(src);\r
+       UniTrimCrlf(src_tmp);\r
+       UniTrim(src_tmp);\r
+\r
+       len = UniStrLen(src_tmp);\r
+       tmp = Malloc(sizeof(wchar_t) * (len + 32));\r
+       wp = 0;\r
+\r
+       for (i = 0;i < (len + 1);i++)\r
+       {\r
+               wchar_t c = src_tmp[i];\r
+\r
+               switch (c)\r
+               {\r
+               case 0:\r
+               case L' ':\r
+               case L'\t':\r
+                       tmp[wp] = 0;\r
+                       if (UniIsEmptyStr(tmp))\r
+                       {\r
+                               Free(tmp);\r
+                               Free(src_tmp);\r
+                               return false;\r
+                       }\r
+                       if (cmd != NULL)\r
+                       {\r
+                               *cmd = CopyUniToStr(tmp);\r
+                               Trim(*cmd);\r
+                       }\r
+                       goto ESCAPE;\r
+\r
+               default:\r
+                       tmp[wp++] = c;\r
+                       break;\r
+               }\r
+       }\r
+\r
+ESCAPE:\r
+       if (param != NULL)\r
+       {\r
+               *param = CopyUniStr(&src_tmp[wp]);\r
+               UniTrim(*param);\r
+       }\r
+\r
+       Free(tmp);\r
+       Free(src_tmp);\r
+\r
+       return true;\r
+}\r
+\r
+// ユーザーが指定したコマンド名の省略形に一致する実在するコマンドの一覧の候補を取得する\r
+TOKEN_LIST *GetRealnameCandidate(char *input_name, TOKEN_LIST *real_name_list)\r
+{\r
+       TOKEN_LIST *ret;\r
+       LIST *o;\r
+       UINT i;\r
+       bool ok = false;\r
+       // 引数チェック\r
+       if (input_name == NULL || real_name_list == NULL)\r
+       {\r
+               return NullToken();\r
+       }\r
+\r
+       o = NewListFast(NULL);\r
+\r
+       for (i = 0;i < real_name_list->NumTokens;i++)\r
+       {\r
+               char *name = real_name_list->Token[i];\r
+\r
+               // まず最優先で完全一致するものを検索する\r
+               if (StrCmpi(name, input_name) == 0)\r
+               {\r
+                       Insert(o, name);\r
+                       ok = true;\r
+                       break;\r
+               }\r
+       }\r
+\r
+       if (ok == false)\r
+       {\r
+               // 完全一致するコマンドが無い場合、省略形コマンドとして一致するかどうかチェックする\r
+               for (i = 0;i < real_name_list->NumTokens;i++)\r
+               {\r
+                       char *name = real_name_list->Token[i];\r
+\r
+                       if (IsOmissionName(input_name, name) || IsNameInRealName(input_name, name))\r
+                       {\r
+                               // 省略形を発見した\r
+                               Insert(o, name);\r
+                               ok = true;\r
+                       }\r
+               }\r
+       }\r
+\r
+       if (ok)\r
+       {\r
+               // 1 つ以上の候補が見つかった\r
+               ret = ListToTokenList(o);\r
+       }\r
+       else\r
+       {\r
+               ret = NullToken();\r
+       }\r
+\r
+       ReleaseList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// ユーザーが指定したコマンドが既存のコマンドの省略形かどうかチェックする\r
+bool IsOmissionName(char *input_name, char *real_name)\r
+{\r
+       char oname[128];\r
+       // 引数チェック\r
+       if (input_name == NULL || real_name == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (IsAllUpperStr(real_name))\r
+       {\r
+               // すべて大文字のコマンドは省略形をとらない\r
+               return false;\r
+       }\r
+\r
+       GetOmissionName(oname, sizeof(oname), real_name);\r
+\r
+       if (IsEmptyStr(oname))\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (StartWith(oname, input_name))\r
+       {\r
+               // 例: AccountSecureCertSet の oname は ascs だが\r
+               //     ユーザーが asc と入力した場合は true を返す\r
+               return true;\r
+       }\r
+\r
+       if (StartWith(input_name, oname))\r
+       {\r
+               // 例: AccountConnect と\r
+               //     AccountCreate の 2 つのコマンドが実在する際、\r
+               //     ユーザーが "aconnect" と入力すると、\r
+               //     AccountConnect のみ true になるようにする\r
+\r
+               if (EndWith(real_name, &input_name[StrLen(oname)]))\r
+               {\r
+                       return true;\r
+               }\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+// 指定したコマンド名の省略名を取得する\r
+void GetOmissionName(char *dst, UINT size, char *src)\r
+{\r
+       UINT i, len;\r
+       // 引数チェック\r
+       if (dst == NULL || src == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       StrCpy(dst, size, "");\r
+       len = StrLen(src);\r
+\r
+       for (i = 0;i < len;i++)\r
+       {\r
+               char c = src[i];\r
+\r
+               if ((c >= '0' && c <= '9') ||\r
+                       (c >= 'A' && c <= 'Z'))\r
+               {\r
+                       char tmp[2];\r
+                       tmp[0] = c;\r
+                       tmp[1] = 0;\r
+\r
+                       StrCat(dst, size, tmp);\r
+               }\r
+       }\r
+}\r
+\r
+// ユーザーが指定したコマンドが既存のコマンドに一致するかどうかチェックする\r
+bool IsNameInRealName(char *input_name, char *real_name)\r
+{\r
+       // 引数チェック\r
+       if (input_name == NULL || real_name == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (StartWith(real_name, input_name))\r
+       {\r
+               return true;\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+// コマンドリストをパースする\r
+LIST *ParseCommandList(CONSOLE *c, char *cmd_name, wchar_t *command, PARAM param[], UINT num_param)\r
+{\r
+       UINT i;\r
+       LIST *o;\r
+       bool ok = true;\r
+       TOKEN_LIST *param_list;\r
+       TOKEN_LIST *real_name_list;\r
+       bool help_mode = false;\r
+       wchar_t *tmp;\r
+       // 引数チェック\r
+       if (c == NULL || command == NULL || (num_param >= 1 && param == NULL) || cmd_name == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       // 初期化\r
+       for (i = 0;i < num_param;i++)\r
+       {\r
+               if (IsEmptyStr(param[i].Name) == false)\r
+               {\r
+                       if (param[i].Name[0] == '[')\r
+                       {\r
+                               param[i].Tmp = "";\r
+                       }\r
+                       else\r
+                       {\r
+                               param[i].Tmp = NULL;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       param[i].Tmp = "";\r
+               }\r
+       }\r
+\r
+       real_name_list = ZeroMalloc(sizeof(TOKEN_LIST));\r
+       real_name_list->NumTokens = num_param;\r
+       real_name_list->Token = ZeroMalloc(sizeof(char *) * real_name_list->NumTokens);\r
+\r
+       for (i = 0;i < real_name_list->NumTokens;i++)\r
+       {\r
+               real_name_list->Token[i] = CopyStr(param[i].Name);\r
+       }\r
+\r
+       // ユーザーが指定したパラメータ名のリストを生成する\r
+       param_list = GetCommandNameList(command);\r
+\r
+       for (i = 0;i < param_list->NumTokens;i++)\r
+       {\r
+               char *s = param_list->Token[i];\r
+\r
+               if (StrCmpi(s, "help") == 0 || StrCmpi(s, "?") == 0)\r
+               {\r
+                       help_mode = true;\r
+                       break;\r
+               }\r
+       }\r
+\r
+       tmp = ParseCommand(command, L"");\r
+       if (tmp != NULL)\r
+       {\r
+               if (UniStrCmpi(tmp, L"?") == 0)\r
+               {\r
+                       help_mode = true;\r
+               }\r
+               Free(tmp);\r
+       }\r
+\r
+       if (help_mode)\r
+       {\r
+               // ヘルプを表示\r
+               PrintCmdHelp(c, cmd_name, real_name_list);\r
+               FreeToken(param_list);\r
+               FreeToken(real_name_list);\r
+               return NULL;\r
+       }\r
+\r
+       for (i = 0;i < param_list->NumTokens;i++)\r
+       {\r
+               // ユーザーが指定したすべてのパラメータ名について対応するコマンドを取得する\r
+               TOKEN_LIST *candidate = GetRealnameCandidate(param_list->Token[i], real_name_list);\r
+\r
+               if (candidate != NULL && candidate->NumTokens >= 1)\r
+               {\r
+                       if (candidate->NumTokens >= 2)\r
+                       {\r
+                               wchar_t tmp[MAX_SIZE];\r
+\r
+                               // 2 つ以上の候補がある\r
+                               UniFormat(tmp, sizeof(tmp), _UU("CON_AMBIGIOUS_PARAM"), param_list->Token[i]);\r
+                               c->Write(c, tmp);\r
+                               UniFormat(tmp, sizeof(tmp), _UU("CON_AMBIGIOUS_PARAM_1"), cmd_name);\r
+                               c->Write(c, tmp);\r
+\r
+                               PrintCandidateHelp(c, cmd_name, candidate, 1);\r
+\r
+                               c->Write(c, _UU("CON_AMBIGIOUS_PARAM_2"));\r
+\r
+                               ok = false;\r
+                       }\r
+                       else\r
+                       {\r
+                               UINT j;\r
+                               char *real_name = candidate->Token[0];\r
+\r
+                               // 候補が 1 つだけしか無い\r
+                               for (j = 0;j < num_param;j++)\r
+                               {\r
+                                       if (StrCmpi(param[j].Name, real_name) == 0)\r
+                                       {\r
+                                               param[j].Tmp = param_list->Token[i];\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       wchar_t tmp[MAX_SIZE];\r
+\r
+                       // 候補無し\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CON_INVALID_PARAM"), param_list->Token[i], cmd_name, cmd_name);\r
+                       c->Write(c, tmp);\r
+\r
+                       ok = false;\r
+               }\r
+\r
+               FreeToken(candidate);\r
+       }\r
+\r
+       if (ok == false)\r
+       {\r
+               FreeToken(param_list);\r
+               FreeToken(real_name_list);\r
+\r
+               return NULL;\r
+       }\r
+\r
+       // リストの作成\r
+       o = NewParamValueList();\r
+\r
+       // パラメータ一覧に指定された名前のすべてのパラメータを読み込む\r
+       for (i = 0;i < num_param;i++)\r
+       {\r
+               bool prompt_input_value = false;\r
+               PARAM *p = &param[i];\r
+\r
+               if (p->Tmp != NULL || p->PromptProc != NULL)\r
+               {\r
+                       wchar_t *name = CopyStrToUni(p->Name);\r
+                       wchar_t *tmp;\r
+                       wchar_t *str;\r
+\r
+                       if (p->Tmp != NULL)\r
+                       {\r
+                               tmp = CopyStrToUni(p->Tmp);\r
+                       }\r
+                       else\r
+                       {\r
+                               tmp = CopyStrToUni(p->Name);\r
+                       }\r
+\r
+                       str = ParseCommand(command, tmp);\r
+                       Free(tmp);\r
+                       if (str != NULL)\r
+                       {\r
+                               wchar_t *unistr;\r
+                               bool ret;\r
+EVAL_VALUE:\r
+                               // 読み込みに成功した\r
+                               unistr = str;\r
+\r
+                               if (p->EvalProc != NULL)\r
+                               {\r
+                                       // EvalProc が指定されている場合は値を評価する\r
+                                       ret = p->EvalProc(c, unistr, p->EvalProcParam);\r
+                               }\r
+                               else\r
+                               {\r
+                                       // EvalProc が指定されていない場合はどのような値でも受け付ける\r
+                                       ret = true;\r
+                               }\r
+\r
+                               if (ret == false)\r
+                               {\r
+                                       // 指定した値は不正である\r
+                                       if (p->PromptProc == NULL)\r
+                                       {\r
+                                               // キャンセル\r
+                                               ok = false;\r
+                                               Free(name);\r
+                                               Free(str);\r
+                                               break;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               // もう一度入力させる\r
+                                               Free(str);\r
+                                               str = NULL;\r
+                                               goto SHOW_PROMPT;\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       PARAM_VALUE *v;\r
+                                       // 読み込み完了したのでリストに追加する\r
+                                       v = ZeroMalloc(sizeof(PARAM_VALUE));\r
+                                       v->Name = CopyStr(p->Name);\r
+                                       v->StrValue = CopyUniToStr(str);\r
+                                       v->UniStrValue = CopyUniStr(str);\r
+                                       v->IntValue = ToInt(v->StrValue);\r
+                                       Insert(o, v);\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               // 読み込みに失敗した。指定されたパラメータが指定されていない\r
+                               if (p->PromptProc != NULL)\r
+                               {\r
+                                       wchar_t *tmp;\r
+SHOW_PROMPT:\r
+                                       // 必須パラメータであるのでプロンプトを表示する\r
+                                       tmp = p->PromptProc(c, p->PromptProcParam);\r
+                                       if (tmp == NULL)\r
+                                       {\r
+                                               // ユーザーがキャンセルした\r
+                                               ok = false;\r
+                                               Free(str);\r
+                                               Free(name);\r
+                                               break;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               // ユーザーが入力した\r
+                                               c->Write(c, L"");\r
+                                               str = tmp;\r
+                                               prompt_input_value = true;\r
+                                               goto EVAL_VALUE;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       Free(str);\r
+                       Free(name);\r
+               }\r
+       }\r
+\r
+       FreeToken(param_list);\r
+       FreeToken(real_name_list);\r
+\r
+       if (ok)\r
+       {\r
+               return o;\r
+       }\r
+       else\r
+       {\r
+               FreeParamValueList(o);\r
+               return NULL;\r
+       }\r
+}\r
+\r
+// [はい] か [いいえ] の取得\r
+bool GetParamYes(LIST *o, char *name)\r
+{\r
+       char *s;\r
+       char tmp[64];\r
+       // 引数チェック\r
+       if (o == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       s = GetParamStr(o, name);\r
+       if (s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       StrCpy(tmp, sizeof(tmp), s);\r
+       Trim(tmp);\r
+\r
+       if (StartWith(tmp, "y"))\r
+       {\r
+               return true;\r
+       }\r
+\r
+       if (StartWith(tmp, "t"))\r
+       {\r
+               return true;\r
+       }\r
+\r
+       if (ToInt(tmp) != 0)\r
+       {\r
+               return true;\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+// パラメータ値 Int の取得\r
+UINT GetParamInt(LIST *o, char *name)\r
+{\r
+       PARAM_VALUE *v;\r
+       // 引数チェック\r
+       if (o == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       v = FindParamValue(o, name);\r
+       if (v == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+       else\r
+       {\r
+               return v->IntValue;\r
+       }\r
+}\r
+\r
+// パラメータ値 Unicode 文字列の取得\r
+wchar_t *GetParamUniStr(LIST *o, char *name)\r
+{\r
+       PARAM_VALUE *v;\r
+       // 引数チェック\r
+       if (o == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       v = FindParamValue(o, name);\r
+       if (v == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+       else\r
+       {\r
+               return v->UniStrValue;\r
+       }\r
+}\r
+\r
+// パラメータ値文字列の所得\r
+char *GetParamStr(LIST *o, char *name)\r
+{\r
+       PARAM_VALUE *v;\r
+       // 引数チェック\r
+       if (o == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       v = FindParamValue(o, name);\r
+       if (v == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+       else\r
+       {\r
+               return v->StrValue;\r
+       }\r
+}\r
+\r
+// パラメータ値の取得\r
+PARAM_VALUE *FindParamValue(LIST *o, char *name)\r
+{\r
+       PARAM_VALUE t, *ret;\r
+       // 引数チェック\r
+       if (o == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+       if (name == NULL)\r
+       {\r
+               name = "";\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       t.Name = name;\r
+\r
+       ret = Search(o, &t);\r
+\r
+       return ret;\r
+}\r
+\r
+// パラメータ値リストの解放\r
+void FreeParamValueList(LIST *o)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (o == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       for (i = 0;i < LIST_NUM(o);i++)\r
+       {\r
+               PARAM_VALUE *v = LIST_DATA(o, i);\r
+\r
+               Free(v->StrValue);\r
+               Free(v->UniStrValue);\r
+               Free(v->Name);\r
+               Free(v);\r
+       }\r
+\r
+       ReleaseList(o);\r
+}\r
+\r
+// パラメータ値リストソート関数\r
+int CmpParamValue(void *p1, void *p2)\r
+{\r
+       PARAM_VALUE *v1, *v2;\r
+       if (p1 == NULL || p2 == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+       v1 = *(PARAM_VALUE **)p1;\r
+       v2 = *(PARAM_VALUE **)p2;\r
+       if (v1 == NULL || v2 == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       if (IsEmptyStr(v1->Name) && IsEmptyStr(v2->Name))\r
+       {\r
+               return 0;\r
+       }\r
+       return StrCmpi(v1->Name, v2->Name);\r
+}\r
+\r
+// パラメータ値リストの生成\r
+LIST *NewParamValueList()\r
+{\r
+       return NewListFast(CmpParamValue);\r
+}\r
+\r
+// 入力されたコマンドに含まれていたパラメータ名のリストを取得する\r
+TOKEN_LIST *GetCommandNameList(wchar_t *str)\r
+{\r
+       TOKEN_LIST *t;\r
+       // 引数チェック\r
+       if (str == NULL)\r
+       {\r
+               return NullToken();\r
+       }\r
+\r
+       Free(ParseCommandEx(str, L"dummy_str", &t));\r
+\r
+       return t;\r
+}\r
+\r
+// 指定した名前で始まるコマンドを取得する\r
+wchar_t *ParseCommand(wchar_t *str, wchar_t *name)\r
+{\r
+       return ParseCommandEx(str, name, NULL);\r
+}\r
+wchar_t *ParseCommandEx(wchar_t *str, wchar_t *name, TOKEN_LIST **param_list)\r
+{\r
+       UNI_TOKEN_LIST *t;\r
+       UINT i;\r
+       wchar_t *tmp;\r
+       wchar_t *ret = NULL;\r
+       LIST *o;\r
+       // 引数チェック\r
+       if (str == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+       if (name != NULL && UniIsEmptyStr(name))\r
+       {\r
+               name = NULL;\r
+       }\r
+\r
+       o = NULL;\r
+       if (param_list != NULL)\r
+       {\r
+               o = NewListFast(CompareStr);\r
+       }\r
+\r
+       tmp = CopyUniStr(str);\r
+       UniTrim(tmp);\r
+\r
+       i = UniSearchStrEx(tmp, L"/CMD ", 0, false);\r
+\r
+       // このあたりは急いで実装したのでコードがあまり美しくない。\r
+       if (i != INFINITE && i >= 1 && tmp[i - 1] == L'/')\r
+       {\r
+               i = INFINITE;\r
+       }\r
+       if (i == INFINITE)\r
+       {\r
+               i = UniSearchStrEx(tmp, L"/CMD\t", 0, false);\r
+               if (i != INFINITE && i >= 1 && tmp[i - 1] == L'/')\r
+               {\r
+                       i = INFINITE;\r
+               }\r
+       }\r
+       if (i == INFINITE)\r
+       {\r
+               i = UniSearchStrEx(tmp, L"/CMD:", 0, false);\r
+               if (i != INFINITE && i >= 1 && tmp[i - 1] == L'/')\r
+               {\r
+                       i = INFINITE;\r
+               }\r
+       }\r
+       if (i == INFINITE)\r
+       {\r
+               i = UniSearchStrEx(tmp, L"/CMD=", 0, false);\r
+               if (i != INFINITE && i >= 1 && tmp[i - 1] == L'/')\r
+               {\r
+                       i = INFINITE;\r
+               }\r
+       }\r
+       if (i == INFINITE)\r
+       {\r
+               i = UniSearchStrEx(tmp, L"-CMD ", 0, false);\r
+               if (i != INFINITE && i >= 1 && tmp[i - 1] == L'-')\r
+               {\r
+                       i = INFINITE;\r
+               }\r
+       }\r
+       if (i == INFINITE)\r
+       {\r
+               i = UniSearchStrEx(tmp, L"-CMD\t", 0, false);\r
+               if (i != INFINITE && i >= 1 && tmp[i - 1] == L'-')\r
+               {\r
+                       i = INFINITE;\r
+               }\r
+       }\r
+       if (i == INFINITE)\r
+       {\r
+               i = UniSearchStrEx(tmp, L"-CMD:", 0, false);\r
+               if (i != INFINITE && i >= 1 && tmp[i - 1] == L'-')\r
+               {\r
+                       i = INFINITE;\r
+               }\r
+       }\r
+       if (i == INFINITE)\r
+       {\r
+               i = UniSearchStrEx(tmp, L"-CMD=", 0, false);\r
+               if (i != INFINITE && i >= 1 && tmp[i - 1] == L'-')\r
+               {\r
+                       i = INFINITE;\r
+               }\r
+       }\r
+\r
+       if (i != INFINITE)\r
+       {\r
+               char *s = CopyStr("CMD");\r
+               if (InsertStr(o, s) == false)\r
+               {\r
+                       Free(s);\r
+               }\r
+               if (UniStrCmpi(name, L"CMD") == 0)\r
+               {\r
+                       ret = CopyUniStr(&str[i + 5]);\r
+                       UniTrim(ret);\r
+               }\r
+               else\r
+               {\r
+                       tmp[i] = 0;\r
+               }\r
+       }\r
+\r
+       if (ret == NULL)\r
+       {\r
+               t = UniParseCmdLine(tmp);\r
+\r
+               if (t != NULL)\r
+               {\r
+                       for (i = 0;i < t->NumTokens;i++)\r
+                       {\r
+                               wchar_t *token = t->Token[i];\r
+\r
+                               if ((token[0] == L'-' && token[1] != L'-') ||\r
+                                       (UniStrCmpi(token, L"--help") == 0) ||\r
+                                       (token[0] == L'/' && token[1] != L'/'))\r
+                               {\r
+                                       UINT i;\r
+\r
+                                       // 名前付き引数\r
+                                       // コロン文字があるかどうか調べる\r
+\r
+                                       if (UniStrCmpi(token, L"--help") == 0)\r
+                                       {\r
+                                               token++;\r
+                                       }\r
+\r
+                                       i = UniSearchStrEx(token, L":", 0, false);\r
+                                       if (i == INFINITE)\r
+                                       {\r
+                                               i = UniSearchStrEx(token, L"=", 0, false);\r
+                                       }\r
+                                       if (i != INFINITE)\r
+                                       {\r
+                                               wchar_t *tmp;\r
+                                               char *a;\r
+\r
+                                               // コロン文字がある\r
+                                               tmp = CopyUniStr(token);\r
+                                               tmp[i] = 0;\r
+\r
+                                               a = CopyUniToStr(&tmp[1]);\r
+                                               if (InsertStr(o, a) == false)\r
+                                               {\r
+                                                       Free(a);\r
+                                               }\r
+\r
+                                               if (UniStrCmpi(name, &tmp[1]) == 0)\r
+                                               {\r
+                                                       if (ret == NULL)\r
+                                                       {\r
+                                                               // 内容\r
+                                                               ret = UniCopyStr(&token[i + 1]);\r
+                                                       }\r
+                                               }\r
+\r
+                                               Free(tmp);\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               // コロン文字が無い\r
+                                               char *a;\r
+\r
+                                               a = CopyUniToStr(&token[1]);\r
+                                               if (InsertStr(o, a) == false)\r
+                                               {\r
+                                                       Free(a);\r
+                                               }\r
+\r
+                                               if (UniStrCmpi(name, &token[1]) == 0)\r
+                                               {\r
+                                                       if (ret == NULL)\r
+                                                       {\r
+                                                               // 空文字\r
+                                                               ret = UniCopyStr(L"");\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       // 名前無し引数\r
+                                       if (name == NULL)\r
+                                       {\r
+                                               if (ret == NULL)\r
+                                               {\r
+                                                       if (token[0] == L'-' && token[1] == L'-')\r
+                                                       {\r
+                                                               ret = UniCopyStr(&token[1]);\r
+                                                       }\r
+                                                       else if (token[0] == L'/' && token[1] == L'/')\r
+                                                       {\r
+                                                               ret = UniCopyStr(&token[1]);\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               ret = UniCopyStr(token);\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       UniFreeToken(t);\r
+               }\r
+       }\r
+\r
+       Free(tmp);\r
+\r
+       if (o != NULL)\r
+       {\r
+               TOKEN_LIST *t = ZeroMalloc(sizeof(TOKEN_LIST));\r
+               UINT i;\r
+\r
+               t->NumTokens = LIST_NUM(o);\r
+               t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);\r
+\r
+               for (i = 0;i < t->NumTokens;i++)\r
+               {\r
+                       t->Token[i] = LIST_DATA(o, i);\r
+               }\r
+\r
+               ReleaseList(o);\r
+\r
+               *param_list = t;\r
+       }\r
+\r
+       if (UniStrCmpi(ret, L"none") == 0 || UniStrCmpi(ret, L"null") == 0)\r
+       {\r
+               // none と null は予約語である\r
+               ret[0] = 0;\r
+       }\r
+\r
+       return ret;\r
+}\r
+char *ParseCommandA(wchar_t *str, char *name)\r
+{\r
+       wchar_t *tmp1, *tmp2;\r
+       char *ret;\r
+       // 引数チェック\r
+       if (str == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       if (name != NULL)\r
+       {\r
+               tmp1 = CopyStrToUni(name);\r
+       }\r
+       else\r
+       {\r
+               tmp1 = NULL;\r
+       }\r
+\r
+       tmp2 = ParseCommand(str, tmp1);\r
+\r
+       if (tmp2 == NULL)\r
+       {\r
+               ret = NULL;\r
+       }\r
+       else\r
+       {\r
+               ret = CopyUniToStr(tmp2);\r
+               Free(tmp2);\r
+       }\r
+\r
+       Free(tmp1);\r
+\r
+       return ret;\r
+}\r
+\r
+// パスワードプロンプト\r
+bool PasswordPrompt(char *password, UINT size)\r
+{\r
+       UINT wp;\r
+       bool escape = false;\r
+       void *console;\r
+       // 引数チェック\r
+       if (password == NULL || size <= 1)\r
+       {\r
+               if (size >= 1)\r
+               {\r
+                       password[0] = 0;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       wp = 0;\r
+\r
+       Zero(password, size);\r
+\r
+       console = SetConsoleRaw();\r
+\r
+       while (true)\r
+       {\r
+               int c;\r
+\r
+#ifdef OS_WIN32\r
+               c = getch();\r
+#else  // OS_WIN32\r
+               c = getc(stdin);\r
+#endif // OS_WIN32\r
+\r
+               if (c >= 0x20 && c <= 0x7E)\r
+               {\r
+                       // 文字\r
+                       if ((wp + 1) < size)\r
+                       {\r
+                               password[wp++] = (char)c;\r
+                               putc('*', stdout);\r
+                       }\r
+               }\r
+               else if (c == 0x03)\r
+               {\r
+                       // 強制終了\r
+                       exit(0);\r
+               }\r
+               else if (c == 0x04 || c == 0x1a || c == 0x0D || c==0x0A)\r
+               {\r
+                       // 終了\r
+                       if (c == 0x04 || c == 0x1a)\r
+                       {\r
+                               escape = true;\r
+                       }\r
+                       break;\r
+               }\r
+               else if (c == 0xE0)\r
+               {\r
+                       // もう 1 文字読む\r
+                       c = getch();\r
+                       if (c == 0x4B || c == 0x53)\r
+                       {\r
+                               // バックスペース\r
+                               goto BACKSPACE;\r
+                       }\r
+               }\r
+               else if (c == 0x08)\r
+               {\r
+BACKSPACE:\r
+                       // バックスペース\r
+                       if (wp >= 1)\r
+                       {\r
+                               password[--wp] = 0;\r
+                               putc(0x08, stdout);\r
+                               putc(' ', stdout);\r
+                               putc(0x08, stdout);\r
+                       }\r
+               }\r
+       }\r
+       Print("\n");\r
+\r
+       RestoreConsole(console);\r
+\r
+       return (escape ? false : true);\r
+}\r
+\r
+// プロンプトを表示\r
+wchar_t *Prompt(wchar_t *prompt_str)\r
+{\r
+       wchar_t *ret = NULL;\r
+       wchar_t *tmp = NULL;\r
+       // 引数チェック\r
+       if (prompt_str == NULL)\r
+       {\r
+               prompt_str = L"";\r
+       }\r
+\r
+#ifdef OS_WIN32\r
+       UniPrint(L"%s", prompt_str);\r
+       tmp = Malloc(MAX_PROMPT_STRSIZE);\r
+       if (fgetws(tmp, MAX_PROMPT_STRSIZE - 1, stdin) != NULL)\r
+       {\r
+               bool escape = false;\r
+               UINT i, len;\r
+\r
+               len = UniStrLen(tmp);\r
+               for (i = 0;i < len;i++)\r
+               {\r
+                       if (tmp[i] == 0x04 || tmp[i] == 0x1A)\r
+                       {\r
+                               escape = true;\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               if (escape == false)\r
+               {\r
+                       UniTrimCrlf(tmp);\r
+\r
+                       ret = UniCopyStr(tmp);\r
+               }\r
+       }\r
+       Free(tmp);\r
+#else  // OS_WIN32\r
+       {\r
+               char *prompt = CopyUniToStr(prompt_str);\r
+               char *s = readline(prompt);\r
+               Free(prompt);\r
+\r
+               if (s != NULL)\r
+               {\r
+                       TrimCrlf(s);\r
+                       Trim(s);\r
+\r
+                       if (IsEmptyStr(s) == false)\r
+                       {\r
+                               add_history(s);\r
+                       }\r
+\r
+                       ret = CopyStrToUni(s);\r
+\r
+                       free(s);\r
+               }\r
+       }\r
+#endif // OS_WIN32\r
+\r
+       if (ret == NULL)\r
+       {\r
+               Print("\n");\r
+       }\r
+\r
+       return ret;\r
+}\r
+char *PromptA(wchar_t *prompt_str)\r
+{\r
+       wchar_t *str = Prompt(prompt_str);\r
+\r
+       if (str == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+       else\r
+       {\r
+               char *ret = CopyUniToStr(str);\r
+\r
+               Free(str);\r
+               return ret;\r
+       }\r
+}\r
+\r
+// コンソールを Raw モードにする\r
+void *SetConsoleRaw()\r
+{\r
+#ifdef OS_UNIX\r
+       struct termios t, *ret;\r
+\r
+       Zero(&t, sizeof(t));\r
+       if (tcgetattr(0, &t) != 0)\r
+       {\r
+               // 失敗\r
+               return NULL;\r
+       }\r
+\r
+       // 現在の設定をコピー\r
+       ret = Clone(&t, sizeof(t));\r
+\r
+       // 設定を変更\r
+       t.c_lflag &= (~ICANON);\r
+       t.c_lflag &= (~ECHO);\r
+       t.c_cc[VTIME] = 0;\r
+       t.c_cc[VMIN] = 1;\r
+       tcsetattr(0, TCSANOW, &t);\r
+\r
+       return ret;\r
+#else  // OS_UNIX\r
+       return Malloc(0);\r
+#endif // OS_UNIX\r
+}\r
+\r
+// コンソールのモードを復帰する\r
+void RestoreConsole(void *p)\r
+{\r
+#ifdef OS_UNIX\r
+       struct termios *t;\r
+       // 引数チェック\r
+       if (p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       t = (struct termios *)p;\r
+\r
+       // 設定を復帰する\r
+       tcsetattr(0, TCSANOW, t);\r
+\r
+       Free(t);\r
+#else  // OS_UNIX\r
+       if (p != NULL)\r
+       {\r
+               Free(p);\r
+       }\r
+#endif // OS_UNIX\r
+}\r
+\r
+////////////////////////////\r
+// ローカルコンソール関数\r
+\r
+// 新しいローカルコンソールの作成\r
+CONSOLE *NewLocalConsole(wchar_t *infile, wchar_t *outfile)\r
+{\r
+       IO *in_io = NULL, *out_io = NULL;\r
+       CONSOLE *c = ZeroMalloc(sizeof(CONSOLE));\r
+       LOCAL_CONSOLE_PARAM *p;\r
+       UINT old_size = 0;\r
+\r
+#ifdef OS_WIN32\r
+       if (MsGetConsoleWidth() == 80)\r
+       {\r
+               //old_size = MsSetConsoleWidth(WIN32_DEFAULT_CONSOLE_WIDTH);\r
+       }\r
+#endif // OS_WIN32\r
+\r
+       c->ConsoleType = CONSOLE_LOCAL;\r
+       c->Free = ConsoleLocalFree;\r
+       c->ReadLine = ConsoleLocalReadLine;\r
+       c->ReadPassword = ConsoleLocalReadPassword;\r
+       c->Write = ConsoleLocalWrite;\r
+       c->GetWidth = ConsoleLocalGetWidth;\r
+\r
+       if (UniIsEmptyStr(infile) == false)\r
+       {\r
+               // 入力ファイルが指定されている\r
+               in_io = FileOpenW(infile, false);\r
+               if (in_io == NULL)\r
+               {\r
+                       wchar_t tmp[MAX_SIZE];\r
+\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CON_INFILE_ERROR"), infile);\r
+                       c->Write(c, tmp);\r
+                       Free(c);\r
+                       return NULL;\r
+               }\r
+               else\r
+               {\r
+                       wchar_t tmp[MAX_SIZE];\r
+\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CON_INFILE_START"), infile);\r
+                       c->Write(c, tmp);\r
+               }\r
+       }\r
+\r
+       if (UniIsEmptyStr(outfile) == false)\r
+       {\r
+               // 出力ファイルが指定されている\r
+               out_io = FileCreateW(outfile);\r
+               if (out_io == NULL)\r
+               {\r
+                       wchar_t tmp[MAX_SIZE];\r
+\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CON_OUTFILE_ERROR"), outfile);\r
+                       c->Write(c, tmp);\r
+                       Free(c);\r
+\r
+                       if (in_io != NULL)\r
+                       {\r
+                               FileClose(in_io);\r
+                       }\r
+                       return NULL;\r
+               }\r
+               else\r
+               {\r
+                       wchar_t tmp[MAX_SIZE];\r
+\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CON_OUTFILE_START"), outfile);\r
+                       c->Write(c, tmp);\r
+               }\r
+       }\r
+\r
+       p = ZeroMalloc(sizeof(LOCAL_CONSOLE_PARAM));\r
+       c->Param = p;\r
+\r
+       p->InFile = in_io;\r
+       p->OutFile = out_io;\r
+       p->Win32_OldConsoleWidth = old_size;\r
+\r
+       if (in_io != NULL)\r
+       {\r
+               UINT size;\r
+               void *buf;\r
+\r
+               size = FileSize(in_io);\r
+               buf = ZeroMalloc(size + 1);\r
+               FileRead(in_io, buf, size);\r
+\r
+               p->InBuf = NewBuf();\r
+               WriteBuf(p->InBuf, buf, size);\r
+               Free(buf);\r
+\r
+               p->InBuf->Current = 0;\r
+       }\r
+\r
+       return c;\r
+}\r
+\r
+// コンソール解放\r
+void ConsoleLocalFree(CONSOLE *c)\r
+{\r
+       LOCAL_CONSOLE_PARAM *p;\r
+       // 引数チェック\r
+       if (c == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       p = (LOCAL_CONSOLE_PARAM *)c->Param;\r
+\r
+#ifdef OS_WIN32\r
+       if (p->Win32_OldConsoleWidth != 0)\r
+       {\r
+               MsSetConsoleWidth(p->Win32_OldConsoleWidth);\r
+       }\r
+#endif // OS_WIN32\r
+\r
+       if (p != NULL)\r
+       {\r
+               if (p->InFile != NULL)\r
+               {\r
+                       FileClose(p->InFile);\r
+                       FreeBuf(p->InBuf);\r
+               }\r
+\r
+               if (p->OutFile != NULL)\r
+               {\r
+                       FileClose(p->OutFile);\r
+               }\r
+\r
+               Free(p);\r
+       }\r
+\r
+       // メモリ解放\r
+       Free(c);\r
+}\r
+\r
+// 画面の横幅を取得\r
+UINT ConsoleLocalGetWidth(CONSOLE *c)\r
+{\r
+       UINT ret = 0;\r
+       // 引数チェック\r
+       if (c == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+#ifdef OS_WIN32\r
+       ret = MsGetConsoleWidth();\r
+#else  // OS_WIN32\r
+       {\r
+               struct winsize t;\r
+\r
+               Zero(&t, sizeof(t));\r
+\r
+               if (ioctl(1, TIOCGWINSZ, &t) == 0)\r
+               {\r
+                       ret = t.ws_col;\r
+               }\r
+       }\r
+#endif // OS_WIN32\r
+\r
+       return ret;\r
+}\r
+\r
+// コンソールから 1 行読み込む\r
+wchar_t *ConsoleLocalReadLine(CONSOLE *c, wchar_t *prompt, bool nofile)\r
+{\r
+       wchar_t *ret;\r
+       LOCAL_CONSOLE_PARAM *p;\r
+       // 引数チェック\r
+       if (c == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+       p = (LOCAL_CONSOLE_PARAM *)c->Param;\r
+       if (prompt == NULL)\r
+       {\r
+               prompt = L">";\r
+       }\r
+\r
+       ConsoleWriteOutFile(c, prompt, false);\r
+\r
+       if (nofile == false && p->InBuf != NULL)\r
+       {\r
+               // ファイルから次の行を読み込む\r
+               ret = ConsoleReadNextFromInFile(c);\r
+\r
+               if (ret != NULL)\r
+               {\r
+                       // 擬似プロンプトを表示する\r
+                       UniPrint(L"%s", prompt);\r
+\r
+                       // 画面に描画する\r
+                       UniPrint(L"%s\n", ret);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               // 画面から次の行を読み込む\r
+               ret = Prompt(prompt);\r
+       }\r
+\r
+       if (ret != NULL)\r
+       {\r
+               ConsoleWriteOutFile(c, ret, true);\r
+       }\r
+       else\r
+       {\r
+               ConsoleWriteOutFile(c, _UU("CON_USER_CANCEL"), true);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// コンソールからパスワードを読み込む\r
+char *ConsoleLocalReadPassword(CONSOLE *c, wchar_t *prompt)\r
+{\r
+       char tmp[64];\r
+       // 引数チェック\r
+       if (c == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+       if (prompt == NULL)\r
+       {\r
+               prompt = L"Password>";\r
+       }\r
+\r
+       UniPrint(L"%s", prompt);\r
+       ConsoleWriteOutFile(c, prompt, false);\r
+\r
+       if (PasswordPrompt(tmp, sizeof(tmp)))\r
+       {\r
+               ConsoleWriteOutFile(c, L"********", true);\r
+               return CopyStr(tmp);\r
+       }\r
+       else\r
+       {\r
+               ConsoleWriteOutFile(c, _UU("CON_USER_CANCEL"), true);\r
+               return NULL;\r
+       }\r
+}\r
+\r
+// コンソールに文字列を表示する\r
+bool ConsoleLocalWrite(CONSOLE *c, wchar_t *str)\r
+{\r
+       // 引数チェック\r
+       if (c == NULL || str == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       UniPrint(L"%s%s", str, (UniEndWith(str, L"\n") ? L"" : L"\n"));\r
+\r
+       ConsoleWriteOutFile(c, str, true);\r
+\r
+       return true;\r
+}\r
+\r
+// 入力ファイルから次の 1 行を読み込む\r
+wchar_t *ConsoleReadNextFromInFile(CONSOLE *c)\r
+{\r
+       LOCAL_CONSOLE_PARAM *p;\r
+       char *str;\r
+       // 引数チェック\r
+       if (c == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       p = (LOCAL_CONSOLE_PARAM *)c->Param;\r
+\r
+       if (p->InBuf == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       while (true)\r
+       {\r
+               str = CfgReadNextLine(p->InBuf);\r
+\r
+               if (str == NULL)\r
+               {\r
+                       return NULL;\r
+               }\r
+\r
+               Trim(str);\r
+\r
+               if (IsEmptyStr(str) == false)\r
+               {\r
+                       UINT size;\r
+                       wchar_t *ret;\r
+\r
+                       size = CalcUtf8ToUni((BYTE *)str, StrLen(str));\r
+                       ret = ZeroMalloc(size + 32);\r
+                       Utf8ToUni(ret, size, (BYTE *)str, StrLen(str));\r
+\r
+                       Free(str);\r
+\r
+                       return ret;\r
+               }\r
+\r
+               Free(str);\r
+       }\r
+}\r
+\r
+// 出力ファイルが指定されている場合は書き出す\r
+void ConsoleWriteOutFile(CONSOLE *c, wchar_t *str, bool add_last_crlf)\r
+{\r
+       LOCAL_CONSOLE_PARAM *p;\r
+       // 引数チェック\r
+       if (c == NULL || str == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       p = (LOCAL_CONSOLE_PARAM *)c->Param;\r
+\r
+       if (p != NULL && p->OutFile != NULL)\r
+       {\r
+               wchar_t *tmp = UniNormalizeCrlf(str);\r
+               UINT utf8_size;\r
+               UCHAR *utf8;\r
+\r
+               utf8_size = CalcUniToUtf8(tmp);\r
+               utf8 = ZeroMalloc(utf8_size + 1);\r
+               UniToUtf8(utf8, utf8_size + 1, tmp);\r
+\r
+               FileWrite(p->OutFile, utf8, utf8_size);\r
+\r
+               if (UniEndWith(str, L"\n") == false && add_last_crlf)\r
+               {\r
+                       char *crlf = "\r\n";\r
+                       FileWrite(p->OutFile, "\r\n", StrLen(crlf));\r
+               }\r
+\r
+               Free(utf8);\r
+               Free(tmp);\r
+       }\r
+\r
+}\r
+\r