--- /dev/null
+*.sys
+*.exe
+*.dll
+*.cpl
+*.a
+*.o
+*.d
+*.coff
+*.dsp
+*.dsw
+*.aps
+*.ncb
+*.opt
+*.sym
+*.plg
+*.bak
--- /dev/null
+/*
+ * 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!
+ */
+
+
+#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;
+ DWORD dwUsed;
+} ALIAS, *LPALIAS;
+
+
+static LPALIAS lpFirst = NULL;
+static LPALIAS lpLast = NULL;
+static DWORD dwUsed = 0;
+
+
+/* module internal functions */
+/* strlwr only for first word in string */
+static VOID
+partstrlwr (LPTSTR str)
+{
+ LPTSTR c = str;
+ while (*c && !_istspace (*c) && *c != _T('='))
+ {
+ *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 VOID
+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;
+ }
+
+ free (ptr->lpSubst);
+ ptr->lpSubst = s;
+ _tcscpy (ptr->lpSubst, subst);
+ return;
+ }
+ ptr = ptr->next;
+ }
+
+ ptr = (LPALIAS)malloc (sizeof (ALIAS));
+ if (!ptr)
+ return;
+
+ ptr->next = 0;
+
+ ptr->lpName = (LPTSTR)malloc ((_tcslen (name) + 1)*sizeof(TCHAR));
+ if (!ptr->lpName)
+ {
+ error_out_of_memory ();
+ free (ptr);
+ return;
+ }
+ _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;
+ }
+ _tcscpy (ptr->lpSubst, subst);
+
+ /* it's necessary for recursive substitution */
+ partstrlwr (ptr->lpSubst);
+
+ ptr->dwUsed = 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;
+ }
+ 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;
+}
+
+
+VOID InitializeAlias (VOID)
+{
+ lpFirst = NULL;
+ lpLast = NULL;
+ dwUsed = 0;
+}
+
+VOID DestroyAlias (VOID)
+{
+ if (lpFirst == NULL)
+ return;
+
+ while (lpFirst->next != NULL)
+ {
+ lpLast = lpFirst;
+ lpFirst = lpLast->next;
+
+ free (lpLast->lpName);
+ free (lpLast->lpSubst);
+ free (lpLast);
+ }
+
+ free (lpFirst->lpName);
+ free (lpFirst->lpSubst);
+ free (lpFirst);
+
+ lpFirst = NULL;
+ lpLast = NULL;
+ dwUsed = 0;
+}
+
+/* specified routines */
+VOID ExpandAlias (LPTSTR cmd, INT maxlen)
+{
+ unsigned n = 0,
+ m,
+ i,
+ len;
+ short d = 1;
+ LPALIAS ptr = lpFirst;
+
+ dwUsed++;
+ if (dwUsed == 0)
+ {
+ while (ptr)
+ ptr->dwUsed = 0;
+ ptr = lpFirst;
+ dwUsed = 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->dwUsed != dwUsed)
+ {
+ 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->dwUsed = dwUsed;
+ /* whitespaces are removed! */
+ n = 0;
+ d = 1;
+ }
+ }
+ ptr = ptr->next;
+ }
+ }
+}
+
+
+INT CommandAlias (LPTSTR cmd, LPTSTR param)
+{
+ LPTSTR ptr;
+
+ 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
+ AddAlias (param, ptr);
+
+ return 0;
+}
+#endif
--- /dev/null
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_ATTRIB
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <ctype.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 CommandAttrib (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, FALSE);
+
+ /* 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)
+ {
+ DWORD len;
+
+ len = GetCurrentDirectory (MAX_PATH, szPath);
+ if (szPath[len-1] != _T('\\'))
+ {
+ szPath[len] = _T('\\');
+ szPath[len + 1] = 0;
+ }
+ _tcscpy (szFileName, _T("*.*"));
+ PrintAttribute (szPath, szFileName, bRecurse);
+ freep (arg);
+ return 0;
+ }
+
+ /* 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 */
--- /dev/null
+/* $Id: batch.c,v 1.1 2003/03/20 19:19:22 rcampbell Exp $
+ *
+ * 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!
+ *
+ * 23-Feb-2001 (Carl Nettelblad <cnettel@hem.passagen.es>)
+ * Fixes made to get "for" working.
+ */
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.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;
+}
+
+
+/*
+ * 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;
+}
+
+
+/*
+ * 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 != NULL)
+ {
+ LPBATCH_CONTEXT t = bc;
+
+ if (bc->hBatchFile)
+ {
+ CloseHandle (bc->hBatchFile);
+ bc->hBatchFile = INVALID_HANDLE_VALUE;
+ }
+
+ if (bc->params)
+ free(bc->params);
+
+ if (bc->forproto)
+ free(bc->forproto);
+
+ if (bc->ffind)
+ free(bc->ffind);
+
+ /* Preserve echo state across batch calls */
+ bEcho = bc->bEcho;
+
+ bc = bc->prev;
+ free(t);
+ }
+
+ 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;
+ }
+
+ /* Kill any and all FOR contexts */
+ while (bc && bc->forvar)
+ ExitBatch (NULL);
+
+ if (bc == NULL)
+ {
+ /* No curent batch file, create a new context */
+ LPBATCH_CONTEXT n = (LPBATCH_CONTEXT)malloc (sizeof(BATCH_CONTEXT));
+
+ if (n == NULL)
+ {
+ 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 */
+ bc->shiftlevel = 0;
+
+ bc->ffind = NULL;
+ bc->forvar = _T('\0');
+ bc->forproto = NULL;
+ bc->params = BatchParams (firstword, param);
+
+#ifdef _DEBUG
+ DebugPrintf ("Batch: returns TRUE\n");
+#endif
+
+ 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)
+{
+ 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;
+ }
+
+ /* 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 (bc->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();
+ return NULL;
+ }
+
+ bc->hFind = FindFirstFile (fv, bc->ffind);
+
+ fv = !(bc->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;
+ }
+
+ 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;
+}
+
+/* EOF */
--- /dev/null
+/*
+ * BATCH.H - A structure to preserve the context of a batch file
+ *
+ *
+ */
+
+#ifndef _BATCH_H_INCLUDED_
+#define _BATCH_H_INCLUDED_
+
+
+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 */
+ HANDLE hFind; /* Preserve find handle when doing a for */
+ TCHAR forvar;
+} BATCH_CONTEXT, *LPBATCH_CONTEXT;
+
+
+/* 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);
+
+#endif /* _BATCH_H_INCLUDED_ */
--- /dev/null
+/*
+ * 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!
+ */
+
+#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
+#ifdef __REACTOS__
+ Beep (440, 50);
+#else
+ MessageBeep (-1);
+#endif
+
+ return 0;
+}
+#endif
--- /dev/null
+ **** Please report bugs to ekohl@rz-online.de! ****
+
+Known bugs in CMD version 0.1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+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@rz-online.de! ****
--- /dev/null
+/* $Id: call.c,v 1.1 2003/03/20 19:19:22 rcampbell Exp $
+ *
+ * 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!
+ */
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.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;
+}
+
+/* EOF */
--- /dev/null
+/*
+ * CHCP.C - chcp internal command.
+ *
+ *
+ * History:
+ *
+ * 23-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ * Started.
+ *
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_CHCP
+
+#include <windows.h>
+#include <tchar.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "cmd.h"
+
+
+INT CommandChcp (LPTSTR cmd, LPTSTR param)
+{
+ LPTSTR *arg;
+ INT args;
+ UINT uOldCodePage;
+ UINT uNewCodePage;
+
+ /* 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;
+ }
+
+ if (args == 0)
+ {
+ /* display active code page number */
+ ConOutPrintf ("Active code page: %u\n", GetConsoleCP ());
+ return 0;
+ }
+
+ if (args >= 2)
+ {
+ /* too many parameters */
+ ConErrPrintf ("Invalid parameter format - %s\n", param);
+ return 1;
+ }
+
+ /* get parameters */
+ arg = split (param, &args, FALSE);
+
+ /* save old code page */
+ uOldCodePage = GetConsoleCP ();
+
+ uNewCodePage = (UINT)_ttoi (arg[0]);
+
+ if (uNewCodePage == 0)
+ {
+ ConErrPrintf ("Parameter format incorrect - %s\n", arg[0]);
+ freep (arg);
+ return 1;
+ }
+
+ if (!SetConsoleCP (uNewCodePage))
+ {
+ ConErrPrintf ("Invalid code page\n");
+ }
+ else
+ {
+ SetConsoleOutputCP (uNewCodePage);
+ InitLocale ();
+ }
+
+ freep (arg);
+
+ return 0;
+}
+
+#endif /* INCLUDE_CMD_CHCP */
--- /dev/null
+/*
+ * CHOICE.C - internal command.
+ *
+ *
+ * History:
+ *
+ * 12 Aug 1999 (Eric Kohl)
+ * started.
+ *
+ * 01 Sep 1999 (Eric Kohl)
+ * Fixed help text.
+ *
+ * 26 Sep 1999 (Paolo Pantaleo)
+ * Fixed timeout.
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_CHOICE
+
+#include <windows.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <tchar.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+#define GC_TIMEOUT -1
+#define GC_NOKEY 0 //an event occurred but it wasn't a key pressed
+#define GC_KEYREAD 1 //a key has been read
+
+
+static INT
+GetCharacterTimeout (LPTCH ch, DWORD dwMilliseconds)
+{
+//--------------------------------------------
+// Get a character from standard input but with a timeout.
+// The function will wait a limited amount
+// of time, then the function returns GC_TIMEOUT.
+//
+// dwMilliseconds is the timeout value, that can
+// be set to INFINITE, so the function works like
+// stdio.h's getchar()
+
+ HANDLE hInput;
+ DWORD dwRead;
+
+ INPUT_RECORD lpBuffer;
+
+ hInput = GetStdHandle (STD_INPUT_HANDLE);
+
+ //if the timeout experied return GC_TIMEOUT
+ if (WaitForSingleObject (hInput, dwMilliseconds) == WAIT_TIMEOUT)
+ return GC_TIMEOUT;
+
+ //otherwise get the event
+ ReadConsoleInput (hInput, &lpBuffer, 1, &dwRead);
+
+ //if the event is a key pressed
+ if ((lpBuffer.EventType == KEY_EVENT) &&
+ (lpBuffer.Event.KeyEvent.bKeyDown == TRUE))
+ {
+ //read the key
+#ifdef _UNICODE
+ *ch = lpBuffer.Event.KeyEvent.uChar.UnicodeChar;
+#else
+ *ch = lpBuffer.Event.KeyEvent.uChar.AsciiChar;
+#endif
+ return GC_KEYREAD;
+ }
+
+ //else return no key
+ return GC_NOKEY;
+}
+
+static INT
+IsKeyInString (LPTSTR lpString, TCHAR cKey, BOOL bCaseSensitive)
+{
+ LPTCH p = lpString;
+ INT val = 0;
+
+ while (*p)
+ {
+ if (bCaseSensitive)
+ {
+ if (*p == cKey)
+ return val;
+ }
+ else
+ {
+ if (_totlower (*p) == _totlower (cKey))
+ return val;
+ }
+
+ val++;
+ p++;
+ }
+
+ return -1;
+}
+
+
+INT
+CommandChoice (LPTSTR cmd, LPTSTR param)
+{
+ LPTSTR lpOptions = "YN";
+ LPTSTR lpText = NULL;
+ BOOL bNoPrompt = FALSE;
+ BOOL bCaseSensitive = FALSE;
+ BOOL bTimeout = FALSE;
+ INT nTimeout = 0;
+ TCHAR cDefault = _T('\0');
+ INPUT_RECORD ir;
+ LPTSTR p, np;
+ LPTSTR *arg;
+ INT argc;
+ INT i;
+ INT val;
+
+ INT GCret;
+ TCHAR Ch;
+ DWORD amount,clk;
+
+ if (_tcsncmp (param, _T("/?"), 2) == 0)
+ {
+ ConOutPuts (_T("Waits for the user to choose one of a set of choices.\n"
+ "\n"
+ "CHOICE [/C[:]choices][/N][/S][/T[:]c,nn][text]\n"
+ "\n"
+ " /C[:]choices Specifies allowable keys. Default is YN.\n"
+ " /N Do not display choices and ? at the end of the prompt string.\n"
+ " /S Treat choice keys as case sensitive.\n"
+ " /T[:]c,nn Default choice to c after nn seconds.\n"
+ " text Prompt string to display.\n"
+ "\n"
+ "ERRORLEVEL is set to offset of key user presses in choices."));
+ return 0;
+ }
+
+ /* retrieve text */
+ p = param;
+
+ while (TRUE)
+ {
+ if (*p == _T('\0'))
+ break;
+
+ if (*p != _T('/'))
+ {
+ lpText = p;
+ break;
+ }
+ np = _tcschr (p, _T(' '));
+ if (!np)
+ break;
+ p = np + 1;
+ }
+
+ /* build parameter array */
+ arg = split (param, &argc, FALSE);
+
+ /* evaluate arguments */
+ if (argc > 0)
+ {
+ for (i = 0; i < argc; i++)
+ {
+ if (_tcsnicmp (arg[i], _T("/c"), 2) == 0)
+ {
+ if (arg[i][2] == _T(':'))
+ lpOptions = &arg[i][3];
+ else
+ lpOptions = &arg[i][2];
+
+ if (_tcslen (lpOptions) == 0)
+ {
+ ConErrPuts (_T("Invalid option. Expected format: /C[:]options"));
+ freep (arg);
+ return 1;
+ }
+ }
+ else if (_tcsnicmp (arg[i], _T("/n"), 2) == 0)
+ {
+ bNoPrompt = TRUE;
+ }
+ else if (_tcsnicmp (arg[i], _T("/s"), 2) == 0)
+ {
+ bCaseSensitive = TRUE;
+ }
+ else if (_tcsnicmp (arg[i], _T("/t"), 2) == 0)
+ {
+ LPTSTR s;
+
+ if (arg[i][2] == _T(':'))
+ {
+ cDefault = arg[i][3];
+ s = &arg[i][4];
+ }
+ else
+ {
+ cDefault = arg[i][2];
+ s = &arg[i][3];
+ }
+
+ if (*s != _T(','))
+ {
+ ConErrPuts (_T("Invalid option. Expected format: /T[:]c,nn"));
+ freep (arg);
+ return 1;
+ }
+
+ s++;
+ nTimeout = _ttoi(s);
+ bTimeout = TRUE;
+ }
+ else if (arg[i][0] == _T('/'))
+ {
+ ConErrPrintf (_T("Illegal Option: %s"), arg[i]);
+ freep (arg);
+ return 1;
+ }
+ }
+ }
+
+ /* print text */
+ if (lpText)
+ ConOutPrintf (_T("%s"), lpText);
+
+ /* print options */
+ if (bNoPrompt == FALSE)
+ {
+ ConOutPrintf (_T("[%c"), lpOptions[0]);
+
+ for (i = 1; (unsigned)i < _tcslen (lpOptions); i++)
+ ConOutPrintf (_T(",%c"), lpOptions[i]);
+
+ ConOutPrintf (_T("]?"));
+ }
+
+ ConInFlush ();
+
+ if(!bTimeout)
+ {
+ while (TRUE)
+ {
+ ConInKey (&ir);
+
+ val = IsKeyInString (lpOptions,
+#ifdef _UNICODE
+ ir.Event.KeyEvent.uChar.UnicodeChar,
+#else
+ ir.Event.KeyEvent.uChar.AsciiChar,
+#endif /* _UNICODE */
+ bCaseSensitive);
+
+ if (val >= 0)
+ {
+ ConOutPrintf (_T("%c\n"), lpOptions[val]);
+
+ nErrorLevel = val + 1;
+
+ break;
+ }
+
+ Beep (440, 50);
+ }
+
+ freep (arg);
+ return 0;
+ }
+
+ clk = GetTickCount ();
+ amount = nTimeout*1000;
+
+loop:
+ GCret = GetCharacterTimeout (&Ch, amount - (GetTickCount () - clk));
+
+ switch (GCret)
+ {
+ case GC_TIMEOUT:
+#ifdef _DEBUG
+ DebugPrintf (_T("GC_TIMEOUT\n"));
+ DebugPrintf (_T("elapsed %d msecs\n"), GetTickCount () - clk);
+#endif /* _DEBUG */
+ break;
+
+ case GC_NOKEY:
+#ifdef _DEBUG
+ DebugPrintf(_T("GC_NOKEY\n"));
+ DebugPrintf(_T("elapsed %d msecs\n"), GetTickCount () - clk);
+#endif /* _DEBUG */
+ goto loop;
+
+ case GC_KEYREAD:
+#ifdef _DEBUG
+ DebugPrintf(_T("GC_KEYREAD\n"));
+ DebugPrintf(_T("elapsed %d msecs\n"), GetTickCount () - clk);
+ DebugPrintf(_T("read %c"), Ch);
+#endif /* _DEBUG */
+ if ((val=IsKeyInString(lpOptions,Ch,bCaseSensitive))==-1)
+ {
+ Beep (440, 50);
+ goto loop;
+ }
+ cDefault=Ch;
+ break;
+ }
+
+#ifdef _DEBUG
+ DebugPrintf(_T("exiting wait loop after %d msecs\n"),
+ GetTickCount () - clk);
+#endif /* _DEBUG */
+
+ val = IsKeyInString (lpOptions, cDefault, bCaseSensitive);
+ ConOutPrintf (_T("%c\n"), lpOptions[val]);
+
+ nErrorLevel = val + 1;
+
+ freep (arg);
+
+#ifdef _DEBUG
+ DebugPrintf (_T("ErrorLevel: %d\n"), nErrorLevel);
+#endif /* _DEBUG */
+
+ return 0;
+}
+#endif /* INCLUDE_CMD_CHOICE */
+
+/* EOF */
--- /dev/null
+/*
+ * 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!
+ */
+
+#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
--- /dev/null
+/* $Id: cmd.c,v 1.1 2003/03/20 19:19:22 rcampbell Exp $
+ *
+ * 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().
+ *
+ * 22-Oct-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ * Added break handler.
+ *
+ * 15-Dec-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ * Fixed current directory
+ *
+ * 28-Dec-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ * Restore window title after program/batch execution
+ *
+ * 03-Feb-2001 (Eric Kohl <ekohl@rz-online.de>)
+ * Workaround because argc[0] is NULL under ReactOS
+ *
+ * 23-Feb-2001 (Carl Nettelblad <cnettel@hem.passagen.se>)
+ * %envvar% replacement conflicted with for.
+ */
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <stdio.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+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 nErrorLevel = 0; /* Errorlevel of last launched external program */
+BOOL bChildProcessRunning = FALSE;
+DWORD dwChildProcessId = 0;
+OSVERSIONINFO osvi;
+HANDLE hIn;
+HANDLE hOut;
+
+#ifdef INCLUDE_CMD_COLOR
+WORD wColor; /* current color */
+WORD wDefColor; /* default color */
+#endif
+
+
+/*
+ * is character a delimeter when used on first word?
+ *
+ */
+
+static BOOL IsDelimiter (TCHAR c)
+{
+ return (c == _T('/') || c == _T('=') || c == _T('\0') || _istspace (c));
+}
+
+
+/*
+ * 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)
+{
+ TCHAR szFullName[MAX_PATH];
+#ifndef __REACTOS__
+ TCHAR szWindowTitle[MAX_PATH];
+#endif
+ DWORD dwExitCode = 0;
+
+#ifdef _DEBUG
+ DebugPrintf ("Execute: \'%s\' \'%s\'\n", first, rest);
+#endif
+
+ /* check for a drive change */
+ if ((_istalpha (first[0])) && (!_tcscmp (first + 1, _T(":"))))
+ {
+ BOOL working = TRUE;
+ if (!SetCurrentDirectory(first))
+ /* Guess they changed disc or something, handle that gracefully and get to root */
+ {
+ TCHAR str[4];
+ str[0]=first[0];
+ str[1]=':';
+ str[2]='\\';
+ str[3]=0;
+ working = SetCurrentDirectory(str);
+ }
+
+ if (!working) ConErrPuts (INVALIDDRIVE);
+
+ return;
+ }
+
+ /* get the PATH environment variable and parse it */
+ /* search the PATH environment variable for the binary */
+ if (!SearchForExecutable (first, szFullName))
+ {
+ error_bad_command ();
+ return;
+ }
+
+#ifndef __REACTOS__
+ GetConsoleTitle (szWindowTitle, MAX_PATH);
+#endif
+
+ /* 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 [CMDLINE_LENGTH];
+ PROCESS_INFORMATION prci;
+ STARTUPINFO stui;
+
+#ifdef _DEBUG
+ DebugPrintf ("[EXEC: %s %s]\n", szFullName, rest);
+#endif
+ /* build command line for CreateProcess() */
+ _tcscpy (szFullCmdLine, first);
+ _tcscat (szFullCmdLine, _T(" "));
+ _tcscat (szFullCmdLine, rest);
+
+ /* fill startup info */
+ memset (&stui, 0, sizeof (STARTUPINFO));
+ stui.cb = sizeof (STARTUPINFO);
+ stui.dwFlags = STARTF_USESHOWWINDOW;
+ stui.wShowWindow = SW_SHOWDEFAULT;
+
+ // return console to standard mode
+ SetConsoleMode( GetStdHandle( STD_INPUT_HANDLE ),
+ ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT );
+
+ if (CreateProcess (szFullName,
+ szFullCmdLine,
+ NULL,
+ NULL,
+ FALSE,
+ CREATE_NEW_PROCESS_GROUP,
+ NULL,
+ NULL,
+ &stui,
+ &prci))
+ {
+ /* FIXME: Protect this with critical section */
+ bChildProcessRunning = TRUE;
+ dwChildProcessId = prci.dwProcessId;
+
+ WaitForSingleObject (prci.hProcess, INFINITE);
+
+ /* FIXME: Protect this with critical section */
+ bChildProcessRunning = TRUE;
+
+ GetExitCodeProcess (prci.hProcess, &dwExitCode);
+ nErrorLevel = (INT)dwExitCode;
+ CloseHandle (prci.hThread);
+ CloseHandle (prci.hProcess);
+ }
+ else
+ {
+ ErrorMessage (GetLastError (),
+ "Error executing CreateProcess()!!\n");
+ }
+ // restore console mode
+ SetConsoleMode( GetStdHandle( STD_INPUT_HANDLE ),
+ ENABLE_PROCESSED_INPUT );
+ }
+
+#ifndef __REACTOS__
+ SetConsoleTitle (szWindowTitle);
+#endif
+}
+
+
+/*
+ * 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)
+{
+ 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;
+
+#ifdef _DEBUG
+ DebugPrintf ("DoCommand: (\'%s\')\n", line);
+#endif /* DEBUG */
+
+ /* 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
+ */
+
+ /* Get length of command name */
+ cl = _tcslen (cmdptr->name);
+
+ 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;
+ }
+ }
+ }
+}
+
+
+/*
+ * process the command line and execute the appropriate functions
+ * full input/output redirection and piping are supported
+ */
+
+VOID ParseCommandLine (LPTSTR cmd)
+{
+ TCHAR cmdline[CMDLINE_LENGTH];
+ LPTSTR s;
+#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 */
+
+ _tcscpy (cmdline, cmd);
+ s = &cmdline[0];
+
+#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;
+ SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
+
+ hFile = CreateFile (in, GENERIC_READ, FILE_SHARE_READ, &sa, 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)
+ {
+ SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
+
+ /* 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, &sa,
+ 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, &sa,
+ 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;
+ SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
+
+ hFile = CreateFile (out, GENERIC_WRITE, FILE_SHARE_READ, &sa,
+ (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;
+ SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
+
+ 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,
+ &sa,
+ (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 */
+}
+
+
+/*
+ * do the prompt/input/process loop
+ *
+ */
+
+static INT
+ProcessInput (BOOL bFlag)
+{
+ TCHAR commandline[CMDLINE_LENGTH];
+ TCHAR readline[CMDLINE_LENGTH];
+ LPTSTR tp = NULL;
+ LPTSTR ip;
+ LPTSTR cp;
+ 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 += _stprintf (cp, _T("%u"), nErrorLevel);
+ ip++;
+ break;
+
+ default:
+ tp = _tcschr(ip, _T('%'));
+ if ((tp != NULL) &&
+ (tp <= _tcschr(ip, _T(' ')) - 1))
+ {
+ 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;
+ }
+ else
+ {
+ *cp++ = _T('%');
+ }
+ 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;
+}
+
+
+/*
+ * control-break handler.
+ */
+BOOL BreakHandler (DWORD dwCtrlType)
+{
+ if ((dwCtrlType != CTRL_C_EVENT) &&
+ (dwCtrlType != CTRL_BREAK_EVENT))
+ return FALSE;
+
+ if (bChildProcessRunning == TRUE)
+ {
+ GenerateConsoleCtrlEvent (CTRL_C_EVENT,
+ dwChildProcessId);
+ return TRUE;
+ }
+
+ /* FIXME: Handle batch files */
+
+ /* FIXME: Print "^C" */
+
+
+ return TRUE;
+}
+
+
+VOID AddBreakHandler (VOID)
+{
+#ifndef __REACTOS__
+ SetConsoleCtrlHandler ((PHANDLER_ROUTINE)&BreakHandler,
+ TRUE);
+#endif
+}
+
+
+VOID RemoveBreakHandler (VOID)
+{
+#ifndef __REACTOS__
+ SetConsoleCtrlHandler (NULL, FALSE);
+#endif
+}
+
+
+/*
+ * show commands and options that are available.
+ *
+ */
+static VOID
+ShowCommands (VOID)
+{
+ /* print command list */
+ ConOutPrintf (_T("\nInternal commands available:\n"));
+ PrintCommandList ();
+
+ /* 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');
+}
+
+
+/*
+ * 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[])
+{
+ TCHAR commandline[CMDLINE_LENGTH];
+ TCHAR ModuleName[_MAX_PATH + 1];
+ INT i;
+
+#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);
+
+
+ if (argc >= 2 && !_tcsncmp (argv[1], _T("/?"), 2))
+ {
+ ConOutPuts (_T("Starts a new instance of the ReactOS command line interpreter.\n"
+ "\n"
+ "CMD [/[C|K] command][/P][/Q][/T:bf]\n"
+ "\n"
+ " /C command Runs the specified command and terminates.\n"
+ " /K command Runs the specified command and remains.\n"
+ " /P CMD becomes permanent and runs autoexec.bat\n"
+ " (cannot be terminated).\n"
+ " /T:bf Sets the background/foreground color (see COLOR command)."));
+ ExitProcess (0);
+ }
+ SetConsoleMode (hIn, ENABLE_PROCESSED_INPUT);
+
+#ifdef INCLUDE_CMD_CHDIR
+ InitLastPath ();
+#endif
+
+#ifdef FATURE_ALIASES
+ InitializeAlias ();
+#endif
+
+ if (argc >= 2)
+ {
+ 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 (_T("\\autoexec.bat"));
+ }
+ bCanExit = FALSE;
+ }
+ else if (!_tcsicmp (argv[i], _T("/c")))
+ {
+ /* This just runs a program and exits */
+ ++i;
+ if (argv[i])
+ {
+ _tcscpy (commandline, argv[i]);
+ while (argv[++i])
+ {
+ _tcscat (commandline, " ");
+ _tcscat (commandline, argv[i]);
+ }
+
+ ParseCommandLine(commandline);
+ ExitProcess (ProcessInput (TRUE));
+ }
+ else
+ {
+ ExitProcess (0);
+ }
+ }
+ else if (!_tcsicmp (argv[i], _T("/k")))
+ {
+ /* This just runs a program and remains */
+ ++i;
+ if (argv[i])
+ {
+ _tcscpy (commandline, argv[i]);
+ while (argv[++i])
+ {
+ _tcscat (commandline, " ");
+ _tcscat (commandline, argv[i]);
+ }
+
+ ParseCommandLine(commandline);
+ }
+ }
+#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;
+ SetScreenColor (wColor, TRUE);
+ }
+#endif
+ }
+ }
+
+ /* run cmdstart.bat */
+ if (IsValidFileName (_T("cmdstart.bat")))
+ {
+ ParseCommandLine (_T("cmdstart.bat"));
+ }
+ else if (IsValidFileName (_T("\\cmdstart.bat")))
+ {
+ ParseCommandLine (_T("\\cmdstart.bat"));
+ }
+#ifndef __REACTOS__
+ else
+ {
+ /* try to run cmdstart.bat from install dir */
+ LPTSTR p;
+
+ _tcscpy (commandline, argv[0]);
+ p = _tcsrchr (commandline, _T('\\')) + 1;
+ _tcscpy (p, _T("cmdstart.bat"));
+
+ if (IsValidFileName (_T("commandline")))
+ {
+ ConErrPrintf ("Running %s...\n", commandline);
+ ParseCommandLine (commandline);
+ }
+ }
+#endif
+
+#ifdef FEATURE_DIR_STACK
+ /* initialize directory stack */
+ InitDirectoryStack ();
+#endif
+
+
+#ifdef FEATURE_HISTORY
+ /*initialize history*/
+ InitHistory();
+#endif
+
+ /* Set COMSPEC environment variable */
+ if (0 != GetModuleFileName (NULL, ModuleName, _MAX_PATH + 1))
+ {
+ ModuleName[_MAX_PATH] = _T('\0');
+ SetEnvironmentVariable (_T("COMSPEC"), ModuleName);
+ }
+
+ /* add ctrl break handler */
+ AddBreakHandler ();
+}
+
+
+static VOID Cleanup (int argc, char *argv[])
+{
+ /* run cmdexit.bat */
+ if (IsValidFileName (_T("cmdexit.bat")))
+ {
+ ConErrPrintf ("Running cmdexit.bat...\n");
+ ParseCommandLine (_T("cmdexit.bat"));
+ }
+ else if (IsValidFileName (_T("\\cmdexit.bat")))
+ {
+ ConErrPrintf ("Running \\cmdexit.bat...\n");
+ ParseCommandLine (_T("\\cmdexit.bat"));
+ }
+#ifndef __REACTOS__
+ else
+ {
+ /* try to run cmdexit.bat from install dir */
+ TCHAR commandline[CMDLINE_LENGTH];
+ LPTSTR p;
+
+ _tcscpy (commandline, argv[0]);
+ p = _tcsrchr (commandline, _T('\\')) + 1;
+ _tcscpy (p, _T("cmdexit.bat"));
+
+ if (IsValidFileName (_T("commandline")))
+ {
+ ConErrPrintf ("Running %s...\n", commandline);
+ ParseCommandLine (commandline);
+ }
+ }
+#endif
+
+#ifdef FEATURE_ALIASES
+ DestroyAlias ();
+#endif
+
+#ifdef FEATURE_DIECTORY_STACK
+ /* destroy directory stack */
+ DestroyDirectoryStack ();
+#endif
+
+#ifdef INCLUDE_CMD_CHDIR
+ FreeLastPath ();
+#endif
+
+#ifdef FEATURE_HISTORY
+ CleanHistory();
+#endif
+
+
+ /* remove ctrl break handler */
+ RemoveBreakHandler ();
+ SetConsoleMode( GetStdHandle( STD_INPUT_HANDLE ),
+ ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT );
+}
+
+
+/*
+ * main function
+ */
+int main (int argc, char *argv[])
+{
+ CONSOLE_SCREEN_BUFFER_INFO Info;
+ INT nExitCode;
+
+ SetFileApisToOEM();
+
+ AllocConsole();
+ if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &Info) == FALSE)
+ {
+ fprintf(stderr, "GetConsoleScreenBufferInfo: Error: %ld\n", GetLastError());
+#ifndef __REACTOS__
+ /* On ReactOS GetConsoleScreenBufferInfo returns an error if the stdin
+ handle is redirected to a pipe or file. This stops windres from working. */
+ return(1);
+#endif
+ }
+ wColor = Info.wAttributes;
+ wDefColor = wColor;
+
+ /* check switches on command-line */
+ Initialize(argc, argv);
+
+ /* call prompt routine */
+ nExitCode = ProcessInput(FALSE);
+
+ /* do the cleanup */
+ Cleanup(argc, argv);
+
+ return(nExitCode);
+}
+
+/* EOF */
--- /dev/null
+/* $Id: cmd.h,v 1.1 2003/03/20 19:19:22 rcampbell Exp $
+ *
+ * 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.
+ *
+ * 26-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ * Introduced a new version string.
+ * Thanks to Emanuele Aliberti!
+ */
+
+#ifndef _CMD_H_INCLUDED_
+#define _CMD_H_INCLUDED_
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+
+#include "cmdver.h"
+
+#ifdef _MSC_VER
+#define SHELLVER "Version " CMD_VER " [" __DATE__ ", msc]"
+#else
+#ifdef __LCC__
+#define SHELLVER "Version " CMD_VER " [" __DATE__ ", lcc-win32]"
+#else
+#define SHELLVER "Version " CMD_VER " [" __DATE__ "]"
+#endif
+#endif
+
+
+#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 Interpreter"
+
+
+#define D_ON "on"
+#define D_OFF "off"
+
+
+/* command line buffer length */
+#ifdef __REACTOS__
+#define CMDLINE_LENGTH 512
+#else
+#define CMDLINE_LENGTH 8192
+//#define CMDLINE_LENGTH 1024
+#endif
+
+/* global variables */
+extern HANDLE hOut;
+extern HANDLE hIn;
+extern WORD wColor;
+extern WORD wDefColor;
+extern BOOL bCtrlBreak;
+extern BOOL bIgnoreEcho;
+extern BOOL bExit;
+extern INT nErrorLevel;
+extern SHORT maxx;
+extern SHORT maxy;
+extern OSVERSIONINFO osvi;
+
+
+
+/* Prototypes for ALIAS.C */
+VOID InitializeAlias (VOID);
+VOID DestroyAlias (VOID);
+VOID ExpandAlias (LPTSTR, INT);
+INT CommandAlias (LPTSTR, LPTSTR);
+
+
+/* Prototypes for ATTRIB.C */
+INT CommandAttrib (LPTSTR, LPTSTR);
+
+
+/* Prototypes for BEEP.C */
+INT cmd_beep (LPTSTR, LPTSTR);
+
+
+/* Prototypes for CALL.C */
+INT cmd_call (LPTSTR, LPTSTR);
+
+
+/* Prototypes for CHCP.C */
+INT CommandChcp (LPTSTR, LPTSTR);
+
+
+/* Prototypes for CHOICE.C */
+INT CommandChoice (LPTSTR, LPTSTR);
+
+
+/* Prototypes for CLS.C */
+INT cmd_cls (LPTSTR, LPTSTR);
+
+
+/* Prototypes for CMD.C */
+VOID ParseCommandLine (LPTSTR);
+VOID AddBreakHandler (VOID);
+VOID RemoveBreakHandler (VOID);
+
+
+/* Prototypes for CMDINPUT.C */
+VOID ReadCommand (LPTSTR, INT);
+
+
+/* Prototypes for CMDTABLE.C */
+#define CMD_SPECIAL 1
+#define CMD_BATCHONLY 2
+#define CMD_HIDE 4
+
+typedef struct tagCOMMAND
+{
+ LPTSTR name;
+ INT flags;
+ INT (*func) (LPTSTR, LPTSTR);
+} COMMAND, *LPCOMMAND;
+
+extern COMMAND cmds[]; /* The internal command table */
+
+VOID PrintCommandList (VOID);
+
+
+/* Prototypes for COLOR.C */
+VOID SetScreenColor(WORD wArgColor, BOOL bFill);
+INT CommandColor (LPTSTR, LPTSTR);
+
+
+/* Prototypes for CONSOLE.C */
+#ifdef _DEBUG
+VOID DebugPrintf (LPTSTR, ...);
+#endif /* _DEBUG */
+
+VOID ConInDummy (VOID);
+VOID ConInDisable (VOID);
+VOID ConInEnable (VOID);
+VOID ConInFlush (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 GetCursorX (VOID);
+SHORT GetCursorY (VOID);
+VOID GetCursorXY (PSHORT, PSHORT);
+VOID SetCursorXY (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 CommandDelete (LPTSTR, LPTSTR);
+
+
+/* Prototypes for DELAY.C */
+INT CommandDelay (LPTSTR, LPTSTR);
+
+
+/* Prototypes for DIR.C */
+INT CommandDir (LPTSTR, LPTSTR);
+
+
+/* Prototypes for DIRSTACK.C */
+VOID InitDirectoryStack (VOID);
+VOID DestroyDirectoryStack (VOID);
+INT GetDirectoryStackDepth (VOID);
+INT CommandPushd (LPTSTR, LPTSTR);
+INT CommandPopd (LPTSTR, LPTSTR);
+INT CommandDirs (LPTSTR, LPTSTR);
+
+
+/* Prototypes for ECHO.C */
+INT CommandEcho (LPTSTR, LPTSTR);
+INT CommandEchos (LPTSTR, LPTSTR);
+INT CommandEchoerr (LPTSTR, LPTSTR);
+INT CommandEchoserr (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 FOR.C */
+INT cmd_for (LPTSTR, LPTSTR);
+
+
+/* Prototypes for FREE.C */
+INT CommandFree (LPTSTR, LPTSTR);
+
+
+/* Prototypes for GOTO.C */
+INT cmd_goto (LPTSTR, LPTSTR);
+
+
+/* Prototypes for HISTORY.C */
+#ifdef FEATURE_HISTORY
+VOID History (INT, LPTSTR);/*add entries browse history*/
+VOID History_move_to_bottom(VOID);/*F3*/
+VOID InitHistory(VOID);
+VOID CleanHistory(VOID);
+VOID History_del_current_entry(LPTSTR str);/*CTRL-D*/
+INT CommandHistory (LPTSTR cmd, LPTSTR param);
+#endif
+
+
+/* Prototypes for INTERNAL.C */
+VOID InitLastPath (VOID);
+VOID FreeLastPath (VOID);
+INT cmd_chdir (LPTSTR, LPTSTR);
+INT cmd_mkdir (LPTSTR, LPTSTR);
+INT cmd_rmdir (LPTSTR, LPTSTR);
+INT CommandExit (LPTSTR, LPTSTR);
+INT CommandRem (LPTSTR, LPTSTR);
+INT CommandShowCommands (LPTSTR, LPTSTR);
+
+
+/* Prototypes 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);
+VOID PrintDate (VOID);
+VOID PrintTime (VOID);
+
+
+/* Prototypes for MEMORY.C */
+INT CommandMemory (LPTSTR, LPTSTR);
+
+
+/* Prototypes for MISC.C */
+TCHAR cgetchar (VOID);
+BOOL CheckCtrlBreak (INT);
+LPTSTR *split (LPTSTR, LPINT, BOOL);
+VOID freep (LPTSTR *);
+LPTSTR stpcpy (LPTSTR, LPTSTR);
+BOOL IsValidPathName (LPCTSTR);
+BOOL IsValidFileName (LPCTSTR);
+BOOL IsValidDirectory (LPCTSTR);
+BOOL FileGetString (HANDLE, LPTSTR, INT);
+#ifndef __REACTOS__
+HWND GetConsoleWindow(VOID);
+#endif
+
+#define PROMPT_NO 0
+#define PROMPT_YES 1
+#define PROMPT_ALL 2
+#define PROMPT_BREAK 3
+
+INT PagePrompt (VOID);
+INT FilePromptYN (LPTSTR, ...);
+INT FilePromptYNA (LPTSTR, ...);
+
+
+/* Prototypes for MOVE.C */
+INT cmd_move (LPTSTR, LPTSTR);
+
+
+/* Prototypes for MSGBOX.C */
+INT CommandMsgbox (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 SCREEN.C */
+INT CommandScreen (LPTSTR, LPTSTR);
+
+
+/* Prototypes for SET.C */
+INT cmd_set (LPTSTR, LPTSTR);
+
+
+/* Prototypes for START.C */
+INT cmd_start (LPTSTR, LPTSTR);
+
+
+/* Prototypes for STRTOCLR.C */
+BOOL StringToColor (LPWORD, LPTSTR *);
+
+
+/* Prototypes for TIME.C */
+INT cmd_time (LPTSTR, LPTSTR);
+
+
+/* Prototypes for TIMER.C */
+INT CommandTimer (LPTSTR cmd, LPTSTR param);
+
+
+/* Prototypes for TITLE.C */
+INT cmd_title (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 SearchForExecutable (LPCTSTR, LPTSTR);
+
+/* Prototypes for WINDOW.C */
+INT CommandActivate (LPTSTR, LPTSTR);
+INT CommandWindow (LPTSTR, LPTSTR);
+
+
+/* The MSDOS Batch Commands [MS-DOS 5.0 User's Guide and Reference p359] */
+int cmd_if(char *, char *);
+int cmd_pause(char *, char *);
+int cmd_shift(char *, char *);
+
+#endif /* _CMD_H_INCLUDED_ */
--- /dev/null
+#include <windows.h>
+#include <reactos/resource.h>
+#include "cmdver.h"
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
+ PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", RES_STR_COMPANY_NAME
+ VALUE "FileDescription", "ReactOS Command Processor\0"
+ VALUE "FileVersion", CMD_VER_RC
+ VALUE "InternalName", "cmd\0"
+ VALUE "OriginalCopyright", "Copyright (C) 1994-1998 Tim Norman and others\0"
+ VALUE "LegalCopyright", "Copyright (C) 1998-2001 Eric Kohl and others\0"
+ VALUE "OriginalFilename", "cmd.exe\0"
+ VALUE "ProductName", RES_STR_PRODUCT_NAME
+ VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
--- /dev/null
+/*
+ * 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 remained in the keyboard
+ * input queue when you pressed <RETURN>. This sometimes caused
+ * some very strange effects.
+ * Fixed some command line editing annoyances.
+ */
+
+#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;
+
+ SetCursorXY (orgx, orgy);
+ for (count = 0; count < (INT)_tcslen (str); count++)
+ ConOutChar (_T(' '));
+ _tcsnset (str, _T('\0'), maxlen);
+ SetCursorXY (orgx, orgy);
+}
+
+
+/* read in a command line */
+VOID ReadCommand (LPTSTR str, INT maxlen)
+{
+ SHORT orgx; /* origin x/y */
+ SHORT orgy;
+ SHORT curx; /*current x/y cursor position*/
+ SHORT cury;
+ INT count; /*used in some for loops*/
+ INT current = 0; /*the position of the cursor in the string (str)*/
+ INT charcount = 0;/*chars in the string (str)*/
+ INPUT_RECORD ir;
+ WORD wLastKey = 0;
+ TCHAR ch;
+ BOOL bContinue=FALSE;/*is TRUE the second case will not be executed*/
+
+ /* get screen size */
+ GetScreenSize (&maxx, &maxy);
+
+ /* JPP 19980807 - if echo off, don't print prompt */
+ if (bEcho)
+ PrintPrompt();
+
+ GetCursorXY (&orgx, &orgy);
+
+ memset (str, 0, maxlen * sizeof (TCHAR));
+
+ SetCursorType (bInsert, TRUE);
+
+ do
+ {
+ ConInKey (&ir);
+
+ if (ir.Event.KeyEvent.dwControlKeyState &
+ (RIGHT_ALT_PRESSED|RIGHT_ALT_PRESSED|
+ RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED) )
+ {
+
+ switch (ir.Event.KeyEvent.wVirtualKeyCode)
+ {
+
+#ifdef FEATURE_HISTORY
+
+ case 'K':
+ /*add the current command line to the history*/
+ if (ir.Event.KeyEvent.dwControlKeyState &
+ (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
+ {
+
+ if (str[0])
+ History(0,str);
+
+ ClearCommandLine (str, maxlen, orgx, orgy);
+ current = charcount = 0;
+ bContinue=TRUE;
+ break;
+ }
+
+ case 'D':
+ /*delete current history entry*/
+ if (ir.Event.KeyEvent.dwControlKeyState &
+ (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
+ {
+ ClearCommandLine (str, maxlen, orgx, orgy);
+ History_del_current_entry(str);
+ current = charcount = _tcslen (str);
+ ConOutPrintf (_T("%s"), str);
+ bContinue=TRUE;
+ break;
+ }
+
+#endif/*FEATURE_HISTORY*/
+ }
+
+
+
+
+ }
+
+ //if (bContinue)
+ // continue;
+
+
+
+ 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 (GetCursorX () != 0)
+ {
+ ConOutPrintf ("\b \b");
+ }
+ else
+ {
+ SetCursorXY ((SHORT)(maxx - 1), (SHORT)(GetCursorY () - 1));
+ ConOutChar (_T(' '));
+ SetCursorXY ((SHORT)(maxx - 1), (SHORT)(GetCursorY () - 1));
+ }
+ }
+ else
+ {
+ for (count = current - 1; count < charcount; count++)
+ str[count] = str[count + 1];
+ if (GetCursorX () != 0)
+ SetCursorXY ((SHORT)(GetCursorX () - 1), GetCursorY ());
+ else
+ SetCursorXY ((SHORT)(maxx - 1), (SHORT)(GetCursorY () - 1));
+ GetCursorXY (&curx, &cury);
+ ConOutPrintf (_T("%s "), &str[current - 1]);
+ SetCursorXY (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--;
+ GetCursorXY (&curx, &cury);
+ ConOutPrintf (_T("%s "), &str[current]);
+ SetCursorXY (curx, cury);
+ }
+ break;
+
+ case VK_HOME:
+ /* goto beginning of string */
+ if (current != 0)
+ {
+ SetCursorXY (orgx, orgy);
+ current = 0;
+ }
+ break;
+
+ case VK_END:
+ /* goto end of string */
+ if (current != charcount)
+ {
+ SetCursorXY (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;
+
+ SetCursorXY (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 ();
+ GetCursorXY (&orgx, &orgy);
+ ConOutPrintf (_T("%s"), str);
+ }
+
+ }
+ }
+ else
+ {
+#ifdef __REACTOS__
+ Beep (440, 50);
+#else
+ MessageBeep (-1);
+#endif
+ }
+#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;
+
+#ifdef FEATURE_HISTORY
+ case VK_F3:
+ History_move_to_bottom();
+#endif
+ 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 (GetCursorX () == 0)
+ SetCursorXY ((SHORT)(maxx - 1), (SHORT)(GetCursorY () - 1));
+ else
+ SetCursorXY ((SHORT)(GetCursorX () - 1), GetCursorY ());
+ }
+ else
+ {
+#ifdef __REACTOS__
+ Beep (440, 50);
+#else
+ MessageBeep (-1);
+#endif
+ }
+ break;
+
+ case VK_RIGHT:
+ /* move cursor right */
+ if (current != charcount)
+ {
+ current++;
+ if (GetCursorX () == maxx - 1)
+ SetCursorXY (0, (SHORT)(GetCursorY () + 1));
+ else
+ SetCursorXY ((SHORT)(GetCursorX () + 1), GetCursorY ());
+ }
+ break;
+
+#if 0
+
+#ifdef FEATURE_HISTORY
+
+
+ /*!!!WARNING!!!*/
+ /*this will only work as long as the two if statement
+ evaluates the same expression and a break is included
+ in each if statement.
+ This can be used for any combination using CTRL.
+ For other combinations is needed another system*/
+
+ case 'K':
+ /*add the current command line to the history*/
+ if (ir.Event.KeyEvent.dwControlKeyState &
+ (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
+ {
+
+ if (str[0])
+ History(0,str);
+
+ ClearCommandLine (str, maxlen, orgx, orgy);
+ current = charcount = 0;
+ break;
+ }
+
+ case 'D':
+ if (ir.Event.KeyEvent.dwControlKeyState &
+ (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
+ {
+ ClearCommandLine (str, maxlen, orgx, orgy);
+ History_del_current_entry(str);
+ current = charcount = _tcslen (str);
+ ConOutPrintf (_T("%s"), str);
+ break;
+ }
+
+#endif/*FEATURE_HISTORY*/
+#endif/*0*/
+
+ default:
+#ifdef _UNICODE
+ ch = ir.Event.KeyEvent.uChar.UnicodeChar;
+ if ((ch >= 32 && ch <= 255) && (charcount != (maxlen - 2)))
+#else
+ ch = ir.Event.KeyEvent.uChar.AsciiChar;
+ if (ch >= 32 && (charcount != (maxlen - 2)))
+#endif /* _UNICODE */
+ {
+ /* insert character into string... */
+ if (bInsert && current != charcount)
+ {
+ for (count = charcount; count > current; count--)
+ str[count] = str[count - 1];
+ str[current++] = ch;
+ if (GetCursorX () == maxx - 1)
+ {
+ curx = 0;
+ cury = GetCursorY () + 1;
+ }
+ else
+ {
+ GetCursorXY (&curx, &cury);
+ curx++;
+ }
+ ConOutPrintf (_T("%s"), &str[current - 1]);
+ if ((_tcslen (str) > (USHORT)(maxx - orgx)) && (orgy == maxy + 1))
+ cury--;
+ SetCursorXY (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
+ {
+#ifdef __REACTOS__
+ Beep (440, 100);
+#else
+ MessageBeep (-1);
+#endif
+ }
+#endif
+ break;
+
+ }
+ wLastKey = ir.Event.KeyEvent.wVirtualKeyCode;
+ }
+ while (ir.Event.KeyEvent.wVirtualKeyCode != VK_RETURN);
+
+ SetCursorType (bInsert, TRUE);
+}
--- /dev/null
+/*
+ * 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!
+ */
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+
+#include "cmd.h"
+
+/* a list of all the internal commands, associating their command names */
+/* to the functions to process them */
+
+
+COMMAND cmds[] =
+{
+ {_T("?"), 0, CommandShowCommands},
+
+#ifdef INCLUDE_CMD_ACTIVATE
+ {_T("activate"), 0, CommandActivate},
+#endif
+
+#ifdef FEATURE_ALIASES
+ {_T("alias"), 0, CommandAlias},
+#endif
+
+#ifdef INCLUDE_CMD_ATTRIB
+ {_T("attrib"), 0, CommandAttrib},
+#endif
+
+#ifdef INCLUDE_CMD_BEEP
+ {_T("beep"), 0, cmd_beep},
+#endif
+
+ {_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_CHOICE
+ {_T("choice"), 0, CommandChoice},
+#endif
+
+#ifdef INCLUDE_CMD_CLS
+ {_T("cls"), 0, cmd_cls},
+#endif
+
+#ifdef INCLUDE_CMD_COLOR
+ {_T("color"), 0, CommandColor},
+#endif
+
+#ifdef INCLUDE_CMD_COPY
+ {_T("copy"), 0, cmd_copy},
+#endif
+
+#ifdef INCLUDE_CMD_DATE
+ {_T("date"), 0, cmd_date},
+#endif
+
+#ifdef INCLUDE_CMD_DEL
+ {_T("del"), 0, CommandDelete},
+ {_T("delete"), 0, CommandDelete},
+#endif
+
+#ifdef INCLUDE_CMD_DELAY
+ {_T("delay"), 0, CommandDelay},
+#endif
+
+#ifdef INCLUDE_CMD_DIR
+ {_T("dir"), CMD_SPECIAL, CommandDir},
+#endif
+
+#ifdef FEATURE_DIRECTORY_STACK
+ {_T("dirs"), 0, CommandDirs},
+#endif
+
+ {_T("echo"), 0, CommandEcho},
+ {_T("echo."), CMD_HIDE, CommandEcho},
+ {_T("echos"), 0, CommandEchos},
+ {_T("echoerr"), 0, CommandEchoerr},
+ {_T("echoerr."), CMD_HIDE, CommandEchoerr},
+ {_T("echoserr"), 0, CommandEchoserr},
+
+#ifdef INCLUDE_CMD_DEL
+ {_T("erase"), 0, CommandDelete},
+#endif
+
+ {_T("exit"), 0, CommandExit},
+
+ {_T("for"), 0, cmd_for},
+
+#ifdef INCLUDE_CMD_FREE
+ {_T("free"), 0, CommandFree},
+#endif
+
+ {_T("goto"), CMD_BATCHONLY, cmd_goto},
+
+#ifdef FEATURE_HISTORY
+ {_T("history"), 0, CommandHistory},
+#endif
+
+ {_T("if"), 0, cmd_if},
+
+#ifdef INCLUDE_CMD_LABEL
+ {_T("label"), 0, cmd_label},
+#endif
+
+#ifdef INCLUDE_CMD_MEMORY
+ {_T("memory"), 0, CommandMemory},
+#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_MSGBOX
+ {_T("msgbox"), 0, CommandMsgbox},
+#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, CommandPopd},
+#endif
+
+#ifdef INCLUDE_CMD_PROMPT
+ {_T("prompt"), 0, cmd_prompt},
+#endif
+
+#ifdef FEATURE_DIRECTORY_STACK
+ {_T("pushd"), 0, CommandPushd},
+#endif
+
+#ifdef INCLUDE_CMD_RMDIR
+ {_T("rd"), CMD_SPECIAL, cmd_rmdir},
+#endif
+
+#ifdef INCLUDE_CMD_REM
+ {_T("rem"), 0, CommandRem},
+#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_SCREEN
+ {_T("screen"), 0, CommandScreen},
+#endif
+
+#ifdef INCLUDE_CMD_SET
+ {_T("set"), 0, cmd_set},
+#endif
+
+ {_T("shift"), CMD_BATCHONLY, cmd_shift},
+
+#ifdef INCLUDE_CMD_START
+ {_T("start"), 0, cmd_start},
+#endif
+
+#ifdef INCLUDE_CMD_TIME
+ {_T("time"), 0, cmd_time},
+#endif
+
+#ifdef INCLUDE_CMD_TIMER
+ {_T("timer"), 0, CommandTimer},
+#endif
+
+#ifdef INCLUDE_CMD_TITLE
+ {_T("title"), 0, cmd_title},
+#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
+
+#ifdef INCLUDE_CMD_WINDOW
+ {_T("window"), 0, CommandWindow},
+#endif
+
+ {NULL, 0, NULL}
+};
+
+
+VOID PrintCommandList (VOID)
+{
+ LPCOMMAND cmdptr;
+ INT y;
+
+ y = 0;
+ cmdptr = cmds;
+ while (cmdptr->name)
+ {
+ if (!(cmdptr->flags & CMD_HIDE))
+ {
+ if (++y == 8)
+ {
+ ConOutPuts (cmdptr->name);
+ y = 0;
+ }
+ else
+ {
+ ConOutPrintf (_T("%-10s"), cmdptr->name);
+ }
+ }
+
+ cmdptr++;
+ }
+
+ if (y != 0)
+ ConOutChar ('\n');
+}
+
+/* EOF */
--- /dev/null
+#define CMD_VER "0.1.2"
+#define CMD_VER_RC CMD_VER"\0"
--- /dev/null
+/* $Id: color.c,v 1.1 2003/03/20 19:19:22 rcampbell Exp $
+ *
+ * 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!
+ *
+ * 14-Oct-1999 (Paolo Pantaleo <paolopan@freemail.it>)
+ * 4nt's syntax implemented
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_COLOR
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+static VOID ColorHelp (VOID)
+{
+ ConOutPuts (_T(
+ "Sets the default foreground and background colors.\n"
+ "\n"
+ "COLOR [attr [/F]] \n\n"
+ " attr Specifies color attribute of console output\n"
+ " /F fill the console with color attribute\n"
+ "\n"
+ "There are three ways to specify the colors:"
+ ));
+
+ ConOutPuts (_T(
+ "\n"
+ "1) [bright] name on [bright] name (only the first three letters are required)\n"
+ "2) decimal on decimal\n"
+ "3) two hex digits\n"
+ "\n"
+ "Colors are:"
+ ));
+
+ ConOutPuts (_T(
+ "dec hex name dec hex name\n"
+ "0 0 Black 8 8 Gray(Bright black)\n"
+ "1 1 Blue 9 9 Bright Blue\n"
+ "2 2 Green 10 A Bright Green\n"
+ "3 3 Cyan 11 B Bright Cyan\n"
+ "4 4 Red 12 C Bright Red\n"
+ "5 5 Magenta 13 D Bright Magenta\n"
+ "6 6 Yellow 14 E Bright Yellow\n"
+ "7 7 White 15 F Bright White"));
+}
+
+
+VOID SetScreenColor (WORD wColor, BOOL bFill)
+{
+ DWORD dwWritten;
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ COORD coPos;
+
+ if (bFill == TRUE)
+ {
+ GetConsoleScreenBufferInfo (hOut, &csbi);
+
+ coPos.X = 0;
+ coPos.Y = 0;
+ FillConsoleOutputAttribute (hOut,
+ (WORD)(wColor & 0x00FF),
+ (csbi.dwSize.X)*(csbi.dwSize.Y),
+ coPos,
+ &dwWritten);
+ }
+ SetConsoleTextAttribute (hOut, (WORD)(wColor & 0x00FF));
+}
+
+
+/*
+ * color
+ *
+ * internal dir command
+ */
+INT CommandColor (LPTSTR first, LPTSTR rest)
+{
+ if (_tcsncmp (rest, _T("/?"), 2) == 0)
+ {
+ ColorHelp ();
+ return 0;
+ }
+
+ if (rest[0] == _T('\0'))
+ {
+ /* set default color */
+ wColor = wDefColor;
+ SetScreenColor (wColor, TRUE);
+ return 0;
+ }
+
+ if (StringToColor (&wColor, &rest) == FALSE)
+ {
+ ConErrPuts("error in color specification");
+ return 1;
+ }
+
+ ConErrPrintf ("Color %x\n", wColor);
+
+ if ((wColor & 0xF) == (wColor &0xF0) >> 4)
+ {
+ ConErrPuts (_T("same colors error!"));
+ return 1;
+ }
+
+ /* set color */
+ SetScreenColor (wColor,
+ (_tcsstr (rest,"/F") || _tcsstr (rest,"/f")));
+
+ return 0;
+}
+
+#endif /* INCLUDE_CMD_COLOR */
+
+/* EOF */
--- /dev/null
+/*
+ * CONFIG.H - Used to configure what will be compiled into the shell.
+ *
+ *
+ * History:
+ *
+ * 27 Jul 1998 - John P. Price
+ * started.
+ *
+ */
+
+/* Define only if used under ReactOS */
+#define __REACTOS__
+
+#ifndef _CONFIG_H_INCLUDED_
+#define _CONFIG_H_INCLUDED_
+
+
+#ifndef __REACTOS__
+#define WIN32_LEAN_AND_MEAN
+#endif /* __REACTOS__ */
+
+
+/* Define to enable debugging code */
+//#define _DEBUG
+
+
+/* Define to enable the alias command, and aliases.*/
+#define FEATURE_ALIASES
+
+
+/* Define to enable history */
+#define FEATURE_HISTORY
+
+/*Define to enable history wrap (4nt's style)*/
+#define WRAP_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, PROMPT etc. */
+#ifdef __REACTOS__
+#define LOCALE_DEFAULT
+#else
+#define LOCALE_WINDOWS /* System locale */
+/* #define LOCALE_GERMAN */ /* German locale */
+/* #define LOCALE_DEFAULT */ /* United States locale */
+#endif
+
+#ifndef __REACTOS__
+#define INCLUDE_CMD_ACTIVATE
+#endif
+#define INCLUDE_CMD_ATTRIB
+#define INCLUDE_CMD_CHCP
+#define INCLUDE_CMD_CHDIR
+#define INCLUDE_CMD_CHOICE
+#define INCLUDE_CMD_CLS
+#define INCLUDE_CMD_COLOR
+#define INCLUDE_CMD_COPY
+#define INCLUDE_CMD_DATE
+#define INCLUDE_CMD_DEL
+#define INCLUDE_CMD_DELAY
+#define INCLUDE_CMD_DIR
+#define INCLUDE_CMD_FREE
+#define INCLUDE_CMD_LABEL
+#define INCLUDE_CMD_MEMORY
+#define INCLUDE_CMD_MKDIR
+#define INCLUDE_CMD_MOVE
+#ifndef __REACTOS__
+#define INCLUDE_CMD_MSGBOX
+#endif
+#define INCLUDE_CMD_PATH
+#define INCLUDE_CMD_PROMPT
+#define INCLUDE_CMD_RMDIR
+#define INCLUDE_CMD_RENAME
+#define INCLUDE_CMD_SCREEN
+#define INCLUDE_CMD_SET
+#define INCLUDE_CMD_START
+#define INCLUDE_CMD_TIME
+#define INCLUDE_CMD_TIMER
+#define INCLUDE_CMD_TITLE
+#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
+#ifndef __REACTOS__
+#define INCLUDE_CMD_WINDOW
+#endif
+
+#endif /* _CONFIG_H_INCLUDED_ */
--- /dev/null
+/* $Id: console.c,v 1.1 2003/03/20 19:19:22 rcampbell Exp $
+ *
+ * CONSOLE.C - console input/output functions.
+ *
+ *
+ * History:
+ *
+ * 20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ * started
+ */
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "cmd.h"
+
+
+#define OUTPUT_BUFFER_SIZE 4096
+
+
+#ifdef _DEBUG
+VOID DebugPrintf (LPTSTR szFormat, ...)
+{
+ TCHAR szOut[OUTPUT_BUFFER_SIZE];
+ va_list arg_ptr;
+ DWORD dwWritten;
+
+ va_start (arg_ptr, szFormat);
+ _vstprintf (szOut, szFormat, arg_ptr);
+ va_end (arg_ptr);
+
+ WriteFile (GetStdHandle (STD_ERROR_HANDLE),
+ szOut,
+ _tcslen(szOut) * sizeof(TCHAR),
+ &dwWritten,
+ NULL);
+#if 0
+ OutputDebugString (szOut);
+#endif
+}
+#endif /* _DEBUG */
+
+
+VOID ConInDisable (VOID)
+{
+ HANDLE hInput = GetStdHandle (STD_INPUT_HANDLE);
+ DWORD dwMode;
+
+ GetConsoleMode (hInput, &dwMode);
+ dwMode &= ~ENABLE_PROCESSED_INPUT;
+ SetConsoleMode (hInput, dwMode);
+}
+
+
+VOID ConInEnable (VOID)
+{
+ HANDLE hInput = GetStdHandle (STD_INPUT_HANDLE);
+ DWORD dwMode;
+
+ GetConsoleMode (hInput, &dwMode);
+ dwMode |= ENABLE_PROCESSED_INPUT;
+ SetConsoleMode (hInput, dwMode);
+}
+
+
+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 /* _DEBUG */
+
+ ReadConsoleInput (hInput, &dummy, 1, &dwRead);
+}
+
+VOID ConInFlush (VOID)
+{
+ FlushConsoleInputBuffer (GetStdHandle (STD_INPUT_HANDLE));
+}
+
+
+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 /* _DEBUG */
+
+ do
+ {
+ 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);
+
+ 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,
+ sizeof(TCHAR),
+ &dwWritten,
+ NULL);
+}
+
+
+VOID ConOutPuts (LPTSTR szText)
+{
+ DWORD dwWritten;
+
+ WriteFile (GetStdHandle (STD_OUTPUT_HANDLE),
+ szText,
+ _tcslen(szText) * sizeof(TCHAR),
+ &dwWritten,
+ NULL);
+ WriteFile (GetStdHandle (STD_OUTPUT_HANDLE),
+ _T("\n"),
+ sizeof(TCHAR),
+ &dwWritten,
+ NULL);
+}
+
+
+VOID ConOutPrintf (LPTSTR szFormat, ...)
+{
+ TCHAR szOut[OUTPUT_BUFFER_SIZE];
+ DWORD dwWritten;
+ va_list arg_ptr;
+
+ va_start (arg_ptr, szFormat);
+ _vstprintf (szOut, szFormat, arg_ptr);
+ va_end (arg_ptr);
+
+ WriteFile (GetStdHandle (STD_OUTPUT_HANDLE),
+ szOut,
+ _tcslen(szOut) * sizeof(TCHAR),
+ &dwWritten,
+ NULL);
+}
+
+
+VOID ConErrChar (TCHAR c)
+{
+ DWORD dwWritten;
+
+ WriteFile (GetStdHandle (STD_ERROR_HANDLE),
+ &c,
+ sizeof(TCHAR),
+ &dwWritten,
+ NULL);
+}
+
+
+VOID ConErrPuts (LPTSTR szText)
+{
+ DWORD dwWritten;
+
+ WriteFile (GetStdHandle (STD_ERROR_HANDLE),
+ szText,
+ _tcslen(szText) * sizeof(TCHAR),
+ &dwWritten,
+ NULL);
+ WriteFile (GetStdHandle (STD_ERROR_HANDLE),
+ _T ("\n"),
+ sizeof(TCHAR),
+ &dwWritten,
+ NULL);
+}
+
+
+VOID ConErrPrintf (LPTSTR szFormat, ...)
+{
+ TCHAR szOut[OUTPUT_BUFFER_SIZE];
+ DWORD dwWritten;
+ va_list arg_ptr;
+
+ va_start (arg_ptr, szFormat);
+ _vstprintf (szOut, szFormat, arg_ptr);
+ va_end (arg_ptr);
+
+ WriteFile (GetStdHandle (STD_ERROR_HANDLE),
+ szOut,
+ _tcslen(szOut) * sizeof(TCHAR),
+ &dwWritten,
+ NULL);
+}
+
+
+VOID SetCursorXY (SHORT x, SHORT y)
+{
+ COORD coPos;
+
+ coPos.X = x;
+ coPos.Y = y;
+ SetConsoleCursorPosition (GetStdHandle (STD_OUTPUT_HANDLE), coPos);
+}
+
+
+VOID GetCursorXY (PSHORT x, PSHORT y)
+{
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+ GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &csbi);
+
+ *x = csbi.dwCursorPosition.X;
+ *y = csbi.dwCursorPosition.Y;
+}
+
+
+SHORT GetCursorX (VOID)
+{
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+ GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &csbi);
+
+ return csbi.dwCursorPosition.X;
+}
+
+
+SHORT GetCursorY (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 : 99;
+ cci.bVisible = bVisible;
+
+ SetConsoleCursorInfo (GetStdHandle (STD_OUTPUT_HANDLE), &cci);
+}
+
+/* EOF */
--- /dev/null
+/* $Id: copy.c,v 1.1 2003/03/20 19:19:22 rcampbell Exp $
+ *
+ * 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.
+ *
+ * 27-Oct-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ * Disabled prompting when used in batch mode.
+ */
+
+#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"
+#include "batch.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 *, LPDWORD);
+static BOOL AddFiles (LPFILES, char *, int *, int *, int *, LPDWORD);
+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, LPDWORD 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, LPDWORD 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 = NULL;
+ 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);
+ ConOutPuts (_T(""));
+
+ _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;
+ }
+
+ 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;
+}
+
+
+static INT
+SetupCopy (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];
+ CHAR dir_s[_MAX_DIR];
+ char file_s[_MAX_FNAME];
+ char 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;
+
+#ifdef _DEBUG
+ DebugPrintf (_T("SetupCopy\n"));
+#endif
+
+ 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();
+ 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)
+ {
+ /* Don't prompt in a batch file */
+ if (bc != NULL)
+ {
+ bAll = TRUE;
+ }
+ else
+ {
+ int over;
+
+ 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];
+ char dir_d[_MAX_DIR];
+ char file_d[_MAX_FNAME];
+ char ext_d[_MAX_EXT];
+
+ int argc;
+ int append;
+ int files;
+ int copied;
+
+ LPFILES sources = NULL;
+ LPFILES start = NULL;
+ FILES dest;
+ 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, FALSE);
+
+ 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 = SetupCopy (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 = SetupCopy (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 = SetupCopy (sources->next, p, bMultiple, drive_d, dir_d, file_d, ext_d, &append, &dwFlags) + 1;
+ }
+
+ DeleteFileList (sources);
+ freep (p);
+ ConOutPrintf (_T(" %d file(s) copied\n"), copied);
+
+ return 1;
+}
+#endif /* INCLUDE_CMD_COPY */
+
+/* EOF */
--- /dev/null
+/*
+ * 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.
+ */
+
+#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
+PrintDateString (VOID)
+{
+ switch (nDateFormat)
+ {
+ case 0: /* mmddyy */
+ default:
+ ConOutPrintf (_T("\nEnter new date (mm%cdd%cyyyy): "),
+ cDateSeparator, cDateSeparator);
+ break;
+
+ case 1: /* ddmmyy */
+ ConOutPrintf (_T("\nEnter new date (dd%cmm%cyyyy): "),
+ cDateSeparator, cDateSeparator);
+ break;
+
+ case 2: /* yymmdd */
+ ConOutPrintf (_T("\nEnter 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, FALSE);
+
+ /* 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
+
--- /dev/null
+/*
+ * 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-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeiung.de>)
+ * First working version.
+ *
+ * 30-Mar-1999 (Eric Kohl <ekohl@abo.rhein-zeiung.de>)
+ * Added quiet ("/Q"), wipe ("/W") and zap ("/Z") option.
+ *
+ * 06-Nov-1999 (Eric Kohl <ekohl@abo.rhein-zeiung.de>)
+ * Little fix to keep DEL quiet inside batch files.
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_DEL
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+enum
+{
+ DEL_ATTRIBUTES = 0x001, /* /A : not implemented */
+ DEL_ERROR = 0x002, /* /E : not implemented */
+ DEL_NOTHING = 0x004, /* /N */
+ DEL_PROMPT = 0x008, /* /P : not implemented */
+ DEL_QUIET = 0x010, /* /Q */
+ DEL_SUBDIR = 0x020, /* /S : not implemented */
+ DEL_TOTAL = 0x040, /* /T */
+ DEL_WIPE = 0x080, /* /W */
+ DEL_EMPTYDIR = 0x100, /* /X : not implemented */
+ DEL_YES = 0x200, /* /Y : not implemented */
+ DEL_ZAP = 0x400 /* /Z */
+};
+
+
+
+static BOOL
+RemoveFile (LPTSTR lpFileName, DWORD dwFlags)
+{
+ if (dwFlags & DEL_WIPE)
+ {
+
+ /* FIXME: Wipe the given file */
+
+ }
+
+ return DeleteFile (lpFileName);
+}
+
+
+INT CommandDelete (LPTSTR cmd, LPTSTR param)
+{
+ TCHAR szFullPath[MAX_PATH];
+ LPTSTR pFilePart;
+ LPTSTR *arg = NULL;
+ INT args;
+ INT i;
+ INT nEvalArgs = 0; /* nunber of evaluated arguments */
+ DWORD dwFlags = 0;
+ DWORD dwFiles = 0;
+
+ HANDLE hFile;
+ WIN32_FIND_DATA f;
+
+ if (!_tcsncmp (param, _T("/?"), 2))
+ {
+ ConOutPuts (_T("Deletes one or more files.\n"
+ "\n"
+ "DEL [/N /P /T /Q /W /Z] file ...\n"
+ "DELETE [/N /P /T /Q /W /Z] file ...\n"
+ "ERASE [/N /P /T /Q /W /Z] 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"
+ " /T Display total number of deleted files and freed disk space.\n"
+ " /Q Quiet.\n"
+ " /W Wipe. Overwrite the file with zeros before deleting it.\n"
+ " /Z Zap (delete hidden, read-only and system files).\n"));
+
+ return 0;
+ }
+
+ arg = split (param, &args, FALSE);
+
+ 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'):
+ dwFlags |= DEL_NOTHING;
+ break;
+
+ case _T('P'):
+ dwFlags |= DEL_PROMPT;
+ break;
+
+ case _T('Q'):
+ dwFlags |= DEL_QUIET;
+ break;
+
+ case _T('S'):
+ dwFlags |= DEL_SUBDIR;
+ break;
+
+ case _T('T'):
+ dwFlags |= DEL_TOTAL;
+ break;
+
+ case _T('W'):
+ dwFlags |= DEL_WIPE;
+ break;
+
+ case _T('Z'):
+ dwFlags |= DEL_ZAP;
+ break;
+ }
+
+ }
+
+ nEvalArgs++;
+ }
+ }
+
+ /* there are only options on the command line --> error!!! */
+ if (args == nEvalArgs)
+ {
+ error_req_param_missing ();
+ freep (arg);
+ return 1;
+ }
+
+ /* keep quiet within batch files */
+ if (bc != NULL)
+ dwFlags |= DEL_QUIET;
+
+ /* check for filenames anywhere in command line */
+ for (i = 0; i < args; i++)
+ {
+ if (!_tcscmp (arg[i], _T("*")) ||
+ !_tcscmp (arg[i], _T("*.*")))
+ {
+ INT res;
+
+ res = FilePromptYN (_T("All files in directory will be deleted!\n"
+ "Are you sure (Y/N)?"));
+ if ((res == PROMPT_NO) ||
+ (res == PROMPT_BREAK))
+ break;
+ }
+
+ if (*arg[i] != _T('/'))
+ {
+#ifdef _DEBUG
+ ConErrPrintf (_T("File: %s\n"), arg[i]);
+#endif
+
+ if (_tcschr (arg[i], _T('*')) || _tcschr (arg[i], _T('?')))
+ {
+ /* wildcards in filespec */
+#ifdef _DEBUG
+ ConErrPrintf (_T("Wildcards!\n\n"));
+#endif
+
+ GetFullPathName (arg[i],
+ MAX_PATH,
+ szFullPath,
+ &pFilePart);
+
+#ifdef _DEBUG
+ ConErrPrintf (_T("Full path: %s\n"), szFullPath);
+ ConErrPrintf (_T("File part: %s\n"), pFilePart);
+#endif
+
+ hFile = FindFirstFile (szFullPath, &f);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ error_file_not_found ();
+ freep (arg);
+ return 0;
+ }
+
+ do
+ {
+ /* ignore "." and ".." */
+ if (!_tcscmp (f.cFileName, _T(".")) ||
+ !_tcscmp (f.cFileName, _T("..")))
+ continue;
+
+ _tcscpy (pFilePart, f.cFileName);
+
+#ifdef _DEBUG
+ ConErrPrintf (_T("Full filename: %s\n"), szFullPath);
+#endif
+
+ if (!(dwFlags & DEL_QUIET) && !(dwFlags & DEL_TOTAL))
+ ConErrPrintf (_T("Deleting: %s\n"), szFullPath);
+
+ /* delete the file */
+ if (!(dwFlags & DEL_NOTHING))
+ {
+ if (RemoveFile (szFullPath, dwFlags))
+ {
+ dwFiles++;
+ }
+ else
+ {
+ if (dwFlags & DEL_ZAP)
+ {
+ if (SetFileAttributes (szFullPath, 0))
+ {
+ if (RemoveFile (szFullPath, dwFlags))
+ {
+ dwFiles++;
+ }
+ else
+ {
+ ErrorMessage (GetLastError(), _T(""));
+ }
+ }
+ else
+ {
+ ErrorMessage (GetLastError(), _T(""));
+ }
+ }
+ else
+ {
+ ErrorMessage (GetLastError(), _T(""));
+ }
+ }
+ }
+ }
+ while (FindNextFile (hFile, &f));
+ FindClose (hFile);
+ }
+ else
+ {
+ /* no wildcards in filespec */
+#ifdef _DEBUG
+ ConErrPrintf (_T("No Wildcards!\n"));
+#endif
+ GetFullPathName (arg[i],
+ MAX_PATH,
+ szFullPath,
+ &pFilePart);
+#ifdef _DEBUG
+ ConErrPrintf (_T("Full path: %s\n"), szFullPath);
+#endif
+ if (!(dwFlags & DEL_QUIET) && !(dwFlags & DEL_TOTAL))
+ ConOutPrintf (_T("Deleting %s\n"), szFullPath);
+
+ if (!(dwFlags & DEL_NOTHING))
+ {
+ if (RemoveFile (szFullPath, dwFlags))
+ {
+ dwFiles++;
+ }
+ else
+ {
+ if (dwFlags & DEL_ZAP)
+ {
+ if (SetFileAttributes (szFullPath, 0))
+ {
+ if (RemoveFile (szFullPath, dwFlags))
+ {
+ dwFiles++;
+ }
+ else
+ {
+ ErrorMessage (GetLastError(), _T(""));
+ }
+ }
+ else
+ {
+ ErrorMessage (GetLastError(), _T(""));
+ }
+ }
+ else
+ {
+ ErrorMessage (GetLastError(), _T(""));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ /* only command given */
+ error_req_param_missing ();
+ freep (arg);
+ return 1;
+ }
+
+ freep (arg);
+
+ if (!(dwFlags & DEL_QUIET))
+ {
+ if (dwFiles == 0)
+ ConOutPrintf (_T(" 0 files deleted\n"));
+ else
+ ConOutPrintf (_T(" %lu file%s deleted\n"),
+ dwFiles,
+ (dwFiles == 1) ? "" : "s");
+ }
+
+ return 0;
+}
+
+#endif
--- /dev/null
+/*
+ * DELAY.C - internal command.
+ *
+ * clone from 4nt delay command
+ *
+ * 30 Aug 1999
+ * started - Paolo Pantaleo <paolopan@freemail.it>
+ *
+ *
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_DELAY
+
+#include <tchar.h>
+#include <windows.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+
+INT CommandDelay (LPTSTR cmd, LPTSTR param)
+{
+ DWORD val;
+ DWORD mul=1000;
+
+ if (_tcsncmp (param, _T("/?"), 2) == 0)
+ {
+ ConOutPuts(_T(
+ "pause for n seconds or milliseconds"
+ "\n"
+ "DELAY [/m]n\n"
+ "\n"
+ " /m specifiy than n are milliseconds\n"
+ " otherwise n are seconds"));
+ return 0;
+ }
+
+ if (*param==0)
+ {
+ error_req_param_missing ();
+ return 1;
+ }
+
+ if (_tcsnicmp(param,"/m",2) == 0)
+ {
+ mul = 1;
+ param += 2;
+ }
+
+ val = atoi(param);
+ Sleep(val*mul);
+
+ return 0;
+}
+
+#endif /* INCLUDE_CMD_DELAY */
--- /dev/null
+/* $Id: dir.c,v 1.1 2003/03/20 19:19:22 rcampbell Exp $
+ *
+ * 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!
+ *
+ * 01-Mar-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ * Replaced all runtime io functions by their Win32 counterparts.
+ *
+ * 23-Feb-2001 (Carl Nettelblad <cnettel@hem.passagen.se>)
+ * dir /s now works in deeper trees
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_DIR
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "cmd.h"
+
+
+typedef BOOL STDCALL
+(*PGETFREEDISKSPACEEX)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
+
+
+/* flag definitions */
+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 */
+static ULONG recurse_dir_cnt;
+static ULONG recurse_file_cnt;
+static ULARGE_INTEGER recurse_bytes;
+
+
+/*
+ * help
+ *
+ * displays help screen for dir
+ * Rob Lake
+ */
+static VOID Help (VOID)
+{
+ 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"
+ ));
+}
+
+
+/*
+ * DirReadParam
+ *
+ * read the parameters from the command line
+ */
+static BOOL
+DirReadParam (LPTSTR line, LPTSTR *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 (_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 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;
+}
+
+
+/*
+ * ExtendFilespec
+ *
+ * extend the filespec, possibly adding wildcards
+ */
+static VOID
+ExtendFilespec (LPTSTR file)
+{
+ INT len = 0;
+
+ if (!file)
+ return;
+
+ /* if no file spec, change to "*.*" */
+ if (*file == _T('\0'))
+ {
+ _tcscpy (file, _T("*.*"));
+ return;
+ }
+
+ /* if starts with . add * in front */
+ if (*file == _T('.'))
+ {
+ memmove (&file[1], &file[0], (_tcslen (file) + 1) * sizeof(TCHAR));
+ file[0] = _T('*');
+ }
+
+ /* if no . add .* */
+ if (!_tcschr (file, _T('.')))
+ {
+ _tcscat (file, _T(".*"));
+ return;
+ }
+
+ /* if last character is '.' add '*' */
+ len = _tcslen (file);
+ if (file[len - 1] == _T('.'))
+ {
+ _tcscat (file, _T("*"));
+ return;
+ }
+}
+
+
+/*
+ * dir_parse_pathspec
+ *
+ * split the pathspec into drive, directory, and filespec
+ */
+static INT
+DirParsePathspec (LPTSTR szPathspec, LPTSTR szPath, LPTSTR szFilespec)
+{
+ TCHAR szOrigPath[MAX_PATH];
+ LPTSTR start;
+ LPTSTR tmp;
+ INT i;
+ BOOL bWildcards = FALSE;
+
+ GetCurrentDirectory (MAX_PATH, szOrigPath);
+
+ /* get the drive and change to it */
+ if (szPathspec[1] == _T(':'))
+ {
+ TCHAR szRootPath[] = _T("A:");
+
+ szRootPath[0] = szPathspec[0];
+ start = szPathspec + 2;
+ SetCurrentDirectory (szRootPath);
+ }
+ else
+ {
+ start = szPathspec;
+ }
+
+
+ /* check for wildcards */
+ for (i = 0; szPathspec[i]; i++)
+ {
+ if (szPathspec[i] == _T('*') || szPathspec[i] == _T('?'))
+ bWildcards = TRUE;
+ }
+
+ /* check if this spec is a directory */
+ if (!bWildcards)
+ {
+ if (SetCurrentDirectory (szPathspec))
+ {
+ _tcscpy (szFilespec, _T("*.*"));
+
+ if (!GetCurrentDirectory (MAX_PATH, szPath))
+ {
+ szFilespec[0] = _T('\0');
+ SetCurrentDirectory (szOrigPath);
+ error_out_of_memory();
+ return 1;
+ }
+
+ SetCurrentDirectory (szOrigPath);
+ return 0;
+ }
+ }
+
+ /* find the file spec */
+ tmp = _tcsrchr (start, _T('\\'));
+
+ /* if no path is specified */
+ if (!tmp)
+ {
+ _tcscpy (szFilespec, start);
+ ExtendFilespec (szFilespec);
+ if (!GetCurrentDirectory (MAX_PATH, szPath))
+ {
+ szFilespec[0] = _T('\0');
+ SetCurrentDirectory (szOrigPath);
+ error_out_of_memory();
+ return 1;
+ }
+
+ SetCurrentDirectory (szOrigPath);
+ return 0;
+ }
+
+ /* get the filename */
+ _tcscpy (szFilespec, tmp+1);
+ ExtendFilespec (szFilespec);
+
+ *tmp = _T('\0');
+
+ /* change to this directory and get its full name */
+ if (!SetCurrentDirectory (start))
+ {
+ *tmp = _T('\\');
+ szFilespec[0] = _T('\0');
+ SetCurrentDirectory (szOrigPath);
+ error_path_not_found ();
+ return 1;
+ }
+
+ if (!GetCurrentDirectory (MAX_PATH, szPath))
+ {
+ *tmp = _T('\\');
+ szFilespec[0] = _T('\0');
+ SetCurrentDirectory (szOrigPath);
+ error_out_of_memory ();
+ return 1;
+ }
+
+ *tmp = _T('\\');
+
+ SetCurrentDirectory (szOrigPath);
+
+ return 0;
+}
+
+
+/*
+ * incline
+ *
+ * increment our line if paginating, display message at end of screen
+ */
+static BOOL
+IncLine (LPINT pLine, DWORD dwFlags)
+{
+ if (!(dwFlags & DIR_PAGE))
+ return FALSE;
+
+ (*pLine)++;
+
+ if (*pLine >= (int)maxy - 2)
+ {
+ *pLine = 0;
+ return (PagePrompt () == PROMPT_BREAK);
+ }
+
+ return FALSE;
+}
+
+
+/*
+ * PrintDirectoryHeader
+ *
+ * print the header for the dir command
+ */
+static BOOL
+PrintDirectoryHeader (LPTSTR szPath, LPINT pLine, DWORD dwFlags)
+{
+ TCHAR szRootName[MAX_PATH];
+ TCHAR szVolName[80];
+ DWORD dwSerialNr;
+ LPTSTR p;
+
+ if (dwFlags & DIR_BARE)
+ return(TRUE);
+
+ /* build usable root path */
+ if (szPath[1] == _T(':') && szPath[2] == _T('\\'))
+ {
+ /* normal path */
+ szRootName[0] = szPath[0];
+ szRootName[1] = _T(':');
+ szRootName[2] = _T('\\');
+ szRootName[3] = 0;
+ }
+ else if (szPath[0] == _T('\\') && szPath[1] == _T('\\'))
+ {
+ /* UNC path */
+ p = _tcschr(&szPath[2], _T('\\'));
+ if (p == NULL)
+ {
+ error_invalid_drive();
+ return(FALSE);
+ }
+ p = _tcschr(p+1, _T('\\'));
+ if (p == NULL)
+ {
+ _tcscpy(szRootName, szPath);
+ _tcscat(szRootName, _T("\\"));
+ }
+ else
+ {
+ *p = 0;
+ _tcscpy(szRootName, szPath);
+ _tcscat(szRootName, _T("\\"));
+ *p = _T('\\');
+ }
+ }
+ else
+ {
+ error_invalid_drive();
+ return(FALSE);
+ }
+
+ /* get the media ID of the drive */
+ 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(pLine, dwFlags))
+ 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(pLine, dwFlags))
+ return(FALSE);
+
+ return(TRUE);
+}
+
+
+/*
+ * convert
+ *
+ * insert commas into a number
+ */
+static INT
+ConvertULong (ULONG 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 (_T("%.2d%c%.2d%c%d"),
+ dt->wMonth, cDateSeparator, dt->wDay, cDateSeparator, wYear);
+ break;
+
+ case 1: /* ddmmyy */
+ ConOutPrintf (_T("%.2d%c%.2d%c%d"),
+ dt->wDay, cDateSeparator, dt->wMonth, cDateSeparator, wYear);
+ break;
+
+ case 2: /* yymmdd */
+ ConOutPrintf (_T("%d%c%.2d%c%.2d"),
+ wYear, cDateSeparator, dt->wMonth, cDateSeparator, dt->wDay);
+ break;
+ }
+
+ switch (nTimeFormat)
+ {
+ case 0: /* 12 hour format */
+ default:
+ ConOutPrintf (_T(" %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 (_T(" %2d%c%.2u"),
+ dt->wHour, cTimeSeparator, dt->wMinute);
+ break;
+ }
+}
+
+
+static VOID
+GetUserDiskFreeSpace(LPCTSTR lpRoot,
+ PULARGE_INTEGER lpFreeSpace)
+{
+ PGETFREEDISKSPACEEX pGetFreeDiskSpaceEx;
+ HINSTANCE hInstance;
+ DWORD dwSecPerCl;
+ DWORD dwBytPerSec;
+ DWORD dwFreeCl;
+ DWORD dwTotCl;
+
+ lpFreeSpace->QuadPart = 0;
+
+ hInstance = LoadLibrary(_T("KERNEL32"));
+ if (hInstance != NULL)
+ {
+#ifndef UNICODE
+ pGetFreeDiskSpaceEx = GetProcAddress(hInstance,
+ "GetDiskFreeSpaceExA");
+#else
+ pGetFreeDiskSpaceEx = GetProcAddress(hInstance,
+ "GetDiskFreeSpaceExW");
+#endif
+ if (pGetFreeDiskSpaceEx != NULL)
+ {
+ if (pGetFreeDiskSpaceEx(lpRoot, lpFreeSpace, NULL, NULL) == TRUE)
+ return;
+ }
+ FreeLibrary(hInstance);
+ }
+
+ GetDiskFreeSpace(lpRoot,
+ &dwSecPerCl,
+ &dwBytPerSec,
+ &dwFreeCl,
+ &dwTotCl);
+
+ lpFreeSpace->QuadPart = dwSecPerCl * dwBytPerSec * dwFreeCl;
+}
+
+
+/*
+ * 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(LPTSTR szPath,
+ ULONG ulFiles,
+ ULONG ulDirs,
+ ULARGE_INTEGER bytes,
+ LPINT pLine,
+ DWORD dwFlags)
+{
+ TCHAR buffer[64];
+ ULARGE_INTEGER uliFree;
+ TCHAR szRoot[] = _T("A:\\");
+
+ if (dwFlags & DIR_BARE)
+ return(0);
+
+ /* Print number of files and bytes */
+ ConvertULong (ulFiles, buffer, sizeof(buffer));
+ ConOutPrintf (_T(" %6s File%c"),
+ buffer, ulFiles == 1 ? _T(' ') : _T('s'));
+
+ ConvertULargeInteger (bytes, buffer, sizeof(buffer));
+ ConOutPrintf (_T(" %15s byte%c\n"),
+ buffer, bytes.QuadPart == 1 ? _T(' ') : _T('s'));
+ ConOutPrintf (_T(" %I64u byte%c\n"),
+ bytes.QuadPart, bytes.QuadPart == 1 ? _T(' ') : _T('s'));
+
+ if (IncLine (pLine, dwFlags))
+ return 1;
+
+ /* Print number of dirs and bytes free */
+ ConvertULong (ulDirs, buffer, sizeof(buffer));
+ ConOutPrintf (_T(" %6s Dir%c"),
+ buffer, ulDirs == 1 ? _T(' ') : _T('s'));
+
+ if (!(dwFlags & DIR_RECURSE))
+ {
+ szRoot[0] = szPath[0];
+ GetUserDiskFreeSpace(szRoot, &uliFree);
+ ConvertULargeInteger (uliFree, buffer, sizeof(buffer));
+ ConOutPrintf (_T(" %15s bytes free\n"), buffer);
+ }
+
+ if (IncLine (pLine, dwFlags))
+ return 1;
+
+ return 0;
+}
+
+
+/*
+ * dir_list
+ *
+ * list the files in the directory
+ */
+static INT
+DirList (LPTSTR szPath, LPTSTR szFilespec, LPINT pLine, DWORD dwFlags)
+{
+ TCHAR szFullPath[MAX_PATH];
+ WIN32_FIND_DATA file;
+ ULARGE_INTEGER bytecount;
+ FILETIME ft;
+ SYSTEMTIME dt;
+ HANDLE hFile;
+ TCHAR buffer[32];
+ ULONG filecount = 0;
+ ULONG dircount = 0;
+ INT count;
+
+ bytecount.QuadPart = 0;
+
+ _tcscpy (szFullPath, szPath);
+ if (szFullPath[_tcslen(szFullPath) - 1] != _T('\\'))
+ _tcscat (szFullPath, _T("\\"));
+ _tcscat (szFullPath, szFilespec);
+
+ hFile = FindFirstFile (szFullPath, &file);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ /* Don't want to print anything if scanning recursively
+ * for a file. RL
+ */
+ if ((dwFlags & DIR_RECURSE) == 0)
+ {
+ FindClose (hFile);
+ error_file_not_found ();
+ if (IncLine (pLine, dwFlags))
+ return 0;
+ 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 ((dwFlags & DIR_BARE) == 0)
+ {
+ ConOutPrintf (_T(" Directory of %s\n"), szPath);
+ if (IncLine (pLine, dwFlags))
+ return 1;
+ ConOutPrintf (_T("\n"));
+ if (IncLine (pLine, dwFlags))
+ return 1;
+ }
+
+ /* For counting columns of output */
+ count = 0;
+
+ do
+ {
+ /* next file, if user doesn't want all files */
+ if (!(dwFlags & DIR_ALL) &&
+ ((file.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ||
+ (file.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)))
+ continue;
+
+ if (dwFlags & DIR_LWR)
+ {
+ _tcslwr (file.cAlternateFileName);
+ }
+
+ if (dwFlags & DIR_WIDE && (dwFlags & DIR_BARE) == 0)
+ {
+ ULARGE_INTEGER uliSize;
+
+ if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ if (file.cAlternateFileName[0] == _T('\0'))
+ _stprintf (buffer, _T("[%s]"), file.cFileName);
+ else
+ _stprintf (buffer, _T("[%s]"), file.cAlternateFileName);
+ dircount++;
+ }
+ else
+ {
+ if (file.cAlternateFileName[0] == _T('\0'))
+ _stprintf (buffer, _T("%s"), file.cFileName);
+ else
+ _stprintf (buffer, _T("%s"), file.cAlternateFileName);
+ filecount++;
+ }
+
+ ConOutPrintf (_T("%-15s"), buffer);
+ count++;
+ if (count == 5)
+ {
+ /* output 5 columns */
+ ConOutPrintf (_T("\n"));
+ if (IncLine (pLine, dwFlags))
+ return 1;
+ count = 0;
+ }
+
+ uliSize.LowPart = file.nFileSizeLow;
+ uliSize.HighPart = file.nFileSizeHigh;
+ bytecount.QuadPart += uliSize.QuadPart;
+ }
+ else if (dwFlags & DIR_BARE)
+ {
+ ULARGE_INTEGER uliSize;
+
+ if (_tcscmp (file.cFileName, _T(".")) == 0 ||
+ _tcscmp (file.cFileName, _T("..")) == 0)
+ continue;
+
+ if (dwFlags & DIR_RECURSE)
+ {
+ TCHAR dir[MAX_PATH];
+
+ _tcscpy (dir, szPath);
+ _tcscat (dir, _T("\\"));
+ if (dwFlags & DIR_LWR)
+ _tcslwr (dir);
+ ConOutPrintf (dir);
+ }
+
+ ConOutPrintf (_T("%-13s\n"), file.cFileName);
+ if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ dircount++;
+ else
+ filecount++;
+ if (IncLine (pLine, dwFlags))
+ return 1;
+
+ uliSize.LowPart = file.nFileSizeLow;
+ uliSize.HighPart = file.nFileSizeHigh;
+ bytecount.QuadPart += uliSize.QuadPart;
+ }
+ else
+ {
+ if (dwFlags & DIR_NEW)
+ {
+ /* print file date and time */
+ if (FileTimeToLocalFileTime (&file.ftLastWriteTime, &ft))
+ {
+ FileTimeToSystemTime (&ft, &dt);
+ PrintFileDateTime (&dt, dwFlags);
+ }
+
+ /* print file size */
+ if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ ConOutPrintf (_T(" <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 (_T(" %s\n"), file.cFileName);
+ }
+ else
+ {
+ if (file.cFileName[0] == _T('.'))
+ ConOutPrintf (_T("%-13s "), file.cFileName);
+ else if (file.cAlternateFileName[0] == _T('\0'))
+ {
+ TCHAR szShortName[13];
+ LPTSTR ext;
+
+ _tcsncpy (szShortName, file.cFileName, 13);
+ ext = _tcschr (szShortName, _T('.'));
+ if (!ext)
+ ext = _T("");
+ else
+ *ext++ = _T('\0');
+ ConOutPrintf (_T("%-8s %-3s "), szShortName, ext);
+ }
+ else
+ {
+ LPTSTR ext;
+
+ ext = _tcschr (file.cAlternateFileName, _T('.'));
+ if (!ext)
+ ext = _T("");
+ else
+ *ext++ = _T('\0');
+ ConOutPrintf (_T("%-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, dwFlags);
+ }
+
+ /* print long filename */
+ ConOutPrintf (" %s\n", file.cFileName);
+ }
+
+ if (IncLine (pLine, dwFlags))
+ 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 ((dwFlags & DIR_WIDE) && (count != 0))
+ {
+ ConOutPrintf (_T("\n"));
+ if (IncLine (pLine, dwFlags))
+ return 1;
+ }
+
+ if (filecount || dircount)
+ {
+ recurse_dir_cnt += dircount;
+ recurse_file_cnt += filecount;
+ recurse_bytes.QuadPart += bytecount.QuadPart;
+
+ /* print_summary */
+ if (PrintSummary (szPath, filecount, dircount, bytecount, pLine, dwFlags))
+ return 1;
+ }
+ else
+ {
+ error_file_not_found ();
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/*
+ * _Read_Dir: Actual function that does recursive listing
+ */
+static INT
+DirRead (LPTSTR szPath, LPTSTR szFilespec, LPINT pLine, DWORD dwFlags)
+{
+ TCHAR szFullPath[MAX_PATH];
+ WIN32_FIND_DATA file;
+ HANDLE hFile;
+
+ _tcscpy (szFullPath, szPath);
+ if (szFullPath[_tcslen (szFullPath) - 1] != _T('\\'))
+ _tcscat (szFullPath, _T("\\"));
+ _tcscat (szFullPath, szFilespec);
+
+ hFile = FindFirstFile (szFullPath, &file);
+ if (hFile == INVALID_HANDLE_VALUE)
+ return 1;
+
+ do
+ {
+ /* don't list "." and ".." */
+ if (_tcscmp (file.cFileName, _T(".")) == 0 ||
+ _tcscmp (file.cFileName, _T("..")) == 0)
+ continue;
+
+ if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ _tcscpy (szFullPath, szPath);
+ if (szFullPath[_tcslen (szFullPath) - 1] != _T('\\'))
+ _tcscat (szFullPath, _T("\\"));
+ _tcscat (szFullPath, file.cFileName);
+
+ if (DirList (szFullPath, szFilespec, pLine, dwFlags))
+ {
+ FindClose (hFile);
+ return 1;
+ }
+
+ if ((dwFlags & DIR_BARE) == 0)
+ {
+ ConOutPrintf ("\n");
+ if (IncLine (pLine, dwFlags) != 0)
+ return 1;
+ ConOutPrintf ("\n");
+ if (IncLine (pLine, dwFlags) != 0)
+ return 1;
+ }
+
+ if (DirRead (szFullPath, szFilespec, pLine, dwFlags) == 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
+DirRecurse (LPTSTR szPath, LPTSTR szSpec, LPINT pLine, DWORD dwFlags)
+{
+ if (!PrintDirectoryHeader (szPath, pLine, dwFlags))
+ return 1;
+
+ if (DirList (szPath, szSpec, pLine, dwFlags))
+ return 1;
+
+ if ((dwFlags & DIR_BARE) == 0)
+ {
+ ConOutPrintf (_T("\n"));
+ if (IncLine (pLine, dwFlags))
+ return 1;
+ }
+
+ if (DirRead (szPath, szSpec, pLine, dwFlags))
+ return 1;
+
+ if ((dwFlags & DIR_BARE) == 0)
+ ConOutPrintf (_T("Total files listed:\n"));
+
+ dwFlags &= ~DIR_RECURSE;
+
+ if (PrintSummary (szPath, recurse_file_cnt,
+ recurse_dir_cnt, recurse_bytes, pLine, dwFlags))
+ return 1;
+
+ if ((dwFlags & DIR_BARE) == 0)
+ {
+ ConOutPrintf (_T("\n"));
+ if (IncLine (pLine, dwFlags))
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/*
+ * dir
+ *
+ * internal dir command
+ */
+INT CommandDir (LPTSTR first, LPTSTR rest)
+{
+ DWORD dwFlags = DIR_NEW | DIR_FOUR;
+ TCHAR dircmd[256];
+ TCHAR szPath[MAX_PATH];
+ TCHAR szFilespec[MAX_PATH];
+ LPTSTR param;
+ INT nLine = 0;
+
+
+ recurse_dir_cnt = 0L;
+ recurse_file_cnt = 0L;
+ recurse_bytes.QuadPart = 0;
+
+ /* read the parameters from the DIRCMD environment variable */
+ if (GetEnvironmentVariable (_T("DIRCMD"), dircmd, 256))
+ {
+ if (!DirReadParam (dircmd, ¶m, &dwFlags))
+ return 1;
+ }
+
+ /* read the parameters */
+ if (!DirReadParam (rest, ¶m, &dwFlags))
+ return 1;
+
+ /* default to current directory */
+ if (!param)
+ param = ".";
+
+ /* parse the directory info */
+ if (DirParsePathspec (param, szPath, szFilespec))
+ return 1;
+
+ if (dwFlags & DIR_RECURSE)
+ {
+ if (IncLine (&nLine, dwFlags))
+ return 0;
+ if (DirRecurse (szPath, szFilespec, &nLine, dwFlags))
+ return 1;
+ return 0;
+ }
+
+ /* print the header */
+ if (!PrintDirectoryHeader (szPath, &nLine, dwFlags))
+ return 1;
+
+ if (DirList (szPath, szFilespec, &nLine, dwFlags))
+ return 1;
+
+ return 0;
+}
+
+#endif
+
+/* EOF */
--- /dev/null
+/*
+ * 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!
+ *
+ * 20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ * Added DIRS command.
+ */
+
+#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 *prev;
+ struct tagDIRENTRY *next;
+ LPTSTR pszPath;
+} DIRENTRY, *LPDIRENTRY;
+
+
+static INT nStackDepth;
+static LPDIRENTRY lpStackTop;
+static LPDIRENTRY lpStackBottom;
+
+
+static INT
+PushDirectory (LPTSTR pszPath)
+{
+ LPDIRENTRY lpDir;
+
+ lpDir = (LPDIRENTRY)malloc (sizeof (DIRENTRY));
+ if (!lpDir)
+ {
+ error_out_of_memory ();
+ return -1;
+ }
+
+ lpDir->prev = NULL;
+ if (lpStackTop == NULL)
+ {
+ lpDir->next = NULL;
+ lpStackBottom = lpDir;
+ }
+ else
+ {
+ lpDir->next = lpStackTop;
+ lpStackTop->prev = lpDir;
+ }
+ 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;
+ if (lpStackTop != NULL)
+ lpStackTop->prev = NULL;
+ else
+ lpStackBottom = NULL;
+
+ 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;
+ lpStackBottom = NULL;
+}
+
+
+/*
+ * destroy directory stack
+ */
+VOID DestroyDirectoryStack (VOID)
+{
+ while (nStackDepth)
+ PopDirectory ();
+}
+
+
+INT GetDirectoryStackDepth (VOID)
+{
+ return nStackDepth;
+}
+
+
+/*
+ * pushd command
+ */
+INT CommandPushd (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 0;
+
+ if (bChangePath)
+ SetCurrentDirectory (newPath);
+
+ return 0;
+}
+
+
+/*
+ * popd command
+ */
+INT CommandPopd (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;
+}
+
+
+/*
+ * dirs command
+ */
+INT CommandDirs (LPTSTR first, LPTSTR rest)
+{
+ LPDIRENTRY lpDir;
+
+ if (!_tcsncmp(rest, _T("/?"), 2))
+ {
+ ConOutPuts (_T("Prints the contents of the directory stack.\n"
+ "\n"
+ "DIRS"));
+ return 0;
+ }
+
+
+ lpDir = lpStackBottom;
+
+ if (lpDir == NULL)
+ {
+ ConOutPuts (_T("Directory stack empty"));
+ return 0;
+ }
+
+ while (lpDir != NULL)
+ {
+ ConOutPuts (lpDir->pszPath);
+
+ lpDir = lpDir->prev;
+ }
+
+ return 0;
+}
+
+#endif /* FEATURE_DIRECTORY_STACK */
--- /dev/null
+/* $Id: echo.c,v 1.1 2003/03/20 19:19:22 rcampbell Exp $
+ *
+ * ECHO.C - internal echo commands.
+ *
+ *
+ * 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!
+ *
+ * 13-Jul-2000 (Eric Kohl <ekohl@rz-online.de>)
+ * Implemented 'echo.' and 'echoerr.'.
+ */
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+
+INT CommandEcho (LPTSTR cmd, LPTSTR param)
+{
+#ifdef _DEBUG
+ DebugPrintf ("CommandEcho '%s' : '%s'\n", cmd, param);
+#endif
+
+ if (!_tcsncmp (param, _T("/?"), 2))
+ {
+ ConOutPuts ("Displays a message or switches command echoing on or off.\n"
+ "\n"
+ " ECHO [ON | OFF]\n"
+ " ECHO [message]\n"
+ " ECHO. prints an empty line\n"
+ "\n"
+ "Type ECHO without a parameter to display the current ECHO setting.");
+ return 0;
+ }
+
+ if (_tcsicmp (cmd, _T("echo.")) == 0)
+ {
+ if (param[0] == 0)
+ ConOutChar (_T('\n'));
+ else
+ ConOutPuts (param);
+ }
+ else
+ {
+ 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;
+}
+
+INT CommandEchos (LPTSTR cmd, LPTSTR param)
+{
+#ifdef _DEBUG
+ DebugPrintf ("CommandEchos '%s' : '%s'\n", cmd, param);
+#endif
+
+ if (!_tcsncmp (param, _T("/?"), 2))
+ {
+ ConOutPuts ("Display a messages without trailing carridge return and line feed.\n"
+ "\n"
+ " ECHOS message");
+ return 0;
+ }
+
+ if (*param)
+ ConOutPrintf ("%s", param);
+
+ return 0;
+}
+
+
+INT CommandEchoerr (LPTSTR cmd, LPTSTR param)
+{
+#ifdef _DEBUG
+ DebugPrintf ("CommandEchoerr '%s' : '%s'\n", cmd, param);
+#endif
+
+ if (!_tcsncmp (param, _T("/?"), 2))
+ {
+ ConOutPuts ("Displays a message to the standard error.\n"
+ "\n"
+ " ECHOERR message\n"
+ " ECHOERR. prints an empty line");
+ return 0;
+ }
+
+ if (_tcsicmp (cmd, _T("echoerr.")) == 0)
+ {
+ if (param[0] == 0)
+ ConErrChar (_T('\n'));
+ else
+ ConErrPuts (param);
+ }
+ else if (*param)
+ {
+ ConErrPuts (param);
+ }
+
+ return 0;
+}
+
+INT CommandEchoserr (LPTSTR cmd, LPTSTR param)
+{
+#ifdef _DEBUG
+ DebugPrintf ("CommandEchoserr '%s' : '%s'\n", cmd, param);
+#endif
+
+ if (!_tcsncmp (param, _T("/?"), 2))
+ {
+ ConOutPuts ("Prints a messages to standard error output without trailing carridge return and line feed.\n"
+ "\n"
+ " ECHOSERR message");
+ return 0;
+ }
+
+ if (*param)
+ ConOutPrintf (_T("%s"), param);
+
+ return 0;
+}
+
+/* EOF */
--- /dev/null
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <stdio.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\n")
+#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);
+ _vstprintf (szMessage, szFormat, arg_ptr);
+ va_end (arg_ptr);
+
+#ifndef __REACTOS__
+
+ 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);
+ 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);
+}
--- /dev/null
+/*
+ * 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!
+ */
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <stdio.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];
+ LPCOMMAND cmds_ptr;
+
+ /* 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] != _T('\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 */
+ do
+ {
+ /* ignore "." and ".." */
+ if (!_tcscmp (file.cFileName, _T(".")) ||
+ !_tcscmp (file.cFileName, _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);
+ if( perfectmatch )
+ {
+ str[start] = '\"';
+ _tcscpy (&str[start+1], directory);
+ _tcscat (&str[start], maxmatch);
+ _tcscat (&str[start], "\"" );
+ }
+
+ else
+#ifdef __REACTOS__
+ Beep (440, 50);
+#else
+ MessageBeep (-1);
+#endif
+ }
+ else
+ {
+ /* no match found - search for internal command */
+ for (cmds_ptr = cmds; cmds_ptr->name; cmds_ptr++)
+ {
+ if (!_tcsnicmp (&str[start], cmds_ptr->name,
+ _tcslen (&str[start])))
+ {
+ /* return the mach only if it is unique */
+ if (_tcsnicmp (&str[start], (cmds_ptr+1)->name, _tcslen (&str[start])))
+ _tcscpy (&str[start], cmds_ptr->name);
+ break;
+ }
+ }
+
+#ifdef __REACTOS__
+ Beep (440, 50);
+#else
+ MessageBeep (-1);
+#endif
+ }
+}
+
+
+/*
+ * 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] != _T('\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 (!_tcscmp (file.cFileName, _T(".")) ||
+ !_tcscmp (file.cFileName, _T("..")))
+ continue;
+
+ if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ _stprintf (fname, _T("[%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 */
+#ifdef __REACTOS__
+ Beep (440, 50);
+#else
+ MessageBeep (-1);
+#endif
+ 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
--- /dev/null
+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
+choice.c Implements choice 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
+free.c Implements free 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
+memory.c Implements memory command
+misc.c Misc. Functions
+msgbox.c Implements msgbox command
+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
+timer.c Implements timer command
+type.c Implements type command
+ver.c Implements ver command
+where.c Code to search path for executables
+verify.c Implements verify command
--- /dev/null
+/*
+ * 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)
+ * Implementation of FOR.
+ *
+ * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
+ * Added config.h include.
+ *
+ * 20-Jan-1999 (Eric Kohl)
+ * Unicode and redirection safe!
+ *
+ * 01-Sep-1999 (Eric Kohl)
+ * Added help text.
+ *
+ * 23-Feb-2001 (Carl Nettelblad <cnettel@hem.passagen.se>)
+ * Implemented preservation of echo flag. Some other for related
+ * code in other files fixed, too.
+ */
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.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 (_T("Runs a specified command for each file in a set of files\n"
+ "\n"
+ "FOR %variable IN (set) DO command [parameters]\n"
+ "\n"
+ " %variable Specifies a replaceable parameter.\n"
+ " (set) Specifies a set of one or more files. Wildcards may be used.\n"
+ " command Specifies the command to carry out for each file.\n"
+ " parameters Specifies parameters or switches for the specified command.\n"
+ "\n"
+ "To user the FOR comamnd in a batch program, specify %%variable instead of\n"
+ "%variable."));
+ 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 variable 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);
+ if (bc->prev)
+ bc->bEcho = bc->prev->bEcho;
+ else
+ bc->bEcho = bEcho;
+
+ return 0;
+}
+
+/* EOF */
--- /dev/null
+/*
+ * FREE.C - internal command.
+ *
+ *
+ * History:
+ *
+ * 01-Sep-1999 (Eric Kohl)
+ * Started.
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_FREE
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "cmd.h"
+
+
+/*
+ * convert
+ *
+ * insert commas into a number
+ */
+
+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
+PrintDiskInfo (LPTSTR szDisk)
+{
+ TCHAR szRootPath[4] = "A:\\";
+ TCHAR szDrive[2] = "A";
+ TCHAR szVolume[64];
+ TCHAR szSerial[10];
+ TCHAR szTotal[40];
+ TCHAR szUsed[40];
+ TCHAR szFree[40];
+ DWORD dwSerial;
+ ULARGE_INTEGER uliSize;
+ DWORD dwSecPerCl;
+ DWORD dwBytPerSec;
+ DWORD dwFreeCl;
+ DWORD dwTotCl;
+
+ if (_tcslen (szDisk) < 2 || szDisk[1] != _T(':'))
+ {
+ ConErrPrintf (_T("Invalid drive %s\n"), szDisk);
+ return;
+ }
+
+ szRootPath[0] = szDisk[0];
+ szDrive[0] = _totupper (szRootPath[0]);
+
+ if (!GetVolumeInformation (szRootPath, szVolume, 64, &dwSerial,
+ NULL, NULL, NULL, 0))
+ {
+ ConErrPrintf (_T("Invalid drive %s:\n"), szDrive);
+ return;
+ }
+
+ if (szVolume[0] == _T('\0'))
+ _tcscpy (szVolume, _T("unlabeled"));
+
+ _stprintf (szSerial,
+ _T("%04X-%04X"),
+ HIWORD(dwSerial),
+ LOWORD(dwSerial));
+
+ if (!GetDiskFreeSpace (szRootPath, &dwSecPerCl,
+ &dwBytPerSec, &dwFreeCl, &dwTotCl))
+ {
+ ConErrPrintf (_T("Invalid drive %s:\n"), szDrive);
+ return;
+ }
+
+ uliSize.QuadPart = dwSecPerCl * dwBytPerSec * dwTotCl;
+ ConvertULargeInteger (uliSize, szTotal, 40);
+
+ uliSize.QuadPart = dwSecPerCl * dwBytPerSec * (dwTotCl - dwFreeCl);
+ ConvertULargeInteger (uliSize, szUsed, 40);
+
+ uliSize.QuadPart = dwSecPerCl * dwBytPerSec * dwFreeCl;
+ ConvertULargeInteger (uliSize, szFree, 40);
+
+ ConOutPrintf (_T("\n"
+ " Volume in drive %s is %-11s Serial number is %s\n"
+ " %16s bytes total disk space\n"
+ " %16s bytes used\n"
+ " %16s bytes free\n"),
+ szDrive, szVolume, szSerial,
+ szTotal, szUsed, szFree);
+}
+
+
+INT CommandFree (LPTSTR cmd, LPTSTR param)
+{
+ LPTSTR szParam;
+ TCHAR szDefPath[MAX_PATH];
+ INT argc, i;
+ LPTSTR *arg;
+
+ if (!_tcsncmp (param, _T("/?"), 2))
+ {
+ ConOutPuts (_T("Displays drive information.\n"
+ "\n"
+ "FREE [drive: ...]"));
+ return 0;
+ }
+
+ if (!param || *param == _T('\0'))
+ {
+ GetCurrentDirectory (MAX_PATH, szDefPath);
+ szDefPath[2] = _T('\0');
+ szParam = szDefPath;
+ }
+ else
+ szParam = param;
+
+ arg = split (szParam, &argc, FALSE);
+
+ for (i = 0; i < argc; i++)
+ PrintDiskInfo (arg[i]);
+
+ freep (arg);
+
+ return 0;
+}
+
+#endif /* INCLUDE_CMD_FREE */
+
+/* EOF */
--- /dev/null
+/*
+ * 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 ("/?").
+ */
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <ctype.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;
+}
--- /dev/null
+/*
+ * 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!
+ *
+ * 25-Jan-1999 (Paolo Pantaleo <paolopan@freemail.it>)
+ * Added lots of comments (beginning studying the source)
+ * Added command.com's F3 support (see cmdinput.c)
+ *
+ */
+
+
+
+/*
+ * HISTORY.C - command line history. Second version
+ *
+ *
+ * History:
+ *
+ * 06/12/99 (Paolo Pantaleo <paolopan@freemail.it>)
+ * started.
+ *
+ */
+
+
+
+
+
+
+#include "config.h"
+
+
+#ifdef FEATURE_HISTORY
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "cmd.h"
+
+
+typedef struct tagHISTORY
+{
+ struct tagHISTORY *prev;
+ struct tagHISTORY *next;
+ LPTSTR string;
+} HIST_ENTRY, * LPHIST_ENTRY;
+
+static INT size,
+ max_size=100;
+
+
+
+static LPHIST_ENTRY Top;
+static LPHIST_ENTRY Bottom;
+
+
+static LPHIST_ENTRY curr_ptr=0;
+
+
+VOID InitHistory(VOID);
+VOID History_move_to_bottom(VOID);
+VOID History (INT dir, LPTSTR commandline);
+VOID CleanHistory(VOID);
+VOID History_del_current_entry(LPTSTR str);
+
+/*service functions*/
+static VOID del(LPHIST_ENTRY item);
+static VOID add_at_bottom(LPTSTR string);
+/*VOID add_before_last(LPTSTR string);*/
+VOID set_size(INT new_size);
+
+
+
+INT CommandHistory (LPTSTR cmd, LPTSTR param)
+{
+ LPTSTR tmp;
+ INT tmp_int;
+ LPHIST_ENTRY h_tmp;
+ TCHAR szBuffer[2048];
+
+ tmp=_tcschr(param,_T('/'));
+
+ if (tmp)
+ {
+ param=tmp;
+ switch (_totupper(param[1]))
+ {
+ case _T('F'):/*delete history*/
+ CleanHistory();InitHistory();
+ break;
+
+ case _T('R'):/*read history from standard in*/
+ //hIn=GetStdHandle (STD_INPUT_HANDLE);
+
+ for(;;)
+ {
+ ConInString(szBuffer,sizeof(szBuffer)/sizeof(TCHAR));
+ if (*szBuffer!=_T('\0'))
+ History(0,szBuffer);
+ else
+ break;
+ }
+ break;
+
+ case _T('A'):/*add an antry*/
+ History(0,param+2);
+ break;
+
+ case _T('S'):/*set history size*/
+ if ((tmp_int=_ttoi(param+2)))
+ set_size(tmp_int);
+ break;
+
+ default:
+ return 1;
+ }
+ }
+ else
+ {
+ for(h_tmp=Top->prev;h_tmp!=Bottom;h_tmp=h_tmp->prev)
+ ConErrPuts(h_tmp->string);
+ }
+ return 0;
+}
+
+VOID set_size(INT new_size)
+{
+
+ while(new_size<size)
+ del(Top->prev);
+
+
+ max_size=new_size;
+}
+
+
+VOID InitHistory(VOID)
+{
+ size=0;
+
+
+ Top = malloc(sizeof(HIST_ENTRY));
+ Bottom = malloc(sizeof(HIST_ENTRY));
+
+
+ Top->prev = Bottom;
+ Top->next = NULL;
+ Top->string = NULL;
+
+
+ Bottom->prev = NULL;
+ Bottom->next = Top;
+ Bottom->string = NULL;
+
+ curr_ptr=Bottom;
+}
+
+
+
+
+VOID CleanHistory(VOID)
+{
+
+ while (Bottom->next!=Top)
+ del(Bottom->next);
+
+ free(Top);
+ free(Bottom);
+
+}
+
+
+VOID History_del_current_entry(LPTSTR str)
+{
+ LPHIST_ENTRY tmp;
+
+ if (size==0)
+ return;
+
+ if(curr_ptr==Bottom)
+ curr_ptr=Bottom->next;
+
+ if(curr_ptr==Top)
+ curr_ptr=Top->prev;
+
+
+ tmp=curr_ptr;
+ curr_ptr=curr_ptr->prev;
+ del(tmp);
+ History(-1,str);
+
+}
+
+
+static
+VOID del(LPHIST_ENTRY item)
+{
+
+ if( item==NULL || item==Top || item==Bottom )
+ {
+#ifdef _DEBUG
+ DebugPrintf("del in " __FILE__ ": retrning\n"
+ "item is 0x%08x (Bottom is0x%08x)\n",
+ item, Bottom);
+
+#endif
+ return;
+ }
+
+
+
+ /*free string's mem*/
+ if (item->string)
+ free(item->string);
+
+
+
+
+
+ /*set links in prev and next item*/
+ item->next->prev=item->prev;
+ item->prev->next=item->next;
+
+ free(item);
+
+ size--;
+
+}
+
+#if 0
+static
+VOID add_before_last(LPTSTR string)
+{
+
+ LPHIST_ENTRY tmp,before,after;
+
+
+ /*delete first entry if maximum number of entries is reached*/
+ while(size>=max_size)
+ del(Top->prev);
+
+ while (_istspace(*string))
+ string++;
+
+ if (*string==_T('\0'))
+ return;
+
+
+
+ /*allocte entry and string*/
+ tmp=malloc(sizeof(HIST_ENTRY));
+ tmp->string=malloc(_tcslen(string)+1);
+ _tcscpy(tmp->string,string);
+
+
+ /*set links*/
+ before=Bottom->next;
+ after=before->next;
+
+ tmp->prev=before;
+ tmp->next=after;
+
+ after->prev=tmp;
+ before->next=tmp;
+
+
+
+
+
+
+
+ /*set new size*/
+ size++;
+
+
+}
+#endif/*0*/
+
+static
+VOID add_at_bottom(LPTSTR string)
+{
+
+
+ LPHIST_ENTRY tmp;
+
+
+ /*delete first entry if maximum number of entries is reached*/
+ while(size>=max_size)
+ del(Top->prev);
+
+ while (_istspace(*string))
+ string++;
+
+ if (*string==_T('\0'))
+ return;
+
+
+ /*if new entry is the same than the last do not add it*/
+ if(size)
+ if(_tcscmp(string,Bottom->next->string)==0)
+ return;
+
+
+ /*fill bottom with string, it will become Bottom->next*/
+ Bottom->string=malloc(_tcslen(string)+1);
+ _tcscpy(Bottom->string,string);
+
+ /*save Bottom value*/
+ tmp=Bottom;
+
+
+ /*create new void Bottom*/
+ Bottom=malloc(sizeof(HIST_ENTRY));
+ Bottom->next=tmp;
+ Bottom->prev=NULL;
+ Bottom->string=NULL;
+
+ tmp->prev=Bottom;
+
+ /*set new size*/
+ size++;
+
+}
+
+
+
+VOID History_move_to_bottom(VOID)
+{
+ curr_ptr=Bottom;
+
+}
+
+
+VOID History (INT dir, LPTSTR commandline)
+{
+
+ if(dir==0)
+ {
+ add_at_bottom(commandline);
+ curr_ptr=Bottom;
+ return;
+ }
+
+ if (size==0)
+ {
+ commandline[0]=_T('\0');
+ return;
+ }
+
+
+ if(dir<0)/*key up*/
+ {
+ if (curr_ptr->next==Top || curr_ptr==Top)
+ {
+#ifdef WRAP_HISTORY
+ curr_ptr=Bottom;
+#else
+ curr_ptr=Top;
+ commandline[0]=_T('\0');
+ return;
+#endif
+ }
+
+
+ curr_ptr = curr_ptr->next;
+ if(curr_ptr->string)
+ _tcscpy(commandline,curr_ptr->string);
+
+ }
+
+
+
+
+
+ if(dir>0)
+ {
+
+ if (curr_ptr->prev==Bottom || curr_ptr==Bottom)
+ {
+#ifdef WRAP_HISTORY
+ curr_ptr=Top;
+#else
+ curr_ptr=Bottom;
+ commandline[0]=_T('\0');
+ return;
+#endif
+ }
+
+ curr_ptr=curr_ptr->prev;
+ if(curr_ptr->string)
+ _tcscpy(commandline,curr_ptr->string);
+
+ }
+}
+
+
+
+
+
+
+#if 0
+
+LPTSTR history = NULL; /*buffer to sotre all the lines*/
+LPTSTR lines[MAXLINES]; /*array of pointers to each line(entry)*/
+ /*located in history buffer*/
+
+INT curline = 0; /*the last line recalled by user*/
+INT numlines = 0; /*number of entries, included the last*/
+ /*empty one*/
+
+INT maxpos = 0; /*index of last byte of last entry*/
+
+
+
+VOID History (INT dir, LPTSTR commandline)
+{
+
+ INT count; /*used in for loops*/
+ INT length; /*used in the same loops of count*/
+ /*both to make room when is full
+ either history or lines*/
+
+ /*first time History is called allocate mem*/
+ 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
+ }
+
+ /*copy entry in the history bufer*/
+ _tcscpy (lines[numlines], commandline);
+ numlines++;
+
+ /*set last lines[numlines] pointer next the end of last, valid,
+ just setted entry (the two lines above)*/
+ lines[numlines] = lines[numlines - 1] + _tcslen (commandline) + 1;
+ maxpos += _tcslen (commandline) + 1;
+ /* last line, empty */
+
+ curline = numlines;
+ }
+
+ return;
+}
+
+#endif
+
+#endif //#if 0
--- /dev/null
+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.
+
+28-Dec-1999 ReactOS CMD version 0.1 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+o Cleaned up DIR command.
+o Searching for executables in the right order.
+o Fixed some little but nasty bugs.
+o Added TITLE command. Thanks to Emanuele Aliberti!
+o Added "/Q", "/W" and "/Z" options to DEL command.
+o Added CHOICE, TIMER, FREE and MEMORY commands.
+o Added MSGBOX command (not available under ReactOS).
+o Added and fixed missing help texts.
+o Fixed bugs in MD and RD that crashed cmd when no directory was specified.
+o Improved history support.
+o Improved COLOR command.
+
+09-Apr-2000 ReactOS CMD version 0.1 (EricKohl <ekohl@rz-online.de>
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+o Fixed bug in COPY command. CMD crashed if source file didn't exist.
+
+13-Jul-2000 ReactOS CMD version 0.1.1 (EricKohl <ekohl@rz-online.de>
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+o Implemented 'ECHO.' and 'ECHOERR.' commands.
--- /dev/null
+/*
+ * 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!
+ *
+ * 01-Sep-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ * Fixed help text.
+ *
+ * 17-Feb-2001 (ea)
+ * IF DEFINED variable command
+ */
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <ctype.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("Performs conditional processing in batch programs.\n"
+ "\n"
+ " IF [NOT] ERRORLEVEL number command\n"
+ " IF [NOT] string1==string2 command\n"
+ " IF [NOT] EXIST filename command\n"
+ " IF [NOT] DEFINED variable command\n"
+ "\n"
+ "NOT Specifies that CMD should carry out the command only if\n"
+ " the condition is false\n"
+ "ERRORLEVEL number Specifies a true condition if the last program run returned\n"
+ " an exit code equal or greater than the number specified.\n"
+ "command Specifies the command to carry out if the condition is met.\n"
+ "string1==string2 Specifies a true condition if the specified text strings\n"
+ " match.\n"
+ "EXIST filename Specifies a true condition if the specified filename exists.\n"
+ "DEFINED variable Specifies a true condition if the specified variable is\n"
+ " defined."));
+ 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 'defined' form */
+ else if (!_tcsnicmp (param, _T("defined"), 7) && _istspace (*(param + 7)))
+ {
+ TCHAR Value [1];
+ INT ValueSize = 0;
+
+ param += 7;
+ /* IF [NOT] DEFINED var COMMAND */
+ /* ^ */
+ while (_istspace (*param))
+ param++;
+ /* IF [NOT] DEFINED var COMMAND */
+ /* ^ */
+ pp = param;
+ while (*pp && !_istspace (*pp))
+ pp++;
+ /* IF [NOT] DEFINED var COMMAND */
+ /* ^ */
+ if (*pp)
+ {
+ *pp++ = _T('\0');
+ ValueSize = GetEnvironmentVariable(param, Value, sizeof Value);
+ x_flag ^= (0 == ValueSize)
+ ? 0
+ : X_EXEC;
+ x_flag |= X_EMPTY;
+ }
+ 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 ^= (nErrorLevel < 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;
+}
--- /dev/null
+/*
+ * 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.
+ *
+ * 15-Mar-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ * Fixed bug in "cd -" feature. If the previous directory was a root
+ * directory, it was ignored.
+ *
+ * 23-Feb-2001 (Carl Nettelblad <cnettel@hem.passagen.se>)
+ * Improved chdir/cd command.
+ */
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "cmd.h"
+
+
+#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 lpOldPath;
+ LPTSTR endofstring; /* pointer to the null character in the directory to change to */
+ LPTSTR lastquote; /* pointer to the last quotation mark in the directory to change to */
+
+ /*Should we better declare a variable containing _tsclen(dir) ? It's used a few times,
+ but on the other hand paths are generally not very long*/
+
+ 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;
+ }
+
+ /* The whole param string is our parameter these days. The only thing we do is eliminating every quotation mark */
+ /* Is it safe to change the characters param is pointing to? I presume it is, as there doesn't seem to be any
+ post-processing of it after the function call (what would that accomplish?) */
+
+ dir=param;
+ endofstring=dir+_tcslen(dir);
+
+ while ((lastquote = _tcsrchr(dir,'\"')))
+ {
+ endofstring--;
+ memmove(lastquote,lastquote+1,endofstring-lastquote);
+ *endofstring=_T('\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);
+
+
+ return 0;
+ }
+
+ if (dir && _tcslen (dir) == 1 && *dir == _T('-'))
+ {
+ if (lpLastPath)
+ dir = lpLastPath;
+ else
+ return 0;
+ }
+ else if (dir && _tcslen (dir)==2 && 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);
+
+
+ return 0;
+ }
+
+ /* remove trailing \ if any, but ONLY if dir is not the root dir */
+ if (_tcslen (dir) > 3 && 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;
+
+ return 1;
+ }
+ else
+ {
+ GetCurrentDirectory(MAX_PATH, dir);
+ if (dir[0]!=lpOldPath[0])
+ {
+ SetCurrentDirectory(lpOldPath);
+ free(lpOldPath);
+ }
+ else
+ {
+ if (lpLastPath)
+ free (lpLastPath);
+ lpLastPath = lpOldPath;
+ }
+ }
+
+
+ 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, FALSE);
+ if (argc > 1)
+ {
+ /*JPP 20-Jul-1998 use standard error message */
+ error_too_many_parameters (param);
+ freep (p);
+ return 1;
+ }
+ else
+ dir = p[0];
+ }
+
+ if (!dir)
+ {
+ ConErrPrintf (_T("Required parameter missing\n"));
+ return 1;
+ }
+
+ /* 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, FALSE);
+ if (argc > 1)
+ {
+ /*JPP 20-Jul-1998 use standard error message */
+ error_too_many_parameters (param);
+ freep (p);
+ return 1;
+ }
+ else
+ dir = p[0];
+ }
+
+ if (!dir)
+ {
+ ConErrPrintf (_T("Required parameter missing\n"));
+ return 1;
+ }
+
+ /* 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 CommandExit (LPTSTR cmd, LPTSTR param)
+{
+ if (!_tcsncmp (param, _T("/?"), 2))
+ {
+ ConOutPuts (_T("Exits the command line interpreter.\n\nEXIT"));
+ return 0;
+ }
+
+ bExit = TRUE;
+ return 0;
+}
+
+
+#ifdef INCLUDE_CMD_REM
+/*
+ * does nothing
+ *
+ */
+INT CommandRem (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 /* INCLUDE_CMD_REM */
+
+
+INT CommandShowCommands (LPTSTR cmd, LPTSTR param)
+{
+ PrintCommandList ();
+ return 0;
+}
+
+/* EOF */
--- /dev/null
+/*
+ * 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!
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_LABEL
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <ctype.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, FALSE);
+
+ 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 */
--- /dev/null
+
+ 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.
+
+
--- /dev/null
+/*
+ * 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!
+ */
+
+#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("Sun"), _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
+}
+
+
+VOID PrintDate (VOID)
+{
+#ifdef __REACTOS__
+ SYSTEMTIME st;
+
+ GetLocalTime (&st);
+
+ switch (nDateFormat)
+ {
+ case 0: /* mmddyy */
+ default:
+ ConOutPrintf (_T("%s %02d%c%02d%c%04d"),
+ aszDayNames[st.wDayOfWeek], st.wMonth, cDateSeparator, st.wDay, cDateSeparator, st.wYear);
+ break;
+
+ case 1: /* ddmmyy */
+ ConOutPrintf (_T("%s %02d%c%02d%c%04d"),
+ aszDayNames[st.wDayOfWeek], st.wDay, cDateSeparator, st.wMonth, cDateSeparator, st.wYear);
+ break;
+
+ case 2: /* yymmdd */
+ ConOutPrintf (_T("%s %04d%c%02d%c%02d"),
+ aszDayNames[st.wDayOfWeek], st.wYear, cDateSeparator, st.wMonth, cDateSeparator, st.wDay);
+ break;
+ }
+#else
+ TCHAR szDate[32];
+
+ GetDateFormat (LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL,
+ szDate, sizeof (szDate));
+ ConOutPrintf (_T("%s"), szDate);
+#endif
+}
+
+
+VOID PrintTime (VOID)
+{
+#ifdef __REACTOS__
+ 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;
+ }
+#else
+ TCHAR szTime[32];
+
+ GetTimeFormat (LOCALE_USER_DEFAULT, 0, NULL, NULL,
+ szTime, sizeof (szTime));
+ ConOutPrintf (_T("Current time is: %s\n"), szTime);
+#endif
+}
--- /dev/null
+#
+# ReactOS CMD
+#
+# Makefile
+#
+
+PATH_TO_TOP = ../../reactos
+
+TARGET_TYPE = program
+
+TARGET_APPTYPE = console
+
+TARGET_NAME = cmd
+
+WINE_MODE = yes
+
+WINE_RC = $(TARGET_NAME)
+
+WINE_INCLUDE = ./
+
+TARGET_SDKLIBS = \
+ kernel32.a \
+ user32.a
+
+TARGET_OBJECTS = \
+ cmd.o attrib.o alias.o batch.o beep.o call.o chcp.o choice.o \
+ cls.o cmdinput.o cmdtable.o color.o console.o copy.o date.o del.o \
+ delay.o dir.o dirstack.o echo.o error.o filecomp.o for.o free.o \
+ goto.o history.o if.o internal.o label.o locale.o memory.o misc.o \
+ move.o msgbox.o path.o pause.o prompt.o redir.o ren.o screen.o \
+ set.o shift.o start.o strtoclr.o time.o timer.o title.o type.o \
+ ver.o verify.o vol.o where.o window.o #cmd.coff
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+# EOF
--- /dev/null
+/*
+ * MEMORY.C - internal command.
+ *
+ *
+ * History:
+ *
+ * 01-Sep-1999 (Eric Kohl)
+ * Started.
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_MEMORY
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "cmd.h"
+
+
+/*
+ * convert
+ *
+ * insert commas into a number
+ */
+static INT
+ConvertDWord (DWORD num, LPTSTR des, INT len, BOOL bSeparator)
+{
+ 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 (bSeparator && (((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;
+}
+
+
+INT CommandMemory (LPTSTR cmd, LPTSTR param)
+{
+ MEMORYSTATUS ms;
+ TCHAR szMemoryLoad[20];
+ TCHAR szTotalPhys[20];
+ TCHAR szAvailPhys[20];
+ TCHAR szTotalPageFile[20];
+ TCHAR szAvailPageFile[20];
+ TCHAR szTotalVirtual[20];
+ TCHAR szAvailVirtual[20];
+
+ if (!_tcsncmp (param, _T("/?"), 2))
+ {
+ ConOutPuts (_T("Displays the amount of system memory.\n"
+ "\n"
+ "MEMORY"));
+ return 0;
+ }
+
+ ms.dwLength = sizeof(MEMORYSTATUS);
+
+ GlobalMemoryStatus (&ms);
+
+ ConvertDWord (ms.dwMemoryLoad, szMemoryLoad, 20, FALSE);
+ ConvertDWord (ms.dwTotalPhys, szTotalPhys, 20, TRUE);
+ ConvertDWord (ms.dwAvailPhys, szAvailPhys, 20, TRUE);
+ ConvertDWord (ms.dwTotalPageFile, szTotalPageFile, 20, TRUE);
+ ConvertDWord (ms.dwAvailPageFile, szAvailPageFile, 20, TRUE);
+ ConvertDWord (ms.dwTotalVirtual, szTotalVirtual, 20, TRUE);
+ ConvertDWord (ms.dwAvailVirtual, szAvailVirtual, 20, TRUE);
+
+ ConOutPrintf (_T("\n"
+ " %12s%% memory load.\n"
+ "\n"
+ " %13s bytes total physical RAM.\n"
+ " %13s bytes available physical RAM.\n"
+ "\n"
+ " %13s bytes total page file.\n"
+ " %13s bytes available page file.\n"
+ "\n"
+ " %13s bytes total virtual memory.\n"
+ " %13s bytes available virtual memory.\n"),
+ szMemoryLoad, szTotalPhys, szAvailPhys, szTotalPageFile,
+ szAvailPageFile, szTotalVirtual, szAvailVirtual);
+
+ return 0;
+}
+
+#endif /* INCLUDE_CMD_MEMORY */
+
+/* EOF */
--- /dev/null
+/*
+ * 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.
+ *
+ * 06-Nov-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ * Added PagePrompt() and FilePrompt().
+ */
+
+#include "config.h"
+
+#include <windows.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <tchar.h>
+
+#include "cmd.h"
+
+
+/*
+ * get a character out-of-band and honor Ctrl-Break characters
+ */
+TCHAR cgetchar (VOID)
+{
+ HANDLE hInput = GetStdHandle (STD_INPUT_HANDLE);
+ INPUT_RECORD irBuffer;
+ DWORD dwRead;
+
+ do
+ {
+ ReadConsoleInput (hInput, &irBuffer, 1, &dwRead);
+ if ((irBuffer.EventType == KEY_EVENT) &&
+ (irBuffer.Event.KeyEvent.bKeyDown == TRUE))
+ {
+ if ((irBuffer.Event.KeyEvent.dwControlKeyState &
+ (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) &
+ (irBuffer.Event.KeyEvent.wVirtualKeyCode == 'C'))
+ bCtrlBreak = TRUE;
+
+ break;
+ }
+ }
+ while (TRUE);
+
+#ifndef _UNICODE
+ return irBuffer.Event.KeyEvent.uChar.AsciiChar;
+#else
+ return irBuffer.Event.KeyEvent.uChar.UnicodeChar;
+#endif /* _UNICODE */
+}
+
+
+/*
+ * 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;
+}
+
+/* add new entry for new argument */
+static BOOL add_entry (LPINT ac, LPTSTR **arg, LPCTSTR entry)
+{
+ LPTSTR q;
+ LPTSTR *oldarg;
+
+ q = malloc ((_tcslen(entry) + 1) * sizeof (TCHAR));
+ if (NULL == q)
+ {
+ return FALSE;
+ }
+ _tcscpy (q, entry);
+
+ oldarg = *arg;
+ *arg = realloc (oldarg, (*ac + 2) * sizeof (LPTSTR));
+ if (NULL == *arg)
+ {
+ *arg = oldarg;
+ return FALSE;
+ }
+
+ /* save new entry */
+ (*arg)[*ac] = q;
+ (*arg)[++(*ac)] = NULL;
+
+ return TRUE;
+}
+
+static BOOL expand (LPINT ac, LPTSTR **arg, LPCTSTR pattern)
+{
+ HANDLE hFind;
+ WIN32_FIND_DATA FindData;
+ BOOL ok;
+ LPCTSTR pathend;
+ LPTSTR dirpart, fullname;
+
+ pathend = _tcsrchr (pattern, _T('\\'));
+ if (NULL != pathend)
+ {
+ dirpart = malloc((pathend - pattern + 2) * sizeof(TCHAR));
+ if (NULL == dirpart)
+ {
+ return FALSE;
+ }
+ memcpy(dirpart, pattern, pathend - pattern + 1);
+ dirpart[pathend - pattern + 1] = '\0';
+ }
+ else
+ {
+ dirpart = NULL;
+ }
+ hFind = FindFirstFile (pattern, &FindData);
+ if (INVALID_HANDLE_VALUE != hFind)
+ {
+ do
+ {
+ if (NULL != dirpart)
+ {
+ fullname = malloc((_tcslen(dirpart) + _tcslen(FindData.cFileName) + 1) * sizeof(TCHAR));
+ if (NULL == fullname)
+ {
+ ok = FALSE;
+ }
+ else
+ {
+ _tcscat (_tcscpy (fullname, dirpart), FindData.cFileName);
+ ok = add_entry(ac, arg, fullname);
+ free (fullname);
+ }
+ }
+ else
+ {
+ ok = add_entry(ac, arg, FindData.cFileName);
+ }
+ } while (FindNextFile (hFind, &FindData) && ok);
+ FindClose (hFind);
+ }
+ else
+ {
+ ok = add_entry(ac, arg, pattern);
+ }
+
+ if (NULL != dirpart)
+ {
+ free (dirpart);
+ }
+
+ return ok;
+}
+
+/*
+ * split - splits a line up into separate arguments, deliminators
+ * are spaces and slashes ('/').
+ */
+
+LPTSTR *split (LPTSTR s, LPINT args, BOOL expand_wildcards)
+{
+ LPTSTR *arg;
+ 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)
+ {
+ q = malloc (((len = s - start) + 1) * sizeof (TCHAR));
+ if (!q)
+ {
+ return NULL;
+ }
+ memcpy (q, start, len * sizeof (TCHAR));
+ q[len] = _T('\0');
+ if (expand_wildcards && _T('/') != *start &&
+ (NULL != _tcschr(q, _T('*')) || NULL != _tcschr(q, _T('?'))))
+ {
+ if (! expand(&ac, &arg, q))
+ {
+ free (q);
+ freep (arg);
+ return NULL;
+ }
+ }
+ else
+ {
+ if (! add_entry(&ac, &arg, q))
+ {
+ free (q);
+ freep (arg);
+ return NULL;
+ }
+ }
+ free (q);
+ }
+
+ /* 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 IsValidDirectory (LPCTSTR pszPath)
+{
+ return (GetFileAttributes (pszPath) & FILE_ATTRIBUTE_DIRECTORY);
+}
+
+
+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)
+ {
+ if (ch == _T('\r'))
+ {
+ /* overread '\n' */
+ ReadFile (hFile, &ch, 1, &dwRead, NULL);
+ break;
+ }
+ *lpString++ = ch;
+ }
+
+ if (!dwRead && lpString == lpBuffer)
+ return FALSE;
+
+ *lpString++ = _T('\0');
+
+ return TRUE;
+}
+
+#ifndef __REACTOS__
+/*
+ * GetConsoleWindow - returns the handle to the current console window
+ */
+HWND GetConsoleWindow (VOID)
+{
+ TCHAR original[256];
+ TCHAR temp[256];
+ HWND h=0;
+
+ if(h)
+ return h;
+
+ GetConsoleTitle (original, sizeof(original));
+
+ _tcscpy (temp, original);
+ _tcscat (temp, _T("-xxx "));
+
+ if (FindWindow (0, temp) == NULL )
+ {
+ SetConsoleTitle (temp);
+ Sleep (0);
+
+ while(!(h = FindWindow (0, temp)))
+ ;
+
+ SetConsoleTitle (original);
+ }
+
+ return h;
+}
+#endif
+
+
+INT PagePrompt (VOID)
+{
+ INPUT_RECORD ir;
+
+ ConOutPrintf ("Press a key to continue...\n");
+
+ RemoveBreakHandler ();
+ ConInDisable ();
+
+ do
+ {
+ ConInKey (&ir);
+ }
+ while ((ir.Event.KeyEvent.wVirtualKeyCode == VK_SHIFT) ||
+ (ir.Event.KeyEvent.wVirtualKeyCode == VK_MENU) ||
+ (ir.Event.KeyEvent.wVirtualKeyCode == VK_CONTROL));
+
+ AddBreakHandler ();
+ ConInEnable ();
+
+ if ((ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) ||
+ ((ir.Event.KeyEvent.wVirtualKeyCode == 'C') &&
+ (ir.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))))
+ return PROMPT_BREAK;
+
+ return PROMPT_YES;
+}
+
+
+INT FilePromptYN (LPTSTR szFormat, ...)
+{
+ TCHAR szOut[512];
+ va_list arg_ptr;
+// TCHAR cKey = 0;
+// LPTSTR szKeys = _T("yna");
+
+ TCHAR szIn[10];
+ LPTSTR p;
+
+ va_start (arg_ptr, szFormat);
+ _vstprintf (szOut, szFormat, arg_ptr);
+ va_end (arg_ptr);
+
+ ConOutPrintf (szFormat);
+
+/* preliminary fix */
+ ConInString (szIn, 10);
+ ConOutPrintf (_T("\n"));
+
+ _tcsupr (szIn);
+ for (p = szIn; _istspace (*p); p++)
+ ;
+
+ if (*p == _T('Y'))
+ return PROMPT_YES;
+ else if (*p == _T('N'))
+ return PROMPT_NO;
+#if 0
+ else if (*p == _T('\03'))
+ return PROMPT_BREAK;
+#endif
+
+ return PROMPT_NO;
+
+
+/* unfinished sollution */
+#if 0
+ RemoveBreakHandler ();
+ ConInDisable ();
+
+ do
+ {
+ ConInKey (&ir);
+ cKey = _totlower (ir.Event.KeyEvent.uChar.AsciiChar);
+ if (_tcschr (szKeys, cKey[0]) == NULL)
+ cKey = 0;
+
+
+ }
+ while ((ir.Event.KeyEvent.wVirtualKeyCode == VK_SHIFT) ||
+ (ir.Event.KeyEvent.wVirtualKeyCode == VK_MENU) ||
+ (ir.Event.KeyEvent.wVirtualKeyCode == VK_CONTROL));
+
+ AddBreakHandler ();
+ ConInEnable ();
+
+ if ((ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) ||
+ ((ir.Event.KeyEvent.wVirtualKeyCode == 'C') &&
+ (ir.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))))
+ return PROMPT_BREAK;
+
+ return PROMPT_YES;
+#endif
+}
+
+
+INT FilePromptYNA (LPTSTR szFormat, ...)
+{
+ TCHAR szOut[512];
+ va_list arg_ptr;
+// TCHAR cKey = 0;
+// LPTSTR szKeys = _T("yna");
+
+ TCHAR szIn[10];
+ LPTSTR p;
+
+ va_start (arg_ptr, szFormat);
+ _vstprintf (szOut, szFormat, arg_ptr);
+ va_end (arg_ptr);
+
+ ConOutPrintf (szFormat);
+
+/* preliminary fix */
+ ConInString (szIn, 10);
+ ConOutPrintf (_T("\n"));
+
+ _tcsupr (szIn);
+ for (p = szIn; _istspace (*p); p++)
+ ;
+
+ if (*p == _T('Y'))
+ return PROMPT_YES;
+ else if (*p == _T('N'))
+ return PROMPT_NO;
+ if (*p == _T('A'))
+ return PROMPT_ALL;
+#if 0
+ else if (*p == _T('\03'))
+ return PROMPT_BREAK;
+#endif
+
+ return PROMPT_NO;
+
+
+/* unfinished sollution */
+#if 0
+ RemoveBreakHandler ();
+ ConInDisable ();
+
+ do
+ {
+ ConInKey (&ir);
+ cKey = _totlower (ir.Event.KeyEvent.uChar.AsciiChar);
+ if (_tcschr (szKeys, cKey[0]) == NULL)
+ cKey = 0;
+
+
+ }
+ while ((ir.Event.KeyEvent.wVirtualKeyCode == VK_SHIFT) ||
+ (ir.Event.KeyEvent.wVirtualKeyCode == VK_MENU) ||
+ (ir.Event.KeyEvent.wVirtualKeyCode == VK_CONTROL));
+
+ AddBreakHandler ();
+ ConInEnable ();
+
+ if ((ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) ||
+ ((ir.Event.KeyEvent.wVirtualKeyCode == 'C') &&
+ (ir.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))))
+ return PROMPT_BREAK;
+
+ return PROMPT_YES;
+#endif
+}
+
+/* EOF */
--- /dev/null
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_MOVE
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <ctype.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, FALSE);
+ 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 */
--- /dev/null
+/*
+ * MSGBOX.C - msgbox internal command.
+ *
+ * clone from 4nt msgbox command
+ *
+ * 25 Aug 1999
+ * started - Paolo Pantaleo <paolopan@freemail.it>
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_MSGBOX
+#include <windows.h>
+#include <ctype.h>
+#include <string.h>
+#include <tchar.h>
+#include "cmd.h"
+//#include <assert.h>
+
+//#include <malloc.h>
+
+
+#define U_TYPE_INIT 0
+
+//undefine it to allow to omit arguments
+//that will be replaced by default ones
+#define _SYNTAX_CHECK
+
+
+INT CommandMsgbox (LPTSTR cmd, LPTSTR param)
+{
+ //used to parse command line
+ LPTSTR tmp;
+
+ //used to find window title (used as messagebox title)
+ //and to find window handle to pass to MessageBox
+ HWND hWnd;
+ TCHAR buff[128];
+
+ //these are MessabeBox() parameters
+ LPTSTR title, prompt="";
+ UINT uType=U_TYPE_INIT;
+
+ //set default title to window title
+ GetConsoleTitle(buff,128);
+ title = buff;
+
+ if (_tcsncmp (param, _T("/?"), 2) == 0)
+ {
+ ConOutPuts(_T(
+ "display a message box and return user responce\n"
+ "\n"
+ "MSGBOX type [\"title\"] prompt\n"
+ "\n"
+ "type button displayed\n"
+ " possible values are: OK, OKCANCEL,\n"
+ " YESNO, YESNOCANCEL\n"
+ "title title of message box\n"
+ "prompt text displayed by the message box\n"
+ "\n"
+ "\n"
+ "ERRORLEVEL is set according the button pressed:\n"
+ "\n"
+ "YES : 10 | NO : 11\n"
+ "OK : 10 | CANCEL : 12\n"));
+ return 0;
+ }
+
+ //yes here things are quite massed up :)
+
+ //skip spaces
+ while(_istspace(*param))
+ param++;
+
+ //search for type of messagebox (ok, okcancel, ...)
+ if (_tcsnicmp(param, _T("ok "),3 ) == 0)
+ {
+ uType |= MB_ICONEXCLAMATION | MB_OK;
+ param+=3;
+ }
+ else if (_tcsnicmp(param, _T("okcancel "),9 ) == 0)
+ {
+ uType |= MB_ICONQUESTION | MB_OKCANCEL;
+ param+=9;
+ }
+ else if (_tcsnicmp(param, _T("yesno "),6 ) == 0)
+ {
+ uType |= MB_ICONQUESTION | MB_YESNO;
+ param+=6;
+ }
+ else if (_tcsnicmp(param, _T("yesnocancel "), 12 ) == 0)
+ {
+ uType |= MB_ICONQUESTION | MB_YESNOCANCEL;
+ param+=12;
+ }
+ else{
+#ifdef _SYNTAX_CHECK
+ error_req_param_missing ();
+ return 1;
+#else
+ uType |= MB_ICONEXCLAMATION | MB_OK;
+#endif
+ }
+
+
+ //skip spaces
+ while(_istspace(*param))
+ param++;
+
+#ifdef _SYNTAX_CHECK
+ //if reached end of string
+ //it is an error becuase we do not yet have prompt
+ if ( *param == 0)
+ {
+ error_req_param_missing ();
+ return 1;
+ }
+#endif
+
+ //search for "title"
+ tmp = param;
+
+ if(*param == '"')
+ {
+ tmp = _tcschr(param+1,'"');
+ if (tmp)
+ {
+ *tmp = 0;
+ title = param+1;
+ tmp++;
+ param = tmp;
+ }
+ }
+
+ //skip spaces
+ while(_istspace(*param))
+ param++;
+#ifdef _SYNTAX_CHECK
+ //get prompt
+ if ( *param == 0)
+ {
+ error_req_param_missing ();
+ return 1;
+ }
+#endif
+
+ prompt = param;
+
+ hWnd=GetConsoleWindow ();
+// DebugPrintf("FindWindow hWnd = %d\n",hWnd);
+ ConErrPrintf("FindWindow hWnd = %d\n",hWnd);
+
+ switch (
+ MessageBox(hWnd,prompt,title,uType)
+ )
+ {
+ case IDYES:
+ case IDOK:
+ nErrorLevel = 10;
+ break;
+
+ case IDNO:
+ nErrorLevel = 11;
+ break;
+
+ case IDCANCEL:
+ nErrorLevel = 12;
+ break;
+ }
+
+ return 0;
+}
+
+#endif /* INCLUDE_CMD_MSGBOX */
--- /dev/null
+/*
+ * 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.
+ */
+
+#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;
+ }
+
+ /* skip leading '=' */
+ if (*param == _T('='))
+ param++;
+
+ /* set PATH environment variable */
+ if (!SetEnvironmentVariable (_T("PATH"), param))
+ return 1;
+
+ return 0;
+}
+
+#endif
--- /dev/null
+/*
+ * 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!
+ */
+
+#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
--- /dev/null
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <ctype.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'):
+ PrintDate ();
+ 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'):
+ PrintTime ();
+ 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
--- /dev/null
+ReactOS command line interpreter CMD version 0.1.1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ReactOS command line interpreter CMD is derived from FreeCOM, the
+FreeDOS command line interpreter.
+
+We are going for 4NT compatibility but try to stay compatible with
+WinNT's CMD.EXE too.
+
+
+Compiling
+~~~~~~~~~
+Cmd can be built in two different versions. A full version for use under
+Windows 9x or Windows NT and a reduced version for use under ReactOS.
+
+Note: The full version won't run on ReactOS and the reduced version is not
+usable under Win 9x/NT.
+
+To build the full version, make sure the symbol '__REACTOS__' is NOT defined
+in 'rosapps/cmd/config.h' line 13.
+
+To build the reduced version, make sure the symbol '__REACTOS__' is defined
+in 'rosapps/cmd/config.h' line 13.
+
+
+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)
+ (this is still incomplete)
+
+
+Credits
+~~~~~~~
+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@rz-online.de>
+ Emanuele Aliberti <ea@iol.it>
+ Paolo Pantaleo <paolopan@freemail.it>
+
+
+Bugs
+~~~~
+Batch file handling is still untested or buggy. Please report
+any bug you find.
+
+Please report bugs to Eric Kohl <ekohl@rz-online.de>.
+
+
+Good luck
+
+ Eric Kohl
--- /dev/null
+/*
+ * 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 "&>>".
+ */
+
+#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 && *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;
+ do sp++;
+ while( _istspace (*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 && *sp != qc);
+
+ sp++;
+ }
+ else if (*sp == _T('|'))
+ {
+ *sp++ = _T('\0');
+ num++;
+ }
+ else
+ sp++;
+ }
+
+ return num;
+}
+
+#endif /* FEATURE_REDIRECTION */
--- /dev/null
+/*
+ * 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!
+ *
+ * 17-Oct-2001 (Eric Kohl <ekohl@rz.online.de>
+ * Implemented basic rename code.
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_RENAME
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "cmd.h"
+#include "batch.h"
+
+enum
+{
+ REN_ATTRIBUTES = 0x001, /* /A : not implemented */
+ REN_ERROR = 0x002, /* /E */
+ REN_NOTHING = 0x004, /* /N */
+ REN_PROMPT = 0x008, /* /P : not implemented */
+ REN_QUIET = 0x010, /* /Q */
+ REN_SUBDIR = 0x020, /* /S */
+ REN_TOTAL = 0x040, /* /T */
+};
+
+
+/*
+ * file rename internal command.
+ *
+ */
+INT cmd_rename (LPTSTR cmd, LPTSTR param)
+{
+ LPTSTR *arg = NULL;
+ INT args = 0;
+ INT nEvalArgs = 0; /* nunber of evaluated arguments */
+ DWORD dwFlags = 0;
+ DWORD dwFiles = 0; /* number of renamedd files */
+ INT i;
+ LPTSTR srcPattern = NULL;
+ LPTSTR dstPattern = NULL;
+ TCHAR dstFile[MAX_PATH];
+ BOOL bDstWildcard = FALSE;
+
+ LPTSTR p,q,r;
+
+ HANDLE hFile;
+ WIN32_FIND_DATA f;
+
+ if (!_tcsncmp(param, _T("/?"), 2))
+ {
+ ConOutPuts(_T("Renames a file/directory or files/directories.\n"
+ "\n"
+ "RENAME [/E /N /P /Q /S /T] old_name ... new_name\n"
+ "REN [/E /N /P /Q /S /T] old_name ... new_name\n"
+ "\n"
+ " /E No eror messages.\n"
+ " /N Nothing.\n"
+ " /P Prompts for confirmation before renaming each file.\n"
+ " (Not implemented yet!)\n"
+ " /Q Quiet.\n"
+ " /S Rename subdirectories.\n"
+ " /T Display total number of renamed files.\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, &args, FALSE);
+
+ if (args < 2)
+ {
+ if (!(dwFlags & REN_ERROR))
+ error_req_param_missing();
+ freep(arg);
+ return(1);
+ }
+
+ /* read options */
+ for (i = 0; i < args; i++)
+ {
+ if (*arg[i] == _T('/'))
+ {
+ if (_tcslen(arg[i]) >= 2)
+ {
+ switch (_totupper(arg[i][1]))
+ {
+ case _T('E'):
+ dwFlags |= REN_ERROR;
+ break;
+
+ case _T('N'):
+ dwFlags |= REN_NOTHING;
+ break;
+
+ case _T('P'):
+ dwFlags |= REN_PROMPT;
+ break;
+
+ case _T('Q'):
+ dwFlags |= REN_QUIET;
+ break;
+
+ case _T('S'):
+ dwFlags |= REN_SUBDIR;
+ break;
+
+ case _T('T'):
+ dwFlags |= REN_TOTAL;
+ break;
+ }
+ }
+ nEvalArgs++;
+ }
+ }
+
+ /* keep quiet within batch files */
+ if (bc != NULL)
+ dwFlags |= REN_QUIET;
+
+ /* there are only options on the command line --> error!!! */
+ if (args < nEvalArgs + 2)
+ {
+ if (!(dwFlags & REN_ERROR))
+ error_req_param_missing();
+ freep(arg);
+ return(1);
+ }
+
+ /* get destination pattern */
+ for (i = 0; i < args; i++)
+ {
+ if (*arg[i] == _T('/'))
+ continue;
+ dstPattern = arg[i];
+ }
+
+ if (_tcschr(dstPattern, _T('*')) || _tcschr(dstPattern, _T('?')))
+ bDstWildcard = TRUE;
+
+ /* enumerate source patterns */
+ for (i = 0; i < args; i++)
+ {
+ if (*arg[i] == _T('/') || arg[i] == dstPattern)
+ continue;
+
+ srcPattern = arg[i];
+
+#ifdef _DEBUG
+ ConErrPrintf(_T("\n\nSourcePattern: %s\n"), srcPattern);
+ ConErrPrintf(_T("DestinationPattern: %s\n"), dstPattern);
+#endif
+
+ hFile = FindFirstFile(srcPattern, &f);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ if (!(dwFlags & REN_ERROR))
+ error_file_not_found();
+ continue;
+ }
+
+ do
+ {
+ /* ignore "." and ".." */
+ if (!_tcscmp (f.cFileName, _T(".")) ||
+ !_tcscmp (f.cFileName, _T("..")))
+ continue;
+
+ /* do not rename hidden or system files */
+ if (f.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM))
+ continue;
+
+ /* do not rename directories when the destination pattern contains
+ * wildcards, unless option /S is used */
+ if ((f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ && bDstWildcard
+ && !(dwFlags & REN_SUBDIR))
+ continue;
+
+#ifdef _DEBUG
+ ConErrPrintf(_T("Found source name: %s\n"), f.cFileName);
+#endif
+
+ /* build destination file name */
+ p = f.cFileName;
+ q = dstPattern;
+ r = dstFile;
+ while(*q != 0)
+ {
+ if (*q == '*')
+ {
+ q++;
+ while (*p != 0 && *p != *q)
+ {
+ *r = *p;
+ p++;
+ r++;
+ }
+ }
+ else if (*q == '?')
+ {
+ q++;
+ if (*p != 0)
+ {
+ *r = *p;
+ p++;
+ r++;
+ }
+ }
+ else
+ {
+ *r = *q;
+ if (*p != 0)
+ p++;
+ q++;
+ r++;
+ }
+ }
+ *r = 0;
+
+#ifdef _DEBUG
+ ConErrPrintf(_T("DestinationFile: %s\n"), dstFile);
+#endif
+
+ if (!(dwFlags & REN_QUIET) && !(dwFlags & REN_TOTAL))
+ ConOutPrintf(_T("%s -> %s\n"), f.cFileName, dstFile);
+
+ /* rename the file */
+ if (!(dwFlags & REN_NOTHING))
+ {
+ if (MoveFile(f.cFileName, dstFile))
+ {
+ dwFiles++;
+ }
+ else
+ {
+ if (!(dwFlags & REN_ERROR))
+ ConErrPrintf(_T("MoveFile() failed. Error: %lu\n"), GetLastError());
+ }
+ }
+ }
+ while (FindNextFile(hFile, &f));
+ FindClose(hFile);
+ }
+
+ if (!(dwFlags & REN_QUIET))
+ {
+ if (dwFiles == 1)
+ ConOutPrintf(_T(" %lu file renamed\n"),
+ dwFiles);
+ else
+ ConOutPrintf(_T(" %lu files renamed\n"),
+ dwFiles);
+ }
+
+ freep(arg);
+
+ return(0);
+}
+
+#endif
+
+/* EOF */
--- /dev/null
+/*
+ * SCREEN.C - screen internal command.
+ *
+ * clone from 4nt msgbox command
+ *
+ * 30 Aug 1999
+ * started - Paolo Pantaleo <paolopan@freemail.it>
+ *
+ *
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_SCREEN
+
+#include <tchar.h>
+#include <windows.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "cmd.h"
+
+
+INT CommandScreen (LPTSTR cmd, LPTSTR param)
+{
+ SHORT x,y;
+ BOOL bSkipText = FALSE;
+
+ if (_tcsncmp (param, _T("/?"), 2) == 0)
+ {
+ ConOutPuts(_T(
+ "move cursor and optionally print text\n"
+ "\n"
+ "SCREEN row col [text]\n"
+ "\n"
+ " row row to wich move the cursor\n"
+ " col column to wich move the cursor"));
+ return 0;
+ }
+
+ //get row
+ while(_istspace(*param))
+ param++;
+
+ if(!(*param))
+ {
+ error_req_param_missing ();
+ return 1;
+ }
+
+ y = atoi(param);
+ if (y<0 || y>(maxy-1))
+ {
+ ConOutPrintf("invalid value for row");
+ return 1;
+ }
+
+ //get col
+ if(!(param = _tcschr(param,_T(' '))))
+ {
+ error_req_param_missing ();
+ return 1;
+ }
+
+ while(_istspace(*param))
+ param++;
+
+ if(!(*param))
+ {
+ error_req_param_missing ();
+ return 1;
+ }
+
+ x = atoi(param);
+ if (x<0 || x>(maxx-1))
+ {
+ ConErrPuts(_T("invalid value for col"));
+ return 1;
+ }
+
+ //get text
+ if(!(param = _tcschr(param,_T(' '))))
+ {
+ bSkipText = TRUE;
+ }
+ else
+ {
+ while(_istspace(*param))
+ param++;
+
+ if(!(*param))
+ {
+ bSkipText = TRUE;
+ }
+ }
+
+ bIgnoreEcho = TRUE;
+
+ if(bSkipText)
+ x=0;
+
+
+ SetCursorXY(x,y);
+
+ if(!(bSkipText))
+ ConOutPuts(param);
+
+ return 0;
+}
+
+#endif /* INCLUDE_CMD_SCREEN */
--- /dev/null
+/*
+ * 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!
+ *
+ * 25-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ * Fixed little bug.
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_SET
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+
+/* initial 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, dwBuffer * sizeof (TCHAR));
+ }
+
+ ConOutPrintf ("%s\n", pszBuffer);
+ free (pszBuffer);
+
+ return 0;
+ }
+
+ return 0;
+}
+
+#endif
--- /dev/null
+/*
+ * 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!
+ */
+
+#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;
+}
--- /dev/null
+/*
+ * START.C - start internal command.
+ *
+ *
+ * History:
+ *
+ * 24-Jul-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ * Started.
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_START
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "cmd.h"
+
+
+INT cmd_start (LPTSTR first, LPTSTR rest)
+{
+ TCHAR szFullName[MAX_PATH];
+ BOOL bWait = FALSE;
+ TCHAR *param;
+
+ if (_tcsncmp (rest, _T("/?"), 2) == 0)
+ {
+ ConOutPuts (_T("Starts a command.\n\n"
+ "START command \n\n"
+ " command Specifies the command to run.\n\n"
+ "At the moment all commands are started asynchronously.\n"));
+
+ return 0;
+ }
+
+ /* 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);
+
+ return 0;
+ }
+ if( !*rest )
+ {
+ // FIXME: use comspec instead
+ rest = "cmd";
+ }
+ /* get the PATH environment variable and parse it */
+ /* search the PATH environment variable for the binary */
+ param = strchr( rest, ' ' ); // skip program name to reach parameters
+ if( param )
+ {
+ *param = 0;
+ param++;
+ }
+ if (!SearchForExecutable (rest, szFullName))
+ {
+ error_bad_command ();
+ return 1;
+ }
+ /* 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
+ ConErrPuts (_T("No batch support at the moment!"));
+ }
+ else
+ {
+ /* exec the program */
+ TCHAR szFullCmdLine [CMDLINE_LENGTH];
+ PROCESS_INFORMATION prci;
+ STARTUPINFO stui;
+
+#ifdef _DEBUG
+ DebugPrintf ("[EXEC: %s %s]\n", szFullName, rest);
+#endif
+ /* build command line for CreateProcess() */
+ _tcscpy (szFullCmdLine, first);
+ if( param )
+ {
+ _tcscat(szFullCmdLine, " " );
+ _tcscat (szFullCmdLine, param);
+ }
+
+ /* fill startup info */
+ memset (&stui, 0, sizeof (STARTUPINFO));
+ stui.cb = sizeof (STARTUPINFO);
+ stui.dwFlags = STARTF_USESHOWWINDOW;
+ stui.wShowWindow = SW_SHOWDEFAULT;
+
+ if (CreateProcess (szFullName, szFullCmdLine, NULL, NULL, FALSE,
+ CREATE_NEW_CONSOLE, NULL, NULL, &stui, &prci))
+ {
+ if (bWait)
+ {
+ DWORD dwExitCode;
+ WaitForSingleObject (prci.hProcess, INFINITE);
+ GetExitCodeProcess (prci.hProcess, &dwExitCode);
+ nErrorLevel = (INT)dwExitCode;
+ CloseHandle (prci.hThread);
+ CloseHandle (prci.hProcess);
+ }
+ }
+ else
+ {
+ ErrorMessage (GetLastError (),
+ "Error executing CreateProcess()!!\n");
+ }
+ }
+
+ return 0;
+}
+
+#endif
+
+/* EOF */
--- /dev/null
+/*
+ * STRTOCLR.C - read color (for color command and other)
+ *
+ *
+ * History:
+ *
+ * 07-Oct-1999 (Paolo Pantaleo)
+ * Started.
+ *
+ *
+ */
+
+/*only
+BOOL StringToColor(LPWORD lpColor, LPTSTR*str)
+is to be called
+other are internal service functions*/
+
+
+#include "cmd.h"
+
+#include <ctype.h>
+#include <tchar.h>
+
+
+#define _B FOREGROUND_BLUE
+#define _G FOREGROUND_GREEN
+#define _R FOREGROUND_RED
+#define _I FOREGROUND_INTENSITY
+
+
+/*return values for chop_blank*/
+#define CP_OK 0
+#define CP_BLANK_NOT_FOUND 1
+#define CP_END_OF_STRING 2
+
+#define SC_HEX 0x0100
+#define SC_TXT 0x0200
+
+
+
+typedef struct _CLRTABLE
+{
+ LPTSTR name;
+ WORD val;
+} CLRTABLE;
+
+
+CLRTABLE clrtable[] =
+{
+ {"bla" ,0 },
+ {"blu" ,_B },
+ {"gre" ,_G },
+ {"cya" ,_B|_G },
+ {"red" ,_R },
+ {"mag" ,_B|_R },
+ {"yel" ,_R|_G },
+ {"whi" ,_R|_G|_B },
+ {"gra" ,_I },
+
+
+ {"0" ,0 },
+ {"2" ,_G },
+ {"3" ,_B|_G },
+ {"4" ,_R },
+ {"5" ,_B|_R },
+ {"6" ,_R|_G },
+ {"7" ,_R|_G|_B },
+
+ {"8" ,_I },
+ {"9" ,_I|_B },
+ {"10" ,_I|_G },
+ {"11" ,_I|_B|_G },
+ {"12" ,_I|_R },
+ {"13" ,_I|_B|_R },
+ {"14" ,_I|_R|_G },
+ {"15" ,_I|_R|_G|_B},
+
+
+ /* note that 1 is at the end of list
+ to avoid to confuse it with 10-15*/
+ {"1" ,_B },
+
+ /*cyan synonimous*/
+ {"aqu" ,_B|_G },
+ /*magenta synonimous*/
+ {"pur" ,_B|_R },
+
+
+ {"" ,0},
+};
+
+
+
+/*
+move string pointer to next word (skip all spaces)
+on erro retunr nonzero value
+*/
+static
+INT chop_blank(LPTSTR *arg_str)
+{
+
+ LPTSTR str;
+ str = _tcschr(*arg_str,_T(' '));
+ if(!str)
+ {
+ str = _tcschr (*arg_str, _T('\0'));
+ if(str != NULL)
+ *arg_str=str;
+ return CP_BLANK_NOT_FOUND;
+ }
+
+
+
+ while(_istspace(*str))
+ str++;
+
+ if (*str == _T('\0'))
+ {
+ *arg_str=str;
+ return CP_END_OF_STRING;
+ }
+
+ *arg_str = str;
+
+ return CP_OK;
+}
+
+
+
+/*
+read a color value in hex (like win nt's cmd syntax)
+if an error occurs return -1
+*/
+static
+WORD hex_clr(LPTSTR str)
+{
+ WORD ret= (WORD)-1;
+ TCHAR ch;
+
+ ch = str[1];
+
+ if(_istdigit(ch))
+ ret = ch-_T('0');
+ else
+ {
+ ch=_totupper(ch);
+
+ if( ch >= _T('A') && ch <= _T('F') )
+ ret = ch-_T('A')+10;
+ else
+ return (WORD)-1;
+ }
+
+
+ ch = str[0];
+
+ if(_istdigit(ch))
+ ret |= (ch-_T('0')) << 4;
+ else
+ {
+ ch=_totupper(ch);
+
+ if( ch >= _T('A') && ch <= _T('F') )
+ ret |= (ch-_T('A')+10) <<4;
+ else
+ return (WORD)-1;
+ }
+
+ return ret;
+}
+
+
+/*
+read a color value from a string (like 4nt's syntax)
+if an error occurs return -1
+*/
+static
+WORD txt_clr(LPTSTR str)
+{
+ INT i;
+
+ for(i=0;*(clrtable[i].name);i++)
+ if( _tcsnicmp(str,clrtable[i].name,_tcslen(clrtable[i].name)) == 0)
+ return clrtable[i].val;
+
+ return (WORD)-1;
+}
+
+
+
+/*search for x on y*/
+static
+WORD str_to_color(LPTSTR* arg_str)
+{
+ LPTSTR str;
+ BOOL bBri;
+
+ WORD tmp_clr,ret_clr;
+
+ str = *arg_str;
+
+
+
+ if(!(*str))
+ return (WORD)-1;
+
+
+ /*foreground*/
+ bBri = FALSE;
+
+ if(_tcsnicmp(str,"bri",3) == 0 )
+ {
+ bBri = TRUE;
+
+ if(chop_blank(&str))
+ return (WORD)-1;
+ }
+
+ if( (tmp_clr = txt_clr(str)) == (WORD)-1 )
+ {
+ return (WORD)-1;
+ }
+
+ /*skip spaces and "on"*/
+ if ( chop_blank(&str) || chop_blank(&str) )
+ return (WORD)-1;
+
+ ret_clr = tmp_clr | (bBri << 3);
+
+ /*background*/
+ bBri = FALSE;
+
+ if(_tcsnicmp(str,"bri",3) == 0 )
+ {
+ bBri = TRUE;
+
+ if(chop_blank(&str))
+ return (WORD)-1;
+ }
+
+
+ if( (tmp_clr = txt_clr(str)) == (WORD)-1 )
+ return (WORD)-1;
+
+ chop_blank(&str);
+
+ *arg_str = str;
+
+ return SC_HEX | ret_clr | tmp_clr << 4 | bBri << 7;
+}
+
+
+
+/****main function****/
+/*
+the only parameter is arg_str, a pointer to a string.
+the string is modified so it will begin to first word after
+color specification
+(only the char* is moved, no chars in the string are modfied)
+
+
+it returns the color in the l.o. byte, plus two flags in the
+h.o. byte, they are:
+SC_HEX win nt's cmd syntax (for exampl a0)
+SC_TXT 4nt's syntax ( "bri gre on bla" or "10 on 0")
+
+if succedes also move the LPTSTR to end of
+string that specify color
+*/
+
+
+BOOL StringToColor(LPWORD lpColor, LPTSTR*str)
+{
+ WORD wRet;
+
+ wRet = str_to_color (str);
+ if (wRet == (WORD)-1)
+ {
+ wRet=hex_clr (*str);
+ chop_blank (str);
+ if (wRet == (WORD)-1)
+ return FALSE;
+ }
+
+ *lpColor = wRet;
+
+ return TRUE;
+}
+
+/* EOF */
--- /dev/null
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_TIME
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "cmd.h"
+
+
+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, FALSE);
+
+ /* 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
--- /dev/null
+/*
+ * TIMER.C - timer internal command.
+ *
+ * clone from 4nt timer command
+ *
+ * 20 Aug 1999
+ * started - Paolo Pantaleo <paolopan@freemail.it>
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_TIMER
+#include "cmd.h"
+
+#include <ctype.h>
+#include <string.h>
+#include <tchar.h>
+#include <windows.h>
+
+
+#define NCS_NOT_SPECIFIED -1
+#define NCS_ON 1
+#define NCS_OFF 0
+
+
+
+//print timer status
+#define PS ConOutPrintf("Timer %d is %s: ",clk_n,cS?"ON":"OFF"); \
+ PrintTime()
+
+//print timer value
+#define PT(format) PrintElapsedTime(GetTickCount()-cT,format)
+
+
+//current timer Time (at wich started to count)
+#define cT clksT[clk_n]
+
+//current timer status
+#define cS clksS[clk_n]
+
+
+static VOID
+PrintElapsedTime (DWORD time,INT format)
+{
+
+ DWORD h,m,s,ms;
+
+#ifdef _DEBUG
+ DebugPrintf("PrintTime(%d,%d)",time,format);
+#endif
+
+ switch (format)
+ {
+ case 0:
+ ConOutPrintf("Elapsed %d msecs\n",time);
+ break;
+
+ case 1:
+ ms = time % 1000;
+ time /= 1000;
+ s = time % 60;
+ time /=60;
+ m = time % 60;
+ h = time / 60;
+ ConOutPrintf("Elapsed %02d%c%02d%c%02d%c%02d\n",
+ h,cTimeSeparator,
+ m,cTimeSeparator,
+ s,cDecimalSeparator,ms/10);
+ break;
+ }
+}
+
+
+INT CommandTimer (LPTSTR cmd, LPTSTR param)
+{
+ // all timers are kept
+ static DWORD clksT[10];
+
+ // timers status
+ // set all the clocks off by default
+ static BOOL clksS[10]={FALSE,FALSE,FALSE,FALSE,
+ FALSE,FALSE,FALSE,FALSE,FALSE,FALSE};
+
+ // TRUE if /S in command line
+ BOOL bS = FALSE;
+
+ // avoid to set clk_n more than once
+ BOOL bCanNSet = TRUE;
+
+ INT NewClkStatus = NCS_NOT_SPECIFIED;
+
+ // the clock number specified on the command line
+ // 1 by default
+ INT clk_n=1;
+
+ // output format
+ INT iFormat=1;
+
+
+ // command line parsing variables
+ INT argc;
+ LPTSTR *p;
+
+ INT i;
+
+ if (_tcsncmp (param, _T("/?"), 2) == 0)
+ {
+ ConOutPrintf(_T(
+ "allow the use of ten stopwaches.\n"
+ "\n"
+ "TIMER [ON|OFF] [/S] [/n] [/Fn]\n"
+ "\n"
+ " ON set stopwach ON\n"
+ " OFF set stopwach OFF\n"
+ " /S Split time. Return stopwach split\n"
+ " time without changing its value\n"
+ " /n Specifiy the stopwach number.\n"
+ " Stopwaches avaliable are 0 to 10\n"
+ " If it is not specified default is 1\n"
+ " /Fn Format for output\n"
+ " n can be:\n"
+ " 0 milliseconds\n"
+ " 1 hh%cmm%css%cdd\n"
+ "\n"),
+ cTimeSeparator,cTimeSeparator,cDecimalSeparator);
+
+ ConOutPrintf(_T(
+ "if none of ON, OFF or /S is specified the command\n"
+ "will toggle stopwach state\n"
+ "\n"));
+ return 0;
+ }
+
+
+ p = split (param, &argc, FALSE);
+
+ //read options
+ for (i = 0; i < argc; i++)
+ {
+ //set timer on
+ if (!(_tcsicmp(&p[i][0],"on")) && NewClkStatus == NCS_NOT_SPECIFIED)
+ {
+ NewClkStatus = NCS_ON;
+ continue;
+ }
+
+ //set timer off
+ if (!(_tcsicmp(&p[i][0],"off")) && NewClkStatus == NCS_NOT_SPECIFIED)
+ {
+ NewClkStatus = NCS_OFF;
+ continue;
+ }
+
+ // other options
+ if (p[i][0] == _T('/'))
+ {
+
+ // set timer number
+ if (_istdigit(p[i][1]) && bCanNSet)
+ {
+ clk_n = p[i][1] - _T('0');
+ bCanNSet = FALSE;
+ continue;
+ }
+
+ // set s(plit) option
+ if (_totupper(p[i][1]) == _T('S'))
+ {
+ bS = TRUE;
+ continue;
+ }
+
+ // specify format
+ if(_totupper(p[i][1]) == _T('F'))
+ {
+ iFormat = p[i][2] - _T('0');
+ continue;
+ }
+ }
+ }
+
+ // do stuff (start/stop/read timer)
+ if(NewClkStatus == NCS_ON)
+ {
+ cT=GetTickCount();
+ cS=TRUE;
+ PS;
+ freep(p);
+ return 0;
+ }
+
+ if(bS)
+ {
+ if(cS)
+ {
+ PS;
+ PrintElapsedTime(GetTickCount()-cT, iFormat);
+ freep(p);
+ return 0;
+ }
+
+ cT=GetTickCount();
+ cS=TRUE;
+ PS;
+ freep(p);
+ return 0;
+ }
+
+ if(NewClkStatus == NCS_NOT_SPECIFIED)
+ {
+ if(cS){
+ cS=FALSE;
+ PS;
+ PrintElapsedTime(GetTickCount()-cT, iFormat);
+ freep(p);
+ return 0;
+ }
+
+ cT=GetTickCount();
+ cS=TRUE;
+ PS;
+ freep(p);
+ return 0;
+ }
+
+
+ if(NewClkStatus == NCS_OFF)
+ {
+ if(cS)
+ {
+ cS=FALSE;
+ PS;
+ PrintElapsedTime(GetTickCount()-cT, iFormat);
+ freep(p);
+ return 0;
+ }
+ PS;
+ freep(p);
+ return 0;
+ }
+
+ freep(p);
+ return 0;
+}
+
+#endif /* INCLUDE_CMD_TIMER */
--- /dev/null
+/*
+ * title.c - title internal command.
+ *
+ *
+ * History:
+ * 1999-02-11 Emanuele Aliberti
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_TITLE
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+
+INT cmd_title (LPTSTR cmd, LPTSTR param)
+{
+ /* Do nothing if no args */
+ if (*param == _T('\0'))
+ return 0;
+
+ /* Asking help? */
+ if (!_tcsncmp(param, _T("/?"), 2))
+ {
+ ConOutPuts (_T("Sets the window title for the command prompt window.\n"
+ "\n"
+ "TITLE [string]\n"
+ "\n"
+ " string Specifies the title for the command prompt window."));
+ return 0;
+ }
+
+ return SetConsoleTitle (param);
+}
+
+#endif /* def INCLUDE_CMD_TITLE */
+
+/* EOF */
--- /dev/null
+Things to do
+~~~~~~~~~~~~
+Fix bugs :)
+
+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.
+
+Add wildcard support to REN.
+
+And many, many more...
--- /dev/null
+/*
+ * 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!
+ *
+ * 19-Jan-1999 (Paolo Pantaleo <paolopan@freemail.it>)
+ * Added multiple file support (copied from y.c)
+ */
+
+#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 buff[256];
+ HANDLE hFile, hConsoleOut;
+ DWORD dwRead;
+ DWORD dwWritten;
+ BOOL bRet;
+ INT argc,i;
+ LPTSTR *argv;
+ LPTSTR errmsg;
+
+ hConsoleOut=GetStdHandle (STD_OUTPUT_HANDLE);
+
+ 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;
+ }
+
+ argv = split (param, &argc, TRUE);
+
+ for (i = 0; i < argc; i++)
+ {
+ if (_T('/') == argv[i][0])
+ {
+ ConErrPrintf("Invalid option \"%s\"\n", argv[i] + 1);
+ continue;
+ }
+ hFile = CreateFile(argv[i],
+ GENERIC_READ,
+ FILE_SHARE_READ,NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,NULL);
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &errmsg,
+ 0,
+ NULL);
+ ConErrPrintf ("%s - %s", argv[i], errmsg);
+ LocalFree (errmsg);
+ continue;
+ }
+
+ do
+ {
+ bRet = ReadFile(hFile,buff,sizeof(buff),&dwRead,NULL);
+
+ if (dwRead>0 && bRet)
+ WriteFile(hConsoleOut,buff,dwRead,&dwWritten,NULL);
+
+ } while(dwRead>0 && bRet);
+
+ CloseHandle(hFile);
+ }
+
+ freep (argv);
+
+ return 0;
+}
+
+#endif
--- /dev/null
+/*
+ * 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!
+ *
+ * 26-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ * New version info and some output changes.
+ */
+
+#include "config.h"
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "cmd.h"
+
+
+
+VOID ShortVersion (VOID)
+{
+ ConOutPuts (_T("\n"
+ SHELLINFO "\n"
+ SHELLVER "\n"));
+}
+
+
+#ifdef INCLUDE_CMD_VER
+
+/*
+ * display shell version info internal command.
+ *
+ *
+ */
+INT cmd_ver (LPTSTR cmd, LPTSTR param)
+{
+ INT i;
+
+ if (_tcsstr (param, _T("/?")) != NULL)
+ {
+ ConOutPuts (_T("Displays shell version information\n"
+ "\n"
+ "VER [/C][/R][/W]\n"
+ "\n"
+ " /C Displays credits.\n"
+ " /R Displays redistribution information.\n"
+ " /W Displays warranty information."));
+ return 0;
+ }
+
+ ConOutPuts (_T("\n"
+ SHELLINFO "\n"
+ SHELLVER "\n"
+ "\n"
+ "Copyright (C) 1994-1998 Tim Norman and others."));
+ ConOutPuts (_T("Copyright (C) 1998-2001 Eric Kohl and others."));
+
+ /* 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
+ {
+ 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 */
+ 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 */
+ 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 */
+ ConOutPuts (_T("\n"
+ "FreeDOS version written 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"
+ "\n"
+ "ReactOS version written by:\n"
+ " Eric Kohl Emanuele Aliberti\n"
+ " Paolo Pantaleo Phillip Susi\n"));
+ }
+ else
+ {
+ error_invalid_switch ((TCHAR)_totupper (param[i]));
+ return 1;
+ }
+ }
+ }
+
+ ConOutPuts (_T("\n"
+ "Send bug reports to <ekohl@rz-online.de>.\n"
+ "Updates are available at: http://www.reactos.com"));
+ return 0;
+}
+
+#endif
--- /dev/null
+/*
+ * 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!
+ */
+
+#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
--- /dev/null
+/*
+ * 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!
+ */
+
+#include "config.h"
+
+#ifdef INCLUDE_CMD_VOL
+
+#include <windows.h>
+#include <tchar.h>
+#include <string.h>
+
+#include "cmd.h"
+
+
+static INT
+PrintVolumeHeader (LPTSTR pszRootPath)
+{
+ TCHAR szVolName[80];
+ DWORD dwSerialNr;
+
+ /* get the volume information of the drive */
+ if(!GetVolumeInformation (pszRootPath,
+ szVolName,
+ 80,
+ &dwSerialNr,
+ NULL,
+ NULL,
+ NULL,
+ 0))
+ {
+ ErrorMessage (GetLastError (), _T(""));
+ return 1;
+ }
+
+ /* 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));
+ return 0;
+}
+
+
+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 */
+ if (!PrintVolumeHeader (szRootPath))
+ return 1;
+
+ return 0;
+}
+
+#endif
--- /dev/null
+/*
+ * WHERE.C - file search 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.
+ *
+ * 26-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ * Replaced find_which() by SearchForExecutable().
+ * Now files are searched using the right extension order.
+ *
+ * 20-Apr-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
+ * Some minor changes and improvements.
+ */
+
+#include "config.h"
+
+#include <windows.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cmd.h"
+
+
+/* initial size of environment variable buffer */
+#define ENV_BUFFER_SIZE 1024
+
+
+static LPTSTR ext[] = {".bat", ".cmd", ".com", ".exe"};
+static INT nExtCount = sizeof(ext) / sizeof(LPTSTR);
+
+
+/* searches for file using path info. */
+
+BOOL
+SearchForExecutable (LPCTSTR pFileName, LPTSTR pFullName)
+{
+ TCHAR szPathBuffer[MAX_PATH];
+ LPTSTR pszBuffer = NULL;
+ DWORD dwBuffer, len;
+ INT n;
+ LPTSTR p,s,f;
+
+
+ /* initialize full name buffer */
+ *pFullName = _T('\0');
+
+#ifdef _DEBUG
+ DebugPrintf (_T("SearchForExecutable: \'%s\'\n"), pFileName);
+#endif
+
+ if (_tcschr (pFileName, _T('\\')) != NULL)
+ {
+ LPTSTR pFilePart;
+#ifdef _DEBUG
+ DebugPrintf (_T("Absolute or relative path is given.\n"));
+#endif
+
+ if (GetFullPathName (pFileName,
+ MAX_PATH,
+ szPathBuffer,
+ &pFilePart) ==0)
+ return FALSE;
+
+ if(pFilePart == 0)
+ return FALSE;
+
+
+ if (_tcschr (pFilePart, _T('.')) != NULL)
+ {
+#ifdef _DEBUG
+ DebugPrintf (_T("Filename extension!\n"));
+#endif
+ _tcscpy (pFullName, szPathBuffer);
+ return TRUE;
+
+ }
+ else
+ {
+#ifdef _DEBUG
+ DebugPrintf (_T("No filename extension!\n"));
+#endif
+
+ p = szPathBuffer + _tcslen (szPathBuffer);
+
+ for (n = 0; n < nExtCount; n++)
+ {
+ _tcscpy (p, ext[n]);
+
+#ifdef _DEBUG
+ DebugPrintf (_T("Testing: \'%s\'\n"), szPathBuffer);
+#endif
+
+ if (IsValidFileName (szPathBuffer))
+ {
+#ifdef _DEBUG
+ DebugPrintf (_T("Found: \'%s\'\n"), szPathBuffer);
+#endif
+ _tcscpy (pFullName, szPathBuffer);
+ return TRUE;
+ }
+ }
+ return FALSE;
+ }
+ }
+
+ /* load environment varable PATH into buffer */
+ pszBuffer = (LPTSTR)malloc (ENV_BUFFER_SIZE * sizeof(TCHAR));
+ dwBuffer = GetEnvironmentVariable (_T("PATH"), pszBuffer, ENV_BUFFER_SIZE);
+ if (dwBuffer > ENV_BUFFER_SIZE)
+ {
+ pszBuffer = (LPTSTR)realloc (pszBuffer, dwBuffer * sizeof (TCHAR));
+ GetEnvironmentVariable (_T("PATH"), pszBuffer, dwBuffer * sizeof (TCHAR));
+ }
+
+ if (!(p = _tcsrchr (pFileName, _T('.'))) ||
+ _tcschr (p + 1, _T('\\')))
+ {
+ /* There is no extension ==> test all the extensions. */
+#ifdef _DEBUG
+ DebugPrintf (_T("No filename extension!\n"));
+#endif
+
+ /* search in current directory */
+ len = GetCurrentDirectory (MAX_PATH, szPathBuffer);
+ if (szPathBuffer[len - 1] != _T('\\'))
+ {
+ szPathBuffer[len] = _T('\\');
+ szPathBuffer[len + 1] = _T('\0');
+ }
+ _tcscat (szPathBuffer, pFileName);
+
+ p = szPathBuffer + _tcslen (szPathBuffer);
+
+ for (n = 0; n < nExtCount; n++)
+ {
+ _tcscpy (p, ext[n]);
+
+#ifdef _DEBUG
+ DebugPrintf (_T("Testing: \'%s\'\n"), szPathBuffer);
+#endif
+
+ if (IsValidFileName (szPathBuffer))
+ {
+#ifdef _DEBUG
+ DebugPrintf (_T("Found: \'%s\'\n"), szPathBuffer);
+#endif
+ free (pszBuffer);
+ _tcscpy (pFullName, szPathBuffer);
+ return TRUE;
+ }
+ }
+
+ /* search in PATH */
+ s = pszBuffer;
+ while (s && *s)
+ {
+ f = _tcschr (s, _T(';'));
+
+ if (f)
+ {
+ _tcsncpy (szPathBuffer, s, (size_t)(f-s));
+ szPathBuffer[f-s] = _T('\0');
+ s = f + 1;
+ }
+ else
+ {
+ _tcscpy (szPathBuffer, s);
+ s = NULL;
+ }
+
+ len = _tcslen(szPathBuffer);
+ if (szPathBuffer[len - 1] != _T('\\'))
+ {
+ szPathBuffer[len] = _T('\\');
+ szPathBuffer[len + 1] = _T('\0');
+ }
+ _tcscat (szPathBuffer, pFileName);
+
+ p = szPathBuffer + _tcslen (szPathBuffer);
+
+ for (n = 0; n < nExtCount; n++)
+ {
+ _tcscpy (p, ext[n]);
+
+#ifdef _DEBUG
+ DebugPrintf (_T("Testing: \'%s\'\n"), szPathBuffer);
+#endif
+
+ if (IsValidFileName (szPathBuffer))
+ {
+#ifdef _DEBUG
+ DebugPrintf (_T("Found: \'%s\'\n"), szPathBuffer);
+#endif
+ free (pszBuffer);
+ _tcscpy (pFullName, szPathBuffer);
+ return TRUE;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* There is an extension and it is in the last path component, */
+ /* so don't test all the extensions. */
+#ifdef _DEBUG
+ DebugPrintf (_T("Filename extension!\n"));
+#endif
+
+ /* search in current directory */
+ len = GetCurrentDirectory (MAX_PATH, szPathBuffer);
+ if (szPathBuffer[len - 1] != _T('\\'))
+ {
+ szPathBuffer[len] = _T('\\');
+ szPathBuffer[len + 1] = _T('\0');
+ }
+ _tcscat (szPathBuffer, pFileName);
+
+#ifdef _DEBUG
+ DebugPrintf (_T("Testing: \'%s\'\n"), szPathBuffer);
+#endif
+ if (IsValidFileName (szPathBuffer))
+ {
+#ifdef _DEBUG
+ DebugPrintf (_T("Found: \'%s\'\n"), szPathBuffer);
+#endif
+ free (pszBuffer);
+ _tcscpy (pFullName, szPathBuffer);
+ return TRUE;
+ }
+
+
+ /* search in PATH */
+ s = pszBuffer;
+ while (s && *s)
+ {
+ f = _tcschr (s, _T(';'));
+
+ if (f)
+ {
+ _tcsncpy (szPathBuffer, s, (size_t)(f-s));
+ szPathBuffer[f-s] = _T('\0');
+ s = f + 1;
+ }
+ else
+ {
+ _tcscpy (szPathBuffer, s);
+ s = NULL;
+ }
+
+ len = _tcslen(szPathBuffer);
+ if (szPathBuffer[len - 1] != _T('\\'))
+ {
+ szPathBuffer[len] = _T('\\');
+ szPathBuffer[len + 1] = _T('\0');
+ }
+ _tcscat (szPathBuffer, pFileName);
+
+#ifdef _DEBUG
+ DebugPrintf (_T("Testing: \'%s\'\n"), szPathBuffer);
+#endif
+ if (IsValidFileName (szPathBuffer))
+ {
+#ifdef _DEBUG
+ DebugPrintf (_T("Found: \'%s\'\n"), szPathBuffer);
+#endif
+ free (pszBuffer);
+ _tcscpy (pFullName, szPathBuffer);
+ return TRUE;
+ }
+ }
+ }
+
+ free (pszBuffer);
+
+ return FALSE;
+}
--- /dev/null
+/* $Id: window.c,v 1.1 2003/03/20 19:19:23 rcampbell Exp $
+ *
+ * WINDOW.C - activate & window internal commands.
+ *
+ * clone from 4nt activate command
+ *
+ * 10 Sep 1999 (Paolo Pantaleo)
+ * started (window command in WINDOW.c)
+ *
+ * 29 Sep 1999 (Paolo Pantaleo)
+ * activate and window in a single file using mainly the same code
+ * (nice size optimization :)
+ */
+
+
+#include "config.h"
+
+#if ( defined(INCLUDE_CMD_WINDOW) || defined(INCLUDE_CMD_ACTIVATE) )
+
+#include "cmd.h"
+#include <windows.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tchar.h>
+
+
+#define A_MIN 0x01
+#define A_MAX 0x02
+#define A_RESTORE 0x04
+#define A_POS 0x08
+#define A_SIZE 0x10
+#define A_CLOSE 0x20
+
+
+/*service funciton to perform actions on windows
+
+ param is a string to parse for options/actions
+ hWnd is the handle of window on wich perform actions
+
+*/
+
+static
+INT ServiceActivate (LPTSTR param, HWND hWnd)
+{
+ LPTSTR *p=0,p_tmp;
+ INT argc=0,i;
+ INT iAction=0;
+ LPTSTR title=0;
+ WINDOWPLACEMENT wp;
+ RECT pos;
+ LPTSTR tmp;
+
+
+ if(*param)
+ p=split(param,&argc);
+
+
+ for(i = 0; i < argc; i++)
+ {
+ p_tmp=p[i];
+ if (*p_tmp == _T('/'))
+ p_tmp++;
+
+ if (_tcsicmp(p_tmp,_T("min"))==0)
+ {
+ iAction |= A_MIN;
+ continue;
+ }
+
+ if (_tcsicmp(p_tmp,_T("max"))==0)
+ {
+ iAction |= A_MAX;
+ continue;
+ }
+
+ if (_tcsicmp(p_tmp,_T("restore"))==0)
+ {
+ iAction |= A_RESTORE;
+ continue;
+ }
+
+ if (_tcsicmp(p_tmp,_T("close"))==0)
+ {
+ iAction |= A_CLOSE;
+ continue;
+ }
+
+ if (_tcsnicmp(p_tmp,_T("pos"),3)==0)
+ {
+ iAction |= A_POS;
+ tmp = p_tmp+3;
+ if (*tmp == _T('='))
+ tmp++;
+
+ pos.left= _ttoi(tmp);
+ if(!(tmp=_tcschr(tmp,_T(','))))
+ {
+ error_invalid_parameter_format(p[i]);
+ freep(p);
+ return 1;
+ }
+
+ pos.top = _ttoi (++tmp);
+ if(!(tmp=_tcschr(tmp,_T(','))))
+ {
+ error_invalid_parameter_format(p[i]);
+ freep(p);
+ return 1;
+ }
+
+ pos.right = _ttoi(++tmp)+pos.left;
+ if(!(tmp=_tcschr(tmp,_T(','))))
+ {
+ error_invalid_parameter_format(p[i]);
+ freep(p);
+ return 1;
+ }
+ pos.bottom = _ttoi(++tmp) + pos.top;
+ continue;
+ }
+
+ if (_tcsnicmp(p_tmp,_T("size"),4)==0)
+ {
+ iAction |=A_SIZE;
+ continue;
+ }
+
+ /*none of them=window title*/
+ if (title)
+ {
+ error_invalid_parameter_format(p[i]);
+ freep(p);
+ return 1;
+ }
+
+ if (p_tmp[0] == _T('"'))
+ {
+ title = (p_tmp+1);
+ *_tcschr(p_tmp+1,_T('"'))=0;
+ continue;
+ }
+ title = p_tmp;
+ }
+
+ if(title)
+ SetWindowText(hWnd,title);
+
+ wp.length=sizeof(WINDOWPLACEMENT);
+ GetWindowPlacement(hWnd,&wp);
+
+ if(iAction & A_POS)
+ wp.rcNormalPosition = pos;
+
+ if(iAction & A_MIN)
+ wp.showCmd=SW_MINIMIZE;
+
+ if(iAction & A_MAX)
+ wp.showCmd=SW_SHOWMAXIMIZED;
+
+ /*if no actions are specified default is SW_RESTORE*/
+ if( (iAction & A_RESTORE) || (!iAction) )
+ wp.showCmd=SW_RESTORE;
+
+ if(iAction & A_CLOSE)
+ ConErrPrintf(_T("!!!FIXME: CLOSE Not implemented!!!\n"));
+
+ wp.length=sizeof(WINDOWPLACEMENT);
+ SetWindowPlacement(hWnd,&wp);
+
+ if(p)
+ freep(p);
+
+ return 0;
+}
+
+
+
+
+INT CommandWindow (LPTSTR cmd, LPTSTR param)
+{
+ HWND h;
+
+ if (_tcsncmp (param, _T("/?"), 2) == 0)
+ {
+ ConOutPuts(_T("change console window aspect\n"
+ "\n"
+ "WINDOW [/POS[=]left,top,width,heigth]\n"
+ " [MIN|MAX|RESTORE] [\"title\"]\n"
+ "\n"
+ "/POS specify window placement and dimensions\n"
+ "MIN minimize the window\n"
+ "MAX maximize the window\n"
+ "RESTORE restore the window"));
+ return 0;
+ }
+
+ h = GetConsoleWindow();
+ Sleep(0);
+ return ServiceActivate(param,h);
+}
+
+
+INT CommandActivate (LPTSTR cmd, LPTSTR param)
+{
+ LPTSTR str;
+ HWND h;
+
+ if (_tcsncmp (param, _T("/?"), 2) == 0)
+ {
+ ConOutPuts(_T("change console window aspect\n"
+ "\n"
+ "ACTIAVTE \"window\" [/POS[=]left,top,width,heigth]\n"
+ " [MIN|MAX|RESTORE] [\"title\"]\n"
+ "\n"
+ "window tile of window on wich perform actions\n"
+ "/POS specify window placement and dimensions\n"
+ "MIN minimize the window\n"
+ "MAX maximize the window\n"
+ "RESTORE restore the window\n"
+ "title new title"));
+ return 0;
+ }
+
+ if(!(*param))
+ return 1;
+
+ str=_tcschr(param,_T(' '));
+
+ if (str)
+ {
+ *str=_T('\0');
+ str++;
+ }
+ else
+ str = "";
+
+ h=FindWindow(NULL, param);
+ if (!h)
+ {
+ ConErrPuts("window not found");
+ return 1;
+ }
+
+ return ServiceActivate(str,h);
+}
+
+#endif /* ( defined(INCLUDE_CMD_WINDOW) || defined(INCLUDE_CMD_ACTIVATE) ) */
--- /dev/null
+
+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 subdirectory "test directory".
+
+More ideas?
+
+ Eric Kohl <ekohl@rz-online.de>