[ros-diffs] [jmorlan] 39611: 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.

jmorlan at svn.reactos.org jmorlan at svn.reactos.org
Sun Feb 15 19:18:17 CET 2009


Author: jmorlan
Date: Sun Feb 15 12:18:16 2009
New Revision: 39611

URL: http://svn.reactos.org/svn/reactos?rev=39611&view=rev
Log:
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.

Modified:
    trunk/reactos/base/shell/cmd/batch.c
    trunk/reactos/base/shell/cmd/batch.h
    trunk/reactos/base/shell/cmd/cmd.c
    trunk/reactos/base/shell/cmd/cmd.h
    trunk/reactos/base/shell/cmd/parser.c

Modified: trunk/reactos/base/shell/cmd/batch.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/batch.c?rev=39611&r1=39610&r2=39611&view=diff
==============================================================================
--- trunk/reactos/base/shell/cmd/batch.c [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/batch.c [iso-8859-1] Sun Feb 15 12:18:16 2009
@@ -405,19 +405,14 @@
 			}
 
 			/* At this point, fv points to parameter string */
+			bc->forvalue = fv;
+
+			/* Double up % signs so they will get through the parser intact */
 			while (*sp)
 			{
-				if ((*sp == _T('%')) && (*(sp + 1) == bc->forvar))
-				{
-					/* replace % var */
-					dp = _stpcpy (dp, fv);
-					sp += 2;
-				}
-				else
-				{
-					/* Else just copy */
-					*dp++ = *sp++;
-				}
+				if (*sp == _T('%'))
+					*dp++ = _T('%');
+				*dp++ = *sp++;
 			}
 
 			*dp++ = _T('\n');

Modified: trunk/reactos/base/shell/cmd/batch.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/batch.h?rev=39611&r1=39610&r2=39611&view=diff
==============================================================================
--- trunk/reactos/base/shell/cmd/batch.h [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/batch.h [iso-8859-1] Sun Feb 15 12:18:16 2009
@@ -21,6 +21,7 @@
 	HANDLE hFind;        /* Preserve find handle when doing a for */
 	REDIRECTION *RedirList;
 	TCHAR forvar;
+	LPTSTR forvalue;
 } BATCH_CONTEXT, *LPBATCH_CONTEXT;
 
 

Modified: trunk/reactos/base/shell/cmd/cmd.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/cmd.c?rev=39611&r1=39610&r2=39611&view=diff
==============================================================================
--- trunk/reactos/base/shell/cmd/cmd.c [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/cmd.c [iso-8859-1] Sun Feb 15 12:18:16 2009
@@ -1261,19 +1261,56 @@
 #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
 DoDelayedExpansion(LPTSTR Line)
 {
-	TCHAR Buf[CMDLINE_LENGTH];
-	if (!_tcschr(Line, _T('!')))
-		return cmd_dup(Line);
+	TCHAR Buf1[CMDLINE_LENGTH];
+	TCHAR Buf2[CMDLINE_LENGTH];
+
+	/* 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
 	 * immediate substitutions. In particular, it's possible to escape
 	 * the exclamation point using ^. */
-	if (!SubstituteVars(Line, Buf, _T('!')))
+	if (!SubstituteVars(Buf1, Buf2, _T('!')))
 		return NULL;
-	return cmd_dup(Buf);
+	return cmd_dup(Buf2);
 }
 
 

Modified: trunk/reactos/base/shell/cmd/cmd.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/cmd.h?rev=39611&r1=39610&r2=39611&view=diff
==============================================================================
--- trunk/reactos/base/shell/cmd/cmd.h [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/cmd.h [iso-8859-1] Sun Feb 15 12:18:16 2009
@@ -102,6 +102,7 @@
 LPCTSTR GetEnvVarOrSpecial ( LPCTSTR varName );
 VOID AddBreakHandler (VOID);
 VOID RemoveBreakHandler (VOID);
+BOOL SubstituteForVars(TCHAR *Src, TCHAR *Dest);
 LPTSTR DoDelayedExpansion(LPTSTR Line);
 BOOL DoCommand (LPTSTR line);
 BOOL ReadLine(TCHAR *commandline, BOOL bMore);

Modified: trunk/reactos/base/shell/cmd/parser.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/parser.c?rev=39611&r1=39610&r2=39611&view=diff
==============================================================================
--- trunk/reactos/base/shell/cmd/parser.c [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/parser.c [iso-8859-1] Sun Feb 15 12:18:16 2009
@@ -610,18 +610,21 @@
 	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
 EchoCommand(PARSED_COMMAND *Cmd)
 {
+	TCHAR Buf[CMDLINE_LENGTH];
 	PARSED_COMMAND *Sub;
 	REDIRECTION *Redir;
 
 	switch (Cmd->Type)
 	{
 	case C_COMMAND:
-		ConOutPrintf(_T("%s"), Cmd->Command.CommandLine);
+		if (SubstituteForVars(Cmd->Command.CommandLine, Buf))
+			ConOutPrintf(_T("%s"), Buf);
 		break;
 	case C_QUIET:
 		return;
@@ -649,9 +652,11 @@
 			ConOutPrintf(_T(" /I"));
 		if (Cmd->If.Flags & IFFLAG_NEGATE)
 			ConOutPrintf(_T(" not"));
-		if (Cmd->If.LeftArg)
-			ConOutPrintf(_T(" %s"), Cmd->If.LeftArg);
-		ConOutPrintf(_T(" %s %s "), IfOperatorString[Cmd->If.Operator], Cmd->If.RightArg);
+		if (Cmd->If.LeftArg && SubstituteForVars(Cmd->If.LeftArg, Buf))
+			ConOutPrintf(_T(" %s"), Buf);
+		ConOutPrintf(_T(" %s"), IfOperatorString[Cmd->If.Operator]);
+		if (SubstituteForVars(Cmd->If.RightArg, Buf))
+			ConOutPrintf(_T(" %s "), Buf);
 		Sub = Cmd->Subcommands;
 		EchoCommand(Sub);
 		if (Sub->Next)
@@ -664,8 +669,9 @@
 
 	for (Redir = Cmd->Redirections; Redir; Redir = Redir->Next)
 	{
-		ConOutPrintf(_T(" %c%s%s"), _T('0') + Redir->Number,
-			RedirString[Redir->Type], Redir->Filename);
+		if (SubstituteForVars(Redir->Filename, Buf))
+			ConOutPrintf(_T(" %c%s%s"), _T('0') + Redir->Number,
+				RedirString[Redir->Type], Buf);
 	}
 }
 



More information about the Ros-diffs mailing list