109a3aaf3SDag-Erling Smørgrav /*
209a3aaf3SDag-Erling Smørgrav * a generic (simple) parser. Use to parse rr's, private key
309a3aaf3SDag-Erling Smørgrav * information and /etc/resolv.conf files
409a3aaf3SDag-Erling Smørgrav *
509a3aaf3SDag-Erling Smørgrav * a Net::DNS like library for C
609a3aaf3SDag-Erling Smørgrav * LibDNS Team @ NLnet Labs
709a3aaf3SDag-Erling Smørgrav * (c) NLnet Labs, 2005-2006
809a3aaf3SDag-Erling Smørgrav * See the file LICENSE for the license
909a3aaf3SDag-Erling Smørgrav */
1009a3aaf3SDag-Erling Smørgrav #include "config.h"
1109a3aaf3SDag-Erling Smørgrav #include "sldns/parse.h"
1209a3aaf3SDag-Erling Smørgrav #include "sldns/parseutil.h"
1309a3aaf3SDag-Erling Smørgrav #include "sldns/sbuffer.h"
1409a3aaf3SDag-Erling Smørgrav
1509a3aaf3SDag-Erling Smørgrav #include <limits.h>
1609a3aaf3SDag-Erling Smørgrav #include <strings.h>
1709a3aaf3SDag-Erling Smørgrav
1809a3aaf3SDag-Erling Smørgrav sldns_lookup_table sldns_directive_types[] = {
1909a3aaf3SDag-Erling Smørgrav { LDNS_DIR_TTL, "$TTL" },
2009a3aaf3SDag-Erling Smørgrav { LDNS_DIR_ORIGIN, "$ORIGIN" },
2109a3aaf3SDag-Erling Smørgrav { LDNS_DIR_INCLUDE, "$INCLUDE" },
2209a3aaf3SDag-Erling Smørgrav { 0, NULL }
2309a3aaf3SDag-Erling Smørgrav };
2409a3aaf3SDag-Erling Smørgrav
2509a3aaf3SDag-Erling Smørgrav /* add max_limit here? */
2609a3aaf3SDag-Erling Smørgrav ssize_t
sldns_fget_token(FILE * f,char * token,const char * delim,size_t limit)2709a3aaf3SDag-Erling Smørgrav sldns_fget_token(FILE *f, char *token, const char *delim, size_t limit)
2809a3aaf3SDag-Erling Smørgrav {
2909a3aaf3SDag-Erling Smørgrav return sldns_fget_token_l(f, token, delim, limit, NULL);
3009a3aaf3SDag-Erling Smørgrav }
3109a3aaf3SDag-Erling Smørgrav
3209a3aaf3SDag-Erling Smørgrav ssize_t
sldns_fget_token_l(FILE * f,char * token,const char * delim,size_t limit,int * line_nr)3309a3aaf3SDag-Erling Smørgrav sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr)
3409a3aaf3SDag-Erling Smørgrav {
3509a3aaf3SDag-Erling Smørgrav int c, prev_c;
368a384985SDag-Erling Smørgrav int p; /* 0 -> no parentheses seen, >0 nr of ( seen */
37*0a92a9fcSCy Schubert int com, quoted, only_blank;
3809a3aaf3SDag-Erling Smørgrav char *t;
3909a3aaf3SDag-Erling Smørgrav size_t i;
4009a3aaf3SDag-Erling Smørgrav const char *d;
4109a3aaf3SDag-Erling Smørgrav const char *del;
4209a3aaf3SDag-Erling Smørgrav
438a384985SDag-Erling Smørgrav /* standard delimiters */
4409a3aaf3SDag-Erling Smørgrav if (!delim) {
4509a3aaf3SDag-Erling Smørgrav /* from isspace(3) */
4609a3aaf3SDag-Erling Smørgrav del = LDNS_PARSE_NORMAL;
4709a3aaf3SDag-Erling Smørgrav } else {
4809a3aaf3SDag-Erling Smørgrav del = delim;
4909a3aaf3SDag-Erling Smørgrav }
5009a3aaf3SDag-Erling Smørgrav
5109a3aaf3SDag-Erling Smørgrav p = 0;
5209a3aaf3SDag-Erling Smørgrav i = 0;
5309a3aaf3SDag-Erling Smørgrav com = 0;
5409a3aaf3SDag-Erling Smørgrav quoted = 0;
5509a3aaf3SDag-Erling Smørgrav prev_c = 0;
56*0a92a9fcSCy Schubert only_blank = 1; /* Assume we got only <blank> until now */
5709a3aaf3SDag-Erling Smørgrav t = token;
5809a3aaf3SDag-Erling Smørgrav if (del[0] == '"') {
5909a3aaf3SDag-Erling Smørgrav quoted = 1;
6009a3aaf3SDag-Erling Smørgrav }
6109a3aaf3SDag-Erling Smørgrav while ((c = getc(f)) != EOF) {
6209a3aaf3SDag-Erling Smørgrav if (c == '\r') /* carriage return */
6309a3aaf3SDag-Erling Smørgrav c = ' ';
6409a3aaf3SDag-Erling Smørgrav if (c == '(' && prev_c != '\\' && !quoted) {
6509a3aaf3SDag-Erling Smørgrav /* this only counts for non-comments */
6609a3aaf3SDag-Erling Smørgrav if (com == 0) {
6709a3aaf3SDag-Erling Smørgrav p++;
6809a3aaf3SDag-Erling Smørgrav }
6909a3aaf3SDag-Erling Smørgrav prev_c = c;
7009a3aaf3SDag-Erling Smørgrav continue;
7109a3aaf3SDag-Erling Smørgrav }
7209a3aaf3SDag-Erling Smørgrav
7309a3aaf3SDag-Erling Smørgrav if (c == ')' && prev_c != '\\' && !quoted) {
7409a3aaf3SDag-Erling Smørgrav /* this only counts for non-comments */
7509a3aaf3SDag-Erling Smørgrav if (com == 0) {
7609a3aaf3SDag-Erling Smørgrav p--;
7709a3aaf3SDag-Erling Smørgrav }
7809a3aaf3SDag-Erling Smørgrav prev_c = c;
7909a3aaf3SDag-Erling Smørgrav continue;
8009a3aaf3SDag-Erling Smørgrav }
8109a3aaf3SDag-Erling Smørgrav
8209a3aaf3SDag-Erling Smørgrav if (p < 0) {
8309a3aaf3SDag-Erling Smørgrav /* more ) then ( - close off the string */
8409a3aaf3SDag-Erling Smørgrav *t = '\0';
8509a3aaf3SDag-Erling Smørgrav return 0;
8609a3aaf3SDag-Erling Smørgrav }
8709a3aaf3SDag-Erling Smørgrav
8809a3aaf3SDag-Erling Smørgrav /* do something with comments ; */
8909a3aaf3SDag-Erling Smørgrav if (c == ';' && quoted == 0) {
9009a3aaf3SDag-Erling Smørgrav if (prev_c != '\\') {
9109a3aaf3SDag-Erling Smørgrav com = 1;
9209a3aaf3SDag-Erling Smørgrav }
9309a3aaf3SDag-Erling Smørgrav }
9409a3aaf3SDag-Erling Smørgrav if (c == '\"' && com == 0 && prev_c != '\\') {
9509a3aaf3SDag-Erling Smørgrav quoted = 1 - quoted;
9609a3aaf3SDag-Erling Smørgrav }
9709a3aaf3SDag-Erling Smørgrav
9809a3aaf3SDag-Erling Smørgrav if (c == '\n' && com != 0) {
9909a3aaf3SDag-Erling Smørgrav /* comments */
10009a3aaf3SDag-Erling Smørgrav com = 0;
10109a3aaf3SDag-Erling Smørgrav *t = ' ';
10209a3aaf3SDag-Erling Smørgrav if (line_nr) {
10309a3aaf3SDag-Erling Smørgrav *line_nr = *line_nr + 1;
10409a3aaf3SDag-Erling Smørgrav }
105*0a92a9fcSCy Schubert if (only_blank && i > 0) {
106*0a92a9fcSCy Schubert /* Got only <blank> so far. Reset and try
107*0a92a9fcSCy Schubert * again with the next line.
108*0a92a9fcSCy Schubert */
109*0a92a9fcSCy Schubert i = 0;
110*0a92a9fcSCy Schubert t = token;
111*0a92a9fcSCy Schubert }
112*0a92a9fcSCy Schubert if (p == 0) {
113*0a92a9fcSCy Schubert /* If p != 0 then the next line is a continuation. So
114*0a92a9fcSCy Schubert * we assume that the next line starts with a blank only
115*0a92a9fcSCy Schubert * if it is actually a new line.
116*0a92a9fcSCy Schubert */
117*0a92a9fcSCy Schubert only_blank = 1; /* Assume next line starts with
118*0a92a9fcSCy Schubert * <blank>.
119*0a92a9fcSCy Schubert */
120*0a92a9fcSCy Schubert }
12109a3aaf3SDag-Erling Smørgrav if (p == 0 && i > 0) {
12209a3aaf3SDag-Erling Smørgrav goto tokenread;
12309a3aaf3SDag-Erling Smørgrav } else {
12409a3aaf3SDag-Erling Smørgrav prev_c = c;
12509a3aaf3SDag-Erling Smørgrav continue;
12609a3aaf3SDag-Erling Smørgrav }
12709a3aaf3SDag-Erling Smørgrav }
12809a3aaf3SDag-Erling Smørgrav
12909a3aaf3SDag-Erling Smørgrav if (com == 1) {
13009a3aaf3SDag-Erling Smørgrav *t = ' ';
13109a3aaf3SDag-Erling Smørgrav prev_c = c;
13209a3aaf3SDag-Erling Smørgrav continue;
13309a3aaf3SDag-Erling Smørgrav }
13409a3aaf3SDag-Erling Smørgrav
13509a3aaf3SDag-Erling Smørgrav if (c == '\n' && p != 0 && t > token) {
13609a3aaf3SDag-Erling Smørgrav /* in parentheses */
13709a3aaf3SDag-Erling Smørgrav if (line_nr) {
13809a3aaf3SDag-Erling Smørgrav *line_nr = *line_nr + 1;
13909a3aaf3SDag-Erling Smørgrav }
140091e9e46SCy Schubert if (limit > 0 && (i+1 >= limit || (size_t)(t-token)+1 >= limit)) {
141c7f4d7adSDag-Erling Smørgrav *t = '\0';
142c7f4d7adSDag-Erling Smørgrav return -1;
143c7f4d7adSDag-Erling Smørgrav }
14409a3aaf3SDag-Erling Smørgrav *t++ = ' ';
14509a3aaf3SDag-Erling Smørgrav prev_c = c;
14609a3aaf3SDag-Erling Smørgrav continue;
14709a3aaf3SDag-Erling Smørgrav }
14809a3aaf3SDag-Erling Smørgrav
14909a3aaf3SDag-Erling Smørgrav /* check if we hit the delim */
15009a3aaf3SDag-Erling Smørgrav for (d = del; *d; d++) {
151*0a92a9fcSCy Schubert if (c == *d)
152*0a92a9fcSCy Schubert break;
153*0a92a9fcSCy Schubert }
154*0a92a9fcSCy Schubert
15509a3aaf3SDag-Erling Smørgrav if (c == *d && i > 0 && prev_c != '\\' && p == 0) {
15609a3aaf3SDag-Erling Smørgrav if (c == '\n' && line_nr) {
15709a3aaf3SDag-Erling Smørgrav *line_nr = *line_nr + 1;
15809a3aaf3SDag-Erling Smørgrav }
159*0a92a9fcSCy Schubert if (only_blank) {
160*0a92a9fcSCy Schubert /* Got only <blank> so far. Reset and
161*0a92a9fcSCy Schubert * try again with the next line.
162*0a92a9fcSCy Schubert */
163*0a92a9fcSCy Schubert i = 0;
164*0a92a9fcSCy Schubert t = token;
165*0a92a9fcSCy Schubert only_blank = 1;
166*0a92a9fcSCy Schubert prev_c = c;
167*0a92a9fcSCy Schubert continue;
168*0a92a9fcSCy Schubert }
16909a3aaf3SDag-Erling Smørgrav goto tokenread;
17009a3aaf3SDag-Erling Smørgrav }
171*0a92a9fcSCy Schubert if (c != ' ' && c != '\t') {
172*0a92a9fcSCy Schubert /* Found something that is not <blank> */
173*0a92a9fcSCy Schubert only_blank= 0;
17409a3aaf3SDag-Erling Smørgrav }
17509a3aaf3SDag-Erling Smørgrav if (c != '\0' && c != '\n') {
17609a3aaf3SDag-Erling Smørgrav i++;
17709a3aaf3SDag-Erling Smørgrav }
178091e9e46SCy Schubert /* is there space for the character and the zero after it */
179091e9e46SCy Schubert if (limit > 0 && (i+1 >= limit || (size_t)(t-token)+1 >= limit)) {
18009a3aaf3SDag-Erling Smørgrav *t = '\0';
18109a3aaf3SDag-Erling Smørgrav return -1;
18209a3aaf3SDag-Erling Smørgrav }
18309a3aaf3SDag-Erling Smørgrav if (c != '\0' && c != '\n') {
18409a3aaf3SDag-Erling Smørgrav *t++ = c;
18509a3aaf3SDag-Erling Smørgrav }
186*0a92a9fcSCy Schubert if (c == '\n') {
187*0a92a9fcSCy Schubert if (line_nr) {
1885469a995SCy Schubert *line_nr = *line_nr + 1;
1895469a995SCy Schubert }
190*0a92a9fcSCy Schubert only_blank = 1; /* Assume next line starts with
191*0a92a9fcSCy Schubert * <blank>.
192*0a92a9fcSCy Schubert */
193*0a92a9fcSCy Schubert }
19409a3aaf3SDag-Erling Smørgrav if (c == '\\' && prev_c == '\\')
19509a3aaf3SDag-Erling Smørgrav prev_c = 0;
19609a3aaf3SDag-Erling Smørgrav else prev_c = c;
19709a3aaf3SDag-Erling Smørgrav }
19809a3aaf3SDag-Erling Smørgrav *t = '\0';
19909a3aaf3SDag-Erling Smørgrav if (c == EOF) {
20009a3aaf3SDag-Erling Smørgrav return (ssize_t)i;
20109a3aaf3SDag-Erling Smørgrav }
20209a3aaf3SDag-Erling Smørgrav
20309a3aaf3SDag-Erling Smørgrav if (i == 0) {
20409a3aaf3SDag-Erling Smørgrav /* nothing read */
20509a3aaf3SDag-Erling Smørgrav return -1;
20609a3aaf3SDag-Erling Smørgrav }
20709a3aaf3SDag-Erling Smørgrav if (p != 0) {
20809a3aaf3SDag-Erling Smørgrav return -1;
20909a3aaf3SDag-Erling Smørgrav }
21009a3aaf3SDag-Erling Smørgrav return (ssize_t)i;
21109a3aaf3SDag-Erling Smørgrav
21209a3aaf3SDag-Erling Smørgrav tokenread:
21309a3aaf3SDag-Erling Smørgrav if(*del == '"')
21409a3aaf3SDag-Erling Smørgrav /* do not skip over quotes after the string, they are part
21509a3aaf3SDag-Erling Smørgrav * of the next string. But skip over whitespace (if needed)*/
21609a3aaf3SDag-Erling Smørgrav sldns_fskipcs_l(f, del+1, line_nr);
21709a3aaf3SDag-Erling Smørgrav else sldns_fskipcs_l(f, del, line_nr);
21809a3aaf3SDag-Erling Smørgrav *t = '\0';
21909a3aaf3SDag-Erling Smørgrav if (p != 0) {
22009a3aaf3SDag-Erling Smørgrav return -1;
22109a3aaf3SDag-Erling Smørgrav }
22209a3aaf3SDag-Erling Smørgrav
22309a3aaf3SDag-Erling Smørgrav return (ssize_t)i;
22409a3aaf3SDag-Erling Smørgrav }
22509a3aaf3SDag-Erling Smørgrav
22609a3aaf3SDag-Erling Smørgrav ssize_t
sldns_fget_keyword_data(FILE * f,const char * keyword,const char * k_del,char * data,const char * d_del,size_t data_limit)22709a3aaf3SDag-Erling Smørgrav sldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, char *data,
22809a3aaf3SDag-Erling Smørgrav const char *d_del, size_t data_limit)
22909a3aaf3SDag-Erling Smørgrav {
23009a3aaf3SDag-Erling Smørgrav return sldns_fget_keyword_data_l(f, keyword, k_del, data, d_del,
23109a3aaf3SDag-Erling Smørgrav data_limit, NULL);
23209a3aaf3SDag-Erling Smørgrav }
23309a3aaf3SDag-Erling Smørgrav
23409a3aaf3SDag-Erling Smørgrav ssize_t
sldns_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)23509a3aaf3SDag-Erling Smørgrav sldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_del, char *data,
23609a3aaf3SDag-Erling Smørgrav const char *d_del, size_t data_limit, int *line_nr)
23709a3aaf3SDag-Erling Smørgrav {
23809a3aaf3SDag-Erling Smørgrav /* we assume: keyword|sep|data */
23909a3aaf3SDag-Erling Smørgrav char *fkeyword;
24009a3aaf3SDag-Erling Smørgrav ssize_t i;
24109a3aaf3SDag-Erling Smørgrav
24209a3aaf3SDag-Erling Smørgrav if(strlen(keyword) >= LDNS_MAX_KEYWORDLEN)
24309a3aaf3SDag-Erling Smørgrav return -1;
24409a3aaf3SDag-Erling Smørgrav fkeyword = (char*)malloc(LDNS_MAX_KEYWORDLEN);
24509a3aaf3SDag-Erling Smørgrav if(!fkeyword)
24609a3aaf3SDag-Erling Smørgrav return -1;
24709a3aaf3SDag-Erling Smørgrav
24809a3aaf3SDag-Erling Smørgrav i = sldns_fget_token(f, fkeyword, k_del, LDNS_MAX_KEYWORDLEN);
24909a3aaf3SDag-Erling Smørgrav if(i==0 || i==-1) {
25009a3aaf3SDag-Erling Smørgrav free(fkeyword);
25109a3aaf3SDag-Erling Smørgrav return -1;
25209a3aaf3SDag-Erling Smørgrav }
25309a3aaf3SDag-Erling Smørgrav
25409a3aaf3SDag-Erling Smørgrav /* case??? i instead of strlen? */
25509a3aaf3SDag-Erling Smørgrav if (strncmp(fkeyword, keyword, LDNS_MAX_KEYWORDLEN - 1) == 0) {
25609a3aaf3SDag-Erling Smørgrav /* whee! */
25709a3aaf3SDag-Erling Smørgrav /* printf("%s\n%s\n", "Matching keyword", fkeyword); */
25809a3aaf3SDag-Erling Smørgrav i = sldns_fget_token_l(f, data, d_del, data_limit, line_nr);
25909a3aaf3SDag-Erling Smørgrav free(fkeyword);
26009a3aaf3SDag-Erling Smørgrav return i;
26109a3aaf3SDag-Erling Smørgrav } else {
26209a3aaf3SDag-Erling Smørgrav /*printf("no match for %s (read: %s)\n", keyword, fkeyword);*/
26309a3aaf3SDag-Erling Smørgrav free(fkeyword);
26409a3aaf3SDag-Erling Smørgrav return -1;
26509a3aaf3SDag-Erling Smørgrav }
26609a3aaf3SDag-Erling Smørgrav }
26709a3aaf3SDag-Erling Smørgrav
26809a3aaf3SDag-Erling Smørgrav int
sldns_bgetc(sldns_buffer * buffer)26909a3aaf3SDag-Erling Smørgrav sldns_bgetc(sldns_buffer *buffer)
27009a3aaf3SDag-Erling Smørgrav {
27109a3aaf3SDag-Erling Smørgrav if (!sldns_buffer_available_at(buffer, buffer->_position, sizeof(uint8_t))) {
27209a3aaf3SDag-Erling Smørgrav sldns_buffer_set_position(buffer, sldns_buffer_limit(buffer));
27309a3aaf3SDag-Erling Smørgrav /* sldns_buffer_rewind(buffer);*/
27409a3aaf3SDag-Erling Smørgrav return EOF;
27509a3aaf3SDag-Erling Smørgrav }
27609a3aaf3SDag-Erling Smørgrav return (int)sldns_buffer_read_u8(buffer);
27709a3aaf3SDag-Erling Smørgrav }
27809a3aaf3SDag-Erling Smørgrav
27909a3aaf3SDag-Erling Smørgrav ssize_t
sldns_bget_token(sldns_buffer * b,char * token,const char * delim,size_t limit)28009a3aaf3SDag-Erling Smørgrav sldns_bget_token(sldns_buffer *b, char *token, const char *delim, size_t limit)
28109a3aaf3SDag-Erling Smørgrav {
28209a3aaf3SDag-Erling Smørgrav return sldns_bget_token_par(b, token, delim, limit, NULL, NULL);
28309a3aaf3SDag-Erling Smørgrav }
28409a3aaf3SDag-Erling Smørgrav
28509a3aaf3SDag-Erling Smørgrav ssize_t
sldns_bget_token_par(sldns_buffer * b,char * token,const char * delim,size_t limit,int * par,const char * skipw)28609a3aaf3SDag-Erling Smørgrav sldns_bget_token_par(sldns_buffer *b, char *token, const char *delim,
28709a3aaf3SDag-Erling Smørgrav size_t limit, int* par, const char* skipw)
28809a3aaf3SDag-Erling Smørgrav {
28909a3aaf3SDag-Erling Smørgrav int c, lc;
2908a384985SDag-Erling Smørgrav int p; /* 0 -> no parentheses seen, >0 nr of ( seen */
29109a3aaf3SDag-Erling Smørgrav int com, quoted;
29209a3aaf3SDag-Erling Smørgrav char *t;
29309a3aaf3SDag-Erling Smørgrav size_t i;
29409a3aaf3SDag-Erling Smørgrav const char *d;
29509a3aaf3SDag-Erling Smørgrav const char *del;
29609a3aaf3SDag-Erling Smørgrav
29709a3aaf3SDag-Erling Smørgrav /* standard delimiters */
29809a3aaf3SDag-Erling Smørgrav if (!delim) {
29909a3aaf3SDag-Erling Smørgrav /* from isspace(3) */
30009a3aaf3SDag-Erling Smørgrav del = LDNS_PARSE_NORMAL;
30109a3aaf3SDag-Erling Smørgrav } else {
30209a3aaf3SDag-Erling Smørgrav del = delim;
30309a3aaf3SDag-Erling Smørgrav }
30409a3aaf3SDag-Erling Smørgrav
30509a3aaf3SDag-Erling Smørgrav p = (par?*par:0);
30609a3aaf3SDag-Erling Smørgrav i = 0;
30709a3aaf3SDag-Erling Smørgrav com = 0;
30809a3aaf3SDag-Erling Smørgrav quoted = 0;
30909a3aaf3SDag-Erling Smørgrav t = token;
31009a3aaf3SDag-Erling Smørgrav lc = 0;
31109a3aaf3SDag-Erling Smørgrav if (del[0] == '"') {
31209a3aaf3SDag-Erling Smørgrav quoted = 1;
31309a3aaf3SDag-Erling Smørgrav }
31409a3aaf3SDag-Erling Smørgrav
31509a3aaf3SDag-Erling Smørgrav while ((c = sldns_bgetc(b)) != EOF) {
31609a3aaf3SDag-Erling Smørgrav if (c == '\r') /* carriage return */
31709a3aaf3SDag-Erling Smørgrav c = ' ';
31809a3aaf3SDag-Erling Smørgrav if (c == '(' && lc != '\\' && !quoted) {
31909a3aaf3SDag-Erling Smørgrav /* this only counts for non-comments */
32009a3aaf3SDag-Erling Smørgrav if (com == 0) {
32109a3aaf3SDag-Erling Smørgrav if(par) (*par)++;
32209a3aaf3SDag-Erling Smørgrav p++;
32309a3aaf3SDag-Erling Smørgrav }
32409a3aaf3SDag-Erling Smørgrav lc = c;
32509a3aaf3SDag-Erling Smørgrav continue;
32609a3aaf3SDag-Erling Smørgrav }
32709a3aaf3SDag-Erling Smørgrav
32809a3aaf3SDag-Erling Smørgrav if (c == ')' && lc != '\\' && !quoted) {
32909a3aaf3SDag-Erling Smørgrav /* this only counts for non-comments */
33009a3aaf3SDag-Erling Smørgrav if (com == 0) {
33109a3aaf3SDag-Erling Smørgrav if(par) (*par)--;
33209a3aaf3SDag-Erling Smørgrav p--;
33309a3aaf3SDag-Erling Smørgrav }
33409a3aaf3SDag-Erling Smørgrav lc = c;
33509a3aaf3SDag-Erling Smørgrav continue;
33609a3aaf3SDag-Erling Smørgrav }
33709a3aaf3SDag-Erling Smørgrav
33809a3aaf3SDag-Erling Smørgrav if (p < 0) {
33909a3aaf3SDag-Erling Smørgrav /* more ) then ( */
34009a3aaf3SDag-Erling Smørgrav *t = '\0';
34109a3aaf3SDag-Erling Smørgrav return 0;
34209a3aaf3SDag-Erling Smørgrav }
34309a3aaf3SDag-Erling Smørgrav
34409a3aaf3SDag-Erling Smørgrav /* do something with comments ; */
34509a3aaf3SDag-Erling Smørgrav if (c == ';' && quoted == 0) {
34609a3aaf3SDag-Erling Smørgrav if (lc != '\\') {
34709a3aaf3SDag-Erling Smørgrav com = 1;
34809a3aaf3SDag-Erling Smørgrav }
34909a3aaf3SDag-Erling Smørgrav }
35009a3aaf3SDag-Erling Smørgrav if (c == '"' && com == 0 && lc != '\\') {
35109a3aaf3SDag-Erling Smørgrav quoted = 1 - quoted;
35209a3aaf3SDag-Erling Smørgrav }
35309a3aaf3SDag-Erling Smørgrav
35409a3aaf3SDag-Erling Smørgrav if (c == '\n' && com != 0) {
35509a3aaf3SDag-Erling Smørgrav /* comments */
35609a3aaf3SDag-Erling Smørgrav com = 0;
35709a3aaf3SDag-Erling Smørgrav *t = ' ';
35809a3aaf3SDag-Erling Smørgrav lc = c;
35909a3aaf3SDag-Erling Smørgrav continue;
36009a3aaf3SDag-Erling Smørgrav }
36109a3aaf3SDag-Erling Smørgrav
36209a3aaf3SDag-Erling Smørgrav if (com == 1) {
36309a3aaf3SDag-Erling Smørgrav *t = ' ';
36409a3aaf3SDag-Erling Smørgrav lc = c;
36509a3aaf3SDag-Erling Smørgrav continue;
36609a3aaf3SDag-Erling Smørgrav }
36709a3aaf3SDag-Erling Smørgrav
36809a3aaf3SDag-Erling Smørgrav if (c == '\n' && p != 0) {
36909a3aaf3SDag-Erling Smørgrav /* in parentheses */
37009a3aaf3SDag-Erling Smørgrav /* do not write ' ' if we want to skip spaces */
3710eefd307SCy Schubert if(!(skipw && (strchr(skipw, c)||strchr(skipw, ' ')))) {
372091e9e46SCy Schubert /* check for space for the space character and a zero delimiter after that. */
373091e9e46SCy Schubert if (limit > 0 && (i+1 >= limit || (size_t)(t-token)+1 >= limit)) {
3740eefd307SCy Schubert *t = '\0';
3750eefd307SCy Schubert return -1;
3760eefd307SCy Schubert }
37709a3aaf3SDag-Erling Smørgrav *t++ = ' ';
3780eefd307SCy Schubert }
37909a3aaf3SDag-Erling Smørgrav lc = c;
38009a3aaf3SDag-Erling Smørgrav continue;
38109a3aaf3SDag-Erling Smørgrav }
38209a3aaf3SDag-Erling Smørgrav
38309a3aaf3SDag-Erling Smørgrav /* check to skip whitespace at start, but also after ( */
38409a3aaf3SDag-Erling Smørgrav if(skipw && i==0 && !com && !quoted && lc != '\\') {
38509a3aaf3SDag-Erling Smørgrav if(strchr(skipw, c)) {
38609a3aaf3SDag-Erling Smørgrav lc = c;
38709a3aaf3SDag-Erling Smørgrav continue;
38809a3aaf3SDag-Erling Smørgrav }
38909a3aaf3SDag-Erling Smørgrav }
39009a3aaf3SDag-Erling Smørgrav
39109a3aaf3SDag-Erling Smørgrav /* check if we hit the delim */
39209a3aaf3SDag-Erling Smørgrav for (d = del; *d; d++) {
39309a3aaf3SDag-Erling Smørgrav /* we can only exit if no parens or user tracks them */
39409a3aaf3SDag-Erling Smørgrav if (c == *d && lc != '\\' && (p == 0 || par)) {
39509a3aaf3SDag-Erling Smørgrav goto tokenread;
39609a3aaf3SDag-Erling Smørgrav }
39709a3aaf3SDag-Erling Smørgrav }
39809a3aaf3SDag-Erling Smørgrav
39909a3aaf3SDag-Erling Smørgrav i++;
400091e9e46SCy Schubert if (limit > 0 && (i+1 >= limit || (size_t)(t-token)+1 >= limit)) {
40109a3aaf3SDag-Erling Smørgrav *t = '\0';
40209a3aaf3SDag-Erling Smørgrav return -1;
40309a3aaf3SDag-Erling Smørgrav }
40409a3aaf3SDag-Erling Smørgrav *t++ = c;
40509a3aaf3SDag-Erling Smørgrav
40609a3aaf3SDag-Erling Smørgrav if (c == '\\' && lc == '\\') {
40709a3aaf3SDag-Erling Smørgrav lc = 0;
40809a3aaf3SDag-Erling Smørgrav } else {
40909a3aaf3SDag-Erling Smørgrav lc = c;
41009a3aaf3SDag-Erling Smørgrav }
41109a3aaf3SDag-Erling Smørgrav }
41209a3aaf3SDag-Erling Smørgrav *t = '\0';
41309a3aaf3SDag-Erling Smørgrav if (i == 0) {
41409a3aaf3SDag-Erling Smørgrav /* nothing read */
41509a3aaf3SDag-Erling Smørgrav return -1;
41609a3aaf3SDag-Erling Smørgrav }
41709a3aaf3SDag-Erling Smørgrav if (!par && p != 0) {
41809a3aaf3SDag-Erling Smørgrav return -1;
41909a3aaf3SDag-Erling Smørgrav }
42009a3aaf3SDag-Erling Smørgrav return (ssize_t)i;
42109a3aaf3SDag-Erling Smørgrav
42209a3aaf3SDag-Erling Smørgrav tokenread:
42309a3aaf3SDag-Erling Smørgrav if(*del == '"')
42409a3aaf3SDag-Erling Smørgrav /* do not skip over quotes after the string, they are part
42509a3aaf3SDag-Erling Smørgrav * of the next string. But skip over whitespace (if needed)*/
42609a3aaf3SDag-Erling Smørgrav sldns_bskipcs(b, del+1);
42709a3aaf3SDag-Erling Smørgrav else sldns_bskipcs(b, del);
42809a3aaf3SDag-Erling Smørgrav *t = '\0';
42909a3aaf3SDag-Erling Smørgrav
43009a3aaf3SDag-Erling Smørgrav if (!par && p != 0) {
43109a3aaf3SDag-Erling Smørgrav return -1;
43209a3aaf3SDag-Erling Smørgrav }
43309a3aaf3SDag-Erling Smørgrav return (ssize_t)i;
43409a3aaf3SDag-Erling Smørgrav }
43509a3aaf3SDag-Erling Smørgrav
43609a3aaf3SDag-Erling Smørgrav
43709a3aaf3SDag-Erling Smørgrav void
sldns_bskipcs(sldns_buffer * buffer,const char * s)43809a3aaf3SDag-Erling Smørgrav sldns_bskipcs(sldns_buffer *buffer, const char *s)
43909a3aaf3SDag-Erling Smørgrav {
44009a3aaf3SDag-Erling Smørgrav int found;
44109a3aaf3SDag-Erling Smørgrav char c;
44209a3aaf3SDag-Erling Smørgrav const char *d;
44309a3aaf3SDag-Erling Smørgrav
44409a3aaf3SDag-Erling Smørgrav while(sldns_buffer_available_at(buffer, buffer->_position, sizeof(char))) {
44509a3aaf3SDag-Erling Smørgrav c = (char) sldns_buffer_read_u8_at(buffer, buffer->_position);
44609a3aaf3SDag-Erling Smørgrav found = 0;
44709a3aaf3SDag-Erling Smørgrav for (d = s; *d; d++) {
44809a3aaf3SDag-Erling Smørgrav if (*d == c) {
44909a3aaf3SDag-Erling Smørgrav found = 1;
45009a3aaf3SDag-Erling Smørgrav }
45109a3aaf3SDag-Erling Smørgrav }
45209a3aaf3SDag-Erling Smørgrav if (found && buffer->_limit > buffer->_position) {
45309a3aaf3SDag-Erling Smørgrav buffer->_position += sizeof(char);
45409a3aaf3SDag-Erling Smørgrav } else {
45509a3aaf3SDag-Erling Smørgrav return;
45609a3aaf3SDag-Erling Smørgrav }
45709a3aaf3SDag-Erling Smørgrav }
45809a3aaf3SDag-Erling Smørgrav }
45909a3aaf3SDag-Erling Smørgrav
46009a3aaf3SDag-Erling Smørgrav void
sldns_fskipcs(FILE * fp,const char * s)46109a3aaf3SDag-Erling Smørgrav sldns_fskipcs(FILE *fp, const char *s)
46209a3aaf3SDag-Erling Smørgrav {
46309a3aaf3SDag-Erling Smørgrav sldns_fskipcs_l(fp, s, NULL);
46409a3aaf3SDag-Erling Smørgrav }
46509a3aaf3SDag-Erling Smørgrav
46609a3aaf3SDag-Erling Smørgrav void
sldns_fskipcs_l(FILE * fp,const char * s,int * line_nr)46709a3aaf3SDag-Erling Smørgrav sldns_fskipcs_l(FILE *fp, const char *s, int *line_nr)
46809a3aaf3SDag-Erling Smørgrav {
46909a3aaf3SDag-Erling Smørgrav int found;
47009a3aaf3SDag-Erling Smørgrav int c;
47109a3aaf3SDag-Erling Smørgrav const char *d;
47209a3aaf3SDag-Erling Smørgrav
47309a3aaf3SDag-Erling Smørgrav while ((c = fgetc(fp)) != EOF) {
47409a3aaf3SDag-Erling Smørgrav if (line_nr && c == '\n') {
47509a3aaf3SDag-Erling Smørgrav *line_nr = *line_nr + 1;
47609a3aaf3SDag-Erling Smørgrav }
47709a3aaf3SDag-Erling Smørgrav found = 0;
47809a3aaf3SDag-Erling Smørgrav for (d = s; *d; d++) {
47909a3aaf3SDag-Erling Smørgrav if (*d == c) {
48009a3aaf3SDag-Erling Smørgrav found = 1;
48109a3aaf3SDag-Erling Smørgrav }
48209a3aaf3SDag-Erling Smørgrav }
48309a3aaf3SDag-Erling Smørgrav if (!found) {
48409a3aaf3SDag-Erling Smørgrav /* with getc, we've read too far */
48509a3aaf3SDag-Erling Smørgrav ungetc(c, fp);
48609a3aaf3SDag-Erling Smørgrav return;
48709a3aaf3SDag-Erling Smørgrav }
48809a3aaf3SDag-Erling Smørgrav }
48909a3aaf3SDag-Erling Smørgrav }
49009a3aaf3SDag-Erling Smørgrav
49109a3aaf3SDag-Erling Smørgrav ssize_t
sldns_bget_keyword_data(sldns_buffer * b,const char * keyword,const char * k_del,char * data,const char * d_del,size_t data_limit)49209a3aaf3SDag-Erling Smørgrav sldns_bget_keyword_data(sldns_buffer *b, const char *keyword, const char *k_del, char
49309a3aaf3SDag-Erling Smørgrav *data, const char *d_del, size_t data_limit)
49409a3aaf3SDag-Erling Smørgrav {
49509a3aaf3SDag-Erling Smørgrav /* we assume: keyword|sep|data */
49609a3aaf3SDag-Erling Smørgrav char *fkeyword;
49709a3aaf3SDag-Erling Smørgrav ssize_t i;
49809a3aaf3SDag-Erling Smørgrav
49909a3aaf3SDag-Erling Smørgrav if(strlen(keyword) >= LDNS_MAX_KEYWORDLEN)
50009a3aaf3SDag-Erling Smørgrav return -1;
50109a3aaf3SDag-Erling Smørgrav fkeyword = (char*)malloc(LDNS_MAX_KEYWORDLEN);
50209a3aaf3SDag-Erling Smørgrav if(!fkeyword)
50309a3aaf3SDag-Erling Smørgrav return -1; /* out of memory */
50409a3aaf3SDag-Erling Smørgrav
50509a3aaf3SDag-Erling Smørgrav i = sldns_bget_token(b, fkeyword, k_del, data_limit);
50609a3aaf3SDag-Erling Smørgrav if(i==0 || i==-1) {
50709a3aaf3SDag-Erling Smørgrav free(fkeyword);
50809a3aaf3SDag-Erling Smørgrav return -1; /* nothing read */
50909a3aaf3SDag-Erling Smørgrav }
51009a3aaf3SDag-Erling Smørgrav
51109a3aaf3SDag-Erling Smørgrav /* case??? */
51209a3aaf3SDag-Erling Smørgrav if (strncmp(fkeyword, keyword, strlen(keyword)) == 0) {
51309a3aaf3SDag-Erling Smørgrav free(fkeyword);
51409a3aaf3SDag-Erling Smørgrav /* whee, the match! */
51509a3aaf3SDag-Erling Smørgrav /* retrieve it's data */
51609a3aaf3SDag-Erling Smørgrav i = sldns_bget_token(b, data, d_del, 0);
51709a3aaf3SDag-Erling Smørgrav return i;
51809a3aaf3SDag-Erling Smørgrav } else {
51909a3aaf3SDag-Erling Smørgrav free(fkeyword);
52009a3aaf3SDag-Erling Smørgrav return -1;
52109a3aaf3SDag-Erling Smørgrav }
52209a3aaf3SDag-Erling Smørgrav }
52309a3aaf3SDag-Erling Smørgrav
524