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
98ae8a69
Commit
98ae8a69
authored
Feb 23, 2007
by
Jason Edmeades
Committed by
Alexandre Julliard
Feb 26, 2007
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
cmd.exe: Unify parsing and expansion.
parent
327d7ef9
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
124 additions
and
148 deletions
+124
-148
batch.c
programs/cmd/batch.c
+1
-134
wcmd.h
programs/cmd/wcmd.h
+5
-0
wcmdmain.c
programs/cmd/wcmdmain.c
+118
-14
No files found.
programs/cmd/batch.c
View file @
98ae8a69
...
...
@@ -20,17 +20,11 @@
#include "wcmd.h"
void
WCMD_batch_command
(
char
*
line
);
void
WCMD_HandleTildaModifiers
(
char
**
start
,
char
*
forVariable
);
extern
int
echo_mode
;
extern
char
quals
[
MAX_PATH
],
param1
[
MAX_PATH
],
param2
[
MAX_PATH
];
extern
BATCH_CONTEXT
*
context
;
extern
DWORD
errorlevel
;
/* msdn specified max for Win XP */
#define MAXSTRING 8192
/****************************************************************************
* WCMD_batch
*
...
...
@@ -117,7 +111,7 @@ BATCH_CONTEXT *prev_context;
WCMD_output_asis
(
"
\n
"
);
}
if
(
string
[
0
]
!=
':'
)
{
/* Skip over labels */
WCMD_
batch
_command
(
string
);
WCMD_
process
_command
(
string
);
}
}
CloseHandle
(
h
);
...
...
@@ -138,133 +132,6 @@ BATCH_CONTEXT *prev_context;
}
}
/****************************************************************************
* WCMD_batch_command
*
* Execute one line from a batch file, expanding parameters.
*/
void
WCMD_batch_command
(
char
*
line
)
{
DWORD
status
;
char
cmd1
[
MAXSTRING
],
cmd2
[
MAXSTRING
];
char
*
p
,
*
s
,
*
t
;
int
i
;
/* Get working version of command line */
strcpy
(
cmd1
,
line
);
/* 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 and errorlevel*/
p
=
cmd1
;
while
((
p
=
strchr
(
p
,
'%'
)))
{
i
=
*
(
p
+
1
)
-
'0'
;
if
(
*
(
p
+
1
)
==
'~'
)
{
WCMD_HandleTildaModifiers
(
&
p
,
NULL
);
p
++
;
}
else
if
((
i
>=
0
)
&&
(
i
<=
9
))
{
s
=
strdup
(
p
+
2
);
t
=
WCMD_parameter
(
context
->
command
,
i
+
context
->
shift_count
,
NULL
);
strcpy
(
p
,
t
);
strcat
(
p
,
s
);
free
(
s
);
}
else
if
(
*
(
p
+
1
)
==
'*'
)
{
char
*
startOfParms
=
NULL
;
s
=
strdup
(
p
+
2
);
t
=
WCMD_parameter
(
context
->
command
,
1
,
&
startOfParms
);
if
(
startOfParms
!=
NULL
)
strcpy
(
p
,
startOfParms
);
else
*
p
=
0x00
;
strcat
(
p
,
s
);
free
(
s
);
/* Handle DATE, TIME, ERRORLEVEL and CD replacements allowing */
/* override if existing env var called that name */
}
else
if
((
CompareString
(
LOCALE_USER_DEFAULT
,
NORM_IGNORECASE
|
SORT_STRINGSORT
,
(
p
+
1
),
11
,
"ERRORLEVEL%"
,
-
1
)
==
2
)
&&
(
GetEnvironmentVariable
(
"ERRORLEVEL"
,
cmd2
,
1
)
==
0
)
&&
(
GetLastError
()
==
ERROR_ENVVAR_NOT_FOUND
))
{
char
output
[
10
];
sprintf
(
output
,
"%d"
,
errorlevel
);
s
=
strdup
(
p
+
12
);
strcpy
(
p
,
output
);
strcat
(
p
,
s
);
}
else
if
((
CompareString
(
LOCALE_USER_DEFAULT
,
NORM_IGNORECASE
|
SORT_STRINGSORT
,
(
p
+
1
),
5
,
"DATE%"
,
-
1
)
==
2
)
&&
(
GetEnvironmentVariable
(
"DATE"
,
cmd2
,
1
)
==
0
)
&&
(
GetLastError
()
==
ERROR_ENVVAR_NOT_FOUND
))
{
GetDateFormat
(
LOCALE_USER_DEFAULT
,
DATE_SHORTDATE
,
NULL
,
NULL
,
cmd2
,
MAXSTRING
);
s
=
strdup
(
p
+
6
);
strcpy
(
p
,
cmd2
);
strcat
(
p
,
s
);
}
else
if
((
CompareString
(
LOCALE_USER_DEFAULT
,
NORM_IGNORECASE
|
SORT_STRINGSORT
,
(
p
+
1
),
5
,
"TIME%"
,
-
1
)
==
2
)
&&
(
GetEnvironmentVariable
(
"TIME"
,
cmd2
,
1
)
==
0
)
&&
(
GetLastError
()
==
ERROR_ENVVAR_NOT_FOUND
))
{
GetTimeFormat
(
LOCALE_USER_DEFAULT
,
TIME_NOSECONDS
,
NULL
,
NULL
,
cmd2
,
MAXSTRING
);
s
=
strdup
(
p
+
6
);
strcpy
(
p
,
cmd2
);
strcat
(
p
,
s
);
}
else
if
((
CompareString
(
LOCALE_USER_DEFAULT
,
NORM_IGNORECASE
|
SORT_STRINGSORT
,
(
p
+
1
),
3
,
"CD%"
,
-
1
)
==
2
)
&&
(
GetEnvironmentVariable
(
"CD"
,
cmd2
,
1
)
==
0
)
&&
(
GetLastError
()
==
ERROR_ENVVAR_NOT_FOUND
))
{
GetCurrentDirectory
(
MAXSTRING
,
cmd2
);
s
=
strdup
(
p
+
4
);
strcpy
(
p
,
cmd2
);
strcat
(
p
,
s
);
}
else
{
p
++
;
}
}
/* 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_asis
(
cmd2
);
WCMD_output_asis
(
"
\n
"
);
}
WCMD_process_command
(
cmd2
);
}
/*******************************************************************
* WCMD_parameter - extract a parameter from a command line.
*
...
...
programs/cmd/wcmd.h
View file @
98ae8a69
...
...
@@ -79,6 +79,8 @@ 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
);
void
WCMD_HandleTildaModifiers
(
char
**
start
,
char
*
forVariable
);
/* Data structure to hold context when executing batch files */
...
...
@@ -151,3 +153,6 @@ extern const char nyi[];
extern
const
char
newline
[];
extern
const
char
version_string
[];
extern
const
char
anykey
[];
/* msdn specified max for Win XP */
#define MAXSTRING 8192
programs/cmd/wcmdmain.c
View file @
98ae8a69
...
...
@@ -301,27 +301,104 @@ int main (int argc, char *argv[])
void
WCMD_process_command
(
char
*
command
)
{
char
*
cmd
,
*
p
,
*
s
;
char
*
cmd
,
*
p
,
*
s
,
*
t
;
char
temp
[
MAXSTRING
];
int
status
,
i
,
len
;
DWORD
count
,
creationDisposition
;
HANDLE
h
;
char
*
whichcmd
;
SECURITY_ATTRIBUTES
sa
;
/*
* Replace errorlevel with current value (This shrinks in
* place and hence no need to reallocate the memory yet)
*/
p
=
command
;
char
*
new_cmd
;
/* Move copy of the command onto the heap so it can be expanded */
new_cmd
=
HeapAlloc
(
GetProcessHeap
(),
0
,
MAXSTRING
);
strcpy
(
new_cmd
,
command
);
/* For commands in a context (batch program): */
/* Expand environment variables in a batch file %{0-9} first */
/* including support for any ~ modifiers */
/* Additionally: */
/* Expand the DATE, TIME, CD and ERRORLEVEL special names */
/* allowing environment variable overrides */
/* 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 */
/* NOTE: To support the %PATH:xxx% syntax, also need to do */
/* manual expansion of environment variables here */
p
=
new_cmd
;
while
((
p
=
strchr
(
p
,
'%'
)))
{
if
(
CompareString
(
LOCALE_USER_DEFAULT
,
i
=
*
(
p
+
1
)
-
'0'
;
/* Replace %~ modifications if in batch program */
if
(
context
&&
*
(
p
+
1
)
==
'~'
)
{
WCMD_HandleTildaModifiers
(
&
p
,
NULL
);
p
++
;
/* Replace use of %0...%9 if in batch program*/
}
else
if
(
context
&&
(
i
>=
0
)
&&
(
i
<=
9
))
{
s
=
strdup
(
p
+
2
);
t
=
WCMD_parameter
(
context
->
command
,
i
+
context
->
shift_count
,
NULL
);
strcpy
(
p
,
t
);
strcat
(
p
,
s
);
free
(
s
);
/* Replace use of %* if in batch program*/
}
else
if
(
context
&&
*
(
p
+
1
)
==
'*'
)
{
char
*
startOfParms
=
NULL
;
s
=
strdup
(
p
+
2
);
t
=
WCMD_parameter
(
context
->
command
,
1
,
&
startOfParms
);
if
(
startOfParms
!=
NULL
)
strcpy
(
p
,
startOfParms
);
else
*
p
=
0x00
;
strcat
(
p
,
s
);
free
(
s
);
/* Handle DATE, TIME, ERRORLEVEL and CD replacements allowing */
/* override if existing env var called that name */
}
else
if
((
CompareString
(
LOCALE_USER_DEFAULT
,
NORM_IGNORECASE
|
SORT_STRINGSORT
,
(
p
+
1
),
11
,
"ERRORLEVEL%"
,
-
1
)
==
2
)
{
char
output
[
10
];
sprintf
(
output
,
"%d"
,
errorlevel
);
(
p
+
1
),
11
,
"ERRORLEVEL%"
,
-
1
)
==
2
)
&&
(
GetEnvironmentVariable
(
"ERRORLEVEL"
,
temp
,
1
)
==
0
)
&&
(
GetLastError
()
==
ERROR_ENVVAR_NOT_FOUND
))
{
sprintf
(
temp
,
"%d"
,
errorlevel
);
s
=
strdup
(
p
+
12
);
strcpy
(
p
,
output
);
strcpy
(
p
,
temp
);
strcat
(
p
,
s
);
}
else
if
((
CompareString
(
LOCALE_USER_DEFAULT
,
NORM_IGNORECASE
|
SORT_STRINGSORT
,
(
p
+
1
),
5
,
"DATE%"
,
-
1
)
==
2
)
&&
(
GetEnvironmentVariable
(
"DATE"
,
temp
,
1
)
==
0
)
&&
(
GetLastError
()
==
ERROR_ENVVAR_NOT_FOUND
))
{
GetDateFormat
(
LOCALE_USER_DEFAULT
,
DATE_SHORTDATE
,
NULL
,
NULL
,
temp
,
MAXSTRING
);
s
=
strdup
(
p
+
6
);
strcpy
(
p
,
temp
);
strcat
(
p
,
s
);
}
else
if
((
CompareString
(
LOCALE_USER_DEFAULT
,
NORM_IGNORECASE
|
SORT_STRINGSORT
,
(
p
+
1
),
5
,
"TIME%"
,
-
1
)
==
2
)
&&
(
GetEnvironmentVariable
(
"TIME"
,
temp
,
1
)
==
0
)
&&
(
GetLastError
()
==
ERROR_ENVVAR_NOT_FOUND
))
{
GetTimeFormat
(
LOCALE_USER_DEFAULT
,
TIME_NOSECONDS
,
NULL
,
NULL
,
temp
,
MAXSTRING
);
s
=
strdup
(
p
+
6
);
strcpy
(
p
,
temp
);
strcat
(
p
,
s
);
}
else
if
((
CompareString
(
LOCALE_USER_DEFAULT
,
NORM_IGNORECASE
|
SORT_STRINGSORT
,
(
p
+
1
),
3
,
"CD%"
,
-
1
)
==
2
)
&&
(
GetEnvironmentVariable
(
"CD"
,
temp
,
1
)
==
0
)
&&
(
GetLastError
()
==
ERROR_ENVVAR_NOT_FOUND
))
{
GetCurrentDirectory
(
MAXSTRING
,
temp
);
s
=
strdup
(
p
+
4
);
strcpy
(
p
,
temp
);
strcat
(
p
,
s
);
}
else
{
p
++
;
}
...
...
@@ -329,14 +406,41 @@ void WCMD_process_command (char *command)
/*
* Expand up environment variables.
* FIXME: Move this to above, without reallocating
*/
len
=
ExpandEnvironmentStrings
(
comman
d
,
NULL
,
0
);
len
=
ExpandEnvironmentStrings
(
new_cm
d
,
NULL
,
0
);
cmd
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
);
status
=
ExpandEnvironmentStrings
(
comman
d
,
cmd
,
len
);
status
=
ExpandEnvironmentStrings
(
new_cm
d
,
cmd
,
len
);
if
(
!
status
)
{
WCMD_print_error
();
HeapFree
(
GetProcessHeap
(),
0
,
cmd
);
HeapFree
(
GetProcessHeap
(),
0
,
new_cmd
);
return
;
}
else
{
HeapFree
(
GetProcessHeap
(),
0
,
new_cmd
);
}
/* In a batch program, unknown variables are replace by nothing */
/* so remove any remaining %var% */
if
(
context
)
{
p
=
cmd
;
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 and in batch program */
if
(
echo_mode
&&
(
cmd
[
0
]
!=
'@'
))
{
WCMD_show_prompt
();
WCMD_output_asis
(
cmd
);
WCMD_output_asis
(
"
\n
"
);
}
}
/*
...
...
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