restructure buggy parse_args routine

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@5898 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Kevin P. Fleming 2005-06-10 20:25:23 +00:00
parent 0c082e7e62
commit 0aae19259a
1 changed files with 52 additions and 62 deletions

66
cli.c
View File

@ -1067,7 +1067,7 @@ static int handle_help(int fd, int argc, char *argv[]) {
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
static char *parse_args(char *s, int *max, char *argv[]) static char *parse_args(char *s, int *argc, char *argv[], int max)
{ {
char *dup, *cur; char *dup, *cur;
int x = 0; int x = 0;
@ -1075,51 +1075,41 @@ static char *parse_args(char *s, int *max, char *argv[])
int escaped = 0; int escaped = 0;
int whitespace = 1; int whitespace = 1;
dup = strdup(s); if (!(dup = strdup(s)))
if (dup) { return NULL;
cur = dup; cur = dup;
while (*s) { while (*s) {
switch(*s) { if ((*s == '"') && !escaped) {
case '"':
/* If it's escaped, put a literal quote */
if (escaped)
goto normal;
else
quoted = !quoted; quoted = !quoted;
if (quoted && whitespace) { if (quoted & whitespace) {
/* If we're starting a quote, coming off white space start a new word, too */ /* If we're starting a quoted string, coming off white space, start a new argument */
if (x >= (max - 1)) {
ast_log(LOG_WARNING, "Too many arguments, truncating\n");
break;
}
argv[x++] = cur; argv[x++] = cur;
whitespace = 0; whitespace = 0;
} }
escaped = 0; escaped = 0;
break; } else if (((*s == ' ') || (*s == '\t')) && !(quoted || escaped)) {
case ' ': /* If we are not already in whitespace, and not in a quoted string or
case '\t': processing an escape sequence, and just entered whitespace, then
if (!quoted && !escaped) { finalize the previous argument and remember that we are in whitespace
/* If we're not quoted, mark this as whitespace, and */
end the previous argument */ if (!whitespace) {
whitespace = 1;
*(cur++) = '\0'; *(cur++) = '\0';
} else whitespace = 1;
/* Otherwise, just treat it as anything else */
goto normal;
break;
case '\\':
/* If we're escaped, print a literal, otherwise enable escaping */
if (escaped) {
goto normal;
} else {
escaped=1;
} }
break; } else if ((*s == '\\') && !escaped) {
default: escaped = 1;
normal: } else {
if (whitespace) { if (whitespace) {
if (x >= AST_MAX_ARGS -1) { /* If we are coming out of whitespace, start a new argument */
if (x >= (max - 1)) {
ast_log(LOG_WARNING, "Too many arguments, truncating\n"); ast_log(LOG_WARNING, "Too many arguments, truncating\n");
break; break;
} }
/* Coming off of whitespace, start the next argument */
argv[x++] = cur; argv[x++] = cur;
whitespace = 0; whitespace = 0;
} }
@ -1131,8 +1121,8 @@ normal:
/* Null terminate */ /* Null terminate */
*(cur++) = '\0'; *(cur++) = '\0';
argv[x] = NULL; argv[x] = NULL;
*max = x; *argc = x;
}
return dup; return dup;
} }
@ -1204,7 +1194,7 @@ static char *__ast_cli_generator(char *text, char *word, int state, int lock)
char matchstr[80]; char matchstr[80];
char *fullcmd = NULL; char *fullcmd = NULL;
if ((dup = parse_args(text, &x, argv))) { if ((dup = parse_args(text, &x, argv, sizeof(argv) / sizeof(argv[0])))) {
join(matchstr, sizeof(matchstr), argv); join(matchstr, sizeof(matchstr), argv);
if (lock) if (lock)
ast_mutex_lock(&clilock); ast_mutex_lock(&clilock);
@ -1277,8 +1267,8 @@ int ast_cli_command(int fd, char *s)
struct ast_cli_entry *e; struct ast_cli_entry *e;
int x; int x;
char *dup; char *dup;
x = AST_MAX_ARGS;
if ((dup = parse_args(s, &x, argv))) { if ((dup = parse_args(s, &x, argv, sizeof(argv) / sizeof(argv[0])))) {
/* We need at least one entry, or ignore */ /* We need at least one entry, or ignore */
if (x > 0) { if (x > 0) {
ast_mutex_lock(&clilock); ast_mutex_lock(&clilock);