Added Eric Kohl's port of freedos command
authorRex Jolliff <rex@lvcablemodem.com>
Sat, 20 Mar 1999 20:28:42 +0000 (20:28 +0000)
committerRex Jolliff <rex@lvcablemodem.com>
Sat, 20 Mar 1999 20:28:42 +0000 (20:28 +0000)
svn path=/trunk/; revision=324

110 files changed:
reactos/apps/utils/cmd/alias.c [new file with mode: 0644]
reactos/apps/utils/cmd/attrib.c [new file with mode: 0644]
reactos/apps/utils/cmd/batch.c [new file with mode: 0644]
reactos/apps/utils/cmd/batch.h [new file with mode: 0644]
reactos/apps/utils/cmd/beep.c [new file with mode: 0644]
reactos/apps/utils/cmd/bugs.txt [new file with mode: 0644]
reactos/apps/utils/cmd/call.c [new file with mode: 0644]
reactos/apps/utils/cmd/chcp.c [new file with mode: 0644]
reactos/apps/utils/cmd/chcp.h [new file with mode: 0644]
reactos/apps/utils/cmd/cls.c [new file with mode: 0644]
reactos/apps/utils/cmd/cmd.c
reactos/apps/utils/cmd/cmd.h [new file with mode: 0644]
reactos/apps/utils/cmd/cmdinput.c [new file with mode: 0644]
reactos/apps/utils/cmd/cmdtable.c [new file with mode: 0644]
reactos/apps/utils/cmd/color.c [new file with mode: 0644]
reactos/apps/utils/cmd/config.h [new file with mode: 0644]
reactos/apps/utils/cmd/console.c [new file with mode: 0644]
reactos/apps/utils/cmd/copy.c [new file with mode: 0644]
reactos/apps/utils/cmd/date.c [new file with mode: 0644]
reactos/apps/utils/cmd/del.c [new file with mode: 0644]
reactos/apps/utils/cmd/dir.c [new file with mode: 0644]
reactos/apps/utils/cmd/dirstack.c [new file with mode: 0644]
reactos/apps/utils/cmd/echo.c [new file with mode: 0644]
reactos/apps/utils/cmd/error.c [new file with mode: 0644]
reactos/apps/utils/cmd/filecomp.c [new file with mode: 0644]
reactos/apps/utils/cmd/files.txt [new file with mode: 0644]
reactos/apps/utils/cmd/for.c [new file with mode: 0644]
reactos/apps/utils/cmd/goto.c [new file with mode: 0644]
reactos/apps/utils/cmd/history.c [new file with mode: 0644]
reactos/apps/utils/cmd/history.txt [new file with mode: 0644]
reactos/apps/utils/cmd/if.c [new file with mode: 0644]
reactos/apps/utils/cmd/internal.c [new file with mode: 0644]
reactos/apps/utils/cmd/label.c [new file with mode: 0644]
reactos/apps/utils/cmd/license.txt [new file with mode: 0644]
reactos/apps/utils/cmd/locale.c [new file with mode: 0644]
reactos/apps/utils/cmd/makefile
reactos/apps/utils/cmd/makefile.lcc [new file with mode: 0644]
reactos/apps/utils/cmd/misc.c [new file with mode: 0644]
reactos/apps/utils/cmd/move.c [new file with mode: 0644]
reactos/apps/utils/cmd/path.c [new file with mode: 0644]
reactos/apps/utils/cmd/pause.c [new file with mode: 0644]
reactos/apps/utils/cmd/prompt.c [new file with mode: 0644]
reactos/apps/utils/cmd/readme.txt [new file with mode: 0644]
reactos/apps/utils/cmd/redir.c [new file with mode: 0644]
reactos/apps/utils/cmd/ren.c [new file with mode: 0644]
reactos/apps/utils/cmd/set.c [new file with mode: 0644]
reactos/apps/utils/cmd/shift.c [new file with mode: 0644]
reactos/apps/utils/cmd/time.c [new file with mode: 0644]
reactos/apps/utils/cmd/todo.txt [new file with mode: 0644]
reactos/apps/utils/cmd/type.c [new file with mode: 0644]
reactos/apps/utils/cmd/ver.c [new file with mode: 0644]
reactos/apps/utils/cmd/verify.c [new file with mode: 0644]
reactos/apps/utils/cmd/vol.c [new file with mode: 0644]
reactos/apps/utils/cmd/where.c [new file with mode: 0644]
reactos/apps/utils/cmd/wishlist.txt [new file with mode: 0644]
rosapps/cmd/alias.c [new file with mode: 0644]
rosapps/cmd/attrib.c [new file with mode: 0644]
rosapps/cmd/batch.c [new file with mode: 0644]
rosapps/cmd/batch.h [new file with mode: 0644]
rosapps/cmd/beep.c [new file with mode: 0644]
rosapps/cmd/bugs.txt [new file with mode: 0644]
rosapps/cmd/call.c [new file with mode: 0644]
rosapps/cmd/chcp.c [new file with mode: 0644]
rosapps/cmd/chcp.h [new file with mode: 0644]
rosapps/cmd/cls.c [new file with mode: 0644]
rosapps/cmd/cmd.c
rosapps/cmd/cmd.h [new file with mode: 0644]
rosapps/cmd/cmdinput.c [new file with mode: 0644]
rosapps/cmd/cmdtable.c [new file with mode: 0644]
rosapps/cmd/color.c [new file with mode: 0644]
rosapps/cmd/config.h [new file with mode: 0644]
rosapps/cmd/console.c [new file with mode: 0644]
rosapps/cmd/copy.c [new file with mode: 0644]
rosapps/cmd/date.c [new file with mode: 0644]
rosapps/cmd/del.c [new file with mode: 0644]
rosapps/cmd/dir.c [new file with mode: 0644]
rosapps/cmd/dirstack.c [new file with mode: 0644]
rosapps/cmd/echo.c [new file with mode: 0644]
rosapps/cmd/error.c [new file with mode: 0644]
rosapps/cmd/filecomp.c [new file with mode: 0644]
rosapps/cmd/files.txt [new file with mode: 0644]
rosapps/cmd/for.c [new file with mode: 0644]
rosapps/cmd/goto.c [new file with mode: 0644]
rosapps/cmd/history.c [new file with mode: 0644]
rosapps/cmd/history.txt [new file with mode: 0644]
rosapps/cmd/if.c [new file with mode: 0644]
rosapps/cmd/internal.c [new file with mode: 0644]
rosapps/cmd/label.c [new file with mode: 0644]
rosapps/cmd/license.txt [new file with mode: 0644]
rosapps/cmd/locale.c [new file with mode: 0644]
rosapps/cmd/makefile
rosapps/cmd/makefile.lcc [new file with mode: 0644]
rosapps/cmd/misc.c [new file with mode: 0644]
rosapps/cmd/move.c [new file with mode: 0644]
rosapps/cmd/path.c [new file with mode: 0644]
rosapps/cmd/pause.c [new file with mode: 0644]
rosapps/cmd/prompt.c [new file with mode: 0644]
rosapps/cmd/readme.txt [new file with mode: 0644]
rosapps/cmd/redir.c [new file with mode: 0644]
rosapps/cmd/ren.c [new file with mode: 0644]
rosapps/cmd/set.c [new file with mode: 0644]
rosapps/cmd/shift.c [new file with mode: 0644]
rosapps/cmd/time.c [new file with mode: 0644]
rosapps/cmd/todo.txt [new file with mode: 0644]
rosapps/cmd/type.c [new file with mode: 0644]
rosapps/cmd/ver.c [new file with mode: 0644]
rosapps/cmd/verify.c [new file with mode: 0644]
rosapps/cmd/vol.c [new file with mode: 0644]
rosapps/cmd/where.c [new file with mode: 0644]
rosapps/cmd/wishlist.txt [new file with mode: 0644]

diff --git a/reactos/apps/utils/cmd/alias.c b/reactos/apps/utils/cmd/alias.c
new file mode 100644 (file)
index 0000000..ac0a914
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ *  ALIAS.C - alias administration module.
+ *
+ *
+ *  History:
+ *
+ *    02/02/1996 (Oliver Mueller)
+ *        started.
+ *
+ *    02/03/1996 (Oliver Mueller)
+ *        Added sorting algorithm and case sensitive substitution by using
+ *        partstrupr().
+ *
+ *    27 Jul 1998  John P. Price
+ *        added config.h include
+ *        added ifdef's to disable aliases
+ *
+ *    09-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Fixed crash when removing an alias in DeleteAlias().
+ *        Added help text ("/?").
+ *
+ *    14-Jan-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Clean up and Unicode safe!
+ *
+ *    24-Jan-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Redirection safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef FEATURE_ALIASES
+
+#include <windows.h>
+#include <tchar.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "cmd.h"
+
+
+typedef struct tagALIAS
+{
+       struct tagALIAS *next;
+       LPTSTR lpName;
+       LPTSTR lpSubst;
+       WORD   wUsed;
+} ALIAS, *LPALIAS;
+
+
+static LPALIAS lpFirst = NULL;
+static LPALIAS lpLast = NULL;
+static WORD    wUsed = 0;
+
+
+/* module internal functions */
+/* strlwr only for first word in string */
+static VOID
+partstrlwr (LPTSTR str)
+{
+       LPTSTR c = str;
+       while (*c && !_istspace (*c))
+       {
+               *c = _totlower (*c);
+               c++;
+       }
+}
+
+
+static VOID
+PrintAlias (VOID)
+{
+       LPALIAS ptr = lpFirst;
+       while (ptr)
+       {
+               ConOutPrintf (_T("%s=%s\n"), ptr->lpName, ptr->lpSubst);
+               ptr = ptr->next;
+       }
+}
+
+
+static VOID
+DeleteAlias (LPTSTR pszName)
+{
+       LPALIAS ptr = lpFirst;
+       LPALIAS prev = NULL;
+
+       while (ptr)
+       {
+               if (!_tcsicmp (ptr->lpName, pszName))
+               {
+                       if (prev)
+                               prev->next = ptr->next;
+                       else
+                               lpFirst = ptr->next;
+                       free (ptr->lpName);
+                       free (ptr->lpSubst);
+                       free (ptr);
+                       return;
+               }
+               prev = ptr;
+               ptr = ptr->next;
+       }
+}
+
+
+static INT
+AddAlias (LPTSTR name, LPTSTR subst)
+{
+       LPALIAS ptr = lpFirst;
+       LPALIAS prev, entry;
+       LPTSTR s;
+
+       while (ptr)
+       {
+               if (!_tcsicmp (ptr->lpName, name))
+               {
+                       s = (LPTSTR)malloc ((_tcslen (subst) + 1)*sizeof(TCHAR));
+                       if (!s)
+                       {
+                               error_out_of_memory ();
+                               return 1;
+                       }
+
+                       free (ptr->lpSubst);
+                       ptr->lpSubst = s;
+                       _tcscpy (ptr->lpSubst, subst);
+                       return 0;
+               }
+               ptr = ptr->next;
+       }
+
+       ptr = (LPALIAS)malloc (sizeof (ALIAS));
+       if (!ptr)
+               return 1;
+
+       ptr->next = 0;
+
+       ptr->lpName = (LPTSTR)malloc ((_tcslen (name) + 1)*sizeof(TCHAR));
+       if (!ptr->lpName)
+       {
+               error_out_of_memory ();
+               free (ptr);
+               return 1;
+       }
+       _tcscpy (ptr->lpName, name);
+
+       ptr->lpSubst = (LPTSTR)malloc ((_tcslen (subst) + 1)*sizeof(TCHAR));
+       if (!ptr->lpSubst)
+       {
+               error_out_of_memory ();
+               free (ptr->lpName);
+               free (ptr);
+               return 1;
+       }
+       _tcscpy (ptr->lpSubst, subst);
+
+       /* it's necessary for recursive substitution */
+       partstrlwr (ptr->lpSubst);
+
+       ptr->wUsed = 0;
+
+       /* Alias table must be sorted!
+        * Here a little example:
+        *   command line = "ls -c"
+        * If the entries are
+        *   ls=dir
+        *   ls -c=ls /w
+        * command line will be expanded to "dir -c" which is not correct.
+        * If the entries are sortet as
+        *   ls -c=ls /w
+        *   ls=dir
+        * it will be expanded to "dir /w" which is a valid DOS command.
+        */
+       entry = lpFirst;
+       prev = 0;
+       while (entry)
+       {
+               if (_tcsicmp (ptr->lpName, entry->lpName) > 0)
+               {
+                       if (prev)
+                       {
+                               prev->next = ptr;
+                               ptr->next = entry;
+                       }
+                       else
+                       {
+                               ptr->next = entry;
+                               lpFirst = ptr;
+                       }
+                       return 0;
+               }
+               prev = entry;
+               entry = entry->next;
+       }
+
+       /* The new entry is the smallest (or the first) and must be
+        * added to the end of the list.
+        */
+       if (!lpFirst)
+               lpFirst = ptr;
+       else
+               lpLast->next = ptr;
+       lpLast = ptr;
+
+       return 0;
+}
+
+
+/* specified routines */
+VOID ExpandAlias (LPTSTR cmd, INT maxlen)
+{
+       unsigned n = 0,
+               m,
+               i,
+               len;
+       short d = 1;
+       LPALIAS ptr = lpFirst;
+
+       wUsed++;
+       if (wUsed == 0)
+       {
+               while (ptr)
+                       ptr->wUsed = 0;
+               ptr = lpFirst;
+               wUsed = 1;
+       }
+
+       /* skipping white spaces */
+       while (_istspace (cmd[n]))
+               n++;
+
+       partstrlwr (&cmd[n]);
+
+       if (!_tcsncmp (&cmd[n], _T("NOALIAS"), 7) &&
+               (_istspace (cmd[n + 7]) || cmd[n + 7] == _T('\0')))
+       {
+               memmove (cmd, &cmd[n + 7], (_tcslen (&cmd[n + 7]) + 1) * sizeof (TCHAR));
+               return;
+       }
+
+       /* substitution loop */
+       while (d)
+       {
+               d = 0;
+               while (ptr)
+               {
+                       len = _tcslen (ptr->lpName);
+                       if (!_tcsncmp (&cmd[n], ptr->lpName, len) &&
+                               (_istspace (cmd[n + len]) || cmd[n + len] == _T('\0')) &&
+                               ptr->wUsed != wUsed)
+                       {
+                               m = _tcslen (ptr->lpSubst);
+                               if ((int)(_tcslen (cmd) - len + m - n) > maxlen)
+                               {
+                                       ConErrPrintf (_T("Command line too long after alias expansion!\n"));
+                                       /* the parser won't cause any problems with an empty line */
+                                       cmd[0] = _T('\0');
+                               }
+                               else
+                               {
+                                       memmove (&cmd[m], &cmd[n + len], (_tcslen(&cmd[n + len]) + 1) * sizeof (TCHAR));
+                                       for (i = 0; i < m; i++)
+                                               cmd[i] = ptr->lpSubst[i];
+                                       ptr->wUsed = wUsed;
+                                       /* whitespaces are removed! */
+                                       n = 0;
+                                       d = 1;
+                               }
+                       }
+                       ptr = ptr->next;
+               }
+       }
+}
+
+
+INT cmd_alias (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR ptr;
+       INT n = 0;
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Sets, removes or shows aliases.\n"
+                                          "\n"
+                                          "ALIAS [alias=[command]]\n"
+                                          "\n"
+                                          "  alias    Name for an alias.\n"
+                                          "  command  Text to be substituted for an alias.\n"
+                                          "\n"
+//                                        "For example:\n"
+                                          "To list all aliases:\n"
+                                          "  ALIAS\n\n"
+                                          "To set a new or replace an existing alias:\n"
+                                          "  ALIAS da=dir a:\n\n"
+                                          "To remove an alias from the alias list:\n"
+                                          "  ALIAS da="
+//                                        "Type ALIAS without a parameter to display the alias list.\n"
+                                          ));
+               return 0;
+       }
+
+       if (param[0] == _T('\0'))
+       {
+               PrintAlias ();
+               return 0;
+       }
+
+       /* error if no '=' found */
+       if ((ptr = _tcschr (param, _T('='))) == 0)
+               return -1;
+
+       /* Split rest into name and substitute */
+       *ptr++ = _T('\0');
+
+       partstrlwr (param);
+
+       if (ptr[0] == _T('\0'))
+               DeleteAlias (param);
+       else
+               n = AddAlias (param, ptr);
+
+       return n;
+}
+#endif
diff --git a/reactos/apps/utils/cmd/attrib.c b/reactos/apps/utils/cmd/attrib.c
new file mode 100644 (file)
index 0000000..65a2c31
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ *  ATTRIB.C - attrib internal command.
+ *
+ *
+ *  History:
+ *
+ *    04-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        started
+ *
+ *    09-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        implementation works, except recursion ("attrib /s").
+ *
+ *    05-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        major rewrite.
+ *        fixed recursion ("attrib /s").
+ *        started directory support ("attrib /s /d").
+ *        updated help text.
+ *
+ *    14-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode ready!
+ *
+ *    19-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Redirection ready!
+ *
+ *    21-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added check for invalid filenames.
+ *
+ *    23-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added handling of multiple filenames.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_ATTRIB
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+
+static VOID
+PrintAttribute (LPTSTR pszPath, LPTSTR pszFile, BOOL bRecurse)
+{
+       WIN32_FIND_DATA findData;
+       HANDLE hFind;
+       TCHAR  szFullName[MAX_PATH];
+       LPTSTR pszFileName;
+
+       /* prepare full file name buffer */
+       _tcscpy (szFullName, pszPath);
+       pszFileName = szFullName + _tcslen (szFullName);
+
+       /* display all subdirectories */
+       if (bRecurse)
+       {
+               /* append file name */
+               _tcscpy (pszFileName, pszFile);
+
+               hFind = FindFirstFile (szFullName, &findData);
+               if (hFind == INVALID_HANDLE_VALUE)
+               {
+                       ErrorMessage (GetLastError (), pszFile);
+                       return;
+               }
+
+               do
+               {
+                       if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+                               continue;
+
+                       if (!_tcscmp (findData.cFileName, _T(".")) ||
+                               !_tcscmp (findData.cFileName, _T("..")))
+                               continue;
+
+                       _tcscpy (pszFileName, findData.cFileName);
+                       _tcscat (pszFileName, _T("\\"));
+                       PrintAttribute (szFullName, pszFile, bRecurse);
+               }
+               while (FindNextFile (hFind, &findData));
+               FindClose (hFind);
+       }
+
+       /* append file name */
+       _tcscpy (pszFileName, pszFile);
+
+       /* display current directory */
+       hFind = FindFirstFile (szFullName, &findData);
+       if (hFind == INVALID_HANDLE_VALUE)
+       {
+               ErrorMessage (GetLastError (), pszFile);
+               return;
+       }
+
+       do
+       {
+               if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+                       continue;
+
+               _tcscpy (pszFileName, findData.cFileName);
+
+               ConOutPrintf (_T("%c  %c%c%c     %s\n"),
+                                 (findData.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ? _T('A') : _T(' '),
+                                 (findData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) ? _T('S') : _T(' '),
+                                 (findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? _T('H') : _T(' '),
+                                 (findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? _T('R') : _T(' '),
+                                 szFullName);
+       }
+       while (FindNextFile (hFind, &findData));
+       FindClose (hFind);
+}
+
+
+static VOID
+ChangeAttribute (LPTSTR pszPath, LPTSTR pszFile, DWORD dwMask,
+                                DWORD dwAttrib, BOOL bRecurse, BOOL bDirectories)
+{
+       WIN32_FIND_DATA findData;
+       HANDLE hFind;
+       DWORD  dwAttribute;
+       TCHAR  szFullName[MAX_PATH];
+       LPTSTR pszFileName;
+
+       /* prepare full file name buffer */
+       _tcscpy (szFullName, pszPath);
+       pszFileName = szFullName + _tcslen (szFullName);
+
+       /* change all subdirectories */
+       if (bRecurse)
+       {
+               /* append file name */
+               _tcscpy (pszFileName, _T("*.*"));
+
+               hFind = FindFirstFile (szFullName, &findData);
+               if (hFind == INVALID_HANDLE_VALUE)
+               {
+                       ErrorMessage (GetLastError (), pszFile);
+                       return;
+               }
+
+               do
+               {
+                       if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+                       {
+                               if (!_tcscmp (findData.cFileName, _T(".")) ||
+                                       !_tcscmp (findData.cFileName, _T("..")))
+                                       continue;
+
+                               _tcscpy (pszFileName, findData.cFileName);
+                               _tcscat (pszFileName, _T("\\"));
+
+                               ChangeAttribute (szFullName, pszFile, dwMask,
+                                                                dwAttrib, bRecurse, bDirectories);
+                       }
+               }
+               while (FindNextFile (hFind, &findData));
+               FindClose (hFind);
+       }
+
+       /* append file name */
+       _tcscpy (pszFileName, pszFile);
+
+       hFind = FindFirstFile (szFullName, &findData);
+       if (hFind == INVALID_HANDLE_VALUE)
+       {
+               ErrorMessage (GetLastError (), pszFile);
+               return;
+       }
+
+       do
+       {
+               if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+                       continue;
+
+               _tcscpy (pszFileName, findData.cFileName);
+
+               dwAttribute = GetFileAttributes (szFullName);
+
+               if (dwAttribute != 0xFFFFFFFF)
+               {
+                       dwAttribute = (dwAttribute & ~dwMask) | dwAttrib;
+                       SetFileAttributes (szFullName, dwAttribute);
+               }
+       }
+       while (FindNextFile (hFind, &findData));
+       FindClose (hFind);
+}
+
+
+INT cmd_attrib (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR *arg;
+       INT    argc, i;
+       TCHAR  szPath[MAX_PATH];
+       TCHAR  szFileName [MAX_PATH];
+       BOOL   bRecurse = FALSE;
+       BOOL   bDirectories = FALSE;
+       DWORD  dwAttrib = 0;
+       DWORD  dwMask = 0;
+
+       /* initialize strings */
+       szPath[0] = _T('\0');
+       szFileName[0] = _T('\0');
+
+       /* print help */
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Displays or changes file attributes.\n\n"
+                                          "ATTRIB [+R | -R] [+A | -A] [+S | -S] [+H | -H] file ...\n"
+                                          "       [/S [/D]]\n\n"
+                                          "  +   Sets an attribute\n"
+                                          "  -   Clears an attribute\n"
+                                          "  R   Read-only file attribute\n"
+                                          "  A   Archive file attribute\n"
+                                          "  S   System file attribute\n"
+                                          "  H   Hidden file attribute\n"
+                                          "  /S  Processes matching files in the current directory\n"
+                                          "      and all subdirectories\n"
+                                          "  /D  Processes direcories as well\n\n"
+                                          "Type ATTRIB without a parameter to display the attributes of all files."));
+               return 0;
+       }
+
+       /* build parameter array */
+       arg = split (param, &argc);
+
+       /* check for options */
+       for (i = 0; i < argc; i++)
+       {
+               if (_tcsicmp (arg[i], _T("/s")) == 0)
+                       bRecurse = TRUE;
+               else if (_tcsicmp (arg[i], _T("/d")) == 0)
+                       bDirectories = TRUE;
+       }
+
+       /* create attributes and mask */
+       for (i = 0; i < argc; i++)
+       {
+               if (*arg[i] == _T('+'))
+               {
+                       if (_tcslen (arg[i]) != 2)
+                       {
+                               error_invalid_parameter_format (arg[i]);
+                               freep (arg);
+                               return -1;
+                       }
+
+                       switch ((TCHAR)_totupper (arg[i][1]))
+                       {
+                               case _T('A'):
+                                       dwMask   |= FILE_ATTRIBUTE_ARCHIVE;
+                                       dwAttrib |= FILE_ATTRIBUTE_ARCHIVE;
+                                       break;
+
+                               case _T('H'):
+                                       dwMask   |= FILE_ATTRIBUTE_HIDDEN;
+                                       dwAttrib |= FILE_ATTRIBUTE_HIDDEN;
+                                       break;
+
+                               case _T('R'):
+                                       dwMask   |= FILE_ATTRIBUTE_READONLY;
+                                       dwAttrib |= FILE_ATTRIBUTE_READONLY;
+                                       break;
+
+                               case _T('S'):
+                                       dwMask   |= FILE_ATTRIBUTE_SYSTEM;
+                                       dwAttrib |= FILE_ATTRIBUTE_SYSTEM;
+                                       break;
+
+                               default:
+                                       error_invalid_parameter_format (arg[i]);
+                                       freep (arg);
+                                       return -1;
+                       }
+               }
+               else if (*arg[i] == _T('-'))
+               {
+                       if (_tcslen (arg[i]) != 2)
+                       {
+                               error_invalid_parameter_format (arg[i]);
+                               freep (arg);
+                               return -1;
+                       }
+
+                       switch ((TCHAR)_totupper (arg[i][1]))
+                       {
+                               case _T('A'):
+                                       dwMask   |= FILE_ATTRIBUTE_ARCHIVE;
+                                       dwAttrib &= ~FILE_ATTRIBUTE_ARCHIVE;
+                                       break;
+
+                               case _T('H'):
+                                       dwMask   |= FILE_ATTRIBUTE_HIDDEN;
+                                       dwAttrib &= ~FILE_ATTRIBUTE_HIDDEN;
+                                       break;
+
+                               case _T('R'):
+                                       dwMask   |= FILE_ATTRIBUTE_READONLY;
+                                       dwAttrib &= ~FILE_ATTRIBUTE_READONLY;
+                                       break;
+
+                               case _T('S'):
+                                       dwMask   |= FILE_ATTRIBUTE_SYSTEM;
+                                       dwAttrib &= ~FILE_ATTRIBUTE_SYSTEM;
+                                       break;
+
+                               default:
+                                       error_invalid_parameter_format (arg[i]);
+                                       freep (arg);
+                                       return -1;
+                       }
+               }
+       }
+
+       if (argc == 0)
+       {
+               GetCurrentDirectory (MAX_PATH, szPath);
+               _tcscat (szPath, _T("\\"));
+               _tcscpy (szFileName, _T("*.*"));
+               PrintAttribute (szPath, szFileName, bRecurse);
+       }
+       else
+       {
+               /* get full file name */
+               for (i = 0; i < argc; i++)
+               {
+                       if ((*arg[i] != _T('+')) && (*arg[i] != _T('-')) &&     (*arg[i] != _T('/')))
+                       {
+                               LPTSTR p;
+                               GetFullPathName (arg[i], MAX_PATH, szPath, NULL);
+                               p = _tcsrchr (szPath, _T('\\')) + 1;
+                               _tcscpy (szFileName, p);
+                               *p = _T('\0');
+
+                               if (dwMask == 0)
+                                       PrintAttribute (szPath, szFileName, bRecurse);
+                               else
+                                       ChangeAttribute (szPath, szFileName, dwMask,
+                                                                        dwAttrib, bRecurse, bDirectories);
+                       }
+               }
+       }
+
+       freep (arg);
+
+       return 0;
+}
+
+#endif /* INCLUDE_CMD_ATTRIB */
diff --git a/reactos/apps/utils/cmd/batch.c b/reactos/apps/utils/cmd/batch.c
new file mode 100644 (file)
index 0000000..b1ea5be
--- /dev/null
@@ -0,0 +1,462 @@
+/*
+ *  BATCH.C - batch file processor for CMD.EXE.
+ *
+ *
+ *  History:
+ *
+ *    ??/??/?? (Evan Jeffrey)
+ *        started.
+ *
+ *    15 Jul 1995 (Tim Norman)
+ *        modes and bugfixes.
+ *
+ *    08 Aug 1995 (Matt Rains)
+ *        i have cleaned up the source code. changes now bring this
+ *        source into guidelines for recommended programming practice.
+ *
+ *        i have added some constants to help making changes easier.
+ *
+ *    29 Jan 1996 (Steffan Kaiser)
+ *        made a few cosmetic changes
+ *
+ *    05 Feb 1996 (Tim Norman)
+ *        changed to comply with new first/rest calling scheme
+ *
+ *    14 Jun 1997 (Steffen Kaiser)
+ *        bug fixes.  added error level expansion %?.  ctrl-break handling
+ *
+ *    16 Jul 1998 (Hans B Pufal)
+ *        Totally reorganised in conjunction with COMMAND.C (cf) to
+ *        implement proper BATCH file nesting and other improvements.
+ *
+ *    16 Jul 1998 (John P Price <linux-guru@gcfl.net>)
+ *        Seperated commands into individual files.
+ *
+ *    19 Jul 1998 (Hans B Pufal) [HBP_001]
+ *        Preserve state of echo flag across batch calls.
+ *
+ *    19 Jul 1998 (Hans B Pufal) [HBP_002]
+ *        Implementation of FOR command
+ *
+ *    20-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added error checking after malloc calls
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    02-Aug-1998 (Hans B Pufal) [HBP_003]
+ *        Fixed bug in ECHO flag restoration at exit from batch file
+ *
+ *    26-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Replaced CRT io functions by Win32 io functions.
+ *        Unicode safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+/* The stack of current batch contexts.
+ * NULL when no batch is active
+ */
+LPBATCH_CONTEXT bc = NULL;
+
+BOOL bEcho = TRUE;          /* The echo flag */
+
+
+
+/* Buffer for reading Batch file lines */
+TCHAR textline[BATCH_BUFFSIZE];
+
+
+/*
+ * Returns a pointer to the n'th parameter of the current batch file.
+ * If no such parameter exists returns pointer to empty string.
+ * If no batch file is current, returns NULL
+ *
+ */
+
+LPTSTR FindArg (INT n)
+{
+       LPTSTR pp;
+
+#ifdef _DEBUG
+       DebugPrintf ("FindArg: (%d)\n", n);
+#endif
+
+       if (bc == NULL)
+               return NULL;
+
+       n += bc->shiftlevel;
+       pp = bc->params;
+
+       /* Step up the strings till we reach the end */
+       /* or the one we want */
+       while (*pp && n--)
+               pp += _tcslen (pp) + 1;
+
+       return pp;
+}
+
+
+/* HBP_002 { FOR command support */
+/*
+ * Batch_params builds a parameter list in newlay allocated memory.
+ * The parameters consist of null terminated strings with a final
+ * NULL character signalling the end of the parameters.
+ *
+*/
+
+LPTSTR BatchParams (LPTSTR s1, LPTSTR s2)
+{
+       LPTSTR dp = (LPTSTR)malloc ((_tcslen(s1) + _tcslen(s2) + 3) * sizeof (TCHAR));
+
+       /* JPP 20-Jul-1998 added error checking */
+       if (dp == NULL)
+       {
+               error_out_of_memory();
+               return NULL;
+       }
+
+       if (s1 && *s1)
+       {
+               s1 = stpcpy (dp, s1);
+               *s1++ = _T('\0');
+       }
+       else
+               s1 = dp;
+
+       while (*s2)
+       {
+               if (_istspace (*s2) || _tcschr (_T(",;"), *s2))
+               {
+                       *s1++ = _T('\0');
+                       s2++;
+                       while (*s2 && _tcschr (_T(" ,;"), *s2))
+                               s2++;
+                       continue;
+               }
+
+               if ((*s2 == _T('"')) || (*s2 == _T('\'')))
+               {
+                       TCHAR st = *s2;
+
+                       do
+                               *s1++ = *s2++;
+                       while (*s2 && (*s2 != st));
+               }
+
+               *s1++ = *s2++;
+       }
+
+       *s1++ = _T('\0');
+       *s1 = _T('\0');
+
+       return dp;
+}
+
+/* HBP_002 } */
+
+
+/*
+ * If a batch file is current, exits it, freeing the context block and
+ * chaining back to the previous one.
+ *
+ * If no new batch context is found, sets ECHO back ON.
+ *
+ * If the parameter is non-null or not empty, it is printed as an exit
+ * message
+ */
+
+VOID ExitBatch (LPTSTR msg)
+{
+#ifdef _DEBUG
+       DebugPrintf ("ExitBatch: (\'%s\')\n", msg);
+#endif
+
+       if (bc)
+       {
+               LPBATCH_CONTEXT t = bc;
+
+               if (bc->hBatchFile)
+               {
+                       CloseHandle (bc->hBatchFile);
+                       bc->hBatchFile = INVALID_HANDLE_VALUE;
+               }
+
+               if (bc->params)
+                       free(bc->params);
+
+/* HBP_002 { FOR command support */
+
+               if (bc->forproto)
+                       free(bc->forproto);
+
+               if (bc->ffind)
+                       free(bc->ffind);
+
+/* HBP_002 } */
+
+/* HBP_003 { fix echo restore */
+               /* Preserve echo state across batch calls */
+               bEcho = bc->bEcho;
+
+/* HBP_003 fix echo restore } */
+
+               bc = bc->prev;
+               free(t);
+       }
+
+/* HBP_001 } */
+
+       if (msg && *msg)
+               ConOutPrintf ("%s\n", msg);
+}
+
+
+/*
+ * Start batch file execution
+ *
+ * The firstword parameter is the full filename of the batch file.
+ *
+ */
+
+BOOL Batch (LPTSTR fullname, LPTSTR firstword, LPTSTR param)
+{
+       HANDLE hFile;
+
+       hFile = CreateFile (fullname, GENERIC_READ, FILE_SHARE_READ, NULL,
+                                               OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL |
+                                               FILE_FLAG_SEQUENTIAL_SCAN, NULL);
+
+#ifdef _DEBUG
+       DebugPrintf ("Batch: (\'%s\', \'%s\', \'%s\')  hFile = %x\n",
+                                fullname, firstword, param, hFile);
+#endif
+
+       if (hFile == INVALID_HANDLE_VALUE)
+       {
+               ConErrPrintf (_T("Error opening batch file\n"));
+               return FALSE;
+       }
+
+/* HBP_002 { FOR command support */
+
+       /* Kill any and all FOR contexts */
+       while (bc && bc->forvar)
+               ExitBatch (NULL);
+
+/* HBP_002 } */
+
+       if (bc == NULL)
+       {
+               /* No curent batch file, create a new context */
+               LPBATCH_CONTEXT n = (LPBATCH_CONTEXT)malloc (sizeof(BATCH_CONTEXT));
+
+               if (n == NULL)
+               {
+                       /* JPP 20-Jul-1998 added error checking */
+                       error_out_of_memory ();
+                       return FALSE;
+               }
+
+               n->prev = bc;
+               bc = n;
+       }
+       else if (bc->hBatchFile != INVALID_HANDLE_VALUE)
+       {
+               /* Then we are transferring to another batch */
+               CloseHandle (bc->hBatchFile);
+               bc->hBatchFile = INVALID_HANDLE_VALUE;
+               free (bc->params);
+       }
+
+       bc->hBatchFile = hFile;
+       bc->bEcho = bEcho; /* Preserve echo across batch calls [HBP_001] */
+       bc->shiftlevel = 0;
+
+       /* HBP_002 { FOR command support */
+       bc->ffind = NULL;
+       bc->forvar = _T('\0');
+       bc->forproto = NULL;
+       bc->params = BatchParams (firstword, param);
+       /* HBP_002 } */
+
+       return TRUE;
+}
+
+
+/*
+ * Read and return the next executable line form the current batch file
+ *
+ * If no batch file is current or no further executable lines are found
+ * return NULL.
+ *
+ * Here we also look out for FOR bcontext structures which trigger the
+ * FOR expansion code.
+ *
+ * Set eflag to 0 if line is not to be echoed else 1
+ */
+
+LPTSTR ReadBatchLine (LPBOOL bLocalEcho)
+{
+       HANDLE hFind = INVALID_HANDLE_VALUE;
+       LPTSTR first;
+       LPTSTR ip;
+
+       /* No batch */
+       if (bc == NULL)
+               return NULL;
+
+#ifdef _DEBUG
+       DebugPrintf ("ReadBatchLine ()\n");
+#endif
+
+       while (1)
+       {
+               /* User halt */
+               if (CheckCtrlBreak (BREAK_BATCHFILE))
+               {
+                       while (bc)
+                               ExitBatch (NULL);
+                       return NULL;
+               }
+
+               /* HBP_002 { FOR command support */
+               /* No batch */
+               if (bc == NULL)
+                       return NULL;
+
+               /* If its a FOR context... */
+               if (bc->forvar)
+               {
+                       LPTSTR sp = bc->forproto; /* pointer to prototype command */
+                       LPTSTR dp = textline;     /* Place to expand protoype */
+                       LPTSTR fv = FindArg (0);  /* Next list element */
+
+                       /* End of list so... */
+                       if ((fv == NULL) || (*fv == _T('\0')))
+                       {
+                               /* just exit this context */
+                               ExitBatch (NULL);
+                               continue;
+                       }
+
+                       if (_tcscspn (fv, _T("?*")) == _tcslen (fv))
+                       {
+                               /* element is wild file */
+                               bc->shiftlevel++;       /* No use it and shift list */
+                       }
+                       else
+                       {
+                               /* Wild file spec, find first (or next) file name */
+                               if (bc->ffind)
+                               {
+                                       /* First already done so do next */
+                                       fv = FindNextFile (hFind, bc->ffind) ? bc->ffind->cFileName : NULL;
+                               }
+                               else
+                               {
+                                       /*  For first find, allocate a find first block */
+                                       if ((bc->ffind = (LPWIN32_FIND_DATA)malloc (sizeof (WIN32_FIND_DATA))) == NULL)
+                                       {
+                                               error_out_of_memory();  /* JPP 20-Jul-1998 added error checking */
+                                               return NULL;
+                                       }
+
+                                       hFind = FindFirstFile (fv, bc->ffind);
+                                       fv = !(hFind==INVALID_HANDLE_VALUE) ? bc->ffind->cFileName : NULL;
+                               }
+
+                               if (fv == NULL)
+                               {
+                                       /* Null indicates no more files.. */
+                                       free (bc->ffind);      /* free the buffer */
+                                       bc->ffind = NULL;
+                                       bc->shiftlevel++;     /* On to next list element */
+                                       continue;
+                               }
+                       }
+
+                       /* At this point, fv points to parameter string */
+                       while (*sp)
+                       {
+                               if ((*sp == _T('%')) && (*(sp + 1) == bc->forvar))
+                               {
+                                       /* replace % var */
+                                       dp = stpcpy (dp, fv);
+                                       sp += 2;
+                               }
+                               else
+                               {
+                                       /* Else just copy */
+                                       *dp++ = *sp++;
+                               }
+                       }
+
+                       *dp = _T('\0');
+
+                       *bLocalEcho = bEcho;
+
+                       return textline;
+               }
+
+               /* HBP_002 } */
+
+               if (!FileGetString (bc->hBatchFile, textline, sizeof (textline)))
+               {
+#ifdef _DEBUG
+                       DebugPrintf (_T("ReadBatchLine(): Reached EOF!\n"));
+#endif
+                       /* End of file.... */
+                       ExitBatch (NULL);
+
+                       if (bc == NULL)
+                               return NULL;
+
+                       continue;
+               }
+
+#ifdef _DEBUG
+               DebugPrintf (_T("ReadBatchLine(): textline: \'%s\'\n"), textline);
+#endif
+
+               /* Strip leading spaces and trailing space/control chars */
+               for (first = textline; _istspace (*first); first++)
+                       ;
+
+               for (ip = first + _tcslen (first) - 1; _istspace (*ip) || _istcntrl (*ip); ip--)
+                       ;
+
+               *++ip = _T('\0');
+
+               /* ignore labels and empty lines */
+               if (*first == _T(':') || *first == 0)
+                       continue;
+
+               if (*first == _T('@'))
+               {
+                       /* don't echo this line */
+                       do
+                               first++;
+                       while (_istspace (*first));
+
+                       *bLocalEcho = 0;
+               }
+               else
+                       *bLocalEcho = bEcho;
+
+               break;
+       }
+
+       return first;
+}
diff --git a/reactos/apps/utils/cmd/batch.h b/reactos/apps/utils/cmd/batch.h
new file mode 100644 (file)
index 0000000..11324e3
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ *  BATCH.H - A structure to preserve the context of a batch file
+ *
+ *
+ */
+
+
+typedef struct tagBATCHCONTEXT
+{
+       struct tagBATCHCONTEXT *prev;
+       LPWIN32_FIND_DATA ffind;
+       HANDLE hBatchFile;
+       LPTSTR forproto;
+       LPTSTR params;
+       INT    shiftlevel;
+       BOOL   bEcho;        /* Preserve echo flag across batch calls [HBP_001] */
+       TCHAR forvar;
+} BATCH_CONTEXT, *LPBATCH_CONTEXT;
+
+/* HBP_002 } */
+
+
+/*  The stack of current batch contexts.
+ * NULL when no batch is active
+ */
+extern LPBATCH_CONTEXT bc;
+
+extern BOOL bEcho;       /* The echo flag */
+
+#define BATCH_BUFFSIZE  2048
+
+extern TCHAR textline[BATCH_BUFFSIZE]; /* Buffer for reading Batch file lines */
+
+
+LPTSTR FindArg (INT);
+LPTSTR BatchParams (LPTSTR, LPTSTR);
+VOID   ExitBatch (LPTSTR);
+BOOL   Batch (LPTSTR, LPTSTR, LPTSTR);
+LPTSTR ReadBatchLine (LPBOOL);
diff --git a/reactos/apps/utils/cmd/beep.c b/reactos/apps/utils/cmd/beep.c
new file mode 100644 (file)
index 0000000..9f9834c
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ *  BEEP.C - beep internal 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
+ *
+ *    14-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("beep /?").
+ *        Unicode ready!
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Redirection ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_BEEP
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+INT cmd_beep (LPTSTR cmd, LPTSTR param)
+{
+       if (_tcsncmp (param, _T("/?"), 2) == 0)
+       {
+               ConOutPuts (_T("Beep the speaker.\n\nBEEP"));
+               return 0;
+       }
+
+#if 0
+       /* check if run in batch mode */
+       if (bc == NULL)
+               return 1;
+#endif
+
+       MessageBeep (-1);
+
+       return 0;
+}
+#endif
diff --git a/reactos/apps/utils/cmd/bugs.txt b/reactos/apps/utils/cmd/bugs.txt
new file mode 100644 (file)
index 0000000..2cfa275
--- /dev/null
@@ -0,0 +1,15 @@
+         ****  Please report bugs to ekohl@abo.rhein-zeitung.de!  ****
+
+Known bugs in CMD version 0.0.4
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+o  let set work with or without the '=' sign.  People like it that way.
+    (I don't know, if I should really fix this?)
+
+o  command.com ignores control-c and control-break, which makes it difficult
+   to quit typing a long file, among other things
+
+o  "alias v = dir" doesn't work because of the spaces.
+
+
+         ****  Please report bugs to ekohl@abo.rhein-zeitung.de!  ****
diff --git a/reactos/apps/utils/cmd/call.c b/reactos/apps/utils/cmd/call.c
new file mode 100644 (file)
index 0000000..db5dd63
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ *  CALL.C - call internal batch command.
+ *
+ *
+ *  History:
+ *
+ *    16 Jul 1998 (Hans B Pufal)
+ *        started.
+ *
+ *    16 Jul 1998 (John P Price)
+ *        Seperated 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 <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("call /?") and cleaned up.
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+/*
+ * Perform CALL command.
+ *
+ * Allocate a new batch context and add it to the current chain.
+ * Call parsecommandline passing in our param string
+ * If No batch file was opened then remove our newly allocted
+ * context block.
+ */
+
+INT cmd_call (LPTSTR cmd, LPTSTR param)
+{
+       LPBATCH_CONTEXT n = NULL;
+
+#ifdef _DEBUG
+       DebugPrintf ("cmd_call: (\'%s\',\'%s\')\n", cmd, param);
+#endif
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Calls one batch program from another.\n\n"
+                                          "CALL [drive:][path]filename [batch-parameter]\n\n"
+                                          "  batch-parameter  Specifies any command-line information required by the\n"
+                                          "                   batch program."));
+               return 0;
+       }
+
+       n = (LPBATCH_CONTEXT)malloc (sizeof (BATCH_CONTEXT));
+
+       if (n == NULL)
+       {
+               error_out_of_memory ();
+               return 1;
+       }
+
+       n->prev = bc;
+       bc = n;
+
+       bc->hBatchFile = INVALID_HANDLE_VALUE;
+       bc->params = NULL;
+       bc->shiftlevel = 0;
+       bc->forvar = 0;        /* HBP004 */
+       bc->forproto = NULL;   /* HBP004 */
+
+       ParseCommandLine (param);
+
+       /* Wasn't a batch file so remove conext */
+       if (bc->hBatchFile == INVALID_HANDLE_VALUE)
+       {
+               bc = bc->prev;
+               free (n);
+       }
+
+       return 0;
+}
diff --git a/reactos/apps/utils/cmd/chcp.c b/reactos/apps/utils/cmd/chcp.c
new file mode 100644 (file)
index 0000000..6831e57
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ *  CHCP.C - chcp internal command.
+ *
+ *
+ *  History:
+ *
+ *    23-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Started.
+ *
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_CHCP
+
+#include <windows.h>
+#include <tchar.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+#include "chcp.h"
+
+
+INT CommandChcp (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR *arg;
+       INT    args;
+
+       /* print help */
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Displays or sets the active code page number.\n\n"
+                                          "CHCP [nnn]\n\n"
+                                          "  nnn   Specifies the active code page number.\n\n"
+                                          "Type CHCP without a parameter to display the active code page number."));
+               return 0;
+       }
+
+       /* get parameters */
+       arg = split (param, &args);
+
+       if (args == 0)
+       {
+               /* display active code page number */
+               ConOutPrintf ("Active code page: %u\n", GetConsoleCP ());
+       }
+       else if (args >= 2)
+       {
+               /* too many parameters */
+               ConErrPrintf ("Invalid parameter format - %s\n", param);
+       }
+       else
+       {
+               /* set active code page number */
+
+               UINT uOldCodePage;
+               UINT uNewCodePage;
+
+               /* save old code page */
+               uOldCodePage = GetConsoleCP ();
+
+               uNewCodePage = (UINT)_ttoi (arg[0]);
+
+               if (uNewCodePage == 0)
+               {
+                       ConErrPrintf ("Parameter format incorrect - %s\n", arg[0]);
+
+               }
+               else
+               {
+                       if (!SetConsoleCP (uNewCodePage))
+                       {
+                               ConErrPrintf ("Invalid code page\n");
+                       }
+                       else
+                       {
+                               SetConsoleOutputCP (uNewCodePage);
+                               InitLocale ();
+                       }
+               }
+       }
+
+       freep (arg);
+
+       return 0;
+}
+
+#endif /* INCLUDE_CMD_CHCP */
\ No newline at end of file
diff --git a/reactos/apps/utils/cmd/chcp.h b/reactos/apps/utils/cmd/chcp.h
new file mode 100644 (file)
index 0000000..11ff568
--- /dev/null
@@ -0,0 +1,8 @@
+/* prototypes for CHCP.C */
+
+
+#ifdef INCLUDE_CMD_CHCP
+
+INT CommandChcp (LPTSTR, LPTSTR);
+
+#endif
\ No newline at end of file
diff --git a/reactos/apps/utils/cmd/cls.c b/reactos/apps/utils/cmd/cls.c
new file mode 100644 (file)
index 0000000..2e27fcc
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *  CLS.C - clear screen internal command.
+ *
+ *
+ *  History:
+ *
+ *    07/27/1998 (John P. Price)
+ *        started.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    04-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Changed to Win32 console app.
+ *
+ *    08-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("/?").
+ *
+ *    14-Jan-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode ready!
+ *
+ *    20-Jan-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Redirection ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_CLS
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+
+INT cmd_cls (LPTSTR cmd, LPTSTR param)
+{
+       DWORD dwWritten;
+       CONSOLE_SCREEN_BUFFER_INFO csbi;
+       COORD coPos;
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Clears the screen.\n\nCLS"));
+               return 0;
+       }
+
+       GetConsoleScreenBufferInfo (hOut, &csbi);
+
+       coPos.X = 0;
+       coPos.Y = 0;
+       FillConsoleOutputAttribute (hOut, wColor,
+                                                               (csbi.dwSize.X)*(csbi.dwSize.Y),
+                                                               coPos, &dwWritten);
+       FillConsoleOutputCharacter (hOut, _T(' '),
+                                                               (csbi.dwSize.X)*(csbi.dwSize.Y),
+                                                               coPos, &dwWritten);
+       SetConsoleCursorPosition (hOut, coPos);
+
+       bIgnoreEcho = TRUE;
+
+       return 0;
+}
+#endif
index 22211f7..2841c33 100644 (file)
-#include <stdarg.h>
+/*
+ *  CMD.C - command-line interface.
+ *
+ *
+ *  History:
+ *
+ *    17 Jun 1994 (Tim Norman)
+ *        started.
+ *
+ *    08 Aug 1995 (Matt Rains)
+ *        I have cleaned up the source code. changes now bring this source
+ *        into guidelines for recommended programming practice.
+ *
+ *        A added the the standard FreeDOS GNU licence test to the
+ *        initialize() function.
+ *
+ *        Started to replace puts() with printf(). this will help
+ *        standardize output. please follow my lead.
+ *
+ *        I have added some constants to help making changes easier.
+ *
+ *    15 Dec 1995 (Tim Norman)
+ *        major rewrite of the code to make it more efficient and add
+ *        redirection support (finally!)
+ *
+ *    06 Jan 1996 (Tim Norman)
+ *        finished adding redirection support!  Changed to use our own
+ *        exec code (MUCH thanks to Svante Frey!!)
+ *
+ *    29 Jan 1996 (Tim Norman)
+ *        added support for CHDIR, RMDIR, MKDIR, and ERASE, as per
+ *        suggestion of Steffan Kaiser
+ *
+ *        changed "file not found" error message to "bad command or
+ *        filename" thanks to Dustin Norman for noticing that confusing
+ *        message!
+ *
+ *        changed the format to call internal commands (again) so that if
+ *        they want to split their commands, they can do it themselves 
+ *        (none of the internal functions so far need that much power, anyway)
+ *
+ *    27 Aug 1996 (Tim Norman)
+ *        added in support for Oliver Mueller's ALIAS command
+ *
+ *    14 Jun 1997 (Steffan Kaiser)
+ *        added ctrl-break handling and error level
+ *
+ *    16 Jun 1998 (Rob Lake)
+ *        Runs command.com if /P is specified in command line.  Command.com
+ *        also stays permanent.  If /C is in the command line, starts the
+ *        program next in the line.
+ *
+ *    21 Jun 1998 (Rob Lake)
+ *        Fixed up /C so that arguments for the program
+ *
+ *    08-Jul-1998 (John P. Price)
+ *        Now sets COMSPEC environment variable
+ *        misc clean up and optimization
+ *        added date and time commands
+ *        changed to using spawnl instead of exec.  exec does not copy the
+ *        environment to the child process!
+ *
+ *    14 Jul 1998 (Hans B Pufal)
+ *        Reorganised source to be more efficient and to more closely
+ *        follow MS-DOS conventions. (eg %..% environment variable
+ *        replacement works form command line as well as batch file.
+ *
+ *        New organisation also properly support nested batch files.
+ *
+ *        New command table structure is half way towards providing a
+ *        system in which COMMAND will find out what internal commands
+ *        are loaded
+ *
+ *    24 Jul 1998 (Hans B Pufal) [HBP_003]
+ *        Fixed return value when called with /C option
+ *
+ *    27 Jul 1998  John P. Price
+ *        added config.h include
+ *
+ *    28 Jul 1998  John P. Price
+ *        added showcmds function to show commands and options available
+ *
+ *    07-Aug-1998 (John P Price <linux-guru@gcfl.net>)
+ *        Fixed carrage return output to better match MSDOS with echo
+ *        on or off. (marked with "JPP 19980708")
+ *
+ *    07-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        First ReactOS release.
+ *        Extended length of commandline buffers to 512.
+ *
+ *    13-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added COMSPEC environment variable.
+ *        Added "/t" support (color) on cmd command line.
+ *
+ *    07-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("cmd /?").
+ *
+ *    25-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection safe!
+ *        Fixed redirections and piping.
+ *        Piping is based on temporary files, but basic support
+ *        for anonymous pipes already exists.
+ *
+ *    27-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Replaced spawnl() by CreateProcess().
+ */
+
+// #define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
 #include <windows.h>
+// #include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
 
-HANDLE stdin;
-HANDLE stdout;
+#include "cmd.h"
+#include "batch.h"
 
 
-void Console_puts(char* str)
-{
-        ULONG nchar;
+#define CMDLINE_LENGTH  512
+
+
+BOOL bExit = FALSE;       /* indicates EXIT was typed */
+BOOL bCanExit = TRUE;     /* indicates if this shell is exitable */
+BOOL bCtrlBreak = FALSE;  /* Ctrl-Break or Ctrl-C hit */
+BOOL bIgnoreEcho = FALSE; /* Ignore 'newline' before 'cls' */
+INT  errorlevel = 0;      /* Errorlevel of last launched external program */
+OSVERSIONINFO osvi;
+HANDLE hIn;
+HANDLE hOut;
+
+#ifdef INCLUDE_CMD_COLOR
+WORD wColor = FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN; /* current color */
+WORD wDefColor = FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN; /* default color */
+#endif
+
 
-        WriteConsole(stdout,
-                     str,
-                     strlen(str),
-                     &nchar,
-                     NULL);
+extern COMMAND cmds[];         /* The internal command table */
+
+
+/*
+ *  is character a delimeter when used on first word?
+ *
+ */
+
+static BOOL IsDelimiter (TCHAR c)
+{
+       return (c == _T('/') || c == _T('=') || c == _T('\0') || _istspace (c));
 }
 
-void Console_printf(char* fmt, ...)
+
+/*
+ * This command (in first) was not found in the command table
+ *
+ * first - first word on command line
+ * rest  - rest of command line
+ */
+
+static VOID
+Execute (LPTSTR first, LPTSTR rest)
 {
-        char buffer[255];
-        va_list vargs;
+       TCHAR szFullName[MAX_PATH];
+
+       /* check for a drive change */
+       if (!_tcscmp (first + 1, _T(":")) && _istalpha (*first))
+       {
+               TCHAR szPath[MAX_PATH];
+
+               _tcscpy (szPath, _T("A:"));
+               szPath[0] = _totupper (*first);
+               SetCurrentDirectory (szPath);
+               GetCurrentDirectory (MAX_PATH, szPath);
+               if (szPath[0] != (TCHAR)_totupper (*first))
+                       ConErrPuts (INVALIDDRIVE);
 
-        va_start(vargs,fmt);
-        vsprintf(buffer,fmt,vargs);
-        Console_puts(buffer);
-        va_end(vargs);
+               return;
+       }
+
+       /* get the PATH environment variable and parse it */
+       /* search the PATH environment variable for the binary */
+       find_which (first, szFullName);
+
+       if (szFullName[0] == _T('\0'))
+       {
+               error_bad_command ();
+               return;
+       }
+
+       /* check if this is a .BAT or .CMD file */
+       if (!_tcsicmp (_tcsrchr (szFullName, _T('.')), _T(".bat")) ||
+               !_tcsicmp (_tcsrchr (szFullName, _T('.')), _T(".cmd")))
+       {
+#ifdef _DEBUG
+               DebugPrintf ("[BATCH: %s %s]\n", szFullName, rest);
+#endif
+               Batch (szFullName, first, rest);
+       }
+       else
+       {
+               /* exec the program */
+               TCHAR szFullCmdLine [1024];
+               PROCESS_INFORMATION prci;
+               STARTUPINFO stui;
+               DWORD dwError = 0;
+
+#ifdef _DEBUG
+               DebugPrintf ("[EXEC: %s %s]\n", szFullName, rest);
+#endif
+               /* build command line for CreateProcess() */
+               _tcscpy (szFullCmdLine, szFullName);
+               _tcscat (szFullCmdLine, " ");
+               _tcscat (szFullCmdLine, rest);
+
+               /* fill startup info */
+               memset (&stui, 0, sizeof (STARTUPINFO));
+               stui.cb = sizeof (STARTUPINFO);
+               stui.dwFlags = STARTF_USESHOWWINDOW;
+               stui.wShowWindow = SW_SHOWDEFAULT;
+                       
+               if (CreateProcess (NULL, szFullCmdLine, NULL, NULL, FALSE,
+                                                  0, NULL, NULL, &stui, &prci))
+               {
+                       WaitForSingleObject (prci.hProcess, INFINITE);
+                       GetExitCodeProcess (prci.hProcess, &errorlevel);
+                       CloseHandle (prci.hThread);
+                       CloseHandle (prci.hProcess);
+               }
+               else
+               {
+                       ErrorMessage (GetLastError (),
+                                                 "Error executing CreateProcess()!!\n");
+               }
+       }
 }
 
-void Console_getline(PCH Prompt, PCH Output, DWORD OutputLength)
+
+/*
+ * look through the internal commands and determine whether or not this
+ * command is one of them.  If it is, call the command.  If not, call
+ * execute to run it as an external program.
+ *
+ * line - the command line of the program to run
+ *
+ */
+
+static VOID
+DoCommand (LPTSTR line)
 {
-        char ch;
-        DWORD nbytes;
+       TCHAR com[MAX_PATH];  /* the first word in the command */
+       LPTSTR cp = com;
+       LPTSTR cstart;
+       LPTSTR rest = line;   /* pointer to the rest of the command line */
+       INT cl;
+       LPCOMMAND cmdptr;
+
+       /* Skip over initial white space */
+       while (isspace (*rest))
+               rest++;
+
+       cstart = rest;
+
+       /* Anything to do ? */
+       if (*rest)
+       {
+               /* Copy over 1st word as lower case */
+               while (!IsDelimiter (*rest))
+                       *cp++ = _totlower (*rest++);
+
+               /* Terminate first word */
+               *cp = _T('\0');
+
+               /* Skip over whitespace to rest of line */
+               while (_istspace (*rest))
+                       rest++;
+
+               /* Scan internal command table */
+               for (cmdptr = cmds;; cmdptr++)
+               {
+                       /* If end of table execute ext cmd */
+                       if (cmdptr->name == NULL)
+                       {
+                               Execute (com, rest);
+                               break;
+                       }
+
+                       if (!_tcscmp (com, cmdptr->name))
+                       {
+                               cmdptr->func (com, rest);
+                               break;
+                       }
+
+                       /* The following code handles the case of commands like CD which
+                        * are recognised even when the command name and parameter are
+                        * not space separated.
+                        *
+                        * e.g dir..
+                        * cd\freda
+                        */
 
-        Console_puts(Prompt);
+                       /* Get length of command name */
+                       cl = _tcslen (cmdptr->name);
 
-        ReadConsole(stdin,
-                    Output,
-                    OutputLength,
-                    &nbytes,
-                    NULL);
-        Output[nbytes-2]=0;
+                       if ((cmdptr->flags & CMD_SPECIAL) &&
+                               (!_tcsncmp (cmdptr->name, com, cl)) &&
+                               (_tcschr (_T("\\.-"), *(com + cl))))
+                       {
+                               /* OK its one of the specials...*/
+
+                               /* Terminate first word properly */
+                               com[cl] = _T('\0');
+
+                               /* Call with new rest */
+                               cmdptr->func (com, cstart + cl);
+                               break;
+                       }
+               }
+       }
 }
 
-void func_cd(char* s)
+
+/*
+ * process the command line and execute the appropriate functions
+ * full input/output redirection and piping are supported
+ */
+
+VOID ParseCommandLine (LPTSTR s)
 {
-        Console_printf("Changing directory to %s\n",s);
-        if (!SetCurrentDirectory(s))
-        {
-                Console_puts("Failed to change to directory\n");
-        }
+#ifdef FEATURE_REDIRECTION
+       TCHAR in[CMDLINE_LENGTH] = "";
+       TCHAR out[CMDLINE_LENGTH] = "";
+       TCHAR err[CMDLINE_LENGTH] = "";
+       TCHAR szTempPath[MAX_PATH] = _T(".\\");
+       TCHAR szFileName[2][MAX_PATH] = {"", ""};
+       HANDLE hFile[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
+       LPTSTR t = NULL;
+       INT  num = 0;
+       INT  nRedirFlags = 0;
+
+       HANDLE hOldConIn;
+       HANDLE hOldConOut;
+       HANDLE hOldConErr;
+#endif /* FEATURE_REDIRECTION */
+
+#ifdef _DEBUG
+       DebugPrintf ("ParseCommandLine: (\'%s\')]\n", s);
+#endif /* _DEBUG */
+
+#ifdef FEATURE_ALIASES
+       /* expand all aliases */
+       ExpandAlias (s, CMDLINE_LENGTH);
+#endif /* FEATURE_ALIAS */
+
+#ifdef FEATURE_REDIRECTION
+       /* find the temp path to store temporary files */
+       GetTempPath (MAX_PATH, szTempPath);
+       if (szTempPath[_tcslen (szTempPath) - 1] != _T('\\'))
+               _tcscat (szTempPath, _T("\\"));
+
+       /* get the redirections from the command line */
+       num = GetRedirection (s, in, out, err, &nRedirFlags);
+
+       /* more efficient, but do we really need to do this? */
+       for (t = in; _istspace (*t); t++)
+               ;
+       _tcscpy (in, t);
+
+       for (t = out; _istspace (*t); t++)
+               ;
+       _tcscpy (out, t);
+
+       for (t = err; _istspace (*t); t++)
+               ;
+       _tcscpy (err, t);
+
+       /* Set up the initial conditions ... */
+       /* preserve STDIN, STDOUT and STDERR handles */
+       hOldConIn  = GetStdHandle (STD_INPUT_HANDLE);
+       hOldConOut = GetStdHandle (STD_OUTPUT_HANDLE);
+       hOldConErr = GetStdHandle (STD_ERROR_HANDLE);
+
+       /* redirect STDIN */
+       if (in[0])
+       {
+               HANDLE hFile;
+
+               hFile = CreateFile (in, GENERIC_READ, 0, NULL, OPEN_EXISTING,
+                                                       FILE_ATTRIBUTE_NORMAL, NULL);
+               if (hFile == INVALID_HANDLE_VALUE)
+               {
+                       ConErrPrintf ("Can't redirect input from file %s\n", in);
+                       return;
+               }
+
+               if (!SetStdHandle (STD_INPUT_HANDLE, hFile))
+               {
+                       ConErrPrintf ("Can't redirect input from file %s\n", in);
+                       return;
+               }
+#ifdef _DEBUG
+               DebugPrintf (_T("Input redirected from: %s\n"), in);
+#endif
+       }
+
+       /* Now do all but the last pipe command */
+       *szFileName[0] = '\0';
+       hFile[0] = INVALID_HANDLE_VALUE;
+
+       while (num-- > 1)
+       {
+               /* Create unique temporary file name */
+               GetTempFileName (szTempPath, "CMD", 0, szFileName[1]);
+
+               /* Set current stdout to temporary file */
+               hFile[1] = CreateFile (szFileName[1], GENERIC_WRITE, 0, NULL,
+                                                          TRUNCATE_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL);
+               SetStdHandle (STD_OUTPUT_HANDLE, hFile[1]);
+
+               DoCommand (s);
+
+               /* close stdout file */
+               SetStdHandle (STD_OUTPUT_HANDLE, hOldConOut);
+               if ((hFile[1] != INVALID_HANDLE_VALUE) && (hFile[1] != hOldConOut))
+               {
+                       CloseHandle (hFile[1]);
+                       hFile[1] = INVALID_HANDLE_VALUE;
+               }
+
+               /* close old stdin file */
+               SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
+               if ((hFile[0] != INVALID_HANDLE_VALUE) && (hFile[0] != hOldConIn))
+               {
+                       /* delete old stdin file, if it is a real file */
+                       CloseHandle (hFile[0]);
+                       hFile[0] = INVALID_HANDLE_VALUE;
+                       DeleteFile (szFileName[0]);
+                       *szFileName[0] = _T('\0');
+               }
+
+               /* copy stdout file name to stdin file name */
+               _tcscpy (szFileName[0], szFileName[1]);
+               *szFileName[1] = _T('\0');
+
+               /* open new stdin file */
+               hFile[0] = CreateFile (szFileName[0], GENERIC_READ, 0, NULL,
+                                                          OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL);
+               SetStdHandle (STD_INPUT_HANDLE, hFile[0]);
+
+               s = s + _tcslen (s) + 1;
+       }
+
+       /* Now set up the end conditions... */
+       /* redirect STDOUT */
+       if (out[0])
+       {
+               /* Final output to here */
+               HANDLE hFile;
+
+               hFile = CreateFile (out, GENERIC_WRITE, 0, NULL,
+                                                       (nRedirFlags & OUTPUT_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS,
+                                                       FILE_ATTRIBUTE_NORMAL, NULL);
+               if (hFile == INVALID_HANDLE_VALUE)
+               {
+                       ConErrPrintf ("Can't redirect to file %s\n", out);
+                       return;
+               }
+
+               if (!SetStdHandle (STD_OUTPUT_HANDLE, hFile))
+               {
+                       ConErrPrintf ("Can't redirect to file %s\n", out);
+                       return;
+               }
+
+               if (nRedirFlags & OUTPUT_APPEND)
+               {
+                       LONG lHighPos = 0;
+
+                       if (GetFileType (hFile) == FILE_TYPE_DISK)
+                               SetFilePointer (hFile, 0, &lHighPos, FILE_END);
+               }
+#ifdef _DEBUG
+               DebugPrintf (_T("Output redirected to: %s\n"), out);
+#endif
+       }
+       else if (hOldConOut != INVALID_HANDLE_VALUE)
+       {
+               /* Restore original stdout */
+               HANDLE hOut = GetStdHandle (STD_OUTPUT_HANDLE);
+               SetStdHandle (STD_OUTPUT_HANDLE, hOldConOut);
+               if (hOldConOut != hOut)
+                       CloseHandle (hOut);
+               hOldConOut = INVALID_HANDLE_VALUE;
+       }
+
+       /* redirect STDERR */
+       if (err[0])
+       {
+               /* Final output to here */
+               HANDLE hFile;
+
+               if (!_tcscmp (err, out))
+               {
+#ifdef _DEBUG
+                       DebugPrintf (_T("Stdout and stderr will use the same file!!\n"));
+#endif
+                       DuplicateHandle (GetCurrentProcess (), GetStdHandle (STD_OUTPUT_HANDLE), GetCurrentProcess (),
+                                                        &hFile, 0, TRUE, DUPLICATE_SAME_ACCESS);
+               }
+               else
+               {
+                       hFile =
+                               CreateFile (err, GENERIC_WRITE, 0, NULL,
+                                                       (nRedirFlags & ERROR_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS,
+                                                       FILE_ATTRIBUTE_NORMAL, NULL);
+                       if (hFile == INVALID_HANDLE_VALUE)
+                       {
+                               ConErrPrintf ("Can't redirect to file %s\n", err);
+                               return;
+                       }
+               }
+               if (!SetStdHandle (STD_ERROR_HANDLE, hFile))
+               {
+                       ConErrPrintf ("Can't redirect to file %s\n", err);
+                       return;
+               }
+
+               if (nRedirFlags & ERROR_APPEND)
+               {
+                       LONG lHighPos = 0;
+
+                       if (GetFileType (hFile) == FILE_TYPE_DISK)
+                               SetFilePointer (hFile, 0, &lHighPos, FILE_END);
+               }
+#ifdef _DEBUG
+               DebugPrintf (_T("Error redirected to: %s\n"), err);
+#endif
+       }
+       else if (hOldConErr != INVALID_HANDLE_VALUE)
+       {
+               /* Restore original stderr */
+               HANDLE hErr = GetStdHandle (STD_ERROR_HANDLE);
+               SetStdHandle (STD_ERROR_HANDLE, hOldConErr);
+               if (hOldConErr != hErr)
+                       CloseHandle (hErr);
+               hOldConErr = INVALID_HANDLE_VALUE;
+       }
+#endif
+
+       /* process final command */
+       DoCommand (s);
+
+#ifdef FEATURE_REDIRECTION
+       /* close old stdin file */
+#if 0  /* buggy implementation */
+       SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
+       if ((hFile[0] != INVALID_HANDLE_VALUE) && 
+               (hFile[0] != hOldConIn))
+       {
+               /* delete old stdin file, if it is a real file */
+               CloseHandle (hFile[0]);
+               hFile[0] = INVALID_HANDLE_VALUE;
+               DeleteFile (szFileName[0]);
+               *szFileName[0] = _T('\0');
+       }
+
+       /* Restore original STDIN */
+       if (hOldConIn != INVALID_HANDLE_VALUE)
+       {
+               HANDLE hIn = GetStdHandle (STD_INPUT_HANDLE);
+               SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
+               if (hOldConIn != hIn)
+                       CloseHandle (hIn);
+               hOldConIn = INVALID_HANDLE_VALUE;
+       }
+       else
+       {
+#ifdef _DEBUG
+               DebugPrintf (_T("Can't restore STDIN! Is invalid!!\n"), out);
+#endif
+       }
+#endif  /* buggy implementation */
+
+
+       if (hOldConIn != INVALID_HANDLE_VALUE)
+       {
+               HANDLE hIn = GetStdHandle (STD_INPUT_HANDLE);
+               SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
+               if (hIn == INVALID_HANDLE_VALUE)
+               {
+#ifdef _DEBUG
+                       DebugPrintf (_T("Previous STDIN is invalid!!\n"));
+#endif
+               }
+               else
+               {
+                       if (GetFileType (hIn) == FILE_TYPE_DISK)
+                       {
+                               if (hFile[0] == hIn)
+                               {
+                                       CloseHandle (hFile[0]);
+                                       hFile[0] = INVALID_HANDLE_VALUE;
+                                       DeleteFile (szFileName[0]);
+                                       *szFileName[0] = _T('\0');
+                               }
+                               else
+                               {
+#ifdef _DEBUG
+                                       DebugPrintf (_T("hFile[0] and hIn dont match!!!\n"));
+#endif
+
+                               }
+                       }
+               }
+       }
+
+
+       /* Restore original STDOUT */
+       if (hOldConOut != INVALID_HANDLE_VALUE)
+       {
+               HANDLE hOut = GetStdHandle (STD_OUTPUT_HANDLE);
+               SetStdHandle (STD_OUTPUT_HANDLE, hOldConOut);
+               if (hOldConOut != hOut)
+                       CloseHandle (hOut);
+               hOldConOut = INVALID_HANDLE_VALUE;
+       }
+
+       /* Restore original STDERR */
+       if (hOldConErr != INVALID_HANDLE_VALUE)
+       {
+               HANDLE hErr = GetStdHandle (STD_ERROR_HANDLE);
+               SetStdHandle (STD_ERROR_HANDLE, hOldConErr);
+               if (hOldConErr != hErr)
+                       CloseHandle (hErr);
+               hOldConErr = INVALID_HANDLE_VALUE;
+       }
+#endif /* FEATURE_REDIRECTION */
 }
 
-void func_dir(char* s)
+
+/*
+ * do the prompt/input/process loop
+ *
+ */
+
+static INT 
+ProcessInput (BOOL bFlag)
 {
-        HANDLE shandle;
-        WIN32_FIND_DATA FindData;
-
-        shandle = FindFirstFile("*.*",&FindData);
-
-        if (shandle==INVALID_HANDLE_VALUE)
-        {
-                return;
-        }
-        do
-        {
-                Console_printf("Scanning %s\n",FindData.cFileName);
-        } while(FindNextFile(shandle,&FindData));
+       TCHAR commandline[CMDLINE_LENGTH];
+       TCHAR readline[CMDLINE_LENGTH];
+       LPTSTR tp;
+       LPTSTR ip;
+       LPTSTR cp;
+
+       /* JPP 19980807 - changed name so not to conflict with echo global */
+       BOOL bEchoThisLine;
+
+       do
+       {
+               /* if no batch input then... */
+               if (!(ip = ReadBatchLine (&bEchoThisLine)))
+               {
+                       if (bFlag)
+                               return 0;
+
+                       ReadCommand (readline, CMDLINE_LENGTH);
+                       ip = readline;
+                       bEchoThisLine = FALSE;
+               }
+
+               cp = commandline;
+               while (*ip)
+               {
+                       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 += wsprintf (cp, _T("%u"), errorlevel);
+                                               ip++;
+                                               break;
+
+                                       default:
+                                               if (tp = _tcschr (ip, _T('%')))
+                                               {
+                                                       char evar[512];
+                                                       *tp = _T('\0');
+
+                                                       /* FIXME: This is just a quick hack!! */
+                                                       /* Do a proper memory allocation!! */
+                                                       if (GetEnvironmentVariable (ip, evar, 512))
+                                                               cp = stpcpy (cp, evar);
+
+                                                       ip = tp + 1;
+                                               }
+                                               break;
+                               }
+                               continue;
+                       }
+
+                       if (_istcntrl (*ip))
+                               *ip = _T(' ');
+                       *cp++ = *ip++;
+               }
+
+               *cp = _T('\0');
+
+               /* strip trailing spaces */
+               while ((--cp >= commandline) && _istspace (*cp))
+                       ;
+
+               *(cp + 1) = _T('\0');
+
+               /* JPP 19980807 */
+               /* Echo batch file line */
+               if (bEchoThisLine)
+               {
+                       PrintPrompt ();
+                       ConOutPuts (commandline);
+               }
+
+               if (*commandline)
+               {
+                       ParseCommandLine (commandline);
+                       if (bEcho && !bIgnoreEcho)
+                               ConOutChar ('\n');
+                       bIgnoreEcho = FALSE;
+               }
+       }
+       while (!bCanExit || !bExit);
+
+       return 0;
 }
 
-int is_builtin(char* name, char* args)
+
+/*
+ * control-break handler.
+ */
+BOOL BreakHandler (DWORD dwCtrlType)
 {
-        if (strcmp(name,"dir")==0)
-        {
-                func_dir(args);
-                return(1);
-        }
-        if (strcmp(name,"cd")==0)
-        {
-                func_cd(args);
-                return(1);
-        }
-        return(0);
+       if ((dwCtrlType == CTRL_C_EVENT) ||
+               (dwCtrlType == CTRL_BREAK_EVENT))
+       {
+               bCtrlBreak = TRUE; /* indicate the break condition */
+               return TRUE;
+       }
+       return FALSE;
 }
 
-int process_command(char* str)
+
+/*
+ * show commands and options that are available.
+ *
+ */
+static VOID
+ShowCommands (VOID)
 {
-        char* name;
-        char* args;
-        PROCESS_INFORMATION pi;
-        STARTUPINFO si;
-        char process_arg[255];
-
-        if (strcmp(str,"exit")==0)
-        {
-                return(1);
-        }
-
-        name = strtok(str," \t");
-        args = strtok(NULL,"");
-
-        if (is_builtin(name,args))
-        {
-                return(0);
-        }
-        memset(&si,0,sizeof(STARTUPINFO));
-        si.cb=sizeof(STARTUPINFO);
-        si.lpTitle=strdup(name);
-
-        strcpy(process_arg,name);
-        strcat(process_arg," ");
-        if(args!=NULL)
-        {
-                strcat(process_arg,args);
-        }
-        Console_printf("name '%s' process_arg '%s'\n",name,process_arg);
-        if (!CreateProcess(NULL,process_arg,NULL,NULL,FALSE,
-                     CREATE_NEW_CONSOLE,
-                      NULL,NULL,&si,&pi))
-                      {
-                        Console_printf("Failed to execute process\n");
-                      }
-        return(0);
+       LPCOMMAND cmdptr;
+       INT y;
+
+       ConOutPrintf (_T("\nInternal commands available:\n"));
+       y = 0;
+       cmdptr = cmds;
+       while (cmdptr->name)
+       {
+               if (++y == 8)
+               {
+                       ConOutPuts (cmdptr->name);
+                       y = 0;
+               }
+               else
+                       ConOutPrintf (_T("%-10s"), cmdptr->name);
+
+               cmdptr++;
+       }
+
+       if (y != 0)
+               ConOutChar ('\n');
+
+       /* print feature list */
+       ConOutPuts ("\nFeatures available:");
+#ifdef FEATURE_ALIASES
+       ConOutPuts ("  [aliases]");
+#endif
+#ifdef FEATURE_HISTORY
+       ConOutPuts ("  [history]");
+#endif
+#ifdef FEATURE_UNIX_FILENAME_COMPLETION
+       ConOutPuts ("  [unix filename completion]");
+#endif
+#ifdef FEATURE_DIRECTORY_STACK
+       ConOutPuts ("  [directory stack]");
+#endif
+#ifdef FEATURE_REDIRECTION
+       ConOutPuts ("  [redirections and piping]");
+#endif
+       ConOutChar ('\n');
 }
 
-void build_prompt(char* prompt)
+
+/*
+ * set up global initializations and process parameters
+ *
+ * argc - number of parameters to command.com
+ * argv - command-line parameters
+ *
+ */
+static VOID Initialize (int argc, char *argv[])
 {
-        int len;
+       INT i;
+
+       /* Added by Rob Lake 06/16/98.  This enables the command.com
+        * to run the autoexec.bat at startup */
+
+#ifdef _DEBUG
+       INT x;
+
+       DebugPrintf ("[command args:\n");
+       for (x = 0; x < argc; x++)
+       {
+               DebugPrintf ("%d. %s\n", x, argv[x]);
+       }
+       DebugPrintf ("]\n");
+#endif
+
+       /* get version information */
+       osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+       GetVersionEx (&osvi);
+
+       InitLocale ();
+
+       /* get default input and output console handles */
+       hOut = GetStdHandle (STD_OUTPUT_HANDLE);
+       hIn  = GetStdHandle (STD_INPUT_HANDLE);
+
+#ifdef INCLUDE_CMD_CHDIR
+       InitLastPath ();
+#endif
+
+       if (argc >= 2)
+       {
+               if (!_tcsncmp (argv[1], _T("/?"), 2))
+               {
+                       ConOutPuts (_T("Starts a new instance of the ReactOS command line interpreter\n\n"
+                                                  "CMD [/P][/C]...\n\n"
+                                                  "  /P  ...\n"
+                                                  "  /C  ..."));
+                       ExitProcess (0);
+               }
+               else
+               {
+                       for (i = 1; i < argc; i++)
+                       {
+                               if (!_tcsicmp (argv[i], _T("/p")))
+                               {
+                                       if (!IsValidFileName (_T("\\autoexec.bat")))
+                                       {
+#ifdef INCLUDE_CMD_DATE
+                                               cmd_date ("", "");
+#endif
+#ifdef INCLUDE_CMD_TIME
+                                               cmd_time ("", "");
+#endif
+                                       }
+                                       else
+                                               ParseCommandLine ("\\autoexec.bat");
+                                       bCanExit = FALSE;
+                               }
+                               else if (!_tcsicmp (argv[i], _T("/c")))
+                               {
+                                       /* This just runs a program and exits, RL: 06/16,21/98 */
+                                       char commandline[CMDLINE_LENGTH];
+                                       ++i;
+                                       strcpy(commandline, argv[i]);
+                                       while (argv[++i])
+                                       {
+                                               strcat(commandline, " ");
+                                               strcat(commandline, argv[i]);
+                                       }
+
+                                       ParseCommandLine(commandline);
 
-        len = GetCurrentDirectory(255,prompt);
-        strcat(prompt,">");
+                                       /* HBP_003 { Fix return value when /C used }*/
+                                       ExitProcess (ProcessInput (TRUE));
+                               }
+
+#ifdef INCLUDE_CMD_COLOR
+                               else if (!_tcsnicmp (argv[i], _T("/t:"), 3))
+                               {
+                                       /* process /t (color) argument */
+                                       wDefColor = (WORD)strtoul (&argv[i][3], NULL, 16);
+                                       wColor = wDefColor;
+                               }
+#endif
+                       }
+               }
+       }
+
+#ifdef FEATURE_DIR_STACK
+       /* initialize directory stack */
+       InitDirectoryStack ();
+#endif
+
+#ifdef INCLUDE_CMD_COLOR
+       /* set default colors */
+       SetScreenColor (wColor);
+#endif
+
+       ShortVersion ();
+       ShowCommands ();
+
+       /* Set COMSPEC environment variable */
+       SetEnvironmentVariable (_T("COMSPEC"), argv[0]);
+
+       /* add ctrl handler */
+       SetConsoleCtrlHandler (NULL, TRUE);
 }
 
-void command_loop()
+
+static VOID Cleanup (VOID)
 {
-        char line[255];
-        char prompt[255];
-        int do_exit = 0;
-
-        while (!do_exit)
-        {
-                build_prompt(prompt);
-                Console_getline(prompt,line,255);
-                Console_printf("Processing command '%s'\n",line);
-                do_exit = process_command(line);
-        }        
+
+#ifdef FEATURE_DIECTORY_STACK
+       /* destroy directory stack */
+       DestroyDirectoryStack ();
+#endif
+
+#ifdef INCLUDE_CMD_CHDIR
+       FreeLastPath ();
+#endif
+
+       /* remove ctrl handler */
+//     SetConsoleCtrlHandler ((PHANDLER_ROUTINE)&BreakHandler, FALSE);
 }
 
-int STDCALL WinMain (HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow)
+
+/*
+ * main function
+ */
+int main (int argc, char *argv[])
 {
-        AllocConsole();
-        stdin = GetStdHandle(STD_INPUT_HANDLE);
-        stdout = GetStdHandle(STD_OUTPUT_HANDLE);
+       INT nExitCode;
 
-        command_loop();
+       AllocConsole ();
+       SetFileApisToOEM ();
 
-       return 0;
+       /* check switches on command-line */
+       Initialize (argc, argv);
+
+       /* call prompt routine */
+       nExitCode = ProcessInput (FALSE);
+
+       /* do the cleanup */
+       Cleanup ();
+       FreeConsole ();
+
+       return nExitCode;
 }
diff --git a/reactos/apps/utils/cmd/cmd.h b/reactos/apps/utils/cmd/cmd.h
new file mode 100644 (file)
index 0000000..e34fffe
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ *  CMD.H - header file for the modules in CMD.EXE
+ *
+ *
+ *  History:
+ *
+ *    7-15-95 Tim Norman
+ *        started
+ *
+ *    06/29/98 (Rob Lake)
+ *        Moved error messages in here
+ *
+ *    07/12/98 (Rob Lake)
+ *        Moved more error messages here
+ *
+ *    30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        Added compile date to version
+ */
+
+// #define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+// #include <tchar.h>
+
+#define SHELLVER     "version 0.0.4 [" __DATE__"]"
+
+#define BREAK_BATCHFILE 1
+#define BREAK_OUTOFBATCH 2
+#define BREAK_INPUT 3
+#define BREAK_IGNORE 4
+
+/* define some error messages */
+#define NOENVERR        "ERROR: no environment"
+#define INVALIDDRIVE    "ERROR: invalid drive"
+#define INVALIDFUNCTION "ERROR: invalid function"
+#define ACCESSDENIED    "ERROR: access denied"
+#define BADENVIROMENT   "ERROR: bad enviroment"
+#define BADFORMAT       "ERROR: bad format"
+#define ERROR_E2BIG     "ERROR: Argument list too long"
+#define ERROR_EINVAL    "ERROR: Invalid argument"
+
+#define SHELLINFO    "ReactOS Command Line Interface"
+#define USAGE        "usage"
+
+
+#define D_ON         "on"
+#define D_OFF        "off"
+
+
+
+/* prototypes for CMD.C */
+extern HANDLE hOut;
+extern HANDLE hIn;
+extern WORD   wColor;
+extern WORD   wDefColor;
+extern BOOL   bCtrlBreak;
+extern BOOL   bIgnoreEcho;
+extern BOOL   bExit;
+extern int errorlevel;
+extern SHORT  maxx;
+extern SHORT  maxy;
+extern OSVERSIONINFO osvi;
+
+
+// VOID Execute (char *, char *);
+void command(char *);
+VOID ParseCommandLine (LPTSTR);
+int  c_brk(void);
+
+
+
+
+/* prototypes for ALIAS.C */
+VOID ExpandAlias (char *, int);
+INT cmd_alias (LPTSTR, LPTSTR);
+
+
+/* prototyped for ATTRIB.C */
+INT cmd_attrib (LPTSTR, LPTSTR);
+
+
+/* prototypes for CLS.C */
+INT cmd_cls (LPTSTR, LPTSTR);
+
+
+/* prototypes for CMDINPUT.C */
+VOID ReadCommand (LPTSTR, INT);
+
+
+/* prototypes for CMDTABLE.C */
+#define CMD_SPECIAL     1
+#define CMD_BATCHONLY   2
+
+typedef struct tagCOMMAND
+{
+       LPTSTR name;
+       INT    flags;
+       INT    (*func) (LPTSTR, LPTSTR);
+} COMMAND, *LPCOMMAND;
+
+
+/* prototypes for COLOR.C */
+VOID SetScreenColor (WORD);
+INT cmd_color (LPTSTR, LPTSTR); 
+
+
+/* prototypes for CONSOLE.C */
+#ifdef _DEBUG
+VOID DebugPrintf (LPTSTR, ...);
+#endif /* _DEBUG */
+
+VOID ConInDummy (VOID);
+VOID ConInKey (PINPUT_RECORD);
+
+VOID ConInString (LPTSTR, DWORD);
+
+
+VOID ConOutChar (TCHAR);
+VOID ConOutPuts (LPTSTR);
+VOID ConOutPrintf (LPTSTR, ...);
+VOID ConErrChar (TCHAR);
+VOID ConErrPuts (LPTSTR);
+VOID ConErrPrintf (LPTSTR, ...);
+
+
+SHORT wherex (VOID);
+SHORT wherey (VOID);
+VOID goxy (SHORT, SHORT);
+
+VOID GetScreenSize (PSHORT, PSHORT);
+VOID SetCursorType (BOOL, BOOL);
+
+
+/* prototypes for COPY.C */
+INT cmd_copy (LPTSTR, LPTSTR);
+
+
+/* prototypes for DATE.C */
+INT cmd_date (LPTSTR, LPTSTR);
+
+
+/* prototypes for DEL.C */
+INT cmd_del (LPTSTR, LPTSTR);
+
+
+/* prototypes for DIR.C */
+//int incline(int *line, unsigned flags);
+INT cmd_dir (LPTSTR, LPTSTR);
+
+
+/* prototypes for DIRSTACK.C */
+VOID InitDirectoryStack (VOID);
+VOID DestroyDirectoryStack (VOID);
+INT  GetDirectoryStackDepth (VOID);
+INT  cmd_pushd (LPTSTR, LPTSTR);
+INT  cmd_popd (LPTSTR, LPTSTR);
+
+
+/* Prototypes for ERROR.C */
+VOID ErrorMessage (DWORD, LPTSTR, ...);
+
+VOID error_no_pipe (VOID);
+VOID error_bad_command (VOID);
+VOID error_invalid_drive (VOID);
+VOID error_req_param_missing (VOID);
+VOID error_sfile_not_found (LPTSTR);
+VOID error_file_not_found (VOID);
+VOID error_path_not_found (VOID);
+VOID error_too_many_parameters (LPTSTR);
+VOID error_invalid_switch (TCHAR);
+VOID error_invalid_parameter_format (LPTSTR);
+VOID error_out_of_memory (VOID);
+VOID error_syntax (LPTSTR);
+
+VOID msg_pause (VOID);
+
+
+/* prototypes for FILECOMP.C */
+#ifdef FEATURE_UNIX_FILENAME_COMPLETION
+VOID CompleteFilename (LPTSTR, INT);
+INT  ShowCompletionMatches (LPTSTR, INT);
+#endif
+#ifdef FEATURE_4NT_FILENAME_COMPLETION
+#endif
+
+
+/* prototypes for HISTORY.C */
+#ifdef FEATURE_HISTORY
+VOID History (INT, LPTSTR);
+#endif
+
+
+/* prototypes for INTERNAL.C */
+VOID InitLastPath (VOID);
+VOID FreeLastPath (VOID);
+int cmd_chdir(char *, char *);
+int cmd_mkdir(char *, char *);
+int cmd_rmdir(char *, char *);
+int internal_exit(char *, char *);
+int cmd_rem(char *, char *);
+int cmd_showcommands(char *, char *);
+
+
+/* prototyped for LABEL.C */
+INT cmd_label (LPTSTR, LPTSTR);
+
+
+/* prototypes for LOCALE.C */
+extern TCHAR cDateSeparator;
+extern INT   nDateFormat;
+extern TCHAR cTimeSeparator;
+extern INT   nTimeFormat;
+extern TCHAR aszDayNames[7][8];
+extern TCHAR cThousandSeparator;
+extern TCHAR cDecimalSeparator;
+extern INT   nNumberGroups;
+
+VOID InitLocale (VOID);
+
+
+/* Prototypes for MISC.C */
+TCHAR  cgetchar (VOID);
+BOOL   CheckCtrlBreak (INT);
+LPTSTR *split (LPTSTR, LPINT);
+VOID   freep (LPTSTR *);
+LPTSTR stpcpy (LPTSTR, LPTSTR);
+BOOL   IsValidPathName (LPCTSTR);
+BOOL   IsValidFileName (LPCTSTR);
+BOOL   FileGetString (HANDLE, LPTSTR, INT);
+
+
+/* prototypes for MOVE.C */
+INT cmd_move (LPTSTR, LPTSTR);
+
+
+/* prototypes from PATH.C */
+INT cmd_path (LPTSTR, LPTSTR);
+
+
+/* prototypes from PROMPT.C */
+VOID PrintPrompt (VOID);
+INT  cmd_prompt (LPTSTR, LPTSTR);
+
+
+/* prototypes for REDIR.C */
+#define INPUT_REDIRECTION    1
+#define OUTPUT_REDIRECTION   2
+#define OUTPUT_APPEND        4
+#define ERROR_REDIRECTION    8
+#define ERROR_APPEND        16
+INT GetRedirection (LPTSTR, LPTSTR, LPTSTR, LPTSTR, LPINT);
+
+
+/* prototypes for REN.C */
+INT cmd_rename (LPTSTR, LPTSTR);
+
+
+/* prototypes for SET.C */
+INT cmd_set (LPTSTR, LPTSTR);
+
+
+/* prototypes for TIME.C */
+INT cmd_time (LPTSTR, LPTSTR);
+
+
+/* prototypes for TYPE.C */
+INT cmd_type (LPTSTR, LPTSTR);
+
+
+/* prototypes for VER.C */
+VOID ShortVersion (VOID);
+INT  cmd_ver (LPTSTR, LPTSTR);
+
+
+/* prototypes for VERIFY.C */
+INT cmd_verify (LPTSTR, LPTSTR);
+
+
+/* prototypes for VOL.C */
+INT cmd_vol (LPTSTR, LPTSTR);
+
+
+/* prototypes for WHERE.C */
+BOOL find_which (LPCTSTR, LPTSTR);
+
+
+
+
+/* The MSDOS Batch Commands [MS-DOS 5.0 User's Guide and Reference p359] */
+int cmd_call(char *, char *);
+int cmd_echo(char *, char *);
+int cmd_for(char *, char *);
+int cmd_goto(char *, char *);
+int cmd_if(char *, char *);
+int cmd_pause(char *, char *);
+int cmd_shift(char *, char *);
+
+int cmd_beep(char *, char *);
+
+
diff --git a/reactos/apps/utils/cmd/cmdinput.c b/reactos/apps/utils/cmd/cmdinput.c
new file mode 100644 (file)
index 0000000..6ac5302
--- /dev/null
@@ -0,0 +1,412 @@
+/*
+ *  CMDINPUT.C - handles command input (tab completion, history, etc.).
+ *
+ *
+ *  History:
+ *
+ *    01/14/95 (Tim Norman)
+ *        started.
+ *
+ *    08/08/95 (Matt Rains)
+ *        i have cleaned up the source code. changes now bring this source
+ *        into guidelines for recommended programming practice.
+ *        i have added some constants to help making changes easier.
+ *
+ *    12/12/95 (Tim Norman)
+ *        added findxy() function to get max x/y coordinates to display
+ *        correctly on larger screens
+ *
+ *    12/14/95 (Tim Norman)
+ *        fixed the Tab completion code that Matt Rains broke by moving local
+ *        variables to a more global scope and forgetting to initialize them
+ *        when needed
+ *
+ *    8/1/96 (Tim Norman)
+ *        fixed a bug in tab completion that caused filenames at the beginning
+ *        of the command-line to have their first letter truncated
+ *
+ *    9/1/96 (Tim Norman)
+ *        fixed a silly bug using printf instead of fputs, where typing "%i"
+ *        confused printf :)
+ *
+ *    6/14/97 (Steffan Kaiser)
+ *        ctrl-break checking
+ *
+ *    6/7/97 (Marc Desrochers)
+ *        recoded everything! now properly adjusts when text font is changed.
+ *        removed findxy(), reposition(), and reprint(), as these functions
+ *        were inefficient. added goxy() function as gotoxy() was buggy when
+ *        the screen font was changed. the printf() problem with %i on the
+ *        command line was fixed by doing printf("%s",str) instead of
+ *        printf(str). Don't ask how I find em just be glad I do :)
+ *
+ *    7/12/97 (Tim Norman)
+ *        Note: above changes pre-empted Steffan's ctrl-break checking.
+ *
+ *    7/7/97 (Marc Desrochers)
+ *        rewrote a new findxy() because the new dir() used it.  This
+ *        findxy() simply returns the values of *maxx *maxy.  In the
+ *        future, please use the pointers, they will always be correct
+ *        since they point to BIOS values.
+ *
+ *    7/8/97 (Marc Desrochers)
+ *        once again removed findxy(), moved the *maxx, *maxy pointers
+ *        global and included them as externs in command.h.  Also added
+ *        insert/overstrike capability
+ *
+ *    7/13/97 (Tim Norman)
+ *        added different cursor appearance for insert/overstrike mode
+ *
+ *    7/13/97 (Tim Norman)
+ *        changed my code to use _setcursortype until I can figure out why
+ *        my code is crashing on some machines.  It doesn't crash on mine :)
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    28-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        put ifdef's around filename completion code.
+ *
+ *    30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        moved filename completion code to filecomp.c
+ *        made second TAB display list of filename matches
+ *
+ *    31-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        Fixed bug where if you typed something, then hit HOME, then tried
+ *        to type something else in insert mode, it crashed.
+ *
+ *    07-Aug-1998 (John P Price <linux-guru@gcfl.net>)
+ *        Fixed carrage return output to better match MSDOS with echo
+ *        on or off.(marked with "JPP 19980708")
+ *
+ *    13-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added insert/overwrite cursor.
+ *
+ *    25-Jan-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Replaced CRT io functions by Win32 console io functions.
+ *        This can handle <Shift>-<Tab> for 4NT filename completion.
+ *        Unicode and redirection safe!
+ *
+ *    04-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Fixed input bug. A "line feed" character remined in the keyboard
+ *        input queue when you pressed <RETURN>. This sometimes caused
+ *        some very strange effects.
+ *        Fixed some command line editing annoyances.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+
+SHORT maxx;
+SHORT maxy;
+
+/*
+ * global command line insert/overwrite flag
+ */
+static BOOL bInsert = TRUE;
+
+
+static VOID
+ClearCommandLine (LPTSTR str, INT maxlen, SHORT orgx, SHORT orgy)
+{
+       INT count;
+
+       goxy (orgx, orgy);
+       for (count = 0; count < (INT)_tcslen (str); count++)
+               ConOutChar (_T(' '));
+       _tcsnset (str, _T('\0'), maxlen);
+       goxy (orgx, orgy);
+}
+
+
+/* read in a command line */
+VOID ReadCommand (LPTSTR str, INT maxlen)
+{
+       SHORT orgx;                     /* origin x/y */
+       SHORT orgy;
+       SHORT curx;
+       SHORT cury;
+       INT   count;
+       INT   current = 0;
+       INT   charcount = 0;
+       INPUT_RECORD ir;
+       WORD   wLastKey = 0;
+       TCHAR  ch;
+
+       /* get screen size */
+       GetScreenSize (&maxx, &maxy);
+
+       /* JPP 19980807 - if echo off, don't print prompt */
+       if (bEcho)
+               PrintPrompt();
+
+       orgx = wherex ();
+       orgy = wherey ();
+
+       memset (str, 0, maxlen * sizeof (TCHAR));
+
+       SetCursorType (bInsert, TRUE);
+
+       do
+       {
+               ConInKey (&ir);
+
+               switch (ir.Event.KeyEvent.wVirtualKeyCode)
+               {
+                       case VK_BACK:
+                               /* <BACKSPACE> - delete character to left of cursor */
+                               if (current > 0 && charcount > 0)
+                               {
+                                       if (current == charcount)
+                                       {
+                                               /* if at end of line */
+                                               str[current - 1] = _T('\0');
+                                               if (wherex () != 0)
+                                               {
+                                                       ConOutPrintf ("\b \b");
+                                               }
+                                               else
+                                               {
+                                                       goxy ((SHORT)(maxx - 1), (SHORT)(wherey () - 1));
+                                                       ConOutChar (_T(' '));
+                                                       goxy ((SHORT)(maxx - 1), (SHORT)(wherey () - 1));
+                                               }
+                                       }
+                                       else
+                                       {
+                                               for (count = current - 1; count < charcount; count++)
+                                                       str[count] = str[count + 1];
+                                               if (wherex () != 0)
+                                                       goxy ((SHORT)(wherex () - 1), wherey ());
+                                               else
+                                                       goxy ((SHORT)(maxx - 1), (SHORT)(wherey () - 1));
+                                               curx = wherex ();
+                                               cury = wherey ();
+                                               ConOutPrintf (_T("%s "), &str[current - 1]);
+                                               goxy (curx, cury);
+                                       }
+                                       charcount--;
+                                       current--;
+                               }
+                               break;
+
+                       case VK_INSERT:
+                               /* toggle insert/overstrike mode */
+                               bInsert ^= TRUE;
+                               SetCursorType (bInsert, TRUE);
+                               break;
+
+                       case VK_DELETE:
+                               /* delete character under cursor */
+                               if (current != charcount && charcount > 0)
+                               {
+                                       for (count = current; count < charcount; count++)
+                                               str[count] = str[count + 1];
+                                       charcount--;
+                                       curx = wherex ();
+                                       cury = wherey ();
+                                       ConOutPrintf (_T("%s "), &str[current]);
+                                       goxy (curx, cury);
+                               }
+                               break;
+
+                       case VK_HOME:
+                               /* goto beginning of string */
+                               if (current != 0)
+                               {
+                                       goxy (orgx, orgy);
+                                       current = 0;
+                               }
+                               break;
+
+                       case VK_END:
+                               /* goto end of string */
+                               if (current != charcount)
+                               {
+                                       goxy (orgx, orgy);
+                                       ConOutPrintf (_T("%s"), str);
+                                       current = charcount;
+                               }
+                               break;
+
+                       case VK_TAB:
+#ifdef FEATURE_UNIX_FILENAME_COMPLETION
+                               /* expand current file name */
+                               if (current == charcount) // only works at end of line
+                               {
+                                       if (wLastKey != VK_TAB)
+                                       {
+                                               // if first TAB, complete filename
+                                               CompleteFilename (str, charcount);
+                                               charcount = _tcslen (str);
+                                               current = charcount;
+
+                                               goxy(orgx, orgy);
+                                               ConOutPrintf (_T("%s"), str);
+                                               if ((_tcslen (str) > (USHORT)(maxx - orgx)) && (orgy == maxy + 1))
+                                                       orgy--;
+                                       }
+                                       else
+                                       {
+                                               //if second TAB, list matches
+                                               if (ShowCompletionMatches (str, charcount))
+                                               {
+                                                       PrintPrompt ();
+                                                       orgx = wherex ();
+                                                       orgy = wherey ();
+                                                       ConOutPrintf (_T("%s"), str);
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       MessageBeep (-1);
+                               }
+#endif
+#ifdef FEATURE_4NT_FILENAME_COMPLETION
+                               /* this is not implemented yet */
+                               if (ir.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED)
+                               {
+                                       /* get previous match */
+
+                               }
+                               else
+                               {
+                                       /* get next match */
+
+                               }
+#endif
+                               break;
+
+                       case VK_RETURN:
+                               /* end input, return to main */
+#ifdef FEATURE_HISTORY
+                               /* add to the history */
+                               if (str[0])
+                                       History (0, str);
+#endif
+                               ConInDummy ();
+                               ConOutChar (_T('\n'));
+                               break;
+
+                       case VK_ESCAPE:
+                               /* clear str  Make this callable! */
+                               ClearCommandLine (str, maxlen, orgx, orgy);
+                               current = charcount = 0;
+                               break;
+
+                       case VK_UP:
+#ifdef FEATURE_HISTORY
+                               /* get previous command from buffer */
+                               ClearCommandLine (str, maxlen, orgx, orgy);
+                               History (-1, str);
+                               current = charcount = _tcslen (str);
+                               ConOutPrintf (_T("%s"), str);
+#endif
+                               break;
+
+                       case VK_DOWN:
+#ifdef FEATURE_HISTORY
+                               /* get next command from buffer */
+                               ClearCommandLine (str, maxlen, orgx, orgy);
+                               History (1, str);
+                               current = charcount = _tcslen (str);
+                               ConOutPrintf (_T("%s"), str);
+#endif
+                               break;
+
+                       case VK_LEFT:
+                               /* move cursor left */
+                               if (current > 0)
+                               {
+                                       current--;
+                                       if (wherex () == 0)
+                                               goxy ((SHORT)(maxx - 1), (SHORT)(wherey () - 1));
+                                       else
+                                               goxy ((SHORT)(wherex () - 1), wherey ());
+                               }
+                               else
+                               {
+//                                     Beep (440, 100);
+                                       MessageBeep (-1);
+                               }
+                               break;
+
+                       case VK_RIGHT:
+                               /* move cursor right */
+                               if (current != charcount)
+                               {
+                                       current++;
+                                       if (wherex () == maxx - 1)
+                                               goxy (0, (SHORT)(wherey () + 1));
+                                       else
+                                               goxy ((SHORT)(wherex () + 1), wherey ());
+                               }
+                               break;
+
+                       default:
+#ifdef _UNICODE
+                               ch = ir.Event.KeyEvent.uChar.UnicodeChar;
+#else
+                               ch = ir.Event.KeyEvent.uChar.AsciiChar;
+#endif
+                               if ((ch >= 32 && ch <= 255) && (charcount != (maxlen - 2)))
+                               {
+                                       /* insert character into string... */
+                                       if (bInsert && current != charcount)
+                                       {
+                                               for (count = charcount; count > current; count--)
+                                                       str[count] = str[count - 1];
+                                               str[current++] = ch;
+                                               if (wherex () == maxx - 1)
+                                               {
+                                                       curx = 0;
+                                                       cury = wherey () + 1;
+                                               }
+                                               else
+                                               {
+                                                       curx = wherex () + 1;
+                                                       cury = wherey ();
+                                               }
+                                               ConOutPrintf (_T("%s"), &str[current - 1]);
+                                               if ((_tcslen (str) > (USHORT)(maxx - orgx)) && (orgy == maxy + 1))
+                                                       cury--;
+                                               goxy (curx, cury);
+                                               charcount++;
+                                       }
+                                       else
+                                       {
+                                               if (current == charcount)
+                                                       charcount++;
+                                               str[current++] = ch;
+                                               ConOutChar (ch);
+                                       }
+                                       if ((_tcslen (str) > (USHORT)(maxx - orgx)) && (orgy == maxy + 1))
+                                               orgy--;
+                               }
+#if 0
+                               else
+                               {
+//                                     Beep (440, 100);
+                                       MessageBeep (-1);
+                               }
+#endif
+                               break;
+
+               }
+               wLastKey = ir.Event.KeyEvent.wVirtualKeyCode;
+       }
+       while (ir.Event.KeyEvent.wVirtualKeyCode != VK_RETURN);
+
+       SetCursorType (bInsert, TRUE);
+}
diff --git a/reactos/apps/utils/cmd/cmdtable.c b/reactos/apps/utils/cmd/cmdtable.c
new file mode 100644 (file)
index 0000000..f2d8339
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ *  CMDTABLE.C - table of internal commands.
+ *
+ *
+ *  History:
+ *
+ *    16 Jul 1998 (Hans B Pufal)
+ *        started.
+ *        New file to keep the internal command table. I plan on
+ *        getting rid of the table real soon now and replacing it
+ *        with a dynamic mechnism.
+ *
+ *    27 Jul 1998  John P. Price
+ *        added config.h include
+ *
+ *    21-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+
+#include "cmd.h"
+
+#include "chcp.h"
+
+
+/* a list of all the internal commands, associating their command names */
+/* to the functions to process them                                     */
+
+/* Lines marked
+ *
+ * $$ are external commands
+ * !! internal commands which are not yet implemented
+ * ** special FREEDOS specific implementation
+ */
+
+COMMAND cmds[] =
+{
+       {_T("?"),        0, cmd_showcommands},
+
+#ifdef FEATURE_ALIASES
+       {_T("alias"),    0, cmd_alias},
+#endif
+
+#ifdef INCLUDE_CMD_ATTRIB
+       {_T("attrib"),   0, cmd_attrib},
+#endif
+
+#ifdef INCLUDE_CMD_BEEP
+       {_T("beep"),     0, cmd_beep},
+#endif
+
+/*
+       {_T("break"),    0, cmd_break},
+*/
+
+       {_T("call"), CMD_BATCHONLY, cmd_call},
+
+#ifdef INCLUDE_CMD_CHDIR
+       {_T("cd"), CMD_SPECIAL, cmd_chdir},
+       {_T("chdir"), CMD_SPECIAL, cmd_chdir},
+#endif
+
+#ifdef INCLUDE_CMD_CHCP
+       {_T("chcp"),     0, CommandChcp},
+#endif
+
+#ifdef INCLUDE_CMD_CLS
+       {_T("cls"),      0, cmd_cls},
+#endif
+
+#ifdef INCLUDE_CMD_COLOR
+       {_T("color"),    0, cmd_color},
+#endif
+
+#ifdef INCLUDE_CMD_COPY
+       {_T("copy"),     0, cmd_copy},
+#endif
+
+/*
+#define INCLUDE_CMD_CTTY
+       {_T("ctty"),     0, cmd_ctty},
+#endif
+*/
+
+#ifdef INCLUDE_CMD_DATE
+       {_T("date"),     0, cmd_date},
+#endif
+
+#ifdef INCLUDE_CMD_DEL
+       {_T("del"),      0, cmd_del},
+       {_T("delete"),   0, cmd_del},
+#endif
+
+#ifdef INCLUDE_CMD_DIR
+       {_T("dir"), CMD_SPECIAL, cmd_dir},
+#endif
+
+       {_T("echo"),     0, cmd_echo},
+
+#ifdef INCLUDE_CMD_DEL
+       {_T("erase"),    0, cmd_del},
+#endif
+
+       {_T("exit"), 0, internal_exit},
+
+       {_T("for"), 0, cmd_for},
+
+       {_T("goto"), CMD_BATCHONLY, cmd_goto},
+
+       {_T("if"), 0, cmd_if},
+
+#ifdef INCLUDE_CMD_LABEL
+       {_T("label"), 0, cmd_label},
+#endif
+
+#ifdef INCLUDE_CMD_MKDIR
+       {_T("md"), CMD_SPECIAL, cmd_mkdir},
+       {_T("mkdir"), CMD_SPECIAL, cmd_mkdir},
+#endif
+
+#ifdef INCLUDE_CMD_MOVE
+       {_T("move"),     0, cmd_move},
+#endif
+
+#ifdef INCLUDE_CMD_PATH
+       {_T("path"), 0, cmd_path},
+#endif
+
+#ifdef INCLUDE_CMD_PAUSE
+       {_T("pause"), 0, cmd_pause},
+#endif
+
+#ifdef FEATURE_DIRECTORY_STACK
+       {_T("popd"),   0, cmd_popd},
+#endif
+
+#ifdef INCLUDE_CMD_PROMPT
+       {_T("prompt"), 0, cmd_prompt},
+#endif
+
+#ifdef FEATURE_DIRECTORY_STACK
+       {_T("pushd"),  0, cmd_pushd},
+#endif
+
+#ifdef INCLUDE_CMD_RMDIR
+       {_T("rd"), CMD_SPECIAL, cmd_rmdir},
+#endif
+
+#ifdef INCLUDE_CMD_REM
+       {_T("rem"), 0, cmd_rem},
+#endif
+
+#ifdef INCLUDE_CMD_RENAME
+       {_T("ren"), 0, cmd_rename},
+       {_T("rename"), 0, cmd_rename},
+#endif
+
+#ifdef INCLUDE_CMD_RMDIR
+       {_T("rmdir"), CMD_SPECIAL, cmd_rmdir},
+#endif
+
+#ifdef INCLUDE_CMD_SET
+       {_T("set"), 0, cmd_set},
+#endif
+
+       {_T("shift"), CMD_BATCHONLY, cmd_shift},
+
+#ifdef INCLUDE_CMD_TIME
+       {_T("time"), 0, cmd_time},
+#endif
+
+#ifdef INCLUDE_CMD_TYPE
+       {_T("type"), 0, cmd_type},
+#endif
+
+#ifdef INCLUDE_CMD_VER
+       {_T("ver"), 0, cmd_ver},
+#endif
+
+#ifdef INCLUDE_CMD_VERIFY
+       {_T("verify"), 0, cmd_verify},
+#endif
+
+#ifdef INCLUDE_CMD_VOL
+       {_T("vol"), 0, cmd_vol},
+#endif
+
+       {NULL, 0, NULL}
+};
+
+/*    append,                             $$    */
+/*    assign,                             $$    */
+/*    attrib,                             **    */
+/*    backup,                             $$    */
+/*    chkdsk,                             $$    */
+/*    comp,                               $$    */
+/*    debug,                              $$    */
+/*    diskcomp,                           $$    */
+/*    diskcopy,                           $$    */
+/*    doskey,                             **    */
+/*    dosshell,                           $$    */
+/*    edit,                               $$    */
+/*    edlin,                              $$    */
+/*    emm386,                             $$    */
+/*    exe2bin,                            $$    */
+/*    expand,                             $$    */
+/*    fastopen,                           $$    */
+/*    fc,                                 $$    */
+/*    fdisk,                              $$    */
+/*    find,                               $$    */
+/*    format,                             $$    */
+/*    graftabl,                           $$    */
+/*    graphics,                           $$    */
+/*    help,                               $$    */
+/*    join,                               $$    */
+/*    keyb,                               $$    */
+/*    mem,                                $$    */
+/*    mirror,                             $$    */
+/*    mode,                               $$    */
+/*    more,                               $$    */
+/*    nlsfunc,                            $$    */
+/*    print,                              $$    */
+/*    qbasic,                             $$    */
+/*    recover,                            $$    */
+/*    replace,                            $$    */
+/*    restore,                            $$    */
+/*    setver,                             $$    */
+/*    share,                              $$    */
+/*    sort,                               $$    */
+/*    subst,                              $$    */
+/*    sys,                                $$    */
+/*    tree,                               $$    */
+/*    undelete,                           $$    */
+/*    unformat,                           $$    */
+/*    xcopy,                              $$    */
diff --git a/reactos/apps/utils/cmd/color.c b/reactos/apps/utils/cmd/color.c
new file mode 100644 (file)
index 0000000..f5d0867
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ *  COLOR.C - color internal command.
+ *
+ *
+ *  History:
+ *
+ *    13-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Started.
+ *
+ *    19-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode ready!
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Redirection ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_COLOR
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+
+VOID SetScreenColor (WORD wColor)
+{
+       DWORD dwWritten;
+       CONSOLE_SCREEN_BUFFER_INFO csbi;
+       COORD coPos;
+
+       GetConsoleScreenBufferInfo (hOut, &csbi);
+
+       coPos.X = 0;
+       coPos.Y = 0;
+       FillConsoleOutputAttribute (hOut, wColor,
+                                                               (csbi.dwSize.X)*(csbi.dwSize.Y),
+                                                               coPos, &dwWritten);
+       SetConsoleTextAttribute (hOut, wColor);
+}
+
+
+/*
+ * color
+ *
+ * internal dir command
+ */
+INT cmd_color (LPTSTR first, LPTSTR rest)
+{
+       if (_tcsncmp (rest, _T("/?"), 2) == 0)
+       {
+               ConOutPuts (_T("Sets the default foreground and background colors.\n\n"
+                                  "COLOR [attr]\n\n"
+                                  "  attr        Specifies color attribute of console output\n\n"
+                                  "Color attributes are specified by TWO hex digits -- the first\n"
+                                  "corresponds to the background; the second to the foreground. Each digit\n"
+                                  "can be one of the following:\n"));
+
+               ConOutPuts (_T("    0 = Black       8 = Gray\n"
+                                  "    1 = Blue        9 = Light Blue\n"
+                                  "    2 = Green       A = Light Green\n"
+                                  "    3 = Aqua        B = Light Aqua\n"
+                                  "    4 = Red         C = Light Red\n"
+                                  "    5 = Purple      D = Light Purple\n"
+                                  "    6 = Yellow      E = Light Yellow\n"
+                                  "    7 = White       F = Bright White\n"));
+               return 0;
+       }
+
+       if (rest[0] == _T('\0'))
+       {
+               /* set default color */
+               wColor = wDefColor;
+               SetScreenColor (wColor);
+               return 0;
+       }
+
+       if (_tcslen (rest) != 2)
+       {
+               ConErrPuts (_T("parameter error!"));
+               return 1;
+       }
+
+       wColor = (WORD)_tcstoul (rest, NULL, 16);
+
+       if ((wColor & 0xF) == (wColor &0xF0) >> 4)
+       {
+               ConErrPuts (_T("same colors error!"));
+               return 1;
+       }
+
+       /* set color */
+       SetScreenColor (wColor);
+
+       return 0;
+}
+
+#endif
diff --git a/reactos/apps/utils/cmd/config.h b/reactos/apps/utils/cmd/config.h
new file mode 100644 (file)
index 0000000..1e214e2
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ *  CONFIG.H - Used to configure what will be compiled into the shell.
+ *
+ *
+ *  History:
+ *
+ *    27 Jul 1998 - John P. Price
+ *        started.
+ *
+ */
+
+
+/* JPP 20 Jul 1998 - define DEBUG to add debugging code */
+/*#define DEBUG */
+
+
+/* Define to enable the alias command, and aliases.*/
+#define FEATURE_ALIASES
+
+
+/* Define to enable history */
+#define FEATURE_HISTORY
+
+
+/* Define one of these to enable filename completion */
+#define FEATURE_UNIX_FILENAME_COMPLETION
+/* #define FEATURE_4NT_FILENAME_COMPLETION */
+
+
+/* Define to enable the directory stack */
+#define FEATURE_DIRECTORY_STACK
+
+
+/* Define to activate redirections and piping */
+#define FEATURE_REDIRECTION
+
+
+/* Define one of these to select the used locale. */
+/*  (date and time formats etc.) used in DATE, TIME */
+/*  DIR and PROMPT. */
+#define LOCALE_WINDOWS      /* System locale */
+/* #define LOCALE_GERMAN */    /* German locale */
+/* #define LOCALE_DEFAULT */   /* United States locale */
+
+
+#define INCLUDE_CMD_ATTRIB
+//#define INCLUDE_CMD_BREAK
+#define INCLUDE_CMD_CHCP
+#define INCLUDE_CMD_CHDIR
+#define INCLUDE_CMD_CLS
+#define INCLUDE_CMD_COLOR
+#define INCLUDE_CMD_COPY
+//#define INCLUDE_CMD_CTTY
+#define INCLUDE_CMD_DATE
+#define INCLUDE_CMD_DEL
+#define INCLUDE_CMD_DIR
+#define INCLUDE_CMD_LABEL
+#define INCLUDE_CMD_MKDIR
+#define INCLUDE_CMD_MOVE
+#define INCLUDE_CMD_PATH
+#define INCLUDE_CMD_PROMPT
+#define INCLUDE_CMD_RMDIR
+#define INCLUDE_CMD_RENAME
+#define INCLUDE_CMD_SET
+#define INCLUDE_CMD_TIME
+#define INCLUDE_CMD_TYPE
+#define INCLUDE_CMD_VER
+#define INCLUDE_CMD_REM
+#define INCLUDE_CMD_PAUSE
+#define INCLUDE_CMD_BEEP
+#define INCLUDE_CMD_VERIFY
+#define INCLUDE_CMD_VOL
+
+/*
+command that do not have a define:
+
+exit
+call
+echo
+goto
+for
+if
+shift
+
+*/
+
diff --git a/reactos/apps/utils/cmd/console.c b/reactos/apps/utils/cmd/console.c
new file mode 100644 (file)
index 0000000..c740f2a
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ *  CONSOLE.C - console input/output functions.
+ *
+ *
+ *  History:
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        started
+ */
+
+
+
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+#include <tchar.h>
+
+#include "cmd.h"
+
+
+
+/* internal variables for paged output */
+SHORT sLineCount;
+SHORT sMaxLines;
+BOOL  bPageable;
+
+
+
+#ifdef _DEBUG
+VOID DebugPrintf (LPTSTR szFormat, ...)
+{
+       TCHAR szOut[512];
+       va_list arg_ptr;
+
+       va_start (arg_ptr, szFormat);
+       wvsprintf (szOut, szFormat, arg_ptr);
+       va_end (arg_ptr);
+
+       OutputDebugString (szOut);
+}
+#endif /* _DEBUG */
+
+
+VOID ConInDummy (VOID)
+{
+       HANDLE hInput = GetStdHandle (STD_INPUT_HANDLE);
+       INPUT_RECORD dummy;
+       DWORD  dwRead;
+
+#ifdef _DEBUG
+       if (hInput == INVALID_HANDLE_VALUE)
+               DebugPrintf ("Invalid input handle!!!\n");
+#endif
+
+       ReadConsoleInput (hInput, &dummy, 1, &dwRead);
+}
+
+
+VOID ConInKey (PINPUT_RECORD lpBuffer)
+{
+       HANDLE hInput = GetStdHandle (STD_INPUT_HANDLE);
+       DWORD  dwRead;
+
+#ifdef _DEBUG
+       if (hInput == INVALID_HANDLE_VALUE)
+               DebugPrintf ("Invalid input handle!!!\n");
+#endif
+
+       do
+       {
+               WaitForSingleObject (hInput, INFINITE);
+               ReadConsoleInput (hInput, lpBuffer, 1, &dwRead);
+               if ((lpBuffer->EventType == KEY_EVENT) &&
+                       (lpBuffer->Event.KeyEvent.bKeyDown == TRUE))
+                       break;
+       }
+       while (TRUE);
+}
+
+
+
+VOID ConInString (LPTSTR lpInput, DWORD dwLength)
+{
+       DWORD dwOldMode;
+       DWORD dwRead;
+       HANDLE hFile;
+
+       LPTSTR p;
+       DWORD  i;
+
+       ZeroMemory (lpInput, dwLength * sizeof(TCHAR));
+       hFile = GetStdHandle (STD_INPUT_HANDLE);
+       GetConsoleMode (hFile, &dwOldMode);
+
+       SetConsoleMode (hFile, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT);
+
+       ReadFile (hFile, lpInput, dwLength, &dwRead, NULL);
+
+       p = lpInput;
+       for (i = 0; i < dwRead; i++, p++)
+       {
+               if (*p == _T('\x0d'))
+               {
+                       *p = _T('\0');
+                       break;
+               }
+       }
+
+       SetConsoleMode (hFile, dwOldMode);
+}
+
+
+VOID ConOutChar (TCHAR c)
+{
+       DWORD dwWritten;
+
+       WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), &c, 1, &dwWritten, NULL);
+}
+
+
+VOID ConOutPuts (LPTSTR szText)
+{
+       DWORD dwWritten;
+
+       WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), szText, _tcslen(szText), &dwWritten, NULL);
+       WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), "\x0a\x0d", 2, &dwWritten, NULL);
+}
+
+
+VOID ConOutPrintf (LPTSTR szFormat, ...)
+{
+       DWORD dwWritten;
+       TCHAR szOut[256];
+       va_list arg_ptr;
+
+       va_start (arg_ptr, szFormat);
+       wvsprintf (szOut, szFormat, arg_ptr);
+       va_end (arg_ptr);
+
+       WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), szOut, _tcslen(szOut), &dwWritten, NULL);
+}
+
+
+VOID ConErrChar (TCHAR c)
+{
+       DWORD dwWritten;
+
+       WriteFile (GetStdHandle (STD_ERROR_HANDLE), &c, 1, &dwWritten, NULL);
+}
+
+
+VOID ConErrPuts (LPTSTR szText)
+{
+       DWORD dwWritten;
+
+       WriteFile (GetStdHandle (STD_ERROR_HANDLE), szText, _tcslen(szText), &dwWritten, NULL);
+       WriteFile (GetStdHandle (STD_ERROR_HANDLE), "\x0a\x0d", 2, &dwWritten, NULL);
+}
+
+
+VOID ConErrPrintf (LPTSTR szFormat, ...)
+{
+       DWORD dwWritten;
+       TCHAR szOut[4096];
+       va_list arg_ptr;
+
+       va_start (arg_ptr, szFormat);
+       wvsprintf (szOut, szFormat, arg_ptr);
+       va_end (arg_ptr);
+
+       WriteFile (GetStdHandle (STD_ERROR_HANDLE), szOut, _tcslen(szOut), &dwWritten, NULL);
+}
+
+
+
+
+/*
+ * goxy -- move the cursor on the screen.
+ */
+VOID goxy (SHORT x, SHORT y)
+{
+       COORD coPos;
+
+       coPos.X = x;
+       coPos.Y = y;
+       SetConsoleCursorPosition (GetStdHandle (STD_OUTPUT_HANDLE), coPos);
+}
+
+
+SHORT wherex (VOID)
+{
+       CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+       GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &csbi);
+
+       return csbi.dwCursorPosition.X;
+}
+
+
+SHORT wherey (VOID)
+{
+       CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+       GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &csbi);
+
+       return csbi.dwCursorPosition.Y;
+}
+
+
+VOID GetScreenSize (PSHORT maxx, PSHORT maxy)
+{
+       CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+       GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &csbi);
+
+       if (maxx)
+               *maxx = csbi.dwSize.X;
+       if (maxy)
+               *maxy = csbi.dwSize.Y;
+}
+
+
+VOID SetCursorType (BOOL bInsert, BOOL bVisible)
+{
+       CONSOLE_CURSOR_INFO cci;
+
+       cci.dwSize = bInsert ? 10 : 100;
+       cci.bVisible = bVisible;
+
+       SetConsoleCursorInfo (GetStdHandle (STD_OUTPUT_HANDLE), &cci);
+}
+
+
+
+VOID InitializePageOut (VOID)
+{
+       sLineCount = 0;
+
+       if (GetFileType (GetStdHandle (STD_OUTPUT_HANDLE)) == FILE_TYPE_CHAR)
+       {
+               bPageable = TRUE;
+               GetScreenSize (NULL, &sMaxLines);
+       }
+       else
+       {
+               bPageable = FALSE;
+       }
+}
+
+
+VOID TerminatePageOut (VOID)
+{
+
+
+}
+
+
+
+int LinePageOut (LPTSTR szLine)
+{
+       ConOutPuts (szLine);
+
+       if (bPageable)
+       {
+               sLineCount++;
+               if (sLineCount >= sMaxLines)
+               {
+                       sLineCount = 0;
+                       cmd_pause ("", "");
+               }
+       }
+       return 0;
+}
diff --git a/reactos/apps/utils/cmd/copy.c b/reactos/apps/utils/cmd/copy.c
new file mode 100644 (file)
index 0000000..16b5617
--- /dev/null
@@ -0,0 +1,733 @@
+/*
+ *  COPY.C -- copy internal command.
+ *
+ *
+ *  History:
+ *
+ *    01-Aug-98 (Rob Lake z63rrl@morgan.ucs.mun.ca)
+ *        started
+ *
+ *    13-Aug-1998 (John P. Price)
+ *        fixed memory leak problem in copy function.
+ *        fixed copy function so it would work with wildcards in the source
+ *
+ *    13-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added COPY command to CMD.
+ *
+ *    26-Jan-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Replaced CRT io functions by Win32 io functions.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_COPY
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "cmd.h"
+
+
+#define VERIFY  1               /* VERIFY Switch */
+#define BINARY  2               /* File is to be copied as BINARY */
+#define ASCII   4               /* File is to be copied as ASCII */
+#define PROMPT  8               /* Prompt before overwriting files */
+#define NPROMPT 16              /* Do not prompt before overwriting files */
+#define HELP    32              /* Help was asked for */
+#define SOURCE  128             /* File is a source */
+
+
+typedef struct tagFILES
+{
+       struct tagFILES *next;
+       TCHAR szFile[MAX_PATH];
+       DWORD dwFlag;                   /* BINARY -xor- ASCII */
+} FILES, *LPFILES;
+
+
+static BOOL DoSwitches (LPTSTR, LPDWORD);
+static BOOL AddFile (LPFILES, char *, int *, int *, unsigned *);
+static BOOL AddFiles (LPFILES, char *, int *, int *, int *, unsigned *);
+static BOOL GetDestination (LPFILES, LPFILES);
+static INT  ParseCommand (LPFILES, int, char **, LPDWORD);
+static VOID DeleteFileList (LPFILES);
+static INT  Overwrite (LPTSTR);
+
+
+
+static BOOL IsDirectory (LPTSTR fn)
+{
+       if (!IsValidFileName (fn))
+               return FALSE;
+       return (GetFileAttributes (fn) & FILE_ATTRIBUTE_DIRECTORY);
+}
+
+
+static BOOL DoSwitches (LPTSTR arg, LPDWORD lpdwFlags)
+{
+       if (!_tcsicmp (arg, _T("/-Y")))
+       {
+               *lpdwFlags |= PROMPT;
+               *lpdwFlags &= ~NPROMPT;
+               return TRUE;
+       }
+       else if (_tcslen (arg) > 2)
+       {
+               error_too_many_parameters ("");
+               return FALSE;
+       }
+
+       switch (_totupper (arg[1]))
+       {
+               case _T('V'):
+                       *lpdwFlags |= VERIFY;
+                       break;
+
+               case _T('A'):
+                       *lpdwFlags |= ASCII;
+                       *lpdwFlags &= ~BINARY;
+                       break;
+
+               case _T('B'):
+                       *lpdwFlags |= BINARY;
+                       *lpdwFlags &= ~ASCII;
+                       break;
+
+               case _T('Y'):
+                       *lpdwFlags &= ~PROMPT;
+                       *lpdwFlags |= NPROMPT;
+                       break;
+
+               default:
+                       error_invalid_switch (arg[1]);
+                       return FALSE;
+       }
+       return TRUE;
+}
+
+
+static BOOL
+AddFile (LPFILES f, char *arg, int *source, int *dest, unsigned *flags)
+{
+       if (*dest)
+       {
+               error_too_many_parameters ("");
+               return FALSE;
+       }
+       if (*source)
+       {
+               *dest = 1;
+               f->dwFlag = 0;
+       }
+       else
+       {
+               *source = 1;
+               f->dwFlag = SOURCE;
+       }
+       _tcscpy(f->szFile, arg);
+       f->dwFlag |= *flags & ASCII ? ASCII : BINARY;
+       if ((f->next = (LPFILES)malloc (sizeof (FILES))) == NULL)
+       {
+               error_out_of_memory ();
+               return FALSE;
+       }
+       f = f->next;
+       f->dwFlag = 0;
+       f->next = NULL;
+       return TRUE;
+}
+
+
+static BOOL
+AddFiles (LPFILES f, char *arg, int *source, int *dest,
+                 int *count, unsigned *flags)
+{
+       char t[128];
+       int j;
+       int k;
+
+       if (*dest)
+       {
+               error_too_many_parameters ("");
+               return FALSE;
+       }
+
+       j = 0;
+       k = 0;
+
+       while (arg[j] == _T('+'))
+               j++;
+
+       while (arg[j] != _T('\0'))
+       {
+               t[k] = arg[j++];
+               if (t[k] == '+' || arg[j] == _T('\0'))
+               {
+                       if (!k)
+                               continue;
+                       if (arg[j] == _T('\0') && t[k] != _T('+'))
+                               k++;
+                       t[k] = _T('\0');
+                       *count += 1;
+                       _tcscpy (f->szFile, t);
+                       *source = 1;
+                       if (*flags & ASCII)
+                               f->dwFlag |= *flags | SOURCE | ASCII;
+                       else
+                               f->dwFlag |= *flags | BINARY | SOURCE;
+
+                       if ((f->next = (LPFILES)malloc (sizeof (FILES))) == NULL)
+                       {
+                               error_out_of_memory ();
+                               return FALSE;
+                       }
+                       f = f->next;
+                       f->next = NULL;
+                       k = 0;
+                       f->dwFlag = 0;
+                       continue;
+               }
+               k++;
+       }
+
+       if (arg[--j] == _T('+'))
+               *source = 0;
+
+       return 1;
+}
+
+
+static BOOL GetDestination (LPFILES f, LPFILES dest)
+{
+       LPFILES p;
+       LPFILES start = f;
+
+       while (f->next != NULL)
+       {
+               p = f;
+               f = f->next;
+       }
+
+       f = p;
+
+       if ((f->dwFlag & SOURCE) == 0)
+       {
+               free (p->next);
+               p->next = NULL;
+               _tcscpy (dest->szFile, f->szFile);
+               dest->dwFlag = f->dwFlag;
+               dest->next = NULL;
+               f = start;
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+
+static INT
+ParseCommand (LPFILES f, int argc, char **arg, LPDWORD lpdwFlags)
+{
+       INT i;
+       INT dest;
+       INT source;
+       INT count;
+
+       dest = 0;
+       source = 0;
+       count = 0;
+
+       for (i = 0; i < argc; i++)
+       {
+               if (arg[i][0] == _T('/'))
+               {
+                       if (!DoSwitches (arg[i], lpdwFlags))
+                               return -1;
+               }
+               else
+               {
+                       if (!_tcscmp(arg[i], _T("+")))
+                               source = 0;
+                       else if (!_tcschr(arg[i], _T('+')) && source)
+                       {
+                               if (!AddFile(f, arg[i], &source, &dest, lpdwFlags))
+                                       return -1;
+                               f = f->next;
+                               count++;
+                       }
+                       else
+                       {
+                               if (!AddFiles(f, arg[i], &source, &dest, &count, lpdwFlags))
+                                       return -1;
+                               while (f->next != NULL)
+                                       f = f->next;
+                       }
+               }
+       }
+#ifdef _DEBUG
+       DebugPrintf ("ParseCommand: flags has %s\n",
+                                *lpdwFlags & ASCII ? "ASCII" : "BINARY");
+#endif
+       return count;
+}
+
+
+static VOID DeleteFileList (LPFILES f)
+{
+       LPFILES temp;
+
+       while (f != NULL)
+       {
+               temp = f;
+               f = f->next;
+               free (temp);
+       }
+}
+
+
+static INT
+Overwrite (LPTSTR fn)
+{
+       TCHAR inp[10];
+       LPTSTR p;
+
+       ConOutPrintf (_T("Overwrite %s (Yes/No/All)? "), fn);
+       ConInString (inp, 10);
+
+       _tcsupr (inp);
+       for (p = inp; _istspace (*p); p++)
+               ;
+
+       if (*p != _T('Y') && *p != _T('A'))
+               return 0;
+       if (*p == _T('A'))
+               return 2;
+
+       return 1;
+}
+
+
+#define BUFF_SIZE 16384         /* 16k = max buffer size */
+
+
+int copy (LPTSTR source, LPTSTR dest, int append, LPDWORD lpdwFlags)
+{
+       FILETIME srctime;
+       HANDLE hFileSrc;
+       HANDLE hFileDest;
+       LPBYTE buffer;
+       DWORD  dwAttrib;
+       DWORD  dwRead;
+       DWORD  dwWritten;
+       DWORD  i;
+       BOOL   bEof = FALSE;
+
+#ifdef _DEBUG
+       DebugPrintf ("checking mode\n");
+#endif
+
+       dwAttrib = GetFileAttributes (source);
+
+       hFileSrc = CreateFile (source, GENERIC_READ, FILE_SHARE_READ,
+                                                  NULL, OPEN_EXISTING, 0, NULL);
+       if (hFileSrc == INVALID_HANDLE_VALUE)
+       {
+               ConErrPrintf (_T("Error: Cannot open source - %s!\n"), source);
+               return 0;
+       }
+
+#ifdef _DEBUG
+       DebugPrintf (_T("getting time\n"));
+#endif
+
+       GetFileTime (hFileSrc, &srctime, NULL, NULL);
+
+#ifdef _DEBUG
+       DebugPrintf (_T("copy: flags has %s\n"),
+                                *lpdwFlags & ASCII ? "ASCII" : "BINARY");
+#endif
+
+       if (!IsValidFileName (dest))
+       {
+#ifdef _DEBUG
+               DebugPrintf (_T("opening/creating\n"));
+#endif
+               hFileDest =
+                       CreateFile (dest, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+       }
+       else if (!append)
+       {
+               if (!_tcscmp (dest, source))
+               {
+                       ConErrPrintf (_T("Error: Can't copy onto itself!\n"));
+                       CloseHandle (hFileSrc);
+                       return 0;
+               }
+
+#ifdef _DEBUG
+               DebugPrintf (_T("SetFileAttributes (%s, FILE_ATTRIBUTE_NORMAL);\n"), dest);
+#endif
+               SetFileAttributes (dest, FILE_ATTRIBUTE_NORMAL);
+
+#ifdef _DEBUG
+               DebugPrintf (_T("DeleteFile (%s);\n"), dest);
+#endif
+               DeleteFile (dest);
+
+               hFileDest =
+                       CreateFile (dest, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+       }
+       else
+       {
+               LONG lFilePosHigh = 0;
+
+               if (!_tcscmp (dest, source))
+               {
+                       CloseHandle (hFileSrc);
+                       return 0;
+               }
+
+#ifdef _DEBUG
+               DebugPrintf (_T("opening/appending\n"));
+#endif
+               hFileDest =
+                       CreateFile (dest, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+               SetFilePointer (hFileDest, 0, &lFilePosHigh,FILE_END);
+       }
+
+       if (hFileDest == INVALID_HANDLE_VALUE)
+       {
+               CloseHandle (hFileSrc);
+               error_path_not_found ();
+               return 0;
+       }
+
+       buffer = (LPBYTE)malloc (BUFF_SIZE);
+       if (buffer == NULL)
+       {
+               CloseHandle (hFileDest);
+               CloseHandle (hFileSrc);
+               error_out_of_memory ();
+               return 0;
+       }
+
+       ConOutPuts (source);
+
+       do
+       {
+               ReadFile (hFileSrc, buffer, BUFF_SIZE, &dwRead, NULL);
+               if (*lpdwFlags & ASCII)
+               {
+                       for (i = 0; i < dwRead; i++)
+                       {
+                               if (((LPTSTR)buffer)[i] == 0x1A)
+                               {
+                                       bEof = TRUE;
+                                       break;
+                               }
+                       }
+                       dwRead = i;
+               }
+
+               if (dwRead == 0)
+                       break;
+
+               WriteFile (hFileDest, buffer, dwRead, &dwWritten, NULL);
+               if (dwWritten != dwRead)
+               {
+                       ConErrPrintf (_T("Error writing destination!\n"));
+                       free (buffer);
+                       CloseHandle (hFileDest);
+                       CloseHandle (hFileSrc);
+                       return 0;
+               }
+       }
+       while (dwRead && !bEof);
+
+#ifdef _DEBUG
+       DebugPrintf (_T("setting time\n"));
+#endif
+       SetFileTime (hFileDest, &srctime, NULL, NULL);
+
+       if (*lpdwFlags & ASCII)
+       {
+               ((LPTSTR)buffer)[0] = 0x1A;
+               ((LPTSTR)buffer)[1] = _T('\0');
+#ifdef _DEBUG
+               DebugPrintf (_T("appending ^Z\n"));
+#endif
+               WriteFile (hFileDest, buffer, sizeof(TCHAR), &dwWritten, NULL);
+       }
+
+       free (buffer);
+       CloseHandle (hFileDest);
+       CloseHandle (hFileSrc);
+
+#ifdef _DEBUG
+       DebugPrintf (_T("setting mode\n"));
+#endif
+       SetFileAttributes (dest, dwAttrib);
+
+       return 1;
+}
+
+
+int setup_copy (LPFILES sources, char **p, BOOL bMultiple,
+               char *drive_d, char *dir_d, char *file_d,
+               char *ext_d, int *append, LPDWORD lpdwFlags)
+{
+       WIN32_FIND_DATA find;
+
+  char drive_s[_MAX_DRIVE],
+    dir_s[_MAX_DIR],
+    file_s[_MAX_FNAME],
+    ext_s[_MAX_EXT];
+  char from_merge[_MAX_PATH];
+
+       LPTSTR real_source;
+       LPTSTR real_dest;
+
+       INT  nCopied = 0;
+       BOOL bAll = FALSE;
+       BOOL bDone;
+       HANDLE hFind;
+
+
+       real_source = (LPTSTR)malloc (MAX_PATH);
+       real_dest = (LPTSTR)malloc (MAX_PATH);
+
+       if (!real_source || !real_dest)
+       {
+               error_out_of_memory ();
+               DeleteFileList (sources);
+               free (real_source);
+               free (real_dest);
+               freep (p);
+               return 0;
+       }
+
+       while (sources->next != NULL)
+       {
+               _splitpath (sources->szFile, drive_s, dir_s, file_s, ext_s);
+               hFind = FindFirstFile (sources->szFile, &find);
+               if (hFind == INVALID_HANDLE_VALUE)
+               {
+                       error_file_not_found();
+                       DeleteFileList (sources);
+                       freep(p);
+                       free(real_source);
+                       free(real_dest);
+                       return 0;
+               }
+
+               do
+               {
+                       if (find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+                               goto next;
+
+                       _makepath(from_merge, drive_d, dir_d, file_d, ext_d);
+                       if (from_merge[_tcslen(from_merge) - 1] == _T('\\'))
+                               from_merge[_tcslen(from_merge) - 1] = 0;
+
+                       if (IsDirectory (from_merge))
+                       {
+                               bMultiple = FALSE;
+                               _tcscat (from_merge, _T("\\"));
+                               _tcscat (from_merge, find.cFileName);
+                       }
+                       else
+                               bMultiple = TRUE;
+
+                       _tcscpy (real_dest, from_merge);
+                       _makepath (real_source, drive_s, dir_s, find.cFileName, NULL);
+
+#ifdef _DEBUG
+                       DebugPrintf (_T("copying %s -> %s (%sappending%s)\n"),
+                                                real_source, real_dest,
+                                                *append ? "" : "not ",
+                                                sources->dwFlag & ASCII ? ", ASCII" : ", BINARY");
+#endif
+
+                       if (IsValidFileName (real_dest) && !bAll)
+                       {
+                               int over = Overwrite (real_dest);
+                               if (over == 2)
+                                       bAll = TRUE;
+                               else if (over == 0)
+                                       goto next;
+                               else if (bMultiple)
+                                       bAll = TRUE;
+                       }
+                       if (copy (real_source, real_dest, *append, lpdwFlags))
+                               nCopied++;
+               next:
+                       bDone = FindNextFile (hFind, &find);
+
+                       if (bMultiple)
+                               *append = 1;
+               }
+               while (bDone);
+
+               FindClose (hFind);
+               sources = sources->next;
+
+       }
+       free (real_source);
+       free (real_dest);
+
+       return nCopied;
+}
+
+
+INT cmd_copy (LPTSTR first, LPTSTR rest)
+{
+  char **p;
+  char drive_d[_MAX_DRIVE],
+    dir_d[_MAX_DIR],
+    file_d[_MAX_FNAME],
+    ext_d[_MAX_EXT];
+
+  int argc,
+    append,
+    files,
+    copied;
+
+       LPFILES sources;
+       FILES dest;
+       LPFILES start;
+       BOOL bMultiple;
+       BOOL bWildcards;
+       BOOL bDestFound;
+       DWORD dwFlags = 0;
+
+       if (!_tcsncmp (rest, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Copies one or more files to another location.\n"
+                                          "\n"
+                                          "COPY [/V][/Y|/-Y][/A|/B] source [/A|/B]\n"
+                                          "     [+ source [/A|/B] [+ ...]] [destination [/A|/B]]\n"
+                                          "\n"
+                                          "  source       Specifies the file or files to be copied.\n"
+                                          "  /A           Indicates an ASCII text file.\n"
+                                          "  /B           Indicates a binary file.\n"
+                                          "  destination  Specifies the directory and/or filename for the new file(s).\n"
+                                          "  /V           Verifies that new files are written correctly.\n"
+                                          "  /Y           Suppresses prompting to confirm you want to overwrite an\n"
+                                          "               existing destination file.\n"
+                                          "  /-Y          Causes prompting to confirm you want to overwrite an\n"
+                                          "               existing destination file.\n"
+                                          "\n"
+                                          "The switch /Y may be present in the COPYCMD environment variable.\n"
+                                          "..."));
+               return 1;
+       }
+
+       p = split (rest, &argc);
+
+       if (argc == 0)
+       {
+               error_req_param_missing ();
+               return 0;
+       }
+
+       sources = (LPFILES)malloc (sizeof (FILES));
+       if (!sources)
+       {
+               error_out_of_memory ();
+               return 0;
+       }
+       sources->next = NULL;
+       sources->dwFlag = 0;
+
+       if ((files = ParseCommand (sources, argc, p, &dwFlags)) == -1)
+       {
+               DeleteFileList (sources);
+               freep (p);
+               return 0;
+       }
+       else if (files == 0)
+       {
+               error_req_param_missing();
+               DeleteFileList (sources);
+               freep (p);
+               return 0;
+       }
+       start = sources;
+
+       bDestFound = GetDestination (sources, &dest);
+       if (bDestFound)
+       {
+               _splitpath (dest.szFile, drive_d, dir_d, file_d, ext_d);
+               if (IsDirectory (dest.szFile))
+               {
+                       _tcscat (dir_d, file_d);
+                       _tcscat (dir_d, ext_d);
+                       file_d[0] = _T('\0');
+                       ext_d[0] = _T('\0');
+               }
+       }
+
+       if (_tcschr (dest.szFile, _T('*')) || _tcschr (dest.szFile, _T('?')))
+               bWildcards = TRUE;
+       else
+               bWildcards = FALSE;
+
+       if (strchr(rest, '+'))
+               bMultiple = TRUE;
+       else
+               bMultiple = FALSE;
+
+       append = 0;
+       copied = 0;
+
+       if (bDestFound && !bWildcards)
+       {
+               copied = setup_copy (sources, p, bMultiple, drive_d, dir_d, file_d, ext_d, &append, &dwFlags);
+       }
+       else if (bDestFound && bWildcards)
+       {
+               ConErrPrintf (_T("Error: Not implemented yet!\n"));
+               DeleteFileList (sources);
+               freep (p);
+               return 0;
+       }
+       else if (!bDestFound && !bMultiple)
+       {
+               _splitpath (sources->szFile, drive_d, dir_d, file_d, ext_d);
+               if (IsDirectory (sources->szFile))
+               {
+                       _tcscat (dir_d, file_d);
+                       _tcscat (dir_d, ext_d);
+                       file_d[0] = _T('\0');
+                       ext_d[0] = _T('\0');
+               }
+               copied = setup_copy (sources, p, FALSE, "", "", file_d, ext_d, &append, &dwFlags);
+       }
+       else
+       {
+               _splitpath(sources->szFile, drive_d, dir_d, file_d, ext_d);
+               if (IsDirectory (sources->szFile))
+               {
+                       _tcscat (dir_d, file_d);
+                       _tcscat (dir_d, ext_d);
+                       file_d[0] = _T('\0');
+                       ext_d[0] = _T('\0');
+               }
+
+               ConOutPuts (sources->szFile);
+               append = 1;
+               copied = setup_copy (sources->next, p, bMultiple, drive_d, dir_d, file_d, ext_d, &append, &dwFlags) + 1;
+       }
+
+       DeleteFileList (start);
+       freep (p);
+       ConOutPrintf (_T("        %d file(s) copied\n"), copied);
+
+       return 1;
+}
+#endif /* INCLUDE_CMD_COPY */
diff --git a/reactos/apps/utils/cmd/date.c b/reactos/apps/utils/cmd/date.c
new file mode 100644 (file)
index 0000000..e271236
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ *  DATE.C - date internal command.
+ *
+ *
+ *  History:
+ *
+ *    08 Jul 1998 (John P. Price)
+ *        started.
+ *
+ *    20 Jul 1998 (John P. Price)
+ *        corrected number of days for December from 30 to 31.
+ *        (Thanx to Steffen Kaiser for bug report)
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    29-Jul-1998 (Rob Lake)
+ *        fixed stand-alone mode.
+ *        Added Pacific C compatible dos_getdate functions
+ *
+ *    09-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added locale support
+ *
+ *    23-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection safe!
+ *
+ *    04-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Fixed date input bug.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_DATE
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "cmd.h"
+
+
+static WORD awMonths[2][13] =
+{
+       {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+       {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
+};
+
+
+static VOID
+PrintDate (VOID)
+{
+#if 0
+       SYSTEMTIME st;
+
+       GetLocalTime (&st);
+
+       switch (nDateFormat)
+       {
+               case 0: /* mmddyy */
+               default:
+                       ConOutPrintf (_T("Current date is: %s %02d%c%02d%c%04d\n"),
+                                         aszDayNames[st.wDayOfWeek], st.wMonth, cDateSeparator, st.wDay, cDateSeparator, st.wYear);
+                       break;
+
+               case 1: /* ddmmyy */
+                       ConOutPrintf (_T("Current date is: %s %02d%c%02d%c%04d\n"),
+                                         aszDayNames[st.wDayOfWeek], st.wDay, cDateSeparator, st.wMonth, cDateSeparator, st.wYear);
+                       break;
+
+               case 2: /* yymmdd */
+                       ConOutPrintf (_T("Current date is: %s %04d%c%02d%c%02d\n"),
+                                         aszDayNames[st.wDayOfWeek], st.wYear, cDateSeparator, st.wMonth, cDateSeparator, st.wDay);
+                       break;
+       }
+#endif
+       TCHAR szDate[32];
+
+       GetDateFormat (LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL,
+                                  szDate, sizeof (szDate));
+       ConOutPrintf (_T("Current date is: %s\n"), szDate);
+}
+
+
+static VOID
+PrintDateString (VOID)
+{
+       switch (nDateFormat)
+       {
+               case 0: /* mmddyy */
+               default:
+                       ConOutPrintf (_T("Enter new date (mm%cdd%cyyyy): "),
+                                       cDateSeparator, cDateSeparator);
+                       break;
+
+               case 1: /* ddmmyy */
+                       ConOutPrintf (_T("Enter new date (dd%cmm%cyyyy): "),
+                                         cDateSeparator, cDateSeparator);
+                       break;
+
+               case 2: /* yymmdd */
+                       ConOutPrintf (_T("Enter new date (yyyy%cmm%cdd): "),
+                                         cDateSeparator, cDateSeparator);
+                       break;
+       }
+}
+
+
+static BOOL
+ReadNumber (LPTSTR *s, LPWORD lpwValue)
+{
+       if (_istdigit (**s))
+       {
+               while (_istdigit (**s))
+               {
+                       *lpwValue = *lpwValue * 10 + **s - _T('0');
+                       (*s)++;
+               }
+               return TRUE;
+       }
+       return FALSE;
+}
+
+
+static BOOL
+ReadSeparator (LPTSTR *s)
+{
+       if (**s == _T('/') || **s == _T('-') || **s == cDateSeparator)
+       {
+               (*s)++;
+               return TRUE;
+       }
+       return FALSE;
+}
+
+
+static BOOL
+ParseDate (LPTSTR s)
+{
+       SYSTEMTIME d;
+       unsigned char leap;
+       LPTSTR p = s;
+
+       if (!*s)
+               return TRUE;
+
+       GetLocalTime (&d);
+
+       d.wYear = 0;
+       d.wDay = 0;
+       d.wMonth = 0;
+
+       switch (nDateFormat)
+       {
+               case 0: /* mmddyy */
+               default:
+                       if (!ReadNumber (&p, &d.wMonth))
+                               return FALSE;
+                       if (!ReadSeparator (&p))
+                               return FALSE;
+                       if (!ReadNumber (&p, &d.wDay))
+                               return FALSE;
+                       if (!ReadSeparator (&p))
+                               return FALSE;
+                       if (!ReadNumber (&p, &d.wYear))
+                               return FALSE;
+                       break;
+
+               case 1: /* ddmmyy */
+                       if (!ReadNumber (&p, &d.wDay))
+                               return FALSE;
+                       if (!ReadSeparator (&p))
+                               return FALSE;
+                       if (!ReadNumber (&p, &d.wMonth))
+                               return FALSE;
+                       if (!ReadSeparator (&p))
+                               return FALSE;
+                       if (!ReadNumber (&p, &d.wYear))
+                               return FALSE;
+                       break;
+
+               case 2: /* yymmdd */
+                       if (!ReadNumber (&p, &d.wYear))
+                               return FALSE;
+                       if (!ReadSeparator (&p))
+                               return FALSE;
+                       if (!ReadNumber (&p, &d.wMonth))
+                               return FALSE;
+                       if (!ReadSeparator (&p))
+                               return FALSE;
+                       if (!ReadNumber (&p, &d.wDay))
+                               return FALSE;
+                       break;
+       }
+
+       /* if only entered two digits:
+       /*   assume 2000's if value less than 80 */
+       /*   assume 1900's if value greater or equal 80 */
+       if (d.wYear <= 99)
+       {
+               if (d.wYear >= 80)
+                       d.wYear = 1900 + d.wYear;
+               else
+                       d.wYear = 2000 + d.wYear;
+       }
+
+       leap = (!(d.wYear % 4) && (d.wYear % 100)) || !(d.wYear % 400);
+
+       if ((d.wMonth >= 1 && d.wMonth <= 12) &&
+               (d.wDay >= 1 && d.wDay <= awMonths[leap][d.wMonth]) &&
+               (d.wYear >= 1980 && d.wYear <= 2099))
+       {
+               SetLocalTime (&d);
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+
+INT cmd_date (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR *arg;
+       INT    argc;
+       INT    i;
+       BOOL   bPrompt = TRUE;
+       INT    nDateString = -1;
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Displays or sets the date.\n\n"
+                                  "DATE [/T][date]\n\n"
+                                  "  /T    display only\n\n"
+                                  "Type DATE without parameters to display the current date setting and\n"
+                                  "a prompt for a new one.  Press ENTER to keep the same date."));
+               return 0;
+       }
+
+       /* build parameter array */
+       arg = split (param, &argc);
+
+       /* check for options */
+       for (i = 0; i < argc; i++)
+       {
+               if (_tcsicmp (arg[i], _T("/t")) == 0)
+                       bPrompt = FALSE;
+               if ((*arg[i] != _T('/')) && (nDateString == -1))
+                       nDateString = i;
+       }
+
+       if (nDateString == -1)
+               PrintDate ();
+
+       if (!bPrompt)
+       {
+               freep (arg);
+               return 0;
+       }
+
+       if (nDateString == -1)
+       {
+               while (TRUE)  /* forever loop */
+               {
+                       TCHAR s[40];
+
+                       PrintDateString ();
+                       ConInString (s, 40);
+#ifdef _DEBUG
+                       DebugPrintf ("\'%s\'\n", s);
+#endif
+                       while (*s && s[_tcslen (s) - 1] < ' ')
+                               s[_tcslen (s) - 1] = '\0';
+                       if (ParseDate (s))
+                       {
+                               freep (arg);
+                               return 0;
+                       }
+                       ConErrPuts ("Invalid date.");
+               }
+       }
+       else
+       {
+               if (ParseDate (arg[nDateString]))
+               {
+                       freep (arg);
+                       return 0;
+               }
+               ConErrPuts ("Invalid date.");
+       }
+
+       freep (arg);
+
+       return 0;
+}
+#endif
+
diff --git a/reactos/apps/utils/cmd/del.c b/reactos/apps/utils/cmd/del.c
new file mode 100644 (file)
index 0000000..c249670
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ *  DEL.C - del internal command.
+ *
+ *
+ *  History:
+ *
+ *    06/29/98 (Rob Lake rlake@cs.mun.ca)
+ *        rewrote del to support wildcards
+ *        added my name to the contributors
+ *
+ *    07/13/98 (Rob Lake)
+ *        fixed bug that caused del not to delete file with out
+ *        attribute. moved set, del, ren, and ver to there own files
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    09-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeiung.de>)
+ *        Fixed command line parsing bugs.
+ *
+ *    21-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeiung.de>)
+ *        Started major rewrite using a new structure.
+ *
+ *    03-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeiung.de>)
+ *        First working version.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_DEL
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+
+#define PROMPT_NO              0
+#define PROMPT_YES             1
+#define PROMPT_ALL             2
+#define PROMPT_BREAK   3
+
+
+static BOOL ConfirmDeleteAll (VOID)
+{
+       TCHAR inp[10];
+       LPTSTR p;
+
+       ConOutPrintf ("All files in directory will be deleted!\n"
+                                 "Are you sure (Y/N)? ");
+       ConInString (inp, 10);
+
+       _tcsupr (inp);
+       for (p = inp; _istspace (*p); p++)
+               ;
+
+       if (*p == _T('Y'))
+               return PROMPT_YES;
+       else if (*p == _T('N'))
+               return PROMPT_NO;
+
+#if 0
+       if (*p == _T('A'))
+               return PROMPT_ALL;
+       else if (*p == _T('\03'))
+               return PROMPT_BREAK;
+#endif
+
+       return PROMPT_NO;
+}
+
+
+static INT Prompt (LPTSTR str)
+{
+       TCHAR inp[10];
+       LPTSTR p;
+
+       ConOutPrintf (_T("Delete %s (Yes/No)? "), str);
+       ConInString (inp, 10);
+
+       _tcsupr (inp);
+       for (p = inp; _istspace (*p); p++)
+               ;
+
+       if (*p == _T('Y'))
+               return PROMPT_YES;
+       else if (*p == _T('N'))
+               return PROMPT_NO;
+
+#if 0
+       if (*p == _T('A'))
+               return PROMPT_ALL;
+       else if (*p == _T('\03'))
+               return PROMPT_BREAK;
+#endif
+}
+
+
+
+INT cmd_del (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR *arg = NULL;
+       INT args;
+       INT i;
+       INT  nEvalArgs = 0; /* nunber of evaluated arguments */
+       BOOL bNothing = FALSE;
+       BOOL bQuiet   = FALSE;
+       BOOL bPrompt  = FALSE;
+
+       HANDLE hFile;
+       WIN32_FIND_DATA f;
+//     DWORD dwAttributes;
+
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+/*
+               ConOutPuts (_T("Deletes one or more files.\n\n"
+                       "DEL [drive:][path]filename [/P]\n"
+                       "DELETE [drive:][path]filename [/P]\n"
+                       "ERASE [drive:][path]filename [/P]\n\n"
+                       "  [drive:][path]filename  Specifies the file(s) to delete.  Specify multiple\n"
+                       "                          files by using wildcards.\n"
+                       "  /P        Prompts for confirmation before deleting each file."));
+*/
+
+               ConOutPuts (_T("Deletes one or more files.\n"
+                                          "\n"
+                                          "DEL [/N /P /Q] file ...\n"
+                                          "DELETE [/N /P /Q] file ...\n"
+                                          "ERASE [/N /P /Q] file ...\n"
+                                          "\n"
+                                          "  file  Specifies the file(s) to delete.\n"
+                                          "\n"
+                                          "  /N    Nothing.\n"
+                                          "  /P    Prompts for confirmation before deleting each file.\n"
+                                          "        (Not implemented yet!)\n"
+                                          "  /Q    Quiet."
+                                          ));
+
+               return 0;
+       }
+
+       arg = split (param, &args);
+
+       if (args > 0)
+       {
+               /* check for options anywhere in command line */
+               for (i = 0; i < args; i++)
+               {
+                       if (*arg[i] == _T('/'))
+                       {
+                               if (_tcslen (arg[i]) >= 2)
+                               {
+                                       switch (_totupper (arg[i][1]))
+                                       {
+                                               case _T('N'):
+                                                       bNothing = TRUE;
+                                                       break;
+
+                                               case _T('P'):
+                                                       bPrompt = TRUE;
+                                                       break;
+
+                                               case _T('Q'):
+                                                       bQuiet = TRUE;
+                                                       break;
+                                       }
+
+                               }
+
+                               nEvalArgs++;
+                       }
+               }
+
+               /* there are only options on the command line --> error!!! */
+               if (args == nEvalArgs)
+               {
+                       error_req_param_missing ();
+                       freep (arg);
+                       return 1;
+               }
+
+               /* check for filenames anywhere in command line */
+               for (i = 0; i < args; i++)
+               {
+                       if (!_tcscmp (arg[i], _T("*")) ||
+                               !_tcscmp (arg[i], _T("*.*")))
+                       {
+                               if (!ConfirmDeleteAll ())
+                                       break;
+
+                       }
+
+                       if (*arg[i] != _T('/'))
+                       {
+#ifdef _DEBUG
+                               ConErrPrintf ("File: %s\n", arg[i]);
+#endif
+
+                               if (_tcschr (arg[i], _T('*')) || _tcschr (arg[i], _T('?')))
+                               {
+                                       /* wildcards in filespec */
+#ifdef _DEBUG
+                                       ConErrPrintf ("Wildcards!\n\n");
+#endif
+
+                                       hFile = FindFirstFile (arg[i], &f);
+                                       if (hFile == INVALID_HANDLE_VALUE)
+                                       {
+                                               error_file_not_found ();
+                                               freep (arg);
+                                               return 0;
+                                       }
+
+                                       do
+                                       {
+                                               if (!_tcscmp (f.cFileName, _T(".")) ||
+                                                       !_tcscmp (f.cFileName, _T("..")))
+                                                       continue;
+
+#ifdef _DEBUG
+                                               ConErrPrintf ("Delete file: %s\n", f.cFileName);
+#endif
+
+                                               if (!bNothing)
+                                               {
+                                                       if (!DeleteFile (f.cFileName))
+                                                               ErrorMessage (GetLastError(), _T(""));
+                                               }
+
+
+                                       }
+                                       while (FindNextFile (hFile, &f));
+                                       FindClose (hFile);
+                               }
+                               else
+                               {
+                                       /* no wildcards in filespec */
+#ifdef _DEBUG
+                                       ConErrPrintf ("No Wildcards!\n");
+                                       ConErrPrintf ("Delete file: %s\n", arg[i]);
+#endif
+
+                                       if (!bNothing)
+                                       {
+                                               if (!DeleteFile (arg[i]))
+                                                       ErrorMessage (GetLastError(), _T(""));
+                                       }
+                               }
+                       }
+               }
+       }
+       else
+       {
+               /* only command given */
+               error_req_param_missing ();
+               freep (arg);
+               return 1;
+       }
+
+       freep (arg);
+
+       return 0;
+}
+
+#endif
diff --git a/reactos/apps/utils/cmd/dir.c b/reactos/apps/utils/cmd/dir.c
new file mode 100644 (file)
index 0000000..c56d847
--- /dev/null
@@ -0,0 +1,1225 @@
+/*
+ *  DIR.C - dir internal command.
+ *
+ *
+ *  History:
+ *
+ *    01/29/97 (Tim Norman)
+ *        started.
+ *
+ *    06/13/97 (Tim Norman)
+ *      Fixed code.
+ *
+ *    07/12/97 (Tim Norman)
+ *        Fixed bug that caused the root directory to be unlistable
+ *
+ *    07/12/97 (Marc Desrochers)
+ *        Changed to use maxx, maxy instead of findxy()
+ *
+ *    06/08/98 (Rob Lake)
+ *        Added compatibility for /w in dir
+ *
+ *    06/09/98 (Rob Lake)
+ *        Compatibility for dir/s started
+ *        Tested that program finds directories off root fine
+ *
+ *    06/10/98 (Rob Lake)
+ *        do_recurse saves the cwd and also stores it in Root
+ *        build_tree adds the cwd to the beginning of its' entries
+ *        Program runs fine, added print_tree -- works fine.. as EXE,
+ *        program won't work properly as COM.
+ *
+ *    06/11/98 (Rob Lake)
+ *        Found problem that caused COM not to work
+ *
+ *    06/12/98 (Rob Lake)
+ *        debugged...
+ *        added free mem routine
+ *
+ *    06/13/98 (Rob Lake)
+ *        debugged the free mem routine
+ *        debugged whole thing some more
+ *        Notes:
+ *        ReadDir stores Root name and _Read_Dir does the hard work
+ *        PrintDir prints Root and _Print_Dir does the hard work
+ *        KillDir kills Root _after_ _Kill_Dir does the hard work
+ *        Integrated program into DIR.C(this file) and made some same
+ *        changes throughout
+ *
+ *    06/14/98 (Rob Lake)
+ *        Cleaned up code a bit, added comments
+ *
+ *    06/16/98 (Rob Lake)
+ *        Added error checking to my previously added routines
+ *
+ *    06/17/98 (Rob Lake)
+ *        Rewrote recursive functions, again! Most other recursive
+ *        functions are now obsolete -- ReadDir, PrintDir, _Print_Dir,
+ *        KillDir and _Kill_Dir.  do_recurse does what PrintDir did
+ *        and _Read_Dir did what it did before along with what _Print_Dir
+ *        did.  Makes /s a lot faster!
+ *        Reports 2 more files/dirs that MS-DOS actually reports
+ *        when used in root directory(is this because dir defaults
+ *        to look for read only files?)
+ *        Added support for /b, /a and /l
+ *        Made error message similar to DOS error messages
+ *        Added help screen
+ *
+ *    06/20/98 (Rob Lake)
+ *        Added check for /-(switch) to turn off previously defined
+ *        switches.
+ *        Added ability to check for DIRCMD in environment and
+ *        process it
+ *
+ *    06/21/98 (Rob Lake)
+ *        Fixed up /B
+ *        Now can dir *.ext/X, no spaces!
+ *
+ *    06/29/98 (Rob Lake)
+ *        error message now found in command.h
+ *
+ *    07/08/1998 (John P. Price)
+ *        removed extra returns; closer to MSDOS
+ *        fixed wide display so that an extra return is not displayed
+ *        when there is five filenames in the last line.
+ *
+ *    07/12/98 (Rob Lake)
+ *        Changed error messages
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *
+ *    04-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Converted source code to Win32, except recursive dir ("dir /s").
+ *
+ *    10-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Fixed recursive dir ("dir /s").
+ *
+ *    14-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Converted to Win32 directory functions and
+ *        fixed some output bugs. There are still some more ;)
+ *
+ *    10-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added "/N" and "/4" options, "/O" is a dummy.
+ *        Added locale support.
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Redirection safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_DIR
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <direct.h>
+
+#include "cmd.h"
+
+
+/* useful macro */
+#define MEM_ERR error_out_of_memory(); return 1;
+
+
+/* flag definitions */
+/* Changed hex to decimal, hex wouldn't work
+ * if > 8, Rob Lake 06/17/98.
+ */
+enum
+{
+       DIR_RECURSE = 0x0001,
+       DIR_PAGE    = 0x0002,
+       DIR_WIDE    = 0x0004,        /* Rob Lake */
+       DIR_BARE    = 0x0008,        /* Rob Lake */
+       DIR_ALL     = 0x0010,        /* Rob Lake */
+       DIR_LWR     = 0x0020,        /* Rob Lake */
+       DIR_SORT    = 0x0040,        /* /O sort */
+       DIR_NEW     = 0x0080,        /* /N new style */
+       DIR_FOUR    = 0x0100         /* /4 four digit year */
+};
+
+
+/* Globally save the # of dirs, files and bytes,
+ * probabaly later pass them to functions. Rob Lake  */
+long recurse_dir_cnt;
+long recurse_file_cnt;
+ULARGE_INTEGER recurse_bytes;
+
+
+/*
+ * help
+ *
+ * displays help screen for dir
+ * Rob Lake
+ */
+static VOID Help (VOID)
+{
+#if 1
+       ConOutPuts (_T("Displays a list of files and subdirectories in a directory.\n"
+       "\n"
+       "DIR [drive:][path][filename] [/A] [/B] [/L] [/N] [/S] [/P] [/W] [/4]\n"
+       "\n"
+       "  [drive:][path][filename]\n"
+       "              Specifies drive, directory, and/or files to list.\n"
+       "\n"
+       "  /A          Displays files with HIDDEN SYSTEM attributes\n"
+       "              default is ARCHIVE and READ ONLY\n"
+       "  /B          Uses bare format (no heading information or summary).\n"
+       "  /L          Uses lowercase.\n"
+       "  /N          New long list format where filenames are on the far right.\n"
+       "  /S          Displays files in specified directory and all subdirectories\n"
+       "  /P          Pauses after each screen full\n"
+       "  /W          Prints in wide format\n"
+       "  /4          Display four digit years.\n"
+       "\n"
+       "Switches may be present in the DIRCMD environment variable.  Use\n"
+       "of the - (hyphen) can turn off defined swtiches.  Ex. /-W would\n"
+       "turn off printing in wide format.\n"
+      ));
+#endif
+#if 0
+       InitializePageOut ();
+       LinePageOut (_T("Displays a list of files and subdirectories in a directory."));
+       LinePageOut (_T(""));
+       LinePageOut (_T("DIR [drive:][path][filename] [/A] [/B] [/L] [/N] [/S] [/P] [/W] [/4]"));
+       LinePageOut (_T(""));
+       LinePageOut (_T("  [drive:][path][filename]"));
+       LinePageOut (_T("              Specifies drive, directory, and/or files to list."));
+       LinePageOut (_T(""));
+       LinePageOut (_T("  /A          Displays files with HIDDEN SYSTEM attributes"));
+       LinePageOut (_T("              default is ARCHIVE and READ ONLY"));
+       LinePageOut (_T("  /B          Uses bare format (no heading information or summary)."));
+       LinePageOut (_T("  /L          Uses lowercase."));
+       LinePageOut (_T("  /N          New long list format where filenames are on the far right."));
+       LinePageOut (_T("  /S          Displays files in specified directory and all subdirectories"));
+       LinePageOut (_T("  /P          Pauses after each screen full"));
+       LinePageOut (_T("  /W          Prints in wide format"));
+       LinePageOut (_T("  /4          Display four digit years."));
+       LinePageOut (_T(""));
+       LinePageOut (_T("Switches may be present in the DIRCMD environment variable.  Use"));
+       LinePageOut (_T("of the - (hyphen) can turn off defined swtiches.  Ex. /-W would"));
+       LinePageOut (_T("turn off printing in wide format."));
+       TerminatePageOut ();
+#endif
+}
+
+
+/*
+ * dir_read_param
+ *
+ * read the parameters from the command line
+ */
+static BOOL
+DirReadParam (char *line, char **param, LPDWORD lpFlags)
+{
+       int slash = 0;
+
+       if (!line)
+               return TRUE;
+
+       *param = NULL;
+
+       /* scan the command line, processing switches */
+       while (*line)
+       {
+               /* process switch */
+               if (*line == _T('/') || slash)
+               {
+                       if (!slash)
+                               line++;
+                       slash = 0;
+                       if (*line == _T('-'))
+                       {
+                               line++;
+                               if (_totupper (*line) == _T('S'))
+                                       *lpFlags &= ~DIR_RECURSE;
+                               else if (_totupper (*line) == _T('P'))
+                                       *lpFlags &= ~DIR_PAGE;
+                               else if (_totupper (*line) == _T('W'))
+                                       *lpFlags &= ~DIR_WIDE;
+                               else if (_totupper (*line) == _T('B'))
+                                       *lpFlags &= ~DIR_BARE;
+                               else if (_totupper (*line) == _T('A'))
+                                       *lpFlags &= ~DIR_ALL;
+                               else if (_totupper (*line) == _T('L'))
+                                       *lpFlags &= ~DIR_LWR;
+                               else if (_totupper (*line) == _T('N'))
+                                       *lpFlags &= ~DIR_NEW;
+                               else if (_totupper (*line) == _T('O'))
+                                       *lpFlags &= ~DIR_SORT;
+                               else if (_totupper (*line) == _T('4'))
+                                       *lpFlags &= ~DIR_FOUR;
+                               else
+                               {
+                                       error_invalid_switch ((TCHAR)_totupper (*line));
+                                       return FALSE;
+                               }
+                               line++;
+                               continue;
+                       }
+                       else
+                       {
+                               if (_totupper (*line) == _T('S'))
+                                       *lpFlags |= DIR_RECURSE;
+                               else if (_toupper (*line) == _T('P'))
+                                       *lpFlags |= DIR_PAGE;
+                               else if (_totupper (*line) == _T('W'))
+                                       *lpFlags |= DIR_WIDE;
+                               else if (_totupper (*line) == _T('B'))
+                                       *lpFlags |= DIR_BARE;
+                               else if (_totupper (*line) == _T('A'))
+                                       *lpFlags |= DIR_ALL;
+                               else if (_totupper (*line) == _T('L'))
+                                       *lpFlags |= DIR_LWR;
+                               else if (_totupper (*line) == _T('N'))
+                                       *lpFlags |= DIR_NEW;
+                               else if (_totupper (*line) == _T('O'))
+                                       *lpFlags |= DIR_SORT;
+                               else if (_totupper (*line) == _T('4'))
+                                       *lpFlags |= DIR_FOUR;
+                               else if (*line == _T('?'))
+                               {
+                                       Help();
+                                       return FALSE;
+                               }
+                               else
+                               {
+                                       error_invalid_switch ((TCHAR)_totupper (*line));
+                                       return FALSE;
+                               }
+                               line++;
+                               continue;
+                       }
+               }
+
+               /* process parameter */
+               if (!_istspace (*line))
+               {
+                       if (*param)
+                       {
+                               error_too_many_parameters (*param);
+                               return FALSE;
+                       }
+
+                       *param = line;
+
+                       /* skip to end of line or next whitespace or next / */
+                       while (*line && !_istspace (*line) && *line != _T('/'))
+                               line++;
+
+                       /* if end of line, return */
+                       if (!*line)
+                               return TRUE;
+
+                       /* if parameter, remember to process it later */
+                       if (*line == _T('/'))
+                               slash = 1;
+
+                       *line++ = 0;
+                       continue;
+               }
+
+               line++;
+       }
+
+       if (slash)
+       {
+               error_invalid_switch ((TCHAR)_totupper (*line));
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
+/*
+ * extend_file
+ *
+ * extend the filespec, possibly adding wildcards
+ */
+void extend_file (char **file)
+{
+       LPTSTR tmp;
+
+       if (!*file)
+               return;
+
+       /* if no file spec, change to "*.*" */
+       if (!**file)
+       {
+               free (*file);
+               *file = _tcsdup (_T("*.*"));
+               return;
+       }
+
+       /* if starts with . add * in front */
+       if (**file == _T('.'))
+       {
+               tmp = malloc ((_tcslen (*file) + 2) * sizeof(TCHAR));
+               if (tmp)
+               {
+                       *tmp = _T('*');
+                       _tcscpy (&tmp[1], *file);
+               }
+               free (*file);
+               *file = tmp;
+               return;
+       }
+
+       /* if no . add .* */
+       if (!_tcschr (*file, _T('.')))
+       {
+               tmp = malloc ((_tcslen (*file) + 3) * sizeof(TCHAR));
+               if (tmp)
+               {
+                       _tcscpy (tmp, *file);
+                       _tcscat (tmp, _T(".*"));
+               }
+               free (*file);
+               *file = tmp;
+               return;
+       }
+}
+
+
+/*
+ * dir_parse_pathspec
+ *
+ * split the pathspec into drive, directory, and filespec
+ */
+static int
+DirParsePathspec (char *pathspec, int *drive, char **dir, char **file)
+{
+       TCHAR  orig_dir[MAX_PATH];
+       LPTSTR start;
+       LPTSTR tmp;
+       INT    i;
+       INT    wildcards = 0;
+
+
+       /* get the drive and change to it */
+       if (pathspec[1] == _T(':'))
+       {
+               *drive = _totupper (pathspec[0]) - _T('@');
+               start = pathspec + 2;
+               _chdrive (*drive);
+       }
+       else
+       {
+               *drive = _getdrive ();
+               start = pathspec;
+       }
+
+       GetCurrentDirectory (MAX_PATH, orig_dir);
+
+       /* check for wildcards */
+       for (i = 0; pathspec[i]; i++)
+               if (pathspec[i] == _T('*') || pathspec[i] == _T('?'))
+                       wildcards = 1;
+
+       /* check if this spec is a directory */
+       if (!wildcards)
+       {
+               if (chdir(pathspec) == 0)
+               {
+                       *file = _tcsdup (_T("*.*"));
+                       if (!*file)
+                       {
+                               MEM_ERR
+                       }
+
+                       tmp = getcwd (NULL, MAX_PATH);
+                       if (!tmp)
+                       {
+                               free (*file);
+                               chdir (orig_dir);
+                               MEM_ERR
+                       }
+
+                       *dir = _tcsdup (&tmp[2]);
+                       free (tmp);
+                       if (!*dir)
+                       {
+                               free (*file);
+                               chdir (orig_dir);
+                               MEM_ERR
+                       }
+
+                       chdir (orig_dir);
+                       return 0;
+               }
+       }
+
+       /* find the file spec */
+       tmp = _tcsrchr (start, _T('\\'));
+
+       /* if no path is specified */
+       if (!tmp)
+       {
+               *file = _tcsdup (start);
+               extend_file (file);
+               if (!*file)
+               {
+                       MEM_ERR
+               }
+
+               tmp = getcwd (NULL, _MAX_PATH);
+               if (!tmp)
+               {
+                       free (*file);
+                       chdir (orig_dir);
+                       MEM_ERR
+               }
+               *dir = _tcsdup (&tmp[2]);
+               free(tmp);
+               if (!*dir)
+               {
+                       free (*file);
+                       chdir (orig_dir);
+                       MEM_ERR
+               }
+
+               return 0;
+       }
+
+       /* get the filename */
+       *file = _tcsdup (tmp + 1);
+       extend_file (file);
+       if (!*file)
+       {
+               MEM_ERR
+       }
+
+       *tmp = 0;
+
+       /* change to this directory and get its full name */
+       if (chdir (start) < 0)
+       {
+               error_path_not_found ();
+               *tmp = _T('\\');
+               free (*file);
+               chdir (orig_dir);
+               return 1;
+       }
+
+       tmp = getcwd (NULL, _MAX_PATH);
+       if (!tmp)
+       {
+               free (*file);
+               MEM_ERR
+       }
+       *dir = _tcsdup (&tmp[2]);
+       free(tmp);
+       if (!*dir)
+       {
+               free(*file);
+               MEM_ERR
+       }
+
+       *tmp = _T('\\');
+
+       chdir(orig_dir);
+       return 0;
+}
+
+
+/*
+ * pause
+ *
+ * pause until a key is pressed
+ */
+static INT
+Pause (VOID)
+{
+       cmd_pause ("", "");
+
+       return 0;
+}
+
+
+/*
+ * incline
+ *
+ * increment our line if paginating, display message at end of screen
+ */
+static INT
+incline (int *line, DWORD dwFlags)
+{
+       if (!(dwFlags & DIR_PAGE))
+               return 0;
+
+       (*line)++;
+
+       if (*line >= (int)maxy - 2)
+       {
+               *line = 0;
+               return Pause ();
+       }
+
+       return 0;
+}
+
+
+/*
+ * PrintDirectoryHeader
+ *
+ * print the header for the dir command
+ */
+static BOOL
+PrintDirectoryHeader (int drive, int *line, DWORD dwFlags)
+{
+       TCHAR szRootName[] = _T("A:\\");
+       TCHAR szVolName[80];
+       DWORD dwSerialNr;
+
+       if (dwFlags & DIR_BARE)
+               return TRUE;
+
+       /* get the media ID of the drive */
+       szRootName[0] = drive + _T('@');
+       if (!GetVolumeInformation (szRootName, szVolName, 80, &dwSerialNr,
+                                                          NULL, NULL, NULL, 0))
+       {
+               error_invalid_drive();
+               return FALSE;
+       }
+
+       /* print drive info */
+       ConOutPrintf (_T(" Volume in drive %c"), szRootName[0]);
+
+       if (szVolName[0] != _T('\0'))
+               ConOutPrintf (_T(" is %s\n"), szVolName);
+       else
+               ConOutPrintf (_T(" has no label\n"));
+
+       if (incline (line, dwFlags) != 0)
+               return FALSE;
+
+       /* print the volume serial number if the return was successful */
+       ConOutPrintf (_T(" Volume Serial Number is %04X-%04X\n"),
+                                 HIWORD(dwSerialNr), LOWORD(dwSerialNr));
+       if (incline (line, dwFlags) != 0)
+               return FALSE;
+
+       return TRUE;
+}
+
+
+/*
+ * convert
+ *
+ * insert commas into a number
+ */
+static INT
+ConvertLong (LONG num, LPTSTR des, INT len)
+{
+       TCHAR temp[32];
+       INT c = 0;
+       INT n = 0;
+
+       if (num == 0)
+       {
+               des[0] = _T('0');
+               des[1] = _T('\0');
+               n = 1;
+       }
+       else
+       {
+               temp[31] = 0;
+               while (num > 0)
+               {
+                       if (((c + 1) % (nNumberGroups + 1)) == 0)
+                               temp[30 - c++] = cThousandSeparator;
+                       temp[30 - c++] = (TCHAR)(num % 10) + _T('0');
+                       num /= 10;
+               }
+
+               for (n = 0; n <= c; n++)
+                       des[n] = temp[31 - c + n];
+       }
+
+       return n;
+}
+
+
+static INT
+ConvertULargeInteger (ULARGE_INTEGER num, LPTSTR des, INT len)
+{
+       TCHAR temp[32];
+       INT c = 0;
+       INT n = 0;
+
+       if (num.QuadPart == 0)
+       {
+               des[0] = _T('0');
+               des[1] = _T('\0');
+               n = 1;
+       }
+       else
+       {
+               temp[31] = 0;
+               while (num.QuadPart > 0)
+               {
+                       if (((c + 1) % (nNumberGroups + 1)) == 0)
+                               temp[30 - c++] = cThousandSeparator;
+                       temp[30 - c++] = (TCHAR)(num.QuadPart % 10) + _T('0');
+                       num.QuadPart /= 10;
+               }
+
+               for (n = 0; n <= c; n++)
+                       des[n] = temp[31 - c + n];
+       }
+
+       return n;
+}
+
+
+static VOID
+PrintFileDateTime (LPSYSTEMTIME dt, DWORD dwFlags)
+{
+       WORD wYear = (dwFlags & DIR_FOUR) ? dt->wYear : dt->wYear%100;
+
+       switch (nDateFormat)
+       {
+               case 0: /* mmddyy */
+               default:
+                       ConOutPrintf ("%.2d%c%.2d%c%d", dt->wMonth, cDateSeparator, dt->wDay, cDateSeparator, wYear);
+                       break;
+
+               case 1: /* ddmmyy */
+                       ConOutPrintf ("%.2d%c%.2d%c%d",
+                                       dt->wDay, cDateSeparator, dt->wMonth, cDateSeparator, wYear);
+                       break;
+
+               case 2: /* yymmdd */
+                       ConOutPrintf ("%d%c%.2d%c%.2d",
+                                       wYear, cDateSeparator, dt->wMonth, cDateSeparator, dt->wDay);
+                       break;
+       }
+
+       switch (nTimeFormat)
+       {
+               case 0: /* 12 hour format */
+               default:
+                       ConOutPrintf ("  %2d%c%.2u%c",
+                                       (dt->wHour == 0 ? 12 : (dt->wHour <= 12 ? dt->wHour : dt->wHour - 12)),
+                                       cTimeSeparator,
+                                        dt->wMinute, (dt->wHour <= 11 ? 'a' : 'p'));
+                       break;
+
+               case 1: /* 24 hour format */
+                       ConOutPrintf ("  %2d%c%.2u",
+                                       dt->wHour, cTimeSeparator, dt->wMinute);
+                       break;
+       }
+}
+
+
+/*
+ * print_summary: prints dir summary
+ * Added by Rob Lake 06/17/98 to compact code
+ * Just copied Tim's Code and patched it a bit
+ *
+ */
+static INT
+PrintSummary (int drive, long files, long dirs, ULARGE_INTEGER bytes,
+              DWORD flags, int *line)
+{
+       TCHAR buffer[64];
+
+       if (flags & DIR_BARE)
+               return 0;
+
+       /* print number of files and bytes */
+       ConvertLong (files, buffer, sizeof(buffer));
+       ConOutPrintf (_T("          %6s File%c"),
+                                 buffer, files == 1 ? _T(' ') : _T('s'));
+
+       ConvertULargeInteger (bytes, buffer, sizeof(buffer));
+       ConOutPrintf (_T("  %15s byte%c\n"),
+                                 buffer, bytes.QuadPart == 1 ? _T(' ') : _T('s'));
+
+       if (incline (line, flags) != 0)
+               return 1;
+
+       /* print number of dirs and bytes free */
+       ConvertLong (dirs, buffer, sizeof(buffer));
+       ConOutPrintf (_T("          %6s Dir%c"),
+                                 buffer, files == 1 ? _T(' ') : _T('s'));
+
+
+       if (!(flags & DIR_RECURSE))
+       {
+               ULARGE_INTEGER uliFree;
+               TCHAR szRoot[] = _T("A:\\");
+               DWORD dwSecPerCl;
+               DWORD dwBytPerSec;
+               DWORD dwFreeCl;
+               DWORD dwTotCl;
+
+               szRoot[0] = drive + _T('@');
+               GetDiskFreeSpace (szRoot, &dwSecPerCl, &dwBytPerSec, &dwFreeCl, &dwTotCl);
+               uliFree.QuadPart = dwSecPerCl * dwBytPerSec * dwFreeCl;
+               ConvertULargeInteger (uliFree, buffer, sizeof(buffer));
+               ConOutPrintf (_T("   %15s bytes free\n"), buffer);
+       }
+
+       if (incline (line, flags) != 0)
+               return 1;
+
+       return 0;
+}
+
+
+/*
+ * dir_list
+ *
+ * list the files in the directory
+ */
+static int
+dir_list (int drive, char *directory, char *filespec, int *line,
+          DWORD flags)
+{
+  char pathspec[_MAX_PATH],
+   *ext,
+    buffer[32];
+  WIN32_FIND_DATA file;
+  ULARGE_INTEGER bytecount;
+  long filecount = 0,
+    dircount = 0;
+  int count;
+  FILETIME   ft;
+  SYSTEMTIME dt;
+  HANDLE hFile;
+
+  bytecount.QuadPart = 0;
+
+       if (directory[strlen(directory) - 1] == '\\')
+               wsprintf(pathspec, "%c:%s%s", drive + '@', directory, filespec);
+       else
+               wsprintf(pathspec, "%c:%s\\%s", drive + '@', directory, filespec);
+
+       hFile = FindFirstFile (pathspec, &file);
+       if (hFile == INVALID_HANDLE_VALUE)
+       {
+               /* Don't want to print anything if scanning recursively
+                * for a file. RL
+                */
+               if ((flags & DIR_RECURSE) == 0)
+               {
+                       error_file_not_found();
+                       incline(line, flags);
+                       FindClose (hFile);
+                       return 1;
+               }
+               FindClose (hFile);
+               return 0;
+       }
+
+  /* moved down here because if we are recursively searching and
+   * don't find any files, we don't want just to print
+   * Directory of C:\SOMEDIR
+   * with nothing else
+   * Rob Lake 06/13/98
+   */
+  if ((flags & DIR_BARE) == 0)
+  {
+    ConOutPrintf (" Directory of %c:%s\n", drive + '@', directory);
+    if (incline(line, flags) != 0)
+      return 1;
+    ConOutPrintf ("\n");
+    if (incline(line, flags) != 0)
+      return 1;
+  }
+
+  /* For counting columns of output */
+  count = 0;
+
+  do
+  {
+       /* next file, if user doesn't want all files */
+       if (!(flags & DIR_ALL) &&
+               ((file.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ||
+                (file.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)))
+               continue;
+
+       /* begin Rob Lake */
+       if (flags & DIR_LWR)
+       {
+               strlwr(file.cAlternateFileName);
+       }
+
+    if (flags & DIR_WIDE && (flags & DIR_BARE) == 0)
+    {
+      if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+      {
+               if (file.cAlternateFileName[0] == '\0')
+          wsprintf (buffer, _T("[%s]"), file.cFileName);
+               else
+          wsprintf (buffer, _T("[%s]"), file.cAlternateFileName);
+        dircount++;
+      }
+      else
+      {
+               if (file.cAlternateFileName[0] == '\0')
+          wsprintf (buffer, _T("%s"), file.cFileName);
+               else
+          wsprintf (buffer, _T("%s"), file.cAlternateFileName);
+        filecount++;
+      }
+      ConOutPrintf (_T("%-15s"), buffer);
+      count++;
+      if (count == 5)
+      {
+        /* output 5 columns */
+        ConOutPrintf ("\n");
+        if (incline(line, flags) != 0)
+          return 1;
+        count = 0;
+      }
+
+         /* FIXME: this is buggy - now overflow check */
+      bytecount.LowPart += file.nFileSizeLow;
+      bytecount.HighPart += file.nFileSizeHigh;
+
+      /* next block 06/17/98 */
+    }
+    else if (flags & DIR_BARE)
+    {
+      if (strcmp(file.cFileName, ".") == 0 ||
+                 strcmp(file.cFileName, "..") == 0)
+        continue;
+
+      if (flags & DIR_RECURSE)
+      {
+        TCHAR dir[MAX_PATH];
+        wsprintf (dir, _T("%c:%s\\"), drive + _T('@'), directory);
+        if (flags & DIR_LWR)
+          strlwr(dir);
+        ConOutPrintf (dir);
+      }
+      ConOutPrintf (_T("%-13s\n"), file.cFileName);
+      if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+        dircount++;
+      else
+        filecount++;
+      if (incline(line, flags) != 0)
+        return 1;
+
+      /* FIXME: this is buggy - no overflow check */
+      bytecount.LowPart += file.nFileSizeLow;
+      bytecount.HighPart += file.nFileSizeHigh;
+    }
+    else
+    {
+    /* end Rob Lake */
+         if (flags & DIR_NEW)
+         {
+               /* print file date and time */
+               if (FileTimeToLocalFileTime (&file.ftLastWriteTime, &ft))
+               {
+                 FileTimeToSystemTime (&ft, &dt);
+                 PrintFileDateTime (&dt, flags);
+               }
+
+               /* print file size */
+               if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+               {
+                 ConOutPrintf ("         <DIR>         ");
+                 dircount++;
+               }
+               else
+               {
+                       ULARGE_INTEGER uliSize;
+
+                       uliSize.LowPart = file.nFileSizeLow;
+                       uliSize.HighPart = file.nFileSizeHigh;
+
+                       ConvertULargeInteger (uliSize, buffer, sizeof(buffer));
+                       ConOutPrintf (_T("   %20s"), buffer);
+
+                       bytecount.QuadPart += uliSize.QuadPart;
+                       filecount++;
+               }
+
+               /* print long filename */
+               ConOutPrintf (" %s\n", file.cFileName);
+         }
+         else
+         {
+        if (file.cFileName[0] == '.')
+          ConOutPrintf ("%-13s ", file.cFileName);
+           else if (file.cAlternateFileName[0] == '\0')
+               {
+          char szShortName[13];
+                 strncpy (szShortName, file.cFileName, 13);
+                 ext = strchr(szShortName, '.');
+          if (!ext)
+            ext = "";
+          else
+            *ext++ = 0;
+          ConOutPrintf ("%-8s %-3s  ", szShortName, ext);
+               }
+        else
+               {
+                 ext = strchr(file.cAlternateFileName, '.');
+          if (!ext)
+            ext = "";
+          else
+            *ext++ = 0;
+          ConOutPrintf ("%-8s %-3s  ", file.cAlternateFileName, ext);
+               }
+
+               /* print file size */
+        if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+               {
+          ConOutPrintf ("%-14s", "<DIR>");
+          dircount++;
+               }
+               else
+               {
+                       ULARGE_INTEGER uliSize;
+
+                       uliSize.LowPart = file.nFileSizeLow;
+                       uliSize.HighPart = file.nFileSizeHigh;
+
+                       ConvertULargeInteger (uliSize, buffer, sizeof(buffer));
+                       ConOutPrintf (_T("   %10s "), buffer);
+
+                       bytecount.QuadPart += uliSize.QuadPart;
+                       filecount++;
+               }
+
+               /* print file date and time */
+               if (FileTimeToLocalFileTime (&file.ftLastWriteTime, &ft))
+               {
+                 FileTimeToSystemTime (&ft, &dt);
+                 PrintFileDateTime (&dt, flags);
+               }
+
+               /* print long filename */
+               ConOutPrintf (" %s\n", file.cFileName);
+         }
+
+      if (incline(line, flags) != 0)
+        return 1;
+    }
+  }
+  while (FindNextFile (hFile, &file));
+
+  FindClose (hFile);
+
+       /* Rob Lake, need to make clean output */
+       /* JPP 07/08/1998 added check for count != 0 */
+       if ((flags & DIR_WIDE) && (count != 0))
+       {
+               ConOutPrintf ("\n");
+               if (incline(line, flags) != 0)
+                       return 1;
+       }
+
+       if (filecount || dircount)
+       {
+               recurse_dir_cnt += dircount;
+               recurse_file_cnt += filecount;
+               recurse_bytes.QuadPart += bytecount.QuadPart;
+
+               /* The code that was here is now in print_summary */
+               if (PrintSummary (drive, filecount, dircount,
+                                                 bytecount, flags, line) != 0)
+                       return 1;
+       }
+       else
+       {
+               error_file_not_found ();
+               return 1;
+       }
+
+       return 0;
+}
+
+
+/*
+ * _Read_Dir: Actual function that does recursive listing
+ */
+static int
+Read_Dir (int drive, char *parent, char *filespec, int *lines,
+          DWORD flags)
+{
+  char fullpath[_MAX_PATH];
+  WIN32_FIND_DATA file;
+  HANDLE hFile;
+
+  strcpy (fullpath, parent);
+  strcat (fullpath, "\\");
+  strcat (fullpath, filespec);
+
+  hFile = FindFirstFile (fullpath, &file);
+  if (hFile == INVALID_HANDLE_VALUE)
+    return 1;
+
+  do
+  {
+       /* don't list "." and ".." */
+    if (strcmp (file.cFileName, ".") == 0 ||
+        strcmp (file.cFileName, "..") == 0)
+      continue;
+
+       if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+    {
+      if (dir_list(drive, file.cFileName, filespec, lines, flags) != 0)
+      {
+        FindClose (hFile);
+        return 1;
+      }
+      if ((flags & DIR_BARE) == 0)
+      {
+        ConOutPrintf ("\n");
+        if (incline(lines, flags) != 0)
+          return 1;
+      }
+      if (Read_Dir(drive, file.cFileName, filespec, lines, flags) == 1)
+      {
+        FindClose (hFile);
+        return 1;
+      }
+    }
+  }
+  while (FindNextFile (hFile, &file));
+
+  if (!FindClose (hFile))
+    return 1;
+
+  return 0;
+}
+
+
+/*
+ * do_recurse: Sets up for recursive directory listing
+ */
+static int
+do_recurse(int drive, char *directory, char *filespec,
+           int *line, DWORD flags)
+{
+  char cur_dir[_MAX_DIR];
+
+  recurse_dir_cnt = recurse_file_cnt = 0L;
+  recurse_bytes.QuadPart = 0;
+
+  _chdrive (drive);
+  getcwd(cur_dir, sizeof(cur_dir));
+
+  if (chdir(directory) == -1)
+    return 1;
+
+       if (!PrintDirectoryHeader (drive, line, flags))
+               return 1;
+
+  if (dir_list(drive, directory, filespec, line, flags) != 0)
+    return 1;
+  if ((flags & DIR_BARE) == 0)
+  {
+    ConOutPrintf ("\n");
+    if (incline(line, flags) != 0)
+      return 1;
+  }
+  if (Read_Dir(drive, directory, filespec, line, flags) != 0)
+    return 1;
+  if ((flags & DIR_BARE) == 0)
+    ConOutPrintf ("Total files listed:\n");
+  flags &= ~DIR_RECURSE;
+
+       if (PrintSummary (drive, recurse_file_cnt,
+                                         recurse_dir_cnt, recurse_bytes, flags, line) != 0)
+               return 1;
+
+       if ((flags & DIR_BARE) == 0)
+       {
+               ConOutPrintf ("\n");
+               if (incline(line, flags) != 0)
+                       return 1;
+       }
+       chdir(cur_dir);
+       return 0;
+}
+
+
+/*
+ * dir
+ *
+ * internal dir command
+ */
+INT cmd_dir (LPTSTR first, LPTSTR rest)
+{
+       DWORD dwFlags = DIR_NEW | DIR_FOUR;
+  char *param;
+       TCHAR dircmd[256];
+  int line = 0;
+  int drive,
+    orig_drive;
+  char *directory,
+   *filespec,
+    orig_dir[_MAX_DIR];
+
+
+       /* read the parameters from the DIRCMD environment variable */
+       if (GetEnvironmentVariable (_T("DIRCMD"), dircmd, 256))
+       {
+               if (!DirReadParam (dircmd, &param, &dwFlags))
+                       return 1;
+       }
+
+       /* read the parameters */
+       if (!DirReadParam (rest, &param, &dwFlags))
+               return 1;
+
+       /* default to current directory */
+       if (!param)
+               param = ".";
+
+       if (strchr(param, '/'))
+               param = strtok (param, "/");
+
+       /* save the current directory info */
+       orig_drive = _getdrive ();
+       getcwd(orig_dir, sizeof(orig_dir));
+
+       /* parse the directory info */
+       if (DirParsePathspec (param, &drive, &directory, &filespec) != 0)
+       {
+               _chdrive (orig_drive);
+               chdir(orig_dir);
+               return 1;
+       }
+
+       if (dwFlags & DIR_RECURSE)
+       {
+               incline(&line, dwFlags);
+               if (do_recurse (drive, directory, filespec, &line, dwFlags) != 0)
+                       return 1;
+               _chdrive (orig_drive);
+               chdir (orig_dir);
+               return 0;
+       }
+
+       /* print the header */
+       if (!PrintDirectoryHeader (drive, &line, dwFlags))
+               return 1;
+
+       chdir (orig_dir);
+       _chdrive (orig_drive);
+
+       if (dir_list (drive, directory, filespec, &line, dwFlags) != 0)
+               return 1;
+
+       return 0;
+}
+
+#endif
diff --git a/reactos/apps/utils/cmd/dirstack.c b/reactos/apps/utils/cmd/dirstack.c
new file mode 100644 (file)
index 0000000..5c00c21
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ *  DIRSTACK.C - pushd / pop (directory stack) internal commands.
+ *
+ *
+ *  History:
+ *
+ *    14-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Implemented PUSHD and POPD command.
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef FEATURE_DIRECTORY_STACK
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+
+typedef struct tagDIRENTRY
+{
+       struct tagDIRENTRY *next;
+       LPTSTR pszPath;
+} DIRENTRY, *LPDIRENTRY;
+
+
+static INT nStackDepth;
+static LPDIRENTRY lpStackTop;
+
+
+static INT
+PushDirectory (LPTSTR pszPath)
+{
+       LPDIRENTRY lpDir;
+
+       lpDir = (LPDIRENTRY)malloc (sizeof (DIRENTRY));
+       if (!lpDir)
+       {
+               error_out_of_memory ();
+               return -1;
+       }
+
+       lpDir->next = (lpStackTop) ? lpStackTop : NULL;
+       lpStackTop = lpDir;
+
+       lpDir->pszPath = (LPTSTR)malloc ((_tcslen(pszPath)+1)*sizeof(TCHAR));
+       if (!lpDir->pszPath)
+       {
+               free (lpDir);
+               error_out_of_memory ();
+               return -1;
+       }
+
+       _tcscpy (lpDir->pszPath, pszPath);
+
+       nStackDepth++;
+
+       return 0;
+}
+
+
+static VOID
+PopDirectory (VOID)
+{
+       LPDIRENTRY lpDir;
+
+       if (nStackDepth == 0)
+               return;
+
+       lpDir = lpStackTop;
+       lpStackTop = lpDir->next;
+       free (lpDir->pszPath);
+       free (lpDir);
+
+       nStackDepth--;
+}
+
+
+static VOID
+GetDirectoryStackTop (LPTSTR pszPath)
+{
+       if (lpStackTop)
+               _tcsncpy (pszPath, lpStackTop->pszPath, MAX_PATH);
+       else
+               *pszPath = _T('\0');
+}
+
+
+/*
+ * initialize directory stack
+ */
+VOID InitDirectoryStack (VOID)
+{
+       nStackDepth = 0;
+       lpStackTop = NULL;
+}
+
+
+/*
+ * destroy directory stack
+ */
+VOID DestroyDirectoryStack (VOID)
+{
+       while (nStackDepth)
+               PopDirectory ();
+}
+
+
+INT GetDirectoryStackDepth (VOID)
+{
+       return nStackDepth;
+}
+
+
+/*
+ * pushd command
+ */
+INT cmd_pushd (LPTSTR first, LPTSTR rest)
+{
+       TCHAR curPath[MAX_PATH];
+       TCHAR newPath[MAX_PATH];
+       BOOL  bChangePath = FALSE;
+
+       if (!_tcsncmp (rest, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Stores the current directory for use by the POPD command, then\n"
+                         "changes to the specified directory.\n\n"
+                         "PUSHD [path | ..]\n\n"
+                         "  path        Specifies the directory to make the current directory"));
+               return 0;
+       }
+
+       if (rest[0] != _T('\0'))
+       {
+               GetFullPathName (rest, MAX_PATH, newPath, NULL);
+               bChangePath = IsValidPathName (newPath);
+       }
+
+       GetCurrentDirectory (MAX_PATH, curPath);
+       if (PushDirectory (curPath))
+               return -1;
+
+       if (bChangePath)
+               SetCurrentDirectory (newPath);
+
+       return 0;
+}
+
+
+/*
+ * popd command
+ */
+INT cmd_popd (LPTSTR first, LPTSTR rest)
+{
+       TCHAR szPath[MAX_PATH];
+
+       if (!_tcsncmp(rest, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Changes to the directory stored by the PUSHD command.\n\n"
+                                          "POPD"));
+               return 0;
+       }
+
+       if (GetDirectoryStackDepth () == 0)
+               return 0;
+
+       GetDirectoryStackTop (szPath);
+       PopDirectory ();
+
+       SetCurrentDirectory (szPath);
+
+       return 0;
+}
+
+#endif /* FEATURE_DIRECTORY_STACK */
\ No newline at end of file
diff --git a/reactos/apps/utils/cmd/echo.c b/reactos/apps/utils/cmd/echo.c
new file mode 100644 (file)
index 0000000..9d85c5f
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ *  ECHO.C - echo internal 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
+ *
+ *    08-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("/?").
+ *
+ *    19-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+INT cmd_echo (LPTSTR cmd, LPTSTR param)
+{
+#ifdef _DEBUG
+       DebugPrintf ("cmd_echo '%s' : '%s'\n", cmd, param);
+#endif
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts ("Displays messages or switches command echoing on or off.\n\n"
+                                  "ECHO [ON | OFF]\nECHO [message]\n\n"
+                                  "Type ECHO without a parameter to display the current ECHO setting.");
+               return 0;
+       }
+
+       if (_tcsicmp (param, D_OFF) == 0)
+               bEcho = FALSE;
+       else if (_tcsicmp (param, D_ON) == 0)
+               bEcho = TRUE;
+       else if (*param)
+               ConOutPuts (param);
+       else
+               ConOutPrintf (_T("ECHO is %s\n"), bEcho ? D_ON : D_OFF);
+
+       return 0;
+}
diff --git a/reactos/apps/utils/cmd/error.c b/reactos/apps/utils/cmd/error.c
new file mode 100644 (file)
index 0000000..d89fe31
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ *  ERROR.C - error reporting functions.
+ *
+ *
+ *  History:
+ *
+ *    07/12/98 (Rob Lake)
+ *        started
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    24-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Redirection safe!
+ *
+ *    02-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Use FormatMessage() for error reports.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <stdarg.h>
+
+#include "cmd.h"
+
+
+#define INVALID_SWITCH                 _T("Invalid switch - /%c\n")
+#define TOO_MANY_PARAMETERS            _T("Too many parameters - %s\n")
+#define PATH_NOT_FOUND                 _T("Path not found\n")
+#define FILE_NOT_FOUND                 _T("File not found")
+#define REQ_PARAM_MISSING              _T("Required parameter missing\n")
+#define INVALID_DRIVE                  _T("Invalid drive specification\n")
+#define INVALID_PARAM_FORMAT   _T("Invalid parameter format - %s\n")
+#define BADCOMMAND                             _T("Bad command or filename\n")
+#define OUT_OF_MEMORY                  _T("Out of memory error.\n")
+#define CANNOTPIPE                             _T("Error!  Cannot pipe!  Cannot open temporary file!\n")
+
+#define D_PAUSEMSG                             _T("Press any key to continue . . .")
+
+
+
+VOID ErrorMessage (DWORD dwErrorCode, LPTSTR szFormat, ...)
+{
+       TCHAR  szMessage[1024];
+       LPTSTR szError;
+       va_list arg_ptr;
+
+       if (dwErrorCode == ERROR_SUCCESS)
+               return;
+
+       va_start (arg_ptr, szFormat);
+       wvsprintf (szMessage, szFormat, arg_ptr);
+       va_end (arg_ptr);
+
+#if 1
+
+       if (FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+                                          NULL, dwErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                                          (LPTSTR)&szError, 0, NULL))
+       {
+               ConErrPrintf (_T("%s %s\n"), szError, szMessage);
+               LocalFree (szError);
+               return;
+       }
+       else
+       {
+               ConErrPrintf (_T("Unknown error! Error code: 0x%lx\n"), dwErrorCode);
+//             ConErrPrintf (_T("No error message available!\n"));
+               return;
+       }
+
+#else
+
+       switch (dwErrorCode)
+       {
+               case ERROR_FILE_NOT_FOUND:
+                       szError = _T("File not found --");
+                       break;
+
+               case ERROR_PATH_NOT_FOUND:
+                       szError = _T("Path not found --");
+                       break;
+
+               default:
+                       ConErrPrintf (_T("Unknown error! Error code: 0x%lx\n"), dwErrorCode);
+                       return;
+       }
+
+       ConErrPrintf (_T("%s %s\n"), szError, szMessage);
+#endif
+}
+
+
+
+VOID error_invalid_switch (TCHAR ch)
+{
+       ConErrPrintf (INVALID_SWITCH, ch);
+}
+
+
+VOID error_too_many_parameters (LPTSTR s)
+{
+       ConErrPrintf (TOO_MANY_PARAMETERS, s);
+}
+
+
+VOID error_path_not_found (VOID)
+{
+       ConErrPrintf (PATH_NOT_FOUND);
+}
+
+
+VOID error_file_not_found (VOID)
+{
+       ConErrPrintf (FILE_NOT_FOUND);
+}
+
+
+VOID error_sfile_not_found (LPTSTR f)
+{
+       ConErrPrintf (FILE_NOT_FOUND _T(" - %s\n"), f);
+}
+
+
+VOID error_req_param_missing (VOID)
+{
+       ConErrPrintf (REQ_PARAM_MISSING);
+}
+
+
+VOID error_invalid_drive (VOID)
+{
+       ConErrPrintf (INVALID_DRIVE);
+}
+
+
+VOID error_bad_command (VOID)
+{
+       ConErrPrintf (BADCOMMAND);
+}
+
+
+VOID error_no_pipe (VOID)
+{
+       ConErrPrintf (CANNOTPIPE);
+}
+
+
+VOID error_out_of_memory (VOID)
+{
+       ConErrPrintf (OUT_OF_MEMORY);
+}
+
+
+VOID error_invalid_parameter_format (LPTSTR s)
+{
+       ConErrPrintf (INVALID_PARAM_FORMAT, s);
+}
+
+
+VOID error_syntax (LPTSTR s)
+{
+       if (s)
+               ConErrPrintf (_T("Syntax error - %s\n"), s);
+       else
+               ConErrPrintf (_T("Syntax error.\n"));
+}
+
+
+VOID msg_pause (VOID)
+{
+       ConOutPuts (D_PAUSEMSG);
+}
diff --git a/reactos/apps/utils/cmd/filecomp.c b/reactos/apps/utils/cmd/filecomp.c
new file mode 100644 (file)
index 0000000..2f9d538
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ *  FILECOMP.C - handles filename completion.
+ *
+ *
+ *  Comments:
+ *
+ *    30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *       moved from command.c file
+ *       made second TAB display list of filename matches
+ *       made filename be lower case if last character typed is lower case
+ *
+ *    25-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *       Cleanup. Unicode safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+
+#ifdef FEATURE_UNIX_FILENAME_COMPLETION
+
+VOID CompleteFilename (LPTSTR str, INT charcount)
+{
+       WIN32_FIND_DATA file;
+       HANDLE hFile;
+
+       INT   curplace = 0;
+       INT   start;
+       INT   count;
+       BOOL  found_dot = FALSE;
+       BOOL  perfectmatch = TRUE;
+       TCHAR path[MAX_PATH];
+       TCHAR fname[MAX_PATH];
+       TCHAR maxmatch[MAX_PATH] = _T("");
+       TCHAR directory[MAX_PATH];
+
+       /* expand current file name */
+       count = charcount - 1;
+       if (count < 0)
+               count = 0;
+
+       /* find front of word */
+       while (count > 0 && str[count] != _T(' '))
+               count--;
+
+       /* if not at beginning, go forward 1 */
+       if (str[count] == _T(' '))
+               count++;
+
+       start = count;
+
+       /* extract directory from word */
+       _tcscpy (directory, &str[start]);
+       curplace = _tcslen (directory) - 1;
+       while (curplace >= 0 && directory[curplace] != _T('\\') &&
+                  directory[curplace] != _T(':'))
+       {
+               directory[curplace] = 0;
+               curplace--;
+       }
+
+       _tcscpy (path, &str[start]);
+
+       /* look for a '.' in the filename */
+       for (count = _tcslen (directory); path[count] != 0; count++)
+       {
+               if (path[count] == _T('.'))
+               {
+                       found_dot = 1;
+                       break;
+               }
+       }
+
+       if (found_dot)
+               _tcscat (path, _T("*"));
+       else
+               _tcscat (path, _T("*.*"));
+
+       /* current fname */
+       curplace = 0;
+
+       hFile = FindFirstFile (path, &file);
+       if (hFile != INVALID_HANDLE_VALUE)
+       {
+               /* find anything */
+               do
+               {
+                       /* ignore "." and ".." */
+                       if (file.cFileName[0] == _T('.'))
+                               continue;
+
+                       _tcscpy (fname, file.cFileName);
+
+                       if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+                               _tcscat (fname, _T("\\"));
+                       else
+                               _tcscat (fname, _T(" "));
+
+                       if (!maxmatch[0] && perfectmatch)
+                       {
+                               _tcscpy(maxmatch, fname);
+                       }
+                       else
+                       {
+                               for (count = 0; maxmatch[count] && fname[count]; count++)
+                               {
+                                       if (tolower(maxmatch[count]) != tolower(fname[count]))
+                                       {
+                                               perfectmatch = FALSE;
+                                               maxmatch[count] = 0;
+                                               break;
+                                       }
+                               }
+                       }
+               }
+               while (FindNextFile (hFile, &file));
+
+               FindClose (hFile);
+
+               _tcscpy (&str[start], directory);
+               _tcscat (&str[start], maxmatch);
+
+               if (!perfectmatch)
+                       MessageBeep (-1);
+       }
+       else
+       {
+               /* no match found */
+               MessageBeep (-1);
+       }
+}
+
+
+/*
+ * returns 1 if at least one match, else returns 0
+ */
+
+BOOL ShowCompletionMatches (LPTSTR str, INT charcount)
+{
+       WIN32_FIND_DATA file;
+       HANDLE hFile;
+       BOOL  found_dot = FALSE;
+       INT   curplace = 0;
+       INT   start;
+       INT   count;
+       TCHAR path[MAX_PATH];
+       TCHAR fname[MAX_PATH];
+       TCHAR directory[MAX_PATH];
+
+       /* expand current file name */
+       count = charcount - 1;
+       if (count < 0)
+               count = 0;
+
+       /* find front of word */
+       while (count > 0 && str[count] != _T(' '))
+               count--;
+
+       /* if not at beginning, go forward 1 */
+       if (str[count] == _T(' '))
+               count++;
+
+       start = count;
+
+       /* extract directory from word */
+       _tcscpy (directory, &str[start]);
+       curplace = _tcslen (directory) - 1;
+       while (curplace >= 0 && directory[curplace] != _T('\\') &&
+                  directory[curplace] != _T(':'))
+       {
+               directory[curplace] = 0;
+               curplace--;
+       }
+
+       _tcscpy (path, &str[start]);
+
+       /* look for a . in the filename */
+       for (count = _tcslen (directory); path[count] != 0; count++)
+       {
+               if (path[count] == _T('.'))
+               {
+                       found_dot = TRUE;
+                       break;
+               }
+       }
+       if (found_dot)
+               _tcscat (path, _T("*"));
+       else
+               _tcscat (path, _T("*.*"));
+
+       /* current fname */
+       curplace = 0;
+
+       hFile = FindFirstFile (path, &file);
+       if (hFile != INVALID_HANDLE_VALUE)
+       {
+               /* find anything */
+               ConOutChar (_T('\n'));
+               count = 0;
+               do
+               {
+                       /* ignore . and .. */
+                       if (file.cFileName[0] == _T('.'))
+                               continue;
+
+                       if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+                               wsprintf (fname,"[%s]", file.cFileName);
+                       else
+                               _tcscpy (fname, file.cFileName);
+
+                       ConOutPrintf (_T("%-14s"), fname);
+                       if (++count == 5)
+                       {
+                               ConOutChar (_T('\n'));
+                               count = 0;
+                       }
+               }
+               while (FindNextFile (hFile, &file));
+
+               FindClose (hFile);
+
+               if (count)
+                       ConOutChar (_T('\n'));
+       }
+       else
+       {
+               /* no match found */
+               MessageBeep (-1);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+#endif
+
+#ifdef FEATURE_4NT_FILENAME_COMPLETION
+
+//static VOID BuildFilenameMatchList (...)
+
+// VOID CompleteFilenameNext (LPTSTR, INT)
+// VOID CompleteFilenamePrev (LPTSTR, INT)
+
+// VOID RemoveFilenameMatchList (VOID)
+
+#endif
\ No newline at end of file
diff --git a/reactos/apps/utils/cmd/files.txt b/reactos/apps/utils/cmd/files.txt
new file mode 100644 (file)
index 0000000..8f1dfef
--- /dev/null
@@ -0,0 +1,56 @@
+Archive Contents
+~~~~~~~~~~~~~~~~
+bugs.txt        Bug List
+files.txt       This file list
+history.txt     History of the shell development
+license.txt     GNU license - applies to all files named here
+readme.txt      General shell info
+todo.txt        What I have to do
+wishlist.txt    Wish List
+
+makefile        experimental makefile
+makefile.lcc    makefile for lcc-win
+
+alias.c         Alias code
+alias.h         Alias header file
+attrib.c        Implements attrib command
+batch.c         Batch file interpreter
+beep.c          Implements beep command
+call.c          Implements call command
+chcp.c          Implements chcp command
+cls.c           Implements cls command
+cmdinput.c      Command-line input functions
+cmdtable.c      Table of available internal commands
+cmd.c           Main code for command-line interpreter
+cmd.h           Command header file
+color.c         Implements color command
+console.c       Windows console handling code
+copy.c          Implements copy command
+date.c          Implements date command
+del.c           Implements del command
+dir.c           Directory listing code
+dirstack.c      Directory stack code (PUSHD and POPD)
+echo.c          Implements echo command
+error.c         Error Message Routines
+filecomp.c      Filename completion functions
+for.c           Implements for command
+goto.c          Implements goto command
+history.c       Command-line history handling
+if.c            Implements if command
+internal.c      Internal commands (DIR, RD, etc)
+label.c         Implements label command
+locale.c        Locale handling code
+misc.c          Misc. Functions
+move.c          Implements move command
+path.c          Implements path command
+pause.c         Implements pause command
+prompt.c        Prompt handling functions
+redir.c         Redirection and piping parsing functions
+ren.c           Implements rename command
+set.c           Implements set command
+shift.c         Implements shift command
+time.c          Implements time command
+type.c          Implements type command
+ver.c           Implements ver command
+where.c         Code to search path for executables
+verify.c        Implements verify command
\ No newline at end of file
diff --git a/reactos/apps/utils/cmd/for.c b/reactos/apps/utils/cmd/for.c
new file mode 100644 (file)
index 0000000..7ccb445
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ *  FOR.C - for internal batch command.
+ *
+ *
+ *  History:
+ *
+ *    16 Jul 1998 (Hans B Pufal)
+ *        started.
+ *
+ *    16 Jul 1998 (John P Price)
+ *        Seperated commands into individual files.
+ *
+ *    19 Jul 1998 (Hans B Pufal) [HBP_001]
+ *        Implementation of FOR
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+/*
+ * Perform FOR command.
+ *
+ * First check syntax is correct : FOR %v IN ( <list> ) DO <command>
+ *   v must be alphabetic, <command> must not be empty.
+ *
+ * If all is correct build a new bcontext structure which preserves
+ *   the necessary information so that readbatchline can expand
+ *   each the command prototype for each list element.
+ *
+ * You might look on a FOR as being a called batch file with one line
+ *   per list element.
+ */
+
+INT cmd_for (LPTSTR cmd, LPTSTR param)
+{
+       LPBATCH_CONTEXT lpNew;
+       LPTSTR pp;
+       TCHAR  var;
+
+#ifdef _DEBUG
+       DebugPrintf ("cmd_for (\'%s\', \'%s\'\n", cmd, param);
+#endif
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts ("FOR :");
+               return 0;
+       }
+
+       /* Check that first element is % then an alpha char followed by space */
+       if ((*param != _T('%')) || !_istalpha (*(param + 1)) || !_istspace (*(param + 2)))
+       {
+               error_syntax (_T("bad varable specification."));
+               return 1;
+       }
+
+       param++;
+       var = *param++;               /* Save FOR var name */
+
+       while (_istspace (*param))
+               param++;
+
+       /* Check next element is 'IN' */
+       if ((_tcsnicmp (param, _T("in"), 2) != 0) || !_istspace (*(param + 2)))
+       {
+               error_syntax (_T("'in' missing in for statement."));
+               return 1;
+       }
+
+       param += 2;
+       while (_istspace (*param))
+               param++;
+
+       /* Folowed by a '(', find also matching ')' */
+       if ((*param != _T('(')) || (NULL == (pp = _tcsrchr (param, _T(')')))))
+       {
+               error_syntax (_T("no brackets found."));
+               return 1;
+       }
+
+       *pp++ = _T('\0');
+       param++;                /* param now points at null terminated list */
+
+       while (_istspace (*pp))
+               pp++;
+
+       /* Check DO follows */
+       if ((_tcsnicmp (pp, _T("do"), 2) != 0) || !_istspace (*(pp + 2)))
+       {
+               error_syntax (_T("'do' missing."));
+               return 1;
+       }
+
+       pp += 2;
+       while (_istspace (*pp))
+               pp++;
+
+       /* Check that command tail is not empty */
+       if (*pp == _T('\0'))
+       {
+               error_syntax (_T("no command after 'do'."));
+               return 1;
+       }
+
+       /* OK all is correct, build a bcontext.... */
+       lpNew = (LPBATCH_CONTEXT)malloc (sizeof (BATCH_CONTEXT));
+
+       lpNew->prev = bc;
+       bc = lpNew;
+
+       bc->hBatchFile = INVALID_HANDLE_VALUE;
+       bc->ffind = NULL;
+       bc->params = BatchParams (_T(""), param); /* Split out list */
+       bc->shiftlevel = 0;
+       bc->forvar = var;
+       bc->forproto = _tcsdup (pp);
+
+       return 0;
+}
diff --git a/reactos/apps/utils/cmd/goto.c b/reactos/apps/utils/cmd/goto.c
new file mode 100644 (file)
index 0000000..def1cbf
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ *  GOTO.C - goto internal batch command.
+ *
+ *  History:
+ *
+ *    16 Jul 1998 (Hans B Pufal)
+ *        started.
+ *
+ *    16 Jul 1998 (John P Price)
+ *        Seperated commands into individual files.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    28 Jul 1998 (Hans B Pufal) [HBP_003]
+ *        Terminate label on first space character, use only first 8 chars of
+ *        label string
+ *
+ *    24-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection safe!
+ *
+ *    27-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("/?").
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+/*
+ * Perform GOTO command.
+ *
+ * Only valid if batch file current.
+ *
+ */
+
+INT cmd_goto (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR tmp;
+       LONG   lNewPosHigh;
+
+#ifdef _DEBUG
+       DebugPrintf ("cmd_goto (\'%s\', \'%s\'\n", cmd, param);
+#endif
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Directs CMD to a labeled line in a batch script.\n"
+                                          "\n"
+                                          "GOTO label\n"
+                                          "\n"
+                                          "  label  Specifies a text string used in a batch script as a label.\n"
+                                          "\n"
+                                          "You type a label on a line by itself, beginning with a colon."));
+               return 0;
+       }
+
+       /* if not in batch -- error!! */
+       if (bc == NULL)
+       {
+               return 1;
+       }
+
+       if (*param == _T('\0'))
+       {
+               ExitBatch (_T("No label specified for GOTO\n"));
+               return 1;
+       }
+
+       /* terminate label at first space char */
+       tmp = param;
+       while (*tmp && !_istspace (*tmp))
+               tmp++;
+       *tmp = _T('\0');
+
+       /* set file pointer to the beginning of the batch file */
+       lNewPosHigh = 0;
+       SetFilePointer (bc->hBatchFile, 0, &lNewPosHigh, FILE_BEGIN);
+
+       while (FileGetString (bc->hBatchFile, textline, sizeof(textline)))
+       {
+               /* Strip out any trailing spaces or control chars */
+               tmp = textline + _tcslen (textline) - 1;
+               while (_istcntrl (*tmp) || _istspace (*tmp))
+                       tmp--;
+               *(tmp + 1) = _T('\0');
+
+               /* Then leading spaces... */
+               tmp = textline;
+               while (_istspace (*tmp))
+                       tmp++;
+
+               /* use only 1st 8 chars of label */
+               if ((*tmp == _T(':')) && (_tcsncmp (++tmp, param, 8) == 0))
+                       return 0;
+       }
+
+       ConErrPrintf (_T("Label '%s' not found\n"), param);
+       ExitBatch (NULL);
+
+       return 1;
+}
diff --git a/reactos/apps/utils/cmd/history.c b/reactos/apps/utils/cmd/history.c
new file mode 100644 (file)
index 0000000..2e48d59
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ *  HISTORY.C - command line history.
+ *
+ *
+ *  History:
+ *
+ *    14/01/95 (Tim Norman)
+ *        started.
+ *
+ *    08/08/95 (Matt Rains)
+ *        i have cleaned up the source code. changes now bring this source
+ *        into guidelines for recommended programming practice.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    25-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Cleanup!
+ *        Unicode and redirection safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef FEATURE_HISTORY
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+#define MAXLINES 128
+
+static INT history_size = 2048;    /* make this configurable later */
+
+
+VOID History (INT dir, LPTSTR commandline)
+{
+       static LPTSTR history = NULL;
+       static LPTSTR lines[MAXLINES];
+       static INT curline = 0;
+       static INT numlines = 0;
+       static INT maxpos = 0;
+       INT count;
+       INT length;
+
+       if (!history)
+       {
+               history = malloc (history_size * sizeof (TCHAR));
+               lines[0] = history;
+               history[0] = 0;
+       }
+
+       if (dir > 0)
+       {
+               /* next command */
+               if (curline < numlines)
+               {
+                       curline++;
+               }
+
+               if (curline == numlines)
+               {
+                       commandline[0] = 0;
+               }
+               else
+               {
+                       _tcscpy (commandline, lines[curline]);
+               }
+       }
+       else if (dir < 0)
+       {
+               /* prev command */
+               if (curline > 0)
+               {
+                       curline--;
+               }
+
+               _tcscpy (commandline, lines[curline]);
+       }
+       else
+       {
+               /* add to history */
+               /* remove oldest string until there's enough room for next one */
+               /* strlen (commandline) must be less than history_size! */
+               while ((maxpos + (INT)_tcslen (commandline) + 1 > history_size) || (numlines >= MAXLINES))
+               {
+                       length = _tcslen (lines[0]) + 1;
+
+                       for (count = 0; count < maxpos && count + (lines[1] - lines[0]) < history_size; count++)
+                       {
+                               history[count] = history[count + length];
+                       }
+
+                       maxpos -= length;
+
+                       for (count = 0; count <= numlines && count < MAXLINES; count++)
+                       {
+                               lines[count] = lines[count + 1] - length;
+                       }
+
+                       numlines--;
+#ifdef DEBUG
+                       ConOutPrintf (_T("Reduced size:  %ld lines\n"), numlines);
+
+                       for (count = 0; count < numlines; count++)
+                       {
+                               ConOutPrintf (_T("%d: %s\n"), count, lines[count]);
+                       }
+#endif
+               }
+
+               _tcscpy (lines[numlines], commandline);
+               numlines++;
+               lines[numlines] = lines[numlines - 1] + _tcslen (commandline) + 1;
+               maxpos += _tcslen (commandline) + 1;
+               /* last line, empty */
+               curline = numlines;
+       }
+
+       return;
+}
+
+#endif
diff --git a/reactos/apps/utils/cmd/history.txt b/reactos/apps/utils/cmd/history.txt
new file mode 100644 (file)
index 0000000..7b0769b
--- /dev/null
@@ -0,0 +1,345 @@
+FreeDOS Command Line Interface Development History
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+11/11/94 version 0.01
+~~~~~~~~~~~~~~~~~~~~~
+o  initial release.
+
+01/01/95 version 0.10
+~~~~~~~~~~~~~~~~~~~~~
+o  removed some scaffolding.
+o  modified CD.
+o  added tab file completion.
+o  added command line history.
+
+01/15/95 version 0.20
+~~~~~~~~~~~~~~~~~~~~~
+o  formatted all existing source modules.
+o  added prompt support.
+o  added drive selection.
+o  added dir command.
+o  started this development log.
+
+08/06/95 prerelease of version 0.30
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+o  reorganized code into separate source modules.
+o  added batch processing support (thanks to Evan Jeffrey).
+o  added exec code (thanks to Steffan Kaiser).
+o  removed environment handling (thanks again to Steffan Kaiser)
+
+        [ 08/08/95 -- Matt Rains ]
+o  formatted this development log.
+o  formatted all existing source modules so that they comply with recommended
+        programming practice.
+o  added MD command.
+o  added RD command.
+o  added VER command.
+o  replaced CD command.
+o  modified DIR command.
+o  DIR now called regardless of other DIR.??? files. this is done because of
+        exec() problems.
+
+12/10/95 version 0.30
+~~~~~~~~~~~~~~~~~~~~~
+o  used Borland's spawnve to fix exec problem
+o  fixed CD again so you don't need a space after it
+o  couple of spelling fixes
+
+12/14/95 version 0.31
+~~~~~~~~~~~~~~~~~~~~~
+o  modified cmdinput.c to work with non-standard screen sizes (see 28.com)
+o  fixed a bug in history.c that made it not work when you hit the up arrow
+   on the first line
+o  fixed DIR to work a little more like MS-DOS's DIR (see internal.c)
+o  fixed some code in where.c to make things a bit more efficient and nicer
+
+01/06/96 version 0.40  (never released)
+~~~~~~~~~~~~~~~~~~~~~
+o  added redirection and piping support!!!  (see redir.c and command.c)
+o  fixed a stupid pointer problem in where.c that was causing LOTS of
+   problems in the strangest places...
+o  added day of the week support to prompt.c (oops, that was already supposed
+   to be there! :)
+o  fixed and reorganized the EXEC code!!!  Thanks to Svante Frey!
+o  reorganized command.c and internal.c to handle parsing internal commands
+   more efficiently and consistently.
+o  changed the behavior of MD, CD, RD to work without spaces (e.g. CD\DOS)
+o  small changes here and there to make it work with redirection/piping
+   (e.g. DIR only pauses if you're not doing redirection)
+
+01/17/96 version 0.50
+~~~~~~~~~~~~~~~~~~~~~
+Version 0.40 was never released because I was home on Christmas vacation,
+and I couldn't upload it.  By the time I got back to school, I had the
+LOADHIGH patch from Svante Frey, so I decided to jump up to 0.50 without any
+release of 0.40...       - Tim Norman
+
+o  LOADHIGH/LOADFIX/LH support added!!!!  Many thanks go to Svante Frey!
+o  bug fixed in command parsing that didn't handle / switches correctly...
+o  removed debugging output from history.c
+
+07/26/96 version 0.60
+~~~~~~~~~~~~~~~~~~~~~
+Lots of internal changes here...  Not much added to the interface.
+
+o  Changed internals to use first,rest parameters instead of arrays of params
+o  Fixed some bugs
+o  Some other things I don't remember :)
+
+07/26/96 version 0.61
+~~~~~~~~~~~~~~~~~~~~~
+Bugfixes
+
+o  Added hook to the PATH command
+o  Fixed CD.. bug
+
+08/27/96 version 0.70
+~~~~~~~~~~~~~~~~~~~~~
+Finally added Oliver Mueller's ALIAS command!  Also numerous bug fixes.
+
+o  Added ALIAS command
+o  Removed support for - as a switch in LOADHIGH.C
+o  Bugfixes in BATCH.C.  %0 was returning garbage
+o  Removed lots of unused variables, reducing # of warnings when compiling
+o  Other miscellaneous code clean-ups
+o  Changed WHERE.C to use a little less memory
+
+06/14/97 version 0.71
+~~~~~~~~~~~~~~~~~~~~~
+Lots of bug fixes, plus some additional features.
+
+o  New DIR command.  Now more like MS-DOS's DIR.  /p supported, /s coming soon
+o  bug fix in internal.c - parse_firstarg
+o  Rewrote parser in batch.c (Steffan Kaiser)
+o  Ctrl-Break checking in various places (Steffan Kaiser)
+o  Error level setting/checking (%? in batch files) (Steffan Kaiser)
+o  bug fix in cmdinput.c ("%i" on command-line caused weird behavior)
+o  bug fix in where.c (first item in path wasn't searched)
+
+07/12/97 version 0.72
+~~~~~~~~~~~~~~~~~~~~~
+More bug fixes and code cleanup
+
+o  Rewrote cmdinput.c to be more efficient (Marc Desrochers)
+o  Added insert/overstrike modes (Marc Desrochers)
+o  Replaced findxy() with pointers into BIOS (maxx, maxy) (Marc Desrochers)
+o  Fixed bug that disallowed listing of root directories
+o  Fixed bug that didn't search the first path (again!)
+
+07/13/97 version 0.72b
+~~~~~~~~~~~~~~~~~~~~~~
+Disabled a feature that caused a crash on some machines.
+
+o  Replaced setcursor calls in cmdinput.c with _setcursortype
+o  Added dir.c to the distribution (was left out in 0.72)
+
+07/01/98 version 0.73 (Rob Lake)
+~~~~~~~~~~~~~~~~~~~~~~
+o New DIR commands supported: /S, /B, /L, /A and /W.
+  (/R changed to /S).  Also /? added.
+o Supports DIRCMD in environment.
+o Supports turning off commands with hyphen (ex. /-S
+  turns off recursive listing)
+o Changed error messages for DIR and DEL to more MS-DOS'ish
+o Moved error messages from DIR.C and DEL.C to COMMAND.H
+  (more may go there soon)
+o Fixed bug that caused dir *.ext/X not to work (no spaces
+  between filespec and slash)
+o Added wildcard support for DEL command
+o Added prompt and help switch for DEL command, /P and /?
+  respectively.
+o Added support for /C when envoking the shell
+o Added /P support when Kernel loads shell.  This means
+  the shell now is permanent and runs the autoexec.bat
+  (/E is not implemented)
+o Added my name (Rob Lake) to the developer listing
+o Changed version routine to print out copyright notice
+  with no args, and with appropriate switches, warranty
+  and redistribution notices and developer listing
+
+07/08/1998 version 0.74 (John P. Price (linux-guru@gcfl.net))
+~~~~~~~~~~~~~~~~~~~~~~~~
+COMMAND.C/COMMAND.H:
+o Now sets COMSPEC environment variable
+o misc clean up and optimization
+o added date, time and type commands
+o changed to using spawnl instead of exec.  exec does not copy the
+  environment to the child process!
+DIR.C
+o removed extra returns; closer to MSDOS
+o fixed wide display so that an extra return is not displayed when
+  there is five filenames in the last line.
+ENVIRON.C
+o commented out show_environment function.  Not used anymore.
+INTERAL.C
+o removed call to show_environment in set command.
+o moved test for syntax before allocating memory in set command.
+o misc clean up and optimization.
+
+o created DATE.C
+o created TIME.C
+o created TYPE.C
+
+07/08/1998 version 0.74b (John P. Price (linux-guru@gcfl.net))
+~~~~~~~~~~~~~~~~~~~~~~~~
+COMMAND.C
+o fixed call to spawnl so that it would pass command line arguments
+  correctly.
+
+07/12/98 version 0.74c (Rob Lake rlake@cs.mun.ca)
+~~~~~~~~~~~~~~~~~~~~~~
+Various Files:
+o removed redundant use of error message defines and moved
+  error printing calls to ERROR.C to reduced program size.
+
+o created MISC.C
+o created ERR_HAND.C/H
+o created ERROR.C
+
+07/13/98 version 0.74d (Rob Lake rlake@cs.mun.ca)
+~~~~~~~~~~~~~~~~~~~~~~
+INTERNAL.C
+o removed most of the commands and placed them in there own file
+  -- del, ren, set and ver
+o created DEL.C, REN.C SET.C and VER.C
+o fixed bug that caused del not to delete files with no attributes
+o the critical error handler count number of times called, autofails
+  at 5 calls
+
+
+16 Jul 1998 (Hans B Pufal <hansp@digiweb.com>)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+batch.c
+  A new version, implements CALL, ECHO, GOT, IF, PAUSE, SHIFT and
+  BEEP. There is a stub for FOR but that's all.
+
+cmdtable.c
+  New file to keep the internal command table. I plan on getting rid
+  of the table real soon now and replacing it with a dynamic
+  mechanism.
+
+command.c
+  A new (improved ;) version. Conforms closely to MS-DOS specs.
+  Cleaned up (and fixed) the redirection handler.
+
+command.h
+  Version D with changes. Look for the HBP tag.
+
+redir.c
+  Modified file, now supports append redirects.
+
+
+16 Jul 1998 (Rob Lake rlake@cs.mun.ca)
+~~~~~~~~~~~~~~~~~~~~~~
+Added TRUENAME command.
+
+
+19 Jul 1998 (Hans B Pufal) <hansp@digiweb.com>)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+o Preserve state of echo flag across batch calls.
+o Implementation of FOR command
+
+
+20 Jul 1998 (John P Price <linux-guru@gcfl.net>)
+~~~~~~~~~~~~~~~~~~~~~~
+o Fixed bug in DATE.C.
+o Fixed bug in LH.ASM.
+o Separated commands into individual files.
+
+
+28 Jul 1998 (John P Price <linux-guru@gcfl.net>)
+~~~~~~~~~~~~~~~~~~~~~~
+o Added CLS command.
+o Put ifdef's around all commands and added include file config.h
+  Now you can define exact what commands you want to include in
+  command.com.
+o Also added ifdefs for optional features: aliases, command history
+  and filename completion.
+o Added display of available internal commands and options at startup.
+
+
+29 Jul 1998 (Rob Lake rlake@cs.mun.ca)
+~~~~~~~~~~~~~~~~~~~~~~
+o changed date.c and time.c, and wrote datefunc.c and timefunc.c to
+  impliment _dos_getdate, _dos_setdate, _dos_gettime and _dos_settime.
+  This is the first of many steps to make the shell compatible under
+  Pacific C.
+
+30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+~~~~~~~~~~~~~~~~~~~~~~
+o Changed filename completion so that a second TAB displays a list of
+  matching filenames!
+o made filename be lower case if last character typed is lower case.
+o Moved filename completion code to filecomp.c.
+o Change ver command to display email address to report bugs, and the
+  web page address for updates.
+o fixed so that it find_which returns NULL if filename is not
+  executable (does not have .bat, .com, or .exe extension).  Before
+  command would to execute any file with any extension. (opps!)
+
+30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+~~~~~~~~~~~~~~~~~~~~~~
+o Fixed bug where if you typed something, then hit HOME, then tried to
+  type something else in insert mode, it locked up.
+o Changed default insert mode to on.  There should be a way to change
+  this.  Maybe options to doskey command.
+o Added VERIFY command
+
+02-Aug-1998 (Hans B Pufal) <hansp@digiweb.com>)
+~~~~~~~~~~~~~~~~~~~~~~
+o batch.c: Fixed bug in ECHO flag restoration at exit from batch file
+o command.c: Fixed return value when called with /C option
+o Terminate label on first space character, use only first 8 chars of
+  label string
+
+04-Aug-1998 (Hans B Pufal) <hansp@digiweb.com>)
+~~~~~~~~~~~~~~~~~~~~~~
+o call.c: added lines to initialize for pointers.  This fixed the
+  lock-up that happened sometimes when calling a batch file from
+  another batch file.
+
+07-Aug-1998 (John P Price <linux-guru@gcfl.net>)
+~~~~~~~~~~~~~~~~~~~~~~
+o Fixed carrage return output to better match MSDOS with echo on or off.
+
+
+07-Dec-1998 ReactOS CMD version 0.0.1 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+o First test release.
+o Added internal ATTRIB command.
+
+11-Dec-1998 ReactOS CMD version 0.0.2 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+o Fixed bug in ALIAS. CMD crashed when you tried to remove an alias.
+o Fixed bug in split(). Added freep(). This fixed the DEL command.
+o Improved ATTRIB command.
+o Added most help texts.
+o Fixed recursive DIR ("dir /s").
+o Fixed DATE and TIME command. Now they accept values when used
+  without parameter.
+o Implemented LABEL command.
+
+05-Jan-1999 ReactOS CMD version 0.0.3 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+o Added COLOR command and "/t" option.
+o Cursor shows insert/overwrite mode.
+o COMSPEC environment variable is set upon startup.
+o Started COPY command.
+o Started MOVE command.
+o Added directory stack (PUSHD and POPD commands).
+o Added support for file names or paths that contain spaces
+  (quoted paths / file names).
+o Added recursion to ATTRIB command.
+o Added locale support for DIR, DATE, TIME and PROMPT.
+o Fixed VERIFY.
+
+10-Feb-1999 ReactOS CMD version 0.0.4 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+o "?" lists all available commands.
+o Most commands are unicode and redirection aware now.
+o Input-, Output- and Error-Redirections works with most commands.
+o ATTRIB and DEL can handle multiple filenames now.
+o Fixed handling of environment variables.
+o Added CHCP command.
+o Fixed keyboard input bug.
+o Rewrote DEL and MOVE commands.
\ No newline at end of file
diff --git a/reactos/apps/utils/cmd/if.c b/reactos/apps/utils/cmd/if.c
new file mode 100644 (file)
index 0000000..64744bc
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ *  IF.C - if internal batch command.
+ *
+ *
+ *  History:
+ *
+ *    16 Jul 1998 (Hans B Pufal)
+ *        started.
+ *
+ *    16 Jul 1998 (John P Price)
+ *        Seperated commands into individual files.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    07-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("if /?") and cleaned up.
+ *
+ *    21-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+#define X_EXEC 1
+#define X_EMPTY 0x80
+
+
+INT cmd_if (LPTSTR cmd, LPTSTR param)
+{
+       INT x_flag = 0; /* when set cause 'then' clause to be executed */
+       LPTSTR pp;
+
+#ifdef _DEBUG
+       DebugPrintf ("cmd_if: (\'%s\', \'%s\'\n", cmd, param);
+#endif
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("IF :"));
+               return 0;
+       }
+
+       /* First check if param string begins with word 'not' */
+       if (!_tcsnicmp (param, _T("not"), 3) && _istspace (*(param + 3)))
+       {
+               x_flag = X_EXEC;            /* Remember 'NOT' */
+               param += 3;                 /* Step over 'NOT' */
+               while (_istspace (*param))  /* And subsequent spaces */
+                       param++;
+       }
+
+       /* Check for 'exist' form */
+       if (!_tcsnicmp (param, _T("exist"), 5) && _istspace (*(param + 5)))
+       {
+               param += 5;
+               while (_istspace (*param))
+                       param++;
+
+               pp = param;
+               while (*pp && !_istspace (*pp))
+                       pp++;
+
+               if (*pp)
+               {
+                       WIN32_FIND_DATA f;
+                       HANDLE hFind;
+
+                       *pp++ = _T('\0');
+                       hFind = FindFirstFile (param, &f);
+                       x_flag ^= (hFind != INVALID_HANDLE_VALUE) ? 0 : X_EXEC;
+                       if (hFind != INVALID_HANDLE_VALUE)
+                               FindClose (hFind);
+               }
+               else
+                       return 0;
+       }
+
+       /* Check for 'errorlevel' form */
+       else if (!_tcsnicmp (param, _T("errorlevel"), 10) && _istspace (*(param + 10)))
+       {
+               INT n = 0;
+
+               pp = param + 10;
+               while (_istspace (*pp))
+                       pp++;
+
+               while (_istdigit (*pp))
+                       n = n * 10 + (*pp++ - _T('0'));
+
+               x_flag ^= (errorlevel < n) ? 0 : X_EXEC;
+
+               x_flag |= X_EMPTY;          /* Syntax error if comd empty */
+       }
+
+       /* Check that '==' is present, syntax error if not */
+       else if (NULL == (pp = _tcsstr (param, _T("=="))))
+       {
+               error_syntax (NULL);
+               return 1;
+       }
+
+       else
+       {
+               /* Change first '='to space to terminate comparison loop */
+
+               *pp = _T(' ');   /* Need a space to terminate comparison loop */
+               pp += 2;                /* over '==' */
+               while (_istspace (*pp)) /* Skip subsequent spaces */
+                       pp++;
+
+               _tcscat (pp, _T(" "));  /* Add one space to ensure comparison ends */
+
+               while (*param == *pp)       /* Comparison loop */
+               {
+                       if (_istspace (*param))      /* Terminates on space */
+                               break;
+
+                       param++, pp++;
+               }
+
+               if (x_flag ^= (*param != *pp) ? 0 : X_EXEC)
+               {
+                       while (*pp && !_istspace (*pp))  /* Find first space, */
+                               pp++;
+
+                       x_flag |= X_EMPTY;
+               }
+       }
+
+       if (x_flag & X_EMPTY)
+       {
+               while (_istspace (*pp)) /* Then skip spaces */
+                       pp++;
+
+               if (*pp == _T('\0'))    /* If nothing left then syntax err */
+               {
+                       error_syntax (NULL);
+                       return 1;
+               }
+       }
+
+       if (x_flag & X_EXEC)
+               ParseCommandLine (pp);
+
+       return 0;
+}
diff --git a/reactos/apps/utils/cmd/internal.c b/reactos/apps/utils/cmd/internal.c
new file mode 100644 (file)
index 0000000..b2019f7
--- /dev/null
@@ -0,0 +1,485 @@
+/*
+ *  INTERNAL.C - command.com internal commands.
+ *
+ *
+ *  History:
+ *
+ *  17/08/94 (Tim Norman)
+ *    started.
+ *
+ *  08/08/95 (Matt Rains)
+ *    i have cleaned up the source code. changes now bring this source into
+ *    guidelines for recommended programming practice.
+ *
+ *  cd()
+ *    started.
+ *
+ *  dir()
+ *    i have added support for file attributes to the DIR() function. the
+ *    routine adds "d" (directory) and "r" (read only) output. files with the
+ *    system attribute have the filename converted to lowercase. files with
+ *    the hidden attribute are not displayed.
+ *
+ *    i have added support for directorys. now if the directory attribute is
+ *    detected the file size if replaced with the string "<dir>".
+ *
+ *  ver()
+ *    started.
+ *
+ *  md()
+ *    started.
+ *
+ *  rd()
+ *    started.
+ *
+ *  del()
+ *    started.
+ *
+ *  does not support wildcard selection.
+ *
+ *  todo: add delete directory support.
+ *        add recursive directory delete support.
+ *
+ *  ren()
+ *    started.
+ *
+ *  does not support wildcard selection.
+ *
+ *    todo: add rename directory support.
+ *
+ *  a general structure has been used for the cd, rd and md commands. this
+ *  will be better in the long run. it is too hard to maintain such diverse
+ *  functions when you are involved in a group project like this.
+ *
+ *  12/14/95 (Tim Norman)
+ *    fixed DIR so that it will stick \*.* if a directory is specified and
+ *    that it will stick on .* if a file with no extension is specified or
+ *    *.* if it ends in a \
+ *
+ *  1/6/96 (Tim Norman)
+ *    added an isatty call to DIR so it won't prompt for keypresses unless
+ *    stdin and stdout are the console.
+ *
+ *    changed parameters to be mutually consistent to make calling the
+ *    functions easier
+ *
+ *  rem()
+ *    started.
+ *
+ *  doskey()
+ *    started.
+ *
+ *    01/22/96 (Oliver Mueller)
+ *        error messages are now handled by perror.
+ *
+ *    02/05/96 (Tim Norman)
+ *        converted all functions to accept first/rest parameters
+ *
+ *    07/26/96 (Tim Norman)
+ *        changed return values to int instead of void
+ *
+ *        path() started.
+ *
+ *    12/23/96 (Aaron Kaufman)
+ *        rewrote dir() to mimic MS-DOS's dir
+ *
+ *    01/28/97 (Tim Norman)
+ *        cleaned up Aaron's DIR code
+ *
+ *    06/13/97 (Tim Norman)
+ *        moved DIR code to dir.c
+ *        re-implemented Aaron's DIR code
+ *
+ *    06/14/97 (Steffan Kaiser)
+ *        ctrl-break handling
+ *        bug fixes
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    03-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Replaced DOS calls by Win32 calls.
+ *
+ *    08-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help texts ("/?").
+ *
+ *    18-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added support for quoted arguments (cd "program files").
+ *
+ *    07-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Clean up.
+ *
+ *    26-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Replaced remaining CRT io functions by Win32 io functions.
+ *        Unicode safe!
+ *
+ *    30-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added "cd -" feature. Changes to the previous directory.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+
+extern COMMAND cmds[]; /* The internal command table, used in '?' */
+
+
+#ifdef INCLUDE_CMD_CHDIR
+
+static LPTSTR lpLastPath;
+
+
+VOID InitLastPath (VOID)
+{
+       lpLastPath = NULL;
+}
+
+
+VOID FreeLastPath (VOID)
+{
+       if (lpLastPath)
+               free (lpLastPath);
+}
+
+
+/*
+ * CD / CHDIR
+ *
+ */
+INT cmd_chdir (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR dir;             /* pointer to the directory to change to */
+       LPTSTR place;   /* used to search for the \ when no space is used */
+       LPTSTR lpOldPath;
+       LPTSTR *arg = NULL;
+       INT argc;
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Changes the current directory or displays it's name\n\n"
+                                          "CHDIR [drive:][path]\n"
+                                          "CHDIR[..|-]\n"
+                                          "CD [drive:][path]\n"
+                                          "CD[..|-]\n\n"
+                                          "  ..   parent directory\n"
+                                          "  -    previous directory\n\n"
+                                          "Type CD drive: to display the current directory on the specified drive.\n"
+                                          "Type CD without a parameter to display the current drive and directory."));
+               return 0;
+       }
+
+       /* check if there is no space between the command and the path */
+       if (param[0] == _T('\0'))
+       {
+               /* search for the '\', '.' or '-' so that both short & long names will work */
+               for (place = cmd; *place; place++)
+                       if (*place == _T('.') || *place == _T('\\') || *place == _T('-'))
+                               break;
+
+               if (*place)
+                       dir = place;
+               else
+                       /* signal that there are no parameters */
+                       dir = NULL;
+       }
+       else
+       {
+               arg = split (param, &argc);
+
+               if (argc > 1)
+               {
+                       /*JPP 20-Jul-1998 use standard error message */
+                       error_too_many_parameters (param);
+                       freep (arg);
+                       return 1;
+               }
+               else
+                       dir = arg[0];
+       }
+
+       /* if doing a CD and no parameters given, print out current directory */
+       if (!dir || !dir[0])
+       {
+               TCHAR szPath[MAX_PATH];
+
+               GetCurrentDirectory (MAX_PATH, szPath);
+
+               ConOutPuts (szPath);
+
+               freep (arg);
+
+               return 0;
+       }
+
+       if (dir && _tcslen (dir) == 1 && *dir == _T('-'))
+       {
+               if (lpLastPath)
+                       dir = lpLastPath;
+               else
+               {
+                       freep (arg);
+                       return 0;
+               }
+       }
+       else if (dir && _tcslen (dir) > 1 && dir[1] == _T(':'))
+       {
+               TCHAR szRoot[3] = _T("A:");
+               TCHAR szPath[MAX_PATH];
+
+               szRoot[0] = _totupper (dir[0]);
+               GetFullPathName (szRoot, MAX_PATH, szPath, NULL);
+
+               /* PathRemoveBackslash */
+               if (_tcslen (szPath) > 3)
+               {
+                       LPTSTR p = _tcsrchr (szPath, _T('\\'));
+                       *p = _T('\0');
+               }
+
+               ConOutPuts (szPath);
+
+               freep (arg);
+
+               return 0;
+       }
+
+       /* remove trailing \ if any, but ONLY if dir is not the root dir */
+       if (_tcslen (dir) >= 2 && dir[_tcslen (dir) - 1] == _T('\\'))
+               dir[_tcslen(dir) - 1] = _T('\0');
+
+
+       /* store current directory */
+       lpOldPath = (LPTSTR)malloc (MAX_PATH * sizeof(TCHAR));
+       GetCurrentDirectory (MAX_PATH, lpOldPath);
+
+       if (!SetCurrentDirectory (dir))
+       {
+               ErrorMessage (GetLastError(), _T("CD"));
+
+               /* throw away current directory */
+               free (lpOldPath);
+               lpOldPath = NULL;
+
+               freep (arg);
+               return 1;
+       }
+       else
+       {
+               if (lpLastPath)
+                       free (lpLastPath);
+               lpLastPath = lpOldPath;
+       }
+
+       freep (arg);
+
+       return 0;
+}
+#endif
+
+
+
+#ifdef INCLUDE_CMD_MKDIR
+/*
+ * MD / MKDIR
+ *
+ */
+INT cmd_mkdir (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR dir;             /* pointer to the directory to change to */
+       LPTSTR place;   /* used to search for the \ when no space is used */
+       LPTSTR *p = NULL;
+       INT argc;
+
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Creates a directory.\n\n"
+                                          "MKDIR [drive:]path\nMD [drive:]path"));
+               return 0;
+       }
+
+
+       /* check if there is no space between the command and the path */
+       if (param[0] == _T('\0'))
+       {
+               /* search for the \ or . so that both short & long names will work */
+               for (place = cmd; *place; place++)
+                       if (*place == _T('.') || *place == _T('\\'))
+                               break;
+
+               if (*place)
+                       dir = place;
+               else
+                       /* signal that there are no parameters */
+                       dir = NULL;
+       }
+       else
+       {
+               p = split (param, &argc);
+               if (argc > 1)
+               {
+                       /*JPP 20-Jul-1998 use standard error message */
+                       error_too_many_parameters (param);
+                       freep (p);
+                       return 1;
+               }
+               else
+                       dir = p[0];
+       }
+
+       /* remove trailing \ if any, but ONLY if dir is not the root dir */
+       if (_tcslen (dir) >= 2 && dir[_tcslen (dir) - 1] == _T('\\'))
+               dir[_tcslen(dir) - 1] = _T('\0');
+
+       if (!CreateDirectory (dir, NULL))
+       {
+               ErrorMessage (GetLastError(), _T("MD"));
+
+               freep (p);
+               return 1;
+       }
+
+       freep (p);
+
+       return 0;
+}
+#endif
+
+
+#ifdef INCLUDE_CMD_RMDIR
+/*
+ * RD / RMDIR
+ *
+ */
+INT cmd_rmdir (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR dir;             /* pointer to the directory to change to */
+       LPTSTR place;   /* used to search for the \ when no space is used */
+
+       LPTSTR *p = NULL;
+       INT argc;
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Removes a directory.\n\n"
+                                          "RMDIR [drive:]path\nRD [drive:]path"));
+               return 0;
+       }
+
+       /* check if there is no space between the command and the path */
+       if (param[0] == _T('\0'))
+       {
+               /* search for the \ or . so that both short & long names will work */
+               for (place = cmd; *place; place++)
+                       if (*place == _T('.') || *place == _T('\\'))
+                               break;
+
+               if (*place)
+                       dir = place;
+               else
+                       /* signal that there are no parameters */
+                       dir = NULL;
+       }
+       else
+       {
+               p = split (param, &argc);
+               if (argc > 1)
+               {
+                       /*JPP 20-Jul-1998 use standard error message */
+                       error_too_many_parameters (param);
+                       freep (p);
+                       return 1;
+               }
+               else
+                       dir = p[0];
+       }
+
+       /* remove trailing \ if any, but ONLY if dir is not the root dir */
+       if (_tcslen (dir) >= 2 && dir[_tcslen (dir) - 1] == _T('\\'))
+               dir[_tcslen(dir) - 1] = _T('\0');
+
+       if (!RemoveDirectory (dir))
+       {
+               ErrorMessage (GetLastError(), _T("RD"));
+               freep (p);
+
+               return 1;
+       }
+
+       freep (p);
+
+       return 0;
+}
+#endif
+
+
+/*
+ * set the exitflag to true
+ *
+ */
+INT internal_exit (LPTSTR cmd, LPTSTR param)
+{
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Exits the command line interpreter.\n\nEXIT"));
+       }
+       else
+       {
+               bExit = TRUE;
+       }
+
+       return 0;
+}
+
+
+#ifdef INCLUDE_CMD_REM
+/*
+ * does nothing
+ *
+ */
+INT cmd_rem (LPTSTR cmd, LPTSTR param)
+{
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Starts a comment line in a batch file.\n\n"
+                                          "REM [Comment]"));
+       }
+
+       return 0;
+}
+#endif
+
+
+INT cmd_showcommands (LPTSTR cmd, LPTSTR param)
+{
+       LPCOMMAND cmdptr;
+       INT y;
+
+       y = 0;
+       cmdptr = cmds;
+       while (cmdptr->name)
+       {
+               if (++y == 8)
+               {
+                       ConOutPuts (cmdptr->name);
+                       y = 0;
+               }
+               else
+                       ConOutPrintf (_T("%-10s"), cmdptr->name);
+
+               cmdptr++;
+       }
+
+       if (y != 0)
+               ConOutChar (_T('\n'));
+
+       return 0;
+}
diff --git a/reactos/apps/utils/cmd/label.c b/reactos/apps/utils/cmd/label.c
new file mode 100644 (file)
index 0000000..2854219
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ *  LABEL.C - label internal command.
+ *
+ *
+ *  History:
+ *
+ *    10-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Started.
+ *
+ *    11-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Finished.
+ *
+ *    19-Jan-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_LABEL
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+
+INT cmd_label (LPTSTR cmd, LPTSTR param)
+{
+       TCHAR  szRootPath[] = _T("A:\\");
+       TCHAR  szLabel[80];
+       TCHAR  szOldLabel[80];
+       DWORD  dwSerialNr;
+       LPTSTR *arg;
+       INT    args;
+
+       /* set empty label string */
+       szLabel[0] = _T('\0');
+
+       /* print help */
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Displays or changes drive label.\n\n"
+                                          "LABEL [drive:][label]"));
+               return 0;
+       }
+
+       /* get parameters */
+       arg = split (param, &args);
+
+       if (args > 2)
+       {
+               /* too many parameters */
+               error_too_many_parameters (arg[args - 1]);
+               freep (arg);
+               return 1;
+       }
+
+       if (args == 0)
+       {
+               /* get label of current drive */
+               TCHAR szCurPath[MAX_PATH];
+               GetCurrentDirectory (MAX_PATH, szCurPath);
+               szRootPath[0] = szCurPath[0];
+       }
+       else
+       {
+               if ((_tcslen (arg[0]) >= 2) && (arg[0][1] == _T(':')))
+               {
+                       szRootPath[0] = toupper (*arg[0]);
+                       if (args == 2)
+                               _tcsncpy (szLabel, arg[1], 12);
+               }
+               else
+               {
+                       TCHAR szCurPath[MAX_PATH];
+                       GetCurrentDirectory (MAX_PATH, szCurPath);
+                       szRootPath[0] = szCurPath[0];
+                       _tcsncpy (szLabel, arg[0], 12);
+               }
+       }
+
+       /* check root path */
+       if (!IsValidPathName (szRootPath))
+       {
+               error_invalid_drive ();
+               freep (arg);
+               return 1;
+       }
+
+       GetVolumeInformation (szRootPath, szOldLabel, 80, &dwSerialNr,
+                                                 NULL, NULL, NULL, 0);
+
+       /* print drive info */
+       ConOutPrintf (_T("Volume in drive %c:"), _totupper (szRootPath[0]));
+
+       if (szOldLabel[0] != _T('\0'))
+               ConOutPrintf (_T(" is %s\n"), szOldLabel);
+       else
+               ConOutPrintf (_T(" has no label\n"));
+
+       /* print the volume serial number */
+       ConOutPrintf (_T("Volume Serial Number is %04X-%04X\n"),
+                                 HIWORD(dwSerialNr), LOWORD(dwSerialNr));
+
+       if (szLabel[0] == _T('\0'))
+       {
+               ConOutPrintf (_T("Drive label (11 Characters, ENTER if none)? "));
+               ConInString (szLabel, 80);
+       }
+
+       SetVolumeLabel (szRootPath, szLabel);
+
+       freep (arg);
+
+       return 0;
+}
+
+#endif /* INCLUDE_CMD_LABEL */
\ No newline at end of file
diff --git a/reactos/apps/utils/cmd/license.txt b/reactos/apps/utils/cmd/license.txt
new file mode 100644 (file)
index 0000000..c4fb365
--- /dev/null
@@ -0,0 +1,342 @@
+
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+\f
+        Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+
diff --git a/reactos/apps/utils/cmd/locale.c b/reactos/apps/utils/cmd/locale.c
new file mode 100644 (file)
index 0000000..b97c971
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ *  LOCALE.C - locale handling.
+ *
+ *
+ *  History:
+ *
+ *    09-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Started.
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+
+TCHAR cDateSeparator;
+TCHAR cTimeSeparator;
+TCHAR cThousandSeparator;
+TCHAR cDecimalSeparator;
+INT   nDateFormat;
+INT   nTimeFormat;
+TCHAR aszDayNames[7][8];
+INT   nNumberGroups;
+
+
+VOID InitLocale (VOID)
+{
+#ifdef LOCALE_WINDOWS
+       TCHAR szBuffer[256];
+       INT i;
+
+       /* date settings */
+       GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_SDATE, szBuffer, 256);
+       CharToOem (szBuffer, szBuffer);
+       cDateSeparator = szBuffer[0];
+       GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_IDATE, szBuffer, 256);
+       nDateFormat = _ttoi (szBuffer);
+
+       /* time settings */
+       GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_STIME, szBuffer, 256);
+       CharToOem (szBuffer, szBuffer);
+       cTimeSeparator = szBuffer[0];
+       GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_ITIME, szBuffer, 256);
+       nTimeFormat = _ttoi (szBuffer);
+
+       /* number settings */
+       GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szBuffer, 256);
+       CharToOem (szBuffer, szBuffer);
+       cThousandSeparator = szBuffer[0];
+       GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, szBuffer, 256);
+       CharToOem (szBuffer, szBuffer);
+       cDecimalSeparator  = szBuffer[0];
+       GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_SGROUPING, szBuffer, 256);
+       nNumberGroups = _ttoi (szBuffer);
+
+       /* days of week */
+       for (i = 0; i < 7; i++)
+       {
+               GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_SABBREVDAYNAME1 + i, szBuffer, 256);
+               CharToOem (szBuffer, szBuffer);
+               _tcscpy (aszDayNames[(i+1)%7], szBuffer); /* little hack */
+       }
+#endif
+
+#ifdef LOCALE_GERMAN
+       LPTSTR names [7] = {_T("So"), _T("Mo"), _T("Di"), _T("Mi"), _T("Do"), _T("Fr"), _T("Sa")};
+       INT i;
+
+       /* date settings */
+       cDateSeparator = '.';
+       nDateFormat    = 1;                     /* ddmmyy */
+
+       /* time settings */
+       cTimeSeparator = ':';
+       nTimeFormat    = 1;                     /* 24 hour */
+
+       /* number settings */
+       cThousandSeparator = '.';
+       cDecimalSeparator  = ',';
+       nNumberGroups      = 3;
+
+       /* days of week */
+       for (i = 0; i < 7; i++)
+               _tcscpy (aszDayNames[i], names[i]);
+#endif
+
+#ifdef LOCALE_DEFAULT
+       LPTSTR names [7] = {_T("Son"), _T("Mon"), _T("Tue"), _T("Wed"), _T("Thu"), _T("Fri"), _T("Sat")};
+       INT i;
+
+       /* date settings */
+       cDateSeparator = '-';
+       nDateFormat = 0;                /* mmddyy */
+
+       /* time settings */
+       cTimeSeparator = ':';
+       nTimeFormat = 0;                /* 12 hour */
+
+       /* number settings */
+       cThousandSeparator = ',';
+       cDecimalSeparator  = '.';
+       nNumberGroups      = 3;
+
+       /* days of week */
+       for (i = 0; i < 7; i++)
+               _tcscpy (aszDayNames[i], names[i]);
+#endif
+}
index 7e36f73..f956db7 100644 (file)
@@ -1,12 +1,29 @@
-all: cmd.bin
+#
+#
 
-OBJECTS = ../common/crt0.o cmd.o
+LIB=../../lib
+COMMON=../common
 
-LIBS = ../../lib/mingw32/mingw32.a ../../lib/crtdll/crtdll.a \
-       ../../lib/kernel32/kernel32.a ../../lib/ntdll/ntdll.a
+# target: raw binary (does not work right now)
+#all: cmd.bin
+
+# target: executable (not tested/experimental)
+all: cmd.exe
+
+OBJECTS = $(COMMON)/crt0.o cmd.o attrib.o alias.o batch.o beep.o call.o cls.o cmdinput.o cmdtable.o\
+        color.o date.o del.o dir.o echo.o err_hand.o error.o filecomp.o for.o goto.o history.o if.o\
+        internal.o label.o misc.o path.o pause.o redir.o ren.o set.o shift.o tempfile.o time.o type.o ver.o\
+        verify.o where.o
+
+LIBS = $(LIB)/mingw32/mingw32.a $(LIB)/crtdll/crtdll.a \
+       $(LIB)/kernel32/kernel32.a $(LIB)/ntdll/ntdll.a
 
 cmd.bin: $(OBJECTS)
        $(LD) -Ttext 0x10000 $(OBJECTS) $(LIBS) -o cmd.exe
        $(OBJCOPY) -O binary cmd.exe cmd.bin
 
+cmd.exe: $(OBJECTS)
+       $(LD) $(OBJECTS) $(LIBS) -o cmd.exe
+
 include ../../rules.mak
+
diff --git a/reactos/apps/utils/cmd/makefile.lcc b/reactos/apps/utils/cmd/makefile.lcc
new file mode 100644 (file)
index 0000000..58c114a
--- /dev/null
@@ -0,0 +1,194 @@
+# ReactOS cmd.exe makefile for lcc-win32
+# 19990119 Emanuele Aliberti <ea@iol.it>
+# 19990127 EA
+# 19990128 Eric Kohl <ekohl@abo.rhein-zeitung.de>
+#      Modified for cmd 0.0.4pre3.
+#
+# ReactOS  : http://www.sid-dis.com/reactos/
+# Lcc-Win32: http://www.cs.virginia.edu/*lcc-win32
+#
+TARGET=cmd
+CC=lcc.exe
+CFLAGS=-c -O
+LD=lcclnk.exe
+LFLAGS=-subsystem console -s -o $(TARGET).exe
+OBJS=alias.obj \
+       attrib.obj \
+       batch.obj \
+       beep.obj \
+       call.obj \
+       chcp.obj \
+       cls.obj \
+       cmd.obj \
+       cmdinput.obj \
+       cmdtable.obj \
+       color.obj \
+       console.obj \
+       copy.obj \
+       date.obj \
+       del.obj \
+       dir.obj \
+       dirstack.obj \
+       echo.obj \
+       error.obj \
+       filecomp.obj \
+       for.obj \
+       goto.obj \
+       history.obj \
+       if.obj \
+       internal.obj \
+       label.obj \
+       locale.obj \
+       misc.obj \
+       move.obj \
+       path.obj \
+       pause.obj \
+       prompt.obj \
+       redir.obj \
+       ren.obj \
+       set.obj \
+       shift.obj \
+       time.obj \
+       type.obj \
+       ver.obj \
+       verify.obj \
+       vol.obj \
+       where.obj 
+
+# MAIN
+
+# What about this implicid rule?
+# It should compile all c files.
+# (To test this, uncomment the following two lines.) EK
+#.c.obj:
+#      $(CC) $(CFLAGS) $<
+
+$(TARGET).exe: $(OBJS)
+       $(LD) $(LFLAGS) $(OBJS)
+
+# MODULES
+
+alias.obj: alias.c 
+       $(CC) $(CFLAGS) alias.c
+
+attrib.obj: attrib.c 
+       $(CC) $(CFLAGS) attrib.c
+
+batch.obj: batch.c 
+       $(CC) $(CFLAGS) batch.c
+
+beep.obj: beep.c 
+       $(CC) $(CFLAGS) beep.c
+
+call.obj: call.c 
+       $(CC) $(CFLAGS) call.c
+
+cls.obj: cls.c 
+       $(CC) $(CFLAGS) cls.c
+
+cmd.obj: cmd.c 
+       $(CC) $(CFLAGS) cmd.c
+
+cmdinput.obj: cmdinput.c 
+       $(CC) $(CFLAGS) cmdinput.c
+
+cmdtable.obj: cmdtable.c 
+       $(CC) $(CFLAGS) cmdtable.c
+
+color.obj: color.c 
+       $(CC) $(CFLAGS) color.c
+
+console.obj: console.c 
+       $(CC) $(CFLAGS) console.c
+
+copy.obj: copy.c 
+       $(CC) $(CFLAGS) copy.c
+
+date.obj: date.c 
+       $(CC) $(CFLAGS) date.c
+
+del.obj: del.c 
+       $(CC) $(CFLAGS) del.c
+
+dir.obj: dir.c 
+       $(CC) $(CFLAGS) dir.c
+
+dirstack.obj: dirstack.c 
+       $(CC) $(CFLAGS) dirstack.c
+
+echo.obj: echo.c 
+       $(CC) $(CFLAGS) echo.c
+
+error.obj: error.c 
+       $(CC) $(CFLAGS) error.c
+
+filecomp.obj: filecomp.c 
+       $(CC) $(CFLAGS) filecomp.c
+
+for.obj: for.c 
+       $(CC) $(CFLAGS) for.c
+
+goto.obj: goto.c 
+       $(CC) $(CFLAGS) goto.c
+
+history.obj: history.c 
+       $(CC) $(CFLAGS) history.c
+
+if.obj: if.c 
+       $(CC) $(CFLAGS) if.c
+
+internal.obj: internal.c 
+       $(CC) $(CFLAGS) internal.c
+
+label.obj: label.c 
+       $(CC) $(CFLAGS) label.c
+
+locale.obj: locale.c 
+       $(CC) $(CFLAGS) locale.c
+
+misc.obj: misc.c 
+       $(CC) $(CFLAGS) misc.c
+
+move.obj: move.c 
+       $(CC) $(CFLAGS) move.c
+
+path.obj: path.c 
+       $(CC) $(CFLAGS) path.c
+
+pause.obj: pause.c 
+       $(CC) $(CFLAGS) pause.c
+
+prompt.obj: prompt.c 
+       $(CC) $(CFLAGS) prompt.c
+
+redir.obj: redir.c 
+       $(CC) $(CFLAGS) redir.c
+
+ren.obj: ren.c 
+       $(CC) $(CFLAGS) ren.c
+
+set.obj: set.c 
+       $(CC) $(CFLAGS) set.c
+
+shift.obj: shift.c 
+       $(CC) $(CFLAGS) shift.c
+
+time.obj: time.c 
+       $(CC) $(CFLAGS) time.c
+
+type.obj: type.c 
+       $(CC) $(CFLAGS) type.c
+
+ver.obj: ver.c 
+       $(CC) $(CFLAGS) ver.c
+
+verify.obj: verify.c 
+       $(CC) $(CFLAGS) verify.c
+
+vol.obj: vol.c 
+       $(CC) $(CFLAGS) vol.c
+
+where.obj: where.c 
+       $(CC) $(CFLAGS) where.c
+
+#EOF
diff --git a/reactos/apps/utils/cmd/misc.c b/reactos/apps/utils/cmd/misc.c
new file mode 100644 (file)
index 0000000..1eb5ca4
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ *  MISC.C - misc. functions.
+ *
+ *
+ *  History:
+ *
+ *    07/12/98 (Rob Lake)
+ *        started
+ *
+ *    07/13/98 (Rob Lake)
+ *        moved functions in here
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    18-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Changed split() to accept quoted arguments.
+ *        Removed parse_firstarg().
+ *
+ *    23-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Fixed an ugly bug in split(). In rare cases (last character
+ *        of the string is a space) it ignored the NULL character and
+ *        tried to add the following to the argument list.
+ *
+ *    28-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        FileGetString() seems to be working now.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <conio.h>
+
+#include "cmd.h"
+
+
+/*
+ * get a character out-of-band and honor Ctrl-Break characters
+ */
+TCHAR cgetchar (VOID)
+{
+       TCHAR ch;
+#if 0
+       DWORD dwRead;
+       DWORD dwOldMode;
+       HANDLE hIn;
+
+       hIn = GetStdHandle (STD_INPUT_HANDLE);
+       ConInSwallowInput (hIn);
+
+       GetConsoleMode (hIn, &dwOldMode);
+       SetConsoleMode (hIn, 0);
+
+       ReadConsole (hIn, &ch, 1, &dwRead, NULL);
+
+       DebugPrintf ("[cgetchar (0x%x) \'%c\']\n", ch, ch);
+
+       SetConsoleMode (hIn, dwOldMode);
+#endif
+
+       if ((ch = getch()) == 0)
+               ch = getch() << 8;
+
+       if (ch == 3)
+               bCtrlBreak = TRUE;
+
+       return ch;
+}
+
+
+/*
+ * Check if Ctrl-Break was pressed during the last calls
+ */
+
+BOOL CheckCtrlBreak (INT mode)
+{
+       static BOOL bLeaveAll = FALSE; /* leave all batch files */
+       TCHAR c;
+
+       switch (mode)
+       {
+               case BREAK_OUTOFBATCH:
+                       bLeaveAll = 0;
+                       return FALSE;
+
+               case BREAK_BATCHFILE:
+                       if (bLeaveAll)
+                               return TRUE;
+
+                       if (!bCtrlBreak)
+                               return FALSE;
+
+                       /* we need to be sure the string arrives on the screen! */
+                       do
+                               ConOutPuts (_T("\r\nCtrl-Break pressed.  Cancel batch file? (Yes/No/All) "));
+                       while (!_tcschr ("YNA\3", c = _totupper (cgetchar())) || !c);
+
+                       ConOutPuts (_T("\r\n"));
+
+                       if (c == _T('N'))
+                               return bCtrlBreak = FALSE; /* ignore */
+
+                       /* leave all batch files */
+                       bLeaveAll = ((c == _T('A')) || (c == _T('\3')));
+                       break;
+
+               case BREAK_INPUT:
+                       if (!bCtrlBreak)
+                               return FALSE;
+                       break;
+       }
+
+       /* state processed */
+       bCtrlBreak = FALSE;
+       return TRUE;
+}
+
+
+/*
+ * split - splits a line up into separate arguments, deliminators
+ *         are spaces and slashes ('/').
+ */
+
+LPTSTR *split (LPTSTR s, LPINT args)
+{
+       LPTSTR *arg;
+       LPTSTR *p;
+       LPTSTR start;
+       LPTSTR q;
+       INT  ac;
+       INT  len;
+       BOOL bQuoted = FALSE;
+
+       arg = malloc (sizeof (LPTSTR));
+       if (!arg)
+               return NULL;
+       *arg = NULL;
+
+       ac = 0;
+       while (*s)
+       {
+               /* skip leading spaces */
+               while (*s && (_istspace (*s) || _istcntrl (*s)))
+                       ++s;
+
+               /* if quote (") then set bQuoted */
+               if (*s == _T('\"'))
+               {
+                       ++s;
+                       bQuoted = TRUE;
+               }
+
+               start = s;
+
+               /* the first character can be '/' */
+               if (*s == _T('/'))
+                       ++s;
+
+               /* skip to next word delimiter or start of next option */
+               if (bQuoted)
+               {
+                       while (_istprint (*s) && (*s != _T('\"')) && (*s != _T('/')))
+                               ++s;
+               }
+               else
+               {
+                       while (_istprint (*s) && !_istspace (*s) && (*s != _T('/')))
+                               ++s;
+               }
+
+               /* a word was found */
+               if (s != start)
+               {
+                       /* add new entry for new argument */
+                       arg = realloc (p = arg, (ac + 2) * sizeof (LPTSTR));
+                       if (!arg)
+                       {
+                               freep (p);
+                               return NULL;
+                       }
+
+                       /* create new entry */
+                       q = arg[ac] = malloc (((len = s - start) + 1) * sizeof (TCHAR));
+                       arg[++ac] = NULL;
+                       if (!q)
+                       {
+                               freep (arg);
+                               return NULL;
+                       }
+                       memcpy (q, start, len * sizeof (TCHAR));
+                       q[len] = _T('\0');
+               }
+
+               /* adjust string pointer if quoted (") */
+               if (bQuoted)
+               {
+                       ++s;
+                       bQuoted = FALSE;
+               }
+       }
+
+       *args = ac;
+
+       return arg;
+}
+
+
+/*
+ * freep -- frees memory used for a call to split
+ *
+ */
+VOID freep (LPTSTR *p)
+{
+       LPTSTR *q;
+
+       if (!p)
+               return;
+
+       q = p;
+       while (*q)
+               free(*q++);
+
+       free(p);
+}
+
+
+LPTSTR stpcpy (LPTSTR dest, LPTSTR src)
+{
+       _tcscpy (dest, src);
+       return (dest + _tcslen (src));
+}
+
+
+
+/*
+ * Checks if a path is valid (accessible)
+ */
+
+BOOL IsValidPathName (LPCTSTR pszPath)
+{
+       TCHAR szOldPath[MAX_PATH];
+       BOOL  bResult;
+
+       GetCurrentDirectory (MAX_PATH, szOldPath);
+       bResult = SetCurrentDirectory (pszPath);
+
+       SetCurrentDirectory (szOldPath);
+
+       return bResult;
+}
+
+
+/*
+ * Checks if a file exists (accessible)
+ */
+
+BOOL IsValidFileName (LPCTSTR pszPath)
+{
+       return (GetFileAttributes (pszPath) != 0xFFFFFFFF);
+}
+
+
+
+BOOL FileGetString (HANDLE hFile, LPTSTR lpBuffer, INT nBufferLength)
+{
+       LPTSTR lpString;
+       TCHAR  ch;
+       DWORD  dwRead;
+
+       lpString = lpBuffer;
+
+       while ((--nBufferLength >  0) &&
+                  ReadFile(hFile, &ch, 1, &dwRead, NULL) && dwRead)
+       {
+               *lpString++ = ch;
+               if (ch == _T('\r'))
+               {
+                       /* overread '\n' */
+                       ReadFile (hFile, &ch, 1, &dwRead, NULL);
+                       break;
+               }
+       }
+
+       if (!dwRead && lpString == lpBuffer)
+               return FALSE;
+
+       *lpString++ = _T('\0');
+
+       return TRUE;
+}
diff --git a/reactos/apps/utils/cmd/move.c b/reactos/apps/utils/cmd/move.c
new file mode 100644 (file)
index 0000000..54158d7
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ *  MOVE.C - move internal command.
+ *
+ *
+ *  History:
+ *
+ *    14-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Started.
+ *
+ *    18-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode safe!
+ *        Preliminary version!!!
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Redirection safe!
+ *
+ *    27-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("/?").
+ *        Added more error checks.
+ *
+ *    03-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added "/N" option.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_MOVE
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+
+#define OVERWRITE_NO     0
+#define OVERWRITE_YES    1
+#define OVERWRITE_ALL    2
+#define OVERWRITE_CANCEL 3
+
+
+static INT Overwrite (LPTSTR fn)
+{
+       TCHAR inp[10];
+       LPTSTR p;
+
+       ConOutPrintf (_T("Overwrite %s (Yes/No/All)? "), fn);
+       ConInString (inp, 10);
+
+       _tcsupr (inp);
+       for (p=inp; _istspace (*p); p++)
+               ;
+
+       if (*p != _T('Y') && *p != _T('A'))
+               return OVERWRITE_NO;
+       if (*p == _T('A'))
+               return OVERWRITE_ALL;
+
+       return OVERWRITE_YES;
+}
+
+
+
+INT cmd_move (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR *arg;
+       INT argc, i, nFiles;
+       TCHAR szDestPath[MAX_PATH];
+       TCHAR szSrcPath[MAX_PATH];
+       BOOL bPrompt = TRUE;
+       LPTSTR p;
+       WIN32_FIND_DATA findBuffer;
+       HANDLE hFile;
+       LPTSTR pszFile;
+       BOOL   bNothing = FALSE;
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+#if 0
+               ConOutPuts (_T("Moves files and renames files and directories.\n\n"
+                                          "To move one or more files:\n"
+                                          "MOVE [/N][/Y|/-Y][drive:][path]filename1[,...] destination\n"
+                                          "\n"
+                                          "To rename a directory:\n"
+                                          "MOVE [/N][/Y|/-Y][drive:][path]dirname1 dirname2\n"
+                                          "\n"
+                                          "  [drive:][path]filename1  Specifies the location and name of the file\n"
+                                          "                           or files you want to move.\n"
+                                          "  /N                       Nothing. Don everthing but move files or direcories.\n"
+                                          "  /Y\n"
+                                          "  /-Y\n"
+                                          "..."));
+#else
+               ConOutPuts (_T("Moves files and renames files and directories.\n\n"
+                                          "To move one or more files:\n"
+                                          "MOVE [/N][drive:][path]filename1[,...] destination\n"
+                                          "\n"
+                                          "To rename a directory:\n"
+                                          "MOVE [/N][drive:][path]dirname1 dirname2\n"
+                                          "\n"
+                                          "  [drive:][path]filename1  Specifies the location and name of the file\n"
+                                          "                           or files you want to move.\n"
+                                          "  /N                       Nothing. Don everthing but move files or direcories.\n"
+                                          "\n"
+                                          "Current limitations:\n"
+                                          "  - You can't move a file or directory from one drive to another.\n"
+                                          ));
+#endif
+               return 0;
+       }
+
+       arg = split (param, &argc);
+       nFiles = argc;
+
+       /* read options */
+       for (i = 0; i < argc; i++)
+       {
+               p = arg[i];
+
+               if (*p == _T('/'))
+               {
+                       p++;
+                       if (*p == _T('-'))
+                       {
+                               p++;
+                               if (_totupper (*p) == _T('Y'))
+                                       bPrompt = TRUE;
+                       }
+                       else
+                       {
+                               if (_totupper (*p) == _T('Y'))
+                                       bPrompt = FALSE;
+                               else if  (_totupper (*p) == _T('N'))
+                                       bNothing = TRUE;
+                       }
+                       nFiles--;
+               }
+       }
+
+       if (nFiles < 2)
+       {
+               /* there must be at least two pathspecs */
+               error_req_param_missing ();
+               return 1;
+       }
+
+       /* get destination */
+       GetFullPathName (arg[argc - 1], MAX_PATH, szDestPath, NULL);
+#ifdef _DEBUG
+       DebugPrintf (_T("Destination: %s\n"), szDestPath);
+#endif
+
+       /* move it*/
+       for (i = 0; i < argc - 1; i++)
+       {
+               if (*arg[i] == _T('/'))
+                       continue;
+
+               hFile = FindFirstFile (arg[i], &findBuffer);
+               if (hFile == INVALID_HANDLE_VALUE)
+               {
+                       ErrorMessage (GetLastError (), arg[i]);
+                       freep (arg);
+                       return 1;
+               }
+
+               do
+               {
+                       GetFullPathName (findBuffer.cFileName, MAX_PATH, szSrcPath, &pszFile);
+
+                       if (GetFileAttributes (szSrcPath) & FILE_ATTRIBUTE_DIRECTORY)
+                       {
+                               /* source is directory */
+
+#ifdef _DEBUG
+                               DebugPrintf (_T("Move directory \'%s\' to \'%s\'\n"),
+                                                        szSrcPath, szDestPath);
+#endif
+                               if (!bNothing)
+                               {
+                                       MoveFile (szSrcPath, szDestPath);
+                               }
+                       }
+                       else
+                       {
+                               /* source is file */
+
+                               if (IsValidFileName (szDestPath))
+                               {
+                                       /* destination exists */
+                                       if (GetFileAttributes (szDestPath) & FILE_ATTRIBUTE_DIRECTORY)
+                                       {
+                                               /* destination is existing directory */
+
+                                               TCHAR szFullDestPath[MAX_PATH];
+
+                                               _tcscpy (szFullDestPath, szDestPath);
+                                               _tcscat (szFullDestPath, _T("\\"));
+                                               _tcscat (szFullDestPath, pszFile);
+
+                                               ConOutPrintf (_T("%s => %s"), szSrcPath, szFullDestPath);
+
+                                               if (!bNothing)
+                                               {
+                                                       if (MoveFile (szSrcPath, szFullDestPath))
+                                                               ConOutPrintf (_T("[OK]\n"));
+                                                       else
+                                                               ConOutPrintf (_T("[Error]\n"));
+                                               }
+                                       }
+                                       else
+                                       {
+                                               /* destination is existing file */
+                                               INT nOverwrite;
+
+                                               /* must get the overwrite code */
+                                               if ((nOverwrite = Overwrite (szDestPath)))
+                                               {
+#if 0
+                                                       if (nOverwrite == OVERWRITE_ALL)
+                                                               *lpFlags |= FLAG_OVERWRITE_ALL;
+#endif
+                                                       ConOutPrintf (_T("%s => %s"), szSrcPath, szDestPath);
+
+                                                       if (!bNothing)
+                                                       {
+                                                               if (MoveFile (szSrcPath, szDestPath))
+                                                                       ConOutPrintf (_T("[OK]\n"));
+                                                               else
+                                                                       ConOutPrintf (_T("[Error]\n"));
+                                                       }
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       /* destination does not exist */
+                                       TCHAR szFullDestPath[MAX_PATH];
+
+                                       GetFullPathName (szDestPath, MAX_PATH, szFullDestPath, NULL);
+
+                                       ConOutPrintf (_T("%s => %s"), szSrcPath, szFullDestPath);
+
+                                       if (!bNothing)
+                                       {
+                                               if (MoveFile (szSrcPath, szFullDestPath))
+                                                       ConOutPrintf (_T("[OK]\n"));
+                                               else
+                                                       ConOutPrintf (_T("[Error]\n"));
+                                       }
+                               }
+                       }
+               }
+               while (FindNextFile (hFile, &findBuffer));
+
+               FindClose (hFile);
+       }
+
+
+       freep (arg);
+
+       return 0;
+}
+
+#endif /* INCLUDE_CMD_MOVE */
\ No newline at end of file
diff --git a/reactos/apps/utils/cmd/path.c b/reactos/apps/utils/cmd/path.c
new file mode 100644 (file)
index 0000000..714ee38
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ *  PATH.C - path internal command.
+ *
+ *
+ *  History:
+ *
+ *    17 Jul 1998 (John P Price)
+ *        Separated commands into individual files.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    09-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("/?").
+ *
+ *    18-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode ready!
+ *
+ *    18-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Redirection safe!
+ *
+ *    24-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Fixed Win32 environment handling.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_PATH
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+
+/* size of environment variable buffer */
+#define ENV_BUFFER_SIZE 1024
+
+
+INT cmd_path (LPTSTR cmd, LPTSTR param)
+{
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Displays or sets a search path for executable files.\n\n"
+                                  "PATH [[drive:]path[;...]]\nPATH ;\n\n"
+                                  "Type PATH ; to clear all search-path settings and direct the command shell\n"
+                                  "to search only in the current directory.\n"
+                                  "Type PATH without parameters to display the current path.\n"));
+               return 0;
+       }
+
+       /* if param is empty, display the PATH environment variable */
+       if (!param || !*param)
+       {
+               DWORD  dwBuffer;
+               LPTSTR pszBuffer;
+
+               pszBuffer = (LPTSTR)malloc (ENV_BUFFER_SIZE * sizeof(TCHAR));
+               dwBuffer = GetEnvironmentVariable (_T("PATH"), pszBuffer, ENV_BUFFER_SIZE);
+               if (dwBuffer == 0)
+               {
+                       ConErrPrintf ("CMD: Not in environment \"PATH\"\n");
+                       return 0;
+               }
+               else if (dwBuffer > ENV_BUFFER_SIZE)
+               {
+                       pszBuffer = (LPTSTR)realloc (pszBuffer, dwBuffer * sizeof (TCHAR));
+                       GetEnvironmentVariable (_T("PATH"), pszBuffer, ENV_BUFFER_SIZE);
+               }
+
+               ConOutPrintf (_T("PATH=%s\n"), pszBuffer);
+               free (pszBuffer);
+
+               return 0;
+       }
+
+       /* set PATH environment variable */
+       if (!SetEnvironmentVariable (_T("PATH"), param))
+               return 1;
+
+       return 0;
+}
+
+#endif
diff --git a/reactos/apps/utils/cmd/pause.c b/reactos/apps/utils/cmd/pause.c
new file mode 100644 (file)
index 0000000..f4c01bb
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ *  PAUSE.C - pause internal command.
+ *
+ *
+ *  History:
+ *
+ *    16 Jul 1998 (Hans B Pufal)
+ *        started.
+ *
+ *    16 Jul 1998 (John P Price)
+ *        Seperated commands into individual files.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    18-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_PAUSE
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+/*
+ * Perform PAUSE command.
+ *
+ * FREEDOS extension : If parameter is specified use that as the pause
+ *   message.
+ *
+ * ?? Extend to include functionality of CHOICE if switch chars
+ *     specified.
+ */
+
+INT cmd_pause (LPTSTR cmd, LPTSTR param)
+{
+#ifdef _DEBUG
+       DebugPrintf ("cmd_pause: \'%s\' : \'%s\'\n", cmd, param);
+#endif
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Stops the execution of a batch file and shows the following message:\n"
+                                          "\"Press any key to continue...\" or a user defined message.\n\n"
+                                          "PAUSE [message]"));
+               return 0;
+       }
+
+       if (*param)
+               ConOutPrintf (param);
+       else
+               msg_pause ();
+
+       cgetchar ();
+
+       return 0;
+}
+
+#endif
diff --git a/reactos/apps/utils/cmd/prompt.c b/reactos/apps/utils/cmd/prompt.c
new file mode 100644 (file)
index 0000000..fa674f1
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ *  PROMPT.C - prompt handling.
+ *
+ *
+ *  History:
+ *
+ *    14/01/95 (Tim Normal)
+ *        started.
+ *
+ *    08/08/95 (Matt Rains)
+ *        i have cleaned up the source code. changes now bring this source
+ *        into guidelines for recommended programming practice.
+ *
+ *    01/06/96 (Tim Norman)
+ *        added day of the week printing (oops, forgot about that!)
+ *
+ *    08/07/96 (Steffan Kaiser)
+ *        small changes for speed
+ *
+ *    20-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        removed redundant day strings. Use ones defined in date.c.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    28-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        moved cmd_prompt from internal.c to here
+ *
+ *    09-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("/?").
+ *
+ *    14-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added "$+" option.
+ *
+ *    09-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added "$A", "$C" and "$F" option.
+ *        Added locale support.
+ *        Fixed "$V" option.
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection safe!
+ *
+ *    24-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Fixed Win32 environment handling.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+
+/*
+ * print the command-line prompt
+ *
+ */
+VOID PrintPrompt(VOID)
+{
+       static TCHAR default_pr[] = _T("$P$G");
+       TCHAR  szPrompt[256];
+       LPTSTR pr;
+
+       if (GetEnvironmentVariable (_T("PROMPT"), szPrompt, 256))
+               pr = szPrompt;
+       else
+               pr = default_pr;
+
+       while (*pr)
+       {
+               if (*pr != _T('$'))
+               {
+                       ConOutChar (*pr);
+               }
+               else
+               {
+                       pr++;
+
+                       switch (_totupper (*pr))
+                       {
+                               case _T('A'):
+                                       ConOutChar (_T('&'));
+                                       break;
+
+                               case _T('B'):
+                                       ConOutChar (_T('|'));
+                                       break;
+
+                               case _T('C'):
+                                       ConOutChar (_T('('));
+                                       break;
+
+                               case _T('D'):
+                                       {
+                                               TCHAR szDate[32];
+
+                                               GetDateFormat (LOCALE_USER_DEFAULT, DATE_SHORTDATE,
+                                                                          NULL, NULL, szDate, sizeof (szDate));
+                                               ConOutPrintf (_T("%s"), szDate);
+                                       }
+                                       break;
+
+                               case _T('E'):
+                                       ConOutChar (_T('\x1B'));
+                                       break;
+
+                               case _T('F'):
+                                       ConOutChar (_T(')'));
+                                       break;
+
+                               case _T('G'):
+                                       ConOutChar (_T('>'));
+                                       break;
+
+                               case _T('H'):
+                                       ConOutChar (_T('\x08'));
+                                       break;
+
+                               case _T('L'):
+                                       ConOutChar (_T('<'));
+                                       break;
+
+                               case _T('N'):
+                                       {
+                                               TCHAR szPath[MAX_PATH];
+                                               GetCurrentDirectory (MAX_PATH, szPath);
+                                               ConOutChar (szPath[0]);
+                                       }
+                                       break;
+
+                               case _T('P'):
+                                       {
+                                               TCHAR szPath[MAX_PATH];
+                                               GetCurrentDirectory (MAX_PATH, szPath);
+                                               ConOutPrintf (_T("%s"), szPath);
+                                       }
+                                       break;
+
+                               case _T('Q'):
+                                       ConOutChar (_T('='));
+                                       break;
+
+                               case _T('T'):
+                                       {
+                                               TCHAR szTime[32];
+                                               GetTimeFormat (LOCALE_USER_DEFAULT, 0, NULL,
+                                                                          NULL, szTime, sizeof (szTime));
+                                               ConOutPrintf (_T("%s"), szTime);
+                                       }
+                                       break;
+
+                               case _T('V'):
+                                       switch (osvi.dwPlatformId)
+                                       {
+                                               case VER_PLATFORM_WIN32_WINDOWS:
+                                                       if (osvi.dwMajorVersion == 4 &&
+                                                               osvi.dwMinorVersion == 1)
+                                                               ConOutPrintf (_T("Windows 98"));
+                                                       else
+                                                               ConOutPrintf (_T("Windows 95"));
+                                                       break;
+
+                                               case VER_PLATFORM_WIN32_NT:
+                                                       ConOutPrintf (_T("Windows NT Version %lu.%lu"),
+                                                                                 osvi.dwMajorVersion, osvi.dwMinorVersion);
+                                                       break;
+                                       }
+                                       break;
+
+                               case _T('_'):
+                                       ConOutChar (_T('\n'));
+                                       break;
+
+                               case '$':
+                                       ConOutChar (_T('$'));
+                                       break;
+
+#ifdef FEATURE_DIRECTORY_STACK
+                               case '+':
+                                       {
+                                               INT i;
+                                               for (i = 0; i < GetDirectoryStackDepth (); i++)
+                                                       ConOutChar (_T('+'));
+                                       }
+                                       break;
+#endif
+                       }
+               }
+               pr++;
+       }
+}
+
+
+#ifdef INCLUDE_CMD_PROMPT
+
+INT cmd_prompt (LPTSTR cmd, LPTSTR param)
+{
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Changes the command prompt.\n\n"
+                         "PROMPT [text]\n\n"
+                         "  text    Specifies a new command prompt.\n\n"
+                         "Prompt can be made up of normal characters and the following special codes:\n\n"
+                         "  $A   & (Ampersand)\n"
+                         "  $B   | (pipe)\n"
+                         "  $C   ( (Left parenthesis)\n"
+                         "  $D   Current date\n"
+                         "  $E   Escape code (ASCII code 27)\n"
+                         "  $F   ) (Right parenthesis)\n"
+                         "  $G   > (greater-than sign)\n"
+                         "  $H   Backspace (erases previous character)\n"
+                         "  $L   < (less-than sign)\n"
+                         "  $N   Current drive\n"
+                         "  $P   Current drive and path\n"
+                         "  $Q   = (equal sign)\n"
+                         "  $T   Current time\n"
+                         "  $V   OS version number\n"
+                         "  $_   Carriage return and linefeed\n"
+                         "  $$   $ (dollar sign)"));
+#ifdef FEATURE_DIRECTORY_STACK
+               ConOutPuts (_T("  $+   Displays the current depth of the directory stack"));
+#endif
+               ConOutPuts (_T("\nType PROMPT without parameters to reset the prompt to the default setting."));
+               return 0;
+       }
+
+       /* set PROMPT environment variable */
+       if (!SetEnvironmentVariable (_T("PROMPT"), param))
+               return 1;
+
+       return 0;
+}
+#endif
diff --git a/reactos/apps/utils/cmd/readme.txt b/reactos/apps/utils/cmd/readme.txt
new file mode 100644 (file)
index 0000000..b76a3a7
--- /dev/null
@@ -0,0 +1,101 @@
+ReactOS Command Line Interface "CMD" version 0.0.4
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is the fourth pre-alpha release of CMD.EXE for ReactOS.
+It was converted from the FreeDOS COMMAND.COM.
+
+
+Warning!! Warning!! Warning!!
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This is a pre-alpha version! Many features have not been tested!
+Be careful when you use commands that write to your disk drives,
+they might destroy your files or the file system!!!
+
+
+Status
+~~~~~~
+This is a converted version of FreeDOS COMMAND.COM.
+I added some commands from WinNT's CMD.EXE.
+
+
+New features and improvements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  - Fixed redirection and piping.
+    (E.g. you can use "type > file" now.)
+  - Added new error redirections "2>" and "2>>".
+    (E.g.: "make 2>error.log")
+  - Added CHCP command.
+  - Fixed environment handling.
+  - New makefile for lcc-win (makefile.lcc).
+  - Rewrote DEL and MOVE with a new structure.
+  - Improved national language support.
+  - Fixed filename completion.
+
+
+Compiling
+~~~~~~~~~
+I converted CMD using MS Visual C++ 5.0 and Win95. The included makefile
+is just an experimental version.
+
+If you want to compile and test CMD with djgpp, modify the makefile as needed.
+I put the CMD sources into [reactos\apps], the makefile is written for that
+directory.
+
+If you want to compile and test CMD using another compiler, just create
+a new console application project and add all *.c and *.h files to it.
+It should compile without an error.
+
+
+Please report bugs which are not listed above.
+
+
+Good luck
+
+  Eric Kohl <ekohl@abo.rhein-zeitung.de>
+
+
+
+
+FreeDOS Command Line Interface
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+About
+~~~~~
+This software is part of the FreeDOS project. Please email
+freedos@sunsite.unc.edu for more information, or visit the freedos
+archive at "ftp://sunsite.unc.edu/pub/micro/pc-stuff/freedos".  Also,
+visit our web page at http://www.freedos.org/.
+
+The command.com web site is at
+
+   http://www.gcfl.net/FreeDOS/command.com/
+
+
+This software has been developed by the following people:
+(listed in approximate chronological order of contributions)
+
+FreeDOS developers:
+   normat@rpi.edu (Tim Norman)
+   mrains@apanix.apana.org.au (Matt Rains)
+   ejeffrey@iastate.edu (Evan Jeffrey)
+   Steffen.Kaiser@Informatik.TU-Chemnitz.DE (Steffen Kaiser)
+   Svante Frey (sfrey@kuai.se)
+   Oliver Mueller (ogmueller@t-online.de)
+   Aaron Kaufman (morgan@remarque.berkeley.edu)
+   Marc Desrochers (bitzero@hotmail.com)
+   Rob Lake (rlake@cs.mun.ca)
+   John P. Price <linux-guru@gcfl.net>
+   Hans B Pufal <hansp@digiweb.com>
+
+ReactOS developers:
+   Eric Kohl <ekohl@abo.rhein-zeitung.de>
+
+
+Current Features
+~~~~~~~~~~~~~~~~
+ - environment handling with prompt and path support.
+ - directory utilities.
+ - command-line history with doskey-like features.
+ - batch file processing.
+ - input/output redirection and piping.
+ - alias support.
+ - filename completion (use TAB)
diff --git a/reactos/apps/utils/cmd/redir.c b/reactos/apps/utils/cmd/redir.c
new file mode 100644 (file)
index 0000000..594bc11
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ *  REDIR.C - redirection handling.
+ *
+ *
+ *  History:
+ *
+ *    12/15/95 (Tim Norman)
+ *        started.
+ *
+ *    12 Jul 98 (Hans B Pufal)
+ *        Rewrote to make more efficient and to conform to new command.c
+ *        and batch.c processing.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        Added config.h include
+ *
+ *    22-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode safe!
+ *        Added new error redirection "2>" and "2>>".
+ *
+ *    26-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added new error AND output redirection "&>" and "&>>".
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef FEATURE_REDIRECTION
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "cmd.h"
+
+
+static BOOL
+IsRedirection (TCHAR c)
+{
+       return (c == _T('<')) || (c == _T('>')) || (c == _T('|'));
+}
+
+
+/*
+ * Gets the redirection info from the command line and copies the
+ * file names into ifn, ofn and efn removing them from the command
+ * line.
+ *
+ * Converts remaining command line into a series of null terminated
+ * strings defined by the pipe char '|'. Each string corresponds
+ * to a single executable command. A double null terminates the
+ * command strings.
+ *
+ * Return number of command strings found.
+ *
+ */
+
+INT GetRedirection (LPTSTR s, LPTSTR ifn, LPTSTR ofn, LPTSTR efn, LPINT lpnFlags)
+{
+       INT num = 1;
+       LPTSTR dp = s;
+       LPTSTR sp = s;
+
+       /* find and remove all the redirections first */
+       while (*sp)
+       {
+               if ((*sp == _T('"')) || (*sp == _T('\'')))
+               {
+                       /* No redirects inside quotes */
+                       TCHAR qc = *sp;
+
+                       do
+                               *dp++ = *sp++;
+                       while (*sp != qc);
+
+                       *dp++ = *sp++;
+               }
+               else if ((*sp == _T('<')) || (*sp == _T('>')) ||
+                                (*sp == _T('2')) || (*sp == _T('&')))
+               {
+                       /* MS-DOS ignores multiple redirection symbols and uses the last */
+                       /* redirection, so we'll emulate that and not check */
+
+                       if (*sp == _T('<'))
+                       {
+                               /* input redirection */
+                               *lpnFlags |= INPUT_REDIRECTION;
+                               while (_istspace (*sp))
+                                       sp++;
+
+                               /* copy file name */
+                               while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
+                                       *ifn++ = *sp++;
+                               *ifn = _T('\0');
+                       }
+                       else if (*sp == _T('>'))
+                       {
+                               /* output redirection */
+                               *lpnFlags |= OUTPUT_REDIRECTION;
+                               sp++;
+
+                               /* append request ? */
+                               if (*sp == _T('>'))
+                               {
+                                       *lpnFlags |= OUTPUT_APPEND;
+                                       sp++;
+                               }
+
+                               while (_istspace (*sp))
+                                       sp++;
+
+                               /* copy file name */
+                               while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
+                                       *ofn++ = *sp++;
+                               *ofn = _T('\0');
+                       }
+                       else if (*sp == _T('2'))
+                       {
+                               /* error redirection */
+                               sp++;
+
+                               if (*sp == _T('>'))
+                               {
+                                       *lpnFlags |= ERROR_REDIRECTION;
+                                       sp++;
+
+                                       /* append request ? */
+                                       if (*sp == _T('>'))
+                                       {
+                                               *lpnFlags |= ERROR_APPEND;
+                                               sp++;
+                                       }
+                               }
+                               else
+                               {
+                                       /* no redirection!! copy the '2' character! */
+                                       sp--;
+                                       *dp++ = *sp++;
+                                       continue;
+                               }
+
+                               while (_istspace (*sp))
+                                       sp++;
+
+                               /* copy file name */
+                               while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
+                                       *efn++ = *sp++;
+                               *efn = _T('\0');
+                       }
+                       else if (*sp == _T('&'))
+                       {
+                               /* output AND error redirection */
+                               sp++;
+
+                               if (*sp == _T('>'))
+                               {
+                                       *lpnFlags |= (ERROR_REDIRECTION | OUTPUT_REDIRECTION);
+                                       sp++;
+
+                                       /* append request ? */
+                                       if (*sp == _T('>'))
+                                       {
+                                               *lpnFlags |= (ERROR_APPEND | OUTPUT_APPEND);
+                                               sp++;
+                                       }
+                               }
+                               else
+                               {
+                                       /* no redirection!! copy the '&' character! */
+                                       sp--;
+                                       *dp++ = *sp++;
+                                       continue;
+                               }
+
+                               while (_istspace (*sp))
+                                       sp++;
+
+                               /* copy file name */
+                               while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
+                                       *ofn++ = *efn++ = *sp++;
+                               *ofn = *efn = _T('\0');
+                       }
+               }
+               else
+                       *dp++ = *sp++;
+       }
+       *dp++ = _T('\0');
+       *dp = _T('\0');
+
+       /* now go for the pipes */
+       sp = s;
+       while (*sp)
+       {
+               if ((*sp == _T('"')) || (*sp == _T('\'')))
+               {
+                       TCHAR qc = *sp;
+
+                       do
+                               sp++;
+                       while (*sp != qc);
+
+                       sp++;
+               }
+               else if (*sp == _T('|'))
+               {
+                       *sp++ = '\0';
+                       num++;
+               }
+               else
+                       sp++;
+       }
+
+       return num;
+}
+
+#endif /* FEATURE_REDIRECTION */
diff --git a/reactos/apps/utils/cmd/ren.c b/reactos/apps/utils/cmd/ren.c
new file mode 100644 (file)
index 0000000..2023d07
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ *  REN.C - rename internal command.
+ *
+ *
+ *  History:
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    18-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>
+ *        Added support for quoted long file names with spaces.
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>
+ *        Unicode and redirection safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_RENAME
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+/*
+ *  simple file rename internal command.
+ *
+ */
+INT cmd_rename (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR *arg;
+       INT    argc;
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Renames a file/directory or files/directories.\n"
+                                          "\n"
+                                          "RENAME [drive:][path][directoryname1 | filename1] [directoryname2 | filename2]\n"
+                                          "REN [drive:][path][directoryname1 | filename1] [directoryname2 | filename2]\n"
+                                          "\n"
+                                          "Note that you cannot specify a new drive or path for your destination. Use\n"
+                                          "the MOVE command for that purpose."));
+               return 0;
+       }
+
+       /* split the argument list */
+       arg = split (param, &argc);
+
+       if (argc != 2)
+       {
+               freep (arg);
+               error_too_many_parameters (param);
+               return 1;
+       }
+
+       if (!MoveFile (arg[0], arg[1]))
+       {
+               ConErrPuts (_T("rename"));
+               freep (arg);
+               return 1;
+       }
+
+       freep (arg);
+
+       return 0;
+}
+
+#endif
diff --git a/reactos/apps/utils/cmd/set.c b/reactos/apps/utils/cmd/set.c
new file mode 100644 (file)
index 0000000..7be3388
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ *  SET.C - set internal command.
+ *
+ *
+ *  History:
+ *
+ *    06/14/97 (Tim Norman)
+ *        changed static var in set() to a malloc'd space to pass to putenv.
+ *        need to find a better way to do this, since it seems it is wasting
+ *        memory when variables are redefined.
+ *
+ *    07/08/1998 (John P. Price)
+ *        removed call to show_environment in set command.
+ *        moved test for syntax before allocating memory in set command.
+ *        misc clean up and optimization.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    28-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added set_env function to set env. variable without needing set command
+ *
+ *    09-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("/?").
+ *
+ *    24-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Fixed Win32 environment handling.
+ *        Unicode and redirection safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_SET
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+
+/* size of environment variable buffer */
+#define ENV_BUFFER_SIZE  1024
+
+
+INT cmd_set (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR p;
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Displays, sets, or removes environment variables.\n\n"
+                                          "SET [variable[=][string]]\n\n"
+                                          "  variable  Specifies the environment-variable name.\n"
+                                          "  string    Specifies a series of characters to assign to the variable.\n\n"
+                                          "Type SET without parameters to display the current environment variables.\n"));
+               return 0;
+       }
+
+       /* if no parameters, show the environment */
+       if (param[0] == _T('\0'))
+       {
+               LPTSTR lpEnv;
+               LPTSTR lpOutput;
+               INT len;
+
+               lpEnv = (LPTSTR)GetEnvironmentStrings ();
+               if (lpEnv)
+               {
+                       lpOutput = lpEnv;
+                       while (*lpOutput)
+                       {
+                               len = _tcslen(lpOutput);
+                               if (len)
+                               {
+                                       if (*lpOutput != _T('='))
+                                               ConOutPuts (lpOutput);
+                                       lpOutput += (len + 1);
+                               }
+                       }
+                   FreeEnvironmentStrings (lpEnv);
+               }
+
+               return 0;
+       }
+
+       p = _tcschr (param, _T('='));
+       if (p)
+       {
+               /* set or remove environment variable */
+               *p = _T('\0');
+               p++;
+
+               SetEnvironmentVariable (param, p);
+       }
+       else
+       {
+               /* display environment variable */
+               LPTSTR pszBuffer;
+               DWORD dwBuffer;
+
+               pszBuffer = (LPTSTR)malloc (ENV_BUFFER_SIZE * sizeof(TCHAR));
+               dwBuffer = GetEnvironmentVariable (param, pszBuffer, ENV_BUFFER_SIZE);
+               if (dwBuffer == 0)
+               {
+                       ConErrPrintf ("CMD: Not in environment \"%s\"\n", param);
+                       return 0;
+               }
+               else if (dwBuffer > ENV_BUFFER_SIZE)
+               {
+                       pszBuffer = (LPTSTR)realloc (pszBuffer, dwBuffer * sizeof (TCHAR));
+                       GetEnvironmentVariable (param, pszBuffer, ENV_BUFFER_SIZE);
+               }
+
+               ConOutPrintf ("%s\n", pszBuffer);
+               free (pszBuffer);
+
+               return 0;
+       }
+
+       return 0;
+}
+
+#endif
diff --git a/reactos/apps/utils/cmd/shift.c b/reactos/apps/utils/cmd/shift.c
new file mode 100644 (file)
index 0000000..92ee036
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ *  SHIFT.C - shift 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
+ *
+ *    07-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("shift /?") and cleaned up.
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+/*
+ *  Perform the SHIFT command.
+ *
+ * Only valid inside batch files.
+ *
+ * FREEDOS extension : optional parameter DOWN to allow shifting
+ *   parameters backwards.
+ */
+
+INT cmd_shift (LPTSTR cmd, LPTSTR param)
+{
+#ifdef _DEBUG
+       DebugPrintf ("cmd_shift: (\'%s\', \'%s\'\n", cmd, param);
+#endif
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Changes the position of replaceable parameters in a batch file.\n\n"
+                                          "SHIFT [DOWN]"));
+               return 0;
+       }
+
+       if (bc == NULL)
+       {
+               /* not in batch - error!! */
+               return 1;
+       }
+
+       if (!_tcsicmp (param, _T("down")))
+       {
+               if (bc->shiftlevel)
+                       bc->shiftlevel--;
+       }
+       else /* shift up */
+               bc->shiftlevel++;
+
+       return 0;
+}
diff --git a/reactos/apps/utils/cmd/time.c b/reactos/apps/utils/cmd/time.c
new file mode 100644 (file)
index 0000000..f2b01d8
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ *  TIME.C - time internal command.
+ *
+ *
+ *  History:
+ *
+ *    07/08/1998 (John P. Price)
+ *        started.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    09-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added locale support.
+ *
+ *    19-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection safe!
+ *        Added "/t" option.
+ *
+ *    04-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Fixed time input bug.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_TIME
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "cmd.h"
+
+
+static VOID
+PrintTime (VOID)
+{
+#if 0
+       SYSTEMTIME st;
+
+       GetLocalTime (&st);
+
+       switch (nTimeFormat)
+       {
+               case 0: /* 12 hour format */
+               default:
+                       ConOutPrintf (_T("Current time is %2d%c%02d%c%02d%c%02d%c\n"),
+                                       (st.wHour == 0 ? 12 : (st.wHour <= 12 ? st.wHour : st.wHour - 12)),
+                                       cTimeSeparator, st.wMinute, cTimeSeparator, st.wSecond, cDecimalSeparator,
+                                       st.wMilliseconds / 10, (st.wHour <= 11 ? 'a' : 'p'));
+                       break;
+
+               case 1: /* 24 hour format */
+                       ConOutPrintf (_T("Current time is %2d%c%02d%c%02d%c%02d\n"),
+                                       st.wHour, cTimeSeparator, st.wMinute, cTimeSeparator,
+                                       st.wSecond, cDecimalSeparator, st.wMilliseconds / 10);
+                       break;
+       }
+#endif
+
+       TCHAR szTime[32];
+
+       GetTimeFormat (LOCALE_USER_DEFAULT, 0, NULL, NULL,
+                                  szTime, sizeof (szTime));
+       ConOutPrintf (_T("Current date is: %s\n"), szTime);
+}
+
+
+static BOOL ParseTime (LPTSTR s)
+{
+       SYSTEMTIME t;
+       LPTSTR p = s;
+
+       if (!*s)
+               return TRUE;
+
+       GetLocalTime (&t);
+       t.wHour = 0;
+       t.wMinute = 0;
+       t.wSecond = 0;
+       t.wMilliseconds = 0;
+
+       // first get hour
+       if (_istdigit(*p))
+       {
+               while (_istdigit(*p))
+               {
+                       t.wHour = t.wHour * 10 + *p - _T('0');
+                       p++;
+               }
+       }
+       else
+               return FALSE;
+
+       // get time separator
+       if (*p != cTimeSeparator)
+               return FALSE;
+       p++;
+
+       // now get minutes
+       if (_istdigit(*p))
+       {
+               while (_istdigit(*p))
+               {
+                       t.wMinute = t.wMinute * 10 + *p - _T('0');
+                       p++;
+               }
+       }
+       else
+               return FALSE;
+
+       // get time separator
+       if (*p != cTimeSeparator)
+               return FALSE;
+       p++;
+
+       // now get seconds
+       if (_istdigit(*p))
+       {
+               while (_istdigit(*p))
+               {
+                       t.wSecond = t.wSecond * 10 + *p - _T('0');
+                       p++;
+               }
+       }
+       else
+               return FALSE;
+
+       // get decimal separator
+       if (*p == cDecimalSeparator)
+       {
+               p++;
+
+               // now get hundreths
+               if (_istdigit(*p))
+               {
+                       while (_istdigit(*p))
+                       {
+//                             t.wMilliseconds = t.wMilliseconds * 10 + *p - _T('0');
+                               p++;
+                       }
+//                     t.wMilliseconds *= 10;
+               }
+       }
+
+       /* special case: 12 hour format */
+       if (nTimeFormat == 0)
+       {
+               if (_totupper(*s) == _T('P'))
+               {
+                       t.wHour += 12;
+               }
+
+               if ((_totupper(*s) == _T('A')) && (t.wHour == 12))
+               {
+                       t.wHour = 0;
+               }
+       }
+
+       if (t.wHour > 23 || t.wMinute > 60 || t.wSecond > 60 || t.wMilliseconds > 999)
+               return FALSE;
+
+       SetLocalTime (&t);
+
+       return TRUE;
+}
+
+
+INT cmd_time (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR *arg;
+       INT    argc;
+       INT    i;
+       BOOL   bPrompt = TRUE;
+       INT    nTimeString = -1;
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Displays or sets the system time.\n\n"
+                                          "TIME [/T][time]\n\n"
+                                          "  /T    display only\n\n"
+                                          "Type TIME with no parameters to display the current time setting and a prompt\n"
+                                          "for a new one.  Press ENTER to keep the same time."));
+               return 0;
+       }
+
+       /* build parameter array */
+       arg = split (param, &argc);
+
+       /* check for options */
+       for (i = 0; i < argc; i++)
+       {
+               if (_tcsicmp (arg[i], _T("/t")) == 0)
+                       bPrompt = FALSE;
+               if ((*arg[i] != _T('/')) && (nTimeString == -1))
+                       nTimeString = i;
+       }
+
+       if (nTimeString == -1)
+               PrintTime ();
+
+       if (!bPrompt)
+       {
+               freep (arg);
+               return 0;
+       }
+
+       while (1)
+       {
+               if (nTimeString == -1)
+               {
+                       TCHAR  s[40];
+
+                       ConOutPrintf (_T("Enter new time: "));
+
+                       ConInString (s, 40);
+
+#ifdef _DEBUG
+                       DebugPrintf ("\'%s\'\n", s);
+#endif
+
+                       while (*s && s[_tcslen (s) - 1] < _T(' '))
+                               s[_tcslen(s) - 1] = _T('\0');
+
+                       if (ParseTime (s))
+                       {
+                               freep (arg);
+                               return 0;
+                       }
+               }
+               else
+               {
+                       if (ParseTime (arg[nTimeString]))
+                       {
+                               freep (arg);
+                               return 0;
+                       }
+
+                       // force input the next time around.
+                       nTimeString == -1;
+               }
+               ConErrPuts (_T("Invalid time."));
+       }
+
+       freep (arg);
+
+       return 0;
+}
+
+#endif
diff --git a/reactos/apps/utils/cmd/todo.txt b/reactos/apps/utils/cmd/todo.txt
new file mode 100644 (file)
index 0000000..bcffe59
--- /dev/null
@@ -0,0 +1,21 @@
+Things to do
+~~~~~~~~~~~~
+Fix bugs :)
+
+Rewrite DIR command (Unicode aware / new structure).
+
+Optimize the code!  For size and speed.  There are numerous places
+where the code is hardly optimal for either.
+
+Sorting in DIR command ("dir /o...").
+
+^S and ^Q to pause/resume displays.
+
+Improve DEL, COPY and MOVE commands.
+BREAK command on command-line.
+
+Add wildcard support to REN.
+
+Add "/?" support to all batch commands.
+
+And many, many more...
diff --git a/reactos/apps/utils/cmd/type.c b/reactos/apps/utils/cmd/type.c
new file mode 100644 (file)
index 0000000..b471356
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ *  TYPE.C - type internal command.
+ *
+ *  History:
+ *
+ *    07/08/1998 (John P. Price)
+ *        started.
+ *
+ *    07/12/98 (Rob Lake)
+ *        Changed error messages
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    07-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added support for quoted arguments (type "test file.dat").
+ *        Cleaned up.
+ *
+ *    19-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_TYPE
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+
+INT cmd_type (LPTSTR cmd, LPTSTR param)
+{
+       TCHAR  szBuffer[256];
+       HANDLE hFile;
+       DWORD  dwBytesRead;
+       DWORD  dwBytesWritten;
+       BOOL   bResult;
+       INT    args;
+       LPTSTR *arg;
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Displays the contents of text files.\n\n"
+                                          "TYPE [drive:][path]filename"));
+               return 0;
+       }
+
+       if (!*param)
+       {
+               error_req_param_missing ();
+               return 1;
+       }
+
+       arg = split (param, &args);
+
+       if (args > 1)
+       {
+               error_too_many_parameters (_T("\b \b"));
+               freep (arg);
+               return 1;
+       }
+
+       hFile = CreateFile (arg[0], GENERIC_READ, FILE_SHARE_READ,
+                                               NULL, OPEN_EXISTING,
+                                               FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
+                                               NULL);
+
+       if (hFile == INVALID_HANDLE_VALUE)
+       {
+               error_sfile_not_found (param);
+               freep (arg);
+               return 1;
+       }
+
+       do
+       {
+               bResult = ReadFile (hFile, szBuffer, sizeof(szBuffer),
+                                                       &dwBytesRead, NULL);
+               if (dwBytesRead)
+                       WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), szBuffer, dwBytesRead,
+                                          &dwBytesWritten, NULL);
+       }
+       while (bResult && dwBytesRead > 0);
+
+       CloseHandle (hFile);
+       freep (arg);
+
+       return 0;
+}
+
+#endif
diff --git a/reactos/apps/utils/cmd/ver.c b/reactos/apps/utils/cmd/ver.c
new file mode 100644 (file)
index 0000000..f5e76fc
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ *  VER.C - ver internal command.
+ *
+ *
+ *  History:
+ *
+ *    06/30/98 (Rob Lake)
+ *        rewrote ver command to accept switches, now ver alone prints
+ *        copyright notice only.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added text about where to send bug reports and get updates.
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+#define VER_HELP     "display shell version info   VER [/C/R/W/?]"
+
+
+VOID ShortVersion (VOID)
+{
+       ConOutPuts (_T("\n" SHELLINFO " " SHELLVER "\n"));
+}
+
+
+#ifdef INCLUDE_CMD_VER
+
+/*
+ *  display shell version info internal command.
+ *
+ *
+ */
+INT cmd_ver (LPTSTR cmd, LPTSTR param)
+{
+       INT i;
+
+       /* JPP 07/08/1998 clean up and shortened info. */
+
+       ConOutPuts (_T("\n" SHELLINFO " " SHELLVER "\nCopyright (C) 1994-1998 Tim Norman and others."));
+       ConOutPuts (_T("Copyright (C) 1998,1999 Eric Kohl."));
+
+       /* Basic copyright notice */
+       if (param[0] == _T('\0'))
+       {
+               ConOutPuts (_T("\n"SHELLINFO
+                                          " comes with ABSOLUTELY NO WARRANTY; for details\n"
+                                          "type: `ver /w'. This is free software, and you are welcome to redistribute\n"
+                                          "it under certain conditions; type `ver /r' for details. Type `ver /c' for a\n"
+                                          "listing of credits."));
+       }
+       else
+       {
+               /* MS-DOS ver prints just help if /? is alone or not */
+               if (_tcsstr (param, _T("/?")) != NULL)
+               {
+                       ConOutPuts (_T(USAGE ": " VER_HELP));
+                       return 0;
+               }
+
+               for (i = 0; param[i]; i++)
+               {
+                       /* skip spaces */
+                       if (param[i] == _T(' '))
+                               continue;
+
+                       if (param[i] == _T('/'))
+                       {
+                               /* is this a lone '/' ? */
+                               if (param[i + 1] == 0)
+                               {
+                                       error_invalid_switch (_T(' '));
+                                       return 1;
+                               }
+                               continue;
+                       }
+
+                       if (_totupper (param[i]) == _T('W'))
+                       {
+                               /* Warranty notice */
+                               /* JPP 07/08/1998 removed extra printf calls */
+                               ConOutPuts (_T("\n This program is distributed in the hope that it will be useful,\n"
+                                                          " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+                                                          " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
+                                                          " GNU General Public License for more details."));
+                       }
+                       else if (_totupper (param[i]) == _T('R'))
+                       {
+                               /* Redistribution notice */
+                               /* JPP 07/08/1998 removed extra printf calls */
+                               ConOutPuts (_T("\n This program is free software; you can redistribute it and/or modify\n"
+                                                          " it under the terms of the GNU General Public License as published by\n"
+                                                          " the Free Software Foundation; either version 2 of the License, or\n"
+                                                          " (at your option) any later version."));
+                       }
+                       else if (_totupper (param[i]) == _T('C'))
+                       {
+                               /* Developer listing */
+                               /* JPP 07/08/1998 removed extra printf calls; rearranged names */
+                               ConOutPuts (_T("\ndeveloped by:\n"
+                                                          "    Tim Norman      Matt Rains\n"
+                                                          "    Evan Jeffrey    Steffen Kaiser\n"
+                                                          "    Svante Frey     Oliver Mueller\n"
+                                                          "    Aaron Kaufman   Marc Desrochers\n"
+                                                          "    Rob Lake        John P Price\n"
+                                                          "    Hans B Pufal\n"
+                                                          "\nconverted to Win32 by:\n"
+                                                          "    Eric Kohl\n"));
+                       }
+                       else
+                       {
+                               error_invalid_switch ((TCHAR)_totupper (param[i]));
+                               return 1;
+                       }
+               }
+       }
+
+       ConOutPuts (_T("\nSend bug reports to <ekohl@abo.rhein-zeitung.de>.\n"
+/*
+                                  "Updates are available at ftp://www.sid-dis.com/..."
+*/
+                          ));
+       return 0;
+}
+
+#endif
diff --git a/reactos/apps/utils/cmd/verify.c b/reactos/apps/utils/cmd/verify.c
new file mode 100644 (file)
index 0000000..e3b1f08
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ *  VERIFY.C - verify internal command.
+ *
+ *
+ *  History:
+ *
+ *    31 Jul 1998 (John P Price)
+ *        started.
+ *
+ *    18-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        VERIFY is just a dummy under Win32; it only exists
+ *        for compatibility!!!
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_VERIFY
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+
+/* global verify flag */
+static BOOL bVerify = FALSE;
+
+
+INT cmd_verify (LPTSTR cmd, LPTSTR param)
+{
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("This command is just a dummy!!\n"
+                                          "Sets whether to verify that your files are written correctly to a\n"
+                                          "disk.\n\n"
+                                          "VERIFY [ON | OFF]\n\n"
+                                          "Type VERIFY without a parameter to display the current VERIFY setting."));
+               return 0;
+       }
+
+       if (!*param)
+               ConOutPrintf (_T("VERIFY is %s.\n"), bVerify ? D_ON : D_OFF);
+       else if (_tcsicmp (param, D_OFF) == 0)
+               bVerify = FALSE;
+       else if (_tcsicmp (param, D_ON) == 0)
+               bVerify = TRUE;
+       else
+               ConOutPuts (_T("Must specify ON or OFF."));
+
+       return 0;
+}
+
+#endif
diff --git a/reactos/apps/utils/cmd/vol.c b/reactos/apps/utils/cmd/vol.c
new file mode 100644 (file)
index 0000000..13bd0e1
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ *  VOL.C - vol internal command.
+ *
+ *
+ *  History:
+ *
+ *    03-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Replaced DOS calls by Win32 calls.
+ *
+ *    08-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("/?").
+ *
+ *    07-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Cleanup.
+ *
+ *    18-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode ready!
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Redirection ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_VOL
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+
+static VOID
+PrintVolumeHeader (LPTSTR pszRootPath)
+{
+       TCHAR szVolName[80];
+       DWORD dwSerialNr;
+
+       /* get the volume information of the drive */
+       GetVolumeInformation (pszRootPath, szVolName, 80, &dwSerialNr,
+                                                 NULL, NULL, NULL, 0);
+
+       /* print drive info */
+       ConOutPrintf (_T(" Volume in drive %c:"), pszRootPath[0]);
+
+       if (szVolName[0] != '\0')
+               ConOutPrintf (_T(" is %s\n"), szVolName);
+       else
+               ConOutPrintf (_T(" has no label\n"));
+
+       /* print the volume serial number */
+       ConOutPrintf (_T(" Volume Serial Number is %04X-%04X\n"),
+                                 HIWORD(dwSerialNr), LOWORD(dwSerialNr));
+}
+
+
+INT cmd_vol (LPTSTR cmd, LPTSTR param)
+{
+       TCHAR szRootPath[] = _T("A:\\");
+       TCHAR szPath[MAX_PATH];
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Displays the disk volume label and serial number, if they exist.\n\n"
+                                          "VOL [drive:]"));
+               return 0;
+       }
+
+       if (param[0] == _T('\0'))
+       {
+               GetCurrentDirectory (MAX_PATH, szPath);
+               szRootPath[0] = szPath[0];
+       }
+       else
+       {
+               _tcsupr (param);
+               if (param[1] == _T(':'))
+                       szRootPath[0] = param[0];
+               else
+               {
+                       error_invalid_drive ();
+                       return 1;
+               }
+       }
+
+       if (!IsValidPathName (szRootPath))
+       {
+               error_invalid_drive ();
+               return 1;
+       }
+
+       /* print the header */
+       PrintVolumeHeader (szRootPath);
+
+       return 0;
+}
+
+#endif
diff --git a/reactos/apps/utils/cmd/where.c b/reactos/apps/utils/cmd/where.c
new file mode 100644 (file)
index 0000000..1ea1625
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ *  WHERE.C - file serch functions.
+ *
+ *
+ *  History:
+ *
+ *  07/15/95 (Tim Norman)
+ *    started.
+ *
+ *  08/08/95 (Matt Rains)
+ *    i have cleaned up the source code. changes now bring this source into
+ *    guidelines for recommended programming practice.
+ *
+ *  12/12/95 (Steffan Kaiser & Tim Norman)
+ *    added some patches to fix some things and make more efficient
+ *
+ *  1/6/96 (Tim Norman)
+ *    fixed a stupid pointer mistake...  Thanks to everyone who noticed it!
+ *
+ *  8/1/96 (Tim Norman)
+ *    fixed a bug when getenv returns NULL
+ *
+ *  8/7/96 (Steffan Kaiser and Tim Norman)
+ *    speed improvements and bug fixes
+ *
+ *  8/27/96 (Tim Norman)
+ *    changed code to use pointers directly into PATH environment variable
+ *    rather than making our own copy.  This saves some memory, but requires
+ *    we write our own function to copy pathnames out of the variable.
+ *
+ *  12/23/96 (Aaron Kaufman)
+ *    Fixed a bug in get_paths() that did not point to the first PATH in the
+ *    environment variable.
+ *
+ *  7/12/97 (Tim Norman)
+ *    Apparently, Aaron's bugfix got lost, so I fixed it again.
+ *
+ *  16 July 1998 (John P. Price)
+ *    Added stand alone code.
+ *
+ *  17 July 1998 (John P. Price)
+ *    Rewrote find_which to use searchpath function
+ *
+ * 24-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - fixed bug where didn't check all extensions when path was specified
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
+ * 30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - fixed so that it find_which returns NULL if filename is not executable
+ *   (does not have .bat, .com, or .exe extention). Before command would
+ *   to execute any file with any extension (opps!)
+ *
+ *    03-Dec_1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Changed find_which().
+ *
+ *    07-Dec_1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added ".CMD" extension.
+ *        Replaced numeric constant by _NR_OF_EXTENSIONS.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+
+static LPTSTR ext[]  = {".BAT", ".CMD", ".COM", ".EXE"};
+static INT nExtCount = sizeof(ext) / sizeof(LPTSTR);
+
+
+/* searches for file using path info. */
+
+BOOL find_which (LPCTSTR fname, LPTSTR fullbuffer)
+{
+       static TCHAR temp[MAX_PATH];
+       LPTSTR fullname;
+       INT x;
+
+       *fullbuffer = _T('\0');
+
+       /* if there an extension and it is in the last path component, then
+        * don't test all the extensions. */
+       if (!(fullname = _tcsrchr (fname, _T('.'))) ||
+               _tcschr (fullname + 1, _T('\\')))
+       {
+#ifdef _DEBUG
+               DebugPrintf ("No filename extension!\n");
+#endif
+
+               for (x = 0; x < nExtCount; x++)
+               {
+                       _tcscpy (temp, fname);
+                       _tcscat (temp, ext[x]);
+#ifdef _DEBUG
+                       DebugPrintf ("Checking for %s\n", temp);
+#endif
+                       if (_tcschr (fname, _T('\\')))
+                       {
+                               if (IsValidFileName (temp))
+                               {
+                                       _tcscpy (fullbuffer, temp);
+                                       return TRUE;
+                               }
+                       }
+                       else
+                       {
+                               _searchenv (temp, _T("PATH"), fullbuffer);
+                               if (*fullbuffer != '\0')
+                                       return TRUE;
+                       }
+               }
+       }
+       else
+       {
+               /* there is an extension... don't test other extensions */
+               /* make sure that the extention is one of the four */
+#ifdef _DEBUG
+               DebugPrintf ("No filename extension!\n");
+#endif
+               for (x = 0; x < nExtCount; x++)
+               {
+                       if (!_tcsicmp (_tcsrchr (fname, _T('.')), ext[x]))
+                       {
+                               if (_tcschr (fname, _T('\\')))
+                               {
+                                       if (IsValidFileName (fname))
+                                       {
+                                               _tcscpy (fullbuffer, fname);
+#ifdef _DEBUG
+                                               DebugPrintf ("Found: %s\n", fullbuffer);
+#endif
+                                               return TRUE;
+                                       }
+                               }
+                               else
+                               {
+#ifdef _DEBUG
+                                       DebugPrintf ("Checking for %s\n", fname);
+#endif
+                                       _searchenv (fname, _T("PATH"), fullbuffer);
+                                       if (*fullbuffer != _T('\0'))
+                                       {
+#ifdef _DEBUG
+                                               DebugPrintf ("Found: %s\n", fullbuffer);
+#endif
+                                               return TRUE;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       return FALSE;
+}
diff --git a/reactos/apps/utils/cmd/wishlist.txt b/reactos/apps/utils/cmd/wishlist.txt
new file mode 100644 (file)
index 0000000..65c518d
--- /dev/null
@@ -0,0 +1,15 @@
+
+Wishlist for ReactOS CMD
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+ - Exclusion wildcards: "del /r *.bak -abcd.bak"
+     Deletes ALL *.bak files EXCEPT abcd.bak.
+
+ - Progress indikator on long file operations (copy/move).
+     Percentage at the right side of the filename.
+
+ - [cd test directory] should change to the subdirectoy "test directory".
+
+More ideas?
+
+ Eric Kohl <ekohl@abo.rhein-zeitung.de>
\ No newline at end of file
diff --git a/rosapps/cmd/alias.c b/rosapps/cmd/alias.c
new file mode 100644 (file)
index 0000000..ac0a914
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ *  ALIAS.C - alias administration module.
+ *
+ *
+ *  History:
+ *
+ *    02/02/1996 (Oliver Mueller)
+ *        started.
+ *
+ *    02/03/1996 (Oliver Mueller)
+ *        Added sorting algorithm and case sensitive substitution by using
+ *        partstrupr().
+ *
+ *    27 Jul 1998  John P. Price
+ *        added config.h include
+ *        added ifdef's to disable aliases
+ *
+ *    09-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Fixed crash when removing an alias in DeleteAlias().
+ *        Added help text ("/?").
+ *
+ *    14-Jan-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Clean up and Unicode safe!
+ *
+ *    24-Jan-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Redirection safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef FEATURE_ALIASES
+
+#include <windows.h>
+#include <tchar.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "cmd.h"
+
+
+typedef struct tagALIAS
+{
+       struct tagALIAS *next;
+       LPTSTR lpName;
+       LPTSTR lpSubst;
+       WORD   wUsed;
+} ALIAS, *LPALIAS;
+
+
+static LPALIAS lpFirst = NULL;
+static LPALIAS lpLast = NULL;
+static WORD    wUsed = 0;
+
+
+/* module internal functions */
+/* strlwr only for first word in string */
+static VOID
+partstrlwr (LPTSTR str)
+{
+       LPTSTR c = str;
+       while (*c && !_istspace (*c))
+       {
+               *c = _totlower (*c);
+               c++;
+       }
+}
+
+
+static VOID
+PrintAlias (VOID)
+{
+       LPALIAS ptr = lpFirst;
+       while (ptr)
+       {
+               ConOutPrintf (_T("%s=%s\n"), ptr->lpName, ptr->lpSubst);
+               ptr = ptr->next;
+       }
+}
+
+
+static VOID
+DeleteAlias (LPTSTR pszName)
+{
+       LPALIAS ptr = lpFirst;
+       LPALIAS prev = NULL;
+
+       while (ptr)
+       {
+               if (!_tcsicmp (ptr->lpName, pszName))
+               {
+                       if (prev)
+                               prev->next = ptr->next;
+                       else
+                               lpFirst = ptr->next;
+                       free (ptr->lpName);
+                       free (ptr->lpSubst);
+                       free (ptr);
+                       return;
+               }
+               prev = ptr;
+               ptr = ptr->next;
+       }
+}
+
+
+static INT
+AddAlias (LPTSTR name, LPTSTR subst)
+{
+       LPALIAS ptr = lpFirst;
+       LPALIAS prev, entry;
+       LPTSTR s;
+
+       while (ptr)
+       {
+               if (!_tcsicmp (ptr->lpName, name))
+               {
+                       s = (LPTSTR)malloc ((_tcslen (subst) + 1)*sizeof(TCHAR));
+                       if (!s)
+                       {
+                               error_out_of_memory ();
+                               return 1;
+                       }
+
+                       free (ptr->lpSubst);
+                       ptr->lpSubst = s;
+                       _tcscpy (ptr->lpSubst, subst);
+                       return 0;
+               }
+               ptr = ptr->next;
+       }
+
+       ptr = (LPALIAS)malloc (sizeof (ALIAS));
+       if (!ptr)
+               return 1;
+
+       ptr->next = 0;
+
+       ptr->lpName = (LPTSTR)malloc ((_tcslen (name) + 1)*sizeof(TCHAR));
+       if (!ptr->lpName)
+       {
+               error_out_of_memory ();
+               free (ptr);
+               return 1;
+       }
+       _tcscpy (ptr->lpName, name);
+
+       ptr->lpSubst = (LPTSTR)malloc ((_tcslen (subst) + 1)*sizeof(TCHAR));
+       if (!ptr->lpSubst)
+       {
+               error_out_of_memory ();
+               free (ptr->lpName);
+               free (ptr);
+               return 1;
+       }
+       _tcscpy (ptr->lpSubst, subst);
+
+       /* it's necessary for recursive substitution */
+       partstrlwr (ptr->lpSubst);
+
+       ptr->wUsed = 0;
+
+       /* Alias table must be sorted!
+        * Here a little example:
+        *   command line = "ls -c"
+        * If the entries are
+        *   ls=dir
+        *   ls -c=ls /w
+        * command line will be expanded to "dir -c" which is not correct.
+        * If the entries are sortet as
+        *   ls -c=ls /w
+        *   ls=dir
+        * it will be expanded to "dir /w" which is a valid DOS command.
+        */
+       entry = lpFirst;
+       prev = 0;
+       while (entry)
+       {
+               if (_tcsicmp (ptr->lpName, entry->lpName) > 0)
+               {
+                       if (prev)
+                       {
+                               prev->next = ptr;
+                               ptr->next = entry;
+                       }
+                       else
+                       {
+                               ptr->next = entry;
+                               lpFirst = ptr;
+                       }
+                       return 0;
+               }
+               prev = entry;
+               entry = entry->next;
+       }
+
+       /* The new entry is the smallest (or the first) and must be
+        * added to the end of the list.
+        */
+       if (!lpFirst)
+               lpFirst = ptr;
+       else
+               lpLast->next = ptr;
+       lpLast = ptr;
+
+       return 0;
+}
+
+
+/* specified routines */
+VOID ExpandAlias (LPTSTR cmd, INT maxlen)
+{
+       unsigned n = 0,
+               m,
+               i,
+               len;
+       short d = 1;
+       LPALIAS ptr = lpFirst;
+
+       wUsed++;
+       if (wUsed == 0)
+       {
+               while (ptr)
+                       ptr->wUsed = 0;
+               ptr = lpFirst;
+               wUsed = 1;
+       }
+
+       /* skipping white spaces */
+       while (_istspace (cmd[n]))
+               n++;
+
+       partstrlwr (&cmd[n]);
+
+       if (!_tcsncmp (&cmd[n], _T("NOALIAS"), 7) &&
+               (_istspace (cmd[n + 7]) || cmd[n + 7] == _T('\0')))
+       {
+               memmove (cmd, &cmd[n + 7], (_tcslen (&cmd[n + 7]) + 1) * sizeof (TCHAR));
+               return;
+       }
+
+       /* substitution loop */
+       while (d)
+       {
+               d = 0;
+               while (ptr)
+               {
+                       len = _tcslen (ptr->lpName);
+                       if (!_tcsncmp (&cmd[n], ptr->lpName, len) &&
+                               (_istspace (cmd[n + len]) || cmd[n + len] == _T('\0')) &&
+                               ptr->wUsed != wUsed)
+                       {
+                               m = _tcslen (ptr->lpSubst);
+                               if ((int)(_tcslen (cmd) - len + m - n) > maxlen)
+                               {
+                                       ConErrPrintf (_T("Command line too long after alias expansion!\n"));
+                                       /* the parser won't cause any problems with an empty line */
+                                       cmd[0] = _T('\0');
+                               }
+                               else
+                               {
+                                       memmove (&cmd[m], &cmd[n + len], (_tcslen(&cmd[n + len]) + 1) * sizeof (TCHAR));
+                                       for (i = 0; i < m; i++)
+                                               cmd[i] = ptr->lpSubst[i];
+                                       ptr->wUsed = wUsed;
+                                       /* whitespaces are removed! */
+                                       n = 0;
+                                       d = 1;
+                               }
+                       }
+                       ptr = ptr->next;
+               }
+       }
+}
+
+
+INT cmd_alias (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR ptr;
+       INT n = 0;
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Sets, removes or shows aliases.\n"
+                                          "\n"
+                                          "ALIAS [alias=[command]]\n"
+                                          "\n"
+                                          "  alias    Name for an alias.\n"
+                                          "  command  Text to be substituted for an alias.\n"
+                                          "\n"
+//                                        "For example:\n"
+                                          "To list all aliases:\n"
+                                          "  ALIAS\n\n"
+                                          "To set a new or replace an existing alias:\n"
+                                          "  ALIAS da=dir a:\n\n"
+                                          "To remove an alias from the alias list:\n"
+                                          "  ALIAS da="
+//                                        "Type ALIAS without a parameter to display the alias list.\n"
+                                          ));
+               return 0;
+       }
+
+       if (param[0] == _T('\0'))
+       {
+               PrintAlias ();
+               return 0;
+       }
+
+       /* error if no '=' found */
+       if ((ptr = _tcschr (param, _T('='))) == 0)
+               return -1;
+
+       /* Split rest into name and substitute */
+       *ptr++ = _T('\0');
+
+       partstrlwr (param);
+
+       if (ptr[0] == _T('\0'))
+               DeleteAlias (param);
+       else
+               n = AddAlias (param, ptr);
+
+       return n;
+}
+#endif
diff --git a/rosapps/cmd/attrib.c b/rosapps/cmd/attrib.c
new file mode 100644 (file)
index 0000000..65a2c31
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ *  ATTRIB.C - attrib internal command.
+ *
+ *
+ *  History:
+ *
+ *    04-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        started
+ *
+ *    09-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        implementation works, except recursion ("attrib /s").
+ *
+ *    05-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        major rewrite.
+ *        fixed recursion ("attrib /s").
+ *        started directory support ("attrib /s /d").
+ *        updated help text.
+ *
+ *    14-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode ready!
+ *
+ *    19-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Redirection ready!
+ *
+ *    21-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added check for invalid filenames.
+ *
+ *    23-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added handling of multiple filenames.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_ATTRIB
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+
+static VOID
+PrintAttribute (LPTSTR pszPath, LPTSTR pszFile, BOOL bRecurse)
+{
+       WIN32_FIND_DATA findData;
+       HANDLE hFind;
+       TCHAR  szFullName[MAX_PATH];
+       LPTSTR pszFileName;
+
+       /* prepare full file name buffer */
+       _tcscpy (szFullName, pszPath);
+       pszFileName = szFullName + _tcslen (szFullName);
+
+       /* display all subdirectories */
+       if (bRecurse)
+       {
+               /* append file name */
+               _tcscpy (pszFileName, pszFile);
+
+               hFind = FindFirstFile (szFullName, &findData);
+               if (hFind == INVALID_HANDLE_VALUE)
+               {
+                       ErrorMessage (GetLastError (), pszFile);
+                       return;
+               }
+
+               do
+               {
+                       if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+                               continue;
+
+                       if (!_tcscmp (findData.cFileName, _T(".")) ||
+                               !_tcscmp (findData.cFileName, _T("..")))
+                               continue;
+
+                       _tcscpy (pszFileName, findData.cFileName);
+                       _tcscat (pszFileName, _T("\\"));
+                       PrintAttribute (szFullName, pszFile, bRecurse);
+               }
+               while (FindNextFile (hFind, &findData));
+               FindClose (hFind);
+       }
+
+       /* append file name */
+       _tcscpy (pszFileName, pszFile);
+
+       /* display current directory */
+       hFind = FindFirstFile (szFullName, &findData);
+       if (hFind == INVALID_HANDLE_VALUE)
+       {
+               ErrorMessage (GetLastError (), pszFile);
+               return;
+       }
+
+       do
+       {
+               if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+                       continue;
+
+               _tcscpy (pszFileName, findData.cFileName);
+
+               ConOutPrintf (_T("%c  %c%c%c     %s\n"),
+                                 (findData.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ? _T('A') : _T(' '),
+                                 (findData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) ? _T('S') : _T(' '),
+                                 (findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? _T('H') : _T(' '),
+                                 (findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? _T('R') : _T(' '),
+                                 szFullName);
+       }
+       while (FindNextFile (hFind, &findData));
+       FindClose (hFind);
+}
+
+
+static VOID
+ChangeAttribute (LPTSTR pszPath, LPTSTR pszFile, DWORD dwMask,
+                                DWORD dwAttrib, BOOL bRecurse, BOOL bDirectories)
+{
+       WIN32_FIND_DATA findData;
+       HANDLE hFind;
+       DWORD  dwAttribute;
+       TCHAR  szFullName[MAX_PATH];
+       LPTSTR pszFileName;
+
+       /* prepare full file name buffer */
+       _tcscpy (szFullName, pszPath);
+       pszFileName = szFullName + _tcslen (szFullName);
+
+       /* change all subdirectories */
+       if (bRecurse)
+       {
+               /* append file name */
+               _tcscpy (pszFileName, _T("*.*"));
+
+               hFind = FindFirstFile (szFullName, &findData);
+               if (hFind == INVALID_HANDLE_VALUE)
+               {
+                       ErrorMessage (GetLastError (), pszFile);
+                       return;
+               }
+
+               do
+               {
+                       if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+                       {
+                               if (!_tcscmp (findData.cFileName, _T(".")) ||
+                                       !_tcscmp (findData.cFileName, _T("..")))
+                                       continue;
+
+                               _tcscpy (pszFileName, findData.cFileName);
+                               _tcscat (pszFileName, _T("\\"));
+
+                               ChangeAttribute (szFullName, pszFile, dwMask,
+                                                                dwAttrib, bRecurse, bDirectories);
+                       }
+               }
+               while (FindNextFile (hFind, &findData));
+               FindClose (hFind);
+       }
+
+       /* append file name */
+       _tcscpy (pszFileName, pszFile);
+
+       hFind = FindFirstFile (szFullName, &findData);
+       if (hFind == INVALID_HANDLE_VALUE)
+       {
+               ErrorMessage (GetLastError (), pszFile);
+               return;
+       }
+
+       do
+       {
+               if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+                       continue;
+
+               _tcscpy (pszFileName, findData.cFileName);
+
+               dwAttribute = GetFileAttributes (szFullName);
+
+               if (dwAttribute != 0xFFFFFFFF)
+               {
+                       dwAttribute = (dwAttribute & ~dwMask) | dwAttrib;
+                       SetFileAttributes (szFullName, dwAttribute);
+               }
+       }
+       while (FindNextFile (hFind, &findData));
+       FindClose (hFind);
+}
+
+
+INT cmd_attrib (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR *arg;
+       INT    argc, i;
+       TCHAR  szPath[MAX_PATH];
+       TCHAR  szFileName [MAX_PATH];
+       BOOL   bRecurse = FALSE;
+       BOOL   bDirectories = FALSE;
+       DWORD  dwAttrib = 0;
+       DWORD  dwMask = 0;
+
+       /* initialize strings */
+       szPath[0] = _T('\0');
+       szFileName[0] = _T('\0');
+
+       /* print help */
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Displays or changes file attributes.\n\n"
+                                          "ATTRIB [+R | -R] [+A | -A] [+S | -S] [+H | -H] file ...\n"
+                                          "       [/S [/D]]\n\n"
+                                          "  +   Sets an attribute\n"
+                                          "  -   Clears an attribute\n"
+                                          "  R   Read-only file attribute\n"
+                                          "  A   Archive file attribute\n"
+                                          "  S   System file attribute\n"
+                                          "  H   Hidden file attribute\n"
+                                          "  /S  Processes matching files in the current directory\n"
+                                          "      and all subdirectories\n"
+                                          "  /D  Processes direcories as well\n\n"
+                                          "Type ATTRIB without a parameter to display the attributes of all files."));
+               return 0;
+       }
+
+       /* build parameter array */
+       arg = split (param, &argc);
+
+       /* check for options */
+       for (i = 0; i < argc; i++)
+       {
+               if (_tcsicmp (arg[i], _T("/s")) == 0)
+                       bRecurse = TRUE;
+               else if (_tcsicmp (arg[i], _T("/d")) == 0)
+                       bDirectories = TRUE;
+       }
+
+       /* create attributes and mask */
+       for (i = 0; i < argc; i++)
+       {
+               if (*arg[i] == _T('+'))
+               {
+                       if (_tcslen (arg[i]) != 2)
+                       {
+                               error_invalid_parameter_format (arg[i]);
+                               freep (arg);
+                               return -1;
+                       }
+
+                       switch ((TCHAR)_totupper (arg[i][1]))
+                       {
+                               case _T('A'):
+                                       dwMask   |= FILE_ATTRIBUTE_ARCHIVE;
+                                       dwAttrib |= FILE_ATTRIBUTE_ARCHIVE;
+                                       break;
+
+                               case _T('H'):
+                                       dwMask   |= FILE_ATTRIBUTE_HIDDEN;
+                                       dwAttrib |= FILE_ATTRIBUTE_HIDDEN;
+                                       break;
+
+                               case _T('R'):
+                                       dwMask   |= FILE_ATTRIBUTE_READONLY;
+                                       dwAttrib |= FILE_ATTRIBUTE_READONLY;
+                                       break;
+
+                               case _T('S'):
+                                       dwMask   |= FILE_ATTRIBUTE_SYSTEM;
+                                       dwAttrib |= FILE_ATTRIBUTE_SYSTEM;
+                                       break;
+
+                               default:
+                                       error_invalid_parameter_format (arg[i]);
+                                       freep (arg);
+                                       return -1;
+                       }
+               }
+               else if (*arg[i] == _T('-'))
+               {
+                       if (_tcslen (arg[i]) != 2)
+                       {
+                               error_invalid_parameter_format (arg[i]);
+                               freep (arg);
+                               return -1;
+                       }
+
+                       switch ((TCHAR)_totupper (arg[i][1]))
+                       {
+                               case _T('A'):
+                                       dwMask   |= FILE_ATTRIBUTE_ARCHIVE;
+                                       dwAttrib &= ~FILE_ATTRIBUTE_ARCHIVE;
+                                       break;
+
+                               case _T('H'):
+                                       dwMask   |= FILE_ATTRIBUTE_HIDDEN;
+                                       dwAttrib &= ~FILE_ATTRIBUTE_HIDDEN;
+                                       break;
+
+                               case _T('R'):
+                                       dwMask   |= FILE_ATTRIBUTE_READONLY;
+                                       dwAttrib &= ~FILE_ATTRIBUTE_READONLY;
+                                       break;
+
+                               case _T('S'):
+                                       dwMask   |= FILE_ATTRIBUTE_SYSTEM;
+                                       dwAttrib &= ~FILE_ATTRIBUTE_SYSTEM;
+                                       break;
+
+                               default:
+                                       error_invalid_parameter_format (arg[i]);
+                                       freep (arg);
+                                       return -1;
+                       }
+               }
+       }
+
+       if (argc == 0)
+       {
+               GetCurrentDirectory (MAX_PATH, szPath);
+               _tcscat (szPath, _T("\\"));
+               _tcscpy (szFileName, _T("*.*"));
+               PrintAttribute (szPath, szFileName, bRecurse);
+       }
+       else
+       {
+               /* get full file name */
+               for (i = 0; i < argc; i++)
+               {
+                       if ((*arg[i] != _T('+')) && (*arg[i] != _T('-')) &&     (*arg[i] != _T('/')))
+                       {
+                               LPTSTR p;
+                               GetFullPathName (arg[i], MAX_PATH, szPath, NULL);
+                               p = _tcsrchr (szPath, _T('\\')) + 1;
+                               _tcscpy (szFileName, p);
+                               *p = _T('\0');
+
+                               if (dwMask == 0)
+                                       PrintAttribute (szPath, szFileName, bRecurse);
+                               else
+                                       ChangeAttribute (szPath, szFileName, dwMask,
+                                                                        dwAttrib, bRecurse, bDirectories);
+                       }
+               }
+       }
+
+       freep (arg);
+
+       return 0;
+}
+
+#endif /* INCLUDE_CMD_ATTRIB */
diff --git a/rosapps/cmd/batch.c b/rosapps/cmd/batch.c
new file mode 100644 (file)
index 0000000..b1ea5be
--- /dev/null
@@ -0,0 +1,462 @@
+/*
+ *  BATCH.C - batch file processor for CMD.EXE.
+ *
+ *
+ *  History:
+ *
+ *    ??/??/?? (Evan Jeffrey)
+ *        started.
+ *
+ *    15 Jul 1995 (Tim Norman)
+ *        modes and bugfixes.
+ *
+ *    08 Aug 1995 (Matt Rains)
+ *        i have cleaned up the source code. changes now bring this
+ *        source into guidelines for recommended programming practice.
+ *
+ *        i have added some constants to help making changes easier.
+ *
+ *    29 Jan 1996 (Steffan Kaiser)
+ *        made a few cosmetic changes
+ *
+ *    05 Feb 1996 (Tim Norman)
+ *        changed to comply with new first/rest calling scheme
+ *
+ *    14 Jun 1997 (Steffen Kaiser)
+ *        bug fixes.  added error level expansion %?.  ctrl-break handling
+ *
+ *    16 Jul 1998 (Hans B Pufal)
+ *        Totally reorganised in conjunction with COMMAND.C (cf) to
+ *        implement proper BATCH file nesting and other improvements.
+ *
+ *    16 Jul 1998 (John P Price <linux-guru@gcfl.net>)
+ *        Seperated commands into individual files.
+ *
+ *    19 Jul 1998 (Hans B Pufal) [HBP_001]
+ *        Preserve state of echo flag across batch calls.
+ *
+ *    19 Jul 1998 (Hans B Pufal) [HBP_002]
+ *        Implementation of FOR command
+ *
+ *    20-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added error checking after malloc calls
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    02-Aug-1998 (Hans B Pufal) [HBP_003]
+ *        Fixed bug in ECHO flag restoration at exit from batch file
+ *
+ *    26-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Replaced CRT io functions by Win32 io functions.
+ *        Unicode safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+/* The stack of current batch contexts.
+ * NULL when no batch is active
+ */
+LPBATCH_CONTEXT bc = NULL;
+
+BOOL bEcho = TRUE;          /* The echo flag */
+
+
+
+/* Buffer for reading Batch file lines */
+TCHAR textline[BATCH_BUFFSIZE];
+
+
+/*
+ * Returns a pointer to the n'th parameter of the current batch file.
+ * If no such parameter exists returns pointer to empty string.
+ * If no batch file is current, returns NULL
+ *
+ */
+
+LPTSTR FindArg (INT n)
+{
+       LPTSTR pp;
+
+#ifdef _DEBUG
+       DebugPrintf ("FindArg: (%d)\n", n);
+#endif
+
+       if (bc == NULL)
+               return NULL;
+
+       n += bc->shiftlevel;
+       pp = bc->params;
+
+       /* Step up the strings till we reach the end */
+       /* or the one we want */
+       while (*pp && n--)
+               pp += _tcslen (pp) + 1;
+
+       return pp;
+}
+
+
+/* HBP_002 { FOR command support */
+/*
+ * Batch_params builds a parameter list in newlay allocated memory.
+ * The parameters consist of null terminated strings with a final
+ * NULL character signalling the end of the parameters.
+ *
+*/
+
+LPTSTR BatchParams (LPTSTR s1, LPTSTR s2)
+{
+       LPTSTR dp = (LPTSTR)malloc ((_tcslen(s1) + _tcslen(s2) + 3) * sizeof (TCHAR));
+
+       /* JPP 20-Jul-1998 added error checking */
+       if (dp == NULL)
+       {
+               error_out_of_memory();
+               return NULL;
+       }
+
+       if (s1 && *s1)
+       {
+               s1 = stpcpy (dp, s1);
+               *s1++ = _T('\0');
+       }
+       else
+               s1 = dp;
+
+       while (*s2)
+       {
+               if (_istspace (*s2) || _tcschr (_T(",;"), *s2))
+               {
+                       *s1++ = _T('\0');
+                       s2++;
+                       while (*s2 && _tcschr (_T(" ,;"), *s2))
+                               s2++;
+                       continue;
+               }
+
+               if ((*s2 == _T('"')) || (*s2 == _T('\'')))
+               {
+                       TCHAR st = *s2;
+
+                       do
+                               *s1++ = *s2++;
+                       while (*s2 && (*s2 != st));
+               }
+
+               *s1++ = *s2++;
+       }
+
+       *s1++ = _T('\0');
+       *s1 = _T('\0');
+
+       return dp;
+}
+
+/* HBP_002 } */
+
+
+/*
+ * If a batch file is current, exits it, freeing the context block and
+ * chaining back to the previous one.
+ *
+ * If no new batch context is found, sets ECHO back ON.
+ *
+ * If the parameter is non-null or not empty, it is printed as an exit
+ * message
+ */
+
+VOID ExitBatch (LPTSTR msg)
+{
+#ifdef _DEBUG
+       DebugPrintf ("ExitBatch: (\'%s\')\n", msg);
+#endif
+
+       if (bc)
+       {
+               LPBATCH_CONTEXT t = bc;
+
+               if (bc->hBatchFile)
+               {
+                       CloseHandle (bc->hBatchFile);
+                       bc->hBatchFile = INVALID_HANDLE_VALUE;
+               }
+
+               if (bc->params)
+                       free(bc->params);
+
+/* HBP_002 { FOR command support */
+
+               if (bc->forproto)
+                       free(bc->forproto);
+
+               if (bc->ffind)
+                       free(bc->ffind);
+
+/* HBP_002 } */
+
+/* HBP_003 { fix echo restore */
+               /* Preserve echo state across batch calls */
+               bEcho = bc->bEcho;
+
+/* HBP_003 fix echo restore } */
+
+               bc = bc->prev;
+               free(t);
+       }
+
+/* HBP_001 } */
+
+       if (msg && *msg)
+               ConOutPrintf ("%s\n", msg);
+}
+
+
+/*
+ * Start batch file execution
+ *
+ * The firstword parameter is the full filename of the batch file.
+ *
+ */
+
+BOOL Batch (LPTSTR fullname, LPTSTR firstword, LPTSTR param)
+{
+       HANDLE hFile;
+
+       hFile = CreateFile (fullname, GENERIC_READ, FILE_SHARE_READ, NULL,
+                                               OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL |
+                                               FILE_FLAG_SEQUENTIAL_SCAN, NULL);
+
+#ifdef _DEBUG
+       DebugPrintf ("Batch: (\'%s\', \'%s\', \'%s\')  hFile = %x\n",
+                                fullname, firstword, param, hFile);
+#endif
+
+       if (hFile == INVALID_HANDLE_VALUE)
+       {
+               ConErrPrintf (_T("Error opening batch file\n"));
+               return FALSE;
+       }
+
+/* HBP_002 { FOR command support */
+
+       /* Kill any and all FOR contexts */
+       while (bc && bc->forvar)
+               ExitBatch (NULL);
+
+/* HBP_002 } */
+
+       if (bc == NULL)
+       {
+               /* No curent batch file, create a new context */
+               LPBATCH_CONTEXT n = (LPBATCH_CONTEXT)malloc (sizeof(BATCH_CONTEXT));
+
+               if (n == NULL)
+               {
+                       /* JPP 20-Jul-1998 added error checking */
+                       error_out_of_memory ();
+                       return FALSE;
+               }
+
+               n->prev = bc;
+               bc = n;
+       }
+       else if (bc->hBatchFile != INVALID_HANDLE_VALUE)
+       {
+               /* Then we are transferring to another batch */
+               CloseHandle (bc->hBatchFile);
+               bc->hBatchFile = INVALID_HANDLE_VALUE;
+               free (bc->params);
+       }
+
+       bc->hBatchFile = hFile;
+       bc->bEcho = bEcho; /* Preserve echo across batch calls [HBP_001] */
+       bc->shiftlevel = 0;
+
+       /* HBP_002 { FOR command support */
+       bc->ffind = NULL;
+       bc->forvar = _T('\0');
+       bc->forproto = NULL;
+       bc->params = BatchParams (firstword, param);
+       /* HBP_002 } */
+
+       return TRUE;
+}
+
+
+/*
+ * Read and return the next executable line form the current batch file
+ *
+ * If no batch file is current or no further executable lines are found
+ * return NULL.
+ *
+ * Here we also look out for FOR bcontext structures which trigger the
+ * FOR expansion code.
+ *
+ * Set eflag to 0 if line is not to be echoed else 1
+ */
+
+LPTSTR ReadBatchLine (LPBOOL bLocalEcho)
+{
+       HANDLE hFind = INVALID_HANDLE_VALUE;
+       LPTSTR first;
+       LPTSTR ip;
+
+       /* No batch */
+       if (bc == NULL)
+               return NULL;
+
+#ifdef _DEBUG
+       DebugPrintf ("ReadBatchLine ()\n");
+#endif
+
+       while (1)
+       {
+               /* User halt */
+               if (CheckCtrlBreak (BREAK_BATCHFILE))
+               {
+                       while (bc)
+                               ExitBatch (NULL);
+                       return NULL;
+               }
+
+               /* HBP_002 { FOR command support */
+               /* No batch */
+               if (bc == NULL)
+                       return NULL;
+
+               /* If its a FOR context... */
+               if (bc->forvar)
+               {
+                       LPTSTR sp = bc->forproto; /* pointer to prototype command */
+                       LPTSTR dp = textline;     /* Place to expand protoype */
+                       LPTSTR fv = FindArg (0);  /* Next list element */
+
+                       /* End of list so... */
+                       if ((fv == NULL) || (*fv == _T('\0')))
+                       {
+                               /* just exit this context */
+                               ExitBatch (NULL);
+                               continue;
+                       }
+
+                       if (_tcscspn (fv, _T("?*")) == _tcslen (fv))
+                       {
+                               /* element is wild file */
+                               bc->shiftlevel++;       /* No use it and shift list */
+                       }
+                       else
+                       {
+                               /* Wild file spec, find first (or next) file name */
+                               if (bc->ffind)
+                               {
+                                       /* First already done so do next */
+                                       fv = FindNextFile (hFind, bc->ffind) ? bc->ffind->cFileName : NULL;
+                               }
+                               else
+                               {
+                                       /*  For first find, allocate a find first block */
+                                       if ((bc->ffind = (LPWIN32_FIND_DATA)malloc (sizeof (WIN32_FIND_DATA))) == NULL)
+                                       {
+                                               error_out_of_memory();  /* JPP 20-Jul-1998 added error checking */
+                                               return NULL;
+                                       }
+
+                                       hFind = FindFirstFile (fv, bc->ffind);
+                                       fv = !(hFind==INVALID_HANDLE_VALUE) ? bc->ffind->cFileName : NULL;
+                               }
+
+                               if (fv == NULL)
+                               {
+                                       /* Null indicates no more files.. */
+                                       free (bc->ffind);      /* free the buffer */
+                                       bc->ffind = NULL;
+                                       bc->shiftlevel++;     /* On to next list element */
+                                       continue;
+                               }
+                       }
+
+                       /* At this point, fv points to parameter string */
+                       while (*sp)
+                       {
+                               if ((*sp == _T('%')) && (*(sp + 1) == bc->forvar))
+                               {
+                                       /* replace % var */
+                                       dp = stpcpy (dp, fv);
+                                       sp += 2;
+                               }
+                               else
+                               {
+                                       /* Else just copy */
+                                       *dp++ = *sp++;
+                               }
+                       }
+
+                       *dp = _T('\0');
+
+                       *bLocalEcho = bEcho;
+
+                       return textline;
+               }
+
+               /* HBP_002 } */
+
+               if (!FileGetString (bc->hBatchFile, textline, sizeof (textline)))
+               {
+#ifdef _DEBUG
+                       DebugPrintf (_T("ReadBatchLine(): Reached EOF!\n"));
+#endif
+                       /* End of file.... */
+                       ExitBatch (NULL);
+
+                       if (bc == NULL)
+                               return NULL;
+
+                       continue;
+               }
+
+#ifdef _DEBUG
+               DebugPrintf (_T("ReadBatchLine(): textline: \'%s\'\n"), textline);
+#endif
+
+               /* Strip leading spaces and trailing space/control chars */
+               for (first = textline; _istspace (*first); first++)
+                       ;
+
+               for (ip = first + _tcslen (first) - 1; _istspace (*ip) || _istcntrl (*ip); ip--)
+                       ;
+
+               *++ip = _T('\0');
+
+               /* ignore labels and empty lines */
+               if (*first == _T(':') || *first == 0)
+                       continue;
+
+               if (*first == _T('@'))
+               {
+                       /* don't echo this line */
+                       do
+                               first++;
+                       while (_istspace (*first));
+
+                       *bLocalEcho = 0;
+               }
+               else
+                       *bLocalEcho = bEcho;
+
+               break;
+       }
+
+       return first;
+}
diff --git a/rosapps/cmd/batch.h b/rosapps/cmd/batch.h
new file mode 100644 (file)
index 0000000..11324e3
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ *  BATCH.H - A structure to preserve the context of a batch file
+ *
+ *
+ */
+
+
+typedef struct tagBATCHCONTEXT
+{
+       struct tagBATCHCONTEXT *prev;
+       LPWIN32_FIND_DATA ffind;
+       HANDLE hBatchFile;
+       LPTSTR forproto;
+       LPTSTR params;
+       INT    shiftlevel;
+       BOOL   bEcho;        /* Preserve echo flag across batch calls [HBP_001] */
+       TCHAR forvar;
+} BATCH_CONTEXT, *LPBATCH_CONTEXT;
+
+/* HBP_002 } */
+
+
+/*  The stack of current batch contexts.
+ * NULL when no batch is active
+ */
+extern LPBATCH_CONTEXT bc;
+
+extern BOOL bEcho;       /* The echo flag */
+
+#define BATCH_BUFFSIZE  2048
+
+extern TCHAR textline[BATCH_BUFFSIZE]; /* Buffer for reading Batch file lines */
+
+
+LPTSTR FindArg (INT);
+LPTSTR BatchParams (LPTSTR, LPTSTR);
+VOID   ExitBatch (LPTSTR);
+BOOL   Batch (LPTSTR, LPTSTR, LPTSTR);
+LPTSTR ReadBatchLine (LPBOOL);
diff --git a/rosapps/cmd/beep.c b/rosapps/cmd/beep.c
new file mode 100644 (file)
index 0000000..9f9834c
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ *  BEEP.C - beep internal 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
+ *
+ *    14-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("beep /?").
+ *        Unicode ready!
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Redirection ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_BEEP
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+INT cmd_beep (LPTSTR cmd, LPTSTR param)
+{
+       if (_tcsncmp (param, _T("/?"), 2) == 0)
+       {
+               ConOutPuts (_T("Beep the speaker.\n\nBEEP"));
+               return 0;
+       }
+
+#if 0
+       /* check if run in batch mode */
+       if (bc == NULL)
+               return 1;
+#endif
+
+       MessageBeep (-1);
+
+       return 0;
+}
+#endif
diff --git a/rosapps/cmd/bugs.txt b/rosapps/cmd/bugs.txt
new file mode 100644 (file)
index 0000000..2cfa275
--- /dev/null
@@ -0,0 +1,15 @@
+         ****  Please report bugs to ekohl@abo.rhein-zeitung.de!  ****
+
+Known bugs in CMD version 0.0.4
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+o  let set work with or without the '=' sign.  People like it that way.
+    (I don't know, if I should really fix this?)
+
+o  command.com ignores control-c and control-break, which makes it difficult
+   to quit typing a long file, among other things
+
+o  "alias v = dir" doesn't work because of the spaces.
+
+
+         ****  Please report bugs to ekohl@abo.rhein-zeitung.de!  ****
diff --git a/rosapps/cmd/call.c b/rosapps/cmd/call.c
new file mode 100644 (file)
index 0000000..db5dd63
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ *  CALL.C - call internal batch command.
+ *
+ *
+ *  History:
+ *
+ *    16 Jul 1998 (Hans B Pufal)
+ *        started.
+ *
+ *    16 Jul 1998 (John P Price)
+ *        Seperated 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 <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("call /?") and cleaned up.
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+/*
+ * Perform CALL command.
+ *
+ * Allocate a new batch context and add it to the current chain.
+ * Call parsecommandline passing in our param string
+ * If No batch file was opened then remove our newly allocted
+ * context block.
+ */
+
+INT cmd_call (LPTSTR cmd, LPTSTR param)
+{
+       LPBATCH_CONTEXT n = NULL;
+
+#ifdef _DEBUG
+       DebugPrintf ("cmd_call: (\'%s\',\'%s\')\n", cmd, param);
+#endif
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Calls one batch program from another.\n\n"
+                                          "CALL [drive:][path]filename [batch-parameter]\n\n"
+                                          "  batch-parameter  Specifies any command-line information required by the\n"
+                                          "                   batch program."));
+               return 0;
+       }
+
+       n = (LPBATCH_CONTEXT)malloc (sizeof (BATCH_CONTEXT));
+
+       if (n == NULL)
+       {
+               error_out_of_memory ();
+               return 1;
+       }
+
+       n->prev = bc;
+       bc = n;
+
+       bc->hBatchFile = INVALID_HANDLE_VALUE;
+       bc->params = NULL;
+       bc->shiftlevel = 0;
+       bc->forvar = 0;        /* HBP004 */
+       bc->forproto = NULL;   /* HBP004 */
+
+       ParseCommandLine (param);
+
+       /* Wasn't a batch file so remove conext */
+       if (bc->hBatchFile == INVALID_HANDLE_VALUE)
+       {
+               bc = bc->prev;
+               free (n);
+       }
+
+       return 0;
+}
diff --git a/rosapps/cmd/chcp.c b/rosapps/cmd/chcp.c
new file mode 100644 (file)
index 0000000..6831e57
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ *  CHCP.C - chcp internal command.
+ *
+ *
+ *  History:
+ *
+ *    23-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Started.
+ *
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_CHCP
+
+#include <windows.h>
+#include <tchar.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+#include "chcp.h"
+
+
+INT CommandChcp (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR *arg;
+       INT    args;
+
+       /* print help */
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Displays or sets the active code page number.\n\n"
+                                          "CHCP [nnn]\n\n"
+                                          "  nnn   Specifies the active code page number.\n\n"
+                                          "Type CHCP without a parameter to display the active code page number."));
+               return 0;
+       }
+
+       /* get parameters */
+       arg = split (param, &args);
+
+       if (args == 0)
+       {
+               /* display active code page number */
+               ConOutPrintf ("Active code page: %u\n", GetConsoleCP ());
+       }
+       else if (args >= 2)
+       {
+               /* too many parameters */
+               ConErrPrintf ("Invalid parameter format - %s\n", param);
+       }
+       else
+       {
+               /* set active code page number */
+
+               UINT uOldCodePage;
+               UINT uNewCodePage;
+
+               /* save old code page */
+               uOldCodePage = GetConsoleCP ();
+
+               uNewCodePage = (UINT)_ttoi (arg[0]);
+
+               if (uNewCodePage == 0)
+               {
+                       ConErrPrintf ("Parameter format incorrect - %s\n", arg[0]);
+
+               }
+               else
+               {
+                       if (!SetConsoleCP (uNewCodePage))
+                       {
+                               ConErrPrintf ("Invalid code page\n");
+                       }
+                       else
+                       {
+                               SetConsoleOutputCP (uNewCodePage);
+                               InitLocale ();
+                       }
+               }
+       }
+
+       freep (arg);
+
+       return 0;
+}
+
+#endif /* INCLUDE_CMD_CHCP */
\ No newline at end of file
diff --git a/rosapps/cmd/chcp.h b/rosapps/cmd/chcp.h
new file mode 100644 (file)
index 0000000..11ff568
--- /dev/null
@@ -0,0 +1,8 @@
+/* prototypes for CHCP.C */
+
+
+#ifdef INCLUDE_CMD_CHCP
+
+INT CommandChcp (LPTSTR, LPTSTR);
+
+#endif
\ No newline at end of file
diff --git a/rosapps/cmd/cls.c b/rosapps/cmd/cls.c
new file mode 100644 (file)
index 0000000..2e27fcc
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *  CLS.C - clear screen internal command.
+ *
+ *
+ *  History:
+ *
+ *    07/27/1998 (John P. Price)
+ *        started.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    04-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Changed to Win32 console app.
+ *
+ *    08-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("/?").
+ *
+ *    14-Jan-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode ready!
+ *
+ *    20-Jan-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Redirection ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_CLS
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+
+INT cmd_cls (LPTSTR cmd, LPTSTR param)
+{
+       DWORD dwWritten;
+       CONSOLE_SCREEN_BUFFER_INFO csbi;
+       COORD coPos;
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Clears the screen.\n\nCLS"));
+               return 0;
+       }
+
+       GetConsoleScreenBufferInfo (hOut, &csbi);
+
+       coPos.X = 0;
+       coPos.Y = 0;
+       FillConsoleOutputAttribute (hOut, wColor,
+                                                               (csbi.dwSize.X)*(csbi.dwSize.Y),
+                                                               coPos, &dwWritten);
+       FillConsoleOutputCharacter (hOut, _T(' '),
+                                                               (csbi.dwSize.X)*(csbi.dwSize.Y),
+                                                               coPos, &dwWritten);
+       SetConsoleCursorPosition (hOut, coPos);
+
+       bIgnoreEcho = TRUE;
+
+       return 0;
+}
+#endif
index 22211f7..2841c33 100644 (file)
-#include <stdarg.h>
+/*
+ *  CMD.C - command-line interface.
+ *
+ *
+ *  History:
+ *
+ *    17 Jun 1994 (Tim Norman)
+ *        started.
+ *
+ *    08 Aug 1995 (Matt Rains)
+ *        I have cleaned up the source code. changes now bring this source
+ *        into guidelines for recommended programming practice.
+ *
+ *        A added the the standard FreeDOS GNU licence test to the
+ *        initialize() function.
+ *
+ *        Started to replace puts() with printf(). this will help
+ *        standardize output. please follow my lead.
+ *
+ *        I have added some constants to help making changes easier.
+ *
+ *    15 Dec 1995 (Tim Norman)
+ *        major rewrite of the code to make it more efficient and add
+ *        redirection support (finally!)
+ *
+ *    06 Jan 1996 (Tim Norman)
+ *        finished adding redirection support!  Changed to use our own
+ *        exec code (MUCH thanks to Svante Frey!!)
+ *
+ *    29 Jan 1996 (Tim Norman)
+ *        added support for CHDIR, RMDIR, MKDIR, and ERASE, as per
+ *        suggestion of Steffan Kaiser
+ *
+ *        changed "file not found" error message to "bad command or
+ *        filename" thanks to Dustin Norman for noticing that confusing
+ *        message!
+ *
+ *        changed the format to call internal commands (again) so that if
+ *        they want to split their commands, they can do it themselves 
+ *        (none of the internal functions so far need that much power, anyway)
+ *
+ *    27 Aug 1996 (Tim Norman)
+ *        added in support for Oliver Mueller's ALIAS command
+ *
+ *    14 Jun 1997 (Steffan Kaiser)
+ *        added ctrl-break handling and error level
+ *
+ *    16 Jun 1998 (Rob Lake)
+ *        Runs command.com if /P is specified in command line.  Command.com
+ *        also stays permanent.  If /C is in the command line, starts the
+ *        program next in the line.
+ *
+ *    21 Jun 1998 (Rob Lake)
+ *        Fixed up /C so that arguments for the program
+ *
+ *    08-Jul-1998 (John P. Price)
+ *        Now sets COMSPEC environment variable
+ *        misc clean up and optimization
+ *        added date and time commands
+ *        changed to using spawnl instead of exec.  exec does not copy the
+ *        environment to the child process!
+ *
+ *    14 Jul 1998 (Hans B Pufal)
+ *        Reorganised source to be more efficient and to more closely
+ *        follow MS-DOS conventions. (eg %..% environment variable
+ *        replacement works form command line as well as batch file.
+ *
+ *        New organisation also properly support nested batch files.
+ *
+ *        New command table structure is half way towards providing a
+ *        system in which COMMAND will find out what internal commands
+ *        are loaded
+ *
+ *    24 Jul 1998 (Hans B Pufal) [HBP_003]
+ *        Fixed return value when called with /C option
+ *
+ *    27 Jul 1998  John P. Price
+ *        added config.h include
+ *
+ *    28 Jul 1998  John P. Price
+ *        added showcmds function to show commands and options available
+ *
+ *    07-Aug-1998 (John P Price <linux-guru@gcfl.net>)
+ *        Fixed carrage return output to better match MSDOS with echo
+ *        on or off. (marked with "JPP 19980708")
+ *
+ *    07-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        First ReactOS release.
+ *        Extended length of commandline buffers to 512.
+ *
+ *    13-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added COMSPEC environment variable.
+ *        Added "/t" support (color) on cmd command line.
+ *
+ *    07-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("cmd /?").
+ *
+ *    25-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection safe!
+ *        Fixed redirections and piping.
+ *        Piping is based on temporary files, but basic support
+ *        for anonymous pipes already exists.
+ *
+ *    27-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Replaced spawnl() by CreateProcess().
+ */
+
+// #define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
 #include <windows.h>
+// #include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
 
-HANDLE stdin;
-HANDLE stdout;
+#include "cmd.h"
+#include "batch.h"
 
 
-void Console_puts(char* str)
-{
-        ULONG nchar;
+#define CMDLINE_LENGTH  512
+
+
+BOOL bExit = FALSE;       /* indicates EXIT was typed */
+BOOL bCanExit = TRUE;     /* indicates if this shell is exitable */
+BOOL bCtrlBreak = FALSE;  /* Ctrl-Break or Ctrl-C hit */
+BOOL bIgnoreEcho = FALSE; /* Ignore 'newline' before 'cls' */
+INT  errorlevel = 0;      /* Errorlevel of last launched external program */
+OSVERSIONINFO osvi;
+HANDLE hIn;
+HANDLE hOut;
+
+#ifdef INCLUDE_CMD_COLOR
+WORD wColor = FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN; /* current color */
+WORD wDefColor = FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN; /* default color */
+#endif
+
 
-        WriteConsole(stdout,
-                     str,
-                     strlen(str),
-                     &nchar,
-                     NULL);
+extern COMMAND cmds[];         /* The internal command table */
+
+
+/*
+ *  is character a delimeter when used on first word?
+ *
+ */
+
+static BOOL IsDelimiter (TCHAR c)
+{
+       return (c == _T('/') || c == _T('=') || c == _T('\0') || _istspace (c));
 }
 
-void Console_printf(char* fmt, ...)
+
+/*
+ * This command (in first) was not found in the command table
+ *
+ * first - first word on command line
+ * rest  - rest of command line
+ */
+
+static VOID
+Execute (LPTSTR first, LPTSTR rest)
 {
-        char buffer[255];
-        va_list vargs;
+       TCHAR szFullName[MAX_PATH];
+
+       /* check for a drive change */
+       if (!_tcscmp (first + 1, _T(":")) && _istalpha (*first))
+       {
+               TCHAR szPath[MAX_PATH];
+
+               _tcscpy (szPath, _T("A:"));
+               szPath[0] = _totupper (*first);
+               SetCurrentDirectory (szPath);
+               GetCurrentDirectory (MAX_PATH, szPath);
+               if (szPath[0] != (TCHAR)_totupper (*first))
+                       ConErrPuts (INVALIDDRIVE);
 
-        va_start(vargs,fmt);
-        vsprintf(buffer,fmt,vargs);
-        Console_puts(buffer);
-        va_end(vargs);
+               return;
+       }
+
+       /* get the PATH environment variable and parse it */
+       /* search the PATH environment variable for the binary */
+       find_which (first, szFullName);
+
+       if (szFullName[0] == _T('\0'))
+       {
+               error_bad_command ();
+               return;
+       }
+
+       /* check if this is a .BAT or .CMD file */
+       if (!_tcsicmp (_tcsrchr (szFullName, _T('.')), _T(".bat")) ||
+               !_tcsicmp (_tcsrchr (szFullName, _T('.')), _T(".cmd")))
+       {
+#ifdef _DEBUG
+               DebugPrintf ("[BATCH: %s %s]\n", szFullName, rest);
+#endif
+               Batch (szFullName, first, rest);
+       }
+       else
+       {
+               /* exec the program */
+               TCHAR szFullCmdLine [1024];
+               PROCESS_INFORMATION prci;
+               STARTUPINFO stui;
+               DWORD dwError = 0;
+
+#ifdef _DEBUG
+               DebugPrintf ("[EXEC: %s %s]\n", szFullName, rest);
+#endif
+               /* build command line for CreateProcess() */
+               _tcscpy (szFullCmdLine, szFullName);
+               _tcscat (szFullCmdLine, " ");
+               _tcscat (szFullCmdLine, rest);
+
+               /* fill startup info */
+               memset (&stui, 0, sizeof (STARTUPINFO));
+               stui.cb = sizeof (STARTUPINFO);
+               stui.dwFlags = STARTF_USESHOWWINDOW;
+               stui.wShowWindow = SW_SHOWDEFAULT;
+                       
+               if (CreateProcess (NULL, szFullCmdLine, NULL, NULL, FALSE,
+                                                  0, NULL, NULL, &stui, &prci))
+               {
+                       WaitForSingleObject (prci.hProcess, INFINITE);
+                       GetExitCodeProcess (prci.hProcess, &errorlevel);
+                       CloseHandle (prci.hThread);
+                       CloseHandle (prci.hProcess);
+               }
+               else
+               {
+                       ErrorMessage (GetLastError (),
+                                                 "Error executing CreateProcess()!!\n");
+               }
+       }
 }
 
-void Console_getline(PCH Prompt, PCH Output, DWORD OutputLength)
+
+/*
+ * look through the internal commands and determine whether or not this
+ * command is one of them.  If it is, call the command.  If not, call
+ * execute to run it as an external program.
+ *
+ * line - the command line of the program to run
+ *
+ */
+
+static VOID
+DoCommand (LPTSTR line)
 {
-        char ch;
-        DWORD nbytes;
+       TCHAR com[MAX_PATH];  /* the first word in the command */
+       LPTSTR cp = com;
+       LPTSTR cstart;
+       LPTSTR rest = line;   /* pointer to the rest of the command line */
+       INT cl;
+       LPCOMMAND cmdptr;
+
+       /* Skip over initial white space */
+       while (isspace (*rest))
+               rest++;
+
+       cstart = rest;
+
+       /* Anything to do ? */
+       if (*rest)
+       {
+               /* Copy over 1st word as lower case */
+               while (!IsDelimiter (*rest))
+                       *cp++ = _totlower (*rest++);
+
+               /* Terminate first word */
+               *cp = _T('\0');
+
+               /* Skip over whitespace to rest of line */
+               while (_istspace (*rest))
+                       rest++;
+
+               /* Scan internal command table */
+               for (cmdptr = cmds;; cmdptr++)
+               {
+                       /* If end of table execute ext cmd */
+                       if (cmdptr->name == NULL)
+                       {
+                               Execute (com, rest);
+                               break;
+                       }
+
+                       if (!_tcscmp (com, cmdptr->name))
+                       {
+                               cmdptr->func (com, rest);
+                               break;
+                       }
+
+                       /* The following code handles the case of commands like CD which
+                        * are recognised even when the command name and parameter are
+                        * not space separated.
+                        *
+                        * e.g dir..
+                        * cd\freda
+                        */
 
-        Console_puts(Prompt);
+                       /* Get length of command name */
+                       cl = _tcslen (cmdptr->name);
 
-        ReadConsole(stdin,
-                    Output,
-                    OutputLength,
-                    &nbytes,
-                    NULL);
-        Output[nbytes-2]=0;
+                       if ((cmdptr->flags & CMD_SPECIAL) &&
+                               (!_tcsncmp (cmdptr->name, com, cl)) &&
+                               (_tcschr (_T("\\.-"), *(com + cl))))
+                       {
+                               /* OK its one of the specials...*/
+
+                               /* Terminate first word properly */
+                               com[cl] = _T('\0');
+
+                               /* Call with new rest */
+                               cmdptr->func (com, cstart + cl);
+                               break;
+                       }
+               }
+       }
 }
 
-void func_cd(char* s)
+
+/*
+ * process the command line and execute the appropriate functions
+ * full input/output redirection and piping are supported
+ */
+
+VOID ParseCommandLine (LPTSTR s)
 {
-        Console_printf("Changing directory to %s\n",s);
-        if (!SetCurrentDirectory(s))
-        {
-                Console_puts("Failed to change to directory\n");
-        }
+#ifdef FEATURE_REDIRECTION
+       TCHAR in[CMDLINE_LENGTH] = "";
+       TCHAR out[CMDLINE_LENGTH] = "";
+       TCHAR err[CMDLINE_LENGTH] = "";
+       TCHAR szTempPath[MAX_PATH] = _T(".\\");
+       TCHAR szFileName[2][MAX_PATH] = {"", ""};
+       HANDLE hFile[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
+       LPTSTR t = NULL;
+       INT  num = 0;
+       INT  nRedirFlags = 0;
+
+       HANDLE hOldConIn;
+       HANDLE hOldConOut;
+       HANDLE hOldConErr;
+#endif /* FEATURE_REDIRECTION */
+
+#ifdef _DEBUG
+       DebugPrintf ("ParseCommandLine: (\'%s\')]\n", s);
+#endif /* _DEBUG */
+
+#ifdef FEATURE_ALIASES
+       /* expand all aliases */
+       ExpandAlias (s, CMDLINE_LENGTH);
+#endif /* FEATURE_ALIAS */
+
+#ifdef FEATURE_REDIRECTION
+       /* find the temp path to store temporary files */
+       GetTempPath (MAX_PATH, szTempPath);
+       if (szTempPath[_tcslen (szTempPath) - 1] != _T('\\'))
+               _tcscat (szTempPath, _T("\\"));
+
+       /* get the redirections from the command line */
+       num = GetRedirection (s, in, out, err, &nRedirFlags);
+
+       /* more efficient, but do we really need to do this? */
+       for (t = in; _istspace (*t); t++)
+               ;
+       _tcscpy (in, t);
+
+       for (t = out; _istspace (*t); t++)
+               ;
+       _tcscpy (out, t);
+
+       for (t = err; _istspace (*t); t++)
+               ;
+       _tcscpy (err, t);
+
+       /* Set up the initial conditions ... */
+       /* preserve STDIN, STDOUT and STDERR handles */
+       hOldConIn  = GetStdHandle (STD_INPUT_HANDLE);
+       hOldConOut = GetStdHandle (STD_OUTPUT_HANDLE);
+       hOldConErr = GetStdHandle (STD_ERROR_HANDLE);
+
+       /* redirect STDIN */
+       if (in[0])
+       {
+               HANDLE hFile;
+
+               hFile = CreateFile (in, GENERIC_READ, 0, NULL, OPEN_EXISTING,
+                                                       FILE_ATTRIBUTE_NORMAL, NULL);
+               if (hFile == INVALID_HANDLE_VALUE)
+               {
+                       ConErrPrintf ("Can't redirect input from file %s\n", in);
+                       return;
+               }
+
+               if (!SetStdHandle (STD_INPUT_HANDLE, hFile))
+               {
+                       ConErrPrintf ("Can't redirect input from file %s\n", in);
+                       return;
+               }
+#ifdef _DEBUG
+               DebugPrintf (_T("Input redirected from: %s\n"), in);
+#endif
+       }
+
+       /* Now do all but the last pipe command */
+       *szFileName[0] = '\0';
+       hFile[0] = INVALID_HANDLE_VALUE;
+
+       while (num-- > 1)
+       {
+               /* Create unique temporary file name */
+               GetTempFileName (szTempPath, "CMD", 0, szFileName[1]);
+
+               /* Set current stdout to temporary file */
+               hFile[1] = CreateFile (szFileName[1], GENERIC_WRITE, 0, NULL,
+                                                          TRUNCATE_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL);
+               SetStdHandle (STD_OUTPUT_HANDLE, hFile[1]);
+
+               DoCommand (s);
+
+               /* close stdout file */
+               SetStdHandle (STD_OUTPUT_HANDLE, hOldConOut);
+               if ((hFile[1] != INVALID_HANDLE_VALUE) && (hFile[1] != hOldConOut))
+               {
+                       CloseHandle (hFile[1]);
+                       hFile[1] = INVALID_HANDLE_VALUE;
+               }
+
+               /* close old stdin file */
+               SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
+               if ((hFile[0] != INVALID_HANDLE_VALUE) && (hFile[0] != hOldConIn))
+               {
+                       /* delete old stdin file, if it is a real file */
+                       CloseHandle (hFile[0]);
+                       hFile[0] = INVALID_HANDLE_VALUE;
+                       DeleteFile (szFileName[0]);
+                       *szFileName[0] = _T('\0');
+               }
+
+               /* copy stdout file name to stdin file name */
+               _tcscpy (szFileName[0], szFileName[1]);
+               *szFileName[1] = _T('\0');
+
+               /* open new stdin file */
+               hFile[0] = CreateFile (szFileName[0], GENERIC_READ, 0, NULL,
+                                                          OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL);
+               SetStdHandle (STD_INPUT_HANDLE, hFile[0]);
+
+               s = s + _tcslen (s) + 1;
+       }
+
+       /* Now set up the end conditions... */
+       /* redirect STDOUT */
+       if (out[0])
+       {
+               /* Final output to here */
+               HANDLE hFile;
+
+               hFile = CreateFile (out, GENERIC_WRITE, 0, NULL,
+                                                       (nRedirFlags & OUTPUT_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS,
+                                                       FILE_ATTRIBUTE_NORMAL, NULL);
+               if (hFile == INVALID_HANDLE_VALUE)
+               {
+                       ConErrPrintf ("Can't redirect to file %s\n", out);
+                       return;
+               }
+
+               if (!SetStdHandle (STD_OUTPUT_HANDLE, hFile))
+               {
+                       ConErrPrintf ("Can't redirect to file %s\n", out);
+                       return;
+               }
+
+               if (nRedirFlags & OUTPUT_APPEND)
+               {
+                       LONG lHighPos = 0;
+
+                       if (GetFileType (hFile) == FILE_TYPE_DISK)
+                               SetFilePointer (hFile, 0, &lHighPos, FILE_END);
+               }
+#ifdef _DEBUG
+               DebugPrintf (_T("Output redirected to: %s\n"), out);
+#endif
+       }
+       else if (hOldConOut != INVALID_HANDLE_VALUE)
+       {
+               /* Restore original stdout */
+               HANDLE hOut = GetStdHandle (STD_OUTPUT_HANDLE);
+               SetStdHandle (STD_OUTPUT_HANDLE, hOldConOut);
+               if (hOldConOut != hOut)
+                       CloseHandle (hOut);
+               hOldConOut = INVALID_HANDLE_VALUE;
+       }
+
+       /* redirect STDERR */
+       if (err[0])
+       {
+               /* Final output to here */
+               HANDLE hFile;
+
+               if (!_tcscmp (err, out))
+               {
+#ifdef _DEBUG
+                       DebugPrintf (_T("Stdout and stderr will use the same file!!\n"));
+#endif
+                       DuplicateHandle (GetCurrentProcess (), GetStdHandle (STD_OUTPUT_HANDLE), GetCurrentProcess (),
+                                                        &hFile, 0, TRUE, DUPLICATE_SAME_ACCESS);
+               }
+               else
+               {
+                       hFile =
+                               CreateFile (err, GENERIC_WRITE, 0, NULL,
+                                                       (nRedirFlags & ERROR_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS,
+                                                       FILE_ATTRIBUTE_NORMAL, NULL);
+                       if (hFile == INVALID_HANDLE_VALUE)
+                       {
+                               ConErrPrintf ("Can't redirect to file %s\n", err);
+                               return;
+                       }
+               }
+               if (!SetStdHandle (STD_ERROR_HANDLE, hFile))
+               {
+                       ConErrPrintf ("Can't redirect to file %s\n", err);
+                       return;
+               }
+
+               if (nRedirFlags & ERROR_APPEND)
+               {
+                       LONG lHighPos = 0;
+
+                       if (GetFileType (hFile) == FILE_TYPE_DISK)
+                               SetFilePointer (hFile, 0, &lHighPos, FILE_END);
+               }
+#ifdef _DEBUG
+               DebugPrintf (_T("Error redirected to: %s\n"), err);
+#endif
+       }
+       else if (hOldConErr != INVALID_HANDLE_VALUE)
+       {
+               /* Restore original stderr */
+               HANDLE hErr = GetStdHandle (STD_ERROR_HANDLE);
+               SetStdHandle (STD_ERROR_HANDLE, hOldConErr);
+               if (hOldConErr != hErr)
+                       CloseHandle (hErr);
+               hOldConErr = INVALID_HANDLE_VALUE;
+       }
+#endif
+
+       /* process final command */
+       DoCommand (s);
+
+#ifdef FEATURE_REDIRECTION
+       /* close old stdin file */
+#if 0  /* buggy implementation */
+       SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
+       if ((hFile[0] != INVALID_HANDLE_VALUE) && 
+               (hFile[0] != hOldConIn))
+       {
+               /* delete old stdin file, if it is a real file */
+               CloseHandle (hFile[0]);
+               hFile[0] = INVALID_HANDLE_VALUE;
+               DeleteFile (szFileName[0]);
+               *szFileName[0] = _T('\0');
+       }
+
+       /* Restore original STDIN */
+       if (hOldConIn != INVALID_HANDLE_VALUE)
+       {
+               HANDLE hIn = GetStdHandle (STD_INPUT_HANDLE);
+               SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
+               if (hOldConIn != hIn)
+                       CloseHandle (hIn);
+               hOldConIn = INVALID_HANDLE_VALUE;
+       }
+       else
+       {
+#ifdef _DEBUG
+               DebugPrintf (_T("Can't restore STDIN! Is invalid!!\n"), out);
+#endif
+       }
+#endif  /* buggy implementation */
+
+
+       if (hOldConIn != INVALID_HANDLE_VALUE)
+       {
+               HANDLE hIn = GetStdHandle (STD_INPUT_HANDLE);
+               SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
+               if (hIn == INVALID_HANDLE_VALUE)
+               {
+#ifdef _DEBUG
+                       DebugPrintf (_T("Previous STDIN is invalid!!\n"));
+#endif
+               }
+               else
+               {
+                       if (GetFileType (hIn) == FILE_TYPE_DISK)
+                       {
+                               if (hFile[0] == hIn)
+                               {
+                                       CloseHandle (hFile[0]);
+                                       hFile[0] = INVALID_HANDLE_VALUE;
+                                       DeleteFile (szFileName[0]);
+                                       *szFileName[0] = _T('\0');
+                               }
+                               else
+                               {
+#ifdef _DEBUG
+                                       DebugPrintf (_T("hFile[0] and hIn dont match!!!\n"));
+#endif
+
+                               }
+                       }
+               }
+       }
+
+
+       /* Restore original STDOUT */
+       if (hOldConOut != INVALID_HANDLE_VALUE)
+       {
+               HANDLE hOut = GetStdHandle (STD_OUTPUT_HANDLE);
+               SetStdHandle (STD_OUTPUT_HANDLE, hOldConOut);
+               if (hOldConOut != hOut)
+                       CloseHandle (hOut);
+               hOldConOut = INVALID_HANDLE_VALUE;
+       }
+
+       /* Restore original STDERR */
+       if (hOldConErr != INVALID_HANDLE_VALUE)
+       {
+               HANDLE hErr = GetStdHandle (STD_ERROR_HANDLE);
+               SetStdHandle (STD_ERROR_HANDLE, hOldConErr);
+               if (hOldConErr != hErr)
+                       CloseHandle (hErr);
+               hOldConErr = INVALID_HANDLE_VALUE;
+       }
+#endif /* FEATURE_REDIRECTION */
 }
 
-void func_dir(char* s)
+
+/*
+ * do the prompt/input/process loop
+ *
+ */
+
+static INT 
+ProcessInput (BOOL bFlag)
 {
-        HANDLE shandle;
-        WIN32_FIND_DATA FindData;
-
-        shandle = FindFirstFile("*.*",&FindData);
-
-        if (shandle==INVALID_HANDLE_VALUE)
-        {
-                return;
-        }
-        do
-        {
-                Console_printf("Scanning %s\n",FindData.cFileName);
-        } while(FindNextFile(shandle,&FindData));
+       TCHAR commandline[CMDLINE_LENGTH];
+       TCHAR readline[CMDLINE_LENGTH];
+       LPTSTR tp;
+       LPTSTR ip;
+       LPTSTR cp;
+
+       /* JPP 19980807 - changed name so not to conflict with echo global */
+       BOOL bEchoThisLine;
+
+       do
+       {
+               /* if no batch input then... */
+               if (!(ip = ReadBatchLine (&bEchoThisLine)))
+               {
+                       if (bFlag)
+                               return 0;
+
+                       ReadCommand (readline, CMDLINE_LENGTH);
+                       ip = readline;
+                       bEchoThisLine = FALSE;
+               }
+
+               cp = commandline;
+               while (*ip)
+               {
+                       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 += wsprintf (cp, _T("%u"), errorlevel);
+                                               ip++;
+                                               break;
+
+                                       default:
+                                               if (tp = _tcschr (ip, _T('%')))
+                                               {
+                                                       char evar[512];
+                                                       *tp = _T('\0');
+
+                                                       /* FIXME: This is just a quick hack!! */
+                                                       /* Do a proper memory allocation!! */
+                                                       if (GetEnvironmentVariable (ip, evar, 512))
+                                                               cp = stpcpy (cp, evar);
+
+                                                       ip = tp + 1;
+                                               }
+                                               break;
+                               }
+                               continue;
+                       }
+
+                       if (_istcntrl (*ip))
+                               *ip = _T(' ');
+                       *cp++ = *ip++;
+               }
+
+               *cp = _T('\0');
+
+               /* strip trailing spaces */
+               while ((--cp >= commandline) && _istspace (*cp))
+                       ;
+
+               *(cp + 1) = _T('\0');
+
+               /* JPP 19980807 */
+               /* Echo batch file line */
+               if (bEchoThisLine)
+               {
+                       PrintPrompt ();
+                       ConOutPuts (commandline);
+               }
+
+               if (*commandline)
+               {
+                       ParseCommandLine (commandline);
+                       if (bEcho && !bIgnoreEcho)
+                               ConOutChar ('\n');
+                       bIgnoreEcho = FALSE;
+               }
+       }
+       while (!bCanExit || !bExit);
+
+       return 0;
 }
 
-int is_builtin(char* name, char* args)
+
+/*
+ * control-break handler.
+ */
+BOOL BreakHandler (DWORD dwCtrlType)
 {
-        if (strcmp(name,"dir")==0)
-        {
-                func_dir(args);
-                return(1);
-        }
-        if (strcmp(name,"cd")==0)
-        {
-                func_cd(args);
-                return(1);
-        }
-        return(0);
+       if ((dwCtrlType == CTRL_C_EVENT) ||
+               (dwCtrlType == CTRL_BREAK_EVENT))
+       {
+               bCtrlBreak = TRUE; /* indicate the break condition */
+               return TRUE;
+       }
+       return FALSE;
 }
 
-int process_command(char* str)
+
+/*
+ * show commands and options that are available.
+ *
+ */
+static VOID
+ShowCommands (VOID)
 {
-        char* name;
-        char* args;
-        PROCESS_INFORMATION pi;
-        STARTUPINFO si;
-        char process_arg[255];
-
-        if (strcmp(str,"exit")==0)
-        {
-                return(1);
-        }
-
-        name = strtok(str," \t");
-        args = strtok(NULL,"");
-
-        if (is_builtin(name,args))
-        {
-                return(0);
-        }
-        memset(&si,0,sizeof(STARTUPINFO));
-        si.cb=sizeof(STARTUPINFO);
-        si.lpTitle=strdup(name);
-
-        strcpy(process_arg,name);
-        strcat(process_arg," ");
-        if(args!=NULL)
-        {
-                strcat(process_arg,args);
-        }
-        Console_printf("name '%s' process_arg '%s'\n",name,process_arg);
-        if (!CreateProcess(NULL,process_arg,NULL,NULL,FALSE,
-                     CREATE_NEW_CONSOLE,
-                      NULL,NULL,&si,&pi))
-                      {
-                        Console_printf("Failed to execute process\n");
-                      }
-        return(0);
+       LPCOMMAND cmdptr;
+       INT y;
+
+       ConOutPrintf (_T("\nInternal commands available:\n"));
+       y = 0;
+       cmdptr = cmds;
+       while (cmdptr->name)
+       {
+               if (++y == 8)
+               {
+                       ConOutPuts (cmdptr->name);
+                       y = 0;
+               }
+               else
+                       ConOutPrintf (_T("%-10s"), cmdptr->name);
+
+               cmdptr++;
+       }
+
+       if (y != 0)
+               ConOutChar ('\n');
+
+       /* print feature list */
+       ConOutPuts ("\nFeatures available:");
+#ifdef FEATURE_ALIASES
+       ConOutPuts ("  [aliases]");
+#endif
+#ifdef FEATURE_HISTORY
+       ConOutPuts ("  [history]");
+#endif
+#ifdef FEATURE_UNIX_FILENAME_COMPLETION
+       ConOutPuts ("  [unix filename completion]");
+#endif
+#ifdef FEATURE_DIRECTORY_STACK
+       ConOutPuts ("  [directory stack]");
+#endif
+#ifdef FEATURE_REDIRECTION
+       ConOutPuts ("  [redirections and piping]");
+#endif
+       ConOutChar ('\n');
 }
 
-void build_prompt(char* prompt)
+
+/*
+ * set up global initializations and process parameters
+ *
+ * argc - number of parameters to command.com
+ * argv - command-line parameters
+ *
+ */
+static VOID Initialize (int argc, char *argv[])
 {
-        int len;
+       INT i;
+
+       /* Added by Rob Lake 06/16/98.  This enables the command.com
+        * to run the autoexec.bat at startup */
+
+#ifdef _DEBUG
+       INT x;
+
+       DebugPrintf ("[command args:\n");
+       for (x = 0; x < argc; x++)
+       {
+               DebugPrintf ("%d. %s\n", x, argv[x]);
+       }
+       DebugPrintf ("]\n");
+#endif
+
+       /* get version information */
+       osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+       GetVersionEx (&osvi);
+
+       InitLocale ();
+
+       /* get default input and output console handles */
+       hOut = GetStdHandle (STD_OUTPUT_HANDLE);
+       hIn  = GetStdHandle (STD_INPUT_HANDLE);
+
+#ifdef INCLUDE_CMD_CHDIR
+       InitLastPath ();
+#endif
+
+       if (argc >= 2)
+       {
+               if (!_tcsncmp (argv[1], _T("/?"), 2))
+               {
+                       ConOutPuts (_T("Starts a new instance of the ReactOS command line interpreter\n\n"
+                                                  "CMD [/P][/C]...\n\n"
+                                                  "  /P  ...\n"
+                                                  "  /C  ..."));
+                       ExitProcess (0);
+               }
+               else
+               {
+                       for (i = 1; i < argc; i++)
+                       {
+                               if (!_tcsicmp (argv[i], _T("/p")))
+                               {
+                                       if (!IsValidFileName (_T("\\autoexec.bat")))
+                                       {
+#ifdef INCLUDE_CMD_DATE
+                                               cmd_date ("", "");
+#endif
+#ifdef INCLUDE_CMD_TIME
+                                               cmd_time ("", "");
+#endif
+                                       }
+                                       else
+                                               ParseCommandLine ("\\autoexec.bat");
+                                       bCanExit = FALSE;
+                               }
+                               else if (!_tcsicmp (argv[i], _T("/c")))
+                               {
+                                       /* This just runs a program and exits, RL: 06/16,21/98 */
+                                       char commandline[CMDLINE_LENGTH];
+                                       ++i;
+                                       strcpy(commandline, argv[i]);
+                                       while (argv[++i])
+                                       {
+                                               strcat(commandline, " ");
+                                               strcat(commandline, argv[i]);
+                                       }
+
+                                       ParseCommandLine(commandline);
 
-        len = GetCurrentDirectory(255,prompt);
-        strcat(prompt,">");
+                                       /* HBP_003 { Fix return value when /C used }*/
+                                       ExitProcess (ProcessInput (TRUE));
+                               }
+
+#ifdef INCLUDE_CMD_COLOR
+                               else if (!_tcsnicmp (argv[i], _T("/t:"), 3))
+                               {
+                                       /* process /t (color) argument */
+                                       wDefColor = (WORD)strtoul (&argv[i][3], NULL, 16);
+                                       wColor = wDefColor;
+                               }
+#endif
+                       }
+               }
+       }
+
+#ifdef FEATURE_DIR_STACK
+       /* initialize directory stack */
+       InitDirectoryStack ();
+#endif
+
+#ifdef INCLUDE_CMD_COLOR
+       /* set default colors */
+       SetScreenColor (wColor);
+#endif
+
+       ShortVersion ();
+       ShowCommands ();
+
+       /* Set COMSPEC environment variable */
+       SetEnvironmentVariable (_T("COMSPEC"), argv[0]);
+
+       /* add ctrl handler */
+       SetConsoleCtrlHandler (NULL, TRUE);
 }
 
-void command_loop()
+
+static VOID Cleanup (VOID)
 {
-        char line[255];
-        char prompt[255];
-        int do_exit = 0;
-
-        while (!do_exit)
-        {
-                build_prompt(prompt);
-                Console_getline(prompt,line,255);
-                Console_printf("Processing command '%s'\n",line);
-                do_exit = process_command(line);
-        }        
+
+#ifdef FEATURE_DIECTORY_STACK
+       /* destroy directory stack */
+       DestroyDirectoryStack ();
+#endif
+
+#ifdef INCLUDE_CMD_CHDIR
+       FreeLastPath ();
+#endif
+
+       /* remove ctrl handler */
+//     SetConsoleCtrlHandler ((PHANDLER_ROUTINE)&BreakHandler, FALSE);
 }
 
-int STDCALL WinMain (HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow)
+
+/*
+ * main function
+ */
+int main (int argc, char *argv[])
 {
-        AllocConsole();
-        stdin = GetStdHandle(STD_INPUT_HANDLE);
-        stdout = GetStdHandle(STD_OUTPUT_HANDLE);
+       INT nExitCode;
 
-        command_loop();
+       AllocConsole ();
+       SetFileApisToOEM ();
 
-       return 0;
+       /* check switches on command-line */
+       Initialize (argc, argv);
+
+       /* call prompt routine */
+       nExitCode = ProcessInput (FALSE);
+
+       /* do the cleanup */
+       Cleanup ();
+       FreeConsole ();
+
+       return nExitCode;
 }
diff --git a/rosapps/cmd/cmd.h b/rosapps/cmd/cmd.h
new file mode 100644 (file)
index 0000000..e34fffe
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ *  CMD.H - header file for the modules in CMD.EXE
+ *
+ *
+ *  History:
+ *
+ *    7-15-95 Tim Norman
+ *        started
+ *
+ *    06/29/98 (Rob Lake)
+ *        Moved error messages in here
+ *
+ *    07/12/98 (Rob Lake)
+ *        Moved more error messages here
+ *
+ *    30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        Added compile date to version
+ */
+
+// #define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+// #include <tchar.h>
+
+#define SHELLVER     "version 0.0.4 [" __DATE__"]"
+
+#define BREAK_BATCHFILE 1
+#define BREAK_OUTOFBATCH 2
+#define BREAK_INPUT 3
+#define BREAK_IGNORE 4
+
+/* define some error messages */
+#define NOENVERR        "ERROR: no environment"
+#define INVALIDDRIVE    "ERROR: invalid drive"
+#define INVALIDFUNCTION "ERROR: invalid function"
+#define ACCESSDENIED    "ERROR: access denied"
+#define BADENVIROMENT   "ERROR: bad enviroment"
+#define BADFORMAT       "ERROR: bad format"
+#define ERROR_E2BIG     "ERROR: Argument list too long"
+#define ERROR_EINVAL    "ERROR: Invalid argument"
+
+#define SHELLINFO    "ReactOS Command Line Interface"
+#define USAGE        "usage"
+
+
+#define D_ON         "on"
+#define D_OFF        "off"
+
+
+
+/* prototypes for CMD.C */
+extern HANDLE hOut;
+extern HANDLE hIn;
+extern WORD   wColor;
+extern WORD   wDefColor;
+extern BOOL   bCtrlBreak;
+extern BOOL   bIgnoreEcho;
+extern BOOL   bExit;
+extern int errorlevel;
+extern SHORT  maxx;
+extern SHORT  maxy;
+extern OSVERSIONINFO osvi;
+
+
+// VOID Execute (char *, char *);
+void command(char *);
+VOID ParseCommandLine (LPTSTR);
+int  c_brk(void);
+
+
+
+
+/* prototypes for ALIAS.C */
+VOID ExpandAlias (char *, int);
+INT cmd_alias (LPTSTR, LPTSTR);
+
+
+/* prototyped for ATTRIB.C */
+INT cmd_attrib (LPTSTR, LPTSTR);
+
+
+/* prototypes for CLS.C */
+INT cmd_cls (LPTSTR, LPTSTR);
+
+
+/* prototypes for CMDINPUT.C */
+VOID ReadCommand (LPTSTR, INT);
+
+
+/* prototypes for CMDTABLE.C */
+#define CMD_SPECIAL     1
+#define CMD_BATCHONLY   2
+
+typedef struct tagCOMMAND
+{
+       LPTSTR name;
+       INT    flags;
+       INT    (*func) (LPTSTR, LPTSTR);
+} COMMAND, *LPCOMMAND;
+
+
+/* prototypes for COLOR.C */
+VOID SetScreenColor (WORD);
+INT cmd_color (LPTSTR, LPTSTR); 
+
+
+/* prototypes for CONSOLE.C */
+#ifdef _DEBUG
+VOID DebugPrintf (LPTSTR, ...);
+#endif /* _DEBUG */
+
+VOID ConInDummy (VOID);
+VOID ConInKey (PINPUT_RECORD);
+
+VOID ConInString (LPTSTR, DWORD);
+
+
+VOID ConOutChar (TCHAR);
+VOID ConOutPuts (LPTSTR);
+VOID ConOutPrintf (LPTSTR, ...);
+VOID ConErrChar (TCHAR);
+VOID ConErrPuts (LPTSTR);
+VOID ConErrPrintf (LPTSTR, ...);
+
+
+SHORT wherex (VOID);
+SHORT wherey (VOID);
+VOID goxy (SHORT, SHORT);
+
+VOID GetScreenSize (PSHORT, PSHORT);
+VOID SetCursorType (BOOL, BOOL);
+
+
+/* prototypes for COPY.C */
+INT cmd_copy (LPTSTR, LPTSTR);
+
+
+/* prototypes for DATE.C */
+INT cmd_date (LPTSTR, LPTSTR);
+
+
+/* prototypes for DEL.C */
+INT cmd_del (LPTSTR, LPTSTR);
+
+
+/* prototypes for DIR.C */
+//int incline(int *line, unsigned flags);
+INT cmd_dir (LPTSTR, LPTSTR);
+
+
+/* prototypes for DIRSTACK.C */
+VOID InitDirectoryStack (VOID);
+VOID DestroyDirectoryStack (VOID);
+INT  GetDirectoryStackDepth (VOID);
+INT  cmd_pushd (LPTSTR, LPTSTR);
+INT  cmd_popd (LPTSTR, LPTSTR);
+
+
+/* Prototypes for ERROR.C */
+VOID ErrorMessage (DWORD, LPTSTR, ...);
+
+VOID error_no_pipe (VOID);
+VOID error_bad_command (VOID);
+VOID error_invalid_drive (VOID);
+VOID error_req_param_missing (VOID);
+VOID error_sfile_not_found (LPTSTR);
+VOID error_file_not_found (VOID);
+VOID error_path_not_found (VOID);
+VOID error_too_many_parameters (LPTSTR);
+VOID error_invalid_switch (TCHAR);
+VOID error_invalid_parameter_format (LPTSTR);
+VOID error_out_of_memory (VOID);
+VOID error_syntax (LPTSTR);
+
+VOID msg_pause (VOID);
+
+
+/* prototypes for FILECOMP.C */
+#ifdef FEATURE_UNIX_FILENAME_COMPLETION
+VOID CompleteFilename (LPTSTR, INT);
+INT  ShowCompletionMatches (LPTSTR, INT);
+#endif
+#ifdef FEATURE_4NT_FILENAME_COMPLETION
+#endif
+
+
+/* prototypes for HISTORY.C */
+#ifdef FEATURE_HISTORY
+VOID History (INT, LPTSTR);
+#endif
+
+
+/* prototypes for INTERNAL.C */
+VOID InitLastPath (VOID);
+VOID FreeLastPath (VOID);
+int cmd_chdir(char *, char *);
+int cmd_mkdir(char *, char *);
+int cmd_rmdir(char *, char *);
+int internal_exit(char *, char *);
+int cmd_rem(char *, char *);
+int cmd_showcommands(char *, char *);
+
+
+/* prototyped for LABEL.C */
+INT cmd_label (LPTSTR, LPTSTR);
+
+
+/* prototypes for LOCALE.C */
+extern TCHAR cDateSeparator;
+extern INT   nDateFormat;
+extern TCHAR cTimeSeparator;
+extern INT   nTimeFormat;
+extern TCHAR aszDayNames[7][8];
+extern TCHAR cThousandSeparator;
+extern TCHAR cDecimalSeparator;
+extern INT   nNumberGroups;
+
+VOID InitLocale (VOID);
+
+
+/* Prototypes for MISC.C */
+TCHAR  cgetchar (VOID);
+BOOL   CheckCtrlBreak (INT);
+LPTSTR *split (LPTSTR, LPINT);
+VOID   freep (LPTSTR *);
+LPTSTR stpcpy (LPTSTR, LPTSTR);
+BOOL   IsValidPathName (LPCTSTR);
+BOOL   IsValidFileName (LPCTSTR);
+BOOL   FileGetString (HANDLE, LPTSTR, INT);
+
+
+/* prototypes for MOVE.C */
+INT cmd_move (LPTSTR, LPTSTR);
+
+
+/* prototypes from PATH.C */
+INT cmd_path (LPTSTR, LPTSTR);
+
+
+/* prototypes from PROMPT.C */
+VOID PrintPrompt (VOID);
+INT  cmd_prompt (LPTSTR, LPTSTR);
+
+
+/* prototypes for REDIR.C */
+#define INPUT_REDIRECTION    1
+#define OUTPUT_REDIRECTION   2
+#define OUTPUT_APPEND        4
+#define ERROR_REDIRECTION    8
+#define ERROR_APPEND        16
+INT GetRedirection (LPTSTR, LPTSTR, LPTSTR, LPTSTR, LPINT);
+
+
+/* prototypes for REN.C */
+INT cmd_rename (LPTSTR, LPTSTR);
+
+
+/* prototypes for SET.C */
+INT cmd_set (LPTSTR, LPTSTR);
+
+
+/* prototypes for TIME.C */
+INT cmd_time (LPTSTR, LPTSTR);
+
+
+/* prototypes for TYPE.C */
+INT cmd_type (LPTSTR, LPTSTR);
+
+
+/* prototypes for VER.C */
+VOID ShortVersion (VOID);
+INT  cmd_ver (LPTSTR, LPTSTR);
+
+
+/* prototypes for VERIFY.C */
+INT cmd_verify (LPTSTR, LPTSTR);
+
+
+/* prototypes for VOL.C */
+INT cmd_vol (LPTSTR, LPTSTR);
+
+
+/* prototypes for WHERE.C */
+BOOL find_which (LPCTSTR, LPTSTR);
+
+
+
+
+/* The MSDOS Batch Commands [MS-DOS 5.0 User's Guide and Reference p359] */
+int cmd_call(char *, char *);
+int cmd_echo(char *, char *);
+int cmd_for(char *, char *);
+int cmd_goto(char *, char *);
+int cmd_if(char *, char *);
+int cmd_pause(char *, char *);
+int cmd_shift(char *, char *);
+
+int cmd_beep(char *, char *);
+
+
diff --git a/rosapps/cmd/cmdinput.c b/rosapps/cmd/cmdinput.c
new file mode 100644 (file)
index 0000000..6ac5302
--- /dev/null
@@ -0,0 +1,412 @@
+/*
+ *  CMDINPUT.C - handles command input (tab completion, history, etc.).
+ *
+ *
+ *  History:
+ *
+ *    01/14/95 (Tim Norman)
+ *        started.
+ *
+ *    08/08/95 (Matt Rains)
+ *        i have cleaned up the source code. changes now bring this source
+ *        into guidelines for recommended programming practice.
+ *        i have added some constants to help making changes easier.
+ *
+ *    12/12/95 (Tim Norman)
+ *        added findxy() function to get max x/y coordinates to display
+ *        correctly on larger screens
+ *
+ *    12/14/95 (Tim Norman)
+ *        fixed the Tab completion code that Matt Rains broke by moving local
+ *        variables to a more global scope and forgetting to initialize them
+ *        when needed
+ *
+ *    8/1/96 (Tim Norman)
+ *        fixed a bug in tab completion that caused filenames at the beginning
+ *        of the command-line to have their first letter truncated
+ *
+ *    9/1/96 (Tim Norman)
+ *        fixed a silly bug using printf instead of fputs, where typing "%i"
+ *        confused printf :)
+ *
+ *    6/14/97 (Steffan Kaiser)
+ *        ctrl-break checking
+ *
+ *    6/7/97 (Marc Desrochers)
+ *        recoded everything! now properly adjusts when text font is changed.
+ *        removed findxy(), reposition(), and reprint(), as these functions
+ *        were inefficient. added goxy() function as gotoxy() was buggy when
+ *        the screen font was changed. the printf() problem with %i on the
+ *        command line was fixed by doing printf("%s",str) instead of
+ *        printf(str). Don't ask how I find em just be glad I do :)
+ *
+ *    7/12/97 (Tim Norman)
+ *        Note: above changes pre-empted Steffan's ctrl-break checking.
+ *
+ *    7/7/97 (Marc Desrochers)
+ *        rewrote a new findxy() because the new dir() used it.  This
+ *        findxy() simply returns the values of *maxx *maxy.  In the
+ *        future, please use the pointers, they will always be correct
+ *        since they point to BIOS values.
+ *
+ *    7/8/97 (Marc Desrochers)
+ *        once again removed findxy(), moved the *maxx, *maxy pointers
+ *        global and included them as externs in command.h.  Also added
+ *        insert/overstrike capability
+ *
+ *    7/13/97 (Tim Norman)
+ *        added different cursor appearance for insert/overstrike mode
+ *
+ *    7/13/97 (Tim Norman)
+ *        changed my code to use _setcursortype until I can figure out why
+ *        my code is crashing on some machines.  It doesn't crash on mine :)
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    28-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        put ifdef's around filename completion code.
+ *
+ *    30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        moved filename completion code to filecomp.c
+ *        made second TAB display list of filename matches
+ *
+ *    31-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        Fixed bug where if you typed something, then hit HOME, then tried
+ *        to type something else in insert mode, it crashed.
+ *
+ *    07-Aug-1998 (John P Price <linux-guru@gcfl.net>)
+ *        Fixed carrage return output to better match MSDOS with echo
+ *        on or off.(marked with "JPP 19980708")
+ *
+ *    13-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added insert/overwrite cursor.
+ *
+ *    25-Jan-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Replaced CRT io functions by Win32 console io functions.
+ *        This can handle <Shift>-<Tab> for 4NT filename completion.
+ *        Unicode and redirection safe!
+ *
+ *    04-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Fixed input bug. A "line feed" character remined in the keyboard
+ *        input queue when you pressed <RETURN>. This sometimes caused
+ *        some very strange effects.
+ *        Fixed some command line editing annoyances.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+
+SHORT maxx;
+SHORT maxy;
+
+/*
+ * global command line insert/overwrite flag
+ */
+static BOOL bInsert = TRUE;
+
+
+static VOID
+ClearCommandLine (LPTSTR str, INT maxlen, SHORT orgx, SHORT orgy)
+{
+       INT count;
+
+       goxy (orgx, orgy);
+       for (count = 0; count < (INT)_tcslen (str); count++)
+               ConOutChar (_T(' '));
+       _tcsnset (str, _T('\0'), maxlen);
+       goxy (orgx, orgy);
+}
+
+
+/* read in a command line */
+VOID ReadCommand (LPTSTR str, INT maxlen)
+{
+       SHORT orgx;                     /* origin x/y */
+       SHORT orgy;
+       SHORT curx;
+       SHORT cury;
+       INT   count;
+       INT   current = 0;
+       INT   charcount = 0;
+       INPUT_RECORD ir;
+       WORD   wLastKey = 0;
+       TCHAR  ch;
+
+       /* get screen size */
+       GetScreenSize (&maxx, &maxy);
+
+       /* JPP 19980807 - if echo off, don't print prompt */
+       if (bEcho)
+               PrintPrompt();
+
+       orgx = wherex ();
+       orgy = wherey ();
+
+       memset (str, 0, maxlen * sizeof (TCHAR));
+
+       SetCursorType (bInsert, TRUE);
+
+       do
+       {
+               ConInKey (&ir);
+
+               switch (ir.Event.KeyEvent.wVirtualKeyCode)
+               {
+                       case VK_BACK:
+                               /* <BACKSPACE> - delete character to left of cursor */
+                               if (current > 0 && charcount > 0)
+                               {
+                                       if (current == charcount)
+                                       {
+                                               /* if at end of line */
+                                               str[current - 1] = _T('\0');
+                                               if (wherex () != 0)
+                                               {
+                                                       ConOutPrintf ("\b \b");
+                                               }
+                                               else
+                                               {
+                                                       goxy ((SHORT)(maxx - 1), (SHORT)(wherey () - 1));
+                                                       ConOutChar (_T(' '));
+                                                       goxy ((SHORT)(maxx - 1), (SHORT)(wherey () - 1));
+                                               }
+                                       }
+                                       else
+                                       {
+                                               for (count = current - 1; count < charcount; count++)
+                                                       str[count] = str[count + 1];
+                                               if (wherex () != 0)
+                                                       goxy ((SHORT)(wherex () - 1), wherey ());
+                                               else
+                                                       goxy ((SHORT)(maxx - 1), (SHORT)(wherey () - 1));
+                                               curx = wherex ();
+                                               cury = wherey ();
+                                               ConOutPrintf (_T("%s "), &str[current - 1]);
+                                               goxy (curx, cury);
+                                       }
+                                       charcount--;
+                                       current--;
+                               }
+                               break;
+
+                       case VK_INSERT:
+                               /* toggle insert/overstrike mode */
+                               bInsert ^= TRUE;
+                               SetCursorType (bInsert, TRUE);
+                               break;
+
+                       case VK_DELETE:
+                               /* delete character under cursor */
+                               if (current != charcount && charcount > 0)
+                               {
+                                       for (count = current; count < charcount; count++)
+                                               str[count] = str[count + 1];
+                                       charcount--;
+                                       curx = wherex ();
+                                       cury = wherey ();
+                                       ConOutPrintf (_T("%s "), &str[current]);
+                                       goxy (curx, cury);
+                               }
+                               break;
+
+                       case VK_HOME:
+                               /* goto beginning of string */
+                               if (current != 0)
+                               {
+                                       goxy (orgx, orgy);
+                                       current = 0;
+                               }
+                               break;
+
+                       case VK_END:
+                               /* goto end of string */
+                               if (current != charcount)
+                               {
+                                       goxy (orgx, orgy);
+                                       ConOutPrintf (_T("%s"), str);
+                                       current = charcount;
+                               }
+                               break;
+
+                       case VK_TAB:
+#ifdef FEATURE_UNIX_FILENAME_COMPLETION
+                               /* expand current file name */
+                               if (current == charcount) // only works at end of line
+                               {
+                                       if (wLastKey != VK_TAB)
+                                       {
+                                               // if first TAB, complete filename
+                                               CompleteFilename (str, charcount);
+                                               charcount = _tcslen (str);
+                                               current = charcount;
+
+                                               goxy(orgx, orgy);
+                                               ConOutPrintf (_T("%s"), str);
+                                               if ((_tcslen (str) > (USHORT)(maxx - orgx)) && (orgy == maxy + 1))
+                                                       orgy--;
+                                       }
+                                       else
+                                       {
+                                               //if second TAB, list matches
+                                               if (ShowCompletionMatches (str, charcount))
+                                               {
+                                                       PrintPrompt ();
+                                                       orgx = wherex ();
+                                                       orgy = wherey ();
+                                                       ConOutPrintf (_T("%s"), str);
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       MessageBeep (-1);
+                               }
+#endif
+#ifdef FEATURE_4NT_FILENAME_COMPLETION
+                               /* this is not implemented yet */
+                               if (ir.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED)
+                               {
+                                       /* get previous match */
+
+                               }
+                               else
+                               {
+                                       /* get next match */
+
+                               }
+#endif
+                               break;
+
+                       case VK_RETURN:
+                               /* end input, return to main */
+#ifdef FEATURE_HISTORY
+                               /* add to the history */
+                               if (str[0])
+                                       History (0, str);
+#endif
+                               ConInDummy ();
+                               ConOutChar (_T('\n'));
+                               break;
+
+                       case VK_ESCAPE:
+                               /* clear str  Make this callable! */
+                               ClearCommandLine (str, maxlen, orgx, orgy);
+                               current = charcount = 0;
+                               break;
+
+                       case VK_UP:
+#ifdef FEATURE_HISTORY
+                               /* get previous command from buffer */
+                               ClearCommandLine (str, maxlen, orgx, orgy);
+                               History (-1, str);
+                               current = charcount = _tcslen (str);
+                               ConOutPrintf (_T("%s"), str);
+#endif
+                               break;
+
+                       case VK_DOWN:
+#ifdef FEATURE_HISTORY
+                               /* get next command from buffer */
+                               ClearCommandLine (str, maxlen, orgx, orgy);
+                               History (1, str);
+                               current = charcount = _tcslen (str);
+                               ConOutPrintf (_T("%s"), str);
+#endif
+                               break;
+
+                       case VK_LEFT:
+                               /* move cursor left */
+                               if (current > 0)
+                               {
+                                       current--;
+                                       if (wherex () == 0)
+                                               goxy ((SHORT)(maxx - 1), (SHORT)(wherey () - 1));
+                                       else
+                                               goxy ((SHORT)(wherex () - 1), wherey ());
+                               }
+                               else
+                               {
+//                                     Beep (440, 100);
+                                       MessageBeep (-1);
+                               }
+                               break;
+
+                       case VK_RIGHT:
+                               /* move cursor right */
+                               if (current != charcount)
+                               {
+                                       current++;
+                                       if (wherex () == maxx - 1)
+                                               goxy (0, (SHORT)(wherey () + 1));
+                                       else
+                                               goxy ((SHORT)(wherex () + 1), wherey ());
+                               }
+                               break;
+
+                       default:
+#ifdef _UNICODE
+                               ch = ir.Event.KeyEvent.uChar.UnicodeChar;
+#else
+                               ch = ir.Event.KeyEvent.uChar.AsciiChar;
+#endif
+                               if ((ch >= 32 && ch <= 255) && (charcount != (maxlen - 2)))
+                               {
+                                       /* insert character into string... */
+                                       if (bInsert && current != charcount)
+                                       {
+                                               for (count = charcount; count > current; count--)
+                                                       str[count] = str[count - 1];
+                                               str[current++] = ch;
+                                               if (wherex () == maxx - 1)
+                                               {
+                                                       curx = 0;
+                                                       cury = wherey () + 1;
+                                               }
+                                               else
+                                               {
+                                                       curx = wherex () + 1;
+                                                       cury = wherey ();
+                                               }
+                                               ConOutPrintf (_T("%s"), &str[current - 1]);
+                                               if ((_tcslen (str) > (USHORT)(maxx - orgx)) && (orgy == maxy + 1))
+                                                       cury--;
+                                               goxy (curx, cury);
+                                               charcount++;
+                                       }
+                                       else
+                                       {
+                                               if (current == charcount)
+                                                       charcount++;
+                                               str[current++] = ch;
+                                               ConOutChar (ch);
+                                       }
+                                       if ((_tcslen (str) > (USHORT)(maxx - orgx)) && (orgy == maxy + 1))
+                                               orgy--;
+                               }
+#if 0
+                               else
+                               {
+//                                     Beep (440, 100);
+                                       MessageBeep (-1);
+                               }
+#endif
+                               break;
+
+               }
+               wLastKey = ir.Event.KeyEvent.wVirtualKeyCode;
+       }
+       while (ir.Event.KeyEvent.wVirtualKeyCode != VK_RETURN);
+
+       SetCursorType (bInsert, TRUE);
+}
diff --git a/rosapps/cmd/cmdtable.c b/rosapps/cmd/cmdtable.c
new file mode 100644 (file)
index 0000000..f2d8339
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ *  CMDTABLE.C - table of internal commands.
+ *
+ *
+ *  History:
+ *
+ *    16 Jul 1998 (Hans B Pufal)
+ *        started.
+ *        New file to keep the internal command table. I plan on
+ *        getting rid of the table real soon now and replacing it
+ *        with a dynamic mechnism.
+ *
+ *    27 Jul 1998  John P. Price
+ *        added config.h include
+ *
+ *    21-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+
+#include "cmd.h"
+
+#include "chcp.h"
+
+
+/* a list of all the internal commands, associating their command names */
+/* to the functions to process them                                     */
+
+/* Lines marked
+ *
+ * $$ are external commands
+ * !! internal commands which are not yet implemented
+ * ** special FREEDOS specific implementation
+ */
+
+COMMAND cmds[] =
+{
+       {_T("?"),        0, cmd_showcommands},
+
+#ifdef FEATURE_ALIASES
+       {_T("alias"),    0, cmd_alias},
+#endif
+
+#ifdef INCLUDE_CMD_ATTRIB
+       {_T("attrib"),   0, cmd_attrib},
+#endif
+
+#ifdef INCLUDE_CMD_BEEP
+       {_T("beep"),     0, cmd_beep},
+#endif
+
+/*
+       {_T("break"),    0, cmd_break},
+*/
+
+       {_T("call"), CMD_BATCHONLY, cmd_call},
+
+#ifdef INCLUDE_CMD_CHDIR
+       {_T("cd"), CMD_SPECIAL, cmd_chdir},
+       {_T("chdir"), CMD_SPECIAL, cmd_chdir},
+#endif
+
+#ifdef INCLUDE_CMD_CHCP
+       {_T("chcp"),     0, CommandChcp},
+#endif
+
+#ifdef INCLUDE_CMD_CLS
+       {_T("cls"),      0, cmd_cls},
+#endif
+
+#ifdef INCLUDE_CMD_COLOR
+       {_T("color"),    0, cmd_color},
+#endif
+
+#ifdef INCLUDE_CMD_COPY
+       {_T("copy"),     0, cmd_copy},
+#endif
+
+/*
+#define INCLUDE_CMD_CTTY
+       {_T("ctty"),     0, cmd_ctty},
+#endif
+*/
+
+#ifdef INCLUDE_CMD_DATE
+       {_T("date"),     0, cmd_date},
+#endif
+
+#ifdef INCLUDE_CMD_DEL
+       {_T("del"),      0, cmd_del},
+       {_T("delete"),   0, cmd_del},
+#endif
+
+#ifdef INCLUDE_CMD_DIR
+       {_T("dir"), CMD_SPECIAL, cmd_dir},
+#endif
+
+       {_T("echo"),     0, cmd_echo},
+
+#ifdef INCLUDE_CMD_DEL
+       {_T("erase"),    0, cmd_del},
+#endif
+
+       {_T("exit"), 0, internal_exit},
+
+       {_T("for"), 0, cmd_for},
+
+       {_T("goto"), CMD_BATCHONLY, cmd_goto},
+
+       {_T("if"), 0, cmd_if},
+
+#ifdef INCLUDE_CMD_LABEL
+       {_T("label"), 0, cmd_label},
+#endif
+
+#ifdef INCLUDE_CMD_MKDIR
+       {_T("md"), CMD_SPECIAL, cmd_mkdir},
+       {_T("mkdir"), CMD_SPECIAL, cmd_mkdir},
+#endif
+
+#ifdef INCLUDE_CMD_MOVE
+       {_T("move"),     0, cmd_move},
+#endif
+
+#ifdef INCLUDE_CMD_PATH
+       {_T("path"), 0, cmd_path},
+#endif
+
+#ifdef INCLUDE_CMD_PAUSE
+       {_T("pause"), 0, cmd_pause},
+#endif
+
+#ifdef FEATURE_DIRECTORY_STACK
+       {_T("popd"),   0, cmd_popd},
+#endif
+
+#ifdef INCLUDE_CMD_PROMPT
+       {_T("prompt"), 0, cmd_prompt},
+#endif
+
+#ifdef FEATURE_DIRECTORY_STACK
+       {_T("pushd"),  0, cmd_pushd},
+#endif
+
+#ifdef INCLUDE_CMD_RMDIR
+       {_T("rd"), CMD_SPECIAL, cmd_rmdir},
+#endif
+
+#ifdef INCLUDE_CMD_REM
+       {_T("rem"), 0, cmd_rem},
+#endif
+
+#ifdef INCLUDE_CMD_RENAME
+       {_T("ren"), 0, cmd_rename},
+       {_T("rename"), 0, cmd_rename},
+#endif
+
+#ifdef INCLUDE_CMD_RMDIR
+       {_T("rmdir"), CMD_SPECIAL, cmd_rmdir},
+#endif
+
+#ifdef INCLUDE_CMD_SET
+       {_T("set"), 0, cmd_set},
+#endif
+
+       {_T("shift"), CMD_BATCHONLY, cmd_shift},
+
+#ifdef INCLUDE_CMD_TIME
+       {_T("time"), 0, cmd_time},
+#endif
+
+#ifdef INCLUDE_CMD_TYPE
+       {_T("type"), 0, cmd_type},
+#endif
+
+#ifdef INCLUDE_CMD_VER
+       {_T("ver"), 0, cmd_ver},
+#endif
+
+#ifdef INCLUDE_CMD_VERIFY
+       {_T("verify"), 0, cmd_verify},
+#endif
+
+#ifdef INCLUDE_CMD_VOL
+       {_T("vol"), 0, cmd_vol},
+#endif
+
+       {NULL, 0, NULL}
+};
+
+/*    append,                             $$    */
+/*    assign,                             $$    */
+/*    attrib,                             **    */
+/*    backup,                             $$    */
+/*    chkdsk,                             $$    */
+/*    comp,                               $$    */
+/*    debug,                              $$    */
+/*    diskcomp,                           $$    */
+/*    diskcopy,                           $$    */
+/*    doskey,                             **    */
+/*    dosshell,                           $$    */
+/*    edit,                               $$    */
+/*    edlin,                              $$    */
+/*    emm386,                             $$    */
+/*    exe2bin,                            $$    */
+/*    expand,                             $$    */
+/*    fastopen,                           $$    */
+/*    fc,                                 $$    */
+/*    fdisk,                              $$    */
+/*    find,                               $$    */
+/*    format,                             $$    */
+/*    graftabl,                           $$    */
+/*    graphics,                           $$    */
+/*    help,                               $$    */
+/*    join,                               $$    */
+/*    keyb,                               $$    */
+/*    mem,                                $$    */
+/*    mirror,                             $$    */
+/*    mode,                               $$    */
+/*    more,                               $$    */
+/*    nlsfunc,                            $$    */
+/*    print,                              $$    */
+/*    qbasic,                             $$    */
+/*    recover,                            $$    */
+/*    replace,                            $$    */
+/*    restore,                            $$    */
+/*    setver,                             $$    */
+/*    share,                              $$    */
+/*    sort,                               $$    */
+/*    subst,                              $$    */
+/*    sys,                                $$    */
+/*    tree,                               $$    */
+/*    undelete,                           $$    */
+/*    unformat,                           $$    */
+/*    xcopy,                              $$    */
diff --git a/rosapps/cmd/color.c b/rosapps/cmd/color.c
new file mode 100644 (file)
index 0000000..f5d0867
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ *  COLOR.C - color internal command.
+ *
+ *
+ *  History:
+ *
+ *    13-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Started.
+ *
+ *    19-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode ready!
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Redirection ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_COLOR
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+
+VOID SetScreenColor (WORD wColor)
+{
+       DWORD dwWritten;
+       CONSOLE_SCREEN_BUFFER_INFO csbi;
+       COORD coPos;
+
+       GetConsoleScreenBufferInfo (hOut, &csbi);
+
+       coPos.X = 0;
+       coPos.Y = 0;
+       FillConsoleOutputAttribute (hOut, wColor,
+                                                               (csbi.dwSize.X)*(csbi.dwSize.Y),
+                                                               coPos, &dwWritten);
+       SetConsoleTextAttribute (hOut, wColor);
+}
+
+
+/*
+ * color
+ *
+ * internal dir command
+ */
+INT cmd_color (LPTSTR first, LPTSTR rest)
+{
+       if (_tcsncmp (rest, _T("/?"), 2) == 0)
+       {
+               ConOutPuts (_T("Sets the default foreground and background colors.\n\n"
+                                  "COLOR [attr]\n\n"
+                                  "  attr        Specifies color attribute of console output\n\n"
+                                  "Color attributes are specified by TWO hex digits -- the first\n"
+                                  "corresponds to the background; the second to the foreground. Each digit\n"
+                                  "can be one of the following:\n"));
+
+               ConOutPuts (_T("    0 = Black       8 = Gray\n"
+                                  "    1 = Blue        9 = Light Blue\n"
+                                  "    2 = Green       A = Light Green\n"
+                                  "    3 = Aqua        B = Light Aqua\n"
+                                  "    4 = Red         C = Light Red\n"
+                                  "    5 = Purple      D = Light Purple\n"
+                                  "    6 = Yellow      E = Light Yellow\n"
+                                  "    7 = White       F = Bright White\n"));
+               return 0;
+       }
+
+       if (rest[0] == _T('\0'))
+       {
+               /* set default color */
+               wColor = wDefColor;
+               SetScreenColor (wColor);
+               return 0;
+       }
+
+       if (_tcslen (rest) != 2)
+       {
+               ConErrPuts (_T("parameter error!"));
+               return 1;
+       }
+
+       wColor = (WORD)_tcstoul (rest, NULL, 16);
+
+       if ((wColor & 0xF) == (wColor &0xF0) >> 4)
+       {
+               ConErrPuts (_T("same colors error!"));
+               return 1;
+       }
+
+       /* set color */
+       SetScreenColor (wColor);
+
+       return 0;
+}
+
+#endif
diff --git a/rosapps/cmd/config.h b/rosapps/cmd/config.h
new file mode 100644 (file)
index 0000000..1e214e2
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ *  CONFIG.H - Used to configure what will be compiled into the shell.
+ *
+ *
+ *  History:
+ *
+ *    27 Jul 1998 - John P. Price
+ *        started.
+ *
+ */
+
+
+/* JPP 20 Jul 1998 - define DEBUG to add debugging code */
+/*#define DEBUG */
+
+
+/* Define to enable the alias command, and aliases.*/
+#define FEATURE_ALIASES
+
+
+/* Define to enable history */
+#define FEATURE_HISTORY
+
+
+/* Define one of these to enable filename completion */
+#define FEATURE_UNIX_FILENAME_COMPLETION
+/* #define FEATURE_4NT_FILENAME_COMPLETION */
+
+
+/* Define to enable the directory stack */
+#define FEATURE_DIRECTORY_STACK
+
+
+/* Define to activate redirections and piping */
+#define FEATURE_REDIRECTION
+
+
+/* Define one of these to select the used locale. */
+/*  (date and time formats etc.) used in DATE, TIME */
+/*  DIR and PROMPT. */
+#define LOCALE_WINDOWS      /* System locale */
+/* #define LOCALE_GERMAN */    /* German locale */
+/* #define LOCALE_DEFAULT */   /* United States locale */
+
+
+#define INCLUDE_CMD_ATTRIB
+//#define INCLUDE_CMD_BREAK
+#define INCLUDE_CMD_CHCP
+#define INCLUDE_CMD_CHDIR
+#define INCLUDE_CMD_CLS
+#define INCLUDE_CMD_COLOR
+#define INCLUDE_CMD_COPY
+//#define INCLUDE_CMD_CTTY
+#define INCLUDE_CMD_DATE
+#define INCLUDE_CMD_DEL
+#define INCLUDE_CMD_DIR
+#define INCLUDE_CMD_LABEL
+#define INCLUDE_CMD_MKDIR
+#define INCLUDE_CMD_MOVE
+#define INCLUDE_CMD_PATH
+#define INCLUDE_CMD_PROMPT
+#define INCLUDE_CMD_RMDIR
+#define INCLUDE_CMD_RENAME
+#define INCLUDE_CMD_SET
+#define INCLUDE_CMD_TIME
+#define INCLUDE_CMD_TYPE
+#define INCLUDE_CMD_VER
+#define INCLUDE_CMD_REM
+#define INCLUDE_CMD_PAUSE
+#define INCLUDE_CMD_BEEP
+#define INCLUDE_CMD_VERIFY
+#define INCLUDE_CMD_VOL
+
+/*
+command that do not have a define:
+
+exit
+call
+echo
+goto
+for
+if
+shift
+
+*/
+
diff --git a/rosapps/cmd/console.c b/rosapps/cmd/console.c
new file mode 100644 (file)
index 0000000..c740f2a
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ *  CONSOLE.C - console input/output functions.
+ *
+ *
+ *  History:
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        started
+ */
+
+
+
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+#include <tchar.h>
+
+#include "cmd.h"
+
+
+
+/* internal variables for paged output */
+SHORT sLineCount;
+SHORT sMaxLines;
+BOOL  bPageable;
+
+
+
+#ifdef _DEBUG
+VOID DebugPrintf (LPTSTR szFormat, ...)
+{
+       TCHAR szOut[512];
+       va_list arg_ptr;
+
+       va_start (arg_ptr, szFormat);
+       wvsprintf (szOut, szFormat, arg_ptr);
+       va_end (arg_ptr);
+
+       OutputDebugString (szOut);
+}
+#endif /* _DEBUG */
+
+
+VOID ConInDummy (VOID)
+{
+       HANDLE hInput = GetStdHandle (STD_INPUT_HANDLE);
+       INPUT_RECORD dummy;
+       DWORD  dwRead;
+
+#ifdef _DEBUG
+       if (hInput == INVALID_HANDLE_VALUE)
+               DebugPrintf ("Invalid input handle!!!\n");
+#endif
+
+       ReadConsoleInput (hInput, &dummy, 1, &dwRead);
+}
+
+
+VOID ConInKey (PINPUT_RECORD lpBuffer)
+{
+       HANDLE hInput = GetStdHandle (STD_INPUT_HANDLE);
+       DWORD  dwRead;
+
+#ifdef _DEBUG
+       if (hInput == INVALID_HANDLE_VALUE)
+               DebugPrintf ("Invalid input handle!!!\n");
+#endif
+
+       do
+       {
+               WaitForSingleObject (hInput, INFINITE);
+               ReadConsoleInput (hInput, lpBuffer, 1, &dwRead);
+               if ((lpBuffer->EventType == KEY_EVENT) &&
+                       (lpBuffer->Event.KeyEvent.bKeyDown == TRUE))
+                       break;
+       }
+       while (TRUE);
+}
+
+
+
+VOID ConInString (LPTSTR lpInput, DWORD dwLength)
+{
+       DWORD dwOldMode;
+       DWORD dwRead;
+       HANDLE hFile;
+
+       LPTSTR p;
+       DWORD  i;
+
+       ZeroMemory (lpInput, dwLength * sizeof(TCHAR));
+       hFile = GetStdHandle (STD_INPUT_HANDLE);
+       GetConsoleMode (hFile, &dwOldMode);
+
+       SetConsoleMode (hFile, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT);
+
+       ReadFile (hFile, lpInput, dwLength, &dwRead, NULL);
+
+       p = lpInput;
+       for (i = 0; i < dwRead; i++, p++)
+       {
+               if (*p == _T('\x0d'))
+               {
+                       *p = _T('\0');
+                       break;
+               }
+       }
+
+       SetConsoleMode (hFile, dwOldMode);
+}
+
+
+VOID ConOutChar (TCHAR c)
+{
+       DWORD dwWritten;
+
+       WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), &c, 1, &dwWritten, NULL);
+}
+
+
+VOID ConOutPuts (LPTSTR szText)
+{
+       DWORD dwWritten;
+
+       WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), szText, _tcslen(szText), &dwWritten, NULL);
+       WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), "\x0a\x0d", 2, &dwWritten, NULL);
+}
+
+
+VOID ConOutPrintf (LPTSTR szFormat, ...)
+{
+       DWORD dwWritten;
+       TCHAR szOut[256];
+       va_list arg_ptr;
+
+       va_start (arg_ptr, szFormat);
+       wvsprintf (szOut, szFormat, arg_ptr);
+       va_end (arg_ptr);
+
+       WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), szOut, _tcslen(szOut), &dwWritten, NULL);
+}
+
+
+VOID ConErrChar (TCHAR c)
+{
+       DWORD dwWritten;
+
+       WriteFile (GetStdHandle (STD_ERROR_HANDLE), &c, 1, &dwWritten, NULL);
+}
+
+
+VOID ConErrPuts (LPTSTR szText)
+{
+       DWORD dwWritten;
+
+       WriteFile (GetStdHandle (STD_ERROR_HANDLE), szText, _tcslen(szText), &dwWritten, NULL);
+       WriteFile (GetStdHandle (STD_ERROR_HANDLE), "\x0a\x0d", 2, &dwWritten, NULL);
+}
+
+
+VOID ConErrPrintf (LPTSTR szFormat, ...)
+{
+       DWORD dwWritten;
+       TCHAR szOut[4096];
+       va_list arg_ptr;
+
+       va_start (arg_ptr, szFormat);
+       wvsprintf (szOut, szFormat, arg_ptr);
+       va_end (arg_ptr);
+
+       WriteFile (GetStdHandle (STD_ERROR_HANDLE), szOut, _tcslen(szOut), &dwWritten, NULL);
+}
+
+
+
+
+/*
+ * goxy -- move the cursor on the screen.
+ */
+VOID goxy (SHORT x, SHORT y)
+{
+       COORD coPos;
+
+       coPos.X = x;
+       coPos.Y = y;
+       SetConsoleCursorPosition (GetStdHandle (STD_OUTPUT_HANDLE), coPos);
+}
+
+
+SHORT wherex (VOID)
+{
+       CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+       GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &csbi);
+
+       return csbi.dwCursorPosition.X;
+}
+
+
+SHORT wherey (VOID)
+{
+       CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+       GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &csbi);
+
+       return csbi.dwCursorPosition.Y;
+}
+
+
+VOID GetScreenSize (PSHORT maxx, PSHORT maxy)
+{
+       CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+       GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &csbi);
+
+       if (maxx)
+               *maxx = csbi.dwSize.X;
+       if (maxy)
+               *maxy = csbi.dwSize.Y;
+}
+
+
+VOID SetCursorType (BOOL bInsert, BOOL bVisible)
+{
+       CONSOLE_CURSOR_INFO cci;
+
+       cci.dwSize = bInsert ? 10 : 100;
+       cci.bVisible = bVisible;
+
+       SetConsoleCursorInfo (GetStdHandle (STD_OUTPUT_HANDLE), &cci);
+}
+
+
+
+VOID InitializePageOut (VOID)
+{
+       sLineCount = 0;
+
+       if (GetFileType (GetStdHandle (STD_OUTPUT_HANDLE)) == FILE_TYPE_CHAR)
+       {
+               bPageable = TRUE;
+               GetScreenSize (NULL, &sMaxLines);
+       }
+       else
+       {
+               bPageable = FALSE;
+       }
+}
+
+
+VOID TerminatePageOut (VOID)
+{
+
+
+}
+
+
+
+int LinePageOut (LPTSTR szLine)
+{
+       ConOutPuts (szLine);
+
+       if (bPageable)
+       {
+               sLineCount++;
+               if (sLineCount >= sMaxLines)
+               {
+                       sLineCount = 0;
+                       cmd_pause ("", "");
+               }
+       }
+       return 0;
+}
diff --git a/rosapps/cmd/copy.c b/rosapps/cmd/copy.c
new file mode 100644 (file)
index 0000000..16b5617
--- /dev/null
@@ -0,0 +1,733 @@
+/*
+ *  COPY.C -- copy internal command.
+ *
+ *
+ *  History:
+ *
+ *    01-Aug-98 (Rob Lake z63rrl@morgan.ucs.mun.ca)
+ *        started
+ *
+ *    13-Aug-1998 (John P. Price)
+ *        fixed memory leak problem in copy function.
+ *        fixed copy function so it would work with wildcards in the source
+ *
+ *    13-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added COPY command to CMD.
+ *
+ *    26-Jan-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Replaced CRT io functions by Win32 io functions.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_COPY
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "cmd.h"
+
+
+#define VERIFY  1               /* VERIFY Switch */
+#define BINARY  2               /* File is to be copied as BINARY */
+#define ASCII   4               /* File is to be copied as ASCII */
+#define PROMPT  8               /* Prompt before overwriting files */
+#define NPROMPT 16              /* Do not prompt before overwriting files */
+#define HELP    32              /* Help was asked for */
+#define SOURCE  128             /* File is a source */
+
+
+typedef struct tagFILES
+{
+       struct tagFILES *next;
+       TCHAR szFile[MAX_PATH];
+       DWORD dwFlag;                   /* BINARY -xor- ASCII */
+} FILES, *LPFILES;
+
+
+static BOOL DoSwitches (LPTSTR, LPDWORD);
+static BOOL AddFile (LPFILES, char *, int *, int *, unsigned *);
+static BOOL AddFiles (LPFILES, char *, int *, int *, int *, unsigned *);
+static BOOL GetDestination (LPFILES, LPFILES);
+static INT  ParseCommand (LPFILES, int, char **, LPDWORD);
+static VOID DeleteFileList (LPFILES);
+static INT  Overwrite (LPTSTR);
+
+
+
+static BOOL IsDirectory (LPTSTR fn)
+{
+       if (!IsValidFileName (fn))
+               return FALSE;
+       return (GetFileAttributes (fn) & FILE_ATTRIBUTE_DIRECTORY);
+}
+
+
+static BOOL DoSwitches (LPTSTR arg, LPDWORD lpdwFlags)
+{
+       if (!_tcsicmp (arg, _T("/-Y")))
+       {
+               *lpdwFlags |= PROMPT;
+               *lpdwFlags &= ~NPROMPT;
+               return TRUE;
+       }
+       else if (_tcslen (arg) > 2)
+       {
+               error_too_many_parameters ("");
+               return FALSE;
+       }
+
+       switch (_totupper (arg[1]))
+       {
+               case _T('V'):
+                       *lpdwFlags |= VERIFY;
+                       break;
+
+               case _T('A'):
+                       *lpdwFlags |= ASCII;
+                       *lpdwFlags &= ~BINARY;
+                       break;
+
+               case _T('B'):
+                       *lpdwFlags |= BINARY;
+                       *lpdwFlags &= ~ASCII;
+                       break;
+
+               case _T('Y'):
+                       *lpdwFlags &= ~PROMPT;
+                       *lpdwFlags |= NPROMPT;
+                       break;
+
+               default:
+                       error_invalid_switch (arg[1]);
+                       return FALSE;
+       }
+       return TRUE;
+}
+
+
+static BOOL
+AddFile (LPFILES f, char *arg, int *source, int *dest, unsigned *flags)
+{
+       if (*dest)
+       {
+               error_too_many_parameters ("");
+               return FALSE;
+       }
+       if (*source)
+       {
+               *dest = 1;
+               f->dwFlag = 0;
+       }
+       else
+       {
+               *source = 1;
+               f->dwFlag = SOURCE;
+       }
+       _tcscpy(f->szFile, arg);
+       f->dwFlag |= *flags & ASCII ? ASCII : BINARY;
+       if ((f->next = (LPFILES)malloc (sizeof (FILES))) == NULL)
+       {
+               error_out_of_memory ();
+               return FALSE;
+       }
+       f = f->next;
+       f->dwFlag = 0;
+       f->next = NULL;
+       return TRUE;
+}
+
+
+static BOOL
+AddFiles (LPFILES f, char *arg, int *source, int *dest,
+                 int *count, unsigned *flags)
+{
+       char t[128];
+       int j;
+       int k;
+
+       if (*dest)
+       {
+               error_too_many_parameters ("");
+               return FALSE;
+       }
+
+       j = 0;
+       k = 0;
+
+       while (arg[j] == _T('+'))
+               j++;
+
+       while (arg[j] != _T('\0'))
+       {
+               t[k] = arg[j++];
+               if (t[k] == '+' || arg[j] == _T('\0'))
+               {
+                       if (!k)
+                               continue;
+                       if (arg[j] == _T('\0') && t[k] != _T('+'))
+                               k++;
+                       t[k] = _T('\0');
+                       *count += 1;
+                       _tcscpy (f->szFile, t);
+                       *source = 1;
+                       if (*flags & ASCII)
+                               f->dwFlag |= *flags | SOURCE | ASCII;
+                       else
+                               f->dwFlag |= *flags | BINARY | SOURCE;
+
+                       if ((f->next = (LPFILES)malloc (sizeof (FILES))) == NULL)
+                       {
+                               error_out_of_memory ();
+                               return FALSE;
+                       }
+                       f = f->next;
+                       f->next = NULL;
+                       k = 0;
+                       f->dwFlag = 0;
+                       continue;
+               }
+               k++;
+       }
+
+       if (arg[--j] == _T('+'))
+               *source = 0;
+
+       return 1;
+}
+
+
+static BOOL GetDestination (LPFILES f, LPFILES dest)
+{
+       LPFILES p;
+       LPFILES start = f;
+
+       while (f->next != NULL)
+       {
+               p = f;
+               f = f->next;
+       }
+
+       f = p;
+
+       if ((f->dwFlag & SOURCE) == 0)
+       {
+               free (p->next);
+               p->next = NULL;
+               _tcscpy (dest->szFile, f->szFile);
+               dest->dwFlag = f->dwFlag;
+               dest->next = NULL;
+               f = start;
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+
+static INT
+ParseCommand (LPFILES f, int argc, char **arg, LPDWORD lpdwFlags)
+{
+       INT i;
+       INT dest;
+       INT source;
+       INT count;
+
+       dest = 0;
+       source = 0;
+       count = 0;
+
+       for (i = 0; i < argc; i++)
+       {
+               if (arg[i][0] == _T('/'))
+               {
+                       if (!DoSwitches (arg[i], lpdwFlags))
+                               return -1;
+               }
+               else
+               {
+                       if (!_tcscmp(arg[i], _T("+")))
+                               source = 0;
+                       else if (!_tcschr(arg[i], _T('+')) && source)
+                       {
+                               if (!AddFile(f, arg[i], &source, &dest, lpdwFlags))
+                                       return -1;
+                               f = f->next;
+                               count++;
+                       }
+                       else
+                       {
+                               if (!AddFiles(f, arg[i], &source, &dest, &count, lpdwFlags))
+                                       return -1;
+                               while (f->next != NULL)
+                                       f = f->next;
+                       }
+               }
+       }
+#ifdef _DEBUG
+       DebugPrintf ("ParseCommand: flags has %s\n",
+                                *lpdwFlags & ASCII ? "ASCII" : "BINARY");
+#endif
+       return count;
+}
+
+
+static VOID DeleteFileList (LPFILES f)
+{
+       LPFILES temp;
+
+       while (f != NULL)
+       {
+               temp = f;
+               f = f->next;
+               free (temp);
+       }
+}
+
+
+static INT
+Overwrite (LPTSTR fn)
+{
+       TCHAR inp[10];
+       LPTSTR p;
+
+       ConOutPrintf (_T("Overwrite %s (Yes/No/All)? "), fn);
+       ConInString (inp, 10);
+
+       _tcsupr (inp);
+       for (p = inp; _istspace (*p); p++)
+               ;
+
+       if (*p != _T('Y') && *p != _T('A'))
+               return 0;
+       if (*p == _T('A'))
+               return 2;
+
+       return 1;
+}
+
+
+#define BUFF_SIZE 16384         /* 16k = max buffer size */
+
+
+int copy (LPTSTR source, LPTSTR dest, int append, LPDWORD lpdwFlags)
+{
+       FILETIME srctime;
+       HANDLE hFileSrc;
+       HANDLE hFileDest;
+       LPBYTE buffer;
+       DWORD  dwAttrib;
+       DWORD  dwRead;
+       DWORD  dwWritten;
+       DWORD  i;
+       BOOL   bEof = FALSE;
+
+#ifdef _DEBUG
+       DebugPrintf ("checking mode\n");
+#endif
+
+       dwAttrib = GetFileAttributes (source);
+
+       hFileSrc = CreateFile (source, GENERIC_READ, FILE_SHARE_READ,
+                                                  NULL, OPEN_EXISTING, 0, NULL);
+       if (hFileSrc == INVALID_HANDLE_VALUE)
+       {
+               ConErrPrintf (_T("Error: Cannot open source - %s!\n"), source);
+               return 0;
+       }
+
+#ifdef _DEBUG
+       DebugPrintf (_T("getting time\n"));
+#endif
+
+       GetFileTime (hFileSrc, &srctime, NULL, NULL);
+
+#ifdef _DEBUG
+       DebugPrintf (_T("copy: flags has %s\n"),
+                                *lpdwFlags & ASCII ? "ASCII" : "BINARY");
+#endif
+
+       if (!IsValidFileName (dest))
+       {
+#ifdef _DEBUG
+               DebugPrintf (_T("opening/creating\n"));
+#endif
+               hFileDest =
+                       CreateFile (dest, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+       }
+       else if (!append)
+       {
+               if (!_tcscmp (dest, source))
+               {
+                       ConErrPrintf (_T("Error: Can't copy onto itself!\n"));
+                       CloseHandle (hFileSrc);
+                       return 0;
+               }
+
+#ifdef _DEBUG
+               DebugPrintf (_T("SetFileAttributes (%s, FILE_ATTRIBUTE_NORMAL);\n"), dest);
+#endif
+               SetFileAttributes (dest, FILE_ATTRIBUTE_NORMAL);
+
+#ifdef _DEBUG
+               DebugPrintf (_T("DeleteFile (%s);\n"), dest);
+#endif
+               DeleteFile (dest);
+
+               hFileDest =
+                       CreateFile (dest, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+       }
+       else
+       {
+               LONG lFilePosHigh = 0;
+
+               if (!_tcscmp (dest, source))
+               {
+                       CloseHandle (hFileSrc);
+                       return 0;
+               }
+
+#ifdef _DEBUG
+               DebugPrintf (_T("opening/appending\n"));
+#endif
+               hFileDest =
+                       CreateFile (dest, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+               SetFilePointer (hFileDest, 0, &lFilePosHigh,FILE_END);
+       }
+
+       if (hFileDest == INVALID_HANDLE_VALUE)
+       {
+               CloseHandle (hFileSrc);
+               error_path_not_found ();
+               return 0;
+       }
+
+       buffer = (LPBYTE)malloc (BUFF_SIZE);
+       if (buffer == NULL)
+       {
+               CloseHandle (hFileDest);
+               CloseHandle (hFileSrc);
+               error_out_of_memory ();
+               return 0;
+       }
+
+       ConOutPuts (source);
+
+       do
+       {
+               ReadFile (hFileSrc, buffer, BUFF_SIZE, &dwRead, NULL);
+               if (*lpdwFlags & ASCII)
+               {
+                       for (i = 0; i < dwRead; i++)
+                       {
+                               if (((LPTSTR)buffer)[i] == 0x1A)
+                               {
+                                       bEof = TRUE;
+                                       break;
+                               }
+                       }
+                       dwRead = i;
+               }
+
+               if (dwRead == 0)
+                       break;
+
+               WriteFile (hFileDest, buffer, dwRead, &dwWritten, NULL);
+               if (dwWritten != dwRead)
+               {
+                       ConErrPrintf (_T("Error writing destination!\n"));
+                       free (buffer);
+                       CloseHandle (hFileDest);
+                       CloseHandle (hFileSrc);
+                       return 0;
+               }
+       }
+       while (dwRead && !bEof);
+
+#ifdef _DEBUG
+       DebugPrintf (_T("setting time\n"));
+#endif
+       SetFileTime (hFileDest, &srctime, NULL, NULL);
+
+       if (*lpdwFlags & ASCII)
+       {
+               ((LPTSTR)buffer)[0] = 0x1A;
+               ((LPTSTR)buffer)[1] = _T('\0');
+#ifdef _DEBUG
+               DebugPrintf (_T("appending ^Z\n"));
+#endif
+               WriteFile (hFileDest, buffer, sizeof(TCHAR), &dwWritten, NULL);
+       }
+
+       free (buffer);
+       CloseHandle (hFileDest);
+       CloseHandle (hFileSrc);
+
+#ifdef _DEBUG
+       DebugPrintf (_T("setting mode\n"));
+#endif
+       SetFileAttributes (dest, dwAttrib);
+
+       return 1;
+}
+
+
+int setup_copy (LPFILES sources, char **p, BOOL bMultiple,
+               char *drive_d, char *dir_d, char *file_d,
+               char *ext_d, int *append, LPDWORD lpdwFlags)
+{
+       WIN32_FIND_DATA find;
+
+  char drive_s[_MAX_DRIVE],
+    dir_s[_MAX_DIR],
+    file_s[_MAX_FNAME],
+    ext_s[_MAX_EXT];
+  char from_merge[_MAX_PATH];
+
+       LPTSTR real_source;
+       LPTSTR real_dest;
+
+       INT  nCopied = 0;
+       BOOL bAll = FALSE;
+       BOOL bDone;
+       HANDLE hFind;
+
+
+       real_source = (LPTSTR)malloc (MAX_PATH);
+       real_dest = (LPTSTR)malloc (MAX_PATH);
+
+       if (!real_source || !real_dest)
+       {
+               error_out_of_memory ();
+               DeleteFileList (sources);
+               free (real_source);
+               free (real_dest);
+               freep (p);
+               return 0;
+       }
+
+       while (sources->next != NULL)
+       {
+               _splitpath (sources->szFile, drive_s, dir_s, file_s, ext_s);
+               hFind = FindFirstFile (sources->szFile, &find);
+               if (hFind == INVALID_HANDLE_VALUE)
+               {
+                       error_file_not_found();
+                       DeleteFileList (sources);
+                       freep(p);
+                       free(real_source);
+                       free(real_dest);
+                       return 0;
+               }
+
+               do
+               {
+                       if (find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+                               goto next;
+
+                       _makepath(from_merge, drive_d, dir_d, file_d, ext_d);
+                       if (from_merge[_tcslen(from_merge) - 1] == _T('\\'))
+                               from_merge[_tcslen(from_merge) - 1] = 0;
+
+                       if (IsDirectory (from_merge))
+                       {
+                               bMultiple = FALSE;
+                               _tcscat (from_merge, _T("\\"));
+                               _tcscat (from_merge, find.cFileName);
+                       }
+                       else
+                               bMultiple = TRUE;
+
+                       _tcscpy (real_dest, from_merge);
+                       _makepath (real_source, drive_s, dir_s, find.cFileName, NULL);
+
+#ifdef _DEBUG
+                       DebugPrintf (_T("copying %s -> %s (%sappending%s)\n"),
+                                                real_source, real_dest,
+                                                *append ? "" : "not ",
+                                                sources->dwFlag & ASCII ? ", ASCII" : ", BINARY");
+#endif
+
+                       if (IsValidFileName (real_dest) && !bAll)
+                       {
+                               int over = Overwrite (real_dest);
+                               if (over == 2)
+                                       bAll = TRUE;
+                               else if (over == 0)
+                                       goto next;
+                               else if (bMultiple)
+                                       bAll = TRUE;
+                       }
+                       if (copy (real_source, real_dest, *append, lpdwFlags))
+                               nCopied++;
+               next:
+                       bDone = FindNextFile (hFind, &find);
+
+                       if (bMultiple)
+                               *append = 1;
+               }
+               while (bDone);
+
+               FindClose (hFind);
+               sources = sources->next;
+
+       }
+       free (real_source);
+       free (real_dest);
+
+       return nCopied;
+}
+
+
+INT cmd_copy (LPTSTR first, LPTSTR rest)
+{
+  char **p;
+  char drive_d[_MAX_DRIVE],
+    dir_d[_MAX_DIR],
+    file_d[_MAX_FNAME],
+    ext_d[_MAX_EXT];
+
+  int argc,
+    append,
+    files,
+    copied;
+
+       LPFILES sources;
+       FILES dest;
+       LPFILES start;
+       BOOL bMultiple;
+       BOOL bWildcards;
+       BOOL bDestFound;
+       DWORD dwFlags = 0;
+
+       if (!_tcsncmp (rest, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Copies one or more files to another location.\n"
+                                          "\n"
+                                          "COPY [/V][/Y|/-Y][/A|/B] source [/A|/B]\n"
+                                          "     [+ source [/A|/B] [+ ...]] [destination [/A|/B]]\n"
+                                          "\n"
+                                          "  source       Specifies the file or files to be copied.\n"
+                                          "  /A           Indicates an ASCII text file.\n"
+                                          "  /B           Indicates a binary file.\n"
+                                          "  destination  Specifies the directory and/or filename for the new file(s).\n"
+                                          "  /V           Verifies that new files are written correctly.\n"
+                                          "  /Y           Suppresses prompting to confirm you want to overwrite an\n"
+                                          "               existing destination file.\n"
+                                          "  /-Y          Causes prompting to confirm you want to overwrite an\n"
+                                          "               existing destination file.\n"
+                                          "\n"
+                                          "The switch /Y may be present in the COPYCMD environment variable.\n"
+                                          "..."));
+               return 1;
+       }
+
+       p = split (rest, &argc);
+
+       if (argc == 0)
+       {
+               error_req_param_missing ();
+               return 0;
+       }
+
+       sources = (LPFILES)malloc (sizeof (FILES));
+       if (!sources)
+       {
+               error_out_of_memory ();
+               return 0;
+       }
+       sources->next = NULL;
+       sources->dwFlag = 0;
+
+       if ((files = ParseCommand (sources, argc, p, &dwFlags)) == -1)
+       {
+               DeleteFileList (sources);
+               freep (p);
+               return 0;
+       }
+       else if (files == 0)
+       {
+               error_req_param_missing();
+               DeleteFileList (sources);
+               freep (p);
+               return 0;
+       }
+       start = sources;
+
+       bDestFound = GetDestination (sources, &dest);
+       if (bDestFound)
+       {
+               _splitpath (dest.szFile, drive_d, dir_d, file_d, ext_d);
+               if (IsDirectory (dest.szFile))
+               {
+                       _tcscat (dir_d, file_d);
+                       _tcscat (dir_d, ext_d);
+                       file_d[0] = _T('\0');
+                       ext_d[0] = _T('\0');
+               }
+       }
+
+       if (_tcschr (dest.szFile, _T('*')) || _tcschr (dest.szFile, _T('?')))
+               bWildcards = TRUE;
+       else
+               bWildcards = FALSE;
+
+       if (strchr(rest, '+'))
+               bMultiple = TRUE;
+       else
+               bMultiple = FALSE;
+
+       append = 0;
+       copied = 0;
+
+       if (bDestFound && !bWildcards)
+       {
+               copied = setup_copy (sources, p, bMultiple, drive_d, dir_d, file_d, ext_d, &append, &dwFlags);
+       }
+       else if (bDestFound && bWildcards)
+       {
+               ConErrPrintf (_T("Error: Not implemented yet!\n"));
+               DeleteFileList (sources);
+               freep (p);
+               return 0;
+       }
+       else if (!bDestFound && !bMultiple)
+       {
+               _splitpath (sources->szFile, drive_d, dir_d, file_d, ext_d);
+               if (IsDirectory (sources->szFile))
+               {
+                       _tcscat (dir_d, file_d);
+                       _tcscat (dir_d, ext_d);
+                       file_d[0] = _T('\0');
+                       ext_d[0] = _T('\0');
+               }
+               copied = setup_copy (sources, p, FALSE, "", "", file_d, ext_d, &append, &dwFlags);
+       }
+       else
+       {
+               _splitpath(sources->szFile, drive_d, dir_d, file_d, ext_d);
+               if (IsDirectory (sources->szFile))
+               {
+                       _tcscat (dir_d, file_d);
+                       _tcscat (dir_d, ext_d);
+                       file_d[0] = _T('\0');
+                       ext_d[0] = _T('\0');
+               }
+
+               ConOutPuts (sources->szFile);
+               append = 1;
+               copied = setup_copy (sources->next, p, bMultiple, drive_d, dir_d, file_d, ext_d, &append, &dwFlags) + 1;
+       }
+
+       DeleteFileList (start);
+       freep (p);
+       ConOutPrintf (_T("        %d file(s) copied\n"), copied);
+
+       return 1;
+}
+#endif /* INCLUDE_CMD_COPY */
diff --git a/rosapps/cmd/date.c b/rosapps/cmd/date.c
new file mode 100644 (file)
index 0000000..e271236
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ *  DATE.C - date internal command.
+ *
+ *
+ *  History:
+ *
+ *    08 Jul 1998 (John P. Price)
+ *        started.
+ *
+ *    20 Jul 1998 (John P. Price)
+ *        corrected number of days for December from 30 to 31.
+ *        (Thanx to Steffen Kaiser for bug report)
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    29-Jul-1998 (Rob Lake)
+ *        fixed stand-alone mode.
+ *        Added Pacific C compatible dos_getdate functions
+ *
+ *    09-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added locale support
+ *
+ *    23-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection safe!
+ *
+ *    04-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Fixed date input bug.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_DATE
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "cmd.h"
+
+
+static WORD awMonths[2][13] =
+{
+       {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+       {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
+};
+
+
+static VOID
+PrintDate (VOID)
+{
+#if 0
+       SYSTEMTIME st;
+
+       GetLocalTime (&st);
+
+       switch (nDateFormat)
+       {
+               case 0: /* mmddyy */
+               default:
+                       ConOutPrintf (_T("Current date is: %s %02d%c%02d%c%04d\n"),
+                                         aszDayNames[st.wDayOfWeek], st.wMonth, cDateSeparator, st.wDay, cDateSeparator, st.wYear);
+                       break;
+
+               case 1: /* ddmmyy */
+                       ConOutPrintf (_T("Current date is: %s %02d%c%02d%c%04d\n"),
+                                         aszDayNames[st.wDayOfWeek], st.wDay, cDateSeparator, st.wMonth, cDateSeparator, st.wYear);
+                       break;
+
+               case 2: /* yymmdd */
+                       ConOutPrintf (_T("Current date is: %s %04d%c%02d%c%02d\n"),
+                                         aszDayNames[st.wDayOfWeek], st.wYear, cDateSeparator, st.wMonth, cDateSeparator, st.wDay);
+                       break;
+       }
+#endif
+       TCHAR szDate[32];
+
+       GetDateFormat (LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL,
+                                  szDate, sizeof (szDate));
+       ConOutPrintf (_T("Current date is: %s\n"), szDate);
+}
+
+
+static VOID
+PrintDateString (VOID)
+{
+       switch (nDateFormat)
+       {
+               case 0: /* mmddyy */
+               default:
+                       ConOutPrintf (_T("Enter new date (mm%cdd%cyyyy): "),
+                                       cDateSeparator, cDateSeparator);
+                       break;
+
+               case 1: /* ddmmyy */
+                       ConOutPrintf (_T("Enter new date (dd%cmm%cyyyy): "),
+                                         cDateSeparator, cDateSeparator);
+                       break;
+
+               case 2: /* yymmdd */
+                       ConOutPrintf (_T("Enter new date (yyyy%cmm%cdd): "),
+                                         cDateSeparator, cDateSeparator);
+                       break;
+       }
+}
+
+
+static BOOL
+ReadNumber (LPTSTR *s, LPWORD lpwValue)
+{
+       if (_istdigit (**s))
+       {
+               while (_istdigit (**s))
+               {
+                       *lpwValue = *lpwValue * 10 + **s - _T('0');
+                       (*s)++;
+               }
+               return TRUE;
+       }
+       return FALSE;
+}
+
+
+static BOOL
+ReadSeparator (LPTSTR *s)
+{
+       if (**s == _T('/') || **s == _T('-') || **s == cDateSeparator)
+       {
+               (*s)++;
+               return TRUE;
+       }
+       return FALSE;
+}
+
+
+static BOOL
+ParseDate (LPTSTR s)
+{
+       SYSTEMTIME d;
+       unsigned char leap;
+       LPTSTR p = s;
+
+       if (!*s)
+               return TRUE;
+
+       GetLocalTime (&d);
+
+       d.wYear = 0;
+       d.wDay = 0;
+       d.wMonth = 0;
+
+       switch (nDateFormat)
+       {
+               case 0: /* mmddyy */
+               default:
+                       if (!ReadNumber (&p, &d.wMonth))
+                               return FALSE;
+                       if (!ReadSeparator (&p))
+                               return FALSE;
+                       if (!ReadNumber (&p, &d.wDay))
+                               return FALSE;
+                       if (!ReadSeparator (&p))
+                               return FALSE;
+                       if (!ReadNumber (&p, &d.wYear))
+                               return FALSE;
+                       break;
+
+               case 1: /* ddmmyy */
+                       if (!ReadNumber (&p, &d.wDay))
+                               return FALSE;
+                       if (!ReadSeparator (&p))
+                               return FALSE;
+                       if (!ReadNumber (&p, &d.wMonth))
+                               return FALSE;
+                       if (!ReadSeparator (&p))
+                               return FALSE;
+                       if (!ReadNumber (&p, &d.wYear))
+                               return FALSE;
+                       break;
+
+               case 2: /* yymmdd */
+                       if (!ReadNumber (&p, &d.wYear))
+                               return FALSE;
+                       if (!ReadSeparator (&p))
+                               return FALSE;
+                       if (!ReadNumber (&p, &d.wMonth))
+                               return FALSE;
+                       if (!ReadSeparator (&p))
+                               return FALSE;
+                       if (!ReadNumber (&p, &d.wDay))
+                               return FALSE;
+                       break;
+       }
+
+       /* if only entered two digits:
+       /*   assume 2000's if value less than 80 */
+       /*   assume 1900's if value greater or equal 80 */
+       if (d.wYear <= 99)
+       {
+               if (d.wYear >= 80)
+                       d.wYear = 1900 + d.wYear;
+               else
+                       d.wYear = 2000 + d.wYear;
+       }
+
+       leap = (!(d.wYear % 4) && (d.wYear % 100)) || !(d.wYear % 400);
+
+       if ((d.wMonth >= 1 && d.wMonth <= 12) &&
+               (d.wDay >= 1 && d.wDay <= awMonths[leap][d.wMonth]) &&
+               (d.wYear >= 1980 && d.wYear <= 2099))
+       {
+               SetLocalTime (&d);
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+
+INT cmd_date (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR *arg;
+       INT    argc;
+       INT    i;
+       BOOL   bPrompt = TRUE;
+       INT    nDateString = -1;
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Displays or sets the date.\n\n"
+                                  "DATE [/T][date]\n\n"
+                                  "  /T    display only\n\n"
+                                  "Type DATE without parameters to display the current date setting and\n"
+                                  "a prompt for a new one.  Press ENTER to keep the same date."));
+               return 0;
+       }
+
+       /* build parameter array */
+       arg = split (param, &argc);
+
+       /* check for options */
+       for (i = 0; i < argc; i++)
+       {
+               if (_tcsicmp (arg[i], _T("/t")) == 0)
+                       bPrompt = FALSE;
+               if ((*arg[i] != _T('/')) && (nDateString == -1))
+                       nDateString = i;
+       }
+
+       if (nDateString == -1)
+               PrintDate ();
+
+       if (!bPrompt)
+       {
+               freep (arg);
+               return 0;
+       }
+
+       if (nDateString == -1)
+       {
+               while (TRUE)  /* forever loop */
+               {
+                       TCHAR s[40];
+
+                       PrintDateString ();
+                       ConInString (s, 40);
+#ifdef _DEBUG
+                       DebugPrintf ("\'%s\'\n", s);
+#endif
+                       while (*s && s[_tcslen (s) - 1] < ' ')
+                               s[_tcslen (s) - 1] = '\0';
+                       if (ParseDate (s))
+                       {
+                               freep (arg);
+                               return 0;
+                       }
+                       ConErrPuts ("Invalid date.");
+               }
+       }
+       else
+       {
+               if (ParseDate (arg[nDateString]))
+               {
+                       freep (arg);
+                       return 0;
+               }
+               ConErrPuts ("Invalid date.");
+       }
+
+       freep (arg);
+
+       return 0;
+}
+#endif
+
diff --git a/rosapps/cmd/del.c b/rosapps/cmd/del.c
new file mode 100644 (file)
index 0000000..c249670
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ *  DEL.C - del internal command.
+ *
+ *
+ *  History:
+ *
+ *    06/29/98 (Rob Lake rlake@cs.mun.ca)
+ *        rewrote del to support wildcards
+ *        added my name to the contributors
+ *
+ *    07/13/98 (Rob Lake)
+ *        fixed bug that caused del not to delete file with out
+ *        attribute. moved set, del, ren, and ver to there own files
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    09-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeiung.de>)
+ *        Fixed command line parsing bugs.
+ *
+ *    21-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeiung.de>)
+ *        Started major rewrite using a new structure.
+ *
+ *    03-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeiung.de>)
+ *        First working version.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_DEL
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+
+#define PROMPT_NO              0
+#define PROMPT_YES             1
+#define PROMPT_ALL             2
+#define PROMPT_BREAK   3
+
+
+static BOOL ConfirmDeleteAll (VOID)
+{
+       TCHAR inp[10];
+       LPTSTR p;
+
+       ConOutPrintf ("All files in directory will be deleted!\n"
+                                 "Are you sure (Y/N)? ");
+       ConInString (inp, 10);
+
+       _tcsupr (inp);
+       for (p = inp; _istspace (*p); p++)
+               ;
+
+       if (*p == _T('Y'))
+               return PROMPT_YES;
+       else if (*p == _T('N'))
+               return PROMPT_NO;
+
+#if 0
+       if (*p == _T('A'))
+               return PROMPT_ALL;
+       else if (*p == _T('\03'))
+               return PROMPT_BREAK;
+#endif
+
+       return PROMPT_NO;
+}
+
+
+static INT Prompt (LPTSTR str)
+{
+       TCHAR inp[10];
+       LPTSTR p;
+
+       ConOutPrintf (_T("Delete %s (Yes/No)? "), str);
+       ConInString (inp, 10);
+
+       _tcsupr (inp);
+       for (p = inp; _istspace (*p); p++)
+               ;
+
+       if (*p == _T('Y'))
+               return PROMPT_YES;
+       else if (*p == _T('N'))
+               return PROMPT_NO;
+
+#if 0
+       if (*p == _T('A'))
+               return PROMPT_ALL;
+       else if (*p == _T('\03'))
+               return PROMPT_BREAK;
+#endif
+}
+
+
+
+INT cmd_del (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR *arg = NULL;
+       INT args;
+       INT i;
+       INT  nEvalArgs = 0; /* nunber of evaluated arguments */
+       BOOL bNothing = FALSE;
+       BOOL bQuiet   = FALSE;
+       BOOL bPrompt  = FALSE;
+
+       HANDLE hFile;
+       WIN32_FIND_DATA f;
+//     DWORD dwAttributes;
+
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+/*
+               ConOutPuts (_T("Deletes one or more files.\n\n"
+                       "DEL [drive:][path]filename [/P]\n"
+                       "DELETE [drive:][path]filename [/P]\n"
+                       "ERASE [drive:][path]filename [/P]\n\n"
+                       "  [drive:][path]filename  Specifies the file(s) to delete.  Specify multiple\n"
+                       "                          files by using wildcards.\n"
+                       "  /P        Prompts for confirmation before deleting each file."));
+*/
+
+               ConOutPuts (_T("Deletes one or more files.\n"
+                                          "\n"
+                                          "DEL [/N /P /Q] file ...\n"
+                                          "DELETE [/N /P /Q] file ...\n"
+                                          "ERASE [/N /P /Q] file ...\n"
+                                          "\n"
+                                          "  file  Specifies the file(s) to delete.\n"
+                                          "\n"
+                                          "  /N    Nothing.\n"
+                                          "  /P    Prompts for confirmation before deleting each file.\n"
+                                          "        (Not implemented yet!)\n"
+                                          "  /Q    Quiet."
+                                          ));
+
+               return 0;
+       }
+
+       arg = split (param, &args);
+
+       if (args > 0)
+       {
+               /* check for options anywhere in command line */
+               for (i = 0; i < args; i++)
+               {
+                       if (*arg[i] == _T('/'))
+                       {
+                               if (_tcslen (arg[i]) >= 2)
+                               {
+                                       switch (_totupper (arg[i][1]))
+                                       {
+                                               case _T('N'):
+                                                       bNothing = TRUE;
+                                                       break;
+
+                                               case _T('P'):
+                                                       bPrompt = TRUE;
+                                                       break;
+
+                                               case _T('Q'):
+                                                       bQuiet = TRUE;
+                                                       break;
+                                       }
+
+                               }
+
+                               nEvalArgs++;
+                       }
+               }
+
+               /* there are only options on the command line --> error!!! */
+               if (args == nEvalArgs)
+               {
+                       error_req_param_missing ();
+                       freep (arg);
+                       return 1;
+               }
+
+               /* check for filenames anywhere in command line */
+               for (i = 0; i < args; i++)
+               {
+                       if (!_tcscmp (arg[i], _T("*")) ||
+                               !_tcscmp (arg[i], _T("*.*")))
+                       {
+                               if (!ConfirmDeleteAll ())
+                                       break;
+
+                       }
+
+                       if (*arg[i] != _T('/'))
+                       {
+#ifdef _DEBUG
+                               ConErrPrintf ("File: %s\n", arg[i]);
+#endif
+
+                               if (_tcschr (arg[i], _T('*')) || _tcschr (arg[i], _T('?')))
+                               {
+                                       /* wildcards in filespec */
+#ifdef _DEBUG
+                                       ConErrPrintf ("Wildcards!\n\n");
+#endif
+
+                                       hFile = FindFirstFile (arg[i], &f);
+                                       if (hFile == INVALID_HANDLE_VALUE)
+                                       {
+                                               error_file_not_found ();
+                                               freep (arg);
+                                               return 0;
+                                       }
+
+                                       do
+                                       {
+                                               if (!_tcscmp (f.cFileName, _T(".")) ||
+                                                       !_tcscmp (f.cFileName, _T("..")))
+                                                       continue;
+
+#ifdef _DEBUG
+                                               ConErrPrintf ("Delete file: %s\n", f.cFileName);
+#endif
+
+                                               if (!bNothing)
+                                               {
+                                                       if (!DeleteFile (f.cFileName))
+                                                               ErrorMessage (GetLastError(), _T(""));
+                                               }
+
+
+                                       }
+                                       while (FindNextFile (hFile, &f));
+                                       FindClose (hFile);
+                               }
+                               else
+                               {
+                                       /* no wildcards in filespec */
+#ifdef _DEBUG
+                                       ConErrPrintf ("No Wildcards!\n");
+                                       ConErrPrintf ("Delete file: %s\n", arg[i]);
+#endif
+
+                                       if (!bNothing)
+                                       {
+                                               if (!DeleteFile (arg[i]))
+                                                       ErrorMessage (GetLastError(), _T(""));
+                                       }
+                               }
+                       }
+               }
+       }
+       else
+       {
+               /* only command given */
+               error_req_param_missing ();
+               freep (arg);
+               return 1;
+       }
+
+       freep (arg);
+
+       return 0;
+}
+
+#endif
diff --git a/rosapps/cmd/dir.c b/rosapps/cmd/dir.c
new file mode 100644 (file)
index 0000000..c56d847
--- /dev/null
@@ -0,0 +1,1225 @@
+/*
+ *  DIR.C - dir internal command.
+ *
+ *
+ *  History:
+ *
+ *    01/29/97 (Tim Norman)
+ *        started.
+ *
+ *    06/13/97 (Tim Norman)
+ *      Fixed code.
+ *
+ *    07/12/97 (Tim Norman)
+ *        Fixed bug that caused the root directory to be unlistable
+ *
+ *    07/12/97 (Marc Desrochers)
+ *        Changed to use maxx, maxy instead of findxy()
+ *
+ *    06/08/98 (Rob Lake)
+ *        Added compatibility for /w in dir
+ *
+ *    06/09/98 (Rob Lake)
+ *        Compatibility for dir/s started
+ *        Tested that program finds directories off root fine
+ *
+ *    06/10/98 (Rob Lake)
+ *        do_recurse saves the cwd and also stores it in Root
+ *        build_tree adds the cwd to the beginning of its' entries
+ *        Program runs fine, added print_tree -- works fine.. as EXE,
+ *        program won't work properly as COM.
+ *
+ *    06/11/98 (Rob Lake)
+ *        Found problem that caused COM not to work
+ *
+ *    06/12/98 (Rob Lake)
+ *        debugged...
+ *        added free mem routine
+ *
+ *    06/13/98 (Rob Lake)
+ *        debugged the free mem routine
+ *        debugged whole thing some more
+ *        Notes:
+ *        ReadDir stores Root name and _Read_Dir does the hard work
+ *        PrintDir prints Root and _Print_Dir does the hard work
+ *        KillDir kills Root _after_ _Kill_Dir does the hard work
+ *        Integrated program into DIR.C(this file) and made some same
+ *        changes throughout
+ *
+ *    06/14/98 (Rob Lake)
+ *        Cleaned up code a bit, added comments
+ *
+ *    06/16/98 (Rob Lake)
+ *        Added error checking to my previously added routines
+ *
+ *    06/17/98 (Rob Lake)
+ *        Rewrote recursive functions, again! Most other recursive
+ *        functions are now obsolete -- ReadDir, PrintDir, _Print_Dir,
+ *        KillDir and _Kill_Dir.  do_recurse does what PrintDir did
+ *        and _Read_Dir did what it did before along with what _Print_Dir
+ *        did.  Makes /s a lot faster!
+ *        Reports 2 more files/dirs that MS-DOS actually reports
+ *        when used in root directory(is this because dir defaults
+ *        to look for read only files?)
+ *        Added support for /b, /a and /l
+ *        Made error message similar to DOS error messages
+ *        Added help screen
+ *
+ *    06/20/98 (Rob Lake)
+ *        Added check for /-(switch) to turn off previously defined
+ *        switches.
+ *        Added ability to check for DIRCMD in environment and
+ *        process it
+ *
+ *    06/21/98 (Rob Lake)
+ *        Fixed up /B
+ *        Now can dir *.ext/X, no spaces!
+ *
+ *    06/29/98 (Rob Lake)
+ *        error message now found in command.h
+ *
+ *    07/08/1998 (John P. Price)
+ *        removed extra returns; closer to MSDOS
+ *        fixed wide display so that an extra return is not displayed
+ *        when there is five filenames in the last line.
+ *
+ *    07/12/98 (Rob Lake)
+ *        Changed error messages
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *
+ *    04-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Converted source code to Win32, except recursive dir ("dir /s").
+ *
+ *    10-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Fixed recursive dir ("dir /s").
+ *
+ *    14-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Converted to Win32 directory functions and
+ *        fixed some output bugs. There are still some more ;)
+ *
+ *    10-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added "/N" and "/4" options, "/O" is a dummy.
+ *        Added locale support.
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Redirection safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_DIR
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <direct.h>
+
+#include "cmd.h"
+
+
+/* useful macro */
+#define MEM_ERR error_out_of_memory(); return 1;
+
+
+/* flag definitions */
+/* Changed hex to decimal, hex wouldn't work
+ * if > 8, Rob Lake 06/17/98.
+ */
+enum
+{
+       DIR_RECURSE = 0x0001,
+       DIR_PAGE    = 0x0002,
+       DIR_WIDE    = 0x0004,        /* Rob Lake */
+       DIR_BARE    = 0x0008,        /* Rob Lake */
+       DIR_ALL     = 0x0010,        /* Rob Lake */
+       DIR_LWR     = 0x0020,        /* Rob Lake */
+       DIR_SORT    = 0x0040,        /* /O sort */
+       DIR_NEW     = 0x0080,        /* /N new style */
+       DIR_FOUR    = 0x0100         /* /4 four digit year */
+};
+
+
+/* Globally save the # of dirs, files and bytes,
+ * probabaly later pass them to functions. Rob Lake  */
+long recurse_dir_cnt;
+long recurse_file_cnt;
+ULARGE_INTEGER recurse_bytes;
+
+
+/*
+ * help
+ *
+ * displays help screen for dir
+ * Rob Lake
+ */
+static VOID Help (VOID)
+{
+#if 1
+       ConOutPuts (_T("Displays a list of files and subdirectories in a directory.\n"
+       "\n"
+       "DIR [drive:][path][filename] [/A] [/B] [/L] [/N] [/S] [/P] [/W] [/4]\n"
+       "\n"
+       "  [drive:][path][filename]\n"
+       "              Specifies drive, directory, and/or files to list.\n"
+       "\n"
+       "  /A          Displays files with HIDDEN SYSTEM attributes\n"
+       "              default is ARCHIVE and READ ONLY\n"
+       "  /B          Uses bare format (no heading information or summary).\n"
+       "  /L          Uses lowercase.\n"
+       "  /N          New long list format where filenames are on the far right.\n"
+       "  /S          Displays files in specified directory and all subdirectories\n"
+       "  /P          Pauses after each screen full\n"
+       "  /W          Prints in wide format\n"
+       "  /4          Display four digit years.\n"
+       "\n"
+       "Switches may be present in the DIRCMD environment variable.  Use\n"
+       "of the - (hyphen) can turn off defined swtiches.  Ex. /-W would\n"
+       "turn off printing in wide format.\n"
+      ));
+#endif
+#if 0
+       InitializePageOut ();
+       LinePageOut (_T("Displays a list of files and subdirectories in a directory."));
+       LinePageOut (_T(""));
+       LinePageOut (_T("DIR [drive:][path][filename] [/A] [/B] [/L] [/N] [/S] [/P] [/W] [/4]"));
+       LinePageOut (_T(""));
+       LinePageOut (_T("  [drive:][path][filename]"));
+       LinePageOut (_T("              Specifies drive, directory, and/or files to list."));
+       LinePageOut (_T(""));
+       LinePageOut (_T("  /A          Displays files with HIDDEN SYSTEM attributes"));
+       LinePageOut (_T("              default is ARCHIVE and READ ONLY"));
+       LinePageOut (_T("  /B          Uses bare format (no heading information or summary)."));
+       LinePageOut (_T("  /L          Uses lowercase."));
+       LinePageOut (_T("  /N          New long list format where filenames are on the far right."));
+       LinePageOut (_T("  /S          Displays files in specified directory and all subdirectories"));
+       LinePageOut (_T("  /P          Pauses after each screen full"));
+       LinePageOut (_T("  /W          Prints in wide format"));
+       LinePageOut (_T("  /4          Display four digit years."));
+       LinePageOut (_T(""));
+       LinePageOut (_T("Switches may be present in the DIRCMD environment variable.  Use"));
+       LinePageOut (_T("of the - (hyphen) can turn off defined swtiches.  Ex. /-W would"));
+       LinePageOut (_T("turn off printing in wide format."));
+       TerminatePageOut ();
+#endif
+}
+
+
+/*
+ * dir_read_param
+ *
+ * read the parameters from the command line
+ */
+static BOOL
+DirReadParam (char *line, char **param, LPDWORD lpFlags)
+{
+       int slash = 0;
+
+       if (!line)
+               return TRUE;
+
+       *param = NULL;
+
+       /* scan the command line, processing switches */
+       while (*line)
+       {
+               /* process switch */
+               if (*line == _T('/') || slash)
+               {
+                       if (!slash)
+                               line++;
+                       slash = 0;
+                       if (*line == _T('-'))
+                       {
+                               line++;
+                               if (_totupper (*line) == _T('S'))
+                                       *lpFlags &= ~DIR_RECURSE;
+                               else if (_totupper (*line) == _T('P'))
+                                       *lpFlags &= ~DIR_PAGE;
+                               else if (_totupper (*line) == _T('W'))
+                                       *lpFlags &= ~DIR_WIDE;
+                               else if (_totupper (*line) == _T('B'))
+                                       *lpFlags &= ~DIR_BARE;
+                               else if (_totupper (*line) == _T('A'))
+                                       *lpFlags &= ~DIR_ALL;
+                               else if (_totupper (*line) == _T('L'))
+                                       *lpFlags &= ~DIR_LWR;
+                               else if (_totupper (*line) == _T('N'))
+                                       *lpFlags &= ~DIR_NEW;
+                               else if (_totupper (*line) == _T('O'))
+                                       *lpFlags &= ~DIR_SORT;
+                               else if (_totupper (*line) == _T('4'))
+                                       *lpFlags &= ~DIR_FOUR;
+                               else
+                               {
+                                       error_invalid_switch ((TCHAR)_totupper (*line));
+                                       return FALSE;
+                               }
+                               line++;
+                               continue;
+                       }
+                       else
+                       {
+                               if (_totupper (*line) == _T('S'))
+                                       *lpFlags |= DIR_RECURSE;
+                               else if (_toupper (*line) == _T('P'))
+                                       *lpFlags |= DIR_PAGE;
+                               else if (_totupper (*line) == _T('W'))
+                                       *lpFlags |= DIR_WIDE;
+                               else if (_totupper (*line) == _T('B'))
+                                       *lpFlags |= DIR_BARE;
+                               else if (_totupper (*line) == _T('A'))
+                                       *lpFlags |= DIR_ALL;
+                               else if (_totupper (*line) == _T('L'))
+                                       *lpFlags |= DIR_LWR;
+                               else if (_totupper (*line) == _T('N'))
+                                       *lpFlags |= DIR_NEW;
+                               else if (_totupper (*line) == _T('O'))
+                                       *lpFlags |= DIR_SORT;
+                               else if (_totupper (*line) == _T('4'))
+                                       *lpFlags |= DIR_FOUR;
+                               else if (*line == _T('?'))
+                               {
+                                       Help();
+                                       return FALSE;
+                               }
+                               else
+                               {
+                                       error_invalid_switch ((TCHAR)_totupper (*line));
+                                       return FALSE;
+                               }
+                               line++;
+                               continue;
+                       }
+               }
+
+               /* process parameter */
+               if (!_istspace (*line))
+               {
+                       if (*param)
+                       {
+                               error_too_many_parameters (*param);
+                               return FALSE;
+                       }
+
+                       *param = line;
+
+                       /* skip to end of line or next whitespace or next / */
+                       while (*line && !_istspace (*line) && *line != _T('/'))
+                               line++;
+
+                       /* if end of line, return */
+                       if (!*line)
+                               return TRUE;
+
+                       /* if parameter, remember to process it later */
+                       if (*line == _T('/'))
+                               slash = 1;
+
+                       *line++ = 0;
+                       continue;
+               }
+
+               line++;
+       }
+
+       if (slash)
+       {
+               error_invalid_switch ((TCHAR)_totupper (*line));
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
+/*
+ * extend_file
+ *
+ * extend the filespec, possibly adding wildcards
+ */
+void extend_file (char **file)
+{
+       LPTSTR tmp;
+
+       if (!*file)
+               return;
+
+       /* if no file spec, change to "*.*" */
+       if (!**file)
+       {
+               free (*file);
+               *file = _tcsdup (_T("*.*"));
+               return;
+       }
+
+       /* if starts with . add * in front */
+       if (**file == _T('.'))
+       {
+               tmp = malloc ((_tcslen (*file) + 2) * sizeof(TCHAR));
+               if (tmp)
+               {
+                       *tmp = _T('*');
+                       _tcscpy (&tmp[1], *file);
+               }
+               free (*file);
+               *file = tmp;
+               return;
+       }
+
+       /* if no . add .* */
+       if (!_tcschr (*file, _T('.')))
+       {
+               tmp = malloc ((_tcslen (*file) + 3) * sizeof(TCHAR));
+               if (tmp)
+               {
+                       _tcscpy (tmp, *file);
+                       _tcscat (tmp, _T(".*"));
+               }
+               free (*file);
+               *file = tmp;
+               return;
+       }
+}
+
+
+/*
+ * dir_parse_pathspec
+ *
+ * split the pathspec into drive, directory, and filespec
+ */
+static int
+DirParsePathspec (char *pathspec, int *drive, char **dir, char **file)
+{
+       TCHAR  orig_dir[MAX_PATH];
+       LPTSTR start;
+       LPTSTR tmp;
+       INT    i;
+       INT    wildcards = 0;
+
+
+       /* get the drive and change to it */
+       if (pathspec[1] == _T(':'))
+       {
+               *drive = _totupper (pathspec[0]) - _T('@');
+               start = pathspec + 2;
+               _chdrive (*drive);
+       }
+       else
+       {
+               *drive = _getdrive ();
+               start = pathspec;
+       }
+
+       GetCurrentDirectory (MAX_PATH, orig_dir);
+
+       /* check for wildcards */
+       for (i = 0; pathspec[i]; i++)
+               if (pathspec[i] == _T('*') || pathspec[i] == _T('?'))
+                       wildcards = 1;
+
+       /* check if this spec is a directory */
+       if (!wildcards)
+       {
+               if (chdir(pathspec) == 0)
+               {
+                       *file = _tcsdup (_T("*.*"));
+                       if (!*file)
+                       {
+                               MEM_ERR
+                       }
+
+                       tmp = getcwd (NULL, MAX_PATH);
+                       if (!tmp)
+                       {
+                               free (*file);
+                               chdir (orig_dir);
+                               MEM_ERR
+                       }
+
+                       *dir = _tcsdup (&tmp[2]);
+                       free (tmp);
+                       if (!*dir)
+                       {
+                               free (*file);
+                               chdir (orig_dir);
+                               MEM_ERR
+                       }
+
+                       chdir (orig_dir);
+                       return 0;
+               }
+       }
+
+       /* find the file spec */
+       tmp = _tcsrchr (start, _T('\\'));
+
+       /* if no path is specified */
+       if (!tmp)
+       {
+               *file = _tcsdup (start);
+               extend_file (file);
+               if (!*file)
+               {
+                       MEM_ERR
+               }
+
+               tmp = getcwd (NULL, _MAX_PATH);
+               if (!tmp)
+               {
+                       free (*file);
+                       chdir (orig_dir);
+                       MEM_ERR
+               }
+               *dir = _tcsdup (&tmp[2]);
+               free(tmp);
+               if (!*dir)
+               {
+                       free (*file);
+                       chdir (orig_dir);
+                       MEM_ERR
+               }
+
+               return 0;
+       }
+
+       /* get the filename */
+       *file = _tcsdup (tmp + 1);
+       extend_file (file);
+       if (!*file)
+       {
+               MEM_ERR
+       }
+
+       *tmp = 0;
+
+       /* change to this directory and get its full name */
+       if (chdir (start) < 0)
+       {
+               error_path_not_found ();
+               *tmp = _T('\\');
+               free (*file);
+               chdir (orig_dir);
+               return 1;
+       }
+
+       tmp = getcwd (NULL, _MAX_PATH);
+       if (!tmp)
+       {
+               free (*file);
+               MEM_ERR
+       }
+       *dir = _tcsdup (&tmp[2]);
+       free(tmp);
+       if (!*dir)
+       {
+               free(*file);
+               MEM_ERR
+       }
+
+       *tmp = _T('\\');
+
+       chdir(orig_dir);
+       return 0;
+}
+
+
+/*
+ * pause
+ *
+ * pause until a key is pressed
+ */
+static INT
+Pause (VOID)
+{
+       cmd_pause ("", "");
+
+       return 0;
+}
+
+
+/*
+ * incline
+ *
+ * increment our line if paginating, display message at end of screen
+ */
+static INT
+incline (int *line, DWORD dwFlags)
+{
+       if (!(dwFlags & DIR_PAGE))
+               return 0;
+
+       (*line)++;
+
+       if (*line >= (int)maxy - 2)
+       {
+               *line = 0;
+               return Pause ();
+       }
+
+       return 0;
+}
+
+
+/*
+ * PrintDirectoryHeader
+ *
+ * print the header for the dir command
+ */
+static BOOL
+PrintDirectoryHeader (int drive, int *line, DWORD dwFlags)
+{
+       TCHAR szRootName[] = _T("A:\\");
+       TCHAR szVolName[80];
+       DWORD dwSerialNr;
+
+       if (dwFlags & DIR_BARE)
+               return TRUE;
+
+       /* get the media ID of the drive */
+       szRootName[0] = drive + _T('@');
+       if (!GetVolumeInformation (szRootName, szVolName, 80, &dwSerialNr,
+                                                          NULL, NULL, NULL, 0))
+       {
+               error_invalid_drive();
+               return FALSE;
+       }
+
+       /* print drive info */
+       ConOutPrintf (_T(" Volume in drive %c"), szRootName[0]);
+
+       if (szVolName[0] != _T('\0'))
+               ConOutPrintf (_T(" is %s\n"), szVolName);
+       else
+               ConOutPrintf (_T(" has no label\n"));
+
+       if (incline (line, dwFlags) != 0)
+               return FALSE;
+
+       /* print the volume serial number if the return was successful */
+       ConOutPrintf (_T(" Volume Serial Number is %04X-%04X\n"),
+                                 HIWORD(dwSerialNr), LOWORD(dwSerialNr));
+       if (incline (line, dwFlags) != 0)
+               return FALSE;
+
+       return TRUE;
+}
+
+
+/*
+ * convert
+ *
+ * insert commas into a number
+ */
+static INT
+ConvertLong (LONG num, LPTSTR des, INT len)
+{
+       TCHAR temp[32];
+       INT c = 0;
+       INT n = 0;
+
+       if (num == 0)
+       {
+               des[0] = _T('0');
+               des[1] = _T('\0');
+               n = 1;
+       }
+       else
+       {
+               temp[31] = 0;
+               while (num > 0)
+               {
+                       if (((c + 1) % (nNumberGroups + 1)) == 0)
+                               temp[30 - c++] = cThousandSeparator;
+                       temp[30 - c++] = (TCHAR)(num % 10) + _T('0');
+                       num /= 10;
+               }
+
+               for (n = 0; n <= c; n++)
+                       des[n] = temp[31 - c + n];
+       }
+
+       return n;
+}
+
+
+static INT
+ConvertULargeInteger (ULARGE_INTEGER num, LPTSTR des, INT len)
+{
+       TCHAR temp[32];
+       INT c = 0;
+       INT n = 0;
+
+       if (num.QuadPart == 0)
+       {
+               des[0] = _T('0');
+               des[1] = _T('\0');
+               n = 1;
+       }
+       else
+       {
+               temp[31] = 0;
+               while (num.QuadPart > 0)
+               {
+                       if (((c + 1) % (nNumberGroups + 1)) == 0)
+                               temp[30 - c++] = cThousandSeparator;
+                       temp[30 - c++] = (TCHAR)(num.QuadPart % 10) + _T('0');
+                       num.QuadPart /= 10;
+               }
+
+               for (n = 0; n <= c; n++)
+                       des[n] = temp[31 - c + n];
+       }
+
+       return n;
+}
+
+
+static VOID
+PrintFileDateTime (LPSYSTEMTIME dt, DWORD dwFlags)
+{
+       WORD wYear = (dwFlags & DIR_FOUR) ? dt->wYear : dt->wYear%100;
+
+       switch (nDateFormat)
+       {
+               case 0: /* mmddyy */
+               default:
+                       ConOutPrintf ("%.2d%c%.2d%c%d", dt->wMonth, cDateSeparator, dt->wDay, cDateSeparator, wYear);
+                       break;
+
+               case 1: /* ddmmyy */
+                       ConOutPrintf ("%.2d%c%.2d%c%d",
+                                       dt->wDay, cDateSeparator, dt->wMonth, cDateSeparator, wYear);
+                       break;
+
+               case 2: /* yymmdd */
+                       ConOutPrintf ("%d%c%.2d%c%.2d",
+                                       wYear, cDateSeparator, dt->wMonth, cDateSeparator, dt->wDay);
+                       break;
+       }
+
+       switch (nTimeFormat)
+       {
+               case 0: /* 12 hour format */
+               default:
+                       ConOutPrintf ("  %2d%c%.2u%c",
+                                       (dt->wHour == 0 ? 12 : (dt->wHour <= 12 ? dt->wHour : dt->wHour - 12)),
+                                       cTimeSeparator,
+                                        dt->wMinute, (dt->wHour <= 11 ? 'a' : 'p'));
+                       break;
+
+               case 1: /* 24 hour format */
+                       ConOutPrintf ("  %2d%c%.2u",
+                                       dt->wHour, cTimeSeparator, dt->wMinute);
+                       break;
+       }
+}
+
+
+/*
+ * print_summary: prints dir summary
+ * Added by Rob Lake 06/17/98 to compact code
+ * Just copied Tim's Code and patched it a bit
+ *
+ */
+static INT
+PrintSummary (int drive, long files, long dirs, ULARGE_INTEGER bytes,
+              DWORD flags, int *line)
+{
+       TCHAR buffer[64];
+
+       if (flags & DIR_BARE)
+               return 0;
+
+       /* print number of files and bytes */
+       ConvertLong (files, buffer, sizeof(buffer));
+       ConOutPrintf (_T("          %6s File%c"),
+                                 buffer, files == 1 ? _T(' ') : _T('s'));
+
+       ConvertULargeInteger (bytes, buffer, sizeof(buffer));
+       ConOutPrintf (_T("  %15s byte%c\n"),
+                                 buffer, bytes.QuadPart == 1 ? _T(' ') : _T('s'));
+
+       if (incline (line, flags) != 0)
+               return 1;
+
+       /* print number of dirs and bytes free */
+       ConvertLong (dirs, buffer, sizeof(buffer));
+       ConOutPrintf (_T("          %6s Dir%c"),
+                                 buffer, files == 1 ? _T(' ') : _T('s'));
+
+
+       if (!(flags & DIR_RECURSE))
+       {
+               ULARGE_INTEGER uliFree;
+               TCHAR szRoot[] = _T("A:\\");
+               DWORD dwSecPerCl;
+               DWORD dwBytPerSec;
+               DWORD dwFreeCl;
+               DWORD dwTotCl;
+
+               szRoot[0] = drive + _T('@');
+               GetDiskFreeSpace (szRoot, &dwSecPerCl, &dwBytPerSec, &dwFreeCl, &dwTotCl);
+               uliFree.QuadPart = dwSecPerCl * dwBytPerSec * dwFreeCl;
+               ConvertULargeInteger (uliFree, buffer, sizeof(buffer));
+               ConOutPrintf (_T("   %15s bytes free\n"), buffer);
+       }
+
+       if (incline (line, flags) != 0)
+               return 1;
+
+       return 0;
+}
+
+
+/*
+ * dir_list
+ *
+ * list the files in the directory
+ */
+static int
+dir_list (int drive, char *directory, char *filespec, int *line,
+          DWORD flags)
+{
+  char pathspec[_MAX_PATH],
+   *ext,
+    buffer[32];
+  WIN32_FIND_DATA file;
+  ULARGE_INTEGER bytecount;
+  long filecount = 0,
+    dircount = 0;
+  int count;
+  FILETIME   ft;
+  SYSTEMTIME dt;
+  HANDLE hFile;
+
+  bytecount.QuadPart = 0;
+
+       if (directory[strlen(directory) - 1] == '\\')
+               wsprintf(pathspec, "%c:%s%s", drive + '@', directory, filespec);
+       else
+               wsprintf(pathspec, "%c:%s\\%s", drive + '@', directory, filespec);
+
+       hFile = FindFirstFile (pathspec, &file);
+       if (hFile == INVALID_HANDLE_VALUE)
+       {
+               /* Don't want to print anything if scanning recursively
+                * for a file. RL
+                */
+               if ((flags & DIR_RECURSE) == 0)
+               {
+                       error_file_not_found();
+                       incline(line, flags);
+                       FindClose (hFile);
+                       return 1;
+               }
+               FindClose (hFile);
+               return 0;
+       }
+
+  /* moved down here because if we are recursively searching and
+   * don't find any files, we don't want just to print
+   * Directory of C:\SOMEDIR
+   * with nothing else
+   * Rob Lake 06/13/98
+   */
+  if ((flags & DIR_BARE) == 0)
+  {
+    ConOutPrintf (" Directory of %c:%s\n", drive + '@', directory);
+    if (incline(line, flags) != 0)
+      return 1;
+    ConOutPrintf ("\n");
+    if (incline(line, flags) != 0)
+      return 1;
+  }
+
+  /* For counting columns of output */
+  count = 0;
+
+  do
+  {
+       /* next file, if user doesn't want all files */
+       if (!(flags & DIR_ALL) &&
+               ((file.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ||
+                (file.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)))
+               continue;
+
+       /* begin Rob Lake */
+       if (flags & DIR_LWR)
+       {
+               strlwr(file.cAlternateFileName);
+       }
+
+    if (flags & DIR_WIDE && (flags & DIR_BARE) == 0)
+    {
+      if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+      {
+               if (file.cAlternateFileName[0] == '\0')
+          wsprintf (buffer, _T("[%s]"), file.cFileName);
+               else
+          wsprintf (buffer, _T("[%s]"), file.cAlternateFileName);
+        dircount++;
+      }
+      else
+      {
+               if (file.cAlternateFileName[0] == '\0')
+          wsprintf (buffer, _T("%s"), file.cFileName);
+               else
+          wsprintf (buffer, _T("%s"), file.cAlternateFileName);
+        filecount++;
+      }
+      ConOutPrintf (_T("%-15s"), buffer);
+      count++;
+      if (count == 5)
+      {
+        /* output 5 columns */
+        ConOutPrintf ("\n");
+        if (incline(line, flags) != 0)
+          return 1;
+        count = 0;
+      }
+
+         /* FIXME: this is buggy - now overflow check */
+      bytecount.LowPart += file.nFileSizeLow;
+      bytecount.HighPart += file.nFileSizeHigh;
+
+      /* next block 06/17/98 */
+    }
+    else if (flags & DIR_BARE)
+    {
+      if (strcmp(file.cFileName, ".") == 0 ||
+                 strcmp(file.cFileName, "..") == 0)
+        continue;
+
+      if (flags & DIR_RECURSE)
+      {
+        TCHAR dir[MAX_PATH];
+        wsprintf (dir, _T("%c:%s\\"), drive + _T('@'), directory);
+        if (flags & DIR_LWR)
+          strlwr(dir);
+        ConOutPrintf (dir);
+      }
+      ConOutPrintf (_T("%-13s\n"), file.cFileName);
+      if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+        dircount++;
+      else
+        filecount++;
+      if (incline(line, flags) != 0)
+        return 1;
+
+      /* FIXME: this is buggy - no overflow check */
+      bytecount.LowPart += file.nFileSizeLow;
+      bytecount.HighPart += file.nFileSizeHigh;
+    }
+    else
+    {
+    /* end Rob Lake */
+         if (flags & DIR_NEW)
+         {
+               /* print file date and time */
+               if (FileTimeToLocalFileTime (&file.ftLastWriteTime, &ft))
+               {
+                 FileTimeToSystemTime (&ft, &dt);
+                 PrintFileDateTime (&dt, flags);
+               }
+
+               /* print file size */
+               if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+               {
+                 ConOutPrintf ("         <DIR>         ");
+                 dircount++;
+               }
+               else
+               {
+                       ULARGE_INTEGER uliSize;
+
+                       uliSize.LowPart = file.nFileSizeLow;
+                       uliSize.HighPart = file.nFileSizeHigh;
+
+                       ConvertULargeInteger (uliSize, buffer, sizeof(buffer));
+                       ConOutPrintf (_T("   %20s"), buffer);
+
+                       bytecount.QuadPart += uliSize.QuadPart;
+                       filecount++;
+               }
+
+               /* print long filename */
+               ConOutPrintf (" %s\n", file.cFileName);
+         }
+         else
+         {
+        if (file.cFileName[0] == '.')
+          ConOutPrintf ("%-13s ", file.cFileName);
+           else if (file.cAlternateFileName[0] == '\0')
+               {
+          char szShortName[13];
+                 strncpy (szShortName, file.cFileName, 13);
+                 ext = strchr(szShortName, '.');
+          if (!ext)
+            ext = "";
+          else
+            *ext++ = 0;
+          ConOutPrintf ("%-8s %-3s  ", szShortName, ext);
+               }
+        else
+               {
+                 ext = strchr(file.cAlternateFileName, '.');
+          if (!ext)
+            ext = "";
+          else
+            *ext++ = 0;
+          ConOutPrintf ("%-8s %-3s  ", file.cAlternateFileName, ext);
+               }
+
+               /* print file size */
+        if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+               {
+          ConOutPrintf ("%-14s", "<DIR>");
+          dircount++;
+               }
+               else
+               {
+                       ULARGE_INTEGER uliSize;
+
+                       uliSize.LowPart = file.nFileSizeLow;
+                       uliSize.HighPart = file.nFileSizeHigh;
+
+                       ConvertULargeInteger (uliSize, buffer, sizeof(buffer));
+                       ConOutPrintf (_T("   %10s "), buffer);
+
+                       bytecount.QuadPart += uliSize.QuadPart;
+                       filecount++;
+               }
+
+               /* print file date and time */
+               if (FileTimeToLocalFileTime (&file.ftLastWriteTime, &ft))
+               {
+                 FileTimeToSystemTime (&ft, &dt);
+                 PrintFileDateTime (&dt, flags);
+               }
+
+               /* print long filename */
+               ConOutPrintf (" %s\n", file.cFileName);
+         }
+
+      if (incline(line, flags) != 0)
+        return 1;
+    }
+  }
+  while (FindNextFile (hFile, &file));
+
+  FindClose (hFile);
+
+       /* Rob Lake, need to make clean output */
+       /* JPP 07/08/1998 added check for count != 0 */
+       if ((flags & DIR_WIDE) && (count != 0))
+       {
+               ConOutPrintf ("\n");
+               if (incline(line, flags) != 0)
+                       return 1;
+       }
+
+       if (filecount || dircount)
+       {
+               recurse_dir_cnt += dircount;
+               recurse_file_cnt += filecount;
+               recurse_bytes.QuadPart += bytecount.QuadPart;
+
+               /* The code that was here is now in print_summary */
+               if (PrintSummary (drive, filecount, dircount,
+                                                 bytecount, flags, line) != 0)
+                       return 1;
+       }
+       else
+       {
+               error_file_not_found ();
+               return 1;
+       }
+
+       return 0;
+}
+
+
+/*
+ * _Read_Dir: Actual function that does recursive listing
+ */
+static int
+Read_Dir (int drive, char *parent, char *filespec, int *lines,
+          DWORD flags)
+{
+  char fullpath[_MAX_PATH];
+  WIN32_FIND_DATA file;
+  HANDLE hFile;
+
+  strcpy (fullpath, parent);
+  strcat (fullpath, "\\");
+  strcat (fullpath, filespec);
+
+  hFile = FindFirstFile (fullpath, &file);
+  if (hFile == INVALID_HANDLE_VALUE)
+    return 1;
+
+  do
+  {
+       /* don't list "." and ".." */
+    if (strcmp (file.cFileName, ".") == 0 ||
+        strcmp (file.cFileName, "..") == 0)
+      continue;
+
+       if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+    {
+      if (dir_list(drive, file.cFileName, filespec, lines, flags) != 0)
+      {
+        FindClose (hFile);
+        return 1;
+      }
+      if ((flags & DIR_BARE) == 0)
+      {
+        ConOutPrintf ("\n");
+        if (incline(lines, flags) != 0)
+          return 1;
+      }
+      if (Read_Dir(drive, file.cFileName, filespec, lines, flags) == 1)
+      {
+        FindClose (hFile);
+        return 1;
+      }
+    }
+  }
+  while (FindNextFile (hFile, &file));
+
+  if (!FindClose (hFile))
+    return 1;
+
+  return 0;
+}
+
+
+/*
+ * do_recurse: Sets up for recursive directory listing
+ */
+static int
+do_recurse(int drive, char *directory, char *filespec,
+           int *line, DWORD flags)
+{
+  char cur_dir[_MAX_DIR];
+
+  recurse_dir_cnt = recurse_file_cnt = 0L;
+  recurse_bytes.QuadPart = 0;
+
+  _chdrive (drive);
+  getcwd(cur_dir, sizeof(cur_dir));
+
+  if (chdir(directory) == -1)
+    return 1;
+
+       if (!PrintDirectoryHeader (drive, line, flags))
+               return 1;
+
+  if (dir_list(drive, directory, filespec, line, flags) != 0)
+    return 1;
+  if ((flags & DIR_BARE) == 0)
+  {
+    ConOutPrintf ("\n");
+    if (incline(line, flags) != 0)
+      return 1;
+  }
+  if (Read_Dir(drive, directory, filespec, line, flags) != 0)
+    return 1;
+  if ((flags & DIR_BARE) == 0)
+    ConOutPrintf ("Total files listed:\n");
+  flags &= ~DIR_RECURSE;
+
+       if (PrintSummary (drive, recurse_file_cnt,
+                                         recurse_dir_cnt, recurse_bytes, flags, line) != 0)
+               return 1;
+
+       if ((flags & DIR_BARE) == 0)
+       {
+               ConOutPrintf ("\n");
+               if (incline(line, flags) != 0)
+                       return 1;
+       }
+       chdir(cur_dir);
+       return 0;
+}
+
+
+/*
+ * dir
+ *
+ * internal dir command
+ */
+INT cmd_dir (LPTSTR first, LPTSTR rest)
+{
+       DWORD dwFlags = DIR_NEW | DIR_FOUR;
+  char *param;
+       TCHAR dircmd[256];
+  int line = 0;
+  int drive,
+    orig_drive;
+  char *directory,
+   *filespec,
+    orig_dir[_MAX_DIR];
+
+
+       /* read the parameters from the DIRCMD environment variable */
+       if (GetEnvironmentVariable (_T("DIRCMD"), dircmd, 256))
+       {
+               if (!DirReadParam (dircmd, &param, &dwFlags))
+                       return 1;
+       }
+
+       /* read the parameters */
+       if (!DirReadParam (rest, &param, &dwFlags))
+               return 1;
+
+       /* default to current directory */
+       if (!param)
+               param = ".";
+
+       if (strchr(param, '/'))
+               param = strtok (param, "/");
+
+       /* save the current directory info */
+       orig_drive = _getdrive ();
+       getcwd(orig_dir, sizeof(orig_dir));
+
+       /* parse the directory info */
+       if (DirParsePathspec (param, &drive, &directory, &filespec) != 0)
+       {
+               _chdrive (orig_drive);
+               chdir(orig_dir);
+               return 1;
+       }
+
+       if (dwFlags & DIR_RECURSE)
+       {
+               incline(&line, dwFlags);
+               if (do_recurse (drive, directory, filespec, &line, dwFlags) != 0)
+                       return 1;
+               _chdrive (orig_drive);
+               chdir (orig_dir);
+               return 0;
+       }
+
+       /* print the header */
+       if (!PrintDirectoryHeader (drive, &line, dwFlags))
+               return 1;
+
+       chdir (orig_dir);
+       _chdrive (orig_drive);
+
+       if (dir_list (drive, directory, filespec, &line, dwFlags) != 0)
+               return 1;
+
+       return 0;
+}
+
+#endif
diff --git a/rosapps/cmd/dirstack.c b/rosapps/cmd/dirstack.c
new file mode 100644 (file)
index 0000000..5c00c21
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ *  DIRSTACK.C - pushd / pop (directory stack) internal commands.
+ *
+ *
+ *  History:
+ *
+ *    14-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Implemented PUSHD and POPD command.
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef FEATURE_DIRECTORY_STACK
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+
+typedef struct tagDIRENTRY
+{
+       struct tagDIRENTRY *next;
+       LPTSTR pszPath;
+} DIRENTRY, *LPDIRENTRY;
+
+
+static INT nStackDepth;
+static LPDIRENTRY lpStackTop;
+
+
+static INT
+PushDirectory (LPTSTR pszPath)
+{
+       LPDIRENTRY lpDir;
+
+       lpDir = (LPDIRENTRY)malloc (sizeof (DIRENTRY));
+       if (!lpDir)
+       {
+               error_out_of_memory ();
+               return -1;
+       }
+
+       lpDir->next = (lpStackTop) ? lpStackTop : NULL;
+       lpStackTop = lpDir;
+
+       lpDir->pszPath = (LPTSTR)malloc ((_tcslen(pszPath)+1)*sizeof(TCHAR));
+       if (!lpDir->pszPath)
+       {
+               free (lpDir);
+               error_out_of_memory ();
+               return -1;
+       }
+
+       _tcscpy (lpDir->pszPath, pszPath);
+
+       nStackDepth++;
+
+       return 0;
+}
+
+
+static VOID
+PopDirectory (VOID)
+{
+       LPDIRENTRY lpDir;
+
+       if (nStackDepth == 0)
+               return;
+
+       lpDir = lpStackTop;
+       lpStackTop = lpDir->next;
+       free (lpDir->pszPath);
+       free (lpDir);
+
+       nStackDepth--;
+}
+
+
+static VOID
+GetDirectoryStackTop (LPTSTR pszPath)
+{
+       if (lpStackTop)
+               _tcsncpy (pszPath, lpStackTop->pszPath, MAX_PATH);
+       else
+               *pszPath = _T('\0');
+}
+
+
+/*
+ * initialize directory stack
+ */
+VOID InitDirectoryStack (VOID)
+{
+       nStackDepth = 0;
+       lpStackTop = NULL;
+}
+
+
+/*
+ * destroy directory stack
+ */
+VOID DestroyDirectoryStack (VOID)
+{
+       while (nStackDepth)
+               PopDirectory ();
+}
+
+
+INT GetDirectoryStackDepth (VOID)
+{
+       return nStackDepth;
+}
+
+
+/*
+ * pushd command
+ */
+INT cmd_pushd (LPTSTR first, LPTSTR rest)
+{
+       TCHAR curPath[MAX_PATH];
+       TCHAR newPath[MAX_PATH];
+       BOOL  bChangePath = FALSE;
+
+       if (!_tcsncmp (rest, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Stores the current directory for use by the POPD command, then\n"
+                         "changes to the specified directory.\n\n"
+                         "PUSHD [path | ..]\n\n"
+                         "  path        Specifies the directory to make the current directory"));
+               return 0;
+       }
+
+       if (rest[0] != _T('\0'))
+       {
+               GetFullPathName (rest, MAX_PATH, newPath, NULL);
+               bChangePath = IsValidPathName (newPath);
+       }
+
+       GetCurrentDirectory (MAX_PATH, curPath);
+       if (PushDirectory (curPath))
+               return -1;
+
+       if (bChangePath)
+               SetCurrentDirectory (newPath);
+
+       return 0;
+}
+
+
+/*
+ * popd command
+ */
+INT cmd_popd (LPTSTR first, LPTSTR rest)
+{
+       TCHAR szPath[MAX_PATH];
+
+       if (!_tcsncmp(rest, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Changes to the directory stored by the PUSHD command.\n\n"
+                                          "POPD"));
+               return 0;
+       }
+
+       if (GetDirectoryStackDepth () == 0)
+               return 0;
+
+       GetDirectoryStackTop (szPath);
+       PopDirectory ();
+
+       SetCurrentDirectory (szPath);
+
+       return 0;
+}
+
+#endif /* FEATURE_DIRECTORY_STACK */
\ No newline at end of file
diff --git a/rosapps/cmd/echo.c b/rosapps/cmd/echo.c
new file mode 100644 (file)
index 0000000..9d85c5f
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ *  ECHO.C - echo internal 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
+ *
+ *    08-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("/?").
+ *
+ *    19-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+INT cmd_echo (LPTSTR cmd, LPTSTR param)
+{
+#ifdef _DEBUG
+       DebugPrintf ("cmd_echo '%s' : '%s'\n", cmd, param);
+#endif
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts ("Displays messages or switches command echoing on or off.\n\n"
+                                  "ECHO [ON | OFF]\nECHO [message]\n\n"
+                                  "Type ECHO without a parameter to display the current ECHO setting.");
+               return 0;
+       }
+
+       if (_tcsicmp (param, D_OFF) == 0)
+               bEcho = FALSE;
+       else if (_tcsicmp (param, D_ON) == 0)
+               bEcho = TRUE;
+       else if (*param)
+               ConOutPuts (param);
+       else
+               ConOutPrintf (_T("ECHO is %s\n"), bEcho ? D_ON : D_OFF);
+
+       return 0;
+}
diff --git a/rosapps/cmd/error.c b/rosapps/cmd/error.c
new file mode 100644 (file)
index 0000000..d89fe31
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ *  ERROR.C - error reporting functions.
+ *
+ *
+ *  History:
+ *
+ *    07/12/98 (Rob Lake)
+ *        started
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    24-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Redirection safe!
+ *
+ *    02-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Use FormatMessage() for error reports.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <stdarg.h>
+
+#include "cmd.h"
+
+
+#define INVALID_SWITCH                 _T("Invalid switch - /%c\n")
+#define TOO_MANY_PARAMETERS            _T("Too many parameters - %s\n")
+#define PATH_NOT_FOUND                 _T("Path not found\n")
+#define FILE_NOT_FOUND                 _T("File not found")
+#define REQ_PARAM_MISSING              _T("Required parameter missing\n")
+#define INVALID_DRIVE                  _T("Invalid drive specification\n")
+#define INVALID_PARAM_FORMAT   _T("Invalid parameter format - %s\n")
+#define BADCOMMAND                             _T("Bad command or filename\n")
+#define OUT_OF_MEMORY                  _T("Out of memory error.\n")
+#define CANNOTPIPE                             _T("Error!  Cannot pipe!  Cannot open temporary file!\n")
+
+#define D_PAUSEMSG                             _T("Press any key to continue . . .")
+
+
+
+VOID ErrorMessage (DWORD dwErrorCode, LPTSTR szFormat, ...)
+{
+       TCHAR  szMessage[1024];
+       LPTSTR szError;
+       va_list arg_ptr;
+
+       if (dwErrorCode == ERROR_SUCCESS)
+               return;
+
+       va_start (arg_ptr, szFormat);
+       wvsprintf (szMessage, szFormat, arg_ptr);
+       va_end (arg_ptr);
+
+#if 1
+
+       if (FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+                                          NULL, dwErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                                          (LPTSTR)&szError, 0, NULL))
+       {
+               ConErrPrintf (_T("%s %s\n"), szError, szMessage);
+               LocalFree (szError);
+               return;
+       }
+       else
+       {
+               ConErrPrintf (_T("Unknown error! Error code: 0x%lx\n"), dwErrorCode);
+//             ConErrPrintf (_T("No error message available!\n"));
+               return;
+       }
+
+#else
+
+       switch (dwErrorCode)
+       {
+               case ERROR_FILE_NOT_FOUND:
+                       szError = _T("File not found --");
+                       break;
+
+               case ERROR_PATH_NOT_FOUND:
+                       szError = _T("Path not found --");
+                       break;
+
+               default:
+                       ConErrPrintf (_T("Unknown error! Error code: 0x%lx\n"), dwErrorCode);
+                       return;
+       }
+
+       ConErrPrintf (_T("%s %s\n"), szError, szMessage);
+#endif
+}
+
+
+
+VOID error_invalid_switch (TCHAR ch)
+{
+       ConErrPrintf (INVALID_SWITCH, ch);
+}
+
+
+VOID error_too_many_parameters (LPTSTR s)
+{
+       ConErrPrintf (TOO_MANY_PARAMETERS, s);
+}
+
+
+VOID error_path_not_found (VOID)
+{
+       ConErrPrintf (PATH_NOT_FOUND);
+}
+
+
+VOID error_file_not_found (VOID)
+{
+       ConErrPrintf (FILE_NOT_FOUND);
+}
+
+
+VOID error_sfile_not_found (LPTSTR f)
+{
+       ConErrPrintf (FILE_NOT_FOUND _T(" - %s\n"), f);
+}
+
+
+VOID error_req_param_missing (VOID)
+{
+       ConErrPrintf (REQ_PARAM_MISSING);
+}
+
+
+VOID error_invalid_drive (VOID)
+{
+       ConErrPrintf (INVALID_DRIVE);
+}
+
+
+VOID error_bad_command (VOID)
+{
+       ConErrPrintf (BADCOMMAND);
+}
+
+
+VOID error_no_pipe (VOID)
+{
+       ConErrPrintf (CANNOTPIPE);
+}
+
+
+VOID error_out_of_memory (VOID)
+{
+       ConErrPrintf (OUT_OF_MEMORY);
+}
+
+
+VOID error_invalid_parameter_format (LPTSTR s)
+{
+       ConErrPrintf (INVALID_PARAM_FORMAT, s);
+}
+
+
+VOID error_syntax (LPTSTR s)
+{
+       if (s)
+               ConErrPrintf (_T("Syntax error - %s\n"), s);
+       else
+               ConErrPrintf (_T("Syntax error.\n"));
+}
+
+
+VOID msg_pause (VOID)
+{
+       ConOutPuts (D_PAUSEMSG);
+}
diff --git a/rosapps/cmd/filecomp.c b/rosapps/cmd/filecomp.c
new file mode 100644 (file)
index 0000000..2f9d538
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ *  FILECOMP.C - handles filename completion.
+ *
+ *
+ *  Comments:
+ *
+ *    30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *       moved from command.c file
+ *       made second TAB display list of filename matches
+ *       made filename be lower case if last character typed is lower case
+ *
+ *    25-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *       Cleanup. Unicode safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+
+#ifdef FEATURE_UNIX_FILENAME_COMPLETION
+
+VOID CompleteFilename (LPTSTR str, INT charcount)
+{
+       WIN32_FIND_DATA file;
+       HANDLE hFile;
+
+       INT   curplace = 0;
+       INT   start;
+       INT   count;
+       BOOL  found_dot = FALSE;
+       BOOL  perfectmatch = TRUE;
+       TCHAR path[MAX_PATH];
+       TCHAR fname[MAX_PATH];
+       TCHAR maxmatch[MAX_PATH] = _T("");
+       TCHAR directory[MAX_PATH];
+
+       /* expand current file name */
+       count = charcount - 1;
+       if (count < 0)
+               count = 0;
+
+       /* find front of word */
+       while (count > 0 && str[count] != _T(' '))
+               count--;
+
+       /* if not at beginning, go forward 1 */
+       if (str[count] == _T(' '))
+               count++;
+
+       start = count;
+
+       /* extract directory from word */
+       _tcscpy (directory, &str[start]);
+       curplace = _tcslen (directory) - 1;
+       while (curplace >= 0 && directory[curplace] != _T('\\') &&
+                  directory[curplace] != _T(':'))
+       {
+               directory[curplace] = 0;
+               curplace--;
+       }
+
+       _tcscpy (path, &str[start]);
+
+       /* look for a '.' in the filename */
+       for (count = _tcslen (directory); path[count] != 0; count++)
+       {
+               if (path[count] == _T('.'))
+               {
+                       found_dot = 1;
+                       break;
+               }
+       }
+
+       if (found_dot)
+               _tcscat (path, _T("*"));
+       else
+               _tcscat (path, _T("*.*"));
+
+       /* current fname */
+       curplace = 0;
+
+       hFile = FindFirstFile (path, &file);
+       if (hFile != INVALID_HANDLE_VALUE)
+       {
+               /* find anything */
+               do
+               {
+                       /* ignore "." and ".." */
+                       if (file.cFileName[0] == _T('.'))
+                               continue;
+
+                       _tcscpy (fname, file.cFileName);
+
+                       if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+                               _tcscat (fname, _T("\\"));
+                       else
+                               _tcscat (fname, _T(" "));
+
+                       if (!maxmatch[0] && perfectmatch)
+                       {
+                               _tcscpy(maxmatch, fname);
+                       }
+                       else
+                       {
+                               for (count = 0; maxmatch[count] && fname[count]; count++)
+                               {
+                                       if (tolower(maxmatch[count]) != tolower(fname[count]))
+                                       {
+                                               perfectmatch = FALSE;
+                                               maxmatch[count] = 0;
+                                               break;
+                                       }
+                               }
+                       }
+               }
+               while (FindNextFile (hFile, &file));
+
+               FindClose (hFile);
+
+               _tcscpy (&str[start], directory);
+               _tcscat (&str[start], maxmatch);
+
+               if (!perfectmatch)
+                       MessageBeep (-1);
+       }
+       else
+       {
+               /* no match found */
+               MessageBeep (-1);
+       }
+}
+
+
+/*
+ * returns 1 if at least one match, else returns 0
+ */
+
+BOOL ShowCompletionMatches (LPTSTR str, INT charcount)
+{
+       WIN32_FIND_DATA file;
+       HANDLE hFile;
+       BOOL  found_dot = FALSE;
+       INT   curplace = 0;
+       INT   start;
+       INT   count;
+       TCHAR path[MAX_PATH];
+       TCHAR fname[MAX_PATH];
+       TCHAR directory[MAX_PATH];
+
+       /* expand current file name */
+       count = charcount - 1;
+       if (count < 0)
+               count = 0;
+
+       /* find front of word */
+       while (count > 0 && str[count] != _T(' '))
+               count--;
+
+       /* if not at beginning, go forward 1 */
+       if (str[count] == _T(' '))
+               count++;
+
+       start = count;
+
+       /* extract directory from word */
+       _tcscpy (directory, &str[start]);
+       curplace = _tcslen (directory) - 1;
+       while (curplace >= 0 && directory[curplace] != _T('\\') &&
+                  directory[curplace] != _T(':'))
+       {
+               directory[curplace] = 0;
+               curplace--;
+       }
+
+       _tcscpy (path, &str[start]);
+
+       /* look for a . in the filename */
+       for (count = _tcslen (directory); path[count] != 0; count++)
+       {
+               if (path[count] == _T('.'))
+               {
+                       found_dot = TRUE;
+                       break;
+               }
+       }
+       if (found_dot)
+               _tcscat (path, _T("*"));
+       else
+               _tcscat (path, _T("*.*"));
+
+       /* current fname */
+       curplace = 0;
+
+       hFile = FindFirstFile (path, &file);
+       if (hFile != INVALID_HANDLE_VALUE)
+       {
+               /* find anything */
+               ConOutChar (_T('\n'));
+               count = 0;
+               do
+               {
+                       /* ignore . and .. */
+                       if (file.cFileName[0] == _T('.'))
+                               continue;
+
+                       if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+                               wsprintf (fname,"[%s]", file.cFileName);
+                       else
+                               _tcscpy (fname, file.cFileName);
+
+                       ConOutPrintf (_T("%-14s"), fname);
+                       if (++count == 5)
+                       {
+                               ConOutChar (_T('\n'));
+                               count = 0;
+                       }
+               }
+               while (FindNextFile (hFile, &file));
+
+               FindClose (hFile);
+
+               if (count)
+                       ConOutChar (_T('\n'));
+       }
+       else
+       {
+               /* no match found */
+               MessageBeep (-1);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+#endif
+
+#ifdef FEATURE_4NT_FILENAME_COMPLETION
+
+//static VOID BuildFilenameMatchList (...)
+
+// VOID CompleteFilenameNext (LPTSTR, INT)
+// VOID CompleteFilenamePrev (LPTSTR, INT)
+
+// VOID RemoveFilenameMatchList (VOID)
+
+#endif
\ No newline at end of file
diff --git a/rosapps/cmd/files.txt b/rosapps/cmd/files.txt
new file mode 100644 (file)
index 0000000..8f1dfef
--- /dev/null
@@ -0,0 +1,56 @@
+Archive Contents
+~~~~~~~~~~~~~~~~
+bugs.txt        Bug List
+files.txt       This file list
+history.txt     History of the shell development
+license.txt     GNU license - applies to all files named here
+readme.txt      General shell info
+todo.txt        What I have to do
+wishlist.txt    Wish List
+
+makefile        experimental makefile
+makefile.lcc    makefile for lcc-win
+
+alias.c         Alias code
+alias.h         Alias header file
+attrib.c        Implements attrib command
+batch.c         Batch file interpreter
+beep.c          Implements beep command
+call.c          Implements call command
+chcp.c          Implements chcp command
+cls.c           Implements cls command
+cmdinput.c      Command-line input functions
+cmdtable.c      Table of available internal commands
+cmd.c           Main code for command-line interpreter
+cmd.h           Command header file
+color.c         Implements color command
+console.c       Windows console handling code
+copy.c          Implements copy command
+date.c          Implements date command
+del.c           Implements del command
+dir.c           Directory listing code
+dirstack.c      Directory stack code (PUSHD and POPD)
+echo.c          Implements echo command
+error.c         Error Message Routines
+filecomp.c      Filename completion functions
+for.c           Implements for command
+goto.c          Implements goto command
+history.c       Command-line history handling
+if.c            Implements if command
+internal.c      Internal commands (DIR, RD, etc)
+label.c         Implements label command
+locale.c        Locale handling code
+misc.c          Misc. Functions
+move.c          Implements move command
+path.c          Implements path command
+pause.c         Implements pause command
+prompt.c        Prompt handling functions
+redir.c         Redirection and piping parsing functions
+ren.c           Implements rename command
+set.c           Implements set command
+shift.c         Implements shift command
+time.c          Implements time command
+type.c          Implements type command
+ver.c           Implements ver command
+where.c         Code to search path for executables
+verify.c        Implements verify command
\ No newline at end of file
diff --git a/rosapps/cmd/for.c b/rosapps/cmd/for.c
new file mode 100644 (file)
index 0000000..7ccb445
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ *  FOR.C - for internal batch command.
+ *
+ *
+ *  History:
+ *
+ *    16 Jul 1998 (Hans B Pufal)
+ *        started.
+ *
+ *    16 Jul 1998 (John P Price)
+ *        Seperated commands into individual files.
+ *
+ *    19 Jul 1998 (Hans B Pufal) [HBP_001]
+ *        Implementation of FOR
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+/*
+ * Perform FOR command.
+ *
+ * First check syntax is correct : FOR %v IN ( <list> ) DO <command>
+ *   v must be alphabetic, <command> must not be empty.
+ *
+ * If all is correct build a new bcontext structure which preserves
+ *   the necessary information so that readbatchline can expand
+ *   each the command prototype for each list element.
+ *
+ * You might look on a FOR as being a called batch file with one line
+ *   per list element.
+ */
+
+INT cmd_for (LPTSTR cmd, LPTSTR param)
+{
+       LPBATCH_CONTEXT lpNew;
+       LPTSTR pp;
+       TCHAR  var;
+
+#ifdef _DEBUG
+       DebugPrintf ("cmd_for (\'%s\', \'%s\'\n", cmd, param);
+#endif
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts ("FOR :");
+               return 0;
+       }
+
+       /* Check that first element is % then an alpha char followed by space */
+       if ((*param != _T('%')) || !_istalpha (*(param + 1)) || !_istspace (*(param + 2)))
+       {
+               error_syntax (_T("bad varable specification."));
+               return 1;
+       }
+
+       param++;
+       var = *param++;               /* Save FOR var name */
+
+       while (_istspace (*param))
+               param++;
+
+       /* Check next element is 'IN' */
+       if ((_tcsnicmp (param, _T("in"), 2) != 0) || !_istspace (*(param + 2)))
+       {
+               error_syntax (_T("'in' missing in for statement."));
+               return 1;
+       }
+
+       param += 2;
+       while (_istspace (*param))
+               param++;
+
+       /* Folowed by a '(', find also matching ')' */
+       if ((*param != _T('(')) || (NULL == (pp = _tcsrchr (param, _T(')')))))
+       {
+               error_syntax (_T("no brackets found."));
+               return 1;
+       }
+
+       *pp++ = _T('\0');
+       param++;                /* param now points at null terminated list */
+
+       while (_istspace (*pp))
+               pp++;
+
+       /* Check DO follows */
+       if ((_tcsnicmp (pp, _T("do"), 2) != 0) || !_istspace (*(pp + 2)))
+       {
+               error_syntax (_T("'do' missing."));
+               return 1;
+       }
+
+       pp += 2;
+       while (_istspace (*pp))
+               pp++;
+
+       /* Check that command tail is not empty */
+       if (*pp == _T('\0'))
+       {
+               error_syntax (_T("no command after 'do'."));
+               return 1;
+       }
+
+       /* OK all is correct, build a bcontext.... */
+       lpNew = (LPBATCH_CONTEXT)malloc (sizeof (BATCH_CONTEXT));
+
+       lpNew->prev = bc;
+       bc = lpNew;
+
+       bc->hBatchFile = INVALID_HANDLE_VALUE;
+       bc->ffind = NULL;
+       bc->params = BatchParams (_T(""), param); /* Split out list */
+       bc->shiftlevel = 0;
+       bc->forvar = var;
+       bc->forproto = _tcsdup (pp);
+
+       return 0;
+}
diff --git a/rosapps/cmd/goto.c b/rosapps/cmd/goto.c
new file mode 100644 (file)
index 0000000..def1cbf
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ *  GOTO.C - goto internal batch command.
+ *
+ *  History:
+ *
+ *    16 Jul 1998 (Hans B Pufal)
+ *        started.
+ *
+ *    16 Jul 1998 (John P Price)
+ *        Seperated commands into individual files.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    28 Jul 1998 (Hans B Pufal) [HBP_003]
+ *        Terminate label on first space character, use only first 8 chars of
+ *        label string
+ *
+ *    24-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection safe!
+ *
+ *    27-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("/?").
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+/*
+ * Perform GOTO command.
+ *
+ * Only valid if batch file current.
+ *
+ */
+
+INT cmd_goto (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR tmp;
+       LONG   lNewPosHigh;
+
+#ifdef _DEBUG
+       DebugPrintf ("cmd_goto (\'%s\', \'%s\'\n", cmd, param);
+#endif
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Directs CMD to a labeled line in a batch script.\n"
+                                          "\n"
+                                          "GOTO label\n"
+                                          "\n"
+                                          "  label  Specifies a text string used in a batch script as a label.\n"
+                                          "\n"
+                                          "You type a label on a line by itself, beginning with a colon."));
+               return 0;
+       }
+
+       /* if not in batch -- error!! */
+       if (bc == NULL)
+       {
+               return 1;
+       }
+
+       if (*param == _T('\0'))
+       {
+               ExitBatch (_T("No label specified for GOTO\n"));
+               return 1;
+       }
+
+       /* terminate label at first space char */
+       tmp = param;
+       while (*tmp && !_istspace (*tmp))
+               tmp++;
+       *tmp = _T('\0');
+
+       /* set file pointer to the beginning of the batch file */
+       lNewPosHigh = 0;
+       SetFilePointer (bc->hBatchFile, 0, &lNewPosHigh, FILE_BEGIN);
+
+       while (FileGetString (bc->hBatchFile, textline, sizeof(textline)))
+       {
+               /* Strip out any trailing spaces or control chars */
+               tmp = textline + _tcslen (textline) - 1;
+               while (_istcntrl (*tmp) || _istspace (*tmp))
+                       tmp--;
+               *(tmp + 1) = _T('\0');
+
+               /* Then leading spaces... */
+               tmp = textline;
+               while (_istspace (*tmp))
+                       tmp++;
+
+               /* use only 1st 8 chars of label */
+               if ((*tmp == _T(':')) && (_tcsncmp (++tmp, param, 8) == 0))
+                       return 0;
+       }
+
+       ConErrPrintf (_T("Label '%s' not found\n"), param);
+       ExitBatch (NULL);
+
+       return 1;
+}
diff --git a/rosapps/cmd/history.c b/rosapps/cmd/history.c
new file mode 100644 (file)
index 0000000..2e48d59
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ *  HISTORY.C - command line history.
+ *
+ *
+ *  History:
+ *
+ *    14/01/95 (Tim Norman)
+ *        started.
+ *
+ *    08/08/95 (Matt Rains)
+ *        i have cleaned up the source code. changes now bring this source
+ *        into guidelines for recommended programming practice.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    25-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Cleanup!
+ *        Unicode and redirection safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef FEATURE_HISTORY
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+#define MAXLINES 128
+
+static INT history_size = 2048;    /* make this configurable later */
+
+
+VOID History (INT dir, LPTSTR commandline)
+{
+       static LPTSTR history = NULL;
+       static LPTSTR lines[MAXLINES];
+       static INT curline = 0;
+       static INT numlines = 0;
+       static INT maxpos = 0;
+       INT count;
+       INT length;
+
+       if (!history)
+       {
+               history = malloc (history_size * sizeof (TCHAR));
+               lines[0] = history;
+               history[0] = 0;
+       }
+
+       if (dir > 0)
+       {
+               /* next command */
+               if (curline < numlines)
+               {
+                       curline++;
+               }
+
+               if (curline == numlines)
+               {
+                       commandline[0] = 0;
+               }
+               else
+               {
+                       _tcscpy (commandline, lines[curline]);
+               }
+       }
+       else if (dir < 0)
+       {
+               /* prev command */
+               if (curline > 0)
+               {
+                       curline--;
+               }
+
+               _tcscpy (commandline, lines[curline]);
+       }
+       else
+       {
+               /* add to history */
+               /* remove oldest string until there's enough room for next one */
+               /* strlen (commandline) must be less than history_size! */
+               while ((maxpos + (INT)_tcslen (commandline) + 1 > history_size) || (numlines >= MAXLINES))
+               {
+                       length = _tcslen (lines[0]) + 1;
+
+                       for (count = 0; count < maxpos && count + (lines[1] - lines[0]) < history_size; count++)
+                       {
+                               history[count] = history[count + length];
+                       }
+
+                       maxpos -= length;
+
+                       for (count = 0; count <= numlines && count < MAXLINES; count++)
+                       {
+                               lines[count] = lines[count + 1] - length;
+                       }
+
+                       numlines--;
+#ifdef DEBUG
+                       ConOutPrintf (_T("Reduced size:  %ld lines\n"), numlines);
+
+                       for (count = 0; count < numlines; count++)
+                       {
+                               ConOutPrintf (_T("%d: %s\n"), count, lines[count]);
+                       }
+#endif
+               }
+
+               _tcscpy (lines[numlines], commandline);
+               numlines++;
+               lines[numlines] = lines[numlines - 1] + _tcslen (commandline) + 1;
+               maxpos += _tcslen (commandline) + 1;
+               /* last line, empty */
+               curline = numlines;
+       }
+
+       return;
+}
+
+#endif
diff --git a/rosapps/cmd/history.txt b/rosapps/cmd/history.txt
new file mode 100644 (file)
index 0000000..7b0769b
--- /dev/null
@@ -0,0 +1,345 @@
+FreeDOS Command Line Interface Development History
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+11/11/94 version 0.01
+~~~~~~~~~~~~~~~~~~~~~
+o  initial release.
+
+01/01/95 version 0.10
+~~~~~~~~~~~~~~~~~~~~~
+o  removed some scaffolding.
+o  modified CD.
+o  added tab file completion.
+o  added command line history.
+
+01/15/95 version 0.20
+~~~~~~~~~~~~~~~~~~~~~
+o  formatted all existing source modules.
+o  added prompt support.
+o  added drive selection.
+o  added dir command.
+o  started this development log.
+
+08/06/95 prerelease of version 0.30
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+o  reorganized code into separate source modules.
+o  added batch processing support (thanks to Evan Jeffrey).
+o  added exec code (thanks to Steffan Kaiser).
+o  removed environment handling (thanks again to Steffan Kaiser)
+
+        [ 08/08/95 -- Matt Rains ]
+o  formatted this development log.
+o  formatted all existing source modules so that they comply with recommended
+        programming practice.
+o  added MD command.
+o  added RD command.
+o  added VER command.
+o  replaced CD command.
+o  modified DIR command.
+o  DIR now called regardless of other DIR.??? files. this is done because of
+        exec() problems.
+
+12/10/95 version 0.30
+~~~~~~~~~~~~~~~~~~~~~
+o  used Borland's spawnve to fix exec problem
+o  fixed CD again so you don't need a space after it
+o  couple of spelling fixes
+
+12/14/95 version 0.31
+~~~~~~~~~~~~~~~~~~~~~
+o  modified cmdinput.c to work with non-standard screen sizes (see 28.com)
+o  fixed a bug in history.c that made it not work when you hit the up arrow
+   on the first line
+o  fixed DIR to work a little more like MS-DOS's DIR (see internal.c)
+o  fixed some code in where.c to make things a bit more efficient and nicer
+
+01/06/96 version 0.40  (never released)
+~~~~~~~~~~~~~~~~~~~~~
+o  added redirection and piping support!!!  (see redir.c and command.c)
+o  fixed a stupid pointer problem in where.c that was causing LOTS of
+   problems in the strangest places...
+o  added day of the week support to prompt.c (oops, that was already supposed
+   to be there! :)
+o  fixed and reorganized the EXEC code!!!  Thanks to Svante Frey!
+o  reorganized command.c and internal.c to handle parsing internal commands
+   more efficiently and consistently.
+o  changed the behavior of MD, CD, RD to work without spaces (e.g. CD\DOS)
+o  small changes here and there to make it work with redirection/piping
+   (e.g. DIR only pauses if you're not doing redirection)
+
+01/17/96 version 0.50
+~~~~~~~~~~~~~~~~~~~~~
+Version 0.40 was never released because I was home on Christmas vacation,
+and I couldn't upload it.  By the time I got back to school, I had the
+LOADHIGH patch from Svante Frey, so I decided to jump up to 0.50 without any
+release of 0.40...       - Tim Norman
+
+o  LOADHIGH/LOADFIX/LH support added!!!!  Many thanks go to Svante Frey!
+o  bug fixed in command parsing that didn't handle / switches correctly...
+o  removed debugging output from history.c
+
+07/26/96 version 0.60
+~~~~~~~~~~~~~~~~~~~~~
+Lots of internal changes here...  Not much added to the interface.
+
+o  Changed internals to use first,rest parameters instead of arrays of params
+o  Fixed some bugs
+o  Some other things I don't remember :)
+
+07/26/96 version 0.61
+~~~~~~~~~~~~~~~~~~~~~
+Bugfixes
+
+o  Added hook to the PATH command
+o  Fixed CD.. bug
+
+08/27/96 version 0.70
+~~~~~~~~~~~~~~~~~~~~~
+Finally added Oliver Mueller's ALIAS command!  Also numerous bug fixes.
+
+o  Added ALIAS command
+o  Removed support for - as a switch in LOADHIGH.C
+o  Bugfixes in BATCH.C.  %0 was returning garbage
+o  Removed lots of unused variables, reducing # of warnings when compiling
+o  Other miscellaneous code clean-ups
+o  Changed WHERE.C to use a little less memory
+
+06/14/97 version 0.71
+~~~~~~~~~~~~~~~~~~~~~
+Lots of bug fixes, plus some additional features.
+
+o  New DIR command.  Now more like MS-DOS's DIR.  /p supported, /s coming soon
+o  bug fix in internal.c - parse_firstarg
+o  Rewrote parser in batch.c (Steffan Kaiser)
+o  Ctrl-Break checking in various places (Steffan Kaiser)
+o  Error level setting/checking (%? in batch files) (Steffan Kaiser)
+o  bug fix in cmdinput.c ("%i" on command-line caused weird behavior)
+o  bug fix in where.c (first item in path wasn't searched)
+
+07/12/97 version 0.72
+~~~~~~~~~~~~~~~~~~~~~
+More bug fixes and code cleanup
+
+o  Rewrote cmdinput.c to be more efficient (Marc Desrochers)
+o  Added insert/overstrike modes (Marc Desrochers)
+o  Replaced findxy() with pointers into BIOS (maxx, maxy) (Marc Desrochers)
+o  Fixed bug that disallowed listing of root directories
+o  Fixed bug that didn't search the first path (again!)
+
+07/13/97 version 0.72b
+~~~~~~~~~~~~~~~~~~~~~~
+Disabled a feature that caused a crash on some machines.
+
+o  Replaced setcursor calls in cmdinput.c with _setcursortype
+o  Added dir.c to the distribution (was left out in 0.72)
+
+07/01/98 version 0.73 (Rob Lake)
+~~~~~~~~~~~~~~~~~~~~~~
+o New DIR commands supported: /S, /B, /L, /A and /W.
+  (/R changed to /S).  Also /? added.
+o Supports DIRCMD in environment.
+o Supports turning off commands with hyphen (ex. /-S
+  turns off recursive listing)
+o Changed error messages for DIR and DEL to more MS-DOS'ish
+o Moved error messages from DIR.C and DEL.C to COMMAND.H
+  (more may go there soon)
+o Fixed bug that caused dir *.ext/X not to work (no spaces
+  between filespec and slash)
+o Added wildcard support for DEL command
+o Added prompt and help switch for DEL command, /P and /?
+  respectively.
+o Added support for /C when envoking the shell
+o Added /P support when Kernel loads shell.  This means
+  the shell now is permanent and runs the autoexec.bat
+  (/E is not implemented)
+o Added my name (Rob Lake) to the developer listing
+o Changed version routine to print out copyright notice
+  with no args, and with appropriate switches, warranty
+  and redistribution notices and developer listing
+
+07/08/1998 version 0.74 (John P. Price (linux-guru@gcfl.net))
+~~~~~~~~~~~~~~~~~~~~~~~~
+COMMAND.C/COMMAND.H:
+o Now sets COMSPEC environment variable
+o misc clean up and optimization
+o added date, time and type commands
+o changed to using spawnl instead of exec.  exec does not copy the
+  environment to the child process!
+DIR.C
+o removed extra returns; closer to MSDOS
+o fixed wide display so that an extra return is not displayed when
+  there is five filenames in the last line.
+ENVIRON.C
+o commented out show_environment function.  Not used anymore.
+INTERAL.C
+o removed call to show_environment in set command.
+o moved test for syntax before allocating memory in set command.
+o misc clean up and optimization.
+
+o created DATE.C
+o created TIME.C
+o created TYPE.C
+
+07/08/1998 version 0.74b (John P. Price (linux-guru@gcfl.net))
+~~~~~~~~~~~~~~~~~~~~~~~~
+COMMAND.C
+o fixed call to spawnl so that it would pass command line arguments
+  correctly.
+
+07/12/98 version 0.74c (Rob Lake rlake@cs.mun.ca)
+~~~~~~~~~~~~~~~~~~~~~~
+Various Files:
+o removed redundant use of error message defines and moved
+  error printing calls to ERROR.C to reduced program size.
+
+o created MISC.C
+o created ERR_HAND.C/H
+o created ERROR.C
+
+07/13/98 version 0.74d (Rob Lake rlake@cs.mun.ca)
+~~~~~~~~~~~~~~~~~~~~~~
+INTERNAL.C
+o removed most of the commands and placed them in there own file
+  -- del, ren, set and ver
+o created DEL.C, REN.C SET.C and VER.C
+o fixed bug that caused del not to delete files with no attributes
+o the critical error handler count number of times called, autofails
+  at 5 calls
+
+
+16 Jul 1998 (Hans B Pufal <hansp@digiweb.com>)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+batch.c
+  A new version, implements CALL, ECHO, GOT, IF, PAUSE, SHIFT and
+  BEEP. There is a stub for FOR but that's all.
+
+cmdtable.c
+  New file to keep the internal command table. I plan on getting rid
+  of the table real soon now and replacing it with a dynamic
+  mechanism.
+
+command.c
+  A new (improved ;) version. Conforms closely to MS-DOS specs.
+  Cleaned up (and fixed) the redirection handler.
+
+command.h
+  Version D with changes. Look for the HBP tag.
+
+redir.c
+  Modified file, now supports append redirects.
+
+
+16 Jul 1998 (Rob Lake rlake@cs.mun.ca)
+~~~~~~~~~~~~~~~~~~~~~~
+Added TRUENAME command.
+
+
+19 Jul 1998 (Hans B Pufal) <hansp@digiweb.com>)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+o Preserve state of echo flag across batch calls.
+o Implementation of FOR command
+
+
+20 Jul 1998 (John P Price <linux-guru@gcfl.net>)
+~~~~~~~~~~~~~~~~~~~~~~
+o Fixed bug in DATE.C.
+o Fixed bug in LH.ASM.
+o Separated commands into individual files.
+
+
+28 Jul 1998 (John P Price <linux-guru@gcfl.net>)
+~~~~~~~~~~~~~~~~~~~~~~
+o Added CLS command.
+o Put ifdef's around all commands and added include file config.h
+  Now you can define exact what commands you want to include in
+  command.com.
+o Also added ifdefs for optional features: aliases, command history
+  and filename completion.
+o Added display of available internal commands and options at startup.
+
+
+29 Jul 1998 (Rob Lake rlake@cs.mun.ca)
+~~~~~~~~~~~~~~~~~~~~~~
+o changed date.c and time.c, and wrote datefunc.c and timefunc.c to
+  impliment _dos_getdate, _dos_setdate, _dos_gettime and _dos_settime.
+  This is the first of many steps to make the shell compatible under
+  Pacific C.
+
+30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+~~~~~~~~~~~~~~~~~~~~~~
+o Changed filename completion so that a second TAB displays a list of
+  matching filenames!
+o made filename be lower case if last character typed is lower case.
+o Moved filename completion code to filecomp.c.
+o Change ver command to display email address to report bugs, and the
+  web page address for updates.
+o fixed so that it find_which returns NULL if filename is not
+  executable (does not have .bat, .com, or .exe extension).  Before
+  command would to execute any file with any extension. (opps!)
+
+30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+~~~~~~~~~~~~~~~~~~~~~~
+o Fixed bug where if you typed something, then hit HOME, then tried to
+  type something else in insert mode, it locked up.
+o Changed default insert mode to on.  There should be a way to change
+  this.  Maybe options to doskey command.
+o Added VERIFY command
+
+02-Aug-1998 (Hans B Pufal) <hansp@digiweb.com>)
+~~~~~~~~~~~~~~~~~~~~~~
+o batch.c: Fixed bug in ECHO flag restoration at exit from batch file
+o command.c: Fixed return value when called with /C option
+o Terminate label on first space character, use only first 8 chars of
+  label string
+
+04-Aug-1998 (Hans B Pufal) <hansp@digiweb.com>)
+~~~~~~~~~~~~~~~~~~~~~~
+o call.c: added lines to initialize for pointers.  This fixed the
+  lock-up that happened sometimes when calling a batch file from
+  another batch file.
+
+07-Aug-1998 (John P Price <linux-guru@gcfl.net>)
+~~~~~~~~~~~~~~~~~~~~~~
+o Fixed carrage return output to better match MSDOS with echo on or off.
+
+
+07-Dec-1998 ReactOS CMD version 0.0.1 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+o First test release.
+o Added internal ATTRIB command.
+
+11-Dec-1998 ReactOS CMD version 0.0.2 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+o Fixed bug in ALIAS. CMD crashed when you tried to remove an alias.
+o Fixed bug in split(). Added freep(). This fixed the DEL command.
+o Improved ATTRIB command.
+o Added most help texts.
+o Fixed recursive DIR ("dir /s").
+o Fixed DATE and TIME command. Now they accept values when used
+  without parameter.
+o Implemented LABEL command.
+
+05-Jan-1999 ReactOS CMD version 0.0.3 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+o Added COLOR command and "/t" option.
+o Cursor shows insert/overwrite mode.
+o COMSPEC environment variable is set upon startup.
+o Started COPY command.
+o Started MOVE command.
+o Added directory stack (PUSHD and POPD commands).
+o Added support for file names or paths that contain spaces
+  (quoted paths / file names).
+o Added recursion to ATTRIB command.
+o Added locale support for DIR, DATE, TIME and PROMPT.
+o Fixed VERIFY.
+
+10-Feb-1999 ReactOS CMD version 0.0.4 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+o "?" lists all available commands.
+o Most commands are unicode and redirection aware now.
+o Input-, Output- and Error-Redirections works with most commands.
+o ATTRIB and DEL can handle multiple filenames now.
+o Fixed handling of environment variables.
+o Added CHCP command.
+o Fixed keyboard input bug.
+o Rewrote DEL and MOVE commands.
\ No newline at end of file
diff --git a/rosapps/cmd/if.c b/rosapps/cmd/if.c
new file mode 100644 (file)
index 0000000..64744bc
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ *  IF.C - if internal batch command.
+ *
+ *
+ *  History:
+ *
+ *    16 Jul 1998 (Hans B Pufal)
+ *        started.
+ *
+ *    16 Jul 1998 (John P Price)
+ *        Seperated commands into individual files.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    07-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("if /?") and cleaned up.
+ *
+ *    21-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+#define X_EXEC 1
+#define X_EMPTY 0x80
+
+
+INT cmd_if (LPTSTR cmd, LPTSTR param)
+{
+       INT x_flag = 0; /* when set cause 'then' clause to be executed */
+       LPTSTR pp;
+
+#ifdef _DEBUG
+       DebugPrintf ("cmd_if: (\'%s\', \'%s\'\n", cmd, param);
+#endif
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("IF :"));
+               return 0;
+       }
+
+       /* First check if param string begins with word 'not' */
+       if (!_tcsnicmp (param, _T("not"), 3) && _istspace (*(param + 3)))
+       {
+               x_flag = X_EXEC;            /* Remember 'NOT' */
+               param += 3;                 /* Step over 'NOT' */
+               while (_istspace (*param))  /* And subsequent spaces */
+                       param++;
+       }
+
+       /* Check for 'exist' form */
+       if (!_tcsnicmp (param, _T("exist"), 5) && _istspace (*(param + 5)))
+       {
+               param += 5;
+               while (_istspace (*param))
+                       param++;
+
+               pp = param;
+               while (*pp && !_istspace (*pp))
+                       pp++;
+
+               if (*pp)
+               {
+                       WIN32_FIND_DATA f;
+                       HANDLE hFind;
+
+                       *pp++ = _T('\0');
+                       hFind = FindFirstFile (param, &f);
+                       x_flag ^= (hFind != INVALID_HANDLE_VALUE) ? 0 : X_EXEC;
+                       if (hFind != INVALID_HANDLE_VALUE)
+                               FindClose (hFind);
+               }
+               else
+                       return 0;
+       }
+
+       /* Check for 'errorlevel' form */
+       else if (!_tcsnicmp (param, _T("errorlevel"), 10) && _istspace (*(param + 10)))
+       {
+               INT n = 0;
+
+               pp = param + 10;
+               while (_istspace (*pp))
+                       pp++;
+
+               while (_istdigit (*pp))
+                       n = n * 10 + (*pp++ - _T('0'));
+
+               x_flag ^= (errorlevel < n) ? 0 : X_EXEC;
+
+               x_flag |= X_EMPTY;          /* Syntax error if comd empty */
+       }
+
+       /* Check that '==' is present, syntax error if not */
+       else if (NULL == (pp = _tcsstr (param, _T("=="))))
+       {
+               error_syntax (NULL);
+               return 1;
+       }
+
+       else
+       {
+               /* Change first '='to space to terminate comparison loop */
+
+               *pp = _T(' ');   /* Need a space to terminate comparison loop */
+               pp += 2;                /* over '==' */
+               while (_istspace (*pp)) /* Skip subsequent spaces */
+                       pp++;
+
+               _tcscat (pp, _T(" "));  /* Add one space to ensure comparison ends */
+
+               while (*param == *pp)       /* Comparison loop */
+               {
+                       if (_istspace (*param))      /* Terminates on space */
+                               break;
+
+                       param++, pp++;
+               }
+
+               if (x_flag ^= (*param != *pp) ? 0 : X_EXEC)
+               {
+                       while (*pp && !_istspace (*pp))  /* Find first space, */
+                               pp++;
+
+                       x_flag |= X_EMPTY;
+               }
+       }
+
+       if (x_flag & X_EMPTY)
+       {
+               while (_istspace (*pp)) /* Then skip spaces */
+                       pp++;
+
+               if (*pp == _T('\0'))    /* If nothing left then syntax err */
+               {
+                       error_syntax (NULL);
+                       return 1;
+               }
+       }
+
+       if (x_flag & X_EXEC)
+               ParseCommandLine (pp);
+
+       return 0;
+}
diff --git a/rosapps/cmd/internal.c b/rosapps/cmd/internal.c
new file mode 100644 (file)
index 0000000..b2019f7
--- /dev/null
@@ -0,0 +1,485 @@
+/*
+ *  INTERNAL.C - command.com internal commands.
+ *
+ *
+ *  History:
+ *
+ *  17/08/94 (Tim Norman)
+ *    started.
+ *
+ *  08/08/95 (Matt Rains)
+ *    i have cleaned up the source code. changes now bring this source into
+ *    guidelines for recommended programming practice.
+ *
+ *  cd()
+ *    started.
+ *
+ *  dir()
+ *    i have added support for file attributes to the DIR() function. the
+ *    routine adds "d" (directory) and "r" (read only) output. files with the
+ *    system attribute have the filename converted to lowercase. files with
+ *    the hidden attribute are not displayed.
+ *
+ *    i have added support for directorys. now if the directory attribute is
+ *    detected the file size if replaced with the string "<dir>".
+ *
+ *  ver()
+ *    started.
+ *
+ *  md()
+ *    started.
+ *
+ *  rd()
+ *    started.
+ *
+ *  del()
+ *    started.
+ *
+ *  does not support wildcard selection.
+ *
+ *  todo: add delete directory support.
+ *        add recursive directory delete support.
+ *
+ *  ren()
+ *    started.
+ *
+ *  does not support wildcard selection.
+ *
+ *    todo: add rename directory support.
+ *
+ *  a general structure has been used for the cd, rd and md commands. this
+ *  will be better in the long run. it is too hard to maintain such diverse
+ *  functions when you are involved in a group project like this.
+ *
+ *  12/14/95 (Tim Norman)
+ *    fixed DIR so that it will stick \*.* if a directory is specified and
+ *    that it will stick on .* if a file with no extension is specified or
+ *    *.* if it ends in a \
+ *
+ *  1/6/96 (Tim Norman)
+ *    added an isatty call to DIR so it won't prompt for keypresses unless
+ *    stdin and stdout are the console.
+ *
+ *    changed parameters to be mutually consistent to make calling the
+ *    functions easier
+ *
+ *  rem()
+ *    started.
+ *
+ *  doskey()
+ *    started.
+ *
+ *    01/22/96 (Oliver Mueller)
+ *        error messages are now handled by perror.
+ *
+ *    02/05/96 (Tim Norman)
+ *        converted all functions to accept first/rest parameters
+ *
+ *    07/26/96 (Tim Norman)
+ *        changed return values to int instead of void
+ *
+ *        path() started.
+ *
+ *    12/23/96 (Aaron Kaufman)
+ *        rewrote dir() to mimic MS-DOS's dir
+ *
+ *    01/28/97 (Tim Norman)
+ *        cleaned up Aaron's DIR code
+ *
+ *    06/13/97 (Tim Norman)
+ *        moved DIR code to dir.c
+ *        re-implemented Aaron's DIR code
+ *
+ *    06/14/97 (Steffan Kaiser)
+ *        ctrl-break handling
+ *        bug fixes
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    03-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Replaced DOS calls by Win32 calls.
+ *
+ *    08-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help texts ("/?").
+ *
+ *    18-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added support for quoted arguments (cd "program files").
+ *
+ *    07-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Clean up.
+ *
+ *    26-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Replaced remaining CRT io functions by Win32 io functions.
+ *        Unicode safe!
+ *
+ *    30-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added "cd -" feature. Changes to the previous directory.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+
+extern COMMAND cmds[]; /* The internal command table, used in '?' */
+
+
+#ifdef INCLUDE_CMD_CHDIR
+
+static LPTSTR lpLastPath;
+
+
+VOID InitLastPath (VOID)
+{
+       lpLastPath = NULL;
+}
+
+
+VOID FreeLastPath (VOID)
+{
+       if (lpLastPath)
+               free (lpLastPath);
+}
+
+
+/*
+ * CD / CHDIR
+ *
+ */
+INT cmd_chdir (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR dir;             /* pointer to the directory to change to */
+       LPTSTR place;   /* used to search for the \ when no space is used */
+       LPTSTR lpOldPath;
+       LPTSTR *arg = NULL;
+       INT argc;
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Changes the current directory or displays it's name\n\n"
+                                          "CHDIR [drive:][path]\n"
+                                          "CHDIR[..|-]\n"
+                                          "CD [drive:][path]\n"
+                                          "CD[..|-]\n\n"
+                                          "  ..   parent directory\n"
+                                          "  -    previous directory\n\n"
+                                          "Type CD drive: to display the current directory on the specified drive.\n"
+                                          "Type CD without a parameter to display the current drive and directory."));
+               return 0;
+       }
+
+       /* check if there is no space between the command and the path */
+       if (param[0] == _T('\0'))
+       {
+               /* search for the '\', '.' or '-' so that both short & long names will work */
+               for (place = cmd; *place; place++)
+                       if (*place == _T('.') || *place == _T('\\') || *place == _T('-'))
+                               break;
+
+               if (*place)
+                       dir = place;
+               else
+                       /* signal that there are no parameters */
+                       dir = NULL;
+       }
+       else
+       {
+               arg = split (param, &argc);
+
+               if (argc > 1)
+               {
+                       /*JPP 20-Jul-1998 use standard error message */
+                       error_too_many_parameters (param);
+                       freep (arg);
+                       return 1;
+               }
+               else
+                       dir = arg[0];
+       }
+
+       /* if doing a CD and no parameters given, print out current directory */
+       if (!dir || !dir[0])
+       {
+               TCHAR szPath[MAX_PATH];
+
+               GetCurrentDirectory (MAX_PATH, szPath);
+
+               ConOutPuts (szPath);
+
+               freep (arg);
+
+               return 0;
+       }
+
+       if (dir && _tcslen (dir) == 1 && *dir == _T('-'))
+       {
+               if (lpLastPath)
+                       dir = lpLastPath;
+               else
+               {
+                       freep (arg);
+                       return 0;
+               }
+       }
+       else if (dir && _tcslen (dir) > 1 && dir[1] == _T(':'))
+       {
+               TCHAR szRoot[3] = _T("A:");
+               TCHAR szPath[MAX_PATH];
+
+               szRoot[0] = _totupper (dir[0]);
+               GetFullPathName (szRoot, MAX_PATH, szPath, NULL);
+
+               /* PathRemoveBackslash */
+               if (_tcslen (szPath) > 3)
+               {
+                       LPTSTR p = _tcsrchr (szPath, _T('\\'));
+                       *p = _T('\0');
+               }
+
+               ConOutPuts (szPath);
+
+               freep (arg);
+
+               return 0;
+       }
+
+       /* remove trailing \ if any, but ONLY if dir is not the root dir */
+       if (_tcslen (dir) >= 2 && dir[_tcslen (dir) - 1] == _T('\\'))
+               dir[_tcslen(dir) - 1] = _T('\0');
+
+
+       /* store current directory */
+       lpOldPath = (LPTSTR)malloc (MAX_PATH * sizeof(TCHAR));
+       GetCurrentDirectory (MAX_PATH, lpOldPath);
+
+       if (!SetCurrentDirectory (dir))
+       {
+               ErrorMessage (GetLastError(), _T("CD"));
+
+               /* throw away current directory */
+               free (lpOldPath);
+               lpOldPath = NULL;
+
+               freep (arg);
+               return 1;
+       }
+       else
+       {
+               if (lpLastPath)
+                       free (lpLastPath);
+               lpLastPath = lpOldPath;
+       }
+
+       freep (arg);
+
+       return 0;
+}
+#endif
+
+
+
+#ifdef INCLUDE_CMD_MKDIR
+/*
+ * MD / MKDIR
+ *
+ */
+INT cmd_mkdir (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR dir;             /* pointer to the directory to change to */
+       LPTSTR place;   /* used to search for the \ when no space is used */
+       LPTSTR *p = NULL;
+       INT argc;
+
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Creates a directory.\n\n"
+                                          "MKDIR [drive:]path\nMD [drive:]path"));
+               return 0;
+       }
+
+
+       /* check if there is no space between the command and the path */
+       if (param[0] == _T('\0'))
+       {
+               /* search for the \ or . so that both short & long names will work */
+               for (place = cmd; *place; place++)
+                       if (*place == _T('.') || *place == _T('\\'))
+                               break;
+
+               if (*place)
+                       dir = place;
+               else
+                       /* signal that there are no parameters */
+                       dir = NULL;
+       }
+       else
+       {
+               p = split (param, &argc);
+               if (argc > 1)
+               {
+                       /*JPP 20-Jul-1998 use standard error message */
+                       error_too_many_parameters (param);
+                       freep (p);
+                       return 1;
+               }
+               else
+                       dir = p[0];
+       }
+
+       /* remove trailing \ if any, but ONLY if dir is not the root dir */
+       if (_tcslen (dir) >= 2 && dir[_tcslen (dir) - 1] == _T('\\'))
+               dir[_tcslen(dir) - 1] = _T('\0');
+
+       if (!CreateDirectory (dir, NULL))
+       {
+               ErrorMessage (GetLastError(), _T("MD"));
+
+               freep (p);
+               return 1;
+       }
+
+       freep (p);
+
+       return 0;
+}
+#endif
+
+
+#ifdef INCLUDE_CMD_RMDIR
+/*
+ * RD / RMDIR
+ *
+ */
+INT cmd_rmdir (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR dir;             /* pointer to the directory to change to */
+       LPTSTR place;   /* used to search for the \ when no space is used */
+
+       LPTSTR *p = NULL;
+       INT argc;
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Removes a directory.\n\n"
+                                          "RMDIR [drive:]path\nRD [drive:]path"));
+               return 0;
+       }
+
+       /* check if there is no space between the command and the path */
+       if (param[0] == _T('\0'))
+       {
+               /* search for the \ or . so that both short & long names will work */
+               for (place = cmd; *place; place++)
+                       if (*place == _T('.') || *place == _T('\\'))
+                               break;
+
+               if (*place)
+                       dir = place;
+               else
+                       /* signal that there are no parameters */
+                       dir = NULL;
+       }
+       else
+       {
+               p = split (param, &argc);
+               if (argc > 1)
+               {
+                       /*JPP 20-Jul-1998 use standard error message */
+                       error_too_many_parameters (param);
+                       freep (p);
+                       return 1;
+               }
+               else
+                       dir = p[0];
+       }
+
+       /* remove trailing \ if any, but ONLY if dir is not the root dir */
+       if (_tcslen (dir) >= 2 && dir[_tcslen (dir) - 1] == _T('\\'))
+               dir[_tcslen(dir) - 1] = _T('\0');
+
+       if (!RemoveDirectory (dir))
+       {
+               ErrorMessage (GetLastError(), _T("RD"));
+               freep (p);
+
+               return 1;
+       }
+
+       freep (p);
+
+       return 0;
+}
+#endif
+
+
+/*
+ * set the exitflag to true
+ *
+ */
+INT internal_exit (LPTSTR cmd, LPTSTR param)
+{
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Exits the command line interpreter.\n\nEXIT"));
+       }
+       else
+       {
+               bExit = TRUE;
+       }
+
+       return 0;
+}
+
+
+#ifdef INCLUDE_CMD_REM
+/*
+ * does nothing
+ *
+ */
+INT cmd_rem (LPTSTR cmd, LPTSTR param)
+{
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Starts a comment line in a batch file.\n\n"
+                                          "REM [Comment]"));
+       }
+
+       return 0;
+}
+#endif
+
+
+INT cmd_showcommands (LPTSTR cmd, LPTSTR param)
+{
+       LPCOMMAND cmdptr;
+       INT y;
+
+       y = 0;
+       cmdptr = cmds;
+       while (cmdptr->name)
+       {
+               if (++y == 8)
+               {
+                       ConOutPuts (cmdptr->name);
+                       y = 0;
+               }
+               else
+                       ConOutPrintf (_T("%-10s"), cmdptr->name);
+
+               cmdptr++;
+       }
+
+       if (y != 0)
+               ConOutChar (_T('\n'));
+
+       return 0;
+}
diff --git a/rosapps/cmd/label.c b/rosapps/cmd/label.c
new file mode 100644 (file)
index 0000000..2854219
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ *  LABEL.C - label internal command.
+ *
+ *
+ *  History:
+ *
+ *    10-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Started.
+ *
+ *    11-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Finished.
+ *
+ *    19-Jan-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_LABEL
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+
+INT cmd_label (LPTSTR cmd, LPTSTR param)
+{
+       TCHAR  szRootPath[] = _T("A:\\");
+       TCHAR  szLabel[80];
+       TCHAR  szOldLabel[80];
+       DWORD  dwSerialNr;
+       LPTSTR *arg;
+       INT    args;
+
+       /* set empty label string */
+       szLabel[0] = _T('\0');
+
+       /* print help */
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Displays or changes drive label.\n\n"
+                                          "LABEL [drive:][label]"));
+               return 0;
+       }
+
+       /* get parameters */
+       arg = split (param, &args);
+
+       if (args > 2)
+       {
+               /* too many parameters */
+               error_too_many_parameters (arg[args - 1]);
+               freep (arg);
+               return 1;
+       }
+
+       if (args == 0)
+       {
+               /* get label of current drive */
+               TCHAR szCurPath[MAX_PATH];
+               GetCurrentDirectory (MAX_PATH, szCurPath);
+               szRootPath[0] = szCurPath[0];
+       }
+       else
+       {
+               if ((_tcslen (arg[0]) >= 2) && (arg[0][1] == _T(':')))
+               {
+                       szRootPath[0] = toupper (*arg[0]);
+                       if (args == 2)
+                               _tcsncpy (szLabel, arg[1], 12);
+               }
+               else
+               {
+                       TCHAR szCurPath[MAX_PATH];
+                       GetCurrentDirectory (MAX_PATH, szCurPath);
+                       szRootPath[0] = szCurPath[0];
+                       _tcsncpy (szLabel, arg[0], 12);
+               }
+       }
+
+       /* check root path */
+       if (!IsValidPathName (szRootPath))
+       {
+               error_invalid_drive ();
+               freep (arg);
+               return 1;
+       }
+
+       GetVolumeInformation (szRootPath, szOldLabel, 80, &dwSerialNr,
+                                                 NULL, NULL, NULL, 0);
+
+       /* print drive info */
+       ConOutPrintf (_T("Volume in drive %c:"), _totupper (szRootPath[0]));
+
+       if (szOldLabel[0] != _T('\0'))
+               ConOutPrintf (_T(" is %s\n"), szOldLabel);
+       else
+               ConOutPrintf (_T(" has no label\n"));
+
+       /* print the volume serial number */
+       ConOutPrintf (_T("Volume Serial Number is %04X-%04X\n"),
+                                 HIWORD(dwSerialNr), LOWORD(dwSerialNr));
+
+       if (szLabel[0] == _T('\0'))
+       {
+               ConOutPrintf (_T("Drive label (11 Characters, ENTER if none)? "));
+               ConInString (szLabel, 80);
+       }
+
+       SetVolumeLabel (szRootPath, szLabel);
+
+       freep (arg);
+
+       return 0;
+}
+
+#endif /* INCLUDE_CMD_LABEL */
\ No newline at end of file
diff --git a/rosapps/cmd/license.txt b/rosapps/cmd/license.txt
new file mode 100644 (file)
index 0000000..c4fb365
--- /dev/null
@@ -0,0 +1,342 @@
+
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+\f
+        Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+
diff --git a/rosapps/cmd/locale.c b/rosapps/cmd/locale.c
new file mode 100644 (file)
index 0000000..b97c971
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ *  LOCALE.C - locale handling.
+ *
+ *
+ *  History:
+ *
+ *    09-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Started.
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+
+TCHAR cDateSeparator;
+TCHAR cTimeSeparator;
+TCHAR cThousandSeparator;
+TCHAR cDecimalSeparator;
+INT   nDateFormat;
+INT   nTimeFormat;
+TCHAR aszDayNames[7][8];
+INT   nNumberGroups;
+
+
+VOID InitLocale (VOID)
+{
+#ifdef LOCALE_WINDOWS
+       TCHAR szBuffer[256];
+       INT i;
+
+       /* date settings */
+       GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_SDATE, szBuffer, 256);
+       CharToOem (szBuffer, szBuffer);
+       cDateSeparator = szBuffer[0];
+       GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_IDATE, szBuffer, 256);
+       nDateFormat = _ttoi (szBuffer);
+
+       /* time settings */
+       GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_STIME, szBuffer, 256);
+       CharToOem (szBuffer, szBuffer);
+       cTimeSeparator = szBuffer[0];
+       GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_ITIME, szBuffer, 256);
+       nTimeFormat = _ttoi (szBuffer);
+
+       /* number settings */
+       GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szBuffer, 256);
+       CharToOem (szBuffer, szBuffer);
+       cThousandSeparator = szBuffer[0];
+       GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, szBuffer, 256);
+       CharToOem (szBuffer, szBuffer);
+       cDecimalSeparator  = szBuffer[0];
+       GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_SGROUPING, szBuffer, 256);
+       nNumberGroups = _ttoi (szBuffer);
+
+       /* days of week */
+       for (i = 0; i < 7; i++)
+       {
+               GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_SABBREVDAYNAME1 + i, szBuffer, 256);
+               CharToOem (szBuffer, szBuffer);
+               _tcscpy (aszDayNames[(i+1)%7], szBuffer); /* little hack */
+       }
+#endif
+
+#ifdef LOCALE_GERMAN
+       LPTSTR names [7] = {_T("So"), _T("Mo"), _T("Di"), _T("Mi"), _T("Do"), _T("Fr"), _T("Sa")};
+       INT i;
+
+       /* date settings */
+       cDateSeparator = '.';
+       nDateFormat    = 1;                     /* ddmmyy */
+
+       /* time settings */
+       cTimeSeparator = ':';
+       nTimeFormat    = 1;                     /* 24 hour */
+
+       /* number settings */
+       cThousandSeparator = '.';
+       cDecimalSeparator  = ',';
+       nNumberGroups      = 3;
+
+       /* days of week */
+       for (i = 0; i < 7; i++)
+               _tcscpy (aszDayNames[i], names[i]);
+#endif
+
+#ifdef LOCALE_DEFAULT
+       LPTSTR names [7] = {_T("Son"), _T("Mon"), _T("Tue"), _T("Wed"), _T("Thu"), _T("Fri"), _T("Sat")};
+       INT i;
+
+       /* date settings */
+       cDateSeparator = '-';
+       nDateFormat = 0;                /* mmddyy */
+
+       /* time settings */
+       cTimeSeparator = ':';
+       nTimeFormat = 0;                /* 12 hour */
+
+       /* number settings */
+       cThousandSeparator = ',';
+       cDecimalSeparator  = '.';
+       nNumberGroups      = 3;
+
+       /* days of week */
+       for (i = 0; i < 7; i++)
+               _tcscpy (aszDayNames[i], names[i]);
+#endif
+}
index 7e36f73..f956db7 100644 (file)
@@ -1,12 +1,29 @@
-all: cmd.bin
+#
+#
 
-OBJECTS = ../common/crt0.o cmd.o
+LIB=../../lib
+COMMON=../common
 
-LIBS = ../../lib/mingw32/mingw32.a ../../lib/crtdll/crtdll.a \
-       ../../lib/kernel32/kernel32.a ../../lib/ntdll/ntdll.a
+# target: raw binary (does not work right now)
+#all: cmd.bin
+
+# target: executable (not tested/experimental)
+all: cmd.exe
+
+OBJECTS = $(COMMON)/crt0.o cmd.o attrib.o alias.o batch.o beep.o call.o cls.o cmdinput.o cmdtable.o\
+        color.o date.o del.o dir.o echo.o err_hand.o error.o filecomp.o for.o goto.o history.o if.o\
+        internal.o label.o misc.o path.o pause.o redir.o ren.o set.o shift.o tempfile.o time.o type.o ver.o\
+        verify.o where.o
+
+LIBS = $(LIB)/mingw32/mingw32.a $(LIB)/crtdll/crtdll.a \
+       $(LIB)/kernel32/kernel32.a $(LIB)/ntdll/ntdll.a
 
 cmd.bin: $(OBJECTS)
        $(LD) -Ttext 0x10000 $(OBJECTS) $(LIBS) -o cmd.exe
        $(OBJCOPY) -O binary cmd.exe cmd.bin
 
+cmd.exe: $(OBJECTS)
+       $(LD) $(OBJECTS) $(LIBS) -o cmd.exe
+
 include ../../rules.mak
+
diff --git a/rosapps/cmd/makefile.lcc b/rosapps/cmd/makefile.lcc
new file mode 100644 (file)
index 0000000..58c114a
--- /dev/null
@@ -0,0 +1,194 @@
+# ReactOS cmd.exe makefile for lcc-win32
+# 19990119 Emanuele Aliberti <ea@iol.it>
+# 19990127 EA
+# 19990128 Eric Kohl <ekohl@abo.rhein-zeitung.de>
+#      Modified for cmd 0.0.4pre3.
+#
+# ReactOS  : http://www.sid-dis.com/reactos/
+# Lcc-Win32: http://www.cs.virginia.edu/*lcc-win32
+#
+TARGET=cmd
+CC=lcc.exe
+CFLAGS=-c -O
+LD=lcclnk.exe
+LFLAGS=-subsystem console -s -o $(TARGET).exe
+OBJS=alias.obj \
+       attrib.obj \
+       batch.obj \
+       beep.obj \
+       call.obj \
+       chcp.obj \
+       cls.obj \
+       cmd.obj \
+       cmdinput.obj \
+       cmdtable.obj \
+       color.obj \
+       console.obj \
+       copy.obj \
+       date.obj \
+       del.obj \
+       dir.obj \
+       dirstack.obj \
+       echo.obj \
+       error.obj \
+       filecomp.obj \
+       for.obj \
+       goto.obj \
+       history.obj \
+       if.obj \
+       internal.obj \
+       label.obj \
+       locale.obj \
+       misc.obj \
+       move.obj \
+       path.obj \
+       pause.obj \
+       prompt.obj \
+       redir.obj \
+       ren.obj \
+       set.obj \
+       shift.obj \
+       time.obj \
+       type.obj \
+       ver.obj \
+       verify.obj \
+       vol.obj \
+       where.obj 
+
+# MAIN
+
+# What about this implicid rule?
+# It should compile all c files.
+# (To test this, uncomment the following two lines.) EK
+#.c.obj:
+#      $(CC) $(CFLAGS) $<
+
+$(TARGET).exe: $(OBJS)
+       $(LD) $(LFLAGS) $(OBJS)
+
+# MODULES
+
+alias.obj: alias.c 
+       $(CC) $(CFLAGS) alias.c
+
+attrib.obj: attrib.c 
+       $(CC) $(CFLAGS) attrib.c
+
+batch.obj: batch.c 
+       $(CC) $(CFLAGS) batch.c
+
+beep.obj: beep.c 
+       $(CC) $(CFLAGS) beep.c
+
+call.obj: call.c 
+       $(CC) $(CFLAGS) call.c
+
+cls.obj: cls.c 
+       $(CC) $(CFLAGS) cls.c
+
+cmd.obj: cmd.c 
+       $(CC) $(CFLAGS) cmd.c
+
+cmdinput.obj: cmdinput.c 
+       $(CC) $(CFLAGS) cmdinput.c
+
+cmdtable.obj: cmdtable.c 
+       $(CC) $(CFLAGS) cmdtable.c
+
+color.obj: color.c 
+       $(CC) $(CFLAGS) color.c
+
+console.obj: console.c 
+       $(CC) $(CFLAGS) console.c
+
+copy.obj: copy.c 
+       $(CC) $(CFLAGS) copy.c
+
+date.obj: date.c 
+       $(CC) $(CFLAGS) date.c
+
+del.obj: del.c 
+       $(CC) $(CFLAGS) del.c
+
+dir.obj: dir.c 
+       $(CC) $(CFLAGS) dir.c
+
+dirstack.obj: dirstack.c 
+       $(CC) $(CFLAGS) dirstack.c
+
+echo.obj: echo.c 
+       $(CC) $(CFLAGS) echo.c
+
+error.obj: error.c 
+       $(CC) $(CFLAGS) error.c
+
+filecomp.obj: filecomp.c 
+       $(CC) $(CFLAGS) filecomp.c
+
+for.obj: for.c 
+       $(CC) $(CFLAGS) for.c
+
+goto.obj: goto.c 
+       $(CC) $(CFLAGS) goto.c
+
+history.obj: history.c 
+       $(CC) $(CFLAGS) history.c
+
+if.obj: if.c 
+       $(CC) $(CFLAGS) if.c
+
+internal.obj: internal.c 
+       $(CC) $(CFLAGS) internal.c
+
+label.obj: label.c 
+       $(CC) $(CFLAGS) label.c
+
+locale.obj: locale.c 
+       $(CC) $(CFLAGS) locale.c
+
+misc.obj: misc.c 
+       $(CC) $(CFLAGS) misc.c
+
+move.obj: move.c 
+       $(CC) $(CFLAGS) move.c
+
+path.obj: path.c 
+       $(CC) $(CFLAGS) path.c
+
+pause.obj: pause.c 
+       $(CC) $(CFLAGS) pause.c
+
+prompt.obj: prompt.c 
+       $(CC) $(CFLAGS) prompt.c
+
+redir.obj: redir.c 
+       $(CC) $(CFLAGS) redir.c
+
+ren.obj: ren.c 
+       $(CC) $(CFLAGS) ren.c
+
+set.obj: set.c 
+       $(CC) $(CFLAGS) set.c
+
+shift.obj: shift.c 
+       $(CC) $(CFLAGS) shift.c
+
+time.obj: time.c 
+       $(CC) $(CFLAGS) time.c
+
+type.obj: type.c 
+       $(CC) $(CFLAGS) type.c
+
+ver.obj: ver.c 
+       $(CC) $(CFLAGS) ver.c
+
+verify.obj: verify.c 
+       $(CC) $(CFLAGS) verify.c
+
+vol.obj: vol.c 
+       $(CC) $(CFLAGS) vol.c
+
+where.obj: where.c 
+       $(CC) $(CFLAGS) where.c
+
+#EOF
diff --git a/rosapps/cmd/misc.c b/rosapps/cmd/misc.c
new file mode 100644 (file)
index 0000000..1eb5ca4
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ *  MISC.C - misc. functions.
+ *
+ *
+ *  History:
+ *
+ *    07/12/98 (Rob Lake)
+ *        started
+ *
+ *    07/13/98 (Rob Lake)
+ *        moved functions in here
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    18-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Changed split() to accept quoted arguments.
+ *        Removed parse_firstarg().
+ *
+ *    23-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Fixed an ugly bug in split(). In rare cases (last character
+ *        of the string is a space) it ignored the NULL character and
+ *        tried to add the following to the argument list.
+ *
+ *    28-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        FileGetString() seems to be working now.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <conio.h>
+
+#include "cmd.h"
+
+
+/*
+ * get a character out-of-band and honor Ctrl-Break characters
+ */
+TCHAR cgetchar (VOID)
+{
+       TCHAR ch;
+#if 0
+       DWORD dwRead;
+       DWORD dwOldMode;
+       HANDLE hIn;
+
+       hIn = GetStdHandle (STD_INPUT_HANDLE);
+       ConInSwallowInput (hIn);
+
+       GetConsoleMode (hIn, &dwOldMode);
+       SetConsoleMode (hIn, 0);
+
+       ReadConsole (hIn, &ch, 1, &dwRead, NULL);
+
+       DebugPrintf ("[cgetchar (0x%x) \'%c\']\n", ch, ch);
+
+       SetConsoleMode (hIn, dwOldMode);
+#endif
+
+       if ((ch = getch()) == 0)
+               ch = getch() << 8;
+
+       if (ch == 3)
+               bCtrlBreak = TRUE;
+
+       return ch;
+}
+
+
+/*
+ * Check if Ctrl-Break was pressed during the last calls
+ */
+
+BOOL CheckCtrlBreak (INT mode)
+{
+       static BOOL bLeaveAll = FALSE; /* leave all batch files */
+       TCHAR c;
+
+       switch (mode)
+       {
+               case BREAK_OUTOFBATCH:
+                       bLeaveAll = 0;
+                       return FALSE;
+
+               case BREAK_BATCHFILE:
+                       if (bLeaveAll)
+                               return TRUE;
+
+                       if (!bCtrlBreak)
+                               return FALSE;
+
+                       /* we need to be sure the string arrives on the screen! */
+                       do
+                               ConOutPuts (_T("\r\nCtrl-Break pressed.  Cancel batch file? (Yes/No/All) "));
+                       while (!_tcschr ("YNA\3", c = _totupper (cgetchar())) || !c);
+
+                       ConOutPuts (_T("\r\n"));
+
+                       if (c == _T('N'))
+                               return bCtrlBreak = FALSE; /* ignore */
+
+                       /* leave all batch files */
+                       bLeaveAll = ((c == _T('A')) || (c == _T('\3')));
+                       break;
+
+               case BREAK_INPUT:
+                       if (!bCtrlBreak)
+                               return FALSE;
+                       break;
+       }
+
+       /* state processed */
+       bCtrlBreak = FALSE;
+       return TRUE;
+}
+
+
+/*
+ * split - splits a line up into separate arguments, deliminators
+ *         are spaces and slashes ('/').
+ */
+
+LPTSTR *split (LPTSTR s, LPINT args)
+{
+       LPTSTR *arg;
+       LPTSTR *p;
+       LPTSTR start;
+       LPTSTR q;
+       INT  ac;
+       INT  len;
+       BOOL bQuoted = FALSE;
+
+       arg = malloc (sizeof (LPTSTR));
+       if (!arg)
+               return NULL;
+       *arg = NULL;
+
+       ac = 0;
+       while (*s)
+       {
+               /* skip leading spaces */
+               while (*s && (_istspace (*s) || _istcntrl (*s)))
+                       ++s;
+
+               /* if quote (") then set bQuoted */
+               if (*s == _T('\"'))
+               {
+                       ++s;
+                       bQuoted = TRUE;
+               }
+
+               start = s;
+
+               /* the first character can be '/' */
+               if (*s == _T('/'))
+                       ++s;
+
+               /* skip to next word delimiter or start of next option */
+               if (bQuoted)
+               {
+                       while (_istprint (*s) && (*s != _T('\"')) && (*s != _T('/')))
+                               ++s;
+               }
+               else
+               {
+                       while (_istprint (*s) && !_istspace (*s) && (*s != _T('/')))
+                               ++s;
+               }
+
+               /* a word was found */
+               if (s != start)
+               {
+                       /* add new entry for new argument */
+                       arg = realloc (p = arg, (ac + 2) * sizeof (LPTSTR));
+                       if (!arg)
+                       {
+                               freep (p);
+                               return NULL;
+                       }
+
+                       /* create new entry */
+                       q = arg[ac] = malloc (((len = s - start) + 1) * sizeof (TCHAR));
+                       arg[++ac] = NULL;
+                       if (!q)
+                       {
+                               freep (arg);
+                               return NULL;
+                       }
+                       memcpy (q, start, len * sizeof (TCHAR));
+                       q[len] = _T('\0');
+               }
+
+               /* adjust string pointer if quoted (") */
+               if (bQuoted)
+               {
+                       ++s;
+                       bQuoted = FALSE;
+               }
+       }
+
+       *args = ac;
+
+       return arg;
+}
+
+
+/*
+ * freep -- frees memory used for a call to split
+ *
+ */
+VOID freep (LPTSTR *p)
+{
+       LPTSTR *q;
+
+       if (!p)
+               return;
+
+       q = p;
+       while (*q)
+               free(*q++);
+
+       free(p);
+}
+
+
+LPTSTR stpcpy (LPTSTR dest, LPTSTR src)
+{
+       _tcscpy (dest, src);
+       return (dest + _tcslen (src));
+}
+
+
+
+/*
+ * Checks if a path is valid (accessible)
+ */
+
+BOOL IsValidPathName (LPCTSTR pszPath)
+{
+       TCHAR szOldPath[MAX_PATH];
+       BOOL  bResult;
+
+       GetCurrentDirectory (MAX_PATH, szOldPath);
+       bResult = SetCurrentDirectory (pszPath);
+
+       SetCurrentDirectory (szOldPath);
+
+       return bResult;
+}
+
+
+/*
+ * Checks if a file exists (accessible)
+ */
+
+BOOL IsValidFileName (LPCTSTR pszPath)
+{
+       return (GetFileAttributes (pszPath) != 0xFFFFFFFF);
+}
+
+
+
+BOOL FileGetString (HANDLE hFile, LPTSTR lpBuffer, INT nBufferLength)
+{
+       LPTSTR lpString;
+       TCHAR  ch;
+       DWORD  dwRead;
+
+       lpString = lpBuffer;
+
+       while ((--nBufferLength >  0) &&
+                  ReadFile(hFile, &ch, 1, &dwRead, NULL) && dwRead)
+       {
+               *lpString++ = ch;
+               if (ch == _T('\r'))
+               {
+                       /* overread '\n' */
+                       ReadFile (hFile, &ch, 1, &dwRead, NULL);
+                       break;
+               }
+       }
+
+       if (!dwRead && lpString == lpBuffer)
+               return FALSE;
+
+       *lpString++ = _T('\0');
+
+       return TRUE;
+}
diff --git a/rosapps/cmd/move.c b/rosapps/cmd/move.c
new file mode 100644 (file)
index 0000000..54158d7
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ *  MOVE.C - move internal command.
+ *
+ *
+ *  History:
+ *
+ *    14-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Started.
+ *
+ *    18-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode safe!
+ *        Preliminary version!!!
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Redirection safe!
+ *
+ *    27-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("/?").
+ *        Added more error checks.
+ *
+ *    03-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added "/N" option.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_MOVE
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+
+#define OVERWRITE_NO     0
+#define OVERWRITE_YES    1
+#define OVERWRITE_ALL    2
+#define OVERWRITE_CANCEL 3
+
+
+static INT Overwrite (LPTSTR fn)
+{
+       TCHAR inp[10];
+       LPTSTR p;
+
+       ConOutPrintf (_T("Overwrite %s (Yes/No/All)? "), fn);
+       ConInString (inp, 10);
+
+       _tcsupr (inp);
+       for (p=inp; _istspace (*p); p++)
+               ;
+
+       if (*p != _T('Y') && *p != _T('A'))
+               return OVERWRITE_NO;
+       if (*p == _T('A'))
+               return OVERWRITE_ALL;
+
+       return OVERWRITE_YES;
+}
+
+
+
+INT cmd_move (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR *arg;
+       INT argc, i, nFiles;
+       TCHAR szDestPath[MAX_PATH];
+       TCHAR szSrcPath[MAX_PATH];
+       BOOL bPrompt = TRUE;
+       LPTSTR p;
+       WIN32_FIND_DATA findBuffer;
+       HANDLE hFile;
+       LPTSTR pszFile;
+       BOOL   bNothing = FALSE;
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+#if 0
+               ConOutPuts (_T("Moves files and renames files and directories.\n\n"
+                                          "To move one or more files:\n"
+                                          "MOVE [/N][/Y|/-Y][drive:][path]filename1[,...] destination\n"
+                                          "\n"
+                                          "To rename a directory:\n"
+                                          "MOVE [/N][/Y|/-Y][drive:][path]dirname1 dirname2\n"
+                                          "\n"
+                                          "  [drive:][path]filename1  Specifies the location and name of the file\n"
+                                          "                           or files you want to move.\n"
+                                          "  /N                       Nothing. Don everthing but move files or direcories.\n"
+                                          "  /Y\n"
+                                          "  /-Y\n"
+                                          "..."));
+#else
+               ConOutPuts (_T("Moves files and renames files and directories.\n\n"
+                                          "To move one or more files:\n"
+                                          "MOVE [/N][drive:][path]filename1[,...] destination\n"
+                                          "\n"
+                                          "To rename a directory:\n"
+                                          "MOVE [/N][drive:][path]dirname1 dirname2\n"
+                                          "\n"
+                                          "  [drive:][path]filename1  Specifies the location and name of the file\n"
+                                          "                           or files you want to move.\n"
+                                          "  /N                       Nothing. Don everthing but move files or direcories.\n"
+                                          "\n"
+                                          "Current limitations:\n"
+                                          "  - You can't move a file or directory from one drive to another.\n"
+                                          ));
+#endif
+               return 0;
+       }
+
+       arg = split (param, &argc);
+       nFiles = argc;
+
+       /* read options */
+       for (i = 0; i < argc; i++)
+       {
+               p = arg[i];
+
+               if (*p == _T('/'))
+               {
+                       p++;
+                       if (*p == _T('-'))
+                       {
+                               p++;
+                               if (_totupper (*p) == _T('Y'))
+                                       bPrompt = TRUE;
+                       }
+                       else
+                       {
+                               if (_totupper (*p) == _T('Y'))
+                                       bPrompt = FALSE;
+                               else if  (_totupper (*p) == _T('N'))
+                                       bNothing = TRUE;
+                       }
+                       nFiles--;
+               }
+       }
+
+       if (nFiles < 2)
+       {
+               /* there must be at least two pathspecs */
+               error_req_param_missing ();
+               return 1;
+       }
+
+       /* get destination */
+       GetFullPathName (arg[argc - 1], MAX_PATH, szDestPath, NULL);
+#ifdef _DEBUG
+       DebugPrintf (_T("Destination: %s\n"), szDestPath);
+#endif
+
+       /* move it*/
+       for (i = 0; i < argc - 1; i++)
+       {
+               if (*arg[i] == _T('/'))
+                       continue;
+
+               hFile = FindFirstFile (arg[i], &findBuffer);
+               if (hFile == INVALID_HANDLE_VALUE)
+               {
+                       ErrorMessage (GetLastError (), arg[i]);
+                       freep (arg);
+                       return 1;
+               }
+
+               do
+               {
+                       GetFullPathName (findBuffer.cFileName, MAX_PATH, szSrcPath, &pszFile);
+
+                       if (GetFileAttributes (szSrcPath) & FILE_ATTRIBUTE_DIRECTORY)
+                       {
+                               /* source is directory */
+
+#ifdef _DEBUG
+                               DebugPrintf (_T("Move directory \'%s\' to \'%s\'\n"),
+                                                        szSrcPath, szDestPath);
+#endif
+                               if (!bNothing)
+                               {
+                                       MoveFile (szSrcPath, szDestPath);
+                               }
+                       }
+                       else
+                       {
+                               /* source is file */
+
+                               if (IsValidFileName (szDestPath))
+                               {
+                                       /* destination exists */
+                                       if (GetFileAttributes (szDestPath) & FILE_ATTRIBUTE_DIRECTORY)
+                                       {
+                                               /* destination is existing directory */
+
+                                               TCHAR szFullDestPath[MAX_PATH];
+
+                                               _tcscpy (szFullDestPath, szDestPath);
+                                               _tcscat (szFullDestPath, _T("\\"));
+                                               _tcscat (szFullDestPath, pszFile);
+
+                                               ConOutPrintf (_T("%s => %s"), szSrcPath, szFullDestPath);
+
+                                               if (!bNothing)
+                                               {
+                                                       if (MoveFile (szSrcPath, szFullDestPath))
+                                                               ConOutPrintf (_T("[OK]\n"));
+                                                       else
+                                                               ConOutPrintf (_T("[Error]\n"));
+                                               }
+                                       }
+                                       else
+                                       {
+                                               /* destination is existing file */
+                                               INT nOverwrite;
+
+                                               /* must get the overwrite code */
+                                               if ((nOverwrite = Overwrite (szDestPath)))
+                                               {
+#if 0
+                                                       if (nOverwrite == OVERWRITE_ALL)
+                                                               *lpFlags |= FLAG_OVERWRITE_ALL;
+#endif
+                                                       ConOutPrintf (_T("%s => %s"), szSrcPath, szDestPath);
+
+                                                       if (!bNothing)
+                                                       {
+                                                               if (MoveFile (szSrcPath, szDestPath))
+                                                                       ConOutPrintf (_T("[OK]\n"));
+                                                               else
+                                                                       ConOutPrintf (_T("[Error]\n"));
+                                                       }
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       /* destination does not exist */
+                                       TCHAR szFullDestPath[MAX_PATH];
+
+                                       GetFullPathName (szDestPath, MAX_PATH, szFullDestPath, NULL);
+
+                                       ConOutPrintf (_T("%s => %s"), szSrcPath, szFullDestPath);
+
+                                       if (!bNothing)
+                                       {
+                                               if (MoveFile (szSrcPath, szFullDestPath))
+                                                       ConOutPrintf (_T("[OK]\n"));
+                                               else
+                                                       ConOutPrintf (_T("[Error]\n"));
+                                       }
+                               }
+                       }
+               }
+               while (FindNextFile (hFile, &findBuffer));
+
+               FindClose (hFile);
+       }
+
+
+       freep (arg);
+
+       return 0;
+}
+
+#endif /* INCLUDE_CMD_MOVE */
\ No newline at end of file
diff --git a/rosapps/cmd/path.c b/rosapps/cmd/path.c
new file mode 100644 (file)
index 0000000..714ee38
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ *  PATH.C - path internal command.
+ *
+ *
+ *  History:
+ *
+ *    17 Jul 1998 (John P Price)
+ *        Separated commands into individual files.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    09-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("/?").
+ *
+ *    18-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode ready!
+ *
+ *    18-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Redirection safe!
+ *
+ *    24-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Fixed Win32 environment handling.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_PATH
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+
+/* size of environment variable buffer */
+#define ENV_BUFFER_SIZE 1024
+
+
+INT cmd_path (LPTSTR cmd, LPTSTR param)
+{
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Displays or sets a search path for executable files.\n\n"
+                                  "PATH [[drive:]path[;...]]\nPATH ;\n\n"
+                                  "Type PATH ; to clear all search-path settings and direct the command shell\n"
+                                  "to search only in the current directory.\n"
+                                  "Type PATH without parameters to display the current path.\n"));
+               return 0;
+       }
+
+       /* if param is empty, display the PATH environment variable */
+       if (!param || !*param)
+       {
+               DWORD  dwBuffer;
+               LPTSTR pszBuffer;
+
+               pszBuffer = (LPTSTR)malloc (ENV_BUFFER_SIZE * sizeof(TCHAR));
+               dwBuffer = GetEnvironmentVariable (_T("PATH"), pszBuffer, ENV_BUFFER_SIZE);
+               if (dwBuffer == 0)
+               {
+                       ConErrPrintf ("CMD: Not in environment \"PATH\"\n");
+                       return 0;
+               }
+               else if (dwBuffer > ENV_BUFFER_SIZE)
+               {
+                       pszBuffer = (LPTSTR)realloc (pszBuffer, dwBuffer * sizeof (TCHAR));
+                       GetEnvironmentVariable (_T("PATH"), pszBuffer, ENV_BUFFER_SIZE);
+               }
+
+               ConOutPrintf (_T("PATH=%s\n"), pszBuffer);
+               free (pszBuffer);
+
+               return 0;
+       }
+
+       /* set PATH environment variable */
+       if (!SetEnvironmentVariable (_T("PATH"), param))
+               return 1;
+
+       return 0;
+}
+
+#endif
diff --git a/rosapps/cmd/pause.c b/rosapps/cmd/pause.c
new file mode 100644 (file)
index 0000000..f4c01bb
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ *  PAUSE.C - pause internal command.
+ *
+ *
+ *  History:
+ *
+ *    16 Jul 1998 (Hans B Pufal)
+ *        started.
+ *
+ *    16 Jul 1998 (John P Price)
+ *        Seperated commands into individual files.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    18-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_PAUSE
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+/*
+ * Perform PAUSE command.
+ *
+ * FREEDOS extension : If parameter is specified use that as the pause
+ *   message.
+ *
+ * ?? Extend to include functionality of CHOICE if switch chars
+ *     specified.
+ */
+
+INT cmd_pause (LPTSTR cmd, LPTSTR param)
+{
+#ifdef _DEBUG
+       DebugPrintf ("cmd_pause: \'%s\' : \'%s\'\n", cmd, param);
+#endif
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Stops the execution of a batch file and shows the following message:\n"
+                                          "\"Press any key to continue...\" or a user defined message.\n\n"
+                                          "PAUSE [message]"));
+               return 0;
+       }
+
+       if (*param)
+               ConOutPrintf (param);
+       else
+               msg_pause ();
+
+       cgetchar ();
+
+       return 0;
+}
+
+#endif
diff --git a/rosapps/cmd/prompt.c b/rosapps/cmd/prompt.c
new file mode 100644 (file)
index 0000000..fa674f1
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ *  PROMPT.C - prompt handling.
+ *
+ *
+ *  History:
+ *
+ *    14/01/95 (Tim Normal)
+ *        started.
+ *
+ *    08/08/95 (Matt Rains)
+ *        i have cleaned up the source code. changes now bring this source
+ *        into guidelines for recommended programming practice.
+ *
+ *    01/06/96 (Tim Norman)
+ *        added day of the week printing (oops, forgot about that!)
+ *
+ *    08/07/96 (Steffan Kaiser)
+ *        small changes for speed
+ *
+ *    20-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        removed redundant day strings. Use ones defined in date.c.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    28-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        moved cmd_prompt from internal.c to here
+ *
+ *    09-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("/?").
+ *
+ *    14-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added "$+" option.
+ *
+ *    09-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added "$A", "$C" and "$F" option.
+ *        Added locale support.
+ *        Fixed "$V" option.
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection safe!
+ *
+ *    24-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Fixed Win32 environment handling.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+
+/*
+ * print the command-line prompt
+ *
+ */
+VOID PrintPrompt(VOID)
+{
+       static TCHAR default_pr[] = _T("$P$G");
+       TCHAR  szPrompt[256];
+       LPTSTR pr;
+
+       if (GetEnvironmentVariable (_T("PROMPT"), szPrompt, 256))
+               pr = szPrompt;
+       else
+               pr = default_pr;
+
+       while (*pr)
+       {
+               if (*pr != _T('$'))
+               {
+                       ConOutChar (*pr);
+               }
+               else
+               {
+                       pr++;
+
+                       switch (_totupper (*pr))
+                       {
+                               case _T('A'):
+                                       ConOutChar (_T('&'));
+                                       break;
+
+                               case _T('B'):
+                                       ConOutChar (_T('|'));
+                                       break;
+
+                               case _T('C'):
+                                       ConOutChar (_T('('));
+                                       break;
+
+                               case _T('D'):
+                                       {
+                                               TCHAR szDate[32];
+
+                                               GetDateFormat (LOCALE_USER_DEFAULT, DATE_SHORTDATE,
+                                                                          NULL, NULL, szDate, sizeof (szDate));
+                                               ConOutPrintf (_T("%s"), szDate);
+                                       }
+                                       break;
+
+                               case _T('E'):
+                                       ConOutChar (_T('\x1B'));
+                                       break;
+
+                               case _T('F'):
+                                       ConOutChar (_T(')'));
+                                       break;
+
+                               case _T('G'):
+                                       ConOutChar (_T('>'));
+                                       break;
+
+                               case _T('H'):
+                                       ConOutChar (_T('\x08'));
+                                       break;
+
+                               case _T('L'):
+                                       ConOutChar (_T('<'));
+                                       break;
+
+                               case _T('N'):
+                                       {
+                                               TCHAR szPath[MAX_PATH];
+                                               GetCurrentDirectory (MAX_PATH, szPath);
+                                               ConOutChar (szPath[0]);
+                                       }
+                                       break;
+
+                               case _T('P'):
+                                       {
+                                               TCHAR szPath[MAX_PATH];
+                                               GetCurrentDirectory (MAX_PATH, szPath);
+                                               ConOutPrintf (_T("%s"), szPath);
+                                       }
+                                       break;
+
+                               case _T('Q'):
+                                       ConOutChar (_T('='));
+                                       break;
+
+                               case _T('T'):
+                                       {
+                                               TCHAR szTime[32];
+                                               GetTimeFormat (LOCALE_USER_DEFAULT, 0, NULL,
+                                                                          NULL, szTime, sizeof (szTime));
+                                               ConOutPrintf (_T("%s"), szTime);
+                                       }
+                                       break;
+
+                               case _T('V'):
+                                       switch (osvi.dwPlatformId)
+                                       {
+                                               case VER_PLATFORM_WIN32_WINDOWS:
+                                                       if (osvi.dwMajorVersion == 4 &&
+                                                               osvi.dwMinorVersion == 1)
+                                                               ConOutPrintf (_T("Windows 98"));
+                                                       else
+                                                               ConOutPrintf (_T("Windows 95"));
+                                                       break;
+
+                                               case VER_PLATFORM_WIN32_NT:
+                                                       ConOutPrintf (_T("Windows NT Version %lu.%lu"),
+                                                                                 osvi.dwMajorVersion, osvi.dwMinorVersion);
+                                                       break;
+                                       }
+                                       break;
+
+                               case _T('_'):
+                                       ConOutChar (_T('\n'));
+                                       break;
+
+                               case '$':
+                                       ConOutChar (_T('$'));
+                                       break;
+
+#ifdef FEATURE_DIRECTORY_STACK
+                               case '+':
+                                       {
+                                               INT i;
+                                               for (i = 0; i < GetDirectoryStackDepth (); i++)
+                                                       ConOutChar (_T('+'));
+                                       }
+                                       break;
+#endif
+                       }
+               }
+               pr++;
+       }
+}
+
+
+#ifdef INCLUDE_CMD_PROMPT
+
+INT cmd_prompt (LPTSTR cmd, LPTSTR param)
+{
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Changes the command prompt.\n\n"
+                         "PROMPT [text]\n\n"
+                         "  text    Specifies a new command prompt.\n\n"
+                         "Prompt can be made up of normal characters and the following special codes:\n\n"
+                         "  $A   & (Ampersand)\n"
+                         "  $B   | (pipe)\n"
+                         "  $C   ( (Left parenthesis)\n"
+                         "  $D   Current date\n"
+                         "  $E   Escape code (ASCII code 27)\n"
+                         "  $F   ) (Right parenthesis)\n"
+                         "  $G   > (greater-than sign)\n"
+                         "  $H   Backspace (erases previous character)\n"
+                         "  $L   < (less-than sign)\n"
+                         "  $N   Current drive\n"
+                         "  $P   Current drive and path\n"
+                         "  $Q   = (equal sign)\n"
+                         "  $T   Current time\n"
+                         "  $V   OS version number\n"
+                         "  $_   Carriage return and linefeed\n"
+                         "  $$   $ (dollar sign)"));
+#ifdef FEATURE_DIRECTORY_STACK
+               ConOutPuts (_T("  $+   Displays the current depth of the directory stack"));
+#endif
+               ConOutPuts (_T("\nType PROMPT without parameters to reset the prompt to the default setting."));
+               return 0;
+       }
+
+       /* set PROMPT environment variable */
+       if (!SetEnvironmentVariable (_T("PROMPT"), param))
+               return 1;
+
+       return 0;
+}
+#endif
diff --git a/rosapps/cmd/readme.txt b/rosapps/cmd/readme.txt
new file mode 100644 (file)
index 0000000..b76a3a7
--- /dev/null
@@ -0,0 +1,101 @@
+ReactOS Command Line Interface "CMD" version 0.0.4
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is the fourth pre-alpha release of CMD.EXE for ReactOS.
+It was converted from the FreeDOS COMMAND.COM.
+
+
+Warning!! Warning!! Warning!!
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This is a pre-alpha version! Many features have not been tested!
+Be careful when you use commands that write to your disk drives,
+they might destroy your files or the file system!!!
+
+
+Status
+~~~~~~
+This is a converted version of FreeDOS COMMAND.COM.
+I added some commands from WinNT's CMD.EXE.
+
+
+New features and improvements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  - Fixed redirection and piping.
+    (E.g. you can use "type > file" now.)
+  - Added new error redirections "2>" and "2>>".
+    (E.g.: "make 2>error.log")
+  - Added CHCP command.
+  - Fixed environment handling.
+  - New makefile for lcc-win (makefile.lcc).
+  - Rewrote DEL and MOVE with a new structure.
+  - Improved national language support.
+  - Fixed filename completion.
+
+
+Compiling
+~~~~~~~~~
+I converted CMD using MS Visual C++ 5.0 and Win95. The included makefile
+is just an experimental version.
+
+If you want to compile and test CMD with djgpp, modify the makefile as needed.
+I put the CMD sources into [reactos\apps], the makefile is written for that
+directory.
+
+If you want to compile and test CMD using another compiler, just create
+a new console application project and add all *.c and *.h files to it.
+It should compile without an error.
+
+
+Please report bugs which are not listed above.
+
+
+Good luck
+
+  Eric Kohl <ekohl@abo.rhein-zeitung.de>
+
+
+
+
+FreeDOS Command Line Interface
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+About
+~~~~~
+This software is part of the FreeDOS project. Please email
+freedos@sunsite.unc.edu for more information, or visit the freedos
+archive at "ftp://sunsite.unc.edu/pub/micro/pc-stuff/freedos".  Also,
+visit our web page at http://www.freedos.org/.
+
+The command.com web site is at
+
+   http://www.gcfl.net/FreeDOS/command.com/
+
+
+This software has been developed by the following people:
+(listed in approximate chronological order of contributions)
+
+FreeDOS developers:
+   normat@rpi.edu (Tim Norman)
+   mrains@apanix.apana.org.au (Matt Rains)
+   ejeffrey@iastate.edu (Evan Jeffrey)
+   Steffen.Kaiser@Informatik.TU-Chemnitz.DE (Steffen Kaiser)
+   Svante Frey (sfrey@kuai.se)
+   Oliver Mueller (ogmueller@t-online.de)
+   Aaron Kaufman (morgan@remarque.berkeley.edu)
+   Marc Desrochers (bitzero@hotmail.com)
+   Rob Lake (rlake@cs.mun.ca)
+   John P. Price <linux-guru@gcfl.net>
+   Hans B Pufal <hansp@digiweb.com>
+
+ReactOS developers:
+   Eric Kohl <ekohl@abo.rhein-zeitung.de>
+
+
+Current Features
+~~~~~~~~~~~~~~~~
+ - environment handling with prompt and path support.
+ - directory utilities.
+ - command-line history with doskey-like features.
+ - batch file processing.
+ - input/output redirection and piping.
+ - alias support.
+ - filename completion (use TAB)
diff --git a/rosapps/cmd/redir.c b/rosapps/cmd/redir.c
new file mode 100644 (file)
index 0000000..594bc11
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ *  REDIR.C - redirection handling.
+ *
+ *
+ *  History:
+ *
+ *    12/15/95 (Tim Norman)
+ *        started.
+ *
+ *    12 Jul 98 (Hans B Pufal)
+ *        Rewrote to make more efficient and to conform to new command.c
+ *        and batch.c processing.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        Added config.h include
+ *
+ *    22-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode safe!
+ *        Added new error redirection "2>" and "2>>".
+ *
+ *    26-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added new error AND output redirection "&>" and "&>>".
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef FEATURE_REDIRECTION
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "cmd.h"
+
+
+static BOOL
+IsRedirection (TCHAR c)
+{
+       return (c == _T('<')) || (c == _T('>')) || (c == _T('|'));
+}
+
+
+/*
+ * Gets the redirection info from the command line and copies the
+ * file names into ifn, ofn and efn removing them from the command
+ * line.
+ *
+ * Converts remaining command line into a series of null terminated
+ * strings defined by the pipe char '|'. Each string corresponds
+ * to a single executable command. A double null terminates the
+ * command strings.
+ *
+ * Return number of command strings found.
+ *
+ */
+
+INT GetRedirection (LPTSTR s, LPTSTR ifn, LPTSTR ofn, LPTSTR efn, LPINT lpnFlags)
+{
+       INT num = 1;
+       LPTSTR dp = s;
+       LPTSTR sp = s;
+
+       /* find and remove all the redirections first */
+       while (*sp)
+       {
+               if ((*sp == _T('"')) || (*sp == _T('\'')))
+               {
+                       /* No redirects inside quotes */
+                       TCHAR qc = *sp;
+
+                       do
+                               *dp++ = *sp++;
+                       while (*sp != qc);
+
+                       *dp++ = *sp++;
+               }
+               else if ((*sp == _T('<')) || (*sp == _T('>')) ||
+                                (*sp == _T('2')) || (*sp == _T('&')))
+               {
+                       /* MS-DOS ignores multiple redirection symbols and uses the last */
+                       /* redirection, so we'll emulate that and not check */
+
+                       if (*sp == _T('<'))
+                       {
+                               /* input redirection */
+                               *lpnFlags |= INPUT_REDIRECTION;
+                               while (_istspace (*sp))
+                                       sp++;
+
+                               /* copy file name */
+                               while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
+                                       *ifn++ = *sp++;
+                               *ifn = _T('\0');
+                       }
+                       else if (*sp == _T('>'))
+                       {
+                               /* output redirection */
+                               *lpnFlags |= OUTPUT_REDIRECTION;
+                               sp++;
+
+                               /* append request ? */
+                               if (*sp == _T('>'))
+                               {
+                                       *lpnFlags |= OUTPUT_APPEND;
+                                       sp++;
+                               }
+
+                               while (_istspace (*sp))
+                                       sp++;
+
+                               /* copy file name */
+                               while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
+                                       *ofn++ = *sp++;
+                               *ofn = _T('\0');
+                       }
+                       else if (*sp == _T('2'))
+                       {
+                               /* error redirection */
+                               sp++;
+
+                               if (*sp == _T('>'))
+                               {
+                                       *lpnFlags |= ERROR_REDIRECTION;
+                                       sp++;
+
+                                       /* append request ? */
+                                       if (*sp == _T('>'))
+                                       {
+                                               *lpnFlags |= ERROR_APPEND;
+                                               sp++;
+                                       }
+                               }
+                               else
+                               {
+                                       /* no redirection!! copy the '2' character! */
+                                       sp--;
+                                       *dp++ = *sp++;
+                                       continue;
+                               }
+
+                               while (_istspace (*sp))
+                                       sp++;
+
+                               /* copy file name */
+                               while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
+                                       *efn++ = *sp++;
+                               *efn = _T('\0');
+                       }
+                       else if (*sp == _T('&'))
+                       {
+                               /* output AND error redirection */
+                               sp++;
+
+                               if (*sp == _T('>'))
+                               {
+                                       *lpnFlags |= (ERROR_REDIRECTION | OUTPUT_REDIRECTION);
+                                       sp++;
+
+                                       /* append request ? */
+                                       if (*sp == _T('>'))
+                                       {
+                                               *lpnFlags |= (ERROR_APPEND | OUTPUT_APPEND);
+                                               sp++;
+                                       }
+                               }
+                               else
+                               {
+                                       /* no redirection!! copy the '&' character! */
+                                       sp--;
+                                       *dp++ = *sp++;
+                                       continue;
+                               }
+
+                               while (_istspace (*sp))
+                                       sp++;
+
+                               /* copy file name */
+                               while (*sp && !IsRedirection (*sp) && !_istspace (*sp))
+                                       *ofn++ = *efn++ = *sp++;
+                               *ofn = *efn = _T('\0');
+                       }
+               }
+               else
+                       *dp++ = *sp++;
+       }
+       *dp++ = _T('\0');
+       *dp = _T('\0');
+
+       /* now go for the pipes */
+       sp = s;
+       while (*sp)
+       {
+               if ((*sp == _T('"')) || (*sp == _T('\'')))
+               {
+                       TCHAR qc = *sp;
+
+                       do
+                               sp++;
+                       while (*sp != qc);
+
+                       sp++;
+               }
+               else if (*sp == _T('|'))
+               {
+                       *sp++ = '\0';
+                       num++;
+               }
+               else
+                       sp++;
+       }
+
+       return num;
+}
+
+#endif /* FEATURE_REDIRECTION */
diff --git a/rosapps/cmd/ren.c b/rosapps/cmd/ren.c
new file mode 100644 (file)
index 0000000..2023d07
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ *  REN.C - rename internal command.
+ *
+ *
+ *  History:
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    18-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>
+ *        Added support for quoted long file names with spaces.
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>
+ *        Unicode and redirection safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_RENAME
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+/*
+ *  simple file rename internal command.
+ *
+ */
+INT cmd_rename (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR *arg;
+       INT    argc;
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Renames a file/directory or files/directories.\n"
+                                          "\n"
+                                          "RENAME [drive:][path][directoryname1 | filename1] [directoryname2 | filename2]\n"
+                                          "REN [drive:][path][directoryname1 | filename1] [directoryname2 | filename2]\n"
+                                          "\n"
+                                          "Note that you cannot specify a new drive or path for your destination. Use\n"
+                                          "the MOVE command for that purpose."));
+               return 0;
+       }
+
+       /* split the argument list */
+       arg = split (param, &argc);
+
+       if (argc != 2)
+       {
+               freep (arg);
+               error_too_many_parameters (param);
+               return 1;
+       }
+
+       if (!MoveFile (arg[0], arg[1]))
+       {
+               ConErrPuts (_T("rename"));
+               freep (arg);
+               return 1;
+       }
+
+       freep (arg);
+
+       return 0;
+}
+
+#endif
diff --git a/rosapps/cmd/set.c b/rosapps/cmd/set.c
new file mode 100644 (file)
index 0000000..7be3388
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ *  SET.C - set internal command.
+ *
+ *
+ *  History:
+ *
+ *    06/14/97 (Tim Norman)
+ *        changed static var in set() to a malloc'd space to pass to putenv.
+ *        need to find a better way to do this, since it seems it is wasting
+ *        memory when variables are redefined.
+ *
+ *    07/08/1998 (John P. Price)
+ *        removed call to show_environment in set command.
+ *        moved test for syntax before allocating memory in set command.
+ *        misc clean up and optimization.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    28-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added set_env function to set env. variable without needing set command
+ *
+ *    09-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("/?").
+ *
+ *    24-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Fixed Win32 environment handling.
+ *        Unicode and redirection safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_SET
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+
+/* size of environment variable buffer */
+#define ENV_BUFFER_SIZE  1024
+
+
+INT cmd_set (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR p;
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Displays, sets, or removes environment variables.\n\n"
+                                          "SET [variable[=][string]]\n\n"
+                                          "  variable  Specifies the environment-variable name.\n"
+                                          "  string    Specifies a series of characters to assign to the variable.\n\n"
+                                          "Type SET without parameters to display the current environment variables.\n"));
+               return 0;
+       }
+
+       /* if no parameters, show the environment */
+       if (param[0] == _T('\0'))
+       {
+               LPTSTR lpEnv;
+               LPTSTR lpOutput;
+               INT len;
+
+               lpEnv = (LPTSTR)GetEnvironmentStrings ();
+               if (lpEnv)
+               {
+                       lpOutput = lpEnv;
+                       while (*lpOutput)
+                       {
+                               len = _tcslen(lpOutput);
+                               if (len)
+                               {
+                                       if (*lpOutput != _T('='))
+                                               ConOutPuts (lpOutput);
+                                       lpOutput += (len + 1);
+                               }
+                       }
+                   FreeEnvironmentStrings (lpEnv);
+               }
+
+               return 0;
+       }
+
+       p = _tcschr (param, _T('='));
+       if (p)
+       {
+               /* set or remove environment variable */
+               *p = _T('\0');
+               p++;
+
+               SetEnvironmentVariable (param, p);
+       }
+       else
+       {
+               /* display environment variable */
+               LPTSTR pszBuffer;
+               DWORD dwBuffer;
+
+               pszBuffer = (LPTSTR)malloc (ENV_BUFFER_SIZE * sizeof(TCHAR));
+               dwBuffer = GetEnvironmentVariable (param, pszBuffer, ENV_BUFFER_SIZE);
+               if (dwBuffer == 0)
+               {
+                       ConErrPrintf ("CMD: Not in environment \"%s\"\n", param);
+                       return 0;
+               }
+               else if (dwBuffer > ENV_BUFFER_SIZE)
+               {
+                       pszBuffer = (LPTSTR)realloc (pszBuffer, dwBuffer * sizeof (TCHAR));
+                       GetEnvironmentVariable (param, pszBuffer, ENV_BUFFER_SIZE);
+               }
+
+               ConOutPrintf ("%s\n", pszBuffer);
+               free (pszBuffer);
+
+               return 0;
+       }
+
+       return 0;
+}
+
+#endif
diff --git a/rosapps/cmd/shift.c b/rosapps/cmd/shift.c
new file mode 100644 (file)
index 0000000..92ee036
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ *  SHIFT.C - shift 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
+ *
+ *    07-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("shift /?") and cleaned up.
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+/*
+ *  Perform the SHIFT command.
+ *
+ * Only valid inside batch files.
+ *
+ * FREEDOS extension : optional parameter DOWN to allow shifting
+ *   parameters backwards.
+ */
+
+INT cmd_shift (LPTSTR cmd, LPTSTR param)
+{
+#ifdef _DEBUG
+       DebugPrintf ("cmd_shift: (\'%s\', \'%s\'\n", cmd, param);
+#endif
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Changes the position of replaceable parameters in a batch file.\n\n"
+                                          "SHIFT [DOWN]"));
+               return 0;
+       }
+
+       if (bc == NULL)
+       {
+               /* not in batch - error!! */
+               return 1;
+       }
+
+       if (!_tcsicmp (param, _T("down")))
+       {
+               if (bc->shiftlevel)
+                       bc->shiftlevel--;
+       }
+       else /* shift up */
+               bc->shiftlevel++;
+
+       return 0;
+}
diff --git a/rosapps/cmd/time.c b/rosapps/cmd/time.c
new file mode 100644 (file)
index 0000000..f2b01d8
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ *  TIME.C - time internal command.
+ *
+ *
+ *  History:
+ *
+ *    07/08/1998 (John P. Price)
+ *        started.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    09-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added locale support.
+ *
+ *    19-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection safe!
+ *        Added "/t" option.
+ *
+ *    04-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Fixed time input bug.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_TIME
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "cmd.h"
+
+
+static VOID
+PrintTime (VOID)
+{
+#if 0
+       SYSTEMTIME st;
+
+       GetLocalTime (&st);
+
+       switch (nTimeFormat)
+       {
+               case 0: /* 12 hour format */
+               default:
+                       ConOutPrintf (_T("Current time is %2d%c%02d%c%02d%c%02d%c\n"),
+                                       (st.wHour == 0 ? 12 : (st.wHour <= 12 ? st.wHour : st.wHour - 12)),
+                                       cTimeSeparator, st.wMinute, cTimeSeparator, st.wSecond, cDecimalSeparator,
+                                       st.wMilliseconds / 10, (st.wHour <= 11 ? 'a' : 'p'));
+                       break;
+
+               case 1: /* 24 hour format */
+                       ConOutPrintf (_T("Current time is %2d%c%02d%c%02d%c%02d\n"),
+                                       st.wHour, cTimeSeparator, st.wMinute, cTimeSeparator,
+                                       st.wSecond, cDecimalSeparator, st.wMilliseconds / 10);
+                       break;
+       }
+#endif
+
+       TCHAR szTime[32];
+
+       GetTimeFormat (LOCALE_USER_DEFAULT, 0, NULL, NULL,
+                                  szTime, sizeof (szTime));
+       ConOutPrintf (_T("Current date is: %s\n"), szTime);
+}
+
+
+static BOOL ParseTime (LPTSTR s)
+{
+       SYSTEMTIME t;
+       LPTSTR p = s;
+
+       if (!*s)
+               return TRUE;
+
+       GetLocalTime (&t);
+       t.wHour = 0;
+       t.wMinute = 0;
+       t.wSecond = 0;
+       t.wMilliseconds = 0;
+
+       // first get hour
+       if (_istdigit(*p))
+       {
+               while (_istdigit(*p))
+               {
+                       t.wHour = t.wHour * 10 + *p - _T('0');
+                       p++;
+               }
+       }
+       else
+               return FALSE;
+
+       // get time separator
+       if (*p != cTimeSeparator)
+               return FALSE;
+       p++;
+
+       // now get minutes
+       if (_istdigit(*p))
+       {
+               while (_istdigit(*p))
+               {
+                       t.wMinute = t.wMinute * 10 + *p - _T('0');
+                       p++;
+               }
+       }
+       else
+               return FALSE;
+
+       // get time separator
+       if (*p != cTimeSeparator)
+               return FALSE;
+       p++;
+
+       // now get seconds
+       if (_istdigit(*p))
+       {
+               while (_istdigit(*p))
+               {
+                       t.wSecond = t.wSecond * 10 + *p - _T('0');
+                       p++;
+               }
+       }
+       else
+               return FALSE;
+
+       // get decimal separator
+       if (*p == cDecimalSeparator)
+       {
+               p++;
+
+               // now get hundreths
+               if (_istdigit(*p))
+               {
+                       while (_istdigit(*p))
+                       {
+//                             t.wMilliseconds = t.wMilliseconds * 10 + *p - _T('0');
+                               p++;
+                       }
+//                     t.wMilliseconds *= 10;
+               }
+       }
+
+       /* special case: 12 hour format */
+       if (nTimeFormat == 0)
+       {
+               if (_totupper(*s) == _T('P'))
+               {
+                       t.wHour += 12;
+               }
+
+               if ((_totupper(*s) == _T('A')) && (t.wHour == 12))
+               {
+                       t.wHour = 0;
+               }
+       }
+
+       if (t.wHour > 23 || t.wMinute > 60 || t.wSecond > 60 || t.wMilliseconds > 999)
+               return FALSE;
+
+       SetLocalTime (&t);
+
+       return TRUE;
+}
+
+
+INT cmd_time (LPTSTR cmd, LPTSTR param)
+{
+       LPTSTR *arg;
+       INT    argc;
+       INT    i;
+       BOOL   bPrompt = TRUE;
+       INT    nTimeString = -1;
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Displays or sets the system time.\n\n"
+                                          "TIME [/T][time]\n\n"
+                                          "  /T    display only\n\n"
+                                          "Type TIME with no parameters to display the current time setting and a prompt\n"
+                                          "for a new one.  Press ENTER to keep the same time."));
+               return 0;
+       }
+
+       /* build parameter array */
+       arg = split (param, &argc);
+
+       /* check for options */
+       for (i = 0; i < argc; i++)
+       {
+               if (_tcsicmp (arg[i], _T("/t")) == 0)
+                       bPrompt = FALSE;
+               if ((*arg[i] != _T('/')) && (nTimeString == -1))
+                       nTimeString = i;
+       }
+
+       if (nTimeString == -1)
+               PrintTime ();
+
+       if (!bPrompt)
+       {
+               freep (arg);
+               return 0;
+       }
+
+       while (1)
+       {
+               if (nTimeString == -1)
+               {
+                       TCHAR  s[40];
+
+                       ConOutPrintf (_T("Enter new time: "));
+
+                       ConInString (s, 40);
+
+#ifdef _DEBUG
+                       DebugPrintf ("\'%s\'\n", s);
+#endif
+
+                       while (*s && s[_tcslen (s) - 1] < _T(' '))
+                               s[_tcslen(s) - 1] = _T('\0');
+
+                       if (ParseTime (s))
+                       {
+                               freep (arg);
+                               return 0;
+                       }
+               }
+               else
+               {
+                       if (ParseTime (arg[nTimeString]))
+                       {
+                               freep (arg);
+                               return 0;
+                       }
+
+                       // force input the next time around.
+                       nTimeString == -1;
+               }
+               ConErrPuts (_T("Invalid time."));
+       }
+
+       freep (arg);
+
+       return 0;
+}
+
+#endif
diff --git a/rosapps/cmd/todo.txt b/rosapps/cmd/todo.txt
new file mode 100644 (file)
index 0000000..bcffe59
--- /dev/null
@@ -0,0 +1,21 @@
+Things to do
+~~~~~~~~~~~~
+Fix bugs :)
+
+Rewrite DIR command (Unicode aware / new structure).
+
+Optimize the code!  For size and speed.  There are numerous places
+where the code is hardly optimal for either.
+
+Sorting in DIR command ("dir /o...").
+
+^S and ^Q to pause/resume displays.
+
+Improve DEL, COPY and MOVE commands.
+BREAK command on command-line.
+
+Add wildcard support to REN.
+
+Add "/?" support to all batch commands.
+
+And many, many more...
diff --git a/rosapps/cmd/type.c b/rosapps/cmd/type.c
new file mode 100644 (file)
index 0000000..b471356
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ *  TYPE.C - type internal command.
+ *
+ *  History:
+ *
+ *    07/08/1998 (John P. Price)
+ *        started.
+ *
+ *    07/12/98 (Rob Lake)
+ *        Changed error messages
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    07-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added support for quoted arguments (type "test file.dat").
+ *        Cleaned up.
+ *
+ *    19-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_TYPE
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+
+INT cmd_type (LPTSTR cmd, LPTSTR param)
+{
+       TCHAR  szBuffer[256];
+       HANDLE hFile;
+       DWORD  dwBytesRead;
+       DWORD  dwBytesWritten;
+       BOOL   bResult;
+       INT    args;
+       LPTSTR *arg;
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Displays the contents of text files.\n\n"
+                                          "TYPE [drive:][path]filename"));
+               return 0;
+       }
+
+       if (!*param)
+       {
+               error_req_param_missing ();
+               return 1;
+       }
+
+       arg = split (param, &args);
+
+       if (args > 1)
+       {
+               error_too_many_parameters (_T("\b \b"));
+               freep (arg);
+               return 1;
+       }
+
+       hFile = CreateFile (arg[0], GENERIC_READ, FILE_SHARE_READ,
+                                               NULL, OPEN_EXISTING,
+                                               FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
+                                               NULL);
+
+       if (hFile == INVALID_HANDLE_VALUE)
+       {
+               error_sfile_not_found (param);
+               freep (arg);
+               return 1;
+       }
+
+       do
+       {
+               bResult = ReadFile (hFile, szBuffer, sizeof(szBuffer),
+                                                       &dwBytesRead, NULL);
+               if (dwBytesRead)
+                       WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), szBuffer, dwBytesRead,
+                                          &dwBytesWritten, NULL);
+       }
+       while (bResult && dwBytesRead > 0);
+
+       CloseHandle (hFile);
+       freep (arg);
+
+       return 0;
+}
+
+#endif
diff --git a/rosapps/cmd/ver.c b/rosapps/cmd/ver.c
new file mode 100644 (file)
index 0000000..f5e76fc
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ *  VER.C - ver internal command.
+ *
+ *
+ *  History:
+ *
+ *    06/30/98 (Rob Lake)
+ *        rewrote ver command to accept switches, now ver alone prints
+ *        copyright notice only.
+ *
+ *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added config.h include
+ *
+ *    30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ *        added text about where to send bug reports and get updates.
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection safe!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+#define VER_HELP     "display shell version info   VER [/C/R/W/?]"
+
+
+VOID ShortVersion (VOID)
+{
+       ConOutPuts (_T("\n" SHELLINFO " " SHELLVER "\n"));
+}
+
+
+#ifdef INCLUDE_CMD_VER
+
+/*
+ *  display shell version info internal command.
+ *
+ *
+ */
+INT cmd_ver (LPTSTR cmd, LPTSTR param)
+{
+       INT i;
+
+       /* JPP 07/08/1998 clean up and shortened info. */
+
+       ConOutPuts (_T("\n" SHELLINFO " " SHELLVER "\nCopyright (C) 1994-1998 Tim Norman and others."));
+       ConOutPuts (_T("Copyright (C) 1998,1999 Eric Kohl."));
+
+       /* Basic copyright notice */
+       if (param[0] == _T('\0'))
+       {
+               ConOutPuts (_T("\n"SHELLINFO
+                                          " comes with ABSOLUTELY NO WARRANTY; for details\n"
+                                          "type: `ver /w'. This is free software, and you are welcome to redistribute\n"
+                                          "it under certain conditions; type `ver /r' for details. Type `ver /c' for a\n"
+                                          "listing of credits."));
+       }
+       else
+       {
+               /* MS-DOS ver prints just help if /? is alone or not */
+               if (_tcsstr (param, _T("/?")) != NULL)
+               {
+                       ConOutPuts (_T(USAGE ": " VER_HELP));
+                       return 0;
+               }
+
+               for (i = 0; param[i]; i++)
+               {
+                       /* skip spaces */
+                       if (param[i] == _T(' '))
+                               continue;
+
+                       if (param[i] == _T('/'))
+                       {
+                               /* is this a lone '/' ? */
+                               if (param[i + 1] == 0)
+                               {
+                                       error_invalid_switch (_T(' '));
+                                       return 1;
+                               }
+                               continue;
+                       }
+
+                       if (_totupper (param[i]) == _T('W'))
+                       {
+                               /* Warranty notice */
+                               /* JPP 07/08/1998 removed extra printf calls */
+                               ConOutPuts (_T("\n This program is distributed in the hope that it will be useful,\n"
+                                                          " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+                                                          " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
+                                                          " GNU General Public License for more details."));
+                       }
+                       else if (_totupper (param[i]) == _T('R'))
+                       {
+                               /* Redistribution notice */
+                               /* JPP 07/08/1998 removed extra printf calls */
+                               ConOutPuts (_T("\n This program is free software; you can redistribute it and/or modify\n"
+                                                          " it under the terms of the GNU General Public License as published by\n"
+                                                          " the Free Software Foundation; either version 2 of the License, or\n"
+                                                          " (at your option) any later version."));
+                       }
+                       else if (_totupper (param[i]) == _T('C'))
+                       {
+                               /* Developer listing */
+                               /* JPP 07/08/1998 removed extra printf calls; rearranged names */
+                               ConOutPuts (_T("\ndeveloped by:\n"
+                                                          "    Tim Norman      Matt Rains\n"
+                                                          "    Evan Jeffrey    Steffen Kaiser\n"
+                                                          "    Svante Frey     Oliver Mueller\n"
+                                                          "    Aaron Kaufman   Marc Desrochers\n"
+                                                          "    Rob Lake        John P Price\n"
+                                                          "    Hans B Pufal\n"
+                                                          "\nconverted to Win32 by:\n"
+                                                          "    Eric Kohl\n"));
+                       }
+                       else
+                       {
+                               error_invalid_switch ((TCHAR)_totupper (param[i]));
+                               return 1;
+                       }
+               }
+       }
+
+       ConOutPuts (_T("\nSend bug reports to <ekohl@abo.rhein-zeitung.de>.\n"
+/*
+                                  "Updates are available at ftp://www.sid-dis.com/..."
+*/
+                          ));
+       return 0;
+}
+
+#endif
diff --git a/rosapps/cmd/verify.c b/rosapps/cmd/verify.c
new file mode 100644 (file)
index 0000000..e3b1f08
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ *  VERIFY.C - verify internal command.
+ *
+ *
+ *  History:
+ *
+ *    31 Jul 1998 (John P Price)
+ *        started.
+ *
+ *    18-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        VERIFY is just a dummy under Win32; it only exists
+ *        for compatibility!!!
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode and redirection ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_VERIFY
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+
+/* global verify flag */
+static BOOL bVerify = FALSE;
+
+
+INT cmd_verify (LPTSTR cmd, LPTSTR param)
+{
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("This command is just a dummy!!\n"
+                                          "Sets whether to verify that your files are written correctly to a\n"
+                                          "disk.\n\n"
+                                          "VERIFY [ON | OFF]\n\n"
+                                          "Type VERIFY without a parameter to display the current VERIFY setting."));
+               return 0;
+       }
+
+       if (!*param)
+               ConOutPrintf (_T("VERIFY is %s.\n"), bVerify ? D_ON : D_OFF);
+       else if (_tcsicmp (param, D_OFF) == 0)
+               bVerify = FALSE;
+       else if (_tcsicmp (param, D_ON) == 0)
+               bVerify = TRUE;
+       else
+               ConOutPuts (_T("Must specify ON or OFF."));
+
+       return 0;
+}
+
+#endif
diff --git a/rosapps/cmd/vol.c b/rosapps/cmd/vol.c
new file mode 100644 (file)
index 0000000..13bd0e1
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ *  VOL.C - vol internal command.
+ *
+ *
+ *  History:
+ *
+ *    03-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Replaced DOS calls by Win32 calls.
+ *
+ *    08-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added help text ("/?").
+ *
+ *    07-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Cleanup.
+ *
+ *    18-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Unicode ready!
+ *
+ *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Redirection ready!
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_VOL
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+
+static VOID
+PrintVolumeHeader (LPTSTR pszRootPath)
+{
+       TCHAR szVolName[80];
+       DWORD dwSerialNr;
+
+       /* get the volume information of the drive */
+       GetVolumeInformation (pszRootPath, szVolName, 80, &dwSerialNr,
+                                                 NULL, NULL, NULL, 0);
+
+       /* print drive info */
+       ConOutPrintf (_T(" Volume in drive %c:"), pszRootPath[0]);
+
+       if (szVolName[0] != '\0')
+               ConOutPrintf (_T(" is %s\n"), szVolName);
+       else
+               ConOutPrintf (_T(" has no label\n"));
+
+       /* print the volume serial number */
+       ConOutPrintf (_T(" Volume Serial Number is %04X-%04X\n"),
+                                 HIWORD(dwSerialNr), LOWORD(dwSerialNr));
+}
+
+
+INT cmd_vol (LPTSTR cmd, LPTSTR param)
+{
+       TCHAR szRootPath[] = _T("A:\\");
+       TCHAR szPath[MAX_PATH];
+
+       if (!_tcsncmp (param, _T("/?"), 2))
+       {
+               ConOutPuts (_T("Displays the disk volume label and serial number, if they exist.\n\n"
+                                          "VOL [drive:]"));
+               return 0;
+       }
+
+       if (param[0] == _T('\0'))
+       {
+               GetCurrentDirectory (MAX_PATH, szPath);
+               szRootPath[0] = szPath[0];
+       }
+       else
+       {
+               _tcsupr (param);
+               if (param[1] == _T(':'))
+                       szRootPath[0] = param[0];
+               else
+               {
+                       error_invalid_drive ();
+                       return 1;
+               }
+       }
+
+       if (!IsValidPathName (szRootPath))
+       {
+               error_invalid_drive ();
+               return 1;
+       }
+
+       /* print the header */
+       PrintVolumeHeader (szRootPath);
+
+       return 0;
+}
+
+#endif
diff --git a/rosapps/cmd/where.c b/rosapps/cmd/where.c
new file mode 100644 (file)
index 0000000..1ea1625
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ *  WHERE.C - file serch functions.
+ *
+ *
+ *  History:
+ *
+ *  07/15/95 (Tim Norman)
+ *    started.
+ *
+ *  08/08/95 (Matt Rains)
+ *    i have cleaned up the source code. changes now bring this source into
+ *    guidelines for recommended programming practice.
+ *
+ *  12/12/95 (Steffan Kaiser & Tim Norman)
+ *    added some patches to fix some things and make more efficient
+ *
+ *  1/6/96 (Tim Norman)
+ *    fixed a stupid pointer mistake...  Thanks to everyone who noticed it!
+ *
+ *  8/1/96 (Tim Norman)
+ *    fixed a bug when getenv returns NULL
+ *
+ *  8/7/96 (Steffan Kaiser and Tim Norman)
+ *    speed improvements and bug fixes
+ *
+ *  8/27/96 (Tim Norman)
+ *    changed code to use pointers directly into PATH environment variable
+ *    rather than making our own copy.  This saves some memory, but requires
+ *    we write our own function to copy pathnames out of the variable.
+ *
+ *  12/23/96 (Aaron Kaufman)
+ *    Fixed a bug in get_paths() that did not point to the first PATH in the
+ *    environment variable.
+ *
+ *  7/12/97 (Tim Norman)
+ *    Apparently, Aaron's bugfix got lost, so I fixed it again.
+ *
+ *  16 July 1998 (John P. Price)
+ *    Added stand alone code.
+ *
+ *  17 July 1998 (John P. Price)
+ *    Rewrote find_which to use searchpath function
+ *
+ * 24-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - fixed bug where didn't check all extensions when path was specified
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - added config.h include
+ *
+ * 30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * - fixed so that it find_which returns NULL if filename is not executable
+ *   (does not have .bat, .com, or .exe extention). Before command would
+ *   to execute any file with any extension (opps!)
+ *
+ *    03-Dec_1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Changed find_which().
+ *
+ *    07-Dec_1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ *        Added ".CMD" extension.
+ *        Replaced numeric constant by _NR_OF_EXTENSIONS.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "config.h"
+
+#include <windows.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+
+static LPTSTR ext[]  = {".BAT", ".CMD", ".COM", ".EXE"};
+static INT nExtCount = sizeof(ext) / sizeof(LPTSTR);
+
+
+/* searches for file using path info. */
+
+BOOL find_which (LPCTSTR fname, LPTSTR fullbuffer)
+{
+       static TCHAR temp[MAX_PATH];
+       LPTSTR fullname;
+       INT x;
+
+       *fullbuffer = _T('\0');
+
+       /* if there an extension and it is in the last path component, then
+        * don't test all the extensions. */
+       if (!(fullname = _tcsrchr (fname, _T('.'))) ||
+               _tcschr (fullname + 1, _T('\\')))
+       {
+#ifdef _DEBUG
+               DebugPrintf ("No filename extension!\n");
+#endif
+
+               for (x = 0; x < nExtCount; x++)
+               {
+                       _tcscpy (temp, fname);
+                       _tcscat (temp, ext[x]);
+#ifdef _DEBUG
+                       DebugPrintf ("Checking for %s\n", temp);
+#endif
+                       if (_tcschr (fname, _T('\\')))
+                       {
+                               if (IsValidFileName (temp))
+                               {
+                                       _tcscpy (fullbuffer, temp);
+                                       return TRUE;
+                               }
+                       }
+                       else
+                       {
+                               _searchenv (temp, _T("PATH"), fullbuffer);
+                               if (*fullbuffer != '\0')
+                                       return TRUE;
+                       }
+               }
+       }
+       else
+       {
+               /* there is an extension... don't test other extensions */
+               /* make sure that the extention is one of the four */
+#ifdef _DEBUG
+               DebugPrintf ("No filename extension!\n");
+#endif
+               for (x = 0; x < nExtCount; x++)
+               {
+                       if (!_tcsicmp (_tcsrchr (fname, _T('.')), ext[x]))
+                       {
+                               if (_tcschr (fname, _T('\\')))
+                               {
+                                       if (IsValidFileName (fname))
+                                       {
+                                               _tcscpy (fullbuffer, fname);
+#ifdef _DEBUG
+                                               DebugPrintf ("Found: %s\n", fullbuffer);
+#endif
+                                               return TRUE;
+                                       }
+                               }
+                               else
+                               {
+#ifdef _DEBUG
+                                       DebugPrintf ("Checking for %s\n", fname);
+#endif
+                                       _searchenv (fname, _T("PATH"), fullbuffer);
+                                       if (*fullbuffer != _T('\0'))
+                                       {
+#ifdef _DEBUG
+                                               DebugPrintf ("Found: %s\n", fullbuffer);
+#endif
+                                               return TRUE;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       return FALSE;
+}
diff --git a/rosapps/cmd/wishlist.txt b/rosapps/cmd/wishlist.txt
new file mode 100644 (file)
index 0000000..65c518d
--- /dev/null
@@ -0,0 +1,15 @@
+
+Wishlist for ReactOS CMD
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+ - Exclusion wildcards: "del /r *.bak -abcd.bak"
+     Deletes ALL *.bak files EXCEPT abcd.bak.
+
+ - Progress indikator on long file operations (copy/move).
+     Percentage at the right side of the filename.
+
+ - [cd test directory] should change to the subdirectoy "test directory".
+
+More ideas?
+
+ Eric Kohl <ekohl@abo.rhein-zeitung.de>
\ No newline at end of file