Annotation of embedaddon/bmon/src/conf.c, revision 1.1.1.2
1.1 misho 1: /*
2: * conf.c Config Crap
3: *
1.1.1.2 ! misho 4: * Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch>
! 5: * Copyright (c) 2013 Red Hat, Inc.
1.1 misho 6: *
7: * Permission is hereby granted, free of charge, to any person obtaining a
8: * copy of this software and associated documentation files (the "Software"),
9: * to deal in the Software without restriction, including without limitation
10: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11: * and/or sell copies of the Software, and to permit persons to whom the
12: * Software is furnished to do so, subject to the following conditions:
13: *
14: * The above copyright notice and this permission notice shall be included
15: * in all copies or substantial portions of the Software.
16: *
17: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23: * DEALINGS IN THE SOFTWARE.
24: */
25:
26: #include <bmon/bmon.h>
27: #include <bmon/conf.h>
1.1.1.2 ! misho 28: #include <bmon/unit.h>
! 29: #include <bmon/attr.h>
! 30: #include <bmon/element.h>
! 31: #include <bmon/element_cfg.h>
! 32: #include <bmon/history.h>
1.1 misho 33: #include <bmon/utils.h>
34:
1.1.1.2 ! misho 35: cfg_t *cfg;
! 36:
! 37: static cfg_opt_t element_opts[] = {
! 38: CFG_STR("description", NULL, CFGF_NONE),
! 39: CFG_BOOL("show", cfg_true, CFGF_NONE),
! 40: CFG_INT("rxmax", 0, CFGF_NONE),
! 41: CFG_INT("txmax", 0, CFGF_NONE),
! 42: CFG_INT("max", 0, CFGF_NONE),
! 43: CFG_END()
! 44: };
! 45:
! 46: static cfg_opt_t history_opts[] = {
! 47: CFG_FLOAT("interval", 1.0f, CFGF_NONE),
! 48: CFG_INT("size", 60, CFGF_NONE),
! 49: CFG_STR("type", "64bit", CFGF_NONE),
! 50: CFG_END()
! 51: };
! 52:
! 53: static cfg_opt_t attr_opts[] = {
! 54: CFG_STR("description", "", CFGF_NONE),
! 55: CFG_STR("unit", "", CFGF_NONE),
! 56: CFG_STR("type", "counter", CFGF_NONE),
! 57: CFG_BOOL("history", cfg_false, CFGF_NONE),
! 58: CFG_END()
! 59: };
! 60:
! 61: static cfg_opt_t variant_opts[] = {
! 62: CFG_FLOAT_LIST("div", "{}", CFGF_NONE),
! 63: CFG_STR_LIST("txt", "", CFGF_NONE),
! 64: CFG_END()
! 65: };
! 66:
! 67: static cfg_opt_t unit_opts[] = {
! 68: CFG_SEC("variant", variant_opts, CFGF_MULTI | CFGF_TITLE),
! 69: CFG_END()
! 70: };
! 71:
! 72: static cfg_opt_t global_opts[] = {
! 73: CFG_FLOAT("read_interval", 1.0f, CFGF_NONE),
! 74: CFG_FLOAT("rate_interval", 1.0f, CFGF_NONE),
! 75: CFG_FLOAT("lifetime", 30.0f, CFGF_NONE),
! 76: CFG_FLOAT("history_variance", 0.1f, CFGF_NONE),
! 77: CFG_FLOAT("variance", 0.1f, CFGF_NONE),
! 78: CFG_BOOL("show_all", cfg_false, CFGF_NONE),
! 79: CFG_INT("unit_exp", -1, CFGF_NONE),
! 80: CFG_INT("sleep_time", 20000UL, CFGF_NONE),
! 81: CFG_BOOL("use_si", 0, CFGF_NONE),
! 82: CFG_BOOL("use_bit", 0, CFGF_NONE),
! 83: CFG_STR("uid", NULL, CFGF_NONE),
! 84: CFG_STR("gid", NULL, CFGF_NONE),
! 85: CFG_STR("policy", "", CFGF_NONE),
! 86: CFG_SEC("unit", unit_opts, CFGF_MULTI | CFGF_TITLE),
! 87: CFG_SEC("attr", attr_opts, CFGF_MULTI | CFGF_TITLE),
! 88: CFG_SEC("history", history_opts, CFGF_MULTI | CFGF_TITLE),
! 89: CFG_SEC("element", element_opts, CFGF_MULTI | CFGF_TITLE),
! 90: CFG_END()
! 91: };
! 92:
! 93: float cfg_read_interval;
! 94: float cfg_rate_interval;
! 95: float cfg_rate_variance;
! 96: float cfg_history_variance;
! 97: int cfg_show_all;
! 98: int cfg_unit_exp = DYNAMIC_EXP;
! 99:
! 100: static char * configfile = NULL;
1.1 misho 101:
102: #if defined HAVE_CURSES
103: #if defined HAVE_USE_DEFAULT_COLORS
1.1.1.2 ! misho 104: struct layout cfg_layout[] =
1.1 misho 105: {
106: {-1, -1, 0}, /* dummy, not used */
107: {-1, -1, 0}, /* default */
108: {-1, -1, A_REVERSE}, /* statusbar */
109: {-1, -1, 0}, /* header */
110: {-1, -1, 0}, /* list */
111: {-1, -1, A_REVERSE}, /* selected */
112: };
113: #else
1.1.1.2 ! misho 114: struct layout cfg_layout[] =
1.1 misho 115: {
116: {0, 0, 0}, /* dummy, not used */
117: {COLOR_BLACK, COLOR_WHITE, 0}, /* default */
118: {COLOR_BLACK, COLOR_WHITE, A_REVERSE}, /* statusbar */
119: {COLOR_BLACK, COLOR_WHITE, 0}, /* header */
120: {COLOR_BLACK, COLOR_WHITE, 0}, /* list */
121: {COLOR_BLACK, COLOR_WHITE, A_REVERSE}, /* selected */
122: };
123: #endif
124: #endif
125:
126: tv_t * parse_tv(char *data)
127: {
128: char *value;
129: tv_t *tv = xcalloc(1, sizeof(tv_t));
130:
1.1.1.2 ! misho 131: init_list_head(&tv->tv_list);
! 132:
1.1 misho 133: value = strchr(data, '=');
134:
135: if (value) {
136: *value = '\0';
137: ++value;
1.1.1.2 ! misho 138: tv->tv_value = strdup(value);
1.1 misho 139: }
140:
1.1.1.2 ! misho 141: tv->tv_type = strdup(data);
1.1 misho 142: return tv;
143: }
144:
145: module_conf_t * parse_module(char *data)
146: {
147: char *name = data, *opts = data, *next;
148: module_conf_t *m;
149:
150: if (!*name)
151: quit("No module name given");
152:
153: m = xcalloc(1, sizeof(module_conf_t));
154:
1.1.1.2 ! misho 155: init_list_head(&m->m_attrs);
! 156:
1.1 misho 157: opts = strchr(data, ':');
158:
159: if (opts) {
160: *opts = '\0';
161: opts++;
162:
163: do {
164: tv_t *tv;
165: next = strchr(opts, ';');
166:
167: if (next) {
168: *next = '\0';
169: ++next;
170: }
171:
172: tv = parse_tv(opts);
1.1.1.2 ! misho 173: list_add_tail(&tv->tv_list, &m->m_attrs);
1.1 misho 174:
175: opts = next;
176: } while(next);
177: }
178:
1.1.1.2 ! misho 179: m->m_name = strdup(name);
1.1 misho 180: return m;
181: }
182:
183:
1.1.1.2 ! misho 184: int parse_module_param(const char *data, struct list_head *list)
1.1 misho 185: {
186: char *buf = strdup(data);
187: char *next;
188: char *current = buf;
1.1.1.2 ! misho 189: module_conf_t *m;
! 190: int n = 0;
1.1 misho 191:
192: do {
193: next = strchr(current, ',');
194:
195: if (next) {
196: *next = '\0';
197: ++next;
198: }
199:
200: m = parse_module(current);
201: if (m) {
1.1.1.2 ! misho 202: list_add_tail(&m->m_list, list);
! 203: n++;
1.1 misho 204: }
205:
206: current = next;
207: } while (next);
208:
209: free(buf);
210:
1.1.1.2 ! misho 211: return n;
1.1 misho 212: }
213:
1.1.1.2 ! misho 214: static void configfile_read_history(void)
1.1 misho 215: {
1.1.1.2 ! misho 216: int i, nhistory;
1.1 misho 217:
1.1.1.2 ! misho 218: nhistory = cfg_size(cfg, "history");
1.1 misho 219:
1.1.1.2 ! misho 220: for (i = 0; i < nhistory; i++) {
! 221: struct history_def *def;
! 222: cfg_t *history;
! 223: const char *name, *type;
! 224: float interval;
! 225: int size;
1.1 misho 226:
1.1.1.2 ! misho 227: if (!(history = cfg_getnsec(cfg, "history", i)))
! 228: BUG();
1.1 misho 229:
1.1.1.2 ! misho 230: if (!(name = cfg_title(history)))
! 231: BUG();
1.1 misho 232:
1.1.1.2 ! misho 233: interval = cfg_getfloat(history, "interval");
! 234: size = cfg_getint(history, "size");
! 235: type = cfg_getstr(history, "type");
1.1 misho 236:
1.1.1.2 ! misho 237: if (interval == 0.0f)
! 238: interval = cfg_getfloat(cfg, "read_interval");
1.1 misho 239:
1.1.1.2 ! misho 240: def = history_def_alloc(name);
! 241: def->hd_interval = interval;
! 242: def->hd_size = size;
1.1 misho 243:
1.1.1.2 ! misho 244: if (!strcasecmp(type, "8bit"))
! 245: def->hd_type = HISTORY_TYPE_8;
! 246: else if (!strcasecmp(type, "16bit"))
! 247: def->hd_type = HISTORY_TYPE_16;
! 248: else if (!strcasecmp(type, "32bit"))
! 249: def->hd_type = HISTORY_TYPE_32;
! 250: else if (!strcasecmp(type, "64bit"))
! 251: def->hd_type = HISTORY_TYPE_64;
! 252: else
! 253: quit("Invalid type \'%s\', must be \"(8|16|32|64)bit\""
! 254: " in history definition #%d\n", type, i+1);
1.1 misho 255: }
256: }
257:
1.1.1.2 ! misho 258: static void configfile_read_element_cfg(void)
1.1 misho 259: {
1.1.1.2 ! misho 260: int i, nelement;
1.1 misho 261:
1.1.1.2 ! misho 262: nelement = cfg_size(cfg, "element");
1.1 misho 263:
1.1.1.2 ! misho 264: for (i = 0; i < nelement; i++) {
! 265: struct element_cfg *ec;
! 266: cfg_t *element;
! 267: const char *name, *description;
! 268: long max;
1.1 misho 269:
1.1.1.2 ! misho 270: if (!(element = cfg_getnsec(cfg, "element", i)))
! 271: BUG();
1.1 misho 272:
1.1.1.2 ! misho 273: if (!(name = cfg_title(element)))
! 274: BUG();
1.1 misho 275:
1.1.1.2 ! misho 276: ec = element_cfg_alloc(name);
1.1 misho 277:
1.1.1.2 ! misho 278: if ((description = cfg_getstr(element, "description")))
! 279: ec->ec_description = strdup(description);
1.1 misho 280:
1.1.1.2 ! misho 281: if ((max = cfg_getint(element, "max")))
! 282: ec->ec_rxmax = ec->ec_txmax = max;
1.1 misho 283:
1.1.1.2 ! misho 284: if ((max = cfg_getint(element, "rxmax")))
! 285: ec->ec_rxmax = max;
1.1 misho 286:
1.1.1.2 ! misho 287: if ((max = cfg_getint(element, "txmax")))
! 288: ec->ec_txmax = max;
1.1 misho 289:
1.1.1.2 ! misho 290: if (cfg_getbool(element, "show"))
! 291: ec->ec_flags |= ELEMENT_CFG_SHOW;
1.1 misho 292: else
1.1.1.2 ! misho 293: ec->ec_flags |= ELEMENT_CFG_HIDE;
1.1 misho 294: }
295: }
296:
1.1.1.2 ! misho 297: static void add_div(struct unit *unit, int type, cfg_t *variant)
1.1 misho 298: {
1.1.1.2 ! misho 299: int ndiv, n, ntxt;
1.1 misho 300:
1.1.1.2 ! misho 301: if (!(ndiv = cfg_size(variant, "div")))
! 302: return;
1.1 misho 303:
1.1.1.2 ! misho 304: ntxt = cfg_size(variant, "txt");
! 305: if (ntxt != ndiv)
! 306: quit("Number of elements for div and txt not equal\n");
1.1 misho 307:
1.1.1.2 ! misho 308: if (!list_empty(&unit->u_div[type])) {
! 309: struct fraction *f, *n;
! 310:
! 311: list_for_each_entry_safe(f, n, &unit->u_div[type], f_list)
! 312: fraction_free(f);
1.1 misho 313: }
314:
1.1.1.2 ! misho 315: for (n = 0; n < ndiv; n++) {
! 316: char *txt;
! 317: float div;
1.1 misho 318:
1.1.1.2 ! misho 319: div = cfg_getnfloat(variant, "div", n);
! 320: txt = cfg_getnstr(variant, "txt", n);
! 321:
! 322: unit_add_div(unit, type, txt, div);
1.1 misho 323: }
324: }
325:
1.1.1.2 ! misho 326: static void configfile_read_units(void)
1.1 misho 327: {
1.1.1.2 ! misho 328: int i, nunits;
! 329: struct unit *u;
1.1 misho 330:
1.1.1.2 ! misho 331: nunits = cfg_size(cfg, "unit");
1.1 misho 332:
1.1.1.2 ! misho 333: for (i = 0; i < nunits; i++) {
! 334: int nvariants, n;
! 335: cfg_t *unit;
! 336: const char *name;
1.1 misho 337:
1.1.1.2 ! misho 338: if (!(unit = cfg_getnsec(cfg, "unit", i)))
! 339: BUG();
1.1 misho 340:
1.1.1.2 ! misho 341: if (!(name = cfg_title(unit)))
! 342: BUG();
1.1 misho 343:
1.1.1.2 ! misho 344: if (!(nvariants = cfg_size(unit, "variant")))
! 345: continue;
1.1 misho 346:
1.1.1.2 ! misho 347: if (!(u = unit_add(name)))
! 348: continue;
! 349:
! 350: for (n = 0; n < nvariants; n++) {
! 351: cfg_t *variant;
! 352: const char *vtitle;
! 353:
! 354: if (!(variant = cfg_getnsec(unit, "variant", n)))
! 355: BUG();
! 356:
! 357: if (!(vtitle = cfg_title(variant)))
! 358: BUG();
! 359:
! 360: if (!strcasecmp(vtitle, "default"))
! 361: add_div(u, UNIT_DEFAULT, variant);
! 362: else if (!strcasecmp(vtitle, "si"))
! 363: add_div(u, UNIT_SI, variant);
! 364: else if (!strcasecmp(vtitle, "bit"))
! 365: add_div(u, UNIT_BIT, variant);
! 366: else
! 367: quit("Unknown unit variant \'%s\'\n", vtitle);
! 368: }
1.1 misho 369: }
370: }
371:
1.1.1.2 ! misho 372: static void configfile_read_attrs(void)
1.1 misho 373: {
1.1.1.2 ! misho 374: int i, nattrs, t;
1.1 misho 375:
1.1.1.2 ! misho 376: nattrs = cfg_size(cfg, "attr");
! 377:
! 378: for (i = 0; i < nattrs; i++) {
! 379: struct unit *u;
! 380: cfg_t *attr;
! 381: const char *name, *description, *unit, *type;
! 382: int flags = 0;
! 383:
! 384: if (!(attr = cfg_getnsec(cfg, "attr", i)))
! 385: BUG();
! 386:
! 387: if (!(name = cfg_title(attr)))
! 388: BUG();
! 389:
! 390: description = cfg_getstr(attr, "description");
! 391: unit = cfg_getstr(attr, "unit");
! 392: type = cfg_getstr(attr, "type");
! 393:
! 394: if (!unit)
! 395: quit("Attribute '%s' is missing unit specification\n",
! 396: name);
! 397:
! 398: if (!type)
! 399: quit("Attribute '%s' is missing type specification\n",
! 400: name);
! 401:
! 402: if (!(u = unit_lookup(unit)))
! 403: quit("Unknown unit \'%s\' attribute '%s'\n",
! 404: unit, name);
! 405:
! 406: if (!strcasecmp(type, "counter"))
! 407: t = ATTR_TYPE_COUNTER;
! 408: else if (!strcasecmp(type, "rate"))
! 409: t = ATTR_TYPE_RATE;
! 410: else if (!strcasecmp(type, "percent"))
! 411: t = ATTR_TYPE_PERCENT;
! 412: else
! 413: quit("Unknown type \'%s\' in attribute '%s'\n",
! 414: type, name);
! 415:
! 416: if (cfg_getbool(attr, "history"))
! 417: flags |= ATTR_FORCE_HISTORY;
! 418:
! 419: if (cfg_getbool(attr, "ignore_overflows"))
! 420: flags |= ATTR_IGNORE_OVERFLOWS;
! 421:
! 422: attr_def_add(name, description, u, t, flags);
1.1 misho 423: }
424: }
425:
1.1.1.2 ! misho 426: static void conf_read(const char *path, int must)
1.1 misho 427: {
1.1.1.2 ! misho 428: int err;
1.1 misho 429:
1.1.1.2 ! misho 430: DBG("Reading configfile %s...", path);
1.1 misho 431:
1.1.1.2 ! misho 432: if (access(path, R_OK) != 0) {
! 433: if (must)
! 434: quit("Error: Unable to read configfile \"%s\": %s\n",
! 435: path, strerror(errno));
! 436: else
! 437: return;
! 438: }
! 439:
! 440: err = cfg_parse(cfg, path);
! 441: if (err == CFG_FILE_ERROR) {
! 442: quit("Error while reading configfile \"%s\": %s\n",
! 443: path, strerror(errno));
! 444: } else if (err == CFG_PARSE_ERROR) {
! 445: quit("Error while reading configfile \"%s\": parse error\n",
! 446: path);
! 447: }
! 448:
! 449: configfile_read_units();
! 450: configfile_read_history();
! 451: configfile_read_attrs();
! 452: configfile_read_element_cfg();
! 453: }
! 454:
! 455: static const char default_config[] = \
! 456: "unit byte {" \
! 457: " variant default {" \
! 458: " div = { 1, 1024, 1048576, 1073741824, 1099511627776}" \
! 459: " txt = { \"B\", \"KiB\", \"MiB\", \"GiB\", \"TiB\" }" \
! 460: " }" \
! 461: " variant si {" \
! 462: " div = { 1, 1000, 1000000, 1000000000, 1000000000000 }" \
! 463: " txt = { \"B\", \"KB\", \"MB\", \"GB\", \"TB\" }" \
! 464: " }" \
! 465: " variant bit {" \
! 466: " div = { 0.125, 125, 125000, 125000000, 125000000000 }" \
! 467: " txt = { \"b\", \"Kb\", \"Mb\", \"Gb\", \"Tb\" }" \
! 468: " }" \
! 469: " }" \
! 470: "unit bit {" \
! 471: " variant default {" \
! 472: " div = { 1, 1000, 1000000, 1000000000, 1000000000000 }" \
! 473: " txt = { \"b\", \"Kb\", \"Mb\", \"Gb\", \"Tb\" }" \
! 474: " }" \
! 475: " variant si {" \
! 476: " div = { 1, 1000, 1000000, 1000000000, 1000000000000 }" \
! 477: " txt = { \"b\", \"Kb\", \"Mb\", \"Gb\", \"Tb\" }" \
! 478: " }" \
! 479: " variant bit {" \
! 480: " div = { 1, 1000, 1000000, 1000000000, 1000000000000 }" \
! 481: " txt = { \"b\", \"Kb\", \"Mb\", \"Gb\", \"Tb\" }" \
! 482: " }" \
! 483: "}" \
! 484: "unit number {" \
! 485: " variant default {" \
! 486: " div = { 1, 1000, 1000000, 1000000000, 1000000000000 }" \
! 487: " txt = { \"\", \"K\", \"M\", \"G\", \"T\" }" \
! 488: " }" \
! 489: "}" \
! 490: "unit percent {" \
! 491: " variant default {" \
! 492: " div = { 1. }" \
! 493: " txt = { \"%\" }" \
! 494: " }" \
! 495: "}" \
! 496: "history second {" \
! 497: " interval = 1.0" \
! 498: " size = 60" \
! 499: "}" \
! 500: "history minute {" \
! 501: " interval = 60.0" \
! 502: " size = 60" \
! 503: "}" \
! 504: "history hour {" \
! 505: " interval = 3600.0" \
! 506: " size = 60" \
! 507: "}" \
! 508: "history day {" \
! 509: " interval = 86400.0" \
! 510: " size = 60" \
! 511: "}";
! 512:
! 513: static void conf_read_default(void)
! 514: {
! 515: int err;
! 516:
! 517: DBG("Reading default config");
! 518:
! 519: err = cfg_parse_buf(cfg, default_config);
! 520: if (err)
! 521: quit("Error while parsing default config\n");
! 522:
! 523: configfile_read_units();
! 524: configfile_read_history();
! 525: configfile_read_attrs();
! 526: configfile_read_element_cfg();
1.1 misho 527: }
528:
1.1.1.2 ! misho 529: void configfile_read(void)
1.1 misho 530: {
1.1.1.2 ! misho 531: if (configfile)
! 532: conf_read(configfile, 1);
! 533: else {
! 534: conf_read(SYSCONFDIR "/bmon.conf", 0);
! 535:
! 536: if (getenv("HOME")) {
! 537: char path[FILENAME_MAX+1];
! 538: snprintf(path, sizeof(path), "%s/.bmonrc",
! 539: getenv("HOME"));
! 540: conf_read(path, 0);
! 541: }
1.1 misho 542: }
543: }
544:
1.1.1.2 ! misho 545: void conf_init_pre(void)
1.1 misho 546: {
1.1.1.2 ! misho 547: conf_read_default();
1.1 misho 548: }
549:
1.1.1.2 ! misho 550: void conf_init_post(void)
1.1 misho 551: {
1.1.1.2 ! misho 552: cfg_read_interval = cfg_getfloat(cfg, "read_interval");
! 553: cfg_rate_interval = cfg_getfloat(cfg, "rate_interval");
! 554: cfg_rate_variance = cfg_getfloat(cfg, "variance") * cfg_rate_interval;
! 555: cfg_history_variance = cfg_getfloat(cfg, "history_variance");
! 556: cfg_show_all = cfg_getbool(cfg, "show_all");
! 557: cfg_unit_exp = cfg_getint(cfg, "unit_exp");
! 558:
! 559: element_parse_policy(cfg_getstr(cfg, "policy"));
1.1 misho 560: }
561:
1.1.1.2 ! misho 562: void set_configfile(const char *file)
1.1 misho 563: {
564: static int set = 0;
565: if (!set) {
1.1.1.2 ! misho 566: configfile = strdup(file);
1.1 misho 567: set = 1;
568: }
569: }
570:
1.1.1.2 ! misho 571: void set_unit_exp(const char *name)
1.1 misho 572: {
1.1.1.2 ! misho 573: if (tolower(*name) == 'b')
! 574: cfg_setint(cfg, "unit_exp", 0);
! 575: else if (tolower(*name) == 'k')
! 576: cfg_setint(cfg, "unit_exp", 1);
! 577: else if (tolower(*name) == 'm')
! 578: cfg_setint(cfg, "unit_exp", 2);
! 579: else if (tolower(*name) == 'g')
! 580: cfg_setint(cfg, "unit_exp", 3);
! 581: else if (tolower(*name) == 't')
! 582: cfg_setint(cfg, "unit_exp", 4);
! 583: else if (tolower(*name) == 'd')
! 584: cfg_setint(cfg, "unit_exp", DYNAMIC_EXP);
! 585: else
! 586: quit("Unknown unit exponent '%s'\n", name);
1.1 misho 587: }
588:
1.1.1.2 ! misho 589: unsigned int get_lifecycles(void)
1.1 misho 590: {
1.1.1.2 ! misho 591: return (unsigned int)
! 592: (cfg_getfloat(cfg, "lifetime") / cfg_getfloat(cfg, "read_interval"));
1.1 misho 593: }
594:
1.1.1.2 ! misho 595: static void __exit conf_shutdown(void)
1.1 misho 596: {
1.1.1.2 ! misho 597: cfg_free(cfg);
1.1 misho 598: }
599:
1.1.1.2 ! misho 600: static void __init __conf_init(void)
1.1 misho 601: {
1.1.1.2 ! misho 602: DBG("init");
! 603:
! 604: cfg = cfg_init(global_opts, CFGF_NOCASE);
! 605:
! 606: /* FIXME: Add validation functions */
! 607: //cfg_set_validate_func(cfg, "bookmark", &cb_validate_bookmark);
1.1 misho 608: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>