1 /* Copyright (C) 2005 Red Hat, Inc. */
2
3 #include <stdio.h>
4 #include <stdio_ext.h>
5 #include <errno.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <ctype.h>
9 #include <semanage/handle.h>
10 #include "parse_utils.h"
11 #include "debug.h"
12
parse_init(semanage_handle_t * handle,const char * filename,void * parse_arg,parse_info_t ** info)13 int parse_init(semanage_handle_t * handle,
14 const char *filename, void *parse_arg, parse_info_t ** info)
15 {
16
17 parse_info_t *tmp_info = (parse_info_t *) malloc(sizeof(parse_info_t));
18
19 if (!tmp_info) {
20 ERR(handle,
21 "out of memory, could not allocate parse structure");
22 return STATUS_ERR;
23 }
24
25 tmp_info->filename = filename;
26 tmp_info->file_stream = NULL;
27 tmp_info->working_copy = NULL;
28 tmp_info->orig_line = NULL;
29 tmp_info->ptr = NULL;
30 tmp_info->lineno = 0;
31 tmp_info->parse_arg = parse_arg;
32
33 *info = tmp_info;
34 return STATUS_SUCCESS;
35 }
36
parse_release(parse_info_t * info)37 void parse_release(parse_info_t * info)
38 {
39
40 parse_close(info);
41 parse_dispose_line(info);
42 free(info);
43 }
44
parse_open(semanage_handle_t * handle,parse_info_t * info)45 int parse_open(semanage_handle_t * handle, parse_info_t * info)
46 {
47
48 info->file_stream = fopen(info->filename, "r");
49 if (!info->file_stream && (errno != ENOENT)) {
50 ERR(handle, "could not open file %s: %s",
51 info->filename, strerror(errno));
52 return STATUS_ERR;
53 }
54 if (info->file_stream)
55 __fsetlocking(info->file_stream, FSETLOCKING_BYCALLER);
56
57 return STATUS_SUCCESS;
58 }
59
parse_close(parse_info_t * info)60 void parse_close(parse_info_t * info)
61 {
62
63 if (info->file_stream)
64 fclose(info->file_stream);
65 info->file_stream = NULL;
66 }
67
parse_dispose_line(parse_info_t * info)68 void parse_dispose_line(parse_info_t * info)
69 {
70 if (info->orig_line) {
71 free(info->orig_line);
72 info->orig_line = NULL;
73 }
74
75 if (info->working_copy) {
76 free(info->working_copy);
77 info->working_copy = NULL;
78 }
79
80 info->ptr = NULL;
81 }
82
parse_skip_space(semanage_handle_t * handle,parse_info_t * info)83 int parse_skip_space(semanage_handle_t * handle, parse_info_t * info)
84 {
85
86 size_t buf_len = 0;
87 ssize_t len;
88 int lineno = info->lineno;
89 char *buffer = NULL;
90 char *ptr;
91
92 if (info->ptr) {
93 while (*(info->ptr) && isspace(*(info->ptr)))
94 info->ptr++;
95
96 if (*(info->ptr))
97 return STATUS_SUCCESS;
98 }
99
100 parse_dispose_line(info);
101
102 while (info->file_stream &&
103 ((len = getline(&buffer, &buf_len, info->file_stream)) > 0)) {
104
105 lineno++;
106
107 /* Eat newline, preceding whitespace */
108 if (buffer[len - 1] == '\n')
109 buffer[len - 1] = '\0';
110
111 ptr = buffer;
112 while (*ptr && isspace(*ptr))
113 ptr++;
114
115 /* Skip comments and blank lines */
116 if ((*ptr) && *ptr != '#') {
117 char *tmp = strdup(buffer);
118 if (!tmp)
119 goto omem;
120
121 info->lineno = lineno;
122 info->working_copy = buffer;
123 info->orig_line = tmp;
124 info->ptr = ptr;
125
126 return STATUS_SUCCESS;
127 }
128 }
129
130 free(buffer);
131 buffer = NULL;
132
133 return STATUS_SUCCESS;
134
135 omem:
136 ERR(handle, "out of memory, could not allocate buffer");
137 free(buffer);
138 return STATUS_ERR;
139 }
140
parse_assert_noeof(semanage_handle_t * handle,parse_info_t * info)141 int parse_assert_noeof(semanage_handle_t * handle, parse_info_t * info)
142 {
143
144 if (!info->ptr) {
145 ERR(handle, "unexpected end of file (%s: %u)",
146 info->filename, info->lineno);
147 return STATUS_ERR;
148 }
149
150 return STATUS_SUCCESS;
151 }
152
parse_assert_space(semanage_handle_t * handle,parse_info_t * info)153 int parse_assert_space(semanage_handle_t * handle, parse_info_t * info)
154 {
155
156 if (parse_assert_noeof(handle, info) < 0)
157 return STATUS_ERR;
158
159 if (*(info->ptr) && !isspace(*(info->ptr))) {
160 ERR(handle, "missing whitespace (%s: %u):\n%s",
161 info->filename, info->lineno, info->orig_line);
162 return STATUS_ERR;
163 }
164
165 if (parse_skip_space(handle, info) < 0)
166 return STATUS_ERR;
167
168 return STATUS_SUCCESS;
169 }
170
parse_assert_ch(semanage_handle_t * handle,parse_info_t * info,const char ch)171 int parse_assert_ch(semanage_handle_t * handle,
172 parse_info_t * info, const char ch)
173 {
174
175 if (parse_assert_noeof(handle, info) < 0)
176 return STATUS_ERR;
177
178 if (*(info->ptr) != ch) {
179 ERR(handle, "expected character \'%c\', but found \'%c\' "
180 "(%s: %u):\n%s", ch, *(info->ptr), info->filename,
181 info->lineno, info->orig_line);
182 return STATUS_ERR;
183 }
184
185 info->ptr++;
186
187 return STATUS_SUCCESS;
188 }
189
parse_assert_str(semanage_handle_t * handle,parse_info_t * info,const char * assert_str)190 int parse_assert_str(semanage_handle_t * handle,
191 parse_info_t * info, const char *assert_str)
192 {
193
194 size_t len = strlen(assert_str);
195
196 if (parse_assert_noeof(handle, info) < 0)
197 return STATUS_ERR;
198
199 if (strncmp(info->ptr, assert_str, len)) {
200 ERR(handle, "experted string \"%s\", but found \"%s\" "
201 "(%s: %u):\n%s", assert_str, info->ptr,
202 info->filename, info->lineno, info->orig_line);
203
204 return STATUS_ERR;
205 }
206
207 info->ptr += len;
208 return STATUS_SUCCESS;
209 }
210
parse_optional_ch(parse_info_t * info,const char ch)211 int parse_optional_ch(parse_info_t * info, const char ch)
212 {
213
214 if (!info->ptr)
215 return STATUS_NODATA;
216 if (*(info->ptr) != ch)
217 return STATUS_NODATA;
218
219 info->ptr++;
220 return STATUS_SUCCESS;
221 }
222
parse_optional_str(parse_info_t * info,const char * str)223 int parse_optional_str(parse_info_t * info, const char *str)
224 {
225 size_t len = strlen(str);
226
227 if (strncmp(info->ptr, str, len))
228 return STATUS_NODATA;
229
230 info->ptr += len;
231 return STATUS_SUCCESS;
232 }
233
parse_fetch_int(semanage_handle_t * handle,parse_info_t * info,int * num,char delim)234 int parse_fetch_int(semanage_handle_t * handle,
235 parse_info_t * info, int *num, char delim)
236 {
237
238 char *str = NULL;
239 char *test = NULL;
240 int value = 0;
241
242 if (parse_fetch_string(handle, info, &str, delim) < 0)
243 goto err;
244
245 if (!isdigit((int)*str)) {
246 ERR(handle, "expected a numeric value: (%s: %u)\n%s",
247 info->filename, info->lineno, info->orig_line);
248 goto err;
249 }
250
251 value = strtol(str, &test, 10);
252 if (*test != '\0') {
253 ERR(handle, "could not parse numeric value \"%s\": "
254 "(%s: %u)\n%s", str, info->filename,
255 info->lineno, info->orig_line);
256 goto err;
257 }
258
259 *num = value;
260 free(str);
261 return STATUS_SUCCESS;
262
263 err:
264 ERR(handle, "could not fetch numeric value");
265 free(str);
266 return STATUS_ERR;
267 }
268
parse_fetch_string(semanage_handle_t * handle,parse_info_t * info,char ** str,char delim)269 int parse_fetch_string(semanage_handle_t * handle,
270 parse_info_t * info, char **str, char delim)
271 {
272
273 char *start = info->ptr;
274 int len = 0;
275 char *tmp_str = NULL;
276
277 if (parse_assert_noeof(handle, info) < 0)
278 goto err;
279
280 while (*(info->ptr) && !isspace(*(info->ptr)) &&
281 (*(info->ptr) != delim)) {
282 info->ptr++;
283 len++;
284 }
285
286 if (len == 0) {
287 ERR(handle, "expected non-empty string, but did not "
288 "find one (%s: %u):\n%s", info->filename, info->lineno,
289 info->orig_line);
290 goto err;
291 }
292
293 tmp_str = (char *)malloc(len + 1);
294 if (!tmp_str) {
295 ERR(handle, "out of memory");
296 goto err;
297 }
298
299 strncpy(tmp_str, start, len);
300 *(tmp_str + len) = '\0';
301 *str = tmp_str;
302 return STATUS_SUCCESS;
303
304 err:
305 ERR(handle, "could not fetch string value");
306 return STATUS_ERR;
307 }
308