1*4882a630Sflorian /* $OpenBSD: parser.c,v 1.1 2018/07/10 22:12:43 florian Exp $ */
2*4882a630Sflorian
3*4882a630Sflorian /*
4*4882a630Sflorian * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
5*4882a630Sflorian * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
6*4882a630Sflorian *
7*4882a630Sflorian * Permission to use, copy, modify, and distribute this software for any
8*4882a630Sflorian * purpose with or without fee is hereby granted, provided that the above
9*4882a630Sflorian * copyright notice and this permission notice appear in all copies.
10*4882a630Sflorian *
11*4882a630Sflorian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12*4882a630Sflorian * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13*4882a630Sflorian * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14*4882a630Sflorian * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15*4882a630Sflorian * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16*4882a630Sflorian * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17*4882a630Sflorian * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18*4882a630Sflorian */
19*4882a630Sflorian
20*4882a630Sflorian #include <sys/types.h>
21*4882a630Sflorian #include <sys/queue.h>
22*4882a630Sflorian #include <sys/socket.h>
23*4882a630Sflorian #include <netinet/in.h>
24*4882a630Sflorian #include <arpa/inet.h>
25*4882a630Sflorian #include <net/if.h>
26*4882a630Sflorian #include <err.h>
27*4882a630Sflorian #include <errno.h>
28*4882a630Sflorian #include <event.h>
29*4882a630Sflorian #include <imsg.h>
30*4882a630Sflorian #include <limits.h>
31*4882a630Sflorian #include <stdio.h>
32*4882a630Sflorian #include <stdlib.h>
33*4882a630Sflorian #include <string.h>
34*4882a630Sflorian
35*4882a630Sflorian #include "rad.h"
36*4882a630Sflorian #include "parser.h"
37*4882a630Sflorian
38*4882a630Sflorian enum token_type {
39*4882a630Sflorian NOTOKEN,
40*4882a630Sflorian ENDTOKEN,
41*4882a630Sflorian KEYWORD
42*4882a630Sflorian };
43*4882a630Sflorian
44*4882a630Sflorian struct token {
45*4882a630Sflorian enum token_type type;
46*4882a630Sflorian const char *keyword;
47*4882a630Sflorian int value;
48*4882a630Sflorian const struct token *next;
49*4882a630Sflorian };
50*4882a630Sflorian
51*4882a630Sflorian static const struct token t_main[];
52*4882a630Sflorian static const struct token t_log[];
53*4882a630Sflorian
54*4882a630Sflorian static const struct token t_main[] = {
55*4882a630Sflorian {KEYWORD, "reload", RELOAD, NULL},
56*4882a630Sflorian {KEYWORD, "log", NONE, t_log},
57*4882a630Sflorian {ENDTOKEN, "", NONE, NULL}
58*4882a630Sflorian };
59*4882a630Sflorian
60*4882a630Sflorian static const struct token t_log[] = {
61*4882a630Sflorian {KEYWORD, "verbose", LOG_VERBOSE, NULL},
62*4882a630Sflorian {KEYWORD, "brief", LOG_BRIEF, NULL},
63*4882a630Sflorian {ENDTOKEN, "", NONE, NULL}
64*4882a630Sflorian };
65*4882a630Sflorian
66*4882a630Sflorian static const struct token *match_token(const char *, const struct token *,
67*4882a630Sflorian struct parse_result *);
68*4882a630Sflorian static void show_valid_args(const struct token *);
69*4882a630Sflorian
70*4882a630Sflorian struct parse_result *
parse(int argc,char * argv[])71*4882a630Sflorian parse(int argc, char *argv[])
72*4882a630Sflorian {
73*4882a630Sflorian static struct parse_result res;
74*4882a630Sflorian const struct token *table = t_main;
75*4882a630Sflorian const struct token *match;
76*4882a630Sflorian
77*4882a630Sflorian memset(&res, 0, sizeof(res));
78*4882a630Sflorian
79*4882a630Sflorian while (argc >= 0) {
80*4882a630Sflorian if ((match = match_token(argv[0], table, &res)) == NULL) {
81*4882a630Sflorian fprintf(stderr, "valid commands/args:\n");
82*4882a630Sflorian show_valid_args(table);
83*4882a630Sflorian return (NULL);
84*4882a630Sflorian }
85*4882a630Sflorian
86*4882a630Sflorian argc--;
87*4882a630Sflorian argv++;
88*4882a630Sflorian
89*4882a630Sflorian if (match->type == NOTOKEN || match->next == NULL)
90*4882a630Sflorian break;
91*4882a630Sflorian
92*4882a630Sflorian table = match->next;
93*4882a630Sflorian }
94*4882a630Sflorian
95*4882a630Sflorian if (argc > 0) {
96*4882a630Sflorian fprintf(stderr, "superfluous argument: %s\n", argv[0]);
97*4882a630Sflorian return (NULL);
98*4882a630Sflorian }
99*4882a630Sflorian
100*4882a630Sflorian return (&res);
101*4882a630Sflorian }
102*4882a630Sflorian
103*4882a630Sflorian static const struct token *
match_token(const char * word,const struct token * table,struct parse_result * res)104*4882a630Sflorian match_token(const char *word, const struct token *table,
105*4882a630Sflorian struct parse_result *res)
106*4882a630Sflorian {
107*4882a630Sflorian u_int i, match;
108*4882a630Sflorian const struct token *t = NULL;
109*4882a630Sflorian
110*4882a630Sflorian match = 0;
111*4882a630Sflorian
112*4882a630Sflorian for (i = 0; table[i].type != ENDTOKEN; i++) {
113*4882a630Sflorian switch (table[i].type) {
114*4882a630Sflorian case NOTOKEN:
115*4882a630Sflorian if (word == NULL || strlen(word) == 0) {
116*4882a630Sflorian match++;
117*4882a630Sflorian t = &table[i];
118*4882a630Sflorian }
119*4882a630Sflorian break;
120*4882a630Sflorian case KEYWORD:
121*4882a630Sflorian if (word != NULL && strncmp(word, table[i].keyword,
122*4882a630Sflorian strlen(word)) == 0) {
123*4882a630Sflorian match++;
124*4882a630Sflorian t = &table[i];
125*4882a630Sflorian if (t->value)
126*4882a630Sflorian res->action = t->value;
127*4882a630Sflorian }
128*4882a630Sflorian break;
129*4882a630Sflorian case ENDTOKEN:
130*4882a630Sflorian break;
131*4882a630Sflorian }
132*4882a630Sflorian }
133*4882a630Sflorian
134*4882a630Sflorian if (match != 1) {
135*4882a630Sflorian if (word == NULL)
136*4882a630Sflorian fprintf(stderr, "missing argument:\n");
137*4882a630Sflorian else if (match > 1)
138*4882a630Sflorian fprintf(stderr, "ambiguous argument: %s\n", word);
139*4882a630Sflorian else if (match < 1)
140*4882a630Sflorian fprintf(stderr, "unknown argument: %s\n", word);
141*4882a630Sflorian return (NULL);
142*4882a630Sflorian }
143*4882a630Sflorian
144*4882a630Sflorian return (t);
145*4882a630Sflorian }
146*4882a630Sflorian
147*4882a630Sflorian static void
show_valid_args(const struct token * table)148*4882a630Sflorian show_valid_args(const struct token *table)
149*4882a630Sflorian {
150*4882a630Sflorian int i;
151*4882a630Sflorian
152*4882a630Sflorian for (i = 0; table[i].type != ENDTOKEN; i++) {
153*4882a630Sflorian switch (table[i].type) {
154*4882a630Sflorian case NOTOKEN:
155*4882a630Sflorian fprintf(stderr, " <cr>\n");
156*4882a630Sflorian break;
157*4882a630Sflorian case KEYWORD:
158*4882a630Sflorian fprintf(stderr, " %s\n", table[i].keyword);
159*4882a630Sflorian break;
160*4882a630Sflorian case ENDTOKEN:
161*4882a630Sflorian break;
162*4882a630Sflorian }
163*4882a630Sflorian }
164*4882a630Sflorian }
165