[DOSKEY] Improvements when importing aliases definition files.

- The aliases ("macros") definition files have the same format as what
  is output by DosKey when one displays the list of defined aliases with
  the /macros: command-line switch. It should then, in particular,
  understand the format where executable names are also specified:

[exename1]
    alias1=command1
    ...

[exename2]
    aliasN=commandN
    ...

  We now behave similarly as Windows' version of this utility in that
  regard.

- Use ARRAYSIZE() when needed.
- Take the opportunity to add a license header to the source file.
This commit is contained in:
Hermès Bélusca-Maïto 2017-12-16 21:01:08 +01:00
parent eea43394bf
commit ae9702fcec
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
2 changed files with 89 additions and 28 deletions

View file

@ -1,3 +1,12 @@
/*
* PROJECT: ReactOS DosKey Command
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Provides history and command aliases management for
* command-line programs.
* COPYRIGHT: Copyright 2008 Christoph von Wittich
* Copyright 2013-2017 Hermès Bélusca-Maïto
*/
#include <stdio.h> #include <stdio.h>
#include <wchar.h> #include <wchar.h>
#include <locale.h> #include <locale.h>
@ -8,6 +17,8 @@
#include <wincon.h> #include <wincon.h>
/* Console API functions which are absent from wincon.h */ /* Console API functions which are absent from wincon.h */
#define EXENAME_LENGTH (255 + 1)
VOID VOID
WINAPI WINAPI
ExpungeConsoleCommandHistoryW(LPCWSTR lpExeName); ExpungeConsoleCommandHistoryW(LPCWSTR lpExeName);
@ -37,7 +48,7 @@ static VOID SetInsert(DWORD dwFlag)
{ {
/* /*
* NOTE: Enabling the ENABLE_INSERT_MODE mode can also be done by calling * NOTE: Enabling the ENABLE_INSERT_MODE mode can also be done by calling
* kernel32:SetConsoleCommandHistoryMode(CONSOLE_OVERSTRIKE) . * kernel32:SetConsoleCommandHistoryMode(CONSOLE_OVERSTRIKE) (deprecated).
*/ */
DWORD dwMode; DWORD dwMode;
HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE); HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE);
@ -98,7 +109,10 @@ static INT SetMacro(LPWSTR definition)
*nameend = temp; *nameend = temp;
} }
LoadStringW(GetModuleHandle(NULL), IDS_INVALID_MACRO_DEF, szStringBuf, MAX_STRING); LoadStringW(GetModuleHandle(NULL),
IDS_INVALID_MACRO_DEF,
szStringBuf,
ARRAYSIZE(szStringBuf));
wprintf(szStringBuf, definition); wprintf(szStringBuf, definition);
return 1; return 1;
} }
@ -155,29 +169,86 @@ static VOID PrintAllMacros(VOID)
HeapFree(GetProcessHeap(), 0, ExeNameBuf); HeapFree(GetProcessHeap(), 0, ExeNameBuf);
} }
static VOID ReadFromFile(LPWSTR param) /* Remove starting and ending quotes from a string, if present */
static LPWSTR RemoveQuotes(LPWSTR str)
{
WCHAR *end;
if (*str == L'"' && *(end = str + wcslen(str) - 1) == L'"')
{
str++;
*end = L'\0';
}
return str;
}
static VOID ReadFromFile(LPWSTR FileName)
{ {
FILE* fp; FILE* fp;
WCHAR line[MAX_PATH]; WCHAR line[MAX_PATH];
WCHAR ExeNameBuffer[EXENAME_LENGTH];
LPWSTR pszOrgExeName = pszExeName;
fp = _wfopen(param, L"r"); /* Open the file */
fp = _wfopen(FileName, L"rt");
if (!fp) if (!fp)
{ {
_wperror(param); _wperror(FileName);
return; return;
} }
while ( fgetws(line, MAX_PATH, fp) != NULL) while (fgetws(line, ARRAYSIZE(line), fp) != NULL)
{ {
/* Remove newline character */ PWCHAR end;
WCHAR *end = &line[wcslen(line) - 1];
if (!*line)
continue;
/* Remove trailing newline character */
end = &line[wcslen(line) - 1];
if (*end == L'\n') if (*end == L'\n')
*end = L'\0'; *end = L'\0';
if (*line) if (!*line)
continue;
/* Check for any section redefining the current executable name */
end = NULL;
if (*line == L'[')
end = wcschr(line, L']');
if (end != NULL)
{
/* New section: change the current executable name */
*end = L'\0'; // NULL-terminate it
pszExeName = RemoveQuotes(line + 1);
if (*pszExeName)
{
/* Capture the new executable name and truncate it if needed */
end = &pszExeName[wcslen(pszExeName)];
if (end - pszExeName >= EXENAME_LENGTH)
end = &pszExeName[EXENAME_LENGTH - 1];
*end = L'\0'; // Truncate it
wcscpy(ExeNameBuffer, pszExeName);
pszExeName = ExeNameBuffer;
}
else
{
/* Restore the original current executable name */
pszExeName = pszOrgExeName;
}
}
else
{
/* Set the new macro for the current executable */
SetMacro(line); SetMacro(line);
}
} }
/* Restore the original current executable name if it has changed */
pszExeName = pszOrgExeName;
/* Close the file and return */
fclose(fp); fclose(fp);
return; return;
} }
@ -201,23 +272,10 @@ static BOOL GetArg(WCHAR **pStart, WCHAR **pEnd)
return TRUE; return TRUE;
} }
/* Remove starting and ending quotes from a string, if present */
static LPWSTR RemoveQuotes(LPWSTR str)
{
WCHAR *end;
if (*str == L'"' && *(end = str + wcslen(str) - 1) == L'"')
{
str++;
*end = L'\0';
}
return str;
}
int int
wmain(VOID) wmain(VOID)
{ {
WCHAR *pArgStart; LPWSTR pArgStart, pArgEnd;
WCHAR *pArgEnd;
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
@ -230,13 +288,16 @@ wmain(VOID)
while (GetArg(&pArgStart, &pArgEnd)) while (GetArg(&pArgStart, &pArgEnd))
{ {
/* NUL-terminate this argument to make processing easier */ /* NULL-terminate this argument to make processing easier */
WCHAR tmp = *pArgEnd; WCHAR tmp = *pArgEnd;
*pArgEnd = L'\0'; *pArgEnd = L'\0';
if (!wcscmp(pArgStart, L"/?")) if (!wcscmp(pArgStart, L"/?"))
{ {
LoadStringW(GetModuleHandle(NULL), IDS_HELP, szStringBuf, MAX_STRING); LoadStringW(GetModuleHandle(NULL),
IDS_HELP,
szStringBuf,
ARRAYSIZE(szStringBuf));
wprintf(szStringBuf); wprintf(szStringBuf);
break; break;
} }
@ -287,7 +348,7 @@ wmain(VOID)
{ {
/* This is the beginning of a macro definition. It includes /* This is the beginning of a macro definition. It includes
* the entire remainder of the line, so first put back the * the entire remainder of the line, so first put back the
* character that we replaced with NUL. */ * character that we replaced with NULL. */
*pArgEnd = tmp; *pArgEnd = tmp;
return SetMacro(pArgStart); return SetMacro(pArgStart);
} }

View file

@ -2,7 +2,7 @@
#include "doskey.h" #include "doskey.h"
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Doskey Command" #define REACTOS_STR_FILE_DESCRIPTION "ReactOS DosKey Command"
#define REACTOS_STR_INTERNAL_NAME "doskey" #define REACTOS_STR_INTERNAL_NAME "doskey"
#define REACTOS_STR_ORIGINAL_FILENAME "doskey.exe" #define REACTOS_STR_ORIGINAL_FILENAME "doskey.exe"
#include <reactos/version.rc> #include <reactos/version.rc>
@ -54,4 +54,4 @@
#endif #endif
#ifdef LANGUAGE_ZH_TW #ifdef LANGUAGE_ZH_TW
#include "lang/zh-TW.rc" #include "lang/zh-TW.rc"
#endif #endif