Home | History | Annotate | Download | only in src
      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 
     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 
     37 void parse_release(parse_info_t * info)
     38 {
     39 
     40 	parse_close(info);
     41 	parse_dispose_line(info);
     42 	free(info);
     43 }
     44 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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