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