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