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