v2: Rel -> Relative Freq -> Frequency passes NULL instead of FILE to config_parse --- src/bootchart/bootchart.c | 82 +++++++++++++++++--------------------------- src/bootchart/bootchart.conf | 22 ++++++------ src/shared/conf-parser.c | 27 +++++++++++++++ src/shared/conf-parser.h | 1 + src/shared/util.c | 17 +++++++++ src/shared/util.h | 2 ++ 6 files changed, 89 insertions(+), 62 deletions(-)
diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c index fb95c6b..c4a008f 100644 --- a/src/bootchart/bootchart.c +++ b/src/bootchart/bootchart.c @@ -36,6 +36,9 @@ #include "bootchart.h" #include "util.h" +#include "macro.h" +#include "conf-parser.h" +#include "strxcpyx.h" double graph_start; double log_start; @@ -54,7 +57,7 @@ static int exiting = 0; /* graph defaults */ int entropy = 0; int initcall = 1; -int relative; +int relative = 0; int filter = 1; int pss = 0; int samples; @@ -83,61 +86,38 @@ int main(int argc, char *argv[]) char output_file[PATH_MAX]; char datestr[200]; time_t t = 0; - FILE *f; + const char *fn; int gind; - int i; + int i, r; + char *init = NULL, *output = NULL; + + const ConfigTableItem items[] = { + { "Bootchart", "Samples", config_parse_int, 0, &len }, + { "Bootchart", "Frequency", config_parse_double, 0, &hz }, + { "Bootchart", "Relative", config_parse_int, 0, &relative }, + { "Bootchart", "Filter", config_parse_int, 0, &filter }, + { "Bootchart", "Output", config_parse_path, 0, &output }, + { "Bootchart", "Init", config_parse_path, 0, &init }, + { "Bootchart", "Pss", config_parse_int, 0, &pss }, + { "Bootchart", "Entropy", config_parse_int, 0, &entropy }, + { "Bootchart", "ScaleX", config_parse_double, 0, &scale_x }, + { "Bootchart", "ScaleY", config_parse_double, 0, &scale_y }, + { NULL, NULL, NULL, 0, NULL } + }; rlim.rlim_cur = 4096; rlim.rlim_max = 4096; (void) setrlimit(RLIMIT_NOFILE, &rlim); - f = fopen("/etc/systemd/bootchart.conf", "r"); - if (f) { - char buf[256]; - char *key; - char *val; - - while (fgets(buf, 80, f) != NULL) { - char *c; - - c = strchr(buf, '\n'); - if (c) *c = 0; /* remove trailing \n */ - - if (buf[0] == '#') - continue; /* comment line */ - - key = strtok(buf, "="); - if (!key) - continue; - val = strtok(NULL, "="); - if (!val) - continue; - - // todo: filter leading/trailing whitespace - - if (streq(key, "samples")) - len = atoi(val); - if (streq(key, "freq")) - hz = atof(val); - if (streq(key, "rel")) - relative = atoi(val); - if (streq(key, "filter")) - filter = atoi(val); - if (streq(key, "pss")) - pss = atoi(val); - if (streq(key, "output")) - strncpy(output_path, val, PATH_MAX - 1); - if (streq(key, "init")) - strncpy(init_path, val, PATH_MAX - 1); - if (streq(key, "scale_x")) - scale_x = atof(val); - if (streq(key, "scale_y")) - scale_y = atof(val); - if (streq(key, "entropy")) - entropy = atoi(val); - } - fclose(f); - } + fn = "/etc/systemd/bootchart.conf"; + r = config_parse(fn, NULL, NULL, config_item_table_lookup, (void*) items, true, NULL); + if (r < 0) + log_warning("Failed to parse configuration file: %s", strerror(-r)); + + if (init != NULL) + strscpy(init_path, sizeof(init_path), init); + if (output != NULL) + strscpy(output_path, sizeof(output_path), output); while (1) { static struct option opts[] = { @@ -235,7 +215,7 @@ int main(int argc, char *argv[]) execl(init_path, init_path, NULL); } } - argv[0][0] = '@'; + argv[0][0] = '@'; /* start with empty ps LL */ ps_first = calloc(1, sizeof(struct ps_struct)); diff --git a/src/bootchart/bootchart.conf b/src/bootchart/bootchart.conf index fa1a09b..42810aa 100644 --- a/src/bootchart/bootchart.conf +++ b/src/bootchart/bootchart.conf @@ -1,4 +1,3 @@ - # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it @@ -8,13 +7,14 @@ # # See bootchart.conf(5) for details -#samples=500 -#freq=25 -#rel=0 -#filter=1 -#output=<folder name, defaults to /var/log> -#init=/path/to/init-binary -#pss=0 -#entropy=0 -#scale_x=100 -#scale_y=20 +[Bootchart] +#Samples=500 +#Frequency=25 +#Relative=0 +#Filter=1 +#Output=<folder name, defaults to /run/log> +#Init=/path/to/init-binary +#Pss=0 +#Entropy=0 +#ScaleX=100 +#ScaleY=20 diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index c5dd26d..b09e90a 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -467,6 +467,33 @@ int config_parse_unsigned( return 0; } +int config_parse_double( + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + double *d = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = safe_atod(rvalue, d); + if (r < 0) { + log_error("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue); + return r; + } + + return 0; +} + int config_parse_bytes_size( const char *filename, unsigned line, diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h index 56ffc2f..9096c60 100644 --- a/src/shared/conf-parser.h +++ b/src/shared/conf-parser.h @@ -92,6 +92,7 @@ int config_parse_int(const char *filename, unsigned line, const char *section, c int config_parse_unsigned(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_long(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_uint64(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_double(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bytes_size(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bytes_off(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bool(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); diff --git a/src/shared/util.c b/src/shared/util.c index 4f0b652..58029aa 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -352,6 +352,23 @@ int safe_atolli(const char *s, long long int *ret_lli) { return 0; } +int safe_atod(const char *s, double *ret_d) { + char *x = NULL; + double d; + + assert(s); + assert(ret_d); + + errno = 0; + d = strtod(s, &x); + + if (!x || x == s || *x || errno) + return errno ? -errno : -EINVAL; + + *ret_d = (double) d; + return 0; +} + /* Split a string into words. */ char *split(const char *c, size_t *l, const char *separator, char **state) { char *current; diff --git a/src/shared/util.h b/src/shared/util.h index fcb0d9a..99990db 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -122,6 +122,8 @@ int safe_atoi(const char *s, int *ret_i); int safe_atollu(const char *s, unsigned long long *ret_u); int safe_atolli(const char *s, long long int *ret_i); +int safe_atod(const char *s, double *ret_d); + #if __WORDSIZE == 32 static inline int safe_atolu(const char *s, unsigned long *ret_u) { assert_cc(sizeof(unsigned long) == sizeof(unsigned)); -- 1.8.1.2 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel