parser.c revision 1.13
1/* $OpenBSD: parser.c,v 1.13 2007/09/28 13:29:56 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", NULL, t_show}, 69 {KEYWORD, "reload", RELOAD, NULL}, 70 {KEYWORD, "stop", SHUTDOWN, NULL}, 71 {KEYWORD, "service", NONE, t_service}, 72 {KEYWORD, "table", NONE, t_table}, 73 {KEYWORD, "host", NONE, t_host}, 74 {ENDTOKEN, "", NONE, NULL} 75}; 76 77static const struct token t_show[] = { 78 {KEYWORD, "summary", SHOW_SUM, NULL}, 79 {KEYWORD, "hosts", SHOW_HOSTS, NULL}, 80 {KEYWORD, "relays", SHOW_RELAYS, NULL}, 81 {KEYWORD, "sessions", SHOW_SESSIONS, NULL}, 82 {ENDTOKEN, "", NONE, NULL} 83}; 84 85static const struct token t_service[] = { 86 {NOTOKEN, "", NONE, NULL}, 87 {KEYWORD, "disable", SERV_DISABLE, t_service_id}, 88 {KEYWORD, "enable", SERV_ENABLE, t_service_id}, 89 {ENDTOKEN, "", NONE, NULL} 90}; 91 92static const struct token t_table[] = { 93 {NOTOKEN, "", NONE, NULL}, 94 {KEYWORD, "disable", TABLE_DISABLE, t_table_id}, 95 {KEYWORD, "enable", TABLE_ENABLE, t_table_id}, 96 {ENDTOKEN, "", NONE, NULL} 97}; 98 99static const struct token t_host[] = { 100 {NOTOKEN, "", NONE, NULL}, 101 {KEYWORD, "disable", HOST_DISABLE, t_host_id}, 102 {KEYWORD, "enable", HOST_ENABLE, t_host_id}, 103 {ENDTOKEN, "", NONE, NULL} 104}; 105 106static const struct token t_service_id[] = { 107 {SERVICEID, "", NONE, NULL}, 108 {ENDTOKEN, "", NONE, NULL} 109}; 110 111static const struct token t_table_id[] = { 112 {TABLEID, "", NONE, NULL}, 113 {ENDTOKEN, "", NONE, NULL} 114}; 115 116static const struct token t_host_id[] = { 117 {HOSTID, "", NONE, NULL}, 118 {ENDTOKEN, "", NONE, NULL} 119}; 120 121static struct parse_result res; 122 123struct parse_result * 124parse(int argc, char *argv[]) 125{ 126 const struct token *table = t_main; 127 const struct token *match; 128 129 bzero(&res, sizeof(res)); 130 131 while (argc >= 0) { 132 if ((match = match_token(argv[0], table)) == NULL) { 133 fprintf(stderr, "valid commands/args:\n"); 134 show_valid_args(table); 135 return (NULL); 136 } 137 138 argc--; 139 argv++; 140 141 if (match->type == NOTOKEN || match->next == NULL) 142 break; 143 144 table = match->next; 145 } 146 147 if (argc > 0) { 148 fprintf(stderr, "superfluous argument: %s\n", argv[0]); 149 return (NULL); 150 } 151 152 return (&res); 153} 154 155const struct token * 156match_token(const char *word, const struct token table[]) 157{ 158 u_int i, match; 159 const struct token *t = NULL; 160 const char *errstr; 161 162 match = 0; 163 164 for (i = 0; table[i].type != ENDTOKEN; i++) { 165 switch (table[i].type) { 166 case NOTOKEN: 167 if (word == NULL || strlen(word) == 0) { 168 match++; 169 t = &table[i]; 170 } 171 break; 172 case KEYWORD: 173 if (word != NULL && strncmp(word, table[i].keyword, 174 strlen(word)) == 0) { 175 match++; 176 t = &table[i]; 177 if (t->value) 178 res.action = t->value; 179 } 180 break; 181 case HOSTID: 182 if (word == NULL) 183 break; 184 res.id.id = strtonum(word, 0, UINT_MAX, &errstr); 185 if (errstr) { 186 strlcpy(res.id.name, word, sizeof(res.id.name)); 187 res.id.id = EMPTY_ID; 188 } 189 t = &table[i]; 190 match++; 191 break; 192 case TABLEID: 193 if (word == NULL) 194 break; 195 res.id.id = strtonum(word, 0, UINT_MAX, &errstr); 196 if (errstr) { 197 strlcpy(res.id.name, word, sizeof(res.id.name)); 198 res.id.id = EMPTY_ID; 199 } 200 t = &table[i]; 201 match++; 202 break; 203 case SERVICEID: 204 if (word == NULL) 205 break; 206 res.id.id = strtonum(word, 0, UINT_MAX, &errstr); 207 if (errstr) { 208 strlcpy(res.id.name, word, sizeof(res.id.name)); 209 res.id.id = EMPTY_ID; 210 } 211 t = &table[i]; 212 match++; 213 break; 214 case ENDTOKEN: 215 break; 216 } 217 } 218 219 if (match != 1) { 220 if (word == NULL) 221 fprintf(stderr, "missing argument:\n"); 222 else if (match > 1) 223 fprintf(stderr, "ambiguous argument: %s\n", word); 224 else if (match < 1) 225 fprintf(stderr, "unknown argument: %s\n", word); 226 return (NULL); 227 } 228 229 return (t); 230} 231 232void 233show_valid_args(const struct token table[]) 234{ 235 int i; 236 237 for (i = 0; table[i].type != ENDTOKEN; i++) { 238 switch (table[i].type) { 239 case NOTOKEN: 240 fprintf(stderr, " <cr>\n"); 241 break; 242 case KEYWORD: 243 fprintf(stderr, " %s\n", table[i].keyword); 244 break; 245 case SERVICEID: 246 fprintf(stderr, " <serviceid>\n"); 247 break; 248 case TABLEID: 249 fprintf(stderr, " <tableid>\n"); 250 break; 251 case HOSTID: 252 fprintf(stderr, " <hostid>\n"); 253 break; 254 case ENDTOKEN: 255 break; 256 } 257 } 258} 259