1 /*
2  * Configuration parsing
3  * Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "includes.h"
10 
11 #include "utils/config.h"
12 #include "common.h"
13 
14 
newline_terminated(const char * buf,size_t buflen)15 static int newline_terminated(const char *buf, size_t buflen)
16 {
17 	size_t len = os_strlen(buf);
18 	if (len == 0)
19 		return 0;
20 	if (len == buflen - 1 && buf[buflen - 1] != '\r' &&
21 	    buf[len - 1] != '\n')
22 		return 0;
23 	return 1;
24 }
25 
26 
skip_line_end(FILE * stream)27 static void skip_line_end(FILE *stream)
28 {
29 	char buf[100];
30 	while (fgets(buf, sizeof(buf), stream)) {
31 		buf[sizeof(buf) - 1] = '\0';
32 		if (newline_terminated(buf, sizeof(buf)))
33 			return;
34 	}
35 }
36 
37 
wpa_config_get_line(char * s,int size,FILE * stream,int * line,char ** _pos)38 char * wpa_config_get_line(char *s, int size, FILE *stream, int *line,
39 			   char **_pos)
40 {
41 	char *pos, *end, *sstart;
42 
43 	while (fgets(s, size, stream)) {
44 		(*line)++;
45 		s[size - 1] = '\0';
46 		if (!newline_terminated(s, size)) {
47 			/*
48 			 * The line was truncated - skip rest of it to avoid
49 			 * confusing error messages.
50 			 */
51 			wpa_printf(MSG_INFO, "Long line in configuration file "
52 				   "truncated");
53 			skip_line_end(stream);
54 		}
55 		pos = s;
56 
57 		/* Skip white space from the beginning of line. */
58 		while (*pos == ' ' || *pos == '\t' || *pos == '\r')
59 			pos++;
60 
61 		/* Skip comment lines and empty lines */
62 		if (*pos == '#' || *pos == '\n' || *pos == '\0')
63 			continue;
64 
65 		/*
66 		 * Remove # comments unless they are within a double quoted
67 		 * string.
68 		 */
69 		sstart = pos;
70 		end = os_strchr(sstart, '#');
71 		while (end) {
72 			sstart = os_strchr(sstart, '"');
73 			if (!sstart || sstart > end)
74 				break;
75 			sstart = os_strchr(sstart + 1, '"');
76 			if (!sstart)
77 				break;
78 			sstart++;
79 			if (sstart > end)
80 				end = os_strchr(sstart, '#');
81 		}
82 
83 		if (end)
84 			*end-- = '\0';
85 		else
86 			end = pos + os_strlen(pos) - 1;
87 
88 		/* Remove trailing white space. */
89 		while (end > pos &&
90 		       (*end == '\n' || *end == ' ' || *end == '\t' ||
91 			*end == '\r'))
92 			*end-- = '\0';
93 
94 		if (*pos == '\0')
95 			continue;
96 
97 		if (_pos)
98 			*_pos = pos;
99 		return pos;
100 	}
101 
102 	if (_pos)
103 		*_pos = NULL;
104 	return NULL;
105 }
106