parser.c (3163B)
1 #include <fcntl.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <sys/mman.h> 6 #include <sys/stat.h> 7 #include <stdlib.h> 8 #include <unistd.h> 9 #include <regex.h> 10 11 #include "parser.h" 12 13 static void * 14 smash_load_file_in_memory(const char *filename, size_t *data_size) 15 { 16 int fd; 17 char *data; 18 struct stat finfo; 19 20 if ((fd = open(filename, O_RDONLY, S_IRUSR | S_IWUSR)) < 0) 21 goto err1; 22 23 if (fstat(fd, &finfo) < 0) 24 goto err2; 25 26 if ((data = mmap(NULL, finfo.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0)) 27 == MAP_FAILED) 28 goto err2; 29 30 *data_size = finfo.st_size; 31 close(fd); 32 return data; 33 err2: 34 close(fd); 35 err1: 36 return NULL; 37 } 38 39 static void 40 smash_populate_delay(const char *line, size_t n, const regmatch_t *rm, struct cfg_delays *delays) 41 { 42 delays->delays[n].src = strtol(line + rm[1].rm_so, NULL, 10); 43 delays->delays[n].dst = strtol(line + rm[2].rm_so, NULL, 10); 44 delays->delays[n].delay = strtol(line + rm[3].rm_so, NULL, 10); 45 delays->delays[n].msg = strtol(line + rm[4].rm_so, NULL, 10); 46 } 47 48 static void 49 smash_populate_failure(const char *line, size_t n, const regmatch_t *rm, struct cfg_failures *failures) 50 { 51 failures->failures[n].node = strtol(line + rm[1].rm_so, NULL, 10); 52 failures->failures[n].time = strtol(line + rm[2].rm_so, NULL, 10); 53 } 54 55 static char * 56 smash_get_config_path(enum CFG ctype) 57 { 58 return getenv((ctype == CFG_DELAY ? CFG_DELAY_PATH : CFG_FAILURE_PATH)); 59 } 60 61 static int 62 count_lines(const char *rs) 63 { 64 int lines = 0; 65 while (*(rs)++ != '\0') 66 if (*rs == '\n' || *rs == '\r') 67 lines++; 68 return lines; 69 } 70 71 int 72 smash_parse_cfg(enum CFG ctype, void **cfg) 73 { 74 struct cfg_delays *delays; 75 struct cfg_failures *failures; 76 void *data; 77 int ret, lines; 78 size_t data_size, nline, n_cfg; 79 char *config_path, *line, err_buf[100]; 80 const char *rs; 81 regex_t r; 82 regmatch_t rm[5]; 83 void (*f)(); 84 85 if (!(config_path = smash_get_config_path(ctype))) { 86 *cfg = NULL; 87 return ctype == CFG_DELAY ? -1 : 0; 88 } 89 90 if (!(data = smash_load_file_in_memory(config_path, &data_size))) 91 return -1; 92 93 lines = count_lines(data); 94 *cfg = malloc(ctype == CFG_DELAY ? sizeof(struct cfg_delays) + 95 lines * sizeof(struct cfg_delay) 96 : sizeof(struct cfg_failures) + 97 lines * sizeof(struct cfg_delay)); 98 99 if (ctype == CFG_DELAY) { 100 delays = *cfg; 101 delays->size = lines; 102 rs = "([0-9]+);([0-9]+);([0-9]+);(-?[0-9]+)"; 103 n_cfg = 5; 104 f = smash_populate_delay; 105 } else { 106 failures = *cfg; 107 failures->size = lines; 108 rs = "([0-9]+);([0-9]+)"; 109 n_cfg = 3; 110 f = smash_populate_failure; 111 } 112 113 if ((ret = regcomp(&r, rs, REG_EXTENDED)) != 0) { 114 regerror(ret, &r, err_buf, 100); 115 fprintf(stderr, "failed to compile regex <%s>:%s\n", rs, 116 err_buf); 117 goto err; 118 } 119 120 nline = 0; 121 line = strtok(data, "\n"); 122 while (line) { 123 /* if line is a comment or snaphot, do smth */ 124 if ((ret = regexec(&r, line, n_cfg, rm, 0)) != 0) { 125 regerror(ret, &r, err_buf, 100); 126 fprintf(stderr, "line %ld: %s\n", nline + 1, err_buf); 127 goto err; 128 } 129 f(line, nline, rm, *cfg); 130 nline++; 131 line = strtok(NULL, "\n"); 132 } 133 134 regfree(&r); 135 munmap(data, data_size); 136 return 0; 137 err: 138 regfree(&r); 139 munmap(data, data_size); 140 return -1; 141 }