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
38enum token_type {
39	NOTOKEN,
40	ENDTOKEN,
41	KEYWORD
42};
43
44struct token {
45	enum token_type		 type;
46	const char		*keyword;
47	int			 value;
48	const struct token	*next;
49};
50
51static const struct token t_main[];
52static const struct token t_log[];
53
54static const struct token t_main[] = {
55	{KEYWORD,	"reload",	RELOAD,		NULL},
56	{KEYWORD,	"log",		NONE,		t_log},
57	{ENDTOKEN,	"",		NONE,		NULL}
58};
59
60static const struct token t_log[] = {
61	{KEYWORD,	"verbose",	LOG_VERBOSE,	NULL},
62	{KEYWORD,	"brief",	LOG_BRIEF,	NULL},
63	{ENDTOKEN,	"",		NONE,		NULL}
64};
65
66static const struct token *match_token(const char *, const struct token *,
67    struct parse_result *);
68static void show_valid_args(const struct token *);
69
70struct parse_result *
71parse(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
103static const struct token *
104match_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
147static void
148show_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