142 lines
3.1 KiB
C
142 lines
3.1 KiB
C
|
#include <fcntl.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <sys/mman.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <unistd.h>
|
||
|
#include <regex.h>
|
||
|
|
||
|
#include "parser.h"
|
||
|
|
||
|
static void *
|
||
|
smash_load_file_in_memory(const char *filename, size_t *data_size)
|
||
|
{
|
||
|
int fd;
|
||
|
char *data;
|
||
|
struct stat finfo;
|
||
|
|
||
|
if ((fd = open(filename, O_RDONLY, S_IRUSR | S_IWUSR)) < 0)
|
||
|
goto err1;
|
||
|
|
||
|
if (fstat(fd, &finfo) < 0)
|
||
|
goto err2;
|
||
|
|
||
|
if ((data = mmap(NULL, finfo.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0))
|
||
|
== MAP_FAILED)
|
||
|
goto err2;
|
||
|
|
||
|
*data_size = finfo.st_size;
|
||
|
close(fd);
|
||
|
return data;
|
||
|
err2:
|
||
|
close(fd);
|
||
|
err1:
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
smash_populate_delay(const char *line, size_t n, const regmatch_t *rm, struct cfg_delays *delays)
|
||
|
{
|
||
|
delays->delays[n].src = strtol(line + rm[1].rm_so, NULL, 10);
|
||
|
delays->delays[n].dst = strtol(line + rm[2].rm_so, NULL, 10);
|
||
|
delays->delays[n].delay = strtol(line + rm[3].rm_so, NULL, 10);
|
||
|
delays->delays[n].msg = strtol(line + rm[4].rm_so, NULL, 10);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
smash_populate_failure(const char *line, size_t n, const regmatch_t *rm, struct cfg_failures *failures)
|
||
|
{
|
||
|
failures->failures[n].node = strtol(line + rm[1].rm_so, NULL, 10);
|
||
|
failures->failures[n].time = strtol(line + rm[2].rm_so, NULL, 10);
|
||
|
}
|
||
|
|
||
|
static char *
|
||
|
smash_get_config_path(enum CFG ctype)
|
||
|
{
|
||
|
return getenv((ctype == CFG_DELAY ? CFG_DELAY_PATH : CFG_FAILURE_PATH));
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
count_lines(const char *rs)
|
||
|
{
|
||
|
int lines = 0;
|
||
|
while (*(rs)++ != '\0')
|
||
|
if (*rs == '\n' || *rs == '\r')
|
||
|
lines++;
|
||
|
return lines;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
smash_parse_cfg(enum CFG ctype, void **cfg)
|
||
|
{
|
||
|
struct cfg_delays *delays;
|
||
|
struct cfg_failures *failures;
|
||
|
void *data;
|
||
|
int ret, lines;
|
||
|
size_t data_size, nline, n_cfg;
|
||
|
char *config_path, *line, err_buf[100];
|
||
|
const char *rs;
|
||
|
regex_t r;
|
||
|
regmatch_t rm[5];
|
||
|
void (*f)();
|
||
|
|
||
|
if (!(config_path = smash_get_config_path(ctype))) {
|
||
|
*cfg = NULL;
|
||
|
return ctype == CFG_DELAY ? -1 : 0;
|
||
|
}
|
||
|
|
||
|
if (!(data = smash_load_file_in_memory(config_path, &data_size)))
|
||
|
return -1;
|
||
|
|
||
|
lines = count_lines(data);
|
||
|
*cfg = malloc(ctype == CFG_DELAY ? sizeof(struct cfg_delays) +
|
||
|
lines * sizeof(struct cfg_delay)
|
||
|
: sizeof(struct cfg_failures) +
|
||
|
lines * sizeof(struct cfg_delay));
|
||
|
|
||
|
if (ctype == CFG_DELAY) {
|
||
|
delays = *cfg;
|
||
|
delays->size = lines;
|
||
|
rs = "([0-9]+);([0-9]+);([0-9]+);(-?[0-9]+)";
|
||
|
n_cfg = 5;
|
||
|
f = smash_populate_delay;
|
||
|
} else {
|
||
|
failures = *cfg;
|
||
|
failures->size = lines;
|
||
|
rs = "([0-9]+);([0-9]+)";
|
||
|
n_cfg = 3;
|
||
|
f = smash_populate_failure;
|
||
|
}
|
||
|
|
||
|
if ((ret = regcomp(&r, rs, REG_EXTENDED)) != 0) {
|
||
|
regerror(ret, &r, err_buf, 100);
|
||
|
fprintf(stderr, "failed to compile regex <%s>:%s\n", rs,
|
||
|
err_buf);
|
||
|
goto err;
|
||
|
}
|
||
|
|
||
|
nline = 0;
|
||
|
line = strtok(data, "\n");
|
||
|
while (line) {
|
||
|
/* if line is a comment or snaphot, do smth */
|
||
|
if ((ret = regexec(&r, line, n_cfg, rm, 0)) != 0) {
|
||
|
regerror(ret, &r, err_buf, 100);
|
||
|
fprintf(stderr, "line %ld: %s\n", nline + 1, err_buf);
|
||
|
goto err;
|
||
|
}
|
||
|
f(line, nline, rm, *cfg);
|
||
|
nline++;
|
||
|
line = strtok(NULL, "\n");
|
||
|
}
|
||
|
|
||
|
regfree(&r);
|
||
|
munmap(data, data_size);
|
||
|
return 0;
|
||
|
err:
|
||
|
regfree(&r);
|
||
|
munmap(data, data_size);
|
||
|
return -1;
|
||
|
}
|