1 // SoftEther UT-VPN SourceCode
\r
3 // Copyright (C) 2004-2010 SoftEther Corporation.
\r
4 // Copyright (C) 2004-2010 University of Tsukuba, Japan.
\r
5 // Copyright (C) 2003-2010 Daiyuu Nobori.
\r
6 // All Rights Reserved.
\r
8 // http://utvpn.tsukuba.ac.jp/
\r
10 // This program is free software; you can redistribute it and/or
\r
11 // modify it under the terms of the GNU General Public License
\r
12 // version 2 as published by the Free Software Foundation.
\r
14 // This program is distributed in the hope that it will be useful,
\r
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
17 // GNU General Public License for more details.
\r
19 // You should have received a copy of the GNU General Public License version 2
\r
20 // along with this program; if not, write to the Free Software
\r
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
\r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。
\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布
\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示
\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の
\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。
\r
29 // この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の
\r
30 // ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )
\r
31 // および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって
\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、
\r
34 // および、試験または研究のために利用が行われることを想定して配布
\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に
\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード
\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して
\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して
\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース
\r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する
\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。
\r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社
\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。
\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの
\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意
\r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の
\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、
\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの
\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社
\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、
\r
58 // 公益保護にご協力いただきますようお願い申し上げます。
\r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を
\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客
\r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/
\r
65 // 日本国内の脆弱性情報届出受付公的機関:
\r
67 // http://www.ipa.go.jp/security/vuln/report/
\r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。
\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/
\r
72 // -----------------------------------------------
\r
75 // 新規リリース by SoftEther
\r
76 // -----------------------------------------------
\r
81 #include "CedarPch.h"
\r
85 void PrintCmdHelp(CONSOLE *c, char *cmd_name, TOKEN_LIST *param_list)
\r
87 wchar_t tmp[MAX_SIZE];
\r
90 wchar_t *description, *args, *help;
\r
96 if (c == NULL || cmd_name == NULL || param_list == NULL)
\r
101 width = GetConsoleWidth(c) - 2;
\r
103 buf_size = sizeof(wchar_t) * (width + 32);
\r
104 buf = Malloc(buf_size);
\r
106 GetCommandHelpStr(cmd_name, &description, &args, &help);
\r
108 space = MakeCharArray(' ', 2);
\r
111 UniFormat(tmp, sizeof(tmp), _UU("CMD_HELP_TITLE"), cmd_name);
\r
116 c->Write(c, _UU("CMD_HELP_DESCRIPTION"));
\r
117 t = SeparateStringByWidth(description, width - 2);
\r
118 for (i = 0;i < t->NumTokens;i++)
\r
120 UniFormat(buf, buf_size, L"%S%s", space, t->Token[i]);
\r
127 c->Write(c, _UU("CMD_HELP_HELP"));
\r
128 t = SeparateStringByWidth(help, width - 2);
\r
129 for (i = 0;i < t->NumTokens;i++)
\r
131 UniFormat(buf, buf_size, L"%S%s", space, t->Token[i]);
\r
138 c->Write(c, _UU("CMD_HELP_USAGE"));
\r
139 t = SeparateStringByWidth(args, width - 2);
\r
140 for (i = 0;i < t->NumTokens;i++)
\r
142 UniFormat(buf, buf_size, L"%S%s", space, t->Token[i]);
\r
148 if (param_list->NumTokens >= 1)
\r
151 c->Write(c, _UU("CMD_HELP_ARGS"));
\r
152 PrintCandidateHelp(c, cmd_name, param_list, 2);
\r
160 // SafeStr であるかどうかの評価
\r
161 bool CmdEvalSafe(CONSOLE *c, wchar_t *str, void *param)
\r
163 wchar_t *p = (param == NULL) ? _UU("CMD_EVAL_SAFE") : (wchar_t *)param;
\r
165 if (IsSafeUniStr(str))
\r
176 wchar_t *CmdPrompt(CONSOLE *c, void *param)
\r
178 wchar_t *p = (param == NULL) ? _UU("CMD_PROMPT") : (wchar_t *)param;
\r
180 return c->ReadLine(c, p, true);
\r
183 // 指定されたファイルが存在するかどうか評価
\r
184 bool CmdEvalIsFile(CONSOLE *c, wchar_t *str, void *param)
\r
186 char tmp[MAX_PATH];
\r
188 if (c == NULL || str == NULL)
\r
193 UniToStr(tmp, sizeof(tmp), str);
\r
195 if (IsEmptyStr(tmp))
\r
197 c->Write(c, _UU("CMD_FILE_NAME_EMPTY"));
\r
201 if (IsFileExists(tmp) == false)
\r
203 wchar_t tmp2[MAX_SIZE];
\r
205 UniFormat(tmp2, sizeof(tmp2), _UU("CMD_FILE_NOT_FOUND"), tmp);
\r
215 bool CmdEvalInt1(CONSOLE *c, wchar_t *str, void *param)
\r
217 wchar_t *p = (param == NULL) ? _UU("CMD_EVAL_INT") : (wchar_t *)param;
\r
219 if (UniToInt(str) == 0)
\r
229 // 空白を指定できないパラメータの評価
\r
230 bool CmdEvalNotEmpty(CONSOLE *c, wchar_t *str, void *param)
\r
232 wchar_t *p = (param == NULL) ? _UU("CMD_EVAL_NOT_EMPTY") : (wchar_t *)param;
\r
234 if (UniIsEmptyStr(str) == false)
\r
244 // パラメータの最小 / 最大値評価関数
\r
245 bool CmdEvalMinMax(CONSOLE *c, wchar_t *str, void *param)
\r
247 CMD_EVAL_MIN_MAX *e;
\r
256 e = (CMD_EVAL_MIN_MAX *)param;
\r
258 if (e->StrName == NULL)
\r
260 tag = _UU("CMD_EVAL_MIN_MAX");
\r
264 tag = _UU(e->StrName);
\r
269 if (v >= e->MinValue && v <= e->MaxValue)
\r
275 wchar_t tmp[MAX_SIZE];
\r
277 UniFormat(tmp, sizeof(tmp), tag, e->MinValue, e->MaxValue);
\r
284 // コマンドのヘルプ文字列を取得する
\r
285 void GetCommandHelpStr(char *command_name, wchar_t **description, wchar_t **args, wchar_t **help)
\r
287 char tmp1[128], tmp2[128], tmp3[128];
\r
289 Format(tmp1, sizeof(tmp1), "CMD_%s", command_name);
\r
290 Format(tmp2, sizeof(tmp2), "CMD_%s_ARGS", command_name);
\r
291 Format(tmp3, sizeof(tmp3), "CMD_%s_HELP", command_name);
\r
293 if (description != NULL)
\r
295 *description = _UU(tmp1);
\r
296 if (UniIsEmptyStr(*description))
\r
298 *description = _UU("CMD_UNKNOWM");
\r
305 if (UniIsEmptyStr(*args))
\r
307 *args = _UU("CMD_UNKNOWN_ARGS");
\r
314 if (UniIsEmptyStr(*help))
\r
316 *help = _UU("CMD_UNKNOWN_HELP");
\r
321 // パラメータのヘルプ文字列を取得する
\r
322 void GetCommandParamHelpStr(char *command_name, char *param_name, wchar_t **description)
\r
325 if (description == NULL)
\r
330 Format(tmp, sizeof(tmp), "CMD_%s_%s", command_name, param_name);
\r
332 *description = _UU(tmp);
\r
334 if (UniIsEmptyStr(*description))
\r
336 *description = _UU("CMD_UNKNOWN_PARAM");
\r
341 int CompareCandidateStr(void *p1, void *p2)
\r
344 if (p1 == NULL || p2 == NULL)
\r
350 if (s1 == NULL || s2 == NULL)
\r
355 if (s1[0] == '[' && s2[0] != '[')
\r
359 else if (s2[0] == '[' && s1[0] != '[')
\r
364 return StrCmp(s1, s2);
\r
368 void PrintCandidateHelp(CONSOLE *c, char *cmd_name, TOKEN_LIST *candidate_list, UINT left_space)
\r
370 UINT console_width;
\r
371 UINT max_keyword_width;
\r
376 char *left_space_array;
\r
377 char *max_space_array;
\r
379 if (c == NULL || candidate_list == NULL)
\r
385 console_width = GetConsoleWidth(c) - 1;
\r
387 tmpbuf_size = sizeof(wchar_t) * (console_width + 32);
\r
388 tmpbuf = Malloc(tmpbuf_size);
\r
390 left_space_array = MakeCharArray(' ', left_space);
\r
392 // コマンド名はソートしてリスト化する
\r
394 o = NewListFast(cmd_name == NULL ? CompareCandidateStr : NULL);
\r
396 max_keyword_width = 0;
\r
398 for (i = 0;i < candidate_list->NumTokens;i++)
\r
400 UINT keyword_width;
\r
403 Insert(o, candidate_list->Token[i]);
\r
405 keyword_width = StrWidth(candidate_list->Token[i]);
\r
406 if (cmd_name != NULL)
\r
408 if (candidate_list->Token[i][0] != '[')
\r
410 keyword_width += 1;
\r
414 keyword_width -= 2;
\r
418 max_keyword_width = MAX(max_keyword_width, keyword_width);
\r
421 max_space_array = MakeCharArray(' ', max_keyword_width);
\r
424 for (i = 0;i < LIST_NUM(o);i++)
\r
427 char *name = LIST_DATA(o, i);
\r
431 UINT keyword_start_width = left_space;
\r
432 UINT descript_start_width = left_space + max_keyword_width + 1;
\r
433 UINT descript_width;
\r
436 if (console_width >= (descript_start_width + 5))
\r
438 descript_width = console_width - descript_start_width - 3;
\r
442 descript_width = 2;
\r
446 if (cmd_name != NULL && name[0] != '[')
\r
448 // パラメータの場合は先頭に "/" を付ける
\r
449 Format(tmp, sizeof(tmp), "/%s", name);
\r
453 // コマンド名の場合はそのままの文字を使用する
\r
454 if (cmd_name == NULL)
\r
456 StrCpy(tmp, sizeof(tmp), name);
\r
460 StrCpy(tmp, sizeof(tmp), name + 1);
\r
461 if (StrLen(tmp) >= 1)
\r
463 tmp[StrLen(tmp) - 1] = 0;
\r
469 if (cmd_name == NULL)
\r
471 GetCommandHelpStr(name, &help, NULL, NULL);
\r
475 GetCommandParamHelpStr(cmd_name, name, &help);
\r
478 space = MakeCharArray(' ', max_keyword_width - StrWidth(name) - (cmd_name == NULL ? 0 : (name[0] != '[' ? 1 : -2)));
\r
480 t = SeparateStringByWidth(help, descript_width);
\r
482 for (j = 0;j < t->NumTokens;j++)
\r
486 UniFormat(tmpbuf, tmpbuf_size, L"%S%S%S - %s",
\r
487 left_space_array, tmp, space, t->Token[j]);
\r
491 UniFormat(tmpbuf, tmpbuf_size, L"%S%S %s",
\r
492 left_space_array, max_space_array, t->Token[j]);
\r
495 c->Write(c, tmpbuf);
\r
505 Free(max_space_array);
\r
507 Free(left_space_array);
\r
510 // 文字列を指定された横幅で分割する
\r
511 UNI_TOKEN_LIST *SeparateStringByWidth(wchar_t *str, UINT width)
\r
517 UNI_TOKEN_LIST *ret;
\r
521 return UniNullToken();
\r
528 o = NewListFast(NULL);
\r
530 len = UniStrLen(str);
\r
531 tmp = ZeroMalloc(sizeof(wchar_t) * (len + 32));
\r
534 for (i = 0;i < (len + 1);i++)
\r
536 wchar_t c = str[i];
\r
545 if (str[i + 1] == L'\n')
\r
554 Insert(o, UniCopyStr(tmp));
\r
560 if (UniStrWidth(tmp) >= width)
\r
565 Insert(o, UniCopyStr(tmp));
\r
571 if (LIST_NUM(o) == 0)
\r
573 Insert(o, CopyUniStr(L""));
\r
576 ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
\r
577 ret->NumTokens = LIST_NUM(o);
\r
578 ret->Token = ZeroMalloc(sizeof(wchar_t *) * ret->NumTokens);
\r
580 for (i = 0;i < LIST_NUM(o);i++)
\r
582 wchar_t *s = LIST_DATA(o, i);
\r
593 // 指定した文字列が help を示すかどうかをチェック
\r
594 bool IsHelpStr(char *str)
\r
602 if (StrCmpi(str, "help") == 0 || StrCmpi(str, "?") == 0 ||
\r
603 StrCmpi(str, "man") == 0 || StrCmpi(str, "/man") == 0 ||
\r
604 StrCmpi(str, "-man") == 0 || StrCmpi(str, "--man") == 0 ||
\r
605 StrCmpi(str, "/help") == 0 || StrCmpi(str, "/?") == 0 ||
\r
606 StrCmpi(str, "-help") == 0 || StrCmpi(str, "-?") == 0 ||
\r
607 StrCmpi(str, "/h") == 0 || StrCmpi(str, "--help") == 0 ||
\r
608 StrCmpi(str, "--?") == 0)
\r
617 bool DispatchNextCmd(CONSOLE *c, char *prompt, CMD cmd[], UINT num_cmd, void *param)
\r
619 return DispatchNextCmdEx(c, NULL, prompt, cmd, num_cmd, param);
\r
621 bool DispatchNextCmdEx(CONSOLE *c, wchar_t *exec_command, char *prompt, CMD cmd[], UINT num_cmd, void *param)
\r
626 bool b_exit = false;
\r
627 wchar_t *cmd_param;
\r
628 UINT ret = ERR_NO_ERROR;
\r
630 TOKEN_LIST *candidate;
\r
631 bool no_end_crlf = false;
\r
634 if (c == NULL || (num_cmd >= 1 && cmd == NULL))
\r
639 if (exec_command == NULL)
\r
643 tmp = CopyStrToUni(prompt);
\r
644 str = c->ReadLine(c, tmp, false);
\r
647 if (str != NULL && IsEmptyUniStr(str))
\r
655 wchar_t tmp[MAX_SIZE];
\r
656 // exec_command を使用
\r
657 if (UniStartWith(exec_command, L"utvpncmd") == false)
\r
659 if (prompt != NULL)
\r
661 if (c->ConsoleType != CONSOLE_CSV)
\r
663 UniFormat(tmp, sizeof(tmp), L"%S%s", prompt, exec_command);
\r
668 str = CopyUniStr(exec_command);
\r
680 if (UniIsEmptyStr(str))
\r
688 if (SeparateCommandAndParam(str, &cmd_name, &cmd_param) == false)
\r
695 if (StrLen(cmd_name) >= 2 && cmd_name[0] == '?' && cmd_name[1] != '?')
\r
697 char tmp[MAX_SIZE];
\r
700 StrCpy(tmp, sizeof(tmp), cmd_name + 1);
\r
701 StrCpy(cmd_name, 0, tmp);
\r
703 s = UniCopyStr(L"/?");
\r
709 if (StrLen(cmd_name) >= 2 && EndWith(cmd_name, "?") && cmd_name[StrLen(cmd_name) - 2] != '?')
\r
713 cmd_name[StrLen(cmd_name) - 1] = 0;
\r
715 s = UniCopyStr(L"/?");
\r
722 t = ZeroMalloc(sizeof(TOKEN_LIST));
\r
723 t->NumTokens = num_cmd;
\r
724 t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
\r
725 for (i = 0;i < t->NumTokens;i++)
\r
727 t->Token[i] = CopyStr(cmd[i].Name);
\r
730 if (IsHelpStr(cmd_name))
\r
732 if (UniIsEmptyStr(cmd_param))
\r
734 wchar_t tmp[MAX_SIZE];
\r
736 // 使用できるコマンド一覧を表示する
\r
737 UniFormat(tmp, sizeof(tmp), _UU("CMD_HELP_1"), t->NumTokens);
\r
740 PrintCandidateHelp(c, NULL, t, 1);
\r
743 c->Write(c, _UU("CMD_HELP_2"));
\r
749 // 指定したコマンドのヘルプを表示する
\r
750 if (SeparateCommandAndParam(cmd_param, &cmd_name, NULL))
\r
754 if (IsHelpStr(cmd_name))
\r
761 wchar_t str[MAX_SIZE];
\r
763 UniFormat(str, sizeof(str), L"%S /help", cmd_name);
\r
764 DispatchNextCmdEx(c, str, NULL, cmd, num_cmd, param);
\r
765 no_end_crlf = true;
\r
772 else if (StrCmpi(cmd_name, "exit") == 0 || StrCmpi(cmd_name, "quit") == 0)
\r
779 candidate = GetRealnameCandidate(cmd_name, t);
\r
781 if (candidate == NULL || candidate->NumTokens == 0)
\r
783 wchar_t tmp[MAX_SIZE];
\r
786 UniFormat(tmp, sizeof(tmp), _UU("CON_UNKNOWN_CMD"), cmd_name);
\r
789 c->RetCode = ERR_BAD_COMMAND_OR_PARAM;
\r
791 else if (candidate->NumTokens >= 2)
\r
793 wchar_t tmp[MAX_SIZE];
\r
796 UniFormat(tmp, sizeof(tmp), _UU("CON_AMBIGIOUS_CMD"), cmd_name);
\r
798 c->Write(c, _UU("CON_AMBIGIOUS_CMD_1"));
\r
799 PrintCandidateHelp(c, NULL, candidate, 1);
\r
800 c->Write(c, _UU("CON_AMBIGIOUS_CMD_2"));
\r
802 c->RetCode = ERR_BAD_COMMAND_OR_PARAM;
\r
806 char *real_cmd_name;
\r
810 real_cmd_name = candidate->Token[0];
\r
812 for (i = 0;i < num_cmd;i++)
\r
814 if (StrCmpi(cmd[i].Name, real_cmd_name) == 0)
\r
816 if (cmd[i].Proc != NULL)
\r
818 // CSV モードでなければコマンドの説明を表示する
\r
819 if(c->ConsoleType != CONSOLE_CSV)
\r
824 GetCommandHelpStr(cmd[i].Name, ¬e, NULL, NULL);
\r
825 UniFormat(tmp, sizeof(tmp), _UU("CMD_EXEC_MSG_NAME"), cmd[i].Name, note);
\r
829 // コマンドのプロシージャを呼び出す
\r
830 ret = cmd[i].Proc(c, cmd[i].Name, cmd_param, param);
\r
832 if (ret == INFINITE)
\r
846 FreeToken(candidate);
\r
854 if (no_end_crlf == false)
\r
856 //c->Write(c, L"");
\r
867 // 現在のコンソールの横幅を取得する
\r
868 UINT GetConsoleWidth(CONSOLE *c)
\r
872 size = c->GetWidth(c);
\r
892 // コマンドラインをコマンドとパラメータの 2 つに分離する
\r
893 bool SeparateCommandAndParam(wchar_t *src, char **cmd, wchar_t **param)
\r
912 src_tmp = UniCopyStr(src);
\r
913 UniTrimCrlf(src_tmp);
\r
916 len = UniStrLen(src_tmp);
\r
917 tmp = Malloc(sizeof(wchar_t) * (len + 32));
\r
920 for (i = 0;i < (len + 1);i++)
\r
922 wchar_t c = src_tmp[i];
\r
930 if (UniIsEmptyStr(tmp))
\r
938 *cmd = CopyUniToStr(tmp);
\r
952 *param = CopyUniStr(&src_tmp[wp]);
\r
962 // ユーザーが指定したコマンド名の省略形に一致する実在するコマンドの一覧の候補を取得する
\r
963 TOKEN_LIST *GetRealnameCandidate(char *input_name, TOKEN_LIST *real_name_list)
\r
970 if (input_name == NULL || real_name_list == NULL)
\r
972 return NullToken();
\r
975 o = NewListFast(NULL);
\r
977 for (i = 0;i < real_name_list->NumTokens;i++)
\r
979 char *name = real_name_list->Token[i];
\r
981 // まず最優先で完全一致するものを検索する
\r
982 if (StrCmpi(name, input_name) == 0)
\r
992 // 完全一致するコマンドが無い場合、省略形コマンドとして一致するかどうかチェックする
\r
993 for (i = 0;i < real_name_list->NumTokens;i++)
\r
995 char *name = real_name_list->Token[i];
\r
997 if (IsOmissionName(input_name, name) || IsNameInRealName(input_name, name))
\r
1009 ret = ListToTokenList(o);
\r
1013 ret = NullToken();
\r
1021 // ユーザーが指定したコマンドが既存のコマンドの省略形かどうかチェックする
\r
1022 bool IsOmissionName(char *input_name, char *real_name)
\r
1026 if (input_name == NULL || real_name == NULL)
\r
1031 if (IsAllUpperStr(real_name))
\r
1033 // すべて大文字のコマンドは省略形をとらない
\r
1037 GetOmissionName(oname, sizeof(oname), real_name);
\r
1039 if (IsEmptyStr(oname))
\r
1044 if (StartWith(oname, input_name))
\r
1046 // 例: AccountSecureCertSet の oname は ascs だが
\r
1047 // ユーザーが asc と入力した場合は true を返す
\r
1051 if (StartWith(input_name, oname))
\r
1053 // 例: AccountConnect と
\r
1054 // AccountCreate の 2 つのコマンドが実在する際、
\r
1055 // ユーザーが "aconnect" と入力すると、
\r
1056 // AccountConnect のみ true になるようにする
\r
1058 if (EndWith(real_name, &input_name[StrLen(oname)]))
\r
1067 // 指定したコマンド名の省略名を取得する
\r
1068 void GetOmissionName(char *dst, UINT size, char *src)
\r
1072 if (dst == NULL || src == NULL)
\r
1077 StrCpy(dst, size, "");
\r
1078 len = StrLen(src);
\r
1080 for (i = 0;i < len;i++)
\r
1084 if ((c >= '0' && c <= '9') ||
\r
1085 (c >= 'A' && c <= 'Z'))
\r
1091 StrCat(dst, size, tmp);
\r
1096 // ユーザーが指定したコマンドが既存のコマンドに一致するかどうかチェックする
\r
1097 bool IsNameInRealName(char *input_name, char *real_name)
\r
1100 if (input_name == NULL || real_name == NULL)
\r
1105 if (StartWith(real_name, input_name))
\r
1114 LIST *ParseCommandList(CONSOLE *c, char *cmd_name, wchar_t *command, PARAM param[], UINT num_param)
\r
1119 TOKEN_LIST *param_list;
\r
1120 TOKEN_LIST *real_name_list;
\r
1121 bool help_mode = false;
\r
1124 if (c == NULL || command == NULL || (num_param >= 1 && param == NULL) || cmd_name == NULL)
\r
1130 for (i = 0;i < num_param;i++)
\r
1132 if (IsEmptyStr(param[i].Name) == false)
\r
1134 if (param[i].Name[0] == '[')
\r
1136 param[i].Tmp = "";
\r
1140 param[i].Tmp = NULL;
\r
1145 param[i].Tmp = "";
\r
1149 real_name_list = ZeroMalloc(sizeof(TOKEN_LIST));
\r
1150 real_name_list->NumTokens = num_param;
\r
1151 real_name_list->Token = ZeroMalloc(sizeof(char *) * real_name_list->NumTokens);
\r
1153 for (i = 0;i < real_name_list->NumTokens;i++)
\r
1155 real_name_list->Token[i] = CopyStr(param[i].Name);
\r
1158 // ユーザーが指定したパラメータ名のリストを生成する
\r
1159 param_list = GetCommandNameList(command);
\r
1161 for (i = 0;i < param_list->NumTokens;i++)
\r
1163 char *s = param_list->Token[i];
\r
1165 if (StrCmpi(s, "help") == 0 || StrCmpi(s, "?") == 0)
\r
1172 tmp = ParseCommand(command, L"");
\r
1175 if (UniStrCmpi(tmp, L"?") == 0)
\r
1185 PrintCmdHelp(c, cmd_name, real_name_list);
\r
1186 FreeToken(param_list);
\r
1187 FreeToken(real_name_list);
\r
1191 for (i = 0;i < param_list->NumTokens;i++)
\r
1193 // ユーザーが指定したすべてのパラメータ名について対応するコマンドを取得する
\r
1194 TOKEN_LIST *candidate = GetRealnameCandidate(param_list->Token[i], real_name_list);
\r
1196 if (candidate != NULL && candidate->NumTokens >= 1)
\r
1198 if (candidate->NumTokens >= 2)
\r
1200 wchar_t tmp[MAX_SIZE];
\r
1203 UniFormat(tmp, sizeof(tmp), _UU("CON_AMBIGIOUS_PARAM"), param_list->Token[i]);
\r
1205 UniFormat(tmp, sizeof(tmp), _UU("CON_AMBIGIOUS_PARAM_1"), cmd_name);
\r
1208 PrintCandidateHelp(c, cmd_name, candidate, 1);
\r
1210 c->Write(c, _UU("CON_AMBIGIOUS_PARAM_2"));
\r
1217 char *real_name = candidate->Token[0];
\r
1220 for (j = 0;j < num_param;j++)
\r
1222 if (StrCmpi(param[j].Name, real_name) == 0)
\r
1224 param[j].Tmp = param_list->Token[i];
\r
1231 wchar_t tmp[MAX_SIZE];
\r
1234 UniFormat(tmp, sizeof(tmp), _UU("CON_INVALID_PARAM"), param_list->Token[i], cmd_name, cmd_name);
\r
1240 FreeToken(candidate);
\r
1245 FreeToken(param_list);
\r
1246 FreeToken(real_name_list);
\r
1252 o = NewParamValueList();
\r
1254 // パラメータ一覧に指定された名前のすべてのパラメータを読み込む
\r
1255 for (i = 0;i < num_param;i++)
\r
1257 bool prompt_input_value = false;
\r
1258 PARAM *p = ¶m[i];
\r
1260 if (p->Tmp != NULL || p->PromptProc != NULL)
\r
1262 wchar_t *name = CopyStrToUni(p->Name);
\r
1266 if (p->Tmp != NULL)
\r
1268 tmp = CopyStrToUni(p->Tmp);
\r
1272 tmp = CopyStrToUni(p->Name);
\r
1275 str = ParseCommand(command, tmp);
\r
1285 if (p->EvalProc != NULL)
\r
1287 // EvalProc が指定されている場合は値を評価する
\r
1288 ret = p->EvalProc(c, unistr, p->EvalProcParam);
\r
1292 // EvalProc が指定されていない場合はどのような値でも受け付ける
\r
1299 if (p->PromptProc == NULL)
\r
1318 // 読み込み完了したのでリストに追加する
\r
1319 v = ZeroMalloc(sizeof(PARAM_VALUE));
\r
1320 v->Name = CopyStr(p->Name);
\r
1321 v->StrValue = CopyUniToStr(str);
\r
1322 v->UniStrValue = CopyUniStr(str);
\r
1323 v->IntValue = ToInt(v->StrValue);
\r
1329 // 読み込みに失敗した。指定されたパラメータが指定されていない
\r
1330 if (p->PromptProc != NULL)
\r
1334 // 必須パラメータであるのでプロンプトを表示する
\r
1335 tmp = p->PromptProc(c, p->PromptProcParam);
\r
1349 prompt_input_value = true;
\r
1360 FreeToken(param_list);
\r
1361 FreeToken(real_name_list);
\r
1369 FreeParamValueList(o);
\r
1374 // [はい] か [いいえ] の取得
\r
1375 bool GetParamYes(LIST *o, char *name)
\r
1385 s = GetParamStr(o, name);
\r
1391 StrCpy(tmp, sizeof(tmp), s);
\r
1394 if (StartWith(tmp, "y"))
\r
1399 if (StartWith(tmp, "t"))
\r
1404 if (ToInt(tmp) != 0)
\r
1413 UINT GetParamInt(LIST *o, char *name)
\r
1422 v = FindParamValue(o, name);
\r
1429 return v->IntValue;
\r
1433 // パラメータ値 Unicode 文字列の取得
\r
1434 wchar_t *GetParamUniStr(LIST *o, char *name)
\r
1443 v = FindParamValue(o, name);
\r
1450 return v->UniStrValue;
\r
1455 char *GetParamStr(LIST *o, char *name)
\r
1464 v = FindParamValue(o, name);
\r
1471 return v->StrValue;
\r
1476 PARAM_VALUE *FindParamValue(LIST *o, char *name)
\r
1478 PARAM_VALUE t, *ret;
\r
1489 Zero(&t, sizeof(t));
\r
1492 ret = Search(o, &t);
\r
1498 void FreeParamValueList(LIST *o)
\r
1507 for (i = 0;i < LIST_NUM(o);i++)
\r
1509 PARAM_VALUE *v = LIST_DATA(o, i);
\r
1511 Free(v->StrValue);
\r
1512 Free(v->UniStrValue);
\r
1521 int CmpParamValue(void *p1, void *p2)
\r
1523 PARAM_VALUE *v1, *v2;
\r
1524 if (p1 == NULL || p2 == NULL)
\r
1528 v1 = *(PARAM_VALUE **)p1;
\r
1529 v2 = *(PARAM_VALUE **)p2;
\r
1530 if (v1 == NULL || v2 == NULL)
\r
1535 if (IsEmptyStr(v1->Name) && IsEmptyStr(v2->Name))
\r
1539 return StrCmpi(v1->Name, v2->Name);
\r
1543 LIST *NewParamValueList()
\r
1545 return NewListFast(CmpParamValue);
\r
1548 // 入力されたコマンドに含まれていたパラメータ名のリストを取得する
\r
1549 TOKEN_LIST *GetCommandNameList(wchar_t *str)
\r
1555 return NullToken();
\r
1558 Free(ParseCommandEx(str, L"dummy_str", &t));
\r
1563 // 指定した名前で始まるコマンドを取得する
\r
1564 wchar_t *ParseCommand(wchar_t *str, wchar_t *name)
\r
1566 return ParseCommandEx(str, name, NULL);
\r
1568 wchar_t *ParseCommandEx(wchar_t *str, wchar_t *name, TOKEN_LIST **param_list)
\r
1570 UNI_TOKEN_LIST *t;
\r
1573 wchar_t *ret = NULL;
\r
1580 if (name != NULL && UniIsEmptyStr(name))
\r
1586 if (param_list != NULL)
\r
1588 o = NewListFast(CompareStr);
\r
1591 tmp = CopyUniStr(str);
\r
1594 i = UniSearchStrEx(tmp, L"/CMD ", 0, false);
\r
1596 // このあたりは急いで実装したのでコードがあまり美しくない。
\r
1597 if (i != INFINITE && i >= 1 && tmp[i - 1] == L'/')
\r
1601 if (i == INFINITE)
\r
1603 i = UniSearchStrEx(tmp, L"/CMD\t", 0, false);
\r
1604 if (i != INFINITE && i >= 1 && tmp[i - 1] == L'/')
\r
1609 if (i == INFINITE)
\r
1611 i = UniSearchStrEx(tmp, L"/CMD:", 0, false);
\r
1612 if (i != INFINITE && i >= 1 && tmp[i - 1] == L'/')
\r
1617 if (i == INFINITE)
\r
1619 i = UniSearchStrEx(tmp, L"/CMD=", 0, false);
\r
1620 if (i != INFINITE && i >= 1 && tmp[i - 1] == L'/')
\r
1625 if (i == INFINITE)
\r
1627 i = UniSearchStrEx(tmp, L"-CMD ", 0, false);
\r
1628 if (i != INFINITE && i >= 1 && tmp[i - 1] == L'-')
\r
1633 if (i == INFINITE)
\r
1635 i = UniSearchStrEx(tmp, L"-CMD\t", 0, false);
\r
1636 if (i != INFINITE && i >= 1 && tmp[i - 1] == L'-')
\r
1641 if (i == INFINITE)
\r
1643 i = UniSearchStrEx(tmp, L"-CMD:", 0, false);
\r
1644 if (i != INFINITE && i >= 1 && tmp[i - 1] == L'-')
\r
1649 if (i == INFINITE)
\r
1651 i = UniSearchStrEx(tmp, L"-CMD=", 0, false);
\r
1652 if (i != INFINITE && i >= 1 && tmp[i - 1] == L'-')
\r
1658 if (i != INFINITE)
\r
1660 char *s = CopyStr("CMD");
\r
1661 if (InsertStr(o, s) == false)
\r
1665 if (UniStrCmpi(name, L"CMD") == 0)
\r
1667 ret = CopyUniStr(&str[i + 5]);
\r
1678 t = UniParseCmdLine(tmp);
\r
1682 for (i = 0;i < t->NumTokens;i++)
\r
1684 wchar_t *token = t->Token[i];
\r
1686 if ((token[0] == L'-' && token[1] != L'-') ||
\r
1687 (UniStrCmpi(token, L"--help") == 0) ||
\r
1688 (token[0] == L'/' && token[1] != L'/'))
\r
1693 // コロン文字があるかどうか調べる
\r
1695 if (UniStrCmpi(token, L"--help") == 0)
\r
1700 i = UniSearchStrEx(token, L":", 0, false);
\r
1701 if (i == INFINITE)
\r
1703 i = UniSearchStrEx(token, L"=", 0, false);
\r
1705 if (i != INFINITE)
\r
1711 tmp = CopyUniStr(token);
\r
1714 a = CopyUniToStr(&tmp[1]);
\r
1715 if (InsertStr(o, a) == false)
\r
1720 if (UniStrCmpi(name, &tmp[1]) == 0)
\r
1725 ret = UniCopyStr(&token[i + 1]);
\r
1736 a = CopyUniToStr(&token[1]);
\r
1737 if (InsertStr(o, a) == false)
\r
1742 if (UniStrCmpi(name, &token[1]) == 0)
\r
1747 ret = UniCopyStr(L"");
\r
1759 if (token[0] == L'-' && token[1] == L'-')
\r
1761 ret = UniCopyStr(&token[1]);
\r
1763 else if (token[0] == L'/' && token[1] == L'/')
\r
1765 ret = UniCopyStr(&token[1]);
\r
1769 ret = UniCopyStr(token);
\r
1784 TOKEN_LIST *t = ZeroMalloc(sizeof(TOKEN_LIST));
\r
1787 t->NumTokens = LIST_NUM(o);
\r
1788 t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
\r
1790 for (i = 0;i < t->NumTokens;i++)
\r
1792 t->Token[i] = LIST_DATA(o, i);
\r
1800 if (UniStrCmpi(ret, L"none") == 0 || UniStrCmpi(ret, L"null") == 0)
\r
1802 // none と null は予約語である
\r
1808 char *ParseCommandA(wchar_t *str, char *name)
\r
1810 wchar_t *tmp1, *tmp2;
\r
1820 tmp1 = CopyStrToUni(name);
\r
1827 tmp2 = ParseCommand(str, tmp1);
\r
1835 ret = CopyUniToStr(tmp2);
\r
1845 bool PasswordPrompt(char *password, UINT size)
\r
1848 bool escape = false;
\r
1851 if (password == NULL || size <= 1)
\r
1862 Zero(password, size);
\r
1864 console = SetConsoleRaw();
\r
1874 #endif // OS_WIN32
\r
1876 if (c >= 0x20 && c <= 0x7E)
\r
1879 if ((wp + 1) < size)
\r
1881 password[wp++] = (char)c;
\r
1882 putc('*', stdout);
\r
1885 else if (c == 0x03)
\r
1890 else if (c == 0x04 || c == 0x1a || c == 0x0D || c==0x0A)
\r
1893 if (c == 0x04 || c == 0x1a)
\r
1899 else if (c == 0xE0)
\r
1903 if (c == 0x4B || c == 0x53)
\r
1909 else if (c == 0x08)
\r
1915 password[--wp] = 0;
\r
1916 putc(0x08, stdout);
\r
1917 putc(' ', stdout);
\r
1918 putc(0x08, stdout);
\r
1924 RestoreConsole(console);
\r
1926 return (escape ? false : true);
\r
1930 wchar_t *Prompt(wchar_t *prompt_str)
\r
1932 wchar_t *ret = NULL;
\r
1933 wchar_t *tmp = NULL;
\r
1935 if (prompt_str == NULL)
\r
1941 UniPrint(L"%s", prompt_str);
\r
1942 tmp = Malloc(MAX_PROMPT_STRSIZE);
\r
1943 if (fgetws(tmp, MAX_PROMPT_STRSIZE - 1, stdin) != NULL)
\r
1945 bool escape = false;
\r
1948 len = UniStrLen(tmp);
\r
1949 for (i = 0;i < len;i++)
\r
1951 if (tmp[i] == 0x04 || tmp[i] == 0x1A)
\r
1958 if (escape == false)
\r
1962 ret = UniCopyStr(tmp);
\r
1968 char *prompt = CopyUniToStr(prompt_str);
\r
1969 char *s = readline(prompt);
\r
1977 if (IsEmptyStr(s) == false)
\r
1982 ret = CopyStrToUni(s);
\r
1987 #endif // OS_WIN32
\r
1996 char *PromptA(wchar_t *prompt_str)
\r
1998 wchar_t *str = Prompt(prompt_str);
\r
2006 char *ret = CopyUniToStr(str);
\r
2013 // コンソールを Raw モードにする
\r
2014 void *SetConsoleRaw()
\r
2017 struct termios t, *ret;
\r
2019 Zero(&t, sizeof(t));
\r
2020 if (tcgetattr(0, &t) != 0)
\r
2027 ret = Clone(&t, sizeof(t));
\r
2030 t.c_lflag &= (~ICANON);
\r
2031 t.c_lflag &= (~ECHO);
\r
2032 t.c_cc[VTIME] = 0;
\r
2034 tcsetattr(0, TCSANOW, &t);
\r
2043 void RestoreConsole(void *p)
\r
2046 struct termios *t;
\r
2053 t = (struct termios *)p;
\r
2056 tcsetattr(0, TCSANOW, t);
\r
2067 ////////////////////////////
\r
2070 // 新しいローカルコンソールの作成
\r
2071 CONSOLE *NewLocalConsole(wchar_t *infile, wchar_t *outfile)
\r
2073 IO *in_io = NULL, *out_io = NULL;
\r
2074 CONSOLE *c = ZeroMalloc(sizeof(CONSOLE));
\r
2075 LOCAL_CONSOLE_PARAM *p;
\r
2076 UINT old_size = 0;
\r
2079 if (MsGetConsoleWidth() == 80)
\r
2081 //old_size = MsSetConsoleWidth(WIN32_DEFAULT_CONSOLE_WIDTH);
\r
2083 #endif // OS_WIN32
\r
2085 c->ConsoleType = CONSOLE_LOCAL;
\r
2086 c->Free = ConsoleLocalFree;
\r
2087 c->ReadLine = ConsoleLocalReadLine;
\r
2088 c->ReadPassword = ConsoleLocalReadPassword;
\r
2089 c->Write = ConsoleLocalWrite;
\r
2090 c->GetWidth = ConsoleLocalGetWidth;
\r
2092 if (UniIsEmptyStr(infile) == false)
\r
2095 in_io = FileOpenW(infile, false);
\r
2096 if (in_io == NULL)
\r
2098 wchar_t tmp[MAX_SIZE];
\r
2100 UniFormat(tmp, sizeof(tmp), _UU("CON_INFILE_ERROR"), infile);
\r
2107 wchar_t tmp[MAX_SIZE];
\r
2109 UniFormat(tmp, sizeof(tmp), _UU("CON_INFILE_START"), infile);
\r
2114 if (UniIsEmptyStr(outfile) == false)
\r
2117 out_io = FileCreateW(outfile);
\r
2118 if (out_io == NULL)
\r
2120 wchar_t tmp[MAX_SIZE];
\r
2122 UniFormat(tmp, sizeof(tmp), _UU("CON_OUTFILE_ERROR"), outfile);
\r
2126 if (in_io != NULL)
\r
2134 wchar_t tmp[MAX_SIZE];
\r
2136 UniFormat(tmp, sizeof(tmp), _UU("CON_OUTFILE_START"), outfile);
\r
2141 p = ZeroMalloc(sizeof(LOCAL_CONSOLE_PARAM));
\r
2144 p->InFile = in_io;
\r
2145 p->OutFile = out_io;
\r
2146 p->Win32_OldConsoleWidth = old_size;
\r
2148 if (in_io != NULL)
\r
2153 size = FileSize(in_io);
\r
2154 buf = ZeroMalloc(size + 1);
\r
2155 FileRead(in_io, buf, size);
\r
2157 p->InBuf = NewBuf();
\r
2158 WriteBuf(p->InBuf, buf, size);
\r
2161 p->InBuf->Current = 0;
\r
2168 void ConsoleLocalFree(CONSOLE *c)
\r
2170 LOCAL_CONSOLE_PARAM *p;
\r
2177 p = (LOCAL_CONSOLE_PARAM *)c->Param;
\r
2180 if (p->Win32_OldConsoleWidth != 0)
\r
2182 MsSetConsoleWidth(p->Win32_OldConsoleWidth);
\r
2184 #endif // OS_WIN32
\r
2188 if (p->InFile != NULL)
\r
2190 FileClose(p->InFile);
\r
2191 FreeBuf(p->InBuf);
\r
2194 if (p->OutFile != NULL)
\r
2196 FileClose(p->OutFile);
\r
2207 UINT ConsoleLocalGetWidth(CONSOLE *c)
\r
2217 ret = MsGetConsoleWidth();
\r
2222 Zero(&t, sizeof(t));
\r
2224 if (ioctl(1, TIOCGWINSZ, &t) == 0)
\r
2229 #endif // OS_WIN32
\r
2234 // コンソールから 1 行読み込む
\r
2235 wchar_t *ConsoleLocalReadLine(CONSOLE *c, wchar_t *prompt, bool nofile)
\r
2238 LOCAL_CONSOLE_PARAM *p;
\r
2244 p = (LOCAL_CONSOLE_PARAM *)c->Param;
\r
2245 if (prompt == NULL)
\r
2250 ConsoleWriteOutFile(c, prompt, false);
\r
2252 if (nofile == false && p->InBuf != NULL)
\r
2255 ret = ConsoleReadNextFromInFile(c);
\r
2260 UniPrint(L"%s", prompt);
\r
2263 UniPrint(L"%s\n", ret);
\r
2269 ret = Prompt(prompt);
\r
2274 ConsoleWriteOutFile(c, ret, true);
\r
2278 ConsoleWriteOutFile(c, _UU("CON_USER_CANCEL"), true);
\r
2284 // コンソールからパスワードを読み込む
\r
2285 char *ConsoleLocalReadPassword(CONSOLE *c, wchar_t *prompt)
\r
2293 if (prompt == NULL)
\r
2295 prompt = L"Password>";
\r
2298 UniPrint(L"%s", prompt);
\r
2299 ConsoleWriteOutFile(c, prompt, false);
\r
2301 if (PasswordPrompt(tmp, sizeof(tmp)))
\r
2303 ConsoleWriteOutFile(c, L"********", true);
\r
2304 return CopyStr(tmp);
\r
2308 ConsoleWriteOutFile(c, _UU("CON_USER_CANCEL"), true);
\r
2314 bool ConsoleLocalWrite(CONSOLE *c, wchar_t *str)
\r
2317 if (c == NULL || str == NULL)
\r
2322 UniPrint(L"%s%s", str, (UniEndWith(str, L"\n") ? L"" : L"\n"));
\r
2324 ConsoleWriteOutFile(c, str, true);
\r
2329 // 入力ファイルから次の 1 行を読み込む
\r
2330 wchar_t *ConsoleReadNextFromInFile(CONSOLE *c)
\r
2332 LOCAL_CONSOLE_PARAM *p;
\r
2340 p = (LOCAL_CONSOLE_PARAM *)c->Param;
\r
2342 if (p->InBuf == NULL)
\r
2349 str = CfgReadNextLine(p->InBuf);
\r
2358 if (IsEmptyStr(str) == false)
\r
2363 size = CalcUtf8ToUni((BYTE *)str, StrLen(str));
\r
2364 ret = ZeroMalloc(size + 32);
\r
2365 Utf8ToUni(ret, size, (BYTE *)str, StrLen(str));
\r
2376 // 出力ファイルが指定されている場合は書き出す
\r
2377 void ConsoleWriteOutFile(CONSOLE *c, wchar_t *str, bool add_last_crlf)
\r
2379 LOCAL_CONSOLE_PARAM *p;
\r
2381 if (c == NULL || str == NULL)
\r
2386 p = (LOCAL_CONSOLE_PARAM *)c->Param;
\r
2388 if (p != NULL && p->OutFile != NULL)
\r
2390 wchar_t *tmp = UniNormalizeCrlf(str);
\r
2394 utf8_size = CalcUniToUtf8(tmp);
\r
2395 utf8 = ZeroMalloc(utf8_size + 1);
\r
2396 UniToUtf8(utf8, utf8_size + 1, tmp);
\r
2398 FileWrite(p->OutFile, utf8, utf8_size);
\r
2400 if (UniEndWith(str, L"\n") == false && add_last_crlf)
\r
2402 char *crlf = "\r\n";
\r
2403 FileWrite(p->OutFile, "\r\n", StrLen(crlf));
\r