From bff25ffe7991bde75904d34ca733f2178b088316 Mon Sep 17 00:00:00 2001 From: Thomas Kho Date: Mon, 24 Jul 2006 19:20:31 -0500 Subject: [PATCH] wcmd: Correct handling of quotes and /s flag when a command argument is present. --- programs/wcmd/wcmd.h | 1 + programs/wcmd/wcmdmain.c | 71 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/programs/wcmd/wcmd.h b/programs/wcmd/wcmd.h index 97f90db4bd6..73b929f48b6 100644 --- a/programs/wcmd/wcmd.h +++ b/programs/wcmd/wcmd.h @@ -74,6 +74,7 @@ char *WCMD_fgets (char *s, int n, HANDLE stream); char *WCMD_parameter (char *s, int n, char **where); char *WCMD_strtrim_leading_spaces (char *string); void WCMD_strtrim_trailing_spaces (char *string); +void WCMD_opt_s_strip_quotes(char *cmd); /* Data structure to hold context when executing batch files */ diff --git a/programs/wcmd/wcmdmain.c b/programs/wcmd/wcmdmain.c index 1af01eb2941..c0e09a51358 100644 --- a/programs/wcmd/wcmdmain.c +++ b/programs/wcmd/wcmdmain.c @@ -37,6 +37,7 @@ const char * const inbuilt[] = {"ATTRIB", "CALL", "CD", "CHDIR", "CLS", "COPY", HINSTANCE hinst; DWORD errorlevel; int echo_mode = 1, verify_mode = 0; +static int opt_c, opt_k, opt_s; const char nyi[] = "Not Yet Implemented\n\n"; const char newline[] = "\n"; const char version_string[] = "WCMD Version " PACKAGE_VERSION "\n\n"; @@ -56,9 +57,9 @@ int main (int argc, char *argv[]) char* cmd=NULL; DWORD count; HANDLE h; - int opt_c, opt_k, opt_q; + int opt_q; - opt_c=opt_k=opt_q=0; + opt_c=opt_k=opt_q=opt_s=0; while (*argv!=NULL) { char c; @@ -74,6 +75,8 @@ int main (int argc, char *argv[]) opt_q=1; } else if (tolower(c)=='k') { opt_k=1; + } else if (tolower(c)=='s') { + opt_s=1; } else if (tolower(c)=='t' || tolower(c)=='x' || tolower(c)=='y') { /* Ignored for compatibility with Windows */ } @@ -92,12 +95,18 @@ int main (int argc, char *argv[]) } if (opt_c || opt_k) { - int len; + int len,qcount; char** arg; char* p; + /* opt_s left unflagged if the command starts with and contains exactly + * one quoted string (exactly two quote characters). The quoted string + * must be an executable name that has whitespace and must not have the + * following characters: &<>()@^| */ + /* Build the command to execute */ len = 0; + qcount = 0; for (arg = argv; *arg; arg++) { int has_space,bcount; @@ -118,6 +127,7 @@ int main (int argc, char *argv[]) * plus escaping of said '"' */ len+=2*bcount+1; + qcount++; } bcount=0; } @@ -125,7 +135,29 @@ int main (int argc, char *argv[]) } len+=(a-*arg)+1 /* for the separating space */; if (has_space) + { len+=2; /* for the quotes */ + qcount+=2; + } + } + + if (qcount!=2) + opt_s=1; + + /* check argv[0] for a space and invalid characters */ + if (!opt_s) { + opt_s=1; + p=*argv; + while (*p!='\0') { + if (*p=='&' || *p=='<' || *p=='>' || *p=='(' || *p==')' + || *p=='@' || *p=='^' || *p=='|') { + opt_s=1; + break; + } + if (*p==' ') + opt_s=0; + p++; + } } cmd = HeapAlloc(GetProcessHeap(), 0, len); @@ -194,6 +226,11 @@ int main (int argc, char *argv[]) if (p > cmd) p--; /* remove last space */ *p = '\0'; + + /* strip first and last quote characters if opt_s; check for invalid + * executable is done later */ + if (opt_s && *cmd=='\"') + WCMD_opt_s_strip_quotes(cmd); } if (opt_c) { @@ -614,6 +651,14 @@ char filetorun[MAX_PATH]; status = CreateProcess (NULL, command, NULL, NULL, TRUE, 0, NULL, NULL, &st, &pe); + if ((opt_c || opt_k) && !opt_s && !status + && GetLastError()==ERROR_FILE_NOT_FOUND && command[0]=='\"') { + /* strip first and last quote characters and try again */ + WCMD_opt_s_strip_quotes(command); + opt_s=1; + WCMD_run_program(command, called); + return; + } if (!status) { WCMD_print_error (); return; @@ -896,6 +941,26 @@ char *ptr; } } +/************************************************************************* + * WCMD_opt_s_strip_quotes + * + * Remove first and last quote characters, preserving all other text + */ + +void WCMD_opt_s_strip_quotes(char *cmd) { + char *src = cmd + 1, *dest = cmd, *lastq = NULL; + while((*dest=*src) != '\0') { + if (*src=='\"') + lastq=dest; + dest++, src++; + } + if (lastq) { + dest=lastq++; + while ((*dest++=*lastq++) != 0) + ; + } +} + /************************************************************************* * WCMD_pipe *