kernel - Fix races created by a comedy of circumstansces (3)
[dragonfly.git] / sbin / dhclient / conflex.c
blob6505091485a41f0214c7d9d9c14853eb55c09e2e
1 /* $OpenBSD: src/sbin/dhclient/conflex.c,v 1.15 2012/08/22 00:14:42 tedu Exp $ */
3 /* Lexical scanner for dhclient config file... */
5 /*
6 * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium.
7 * All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The Internet Software Consortium nor the names
19 * of its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
36 * This software has been written for the Internet Software Consortium
37 * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
38 * Enterprises. To learn more about the Internet Software Consortium,
39 * see ``http://www.vix.com/isc''. To learn more about Vixie
40 * Enterprises, see ``http://www.vix.com''.
43 #include <ctype.h>
45 #include "dhcpd.h"
46 #include "dhctoken.h"
48 int lexline;
49 int lexchar;
50 char *token_line;
51 char *prev_line;
52 char *cur_line;
53 char *tlname;
55 static char line1[81];
56 static char line2[81];
57 static uint lpos;
58 static int line;
59 static int tlpos;
60 static int tline;
61 static int token;
62 static int ugflag;
63 static char *tval;
64 static char tokbuf[1500];
66 static int get_char(FILE *);
67 static int get_token(FILE *);
68 static void skip_to_eol(FILE *);
69 static int read_string(FILE *);
70 static int read_number(int, FILE *);
71 static int read_num_or_name(int, FILE *);
72 int kw_cmp(const void *, const void *);
73 static int intern(char *, int);
75 void
76 new_parse(char *name)
79 * Initialize all parsing state, as we are starting to parse a
80 * new file, 'name'.
83 bzero(line1, sizeof(line1));
84 bzero(line2, sizeof(line2));
85 bzero(tokbuf, sizeof(tokbuf));
87 lpos = line = 1;
88 tlpos = tline = token = ugflag = 0;
89 tval = NULL;
91 lexline = lexchar = 0;
92 cur_line = line1;
93 prev_line = line2;
94 token_line = cur_line;
95 tlname = name;
97 warnings_occurred = 0;
100 static int
101 get_char(FILE *cfile)
103 int c = getc(cfile);
104 if (!ugflag) {
105 if (c == '\n') {
106 if (cur_line == line1) {
107 cur_line = line2;
108 prev_line = line1;
109 } else {
110 cur_line = line2;
111 prev_line = line1;
113 line++;
114 lpos = 1;
115 cur_line[0] = 0;
116 } else if (c != EOF) {
117 if (lpos < sizeof(line1)) {
118 cur_line[lpos - 1] = c;
119 cur_line[lpos] = 0;
121 lpos++;
123 } else
124 ugflag = 0;
125 return (c);
128 static int
129 get_token(FILE *cfile)
131 int c, ttok;
132 static char tb[2];
133 int l, p;
135 do {
136 l = line;
137 p = lpos;
139 c = get_char(cfile);
141 if (isascii(c) && isspace(c))
142 continue;
143 if (c == '#') {
144 skip_to_eol(cfile);
145 continue;
147 if (c == '"') {
148 lexline = l;
149 lexchar = p;
150 ttok = read_string(cfile);
151 break;
153 if ((isascii(c) && isdigit(c)) || c == '-') {
154 lexline = l;
155 lexchar = p;
156 ttok = read_number(c, cfile);
157 break;
158 } else if (isascii(c) && isalpha(c)) {
159 lexline = l;
160 lexchar = p;
161 ttok = read_num_or_name(c, cfile);
162 break;
163 } else {
164 lexline = l;
165 lexchar = p;
166 tb[0] = c;
167 tb[1] = 0;
168 tval = tb;
169 ttok = c;
170 break;
172 } while (1);
173 return (ttok);
177 next_token(char **rval, FILE *cfile)
179 int rv;
181 if (token) {
182 if (lexline != tline)
183 token_line = cur_line;
184 lexchar = tlpos;
185 lexline = tline;
186 rv = token;
187 token = 0;
188 } else {
189 rv = get_token(cfile);
190 token_line = cur_line;
192 if (rval)
193 *rval = tval;
195 return (rv);
199 peek_token(char **rval, FILE *cfile)
201 int x;
203 if (!token) {
204 tlpos = lexchar;
205 tline = lexline;
206 token = get_token(cfile);
207 if (lexline != tline)
208 token_line = prev_line;
209 x = lexchar;
210 lexchar = tlpos;
211 tlpos = x;
212 x = lexline;
213 lexline = tline;
214 tline = x;
216 if (rval)
217 *rval = tval;
219 return (token);
222 static void
223 skip_to_eol(FILE *cfile)
225 int c;
227 do {
228 c = get_char(cfile);
229 if (c == EOF)
230 return;
231 if (c == '\n')
232 return;
233 } while (1);
236 static int
237 read_string(FILE *cfile)
239 uint i;
240 int c, bs = 0;
242 for (i = 0; i < sizeof(tokbuf); i++) {
243 c = get_char(cfile);
244 if (c == EOF) {
245 parse_warn("eof in string constant");
246 break;
248 if (bs) {
249 bs = 0;
250 tokbuf[i] = c;
251 } else if (c == '\\')
252 bs = 1;
253 else if (c == '"')
254 break;
255 else
256 tokbuf[i] = c;
259 * Normally, I'd feel guilty about this, but we're talking about
260 * strings that'll fit in a DHCP packet here...
262 if (i == sizeof(tokbuf)) {
263 parse_warn("string constant larger than internal buffer");
264 i--;
266 tokbuf[i] = 0;
267 tval = tokbuf;
268 return (TOK_STRING);
271 static int
272 read_number(int c, FILE *cfile)
274 uint i = 0;
275 int seenx = 0, token = TOK_NUMBER;
277 tokbuf[i++] = c;
278 for (; i < sizeof(tokbuf); i++) {
279 c = get_char(cfile);
280 if (!seenx && c == 'x')
281 seenx = 1;
282 else if (!isascii(c) || !isxdigit(c)) {
283 ungetc(c, cfile);
284 ugflag = 1;
285 break;
287 tokbuf[i] = c;
289 if (i == sizeof(tokbuf)) {
290 parse_warn("numeric token larger than internal buffer");
291 i--;
293 tokbuf[i] = 0;
294 tval = tokbuf;
296 return (token);
299 static int
300 read_num_or_name(int c, FILE *cfile)
302 uint i = 0;
303 int rv = TOK_NUMBER_OR_NAME;
305 tokbuf[i++] = c;
306 for (; i < sizeof(tokbuf); i++) {
307 c = get_char(cfile);
308 if (!isascii(c) || (c != '-' && c != '_' && !isalnum(c))) {
309 ungetc(c, cfile);
310 ugflag = 1;
311 break;
313 if (!isxdigit(c))
314 rv = TOK_NAME;
315 tokbuf[i] = c;
317 if (i == sizeof(tokbuf)) {
318 parse_warn("token larger than internal buffer");
319 i--;
321 tokbuf[i] = 0;
322 tval = tokbuf;
324 return (intern(tval, rv));
327 static const struct keywords {
328 const char *k_name;
329 int k_val;
330 } keywords[] = {
331 { "alias", TOK_ALIAS },
332 { "append", TOK_APPEND },
333 { "backoff-cutoff", TOK_BACKOFF_CUTOFF },
334 { "bootp", TOK_BOOTP },
335 { "default", TOK_DEFAULT },
336 { "deny", TOK_DENY },
337 { "ethernet", TOK_ETHERNET },
338 { "expire", TOK_EXPIRE },
339 { "fddi", TOK_FDDI },
340 { "filename", TOK_FILENAME },
341 { "fixed-address", TOK_FIXED_ADDR },
342 { "hardware", TOK_HARDWARE },
343 { "ignore", TOK_IGNORE },
344 { "initial-interval", TOK_INITIAL_INTERVAL },
345 { "interface", TOK_INTERFACE },
346 { "lease", TOK_LEASE },
347 { "link-timeout", TOK_LINK_TIMEOUT },
348 { "media", TOK_MEDIA },
349 { "medium", TOK_MEDIUM },
350 { "option", TOK_OPTION },
351 { "prepend", TOK_PREPEND },
352 { "rebind", TOK_REBIND },
353 { "reboot", TOK_REBOOT },
354 { "reject", TOK_REJECT },
355 { "renew", TOK_RENEW },
356 { "request", TOK_REQUEST },
357 { "require", TOK_REQUIRE },
358 { "retry", TOK_RETRY },
359 { "script", TOK_SCRIPT },
360 { "select-timeout", TOK_SELECT_TIMEOUT },
361 { "send", TOK_SEND },
362 { "server-name", TOK_SERVER_NAME },
363 { "supersede", TOK_SUPERSEDE },
364 { "timeout", TOK_TIMEOUT },
365 { "token-ring", TOK_TOKEN_RING }
369 kw_cmp(const void *k, const void *e)
371 return (strcasecmp(k, ((const struct keywords *)e)->k_name));
374 static int
375 intern(char *atom, int dfv)
377 const struct keywords *p;
379 p = bsearch(atom, keywords, sizeof(keywords)/sizeof(keywords[0]),
380 sizeof(keywords[0]), kw_cmp);
381 if (p)
382 return (p->k_val);
383 return (dfv);