|
version 1.1.1.1, 2012/02/21 22:19:56
|
version 1.1.1.2, 2014/07/30 07:55:27
|
|
Line 1
|
Line 1
|
| /* |
/* |
| * conf.c Config Crap |
* conf.c Config Crap |
| * |
* |
| * Copyright (c) 2001-2005 Thomas Graf <tgraf@suug.ch> | * Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch> |
| | * Copyright (c) 2013 Red Hat, Inc. |
| * |
* |
| * Permission is hereby granted, free of charge, to any person obtaining a |
* Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
* copy of this software and associated documentation files (the "Software"), |
|
Line 24
|
Line 25
|
| |
|
| #include <bmon/bmon.h> |
#include <bmon/bmon.h> |
| #include <bmon/conf.h> |
#include <bmon/conf.h> |
| #include <bmon/bindings.h> | #include <bmon/unit.h> |
| #include <bmon/input.h> | #include <bmon/attr.h> |
| #include <bmon/output.h> | #include <bmon/element.h> |
| | #include <bmon/element_cfg.h> |
| | #include <bmon/history.h> |
| #include <bmon/utils.h> |
#include <bmon/utils.h> |
| |
|
| static int show_only_running = 1; | cfg_t *cfg; |
| static int do_signal_output = 0; | |
| static char fg_char = '*'; | |
| static char bg_char = '.'; | |
| static char noise_char = ':'; | |
| static char unk_char = '?'; | |
| static y_unit_t y_unit = Y_DYNAMIC; | |
| static x_unit_t x_unit = X_SEC; | |
| static char * configfile = NULL; | |
| static float read_interval = 1.0f; | |
| static unsigned long sleep_time = 20000; | |
| static int use_si = 0; | |
| static int ngraphs = 1; | |
| static float hb_factor = 0.1; | |
| static float rate_interval = 1.0f; | |
| static float lifetime = 30.0f; | |
| static char * itemtabfile = "/etc/bmon/itemtab"; | |
| |
|
| |
static cfg_opt_t element_opts[] = { |
| |
CFG_STR("description", NULL, CFGF_NONE), |
| |
CFG_BOOL("show", cfg_true, CFGF_NONE), |
| |
CFG_INT("rxmax", 0, CFGF_NONE), |
| |
CFG_INT("txmax", 0, CFGF_NONE), |
| |
CFG_INT("max", 0, CFGF_NONE), |
| |
CFG_END() |
| |
}; |
| |
|
| |
static cfg_opt_t history_opts[] = { |
| |
CFG_FLOAT("interval", 1.0f, CFGF_NONE), |
| |
CFG_INT("size", 60, CFGF_NONE), |
| |
CFG_STR("type", "64bit", CFGF_NONE), |
| |
CFG_END() |
| |
}; |
| |
|
| |
static cfg_opt_t attr_opts[] = { |
| |
CFG_STR("description", "", CFGF_NONE), |
| |
CFG_STR("unit", "", CFGF_NONE), |
| |
CFG_STR("type", "counter", CFGF_NONE), |
| |
CFG_BOOL("history", cfg_false, CFGF_NONE), |
| |
CFG_END() |
| |
}; |
| |
|
| |
static cfg_opt_t variant_opts[] = { |
| |
CFG_FLOAT_LIST("div", "{}", CFGF_NONE), |
| |
CFG_STR_LIST("txt", "", CFGF_NONE), |
| |
CFG_END() |
| |
}; |
| |
|
| |
static cfg_opt_t unit_opts[] = { |
| |
CFG_SEC("variant", variant_opts, CFGF_MULTI | CFGF_TITLE), |
| |
CFG_END() |
| |
}; |
| |
|
| |
static cfg_opt_t global_opts[] = { |
| |
CFG_FLOAT("read_interval", 1.0f, CFGF_NONE), |
| |
CFG_FLOAT("rate_interval", 1.0f, CFGF_NONE), |
| |
CFG_FLOAT("lifetime", 30.0f, CFGF_NONE), |
| |
CFG_FLOAT("history_variance", 0.1f, CFGF_NONE), |
| |
CFG_FLOAT("variance", 0.1f, CFGF_NONE), |
| |
CFG_BOOL("show_all", cfg_false, CFGF_NONE), |
| |
CFG_INT("unit_exp", -1, CFGF_NONE), |
| |
CFG_INT("sleep_time", 20000UL, CFGF_NONE), |
| |
CFG_BOOL("use_si", 0, CFGF_NONE), |
| |
CFG_BOOL("use_bit", 0, CFGF_NONE), |
| |
CFG_STR("uid", NULL, CFGF_NONE), |
| |
CFG_STR("gid", NULL, CFGF_NONE), |
| |
CFG_STR("policy", "", CFGF_NONE), |
| |
CFG_SEC("unit", unit_opts, CFGF_MULTI | CFGF_TITLE), |
| |
CFG_SEC("attr", attr_opts, CFGF_MULTI | CFGF_TITLE), |
| |
CFG_SEC("history", history_opts, CFGF_MULTI | CFGF_TITLE), |
| |
CFG_SEC("element", element_opts, CFGF_MULTI | CFGF_TITLE), |
| |
CFG_END() |
| |
}; |
| |
|
| |
float cfg_read_interval; |
| |
float cfg_rate_interval; |
| |
float cfg_rate_variance; |
| |
float cfg_history_variance; |
| |
int cfg_show_all; |
| |
int cfg_unit_exp = DYNAMIC_EXP; |
| |
|
| |
static char * configfile = NULL; |
| |
|
| #if defined HAVE_CURSES |
#if defined HAVE_CURSES |
| #if defined HAVE_USE_DEFAULT_COLORS |
#if defined HAVE_USE_DEFAULT_COLORS |
| layout_t layout[] = | struct layout cfg_layout[] = |
| { |
{ |
| {-1, -1, 0}, /* dummy, not used */ |
{-1, -1, 0}, /* dummy, not used */ |
| {-1, -1, 0}, /* default */ |
{-1, -1, 0}, /* default */ |
|
Line 59 layout_t layout[] =
|
Line 111 layout_t layout[] =
|
| {-1, -1, A_REVERSE}, /* selected */ |
{-1, -1, A_REVERSE}, /* selected */ |
| }; |
}; |
| #else |
#else |
| layout_t layout[] = | struct layout cfg_layout[] = |
| { |
{ |
| {0, 0, 0}, /* dummy, not used */ |
{0, 0, 0}, /* dummy, not used */ |
| {COLOR_BLACK, COLOR_WHITE, 0}, /* default */ |
{COLOR_BLACK, COLOR_WHITE, 0}, /* default */ |
|
Line 71 layout_t layout[] =
|
Line 123 layout_t layout[] =
|
| #endif |
#endif |
| #endif |
#endif |
| |
|
| #define SPLIT(str, var) \ |
|
| do { \ |
|
| char *s; \ |
|
| for (s = str; *s; s++) { \ |
|
| if (*s == ' ' || *s == '\t') \ |
|
| break; \ |
|
| } \ |
|
| if (!*s) \ |
|
| break; \ |
|
| *s = '\0'; \ |
|
| for (++s;*s == ' ' || *s == '\t'; s++); \ |
|
| if (!*s) \ |
|
| break; \ |
|
| var = s; \ |
|
| } while(0); |
|
| |
|
| static void conf_read(const char *); |
|
| |
|
| static inline void parse_include(char *buf) |
|
| { |
|
| conf_read(buf); |
|
| } |
|
| |
|
| #if defined HAVE_CURSES |
|
| static int parse_color(const char *color) |
|
| { |
|
| if (!strcmp(color, "default")) |
|
| return -1; |
|
| else if (!strcasecmp(color, "black")) |
|
| return COLOR_BLACK; |
|
| else if (!strcasecmp(color, "red")) |
|
| return COLOR_RED; |
|
| else if (!strcasecmp(color, "green")) |
|
| return COLOR_GREEN; |
|
| else if (!strcasecmp(color, "yellow")) |
|
| return COLOR_YELLOW; |
|
| else if (!strcasecmp(color, "blue")) |
|
| return COLOR_BLUE; |
|
| else if (!strcasecmp(color, "magenta")) |
|
| return COLOR_MAGENTA; |
|
| else if (!strcasecmp(color, "cyan")) |
|
| return COLOR_CYAN; |
|
| else if (!strcasecmp(color, "white")) |
|
| return COLOR_WHITE; |
|
| else |
|
| return -1; |
|
| } |
|
| |
|
| static void parse_layout(char *buf) |
|
| { |
|
| char *id, *fg = NULL, *bg = NULL, *attr, *s; |
|
| layout_t l; |
|
| |
|
| id = buf; |
|
| SPLIT(buf, fg) |
|
| SPLIT(fg, bg) |
|
| |
|
| for (s = bg; *s; s++) { |
|
| if (*s == ' ' || *s == '\t') |
|
| break; |
|
| } |
|
| |
|
| if (*s) { |
|
| *s = '\0'; |
|
| s++; |
|
| |
|
| for (; *s == ' ' || *s == '\t'; s++); |
|
| if (*s) |
|
| attr = s; |
|
| else |
|
| attr = NULL; |
|
| } |
|
| else |
|
| attr = NULL; |
|
| |
|
| if ((l.fg = parse_color(fg)) == -1) |
|
| return; |
|
| |
|
| if ((l.bg = parse_color(bg)) == -1) |
|
| return; |
|
| |
|
| l.attr = 0; |
|
| |
|
| if (attr) |
|
| { |
|
| if (!strcasecmp(attr, "reverse")) |
|
| l.attr |= A_REVERSE; |
|
| else if (!strcasecmp(attr, "bold")) |
|
| l.attr |= A_BOLD; |
|
| else if (!strcasecmp(attr, "underline")) |
|
| l.attr |= A_UNDERLINE; |
|
| } |
|
| |
|
| #define COPY_LAYOUT(id) do { \ |
|
| layout[id].fg = l.fg; \ |
|
| layout[id].bg = l.bg; \ |
|
| layout[id].attr = l.attr; \ |
|
| } while (0); |
|
| |
|
| if (!strcasecmp(id, "default")) |
|
| COPY_LAYOUT(LAYOUT_DEFAULT) |
|
| else if (!strcasecmp(id, "statusbar")) |
|
| COPY_LAYOUT(LAYOUT_STATUSBAR) |
|
| else if (!strcasecmp(id, "header")) |
|
| COPY_LAYOUT(LAYOUT_HEADER) |
|
| else if (!strcasecmp(id, "list")) |
|
| COPY_LAYOUT(LAYOUT_LIST) |
|
| else if (!strcasecmp(id, "selected")) |
|
| COPY_LAYOUT(LAYOUT_SELECTED) |
|
| |
|
| #undef COPY_LAYOUT |
|
| } |
|
| #endif |
|
| |
|
| static void parse_bind(char *buf) |
|
| { |
|
| char *ch, *cmd = NULL, *args, *s; |
|
| binding_t *b; |
|
| int i; |
|
| |
|
| ch = buf; |
|
| SPLIT(buf, cmd); |
|
| args = strdup(cmd); |
|
| |
|
| b = xcalloc(1, sizeof(binding_t)); |
|
| b->args[0] = args; |
|
| |
|
| for (s = args, i = 1; i < 255; i++) { |
|
| s = strchr (s, ' '); |
|
| if (s) { |
|
| *s = '\0'; |
|
| s++; |
|
| b->args[i] = s; |
|
| } else |
|
| break; |
|
| } |
|
| |
|
| b->args[i] = NULL; |
|
| |
|
| b->ch = ch[0]; |
|
| b->cmd = strdup(b->args[0]); |
|
| |
|
| add_binding(b); |
|
| } |
|
| |
|
| void conf_parse_option(const char *id, const char *value) |
|
| { |
|
| #define MATCH(STR) if (!strcasecmp(id, STR)) |
|
| MATCH("input") |
|
| set_input(value); |
|
| else MATCH("secondary_input") |
|
| set_sec_input(value); |
|
| else MATCH("output") |
|
| set_output(value); |
|
| else MATCH("secondary_output") |
|
| set_sec_output(value); |
|
| else MATCH("policy") |
|
| item_parse_policy(value); |
|
| else MATCH("read_interval") |
|
| set_read_interval(value); |
|
| else MATCH("sleep_time") |
|
| set_sleep_time(value); |
|
| else MATCH("show_all") |
|
| set_show_only_running(0); |
|
| else MATCH("use_si") |
|
| set_use_si(); |
|
| else MATCH("nr_graphs") |
|
| set_ngraphs(strtol(value, NULL, 0)); |
|
| else MATCH("heartbeat_factor") |
|
| set_hb_factor(value); |
|
| else MATCH("rate_interval") |
|
| set_rate_interval(value); |
|
| else MATCH("lifetime") |
|
| set_lifetime(value); |
|
| else MATCH("itemtab") |
|
| set_itemtab(value); |
|
| #undef MATCH |
|
| } |
|
| |
|
| tv_t * parse_tv(char *data) |
tv_t * parse_tv(char *data) |
| { |
{ |
| char *value; |
char *value; |
| tv_t *tv = xcalloc(1, sizeof(tv_t)); |
tv_t *tv = xcalloc(1, sizeof(tv_t)); |
| |
|
| |
init_list_head(&tv->tv_list); |
| |
|
| value = strchr(data, '='); |
value = strchr(data, '='); |
| |
|
| if (value) { |
if (value) { |
| *value = '\0'; |
*value = '\0'; |
| ++value; |
++value; |
| tv->value = strdup(value); | tv->tv_value = strdup(value); |
| } |
} |
| |
|
| tv->type = strdup(data); | tv->tv_type = strdup(data); |
| return tv; |
return tv; |
| } |
} |
| |
|
|
Line 277 module_conf_t * parse_module(char *data)
|
Line 152 module_conf_t * parse_module(char *data)
|
| |
|
| m = xcalloc(1, sizeof(module_conf_t)); |
m = xcalloc(1, sizeof(module_conf_t)); |
| |
|
| |
init_list_head(&m->m_attrs); |
| |
|
| opts = strchr(data, ':'); |
opts = strchr(data, ':'); |
| |
|
| if (opts) { |
if (opts) { |
|
Line 293 module_conf_t * parse_module(char *data)
|
Line 170 module_conf_t * parse_module(char *data)
|
| } |
} |
| |
|
| tv = parse_tv(opts); |
tv = parse_tv(opts); |
| |
list_add_tail(&tv->tv_list, &m->m_attrs); |
| |
|
| tv->next = m->attrs; |
|
| m->attrs = tv; |
|
| |
|
| opts = next; |
opts = next; |
| } while(next); |
} while(next); |
| } |
} |
| |
|
| m->name = strdup(name); | m->m_name = strdup(name); |
| return m; |
return m; |
| } |
} |
| |
|
| |
|
| module_conf_t * parse_module_param(const char *data) | int parse_module_param(const char *data, struct list_head *list) |
| { |
{ |
| char *buf = strdup(data); |
char *buf = strdup(data); |
| char *next; |
char *next; |
| char *current = buf; |
char *current = buf; |
| module_conf_t *m, *list = NULL; | module_conf_t *m; |
| | int n = 0; |
| |
|
| do { |
do { |
| next = strchr(current, ','); |
next = strchr(current, ','); |
|
Line 322 module_conf_t * parse_module_param(const char *data)
|
Line 198 module_conf_t * parse_module_param(const char *data)
|
| } |
} |
| |
|
| m = parse_module(current); |
m = parse_module(current); |
| |
|
| if (m) { |
if (m) { |
| m->next = list; | list_add_tail(&m->m_list, list); |
| list = m; | n++; |
| } |
} |
| |
|
| current = next; |
current = next; |
|
Line 333 module_conf_t * parse_module_param(const char *data)
|
Line 208 module_conf_t * parse_module_param(const char *data)
|
| |
|
| free(buf); |
free(buf); |
| |
|
| return list; | return n; |
| } |
} |
| |
|
| static void configfile_read_history(void) |
| static inline void parse_config_line(char *buf) | |
| { |
{ |
| char *tok = NULL; | int i, nhistory; |
| | |
| SPLIT(buf, tok); | |
| if (!strcasecmp(buf, "include")) | |
| parse_include(tok); | |
| #if defined HAVE_CURSES | |
| else if (!strcasecmp(buf, "layout")) | |
| parse_layout(tok); | |
| #endif | |
| else if (!strcasecmp(buf, "bind")) | |
| parse_bind(tok); | |
| else | |
| conf_parse_option(buf, tok); | |
| } | |
| |
|
| static void conf_read(const char *path) | nhistory = cfg_size(cfg, "history"); |
| { | |
| FILE *f; | |
| char buf[1024]; | |
| |
|
| if (!(f = fopen(path, "r"))) | for (i = 0; i < nhistory; i++) { |
| return; | struct history_def *def; |
| | cfg_t *history; |
| | const char *name, *type; |
| | float interval; |
| | int size; |
| |
|
| memset(buf, 0, sizeof(buf)); | if (!(history = cfg_getnsec(cfg, "history", i))) |
| | BUG(); |
| |
|
| while (fgets(buf, sizeof(buf), f)) { | if (!(name = cfg_title(history))) |
| char *p; | BUG(); |
| |
|
| if ('#' == *buf) | interval = cfg_getfloat(history, "interval"); |
| goto skip; | size = cfg_getint(history, "size"); |
| | type = cfg_getstr(history, "type"); |
| |
|
| if ((p = strchr(buf, '\r'))) | if (interval == 0.0f) |
| *p = '\0'; | interval = cfg_getfloat(cfg, "read_interval"); |
| |
|
| if ((p = strchr(buf, '\n'))) | def = history_def_alloc(name); |
| *p = '\0'; | def->hd_interval = interval; |
| | def->hd_size = size; |
| |
|
| if (*buf) | if (!strcasecmp(type, "8bit")) |
| parse_config_line(buf); | def->hd_type = HISTORY_TYPE_8; |
| else if (!strcasecmp(type, "16bit")) |
| skip: | def->hd_type = HISTORY_TYPE_16; |
| memset(buf, 0, sizeof(buf)); | else if (!strcasecmp(type, "32bit")) |
| | def->hd_type = HISTORY_TYPE_32; |
| | else if (!strcasecmp(type, "64bit")) |
| | def->hd_type = HISTORY_TYPE_64; |
| | else |
| | quit("Invalid type \'%s\', must be \"(8|16|32|64)bit\"" |
| | " in history definition #%d\n", type, i+1); |
| } |
} |
| |
|
| fclose(f); |
|
| } |
} |
| |
|
| void read_configfile(void) | static void configfile_read_element_cfg(void) |
| { |
{ |
| if (configfile) | int i, nelement; |
| conf_read(configfile); | |
| else { | |
| conf_read("/etc/bmon.conf"); | |
| | |
| if (getenv("HOME")) { | |
| char path[FILENAME_MAX+1]; | |
| snprintf(path, sizeof(path), "%s/.bmonrc", getenv("HOME")); | |
| conf_read(path); | |
| } | |
| } | |
| } | |
| |
|
| |
nelement = cfg_size(cfg, "element"); |
| |
|
| inline void set_configfile(const char *file) | for (i = 0; i < nelement; i++) { |
| { | struct element_cfg *ec; |
| static int set = 0; | cfg_t *element; |
| if (!set) { | const char *name, *description; |
| configfile = strdup(file); | long max; |
| set = 1; | |
| } | |
| } | |
| |
|
| inline void set_itemtab(const char *file) | if (!(element = cfg_getnsec(cfg, "element", i))) |
| { | BUG(); |
| static int set = 0; | |
| if (!set) { | |
| itemtabfile = strdup(file); | |
| set = 1; | |
| } | |
| } | |
| |
|
| inline char *get_itemtab(void) | if (!(name = cfg_title(element))) |
| { | BUG(); |
| return itemtabfile; | |
| } | |
| |
|
| inline void set_read_interval(const char *i) | ec = element_cfg_alloc(name); |
| { | |
| static int set = 0; | |
| if (!set) { | |
| read_interval = (float) strtod(i, NULL); | |
| set = 1; | |
| } | |
| } | |
| |
|
| inline float get_read_interval(void) | if ((description = cfg_getstr(element, "description"))) |
| { | ec->ec_description = strdup(description); |
| return read_interval; | |
| } | |
| |
|
| inline void get_read_interval_as_ts(timestamp_t *ts) | if ((max = cfg_getint(element, "max"))) |
| { | ec->ec_rxmax = ec->ec_txmax = max; |
| float_to_ts(ts, read_interval); | |
| } | |
| |
|
| |
if ((max = cfg_getint(element, "rxmax"))) |
| |
ec->ec_rxmax = max; |
| |
|
| inline void set_x_unit(const char *x, int force) | if ((max = cfg_getint(element, "txmax"))) |
| { | ec->ec_txmax = max; |
| static int set = 0; | |
| if (!set || force) { | if (cfg_getbool(element, "show")) |
| if (tolower(*x) == 's') | ec->ec_flags |= ELEMENT_CFG_SHOW; |
| x_unit = X_SEC; | |
| else if (tolower(*x) == 'm') | |
| x_unit = X_MIN; | |
| else if (tolower(*x) == 'h') | |
| x_unit = X_HOUR; | |
| else if (tolower(*x) == 'd') | |
| x_unit = X_DAY; | |
| else if (tolower(*x) == 'r') | |
| x_unit = X_READ; | |
| else |
else |
| quit("Unknown X-axis unit '%s'\n", x); | ec->ec_flags |= ELEMENT_CFG_HIDE; |
| set = 1; | |
| } |
} |
| } |
} |
| |
|
| inline x_unit_t get_x_unit(void) | static void add_div(struct unit *unit, int type, cfg_t *variant) |
| { |
{ |
| return x_unit; | int ndiv, n, ntxt; |
| } | |
| |
|
| inline void set_y_unit(const char *y) | if (!(ndiv = cfg_size(variant, "div"))) |
| { | return; |
| static int set = 0; | |
| if (!set) { | |
| if (tolower(*y) == 'b') | |
| y_unit = Y_BYTE; | |
| else if (tolower(*y) == 'k') | |
| y_unit = Y_KILO; | |
| else if (tolower(*y) == 'm') | |
| y_unit = Y_MEGA; | |
| else if (tolower(*y) == 'g') | |
| y_unit = Y_GIGA; | |
| else if (tolower(*y) == 't') | |
| y_unit = Y_TERA; | |
| else | |
| quit("Unknown Y-axis unit '%s'\n", y); | |
| set = 1; | |
| } | |
| } | |
| |
|
| inline y_unit_t get_y_unit(void) | ntxt = cfg_size(variant, "txt"); |
| { | if (ntxt != ndiv) |
| return y_unit; | quit("Number of elements for div and txt not equal\n"); |
| } | |
| |
|
| |
if (!list_empty(&unit->u_div[type])) { |
| |
struct fraction *f, *n; |
| |
|
| inline char get_fg_char(void) | list_for_each_entry_safe(f, n, &unit->u_div[type], f_list) |
| { | fraction_free(f); |
| return fg_char; | } |
| } | |
| |
|
| inline void set_fg_char(char c) | for (n = 0; n < ndiv; n++) { |
| { | char *txt; |
| static int set = 0; | float div; |
| if (!set) { | |
| fg_char = c; | div = cfg_getnfloat(variant, "div", n); |
| set = 1; | txt = cfg_getnstr(variant, "txt", n); |
| | |
| | unit_add_div(unit, type, txt, div); |
| } |
} |
| } |
} |
| |
|
| inline char get_unk_char(void) | static void configfile_read_units(void) |
| { |
{ |
| return unk_char; | int i, nunits; |
| } | struct unit *u; |
| |
|
| inline void set_unk_char(char c) | nunits = cfg_size(cfg, "unit"); |
| { | |
| static int set = 0; | for (i = 0; i < nunits; i++) { |
| if (!set) { | int nvariants, n; |
| unk_char = c; | cfg_t *unit; |
| set = 1; | const char *name; |
| | |
| | if (!(unit = cfg_getnsec(cfg, "unit", i))) |
| | BUG(); |
| | |
| | if (!(name = cfg_title(unit))) |
| | BUG(); |
| | |
| | if (!(nvariants = cfg_size(unit, "variant"))) |
| | continue; |
| | |
| | if (!(u = unit_add(name))) |
| | continue; |
| | |
| | for (n = 0; n < nvariants; n++) { |
| | cfg_t *variant; |
| | const char *vtitle; |
| | |
| | if (!(variant = cfg_getnsec(unit, "variant", n))) |
| | BUG(); |
| | |
| | if (!(vtitle = cfg_title(variant))) |
| | BUG(); |
| | |
| | if (!strcasecmp(vtitle, "default")) |
| | add_div(u, UNIT_DEFAULT, variant); |
| | else if (!strcasecmp(vtitle, "si")) |
| | add_div(u, UNIT_SI, variant); |
| | else if (!strcasecmp(vtitle, "bit")) |
| | add_div(u, UNIT_BIT, variant); |
| | else |
| | quit("Unknown unit variant \'%s\'\n", vtitle); |
| | } |
| } |
} |
| } |
} |
| |
|
| inline char get_bg_char(void) | static void configfile_read_attrs(void) |
| { |
{ |
| return bg_char; | int i, nattrs, t; |
| } | |
| |
|
| inline void set_bg_char(char c) | nattrs = cfg_size(cfg, "attr"); |
| { | |
| static int set = 0; | for (i = 0; i < nattrs; i++) { |
| if (!set) { | struct unit *u; |
| bg_char = c; | cfg_t *attr; |
| set = 1; | const char *name, *description, *unit, *type; |
| | int flags = 0; |
| | |
| | if (!(attr = cfg_getnsec(cfg, "attr", i))) |
| | BUG(); |
| | |
| | if (!(name = cfg_title(attr))) |
| | BUG(); |
| | |
| | description = cfg_getstr(attr, "description"); |
| | unit = cfg_getstr(attr, "unit"); |
| | type = cfg_getstr(attr, "type"); |
| | |
| | if (!unit) |
| | quit("Attribute '%s' is missing unit specification\n", |
| | name); |
| | |
| | if (!type) |
| | quit("Attribute '%s' is missing type specification\n", |
| | name); |
| | |
| | if (!(u = unit_lookup(unit))) |
| | quit("Unknown unit \'%s\' attribute '%s'\n", |
| | unit, name); |
| | |
| | if (!strcasecmp(type, "counter")) |
| | t = ATTR_TYPE_COUNTER; |
| | else if (!strcasecmp(type, "rate")) |
| | t = ATTR_TYPE_RATE; |
| | else if (!strcasecmp(type, "percent")) |
| | t = ATTR_TYPE_PERCENT; |
| | else |
| | quit("Unknown type \'%s\' in attribute '%s'\n", |
| | type, name); |
| | |
| | if (cfg_getbool(attr, "history")) |
| | flags |= ATTR_FORCE_HISTORY; |
| | |
| | if (cfg_getbool(attr, "ignore_overflows")) |
| | flags |= ATTR_IGNORE_OVERFLOWS; |
| | |
| | attr_def_add(name, description, u, t, flags); |
| } |
} |
| } |
} |
| |
|
| inline char get_noise_char(void) | static void conf_read(const char *path, int must) |
| { |
{ |
| return noise_char; | int err; |
| } | |
| |
|
| inline void set_noise_char(char c) | DBG("Reading configfile %s...", path); |
| { | |
| static int set = 0; | if (access(path, R_OK) != 0) { |
| if (!set) { | if (must) |
| noise_char = c; | quit("Error: Unable to read configfile \"%s\": %s\n", |
| set = 1; | path, strerror(errno)); |
| | else |
| | return; |
| } |
} |
| } |
|
| |
|
| inline void set_sleep_time(const char *s) | err = cfg_parse(cfg, path); |
| { | if (err == CFG_FILE_ERROR) { |
| static int set = 0; | quit("Error while reading configfile \"%s\": %s\n", |
| if (!set) { | path, strerror(errno)); |
| double d = strtod(s, NULL); | } else if (err == CFG_PARSE_ERROR) { |
| sleep_time = (unsigned long) (d * 1000000.0f); | quit("Error while reading configfile \"%s\": parse error\n", |
| set = 1; | path); |
| } |
} |
| } |
|
| |
|
| inline unsigned long get_sleep_time(void) | configfile_read_units(); |
| { | configfile_read_history(); |
| return sleep_time; | configfile_read_attrs(); |
| | configfile_read_element_cfg(); |
| } |
} |
| |
|
| inline void set_signal_output(int i) | static const char default_config[] = \ |
| { | "unit byte {" \ |
| static int set = 0; | " variant default {" \ |
| if (!set) { | " div = { 1, 1024, 1048576, 1073741824, 1099511627776}" \ |
| do_signal_output = i; | " txt = { \"B\", \"KiB\", \"MiB\", \"GiB\", \"TiB\" }" \ |
| set = 1; | " }" \ |
| } | " variant si {" \ |
| } | " div = { 1, 1000, 1000000, 1000000000, 1000000000000 }" \ |
| | " txt = { \"B\", \"KB\", \"MB\", \"GB\", \"TB\" }" \ |
| | " }" \ |
| | " variant bit {" \ |
| | " div = { 0.125, 125, 125000, 125000000, 125000000000 }" \ |
| | " txt = { \"b\", \"Kb\", \"Mb\", \"Gb\", \"Tb\" }" \ |
| | " }" \ |
| | " }" \ |
| | "unit bit {" \ |
| | " variant default {" \ |
| | " div = { 1, 1000, 1000000, 1000000000, 1000000000000 }" \ |
| | " txt = { \"b\", \"Kb\", \"Mb\", \"Gb\", \"Tb\" }" \ |
| | " }" \ |
| | " variant si {" \ |
| | " div = { 1, 1000, 1000000, 1000000000, 1000000000000 }" \ |
| | " txt = { \"b\", \"Kb\", \"Mb\", \"Gb\", \"Tb\" }" \ |
| | " }" \ |
| | " variant bit {" \ |
| | " div = { 1, 1000, 1000000, 1000000000, 1000000000000 }" \ |
| | " txt = { \"b\", \"Kb\", \"Mb\", \"Gb\", \"Tb\" }" \ |
| | " }" \ |
| | "}" \ |
| | "unit number {" \ |
| | " variant default {" \ |
| | " div = { 1, 1000, 1000000, 1000000000, 1000000000000 }" \ |
| | " txt = { \"\", \"K\", \"M\", \"G\", \"T\" }" \ |
| | " }" \ |
| | "}" \ |
| | "unit percent {" \ |
| | " variant default {" \ |
| | " div = { 1. }" \ |
| | " txt = { \"%\" }" \ |
| | " }" \ |
| | "}" \ |
| | "history second {" \ |
| | " interval = 1.0" \ |
| | " size = 60" \ |
| | "}" \ |
| | "history minute {" \ |
| | " interval = 60.0" \ |
| | " size = 60" \ |
| | "}" \ |
| | "history hour {" \ |
| | " interval = 3600.0" \ |
| | " size = 60" \ |
| | "}" \ |
| | "history day {" \ |
| | " interval = 86400.0" \ |
| | " size = 60" \ |
| | "}"; |
| |
|
| inline int get_signal_output(void) | static void conf_read_default(void) |
| { |
{ |
| return do_signal_output; | int err; |
| } | |
| |
|
| inline void set_show_only_running(int i) | DBG("Reading default config"); |
| { | |
| static int set = 0; | |
| if (!set) { | |
| show_only_running = i; | |
| set = 1; | |
| } | |
| } | |
| |
|
| inline int get_show_only_running(void) | err = cfg_parse_buf(cfg, default_config); |
| { | if (err) |
| return show_only_running; | quit("Error while parsing default config\n"); |
| } | |
| |
|
| inline void set_use_si(void) | configfile_read_units(); |
| { | configfile_read_history(); |
| use_si = 1; | configfile_read_attrs(); |
| | configfile_read_element_cfg(); |
| } |
} |
| |
|
| inline int get_use_si(void) | void configfile_read(void) |
| { |
{ |
| return use_si; | if (configfile) |
| } | conf_read(configfile, 1); |
| else { |
| inline void set_ngraphs(int n) | conf_read(SYSCONFDIR "/bmon.conf", 0); |
| { | |
| static int set = 0; | if (getenv("HOME")) { |
| if (!set) { | char path[FILENAME_MAX+1]; |
| ngraphs = n; | snprintf(path, sizeof(path), "%s/.bmonrc", |
| set = 1; | getenv("HOME")); |
| | conf_read(path, 0); |
| | } |
| } |
} |
| } |
} |
| |
|
| inline int get_ngraphs(void) | void conf_init_pre(void) |
| { |
{ |
| return ngraphs; | conf_read_default(); |
| } |
} |
| |
|
| inline float get_hb_factor(void) | void conf_init_post(void) |
| { |
{ |
| return hb_factor; | cfg_read_interval = cfg_getfloat(cfg, "read_interval"); |
| | cfg_rate_interval = cfg_getfloat(cfg, "rate_interval"); |
| | cfg_rate_variance = cfg_getfloat(cfg, "variance") * cfg_rate_interval; |
| | cfg_history_variance = cfg_getfloat(cfg, "history_variance"); |
| | cfg_show_all = cfg_getbool(cfg, "show_all"); |
| | cfg_unit_exp = cfg_getint(cfg, "unit_exp"); |
| | |
| | element_parse_policy(cfg_getstr(cfg, "policy")); |
| } |
} |
| |
|
| inline void set_hb_factor(const char *s) | void set_configfile(const char *file) |
| { |
{ |
| static int set = 0; |
static int set = 0; |
| if (!set) { |
if (!set) { |
| hb_factor = strtod(s, NULL); | configfile = strdup(file); |
| set = 1; |
set = 1; |
| } |
} |
| } |
} |
| |
|
| inline void set_rate_interval(const char *i) | void set_unit_exp(const char *name) |
| { |
{ |
| static int set = 0; | if (tolower(*name) == 'b') |
| if (!set) { | cfg_setint(cfg, "unit_exp", 0); |
| rate_interval = (float) strtod(i, NULL); | else if (tolower(*name) == 'k') |
| set = 1; | cfg_setint(cfg, "unit_exp", 1); |
| } | else if (tolower(*name) == 'm') |
| | cfg_setint(cfg, "unit_exp", 2); |
| | else if (tolower(*name) == 'g') |
| | cfg_setint(cfg, "unit_exp", 3); |
| | else if (tolower(*name) == 't') |
| | cfg_setint(cfg, "unit_exp", 4); |
| | else if (tolower(*name) == 'd') |
| | cfg_setint(cfg, "unit_exp", DYNAMIC_EXP); |
| | else |
| | quit("Unknown unit exponent '%s'\n", name); |
| } |
} |
| |
|
| inline float get_rate_interval(void) | unsigned int get_lifecycles(void) |
| { |
{ |
| return rate_interval; | return (unsigned int) |
| | (cfg_getfloat(cfg, "lifetime") / cfg_getfloat(cfg, "read_interval")); |
| } |
} |
| |
|
| inline void set_lifetime(const char *i) | static void __exit conf_shutdown(void) |
| { |
{ |
| static int set = 0; | cfg_free(cfg); |
| if (!set) { | |
| lifetime = (float) strtod(i, NULL); | |
| set = 1; | |
| } | |
| } |
} |
| |
|
| inline float get_lifetime(void) | static void __init __conf_init(void) |
| { |
{ |
| return lifetime / read_interval; | DBG("init"); |
| | |
| | cfg = cfg_init(global_opts, CFGF_NOCASE); |
| | |
| | /* FIXME: Add validation functions */ |
| | //cfg_set_validate_func(cfg, "bookmark", &cb_validate_bookmark); |
| } |
} |