xref: /freebsd/contrib/ldns/parse.c (revision 3b092e4936c433889cc668ea9563c8fd437d1a3e)
17b5038d7SDag-Erling Smørgrav /*
27b5038d7SDag-Erling Smørgrav  * a generic (simple) parser. Use to parse rr's, private key
37b5038d7SDag-Erling Smørgrav  * information and /etc/resolv.conf files
47b5038d7SDag-Erling Smørgrav  *
57b5038d7SDag-Erling Smørgrav  * a Net::DNS like library for C
67b5038d7SDag-Erling Smørgrav  * LibDNS Team @ NLnet Labs
77b5038d7SDag-Erling Smørgrav  * (c) NLnet Labs, 2005-2006
87b5038d7SDag-Erling Smørgrav  * See the file LICENSE for the license
97b5038d7SDag-Erling Smørgrav  */
107b5038d7SDag-Erling Smørgrav #include <ldns/config.h>
117b5038d7SDag-Erling Smørgrav #include <ldns/ldns.h>
127b5038d7SDag-Erling Smørgrav 
137b5038d7SDag-Erling Smørgrav #include <limits.h>
147b5038d7SDag-Erling Smørgrav #include <strings.h>
157b5038d7SDag-Erling Smørgrav 
167b5038d7SDag-Erling Smørgrav ldns_lookup_table ldns_directive_types[] = {
177b5038d7SDag-Erling Smørgrav         { LDNS_DIR_TTL, "$TTL" },
187b5038d7SDag-Erling Smørgrav         { LDNS_DIR_ORIGIN, "$ORIGIN" },
197b5038d7SDag-Erling Smørgrav         { LDNS_DIR_INCLUDE, "$INCLUDE" },
207b5038d7SDag-Erling Smørgrav         { 0, NULL }
217b5038d7SDag-Erling Smørgrav };
227b5038d7SDag-Erling Smørgrav 
237b5038d7SDag-Erling Smørgrav /* add max_limit here? */
247b5038d7SDag-Erling Smørgrav ssize_t
ldns_fget_token(FILE * f,char * token,const char * delim,size_t limit)257b5038d7SDag-Erling Smørgrav ldns_fget_token(FILE *f, char *token, const char *delim, size_t limit)
267b5038d7SDag-Erling Smørgrav {
277b5038d7SDag-Erling Smørgrav 	return ldns_fget_token_l(f, token, delim, limit, NULL);
287b5038d7SDag-Erling Smørgrav }
297b5038d7SDag-Erling Smørgrav 
30*3b092e49SDag-Erling Smørgrav enum file_type2parse {
31*3b092e49SDag-Erling Smørgrav 	zone_file_type, resolv_conf_file_type
32*3b092e49SDag-Erling Smørgrav };
33*3b092e49SDag-Erling Smørgrav 
34*3b092e49SDag-Erling Smørgrav static ldns_status
ldns_fget_token_l_st_file_type(FILE * f,char ** token,size_t * limit,bool fixed,const char * delim,int * line_nr,enum file_type2parse file_type)35*3b092e49SDag-Erling Smørgrav ldns_fget_token_l_st_file_type(FILE *f, char **token, size_t *limit,
36*3b092e49SDag-Erling Smørgrav 		bool fixed, const char *delim, int *line_nr,
37*3b092e49SDag-Erling Smørgrav 		enum file_type2parse file_type)
387b5038d7SDag-Erling Smørgrav {
397b5038d7SDag-Erling Smørgrav 	int c, prev_c;
405afab0e5SDag-Erling Smørgrav 	int p; /* 0 -> no parentheses seen, >0 nr of ( seen */
417b5038d7SDag-Erling Smørgrav 	int com, quoted;
425afab0e5SDag-Erling Smørgrav 	char *t, *old_token;
437b5038d7SDag-Erling Smørgrav 	size_t i;
447b5038d7SDag-Erling Smørgrav 	const char *d;
457b5038d7SDag-Erling Smørgrav 	const char *del;
467b5038d7SDag-Erling Smørgrav 
475afab0e5SDag-Erling Smørgrav 	/* standard delimiters */
487b5038d7SDag-Erling Smørgrav 	if (!delim) {
497b5038d7SDag-Erling Smørgrav 		/* from isspace(3) */
507b5038d7SDag-Erling Smørgrav 		del = LDNS_PARSE_NORMAL;
517b5038d7SDag-Erling Smørgrav 	} else {
527b5038d7SDag-Erling Smørgrav 		del = delim;
537b5038d7SDag-Erling Smørgrav 	}
545afab0e5SDag-Erling Smørgrav 	if (!token || !limit)
555afab0e5SDag-Erling Smørgrav 		return LDNS_STATUS_NULL;
567b5038d7SDag-Erling Smørgrav 
575afab0e5SDag-Erling Smørgrav 	if (fixed) {
585afab0e5SDag-Erling Smørgrav 		if (*token == NULL || *limit == 0)
595afab0e5SDag-Erling Smørgrav 			return LDNS_STATUS_NULL;
605afab0e5SDag-Erling Smørgrav 
615afab0e5SDag-Erling Smørgrav 	} else if (*token == NULL) {
625afab0e5SDag-Erling Smørgrav 		*limit = LDNS_MAX_LINELEN;
635afab0e5SDag-Erling Smørgrav 		if (!(*token = LDNS_XMALLOC(char, *limit + 1)))
645afab0e5SDag-Erling Smørgrav 			return LDNS_STATUS_MEM_ERR;
655afab0e5SDag-Erling Smørgrav 
665afab0e5SDag-Erling Smørgrav 	} else if (*limit == 0)
675afab0e5SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
687b5038d7SDag-Erling Smørgrav 	p = 0;
697b5038d7SDag-Erling Smørgrav 	i = 0;
707b5038d7SDag-Erling Smørgrav 	com = 0;
717b5038d7SDag-Erling Smørgrav 	quoted = 0;
727b5038d7SDag-Erling Smørgrav 	prev_c = 0;
735afab0e5SDag-Erling Smørgrav 	t = *token;
747b5038d7SDag-Erling Smørgrav 	if (del[0] == '"') {
757b5038d7SDag-Erling Smørgrav 		quoted = 1;
767b5038d7SDag-Erling Smørgrav 	}
777b5038d7SDag-Erling Smørgrav 	while ((c = getc(f)) != EOF) {
787b5038d7SDag-Erling Smørgrav 		if (c == '\r') /* carriage return */
797b5038d7SDag-Erling Smørgrav 			c = ' ';
807b5038d7SDag-Erling Smørgrav 		if (c == '(' && prev_c != '\\' && !quoted) {
817b5038d7SDag-Erling Smørgrav 			/* this only counts for non-comments */
827b5038d7SDag-Erling Smørgrav 			if (com == 0) {
837b5038d7SDag-Erling Smørgrav 				p++;
847b5038d7SDag-Erling Smørgrav 			}
857b5038d7SDag-Erling Smørgrav 			prev_c = c;
867b5038d7SDag-Erling Smørgrav 			continue;
877b5038d7SDag-Erling Smørgrav 		}
887b5038d7SDag-Erling Smørgrav 
897b5038d7SDag-Erling Smørgrav 		if (c == ')' && prev_c != '\\' && !quoted) {
907b5038d7SDag-Erling Smørgrav 			/* this only counts for non-comments */
917b5038d7SDag-Erling Smørgrav 			if (com == 0) {
927b5038d7SDag-Erling Smørgrav 				p--;
937b5038d7SDag-Erling Smørgrav 			}
947b5038d7SDag-Erling Smørgrav 			prev_c = c;
957b5038d7SDag-Erling Smørgrav 			continue;
967b5038d7SDag-Erling Smørgrav 		}
977b5038d7SDag-Erling Smørgrav 
987b5038d7SDag-Erling Smørgrav 		if (p < 0) {
997b5038d7SDag-Erling Smørgrav 			/* more ) then ( - close off the string */
1007b5038d7SDag-Erling Smørgrav 			*t = '\0';
1015afab0e5SDag-Erling Smørgrav 			return i == 0 ? LDNS_STATUS_SYNTAX_EMPTY
1025afab0e5SDag-Erling Smørgrav 			              : LDNS_STATUS_OK;
1037b5038d7SDag-Erling Smørgrav 		}
1047b5038d7SDag-Erling Smørgrav 
1057b5038d7SDag-Erling Smørgrav 		/* do something with comments ; */
106*3b092e49SDag-Erling Smørgrav 		if ((c == ';'
107*3b092e49SDag-Erling Smørgrav 		||  (c == '#' && file_type == resolv_conf_file_type))
108*3b092e49SDag-Erling Smørgrav 				&& quoted == 0) {
1097b5038d7SDag-Erling Smørgrav 			if (prev_c != '\\') {
1107b5038d7SDag-Erling Smørgrav 				com = 1;
1117b5038d7SDag-Erling Smørgrav 			}
1127b5038d7SDag-Erling Smørgrav 		}
1137b5038d7SDag-Erling Smørgrav 		if (c == '\"' && com == 0 && prev_c != '\\') {
1147b5038d7SDag-Erling Smørgrav 			quoted = 1 - quoted;
1157b5038d7SDag-Erling Smørgrav 		}
1167b5038d7SDag-Erling Smørgrav 
1177b5038d7SDag-Erling Smørgrav 		if (c == '\n' && com != 0) {
1187b5038d7SDag-Erling Smørgrav 			/* comments */
1197b5038d7SDag-Erling Smørgrav 			com = 0;
1207b5038d7SDag-Erling Smørgrav 			*t = ' ';
1217b5038d7SDag-Erling Smørgrav 			if (line_nr) {
1227b5038d7SDag-Erling Smørgrav 				*line_nr = *line_nr + 1;
1237b5038d7SDag-Erling Smørgrav 			}
1247b5038d7SDag-Erling Smørgrav 			if (p == 0 && i > 0) {
1257b5038d7SDag-Erling Smørgrav 				goto tokenread;
1267b5038d7SDag-Erling Smørgrav 			} else {
1277b5038d7SDag-Erling Smørgrav 				prev_c = c;
1287b5038d7SDag-Erling Smørgrav 				continue;
1297b5038d7SDag-Erling Smørgrav 			}
1307b5038d7SDag-Erling Smørgrav 		}
1317b5038d7SDag-Erling Smørgrav 
1327b5038d7SDag-Erling Smørgrav 		if (com == 1) {
1337b5038d7SDag-Erling Smørgrav 			*t = ' ';
1347b5038d7SDag-Erling Smørgrav 			prev_c = c;
1357b5038d7SDag-Erling Smørgrav 			continue;
1367b5038d7SDag-Erling Smørgrav 		}
1377b5038d7SDag-Erling Smørgrav 
1385afab0e5SDag-Erling Smørgrav 		if (c == '\n' && p != 0 && t > *token) {
1397b5038d7SDag-Erling Smørgrav 			/* in parentheses */
1407b5038d7SDag-Erling Smørgrav 			if (line_nr) {
1417b5038d7SDag-Erling Smørgrav 				*line_nr = *line_nr + 1;
1427b5038d7SDag-Erling Smørgrav 			}
1435afab0e5SDag-Erling Smørgrav 			if (*limit > 0
1445afab0e5SDag-Erling Smørgrav 			&&  (i >= *limit || (size_t)(t - *token) >= *limit)) {
1455afab0e5SDag-Erling Smørgrav 				if (fixed) {
1465afab0e5SDag-Erling Smørgrav 					*t = '\0';
1475afab0e5SDag-Erling Smørgrav 					return LDNS_STATUS_SYNTAX_ERR;
1485afab0e5SDag-Erling Smørgrav 				}
1495afab0e5SDag-Erling Smørgrav 				old_token = *token;
1505afab0e5SDag-Erling Smørgrav 				*limit *= 2;
1515afab0e5SDag-Erling Smørgrav 				*token = LDNS_XREALLOC(*token, char, *limit + 1);
1525afab0e5SDag-Erling Smørgrav 				if (*token == NULL) {
1535afab0e5SDag-Erling Smørgrav 					*token = old_token;
1545afab0e5SDag-Erling Smørgrav 					*t = '\0';
1555afab0e5SDag-Erling Smørgrav 					return LDNS_STATUS_MEM_ERR;
1565afab0e5SDag-Erling Smørgrav 				}
1575afab0e5SDag-Erling Smørgrav 				if (*token != old_token)
1585afab0e5SDag-Erling Smørgrav 					t = *token + (t - old_token);
1595afab0e5SDag-Erling Smørgrav 			}
1607b5038d7SDag-Erling Smørgrav 			*t++ = ' ';
1617b5038d7SDag-Erling Smørgrav 			prev_c = c;
1627b5038d7SDag-Erling Smørgrav 			continue;
1637b5038d7SDag-Erling Smørgrav 		}
1647b5038d7SDag-Erling Smørgrav 
1657b5038d7SDag-Erling Smørgrav 		/* check if we hit the delim */
1667b5038d7SDag-Erling Smørgrav 		for (d = del; *d; d++) {
1677b5038d7SDag-Erling Smørgrav 			if (c == *d && i > 0 && prev_c != '\\' && p == 0) {
1687b5038d7SDag-Erling Smørgrav 				if (c == '\n' && line_nr) {
1697b5038d7SDag-Erling Smørgrav 					*line_nr = *line_nr + 1;
1707b5038d7SDag-Erling Smørgrav 				}
1717b5038d7SDag-Erling Smørgrav 				goto tokenread;
1727b5038d7SDag-Erling Smørgrav 			}
1737b5038d7SDag-Erling Smørgrav 		}
1747b5038d7SDag-Erling Smørgrav 		if (c != '\0' && c != '\n') {
1757b5038d7SDag-Erling Smørgrav 			i++;
1767b5038d7SDag-Erling Smørgrav 		}
1775afab0e5SDag-Erling Smørgrav 		if (*limit > 0
1785afab0e5SDag-Erling Smørgrav 		&&  (i >= *limit || (size_t)(t - *token) >= *limit)) {
1795afab0e5SDag-Erling Smørgrav 			if (fixed) {
1807b5038d7SDag-Erling Smørgrav 				*t = '\0';
1815afab0e5SDag-Erling Smørgrav 				return LDNS_STATUS_SYNTAX_ERR;
1825afab0e5SDag-Erling Smørgrav 			}
1835afab0e5SDag-Erling Smørgrav 			old_token = *token;
1845afab0e5SDag-Erling Smørgrav 			*limit *= 2;
1855afab0e5SDag-Erling Smørgrav 			*token = LDNS_XREALLOC(*token, char, *limit + 1);
1865afab0e5SDag-Erling Smørgrav 			if (*token == NULL) {
1875afab0e5SDag-Erling Smørgrav 				*token = old_token;
1885afab0e5SDag-Erling Smørgrav 				*t = '\0';
1895afab0e5SDag-Erling Smørgrav 				return LDNS_STATUS_MEM_ERR;
1905afab0e5SDag-Erling Smørgrav 			}
1915afab0e5SDag-Erling Smørgrav 			if (*token != old_token)
1925afab0e5SDag-Erling Smørgrav 				t = *token + (t - old_token);
1937b5038d7SDag-Erling Smørgrav 		}
1947b5038d7SDag-Erling Smørgrav 		if (c != '\0' && c != '\n') {
1957b5038d7SDag-Erling Smørgrav 			*t++ = c;
1967b5038d7SDag-Erling Smørgrav 		}
1975afab0e5SDag-Erling Smørgrav 		if (c == '\n' && line_nr) {
1985afab0e5SDag-Erling Smørgrav 			*line_nr = *line_nr + 1;
1995afab0e5SDag-Erling Smørgrav 		}
2007b5038d7SDag-Erling Smørgrav 		if (c == '\\' && prev_c == '\\')
2017b5038d7SDag-Erling Smørgrav 			prev_c = 0;
2027b5038d7SDag-Erling Smørgrav 		else	prev_c = c;
2037b5038d7SDag-Erling Smørgrav 	}
2047b5038d7SDag-Erling Smørgrav 	*t = '\0';
2057b5038d7SDag-Erling Smørgrav 	if (c == EOF) {
2065afab0e5SDag-Erling Smørgrav 		return i == 0 ? LDNS_STATUS_SYNTAX_EMPTY : LDNS_STATUS_OK;
2077b5038d7SDag-Erling Smørgrav 	}
2087b5038d7SDag-Erling Smørgrav 
2097b5038d7SDag-Erling Smørgrav 	if (p != 0) {
2105afab0e5SDag-Erling Smørgrav 		return LDNS_STATUS_SYNTAX_ERR;
2117b5038d7SDag-Erling Smørgrav 	}
2125afab0e5SDag-Erling Smørgrav 	return i == 0 ? LDNS_STATUS_SYNTAX_EMPTY : LDNS_STATUS_OK;
2137b5038d7SDag-Erling Smørgrav 
2147b5038d7SDag-Erling Smørgrav tokenread:
215986ba33cSDag-Erling Smørgrav 	if(*del == '"') /* do not skip over quotes, they are significant */
216986ba33cSDag-Erling Smørgrav 		ldns_fskipcs_l(f, del+1, line_nr);
217986ba33cSDag-Erling Smørgrav 	else	ldns_fskipcs_l(f, del, line_nr);
2187b5038d7SDag-Erling Smørgrav 	*t = '\0';
2197b5038d7SDag-Erling Smørgrav 	if (p != 0) {
2205afab0e5SDag-Erling Smørgrav 		return LDNS_STATUS_SYNTAX_ERR;
2215afab0e5SDag-Erling Smørgrav 	}
2225afab0e5SDag-Erling Smørgrav 	return i == 0 ? LDNS_STATUS_SYNTAX_EMPTY : LDNS_STATUS_OK;
2237b5038d7SDag-Erling Smørgrav }
2247b5038d7SDag-Erling Smørgrav 
225*3b092e49SDag-Erling Smørgrav ldns_status
ldns_fget_token_l_st(FILE * f,char ** token,size_t * limit,bool fixed,const char * delim,int * line_nr)226*3b092e49SDag-Erling Smørgrav ldns_fget_token_l_st(FILE *f, char **token, size_t *limit, bool fixed
227*3b092e49SDag-Erling Smørgrav                     , const char *delim, int *line_nr)
228*3b092e49SDag-Erling Smørgrav {
229*3b092e49SDag-Erling Smørgrav 	return ldns_fget_token_l_st_file_type(
230*3b092e49SDag-Erling Smørgrav 		f, token, limit, fixed, delim, line_nr, zone_file_type);
231*3b092e49SDag-Erling Smørgrav }
232*3b092e49SDag-Erling Smørgrav 
233*3b092e49SDag-Erling Smørgrav ssize_t
ldns_fget_token_l_resolv_conf(FILE * f,char * token,const char * delim,size_t limit,int * line_nr)234*3b092e49SDag-Erling Smørgrav ldns_fget_token_l_resolv_conf(FILE *f, char *token, const char *delim,
235*3b092e49SDag-Erling Smørgrav 		size_t limit, int *line_nr)
236*3b092e49SDag-Erling Smørgrav {
237*3b092e49SDag-Erling Smørgrav 	if (limit == 0)
238*3b092e49SDag-Erling Smørgrav 		limit = LDNS_MAX_LINELEN;
239*3b092e49SDag-Erling Smørgrav 	if (ldns_fget_token_l_st_file_type(f, &token, &limit, true, delim,
240*3b092e49SDag-Erling Smørgrav 				line_nr, resolv_conf_file_type))
241*3b092e49SDag-Erling Smørgrav 		return -1;
242*3b092e49SDag-Erling Smørgrav 	else
243*3b092e49SDag-Erling Smørgrav 		return (ssize_t)strlen(token);
244*3b092e49SDag-Erling Smørgrav }
2455afab0e5SDag-Erling Smørgrav 
2465afab0e5SDag-Erling Smørgrav ssize_t
ldns_fget_token_l(FILE * f,char * token,const char * delim,size_t limit,int * line_nr)2475afab0e5SDag-Erling Smørgrav ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr)
2485afab0e5SDag-Erling Smørgrav {
2495afab0e5SDag-Erling Smørgrav 	if (limit == 0)
2505afab0e5SDag-Erling Smørgrav 		limit = LDNS_MAX_LINELEN;
2515afab0e5SDag-Erling Smørgrav 	if (ldns_fget_token_l_st(f, &token, &limit, true, delim, line_nr))
2525afab0e5SDag-Erling Smørgrav 		return -1;
2535afab0e5SDag-Erling Smørgrav 	else
2545afab0e5SDag-Erling Smørgrav 		return (ssize_t)strlen(token);
2557b5038d7SDag-Erling Smørgrav }
2567b5038d7SDag-Erling Smørgrav 
2577b5038d7SDag-Erling Smørgrav ssize_t
ldns_fget_keyword_data(FILE * f,const char * keyword,const char * k_del,char * data,const char * d_del,size_t data_limit)2587b5038d7SDag-Erling Smørgrav ldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, char *data,
2597b5038d7SDag-Erling Smørgrav                const char *d_del, size_t data_limit)
2607b5038d7SDag-Erling Smørgrav {
2617b5038d7SDag-Erling Smørgrav        return ldns_fget_keyword_data_l(f, keyword, k_del, data, d_del,
2627b5038d7SDag-Erling Smørgrav 		       data_limit, NULL);
2637b5038d7SDag-Erling Smørgrav }
2647b5038d7SDag-Erling Smørgrav 
2657b5038d7SDag-Erling Smørgrav ssize_t
ldns_fget_keyword_data_l(FILE * f,const char * keyword,const char * k_del,char * data,const char * d_del,size_t data_limit,int * line_nr)2667b5038d7SDag-Erling Smørgrav ldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_del, char *data,
2677b5038d7SDag-Erling Smørgrav                const char *d_del, size_t data_limit, int *line_nr)
2687b5038d7SDag-Erling Smørgrav {
2697b5038d7SDag-Erling Smørgrav        /* we assume: keyword|sep|data */
2707b5038d7SDag-Erling Smørgrav        char *fkeyword;
2717b5038d7SDag-Erling Smørgrav        ssize_t i;
2727b5038d7SDag-Erling Smørgrav 
2737b5038d7SDag-Erling Smørgrav        if(strlen(keyword) >= LDNS_MAX_KEYWORDLEN)
2747b5038d7SDag-Erling Smørgrav                return -1;
2757b5038d7SDag-Erling Smørgrav        fkeyword = LDNS_XMALLOC(char, LDNS_MAX_KEYWORDLEN);
2767b5038d7SDag-Erling Smørgrav        if(!fkeyword)
2777b5038d7SDag-Erling Smørgrav                return -1;
2787b5038d7SDag-Erling Smørgrav 
2797b5038d7SDag-Erling Smørgrav        i = ldns_fget_token(f, fkeyword, k_del, LDNS_MAX_KEYWORDLEN);
2807b5038d7SDag-Erling Smørgrav        if(i==0 || i==-1) {
2817b5038d7SDag-Erling Smørgrav                LDNS_FREE(fkeyword);
2827b5038d7SDag-Erling Smørgrav                return -1;
2837b5038d7SDag-Erling Smørgrav        }
2847b5038d7SDag-Erling Smørgrav 
2857b5038d7SDag-Erling Smørgrav        /* case??? i instead of strlen? */
2867b5038d7SDag-Erling Smørgrav        if (strncmp(fkeyword, keyword, LDNS_MAX_KEYWORDLEN - 1) == 0) {
2877b5038d7SDag-Erling Smørgrav                /* whee! */
2887b5038d7SDag-Erling Smørgrav                /* printf("%s\n%s\n", "Matching keyword", fkeyword); */
2897b5038d7SDag-Erling Smørgrav                i = ldns_fget_token_l(f, data, d_del, data_limit, line_nr);
2907b5038d7SDag-Erling Smørgrav                LDNS_FREE(fkeyword);
2917b5038d7SDag-Erling Smørgrav                return i;
2927b5038d7SDag-Erling Smørgrav        } else {
2937b5038d7SDag-Erling Smørgrav                /*printf("no match for %s (read: %s)\n", keyword, fkeyword);*/
2947b5038d7SDag-Erling Smørgrav                LDNS_FREE(fkeyword);
2957b5038d7SDag-Erling Smørgrav                return -1;
2967b5038d7SDag-Erling Smørgrav        }
2977b5038d7SDag-Erling Smørgrav }
2987b5038d7SDag-Erling Smørgrav 
2997b5038d7SDag-Erling Smørgrav 
3007b5038d7SDag-Erling Smørgrav ssize_t
ldns_bget_token(ldns_buffer * b,char * token,const char * delim,size_t limit)3017b5038d7SDag-Erling Smørgrav ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t limit)
3027b5038d7SDag-Erling Smørgrav {
3037b5038d7SDag-Erling Smørgrav 	int c, lc;
3045afab0e5SDag-Erling Smørgrav 	int p; /* 0 -> no parentheses seen, >0 nr of ( seen */
3057b5038d7SDag-Erling Smørgrav 	int com, quoted;
3067b5038d7SDag-Erling Smørgrav 	char *t;
3077b5038d7SDag-Erling Smørgrav 	size_t i;
3087b5038d7SDag-Erling Smørgrav 	const char *d;
3097b5038d7SDag-Erling Smørgrav 	const char *del;
3107b5038d7SDag-Erling Smørgrav 
3117b5038d7SDag-Erling Smørgrav 	/* standard delimiters */
3127b5038d7SDag-Erling Smørgrav 	if (!delim) {
3137b5038d7SDag-Erling Smørgrav 		/* from isspace(3) */
3147b5038d7SDag-Erling Smørgrav 		del = LDNS_PARSE_NORMAL;
3157b5038d7SDag-Erling Smørgrav 	} else {
3167b5038d7SDag-Erling Smørgrav 		del = delim;
3177b5038d7SDag-Erling Smørgrav 	}
3187b5038d7SDag-Erling Smørgrav 
3197b5038d7SDag-Erling Smørgrav 	p = 0;
3207b5038d7SDag-Erling Smørgrav 	i = 0;
3217b5038d7SDag-Erling Smørgrav 	com = 0;
3227b5038d7SDag-Erling Smørgrav 	quoted = 0;
3237b5038d7SDag-Erling Smørgrav 	t = token;
3247b5038d7SDag-Erling Smørgrav 	lc = 0;
3257b5038d7SDag-Erling Smørgrav 	if (del[0] == '"') {
3267b5038d7SDag-Erling Smørgrav 		quoted = 1;
3277b5038d7SDag-Erling Smørgrav 	}
3287b5038d7SDag-Erling Smørgrav 
3297b5038d7SDag-Erling Smørgrav 	while ((c = ldns_bgetc(b)) != EOF) {
3307b5038d7SDag-Erling Smørgrav 		if (c == '\r') /* carriage return */
3317b5038d7SDag-Erling Smørgrav 			c = ' ';
3327b5038d7SDag-Erling Smørgrav 		if (c == '(' && lc != '\\' && !quoted) {
3337b5038d7SDag-Erling Smørgrav 			/* this only counts for non-comments */
3347b5038d7SDag-Erling Smørgrav 			if (com == 0) {
3357b5038d7SDag-Erling Smørgrav 				p++;
3367b5038d7SDag-Erling Smørgrav 			}
3377b5038d7SDag-Erling Smørgrav 			lc = c;
3387b5038d7SDag-Erling Smørgrav 			continue;
3397b5038d7SDag-Erling Smørgrav 		}
3407b5038d7SDag-Erling Smørgrav 
3417b5038d7SDag-Erling Smørgrav 		if (c == ')' && lc != '\\' && !quoted) {
3427b5038d7SDag-Erling Smørgrav 			/* this only counts for non-comments */
3437b5038d7SDag-Erling Smørgrav 			if (com == 0) {
3447b5038d7SDag-Erling Smørgrav 				p--;
3457b5038d7SDag-Erling Smørgrav 			}
3467b5038d7SDag-Erling Smørgrav 			lc = c;
3477b5038d7SDag-Erling Smørgrav 			continue;
3487b5038d7SDag-Erling Smørgrav 		}
3497b5038d7SDag-Erling Smørgrav 
3507b5038d7SDag-Erling Smørgrav 		if (p < 0) {
3517b5038d7SDag-Erling Smørgrav 			/* more ) then ( */
3527b5038d7SDag-Erling Smørgrav 			*t = '\0';
3537b5038d7SDag-Erling Smørgrav 			return 0;
3547b5038d7SDag-Erling Smørgrav 		}
3557b5038d7SDag-Erling Smørgrav 
3567b5038d7SDag-Erling Smørgrav 		/* do something with comments ; */
3577b5038d7SDag-Erling Smørgrav 		if (c == ';' && quoted == 0) {
3587b5038d7SDag-Erling Smørgrav 			if (lc != '\\') {
3597b5038d7SDag-Erling Smørgrav 				com = 1;
3607b5038d7SDag-Erling Smørgrav 			}
3617b5038d7SDag-Erling Smørgrav 		}
3627b5038d7SDag-Erling Smørgrav 		if (c == '"' && com == 0 && lc != '\\') {
3637b5038d7SDag-Erling Smørgrav 			quoted = 1 - quoted;
3647b5038d7SDag-Erling Smørgrav 		}
3657b5038d7SDag-Erling Smørgrav 
3667b5038d7SDag-Erling Smørgrav 		if (c == '\n' && com != 0) {
3677b5038d7SDag-Erling Smørgrav 			/* comments */
3687b5038d7SDag-Erling Smørgrav 			com = 0;
3697b5038d7SDag-Erling Smørgrav 			*t = ' ';
3707b5038d7SDag-Erling Smørgrav 			lc = c;
3717b5038d7SDag-Erling Smørgrav 			continue;
3727b5038d7SDag-Erling Smørgrav 		}
3737b5038d7SDag-Erling Smørgrav 
3747b5038d7SDag-Erling Smørgrav 		if (com == 1) {
3757b5038d7SDag-Erling Smørgrav 			*t = ' ';
3767b5038d7SDag-Erling Smørgrav 			lc = c;
3777b5038d7SDag-Erling Smørgrav 			continue;
3787b5038d7SDag-Erling Smørgrav 		}
3797b5038d7SDag-Erling Smørgrav 
3807b5038d7SDag-Erling Smørgrav 		if (c == '\n' && p != 0) {
3817b5038d7SDag-Erling Smørgrav 			/* in parentheses */
3827b5038d7SDag-Erling Smørgrav 			*t++ = ' ';
3837b5038d7SDag-Erling Smørgrav 			lc = c;
3847b5038d7SDag-Erling Smørgrav 			continue;
3857b5038d7SDag-Erling Smørgrav 		}
3867b5038d7SDag-Erling Smørgrav 
3877b5038d7SDag-Erling Smørgrav 		/* check if we hit the delim */
3887b5038d7SDag-Erling Smørgrav 		for (d = del; *d; d++) {
3897b5038d7SDag-Erling Smørgrav                         if (c == *d && lc != '\\' && p == 0) {
3907b5038d7SDag-Erling Smørgrav 				goto tokenread;
3917b5038d7SDag-Erling Smørgrav                         }
3927b5038d7SDag-Erling Smørgrav 		}
3937b5038d7SDag-Erling Smørgrav 
3947b5038d7SDag-Erling Smørgrav 		i++;
39517d15b25SDag-Erling Smørgrav 		if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) {
3967b5038d7SDag-Erling Smørgrav 			*t = '\0';
3977b5038d7SDag-Erling Smørgrav 			return -1;
3987b5038d7SDag-Erling Smørgrav 		}
3997b5038d7SDag-Erling Smørgrav 		*t++ = c;
4007b5038d7SDag-Erling Smørgrav 
4017b5038d7SDag-Erling Smørgrav 		if (c == '\\' && lc == '\\') {
4027b5038d7SDag-Erling Smørgrav 			lc = 0;
4037b5038d7SDag-Erling Smørgrav 		} else {
4047b5038d7SDag-Erling Smørgrav 			lc = c;
4057b5038d7SDag-Erling Smørgrav 		}
4067b5038d7SDag-Erling Smørgrav 	}
4077b5038d7SDag-Erling Smørgrav 	*t = '\0';
4087b5038d7SDag-Erling Smørgrav 	if (i == 0) {
4097b5038d7SDag-Erling Smørgrav 		/* nothing read */
4107b5038d7SDag-Erling Smørgrav 		return -1;
4117b5038d7SDag-Erling Smørgrav 	}
4127b5038d7SDag-Erling Smørgrav 	if (p != 0) {
4137b5038d7SDag-Erling Smørgrav 		return -1;
4147b5038d7SDag-Erling Smørgrav 	}
4157b5038d7SDag-Erling Smørgrav 	return (ssize_t)i;
4167b5038d7SDag-Erling Smørgrav 
4177b5038d7SDag-Erling Smørgrav tokenread:
418986ba33cSDag-Erling Smørgrav 	if(*del == '"') /* do not skip over quotes, they are significant */
419986ba33cSDag-Erling Smørgrav 		ldns_bskipcs(b, del+1);
420986ba33cSDag-Erling Smørgrav 	else	ldns_bskipcs(b, del);
4217b5038d7SDag-Erling Smørgrav 	*t = '\0';
4227b5038d7SDag-Erling Smørgrav 
4237b5038d7SDag-Erling Smørgrav 	if (p != 0) {
4247b5038d7SDag-Erling Smørgrav 		return -1;
4257b5038d7SDag-Erling Smørgrav 	}
4267b5038d7SDag-Erling Smørgrav 	return (ssize_t)i;
4277b5038d7SDag-Erling Smørgrav }
4287b5038d7SDag-Erling Smørgrav 
4297b5038d7SDag-Erling Smørgrav 
4307b5038d7SDag-Erling Smørgrav void
ldns_bskipcs(ldns_buffer * buffer,const char * s)4317b5038d7SDag-Erling Smørgrav ldns_bskipcs(ldns_buffer *buffer, const char *s)
4327b5038d7SDag-Erling Smørgrav {
4337b5038d7SDag-Erling Smørgrav         bool found;
4347b5038d7SDag-Erling Smørgrav         char c;
4357b5038d7SDag-Erling Smørgrav         const char *d;
4367b5038d7SDag-Erling Smørgrav 
4377b5038d7SDag-Erling Smørgrav         while(ldns_buffer_available_at(buffer, buffer->_position, sizeof(char))) {
4387b5038d7SDag-Erling Smørgrav                 c = (char) ldns_buffer_read_u8_at(buffer, buffer->_position);
4397b5038d7SDag-Erling Smørgrav                 found = false;
4407b5038d7SDag-Erling Smørgrav                 for (d = s; *d; d++) {
4417b5038d7SDag-Erling Smørgrav                         if (*d == c) {
4427b5038d7SDag-Erling Smørgrav                                 found = true;
4437b5038d7SDag-Erling Smørgrav                         }
4447b5038d7SDag-Erling Smørgrav                 }
4457b5038d7SDag-Erling Smørgrav                 if (found && buffer->_limit > buffer->_position) {
4467b5038d7SDag-Erling Smørgrav                         buffer->_position += sizeof(char);
4477b5038d7SDag-Erling Smørgrav                 } else {
4487b5038d7SDag-Erling Smørgrav                         return;
4497b5038d7SDag-Erling Smørgrav                 }
4507b5038d7SDag-Erling Smørgrav         }
4517b5038d7SDag-Erling Smørgrav }
4527b5038d7SDag-Erling Smørgrav 
4537b5038d7SDag-Erling Smørgrav void
ldns_fskipcs(FILE * fp,const char * s)4547b5038d7SDag-Erling Smørgrav ldns_fskipcs(FILE *fp, const char *s)
4557b5038d7SDag-Erling Smørgrav {
4567b5038d7SDag-Erling Smørgrav 	ldns_fskipcs_l(fp, s, NULL);
4577b5038d7SDag-Erling Smørgrav }
4587b5038d7SDag-Erling Smørgrav 
4597b5038d7SDag-Erling Smørgrav void
ldns_fskipcs_l(FILE * fp,const char * s,int * line_nr)4607b5038d7SDag-Erling Smørgrav ldns_fskipcs_l(FILE *fp, const char *s, int *line_nr)
4617b5038d7SDag-Erling Smørgrav {
4627b5038d7SDag-Erling Smørgrav         bool found;
4637b5038d7SDag-Erling Smørgrav         int c;
4647b5038d7SDag-Erling Smørgrav         const char *d;
4657b5038d7SDag-Erling Smørgrav 
4667b5038d7SDag-Erling Smørgrav 	while ((c = fgetc(fp)) != EOF) {
4677b5038d7SDag-Erling Smørgrav 		if (line_nr && c == '\n') {
4687b5038d7SDag-Erling Smørgrav 			*line_nr = *line_nr + 1;
4697b5038d7SDag-Erling Smørgrav 		}
4707b5038d7SDag-Erling Smørgrav                 found = false;
4717b5038d7SDag-Erling Smørgrav                 for (d = s; *d; d++) {
4727b5038d7SDag-Erling Smørgrav                         if (*d == c) {
4737b5038d7SDag-Erling Smørgrav                                 found = true;
4747b5038d7SDag-Erling Smørgrav                         }
4757b5038d7SDag-Erling Smørgrav                 }
4767b5038d7SDag-Erling Smørgrav 		if (!found) {
4777b5038d7SDag-Erling Smørgrav 			/* with getc, we've read too far */
4787b5038d7SDag-Erling Smørgrav 			ungetc(c, fp);
4797b5038d7SDag-Erling Smørgrav 			return;
4807b5038d7SDag-Erling Smørgrav 		}
4817b5038d7SDag-Erling Smørgrav 	}
4827b5038d7SDag-Erling Smørgrav }
4837b5038d7SDag-Erling Smørgrav 
4847b5038d7SDag-Erling Smørgrav ssize_t
ldns_bget_keyword_data(ldns_buffer * b,const char * keyword,const char * k_del,char * data,const char * d_del,size_t data_limit)4857b5038d7SDag-Erling Smørgrav ldns_bget_keyword_data(ldns_buffer *b, const char *keyword, const char *k_del, char
4867b5038d7SDag-Erling Smørgrav *data, const char *d_del, size_t data_limit)
4877b5038d7SDag-Erling Smørgrav {
4887b5038d7SDag-Erling Smørgrav        /* we assume: keyword|sep|data */
4897b5038d7SDag-Erling Smørgrav        char *fkeyword;
4907b5038d7SDag-Erling Smørgrav        ssize_t i;
4917b5038d7SDag-Erling Smørgrav 
4927b5038d7SDag-Erling Smørgrav        if(strlen(keyword) >= LDNS_MAX_KEYWORDLEN)
4937b5038d7SDag-Erling Smørgrav                return -1;
4947b5038d7SDag-Erling Smørgrav        fkeyword = LDNS_XMALLOC(char, LDNS_MAX_KEYWORDLEN);
4957b5038d7SDag-Erling Smørgrav        if(!fkeyword)
4967b5038d7SDag-Erling Smørgrav                return -1; /* out of memory */
4977b5038d7SDag-Erling Smørgrav 
4987b5038d7SDag-Erling Smørgrav        i = ldns_bget_token(b, fkeyword, k_del, data_limit);
4997b5038d7SDag-Erling Smørgrav        if(i==0 || i==-1) {
5007b5038d7SDag-Erling Smørgrav                LDNS_FREE(fkeyword);
5017b5038d7SDag-Erling Smørgrav                return -1; /* nothing read */
5027b5038d7SDag-Erling Smørgrav        }
5037b5038d7SDag-Erling Smørgrav 
5047b5038d7SDag-Erling Smørgrav        /* case??? */
5057b5038d7SDag-Erling Smørgrav        if (strncmp(fkeyword, keyword, strlen(keyword)) == 0) {
5067b5038d7SDag-Erling Smørgrav                LDNS_FREE(fkeyword);
5077b5038d7SDag-Erling Smørgrav                /* whee, the match! */
5087b5038d7SDag-Erling Smørgrav                /* retrieve it's data */
5097b5038d7SDag-Erling Smørgrav                i = ldns_bget_token(b, data, d_del, 0);
5107b5038d7SDag-Erling Smørgrav                return i;
5117b5038d7SDag-Erling Smørgrav        } else {
5127b5038d7SDag-Erling Smørgrav                LDNS_FREE(fkeyword);
5137b5038d7SDag-Erling Smørgrav                return -1;
5147b5038d7SDag-Erling Smørgrav        }
5157b5038d7SDag-Erling Smørgrav }
5167b5038d7SDag-Erling Smørgrav 
517