.get_help = get_help_obj_list,
};
-int
+int
parse_obj_list(cmdline_parse_token_hdr_t *tk, const char *buf, void *res)
{
struct token_obj_list *tk2 = (struct token_obj_list *)tk;
struct object *o;
unsigned int token_len = 0;
- if (*buf == 0)
- return -1;
-
- while(!cmdline_isendoftoken(buf[token_len]))
- token_len++;
+ token_len = strlen(buf);
SLIST_FOREACH(o, tkd->list, next) {
- if (token_len != strlen(o->name))
- continue;
- if (strncmp(buf, o->name, token_len))
+ if (strcmp(buf, o->name))
continue;
break;
}
if (!o) /* not found */
return -1;
-
+
/* store the address of object in structure */
if (res)
*(struct object **)res = o;
- return token_len;
+ return token_len;
}
int complete_get_nb_obj_list(cmdline_parse_token_hdr_t *tk)
return ret;
}
-int complete_get_elt_obj_list(cmdline_parse_token_hdr_t *tk, int idx,
+int complete_get_elt_obj_list(cmdline_parse_token_hdr_t *tk, int idx,
char *dstbuf, unsigned int size)
{
struct token_obj_list *tk2 = (struct token_obj_list *)tk;
struct confnode *n;
struct confnode_list l;
unsigned int token_len = 0;
- char token[BUFSIZ];
+ char token[CMDLINE_MAX_TOKEN_SIZE];
- if (*buf == 0)
+ /* if token is too big... */
+ token_len = snprintf(token, sizeof(token), "%s", buf);
+ if (token_len >= sizeof(token))
return -1;
- while(!cmdline_isendoftoken(buf[token_len]))
- token_len++;
-
- if (token_len > sizeof(token) - 1)
- return -1;
-
- memcpy(token, buf, token_len);
- token[token_len] = '\0';
-
TAILQ_INIT(&l);
/* absolute path */
if (res)
*(struct confnode **)res = TAILQ_FIRST(&l);
- return token_len;
+ return token_len;
}
int complete_get_nb_conf_node(cmdline_parse_token_hdr_t *tk)
cmdline_printf(cl, "Command not found\n");
else if (ret == CMDLINE_PARSE_BAD_ARGS)
cmdline_printf(cl, "Bad arguments\n");
+ else if (ret == CMDLINE_PARSE_UNTERMINATED_QUOTE)
+ cmdline_printf(cl, "Unterminated quote\n");
}
static int
#include <inttypes.h>
#include <ctype.h>
#include <termios.h>
+#include <errno.h>
#include <netinet/in.h>
return i;
}
+/* quote a string and escape original quotes */
+int cmdline_quote_token(char *dst, unsigned dstlen, const char *src)
+{
+ unsigned s = 0, d = 0;
+
+ /* the 2 quotes + '\0' */
+ if (dstlen < 3)
+ return -EMSGSIZE;
+
+ dst[d++] = '"';
+ while (src[s] != '\0') {
+ if (d >= (dstlen-2))
+ return -EMSGSIZE;
+
+ if (src[s] == '"')
+ dst[d++] = '\\';
+ if (src[s] == '\\' && src[s+1] == '"')
+ dst[d++] = '\\';
+
+ dst[d++] = src[s++];
+ }
+
+ if (d >= (dstlen-2))
+ return -EMSGSIZE;
+ dst[d++] = '"';
+ dst[d++] = '\0';
+ return s;
+}
+
+/* remove quote and stop when we reach the end of token */
+// XXX ret val comment
+int cmdline_unquote_token(char *dst, unsigned dstlen,
+ const char *src)
+{
+ unsigned s = 0, d = 0;
+ int quoted = 0;
+
+ while (src[s] != '\0') {
+ if (d >= dstlen)
+ return -EMSGSIZE;
+
+ if (cmdline_isendoftoken(src[s]) && quoted == 0)
+ break;
+
+ if (src[s] == '\\' && src[s+1] == '"') {
+ dst[d++] = '"';
+ s += 2;
+ continue;
+ }
+ if (src[s] == '\\' && src[s+1] == '\\') {
+ dst[d++] = '\\';
+ s += 2;
+ continue;
+ }
+ if (src[s] == '"') {
+ s++;
+ quoted = !quoted;
+ continue;
+ }
+ dst[d++] = src[s++];
+ }
+
+ if (quoted)
+ return -EINVAL;
+
+ if (d >= (dstlen-1))
+ return -EMSGSIZE;
+ dst[d++] = '\0';
+ return s;
+}
+
/**
* try to match the buffer with an instruction (only the first
* nb_match_token tokens if != 0). Return 0 if we match all the
unsigned int token_num=0;
cmdline_parse_token_hdr_t * token_p;
unsigned int i=0;
- int n = 0;
+ int n = 0, res;
struct cmdline_token_hdr token_hdr;
+ char token_str[128];
token_p = inst->tokens[token_num];
if (token_p)
if ( isendofline(*buf) || iscomment(*buf) )
break;
+ n = cmdline_unquote_token(token_str, sizeof(token_str), buf);
+ if (n == -EINVAL)
+ return -EINVAL;
+
if (result_buf)
- n = token_hdr.ops->parse(token_p, buf,
+ res = token_hdr.ops->parse(token_p, token_str,
(char *)result_buf +
token_hdr.offset);
else
- n = token_hdr.ops->parse(token_p, buf, NULL);
-
- if (n < 0)
+ res = token_hdr.ops->parse(token_p, token_str, NULL);
+ if (res < 0)
break;
debug_printf("TK parsed (len=%d)\n", n);
/* does not match */
if (i==0)
- return -1;
+ return -ENOENT;
/* in case we want to match a specific num of token */
if (nb_match_token) {
}
}
}
+ else if (tok == -EINVAL) {
+ err = CMDLINE_PARSE_UNTERMINATED_QUOTE;
+ f = NULL;
+ debug_printf("Unterminated quote\n");
+ break;
+ }
inst_num ++;
inst = ctx[inst_num];
#define CMDLINE_PARSE_AMBIGUOUS -1
#define CMDLINE_PARSE_NOMATCH -2
#define CMDLINE_PARSE_BAD_ARGS -3
+#define CMDLINE_PARSE_UNTERMINATED_QUOTE -4
/* return status for completion */
#define CMDLINE_PARSE_COMPLETE_FINISHED 0
#define CMDLINE_PARSE_COMPLETE_AGAIN 1
#define CMDLINE_PARSE_COMPLETED_BUFFER 2
+#define CMDLINE_MAX_TOKEN_SIZE 128 /* including '\0' */
+
/**
* Stores a pointer to the ops struct, and the offset: the place to
* write the parsed result in the destination structure.
* isendofline(c)) */
int cmdline_isendoftoken(char c);
+/* quote a string and escape original quotes */
+int cmdline_quote_token(char *dst, unsigned dstlen, const char *src);
+
+/* remove quote and stop when we reach the end of token */
+int cmdline_unquote_token(char *dst, unsigned dstlen, const char *src);
+
#endif /* _CMDLINE_PARSE_H_ */
struct ether_addr *etheraddr = res;
struct ether_addr *tmp;
- if (! *buf)
- return -1;
-
- while (!cmdline_isendoftoken(buf[token_len]))
- token_len++;
-
/* if token is too big... */
- if (token_len >= ETHER_ADDRSTRLEN)
+ token_len = snprintf(ether_str, sizeof(ether_str), "%s", buf);
+ if (token_len >= sizeof(ether_str))
return -1;
- snprintf(ether_str, token_len+1, "%s", buf);
-
tmp = my_ether_aton(ether_str);
if (tmp == NULL)
return -1;
char *prefix, *prefix_end;
long prefixlen;
- if (! *buf)
- return -1;
-
- while (!cmdline_isendoftoken(buf[token_len]))
- token_len++;
-
/* if token is too big... */
- if (token_len >= INET6_ADDRSTRLEN+4)
+ token_len = snprintf(ip_str, sizeof(ip_str), "%s", buf);
+ if (token_len >= sizeof(ip_str))
return -1;
- snprintf(ip_str, token_len+1, "%s", buf);
-
/* convert the network prefix */
if (tk2->ipaddr_data.flags & CMDLINE_IPADDR_NETWORK) {
prefix = strrchr(ip_str, '/');
memcpy(&nd, &((struct cmdline_token_num *)tk)->num_data, sizeof(nd));
- while ( st != ERROR && c && ! cmdline_isendoftoken(c) ) {
+ while (st != ERROR && c != '\0') {
debug_printf("%c %x -> ", c, c);
switch (st) {
case START:
return NULL;
}
+static int parse_fixed_string(struct cmdline_token_string_data *sd,
+ const char *buf, unsigned token_len)
+{
+ unsigned int conf_token_len;
+ const char *str;
+
+ str = sd->str;
+ for (str = sd->str; str != NULL ; str = get_next_token(str)) {
+
+ conf_token_len = get_token_len(str);
+
+ /* if token from config is too big... */
+ if (conf_token_len >= STR_TOKEN_SIZE - 1)
+ continue;
+
+ /* compare conf token and user token */
+ if (token_len == conf_token_len &&
+ strncmp(buf, str, token_len) == 0)
+ return 0;
+ }
+
+ return -1;
+}
+
int
cmdline_parse_string(cmdline_parse_token_hdr_t *tk, const char *buf, void *res)
{
struct cmdline_token_string *tk2 = (struct cmdline_token_string *)tk;
struct cmdline_token_string_data *sd = &tk2->string_data;;
unsigned int token_len;
- const char *str;
- if (! *buf)
+ token_len = strlen(buf);
+
+ if (token_len >= (STR_TOKEN_SIZE - 1) || token_len == 0)
return -1;
/* fixed string */
if (sd->str) {
- str = sd->str;
- do {
- token_len = get_token_len(str);
-
- /* if token is too big... */
- if (token_len >= STR_TOKEN_SIZE - 1) {
- continue;
- }
-
- if ( strncmp(buf, str, token_len) ) {
- continue;
- }
-
- if ( !cmdline_isendoftoken(*(buf+token_len)) ) {
- continue;
- }
-
- break;
- } while ( (str = get_next_token(str)) != NULL );
-
- if (!str)
+ if (parse_fixed_string(sd, buf, token_len) < 0)
return -1;
}
- /* unspecified string */
- else {
- token_len=0;
- while(!cmdline_isendoftoken(buf[token_len]) &&
- token_len < (STR_TOKEN_SIZE-1))
- token_len++;
-
- /* return if token too long */
- if (token_len >= STR_TOKEN_SIZE - 1) {
- return -1;
- }
- }
- if (res) {
- /* we are sure that token_len is < STR_TOKEN_SIZE-1 */
- strncpy(res, buf, token_len);
- *((char *)res + token_len) = 0;
- }
+ /* we already checked that token_len is < STR_TOKEN_SIZE-1 */
+ if (res)
+ strcpy(res, buf);
return token_len;
}