void validate_setup(void) { cfg_opt_t *opt = 0; static cfg_opt_t action_opts[] = { CFG_INT("speed", 0, CFGF_NONE), CFG_STR("name", 0, CFGF_NONE), CFG_INT("xspeed", 0, CFGF_NONE), CFG_END() }; static cfg_opt_t multi_opts[] = { CFG_INT_LIST("speeds", 0, CFGF_NONE), CFG_SEC("options", action_opts, CFGF_NONE), CFG_END() }; cfg_opt_t opts[] = { CFG_STR_LIST("ip-address", 0, CFGF_NONE), CFG_INT_CB("action", ACTION_NONE, CFGF_NONE, parse_action), CFG_SEC("options", action_opts, CFGF_NONE), CFG_SEC("multi_options", multi_opts, CFGF_MULTI), CFG_END() }; cfg = cfg_init(opts, 0); cfg_set_validate_func(cfg, "ip-address", validate_ip); fail_unless(cfg_set_validate_func(cfg, "ip-address", validate_ip) == validate_ip); opt = cfg_getopt(cfg, "ip-address"); fail_unless(opt != 0); fail_unless(opt->validcb == validate_ip); cfg_set_validate_func(cfg, "options", validate_action); fail_unless(cfg_set_validate_func(cfg, "options", validate_action) == validate_action); opt = cfg_getopt(cfg, "options"); fail_unless(opt != 0); fail_unless(opt->validcb == validate_action); cfg_set_validate_func(cfg, "options|speed", validate_speed); fail_unless(cfg_set_validate_func(cfg, "options|speed", validate_speed) == validate_speed); opt = cfg_getopt(cfg, "options|speed"); fail_unless(opt != 0); fail_unless(opt->validcb == validate_speed); cfg_set_validate_func(cfg, "multi_options|speeds", validate_speed); fail_unless(cfg_set_validate_func(cfg, "multi_options|speeds", validate_speed) == validate_speed); cfg_set_validate_func(cfg, "multi_options|options|xspeed", validate_speed); fail_unless(cfg_set_validate_func(cfg, "multi_options|options|xspeed", validate_speed) == validate_speed); /* Validate callbacks for *set*() functions, i.e. not when parsing file content */ cfg_set_validate_func2(cfg, "multi_options|speed", validate_speed2); cfg_set_validate_func2(cfg, "multi_options|options|name", validate_name2); }
/** * Start up the configuration system, using the configuration file given * to get the current values. If the configuration file given does not exist, * go ahead and write out the default config to the file. */ gint config_init (const gchar *config_file) { gint ret = 0; // Can we use a more descriptive name than tc? tc = cfg_init (config_opts, 0); if (g_file_test (config_file, G_FILE_TEST_IS_REGULAR)) { /* Read in the existing configuration options */ ret = cfg_parse (tc, config_file); if (ret == CFG_PARSE_ERROR) { DEBUG_ERROR ("Problem parsing config"); return ret; } else if (ret != CFG_SUCCESS) { DEBUG_ERROR ("Problem parsing config."); return ret; } } /* Deprecate old config settings * This is a lame work around until we get a permenant solution to * libconfuse lacking for this functionality */ const gchar *deprecated_tilda_config_options[] = {"show_on_monitor_number"}; remove_deprecated_config_options(deprecated_tilda_config_options, G_N_ELEMENTS(deprecated_tilda_config_options)); #if VTE_MINOR_VERSION >= 40 /* Deprecate old config settings * This is a lame work around until we get a permenant solution to * libconfuse lacking for this functionality */ const gchar *deprecated_vte_config_options[] = {"word_chars", "image", "scroll_background", "use_image"}; remove_deprecated_config_options (deprecated_vte_config_options, G_N_ELEMENTS(deprecated_vte_config_options)); #else if (cfg_getopt(tc, "use_image")->nvalues < 1) { cfg_setbool(tc, "use_image", FALSE); } if (cfg_getopt(tc, "word_chars")->nvalues < 1) { cfg_setstr(tc, "word_chars", DEFAULT_WORD_CHARS); } if (cfg_getopt(tc, "scroll_background")->nvalues < 1) { cfg_setbool(tc, "scroll_background", TRUE); } #endif #ifndef NO_THREADSAFE g_mutex_init(&mutex); #endif return ret; }
int Settings::setStringSetting(Node type, int intDeviceId, const std::wstring &name, const std::wstring &value, bool parameter) { // already locked if (d->cfg == 0) { return TELLSTICK_ERROR_PERMISSION_DENIED; } std::string strType = getNodeString(type); cfg_t *cfg_device; for (int i = 0; i < cfg_size(d->cfg, strType.c_str()); ++i) { cfg_device = cfg_getnsec(d->cfg, strType.c_str(), i); if (cfg_getint(cfg_device, "id") == intDeviceId) { std::string newValue = TelldusCore::wideToString(value); cfg_t *p = cfg_device; if (parameter) { p = cfg_getsec(cfg_device, "parameters"); } cfg_opt_t *opt = cfg_getopt(p, TelldusCore::wideToString(name).c_str()); if (!opt) { return TELLSTICK_ERROR_CONFIG_SYNTAX; } cfg_setstr(p, TelldusCore::wideToString(name).c_str(), newValue.c_str()); FILE *fp = fopen(CONFIG_FILE, "we"); // e for setting O_CLOEXEC on the file handle if (!fp) { return TELLSTICK_ERROR_PERMISSION_DENIED; } cfg_print(d->cfg, fp); fclose(fp); return TELLSTICK_SUCCESS; } } return TELLSTICK_ERROR_DEVICE_NOT_FOUND; }
DLLIMPORT int cfg_setmulti(cfg_t *cfg, const char *name, unsigned int nvalues, char **values) { cfg_opt_t *opt = cfg_getopt(cfg, name); if (!opt) return -1; return cfg_opt_setmulti(cfg, opt, nvalues, values); }
void remove_deprecated_config_options(const gchar *const *deprecated_config_options, guint size) { cfg_opt_t *opt; for (guint i =0; i < size; i++) { opt = cfg_getopt(tc, deprecated_config_options[i]); if (opt->nvalues != 0) { g_warning("Warning: %s is no longer a valid config option for the current version of Tilda.\n", deprecated_config_options[i]); cfg_free_value(opt); } } }
DLLIMPORT void cfg_addlist(cfg_t *cfg, const char *name, unsigned int nvalues, ...) { va_list ap; cfg_opt_t *opt = cfg_getopt(cfg, name); assert(opt && is_set(CFGF_LIST, opt->flags)); va_start(ap, nvalues); cfg_addlist_internal(opt, nvalues, ap); va_end(ap); }
static const char *set(int argc, char *argv[]) { if (argc < 3) return "Need more args\n"; if (!cfg_getopt(cfg, argv[1])) return "Unknown option\n"; if (cfg_setmulti(cfg, argv[1], argc - 2, &argv[2])) return "Failure\n"; return "OK\n"; }
void validate_test(void) { char *buf; unsigned int i; buf = "action = wlak"; fail_unless(cfg_parse_buf(cfg, buf) == CFG_PARSE_ERROR); buf = "action = walk"; fail_unless(cfg_parse_buf(cfg, buf) == CFG_SUCCESS); buf = "action = run" " options { speed = 6 }"; fail_unless(cfg_parse_buf(cfg, buf) == CFG_PARSE_ERROR); buf = "action = jump" " options { speed = 2 name = 'Joe' }"; fail_unless(cfg_parse_buf(cfg, buf) == CFG_SUCCESS); buf = "action = crawl" " options { speed = -2 name = 'Smith' }"; fail_unless(cfg_parse_buf(cfg, buf) == CFG_PARSE_ERROR); buf = "ip-address = { 0.0.0.0 , 1.2.3.4 , 192.168.0.254 , 10.0.0.255 , 20.30.40.256}"; fail_unless(cfg_parse_buf(cfg, buf) == CFG_PARSE_ERROR); buf = "ip-address = { 0.0.0.0 , 1.2.3.4 , 192.168.0.254 , 10.0.0.255 , 20.30.40.250}"; fail_unless(cfg_parse_buf(cfg, buf) == CFG_SUCCESS); buf = "ip-address = { 1.2.3. }"; fail_unless(cfg_parse_buf(cfg, buf) == CFG_PARSE_ERROR); buf = "action = run" " multi_options { speeds = {1, 2, 3, 4, 5} }"; fail_unless(cfg_parse_buf(cfg, buf) == CFG_SUCCESS); for (i = 0; i < cfg_size(cfg, "multi_options"); i++) { cfg_t *multisec = cfg_getnsec(cfg, "multi_options", i); cfg_opt_t *speeds_opt = cfg_getopt(multisec, "speeds"); fail_unless(speeds_opt != 0); fail_unless(speeds_opt->validcb == validate_speed); } buf = "action = run" " multi_options { speeds = {1, 2, 3, -4, 5} }"; fail_unless(cfg_parse_buf(cfg, buf) == CFG_PARSE_ERROR); buf = "action = run" " multi_options { speeds = {1, 2, 3, 4, 0} }"; fail_unless(cfg_parse_buf(cfg, buf) == CFG_PARSE_ERROR); buf = "action = run" " multi_options { options { xspeed = 3 } }"; fail_unless(cfg_parse_buf(cfg, buf) == CFG_SUCCESS); buf = "action = run" " multi_options { options { xspeed = -3 } }"; fail_unless(cfg_parse_buf(cfg, buf) == CFG_PARSE_ERROR); }
int main(void) { char *comment; char *expect = "Now, is it this comment that goes with the option?"; cfg_t *cfg; cfg_opt_t *opt; cfg_opt_t section_opts[] = { CFG_INT("key", 0, CFGF_NONE), CFG_BOOL("bool", 0, CFGF_NONE), CFG_STR("option", NULL, CFGF_NONE), CFG_END() }; cfg_opt_t opts[] = { CFG_STR("option", NULL, CFGF_NONE), CFG_SEC("section", section_opts, CFGF_MULTI), CFG_END() }; cfg = cfg_init(opts, CFGF_COMMENTS); fail_unless(cfg != NULL); fail_unless(cfg_parse(cfg, SRC_DIR "/annotate.conf") == CFG_SUCCESS); /* Verify the parser read the correct comment for this tricky option */ opt = cfg_getopt(cfg, "section|option"); fail_unless(opt != NULL); comment = cfg_opt_getcomment(opt); fail_unless(comment != NULL); fail_unless(strcmp(comment, expect) == 0); expect = "But what's the worst poetry in the universe?"; fail_unless(cfg_opt_setcomment(opt, expect) == CFG_SUCCESS); cfg_opt_setnstr(opt, "Paula Nancy Millstone Jennings was a poet who wrote the worst poetry in " "the universe. In fact, her poetry is still considered to be the worst in " "the Galaxy, closely followed by that of the Azgoths of Kria and the " "Vogons, in that order.", 0); /* Verify that the comment is not reset when changing option value */ comment = cfg_opt_getcomment(opt); fail_unless(comment != NULL); fail_unless(strcmp(comment, expect) == 0); cfg_print(cfg, stdout); fail_unless(cfg_free(cfg) == CFG_SUCCESS); return 0; }
int validate_action(cfg_t *cfg, cfg_opt_t *opt) { cfg_opt_t *name_opt; cfg_t *action_sec = cfg_opt_getnsec(opt, 0); fail_unless(action_sec != 0); name_opt = cfg_getopt(action_sec, "name"); fail_unless(name_opt != 0); fail_unless(cfg_opt_size(name_opt) == 1); if (cfg_opt_getnstr(name_opt, 0) == NULL) { /* cfg_error(cfg, "missing required option 'name' in section %s", opt->name); */ return 1; } return 0; }
static const char *subset(int argc, char *argv[]) { cfg_t *sub; if (argc < 4) return "Need more args\n"; if (argc > 4) return "Too many args\n"; sub = cfg_gettsec(cfg, "sub", argv[1]); if (!sub) return "No such section\n"; if (!cfg_getopt(sub, argv[2])) return "Unknown option\n"; if (cfg_setmulti(sub, argv[2], argc - 3, &argv[3])) return "Failure\n"; return "OK\n"; }
void gimmix_config_save (Conf *conf) { FILE *fp; cfg_t *cfg; cfg_opt_t *sopts; cfg_opt_t opts[] = { CFG_SIMPLE_STR ("mpd_hostname", NULL), CFG_SIMPLE_INT ("mpd_port", 0), CFG_SIMPLE_STR ("mpd_password", NULL), CFG_SIMPLE_BOOL ("enable_systray", false), CFG_SIMPLE_BOOL ("enable_notify", false), CFG_END() }; cfg = cfg_init(opts, 0); char *rcfile = cfg_tilde_expand ("~/.gimmixrc"); if((fp = fopen(rcfile, "w"))) { fprintf (fp, "# Gimmix configuration\n"); fprintf (fp, "\n# MPD hostname (default: localhost)\n"); if (conf->hostname) cfg_setstr(cfg, "mpd_hostname", conf->hostname); sopts = cfg_getopt (cfg, "mpd_hostname"); cfg_opt_print (sopts, fp); fprintf (fp, "\n# MPD port (default: 6600)\n"); if (conf->port > 0) cfg_setint(cfg, "mpd_port", conf->port); else cfg_setint(cfg, "mpd_port", 0); sopts = cfg_getopt (cfg, "mpd_port"); cfg_opt_print (sopts, fp); fprintf (fp, "\n# MPD password (leave blank for no password) \n"); if (conf->password) cfg_setstr(cfg, "mpd_password", conf->password); sopts = cfg_getopt (cfg, "mpd_password"); cfg_opt_print (sopts, fp); fprintf (fp, "\n# Enable/Disable systray icon (Enable = true, Disable = false)\n"); if (conf->systray_enable == 1) cfg_setbool(cfg, "enable_systray", true); else cfg_setbool(cfg, "enable_systray", false); sopts = cfg_getopt (cfg, "enable_systray"); cfg_opt_print (sopts, fp); fprintf (fp, "\n# Enable/Disable system tray notifications (Enable = true, Disable = false) \n"); if (conf->notify_enable == 1) cfg_setbool(cfg, "enable_notify", true); else cfg_setbool(cfg, "enable_notify", false); sopts = cfg_getopt (cfg, "enable_notify"); cfg_opt_print (sopts, fp); free (rcfile); fclose (fp); } else { fprintf (stderr, "Error while saving config.\n"); } cfg_free_value (opts); cfg_free (cfg); return; }
DLLIMPORT void cfg_rmtsec(cfg_t *cfg, const char *name, const char *title) { cfg_opt_rmtsec(cfg_getopt(cfg, name), title); }
static int cfg_parse_internal(cfg_t *cfg, int level, int force_state, cfg_opt_t *force_opt) { int state = 0; char *opttitle = 0; cfg_opt_t *opt = 0; cfg_value_t *val = 0; cfg_opt_t funcopt = CFG_STR(0, 0, 0); int num_values = 0; /* number of values found for a list option */ int rc; if(force_state != -1) state = force_state; if(force_opt) opt = force_opt; while(1) { int tok = cfg_yylex(cfg); if(tok == 0) { /* lexer.l should have called cfg_error */ return STATE_ERROR; } if(tok == EOF) { if(state != 0) { cfg_error(cfg, _("premature end of file")); return STATE_ERROR; } return STATE_EOF; } switch(state) { case 0: /* expecting an option name */ if(tok == '}') { if(level == 0) { cfg_error(cfg, _("unexpected closing brace")); return STATE_ERROR; } return STATE_EOF; } if(tok != CFGT_STR) { cfg_error(cfg, _("unexpected token '%s'"), cfg_yylval); return STATE_ERROR; } opt = cfg_getopt(cfg, cfg_yylval); if(opt == 0) return STATE_ERROR; if(opt->type == CFGT_SEC) { if(is_set(CFGF_TITLE, opt->flags)) state = 6; else state = 5; } else if(opt->type == CFGT_FUNC) { state = 7; } else state = 1; break; case 1: /* expecting an equal sign or plus-equal sign */ if(tok == '+') { if(!is_set(CFGF_LIST, opt->flags)) { cfg_error(cfg, _("attempt to append to non-list option '%s'"), opt->name); return STATE_ERROR; } /* Even if the reset flag was set by * cfg_init_defaults, appending to the defaults * should be ok. */ opt->flags &= ~CFGF_RESET; } else if(tok == '=') { /* set the (temporary) reset flag to clear the old * values, since we obviously didn't want to append */ opt->flags |= CFGF_RESET; } else { cfg_error(cfg, _("missing equal sign after option '%s'"), opt->name); return STATE_ERROR; } if(is_set(CFGF_LIST, opt->flags)) { state = 3; num_values = 0; } else state = 2; break; case 2: /* expecting an option value */ if(tok == '}' && is_set(CFGF_LIST, opt->flags)) { state = 0; if(num_values == 0 && is_set(CFGF_RESET, opt->flags)) /* Reset flags was set, and the empty list was * specified. Free all old values. */ cfg_free_value(opt); break; } if(tok != CFGT_STR) { cfg_error(cfg, _("unexpected token '%s'"), cfg_yylval); return STATE_ERROR; } if(cfg_setopt(cfg, opt, cfg_yylval) == 0) return STATE_ERROR; if(opt->validcb && (*opt->validcb)(cfg, opt) != 0) return STATE_ERROR; if(is_set(CFGF_LIST, opt->flags)) { state = 4; ++num_values; } else state = 0; break; case 3: /* expecting an opening brace for a list option */ if(tok != '{') { cfg_error(cfg, _("missing opening brace for option '%s'"), opt->name); return STATE_ERROR; } state = 2; break; case 4: /* expecting a separator for a list option, or * closing (list) brace */ if(tok == ',') state = 2; else if(tok == '}') { state = 0; if(opt->validcb && (*opt->validcb)(cfg, opt) != 0) return STATE_ERROR; } else { cfg_error(cfg, _("unexpected token '%s'"), cfg_yylval); return STATE_ERROR; } break; case 5: /* expecting an opening brace for a section */ if(tok != '{') { cfg_error(cfg, _("missing opening brace for section '%s'"), opt->name); return STATE_ERROR; } val = cfg_setopt(cfg, opt, opttitle); opttitle = 0; if(!val) return STATE_ERROR; val->section->line = cfg->line; rc = cfg_parse_internal(val->section, level+1,-1,0); cfg->line = val->section->line; if(rc != STATE_EOF) return STATE_ERROR; if(opt->validcb && (*opt->validcb)(cfg, opt) != 0) return STATE_ERROR; state = 0; break; case 6: /* expecting a title for a section */ if(tok != CFGT_STR) { cfg_error(cfg, _("missing title for section '%s'"), opt->name); return STATE_ERROR; } else opttitle = strdup(cfg_yylval); state = 5; break; case 7: /* expecting an opening parenthesis for a function */ if(tok != '(') { cfg_error(cfg, _("missing parenthesis for function '%s'"), opt->name); return STATE_ERROR; } state = 8; break; case 8: /* expecting a function parameter or a closing paren */ if(tok == ')') { int ret = call_function(cfg, opt, &funcopt); if(ret != 0) return STATE_ERROR; state = 0; } else if(tok == CFGT_STR) { val = cfg_addval(&funcopt); val->string = strdup(cfg_yylval); state = 9; } else { cfg_error(cfg, _("syntax error in call of function '%s'"), opt->name); return STATE_ERROR; } break; case 9: /* expecting a comma in a function or a closing paren */ if(tok == ')') { int ret = call_function(cfg, opt, &funcopt); if(ret != 0) return STATE_ERROR; state = 0; } else if(tok == ',') state = 8; else { cfg_error(cfg, _("syntax error in call of function '%s'"), opt->name); return STATE_ERROR; } break; default: /* missing state, internal error, abort */ assert(0); } } return STATE_EOF; }
DLLIMPORT cfg_t *cfg_gettsec(cfg_t *cfg, const char *name, const char *title) { return cfg_opt_gettsec(cfg_getopt(cfg, name), title); }
DLLIMPORT cfg_t *cfg_getnsec(cfg_t *cfg, const char *name, unsigned int index) { return cfg_opt_getnsec(cfg_getopt(cfg, name), index); }
DLLIMPORT double cfg_getnfloat(cfg_t *cfg, const char *name, unsigned int index) { return cfg_opt_getnfloat(cfg_getopt(cfg, name), index); }
DLLIMPORT unsigned int cfg_size(cfg_t *cfg, const char *name) { return cfg_opt_size(cfg_getopt(cfg, name)); }
DLLIMPORT cfg_print_func_t cfg_set_print_func(cfg_t *cfg, const char *name, cfg_print_func_t pf) { return cfg_opt_set_print_func(cfg_getopt(cfg, name), pf); }
DLLIMPORT void cfg_setnstr(cfg_t *cfg, const char *name, const char *value, unsigned int index) { cfg_opt_setnstr(cfg_getopt(cfg, name), value, index); }
DLLIMPORT void cfg_rmnsec(cfg_t *cfg, const char *name, unsigned int index) { cfg_opt_rmnsec(cfg_getopt(cfg, name), index); }
/** * @brief parses a single rule from a server { vhost { rules { } } } config * * @param cfg * * @return */ rule_cfg_t * rule_cfg_parse(cfg_t * cfg) { rule_cfg_t * rcfg; const char * rname; int i; assert(cfg != NULL); rname = cfg_title(cfg); assert(rname != NULL); rcfg = rule_cfg_new(); assert(cfg != NULL); rcfg->name = strdup(rname); assert(rcfg->name != NULL); if (cfg_getstr(cfg, "uri-match")) { rcfg->type = rule_type_exact; rcfg->matchstr = strdup(cfg_getstr(cfg, "uri-match")); } else if (cfg_getstr(cfg, "uri-gmatch")) { rcfg->type = rule_type_glob; rcfg->matchstr = strdup(cfg_getstr(cfg, "uri-gmatch")); } else if (cfg_getstr(cfg, "uri-rmatch")) { rcfg->type = rule_type_regex; rcfg->matchstr = strdup(cfg_getstr(cfg, "uri-rmatch")); } else { fprintf(stderr, "Rule %s has no match statement!\n", rname); exit(EXIT_FAILURE); } rcfg->lb_method = lbstr_to_lbtype(cfg_getstr(cfg, "lb-method")); rcfg->headers = headers_cfg_parse(cfg_getsec(cfg, "headers")); rcfg->passthrough = cfg_getbool(cfg, "passthrough"); rcfg->allow_redirect = cfg_getbool(cfg, "allow-redirect"); if (cfg_getopt(cfg, "upstream-read-timeout")) { rcfg->up_read_timeout.tv_sec = cfg_getnint(cfg, "upstream-read-timeout", 0); rcfg->up_read_timeout.tv_usec = cfg_getnint(cfg, "upstream-read-timeout", 1); rcfg->has_up_read_timeout = 1; } if (cfg_getopt(cfg, "upstream-write-timeout")) { rcfg->up_write_timeout.tv_sec = cfg_getnint(cfg, "upstream-write-timeout", 0); rcfg->up_write_timeout.tv_usec = cfg_getnint(cfg, "upstream-write-timeout", 1); rcfg->has_up_write_timeout = 1; } for (i = 0; i < cfg_size(cfg, "downstreams"); i++) { lztq_elem * elem; char * ds_name; ds_name = strdup(cfg_getnstr(cfg, "downstreams", i)); assert(ds_name != NULL); elem = lztq_append(rcfg->downstreams, ds_name, strlen(ds_name), free); assert(elem != NULL); } if (rcfg->allow_redirect != 0 && cfg_size(cfg, "redirect-filter")) { /* * if the redirect option is enabled, optionally an administrator can * add a list of allowed hosts it may communicate with. */ int n_filters; n_filters = cfg_size(cfg, "redirect-filter"); assert(n_filters > 0); rcfg->redirect_filter = lztq_new(); assert(rcfg->redirect_filter != NULL); for (i = 0; i < n_filters; i++) { lztq_elem * elem; char * host_ent; host_ent = strdup(cfg_getnstr(cfg, "redirect-filter", i)); assert(host_ent != NULL); elem = lztq_append(rcfg->redirect_filter, host_ent, strlen(host_ent), free); assert(elem != NULL); } } return rcfg; } /* rule_cfg_parse */