keama.c revision 1.1 1 /* $NetBSD: keama.c,v 1.1 2020/08/03 21:09:08 christos Exp $ */
2
3 /*
4 * Copyright(c) 2017-2019 by Internet Systems Consortium, Inc.("ISC")
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
16 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * Internet Systems Consortium, Inc.
19 * 950 Charter Street
20 * Redwood City, CA 94063
21 * <info (at) isc.org>
22 * https://www.isc.org/
23 *
24 */
25
26 #include <sys/cdefs.h>
27 __RCSID("$NetBSD: keama.c,v 1.1 2020/08/03 21:09:08 christos Exp $");
28
29 #include <sys/errno.h>
30 #include <arpa/inet.h>
31 #include <assert.h>
32 #include <fcntl.h>
33 #include <stdarg.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37
38 #include "keama.h"
39
40 #define KEAMA_USAGE "Usage: keama [-4|-6] [-D] [-N]" \
41 " [-r {perform|fatal|pass}\\n" \
42 " [-l hook-library-path]" \
43 " [-i input-file] [-o output-file]\n"
44
45 static void
46 usage(const char *sfmt, const char *sarg) {
47 if (sfmt != NULL) {
48 fprintf(stderr, sfmt, sarg);
49 fprintf(stderr, "\n");
50 }
51 fputs(KEAMA_USAGE, stderr);
52 exit(1);
53 }
54
55 int local_family = 0;
56 char *hook_library_path = NULL;
57 char *input_file = NULL;
58 char *output_file = NULL;
59 FILE *input = NULL;
60 FILE *output = NULL;
61 isc_boolean_t use_isc_lifetimes = ISC_FALSE;
62 isc_boolean_t global_hr = ISC_TRUE;
63 isc_boolean_t json = ISC_FALSE;
64
65 static const char use_noarg[] = "No argument for command: %s";
66 static const char bad_resolve[] = "Bad -r argument: %s";
67
68 int
69 main(int argc, char **argv) {
70 int i, fd;
71 char *inbuf = NULL;
72 size_t oldsize = 0;
73 size_t newsize = 0;
74 ssize_t cc;
75 struct parse *cfile;
76 size_t cnt = 0;
77
78 for (i = 1; i < argc; i++) {
79 if (strcmp(argv[i], "-4") == 0)
80 local_family = AF_INET;
81 else if (strcmp(argv[i], "-6") == 0)
82 local_family = AF_INET6;
83 else if (strcmp(argv[i], "-D") == 0)
84 use_isc_lifetimes = ISC_TRUE;
85 else if (strcmp(argv[i], "-N") == 0)
86 global_hr = ISC_FALSE;
87 else if (strcmp(argv[i], "-T") == 0)
88 json = ISC_TRUE;
89 else if (strcmp(argv[i], "-r") == 0) {
90 if (++i == argc)
91 usage(use_noarg, argv[i - 1]);
92 if (strcmp(argv[i], "perform") == 0)
93 resolve = perform;
94 else if (strcmp(argv[i], "fatal") == 0)
95 resolve = fatal;
96 else if (strcmp(argv[i], "pass") == 0)
97 resolve = pass;
98 else
99 usage(bad_resolve, argv[i]);
100 } else if (strcmp(argv[i], "-l") == 0) {
101 if (++i == argc)
102 usage(use_noarg, argv[i - 1]);
103 hook_library_path = argv[i];
104 } else if (strcmp(argv[i], "-i") == 0) {
105 if (++i == argc)
106 usage(use_noarg, argv[i - 1]);
107 input_file = argv[i];
108 } else if (strcmp(argv[i], "-o") == 0) {
109 if (++i == argc)
110 usage(use_noarg, argv[i - 1]);
111 output_file = argv[i];
112 } else
113 usage("Unknown command: %s", argv[i]);
114 }
115
116 if (!json && (local_family == 0))
117 usage("address family must be set using %s", "-4 or -6");
118
119 if (input_file == NULL) {
120 input_file = "--stdin--";
121 fd = fileno(stdin);
122 for (;;) {
123 if (newsize == 0)
124 newsize = 1024;
125 else {
126 oldsize = newsize;
127 newsize *= 4;
128 }
129 inbuf = (char *)realloc(inbuf, newsize);
130 if (inbuf == 0)
131 usage("out of memory reading standard "
132 "input: %s", strerror(errno));
133 cc = read(fd, inbuf + oldsize, newsize - oldsize);
134 if (cc < 0)
135 usage("error reading standard input: %s",
136 strerror(errno));
137 if (cc + oldsize < newsize) {
138 newsize = cc + oldsize;
139 break;
140 }
141 }
142 } else {
143 fd = open(input_file, O_RDONLY);
144 if (fd < 0)
145 usage("Cannot open '%s' for reading", input_file);
146 }
147
148 if (output_file) {
149 output = fopen(output_file, "w");
150 if (output == NULL)
151 usage("Cannot open '%s' for writing", output_file);
152 } else
153 output = stdout;
154
155 TAILQ_INIT(&parses);
156 cfile = new_parse(fd, inbuf, newsize, input_file, 0);
157 assert(cfile != NULL);
158
159 if (json) {
160 struct element *elem;
161
162 elem = json_parse(cfile);
163 if (elem != NULL) {
164 print(output, elem, 0, 0);
165 fprintf(output, "\n");
166 }
167 } else {
168 spaces_init();
169 options_init();
170 cnt = conf_file_parse(cfile);
171 if (cfile->stack_top > 0) {
172 print(output, cfile->stack[0], 0, 0);
173 fprintf(output, "\n");
174 }
175 }
176
177 end_parse(cfile);
178
179 exit(cnt);
180 }
181
182 void
183 stackPush(struct parse *pc, struct element *elem)
184 {
185 if (pc->stack_top + 2 >= pc->stack_size) {
186 size_t new_size = pc->stack_size + 10;
187 size_t amount = new_size * sizeof(struct element *);
188
189 pc->stack = (struct element **)realloc(pc->stack, amount);
190 if (pc->stack == NULL)
191 parse_error(pc, "can't resize element stack");
192 pc->stack_size = new_size;
193 }
194 pc->stack_top++;
195 pc->stack[pc->stack_top] = elem;
196 }
197
198 void
199 parse_error(struct parse *cfile, const char *fmt, ...)
200 {
201 va_list list;
202 char lexbuf[256];
203 char mbuf[1024];
204 char fbuf[1024];
205 unsigned i, lix;
206
207 snprintf(fbuf, sizeof(fbuf), "%s line %d: %s",
208 cfile->tlname, cfile->lexline, fmt);
209
210 va_start(list, fmt);
211 vsnprintf(mbuf, sizeof(mbuf), fbuf, list);
212 va_end(list);
213
214 lix = 0;
215 for (i = 0;
216 cfile->token_line[i] && i < (cfile->lexchar - 1); i++) {
217 if (lix < sizeof(lexbuf) - 1)
218 lexbuf[lix++] = ' ';
219 if (cfile->token_line[i] == '\t') {
220 for (; lix < (sizeof lexbuf) - 1 && (lix & 7); lix++)
221 lexbuf[lix] = ' ';
222 }
223 }
224 lexbuf[lix] = 0;
225
226 fprintf(stderr, "%s\n%s\n", mbuf, cfile->token_line);
227 if (cfile->lexchar < 81)
228 fprintf(stderr, "%s^\n", lexbuf);
229 exit(-1);
230 }
231