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