This is cmd engine rewrite serie XXXVI. (and the second regarding introducing pipes between commands).
Aim of this serie (and next one) is to ensure all builtin commands properly get their input from a pipe.
Basically, this serie - hardens WCMD_fgets() to support properly pipes, - let a couple of builtin commands use WCMD_fgets() instead of WCMD_ReadFile (basically, we only need by line input - WCMD_fgets() - or on the fly key strokes - WCMD_wait_for_input -.
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- programs/cmd/batch.c | 91 ++++++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 45 deletions(-)
diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c index 38a1e8c2826..591b3bcd489 100644 --- a/programs/cmd/batch.c +++ b/programs/cmd/batch.c @@ -265,58 +265,59 @@ WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, BOOL raw,
static WCHAR *WCMD_fgets_helper(WCHAR *buf, DWORD noChars, HANDLE h, UINT code_page) { - DWORD charsRead; - BOOL status; - DWORD i; - - /* We can't use the native f* functions because of the filename syntax differences - between DOS and Unix. Also need to lose the LF (or CRLF) from the line. */ - - if (WCMD_read_console(h, buf, noChars, &charsRead) && charsRead) { - /* Find first EOL */ - for (i = 0; i < charsRead; i++) { - if (buf[i] == '\n' || buf[i] == '\r') - break; - } - } - else { - LARGE_INTEGER filepos; - char *bufA; - const char *p; - - bufA = xalloc(noChars); + DWORD charsRead;
- /* Save current file position */ - filepos.QuadPart = 0; - SetFilePointerEx(h, filepos, &filepos, FILE_CURRENT); - - status = ReadFile(h, bufA, noChars, &charsRead, NULL); - if (!status || charsRead == 0) { - free(bufA); - return NULL; - } + if (!WCMD_read_console(h, buf, noChars, &charsRead)) + { + LARGE_INTEGER filepos; + char *bufA, *p;
- /* Find first EOL */ - for (p = bufA; p < (bufA + charsRead); p = CharNextExA(code_page, p, 0)) { - if (*p == '\n' || *p == '\r') - break; - } + bufA = xalloc(noChars);
- /* Sets file pointer to the start of the next line, if any */ - filepos.QuadPart += p - bufA + 1 + (*p == '\r' ? 1 : 0); - SetFilePointerEx(h, filepos, NULL, FILE_BEGIN); + /* Save current file position */ + filepos.QuadPart = 0; + if (GetFileType(h) == FILE_TYPE_DISK && SetFilePointerEx(h, filepos, &filepos, FILE_CURRENT)) + { + if (!ReadFile(h, bufA, noChars, &charsRead, NULL) || charsRead == 0) + { + free(bufA); + return NULL; + }
- i = MultiByteToWideChar(code_page, 0, bufA, p - bufA, buf, noChars); - free(bufA); - } + /* Find first EOL */ + for (p = bufA; p < bufA + charsRead; p = CharNextExA(code_page, p, 0)) + { + if (p[0] == L'\n') break; + } + if (p < bufA + charsRead) + { + /* Sets file pointer to the start of the next line, if any */ + filepos.QuadPart += p - bufA + 1; + SetFilePointerEx(h, filepos, NULL, FILE_BEGIN); + } + } + else + { + for (p = bufA; p < bufA + noChars; p++) + { + if (!ReadFile(h, p, 1, &charsRead, NULL) || (!charsRead && p == bufA)) + { + free(bufA); + return NULL; + } + /* FIXME: not multibyte charset compliant */ + if (!charsRead || p[0] == '\n') break; + } + }
- /* Truncate at EOL (or end of buffer) */ - if (i == noChars) - i--; + charsRead = MultiByteToWideChar(code_page, 0, bufA, p - bufA, buf, noChars - 1); + free(bufA); + }
- buf[i] = '\0'; + while (charsRead && (buf[charsRead - 1] == L'\n' || buf[charsRead - 1] == L'\r')) charsRead--; + buf[charsRead] = L'\0';
- return buf; + return buf; }
static UINT get_current_code_page(void)
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- programs/cmd/wcmdmain.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 1e9142ad805..d308cdc9731 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -59,12 +59,14 @@ WCHAR quals[MAXSTRING], param1[MAXSTRING], param2[MAXSTRING]; FOR_CONTEXT *forloopcontext; /* The 'for' loop context */ BOOL delayedsubst = FALSE; /* The current delayed substitution setting */
-BOOL echo_mode = TRUE; - WCHAR anykey[100], version_string[100];
static BOOL unicodeOutput = FALSE;
+/* input handling */ +static HANDLE console_input; +BOOL echo_mode = TRUE; + /* Variables pertaining to paging */ static BOOL paged_mode; static const WCHAR *pagedMessage = NULL; @@ -75,7 +77,6 @@ static HANDLE control_c_event;
#define MAX_WRITECONSOLE_SIZE 65535
- static BOOL is_directory_operation(WCHAR *inputBuffer) { WCHAR *param = NULL, *first_param; @@ -558,17 +559,14 @@ WCHAR* WINAPIV WCMD_format_string (const WCHAR *format, ...)
void WCMD_enter_paged_mode(const WCHAR *msg) { - CONSOLE_SCREEN_BUFFER_INFO consoleInfo; + CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
- if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consoleInfo)) { /* Use console window dimensions, not screen buffer dimensions. */ - max_height = consoleInfo.srWindow.Bottom - consoleInfo.srWindow.Top + 1; - } else { - max_height = 25; - } - paged_mode = TRUE; - line_count = 0; - pagedMessage = (msg==NULL)? anykey : msg; + max_height = GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consoleInfo) ? + consoleInfo.srWindow.Bottom - consoleInfo.srWindow.Top + 1 : 65535; + paged_mode = TRUE; + line_count = 0; + pagedMessage = msg ? msg : anykey; }
void WCMD_leave_paged_mode(void) @@ -695,7 +693,7 @@ RETURN_CODE WCMD_output_asis(const WCHAR *message) { line_count = 0; WCMD_output_unbuffered(pagedMessage, -1, handle); - return_code = WCMD_wait_for_input(GetStdHandle(STD_INPUT_HANDLE)); + return_code = WCMD_wait_for_input(console_input); WCMD_output_unbuffered(L"\r\n", 2, handle); } } @@ -4513,6 +4511,8 @@ int __cdecl wmain(int argc, WCHAR *argvW[])
control_c_event = CreateEventW(NULL, TRUE, FALSE, NULL); SetConsoleCtrlHandler(my_event_handler, TRUE); + console_input = CreateFileW(L"CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, 0);
if (parameters.opt_c) {
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- programs/cmd/builtins.c | 42 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 22 deletions(-)
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index 41ed7fb8a71..f8feaa4f6e4 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -197,9 +197,8 @@ DIRECTORY_STACK *WCMD_dir_stack_free(DIRECTORY_STACK *dir) * set to TRUE * */ -static BOOL WCMD_ask_confirm (const WCHAR *message, BOOL showSureText, - BOOL *optionAll) { - +static BOOL WCMD_ask_confirm(const WCHAR *message, BOOL showSureText, BOOL *optionAll) +{ UINT msgid; WCHAR confirm[MAXSTRING]; WCHAR options[MAXSTRING]; @@ -207,11 +206,10 @@ static BOOL WCMD_ask_confirm (const WCHAR *message, BOOL showSureText, WCHAR Nbuffer[MAXSTRING]; WCHAR Abuffer[MAXSTRING]; WCHAR answer[MAX_PATH] = {'\0'}; - DWORD count = 0;
/* Load the translated valid answers */ if (showSureText) - LoadStringW(hinst, WCMD_CONFIRM, confirm, ARRAY_SIZE(confirm)); + LoadStringW(hinst, WCMD_CONFIRM, confirm, ARRAY_SIZE(confirm)); msgid = optionAll ? WCMD_YESNOALL : WCMD_YESNO; LoadStringW(hinst, msgid, options, ARRAY_SIZE(options)); LoadStringW(hinst, WCMD_YES, Ybuffer, ARRAY_SIZE(Ybuffer)); @@ -223,23 +221,23 @@ static BOOL WCMD_ask_confirm (const WCHAR *message, BOOL showSureText, *optionAll = FALSE; while (1) { - WCMD_output_asis (message); - if (showSureText) - WCMD_output_asis (confirm); - WCMD_output_asis (options); - WCMD_output_flush(); - if (!WCMD_ReadFile(GetStdHandle(STD_INPUT_HANDLE), answer, ARRAY_SIZE(answer), &count) || !count) - return FALSE; - answer[0] = towupper(answer[0]); - if (answer[0] == Ybuffer[0]) - return TRUE; - if (answer[0] == Nbuffer[0]) - return FALSE; - if (optionAll && answer[0] == Abuffer[0]) - { - *optionAll = TRUE; - return TRUE; - } + WCMD_output_asis(message); + if (showSureText) + WCMD_output_asis(confirm); + WCMD_output_asis(options); + WCMD_output_flush(); + if (!WCMD_fgets(answer, ARRAY_SIZE(answer), GetStdHandle(STD_INPUT_HANDLE)) || !*answer) + return FALSE; + answer[0] = towupper(answer[0]); + if (answer[0] == Ybuffer[0]) + return TRUE; + if (answer[0] == Nbuffer[0]) + return FALSE; + if (optionAll && answer[0] == Abuffer[0]) + { + *optionAll = TRUE; + return TRUE; + } } }
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- programs/cmd/builtins.c | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-)
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index f8feaa4f6e4..85040660c3e 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -2392,29 +2392,30 @@ RETURN_CODE WCMD_setshow_default(const WCHAR *args)
RETURN_CODE WCMD_setshow_date(void) { - RETURN_CODE return_code = NO_ERROR; - WCHAR curdate[64], buffer[64]; - DWORD count; + RETURN_CODE return_code = NO_ERROR; + WCHAR curdate[64], buffer[64];
- if (!*param1) { - if (GetDateFormatW(LOCALE_USER_DEFAULT, 0, NULL, NULL, curdate, ARRAY_SIZE(curdate))) { - WCMD_output (WCMD_LoadMessage(WCMD_CURRENTDATE), curdate); - if (wcsstr(quals, L"/T") == NULL) { - WCMD_output(WCMD_LoadMessage(WCMD_NEWDATE)); - WCMD_output_flush(); - if (WCMD_ReadFile(GetStdHandle(STD_INPUT_HANDLE), buffer, ARRAY_SIZE(buffer), &count) && - count > 2) { - WCMD_output_stderr (WCMD_LoadMessage(WCMD_NYI)); + if (!*param1) + { + if (GetDateFormatW(LOCALE_USER_DEFAULT, 0, NULL, NULL, curdate, ARRAY_SIZE(curdate))) + { + WCMD_output(WCMD_LoadMessage(WCMD_CURRENTDATE), curdate); + if (wcsstr(quals, L"/T") == NULL) + { + WCMD_output(WCMD_LoadMessage(WCMD_NEWDATE)); + WCMD_output_flush(); + if (WCMD_fgets(buffer, ARRAY_SIZE(buffer), GetStdHandle(STD_INPUT_HANDLE))) + WCMD_output_stderr(WCMD_LoadMessage(WCMD_NYI)); + } } - } + else WCMD_print_error(); } - else WCMD_print_error (); - } - else { - return_code = ERROR_INVALID_FUNCTION; - WCMD_output_stderr (WCMD_LoadMessage(WCMD_NYI)); - } - return errorlevel = return_code; + else + { + return_code = ERROR_INVALID_FUNCTION; + WCMD_output_stderr(WCMD_LoadMessage(WCMD_NYI)); + } + return errorlevel = return_code; }
/****************************************************************************
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- programs/cmd/builtins.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index 85040660c3e..f7ccb492932 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -3015,9 +3015,8 @@ RETURN_CODE WCMD_setshow_env(WCHAR *s) /* See if /P supplied, and if so echo the prompt, and read in a reply */ else if (CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, - s, 2, L"/P", -1) == CSTR_EQUAL) { - DWORD count; - + s, 2, L"/P", -1) == CSTR_EQUAL) + { s += 2; while (*s && (*s==' ' || *s=='\t')) s++; /* set /P "var=value"jim ignores anything after the last quote */ @@ -3047,9 +3046,8 @@ RETURN_CODE WCMD_setshow_env(WCHAR *s) }
/* Read the reply */ - if (WCMD_ReadFile(GetStdHandle(STD_INPUT_HANDLE), string, ARRAY_SIZE(string), &count) && count > 1) { - string[count-1] = '\0'; /* ReadFile output is not null-terminated! */ - if (string[count-2] == '\r') string[count-2] = '\0'; /* Under Windoze we get CRLF! */ + if (WCMD_fgets(string, ARRAY_SIZE(string), GetStdHandle(STD_INPUT_HANDLE)) && *string) + { TRACE("set /p: Setting var '%s' to '%s'\n", wine_dbgstr_w(s), wine_dbgstr_w(string)); if (*string) SetEnvironmentVariableW(s, string);
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- programs/cmd/builtins.c | 71 ++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 36 deletions(-)
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index f7ccb492932..36d53e15e5b 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -3628,50 +3628,49 @@ BOOL WCMD_print_volume_information(const WCHAR *path)
RETURN_CODE WCMD_label(void) { - DWORD count; - WCHAR string[MAX_PATH], curdir[MAX_PATH]; + WCHAR string[MAX_PATH], curdir[MAX_PATH];
- /* FIXME incomplete implementation: - * - no support for /MP qualifier, - * - no support for passing label as parameter - */ - if (*quals) - return errorlevel = ERROR_INVALID_FUNCTION; - if (!*param1) { - if (!GetCurrentDirectoryW(ARRAY_SIZE(curdir), curdir)) { - WCMD_print_error(); - return errorlevel = ERROR_INVALID_FUNCTION; + /* FIXME incomplete implementation: + * - no support for /MP qualifier, + * - no support for passing label as parameter + */ + if (*quals) + return errorlevel = ERROR_INVALID_FUNCTION; + if (!*param1) + { + if (!GetCurrentDirectoryW(ARRAY_SIZE(curdir), curdir)) + { + WCMD_print_error(); + return errorlevel = ERROR_INVALID_FUNCTION; + } + } + else if (param1[1] == ':' && !param1[2]) + { + curdir[0] = param1[0]; + curdir[1] = param1[1]; + } + else + { + WCMD_output_stderr(WCMD_LoadMessage(WCMD_SYNTAXERR)); + return errorlevel = ERROR_INVALID_FUNCTION; + } + curdir[2] = L'\'; + curdir[3] = L'\0'; + if (!WCMD_print_volume_information(curdir)) + { + WCMD_print_error(); + return errorlevel = ERROR_INVALID_FUNCTION; } - } - else if (param1[1] == ':' && !param1[2]) { - curdir[0] = param1[0]; - curdir[1] = param1[1]; - } else { - WCMD_output_stderr(WCMD_LoadMessage(WCMD_SYNTAXERR)); - return errorlevel = ERROR_INVALID_FUNCTION; - } - curdir[2] = L'\'; - curdir[3] = L'\0'; - if (!WCMD_print_volume_information(curdir)) { - WCMD_print_error(); - return errorlevel = ERROR_INVALID_FUNCTION; - }
- if (WCMD_ReadFile(GetStdHandle(STD_INPUT_HANDLE), string, ARRAY_SIZE(string), &count) && - count > 1) { - string[count-1] = '\0'; /* ReadFile output is not null-terminatrred! */ - if (string[count-2] == '\r') string[count-2] = '\0'; /* Under Windoze we get CRLF! */ - } - else return errorlevel = ERROR_INVALID_FUNCTION; - if (*param1) { - if (!SetVolumeLabelW(curdir, string)) + if (!WCMD_fgets(string, ARRAY_SIZE(string), GetStdHandle(STD_INPUT_HANDLE)) || !string[0]) + return errorlevel = ERROR_INVALID_FUNCTION; + if (*param1 && !SetVolumeLabelW(curdir, string)) { errorlevel = GetLastError(); WCMD_print_error(); return errorlevel; } - } - return errorlevel = NO_ERROR; + return errorlevel = NO_ERROR; }
RETURN_CODE WCMD_volume(void)