*/
#include <precomp.h>
+#include <malloc.h>
#include "resource.h"
#ifndef NT_SUCCESS
/* search the PATH environment variable for the binary */
if (!SearchForExecutable (first, szFullName))
{
- if (!SearchForExecutable (full, szFullName))
- {
error_bad_command ();
free (first);
free (rest);
free (full);
free (szFullName);
return;
- }
}
#endif /* FEATURE_REDIRECTION */
}
+BOOL
+GrowIfNecessary ( UINT needed, LPTSTR* ret, UINT* retlen )
+{
+ if ( *ret && needed < *retlen )
+ return TRUE;
+ *retlen = needed;
+ if ( *ret )
+ free ( *ret );
+ *ret = (LPTSTR)malloc ( *retlen * sizeof(TCHAR) );
+ if ( !*ret )
+ SetLastError ( ERROR_OUTOFMEMORY );
+ return *ret != NULL;
+}
+
+LPCTSTR
+GetEnvVarOrSpecial ( LPCTSTR varName )
+{
+ static LPTSTR ret = NULL;
+ static UINT retlen = 0;
+ UINT size;
+
+ size = GetEnvironmentVariable ( varName, ret, retlen );
+ if ( size > retlen )
+ {
+ if ( !GrowIfNecessary ( size, &ret, &retlen ) )
+ return NULL;
+ size = GetEnvironmentVariable ( varName, ret, retlen );
+ }
+ if ( size )
+ return ret;
+
+ /* env var doesn't exist, look for a "special" one */
+ /* %CD% */
+ if (_tcsicmp(varName,_T("cd")) ==0)
+ {
+ size = GetCurrentDirectory ( retlen, ret );
+ if ( size > retlen )
+ {
+ if ( !GrowIfNecessary ( size, &ret, &retlen ) )
+ return NULL;
+ size = GetCurrentDirectory ( retlen, ret );
+ }
+ if ( !size )
+ return NULL;
+ return ret;
+ }
+ /* %TIME% */
+ else if (_tcsicmp(varName,_T("time")) ==0)
+ {
+ SYSTEMTIME t;
+ if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
+ return NULL;
+ GetSystemTime(&t);
+ _sntprintf ( ret, retlen, _T("%02d%c%02d%c%02d%c%02d"),
+ t.wHour, cTimeSeparator, t.wMinute, cTimeSeparator,
+ t.wSecond, cDecimalSeparator, t.wMilliseconds );
+ return ret;
+ }
+ /* %DATE% */
+ else if (_tcsicmp(varName,_T("date")) ==0)
+ {
+ LPTSTR tmp;
+
+ if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
+ return NULL;
+ size = GetDateFormat(LOCALE_USER_DEFAULT, 0, NULL, _T("ddd"), ret, retlen );
+ /* TODO FIXME - test whether GetDateFormat() can return a value indicating the buffer wasn't big enough */
+ if ( !size )
+ return NULL;
+ tmp = ret + _tcslen(ret);
+ *tmp++ = _T(' ');
+ size = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, tmp, retlen-(tmp-ret));
+ /* TODO FIXME - test whether GetDateFormat() can return a value indicating the buffer wasn't big enough */
+ if ( !size )
+ return NULL;
+ return ret;
+ }
+
+ /* %RANDOM% */
+ else if (_tcsicmp(varName,_T("random")) ==0)
+ {
+ if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
+ return NULL;
+ /* Get random number */
+ _itot(rand(),ret,10);
+ return ret;
+ }
+
+ /* %CMDCMDLINE% */
+ else if (_tcsicmp(varName,_T("cmdcmdline")) ==0)
+ {
+ return GetCommandLine();
+ }
+
+ /* %CMDEXTVERSION% */
+ else if (_tcsicmp(varName,_T("cmdextversion")) ==0)
+ {
+ if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
+ return NULL;
+ /* Set version number to 2 */
+ _itot(2,ret,10);
+ return ret;
+ }
+
+ /* %ERRORLEVEL% */
+ else if (_tcsicmp(varName,_T("errorlevel")) ==0)
+ {
+ if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
+ return NULL;
+ _itot(nErrorLevel,ret,10);
+ return ret;
+ }
+
+ return _T(""); /* not found - return empty string */
+}
+
+LPCTSTR
+GetParsedEnvVar ( LPCTSTR varName, UINT* varNameLen, BOOL ModeSetA )
+{
+ static LPTSTR ret = NULL;
+ static UINT retlen = 0;
+ LPTSTR p, tmp;
+ UINT size;
+
+ if ( varNameLen )
+ *varNameLen = 0;
+ SetLastError(0);
+ if ( *varName++ != '%' )
+ return NULL;
+ switch ( *varName )
+ {
+ case _T('0'):
+ case _T('1'):
+ case _T('2'):
+ case _T('3'):
+ case _T('4'):
+ case _T('5'):
+ case _T('6'):
+ case _T('7'):
+ case _T('8'):
+ case _T('9'):
+ if ((tmp = FindArg (*varName - _T('0'))))
+ {
+ if ( varNameLen )
+ *varNameLen = 2;
+ if ( !*tmp )
+ return _T("");
+ if ( !GrowIfNecessary ( _tcslen(tmp)+1, &ret, &retlen ) )
+ return NULL;
+ _tcscpy ( ret, tmp );
+ return ret;
+ }
+ if ( !GrowIfNecessary ( 3, &ret, &retlen ) )
+ return NULL;
+ ret[0] = _T('%');
+ ret[1] = *varName;
+ ret[2] = 0;
+ if ( varNameLen )
+ *varNameLen = 2;
+ return ret;
+
+ case _T('%'):
+ if ( !GrowIfNecessary ( 2, &ret, &retlen ) )
+ return NULL;
+ ret[0] = _T('%');
+ ret[1] = 0;
+ if ( varNameLen )
+ *varNameLen = 2;
+ return ret;
+
+ case _T('?'):
+ /* TODO FIXME 10 is only max size for 32-bit */
+ if ( !GrowIfNecessary ( 11, &ret, &retlen ) )
+ return NULL;
+ _sntprintf ( ret, retlen, _T("%u"), nErrorLevel);
+ ret[retlen-1] = 0;
+ if ( varNameLen )
+ *varNameLen = 2;
+ return ret;
+ }
+ if ( ModeSetA )
+ {
+ /* HACK for set/a */
+ if ( !GrowIfNecessary ( 2, &ret, &retlen ) )
+ return NULL;
+ ret[0] = _T('%');
+ ret[1] = 0;
+ if ( varNameLen )
+ *varNameLen = 1;
+ return ret;
+ }
+ p = _tcschr ( varName, _T('%') );
+ if ( !p )
+ {
+ SetLastError ( ERROR_INVALID_PARAMETER );
+ return NULL;
+ }
+ size = p-varName;
+ if ( varNameLen )
+ *varNameLen = size + 2;
+ p = alloca ( (size+1) * sizeof(TCHAR) );
+ memmove ( p, varName, size * sizeof(TCHAR) );
+ p[size] = 0;
+ varName = p;
+ return GetEnvVarOrSpecial ( varName );
+}
+
/*
* do the prompt/input/process loop
{
TCHAR commandline[CMDLINE_LENGTH];
TCHAR readline[CMDLINE_LENGTH];
- LPTSTR tp = NULL;
LPTSTR ip;
LPTSTR cp;
LPCTSTR tmp;
BOOL bEchoThisLine;
- BOOL bSubstitute;
+ BOOL bModeSetA;
+ BOOL bIsBatch;
do
{
ReadCommand (readline, CMDLINE_LENGTH);
ip = readline;
bEchoThisLine = FALSE;
+ bIsBatch = FALSE;
}
+ else
+ {
+ bIsBatch = TRUE;
+ }
/* skip leading blanks */
while ( _istspace(*ip) )
++ip;
cp = commandline;
- bSubstitute = TRUE;
+ bModeSetA = FALSE;
while (*ip)
{
- if (bSubstitute && *ip == _T('%'))
+ if ( *ip == _T('%') )
{
- switch (*++ip)
- {
- case _T('%'):
- *cp++ = *ip++;
- break;
-
- case _T('0'):
- case _T('1'):
- case _T('2'):
- case _T('3'):
- case _T('4'):
- case _T('5'):
- case _T('6'):
- case _T('7'):
- case _T('8'):
- case _T('9'):
- if ((tp = FindArg (*ip - _T('0'))))
- {
- cp = _stpcpy (cp, tp);
- ip++;
- }
- else
- *cp++ = _T('%');
- break;
-
- case _T('?'):
- cp += _stprintf (cp, _T("%u"), nErrorLevel);
- ip++;
- break;
-
- default:
- tp = _tcschr(ip, _T('%'));
- if ((tp != NULL) &&
- (tp <= _tcschr(ip, _T(' ')) - 1))
- {
- INT size = 512;
- TCHAR *evar;
- *tp = _T('\0');
-
- /* FIXME: Correct error handling when it can not alloc memmory */
-
- /* %CD% */
- if (_tcsicmp(ip,_T("cd")) ==0)
- {
- TCHAR szPath[MAX_PATH];
- GetCurrentDirectory (MAX_PATH, szPath);
- cp = _stpcpy (cp, szPath);
- }
- /* %TIME% */
- else if (_tcsicmp(ip,_T("time")) ==0)
- {
- TCHAR szTime[40];
- SYSTEMTIME t;
- GetSystemTime(&t);
-
- _sntprintf(szTime ,40,_T("%02d%c%02d%c%02d%c%02d"), t.wHour, cTimeSeparator,t.wMinute , cTimeSeparator,t.wSecond , cDecimalSeparator, t.wMilliseconds );
- cp = _stpcpy (cp, szTime);
- }
-
- /* %DATE% */
- else if (_tcsicmp(ip,_T("date")) ==0)
- {
- TCHAR szDate[40];
-
- GetDateFormat(LOCALE_USER_DEFAULT, 0, NULL, _T("ddd"), szDate, sizeof (szDate));
- cp = _stpcpy (cp, szDate);
- cp = _stpcpy (cp, _T(" "));
- GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, szDate, sizeof (szDate));
- cp = _stpcpy (cp, szDate);
- }
-
- /* %RANDOM% */
- else if (_tcsicmp(ip,_T("random")) ==0)
- {
- TCHAR szRand[40];
- /* Get random number */
- _itot(rand(),szRand,10);
- cp = _stpcpy (cp, szRand);
- }
-
- /* %CMDCMDLINE% */
- else if (_tcsicmp(ip,_T("cmdcmdline")) ==0)
- {
- TCHAR *pargv;
- /* Get random number */
- pargv = GetCommandLine();
- cp = _stpcpy (cp, pargv);
- }
-
- /* %CMDEXTVERSION% */
- else if (_tcsicmp(ip,_T("cmdextversion")) ==0)
- {
- TCHAR szVER[40];
- /* Set version number to 2 */
- _itot(2,szVER,10);
- cp = _stpcpy (cp, szVER);
- }
-
- /* %ERRORLEVEL% */
- else if (_tcsicmp(ip,_T("errorlevel")) ==0)
- {
- evar = malloc ( size * sizeof(TCHAR));
- if (evar==NULL)
- return 1;
-
- memset(evar,0,512 * sizeof(TCHAR));
- _itot(nErrorLevel,evar,10);
- cp = _stpcpy (cp, evar);
-
- free(evar);
- }
- else
- {
- evar = malloc ( 512 * sizeof(TCHAR));
- if (evar==NULL)
- return 1;
- SetLastError(0);
- size = GetEnvironmentVariable (ip, evar, 512);
- if(GetLastError() == ERROR_ENVVAR_NOT_FOUND)
- {
- /* if no env var is found you must
- continue with what was input*/
- cp = _stpcpy (cp, _T("%"));
- cp = _stpcpy (cp, ip);
- cp = _stpcpy (cp, _T("%"));
- }
- else
- {
- if (size > 512)
- {
- evar = realloc(evar,size * sizeof(TCHAR) );
- if (evar==NULL)
- {
- return 1;
- }
- size = GetEnvironmentVariable (ip, evar, size);
- }
-
- if (size)
- {
- cp = _stpcpy (cp, evar);
- }
- }
-
- free(evar);
- }
-
- ip = tp + 1;
-
- }
- else
- {
- *cp++ = _T('%');
- }
-
- break;
- }
+ UINT envNameLen;
+ LPCTSTR envVal = GetParsedEnvVar ( ip, &envNameLen, bModeSetA );
+ if ( !envVal )
+ return 1;
+ ip += envNameLen;
+ cp = _stpcpy ( cp, envVal );
continue;
}
*ip = _T(' ');
*cp++ = *ip++;
- /* HACK HACK HACK check whether bSubstitute needs to be toggled */
+ /* HACK HACK HACK check whether bModeSetA needs to be toggled */
*cp = 0;
tmp = commandline;
tmp += _tcsspn(tmp,_T(" \t"));
* check to see if we've parsed out a set/a. if so, we
* need to disable substitution until we come across a
* redirection */
- if ( bSubstitute )
+ if ( !bModeSetA )
{
/* look for set /a */
if ( !_tcsnicmp(tmp,_T("set"),3) )
tmp += 3;
tmp += _tcsspn(tmp,_T(" \t"));
if ( !_tcsnicmp(tmp,_T("/a"),2) )
- bSubstitute = FALSE;
+ bModeSetA = TRUE;
}
}
/* if we're not currently substituting, it means we're
{
if ( *tmp == _T('^') )
{
- if ( _tcschr(_T("<>|&"), *++tmp ) )
+ if ( _tcschr(_T("<>|&"), *++tmp ) && *tmp )
++tmp;
}
else
{
- bSubstitute = TRUE;
+ bModeSetA = FALSE;
break;
}
}
if (*commandline)
{
ParseCommandLine (commandline);
- if (bEcho && !bIgnoreEcho)
+ if (bEcho && !bIgnoreEcho && (!bIsBatch || bEchoThisLine))
ConOutChar ('\n');
bIgnoreEcho = FALSE;
}
for you can change the EnvirommentVariable for prompt before cmd start
this patch are not 100% right, if it does not exists a PROMPT value cmd should use
$P$G as defualt not set EnvirommentVariable PROMPT to $P$G if it does not exists */
- if (GetEnvironmentVariable(_T("PROMPT"),lpBuffer, 2 * sizeof(TCHAR)) == 0)
+ if (GetEnvironmentVariable(_T("PROMPT"),lpBuffer, sizeof(lpBuffer) / sizeof(lpBuffer[0])) == 0)
SetEnvironmentVariable (_T("PROMPT"), _T("$P$G"));
++i;
if (i < argc)
{
- _tcscpy (commandline, argv[i]);
+ _tcscpy (commandline, _T("\""));
+ _tcscat (commandline, argv[i]);
+ _tcscat (commandline, _T("\""));
while (++i < argc)
{
_tcscat (commandline, _T(" "));
_tcscat (commandline, argv[i]);
}
-
ParseCommandLine(commandline);
}
}
{
ParseCommandLine (_T("\\cmdstart.bat"));
}
-#ifndef __REACTOS__
- else
- {
- /* try to run cmdstart.bat from install dir */
- LPTSTR p;
-
- _tcscpy (commandline, argv[0]);
- p = _tcsrchr (commandline, _T('\\')) + 1;
- _tcscpy (p, _T("cmdstart.bat"));
-
- if (IsExistingFile (_T("commandline")))
- {
- LoadString(CMD_ModuleHandle, STRING_CMD_ERROR4, szMsg, RC_STRING_MAX_SIZE);
- ConErrPrintf(szMsg, commandline);
- ParseCommandLine (commandline);
- }
- }
-#endif
#ifdef FEATURE_DIR_STACK
/* initialize directory stack */
static VOID Cleanup (int argc, TCHAR *argv[])
{
-#ifndef __REACTOS__
- TCHAR szMsg[RC_STRING_MAX_SIZE];
-#endif
-
/* run cmdexit.bat */
if (IsExistingFile (_T("cmdexit.bat")))
{
ConErrResPuts (STRING_CMD_ERROR5);
ParseCommandLine (_T("\\cmdexit.bat"));
}
-#ifndef __REACTOS__
- else
- {
- /* try to run cmdexit.bat from install dir */
- TCHAR commandline[CMDLINE_LENGTH];
- LPTSTR p;
-
- _tcscpy (commandline, argv[0]);
- p = _tcsrchr (commandline, _T('\\')) + 1;
- _tcscpy (p, _T("cmdexit.bat"));
-
- if (IsExistingFile (_T("commandline")))
- {
- LoadString(CMD_ModuleHandle, STRING_CMD_ERROR4, szMsg, RC_STRING_MAX_SIZE);
- ConErrPrintf(szMsg, commandline);
- ParseCommandLine (commandline);
- }
- }
-#endif
#ifdef FEATURE_ALIASES
DestroyAlias ();
}
}
-#ifdef __REACTOS__
-#ifdef _UNICODE
-PWCHAR * _CommandLineToArgvW(PWCHAR lpCmdLine, int *pNumArgs)
-{
- PWCHAR * argvw = NULL;
- PWCHAR ptr = lpCmdLine;
- PWCHAR str;
- int len;
- int NumArgs;
-
- NumArgs = 0;
-
- while(lpCmdLine && *lpCmdLine)
- {
- while (iswspace(*lpCmdLine)) lpCmdLine++;
- if (*lpCmdLine)
- {
- if ((NumArgs % 10)==0)
- {
- PWCHAR * old_argvw = argvw;
- argvw = malloc((NumArgs + 10) * sizeof(PWCHAR));
- memcpy(argvw, old_argvw, NumArgs * sizeof(PWCHAR));
- free(old_argvw);
- }
- ptr = wcschr(lpCmdLine, L' ');
- if (ptr)
- {
- len = ptr - lpCmdLine;
- }
- else
- {
- len = wcslen(lpCmdLine);
- }
- str = malloc((len + 1) * sizeof(WCHAR));
- memcpy(str, lpCmdLine, len * sizeof(WCHAR));
- str[len] = 0;
- argvw[NumArgs]=str;
- NumArgs++;
- lpCmdLine = ptr;
- }
- }
- *pNumArgs = NumArgs;
- return argvw;
-}
-#endif
-#endif
-
/*
* main function
*/
#ifdef _UNICODE
PWCHAR * argv;
int argc=0;
-#ifdef __REACTOS__
- argv = _CommandLineToArgvW(GetCommandLineW(), &argc);
-#else
argv = CommandLineToArgvW(GetCommandLineW(), &argc);
-#endif
#endif
GetCurrentDirectory(MAX_PATH,startPath);