xref: /openbsd-src/usr.sbin/ractl/parser.c (revision 4882a63085afdff3a00ce8a7228f9e0168a7e0fb)
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