147c08596SBrooks Davis /* $OpenBSD: parse.c,v 1.11 2004/05/05 23:07:47 deraadt Exp $ */
247c08596SBrooks Davis
347c08596SBrooks Davis /* Common parser code for dhcpd and dhclient. */
447c08596SBrooks Davis
58a16b7a1SPedro F. Giffuni /*-
68a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
78a16b7a1SPedro F. Giffuni *
847c08596SBrooks Davis * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium.
947c08596SBrooks Davis * All rights reserved.
1047c08596SBrooks Davis *
1147c08596SBrooks Davis * Redistribution and use in source and binary forms, with or without
1247c08596SBrooks Davis * modification, are permitted provided that the following conditions
1347c08596SBrooks Davis * are met:
1447c08596SBrooks Davis *
1547c08596SBrooks Davis * 1. Redistributions of source code must retain the above copyright
1647c08596SBrooks Davis * notice, this list of conditions and the following disclaimer.
1747c08596SBrooks Davis * 2. Redistributions in binary form must reproduce the above copyright
1847c08596SBrooks Davis * notice, this list of conditions and the following disclaimer in the
1947c08596SBrooks Davis * documentation and/or other materials provided with the distribution.
2047c08596SBrooks Davis * 3. Neither the name of The Internet Software Consortium nor the names
2147c08596SBrooks Davis * of its contributors may be used to endorse or promote products derived
2247c08596SBrooks Davis * from this software without specific prior written permission.
2347c08596SBrooks Davis *
2447c08596SBrooks Davis * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
2547c08596SBrooks Davis * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
2647c08596SBrooks Davis * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2747c08596SBrooks Davis * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2847c08596SBrooks Davis * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
2947c08596SBrooks Davis * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3047c08596SBrooks Davis * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3147c08596SBrooks Davis * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
3247c08596SBrooks Davis * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
3347c08596SBrooks Davis * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
3447c08596SBrooks Davis * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
3547c08596SBrooks Davis * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3647c08596SBrooks Davis * SUCH DAMAGE.
3747c08596SBrooks Davis *
3847c08596SBrooks Davis * This software has been written for the Internet Software Consortium
3947c08596SBrooks Davis * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
4047c08596SBrooks Davis * Enterprises. To learn more about the Internet Software Consortium,
4147c08596SBrooks Davis * see ``http://www.vix.com/isc''. To learn more about Vixie
4247c08596SBrooks Davis * Enterprises, see ``http://www.vix.com''.
4347c08596SBrooks Davis */
4447c08596SBrooks Davis
458794fdbbSBrooks Davis #include <sys/cdefs.h>
46066ebd56SAlan Somers #include <stdbool.h>
47066ebd56SAlan Somers
4847c08596SBrooks Davis #include "dhcpd.h"
4947c08596SBrooks Davis #include "dhctoken.h"
5047c08596SBrooks Davis
5147c08596SBrooks Davis /* Skip to the semicolon ending the current statement. If we encounter
5247c08596SBrooks Davis * braces, the matching closing brace terminates the statement. If we
5347c08596SBrooks Davis * encounter a right brace but haven't encountered a left brace, return
5447c08596SBrooks Davis * leaving the brace in the token buffer for the caller. If we see a
5547c08596SBrooks Davis * semicolon and haven't seen a left brace, return. This lets us skip
5647c08596SBrooks Davis * over:
5747c08596SBrooks Davis *
5847c08596SBrooks Davis * statement;
5947c08596SBrooks Davis * statement foo bar { }
6047c08596SBrooks Davis * statement foo bar { statement { } }
6147c08596SBrooks Davis * statement}
6247c08596SBrooks Davis *
6347c08596SBrooks Davis * ...et cetera.
6447c08596SBrooks Davis */
6547c08596SBrooks Davis void
skip_to_semi(FILE * cfile)6647c08596SBrooks Davis skip_to_semi(FILE *cfile)
6747c08596SBrooks Davis {
6847c08596SBrooks Davis int brace_count = 0, token;
6947c08596SBrooks Davis char *val;
7047c08596SBrooks Davis
7147c08596SBrooks Davis do {
7247c08596SBrooks Davis token = peek_token(&val, cfile);
7347c08596SBrooks Davis if (token == RBRACE) {
7447c08596SBrooks Davis if (brace_count) {
7547c08596SBrooks Davis token = next_token(&val, cfile);
7647c08596SBrooks Davis if (!--brace_count)
7747c08596SBrooks Davis return;
7847c08596SBrooks Davis } else
7947c08596SBrooks Davis return;
8047c08596SBrooks Davis } else if (token == LBRACE) {
8147c08596SBrooks Davis brace_count++;
8247c08596SBrooks Davis } else if (token == SEMI && !brace_count) {
8347c08596SBrooks Davis token = next_token(&val, cfile);
8447c08596SBrooks Davis return;
8547c08596SBrooks Davis } else if (token == '\n') {
8647c08596SBrooks Davis /*
8747c08596SBrooks Davis * EOL only happens when parsing
8847c08596SBrooks Davis * /etc/resolv.conf, and we treat it like a
8947c08596SBrooks Davis * semicolon because the resolv.conf file is
9047c08596SBrooks Davis * line-oriented.
9147c08596SBrooks Davis */
9247c08596SBrooks Davis token = next_token(&val, cfile);
9347c08596SBrooks Davis return;
9447c08596SBrooks Davis }
9547c08596SBrooks Davis token = next_token(&val, cfile);
9647c08596SBrooks Davis } while (token != EOF);
9747c08596SBrooks Davis }
9847c08596SBrooks Davis
9947c08596SBrooks Davis int
parse_semi(FILE * cfile)10047c08596SBrooks Davis parse_semi(FILE *cfile)
10147c08596SBrooks Davis {
10247c08596SBrooks Davis int token;
10347c08596SBrooks Davis char *val;
10447c08596SBrooks Davis
10547c08596SBrooks Davis token = next_token(&val, cfile);
10647c08596SBrooks Davis if (token != SEMI) {
10747c08596SBrooks Davis parse_warn("semicolon expected.");
10847c08596SBrooks Davis skip_to_semi(cfile);
10947c08596SBrooks Davis return (0);
11047c08596SBrooks Davis }
11147c08596SBrooks Davis return (1);
11247c08596SBrooks Davis }
11347c08596SBrooks Davis
11447c08596SBrooks Davis /*
11547c08596SBrooks Davis * string-parameter :== STRING SEMI
11647c08596SBrooks Davis */
11747c08596SBrooks Davis char *
parse_string(FILE * cfile)11847c08596SBrooks Davis parse_string(FILE *cfile)
11947c08596SBrooks Davis {
12047c08596SBrooks Davis char *val, *s;
121e2f95dd9SDimitry Andric size_t valsize;
12247c08596SBrooks Davis int token;
12347c08596SBrooks Davis
12447c08596SBrooks Davis token = next_token(&val, cfile);
12547c08596SBrooks Davis if (token != STRING) {
12647c08596SBrooks Davis parse_warn("filename must be a string");
12747c08596SBrooks Davis skip_to_semi(cfile);
12847c08596SBrooks Davis return (NULL);
12947c08596SBrooks Davis }
130e2f95dd9SDimitry Andric valsize = strlen(val) + 1;
131e2f95dd9SDimitry Andric s = malloc(valsize);
13247c08596SBrooks Davis if (!s)
13347c08596SBrooks Davis error("no memory for string %s.", val);
13478247412SDimitry Andric memcpy(s, val, valsize);
13547c08596SBrooks Davis
136bbeb726bSStephen J. Kiernan if (!parse_semi(cfile)) {
137bbeb726bSStephen J. Kiernan free(s);
13847c08596SBrooks Davis return (NULL);
139bbeb726bSStephen J. Kiernan }
14047c08596SBrooks Davis return (s);
14147c08596SBrooks Davis }
14247c08596SBrooks Davis
14347c08596SBrooks Davis int
parse_ip_addr(FILE * cfile,struct iaddr * addr)14447c08596SBrooks Davis parse_ip_addr(FILE *cfile, struct iaddr *addr)
14547c08596SBrooks Davis {
14647c08596SBrooks Davis addr->len = 4;
14747c08596SBrooks Davis if (parse_numeric_aggregate(cfile, addr->iabuf,
14847c08596SBrooks Davis &addr->len, DOT, 10, 8))
14947c08596SBrooks Davis return (1);
15047c08596SBrooks Davis return (0);
15147c08596SBrooks Davis }
15247c08596SBrooks Davis
15347c08596SBrooks Davis /*
15447c08596SBrooks Davis * hardware-parameter :== HARDWARE ETHERNET csns SEMI
15547c08596SBrooks Davis * csns :== NUMBER | csns COLON NUMBER
15647c08596SBrooks Davis */
15747c08596SBrooks Davis void
parse_hardware_param(FILE * cfile,struct hardware * hardware)15847c08596SBrooks Davis parse_hardware_param(FILE *cfile, struct hardware *hardware)
15947c08596SBrooks Davis {
16047c08596SBrooks Davis unsigned char *t;
161afe6f835SAlan Somers int token;
162afe6f835SAlan Somers size_t hlen;
16347c08596SBrooks Davis char *val;
16447c08596SBrooks Davis
16547c08596SBrooks Davis token = next_token(&val, cfile);
16647c08596SBrooks Davis switch (token) {
16747c08596SBrooks Davis case ETHERNET:
16847c08596SBrooks Davis hardware->htype = HTYPE_ETHER;
16947c08596SBrooks Davis break;
17047c08596SBrooks Davis case TOKEN_RING:
17147c08596SBrooks Davis hardware->htype = HTYPE_IEEE802;
17247c08596SBrooks Davis break;
17347c08596SBrooks Davis case FDDI:
17447c08596SBrooks Davis hardware->htype = HTYPE_FDDI;
17547c08596SBrooks Davis break;
17647c08596SBrooks Davis default:
17747c08596SBrooks Davis parse_warn("expecting a network hardware type");
17847c08596SBrooks Davis skip_to_semi(cfile);
17947c08596SBrooks Davis return;
18047c08596SBrooks Davis }
18147c08596SBrooks Davis
18247c08596SBrooks Davis /*
18347c08596SBrooks Davis * Parse the hardware address information. Technically, it
18447c08596SBrooks Davis * would make a lot of sense to restrict the length of the data
18547c08596SBrooks Davis * we'll accept here to the length of a particular hardware
18647c08596SBrooks Davis * address type. Unfortunately, there are some broken clients
18747c08596SBrooks Davis * out there that put bogus data in the chaddr buffer, and we
18847c08596SBrooks Davis * accept that data in the lease file rather than simply failing
18947c08596SBrooks Davis * on such clients. Yuck.
19047c08596SBrooks Davis */
19147c08596SBrooks Davis hlen = 0;
19247c08596SBrooks Davis t = parse_numeric_aggregate(cfile, NULL, &hlen, COLON, 16, 8);
19347c08596SBrooks Davis if (!t)
19447c08596SBrooks Davis return;
19547c08596SBrooks Davis if (hlen > sizeof(hardware->haddr)) {
19647c08596SBrooks Davis free(t);
19747c08596SBrooks Davis parse_warn("hardware address too long");
19847c08596SBrooks Davis } else {
19947c08596SBrooks Davis hardware->hlen = hlen;
20047c08596SBrooks Davis memcpy((unsigned char *)&hardware->haddr[0], t,
20147c08596SBrooks Davis hardware->hlen);
20247c08596SBrooks Davis if (hlen < sizeof(hardware->haddr))
20347c08596SBrooks Davis memset(&hardware->haddr[hlen], 0,
20447c08596SBrooks Davis sizeof(hardware->haddr) - hlen);
20547c08596SBrooks Davis free(t);
20647c08596SBrooks Davis }
20747c08596SBrooks Davis
20847c08596SBrooks Davis token = next_token(&val, cfile);
20947c08596SBrooks Davis if (token != SEMI) {
21047c08596SBrooks Davis parse_warn("expecting semicolon.");
21147c08596SBrooks Davis skip_to_semi(cfile);
21247c08596SBrooks Davis }
21347c08596SBrooks Davis }
21447c08596SBrooks Davis
21547c08596SBrooks Davis /*
21647c08596SBrooks Davis * lease-time :== NUMBER SEMI
21747c08596SBrooks Davis */
21847c08596SBrooks Davis void
parse_lease_time(FILE * cfile,time_t * timep)21947c08596SBrooks Davis parse_lease_time(FILE *cfile, time_t *timep)
22047c08596SBrooks Davis {
22147c08596SBrooks Davis char *val;
22247c08596SBrooks Davis int token;
22347c08596SBrooks Davis
22447c08596SBrooks Davis token = next_token(&val, cfile);
22547c08596SBrooks Davis if (token != NUMBER) {
22647c08596SBrooks Davis parse_warn("Expecting numeric lease time");
22747c08596SBrooks Davis skip_to_semi(cfile);
22847c08596SBrooks Davis return;
22947c08596SBrooks Davis }
23047c08596SBrooks Davis convert_num((unsigned char *)timep, val, 10, 32);
23147c08596SBrooks Davis /* Unswap the number - convert_num returns stuff in NBO. */
23247c08596SBrooks Davis *timep = ntohl(*timep); /* XXX */
23347c08596SBrooks Davis
23447c08596SBrooks Davis parse_semi(cfile);
23547c08596SBrooks Davis }
23647c08596SBrooks Davis
23747c08596SBrooks Davis /*
23847c08596SBrooks Davis * No BNF for numeric aggregates - that's defined by the caller. What
23947c08596SBrooks Davis * this function does is to parse a sequence of numbers separated by the
24047c08596SBrooks Davis * token specified in separator. If max is zero, any number of numbers
24147c08596SBrooks Davis * will be parsed; otherwise, exactly max numbers are expected. Base
24247c08596SBrooks Davis * and size tell us how to internalize the numbers once they've been
24347c08596SBrooks Davis * tokenized.
24447c08596SBrooks Davis */
24547c08596SBrooks Davis unsigned char *
parse_numeric_aggregate(FILE * cfile,unsigned char * buf,size_t * max,int separator,unsigned base,int size)246afe6f835SAlan Somers parse_numeric_aggregate(FILE *cfile, unsigned char *buf, size_t *max,
247afe6f835SAlan Somers int separator, unsigned base, int size)
24847c08596SBrooks Davis {
24947c08596SBrooks Davis unsigned char *bufp = buf, *s = NULL;
250afe6f835SAlan Somers int token;
25147c08596SBrooks Davis char *val, *t;
252afe6f835SAlan Somers size_t valsize, count = 0;
25347c08596SBrooks Davis pair c = NULL;
254bbeb726bSStephen J. Kiernan unsigned char *lbufp = NULL;
25547c08596SBrooks Davis
25647c08596SBrooks Davis if (!bufp && *max) {
257bbeb726bSStephen J. Kiernan lbufp = bufp = malloc(*max * size / 8);
25847c08596SBrooks Davis if (!bufp)
25947c08596SBrooks Davis error("can't allocate space for numeric aggregate");
26047c08596SBrooks Davis } else
26147c08596SBrooks Davis s = bufp;
26247c08596SBrooks Davis
26347c08596SBrooks Davis do {
26447c08596SBrooks Davis if (count) {
26547c08596SBrooks Davis token = peek_token(&val, cfile);
26647c08596SBrooks Davis if (token != separator) {
26747c08596SBrooks Davis if (!*max)
26847c08596SBrooks Davis break;
26947c08596SBrooks Davis if (token != RBRACE && token != LBRACE)
27047c08596SBrooks Davis token = next_token(&val, cfile);
27147c08596SBrooks Davis parse_warn("too few numbers.");
27247c08596SBrooks Davis if (token != SEMI)
27347c08596SBrooks Davis skip_to_semi(cfile);
274bbeb726bSStephen J. Kiernan free(lbufp);
27547c08596SBrooks Davis return (NULL);
27647c08596SBrooks Davis }
27747c08596SBrooks Davis token = next_token(&val, cfile);
27847c08596SBrooks Davis }
27947c08596SBrooks Davis token = next_token(&val, cfile);
28047c08596SBrooks Davis
28147c08596SBrooks Davis if (token == EOF) {
28247c08596SBrooks Davis parse_warn("unexpected end of file");
28347c08596SBrooks Davis break;
28447c08596SBrooks Davis }
28547c08596SBrooks Davis
28647c08596SBrooks Davis /* Allow NUMBER_OR_NAME if base is 16. */
28747c08596SBrooks Davis if (token != NUMBER &&
28847c08596SBrooks Davis (base != 16 || token != NUMBER_OR_NAME)) {
28947c08596SBrooks Davis parse_warn("expecting numeric value.");
29047c08596SBrooks Davis skip_to_semi(cfile);
291bbeb726bSStephen J. Kiernan free(lbufp);
29247c08596SBrooks Davis return (NULL);
29347c08596SBrooks Davis }
29447c08596SBrooks Davis /*
29547c08596SBrooks Davis * If we can, convert the number now; otherwise, build a
29647c08596SBrooks Davis * linked list of all the numbers.
29747c08596SBrooks Davis */
29847c08596SBrooks Davis if (s) {
29947c08596SBrooks Davis convert_num(s, val, base, size);
30047c08596SBrooks Davis s += size / 8;
30147c08596SBrooks Davis } else {
302e2f95dd9SDimitry Andric valsize = strlen(val) + 1;
303e2f95dd9SDimitry Andric t = malloc(valsize);
30447c08596SBrooks Davis if (!t)
30547c08596SBrooks Davis error("no temp space for number.");
30678247412SDimitry Andric memcpy(t, val, valsize);
30747c08596SBrooks Davis c = cons(t, c);
30847c08596SBrooks Davis }
30947c08596SBrooks Davis } while (++count != *max);
31047c08596SBrooks Davis
31147c08596SBrooks Davis /* If we had to cons up a list, convert it now. */
31247c08596SBrooks Davis if (c) {
313bbeb726bSStephen J. Kiernan free(lbufp);
31447c08596SBrooks Davis bufp = malloc(count * size / 8);
31547c08596SBrooks Davis if (!bufp)
31647c08596SBrooks Davis error("can't allocate space for numeric aggregate.");
31747c08596SBrooks Davis s = bufp + count - size / 8;
31847c08596SBrooks Davis *max = count;
31947c08596SBrooks Davis }
32047c08596SBrooks Davis while (c) {
32147c08596SBrooks Davis pair cdr = c->cdr;
32247c08596SBrooks Davis convert_num(s, (char *)c->car, base, size);
32347c08596SBrooks Davis s -= size / 8;
32447c08596SBrooks Davis /* Free up temp space. */
32547c08596SBrooks Davis free(c->car);
32647c08596SBrooks Davis free(c);
32747c08596SBrooks Davis c = cdr;
32847c08596SBrooks Davis }
32947c08596SBrooks Davis return (bufp);
33047c08596SBrooks Davis }
33147c08596SBrooks Davis
33247c08596SBrooks Davis void
convert_num(unsigned char * buf,char * str,unsigned base,int size)333afe6f835SAlan Somers convert_num(unsigned char *buf, char *str, unsigned base, int size)
33447c08596SBrooks Davis {
335afe6f835SAlan Somers bool negative = false;
336afe6f835SAlan Somers unsigned tval, max;
33747c08596SBrooks Davis u_int32_t val = 0;
33847c08596SBrooks Davis char *ptr = str;
33947c08596SBrooks Davis
34047c08596SBrooks Davis if (*ptr == '-') {
341afe6f835SAlan Somers negative = true;
34247c08596SBrooks Davis ptr++;
34347c08596SBrooks Davis }
34447c08596SBrooks Davis
34547c08596SBrooks Davis /* If base wasn't specified, figure it out from the data. */
34647c08596SBrooks Davis if (!base) {
34747c08596SBrooks Davis if (ptr[0] == '0') {
34847c08596SBrooks Davis if (ptr[1] == 'x') {
34947c08596SBrooks Davis base = 16;
35047c08596SBrooks Davis ptr += 2;
35147c08596SBrooks Davis } else if (isascii(ptr[1]) && isdigit(ptr[1])) {
35247c08596SBrooks Davis base = 8;
35347c08596SBrooks Davis ptr += 1;
35447c08596SBrooks Davis } else
35547c08596SBrooks Davis base = 10;
35647c08596SBrooks Davis } else
35747c08596SBrooks Davis base = 10;
35847c08596SBrooks Davis }
35947c08596SBrooks Davis
36047c08596SBrooks Davis do {
36147c08596SBrooks Davis tval = *ptr++;
36247c08596SBrooks Davis /* XXX assumes ASCII... */
36347c08596SBrooks Davis if (tval >= 'a')
36447c08596SBrooks Davis tval = tval - 'a' + 10;
36547c08596SBrooks Davis else if (tval >= 'A')
36647c08596SBrooks Davis tval = tval - 'A' + 10;
36747c08596SBrooks Davis else if (tval >= '0')
36847c08596SBrooks Davis tval -= '0';
36947c08596SBrooks Davis else {
37047c08596SBrooks Davis warning("Bogus number: %s.", str);
37147c08596SBrooks Davis break;
37247c08596SBrooks Davis }
37347c08596SBrooks Davis if (tval >= base) {
37447c08596SBrooks Davis warning("Bogus number: %s: digit %d not in base %d",
37547c08596SBrooks Davis str, tval, base);
37647c08596SBrooks Davis break;
37747c08596SBrooks Davis }
37847c08596SBrooks Davis val = val * base + tval;
37947c08596SBrooks Davis } while (*ptr);
38047c08596SBrooks Davis
38147c08596SBrooks Davis if (negative)
38247c08596SBrooks Davis max = (1 << (size - 1));
38347c08596SBrooks Davis else
38447c08596SBrooks Davis max = (1 << (size - 1)) + ((1 << (size - 1)) - 1);
38547c08596SBrooks Davis if (val > max) {
38647c08596SBrooks Davis switch (base) {
38747c08596SBrooks Davis case 8:
38847c08596SBrooks Davis warning("value %s%o exceeds max (%d) for precision.",
38947c08596SBrooks Davis negative ? "-" : "", val, max);
39047c08596SBrooks Davis break;
39147c08596SBrooks Davis case 16:
39247c08596SBrooks Davis warning("value %s%x exceeds max (%d) for precision.",
39347c08596SBrooks Davis negative ? "-" : "", val, max);
39447c08596SBrooks Davis break;
39547c08596SBrooks Davis default:
39647c08596SBrooks Davis warning("value %s%u exceeds max (%d) for precision.",
39747c08596SBrooks Davis negative ? "-" : "", val, max);
39847c08596SBrooks Davis break;
39947c08596SBrooks Davis }
40047c08596SBrooks Davis }
40147c08596SBrooks Davis
40247c08596SBrooks Davis if (negative)
40347c08596SBrooks Davis switch (size) {
40447c08596SBrooks Davis case 8:
40547c08596SBrooks Davis *buf = -(unsigned long)val;
40647c08596SBrooks Davis break;
40747c08596SBrooks Davis case 16:
40847c08596SBrooks Davis putShort(buf, -(unsigned long)val);
40947c08596SBrooks Davis break;
41047c08596SBrooks Davis case 32:
41147c08596SBrooks Davis putLong(buf, -(unsigned long)val);
41247c08596SBrooks Davis break;
41347c08596SBrooks Davis default:
41447c08596SBrooks Davis warning("Unexpected integer size: %d", size);
41547c08596SBrooks Davis break;
41647c08596SBrooks Davis }
41747c08596SBrooks Davis else
41847c08596SBrooks Davis switch (size) {
41947c08596SBrooks Davis case 8:
42047c08596SBrooks Davis *buf = (u_int8_t)val;
42147c08596SBrooks Davis break;
42247c08596SBrooks Davis case 16:
42347c08596SBrooks Davis putUShort(buf, (u_int16_t)val);
42447c08596SBrooks Davis break;
42547c08596SBrooks Davis case 32:
42647c08596SBrooks Davis putULong(buf, val);
42747c08596SBrooks Davis break;
42847c08596SBrooks Davis default:
42947c08596SBrooks Davis warning("Unexpected integer size: %d", size);
43047c08596SBrooks Davis break;
43147c08596SBrooks Davis }
43247c08596SBrooks Davis }
43347c08596SBrooks Davis
43447c08596SBrooks Davis /*
43547c08596SBrooks Davis * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER
43647c08596SBrooks Davis * NUMBER COLON NUMBER COLON NUMBER SEMI
43747c08596SBrooks Davis *
43847c08596SBrooks Davis * Dates are always in GMT; first number is day of week; next is
43947c08596SBrooks Davis * year/month/day; next is hours:minutes:seconds on a 24-hour
44047c08596SBrooks Davis * clock.
44147c08596SBrooks Davis */
44247c08596SBrooks Davis time_t
parse_date(FILE * cfile)44347c08596SBrooks Davis parse_date(FILE *cfile)
44447c08596SBrooks Davis {
445*c210cac0SAlex Bahm int token;
44647c08596SBrooks Davis struct tm tm;
44747c08596SBrooks Davis char *val;
44847c08596SBrooks Davis
44947c08596SBrooks Davis /* Day of week... */
45047c08596SBrooks Davis token = next_token(&val, cfile);
45147c08596SBrooks Davis if (token != NUMBER) {
45247c08596SBrooks Davis parse_warn("numeric day of week expected.");
45347c08596SBrooks Davis if (token != SEMI)
45447c08596SBrooks Davis skip_to_semi(cfile);
455b5be635aSBrooks Davis return (0);
45647c08596SBrooks Davis }
45747c08596SBrooks Davis tm.tm_wday = atoi(val);
45847c08596SBrooks Davis
45947c08596SBrooks Davis /* Year... */
46047c08596SBrooks Davis token = next_token(&val, cfile);
46147c08596SBrooks Davis if (token != NUMBER) {
46247c08596SBrooks Davis parse_warn("numeric year expected.");
46347c08596SBrooks Davis if (token != SEMI)
46447c08596SBrooks Davis skip_to_semi(cfile);
465b5be635aSBrooks Davis return (0);
46647c08596SBrooks Davis }
46747c08596SBrooks Davis tm.tm_year = atoi(val);
46847c08596SBrooks Davis if (tm.tm_year > 1900)
46947c08596SBrooks Davis tm.tm_year -= 1900;
47047c08596SBrooks Davis
47147c08596SBrooks Davis /* Slash separating year from month... */
47247c08596SBrooks Davis token = next_token(&val, cfile);
47347c08596SBrooks Davis if (token != SLASH) {
47447c08596SBrooks Davis parse_warn("expected slash separating year from month.");
47547c08596SBrooks Davis if (token != SEMI)
47647c08596SBrooks Davis skip_to_semi(cfile);
477b5be635aSBrooks Davis return (0);
47847c08596SBrooks Davis }
47947c08596SBrooks Davis
48047c08596SBrooks Davis /* Month... */
48147c08596SBrooks Davis token = next_token(&val, cfile);
48247c08596SBrooks Davis if (token != NUMBER) {
48347c08596SBrooks Davis parse_warn("numeric month expected.");
48447c08596SBrooks Davis if (token != SEMI)
48547c08596SBrooks Davis skip_to_semi(cfile);
486b5be635aSBrooks Davis return (0);
48747c08596SBrooks Davis }
48847c08596SBrooks Davis tm.tm_mon = atoi(val) - 1;
48947c08596SBrooks Davis
49047c08596SBrooks Davis /* Slash separating month from day... */
49147c08596SBrooks Davis token = next_token(&val, cfile);
49247c08596SBrooks Davis if (token != SLASH) {
49347c08596SBrooks Davis parse_warn("expected slash separating month from day.");
49447c08596SBrooks Davis if (token != SEMI)
49547c08596SBrooks Davis skip_to_semi(cfile);
496b5be635aSBrooks Davis return (0);
49747c08596SBrooks Davis }
49847c08596SBrooks Davis
49947c08596SBrooks Davis /* Month... */
50047c08596SBrooks Davis token = next_token(&val, cfile);
50147c08596SBrooks Davis if (token != NUMBER) {
50247c08596SBrooks Davis parse_warn("numeric day of month expected.");
50347c08596SBrooks Davis if (token != SEMI)
50447c08596SBrooks Davis skip_to_semi(cfile);
505b5be635aSBrooks Davis return (0);
50647c08596SBrooks Davis }
50747c08596SBrooks Davis tm.tm_mday = atoi(val);
50847c08596SBrooks Davis
50947c08596SBrooks Davis /* Hour... */
51047c08596SBrooks Davis token = next_token(&val, cfile);
51147c08596SBrooks Davis if (token != NUMBER) {
51247c08596SBrooks Davis parse_warn("numeric hour expected.");
51347c08596SBrooks Davis if (token != SEMI)
51447c08596SBrooks Davis skip_to_semi(cfile);
515b5be635aSBrooks Davis return (0);
51647c08596SBrooks Davis }
51747c08596SBrooks Davis tm.tm_hour = atoi(val);
51847c08596SBrooks Davis
51947c08596SBrooks Davis /* Colon separating hour from minute... */
52047c08596SBrooks Davis token = next_token(&val, cfile);
52147c08596SBrooks Davis if (token != COLON) {
52247c08596SBrooks Davis parse_warn("expected colon separating hour from minute.");
52347c08596SBrooks Davis if (token != SEMI)
52447c08596SBrooks Davis skip_to_semi(cfile);
525b5be635aSBrooks Davis return (0);
52647c08596SBrooks Davis }
52747c08596SBrooks Davis
52847c08596SBrooks Davis /* Minute... */
52947c08596SBrooks Davis token = next_token(&val, cfile);
53047c08596SBrooks Davis if (token != NUMBER) {
53147c08596SBrooks Davis parse_warn("numeric minute expected.");
53247c08596SBrooks Davis if (token != SEMI)
53347c08596SBrooks Davis skip_to_semi(cfile);
534b5be635aSBrooks Davis return (0);
53547c08596SBrooks Davis }
53647c08596SBrooks Davis tm.tm_min = atoi(val);
53747c08596SBrooks Davis
53847c08596SBrooks Davis /* Colon separating minute from second... */
53947c08596SBrooks Davis token = next_token(&val, cfile);
54047c08596SBrooks Davis if (token != COLON) {
54147c08596SBrooks Davis parse_warn("expected colon separating hour from minute.");
54247c08596SBrooks Davis if (token != SEMI)
54347c08596SBrooks Davis skip_to_semi(cfile);
544b5be635aSBrooks Davis return (0);
54547c08596SBrooks Davis }
54647c08596SBrooks Davis
54747c08596SBrooks Davis /* Minute... */
54847c08596SBrooks Davis token = next_token(&val, cfile);
54947c08596SBrooks Davis if (token != NUMBER) {
55047c08596SBrooks Davis parse_warn("numeric minute expected.");
55147c08596SBrooks Davis if (token != SEMI)
55247c08596SBrooks Davis skip_to_semi(cfile);
553b5be635aSBrooks Davis return (0);
55447c08596SBrooks Davis }
55547c08596SBrooks Davis tm.tm_sec = atoi(val);
55647c08596SBrooks Davis tm.tm_isdst = 0;
55747c08596SBrooks Davis
55847c08596SBrooks Davis /* XXX: We assume that mktime does not use tm_yday. */
55947c08596SBrooks Davis tm.tm_yday = 0;
56047c08596SBrooks Davis
56147c08596SBrooks Davis /* Make sure the date ends in a semicolon... */
56247c08596SBrooks Davis token = next_token(&val, cfile);
56347c08596SBrooks Davis if (token != SEMI) {
56447c08596SBrooks Davis parse_warn("semicolon expected.");
56547c08596SBrooks Davis skip_to_semi(cfile);
566b5be635aSBrooks Davis return (0);
56747c08596SBrooks Davis }
56847c08596SBrooks Davis
569*c210cac0SAlex Bahm return (timegm(&tm));
57047c08596SBrooks Davis }
571