mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
18acf79551
Promote localization of cmd.exe. JIRA issue: CORE-19680 Add some resource strings. Use them instead of raw strings.
217 lines
5.7 KiB
C
217 lines
5.7 KiB
C
/*
|
|
* CALL.C - call internal batch command.
|
|
*
|
|
*
|
|
* History:
|
|
*
|
|
* 16 Jul 1998 (Hans B Pufal)
|
|
* started.
|
|
*
|
|
* 16 Jul 1998 (John P Price)
|
|
* Separated commands into individual files.
|
|
*
|
|
* 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
|
|
* added config.h include
|
|
*
|
|
* 04-Aug-1998 (Hans B Pufal)
|
|
* added lines to initialize for pointers (HBP004) This fixed the
|
|
* lock-up that happened sometimes when calling a batch file from
|
|
* another batch file.
|
|
*
|
|
* 07-Jan-1999 (Eric Kohl)
|
|
* Added help text ("call /?") and cleaned up.
|
|
*
|
|
* 20-Jan-1999 (Eric Kohl)
|
|
* Unicode and redirection safe!
|
|
*
|
|
* 02-Apr-2005 (Magnus Olsen <magnus@greatlord.com>)
|
|
* Remove all hardcoded strings in En.rc
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
/* Enable this define for "buggy" Windows' CMD CALL-command compatibility */
|
|
#define MSCMD_CALL_QUIRKS
|
|
|
|
|
|
/*
|
|
* Perform CALL command.
|
|
*/
|
|
INT cmd_call(LPTSTR param)
|
|
{
|
|
PARSED_COMMAND* Cmd = NULL;
|
|
BOOL bOldIgnoreParserComments;
|
|
#ifndef MSCMD_CALL_QUIRKS
|
|
BOOL bOldHandleContinuations;
|
|
#else
|
|
SIZE_T nNumCarets;
|
|
#endif
|
|
PTSTR first;
|
|
|
|
TRACE("cmd_call(\'%s\')\n", debugstr_aw(param));
|
|
|
|
if (!_tcsncmp(param, _T("/?"), 2))
|
|
{
|
|
ConOutResPaging(TRUE, STRING_CALL_HELP);
|
|
return 0;
|
|
}
|
|
|
|
/* Fail if no command or label has been provided */
|
|
if (*param == _T('\0'))
|
|
return (nErrorLevel = 1);
|
|
|
|
/* Ignore parser comments (starting with a colon) */
|
|
bOldIgnoreParserComments = bIgnoreParserComments;
|
|
bIgnoreParserComments = FALSE;
|
|
|
|
#ifndef MSCMD_CALL_QUIRKS
|
|
/* Disable parsing of escape carets */
|
|
bOldHandleContinuations = bHandleContinuations;
|
|
bHandleContinuations = FALSE;
|
|
first = param;
|
|
#else
|
|
/*
|
|
* As the original escape carets have been dealt with during the first
|
|
* command parsing step, the remaining ones need to be doubled so that
|
|
* they can again survive the new parsing step done below.
|
|
* But do it the Windows' CMD "buggy" way: **all** carets are doubled,
|
|
* even those inside quotes. However, this causes carets inside quotes
|
|
* to remain doubled after the parsing step...
|
|
*/
|
|
|
|
/* Count all the carets */
|
|
nNumCarets = 0;
|
|
first = param;
|
|
while (first)
|
|
{
|
|
first = _tcschr(first, _T('^'));
|
|
if (first)
|
|
{
|
|
++nNumCarets;
|
|
++first;
|
|
}
|
|
}
|
|
|
|
/* Re-allocate a large enough parameter string if needed */
|
|
if (nNumCarets > 0)
|
|
{
|
|
PTCHAR Src, Dest, End;
|
|
|
|
// TODO: Improvement: Use the scratch TempBuf if the string is not too long.
|
|
first = cmd_alloc((_tcslen(param) + nNumCarets + 1) * sizeof(TCHAR));
|
|
if (!first)
|
|
{
|
|
WARN("Cannot allocate memory for new CALL parameter string!\n");
|
|
error_out_of_memory();
|
|
return (nErrorLevel = 1);
|
|
}
|
|
|
|
/* Copy the parameter string and double the escape carets */
|
|
Src = param;
|
|
Dest = first;
|
|
while (*Src)
|
|
{
|
|
if (*Src != _T('^'))
|
|
{
|
|
/* Copy everything before the next caret (or the end of the string) */
|
|
End = _tcschr(Src, _T('^'));
|
|
if (!End)
|
|
End = Src + _tcslen(Src);
|
|
memcpy(Dest, Src, (End - Src) * sizeof(TCHAR));
|
|
Dest += End - Src;
|
|
Src = End;
|
|
continue;
|
|
}
|
|
|
|
/* Copy the original caret and double it */
|
|
*Dest++ = *Src;
|
|
*Dest++ = *Src++;
|
|
}
|
|
*Dest = _T('\0');
|
|
}
|
|
else
|
|
{
|
|
first = param;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Reparse the CALL parameter string as a command.
|
|
* Note that this will trigger a second round of %-variable substitutions.
|
|
*/
|
|
Cmd = ParseCommand(first);
|
|
|
|
/* Restore the global parsing state */
|
|
#ifndef MSCMD_CALL_QUIRKS
|
|
bHandleContinuations = bOldHandleContinuations;
|
|
#endif
|
|
bIgnoreParserComments = bOldIgnoreParserComments;
|
|
|
|
/*
|
|
* If no command is there, yet no error occurred, this means that
|
|
* a whitespace label was given. Do not consider this as a failure.
|
|
*/
|
|
if (!Cmd && !bParseError)
|
|
{
|
|
#ifdef MSCMD_CALL_QUIRKS
|
|
if (first != param)
|
|
cmd_free(first);
|
|
#endif
|
|
return (nErrorLevel = 0);
|
|
}
|
|
|
|
/* Reset bParseError so as to continue running afterwards */
|
|
bParseError = FALSE;
|
|
|
|
/*
|
|
* Otherwise, if no command is there because a parse error occurred,
|
|
* or if this an unsupported command: not a standard one, including
|
|
* FOR and IF, fail and bail out.
|
|
*/
|
|
if (!Cmd || (Cmd->Type == C_FOR) || (Cmd->Type == C_IF) ||
|
|
((Cmd->Type != C_COMMAND) && (Cmd->Type != C_REM)))
|
|
{
|
|
ConErrResPrintf(STRING_ERROR_UNEXPECTED, first);
|
|
|
|
#ifdef MSCMD_CALL_QUIRKS
|
|
if (first != param)
|
|
cmd_free(first);
|
|
#endif
|
|
if (Cmd) FreeCommand(Cmd);
|
|
return (nErrorLevel = 1);
|
|
}
|
|
|
|
#ifdef MSCMD_CALL_QUIRKS
|
|
if (first != param)
|
|
cmd_free(first);
|
|
#endif
|
|
|
|
first = Cmd->Command.First;
|
|
param = Cmd->Command.Rest;
|
|
|
|
/* "CALL :label args ..." - Call a subroutine of the current batch file, only if extensions are enabled */
|
|
if (bEnableExtensions && (*first == _T(':')))
|
|
{
|
|
INT ret;
|
|
|
|
/* A batch context must be present */
|
|
if (!bc)
|
|
{
|
|
ConErrResPuts(STRING_ERROR_CALL_BAD_LABEL);
|
|
FreeCommand(Cmd);
|
|
return (nErrorLevel = 1);
|
|
}
|
|
|
|
ret = Batch(bc->BatchFilePath, first, param, NULL);
|
|
nErrorLevel = (ret != 0 ? ret : nErrorLevel);
|
|
}
|
|
else
|
|
{
|
|
nErrorLevel = DoCommand(first, param, NULL);
|
|
}
|
|
|
|
FreeCommand(Cmd);
|
|
return nErrorLevel;
|
|
}
|
|
|
|
/* EOF */
|