Author: jmorlan Date: Thu Mar 12 07:37:01 2009 New Revision: 39973
URL: http://svn.reactos.org/svn/reactos?rev=39973&view=rev Log: Instead of having DOSKEY print something when it successfully adds an alias, print an error message when it fails. Also implement some options that were missing.
Added: trunk/reactos/base/applications/cmdutils/doskey/doskey.h (with props) trunk/reactos/base/applications/cmdutils/doskey/lang/ trunk/reactos/base/applications/cmdutils/doskey/lang/en-US.rc (with props) Modified: trunk/reactos/base/applications/cmdutils/doskey/doskey.c trunk/reactos/base/applications/cmdutils/doskey/doskey.rbuild trunk/reactos/base/applications/cmdutils/doskey/doskey.rc
Modified: trunk/reactos/base/applications/cmdutils/doskey/doskey.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/doskey/doskey.c [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/doskey/doskey.c [iso-8859-1] Thu Mar 12 07:37:01 2009 @@ -1,71 +1,95 @@ #include <windows.h> #include <stdio.h> #include <tchar.h> - -static VOID -PrintAlias (VOID) -{ - LPTSTR Aliases; - LPTSTR ptr; - DWORD len; - - len = GetConsoleAliasesLength(_T("cmd.exe")); - if (len <= 0) - return; - - /* allocate memory for an extra \0 char to make parsing easier */ - ptr = HeapAlloc(GetProcessHeap(), 0, (len + sizeof(TCHAR))); - if (!ptr) - return; - - Aliases = ptr; - - ZeroMemory(Aliases, len + sizeof(TCHAR)); - - if (GetConsoleAliases(Aliases, len, _T("cmd.exe")) != 0) - { - while (*Aliases != '\0') - { - _tprintf(_T("%s\n"), Aliases); - Aliases = Aliases + lstrlen(Aliases); - Aliases++; - } - } - HeapFree(GetProcessHeap(), 0 , ptr); -} - -INT SetMacro (LPTSTR param) -{ - LPTSTR ptr, text; - - while (*param == _T(' ')) - param++; +#include "doskey.h" + +#define MAX_STRING 2000 +TCHAR szStringBuf[MAX_STRING]; +LPTSTR pszExeName = _T("cmd.exe"); + +static VOID SetInsert(DWORD dwFlag) +{ + DWORD dwMode; + HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE); + GetConsoleMode(hConsole, &dwMode); + dwMode |= ENABLE_EXTENDED_FLAGS; + SetConsoleMode(hConsole, (dwMode & ~ENABLE_INSERT_MODE) | dwFlag); +} + +static VOID PrintHistory(VOID) +{ + DWORD Length = GetConsoleCommandHistoryLength(pszExeName); + /* On Windows, the ANSI version of GetConsoleCommandHistory requires + * a buffer twice as large as the actual history length. */ + BYTE HistBuf[Length * (sizeof(WCHAR) / sizeof(TCHAR))]; + TCHAR *Hist = (TCHAR *)HistBuf; + TCHAR *HistEnd = (TCHAR *)&HistBuf[Length]; + + if (GetConsoleCommandHistory(Hist, sizeof HistBuf, pszExeName)) + for (; Hist < HistEnd; Hist += _tcslen(Hist) + 1) + _tprintf(_T("%s\n"), Hist); +} + +static INT SetMacro(LPTSTR definition) +{ + TCHAR *name, *nameend, *text, temp; + + name = definition; + while (*name == _T(' ')) + name++;
/* error if no '=' found */ - if ((ptr = _tcschr (param, _T('='))) == 0) - return 1; - - text = ptr + 1; - while (*text == _T(' ')) - text++; - - while (ptr > param && ptr[-1] == _T(' ')) - ptr--; - - /* Split rest into name and substitute */ - *ptr++ = _T('\0'); - - if (*param == _T('\0') || _tcschr(param, _T(' '))) - return 1; - - _tprintf(_T("%s, %s\n"), text, param); - - if (ptr[0] == _T('\0')) - AddConsoleAlias(param, NULL, _T("cmd.exe")); - else - AddConsoleAlias(param, text, _T("cmd.exe")); - - return 0; + if ((nameend = _tcschr(name, _T('='))) != NULL) + { + text = nameend + 1; + while (*text == _T(' ')) + text++; + + while (nameend > name && nameend[-1] == _T(' ')) + nameend--; + + /* Split rest into name and substitute */ + temp = *nameend; + *nameend = _T('\0'); + /* Don't allow spaces in the name, since such a macro would be unusable */ + if (!_tcschr(name, _T(' ')) && AddConsoleAlias(name, text, pszExeName)) + return 0; + *nameend = temp; + } + + LoadString(GetModuleHandle(NULL), IDS_INVALID_MACRO_DEF, szStringBuf, MAX_STRING); + _tprintf(szStringBuf, definition); + return 1; +} + +static VOID PrintMacros(LPTSTR pszExeName, LPTSTR Indent) +{ + DWORD Length = GetConsoleAliasesLength(pszExeName); + BYTE AliasBuf[Length]; + TCHAR *Alias = (TCHAR *)AliasBuf; + TCHAR *AliasEnd = (TCHAR *)&AliasBuf[Length]; + + if (GetConsoleAliases(Alias, sizeof AliasBuf, pszExeName)) + for (; Alias < AliasEnd; Alias += _tcslen(Alias) + 1) + _tprintf(_T("%s%s\n"), Indent, Alias); +} + +static VOID PrintAllMacros(VOID) +{ + DWORD Length = GetConsoleAliasExesLength(); + BYTE ExeNameBuf[Length]; + TCHAR *ExeName = (TCHAR *)ExeNameBuf; + TCHAR *ExeNameEnd = (TCHAR *)&ExeNameBuf[Length]; + + if (GetConsoleAliasExes(ExeName, sizeof ExeNameBuf)) + { + for (; ExeName < ExeNameEnd; ExeName += _tcslen(ExeName) + 1) + { + _tprintf(_T("[%s]\n"), ExeName); + PrintMacros(ExeName, _T(" ")); + _tprintf(_T("\n")); + } + } }
static VOID ReadFromFile(LPTSTR param) @@ -73,10 +97,16 @@ FILE* fp; TCHAR line[MAX_PATH];
- /* Skip the "/macrofile=" prefix */ - param += 11; - fp = _tfopen(param, _T("r")); + if (!fp) + { +#ifdef UNICODE + _wperror(param); +#else + perror(param); +#endif + return; + }
while ( _fgetts(line, MAX_PATH, fp) != NULL) { @@ -85,53 +115,122 @@ if (*end == _T('\n')) *end = _T('\0');
- SetMacro(line); + if (*line) + SetMacro(line); }
fclose(fp); return; }
+/* Get the start and end of the next command-line argument. */ +static BOOL GetArg(TCHAR **pStart, TCHAR **pEnd) +{ + BOOL bInQuotes = FALSE; + TCHAR *p = *pEnd; + p += _tcsspn(p, _T(" \t")); + if (!*p) + return FALSE; + *pStart = p; + do + { + if (!bInQuotes && (*p == _T(' ') || *p == _T('\t'))) + break; + bInQuotes ^= (*p++ == _T('"')); + } while (*p); + *pEnd = p; + return TRUE; +} + +/* Remove starting and ending quotes from a string, if present */ +static LPTSTR RemoveQuotes(LPTSTR str) +{ + TCHAR *end; + if (*str == _T('"') && *(end = str + _tcslen(str) - 1) == _T('"')) + { + str++; + *end = _T('\0'); + } + return str; +} + int -_tmain (int argc, LPTSTR argv[]) -{ - if (argc < 2) - return 0; - - if (argv[1][0] == '/') - { - if (_tcsnicmp(argv[1], _T("/macrofile"), 10) == 0) - ReadFromFile(argv[1]); - if (_tcscmp(argv[1], _T("/macros")) == 0) - PrintAlias(); - } - else - { - /* Get the full command line using GetCommandLine(). - We can't just pass argv[1] here, because then a parameter like "gotoroot=cd " wouldn't be passed completely. */ - TCHAR* szCommandLine = GetCommandLine(); - - /* Skip the application name */ - if(*szCommandLine == '"') - { - do - { - szCommandLine++; - } - while(*szCommandLine != '"'); - szCommandLine++; +_tmain(VOID) +{ + /* Get the full command line using GetCommandLine(). We can't just use argv, + * because then a parameter like "gotoroot=cd " wouldn't be passed completely. */ + TCHAR *pArgStart; + TCHAR *pArgEnd = GetCommandLine(); + + /* Skip the application name */ + GetArg(&pArgStart, &pArgEnd); + + while (GetArg(&pArgStart, &pArgEnd)) + { + /* NUL-terminate this argument to make processing easier */ + TCHAR tmp = *pArgEnd; + *pArgEnd = _T('\0'); + + if (!_tcscmp(pArgStart, _T("/?"))) + { + LoadString(GetModuleHandle(NULL), IDS_HELP, szStringBuf, MAX_STRING); + _tprintf(szStringBuf); + break; + } + else if (!_tcsnicmp(pArgStart, _T("/EXENAME="), 9)) + { + pszExeName = RemoveQuotes(pArgStart + 9); + } + else if (!_tcsicmp(pArgStart, _T("/H")) || + !_tcsicmp(pArgStart, _T("/HISTORY"))) + { + PrintHistory(); + } + else if (!_tcsnicmp(pArgStart, _T("/LISTSIZE="), 10)) + { + SetConsoleNumberOfCommands(_ttoi(pArgStart + 10), pszExeName); + } + else if (!_tcsicmp(pArgStart, _T("/REINSTALL"))) + { + ExpungeConsoleCommandHistory(pszExeName); + } + else if (!_tcsicmp(pArgStart, _T("/INSERT"))) + { + SetInsert(ENABLE_INSERT_MODE); + } + else if (!_tcsicmp(pArgStart, _T("/OVERSTRIKE"))) + { + SetInsert(0); + } + else if (!_tcsicmp(pArgStart, _T("/M")) || + !_tcsicmp(pArgStart, _T("/MACROS"))) + { + PrintMacros(pszExeName, _T("")); + } + else if (!_tcsnicmp(pArgStart, _T("/M:"), 3) || + !_tcsnicmp(pArgStart, _T("/MACROS:"), 8)) + { + LPTSTR exe = RemoveQuotes(_tcschr(pArgStart, _T(':')) + 1); + if (!_tcsicmp(exe, _T("ALL"))) + PrintAllMacros(); + else + PrintMacros(exe, _T("")); + } + else if (!_tcsnicmp(pArgStart, _T("/MACROFILE="), 11)) + { + ReadFromFile(RemoveQuotes(pArgStart + 11)); } else { - do - { - szCommandLine++; - } - while(*szCommandLine != ' '); - } - - /* Skip the leading whitespace and pass the command line to SetMacro */ - SetMacro(szCommandLine + _tcsspn(szCommandLine, _T(" \t"))); + /* This is the beginning of a macro definition. It includes + * the entire remainder of the line, so first put back the + * character that we replaced with NUL. */ + *pArgEnd = tmp; + return SetMacro(pArgStart); + } + + if (!tmp) break; + pArgEnd++; }
return 0;
Added: trunk/reactos/base/applications/cmdutils/doskey/doskey.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/doskey/doskey.h (added) +++ trunk/reactos/base/applications/cmdutils/doskey/doskey.h [iso-8859-1] Thu Mar 12 07:37:01 2009 @@ -1,0 +1,67 @@ +#define IDS_HELP 0 +#define IDS_INVALID_MACRO_DEF 1 + +#ifndef RC_INVOKED + +#ifdef UNICODE +#define TNAME(x) x##W +#else +#define TNAME(x) x##A +#endif + +/* Missing from include/psdk/wincon.h */ +#ifndef ENABLE_INSERT_MODE +#define ENABLE_INSERT_MODE 0x20 +#endif +#ifndef ENABLE_EXTENDED_FLAGS +#define ENABLE_EXTENDED_FLAGS 0x80 +#endif + +/* Undocumented APIs */ +#ifndef AddConsoleAlias +BOOL WINAPI AddConsoleAliasA(LPSTR, LPSTR, LPSTR); +BOOL WINAPI AddConsoleAliasW(LPWSTR, LPWSTR, LPWSTR); +#define AddConsoleAlias TNAME(AddConsoleAlias) +#endif +#ifndef ExpungeConsoleCommandHistory +BOOL WINAPI ExpungeConsoleCommandHistoryA(LPSTR); +BOOL WINAPI ExpungeConsoleCommandHistoryW(LPWSTR); +#define ExpungeConsoleCommandHistory TNAME(ExpungeConsoleCommandHistory) +#endif +#ifndef GetConsoleAliases +DWORD WINAPI GetConsoleAliasesA(LPSTR, DWORD, LPSTR); +DWORD WINAPI GetConsoleAliasesW(LPWSTR, DWORD, LPWSTR); +#define GetConsoleAliases TNAME(GetConsoleAliases) +#endif +#ifndef GetConsoleAliasesLength +DWORD WINAPI GetConsoleAliasesLengthA(LPSTR); +DWORD WINAPI GetConsoleAliasesLengthW(LPWSTR); +#define GetConsoleAliasesLength TNAME(GetConsoleAliasesLength) +#endif +#ifndef GetConsoleAliasExes +DWORD WINAPI GetConsoleAliasExesA(LPSTR, DWORD); +DWORD WINAPI GetConsoleAliasExesW(LPWSTR, DWORD); +#define GetConsoleAliasExes TNAME(GetConsoleAliasExes) +#endif +#ifndef GetConsoleAliasExesLength +DWORD WINAPI GetConsoleAliasExesLengthA(VOID); +DWORD WINAPI GetConsoleAliasExesLengthW(VOID); +#define GetConsoleAliasExesLength TNAME(GetConsoleAliasExesLength) +#endif +#ifndef GetConsoleCommandHistory +DWORD WINAPI GetConsoleCommandHistoryA(LPSTR, DWORD, LPSTR); +DWORD WINAPI GetConsoleCommandHistoryW(LPWSTR, DWORD, LPWSTR); +#define GetConsoleCommandHistory TNAME(GetConsoleCommandHistory) +#endif +#ifndef GetConsoleCommandHistoryLength +DWORD WINAPI GetConsoleCommandHistoryLengthA(LPSTR); +DWORD WINAPI GetConsoleCommandHistoryLengthW(LPWSTR); +#define GetConsoleCommandHistoryLength TNAME(GetConsoleCommandHistoryLength) +#endif +#ifndef SetConsoleNumberOfCommands +BOOL WINAPI SetConsoleNumberOfCommandsA(DWORD, LPSTR); +BOOL WINAPI SetConsoleNumberOfCommandsW(DWORD, LPWSTR); +#define SetConsoleNumberOfCommands TNAME(SetConsoleNumberOfCommands) +#endif + +#endif /* RC_INVOKED */
Propchange: trunk/reactos/base/applications/cmdutils/doskey/doskey.h ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/base/applications/cmdutils/doskey/doskey.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/doskey/doskey.rbuild [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/doskey/doskey.rbuild [iso-8859-1] Thu Mar 12 07:37:01 2009 @@ -2,6 +2,7 @@ <!DOCTYPE module SYSTEM "../../../../tools/rbuild/project.dtd"> <module name="doskey" type="win32cui" installbase="system32" installname="doskey.exe" unicode="yes"> <library>kernel32</library> + <library>user32</library> <file>doskey.c</file> <file>doskey.rc</file> </module>
Modified: trunk/reactos/base/applications/cmdutils/doskey/doskey.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/doskey/doskey.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/cmdutils/doskey/doskey.rc [iso-8859-1] Thu Mar 12 07:37:01 2009 @@ -1,7 +1,8 @@ -/* $Id: find.rc 28350 2007-08-15 14:46:36Z fireball $ */ - #define REACTOS_STR_FILE_DESCRIPTION "W32 doskey command\0" #define REACTOS_STR_INTERNAL_NAME "doskey\0" #define REACTOS_STR_ORIGINAL_FILENAME "doskey.exe\0" #include <reactos/version.rc>
+#include <windows.h> +#include "doskey.h" +#include "lang/en-US.rc"
Added: trunk/reactos/base/applications/cmdutils/doskey/lang/en-US.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/cmdutils/... ============================================================================== --- trunk/reactos/base/applications/cmdutils/doskey/lang/en-US.rc (added) +++ trunk/reactos/base/applications/cmdutils/doskey/lang/en-US.rc [iso-8859-1] Thu Mar 12 07:37:01 2009 @@ -1,0 +1,27 @@ +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +STRINGTABLE DISCARDABLE +BEGIN + +IDS_HELP, "Manages command-line editing settings, history, and macros.\n\ +\n\ +DOSKEY [/INSERT | /OVERSTRIKE] [/EXENAME=exe] [/HISTORY] [/LISTSIZE=size]\n\ + [/REINSTALL] [/MACROS[:exe | :ALL]] [/MACROFILE=file] [macroname=[text]]\n\ +\n\ + /INSERT Enables insert mode.\n\ + /OVERSTRIKE Disables insert mode.\n\ + /EXENAME=exename Sets the name of the program to view/change history\n\ + and macros for. The default is cmd.exe.\n\ + /HISTORY Displays the command history.\n\ + /LISTSIZE=size Sets the number of commands per history buffer.\n\ + /REINSTALL Clears the command history.\n\ + /MACROS Displays macro definitions.\n\ + /MACROS:exename Displays macro definitions for a specific program.\n\ + /MACROS:ALL Displays macro definitions for all programs.\n\ + /MACROFILE=filename Loads macro definitions from a file.\n\ + macroname Specifies the name of a macro to create.\n\ + text Specifies the replacement text for the macro.\n" + +IDS_INVALID_MACRO_DEF, "Invalid macro definition: %s\n" + +END
Propchange: trunk/reactos/base/applications/cmdutils/doskey/lang/en-US.rc ------------------------------------------------------------------------------ svn:eol-style = native