Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
f252e9df
Commit
f252e9df
authored
Oct 03, 2012
by
Jason Edmeades
Committed by
Alexandre Julliard
Oct 03, 2012
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
cmd: Change command line parsing away from argv/argc.
parent
a2db974d
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
76 additions
and
138 deletions
+76
-138
test_builtins.cmd
programs/cmd/tests/test_builtins.cmd
+6
-1
test_builtins.cmd.exp
programs/cmd/tests/test_builtins.cmd.exp
+13
-9
wcmdmain.c
programs/cmd/wcmdmain.c
+57
-128
No files found.
programs/cmd/tests/test_builtins.cmd
View file @
f252e9df
...
...
@@ -1861,7 +1861,12 @@ cmd.exe /c " echo passed2 "
echo --- Test 14
cmd.exe /c "dir /ad ..\fooba* /b"
echo --- Test 15
cmd.exe /cecho No whitespace
echo --- Test 16
cmd.exe /c
echo --- Test 17
cmd.exe /c@space@
echo --- Test 18
rem Ensure no interactive prompting when cmd.exe /c or /k
echo file2 > file2
cmd.exe /c copy file1 file2 >nul
...
...
programs/cmd/tests/test_builtins.cmd.exp
View file @
f252e9df
...
...
@@ -910,23 +910,23 @@ value1
------------ cmd.exe command lines ------------
--- Test 1
Line1
@todo_wine@
"Line2"
"Line2"
--- Test 2
@todo_wine@
Test quotes "&" work
Test quotes "&" work
--- Test 3
@todo_wine@
"&"
"&"
--- Test 4
@todo_wine@
"<"
"<"
--- Test 5
@todo_wine@
">"
">"
--- Test 6
@todo_wine@
"\"
"\"
--- Test 7
@todo_wine@
"|"
"|"
--- Test 8
@todo_wine@
"`"
"`"
--- Test 9
@todo_wine@
"""
"""
--- Test 10
--- Test 11
--- Test 12
...
...
@@ -936,6 +936,10 @@ passed2@space@
--- Test 14
foobar
--- Test 15
No whitespace
--- Test 16
--- Test 17
--- Test 18
No prompts or I would not get here1
No prompts or I would not get here2
%hello1%
...
...
programs/cmd/wcmdmain.c
View file @
f252e9df
...
...
@@ -2300,7 +2300,9 @@ void WCMD_free_commands(CMD_LIST *cmds) {
int
wmain
(
int
argc
,
WCHAR
*
argvW
[])
{
int
args
;
WCHAR
*
cmd
;
WCHAR
*
cmdLine
=
NULL
;
WCHAR
*
cmd
=
NULL
;
WCHAR
*
argPos
=
NULL
;
WCHAR
string
[
1024
];
WCHAR
envvar
[
4
];
BOOL
opt_q
;
...
...
@@ -2318,19 +2320,26 @@ int wmain (int argc, WCHAR *argvW[])
LocalFree
(
cmd
);
cmd
=
NULL
;
args
=
argc
;
/* Can't use argc/argv as it will have stripped quotes from parameters
* meaning cmd.exe /C echo "quoted string" is impossible
*/
cmdLine
=
GetCommandLineW
();
WINE_TRACE
(
"Full commandline '%s'
\n
"
,
wine_dbgstr_w
(
cmdLine
));
args
=
1
;
/* start at first arg, skipping cmd.exe itself */
opt_c
=
opt_k
=
opt_q
=
opt_s
=
FALSE
;
while
(
args
>
0
)
WCMD_parameter
(
cmdLine
,
args
,
&
argPos
,
NULL
,
TRUE
);
while
(
argPos
&&
argPos
[
0
]
!=
0x00
)
{
WCHAR
c
;
WINE_TRACE
(
"Command line parm: '%s'
\n
"
,
wine_dbgstr_w
(
*
argvW
));
if
(
(
*
argvW
)[
0
]
!=
'/'
||
(
*
argvW
)
[
1
]
==
'\0'
)
{
arg
vW
++
;
args
--
;
WINE_TRACE
(
"Command line parm: '%s'
\n
"
,
wine_dbgstr_w
(
argPos
));
if
(
argPos
[
0
]
!=
'/'
||
argPos
[
1
]
==
'\0'
)
{
arg
s
++
;
WCMD_parameter
(
cmdLine
,
args
,
&
argPos
,
NULL
,
TRUE
)
;
continue
;
}
c
=
(
*
argvW
)
[
1
];
c
=
argPos
[
1
];
if
(
tolowerW
(
c
)
==
'c'
)
{
opt_c
=
TRUE
;
}
else
if
(
tolowerW
(
c
)
==
'q'
)
{
...
...
@@ -2343,19 +2352,20 @@ int wmain (int argc, WCHAR *argvW[])
unicodeOutput
=
FALSE
;
}
else
if
(
tolowerW
(
c
)
==
'u'
)
{
unicodeOutput
=
TRUE
;
}
else
if
(
tolowerW
(
c
)
==
't'
&&
(
*
argvW
)
[
2
]
==
':'
)
{
opt_t
=
strtoulW
(
&
(
*
argvW
)
[
3
],
NULL
,
16
);
}
else
if
(
tolowerW
(
c
)
==
't'
&&
argPos
[
2
]
==
':'
)
{
opt_t
=
strtoulW
(
&
argPos
[
3
],
NULL
,
16
);
}
else
if
(
tolowerW
(
c
)
==
'x'
||
tolowerW
(
c
)
==
'y'
)
{
/* Ignored for compatibility with Windows */
}
if
(
(
*
argvW
)[
2
]
==
0
)
{
arg
vW
++
;
args
--
;
if
(
argPos
[
2
]
==
0
||
argPos
[
2
]
==
' '
||
argPos
[
2
]
==
'\t'
)
{
arg
s
++
;
WCMD_parameter
(
cmdLine
,
args
,
&
argPos
,
NULL
,
TRUE
)
;
}
else
/* handle `cmd /cnotepad.exe` and `cmd /x/c ...` */
{
*
argvW
+=
2
;
/* Do not step to next paramater, instead carry on parsing this one */
argPos
+=
2
;
}
if
(
opt_c
||
opt_k
)
/* break out of parsing immediately after c or k */
...
...
@@ -2371,64 +2381,50 @@ int wmain (int argc, WCHAR *argvW[])
interactive
=
FALSE
;
if
(
opt_c
||
opt_k
)
{
int
len
,
qcount
;
WCHAR
**
arg
;
int
argsLeft
;
WCHAR
*
p
;
int
len
;
WCHAR
*
q1
=
NULL
,
*
q2
=
NULL
,
*
p
;
/* Handle very edge case error scenarion, "cmd.exe /c" ie when there are no
* parameters after the /C or /K by pretending there was a single space */
if
(
argPos
==
NULL
)
argPos
=
(
WCHAR
*
)
spaceW
;
/* Build the command to execute - It is what is left in argPos */
len
=
strlenW
(
argPos
);
/* Take a copy */
cmd
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
WCHAR
));
if
(
!
cmd
)
exit
(
1
);
strcpyW
(
cmd
,
argPos
);
/* 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
;
argsLeft
=
args
;
for
(
arg
=
argvW
;
argsLeft
>
0
;
arg
++
,
argsLeft
--
)
{
BOOL
has_space
=
FALSE
;
int
bcount
;
WCHAR
*
a
;
bcount
=
0
;
a
=*
arg
;
if
(
!*
a
)
has_space
=
TRUE
;
while
(
*
a
!=
'\0'
)
{
if
(
*
a
==
'\\'
)
{
bcount
++
;
}
else
{
if
(
*
a
==
' '
||
*
a
==
'\t'
)
{
has_space
=
TRUE
;
}
else
if
(
*
a
==
'"'
)
{
/* doubling of '\' preceding a '"',
* plus escaping of said '"'
*/
len
+=
2
*
bcount
+
1
;
qcount
++
;
}
bcount
=
0
;
}
a
++
;
}
len
+=
(
a
-*
arg
)
+
1
;
/* for the separating space */
if
(
has_space
)
{
len
+=
2
;
/* for the quotes */
qcount
+=
2
;
}
if
(
!
opt_s
)
{
/* 1. Confirm there is at least one quote */
q1
=
strchrW
(
argPos
,
'"'
);
if
(
!
q1
)
opt_s
=
1
;
}
/* If there is not exactly 2 quote characters, then /S (old behaviour) is enabled */
if
(
qcount
!=
2
)
opt_s
=
TRUE
;
if
(
!
opt_s
)
{
/* 2. Confirm there is a second quote */
q2
=
strchrW
(
q1
+
1
,
'"'
);
if
(
!
q2
)
opt_s
=
1
;
}
/* check argvW[0] for a space and invalid characters. There must not be any invalid
* characters, but there must be one or more whitespace */
if
(
!
opt_s
)
{
/* 3. Ensure there are no more quotes */
if
(
strchrW
(
q2
+
1
,
'"'
))
opt_s
=
1
;
}
/* check first parameter for a space and invalid characters. There must not be any
* invalid characters, but there must be one or more whitespace */
if
(
!
opt_s
)
{
opt_s
=
TRUE
;
p
=
*
argvW
;
while
(
*
p
!=
'\0'
)
{
p
=
q1
;
while
(
p
!=
q2
)
{
if
(
*
p
==
'&'
||
*
p
==
'<'
||
*
p
==
'>'
||
*
p
==
'('
||
*
p
==
')'
||
*
p
==
'@'
||
*
p
==
'^'
||
*
p
==
'|'
)
{
opt_s
=
TRUE
;
...
...
@@ -2440,73 +2436,6 @@ int wmain (int argc, WCHAR *argvW[])
}
}
cmd
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
WCHAR
));
if
(
!
cmd
)
exit
(
1
);
p
=
cmd
;
argsLeft
=
args
;
for
(
arg
=
argvW
;
argsLeft
>
0
;
arg
++
,
argsLeft
--
)
{
BOOL
has_space
=
FALSE
,
has_quote
=
FALSE
;
WCHAR
*
a
;
/* Check for quotes and spaces in this argument */
a
=*
arg
;
if
(
!*
a
)
has_space
=
TRUE
;
while
(
*
a
!=
'\0'
)
{
if
(
*
a
==
' '
||
*
a
==
'\t'
)
{
has_space
=
TRUE
;
if
(
has_quote
)
break
;
}
else
if
(
*
a
==
'"'
)
{
has_quote
=
TRUE
;
if
(
has_space
)
break
;
}
a
++
;
}
/* Now transfer it to the command line */
if
(
has_space
)
*
p
++=
'"'
;
if
(
has_quote
)
{
int
bcount
;
WCHAR
*
a
;
bcount
=
0
;
a
=*
arg
;
while
(
*
a
!=
'\0'
)
{
if
(
*
a
==
'\\'
)
{
*
p
++=*
a
;
bcount
++
;
}
else
{
if
(
*
a
==
'"'
)
{
int
i
;
/* Double all the '\\' preceding this '"', plus one */
for
(
i
=
0
;
i
<=
bcount
;
i
++
)
*
p
++=
'\\'
;
*
p
++=
'"'
;
}
else
{
*
p
++=*
a
;
}
bcount
=
0
;
}
a
++
;
}
}
else
{
strcpyW
(
p
,
*
arg
);
p
+=
strlenW
(
*
arg
);
}
if
(
has_space
)
*
p
++=
'"'
;
*
p
++=
' '
;
}
if
(
p
>
cmd
)
p
--
;
/* remove last space */
*
p
=
'\0'
;
WINE_TRACE
(
"/c command line: '%s'
\n
"
,
wine_dbgstr_w
(
cmd
));
/* Finally, we only stay in new mode IF the first parameter is quoted and
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment