jcs's openbsd hax
openbsd
1/* $OpenBSD: parser.c,v 1.12 2025/08/03 13:20:36 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 "unwind.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[];
53static const struct token t_status[];
54
55static const struct token t_main[] = {
56 {KEYWORD, "reload", RELOAD, NULL},
57 {KEYWORD, "status", STATUS, t_status},
58 {KEYWORD, "log", NONE, t_log},
59 {ENDTOKEN, "", NONE, NULL}
60};
61
62static const struct token t_log[] = {
63 {KEYWORD, "debug", LOG_DEBUG, NULL},
64 {KEYWORD, "verbose", LOG_VERBOSE, NULL},
65 {KEYWORD, "brief", LOG_BRIEF, NULL},
66 {ENDTOKEN, "", NONE, NULL}
67};
68
69static const struct token t_status[] = {
70 {NOTOKEN, "", NONE, NULL},
71 {KEYWORD, "autoconf", AUTOCONF, NULL},
72#ifdef UNIFIED_CACHE
73 {KEYWORD, "memory", MEM, NULL},
74#endif /* UNIFIED_CACHE */
75 {ENDTOKEN, "", NONE, NULL}
76};
77
78static const struct token *match_token(const char *, const struct token *,
79 struct parse_result *);
80static void show_valid_args(const struct token *);
81
82struct parse_result *
83parse(int argc, char *argv[])
84{
85 static struct parse_result res;
86 const struct token *table = t_main;
87 const struct token *match;
88
89 memset(&res, 0, sizeof(res));
90
91 while (argc >= 0) {
92 if ((match = match_token(argv[0], table, &res)) == NULL) {
93 fprintf(stderr, "valid commands/args:\n");
94 show_valid_args(table);
95 return (NULL);
96 }
97
98 argc--;
99 argv++;
100
101 if (match->type == NOTOKEN || match->next == NULL)
102 break;
103
104 table = match->next;
105 }
106
107 if (argc > 0) {
108 fprintf(stderr, "superfluous argument: %s\n", argv[0]);
109 return (NULL);
110 }
111
112 return (&res);
113}
114
115static const struct token *
116match_token(const char *word, const struct token *table,
117 struct parse_result *res)
118{
119 u_int i, match;
120 const struct token *t = NULL;
121
122 match = 0;
123
124 for (i = 0; table[i].type != ENDTOKEN; i++) {
125 switch (table[i].type) {
126 case NOTOKEN:
127 if (word == NULL || strlen(word) == 0) {
128 match++;
129 t = &table[i];
130 }
131 break;
132 case KEYWORD:
133 if (word != NULL && strncmp(word, table[i].keyword,
134 strlen(word)) == 0) {
135 match++;
136 t = &table[i];
137 if (t->value)
138 res->action = t->value;
139 }
140 break;
141 case ENDTOKEN:
142 break;
143 }
144 }
145
146 if (match != 1) {
147 if (word == NULL)
148 fprintf(stderr, "missing argument:\n");
149 else if (match > 1)
150 fprintf(stderr, "ambiguous argument: %s\n", word);
151 else if (match < 1)
152 fprintf(stderr, "unknown argument: %s\n", word);
153 return (NULL);
154 }
155
156 return (t);
157}
158
159static void
160show_valid_args(const struct token *table)
161{
162 int i;
163
164 for (i = 0; table[i].type != ENDTOKEN; i++) {
165 switch (table[i].type) {
166 case NOTOKEN:
167 fprintf(stderr, " <cr>\n");
168 break;
169 case KEYWORD:
170 fprintf(stderr, " %s\n", table[i].keyword);
171 break;
172 case ENDTOKEN:
173 break;
174 }
175 }
176}