regedit: Tokenize command-line input.

Signed-off-by: Hugh McMaster <hugh.mcmaster@outlook.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
oldstable
Hugh McMaster 2016-06-22 12:59:13 +00:00 committed by Alexandre Julliard
parent 493b5aab22
commit 53c9a78970
1 changed files with 111 additions and 140 deletions

View File

@ -56,81 +56,23 @@ static const char *usage =
"regedit.\n"; "regedit.\n";
typedef enum { typedef enum {
ACTION_UNDEF, ACTION_ADD, ACTION_EXPORT, ACTION_DELETE ACTION_ADD, ACTION_EXPORT, ACTION_DELETE
} REGEDIT_ACTION; } REGEDIT_ACTION;
/****************************************************************************** static BOOL PerformRegAction(REGEDIT_ACTION action, char **argv, int *i)
* Copies file name from command line string to the buffer.
* Rewinds the command line string pointer to the next non-space character
* after the file name.
* Buffer contains an empty string if no filename was found;
*
* params:
* command_line - command line current position pointer
* where *s[0] is the first symbol of the file name.
* file_name - buffer to write the file name to.
*/
static void get_file_name(CHAR **command_line, CHAR *file_name)
{
CHAR *s = *command_line;
int pos = 0; /* position of pointer "s" in *command_line */
file_name[0] = 0;
if (!s[0]) {
return;
}
if (s[0] == '"') {
s++;
(*command_line)++;
while(s[0] != '"') {
if (!s[0]) {
fprintf(stderr, "regedit: Unexpected end of file name!\n");
exit(1);
}
s++;
pos++;
}
} else {
while(s[0] && !isspace(s[0])) {
s++;
pos++;
}
}
memcpy(file_name, *command_line, pos * sizeof((*command_line)[0]));
/* Terminate the string and remove the trailing backslash */
if (pos > 0 && file_name[pos - 1] == '\\') {
file_name[pos - 1] = '\0';
} else {
file_name[pos] = '\0';
}
if (s[0]) {
s++;
pos++;
}
while(s[0] && isspace(s[0])) {
s++;
pos++;
}
(*command_line) += pos;
}
static BOOL PerformRegAction(REGEDIT_ACTION action, LPSTR s)
{ {
switch (action) { switch (action) {
case ACTION_ADD: { case ACTION_ADD: {
CHAR filename[MAX_PATH]; char *filename = argv[*i];
FILE *reg_file; FILE *reg_file;
get_file_name(&s, filename);
if (!filename[0]) { if (!filename[0]) {
fprintf(stderr, "regedit: No file name was specified\n"); fprintf(stderr, "regedit: No file name was specified\n");
fprintf(stderr,usage); fprintf(stderr,usage);
exit(1); exit(1);
} }
while(filename[0]) { if (filename[0]) {
char* realname = NULL; char* realname = NULL;
if (strcmp(filename, "-") == 0) if (strcmp(filename, "-") == 0)
@ -167,14 +109,12 @@ static BOOL PerformRegAction(REGEDIT_ACTION action, LPSTR s)
HeapFree(GetProcessHeap(),0,realname); HeapFree(GetProcessHeap(),0,realname);
fclose(reg_file); fclose(reg_file);
} }
get_file_name(&s, filename);
} }
break; break;
} }
case ACTION_DELETE: { case ACTION_DELETE: {
CHAR reg_key_name[KEY_MAX_LEN]; char *reg_key_name = argv[*i];
get_file_name(&s, reg_key_name);
if (!reg_key_name[0]) { if (!reg_key_name[0]) {
fprintf(stderr, "regedit: No registry key was specified for removal\n"); fprintf(stderr, "regedit: No registry key was specified for removal\n");
fprintf(stderr,usage); fprintf(stderr,usage);
@ -188,11 +128,9 @@ static BOOL PerformRegAction(REGEDIT_ACTION action, LPSTR s)
break; break;
} }
case ACTION_EXPORT: { case ACTION_EXPORT: {
CHAR filename[MAX_PATH]; char *filename = argv[*i];
WCHAR* filenameW; WCHAR* filenameW;
filename[0] = '\0';
get_file_name(&s, filename);
if (!filename[0]) { if (!filename[0]) {
fprintf(stderr, "regedit: No filename was specified\n"); fprintf(stderr, "regedit: No filename was specified\n");
fprintf(stderr,usage); fprintf(stderr,usage);
@ -200,11 +138,10 @@ static BOOL PerformRegAction(REGEDIT_ACTION action, LPSTR s)
} }
filenameW = GetWideString(filename); filenameW = GetWideString(filename);
if (s[0]) { if (filenameW[0]) {
CHAR reg_key_name[KEY_MAX_LEN]; char *reg_key_name = argv[++(*i)];
WCHAR* reg_key_nameW; WCHAR* reg_key_nameW;
get_file_name(&s, reg_key_name);
reg_key_nameW = GetWideString(reg_key_name); reg_key_nameW = GetWideString(reg_key_name);
export_registry_key(filenameW, reg_key_nameW, REG_FORMAT_4); export_registry_key(filenameW, reg_key_nameW, REG_FORMAT_4);
HeapFree(GetProcessHeap(), 0, reg_key_nameW); HeapFree(GetProcessHeap(), 0, reg_key_nameW);
@ -222,83 +159,117 @@ static BOOL PerformRegAction(REGEDIT_ACTION action, LPSTR s)
return TRUE; return TRUE;
} }
BOOL ProcessCmdLine(LPSTR lpCmdLine) char *get_token(char *input, char **next)
{ {
REGEDIT_ACTION action = ACTION_UNDEF; char *ch = input;
LPSTR s = lpCmdLine; /* command line pointer */ char *str;
CHAR ch = *s; /* current character */
while (ch && ((ch == '-') || (ch == '/'))) { while (*ch && isspace(*ch))
char chu; ch++;
char ch2;
s++; str = ch;
ch = *s;
if (!ch || isspace(ch)) if (*ch == '"') {
{ ch++;
/* '-' is a file name. It indicates we should use stdin */ str = ch;
s--; for (;;) {
while (*ch && (*ch != '"'))
ch++;
if (!*ch)
break;
if (*(ch - 1) == '\\') {
ch++;
continue;
}
break; break;
} }
ch2 = *(s+1); }
chu = toupper(ch); else {
if (!ch2 || isspace(ch2)) { while (*ch && !isspace(*ch))
if (chu == 'S' || chu == 'V') { ch++;
/* ignore these switches */ }
} else {
switch (chu) { if (*ch) {
case 'D': *ch = 0;
action = ACTION_DELETE; ch++;
break; }
case 'E':
action = ACTION_EXPORT; *next = ch;
break; return str;
case '?': }
fprintf(stderr,usage);
exit(0); BOOL ProcessCmdLine(LPSTR lpCmdLine)
break; {
default: char *s = lpCmdLine;
fprintf(stderr, "regedit: Invalid or unrecognized switch [/%c]\n", chu); char **argv;
exit(1); char *tok;
break; int argc = 0, i = 1;
} REGEDIT_ACTION action = ACTION_ADD;
}
s++; if (!*lpCmdLine)
} else { return FALSE;
if (ch2 == ':') {
switch (chu) { while (*s) {
case 'L': if (isspace(*s))
/* fall through */ i++;
case 'R': s++;
s += 2; }
while (*s && !isspace(*s)) {
s++; s = lpCmdLine;
} argv = HeapAlloc(GetProcessHeap(), 0, i * sizeof(char *));
break;
default: for (i = 0; *s; i++)
fprintf(stderr, "regedit: Invalid or unrecognized switch [/%c]\n", chu); {
exit(1); tok = get_token(s, &s);
break; argv[i] = HeapAlloc(GetProcessHeap(), 0, strlen(tok) + 1);
} strcpy(argv[i], tok);
} else { argc++;
/* this is a file name, starting from '/' */ }
s--;
break; for (i = 0; i < argc; i++)
} {
} if (argv[i][0] != '/' && argv[i][0] != '-')
/* skip spaces to the next parameter */ break; /* No flags specified. */
ch = *s;
while (ch && isspace(ch)) { if (!argv[i][1] && argv[i][0] == '-')
s++; break; /* '-' is a filename. It indicates we should use stdin. */
ch = *s;
if (argv[i][1] && argv[i][2] && argv[i][2] != ':')
break; /* This is a file path beginning with '/'. */
switch (toupper(argv[i][1]))
{
case '?':
fprintf(stderr, usage);
exit(0);
break;
case 'D':
action = ACTION_DELETE;
break;
case 'E':
action = ACTION_EXPORT;
break;
case 'L':
case 'R':
/* unhandled */;
break;
case 'S':
case 'V':
/* ignored */;
break;
default:
fprintf(stderr, "regedit: Invalid switch [%ls]\n", argv[i]);
exit(1);
} }
} }
if (*s && action == ACTION_UNDEF) PerformRegAction(action, argv, &i);
action = ACTION_ADD;
if (action == ACTION_UNDEF) for (i = 0; i < argc; i++)
return FALSE; HeapFree(GetProcessHeap(), 0, argv[i]);
HeapFree(GetProcessHeap(), 0, argv);
return PerformRegAction(action, s); return TRUE;
} }