Merge branch 'master' of ssh://crater.dragonflybsd.org/repository/git/dragonfly
[dragonfly.git] / sbin / dhclient / conflex.c
bloba4698e15acb399e4aff022f9efd193713fa75249
1 /* $OpenBSD: conflex.c,v 1.13 2006/12/17 17:41:56 stevesk Exp $ */
2 /* $DragonFly: src/sbin/dhclient/conflex.c,v 1.1 2008/08/30 16:07:58 hasso Exp $ */
4 /* Lexical scanner for dhclient config file... */
6 /*
7 * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium.
8 * All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of The Internet Software Consortium nor the names
20 * of its contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
24 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
31 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
34 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
37 * This software has been written for the Internet Software Consortium
38 * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
39 * Enterprises. To learn more about the Internet Software Consortium,
40 * see ``http://www.vix.com/isc''. To learn more about Vixie
41 * Enterprises, see ``http://www.vix.com''.
44 #include <ctype.h>
46 #include "dhcpd.h"
47 #include "dhctoken.h"
49 int lexline;
50 int lexchar;
51 char *token_line;
52 char *prev_line;
53 char *cur_line;
54 char *tlname;
56 static char line1[81];
57 static char line2[81];
58 static uint lpos;
59 static int line;
60 static int tlpos;
61 static int tline;
62 static int token;
63 static int ugflag;
64 static char *tval;
65 static char tokbuf[1500];
67 static int get_char(FILE *);
68 static int get_token(FILE *);
69 static void skip_to_eol(FILE *);
70 static int read_string(FILE *);
71 static int read_number(int, FILE *);
72 static int read_num_or_name(int, FILE *);
73 int kw_cmp(const void *, const void *);
74 static int intern(char *, int);
76 void
77 new_parse(char *name)
79 tlname = name;
80 lpos = line = 1;
81 cur_line = line1;
82 prev_line = line2;
83 token_line = cur_line;
84 cur_line[0] = prev_line[0] = 0;
85 warnings_occurred = 0;
88 static int
89 get_char(FILE *cfile)
91 int c = getc(cfile);
92 if (!ugflag) {
93 if (c == '\n') {
94 if (cur_line == line1) {
95 cur_line = line2;
96 prev_line = line1;
97 } else {
98 cur_line = line2;
99 prev_line = line1;
101 line++;
102 lpos = 1;
103 cur_line[0] = 0;
104 } else if (c != EOF) {
105 if (lpos < sizeof(line1)) {
106 cur_line[lpos - 1] = c;
107 cur_line[lpos] = 0;
109 lpos++;
111 } else
112 ugflag = 0;
113 return (c);
116 static int
117 get_token(FILE *cfile)
119 int c, ttok;
120 static char tb[2];
121 int l, p;
123 do {
124 l = line;
125 p = lpos;
127 c = get_char(cfile);
129 if (isascii(c) && isspace(c))
130 continue;
131 if (c == '#') {
132 skip_to_eol(cfile);
133 continue;
135 if (c == '"') {
136 lexline = l;
137 lexchar = p;
138 ttok = read_string(cfile);
139 break;
141 if ((isascii(c) && isdigit(c)) || c == '-') {
142 lexline = l;
143 lexchar = p;
144 ttok = read_number(c, cfile);
145 break;
146 } else if (isascii(c) && isalpha(c)) {
147 lexline = l;
148 lexchar = p;
149 ttok = read_num_or_name(c, cfile);
150 break;
151 } else {
152 lexline = l;
153 lexchar = p;
154 tb[0] = c;
155 tb[1] = 0;
156 tval = tb;
157 ttok = c;
158 break;
160 } while (1);
161 return (ttok);
165 next_token(char **rval, FILE *cfile)
167 int rv;
169 if (token) {
170 if (lexline != tline)
171 token_line = cur_line;
172 lexchar = tlpos;
173 lexline = tline;
174 rv = token;
175 token = 0;
176 } else {
177 rv = get_token(cfile);
178 token_line = cur_line;
180 if (rval)
181 *rval = tval;
183 return (rv);
187 peek_token(char **rval, FILE *cfile)
189 int x;
191 if (!token) {
192 tlpos = lexchar;
193 tline = lexline;
194 token = get_token(cfile);
195 if (lexline != tline)
196 token_line = prev_line;
197 x = lexchar;
198 lexchar = tlpos;
199 tlpos = x;
200 x = lexline;
201 lexline = tline;
202 tline = x;
204 if (rval)
205 *rval = tval;
207 return (token);
210 static void
211 skip_to_eol(FILE *cfile)
213 int c;
215 do {
216 c = get_char(cfile);
217 if (c == EOF)
218 return;
219 if (c == '\n')
220 return;
221 } while (1);
224 static int
225 read_string(FILE *cfile)
227 uint i;
228 int c, bs = 0;
230 for (i = 0; i < sizeof(tokbuf); i++) {
231 c = get_char(cfile);
232 if (c == EOF) {
233 parse_warn("eof in string constant");
234 break;
236 if (bs) {
237 bs = 0;
238 tokbuf[i] = c;
239 } else if (c == '\\')
240 bs = 1;
241 else if (c == '"')
242 break;
243 else
244 tokbuf[i] = c;
247 * Normally, I'd feel guilty about this, but we're talking about
248 * strings that'll fit in a DHCP packet here...
250 if (i == sizeof(tokbuf)) {
251 parse_warn("string constant larger than internal buffer");
252 i--;
254 tokbuf[i] = 0;
255 tval = tokbuf;
256 return (TOK_STRING);
259 static int
260 read_number(int c, FILE *cfile)
262 uint i = 0;
263 int seenx = 0, token = TOK_NUMBER;
265 tokbuf[i++] = c;
266 for (; i < sizeof(tokbuf); i++) {
267 c = get_char(cfile);
268 if (!seenx && c == 'x')
269 seenx = 1;
270 else if (!isascii(c) || !isxdigit(c)) {
271 ungetc(c, cfile);
272 ugflag = 1;
273 break;
275 tokbuf[i] = c;
277 if (i == sizeof(tokbuf)) {
278 parse_warn("numeric token larger than internal buffer");
279 i--;
281 tokbuf[i] = 0;
282 tval = tokbuf;
284 return (token);
287 static int
288 read_num_or_name(int c, FILE *cfile)
290 uint i = 0;
291 int rv = TOK_NUMBER_OR_NAME;
293 tokbuf[i++] = c;
294 for (; i < sizeof(tokbuf); i++) {
295 c = get_char(cfile);
296 if (!isascii(c) || (c != '-' && c != '_' && !isalnum(c))) {
297 ungetc(c, cfile);
298 ugflag = 1;
299 break;
301 if (!isxdigit(c))
302 rv = TOK_NAME;
303 tokbuf[i] = c;
305 if (i == sizeof(tokbuf)) {
306 parse_warn("token larger than internal buffer");
307 i--;
309 tokbuf[i] = 0;
310 tval = tokbuf;
312 return (intern(tval, rv));
315 static const struct keywords {
316 const char *k_name;
317 int k_val;
318 } keywords[] = {
319 { "alias", TOK_ALIAS },
320 { "append", TOK_APPEND },
321 { "backoff-cutoff", TOK_BACKOFF_CUTOFF },
322 { "bootp", TOK_BOOTP },
323 { "default", TOK_DEFAULT },
324 { "deny", TOK_DENY },
325 { "ethernet", TOK_ETHERNET },
326 { "expire", TOK_EXPIRE },
327 { "fddi", TOK_FDDI },
328 { "filename", TOK_FILENAME },
329 { "fixed-address", TOK_FIXED_ADDR },
330 { "hardware", TOK_HARDWARE },
331 { "initial-interval", TOK_INITIAL_INTERVAL },
332 { "interface", TOK_INTERFACE },
333 { "lease", TOK_LEASE },
334 { "link-timeout", TOK_LINK_TIMEOUT },
335 { "media", TOK_MEDIA },
336 { "medium", TOK_MEDIUM },
337 { "option", TOK_OPTION },
338 { "prepend", TOK_PREPEND },
339 { "rebind", TOK_REBIND },
340 { "reboot", TOK_REBOOT },
341 { "reject", TOK_REJECT },
342 { "renew", TOK_RENEW },
343 { "request", TOK_REQUEST },
344 { "require", TOK_REQUIRE },
345 { "retry", TOK_RETRY },
346 { "script", TOK_SCRIPT },
347 { "select-timeout", TOK_SELECT_TIMEOUT },
348 { "send", TOK_SEND },
349 { "server-name", TOK_SERVER_NAME },
350 { "supersede", TOK_SUPERSEDE },
351 { "timeout", TOK_TIMEOUT },
352 { "token-ring", TOK_TOKEN_RING }
356 kw_cmp(const void *k, const void *e)
358 return (strcasecmp(k, ((const struct keywords *)e)->k_name));
361 static int
362 intern(char *atom, int dfv)
364 const struct keywords *p;
366 p = bsearch(atom, keywords, sizeof(keywords)/sizeof(keywords[0]),
367 sizeof(keywords[0]), kw_cmp);
368 if (p)
369 return (p->k_val);
370 return (dfv);