parser.c revision 1.15
1/* $OpenBSD: parser.c,v 1.15 2007/11/20 15:37:24 pyr Exp $ */ 2 3/* 4 * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org> 5 * Copyright (c) 2004 Esben Norby <norby@openbsd.org> 6 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21#include <sys/types.h> 22#include <sys/socket.h> 23#include <sys/queue.h> 24#include <netinet/in.h> 25#include <net/if.h> 26#include <arpa/inet.h> 27#include <err.h> 28#include <errno.h> 29#include <limits.h> 30#include <stdio.h> 31#include <stdlib.h> 32#include <string.h> 33#include <event.h> 34 35#include <openssl/ssl.h> 36 37#include "hoststated.h" 38 39#include "parser.h" 40 41enum token_type { 42 NOTOKEN, 43 ENDTOKEN, 44 HOSTID, 45 TABLEID, 46 SERVICEID, 47 KEYWORD 48}; 49 50struct token { 51 enum token_type type; 52 const char *keyword; 53 int value; 54 const struct token *next; 55}; 56 57static const struct token t_main[]; 58static const struct token t_show[]; 59static const struct token t_service[]; 60static const struct token t_table[]; 61static const struct token t_host[]; 62static const struct token t_service_id[]; 63static const struct token t_table_id[]; 64static const struct token t_host_id[]; 65 66static const struct token t_main[] = { 67 {KEYWORD, "monitor", MONITOR, NULL}, 68 {KEYWORD, "show", NONE, t_show}, 69 {KEYWORD, "poll", POLL, NULL}, 70 {KEYWORD, "reload", RELOAD, NULL}, 71 {KEYWORD, "stop", SHUTDOWN, NULL}, 72 {KEYWORD, "service", NONE, t_service}, 73 {KEYWORD, "table", NONE, t_table}, 74 {KEYWORD, "host", NONE, t_host}, 75 {ENDTOKEN, "", NONE, NULL} 76}; 77 78static const struct token t_show[] = { 79 {KEYWORD, "summary", SHOW_SUM, NULL}, 80 {KEYWORD, "hosts", SHOW_HOSTS, NULL}, 81 {KEYWORD, "relays", SHOW_RELAYS, NULL}, 82 {KEYWORD, "sessions", SHOW_SESSIONS, NULL}, 83 {ENDTOKEN, "", NONE, NULL} 84}; 85 86static const struct token t_service[] = { 87 {NOTOKEN, "", NONE, NULL}, 88 {KEYWORD, "disable", SERV_DISABLE, t_service_id}, 89 {KEYWORD, "enable", SERV_ENABLE, t_service_id}, 90 {ENDTOKEN, "", NONE, NULL} 91}; 92 93static const struct token t_table[] = { 94 {NOTOKEN, "", NONE, NULL}, 95 {KEYWORD, "disable", TABLE_DISABLE, t_table_id}, 96 {KEYWORD, "enable", TABLE_ENABLE, t_table_id}, 97 {ENDTOKEN, "", NONE, NULL} 98}; 99 100static const struct token t_host[] = { 101 {NOTOKEN, "", NONE, NULL}, 102 {KEYWORD, "disable", HOST_DISABLE, t_host_id}, 103 {KEYWORD, "enable", HOST_ENABLE, t_host_id}, 104 {ENDTOKEN, "", NONE, NULL} 105}; 106 107static const struct token t_service_id[] = { 108 {SERVICEID, "", NONE, NULL}, 109 {ENDTOKEN, "", NONE, NULL} 110}; 111 112static const struct token t_table_id[] = { 113 {TABLEID, "", NONE, NULL}, 114 {ENDTOKEN, "", NONE, NULL} 115}; 116 117static const struct token t_host_id[] = { 118 {HOSTID, "", NONE, NULL}, 119 {ENDTOKEN, "", NONE, NULL} 120}; 121 122static struct parse_result res; 123 124struct parse_result * 125parse(int argc, char *argv[]) 126{ 127 const struct token *table = t_main; 128 const struct token *match; 129 130 bzero(&res, sizeof(res)); 131 132 while (argc >= 0) { 133 if ((match = match_token(argv[0], table)) == NULL) { 134 fprintf(stderr, "valid commands/args:\n"); 135 show_valid_args(table); 136 return (NULL); 137 } 138 139 argc--; 140 argv++; 141 142 if (match->type == NOTOKEN || match->next == NULL) 143 break; 144 145 table = match->next; 146 } 147 148 if (argc > 0) { 149 fprintf(stderr, "superfluous argument: %s\n", argv[0]); 150 return (NULL); 151 } 152 153 return (&res); 154} 155 156const struct token * 157match_token(const char *word, const struct token table[]) 158{ 159 u_int i, match; 160 const struct token *t = NULL; 161 const char *errstr; 162 163 match = 0; 164 165 for (i = 0; table[i].type != ENDTOKEN; i++) { 166 switch (table[i].type) { 167 case NOTOKEN: 168 if (word == NULL || strlen(word) == 0) { 169 match++; 170 t = &table[i]; 171 } 172 break; 173 case KEYWORD: 174 if (word != NULL && strncmp(word, table[i].keyword, 175 strlen(word)) == 0) { 176 match++; 177 t = &table[i]; 178 if (t->value) 179 res.action = t->value; 180 } 181 break; 182 case HOSTID: 183 if (word == NULL) 184 break; 185 res.id.id = strtonum(word, 0, UINT_MAX, &errstr); 186 if (errstr) { 187 strlcpy(res.id.name, word, sizeof(res.id.name)); 188 res.id.id = EMPTY_ID; 189 } 190 t = &table[i]; 191 match++; 192 break; 193 case TABLEID: 194 if (word == NULL) 195 break; 196 res.id.id = strtonum(word, 0, UINT_MAX, &errstr); 197 if (errstr) { 198 strlcpy(res.id.name, word, sizeof(res.id.name)); 199 res.id.id = EMPTY_ID; 200 } 201 t = &table[i]; 202 match++; 203 break; 204 case SERVICEID: 205 if (word == NULL) 206 break; 207 res.id.id = strtonum(word, 0, UINT_MAX, &errstr); 208 if (errstr) { 209 strlcpy(res.id.name, word, sizeof(res.id.name)); 210 res.id.id = EMPTY_ID; 211 } 212 t = &table[i]; 213 match++; 214 break; 215 case ENDTOKEN: 216 break; 217 } 218 } 219 220 if (match != 1) { 221 if (word == NULL) 222 fprintf(stderr, "missing argument:\n"); 223 else if (match > 1) 224 fprintf(stderr, "ambiguous argument: %s\n", word); 225 else if (match < 1) 226 fprintf(stderr, "unknown argument: %s\n", word); 227 return (NULL); 228 } 229 230 return (t); 231} 232 233void 234show_valid_args(const struct token table[]) 235{ 236 int i; 237 238 for (i = 0; table[i].type != ENDTOKEN; i++) { 239 switch (table[i].type) { 240 case NOTOKEN: 241 fprintf(stderr, " <cr>\n"); 242 break; 243 case KEYWORD: 244 fprintf(stderr, " %s\n", table[i].keyword); 245 break; 246 case SERVICEID: 247 fprintf(stderr, " <serviceid>\n"); 248 break; 249 case TABLEID: 250 fprintf(stderr, " <tableid>\n"); 251 break; 252 case HOSTID: 253 fprintf(stderr, " <hostid>\n"); 254 break; 255 case ENDTOKEN: 256 break; 257 } 258 } 259} 260