From a5910f45bd81b08c0e5c6071df772222b9f5ec86 Mon Sep 17 00:00:00 2001 From: Jason Edmeades Date: Tue, 1 Aug 2000 02:14:33 +0000 Subject: [PATCH] - Support whitespace around commands better, and support the @ prefix better - Enhance the set support to unset, display value error correctly - Enhance the command line support for parms, and env var expansion - Enhance the echo command to not loose whitespace, and display output with % signs better --- programs/wcmd/batch.c | 54 +++++++++++++++++++++++++++++++++++++++--------- programs/wcmd/builtins.c | 21 +++++++++++++++---- programs/wcmd/wcmd.h | 1 + programs/wcmd/wcmdmain.c | 38 +++++++++++++++++++++++++++------- 4 files changed, 93 insertions(+), 21 deletions(-) diff --git a/programs/wcmd/batch.c b/programs/wcmd/batch.c index cc29853b383..6bb9c227a5e 100644 --- a/programs/wcmd/batch.c +++ b/programs/wcmd/batch.c @@ -95,18 +95,22 @@ BATCH_CONTEXT *prev_context; void WCMD_batch_command (char *line) { DWORD status; -char cmd[1024]; +char cmd1[1024],cmd2[1024]; char *p, *s, *t; int i; - if (echo_mode && (line[0] != '@')) WCMD_output ("%s", line); - status = ExpandEnvironmentStrings (line, cmd, sizeof(cmd)); - if (!status) { - WCMD_print_error (); - return; - } + /* Get working version of command line */ + strcpy(cmd1, line); - p = cmd; + /* Expand environment variables in a batch file %{0-9} first */ + /* Then env vars, and if any left (ie use of undefined vars,*/ + /* replace with spaces */ + /* FIXME: Winnt would replace %1%fred%1 with first parm, then */ + /* contents of fred, then the digit 1. Would need to remove */ + /* ExpandEnvStrings to achieve this */ + + /* Replace use of %0...%9 */ + p = cmd1; while ((p = strchr(p, '%'))) { i = *(p+1) - '0'; if ((i >= 0) && (i <= 9)) { @@ -115,9 +119,39 @@ int i; strcpy (p, t); strcat (p, s); free (s); -} + } else { + p++; + } } - WCMD_process_command (cmd); + + /* Now replace environment variables */ + status = ExpandEnvironmentStrings(cmd1, cmd2, sizeof(cmd2)); + if (!status) { + WCMD_print_error (); + return; + } + + /* In a batch program, unknown variables are replace by nothing */ + /* so remove any remaining %var% */ + p = cmd2; + while ((p = strchr(p, '%'))) { + s = strchr(p+1, '%'); + if (!s) { + *p=0x00; + } else { + t = strdup(s+1); + strcpy(p, t); + free(t); + } + } + + /* Show prompt before batch line IF echo is on */ + if (echo_mode && (line[0] != '@')) { + WCMD_show_prompt(); + WCMD_output ("%s\n", cmd2); + } + + WCMD_process_command (cmd2); } /******************************************************************* diff --git a/programs/wcmd/builtins.c b/programs/wcmd/builtins.c index 9fe9384c8f8..cdc18a62564 100644 --- a/programs/wcmd/builtins.c +++ b/programs/wcmd/builtins.c @@ -181,7 +181,7 @@ int count; echo_mode = 0; return; } - WCMD_output (command); + WCMD_output_asis (command); WCMD_output (newline); } @@ -566,6 +566,7 @@ void WCMD_setshow_env (char *s) { LPVOID env; char *p; int status; +char buffer[1048]; if (strlen(param1) == 0) { env = GetEnvironmentStrings (); @@ -578,14 +579,26 @@ int status; else { p = strchr (s, '='); if (p == NULL) { - WCMD_output ("Command Syntax: SET variable=value\n"); + + /* FIXME: Emulate Win98 for now, ie "SET C" looks ONLY for an + environment variable C, whereas on NT it shows ALL variables + starting with C. + */ + status = GetEnvironmentVariable(s, buffer, sizeof(buffer)); + if (status) { + WCMD_output("%s=%s\n", s, buffer); + } else { + WCMD_output ("Environment variable %s not defined\n", s); + } return; } *p++ = '\0'; - status = SetEnvironmentVariable (s, p); + + if (strlen(p) == 0) p = 0x00; + status = SetEnvironmentVariable (s, p); if (!status) WCMD_print_error(); } - WCMD_output (newline); + /* WCMD_output (newline); @JED*/ } /**************************************************************************** diff --git a/programs/wcmd/wcmd.h b/programs/wcmd/wcmd.h index 2bb27eecd90..1b55e8d745d 100644 --- a/programs/wcmd/wcmd.h +++ b/programs/wcmd/wcmd.h @@ -33,6 +33,7 @@ void WCMD_goto (void); void WCMD_if (char *); void WCMD_move (void); void WCMD_output (char *format, ...); +void WCMD_output_asis (char *message); void WCMD_parse (char *s, char *q, char *p1, char *p2); void WCMD_pause (void); void WCMD_print_error (void); diff --git a/programs/wcmd/wcmdmain.c b/programs/wcmd/wcmdmain.c index 23f4aa94f4c..1e6825d1623 100644 --- a/programs/wcmd/wcmdmain.c +++ b/programs/wcmd/wcmdmain.c @@ -127,6 +127,7 @@ char *p; int status, i; DWORD count; HANDLE old_stdin = 0, old_stdout = 0, h; +char *whichcmd; /* * Throw away constructs we don't support yet @@ -156,7 +157,8 @@ HANDLE old_stdin = 0, old_stdout = 0, h; if (!status) WCMD_print_error (); return; } - WCMD_output (newline); + + /* Dont issue newline WCMD_output (newline); @JED*/ /* * Redirect stdin and/or stdout if required. @@ -185,20 +187,26 @@ HANDLE old_stdin = 0, old_stdout = 0, h; } if ((p = strchr(cmd,'<')) != NULL) *p = '\0'; +/* + * Strip leading whitespaces, and a '@' if supplied + */ + whichcmd = WCMD_strtrim_leading_spaces(cmd); + if (whichcmd[0] == '@') whichcmd++; + /* * Check if the command entered is internal. If it is, pass the rest of the * line down to the command. If not try to run a program. */ count = 0; - while (IsCharAlphaNumeric(cmd[count])) { + while (IsCharAlphaNumeric(whichcmd[count])) { count++; } for (i=0; i<=WCMD_EXIT; i++) { if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, - cmd, count, inbuilt[i], -1) == 2) break; + whichcmd, count, inbuilt[i], -1) == 2) break; } - p = WCMD_strtrim_leading_spaces (&cmd[count]); + p = WCMD_strtrim_leading_spaces (&whichcmd[count]); WCMD_parse (p, quals, param1, param2); switch (i) { @@ -232,8 +240,13 @@ HANDLE old_stdin = 0, old_stdout = 0, h; WCMD_directory (); break; case WCMD_ECHO: - WCMD_echo (p); - break; + /* Use the unstripped version of the following data - step over the space */ + /* but only if a parameter follows */ + if (strlen(&whichcmd[count]) > 0) + WCMD_echo(&whichcmd[count+1]); + else + WCMD_echo(&whichcmd[count]); + break; case WCMD_FOR: WCMD_for (p); break; @@ -299,7 +312,7 @@ HANDLE old_stdin = 0, old_stdout = 0, h; case WCMD_EXIT: ExitProcess (0); default: - WCMD_run_program (cmd); + WCMD_run_program (whichcmd); }; if (old_stdin) { CloseHandle (GetStdHandle (STD_INPUT_HANDLE)); @@ -543,6 +556,17 @@ DWORD count; va_end(ap); } +/******************************************************************* + * WCMD_output_asis - send output to current standard output device. + * without formatting eg. when message contains '%' + */ + +void WCMD_output_asis (char *message) { + DWORD count; + WriteFile (GetStdHandle(STD_OUTPUT_HANDLE), message, lstrlen(message), &count, NULL); +} + + /* Remove leading spaces from a string. Return a pointer to the first * non-space character. Does not modify the input string -- 2.11.4.GIT