Don't strip trailing spaces from the command line
[reactos.git] / reactos / base / shell / cmd / cmd.c
index c40a7fe..3b310b1 100644 (file)
@@ -517,7 +517,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest)
                                   NULL,
                                   &stui,
                                   &prci))
-                                                  
+
                {
                        if (IsConsoleProcess(prci.hProcess))
                        {
@@ -650,7 +650,7 @@ DoCommand (LPTSTR line)
                */
 
                /* Skip over whitespace to rest of line, exclude 'echo' command */
-               if (_tcsicmp (com, _T("echo"))) 
+               if (_tcsicmp (com, _T("echo")))
                {
                        while (_istspace (*rest))
                        rest++;
@@ -790,7 +790,6 @@ VOID ParseCommandLine (LPTSTR cmd)
                _tcscpy(err, bc->Err);
        }
 
-
        /* Set up the initial conditions ... */
        /* preserve STDIN, STDOUT and STDERR handles */
        hOldConIn  = GetStdHandle (STD_INPUT_HANDLE);
@@ -1116,18 +1115,23 @@ VOID ParseCommandLine (LPTSTR cmd)
 }
 
 BOOL
-GrowIfNecessary ( UINT needed, LPTSTR* ret, UINT* retlen )
+GrowIfNecessary_dbg ( UINT needed, LPTSTR* ret, UINT* retlen, const char *file, int line )
 {
        if ( *ret && needed < *retlen )
                return TRUE;
        *retlen = needed;
        if ( *ret )
                cmd_free ( *ret );
+#ifdef _DEBUG_MEM
+       *ret = (LPTSTR)cmd_alloc_dbg ( *retlen * sizeof(TCHAR), file, line );
+#else
        *ret = (LPTSTR)cmd_alloc ( *retlen * sizeof(TCHAR) );
+#endif
        if ( !*ret )
                SetLastError ( ERROR_OUTOFMEMORY );
        return *ret != NULL;
 }
+#define GrowIfNecessary(x, y, z) GrowIfNecessary_dbg(x, y, z, __FILE__, __LINE__)
 
 LPCTSTR
 GetEnvVarOrSpecial ( LPCTSTR varName )
@@ -1135,20 +1139,57 @@ GetEnvVarOrSpecial ( LPCTSTR varName )
        static LPTSTR ret = NULL;
        static UINT retlen = 0;
        UINT size;
+       TCHAR varNameFixed[MAX_PATH];
+       TCHAR ReturnValue[MAX_PATH];
+       LPTSTR position;
+       LPTSTR Token;
+       SIZE_T i = 0;
+       INT StringPart[1] = {0};
+       
+       position = _tcsstr(varName, _T(":~"));
+       if (position)
+               _tcsncpy(varNameFixed, varName, (int) (position - varName));
+       else
+               _tcscpy(varNameFixed, varName);
 
-       size = GetEnvironmentVariable ( varName, ret, retlen );
+       size = GetEnvironmentVariable ( varNameFixed, ret, retlen );
        if ( size > retlen )
        {
                if ( !GrowIfNecessary ( size, &ret, &retlen ) )
                        return NULL;
-               size = GetEnvironmentVariable ( varName, ret, retlen );
+               size = GetEnvironmentVariable ( varNameFixed, ret, retlen );
        }
        if ( size )
-               return ret;
+       {
+               if (position)
+               {
+                       position += 2;
+                       if (_tcschr(position, _T(',')) != NULL)
+                       {
+                               Token = _tcstok(position, _T(","));
+                               while ((Token != NULL) && (i < 2))
+                               {
+                                       StringPart[i] = _ttoi(Token);
+                                       i++;
+                                       Token = _tcstok (NULL, _T(","));
+                               }
+                               if (i > 0)
+                               {
+                                       if (StringPart[1] < 0)
+                                               StringPart[1] = _tcslen(ret + StringPart[0]) + StringPart[1];
+                                       _tcsncpy(ReturnValue, ret + StringPart[0], StringPart[1]);
+                                       _tcscpy(ret, ReturnValue);
+                               }
+                       }
+                       return ret;
+               }
+               else
+                       return ret;
+       }
 
        /* env var doesn't exist, look for a "special" one */
        /* %CD% */
-       if (_tcsicmp(varName,_T("cd")) ==0)
+       if (_tcsicmp(varNameFixed,_T("cd")) ==0)
        {
                size = GetCurrentDirectory ( retlen, ret );
                if ( size > retlen )
@@ -1162,7 +1203,7 @@ GetEnvVarOrSpecial ( LPCTSTR varName )
                return ret;
        }
        /* %TIME% */
-       else if (_tcsicmp(varName,_T("time")) ==0)
+       else if (_tcsicmp(varNameFixed,_T("time")) ==0)
        {
                SYSTEMTIME t;
                if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
@@ -1174,7 +1215,7 @@ GetEnvVarOrSpecial ( LPCTSTR varName )
                return ret;
        }
        /* %DATE% */
-       else if (_tcsicmp(varName,_T("date")) ==0)
+       else if (_tcsicmp(varNameFixed,_T("date")) ==0)
        {
 
                if ( !GrowIfNecessary ( GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, NULL, 0), &ret, &retlen ) )
@@ -1188,7 +1229,7 @@ GetEnvVarOrSpecial ( LPCTSTR varName )
        }
 
        /* %RANDOM% */
-       else if (_tcsicmp(varName,_T("random")) ==0)
+       else if (_tcsicmp(varNameFixed,_T("random")) ==0)
        {
                if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
                        return NULL;
@@ -1198,13 +1239,13 @@ GetEnvVarOrSpecial ( LPCTSTR varName )
        }
 
        /* %CMDCMDLINE% */
-       else if (_tcsicmp(varName,_T("cmdcmdline")) ==0)
+       else if (_tcsicmp(varNameFixed,_T("cmdcmdline")) ==0)
        {
                return GetCommandLine();
        }
 
        /* %CMDEXTVERSION% */
-       else if (_tcsicmp(varName,_T("cmdextversion")) ==0)
+       else if (_tcsicmp(varNameFixed,_T("cmdextversion")) ==0)
        {
                if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
                        return NULL;
@@ -1214,7 +1255,7 @@ GetEnvVarOrSpecial ( LPCTSTR varName )
        }
 
        /* %ERRORLEVEL% */
-       else if (_tcsicmp(varName,_T("errorlevel")) ==0)
+       else if (_tcsicmp(varNameFixed,_T("errorlevel")) ==0)
        {
                if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
                        return NULL;
@@ -1222,8 +1263,8 @@ GetEnvVarOrSpecial ( LPCTSTR varName )
                return ret;
        }
 
-       GrowIfNecessary(_tcslen(varName) + 2, &ret, &retlen);
-       _stprintf(ret,_T("%%%s%%"),varName);
+       GrowIfNecessary(_tcslen(varNameFixed) + 3, &ret, &retlen);
+       _stprintf(ret,_T("%%%s%%"),varNameFixed);
        return ret; /* not found - return orginal string */
 }
 
@@ -1234,14 +1275,29 @@ GetParsedEnvVar ( LPCTSTR varName, UINT* varNameLen, BOOL ModeSetA )
        static UINT retlen = 0;
        LPTSTR p, tmp;
        UINT size;
+       TCHAR c;
 
        if ( varNameLen )
                *varNameLen = 0;
        SetLastError(0);
-       if ( *varName++ != '%' )
+       c = *varName;
+
+       if ( (*varName != '!') && (*varName++ != '%') )
                return NULL;
+
+       if (c == _T('!'))
+               varName++;
+
        switch ( *varName )
        {
+       case _T('~'):
+               varName++;
+               if (_tcsncicmp(varName, _T("dp0"), 3) == 0)
+               {
+                       if ( varNameLen )
+                               *varNameLen = 5;
+                       return bc->BatchFilePath;
+               }
        case _T('0'):
        case _T('1'):
        case _T('2'):
@@ -1271,7 +1327,7 @@ GetParsedEnvVar ( LPCTSTR varName, UINT* varNameLen, BOOL ModeSetA )
                if ( varNameLen )
                        *varNameLen = 2;
                return ret;
-   
+
     case _T('*'):
         if(bc == NULL)
         {
@@ -1328,7 +1384,7 @@ GetParsedEnvVar ( LPCTSTR varName, UINT* varNameLen, BOOL ModeSetA )
                        *varNameLen = 1;
                return ret;
        }
-       p = _tcschr ( varName, _T('%') );
+       p = _tcschr ( varName, c );
        if ( !p )
        {
                SetLastError ( ERROR_INVALID_PARAMETER );
@@ -1360,7 +1416,7 @@ ProcessInput (BOOL bFlag)
        LPCTSTR tmp;
        BOOL bEchoThisLine;
        BOOL bModeSetA;
-        BOOL bIsBatch;
+    BOOL bIsBatch;
 
        do
        {
@@ -1388,7 +1444,7 @@ ProcessInput (BOOL bFlag)
                bModeSetA = FALSE;
                while (*ip)
                {
-                       if ( *ip == _T('%') )
+                       if ( (*ip == _T('%')) || (*ip == _T('!')) )
                        {
                                UINT envNameLen;
                                LPCTSTR envVal = GetParsedEnvVar ( ip, &envNameLen, bModeSetA );
@@ -1399,7 +1455,7 @@ ProcessInput (BOOL bFlag)
                                }
                        }
 
-                       if (_istcntrl (*ip))
+                       if (*ip != _T('\0') && (_istcntrl (*ip)))
                                *ip = _T(' ');
                        *cp++ = *ip++;
 
@@ -1473,11 +1529,6 @@ ProcessInput (BOOL bFlag)
 
                *cp = _T('\0');
 
-               /* strip trailing spaces */
-               while ((--cp >= commandline) && _istspace (*cp));
-
-               *(cp + 1) = _T('\0');
-
                /* JPP 19980807 */
                /* Echo batch file line */
                if (bEchoThisLine)
@@ -1509,21 +1560,21 @@ BOOL WINAPI BreakHandler (DWORD dwCtrlType)
        DWORD                   dwWritten;
        INPUT_RECORD    rec;
        static BOOL SelfGenerated = FALSE;
-    
+
        if ((dwCtrlType != CTRL_C_EVENT) &&
            (dwCtrlType != CTRL_BREAK_EVENT))
        {
                return FALSE;
        }
        else
-       {               
+       {
                if(SelfGenerated)
                {
                        SelfGenerated = FALSE;
                        return TRUE;
                }
        }
-       
+
        if (bChildProcessRunning == TRUE)
        {
                SelfGenerated = TRUE;
@@ -1531,7 +1582,7 @@ BOOL WINAPI BreakHandler (DWORD dwCtrlType)
                return TRUE;
        }
 
-    
+
     rec.EventType = KEY_EVENT;
     rec.Event.KeyEvent.bKeyDown = TRUE;
     rec.Event.KeyEvent.wRepeatCount = 1;
@@ -1539,14 +1590,14 @@ BOOL WINAPI BreakHandler (DWORD dwCtrlType)
     rec.Event.KeyEvent.wVirtualScanCode = _T('C') - 35;
     rec.Event.KeyEvent.uChar.AsciiChar = _T('C');
     rec.Event.KeyEvent.uChar.UnicodeChar = _T('C');
-    rec.Event.KeyEvent.dwControlKeyState = RIGHT_CTRL_PRESSED; 
+    rec.Event.KeyEvent.dwControlKeyState = RIGHT_CTRL_PRESSED;
 
     WriteConsoleInput(
         hIn,
         &rec,
         1,
                &dwWritten);
-        
+
        bCtrlBreak = TRUE;
        /* FIXME: Handle batch files */
 
@@ -1603,6 +1654,33 @@ ShowCommands (VOID)
 }
 #endif
 
+static VOID
+ExecuteAutoRunFile (VOID)
+{
+    TCHAR autorun[MAX_PATH];
+       DWORD len = MAX_PATH;
+       HKEY hkey;
+
+    if( RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
+                    _T("SOFTWARE\\Microsoft\\Command Processor"),
+                    0, 
+                    KEY_READ, 
+                    &hkey ) == ERROR_SUCCESS)
+    {
+           if(RegQueryValueEx(hkey, 
+                           _T("AutoRun"),
+                           0, 
+                           0, 
+                           (LPBYTE)autorun, 
+                           &len) == ERROR_SUCCESS)
+           {
+                   ParseCommandLine (autorun);
+           }
+    }
+
+       RegCloseKey(hkey);
+}
+
 /*
  * set up global initializations and process parameters
  *
@@ -1611,7 +1689,7 @@ ShowCommands (VOID)
  *
  */
 static VOID
-Initialize (int argc, TCHAR* argv[])
+Initialize (int argc, const TCHAR* argv[])
 {
        TCHAR commandline[CMDLINE_LENGTH];
        TCHAR ModuleName[_MAX_PATH + 1];
@@ -1673,7 +1751,7 @@ Initialize (int argc, TCHAR* argv[])
        if (argc >= 2 && !_tcsncmp (argv[1], _T("/?"), 2))
        {
                ConOutResPaging(TRUE,STRING_CMD_HELP8);
-               ExitProcess(0);
+               cmd_exit(0);
        }
        SetConsoleMode (hIn, ENABLE_PROCESSED_INPUT);
 
@@ -1681,10 +1759,6 @@ Initialize (int argc, TCHAR* argv[])
        InitLastPath ();
 #endif
 
-#ifdef FATURE_ALIASES
-       InitializeAlias ();
-#endif
-
        if (argc >= 2)
        {
                for (i = 1; i < argc; i++)
@@ -1720,11 +1794,11 @@ Initialize (int argc, TCHAR* argv[])
                                        }
 
                                        ParseCommandLine(commandline);
-                                       ExitProcess (ProcessInput (TRUE));
+                                       cmd_exit (ProcessInput (TRUE));
                                }
                                else
                                {
-                                       ExitProcess (0);
+                                       cmd_exit (0);
                                }
                        }
                        else if (!_tcsicmp (argv[i], _T("/k")))
@@ -1755,16 +1829,17 @@ Initialize (int argc, TCHAR* argv[])
 #endif
                }
        }
+    else
+    {
+        /* Display a simple version string */
+        ConOutPrintf(_T("ReactOS Operating System [Version %s-%s]\n"), 
+            _T(KERNEL_RELEASE_STR),
+            _T(KERNEL_VERSION_BUILD_STR));
 
-       /* run cmdstart.bat */
-       if (IsExistingFile (_T("cmdstart.bat")))
-       {
-               ParseCommandLine (_T("cmdstart.bat"));
-       }
-       else if (IsExistingFile (_T("\\cmdstart.bat")))
-       {
-               ParseCommandLine (_T("\\cmdstart.bat"));
-       }
+           ConOutPuts (_T("(C) Copyright 1998-") _T(COPYRIGHT_YEAR) _T(" ReactOS Team.\n"));
+    }
+
+    ExecuteAutoRunFile ();
 
 #ifdef FEATURE_DIR_STACK
        /* initialize directory stack */
@@ -1789,7 +1864,7 @@ Initialize (int argc, TCHAR* argv[])
 }
 
 
-static VOID Cleanup (int argc, TCHAR *argv[])
+static VOID Cleanup (int argc, const TCHAR *argv[])
 {
        /* run cmdexit.bat */
        if (IsExistingFile (_T("cmdexit.bat")))
@@ -1804,10 +1879,6 @@ static VOID Cleanup (int argc, TCHAR *argv[])
                ParseCommandLine (_T("\\cmdexit.bat"));
        }
 
-#ifdef FEATURE_ALIASES
-       DestroyAlias ();
-#endif
-
 #ifdef FEATURE_DIECTORY_STACK
        /* destroy directory stack */
        DestroyDirectoryStack ();
@@ -1836,20 +1907,11 @@ static VOID Cleanup (int argc, TCHAR *argv[])
 /*
  * main function
  */
-#ifdef _UNICODE
-int _main(void)
-#else
-int _main (int argc, char *argv[])
-#endif
+int cmd_main (int argc, const TCHAR *argv[])
 {
        TCHAR startPath[MAX_PATH];
        CONSOLE_SCREEN_BUFFER_INFO Info;
        INT nExitCode;
-#ifdef _UNICODE
-       PWCHAR * argv;
-       int argc=0;
-       argv = CommandLineToArgvW(GetCommandLineW(), &argc);
-#endif
 
        GetCurrentDirectory(MAX_PATH,startPath);
        _tchdir(startPath);
@@ -1882,6 +1944,7 @@ int _main (int argc, char *argv[])
        /* do the cleanup */
        Cleanup(argc, argv);
 
+       cmd_exit(nExitCode);
        return(nExitCode);
 }