* copy vendor drop to trunk
[lab.git] / Dev / utvpn / utvpn-unix-v101-7101-public / src / Cedar / Console.c
1 // SoftEther UT-VPN SourceCode\r
2 // \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
7 // \r
8 // http://utvpn.tsukuba.ac.jp/\r
9 // \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
13 // \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
18 // \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
22 // \r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。\r
28 // \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
32 // ホストされています。\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、\r
34 // および、試験または研究のために利用が行われることを想定して配布\r
35 // しています。\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に\r
37 // あります。\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース\r
42 // に組み込みさせていただきます。\r
43 // \r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。\r
46 // \r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意\r
51 // ください。\r
52 // \r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、\r
58 // 公益保護にご協力いただきますようお願い申し上げます。\r
59 // \r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客\r
62 // を保護するための努力を行います。\r
63 // \r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/\r
65 // 日本国内の脆弱性情報届出受付公的機関:\r
66 //         独立行政法人 情報処理推進機構\r
67 //         http://www.ipa.go.jp/security/vuln/report/\r
68 // \r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/\r
71 \r
72 // -----------------------------------------------\r
73 // [ChangeLog]\r
74 // 2010.05.20\r
75 //  新規リリース by SoftEther\r
76 // -----------------------------------------------\r
77 \r
78 // Console.c\r
79 // コンソール サービス\r
80 \r
81 #include "CedarPch.h"\r
82 \r
83 \r
84 // コマンドのヘルプを表示する\r
85 void PrintCmdHelp(CONSOLE *c, char *cmd_name, TOKEN_LIST *param_list)\r
86 {\r
87         wchar_t tmp[MAX_SIZE];\r
88         wchar_t *buf;\r
89         UINT buf_size;\r
90         wchar_t *description, *args, *help;\r
91         UNI_TOKEN_LIST *t;\r
92         UINT width;\r
93         UINT i;\r
94         char *space;\r
95         // 引数チェック\r
96         if (c == NULL || cmd_name == NULL || param_list == NULL)\r
97         {\r
98                 return;\r
99         }\r
100 \r
101         width = GetConsoleWidth(c) - 2;\r
102 \r
103         buf_size = sizeof(wchar_t) * (width + 32);\r
104         buf = Malloc(buf_size);\r
105 \r
106         GetCommandHelpStr(cmd_name, &description, &args, &help);\r
107 \r
108         space = MakeCharArray(' ', 2);\r
109 \r
110         // タイトル\r
111         UniFormat(tmp, sizeof(tmp), _UU("CMD_HELP_TITLE"), cmd_name);\r
112         c->Write(c, tmp);\r
113         c->Write(c, L"");\r
114 \r
115         // 目的\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
119         {\r
120                 UniFormat(buf, buf_size, L"%S%s", space, t->Token[i]);\r
121                 c->Write(c, buf);\r
122         }\r
123         UniFreeToken(t);\r
124         c->Write(c, L"");\r
125 \r
126         // 説明\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
130         {\r
131                 UniFormat(buf, buf_size, L"%S%s", space, t->Token[i]);\r
132                 c->Write(c, buf);\r
133         }\r
134         UniFreeToken(t);\r
135         c->Write(c, L"");\r
136 \r
137         // 使用方法\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
141         {\r
142                 UniFormat(buf, buf_size, L"%S%s", space, t->Token[i]);\r
143                 c->Write(c, buf);\r
144         }\r
145         UniFreeToken(t);\r
146 \r
147         // 引数\r
148         if (param_list->NumTokens >= 1)\r
149         {\r
150                 c->Write(c, L"");\r
151                 c->Write(c, _UU("CMD_HELP_ARGS"));\r
152                 PrintCandidateHelp(c, cmd_name, param_list, 2);\r
153         }\r
154 \r
155         Free(space);\r
156 \r
157         Free(buf);\r
158 }\r
159 \r
160 // SafeStr であるかどうかの評価\r
161 bool CmdEvalSafe(CONSOLE *c, wchar_t *str, void *param)\r
162 {\r
163         wchar_t *p = (param == NULL) ? _UU("CMD_EVAL_SAFE") : (wchar_t *)param;\r
164 \r
165         if (IsSafeUniStr(str))\r
166         {\r
167                 return true;\r
168         }\r
169 \r
170         c->Write(c, p);\r
171 \r
172         return false;\r
173 }\r
174 \r
175 // 文字列入力プロンプト\r
176 wchar_t *CmdPrompt(CONSOLE *c, void *param)\r
177 {\r
178         wchar_t *p = (param == NULL) ? _UU("CMD_PROMPT") : (wchar_t *)param;\r
179 \r
180         return c->ReadLine(c, p, true);\r
181 }\r
182 \r
183 // 指定されたファイルが存在するかどうか評価\r
184 bool CmdEvalIsFile(CONSOLE *c, wchar_t *str, void *param)\r
185 {\r
186         char tmp[MAX_PATH];\r
187         // 引数チェック\r
188         if (c == NULL || str == NULL)\r
189         {\r
190                 return false;\r
191         }\r
192 \r
193         UniToStr(tmp, sizeof(tmp), str);\r
194 \r
195         if (IsEmptyStr(tmp))\r
196         {\r
197                 c->Write(c, _UU("CMD_FILE_NAME_EMPTY"));\r
198                 return false;\r
199         }\r
200 \r
201         if (IsFileExists(tmp) == false)\r
202         {\r
203                 wchar_t tmp2[MAX_SIZE];\r
204 \r
205                 UniFormat(tmp2, sizeof(tmp2), _UU("CMD_FILE_NOT_FOUND"), tmp);\r
206                 c->Write(c, tmp2);\r
207 \r
208                 return false;\r
209         }\r
210 \r
211         return true;\r
212 }\r
213 \r
214 // 整数の評価\r
215 bool CmdEvalInt1(CONSOLE *c, wchar_t *str, void *param)\r
216 {\r
217         wchar_t *p = (param == NULL) ? _UU("CMD_EVAL_INT") : (wchar_t *)param;\r
218 \r
219         if (UniToInt(str) == 0)\r
220         {\r
221                 c->Write(c, p);\r
222 \r
223                 return false;\r
224         }\r
225 \r
226         return true;\r
227 }\r
228 \r
229 // 空白を指定できないパラメータの評価\r
230 bool CmdEvalNotEmpty(CONSOLE *c, wchar_t *str, void *param)\r
231 {\r
232         wchar_t *p = (param == NULL) ? _UU("CMD_EVAL_NOT_EMPTY") : (wchar_t *)param;\r
233 \r
234         if (UniIsEmptyStr(str) == false)\r
235         {\r
236                 return true;\r
237         }\r
238 \r
239         c->Write(c, p);\r
240 \r
241         return false;\r
242 }\r
243 \r
244 // パラメータの最小 / 最大値評価関数\r
245 bool CmdEvalMinMax(CONSOLE *c, wchar_t *str, void *param)\r
246 {\r
247         CMD_EVAL_MIN_MAX *e;\r
248         wchar_t *tag;\r
249         UINT v;\r
250         // 引数チェック\r
251         if (param == NULL)\r
252         {\r
253                 return false;\r
254         }\r
255 \r
256         e = (CMD_EVAL_MIN_MAX *)param;\r
257 \r
258         if (e->StrName == NULL)\r
259         {\r
260                 tag = _UU("CMD_EVAL_MIN_MAX");\r
261         }\r
262         else\r
263         {\r
264                 tag = _UU(e->StrName);\r
265         }\r
266 \r
267         v = UniToInt(str);\r
268 \r
269         if (v >= e->MinValue && v <= e->MaxValue)\r
270         {\r
271                 return true;\r
272         }\r
273         else\r
274         {\r
275                 wchar_t tmp[MAX_SIZE];\r
276 \r
277                 UniFormat(tmp, sizeof(tmp), tag, e->MinValue, e->MaxValue);\r
278                 c->Write(c, tmp);\r
279 \r
280                 return false;\r
281         }\r
282 }\r
283 \r
284 // コマンドのヘルプ文字列を取得する\r
285 void GetCommandHelpStr(char *command_name, wchar_t **description, wchar_t **args, wchar_t **help)\r
286 {\r
287         char tmp1[128], tmp2[128], tmp3[128];\r
288 \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
292 \r
293         if (description != NULL)\r
294         {\r
295                 *description = _UU(tmp1);\r
296                 if (UniIsEmptyStr(*description))\r
297                 {\r
298                         *description = _UU("CMD_UNKNOWM");\r
299                 }\r
300         }\r
301 \r
302         if (args != NULL)\r
303         {\r
304                 *args = _UU(tmp2);\r
305                 if (UniIsEmptyStr(*args))\r
306                 {\r
307                         *args = _UU("CMD_UNKNOWN_ARGS");\r
308                 }\r
309         }\r
310 \r
311         if (help != NULL)\r
312         {\r
313                 *help = _UU(tmp3);\r
314                 if (UniIsEmptyStr(*help))\r
315                 {\r
316                         *help = _UU("CMD_UNKNOWN_HELP");\r
317                 }\r
318         }\r
319 }\r
320 \r
321 // パラメータのヘルプ文字列を取得する\r
322 void GetCommandParamHelpStr(char *command_name, char *param_name, wchar_t **description)\r
323 {\r
324         char tmp[160];\r
325         if (description == NULL)\r
326         {\r
327                 return;\r
328         }\r
329 \r
330         Format(tmp, sizeof(tmp), "CMD_%s_%s", command_name, param_name);\r
331 \r
332         *description = _UU(tmp);\r
333 \r
334         if (UniIsEmptyStr(*description))\r
335         {\r
336                 *description = _UU("CMD_UNKNOWN_PARAM");\r
337         }\r
338 }\r
339 \r
340 // 文字列比較関数\r
341 int CompareCandidateStr(void *p1, void *p2)\r
342 {\r
343         char *s1, *s2;\r
344         if (p1 == NULL || p2 == NULL)\r
345         {\r
346                 return 0;\r
347         }\r
348         s1 = *(char **)p1;\r
349         s2 = *(char **)p2;\r
350         if (s1 == NULL || s2 == NULL)\r
351         {\r
352                 return 0;\r
353         }\r
354 \r
355         if (s1[0] == '[' && s2[0] != '[')\r
356         {\r
357                 return -1;\r
358         }\r
359         else if (s2[0] == '[' && s1[0] != '[')\r
360         {\r
361                 return 1;\r
362         }\r
363 \r
364         return StrCmp(s1, s2);\r
365 }\r
366 \r
367 // 候補一覧のヘルプを表示する\r
368 void PrintCandidateHelp(CONSOLE *c, char *cmd_name, TOKEN_LIST *candidate_list, UINT left_space)\r
369 {\r
370         UINT console_width;\r
371         UINT max_keyword_width;\r
372         LIST *o;\r
373         UINT i;\r
374         wchar_t *tmpbuf;\r
375         UINT tmpbuf_size;\r
376         char *left_space_array;\r
377         char *max_space_array;\r
378         // 引数チェック\r
379         if (c == NULL || candidate_list == NULL)\r
380         {\r
381                 return;\r
382         }\r
383 \r
384         // 画面の横幅の取得\r
385         console_width = GetConsoleWidth(c) - 1;\r
386 \r
387         tmpbuf_size = sizeof(wchar_t) * (console_width + 32);\r
388         tmpbuf = Malloc(tmpbuf_size);\r
389 \r
390         left_space_array = MakeCharArray(' ', left_space);\r
391 \r
392         // コマンド名はソートしてリスト化する\r
393         // パラメータ名はソートしない\r
394         o = NewListFast(cmd_name == NULL ? CompareCandidateStr : NULL);\r
395 \r
396         max_keyword_width = 0;\r
397 \r
398         for (i = 0;i < candidate_list->NumTokens;i++)\r
399         {\r
400                 UINT keyword_width;\r
401 \r
402                 // 各キーワードの横幅を取得する\r
403                 Insert(o, candidate_list->Token[i]);\r
404 \r
405                 keyword_width = StrWidth(candidate_list->Token[i]);\r
406                 if (cmd_name != NULL)\r
407                 {\r
408                         if (candidate_list->Token[i][0] != '[')\r
409                         {\r
410                                 keyword_width += 1;\r
411                         }\r
412                         else\r
413                         {\r
414                                 keyword_width -= 2;\r
415                         }\r
416                 }\r
417 \r
418                 max_keyword_width = MAX(max_keyword_width, keyword_width);\r
419         }\r
420 \r
421         max_space_array = MakeCharArray(' ', max_keyword_width);\r
422 \r
423         // 候補を表示する\r
424         for (i = 0;i < LIST_NUM(o);i++)\r
425         {\r
426                 char tmp[128];\r
427                 char *name = LIST_DATA(o, i);\r
428                 UNI_TOKEN_LIST *t;\r
429                 wchar_t *help;\r
430                 UINT j;\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
434                 char *space;\r
435 \r
436                 if (console_width >= (descript_start_width + 5))\r
437                 {\r
438                         descript_width = console_width - descript_start_width - 3;\r
439                 }\r
440                 else\r
441                 {\r
442                         descript_width = 2;\r
443                 }\r
444 \r
445                 // 名前を生成する\r
446                 if (cmd_name != NULL && name[0] != '[')\r
447                 {\r
448                         // パラメータの場合は先頭に "/" を付ける\r
449                         Format(tmp, sizeof(tmp), "/%s", name);\r
450                 }\r
451                 else\r
452                 {\r
453                         // コマンド名の場合はそのままの文字を使用する\r
454                         if (cmd_name == NULL)\r
455                         {\r
456                                 StrCpy(tmp, sizeof(tmp), name);\r
457                         }\r
458                         else\r
459                         {\r
460                                 StrCpy(tmp, sizeof(tmp), name + 1);\r
461                                 if (StrLen(tmp) >= 1)\r
462                                 {\r
463                                         tmp[StrLen(tmp) - 1] = 0;\r
464                                 }\r
465                         }\r
466                 }\r
467 \r
468                 // ヘルプ文字を取得する\r
469                 if (cmd_name == NULL)\r
470                 {\r
471                         GetCommandHelpStr(name, &help, NULL, NULL);\r
472                 }\r
473                 else\r
474                 {\r
475                         GetCommandParamHelpStr(cmd_name, name, &help);\r
476                 }\r
477 \r
478                 space = MakeCharArray(' ', max_keyword_width - StrWidth(name) - (cmd_name == NULL ? 0 : (name[0] != '[' ? 1 : -2)));\r
479 \r
480                 t = SeparateStringByWidth(help, descript_width);\r
481 \r
482                 for (j = 0;j < t->NumTokens;j++)\r
483                 {\r
484                         if (j == 0)\r
485                         {\r
486                                 UniFormat(tmpbuf, tmpbuf_size, L"%S%S%S - %s",\r
487                                         left_space_array, tmp, space, t->Token[j]);\r
488                         }\r
489                         else\r
490                         {\r
491                                 UniFormat(tmpbuf, tmpbuf_size, L"%S%S   %s",\r
492                                         left_space_array, max_space_array, t->Token[j]);\r
493                         }\r
494 \r
495                         c->Write(c, tmpbuf);\r
496                 }\r
497 \r
498                 Free(space);\r
499 \r
500                 UniFreeToken(t);\r
501         }\r
502 \r
503         ReleaseList(o);\r
504 \r
505         Free(max_space_array);\r
506         Free(tmpbuf);\r
507         Free(left_space_array);\r
508 }\r
509 \r
510 // 文字列を指定された横幅で分割する\r
511 UNI_TOKEN_LIST *SeparateStringByWidth(wchar_t *str, UINT width)\r
512 {\r
513         UINT wp;\r
514         wchar_t *tmp;\r
515         UINT len, i;\r
516         LIST *o;\r
517         UNI_TOKEN_LIST *ret;\r
518         // 引数チェック\r
519         if (str == NULL)\r
520         {\r
521                 return UniNullToken();\r
522         }\r
523         if (width == 0)\r
524         {\r
525                 width = 1;\r
526         }\r
527 \r
528         o = NewListFast(NULL);\r
529 \r
530         len = UniStrLen(str);\r
531         tmp = ZeroMalloc(sizeof(wchar_t) * (len + 32));\r
532         wp = 0;\r
533 \r
534         for (i = 0;i < (len + 1);i++)\r
535         {\r
536                 wchar_t c = str[i];\r
537 \r
538                 switch (c)\r
539                 {\r
540                 case 0:\r
541                 case L'\r':\r
542                 case L'\n':\r
543                         if (c == L'\r')\r
544                         {\r
545                                 if (str[i + 1] == L'\n')\r
546                                 {\r
547                                         i++;\r
548                                 }\r
549                         }\r
550 \r
551                         tmp[wp++] = 0;\r
552                         wp = 0;\r
553 \r
554                         Insert(o, UniCopyStr(tmp));\r
555                         break;\r
556 \r
557                 default:\r
558                         tmp[wp++] = c;\r
559                         tmp[wp] = 0;\r
560                         if (UniStrWidth(tmp) >= width)\r
561                         {\r
562                                 tmp[wp++] = 0;\r
563                                 wp = 0;\r
564 \r
565                                 Insert(o, UniCopyStr(tmp));\r
566                         }\r
567                         break;\r
568                 }\r
569         }\r
570 \r
571         if (LIST_NUM(o) == 0)\r
572         {\r
573                 Insert(o, CopyUniStr(L""));\r
574         }\r
575 \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
579 \r
580         for (i = 0;i < LIST_NUM(o);i++)\r
581         {\r
582                 wchar_t *s = LIST_DATA(o, i);\r
583 \r
584                 ret->Token[i] = s;\r
585         }\r
586 \r
587         ReleaseList(o);\r
588         Free(tmp);\r
589 \r
590         return ret;\r
591 }\r
592 \r
593 // 指定した文字列が help を示すかどうかをチェック\r
594 bool IsHelpStr(char *str)\r
595 {\r
596         // 引数チェック\r
597         if (str == NULL)\r
598         {\r
599                 return false;\r
600         }\r
601 \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
609         {\r
610                 return true;\r
611         }\r
612 \r
613         return false;\r
614 }\r
615 \r
616 // コマンドの実行\r
617 bool DispatchNextCmd(CONSOLE *c, char *prompt, CMD cmd[], UINT num_cmd, void *param)\r
618 {\r
619         return DispatchNextCmdEx(c, NULL, prompt, cmd, num_cmd, param);\r
620 }\r
621 bool DispatchNextCmdEx(CONSOLE *c, wchar_t *exec_command, char *prompt, CMD cmd[], UINT num_cmd, void *param)\r
622 {\r
623         wchar_t *str;\r
624         wchar_t *tmp;\r
625         char *cmd_name;\r
626         bool b_exit = false;\r
627         wchar_t *cmd_param;\r
628         UINT ret = ERR_NO_ERROR;\r
629         TOKEN_LIST *t;\r
630         TOKEN_LIST *candidate;\r
631         bool no_end_crlf = false;\r
632         UINT i;\r
633         // 引数チェック\r
634         if (c == NULL || (num_cmd >= 1 && cmd == NULL))\r
635         {\r
636                 return false;\r
637         }\r
638 \r
639         if (exec_command == NULL)\r
640         {\r
641                 // プロンプトを表示\r
642 RETRY:\r
643                 tmp = CopyStrToUni(prompt);\r
644                 str = c->ReadLine(c, tmp, false);\r
645                 Free(tmp);\r
646 \r
647                 if (str != NULL && IsEmptyUniStr(str))\r
648                 {\r
649                         Free(str);\r
650                         goto RETRY;\r
651                 }\r
652         }\r
653         else\r
654         {\r
655                 wchar_t tmp[MAX_SIZE];\r
656                 // exec_command を使用\r
657                 if (UniStartWith(exec_command, L"utvpncmd") == false)\r
658                 {\r
659                         if (prompt != NULL)\r
660                         {\r
661                                 if (c->ConsoleType != CONSOLE_CSV)\r
662                                 {\r
663                                         UniFormat(tmp, sizeof(tmp), L"%S%s", prompt, exec_command);\r
664                                         c->Write(c, tmp);\r
665                                 }\r
666                         }\r
667                 }\r
668                 str = CopyUniStr(exec_command);\r
669         }\r
670 \r
671         if (str == NULL)\r
672         {\r
673                 // ユーザーキャンセル\r
674                 return false;\r
675         }\r
676 \r
677         UniTrimCrlf(str);\r
678         UniTrim(str);\r
679 \r
680         if (UniIsEmptyStr(str))\r
681         {\r
682                 // 何もしない\r
683                 Free(str);\r
684                 return true;\r
685         }\r
686 \r
687         // コマンド名とパラメータに分ける\r
688         if (SeparateCommandAndParam(str, &cmd_name, &cmd_param) == false)\r
689         {\r
690                 // 何もしない\r
691                 Free(str);\r
692                 return true;\r
693         }\r
694 \r
695         if (StrLen(cmd_name) >= 2 && cmd_name[0] == '?' && cmd_name[1] != '?')\r
696         {\r
697                 char tmp[MAX_SIZE];\r
698                 wchar_t *s;\r
699 \r
700                 StrCpy(tmp, sizeof(tmp), cmd_name + 1);\r
701                 StrCpy(cmd_name, 0, tmp);\r
702 \r
703                 s = UniCopyStr(L"/?");\r
704                 Free(cmd_param);\r
705 \r
706                 cmd_param = s;\r
707         }\r
708 \r
709         if (StrLen(cmd_name) >= 2 && EndWith(cmd_name, "?") && cmd_name[StrLen(cmd_name) - 2] != '?')\r
710         {\r
711                 wchar_t *s;\r
712 \r
713                 cmd_name[StrLen(cmd_name) - 1] = 0;\r
714 \r
715                 s = UniCopyStr(L"/?");\r
716                 Free(cmd_param);\r
717 \r
718                 cmd_param = s;\r
719         }\r
720 \r
721         // コマンドの候補を取得する\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
726         {\r
727                 t->Token[i] = CopyStr(cmd[i].Name);\r
728         }\r
729 \r
730         if (IsHelpStr(cmd_name))\r
731         {\r
732                 if (UniIsEmptyStr(cmd_param))\r
733                 {\r
734                         wchar_t tmp[MAX_SIZE];\r
735 \r
736                         // 使用できるコマンド一覧を表示する\r
737                         UniFormat(tmp, sizeof(tmp), _UU("CMD_HELP_1"), t->NumTokens);\r
738                         c->Write(c, tmp);\r
739 \r
740                         PrintCandidateHelp(c, NULL, t, 1);\r
741 \r
742                         c->Write(c, L"");\r
743                         c->Write(c, _UU("CMD_HELP_2"));\r
744                 }\r
745                 else\r
746                 {\r
747                         char *cmd_name;\r
748 \r
749                         // 指定したコマンドのヘルプを表示する\r
750                         if (SeparateCommandAndParam(cmd_param, &cmd_name, NULL))\r
751                         {\r
752                                 bool b = true;\r
753 \r
754                                 if (IsHelpStr(cmd_name))\r
755                                 {\r
756                                         b = false;\r
757                                 }\r
758 \r
759                                 if (b)\r
760                                 {\r
761                                         wchar_t str[MAX_SIZE];\r
762 \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
766                                 }\r
767 \r
768                                 Free(cmd_name);\r
769                         }\r
770                 }\r
771         }\r
772         else if (StrCmpi(cmd_name, "exit") == 0 || StrCmpi(cmd_name, "quit") == 0)\r
773         {\r
774                 // 終了\r
775                 b_exit = true;\r
776         }\r
777         else\r
778         {\r
779                 candidate = GetRealnameCandidate(cmd_name, t);\r
780 \r
781                 if (candidate == NULL || candidate->NumTokens == 0)\r
782                 {\r
783                         wchar_t tmp[MAX_SIZE];\r
784 \r
785                         // 候補無し\r
786                         UniFormat(tmp, sizeof(tmp), _UU("CON_UNKNOWN_CMD"), cmd_name);\r
787                         c->Write(c, tmp);\r
788 \r
789                         c->RetCode = ERR_BAD_COMMAND_OR_PARAM;\r
790                 }\r
791                 else if (candidate->NumTokens >= 2)\r
792                 {\r
793                         wchar_t tmp[MAX_SIZE];\r
794 \r
795                         // 候補が複数ある\r
796                         UniFormat(tmp, sizeof(tmp), _UU("CON_AMBIGIOUS_CMD"), cmd_name);\r
797                         c->Write(c, tmp);\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
801 \r
802                         c->RetCode = ERR_BAD_COMMAND_OR_PARAM;\r
803                 }\r
804                 else\r
805                 {\r
806                         char *real_cmd_name;\r
807                         UINT i;\r
808 \r
809                         // 1 つに定まった\r
810                         real_cmd_name = candidate->Token[0];\r
811 \r
812                         for (i = 0;i < num_cmd;i++)\r
813                         {\r
814                                 if (StrCmpi(cmd[i].Name, real_cmd_name) == 0)\r
815                                 {\r
816                                         if (cmd[i].Proc != NULL)\r
817                                         {\r
818                                                 // CSV モードでなければコマンドの説明を表示する\r
819                                                 if(c->ConsoleType != CONSOLE_CSV)\r
820                                                 {\r
821                                                         wchar_t tmp[256];\r
822                                                         wchar_t *note;\r
823 \r
824                                                         GetCommandHelpStr(cmd[i].Name, &note, NULL, NULL);\r
825                                                         UniFormat(tmp, sizeof(tmp), _UU("CMD_EXEC_MSG_NAME"), cmd[i].Name, note);\r
826                                                         c->Write(c, tmp);\r
827                                                 }\r
828 \r
829                                                 // コマンドのプロシージャを呼び出す\r
830                                                 ret = cmd[i].Proc(c, cmd[i].Name, cmd_param, param);\r
831 \r
832                                                 if (ret == INFINITE)\r
833                                                 {\r
834                                                         // 終了コマンド\r
835                                                         b_exit = true;\r
836                                                 }\r
837                                                 else\r
838                                                 {\r
839                                                         c->RetCode = ret;\r
840                                                 }\r
841                                         }\r
842                                 }\r
843                         }\r
844                 }\r
845 \r
846                 FreeToken(candidate);\r
847         }\r
848 \r
849         FreeToken(t);\r
850         Free(str);\r
851         Free(cmd_name);\r
852         Free(cmd_param);\r
853 \r
854         if (no_end_crlf == false)\r
855         {\r
856                 //c->Write(c, L"");\r
857         }\r
858 \r
859         if (b_exit)\r
860         {\r
861                 return false;\r
862         }\r
863 \r
864         return true;\r
865 }\r
866 \r
867 // 現在のコンソールの横幅を取得する\r
868 UINT GetConsoleWidth(CONSOLE *c)\r
869 {\r
870         UINT size;\r
871 \r
872         size = c->GetWidth(c);\r
873 \r
874         if (size == 0)\r
875         {\r
876                 size = 80;\r
877         }\r
878 \r
879         if (size < 32)\r
880         {\r
881                 size = 32;\r
882         }\r
883 \r
884         if (size > 65536)\r
885         {\r
886                 size = 65535;\r
887         }\r
888 \r
889         return size;\r
890 }\r
891 \r
892 // コマンドラインをコマンドとパラメータの 2 つに分離する\r
893 bool SeparateCommandAndParam(wchar_t *src, char **cmd, wchar_t **param)\r
894 {\r
895         UINT i, len, wp;\r
896         wchar_t *tmp;\r
897         wchar_t *src_tmp;\r
898         // 引数チェック\r
899         if (src == NULL)\r
900         {\r
901                 return false;\r
902         }\r
903         if (cmd != NULL)\r
904         {\r
905                 *cmd = NULL;\r
906         }\r
907         if (param != NULL)\r
908         {\r
909                 *param = NULL;\r
910         }\r
911 \r
912         src_tmp = UniCopyStr(src);\r
913         UniTrimCrlf(src_tmp);\r
914         UniTrim(src_tmp);\r
915 \r
916         len = UniStrLen(src_tmp);\r
917         tmp = Malloc(sizeof(wchar_t) * (len + 32));\r
918         wp = 0;\r
919 \r
920         for (i = 0;i < (len + 1);i++)\r
921         {\r
922                 wchar_t c = src_tmp[i];\r
923 \r
924                 switch (c)\r
925                 {\r
926                 case 0:\r
927                 case L' ':\r
928                 case L'\t':\r
929                         tmp[wp] = 0;\r
930                         if (UniIsEmptyStr(tmp))\r
931                         {\r
932                                 Free(tmp);\r
933                                 Free(src_tmp);\r
934                                 return false;\r
935                         }\r
936                         if (cmd != NULL)\r
937                         {\r
938                                 *cmd = CopyUniToStr(tmp);\r
939                                 Trim(*cmd);\r
940                         }\r
941                         goto ESCAPE;\r
942 \r
943                 default:\r
944                         tmp[wp++] = c;\r
945                         break;\r
946                 }\r
947         }\r
948 \r
949 ESCAPE:\r
950         if (param != NULL)\r
951         {\r
952                 *param = CopyUniStr(&src_tmp[wp]);\r
953                 UniTrim(*param);\r
954         }\r
955 \r
956         Free(tmp);\r
957         Free(src_tmp);\r
958 \r
959         return true;\r
960 }\r
961 \r
962 // ユーザーが指定したコマンド名の省略形に一致する実在するコマンドの一覧の候補を取得する\r
963 TOKEN_LIST *GetRealnameCandidate(char *input_name, TOKEN_LIST *real_name_list)\r
964 {\r
965         TOKEN_LIST *ret;\r
966         LIST *o;\r
967         UINT i;\r
968         bool ok = false;\r
969         // 引数チェック\r
970         if (input_name == NULL || real_name_list == NULL)\r
971         {\r
972                 return NullToken();\r
973         }\r
974 \r
975         o = NewListFast(NULL);\r
976 \r
977         for (i = 0;i < real_name_list->NumTokens;i++)\r
978         {\r
979                 char *name = real_name_list->Token[i];\r
980 \r
981                 // まず最優先で完全一致するものを検索する\r
982                 if (StrCmpi(name, input_name) == 0)\r
983                 {\r
984                         Insert(o, name);\r
985                         ok = true;\r
986                         break;\r
987                 }\r
988         }\r
989 \r
990         if (ok == false)\r
991         {\r
992                 // 完全一致するコマンドが無い場合、省略形コマンドとして一致するかどうかチェックする\r
993                 for (i = 0;i < real_name_list->NumTokens;i++)\r
994                 {\r
995                         char *name = real_name_list->Token[i];\r
996 \r
997                         if (IsOmissionName(input_name, name) || IsNameInRealName(input_name, name))\r
998                         {\r
999                                 // 省略形を発見した\r
1000                                 Insert(o, name);\r
1001                                 ok = true;\r
1002                         }\r
1003                 }\r
1004         }\r
1005 \r
1006         if (ok)\r
1007         {\r
1008                 // 1 つ以上の候補が見つかった\r
1009                 ret = ListToTokenList(o);\r
1010         }\r
1011         else\r
1012         {\r
1013                 ret = NullToken();\r
1014         }\r
1015 \r
1016         ReleaseList(o);\r
1017 \r
1018         return ret;\r
1019 }\r
1020 \r
1021 // ユーザーが指定したコマンドが既存のコマンドの省略形かどうかチェックする\r
1022 bool IsOmissionName(char *input_name, char *real_name)\r
1023 {\r
1024         char oname[128];\r
1025         // 引数チェック\r
1026         if (input_name == NULL || real_name == NULL)\r
1027         {\r
1028                 return false;\r
1029         }\r
1030 \r
1031         if (IsAllUpperStr(real_name))\r
1032         {\r
1033                 // すべて大文字のコマンドは省略形をとらない\r
1034                 return false;\r
1035         }\r
1036 \r
1037         GetOmissionName(oname, sizeof(oname), real_name);\r
1038 \r
1039         if (IsEmptyStr(oname))\r
1040         {\r
1041                 return false;\r
1042         }\r
1043 \r
1044         if (StartWith(oname, input_name))\r
1045         {\r
1046                 // 例: AccountSecureCertSet の oname は ascs だが\r
1047                 //     ユーザーが asc と入力した場合は true を返す\r
1048                 return true;\r
1049         }\r
1050 \r
1051         if (StartWith(input_name, oname))\r
1052         {\r
1053                 // 例: AccountConnect と\r
1054                 //     AccountCreate の 2 つのコマンドが実在する際、\r
1055                 //     ユーザーが "aconnect" と入力すると、\r
1056                 //     AccountConnect のみ true になるようにする\r
1057 \r
1058                 if (EndWith(real_name, &input_name[StrLen(oname)]))\r
1059                 {\r
1060                         return true;\r
1061                 }\r
1062         }\r
1063 \r
1064         return false;\r
1065 }\r
1066 \r
1067 // 指定したコマンド名の省略名を取得する\r
1068 void GetOmissionName(char *dst, UINT size, char *src)\r
1069 {\r
1070         UINT i, len;\r
1071         // 引数チェック\r
1072         if (dst == NULL || src == NULL)\r
1073         {\r
1074                 return;\r
1075         }\r
1076 \r
1077         StrCpy(dst, size, "");\r
1078         len = StrLen(src);\r
1079 \r
1080         for (i = 0;i < len;i++)\r
1081         {\r
1082                 char c = src[i];\r
1083 \r
1084                 if ((c >= '0' && c <= '9') ||\r
1085                         (c >= 'A' && c <= 'Z'))\r
1086                 {\r
1087                         char tmp[2];\r
1088                         tmp[0] = c;\r
1089                         tmp[1] = 0;\r
1090 \r
1091                         StrCat(dst, size, tmp);\r
1092                 }\r
1093         }\r
1094 }\r
1095 \r
1096 // ユーザーが指定したコマンドが既存のコマンドに一致するかどうかチェックする\r
1097 bool IsNameInRealName(char *input_name, char *real_name)\r
1098 {\r
1099         // 引数チェック\r
1100         if (input_name == NULL || real_name == NULL)\r
1101         {\r
1102                 return false;\r
1103         }\r
1104 \r
1105         if (StartWith(real_name, input_name))\r
1106         {\r
1107                 return true;\r
1108         }\r
1109 \r
1110         return false;\r
1111 }\r
1112 \r
1113 // コマンドリストをパースする\r
1114 LIST *ParseCommandList(CONSOLE *c, char *cmd_name, wchar_t *command, PARAM param[], UINT num_param)\r
1115 {\r
1116         UINT i;\r
1117         LIST *o;\r
1118         bool ok = true;\r
1119         TOKEN_LIST *param_list;\r
1120         TOKEN_LIST *real_name_list;\r
1121         bool help_mode = false;\r
1122         wchar_t *tmp;\r
1123         // 引数チェック\r
1124         if (c == NULL || command == NULL || (num_param >= 1 && param == NULL) || cmd_name == NULL)\r
1125         {\r
1126                 return NULL;\r
1127         }\r
1128 \r
1129         // 初期化\r
1130         for (i = 0;i < num_param;i++)\r
1131         {\r
1132                 if (IsEmptyStr(param[i].Name) == false)\r
1133                 {\r
1134                         if (param[i].Name[0] == '[')\r
1135                         {\r
1136                                 param[i].Tmp = "";\r
1137                         }\r
1138                         else\r
1139                         {\r
1140                                 param[i].Tmp = NULL;\r
1141                         }\r
1142                 }\r
1143                 else\r
1144                 {\r
1145                         param[i].Tmp = "";\r
1146                 }\r
1147         }\r
1148 \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
1152 \r
1153         for (i = 0;i < real_name_list->NumTokens;i++)\r
1154         {\r
1155                 real_name_list->Token[i] = CopyStr(param[i].Name);\r
1156         }\r
1157 \r
1158         // ユーザーが指定したパラメータ名のリストを生成する\r
1159         param_list = GetCommandNameList(command);\r
1160 \r
1161         for (i = 0;i < param_list->NumTokens;i++)\r
1162         {\r
1163                 char *s = param_list->Token[i];\r
1164 \r
1165                 if (StrCmpi(s, "help") == 0 || StrCmpi(s, "?") == 0)\r
1166                 {\r
1167                         help_mode = true;\r
1168                         break;\r
1169                 }\r
1170         }\r
1171 \r
1172         tmp = ParseCommand(command, L"");\r
1173         if (tmp != NULL)\r
1174         {\r
1175                 if (UniStrCmpi(tmp, L"?") == 0)\r
1176                 {\r
1177                         help_mode = true;\r
1178                 }\r
1179                 Free(tmp);\r
1180         }\r
1181 \r
1182         if (help_mode)\r
1183         {\r
1184                 // ヘルプを表示\r
1185                 PrintCmdHelp(c, cmd_name, real_name_list);\r
1186                 FreeToken(param_list);\r
1187                 FreeToken(real_name_list);\r
1188                 return NULL;\r
1189         }\r
1190 \r
1191         for (i = 0;i < param_list->NumTokens;i++)\r
1192         {\r
1193                 // ユーザーが指定したすべてのパラメータ名について対応するコマンドを取得する\r
1194                 TOKEN_LIST *candidate = GetRealnameCandidate(param_list->Token[i], real_name_list);\r
1195 \r
1196                 if (candidate != NULL && candidate->NumTokens >= 1)\r
1197                 {\r
1198                         if (candidate->NumTokens >= 2)\r
1199                         {\r
1200                                 wchar_t tmp[MAX_SIZE];\r
1201 \r
1202                                 // 2 つ以上の候補がある\r
1203                                 UniFormat(tmp, sizeof(tmp), _UU("CON_AMBIGIOUS_PARAM"), param_list->Token[i]);\r
1204                                 c->Write(c, tmp);\r
1205                                 UniFormat(tmp, sizeof(tmp), _UU("CON_AMBIGIOUS_PARAM_1"), cmd_name);\r
1206                                 c->Write(c, tmp);\r
1207 \r
1208                                 PrintCandidateHelp(c, cmd_name, candidate, 1);\r
1209 \r
1210                                 c->Write(c, _UU("CON_AMBIGIOUS_PARAM_2"));\r
1211 \r
1212                                 ok = false;\r
1213                         }\r
1214                         else\r
1215                         {\r
1216                                 UINT j;\r
1217                                 char *real_name = candidate->Token[0];\r
1218 \r
1219                                 // 候補が 1 つだけしか無い\r
1220                                 for (j = 0;j < num_param;j++)\r
1221                                 {\r
1222                                         if (StrCmpi(param[j].Name, real_name) == 0)\r
1223                                         {\r
1224                                                 param[j].Tmp = param_list->Token[i];\r
1225                                         }\r
1226                                 }\r
1227                         }\r
1228                 }\r
1229                 else\r
1230                 {\r
1231                         wchar_t tmp[MAX_SIZE];\r
1232 \r
1233                         // 候補無し\r
1234                         UniFormat(tmp, sizeof(tmp), _UU("CON_INVALID_PARAM"), param_list->Token[i], cmd_name, cmd_name);\r
1235                         c->Write(c, tmp);\r
1236 \r
1237                         ok = false;\r
1238                 }\r
1239 \r
1240                 FreeToken(candidate);\r
1241         }\r
1242 \r
1243         if (ok == false)\r
1244         {\r
1245                 FreeToken(param_list);\r
1246                 FreeToken(real_name_list);\r
1247 \r
1248                 return NULL;\r
1249         }\r
1250 \r
1251         // リストの作成\r
1252         o = NewParamValueList();\r
1253 \r
1254         // パラメータ一覧に指定された名前のすべてのパラメータを読み込む\r
1255         for (i = 0;i < num_param;i++)\r
1256         {\r
1257                 bool prompt_input_value = false;\r
1258                 PARAM *p = &param[i];\r
1259 \r
1260                 if (p->Tmp != NULL || p->PromptProc != NULL)\r
1261                 {\r
1262                         wchar_t *name = CopyStrToUni(p->Name);\r
1263                         wchar_t *tmp;\r
1264                         wchar_t *str;\r
1265 \r
1266                         if (p->Tmp != NULL)\r
1267                         {\r
1268                                 tmp = CopyStrToUni(p->Tmp);\r
1269                         }\r
1270                         else\r
1271                         {\r
1272                                 tmp = CopyStrToUni(p->Name);\r
1273                         }\r
1274 \r
1275                         str = ParseCommand(command, tmp);\r
1276                         Free(tmp);\r
1277                         if (str != NULL)\r
1278                         {\r
1279                                 wchar_t *unistr;\r
1280                                 bool ret;\r
1281 EVAL_VALUE:\r
1282                                 // 読み込みに成功した\r
1283                                 unistr = str;\r
1284 \r
1285                                 if (p->EvalProc != NULL)\r
1286                                 {\r
1287                                         // EvalProc が指定されている場合は値を評価する\r
1288                                         ret = p->EvalProc(c, unistr, p->EvalProcParam);\r
1289                                 }\r
1290                                 else\r
1291                                 {\r
1292                                         // EvalProc が指定されていない場合はどのような値でも受け付ける\r
1293                                         ret = true;\r
1294                                 }\r
1295 \r
1296                                 if (ret == false)\r
1297                                 {\r
1298                                         // 指定した値は不正である\r
1299                                         if (p->PromptProc == NULL)\r
1300                                         {\r
1301                                                 // キャンセル\r
1302                                                 ok = false;\r
1303                                                 Free(name);\r
1304                                                 Free(str);\r
1305                                                 break;\r
1306                                         }\r
1307                                         else\r
1308                                         {\r
1309                                                 // もう一度入力させる\r
1310                                                 Free(str);\r
1311                                                 str = NULL;\r
1312                                                 goto SHOW_PROMPT;\r
1313                                         }\r
1314                                 }\r
1315                                 else\r
1316                                 {\r
1317                                         PARAM_VALUE *v;\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
1324                                         Insert(o, v);\r
1325                                 }\r
1326                         }\r
1327                         else\r
1328                         {\r
1329                                 // 読み込みに失敗した。指定されたパラメータが指定されていない\r
1330                                 if (p->PromptProc != NULL)\r
1331                                 {\r
1332                                         wchar_t *tmp;\r
1333 SHOW_PROMPT:\r
1334                                         // 必須パラメータであるのでプロンプトを表示する\r
1335                                         tmp = p->PromptProc(c, p->PromptProcParam);\r
1336                                         if (tmp == NULL)\r
1337                                         {\r
1338                                                 // ユーザーがキャンセルした\r
1339                                                 ok = false;\r
1340                                                 Free(str);\r
1341                                                 Free(name);\r
1342                                                 break;\r
1343                                         }\r
1344                                         else\r
1345                                         {\r
1346                                                 // ユーザーが入力した\r
1347                                                 c->Write(c, L"");\r
1348                                                 str = tmp;\r
1349                                                 prompt_input_value = true;\r
1350                                                 goto EVAL_VALUE;\r
1351                                         }\r
1352                                 }\r
1353                         }\r
1354 \r
1355                         Free(str);\r
1356                         Free(name);\r
1357                 }\r
1358         }\r
1359 \r
1360         FreeToken(param_list);\r
1361         FreeToken(real_name_list);\r
1362 \r
1363         if (ok)\r
1364         {\r
1365                 return o;\r
1366         }\r
1367         else\r
1368         {\r
1369                 FreeParamValueList(o);\r
1370                 return NULL;\r
1371         }\r
1372 }\r
1373 \r
1374 // [はい] か [いいえ] の取得\r
1375 bool GetParamYes(LIST *o, char *name)\r
1376 {\r
1377         char *s;\r
1378         char tmp[64];\r
1379         // 引数チェック\r
1380         if (o == NULL)\r
1381         {\r
1382                 return false;\r
1383         }\r
1384 \r
1385         s = GetParamStr(o, name);\r
1386         if (s == NULL)\r
1387         {\r
1388                 return false;\r
1389         }\r
1390 \r
1391         StrCpy(tmp, sizeof(tmp), s);\r
1392         Trim(tmp);\r
1393 \r
1394         if (StartWith(tmp, "y"))\r
1395         {\r
1396                 return true;\r
1397         }\r
1398 \r
1399         if (StartWith(tmp, "t"))\r
1400         {\r
1401                 return true;\r
1402         }\r
1403 \r
1404         if (ToInt(tmp) != 0)\r
1405         {\r
1406                 return true;\r
1407         }\r
1408 \r
1409         return false;\r
1410 }\r
1411 \r
1412 // パラメータ値 Int の取得\r
1413 UINT GetParamInt(LIST *o, char *name)\r
1414 {\r
1415         PARAM_VALUE *v;\r
1416         // 引数チェック\r
1417         if (o == NULL)\r
1418         {\r
1419                 return 0;\r
1420         }\r
1421 \r
1422         v = FindParamValue(o, name);\r
1423         if (v == NULL)\r
1424         {\r
1425                 return 0;\r
1426         }\r
1427         else\r
1428         {\r
1429                 return v->IntValue;\r
1430         }\r
1431 }\r
1432 \r
1433 // パラメータ値 Unicode 文字列の取得\r
1434 wchar_t *GetParamUniStr(LIST *o, char *name)\r
1435 {\r
1436         PARAM_VALUE *v;\r
1437         // 引数チェック\r
1438         if (o == NULL)\r
1439         {\r
1440                 return NULL;\r
1441         }\r
1442 \r
1443         v = FindParamValue(o, name);\r
1444         if (v == NULL)\r
1445         {\r
1446                 return NULL;\r
1447         }\r
1448         else\r
1449         {\r
1450                 return v->UniStrValue;\r
1451         }\r
1452 }\r
1453 \r
1454 // パラメータ値文字列の所得\r
1455 char *GetParamStr(LIST *o, char *name)\r
1456 {\r
1457         PARAM_VALUE *v;\r
1458         // 引数チェック\r
1459         if (o == NULL)\r
1460         {\r
1461                 return NULL;\r
1462         }\r
1463 \r
1464         v = FindParamValue(o, name);\r
1465         if (v == NULL)\r
1466         {\r
1467                 return NULL;\r
1468         }\r
1469         else\r
1470         {\r
1471                 return v->StrValue;\r
1472         }\r
1473 }\r
1474 \r
1475 // パラメータ値の取得\r
1476 PARAM_VALUE *FindParamValue(LIST *o, char *name)\r
1477 {\r
1478         PARAM_VALUE t, *ret;\r
1479         // 引数チェック\r
1480         if (o == NULL)\r
1481         {\r
1482                 return NULL;\r
1483         }\r
1484         if (name == NULL)\r
1485         {\r
1486                 name = "";\r
1487         }\r
1488 \r
1489         Zero(&t, sizeof(t));\r
1490         t.Name = name;\r
1491 \r
1492         ret = Search(o, &t);\r
1493 \r
1494         return ret;\r
1495 }\r
1496 \r
1497 // パラメータ値リストの解放\r
1498 void FreeParamValueList(LIST *o)\r
1499 {\r
1500         UINT i;\r
1501         // 引数チェック\r
1502         if (o == NULL)\r
1503         {\r
1504                 return;\r
1505         }\r
1506 \r
1507         for (i = 0;i < LIST_NUM(o);i++)\r
1508         {\r
1509                 PARAM_VALUE *v = LIST_DATA(o, i);\r
1510 \r
1511                 Free(v->StrValue);\r
1512                 Free(v->UniStrValue);\r
1513                 Free(v->Name);\r
1514                 Free(v);\r
1515         }\r
1516 \r
1517         ReleaseList(o);\r
1518 }\r
1519 \r
1520 // パラメータ値リストソート関数\r
1521 int CmpParamValue(void *p1, void *p2)\r
1522 {\r
1523         PARAM_VALUE *v1, *v2;\r
1524         if (p1 == NULL || p2 == NULL)\r
1525         {\r
1526                 return 0;\r
1527         }\r
1528         v1 = *(PARAM_VALUE **)p1;\r
1529         v2 = *(PARAM_VALUE **)p2;\r
1530         if (v1 == NULL || v2 == NULL)\r
1531         {\r
1532                 return 0;\r
1533         }\r
1534 \r
1535         if (IsEmptyStr(v1->Name) && IsEmptyStr(v2->Name))\r
1536         {\r
1537                 return 0;\r
1538         }\r
1539         return StrCmpi(v1->Name, v2->Name);\r
1540 }\r
1541 \r
1542 // パラメータ値リストの生成\r
1543 LIST *NewParamValueList()\r
1544 {\r
1545         return NewListFast(CmpParamValue);\r
1546 }\r
1547 \r
1548 // 入力されたコマンドに含まれていたパラメータ名のリストを取得する\r
1549 TOKEN_LIST *GetCommandNameList(wchar_t *str)\r
1550 {\r
1551         TOKEN_LIST *t;\r
1552         // 引数チェック\r
1553         if (str == NULL)\r
1554         {\r
1555                 return NullToken();\r
1556         }\r
1557 \r
1558         Free(ParseCommandEx(str, L"dummy_str", &t));\r
1559 \r
1560         return t;\r
1561 }\r
1562 \r
1563 // 指定した名前で始まるコマンドを取得する\r
1564 wchar_t *ParseCommand(wchar_t *str, wchar_t *name)\r
1565 {\r
1566         return ParseCommandEx(str, name, NULL);\r
1567 }\r
1568 wchar_t *ParseCommandEx(wchar_t *str, wchar_t *name, TOKEN_LIST **param_list)\r
1569 {\r
1570         UNI_TOKEN_LIST *t;\r
1571         UINT i;\r
1572         wchar_t *tmp;\r
1573         wchar_t *ret = NULL;\r
1574         LIST *o;\r
1575         // 引数チェック\r
1576         if (str == NULL)\r
1577         {\r
1578                 return NULL;\r
1579         }\r
1580         if (name != NULL && UniIsEmptyStr(name))\r
1581         {\r
1582                 name = NULL;\r
1583         }\r
1584 \r
1585         o = NULL;\r
1586         if (param_list != NULL)\r
1587         {\r
1588                 o = NewListFast(CompareStr);\r
1589         }\r
1590 \r
1591         tmp = CopyUniStr(str);\r
1592         UniTrim(tmp);\r
1593 \r
1594         i = UniSearchStrEx(tmp, L"/CMD ", 0, false);\r
1595 \r
1596         // このあたりは急いで実装したのでコードがあまり美しくない。\r
1597         if (i != INFINITE && i >= 1 && tmp[i - 1] == L'/')\r
1598         {\r
1599                 i = INFINITE;\r
1600         }\r
1601         if (i == INFINITE)\r
1602         {\r
1603                 i = UniSearchStrEx(tmp, L"/CMD\t", 0, false);\r
1604                 if (i != INFINITE && i >= 1 && tmp[i - 1] == L'/')\r
1605                 {\r
1606                         i = INFINITE;\r
1607                 }\r
1608         }\r
1609         if (i == INFINITE)\r
1610         {\r
1611                 i = UniSearchStrEx(tmp, L"/CMD:", 0, false);\r
1612                 if (i != INFINITE && i >= 1 && tmp[i - 1] == L'/')\r
1613                 {\r
1614                         i = INFINITE;\r
1615                 }\r
1616         }\r
1617         if (i == INFINITE)\r
1618         {\r
1619                 i = UniSearchStrEx(tmp, L"/CMD=", 0, false);\r
1620                 if (i != INFINITE && i >= 1 && tmp[i - 1] == L'/')\r
1621                 {\r
1622                         i = INFINITE;\r
1623                 }\r
1624         }\r
1625         if (i == INFINITE)\r
1626         {\r
1627                 i = UniSearchStrEx(tmp, L"-CMD ", 0, false);\r
1628                 if (i != INFINITE && i >= 1 && tmp[i - 1] == L'-')\r
1629                 {\r
1630                         i = INFINITE;\r
1631                 }\r
1632         }\r
1633         if (i == INFINITE)\r
1634         {\r
1635                 i = UniSearchStrEx(tmp, L"-CMD\t", 0, false);\r
1636                 if (i != INFINITE && i >= 1 && tmp[i - 1] == L'-')\r
1637                 {\r
1638                         i = INFINITE;\r
1639                 }\r
1640         }\r
1641         if (i == INFINITE)\r
1642         {\r
1643                 i = UniSearchStrEx(tmp, L"-CMD:", 0, false);\r
1644                 if (i != INFINITE && i >= 1 && tmp[i - 1] == L'-')\r
1645                 {\r
1646                         i = INFINITE;\r
1647                 }\r
1648         }\r
1649         if (i == INFINITE)\r
1650         {\r
1651                 i = UniSearchStrEx(tmp, L"-CMD=", 0, false);\r
1652                 if (i != INFINITE && i >= 1 && tmp[i - 1] == L'-')\r
1653                 {\r
1654                         i = INFINITE;\r
1655                 }\r
1656         }\r
1657 \r
1658         if (i != INFINITE)\r
1659         {\r
1660                 char *s = CopyStr("CMD");\r
1661                 if (InsertStr(o, s) == false)\r
1662                 {\r
1663                         Free(s);\r
1664                 }\r
1665                 if (UniStrCmpi(name, L"CMD") == 0)\r
1666                 {\r
1667                         ret = CopyUniStr(&str[i + 5]);\r
1668                         UniTrim(ret);\r
1669                 }\r
1670                 else\r
1671                 {\r
1672                         tmp[i] = 0;\r
1673                 }\r
1674         }\r
1675 \r
1676         if (ret == NULL)\r
1677         {\r
1678                 t = UniParseCmdLine(tmp);\r
1679 \r
1680                 if (t != NULL)\r
1681                 {\r
1682                         for (i = 0;i < t->NumTokens;i++)\r
1683                         {\r
1684                                 wchar_t *token = t->Token[i];\r
1685 \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
1689                                 {\r
1690                                         UINT i;\r
1691 \r
1692                                         // 名前付き引数\r
1693                                         // コロン文字があるかどうか調べる\r
1694 \r
1695                                         if (UniStrCmpi(token, L"--help") == 0)\r
1696                                         {\r
1697                                                 token++;\r
1698                                         }\r
1699 \r
1700                                         i = UniSearchStrEx(token, L":", 0, false);\r
1701                                         if (i == INFINITE)\r
1702                                         {\r
1703                                                 i = UniSearchStrEx(token, L"=", 0, false);\r
1704                                         }\r
1705                                         if (i != INFINITE)\r
1706                                         {\r
1707                                                 wchar_t *tmp;\r
1708                                                 char *a;\r
1709 \r
1710                                                 // コロン文字がある\r
1711                                                 tmp = CopyUniStr(token);\r
1712                                                 tmp[i] = 0;\r
1713 \r
1714                                                 a = CopyUniToStr(&tmp[1]);\r
1715                                                 if (InsertStr(o, a) == false)\r
1716                                                 {\r
1717                                                         Free(a);\r
1718                                                 }\r
1719 \r
1720                                                 if (UniStrCmpi(name, &tmp[1]) == 0)\r
1721                                                 {\r
1722                                                         if (ret == NULL)\r
1723                                                         {\r
1724                                                                 // 内容\r
1725                                                                 ret = UniCopyStr(&token[i + 1]);\r
1726                                                         }\r
1727                                                 }\r
1728 \r
1729                                                 Free(tmp);\r
1730                                         }\r
1731                                         else\r
1732                                         {\r
1733                                                 // コロン文字が無い\r
1734                                                 char *a;\r
1735 \r
1736                                                 a = CopyUniToStr(&token[1]);\r
1737                                                 if (InsertStr(o, a) == false)\r
1738                                                 {\r
1739                                                         Free(a);\r
1740                                                 }\r
1741 \r
1742                                                 if (UniStrCmpi(name, &token[1]) == 0)\r
1743                                                 {\r
1744                                                         if (ret == NULL)\r
1745                                                         {\r
1746                                                                 // 空文字\r
1747                                                                 ret = UniCopyStr(L"");\r
1748                                                         }\r
1749                                                 }\r
1750                                         }\r
1751                                 }\r
1752                                 else\r
1753                                 {\r
1754                                         // 名前無し引数\r
1755                                         if (name == NULL)\r
1756                                         {\r
1757                                                 if (ret == NULL)\r
1758                                                 {\r
1759                                                         if (token[0] == L'-' && token[1] == L'-')\r
1760                                                         {\r
1761                                                                 ret = UniCopyStr(&token[1]);\r
1762                                                         }\r
1763                                                         else if (token[0] == L'/' && token[1] == L'/')\r
1764                                                         {\r
1765                                                                 ret = UniCopyStr(&token[1]);\r
1766                                                         }\r
1767                                                         else\r
1768                                                         {\r
1769                                                                 ret = UniCopyStr(token);\r
1770                                                         }\r
1771                                                 }\r
1772                                         }\r
1773                                 }\r
1774                         }\r
1775 \r
1776                         UniFreeToken(t);\r
1777                 }\r
1778         }\r
1779 \r
1780         Free(tmp);\r
1781 \r
1782         if (o != NULL)\r
1783         {\r
1784                 TOKEN_LIST *t = ZeroMalloc(sizeof(TOKEN_LIST));\r
1785                 UINT i;\r
1786 \r
1787                 t->NumTokens = LIST_NUM(o);\r
1788                 t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);\r
1789 \r
1790                 for (i = 0;i < t->NumTokens;i++)\r
1791                 {\r
1792                         t->Token[i] = LIST_DATA(o, i);\r
1793                 }\r
1794 \r
1795                 ReleaseList(o);\r
1796 \r
1797                 *param_list = t;\r
1798         }\r
1799 \r
1800         if (UniStrCmpi(ret, L"none") == 0 || UniStrCmpi(ret, L"null") == 0)\r
1801         {\r
1802                 // none と null は予約語である\r
1803                 ret[0] = 0;\r
1804         }\r
1805 \r
1806         return ret;\r
1807 }\r
1808 char *ParseCommandA(wchar_t *str, char *name)\r
1809 {\r
1810         wchar_t *tmp1, *tmp2;\r
1811         char *ret;\r
1812         // 引数チェック\r
1813         if (str == NULL)\r
1814         {\r
1815                 return NULL;\r
1816         }\r
1817 \r
1818         if (name != NULL)\r
1819         {\r
1820                 tmp1 = CopyStrToUni(name);\r
1821         }\r
1822         else\r
1823         {\r
1824                 tmp1 = NULL;\r
1825         }\r
1826 \r
1827         tmp2 = ParseCommand(str, tmp1);\r
1828 \r
1829         if (tmp2 == NULL)\r
1830         {\r
1831                 ret = NULL;\r
1832         }\r
1833         else\r
1834         {\r
1835                 ret = CopyUniToStr(tmp2);\r
1836                 Free(tmp2);\r
1837         }\r
1838 \r
1839         Free(tmp1);\r
1840 \r
1841         return ret;\r
1842 }\r
1843 \r
1844 // パスワードプロンプト\r
1845 bool PasswordPrompt(char *password, UINT size)\r
1846 {\r
1847         UINT wp;\r
1848         bool escape = false;\r
1849         void *console;\r
1850         // 引数チェック\r
1851         if (password == NULL || size <= 1)\r
1852         {\r
1853                 if (size >= 1)\r
1854                 {\r
1855                         password[0] = 0;\r
1856                 }\r
1857                 return false;\r
1858         }\r
1859 \r
1860         wp = 0;\r
1861 \r
1862         Zero(password, size);\r
1863 \r
1864         console = SetConsoleRaw();\r
1865 \r
1866         while (true)\r
1867         {\r
1868                 int c;\r
1869 \r
1870 #ifdef  OS_WIN32\r
1871                 c = getch();\r
1872 #else   // OS_WIN32\r
1873                 c = getc(stdin);\r
1874 #endif  // OS_WIN32\r
1875 \r
1876                 if (c >= 0x20 && c <= 0x7E)\r
1877                 {\r
1878                         // 文字\r
1879                         if ((wp + 1) < size)\r
1880                         {\r
1881                                 password[wp++] = (char)c;\r
1882                                 putc('*', stdout);\r
1883                         }\r
1884                 }\r
1885                 else if (c == 0x03)\r
1886                 {\r
1887                         // 強制終了\r
1888                         exit(0);\r
1889                 }\r
1890                 else if (c == 0x04 || c == 0x1a || c == 0x0D || c==0x0A)\r
1891                 {\r
1892                         // 終了\r
1893                         if (c == 0x04 || c == 0x1a)\r
1894                         {\r
1895                                 escape = true;\r
1896                         }\r
1897                         break;\r
1898                 }\r
1899                 else if (c == 0xE0)\r
1900                 {\r
1901                         // もう 1 文字読む\r
1902                         c = getch();\r
1903                         if (c == 0x4B || c == 0x53)\r
1904                         {\r
1905                                 // バックスペース\r
1906                                 goto BACKSPACE;\r
1907                         }\r
1908                 }\r
1909                 else if (c == 0x08)\r
1910                 {\r
1911 BACKSPACE:\r
1912                         // バックスペース\r
1913                         if (wp >= 1)\r
1914                         {\r
1915                                 password[--wp] = 0;\r
1916                                 putc(0x08, stdout);\r
1917                                 putc(' ', stdout);\r
1918                                 putc(0x08, stdout);\r
1919                         }\r
1920                 }\r
1921         }\r
1922         Print("\n");\r
1923 \r
1924         RestoreConsole(console);\r
1925 \r
1926         return (escape ? false : true);\r
1927 }\r
1928 \r
1929 // プロンプトを表示\r
1930 wchar_t *Prompt(wchar_t *prompt_str)\r
1931 {\r
1932         wchar_t *ret = NULL;\r
1933         wchar_t *tmp = NULL;\r
1934         // 引数チェック\r
1935         if (prompt_str == NULL)\r
1936         {\r
1937                 prompt_str = L"";\r
1938         }\r
1939 \r
1940 #ifdef  OS_WIN32\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
1944         {\r
1945                 bool escape = false;\r
1946                 UINT i, len;\r
1947 \r
1948                 len = UniStrLen(tmp);\r
1949                 for (i = 0;i < len;i++)\r
1950                 {\r
1951                         if (tmp[i] == 0x04 || tmp[i] == 0x1A)\r
1952                         {\r
1953                                 escape = true;\r
1954                                 break;\r
1955                         }\r
1956                 }\r
1957 \r
1958                 if (escape == false)\r
1959                 {\r
1960                         UniTrimCrlf(tmp);\r
1961 \r
1962                         ret = UniCopyStr(tmp);\r
1963                 }\r
1964         }\r
1965         Free(tmp);\r
1966 #else   // OS_WIN32\r
1967         {\r
1968                 char *prompt = CopyUniToStr(prompt_str);\r
1969                 char *s = readline(prompt);\r
1970                 Free(prompt);\r
1971 \r
1972                 if (s != NULL)\r
1973                 {\r
1974                         TrimCrlf(s);\r
1975                         Trim(s);\r
1976 \r
1977                         if (IsEmptyStr(s) == false)\r
1978                         {\r
1979                                 add_history(s);\r
1980                         }\r
1981 \r
1982                         ret = CopyStrToUni(s);\r
1983 \r
1984                         free(s);\r
1985                 }\r
1986         }\r
1987 #endif  // OS_WIN32\r
1988 \r
1989         if (ret == NULL)\r
1990         {\r
1991                 Print("\n");\r
1992         }\r
1993 \r
1994         return ret;\r
1995 }\r
1996 char *PromptA(wchar_t *prompt_str)\r
1997 {\r
1998         wchar_t *str = Prompt(prompt_str);\r
1999 \r
2000         if (str == NULL)\r
2001         {\r
2002                 return NULL;\r
2003         }\r
2004         else\r
2005         {\r
2006                 char *ret = CopyUniToStr(str);\r
2007 \r
2008                 Free(str);\r
2009                 return ret;\r
2010         }\r
2011 }\r
2012 \r
2013 // コンソールを Raw モードにする\r
2014 void *SetConsoleRaw()\r
2015 {\r
2016 #ifdef  OS_UNIX\r
2017         struct termios t, *ret;\r
2018 \r
2019         Zero(&t, sizeof(t));\r
2020         if (tcgetattr(0, &t) != 0)\r
2021         {\r
2022                 // 失敗\r
2023                 return NULL;\r
2024         }\r
2025 \r
2026         // 現在の設定をコピー\r
2027         ret = Clone(&t, sizeof(t));\r
2028 \r
2029         // 設定を変更\r
2030         t.c_lflag &= (~ICANON);\r
2031         t.c_lflag &= (~ECHO);\r
2032         t.c_cc[VTIME] = 0;\r
2033         t.c_cc[VMIN] = 1;\r
2034         tcsetattr(0, TCSANOW, &t);\r
2035 \r
2036         return ret;\r
2037 #else   // OS_UNIX\r
2038         return Malloc(0);\r
2039 #endif  // OS_UNIX\r
2040 }\r
2041 \r
2042 // コンソールのモードを復帰する\r
2043 void RestoreConsole(void *p)\r
2044 {\r
2045 #ifdef  OS_UNIX\r
2046         struct termios *t;\r
2047         // 引数チェック\r
2048         if (p == NULL)\r
2049         {\r
2050                 return;\r
2051         }\r
2052 \r
2053         t = (struct termios *)p;\r
2054 \r
2055         // 設定を復帰する\r
2056         tcsetattr(0, TCSANOW, t);\r
2057 \r
2058         Free(t);\r
2059 #else   // OS_UNIX\r
2060         if (p != NULL)\r
2061         {\r
2062                 Free(p);\r
2063         }\r
2064 #endif  // OS_UNIX\r
2065 }\r
2066 \r
2067 ////////////////////////////\r
2068 // ローカルコンソール関数\r
2069 \r
2070 // 新しいローカルコンソールの作成\r
2071 CONSOLE *NewLocalConsole(wchar_t *infile, wchar_t *outfile)\r
2072 {\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
2077 \r
2078 #ifdef  OS_WIN32\r
2079         if (MsGetConsoleWidth() == 80)\r
2080         {\r
2081                 //old_size = MsSetConsoleWidth(WIN32_DEFAULT_CONSOLE_WIDTH);\r
2082         }\r
2083 #endif  // OS_WIN32\r
2084 \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
2091 \r
2092         if (UniIsEmptyStr(infile) == false)\r
2093         {\r
2094                 // 入力ファイルが指定されている\r
2095                 in_io = FileOpenW(infile, false);\r
2096                 if (in_io == NULL)\r
2097                 {\r
2098                         wchar_t tmp[MAX_SIZE];\r
2099 \r
2100                         UniFormat(tmp, sizeof(tmp), _UU("CON_INFILE_ERROR"), infile);\r
2101                         c->Write(c, tmp);\r
2102                         Free(c);\r
2103                         return NULL;\r
2104                 }\r
2105                 else\r
2106                 {\r
2107                         wchar_t tmp[MAX_SIZE];\r
2108 \r
2109                         UniFormat(tmp, sizeof(tmp), _UU("CON_INFILE_START"), infile);\r
2110                         c->Write(c, tmp);\r
2111                 }\r
2112         }\r
2113 \r
2114         if (UniIsEmptyStr(outfile) == false)\r
2115         {\r
2116                 // 出力ファイルが指定されている\r
2117                 out_io = FileCreateW(outfile);\r
2118                 if (out_io == NULL)\r
2119                 {\r
2120                         wchar_t tmp[MAX_SIZE];\r
2121 \r
2122                         UniFormat(tmp, sizeof(tmp), _UU("CON_OUTFILE_ERROR"), outfile);\r
2123                         c->Write(c, tmp);\r
2124                         Free(c);\r
2125 \r
2126                         if (in_io != NULL)\r
2127                         {\r
2128                                 FileClose(in_io);\r
2129                         }\r
2130                         return NULL;\r
2131                 }\r
2132                 else\r
2133                 {\r
2134                         wchar_t tmp[MAX_SIZE];\r
2135 \r
2136                         UniFormat(tmp, sizeof(tmp), _UU("CON_OUTFILE_START"), outfile);\r
2137                         c->Write(c, tmp);\r
2138                 }\r
2139         }\r
2140 \r
2141         p = ZeroMalloc(sizeof(LOCAL_CONSOLE_PARAM));\r
2142         c->Param = p;\r
2143 \r
2144         p->InFile = in_io;\r
2145         p->OutFile = out_io;\r
2146         p->Win32_OldConsoleWidth = old_size;\r
2147 \r
2148         if (in_io != NULL)\r
2149         {\r
2150                 UINT size;\r
2151                 void *buf;\r
2152 \r
2153                 size = FileSize(in_io);\r
2154                 buf = ZeroMalloc(size + 1);\r
2155                 FileRead(in_io, buf, size);\r
2156 \r
2157                 p->InBuf = NewBuf();\r
2158                 WriteBuf(p->InBuf, buf, size);\r
2159                 Free(buf);\r
2160 \r
2161                 p->InBuf->Current = 0;\r
2162         }\r
2163 \r
2164         return c;\r
2165 }\r
2166 \r
2167 // コンソール解放\r
2168 void ConsoleLocalFree(CONSOLE *c)\r
2169 {\r
2170         LOCAL_CONSOLE_PARAM *p;\r
2171         // 引数チェック\r
2172         if (c == NULL)\r
2173         {\r
2174                 return;\r
2175         }\r
2176 \r
2177         p = (LOCAL_CONSOLE_PARAM *)c->Param;\r
2178 \r
2179 #ifdef  OS_WIN32\r
2180         if (p->Win32_OldConsoleWidth != 0)\r
2181         {\r
2182                 MsSetConsoleWidth(p->Win32_OldConsoleWidth);\r
2183         }\r
2184 #endif  // OS_WIN32\r
2185 \r
2186         if (p != NULL)\r
2187         {\r
2188                 if (p->InFile != NULL)\r
2189                 {\r
2190                         FileClose(p->InFile);\r
2191                         FreeBuf(p->InBuf);\r
2192                 }\r
2193 \r
2194                 if (p->OutFile != NULL)\r
2195                 {\r
2196                         FileClose(p->OutFile);\r
2197                 }\r
2198 \r
2199                 Free(p);\r
2200         }\r
2201 \r
2202         // メモリ解放\r
2203         Free(c);\r
2204 }\r
2205 \r
2206 // 画面の横幅を取得\r
2207 UINT ConsoleLocalGetWidth(CONSOLE *c)\r
2208 {\r
2209         UINT ret = 0;\r
2210         // 引数チェック\r
2211         if (c == NULL)\r
2212         {\r
2213                 return 0;\r
2214         }\r
2215 \r
2216 #ifdef  OS_WIN32\r
2217         ret = MsGetConsoleWidth();\r
2218 #else   // OS_WIN32\r
2219         {\r
2220                 struct winsize t;\r
2221 \r
2222                 Zero(&t, sizeof(t));\r
2223 \r
2224                 if (ioctl(1, TIOCGWINSZ, &t) == 0)\r
2225                 {\r
2226                         ret = t.ws_col;\r
2227                 }\r
2228         }\r
2229 #endif  // OS_WIN32\r
2230 \r
2231         return ret;\r
2232 }\r
2233 \r
2234 // コンソールから 1 行読み込む\r
2235 wchar_t *ConsoleLocalReadLine(CONSOLE *c, wchar_t *prompt, bool nofile)\r
2236 {\r
2237         wchar_t *ret;\r
2238         LOCAL_CONSOLE_PARAM *p;\r
2239         // 引数チェック\r
2240         if (c == NULL)\r
2241         {\r
2242                 return NULL;\r
2243         }\r
2244         p = (LOCAL_CONSOLE_PARAM *)c->Param;\r
2245         if (prompt == NULL)\r
2246         {\r
2247                 prompt = L">";\r
2248         }\r
2249 \r
2250         ConsoleWriteOutFile(c, prompt, false);\r
2251 \r
2252         if (nofile == false && p->InBuf != NULL)\r
2253         {\r
2254                 // ファイルから次の行を読み込む\r
2255                 ret = ConsoleReadNextFromInFile(c);\r
2256 \r
2257                 if (ret != NULL)\r
2258                 {\r
2259                         // 擬似プロンプトを表示する\r
2260                         UniPrint(L"%s", prompt);\r
2261 \r
2262                         // 画面に描画する\r
2263                         UniPrint(L"%s\n", ret);\r
2264                 }\r
2265         }\r
2266         else\r
2267         {\r
2268                 // 画面から次の行を読み込む\r
2269                 ret = Prompt(prompt);\r
2270         }\r
2271 \r
2272         if (ret != NULL)\r
2273         {\r
2274                 ConsoleWriteOutFile(c, ret, true);\r
2275         }\r
2276         else\r
2277         {\r
2278                 ConsoleWriteOutFile(c, _UU("CON_USER_CANCEL"), true);\r
2279         }\r
2280 \r
2281         return ret;\r
2282 }\r
2283 \r
2284 // コンソールからパスワードを読み込む\r
2285 char *ConsoleLocalReadPassword(CONSOLE *c, wchar_t *prompt)\r
2286 {\r
2287         char tmp[64];\r
2288         // 引数チェック\r
2289         if (c == NULL)\r
2290         {\r
2291                 return NULL;\r
2292         }\r
2293         if (prompt == NULL)\r
2294         {\r
2295                 prompt = L"Password>";\r
2296         }\r
2297 \r
2298         UniPrint(L"%s", prompt);\r
2299         ConsoleWriteOutFile(c, prompt, false);\r
2300 \r
2301         if (PasswordPrompt(tmp, sizeof(tmp)))\r
2302         {\r
2303                 ConsoleWriteOutFile(c, L"********", true);\r
2304                 return CopyStr(tmp);\r
2305         }\r
2306         else\r
2307         {\r
2308                 ConsoleWriteOutFile(c, _UU("CON_USER_CANCEL"), true);\r
2309                 return NULL;\r
2310         }\r
2311 }\r
2312 \r
2313 // コンソールに文字列を表示する\r
2314 bool ConsoleLocalWrite(CONSOLE *c, wchar_t *str)\r
2315 {\r
2316         // 引数チェック\r
2317         if (c == NULL || str == NULL)\r
2318         {\r
2319                 return false;\r
2320         }\r
2321 \r
2322         UniPrint(L"%s%s", str, (UniEndWith(str, L"\n") ? L"" : L"\n"));\r
2323 \r
2324         ConsoleWriteOutFile(c, str, true);\r
2325 \r
2326         return true;\r
2327 }\r
2328 \r
2329 // 入力ファイルから次の 1 行を読み込む\r
2330 wchar_t *ConsoleReadNextFromInFile(CONSOLE *c)\r
2331 {\r
2332         LOCAL_CONSOLE_PARAM *p;\r
2333         char *str;\r
2334         // 引数チェック\r
2335         if (c == NULL)\r
2336         {\r
2337                 return NULL;\r
2338         }\r
2339 \r
2340         p = (LOCAL_CONSOLE_PARAM *)c->Param;\r
2341 \r
2342         if (p->InBuf == NULL)\r
2343         {\r
2344                 return NULL;\r
2345         }\r
2346 \r
2347         while (true)\r
2348         {\r
2349                 str = CfgReadNextLine(p->InBuf);\r
2350 \r
2351                 if (str == NULL)\r
2352                 {\r
2353                         return NULL;\r
2354                 }\r
2355 \r
2356                 Trim(str);\r
2357 \r
2358                 if (IsEmptyStr(str) == false)\r
2359                 {\r
2360                         UINT size;\r
2361                         wchar_t *ret;\r
2362 \r
2363                         size = CalcUtf8ToUni((BYTE *)str, StrLen(str));\r
2364                         ret = ZeroMalloc(size + 32);\r
2365                         Utf8ToUni(ret, size, (BYTE *)str, StrLen(str));\r
2366 \r
2367                         Free(str);\r
2368 \r
2369                         return ret;\r
2370                 }\r
2371 \r
2372                 Free(str);\r
2373         }\r
2374 }\r
2375 \r
2376 // 出力ファイルが指定されている場合は書き出す\r
2377 void ConsoleWriteOutFile(CONSOLE *c, wchar_t *str, bool add_last_crlf)\r
2378 {\r
2379         LOCAL_CONSOLE_PARAM *p;\r
2380         // 引数チェック\r
2381         if (c == NULL || str == NULL)\r
2382         {\r
2383                 return;\r
2384         }\r
2385 \r
2386         p = (LOCAL_CONSOLE_PARAM *)c->Param;\r
2387 \r
2388         if (p != NULL && p->OutFile != NULL)\r
2389         {\r
2390                 wchar_t *tmp = UniNormalizeCrlf(str);\r
2391                 UINT utf8_size;\r
2392                 UCHAR *utf8;\r
2393 \r
2394                 utf8_size = CalcUniToUtf8(tmp);\r
2395                 utf8 = ZeroMalloc(utf8_size + 1);\r
2396                 UniToUtf8(utf8, utf8_size + 1, tmp);\r
2397 \r
2398                 FileWrite(p->OutFile, utf8, utf8_size);\r
2399 \r
2400                 if (UniEndWith(str, L"\n") == false && add_last_crlf)\r
2401                 {\r
2402                         char *crlf = "\r\n";\r
2403                         FileWrite(p->OutFile, "\r\n", StrLen(crlf));\r
2404                 }\r
2405 \r
2406                 Free(utf8);\r
2407                 Free(tmp);\r
2408         }\r
2409 \r
2410 }\r
2411 \r