2 * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the University of California, Berkeley nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <netinet/in.h>
34 #include <sys/queue.h>
36 #include <cmdline_parse_ipaddr.h>
37 #include <cmdline_parse.h>
39 #include "expression.h"
40 #include "conf_parser.h"
42 #include "conf_htable.h"
43 #include "parse_confnode.h"
45 /* return 0 if string matches pattern (string must not contain '*')*/
47 strcmp_joker(const char *s, const char *pattern)
52 while (*s == *pattern && *pattern != '*') {
60 if (*(pattern + 1) == '\0')
63 if (strcmp_joker(s, pattern + 1) == 0)
71 find_in_children(struct confnode_list *l, struct confnode *n,
72 const char *pattern, int flags, int mask, int recurs)
76 TAILQ_FOREACH(c, &n->children, next) {
77 /* if it's a "if" node, parse children */
78 if (c->flags & CONFNODE_F_INVISIBLE)
79 find_in_children(l, c, pattern, flags, mask, recurs);
82 if ((c->flags & mask) == flags &&
83 !strcmp_joker(c->name, pattern))
84 TAILQ_INSERT_TAIL(l, c, user_next);
87 find_in_children(l, c, pattern, flags, mask, recurs);
93 parse_conf_node(cmdline_parse_token_hdr_t *tk, const char *buf, void *res,
96 struct token_conf_node *tk2 = (struct token_conf_node *)tk;
97 struct token_conf_node_data *tkd = &tk2->conf_node_data;
99 struct confnode_list l;
100 unsigned int token_len = 0;
101 char token[CMDLINE_MAX_TOKEN_SIZE];
103 if (res && ressize < sizeof(struct confnode *))
106 /* if token is too big... */
107 token_len = snprintf(token, sizeof(token), "%s", buf);
108 if (token_len >= sizeof(token))
114 if (token[0] == '/' && token[1] == '/') {
115 /* if contains joker */
116 if (strchr(token + 2, '*'))
117 find_in_children(&l, *tkd->root, token+2, tkd->flags,
120 n = conf_htable_lookup(token + 2);
121 if ((n->flags & tkd->mask) != tkd->flags)
123 TAILQ_INSERT_TAIL(&l, n, user_next);
128 find_in_children(&l, *tkd->cur, token, tkd->flags, tkd->mask, 0);
132 /* store the address of object in structure */
134 *(struct confnode **)res = TAILQ_FIRST(&l);
139 struct confnode_complete_callback {
140 struct confnode *start;
141 struct confnode *cur;
145 static struct confnode *get_next_node(struct confnode *start,
146 struct confnode *cur, unsigned flags,
149 struct confnode *prev;
150 struct confnode *parent = start;
155 /* no more node to browse */
159 /* first iteration */
161 cur = TAILQ_FIRST(&parent->children);
163 cur = TAILQ_NEXT(cur, next);
165 /* no next, return to upper level */
168 return NULL; /* no node */
173 /* skip invisible nodes, and browse their contents */
174 if (cur->flags & CONFNODE_F_INVISIBLE) {
180 /* check that flags match what we want */
181 if ((cur->flags & mask) != flags)
184 /* standard node, return it */
190 complete_conf_node_start(cmdline_parse_token_hdr_t *tk,
191 __attribute__((unused)) const char *tokstr,
194 struct token_conf_node *tk2 = (struct token_conf_node *)tk;
195 struct token_conf_node_data *tkd = &tk2->conf_node_data;
196 struct confnode_complete_callback *cb;
198 unsigned flags = tkd->flags;
199 unsigned mask = tkd->mask;
202 cb = malloc(sizeof(*cb));
207 n = get_next_node(*tkd->cur, NULL, flags, mask);
209 return -1; /* no completion */
211 cb->start = *tkd->cur;
217 complete_conf_node_iterate(cmdline_parse_token_hdr_t *tk, void **opaque,
218 char *dstbuf, unsigned int size)
220 struct token_conf_node *tk2 = (struct token_conf_node *)tk;
221 struct token_conf_node_data *tkd = &tk2->conf_node_data;
222 struct confnode_complete_callback *cb;
225 unsigned flags = tkd->flags;
226 unsigned mask = tkd->mask;
232 cb->cur = get_next_node(cb->start, n, flags, mask);
234 len = strlen(n->name) + 1;
238 strcpy(dstbuf, n->name);
243 complete_conf_node_end(cmdline_parse_token_hdr_t *tk, void **opaque)
249 int help_conf_node(cmdline_parse_token_hdr_t *tk, char *dstbuf, unsigned int size)
251 snprintf(dstbuf, size, "conf-node");
255 struct cmdline_token_ops token_conf_node_ops = {
256 .parse = parse_conf_node,
257 .complete_start = complete_conf_node_start,
258 .complete_iterate = complete_conf_node_iterate,
259 .complete_end = complete_conf_node_end,
260 .help = help_conf_node,