mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 15:02:59 +00:00
Don't expand FOR variables until execution time, so that special characters in them won't cause unwanted syntactic effects.
For example, "for %a in (^>) do echo %a" should just echo the greater than sign. svn path=/trunk/; revision=39611
This commit is contained in:
parent
a5d9170830
commit
9b0334da19
5 changed files with 64 additions and 24 deletions
|
@ -405,20 +405,15 @@ LPTSTR ReadBatchLine ()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* At this point, fv points to parameter string */
|
/* At this point, fv points to parameter string */
|
||||||
|
bc->forvalue = fv;
|
||||||
|
|
||||||
|
/* Double up % signs so they will get through the parser intact */
|
||||||
while (*sp)
|
while (*sp)
|
||||||
{
|
{
|
||||||
if ((*sp == _T('%')) && (*(sp + 1) == bc->forvar))
|
if (*sp == _T('%'))
|
||||||
{
|
*dp++ = _T('%');
|
||||||
/* replace % var */
|
|
||||||
dp = _stpcpy (dp, fv);
|
|
||||||
sp += 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Else just copy */
|
|
||||||
*dp++ = *sp++;
|
*dp++ = *sp++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
*dp++ = _T('\n');
|
*dp++ = _T('\n');
|
||||||
*dp = _T('\0');
|
*dp = _T('\0');
|
||||||
|
|
|
@ -21,6 +21,7 @@ typedef struct tagBATCHCONTEXT
|
||||||
HANDLE hFind; /* Preserve find handle when doing a for */
|
HANDLE hFind; /* Preserve find handle when doing a for */
|
||||||
REDIRECTION *RedirList;
|
REDIRECTION *RedirList;
|
||||||
TCHAR forvar;
|
TCHAR forvar;
|
||||||
|
LPTSTR forvalue;
|
||||||
} BATCH_CONTEXT, *LPBATCH_CONTEXT;
|
} BATCH_CONTEXT, *LPBATCH_CONTEXT;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1261,19 +1261,56 @@ too_long:
|
||||||
#undef APPEND1
|
#undef APPEND1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
SubstituteForVars(TCHAR *Src, TCHAR *Dest)
|
||||||
|
{
|
||||||
|
TCHAR *DestEnd = &Dest[CMDLINE_LENGTH - 1];
|
||||||
|
while (*Src)
|
||||||
|
{
|
||||||
|
if (Src[0] == _T('%') && Src[1] != _T('\0'))
|
||||||
|
{
|
||||||
|
/* This might be a variable. Search the list of contexts for it */
|
||||||
|
BATCH_CONTEXT *Ctx = bc;
|
||||||
|
while (Ctx && Ctx->forvar != Src[1])
|
||||||
|
Ctx = Ctx->prev;
|
||||||
|
if (Ctx)
|
||||||
|
{
|
||||||
|
/* Found it */
|
||||||
|
if (Dest + _tcslen(Ctx->forvalue) > DestEnd)
|
||||||
|
return FALSE;
|
||||||
|
Dest = _stpcpy(Dest, Ctx->forvalue);
|
||||||
|
Src += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Not a variable; just copy the character */
|
||||||
|
if (Dest >= DestEnd)
|
||||||
|
return FALSE;
|
||||||
|
*Dest++ = *Src++;
|
||||||
|
}
|
||||||
|
*Dest = _T('\0');
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
LPTSTR
|
LPTSTR
|
||||||
DoDelayedExpansion(LPTSTR Line)
|
DoDelayedExpansion(LPTSTR Line)
|
||||||
{
|
{
|
||||||
TCHAR Buf[CMDLINE_LENGTH];
|
TCHAR Buf1[CMDLINE_LENGTH];
|
||||||
if (!_tcschr(Line, _T('!')))
|
TCHAR Buf2[CMDLINE_LENGTH];
|
||||||
return cmd_dup(Line);
|
|
||||||
|
/* First, substitute FOR variables */
|
||||||
|
if (!SubstituteForVars(Line, Buf1))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!_tcschr(Buf1, _T('!')))
|
||||||
|
return cmd_dup(Buf1);
|
||||||
|
|
||||||
/* FIXME: Delayed substitutions actually aren't quite the same as
|
/* FIXME: Delayed substitutions actually aren't quite the same as
|
||||||
* immediate substitutions. In particular, it's possible to escape
|
* immediate substitutions. In particular, it's possible to escape
|
||||||
* the exclamation point using ^. */
|
* the exclamation point using ^. */
|
||||||
if (!SubstituteVars(Line, Buf, _T('!')))
|
if (!SubstituteVars(Buf1, Buf2, _T('!')))
|
||||||
return NULL;
|
return NULL;
|
||||||
return cmd_dup(Buf);
|
return cmd_dup(Buf2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -102,6 +102,7 @@ BOOL ExecuteCommand(struct _PARSED_COMMAND *Cmd);
|
||||||
LPCTSTR GetEnvVarOrSpecial ( LPCTSTR varName );
|
LPCTSTR GetEnvVarOrSpecial ( LPCTSTR varName );
|
||||||
VOID AddBreakHandler (VOID);
|
VOID AddBreakHandler (VOID);
|
||||||
VOID RemoveBreakHandler (VOID);
|
VOID RemoveBreakHandler (VOID);
|
||||||
|
BOOL SubstituteForVars(TCHAR *Src, TCHAR *Dest);
|
||||||
LPTSTR DoDelayedExpansion(LPTSTR Line);
|
LPTSTR DoDelayedExpansion(LPTSTR Line);
|
||||||
BOOL DoCommand (LPTSTR line);
|
BOOL DoCommand (LPTSTR line);
|
||||||
BOOL ReadLine(TCHAR *commandline, BOOL bMore);
|
BOOL ReadLine(TCHAR *commandline, BOOL bMore);
|
||||||
|
|
|
@ -610,18 +610,21 @@ ParseCommand(LPTSTR Line)
|
||||||
return Cmd;
|
return Cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reconstruct a parse tree into text form;
|
|
||||||
* used for echoing batch file commands */
|
/* Reconstruct a parse tree into text form; used for echoing
|
||||||
|
* batch file commands and FOR instances. */
|
||||||
VOID
|
VOID
|
||||||
EchoCommand(PARSED_COMMAND *Cmd)
|
EchoCommand(PARSED_COMMAND *Cmd)
|
||||||
{
|
{
|
||||||
|
TCHAR Buf[CMDLINE_LENGTH];
|
||||||
PARSED_COMMAND *Sub;
|
PARSED_COMMAND *Sub;
|
||||||
REDIRECTION *Redir;
|
REDIRECTION *Redir;
|
||||||
|
|
||||||
switch (Cmd->Type)
|
switch (Cmd->Type)
|
||||||
{
|
{
|
||||||
case C_COMMAND:
|
case C_COMMAND:
|
||||||
ConOutPrintf(_T("%s"), Cmd->Command.CommandLine);
|
if (SubstituteForVars(Cmd->Command.CommandLine, Buf))
|
||||||
|
ConOutPrintf(_T("%s"), Buf);
|
||||||
break;
|
break;
|
||||||
case C_QUIET:
|
case C_QUIET:
|
||||||
return;
|
return;
|
||||||
|
@ -649,9 +652,11 @@ EchoCommand(PARSED_COMMAND *Cmd)
|
||||||
ConOutPrintf(_T(" /I"));
|
ConOutPrintf(_T(" /I"));
|
||||||
if (Cmd->If.Flags & IFFLAG_NEGATE)
|
if (Cmd->If.Flags & IFFLAG_NEGATE)
|
||||||
ConOutPrintf(_T(" not"));
|
ConOutPrintf(_T(" not"));
|
||||||
if (Cmd->If.LeftArg)
|
if (Cmd->If.LeftArg && SubstituteForVars(Cmd->If.LeftArg, Buf))
|
||||||
ConOutPrintf(_T(" %s"), Cmd->If.LeftArg);
|
ConOutPrintf(_T(" %s"), Buf);
|
||||||
ConOutPrintf(_T(" %s %s "), IfOperatorString[Cmd->If.Operator], Cmd->If.RightArg);
|
ConOutPrintf(_T(" %s"), IfOperatorString[Cmd->If.Operator]);
|
||||||
|
if (SubstituteForVars(Cmd->If.RightArg, Buf))
|
||||||
|
ConOutPrintf(_T(" %s "), Buf);
|
||||||
Sub = Cmd->Subcommands;
|
Sub = Cmd->Subcommands;
|
||||||
EchoCommand(Sub);
|
EchoCommand(Sub);
|
||||||
if (Sub->Next)
|
if (Sub->Next)
|
||||||
|
@ -664,8 +669,9 @@ EchoCommand(PARSED_COMMAND *Cmd)
|
||||||
|
|
||||||
for (Redir = Cmd->Redirections; Redir; Redir = Redir->Next)
|
for (Redir = Cmd->Redirections; Redir; Redir = Redir->Next)
|
||||||
{
|
{
|
||||||
|
if (SubstituteForVars(Redir->Filename, Buf))
|
||||||
ConOutPrintf(_T(" %c%s%s"), _T('0') + Redir->Number,
|
ConOutPrintf(_T(" %c%s%s"), _T('0') + Redir->Number,
|
||||||
RedirString[Redir->Type], Redir->Filename);
|
RedirString[Redir->Type], Buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue