Thomas Kho : wcmd: Correct handling of quotes and /
s flag when a command argument is present.
Alexandre Julliard
julliard at wine.codeweavers.com
Wed Jul 26 09:00:51 CDT 2006
Module: wine
Branch: refs/heads/master
Commit: bff25ffe7991bde75904d34ca733f2178b088316
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=bff25ffe7991bde75904d34ca733f2178b088316
Author: Thomas Kho <tkho at ucla.edu>
Date: Mon Jul 24 19:20:31 2006 -0500
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 97f90db..73b929f 100644
--- a/programs/wcmd/wcmd.h
+++ b/programs/wcmd/wcmd.h
@@ -74,6 +74,7 @@ char *WCMD_fgets (char *s, int n, HANDLE
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 1af01eb..c0e09a5 100644
--- a/programs/wcmd/wcmdmain.c
+++ b/programs/wcmd/wcmdmain.c
@@ -37,6 +37,7 @@ const char * const inbuilt[] = {"ATTRIB"
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;
@@ -897,6 +942,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
*
* Handle pipes within a command - the DOS way using temporary files.
More information about the wine-cvs
mailing list