xref: /reactos/base/shell/cmd/misc.c (revision 075894bc)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  *  MISC.C - misc. functions.
3c2c66affSColin Finck  *
4c2c66affSColin Finck  *
5c2c66affSColin Finck  *  History:
6c2c66affSColin Finck  *
7c2c66affSColin Finck  *    07/12/98 (Rob Lake)
8c2c66affSColin Finck  *        started
9c2c66affSColin Finck  *
10c2c66affSColin Finck  *    07/13/98 (Rob Lake)
11c2c66affSColin Finck  *        moved functions in here
12c2c66affSColin Finck  *
13c2c66affSColin Finck  *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
14c2c66affSColin Finck  *        added config.h include
15c2c66affSColin Finck  *
16c2c66affSColin Finck  *    18-Dec-1998 (Eric Kohl)
17c2c66affSColin Finck  *        Changed split() to accept quoted arguments.
18c2c66affSColin Finck  *        Removed parse_firstarg().
19c2c66affSColin Finck  *
20c2c66affSColin Finck  *    23-Jan-1999 (Eric Kohl)
21c2c66affSColin Finck  *        Fixed an ugly bug in split(). In rare cases (last character
22c2c66affSColin Finck  *        of the string is a space) it ignored the NULL character and
23c2c66affSColin Finck  *        tried to add the following to the argument list.
24c2c66affSColin Finck  *
25c2c66affSColin Finck  *    28-Jan-1999 (Eric Kohl)
26c2c66affSColin Finck  *        FileGetString() seems to be working now.
27c2c66affSColin Finck  *
28c2c66affSColin Finck  *    06-Nov-1999 (Eric Kohl)
29c2c66affSColin Finck  *        Added PagePrompt() and FilePrompt().
30c2c66affSColin Finck  *
31c2c66affSColin Finck  *    30-Apr-2005 (Magnus Olsen <magnus@greatlord.com>)
32c2c66affSColin Finck  *        Remove all hardcoded strings in En.rc
33c2c66affSColin Finck  */
34c2c66affSColin Finck 
35c2c66affSColin Finck #include "precomp.h"
36c2c66affSColin Finck 
37c2c66affSColin Finck /*
38c2c66affSColin Finck  * get a character out-of-band and honor Ctrl-Break characters
39c2c66affSColin Finck  */
40c2c66affSColin Finck TCHAR
cgetchar(VOID)41c2c66affSColin Finck cgetchar (VOID)
42c2c66affSColin Finck {
43c2c66affSColin Finck     HANDLE hInput = GetStdHandle (STD_INPUT_HANDLE);
44c2c66affSColin Finck     INPUT_RECORD irBuffer;
45c2c66affSColin Finck     DWORD  dwRead;
46c2c66affSColin Finck 
47c2c66affSColin Finck     do
48c2c66affSColin Finck     {
49c2c66affSColin Finck         ReadConsoleInput (hInput, &irBuffer, 1, &dwRead);
50c2c66affSColin Finck         if ((irBuffer.EventType == KEY_EVENT) &&
51c2c66affSColin Finck             (irBuffer.Event.KeyEvent.bKeyDown != FALSE))
52c2c66affSColin Finck         {
53c2c66affSColin Finck             if (irBuffer.Event.KeyEvent.dwControlKeyState &
54c2c66affSColin Finck                  (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
55c2c66affSColin Finck             {
56c2c66affSColin Finck                 if (irBuffer.Event.KeyEvent.wVirtualKeyCode == 'C')
57c2c66affSColin Finck                 {
58c2c66affSColin Finck                     bCtrlBreak = TRUE;
59c2c66affSColin Finck                     break;
60c2c66affSColin Finck                 }
61c2c66affSColin Finck             }
62c2c66affSColin Finck             else if ((irBuffer.Event.KeyEvent.wVirtualKeyCode == VK_SHIFT) ||
63c2c66affSColin Finck                      (irBuffer.Event.KeyEvent.wVirtualKeyCode == VK_MENU) ||
64c2c66affSColin Finck                      (irBuffer.Event.KeyEvent.wVirtualKeyCode == VK_CONTROL))
65c2c66affSColin Finck             {
66c2c66affSColin Finck                 // Nothing to do
67c2c66affSColin Finck             }
68c2c66affSColin Finck             else
69c2c66affSColin Finck             {
70c2c66affSColin Finck                 break;
71c2c66affSColin Finck             }
72c2c66affSColin Finck         }
73c2c66affSColin Finck     }
74c2c66affSColin Finck     while (TRUE);
75c2c66affSColin Finck 
76c2c66affSColin Finck #ifndef _UNICODE
77c2c66affSColin Finck     return irBuffer.Event.KeyEvent.uChar.AsciiChar;
78c2c66affSColin Finck #else
79c2c66affSColin Finck     return irBuffer.Event.KeyEvent.uChar.UnicodeChar;
80c2c66affSColin Finck #endif /* _UNICODE */
81c2c66affSColin Finck }
82c2c66affSColin Finck 
83c2c66affSColin Finck /*
84c2c66affSColin Finck  * Takes a path in and returns it with the correct case of the letters
85c2c66affSColin Finck  */
GetPathCase(IN LPCTSTR Path,OUT LPTSTR OutPath)86*075894bcSKatayama Hirofumi MZ VOID GetPathCase(IN LPCTSTR Path, OUT LPTSTR OutPath)
87c2c66affSColin Finck {
88*075894bcSKatayama Hirofumi MZ     SIZE_T i;
89*075894bcSKatayama Hirofumi MZ     SIZE_T cchPath = _tcslen(Path);
90c2c66affSColin Finck     TCHAR TempPath[MAX_PATH];
91*075894bcSKatayama Hirofumi MZ     LPTSTR pchTemp = TempPath;
92*075894bcSKatayama Hirofumi MZ     LPTSTR pchTempEnd = TempPath + _countof(TempPath);
93c2c66affSColin Finck     WIN32_FIND_DATA FindFileData;
94c2c66affSColin Finck     HANDLE hFind;
95c2c66affSColin Finck 
96*075894bcSKatayama Hirofumi MZ     *pchTemp = OutPath[0] = 0;
97*075894bcSKatayama Hirofumi MZ 
98*075894bcSKatayama Hirofumi MZ     for (i = 0; i < cchPath; ++i)
99c2c66affSColin Finck     {
100*075894bcSKatayama Hirofumi MZ         if (pchTemp + 1 >= pchTempEnd)
101c2c66affSColin Finck         {
102*075894bcSKatayama Hirofumi MZ             // On failure, copy the original path for an error message
103*075894bcSKatayama Hirofumi MZ             StringCchCopy(OutPath, MAX_PATH, Path);
104*075894bcSKatayama Hirofumi MZ             return;
105*075894bcSKatayama Hirofumi MZ         }
106*075894bcSKatayama Hirofumi MZ 
107*075894bcSKatayama Hirofumi MZ         if (Path[i] != _T('\\') && Path[i] != _T('/'))
108*075894bcSKatayama Hirofumi MZ         {
109*075894bcSKatayama Hirofumi MZ             *pchTemp++ = Path[i];
110*075894bcSKatayama Hirofumi MZ             *pchTemp = 0;
111*075894bcSKatayama Hirofumi MZ             if (i != cchPath - 1)
112c2c66affSColin Finck                 continue;
113c2c66affSColin Finck         }
114*075894bcSKatayama Hirofumi MZ 
115c2c66affSColin Finck         /* Handle the base part of the path different.
116c2c66affSColin Finck            Because if you put it into findfirstfile, it will
117c2c66affSColin Finck            return your current folder */
118*075894bcSKatayama Hirofumi MZ         if (TempPath[0] && TempPath[1] == _T(':') && !TempPath[2]) /* "C:", "D:" etc. */
119c2c66affSColin Finck         {
120*075894bcSKatayama Hirofumi MZ             StringCchCat(OutPath, MAX_PATH, TempPath);
121*075894bcSKatayama Hirofumi MZ             StringCchCat(OutPath, MAX_PATH, _T("\\"));
122*075894bcSKatayama Hirofumi MZ             StringCchCat(TempPath, _countof(TempPath), _T("\\"));
123c2c66affSColin Finck         }
124c2c66affSColin Finck         else
125c2c66affSColin Finck         {
126c2c66affSColin Finck             hFind = FindFirstFile(TempPath, &FindFileData);
127c2c66affSColin Finck             if (hFind == INVALID_HANDLE_VALUE)
128c2c66affSColin Finck             {
129*075894bcSKatayama Hirofumi MZ                 StringCchCopy(OutPath, MAX_PATH, Path);
130c2c66affSColin Finck                 return;
131c2c66affSColin Finck             }
132c2c66affSColin Finck             FindClose(hFind);
133*075894bcSKatayama Hirofumi MZ             StringCchCat(OutPath, MAX_PATH, _T("\\"));
134*075894bcSKatayama Hirofumi MZ             StringCchCat(OutPath, MAX_PATH, FindFileData.cFileName);
135*075894bcSKatayama Hirofumi MZ             StringCchCat(OutPath, MAX_PATH, _T("\\"));
136*075894bcSKatayama Hirofumi MZ             StringCchCopy(TempPath, _countof(TempPath), OutPath);
137c2c66affSColin Finck         }
138*075894bcSKatayama Hirofumi MZ         pchTemp = TempPath + _tcslen(TempPath);
139c2c66affSColin Finck     }
140c2c66affSColin Finck }
141c2c66affSColin Finck 
142c2c66affSColin Finck /*
143c2c66affSColin Finck  * Check if Ctrl-Break was pressed during the last calls
144c2c66affSColin Finck  */
145c2c66affSColin Finck 
CheckCtrlBreak(INT mode)146c2c66affSColin Finck BOOL CheckCtrlBreak(INT mode)
147c2c66affSColin Finck {
148c2c66affSColin Finck     static BOOL bLeaveAll = FALSE; /* leave all batch files */
149c2c66affSColin Finck     TCHAR options[4]; /* Yes, No, All */
150c2c66affSColin Finck     TCHAR c;
151c2c66affSColin Finck 
152c2c66affSColin Finck     switch (mode)
153c2c66affSColin Finck     {
154c2c66affSColin Finck         case BREAK_OUTOFBATCH:
155a3b36f8dSHermès Bélusca-Maïto             bLeaveAll = FALSE;
156c2c66affSColin Finck             return FALSE;
157c2c66affSColin Finck 
158c2c66affSColin Finck         case BREAK_BATCHFILE:
159a3b36f8dSHermès Bélusca-Maïto         {
160c2c66affSColin Finck             if (bLeaveAll)
161c2c66affSColin Finck                 return TRUE;
162c2c66affSColin Finck 
163c2c66affSColin Finck             if (!bCtrlBreak)
164c2c66affSColin Finck                 return FALSE;
165c2c66affSColin Finck 
166c2c66affSColin Finck             LoadString(CMD_ModuleHandle, STRING_COPY_OPTION, options, ARRAYSIZE(options));
167c2c66affSColin Finck 
168ce543fbbSHermès Bélusca-Maïto             ConOutResPuts(STRING_CANCEL_BATCH_FILE);
169c2c66affSColin Finck             do
170c2c66affSColin Finck             {
171c2c66affSColin Finck                 c = _totupper(cgetchar());
172c2c66affSColin Finck             } while (!(_tcschr(options, c) || c == _T('\3')) || !c);
173c2c66affSColin Finck 
174c2c66affSColin Finck             ConOutChar(_T('\n'));
175c2c66affSColin Finck 
176c2c66affSColin Finck             if (c == options[1])
177a3b36f8dSHermès Bélusca-Maïto             {
178a3b36f8dSHermès Bélusca-Maïto                 bCtrlBreak = FALSE; /* ignore */
179a3b36f8dSHermès Bélusca-Maïto                 return FALSE;
180a3b36f8dSHermès Bélusca-Maïto             }
181c2c66affSColin Finck 
182c2c66affSColin Finck             /* leave all batch files */
183c2c66affSColin Finck             bLeaveAll = ((c == options[2]) || (c == _T('\3')));
184c2c66affSColin Finck             break;
185a3b36f8dSHermès Bélusca-Maïto         }
186c2c66affSColin Finck 
187c2c66affSColin Finck         case BREAK_INPUT:
188c2c66affSColin Finck             if (!bCtrlBreak)
189c2c66affSColin Finck                 return FALSE;
190c2c66affSColin Finck             break;
191c2c66affSColin Finck     }
192c2c66affSColin Finck 
193c2c66affSColin Finck     /* state processed */
194c2c66affSColin Finck     return TRUE;
195c2c66affSColin Finck }
196c2c66affSColin Finck 
197c2c66affSColin Finck /* add new entry for new argument */
add_entry(LPINT ac,LPTSTR ** arg,LPCTSTR entry)198c2c66affSColin Finck BOOL add_entry (LPINT ac, LPTSTR **arg, LPCTSTR entry)
199c2c66affSColin Finck {
200c2c66affSColin Finck     LPTSTR q;
201c2c66affSColin Finck     LPTSTR *oldarg;
202c2c66affSColin Finck 
203c2c66affSColin Finck     q = cmd_alloc ((_tcslen(entry) + 1) * sizeof (TCHAR));
2043f892a8dSHermès Bélusca-Maïto     if (!q)
205c2c66affSColin Finck     {
2063f892a8dSHermès Bélusca-Maïto         WARN("Cannot allocate memory for q!\n");
207c2c66affSColin Finck         return FALSE;
208c2c66affSColin Finck     }
209c2c66affSColin Finck 
210c2c66affSColin Finck     _tcscpy (q, entry);
211c2c66affSColin Finck     oldarg = *arg;
212c2c66affSColin Finck     *arg = cmd_realloc (oldarg, (*ac + 2) * sizeof (LPTSTR));
2133f892a8dSHermès Bélusca-Maïto     if (!*arg)
214c2c66affSColin Finck     {
2153f892a8dSHermès Bélusca-Maïto         WARN("Cannot reallocate memory for arg!\n");
216c2c66affSColin Finck         *arg = oldarg;
2173f892a8dSHermès Bélusca-Maïto         cmd_free (q);
218c2c66affSColin Finck         return FALSE;
219c2c66affSColin Finck     }
220c2c66affSColin Finck 
221c2c66affSColin Finck     /* save new entry */
222c2c66affSColin Finck     (*arg)[*ac] = q;
223c2c66affSColin Finck     (*arg)[++(*ac)] = NULL;
224c2c66affSColin Finck 
225c2c66affSColin Finck     return TRUE;
226c2c66affSColin Finck }
227c2c66affSColin Finck 
expand(LPINT ac,LPTSTR ** arg,LPCTSTR pattern)228c2c66affSColin Finck static BOOL expand (LPINT ac, LPTSTR **arg, LPCTSTR pattern)
229c2c66affSColin Finck {
230c2c66affSColin Finck     HANDLE hFind;
231c2c66affSColin Finck     WIN32_FIND_DATA FindData;
232c2c66affSColin Finck     BOOL ok;
233c2c66affSColin Finck     LPCTSTR pathend;
234c2c66affSColin Finck     LPTSTR dirpart, fullname;
235c2c66affSColin Finck 
236c2c66affSColin Finck     pathend = _tcsrchr (pattern, _T('\\'));
237c2c66affSColin Finck     if (NULL != pathend)
238c2c66affSColin Finck     {
239c2c66affSColin Finck         dirpart = cmd_alloc((pathend - pattern + 2) * sizeof(TCHAR));
2403f892a8dSHermès Bélusca-Maïto         if (!dirpart)
241c2c66affSColin Finck         {
2423f892a8dSHermès Bélusca-Maïto             WARN("Cannot allocate memory for dirpart!\n");
243c2c66affSColin Finck             return FALSE;
244c2c66affSColin Finck         }
245c2c66affSColin Finck         memcpy(dirpart, pattern, pathend - pattern + 1);
246c2c66affSColin Finck         dirpart[pathend - pattern + 1] = _T('\0');
247c2c66affSColin Finck     }
248c2c66affSColin Finck     else
249c2c66affSColin Finck     {
250c2c66affSColin Finck         dirpart = NULL;
251c2c66affSColin Finck     }
252c2c66affSColin Finck     hFind = FindFirstFile (pattern, &FindData);
253c2c66affSColin Finck     if (INVALID_HANDLE_VALUE != hFind)
254c2c66affSColin Finck     {
255c2c66affSColin Finck         do
256c2c66affSColin Finck         {
257c2c66affSColin Finck             if (NULL != dirpart)
258c2c66affSColin Finck             {
259c2c66affSColin Finck                 fullname = cmd_alloc((_tcslen(dirpart) + _tcslen(FindData.cFileName) + 1) * sizeof(TCHAR));
2603f892a8dSHermès Bélusca-Maïto                 if (!fullname)
261c2c66affSColin Finck                 {
2623f892a8dSHermès Bélusca-Maïto                     WARN("Cannot allocate memory for fullname!\n");
263c2c66affSColin Finck                     ok = FALSE;
264c2c66affSColin Finck                 }
265c2c66affSColin Finck                 else
266c2c66affSColin Finck                 {
267c2c66affSColin Finck                     _tcscat (_tcscpy (fullname, dirpart), FindData.cFileName);
268c2c66affSColin Finck                     ok = add_entry(ac, arg, fullname);
269c2c66affSColin Finck                     cmd_free (fullname);
270c2c66affSColin Finck                 }
271c2c66affSColin Finck             }
272c2c66affSColin Finck             else
273c2c66affSColin Finck             {
274c2c66affSColin Finck                 ok = add_entry(ac, arg, FindData.cFileName);
275c2c66affSColin Finck             }
276c2c66affSColin Finck         } while (FindNextFile (hFind, &FindData) && ok);
277c2c66affSColin Finck         FindClose (hFind);
278c2c66affSColin Finck     }
279c2c66affSColin Finck     else
280c2c66affSColin Finck     {
281c2c66affSColin Finck         ok = add_entry(ac, arg, pattern);
282c2c66affSColin Finck     }
283c2c66affSColin Finck 
284c2c66affSColin Finck     if (NULL != dirpart)
285c2c66affSColin Finck     {
286c2c66affSColin Finck         cmd_free (dirpart);
287c2c66affSColin Finck     }
288c2c66affSColin Finck 
289c2c66affSColin Finck     return ok;
290c2c66affSColin Finck }
291c2c66affSColin Finck 
292c2c66affSColin Finck /*
293c2c66affSColin Finck  * split - splits a line up into separate arguments, delimiters
294c2c66affSColin Finck  *         are spaces and slashes ('/').
295c2c66affSColin Finck  */
split(LPTSTR s,LPINT args,BOOL expand_wildcards,BOOL handle_plus)296c2c66affSColin Finck LPTSTR *split (LPTSTR s, LPINT args, BOOL expand_wildcards, BOOL handle_plus)
297c2c66affSColin Finck {
298c2c66affSColin Finck     LPTSTR *arg;
299c2c66affSColin Finck     LPTSTR start;
300c2c66affSColin Finck     LPTSTR q;
301c2c66affSColin Finck     INT  ac;
302c2c66affSColin Finck     INT_PTR  len;
303c2c66affSColin Finck 
304c2c66affSColin Finck     arg = cmd_alloc (sizeof (LPTSTR));
305c2c66affSColin Finck     if (!arg)
3063f892a8dSHermès Bélusca-Maïto     {
3073f892a8dSHermès Bélusca-Maïto         WARN("Cannot allocate memory for arg!\n");
308c2c66affSColin Finck         return NULL;
3093f892a8dSHermès Bélusca-Maïto     }
310c2c66affSColin Finck     *arg = NULL;
311c2c66affSColin Finck 
312c2c66affSColin Finck     ac = 0;
313c2c66affSColin Finck     while (*s)
314c2c66affSColin Finck     {
315c2c66affSColin Finck         BOOL bQuoted = FALSE;
316c2c66affSColin Finck 
317c2c66affSColin Finck         /* skip leading spaces */
318c2c66affSColin Finck         while (*s && (_istspace(*s) || _istcntrl(*s)))
319c2c66affSColin Finck             ++s;
320c2c66affSColin Finck 
321c2c66affSColin Finck         start = s;
322c2c66affSColin Finck 
323c2c66affSColin Finck         /* the first character can be '/' */
324c2c66affSColin Finck         if (*s == _T('/'))
325c2c66affSColin Finck             ++s;
326c2c66affSColin Finck 
327c2c66affSColin Finck         /* skip to next word delimiter or start of next option */
328c2c66affSColin Finck         while (_istprint(*s))
329c2c66affSColin Finck         {
330c2c66affSColin Finck             /* if quote (") then set bQuoted */
331c2c66affSColin Finck             bQuoted ^= (*s == _T('\"'));
332c2c66affSColin Finck 
333c2c66affSColin Finck             /* Check if we have unquoted text */
334c2c66affSColin Finck             if (!bQuoted)
335c2c66affSColin Finck             {
336c2c66affSColin Finck                 /* check for separators */
337c2c66affSColin Finck                 if (_istspace(*s) ||
338c2c66affSColin Finck                     (*s == _T('/')) ||
339c2c66affSColin Finck                     (handle_plus && (*s == _T('+'))))
340c2c66affSColin Finck                 {
341c2c66affSColin Finck                     /* Make length at least one character */
342c2c66affSColin Finck                     if (s == start) s++;
343c2c66affSColin Finck                     break;
344c2c66affSColin Finck                 }
345c2c66affSColin Finck             }
346c2c66affSColin Finck 
347c2c66affSColin Finck             ++s;
348c2c66affSColin Finck         }
349c2c66affSColin Finck 
350c2c66affSColin Finck         /* a word was found */
351c2c66affSColin Finck         if (s != start)
352c2c66affSColin Finck         {
353c2c66affSColin Finck             q = cmd_alloc (((len = s - start) + 1) * sizeof (TCHAR));
354c2c66affSColin Finck             if (!q)
355c2c66affSColin Finck             {
3563f892a8dSHermès Bélusca-Maïto                 WARN("Cannot allocate memory for q!\n");
357c2c66affSColin Finck                 return NULL;
358c2c66affSColin Finck             }
359c2c66affSColin Finck             memcpy (q, start, len * sizeof (TCHAR));
360c2c66affSColin Finck             q[len] = _T('\0');
361c2c66affSColin Finck             StripQuotes(q);
362c2c66affSColin Finck             if (expand_wildcards && (_T('/') != *start) &&
363c2c66affSColin Finck                 (NULL != _tcschr(q, _T('*')) || NULL != _tcschr(q, _T('?'))))
364c2c66affSColin Finck             {
365c2c66affSColin Finck                 if (! expand(&ac, &arg, q))
366c2c66affSColin Finck                 {
367c2c66affSColin Finck                     cmd_free (q);
368c2c66affSColin Finck                     freep (arg);
369c2c66affSColin Finck                     return NULL;
370c2c66affSColin Finck                 }
371c2c66affSColin Finck             }
372c2c66affSColin Finck             else
373c2c66affSColin Finck             {
374c2c66affSColin Finck                 if (! add_entry(&ac, &arg, q))
375c2c66affSColin Finck                 {
376c2c66affSColin Finck                     cmd_free (q);
377c2c66affSColin Finck                     freep (arg);
378c2c66affSColin Finck                     return NULL;
379c2c66affSColin Finck                 }
380c2c66affSColin Finck             }
381c2c66affSColin Finck             cmd_free (q);
382c2c66affSColin Finck         }
383c2c66affSColin Finck     }
384c2c66affSColin Finck 
385c2c66affSColin Finck     *args = ac;
386c2c66affSColin Finck 
387c2c66affSColin Finck     return arg;
388c2c66affSColin Finck }
389c2c66affSColin Finck 
390c2c66affSColin Finck /*
391c2c66affSColin Finck  * splitspace() is a function which uses JUST spaces as delimiters. split() uses "/" AND spaces.
392c2c66affSColin Finck  * The way it works is real similar to split(), search the difference ;)
393c2c66affSColin Finck  * splitspace is needed for commands such as "move" where paths as C:\this/is\allowed/ are allowed
394c2c66affSColin Finck  */
splitspace(LPTSTR s,LPINT args)395c2c66affSColin Finck LPTSTR *splitspace (LPTSTR s, LPINT args)
396c2c66affSColin Finck {
397c2c66affSColin Finck     LPTSTR *arg;
398c2c66affSColin Finck     LPTSTR start;
399c2c66affSColin Finck     LPTSTR q;
400c2c66affSColin Finck     INT  ac;
401c2c66affSColin Finck     INT_PTR  len;
402c2c66affSColin Finck 
403c2c66affSColin Finck     arg = cmd_alloc (sizeof (LPTSTR));
404c2c66affSColin Finck     if (!arg)
4053f892a8dSHermès Bélusca-Maïto     {
4063f892a8dSHermès Bélusca-Maïto         WARN("Cannot allocate memory for arg!\n");
407c2c66affSColin Finck         return NULL;
4083f892a8dSHermès Bélusca-Maïto     }
409c2c66affSColin Finck     *arg = NULL;
410c2c66affSColin Finck 
411c2c66affSColin Finck     ac = 0;
412c2c66affSColin Finck     while (*s)
413c2c66affSColin Finck     {
414c2c66affSColin Finck         BOOL bQuoted = FALSE;
415c2c66affSColin Finck 
416c2c66affSColin Finck         /* skip leading spaces */
417c2c66affSColin Finck         while (*s && (_istspace (*s) || _istcntrl (*s)))
418c2c66affSColin Finck             ++s;
419c2c66affSColin Finck 
420c2c66affSColin Finck         start = s;
421c2c66affSColin Finck 
422c2c66affSColin Finck         /* skip to next word delimiter or start of next option */
423c2c66affSColin Finck         while (_istprint(*s) && (bQuoted || !_istspace(*s)))
424c2c66affSColin Finck         {
425c2c66affSColin Finck             /* if quote (") then set bQuoted */
426c2c66affSColin Finck             bQuoted ^= (*s == _T('\"'));
427c2c66affSColin Finck             ++s;
428c2c66affSColin Finck         }
429c2c66affSColin Finck 
430c2c66affSColin Finck         /* a word was found */
431c2c66affSColin Finck         if (s != start)
432c2c66affSColin Finck         {
433c2c66affSColin Finck             q = cmd_alloc (((len = s - start) + 1) * sizeof (TCHAR));
434c2c66affSColin Finck             if (!q)
435c2c66affSColin Finck             {
4363f892a8dSHermès Bélusca-Maïto                 WARN("Cannot allocate memory for q!\n");
437c2c66affSColin Finck                 return NULL;
438c2c66affSColin Finck             }
439c2c66affSColin Finck             memcpy (q, start, len * sizeof (TCHAR));
440c2c66affSColin Finck             q[len] = _T('\0');
441c2c66affSColin Finck             StripQuotes(q);
442c2c66affSColin Finck             if (! add_entry(&ac, &arg, q))
443c2c66affSColin Finck             {
444c2c66affSColin Finck                 cmd_free (q);
445c2c66affSColin Finck                 freep (arg);
446c2c66affSColin Finck                 return NULL;
447c2c66affSColin Finck             }
448c2c66affSColin Finck             cmd_free (q);
449c2c66affSColin Finck         }
450c2c66affSColin Finck     }
451c2c66affSColin Finck 
452c2c66affSColin Finck     *args = ac;
453c2c66affSColin Finck 
454c2c66affSColin Finck     return arg;
455c2c66affSColin Finck }
456c2c66affSColin Finck 
457c2c66affSColin Finck /*
458c2c66affSColin Finck  * freep -- frees memory used for a call to split
459c2c66affSColin Finck  */
freep(LPTSTR * p)460c2c66affSColin Finck VOID freep (LPTSTR *p)
461c2c66affSColin Finck {
462c2c66affSColin Finck     LPTSTR *q;
463c2c66affSColin Finck 
464c2c66affSColin Finck     if (!p)
465c2c66affSColin Finck         return;
466c2c66affSColin Finck 
467c2c66affSColin Finck     q = p;
468c2c66affSColin Finck     while (*q)
469c2c66affSColin Finck         cmd_free(*q++);
470c2c66affSColin Finck 
471c2c66affSColin Finck     cmd_free(p);
472c2c66affSColin Finck }
473c2c66affSColin Finck 
_stpcpy(LPTSTR dest,LPCTSTR src)474c2c66affSColin Finck LPTSTR _stpcpy (LPTSTR dest, LPCTSTR src)
475c2c66affSColin Finck {
476c2c66affSColin Finck     _tcscpy (dest, src);
477c2c66affSColin Finck     return (dest + _tcslen (src));
478c2c66affSColin Finck }
479c2c66affSColin Finck 
480c2c66affSColin Finck VOID
StripQuotes(TCHAR * in)481c2c66affSColin Finck StripQuotes(TCHAR *in)
482c2c66affSColin Finck {
483c2c66affSColin Finck     TCHAR *out = in;
484c2c66affSColin Finck     for (; *in; in++)
485c2c66affSColin Finck     {
486c2c66affSColin Finck         if (*in != _T('"'))
487c2c66affSColin Finck             *out++ = *in;
488c2c66affSColin Finck     }
489c2c66affSColin Finck     *out = _T('\0');
490c2c66affSColin Finck }
491c2c66affSColin Finck 
492c2c66affSColin Finck 
493c2c66affSColin Finck /*
494050df0f5SHermès Bélusca-Maïto  * Checks if a path is valid (is accessible)
495c2c66affSColin Finck  */
IsValidPathName(IN LPCTSTR pszPath)496050df0f5SHermès Bélusca-Maïto BOOL IsValidPathName(IN LPCTSTR pszPath)
497c2c66affSColin Finck {
498c2c66affSColin Finck     BOOL  bResult;
499050df0f5SHermès Bélusca-Maïto     TCHAR szOldPath[MAX_PATH];
500c2c66affSColin Finck 
501050df0f5SHermès Bélusca-Maïto     GetCurrentDirectory(ARRAYSIZE(szOldPath), szOldPath);
502c2c66affSColin Finck     bResult = SetCurrentDirectory(pszPath);
503c2c66affSColin Finck 
504c2c66affSColin Finck     SetCurrentDirectory(szOldPath);
505c2c66affSColin Finck 
506c2c66affSColin Finck     return bResult;
507c2c66affSColin Finck }
508c2c66affSColin Finck 
509c2c66affSColin Finck /*
510050df0f5SHermès Bélusca-Maïto  * Checks if a file exists (is accessible)
511c2c66affSColin Finck  */
IsExistingFile(IN LPCTSTR pszPath)512050df0f5SHermès Bélusca-Maïto BOOL IsExistingFile(IN LPCTSTR pszPath)
513c2c66affSColin Finck {
514c2c66affSColin Finck     DWORD attr = GetFileAttributes(pszPath);
515050df0f5SHermès Bélusca-Maïto     return ((attr != INVALID_FILE_ATTRIBUTES) && !(attr & FILE_ATTRIBUTE_DIRECTORY));
516c2c66affSColin Finck }
517c2c66affSColin Finck 
IsExistingDirectory(IN LPCTSTR pszPath)518050df0f5SHermès Bélusca-Maïto BOOL IsExistingDirectory(IN LPCTSTR pszPath)
519c2c66affSColin Finck {
520c2c66affSColin Finck     DWORD attr = GetFileAttributes(pszPath);
521050df0f5SHermès Bélusca-Maïto     return ((attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY));
522c2c66affSColin Finck }
523c2c66affSColin Finck 
524c2c66affSColin Finck 
525c2c66affSColin Finck // See r874
PagePrompt(PCON_PAGER Pager,DWORD Done,DWORD Total)526c2c66affSColin Finck BOOL __stdcall PagePrompt(PCON_PAGER Pager, DWORD Done, DWORD Total)
527c2c66affSColin Finck {
528c2c66affSColin Finck     SHORT iScreenWidth, iCursorY;
529c2c66affSColin Finck     INPUT_RECORD ir;
530c2c66affSColin Finck 
531c2c66affSColin Finck     ConOutResPuts(STRING_MISC_HELP1);
532c2c66affSColin Finck 
533c2c66affSColin Finck     RemoveBreakHandler();
534c2c66affSColin Finck     ConInDisable();
535c2c66affSColin Finck 
536c2c66affSColin Finck     do
537c2c66affSColin Finck     {
538c2c66affSColin Finck         ConInKey(&ir);
539c2c66affSColin Finck     }
540c2c66affSColin Finck     while ((ir.Event.KeyEvent.wVirtualKeyCode == VK_SHIFT) ||
541c2c66affSColin Finck            (ir.Event.KeyEvent.wVirtualKeyCode == VK_MENU) ||
542c2c66affSColin Finck            (ir.Event.KeyEvent.wVirtualKeyCode == VK_CONTROL));
543c2c66affSColin Finck 
544c2c66affSColin Finck     AddBreakHandler();
545c2c66affSColin Finck     ConInEnable();
546c2c66affSColin Finck 
547c2c66affSColin Finck     /*
548c2c66affSColin Finck      * Get the screen width, erase the full line where the cursor is,
549c2c66affSColin Finck      * and move the cursor back to the beginning of the line.
550c2c66affSColin Finck      */
551c2c66affSColin Finck     GetScreenSize(&iScreenWidth, NULL);
552c2c66affSColin Finck     iCursorY = GetCursorY();
553c2c66affSColin Finck     SetCursorXY(0, iCursorY);
554c2c66affSColin Finck     while (iScreenWidth-- > 0) // Or call FillConsoleOutputCharacter ?
555c2c66affSColin Finck         ConOutChar(_T(' '));
556c2c66affSColin Finck     SetCursorXY(0, iCursorY);
557c2c66affSColin Finck 
558c2c66affSColin Finck     if ((ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) ||
559c2c66affSColin Finck         ((ir.Event.KeyEvent.wVirtualKeyCode == _T('C')) &&
560c2c66affSColin Finck          (ir.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))))
561c2c66affSColin Finck     {
562c2c66affSColin Finck         /* We break, output a newline */
563c2c66affSColin Finck         ConOutChar(_T('\n'));
564c2c66affSColin Finck 
565c2c66affSColin Finck         bCtrlBreak = TRUE;
566c2c66affSColin Finck         return FALSE;
567c2c66affSColin Finck     }
568c2c66affSColin Finck 
569c2c66affSColin Finck     return TRUE;
570c2c66affSColin Finck }
571c2c66affSColin Finck 
572c2c66affSColin Finck 
FilePromptYN(UINT resID)573c2c66affSColin Finck INT FilePromptYN (UINT resID)
574c2c66affSColin Finck {
575c2c66affSColin Finck     TCHAR szMsg[RC_STRING_MAX_SIZE];
576c2c66affSColin Finck //  TCHAR cKey = 0;
577c2c66affSColin Finck //  LPTSTR szKeys = _T("yna");
578c2c66affSColin Finck 
579c2c66affSColin Finck     TCHAR szIn[10];
580c2c66affSColin Finck     LPTSTR p;
581c2c66affSColin Finck 
582c2c66affSColin Finck     if (resID != 0)
583c2c66affSColin Finck         ConOutResPrintf (resID);
584c2c66affSColin Finck 
585c2c66affSColin Finck     /* preliminary fix */
586c2c66affSColin Finck     ConInString(szIn, 10);
587c2c66affSColin Finck 
588c2c66affSColin Finck     _tcsupr (szIn);
589c2c66affSColin Finck     for (p = szIn; _istspace (*p); p++)
590c2c66affSColin Finck         ;
591c2c66affSColin Finck 
592c2c66affSColin Finck     LoadString(CMD_ModuleHandle, STRING_CHOICE_OPTION, szMsg, ARRAYSIZE(szMsg));
593c2c66affSColin Finck 
594c2c66affSColin Finck     if (_tcsncmp(p, &szMsg[0], 1) == 0)
595c2c66affSColin Finck         return PROMPT_YES;
596c2c66affSColin Finck     else if (_tcsncmp(p, &szMsg[1], 1) == 0)
597c2c66affSColin Finck         return PROMPT_NO;
598c2c66affSColin Finck #if 0
599c2c66affSColin Finck     else if (*p == _T('\03'))
600c2c66affSColin Finck         return PROMPT_BREAK;
601c2c66affSColin Finck #endif
602c2c66affSColin Finck 
603c2c66affSColin Finck     return PROMPT_NO;
604c2c66affSColin Finck 
605c2c66affSColin Finck     /* unfinished solution */
606c2c66affSColin Finck #if 0
607c2c66affSColin Finck     RemoveBreakHandler();
608c2c66affSColin Finck     ConInDisable();
609c2c66affSColin Finck 
610c2c66affSColin Finck     do
611c2c66affSColin Finck     {
612c2c66affSColin Finck         ConInKey (&ir);
613c2c66affSColin Finck         cKey = _totlower (ir.Event.KeyEvent.uChar.AsciiChar);
614c2c66affSColin Finck         if (_tcschr (szKeys, cKey[0]) == NULL)
615c2c66affSColin Finck             cKey = 0;
616c2c66affSColin Finck 
617c2c66affSColin Finck 
618c2c66affSColin Finck     }
619c2c66affSColin Finck     while ((ir.Event.KeyEvent.wVirtualKeyCode == VK_SHIFT) ||
620c2c66affSColin Finck            (ir.Event.KeyEvent.wVirtualKeyCode == VK_MENU) ||
621c2c66affSColin Finck            (ir.Event.KeyEvent.wVirtualKeyCode == VK_CONTROL));
622c2c66affSColin Finck 
623c2c66affSColin Finck     AddBreakHandler();
624c2c66affSColin Finck     ConInEnable();
625c2c66affSColin Finck 
626c2c66affSColin Finck     if ((ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) ||
627c2c66affSColin Finck         ((ir.Event.KeyEvent.wVirtualKeyCode == 'C') &&
628c2c66affSColin Finck          (ir.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))))
629c2c66affSColin Finck         return PROMPT_BREAK;
630c2c66affSColin Finck 
631c2c66affSColin Finck     return PROMPT_YES;
632c2c66affSColin Finck #endif
633c2c66affSColin Finck }
634c2c66affSColin Finck 
635c2c66affSColin Finck 
FilePromptYNA(UINT resID)636c2c66affSColin Finck INT FilePromptYNA (UINT resID)
637c2c66affSColin Finck {
638c2c66affSColin Finck     TCHAR szMsg[RC_STRING_MAX_SIZE];
639c2c66affSColin Finck //  TCHAR cKey = 0;
640c2c66affSColin Finck //  LPTSTR szKeys = _T("yna");
641c2c66affSColin Finck 
642c2c66affSColin Finck     TCHAR szIn[10];
643c2c66affSColin Finck     LPTSTR p;
644c2c66affSColin Finck 
645c2c66affSColin Finck     if (resID != 0)
646c2c66affSColin Finck         ConOutResPrintf (resID);
647c2c66affSColin Finck 
648c2c66affSColin Finck     /* preliminary fix */
649c2c66affSColin Finck     ConInString(szIn, 10);
650c2c66affSColin Finck 
651c2c66affSColin Finck     _tcsupr (szIn);
652c2c66affSColin Finck     for (p = szIn; _istspace (*p); p++)
653c2c66affSColin Finck         ;
654c2c66affSColin Finck 
655c2c66affSColin Finck     LoadString(CMD_ModuleHandle, STRING_COPY_OPTION, szMsg, ARRAYSIZE(szMsg));
656c2c66affSColin Finck 
657c2c66affSColin Finck     if (_tcsncmp(p, &szMsg[0], 1) == 0)
658c2c66affSColin Finck         return PROMPT_YES;
659c2c66affSColin Finck     else if (_tcsncmp(p, &szMsg[1], 1) == 0)
660c2c66affSColin Finck         return PROMPT_NO;
661c2c66affSColin Finck     else if (_tcsncmp(p, &szMsg[2], 1) == 0)
662c2c66affSColin Finck         return PROMPT_ALL;
663c2c66affSColin Finck #if 0
664c2c66affSColin Finck     else if (*p == _T('\03'))
665c2c66affSColin Finck         return PROMPT_BREAK;
666c2c66affSColin Finck #endif
667c2c66affSColin Finck 
668c2c66affSColin Finck     return PROMPT_NO;
669c2c66affSColin Finck 
670c2c66affSColin Finck     /* unfinished solution */
671c2c66affSColin Finck #if 0
672c2c66affSColin Finck     RemoveBreakHandler();
673c2c66affSColin Finck     ConInDisable();
674c2c66affSColin Finck 
675c2c66affSColin Finck     do
676c2c66affSColin Finck     {
677c2c66affSColin Finck         ConInKey (&ir);
678c2c66affSColin Finck         cKey = _totlower (ir.Event.KeyEvent.uChar.AsciiChar);
679c2c66affSColin Finck         if (_tcschr (szKeys, cKey[0]) == NULL)
680c2c66affSColin Finck             cKey = 0;
681c2c66affSColin Finck     }
682c2c66affSColin Finck     while ((ir.Event.KeyEvent.wVirtualKeyCode == VK_SHIFT) ||
683c2c66affSColin Finck            (ir.Event.KeyEvent.wVirtualKeyCode == VK_MENU) ||
684c2c66affSColin Finck            (ir.Event.KeyEvent.wVirtualKeyCode == VK_CONTROL));
685c2c66affSColin Finck 
686c2c66affSColin Finck     AddBreakHandler();
687c2c66affSColin Finck     ConInEnable();
688c2c66affSColin Finck 
689c2c66affSColin Finck     if ((ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) ||
690c2c66affSColin Finck         ((ir.Event.KeyEvent.wVirtualKeyCode == _T('C')) &&
691c2c66affSColin Finck          (ir.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))))
692c2c66affSColin Finck         return PROMPT_BREAK;
693c2c66affSColin Finck 
694c2c66affSColin Finck     return PROMPT_YES;
695c2c66affSColin Finck #endif
696c2c66affSColin Finck }
697c2c66affSColin Finck 
698c2c66affSColin Finck /* EOF */
699