File Coverage

src/ldns/parse.c
Criterion Covered Total %
statement 124 211 58.7
branch 121 216 56.0
condition n/a
subroutine n/a
pod n/a
total 245 427 57.3


line stmt bran cond sub pod time code
1             /*
2             * a generic (simple) parser. Use to parse rr's, private key
3             * information and /etc/resolv.conf files
4             *
5             * a Net::DNS like library for C
6             * LibDNS Team @ NLnet Labs
7             * (c) NLnet Labs, 2005-2006
8             * See the file LICENSE for the license
9             */
10             #include
11             #include
12              
13             #include
14             #include
15              
16             ldns_lookup_table ldns_directive_types[] = {
17             { LDNS_DIR_TTL, "$TTL" },
18             { LDNS_DIR_ORIGIN, "$ORIGIN" },
19             { LDNS_DIR_INCLUDE, "$INCLUDE" },
20             { 0, NULL }
21             };
22              
23             /* add max_limit here? */
24             ssize_t
25 0           ldns_fget_token(FILE *f, char *token, const char *delim, size_t limit)
26             {
27 0           return ldns_fget_token_l(f, token, delim, limit, NULL);
28             }
29              
30             ssize_t
31 45           ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr)
32             {
33             int c, prev_c;
34             int p; /* 0 -> no parenthese seen, >0 nr of ( seen */
35             int com, quoted;
36             char *t;
37             size_t i;
38             const char *d;
39             const char *del;
40              
41             /* standard delimeters */
42 45 50         if (!delim) {
43             /* from isspace(3) */
44 0           del = LDNS_PARSE_NORMAL;
45             } else {
46 45           del = delim;
47             }
48              
49 45           p = 0;
50 45           i = 0;
51 45           com = 0;
52 45           quoted = 0;
53 45           prev_c = 0;
54 45           t = token;
55 45 50         if (del[0] == '"') {
56 0           quoted = 1;
57             }
58 1090 100         while ((c = getc(f)) != EOF) {
59 1087 50         if (c == '\r') /* carriage return */
60 0           c = ' ';
61 1087 100         if (c == '(' && prev_c != '\\' && !quoted) {
    50          
    50          
62             /* this only counts for non-comments */
63 5 100         if (com == 0) {
64 1           p++;
65             }
66 5           prev_c = c;
67 5           continue;
68             }
69              
70 1082 100         if (c == ')' && prev_c != '\\' && !quoted) {
    50          
    50          
71             /* this only counts for non-comments */
72 5 100         if (com == 0) {
73 1           p--;
74             }
75 5           prev_c = c;
76 5           continue;
77             }
78              
79 1077 50         if (p < 0) {
80             /* more ) then ( - close off the string */
81 0           *t = '\0';
82 0           return 0;
83             }
84              
85             /* do something with comments ; */
86 1077 100         if (c == ';' && quoted == 0) {
    50          
87 6 50         if (prev_c != '\\') {
88 6           com = 1;
89             }
90             }
91 1077 50         if (c == '\"' && com == 0 && prev_c != '\\') {
    0          
    0          
92 0           quoted = 1 - quoted;
93             }
94              
95 1077 100         if (c == '\n' && com != 0) {
    100          
96             /* comments */
97 6           com = 0;
98 6           *t = ' ';
99 6 50         if (line_nr) {
100 0           *line_nr = *line_nr + 1;
101             }
102 6 100         if (p == 0 && i > 0) {
    50          
103             goto tokenread;
104             } else {
105 5           prev_c = c;
106 5           continue;
107             }
108             }
109              
110 1071 100         if (com == 1) {
111 77           *t = ' ';
112 77           prev_c = c;
113 77           continue;
114             }
115              
116 994 100         if (c == '\n' && p != 0 && t > token) {
    100          
    50          
117             /* in parentheses */
118 1 50         if (line_nr) {
119 0           *line_nr = *line_nr + 1;
120             }
121 1           *t++ = ' ';
122 1           prev_c = c;
123 1           continue;
124             }
125              
126             /* check if we hit the delim */
127 3953 100         for (d = del; *d; d++) {
128 3001 100         if (c == *d && i > 0 && prev_c != '\\' && p == 0) {
    50          
    50          
    50          
129 41 100         if (c == '\n' && line_nr) {
    100          
130 3           *line_nr = *line_nr + 1;
131             }
132 41           goto tokenread;
133             }
134             }
135 952 50         if (c != '\0' && c != '\n') {
    50          
136 952           i++;
137             }
138 952 100         if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) {
    50          
    50          
139 0           *t = '\0';
140 0           return -1;
141             }
142 952 50         if (c != '\0' && c != '\n') {
    50          
143 952           *t++ = c;
144             }
145 952 50         if (c == '\\' && prev_c == '\\')
    0          
146 0           prev_c = 0;
147 952           else prev_c = c;
148             }
149 3           *t = '\0';
150 3 50         if (c == EOF) {
151 3           return (ssize_t)i;
152             }
153              
154 0 0         if (i == 0) {
155             /* nothing read */
156 0           return -1;
157             }
158 0 0         if (p != 0) {
159 0           return -1;
160             }
161 0           return (ssize_t)i;
162              
163             tokenread:
164 42 50         if(*del == '"') /* do not skip over quotes, they are significant */
165 0           ldns_fskipcs_l(f, del+1, line_nr);
166 42           else ldns_fskipcs_l(f, del, line_nr);
167 42           *t = '\0';
168 42 50         if (p != 0) {
169 0           return -1;
170             }
171              
172 42           return (ssize_t)i;
173             }
174              
175             ssize_t
176 0           ldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, char *data,
177             const char *d_del, size_t data_limit)
178             {
179 0           return ldns_fget_keyword_data_l(f, keyword, k_del, data, d_del,
180             data_limit, NULL);
181             }
182              
183             ssize_t
184 0           ldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_del, char *data,
185             const char *d_del, size_t data_limit, int *line_nr)
186             {
187             /* we assume: keyword|sep|data */
188             char *fkeyword;
189             ssize_t i;
190              
191 0 0         if(strlen(keyword) >= LDNS_MAX_KEYWORDLEN)
192 0           return -1;
193 0           fkeyword = LDNS_XMALLOC(char, LDNS_MAX_KEYWORDLEN);
194 0 0         if(!fkeyword)
195 0           return -1;
196              
197 0           i = ldns_fget_token(f, fkeyword, k_del, LDNS_MAX_KEYWORDLEN);
198 0 0         if(i==0 || i==-1) {
    0          
199 0           LDNS_FREE(fkeyword);
200 0           return -1;
201             }
202              
203             /* case??? i instead of strlen? */
204 0 0         if (strncmp(fkeyword, keyword, LDNS_MAX_KEYWORDLEN - 1) == 0) {
205             /* whee! */
206             /* printf("%s\n%s\n", "Matching keyword", fkeyword); */
207 0           i = ldns_fget_token_l(f, data, d_del, data_limit, line_nr);
208 0           LDNS_FREE(fkeyword);
209 0           return i;
210             } else {
211             /*printf("no match for %s (read: %s)\n", keyword, fkeyword);*/
212 0           LDNS_FREE(fkeyword);
213 0           return -1;
214             }
215             }
216              
217              
218             ssize_t
219 387           ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t limit)
220             {
221             int c, lc;
222             int p; /* 0 -> no parenthese seen, >0 nr of ( seen */
223             int com, quoted;
224             char *t;
225             size_t i;
226             const char *d;
227             const char *del;
228              
229             /* standard delimiters */
230 387 50         if (!delim) {
231             /* from isspace(3) */
232 0           del = LDNS_PARSE_NORMAL;
233             } else {
234 387           del = delim;
235             }
236              
237 387           p = 0;
238 387           i = 0;
239 387           com = 0;
240 387           quoted = 0;
241 387           t = token;
242 387           lc = 0;
243 387 100         if (del[0] == '"') {
244 2           quoted = 1;
245             }
246              
247 5671 100         while ((c = ldns_bgetc(b)) != EOF) {
248 5525 50         if (c == '\r') /* carriage return */
249 0           c = ' ';
250 5525 100         if (c == '(' && lc != '\\' && !quoted) {
    50          
    50          
251             /* this only counts for non-comments */
252 0 0         if (com == 0) {
253 0           p++;
254             }
255 0           lc = c;
256 0           continue;
257             }
258              
259 5525 100         if (c == ')' && lc != '\\' && !quoted) {
    50          
    50          
260             /* this only counts for non-comments */
261 0 0         if (com == 0) {
262 0           p--;
263             }
264 0           lc = c;
265 0           continue;
266             }
267              
268 5525 50         if (p < 0) {
269             /* more ) then ( */
270 0           *t = '\0';
271 0           return 0;
272             }
273              
274             /* do something with comments ; */
275 5525 50         if (c == ';' && quoted == 0) {
    0          
276 0 0         if (lc != '\\') {
277 0           com = 1;
278             }
279             }
280 5525 100         if (c == '"' && com == 0 && lc != '\\') {
    50          
    50          
281 6           quoted = 1 - quoted;
282             }
283              
284 5525 50         if (c == '\n' && com != 0) {
    0          
285             /* comments */
286 0           com = 0;
287 0           *t = ' ';
288 0           lc = c;
289 0           continue;
290             }
291              
292 5525 50         if (com == 1) {
293 0           *t = ' ';
294 0           lc = c;
295 0           continue;
296             }
297              
298 5525 50         if (c == '\n' && p != 0) {
    0          
299             /* in parentheses */
300 0           *t++ = ' ';
301 0           lc = c;
302 0           continue;
303             }
304              
305             /* check if we hit the delim */
306 12553 100         for (d = del; *d; d++) {
307 7269 100         if (c == *d && lc != '\\' && p == 0) {
    50          
    50          
308 241           goto tokenread;
309             }
310             }
311              
312 5284           i++;
313 5284 50         if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) {
    50          
    50          
314 0           *t = '\0';
315 0           return -1;
316             }
317 5284           *t++ = c;
318              
319 5284 50         if (c == '\\' && lc == '\\') {
    0          
320 0           lc = 0;
321             } else {
322 5284           lc = c;
323             }
324             }
325 146           *t = '\0';
326 146 100         if (i == 0) {
327             /* nothing read */
328 21           return -1;
329             }
330 125 50         if (p != 0) {
331 0           return -1;
332             }
333 125           return (ssize_t)i;
334              
335             tokenread:
336 241 100         if(*del == '"') /* do not skip over quotes, they are significant */
337 2           ldns_bskipcs(b, del+1);
338 239           else ldns_bskipcs(b, del);
339 241           *t = '\0';
340              
341 241 50         if (p != 0) {
342 0           return -1;
343             }
344 241           return (ssize_t)i;
345             }
346              
347              
348             void
349 241           ldns_bskipcs(ldns_buffer *buffer, const char *s)
350             {
351             bool found;
352             char c;
353             const char *d;
354              
355 314 100         while(ldns_buffer_available_at(buffer, buffer->_position, sizeof(char))) {
356 312           c = (char) ldns_buffer_read_u8_at(buffer, buffer->_position);
357 312           found = false;
358 1230 100         for (d = s; *d; d++) {
359 918 100         if (*d == c) {
360 73           found = true;
361             }
362             }
363 312 100         if (found && buffer->_limit > buffer->_position) {
    50          
364 73           buffer->_position += sizeof(char);
365             } else {
366 239           return;
367             }
368             }
369             }
370              
371             void
372 0           ldns_fskipcs(FILE *fp, const char *s)
373             {
374 0           ldns_fskipcs_l(fp, s, NULL);
375 0           }
376              
377             void
378 42           ldns_fskipcs_l(FILE *fp, const char *s, int *line_nr)
379             {
380             bool found;
381             int c;
382             const char *d;
383              
384 46 100         while ((c = fgetc(fp)) != EOF) {
385 43 100         if (line_nr && c == '\n') {
    50          
386 0           *line_nr = *line_nr + 1;
387             }
388 43           found = false;
389 205 100         for (d = s; *d; d++) {
390 162 100         if (*d == c) {
391 4           found = true;
392             }
393             }
394 43 100         if (!found) {
395             /* with getc, we've read too far */
396 39           ungetc(c, fp);
397 39           return;
398             }
399             }
400             }
401              
402             ssize_t
403 0           ldns_bget_keyword_data(ldns_buffer *b, const char *keyword, const char *k_del, char
404             *data, const char *d_del, size_t data_limit)
405             {
406             /* we assume: keyword|sep|data */
407             char *fkeyword;
408             ssize_t i;
409              
410 0 0         if(strlen(keyword) >= LDNS_MAX_KEYWORDLEN)
411 0           return -1;
412 0           fkeyword = LDNS_XMALLOC(char, LDNS_MAX_KEYWORDLEN);
413 0 0         if(!fkeyword)
414 0           return -1; /* out of memory */
415              
416 0           i = ldns_bget_token(b, fkeyword, k_del, data_limit);
417 0 0         if(i==0 || i==-1) {
    0          
418 0           LDNS_FREE(fkeyword);
419 0           return -1; /* nothing read */
420             }
421              
422             /* case??? */
423 0 0         if (strncmp(fkeyword, keyword, strlen(keyword)) == 0) {
424 0           LDNS_FREE(fkeyword);
425             /* whee, the match! */
426             /* retrieve it's data */
427 0           i = ldns_bget_token(b, data, d_del, 0);
428 0           return i;
429             } else {
430 0           LDNS_FREE(fkeyword);
431 0           return -1;
432             }
433             }
434