text_placements_ptr registry::from_xml(std::string name, xml_node const& xml, fontset_map const& fontsets, bool is_shield) { std::map<std::string, from_xml_function_ptr>::const_iterator itr = map_.find(name); if (itr == map_.end()) throw config_error("Unknown placement-type '" + name + "'", xml); return itr->second(xml, fontsets, is_shield); }
void grid_renderer<T>::process(text_symbolizer const& sym, Feature const& feature, proj_transform const& prj_trans) { typedef coord_transform2<CoordTransform,geometry_type> path_type; bool placement_found = false; text_placement_info_ptr placement_options = sym.get_placement_options()->get_placement_info(); while (!placement_found && placement_options->next()) { expression_ptr name_expr = sym.get_name(); if (!name_expr) return; value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature),*name_expr); UnicodeString text = result.to_unicode(); if ( sym.get_text_transform() == UPPERCASE) { text = text.toUpper(); } else if ( sym.get_text_transform() == LOWERCASE) { text = text.toLower(); } else if ( sym.get_text_transform() == CAPITALIZE) { text = text.toTitle(NULL); } if ( text.length() <= 0 ) continue; color const& fill = sym.get_fill(); face_set_ptr faces; if (sym.get_fontset().size() > 0) { faces = font_manager_.get_face_set(sym.get_fontset()); } else { faces = font_manager_.get_face_set(sym.get_face_name()); } stroker_ptr strk = font_manager_.get_stroker(); if (!(faces->size() > 0 && strk)) { throw config_error("Unable to find specified font face '" + sym.get_face_name() + "'"); } text_renderer<T> ren(pixmap_, faces, *strk); ren.set_pixel_size(placement_options->text_size * (scale_factor_ * (1.0/pixmap_.get_resolution()))); ren.set_fill(fill); ren.set_halo_fill(sym.get_halo_fill()); ren.set_halo_radius(sym.get_halo_radius() * scale_factor_); ren.set_opacity(sym.get_text_opacity()); // /pixmap_.get_resolution() ? box2d<double> dims(0,0,width_,height_); placement_finder<label_collision_detector4> finder(detector_,dims); string_info info(text); faces->get_string_info(info); unsigned num_geom = feature.num_geometries(); for (unsigned i=0; i<num_geom; ++i) { geometry_type const& geom = feature.get_geometry(i); if (geom.num_points() == 0) continue; // don't bother with empty geometries while (!placement_found && placement_options->next_position_only()) { placement text_placement(info, sym, scale_factor_); text_placement.avoid_edges = sym.get_avoid_edges(); if (sym.get_label_placement() == POINT_PLACEMENT || sym.get_label_placement() == INTERIOR_PLACEMENT) { double label_x, label_y, z=0.0; if (sym.get_label_placement() == POINT_PLACEMENT) geom.label_position(&label_x, &label_y); else geom.label_interior_position(&label_x, &label_y); prj_trans.backward(label_x,label_y, z); t_.forward(&label_x,&label_y); double angle = 0.0; expression_ptr angle_expr = sym.get_orientation(); if (angle_expr) { // apply rotation value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature),*angle_expr); angle = result.to_double(); } finder.find_point_placement(text_placement, placement_options, label_x, label_y, angle, sym.get_line_spacing(), sym.get_character_spacing()); finder.update_detector(text_placement); } else if ( geom.num_points() > 1 && sym.get_label_placement() == LINE_PLACEMENT) { path_type path(t_,geom,prj_trans); finder.find_line_placements<path_type>(text_placement, placement_options, path); } if (!text_placement.placements.size()) continue; placement_found = true; for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ii) { double x = text_placement.placements[ii].starting_x; double y = text_placement.placements[ii].starting_y; ren.prepare_glyphs(&text_placement.placements[ii]); ren.render_id(feature.id(),x,y,2); } } } } if (placement_found) pixmap_.add_feature(feature); }
int Auth_CheckError(ConfigEntry *ce) { short type = AUTHTYPE_PLAINTEXT; #ifdef AUTHENABLE_SSL_CLIENTCERT X509 *x509_filecert = NULL; FILE *x509_f = NULL; #endif if (!ce->ce_vardata) { config_error("%s:%i: authentication module failure: missing parameter", ce->ce_fileptr->cf_filename, ce->ce_varlinenum); return -1; } if (ce->ce_entries && ce->ce_entries->ce_next) { config_error("%s:%i: you may not have multiple authentication methods", ce->ce_fileptr->cf_filename, ce->ce_varlinenum); return -1; } if (ce->ce_entries) { if (ce->ce_entries->ce_varname) { type = Auth_FindType(ce->ce_entries->ce_varname); if (type == -1) { config_error("%s:%i: authentication module failure: %s is not an implemented/enabled authentication method", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_entries->ce_varname); return -1; } switch (type) { #ifdef AUTHENABLE_UNIXCRYPT case AUTHTYPE_UNIXCRYPT: /* If our data is like 1 or none, we just let em through .. */ if (strlen(ce->ce_vardata) < 2) { config_error("%s:%i: authentication module failure: AUTHTYPE_UNIXCRYPT: no salt (crypt strings will always be >2 in length)", ce->ce_fileptr->cf_filename, ce->ce_varlinenum); return -1; } break; #endif #ifdef AUTHENABLE_SSL_CLIENTCERT case AUTHTYPE_SSL_CLIENTCERT: if (!(x509_f = fopen(ce->ce_vardata, "r"))) { config_error("%s:%i: authentication module failure: AUTHTYPE_SSL_CLIENTCERT: error opening file %s: %s", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_vardata, strerror(errno)); return -1; } x509_filecert = PEM_read_X509(x509_f, NULL, NULL, NULL); fclose(x509_f); if (!x509_filecert) { config_error("%s:%i: authentication module failure: AUTHTYPE_SSL_CLIENTCERT: PEM_read_X509 errored in file %s (format error?)", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_vardata); return -1; } X509_free(x509_filecert); break; #endif default: ; } } } return 1; }
static void mini_help(char* appname) { config_error("Run \"%s -h\" for help.",appname); }
static void version(void) { config_error("bbusb %s (%s)",VERSION_STRING,USB_TYPE); config_error("Copyright (C) 2009-2011 Nicholas Parker <*****@*****.**>"); config_error("License GPLv3+: GNU GPL version 3 or later"); config_error("This program comes with ABSOLUTELY NO WARRANTY."); }
broker_config::broker_config(const YAML::Node &config) { try { if (!config.IsMap()) { throw config_error("The configuration is not a YAML map"); } // load client address and port if (config["clients"] && config["clients"].IsMap()) { if (config["clients"]["address"] && config["clients"]["address"].IsScalar()) { client_address_ = config["clients"]["address"].as<std::string>(); } // no throw... can be omitted if (config["clients"]["port"] && config["clients"]["port"].IsScalar()) { client_port_ = config["clients"]["port"].as<uint16_t>(); } // no throw... can be omitted } // load worker address and port if (config["workers"] && config["workers"].IsMap()) { if (config["workers"]["address"] && config["workers"]["address"].IsScalar()) { worker_address_ = config["workers"]["address"].as<std::string>(); } // no throw... can be omitted if (config["workers"]["port"] && config["workers"]["port"].IsScalar()) { worker_port_ = config["workers"]["port"].as<uint16_t>(); } // no throw... can be omitted if (config["workers"]["max_liveness"] && config["workers"]["max_liveness"].IsScalar()) { max_worker_liveness_ = config["workers"]["max_liveness"].as<size_t>(); } // no throw... can be omitted if (config["workers"]["max_request_failures"] && config["workers"]["max_request_failures"].IsScalar()) { max_request_failures_ = config["workers"]["max_request_failures"].as<size_t>(); } // no throw... can be omitted if (config["workers"]["ping_interval"] && config["workers"]["ping_interval"].IsScalar()) { worker_ping_interval_ = std::chrono::milliseconds(config["workers"]["ping_interval"].as<size_t>()); } // no throw... can be omitted } // load monitor address and port if (config["monitor"] && config["monitor"].IsMap()) { if (config["monitor"]["address"] && config["monitor"]["address"].IsScalar()) { monitor_address_ = config["monitor"]["address"].as<std::string>(); } // no throw... can be omitted if (config["monitor"]["port"] && config["monitor"]["port"].IsScalar()) { monitor_port_ = config["monitor"]["port"].as<uint16_t>(); } // no throw... can be omitted } // load frontend address and port if (config["notifier"] && config["notifier"].IsMap()) { if (config["notifier"]["address"] && config["notifier"]["address"].IsScalar()) { notifier_config_.address = config["notifier"]["address"].as<std::string>(); } // no throw... can be omitted if (config["notifier"]["port"] && config["notifier"]["port"].IsScalar()) { notifier_config_.port = config["notifier"]["port"].as<uint16_t>(); } // no throw... can be omitted if (config["notifier"]["username"] && config["notifier"]["username"].IsScalar()) { notifier_config_.username = config["notifier"]["username"].as<std::string>(); } // no throw... can be omitted if (config["notifier"]["password"] && config["notifier"]["password"].IsScalar()) { notifier_config_.password = config["notifier"]["password"].as<std::string>(); } // no throw... can be omitted } // no throw... can be omitted // load logger if (config["logger"] && config["logger"].IsMap()) { if (config["logger"]["file"] && config["logger"]["file"].IsScalar()) { fs::path tmp = config["logger"]["file"].as<std::string>(); log_config_.log_basename = tmp.filename().string(); log_config_.log_path = tmp.parent_path().string(); } // no throw... can be omitted if (config["logger"]["level"] && config["logger"]["level"].IsScalar()) { log_config_.log_level = config["logger"]["level"].as<std::string>(); } // no throw... can be omitted if (config["logger"]["max-size"] && config["logger"]["max-size"].IsScalar()) { log_config_.log_file_size = config["logger"]["max-size"].as<size_t>(); } // no throw... can be omitted if (config["logger"]["rotations"] && config["logger"]["rotations"].IsScalar()) { log_config_.log_files_count = config["logger"]["rotations"].as<size_t>(); } // no throw... can be omitted } // no throw... can be omitted } catch (YAML::Exception &ex) { throw config_error("Default broker configuration was not loaded: " + std::string(ex.what())); } }
/** * Substitute variable references in a value. * * Substitutes variable references in a value (entirely replaces reference * values, and substitutes variables within strings). If the value is a list, * will recurse onto the values contained within the list. If an error occurs * while substituting variables, the error will be raised with config_error() * and the function will return false. For strings/references, if an error * occurs, the value will not be changed. * * @param value Value to substitute in. * @param env Environment to take variables from. * * @return Whether variables were successfully substituted. */ bool value_substitute(value_t *value, environ_t *env) { const value_t *target; char *str; size_t i, start; switch (value->type) { case VALUE_TYPE_REFERENCE: /* Non-string variable reference, replace the whole value. */ target = environ_lookup(env, value->string); if (!target) { config_error("Variable '%s' not found", value->string); return false; } free(value->string); value_copy(target, value); break; case VALUE_TYPE_STRING: /* Search for in-string variable references, which we substitute in the * string for a string representation of the variable. */ str = strdup(value->string); i = 0; start = 0; while (str[i]) { if (start) { if (isalnum(str[i]) || str[i] == '_') { i++; } else if (str[i] == '}') { const char *name; char *subst; size_t prefix_len, var_len, len; str[start - 2] = 0; str[i] = 0; /* We have a whole reference. */ name = &str[start]; target = environ_lookup(env, name); if (!target) { config_error("Variable '%s' not found", name); free(str); return false; } /* Stringify the target into the temporary buffer. */ switch (target->type) { case VALUE_TYPE_INTEGER: snprintf(temp_buf, TEMP_BUF_LEN, "%llu", target->integer); break; case VALUE_TYPE_BOOLEAN: snprintf(temp_buf, TEMP_BUF_LEN, (target->boolean) ? "true" : "false"); break; case VALUE_TYPE_STRING: snprintf(temp_buf, TEMP_BUF_LEN, "%s", target->string); break; default: config_error("Variable '%s' cannot be converted to string", name); free(str); return false; } /* Now allocate a new string. The start and end characters * of the reference have been replaced with null terminators * effectively splitting up the string into 3 parts. */ prefix_len = strlen(str); var_len = strlen(temp_buf); len = prefix_len + var_len + strlen(&str[i + 1]) + 1; subst = malloc(len); snprintf(subst, len, "%s%s%s", str, temp_buf, &str[i + 1]); /* Replace the string and continue after the substituted * portion. */ free(str); str = subst; i = prefix_len + var_len; start = 0; } else { start = 0; i++; } } else { if (str[i] == '$' && str[i + 1] == '{') { i += 2; start = i; } else { i++; } } } free(value->string); value->string = str; break; case VALUE_TYPE_LIST: for (i = 0; i < value->list->count; i++) { if (!value_substitute(&value->list->values[i], env)) return false; } break; default: break; } return true; }
void myfileopt(const char* fn, const struct cmdinfo* cmdinfos) { FILE* file; int line_num = 0; char linebuf[MAX_CONFIG_LINE]; file= fopen(fn, "r"); if (!file) { if (errno==ENOENT) return; warning(_("failed to open configuration file '%.255s' for reading: %s"), fn, strerror(errno)); return; } while (fgets(linebuf, sizeof(linebuf), file)) { char* opt; const struct cmdinfo *cip; int l; line_num++; if ((linebuf[0] == '#') || (linebuf[0] == '\n') || (linebuf[0] == '\0')) continue; l=strlen(linebuf); if (linebuf[l - 1] == '\n') linebuf[l - 1] = '\0'; for (opt=linebuf;isalnum(*opt)||*opt=='-';opt++) ; if (*opt == '\0') opt=NULL; else { *opt++ = '\0'; if (*opt=='=') opt++; while (isspace(*opt)) opt++; opt = str_strip_quotes(opt); if (opt == NULL) config_error(fn, line_num, _("unbalanced quotes in '%s'"), linebuf); } for (cip=cmdinfos; cip->olong || cip->oshort; cip++) { if (!cip->olong) continue; if (!strcmp(cip->olong,linebuf)) break; l=strlen(cip->olong); if ((cip->takesvalue==2) && (linebuf[l]=='-') && !opt && !strncmp(linebuf,cip->olong,l)) { opt=linebuf+l+1; break; } } if (!cip->olong) config_error(fn, line_num, _("unknown option '%s'"), linebuf); if (cip->takesvalue) { if (!opt) config_error(fn, line_num, _("'%s' needs a value"), linebuf); if (cip->call) cip->call(cip,opt); else *cip->sassignto = m_strdup(opt); } else { if (opt) config_error(fn, line_num, _("'%s' does not take a value"), linebuf); if (cip->call) cip->call(cip,NULL); else *cip->iassignto= cip->arg; } } if (ferror(file)) ohshite(_("read error in configuration file `%.255s'"), fn); if (fclose(file)) ohshite(_("error closing configuration file `%.255s'"), fn); }
datasource_ptr datasource_cache::create(parameters const& params) { boost::optional<std::string> type = params.get<std::string>("type"); if (!type) { throw config_error(std::string("Could not create datasource. Required ") + "parameter 'type' is missing"); } datasource_ptr ds; #ifdef MAPNIK_STATIC_PLUGINS // return if it's created, raise otherwise ds = create_static_datasource(params); if (ds) { return ds; } #endif std::map<std::string,std::shared_ptr<PluginInfo> >::iterator itr; // add scope to ensure lock is released asap { #ifdef MAPNIK_THREADSAFE std::lock_guard<std::recursive_mutex> lock(instance_mutex_); #endif itr = plugins_.find(*type); if (itr == plugins_.end()) { std::string s("Could not create datasource for type: '"); s += *type + "'"; if (plugin_directories_.empty()) { s += " (no datasource plugin directories have been successfully registered)"; } else { s += " (searched for datasource plugins in '" + plugin_directories() + "')"; } throw config_error(s); } } if (!itr->second->valid()) { throw std::runtime_error(std::string("Cannot load library: ") + itr->second->get_error()); } // http://www.mr-edd.co.uk/blog/supressing_gcc_warnings #ifdef __GNUC__ __extension__ #endif create_ds create_datasource = reinterpret_cast<create_ds>(itr->second->get_symbol("create")); if (! create_datasource) { throw std::runtime_error(std::string("Cannot load symbols: ") + itr->second->get_error()); } ds = datasource_ptr(create_datasource(params), datasource_deleter()); return ds; }
/**************************************************************************** * config_disk_directive ****************************************************************************/ static cw_bool_t config_disk_directive( struct config *cfg, struct disk *dsk, struct disk_track *dsk_trk, struct disk_params *dsk_prm, cw_flag_t scope) { cw_char_t token[GLOBAL_MAX_NAME_SIZE]; cw_count_t len; len = config_token(cfg, token, sizeof (token)); if (len == 0) { if (scope & SCOPE_ENTER) config_error(cfg, "directive expected"); config_error(cfg, "} expected"); } if ((scope & SCOPE_ENTER) && (string_equal(token, "{"))) return (config_disk_enter(cfg, dsk, dsk_trk, dsk_prm, scope)); if ((scope & SCOPE_LEAVE) && (string_equal(token, "}"))) return (CW_BOOL_FAIL); if (scope & SCOPE_TRACK) { if (string_equal(token, "info")) return (config_disk_info(cfg, dsk)); if (string_equal(token, "copy")) return (config_disk_copy(cfg, dsk)); if (string_equal(token, "image")) return (config_disk_image(cfg, dsk)); if (string_equal(token, "trackmap")) return (config_disk_trackmap(cfg, dsk)); if (string_equal(token, "track")) return (config_disk_track(cfg, dsk, dsk_trk)); if (string_equal(token, "track_range")) return (config_disk_track_range(cfg, dsk, dsk_trk)); } if (scope & SCOPE_RW) { if (string_equal(token, "format")) return (config_disk_format(cfg, dsk_trk)); if (string_equal(token, "clock")) return (config_disk_clock(cfg, dsk_trk)); if (string_equal(token, "timeout")) return (config_disk_timeout(cfg, dsk_trk)); if (string_equal(token, "indexed")) return (config_disk_indexed(cfg, dsk_trk)); if (string_equal(token, "optional")) return (config_disk_optional(cfg, dsk_trk)); if (string_equal(token, "flip_side")) return (config_disk_flip_side(cfg, dsk_trk)); if (string_equal(token, "side_offset")) return (config_disk_side_offset(cfg, dsk_trk)); if (string_equal(token, "read")) return (config_disk_directive(cfg, NULL, dsk_trk, NULL, SCOPE_ENTER | SCOPE_READ)); if (string_equal(token, "write")) return (config_disk_directive(cfg, NULL, dsk_trk, NULL, SCOPE_ENTER | SCOPE_WRITE)); if (disk_get_format(dsk_trk) == NULL) config_disk_error_format(cfg); if (string_equal(token, "skew")) return (config_disk_skew(cfg, dsk_trk)); if (string_equal(token, "interleave")) return (config_disk_interleave(cfg, dsk_trk)); if (config_disk_rw(cfg, dsk_trk, token)) return (CW_BOOL_OK); } if (scope & SCOPE_READ) { if (string_equal(token, "timeout")) return (config_disk_timeout_read(cfg, dsk_trk)); if (string_equal(token, "indexed")) return (config_disk_indexed_read(cfg, dsk_trk)); if (disk_get_format(dsk_trk) == NULL) config_disk_error_format(cfg); if (config_disk_read(cfg, dsk_trk, token)) return (CW_BOOL_OK); } if (scope & SCOPE_WRITE) { if (string_equal(token, "timeout")) return (config_disk_timeout_write(cfg, dsk_trk)); if (string_equal(token, "indexed")) return (config_disk_indexed_write(cfg, dsk_trk)); if (disk_get_format(dsk_trk) == NULL) config_disk_error_format(cfg); if (config_disk_write(cfg, dsk_trk, token)) return (CW_BOOL_OK); } if ((scope & SCOPE_PARAMS) && (config_disk_params(cfg, dsk_trk, dsk_prm, token, len))) return (CW_BOOL_OK); config_error_invalid(cfg, token); /* never reached, only to make gcc happy */ return (CW_BOOL_FAIL); }
static void parse_listener_prefix(struct config *c, struct config_line *l, struct lwan *lwan, const struct lwan_module *module, void *handler) { struct lwan_url_map url_map = {}; struct hash *hash = hash_str_new(free, free); char *prefix = strdupa(l->value); struct config *isolated; isolated = config_isolate_section(c, l); if (!isolated) { config_error(c, "Could not isolate configuration file"); goto out; } while (config_read_line(c, l)) { switch (l->type) { case CONFIG_LINE_TYPE_LINE: if (streq(l->key, "module")) { if (module) { config_error(c, "Module already specified"); goto out; } module = find_module(l->value); if (!module) { config_error(c, "Could not find module \"%s\"", l->value); goto out; } } else if (streq(l->key, "handler")) { if (handler) { config_error(c, "Handler already specified"); goto out; } handler = find_handler(l->value); if (!handler) { config_error(c, "Could not find handler \"%s\"", l->value); goto out; } } else { hash_add(hash, strdup(l->key), strdup(l->value)); } break; case CONFIG_LINE_TYPE_SECTION: if (streq(l->key, "authorization")) { parse_listener_prefix_authorization(c, l, &url_map); } else { if (!config_skip_section(c, l)) { config_error(c, "Could not skip section"); goto out; } } break; case CONFIG_LINE_TYPE_SECTION_END: goto add_map; } } config_error(c, "Expecting section end while parsing prefix"); goto out; add_map: if (module == handler && !handler) { config_error(c, "Missing module or handler"); goto out; } if (module && handler) { config_error(c, "Handler and module are mutually exclusive"); goto out; } if (handler) { url_map.handler = handler; url_map.flags |= HANDLER_PARSE_MASK | HANDLER_DATA_IS_HASH_TABLE; url_map.data = hash; url_map.module = NULL; hash = NULL; } else if (module && module->create_from_hash && module->handle_request) { url_map.data = module->create_from_hash(prefix, hash); if (module->parse_conf && !module->parse_conf(url_map.data, isolated)) { const char *msg = config_last_error(isolated); config_error(c, "Error from module: %s", msg ? msg : "Unknown"); goto out; } url_map.handler = module->handle_request; url_map.flags |= module->flags; url_map.module = module; } else { config_error(c, "Invalid handler"); goto out; } add_url_map(&lwan->url_map_trie, prefix, &url_map); out: hash_free(hash); config_close(isolated); }
static bool setup_from_config(lwan_t *lwan) { config_t conf; config_line_t line; bool has_listener = false; char path_buf[PATH_MAX]; const char *path; path = get_config_path(path_buf); lwan_status_info("Loading configuration file: %s", path); if (!lwan_trie_init(&lwan->url_map_trie, destroy_urlmap)) return false; if (!config_open(&conf, path)) return false; while (config_read_line(&conf, &line)) { switch (line.type) { case CONFIG_LINE_TYPE_LINE: if (!strcmp(line.line.key, "keep_alive_timeout")) lwan->config.keep_alive_timeout = (unsigned short)parse_long(line.line.value, default_config.keep_alive_timeout); else if (!strcmp(line.line.key, "quiet")) lwan->config.quiet = parse_bool(line.line.value, default_config.quiet); else if (!strcmp(line.line.key, "reuse_port")) lwan->config.reuse_port = parse_bool(line.line.value, default_config.reuse_port); else if (!strcmp(line.line.key, "proxy_protocol")) lwan->config.proxy_protocol = parse_bool(line.line.value, default_config.proxy_protocol); else if (!strcmp(line.line.key, "expires")) lwan->config.expires = parse_time_period(line.line.value, default_config.expires); else if (!strcmp(line.line.key, "error_template")) { free(lwan->config.error_template); lwan->config.error_template = strdup(line.line.value); } else if (!strcmp(line.line.key, "threads")) { long n_threads = parse_long(line.line.value, default_config.n_threads); if (n_threads < 0) config_error(&conf, "Invalid number of threads: %d", n_threads); lwan->config.n_threads = (unsigned short int)n_threads; } else config_error(&conf, "Unknown config key: %s", line.line.key); break; case CONFIG_LINE_TYPE_SECTION: if (!strcmp(line.section.name, "listener")) { if (!has_listener) { parse_listener(&conf, &line, lwan); has_listener = true; } else { config_error(&conf, "Only one listener supported"); } } else if (!strcmp(line.section.name, "straitjacket")) { lwan_straitjacket_enforce(&conf, &line); } else { config_error(&conf, "Unknown section type: %s", line.section.name); } break; case CONFIG_LINE_TYPE_SECTION_END: config_error(&conf, "Unexpected section end"); } } if (conf.error_message) { lwan_status_critical("Error on config file \"%s\", line %d: %s", path, conf.line, conf.error_message); } config_close(&conf); return true; }
static void parse_listener_prefix(config_t *c, config_line_t *l, lwan_t *lwan, const lwan_module_t *module) { lwan_url_map_t url_map = { }; struct hash *hash = hash_str_new(free, free); void *handler = NULL; char *prefix = strdupa(l->line.value); config_t isolated = { }; if (!config_isolate_section(c, l, &isolated)) { config_error(c, "Could not isolate configuration file"); goto out; } while (config_read_line(c, l)) { switch (l->type) { case CONFIG_LINE_TYPE_LINE: if (!strcmp(l->line.key, "module")) { if (module) { config_error(c, "Module already specified"); goto out; } module = lwan_module_find(lwan, l->line.value); if (!module) { config_error(c, "Could not find module \"%s\"", l->line.value); goto out; } } else if (!strcmp(l->line.key, "handler")) { handler = find_handler_symbol(l->line.value); if (!handler) { config_error(c, "Could not find handler \"%s\"", l->line.value); goto out; } } else { hash_add(hash, strdup(l->line.key), strdup(l->line.value)); } break; case CONFIG_LINE_TYPE_SECTION: if (!strcmp(l->section.name, "authorization")) { parse_listener_prefix_authorization(c, l, &url_map); } else { if (!config_skip_section(c, l)) { config_error(c, "Could not skip section"); goto out; } } break; case CONFIG_LINE_TYPE_SECTION_END: goto add_map; } } config_error(c, "Expecting section end while parsing prefix"); goto out; add_map: if (module == handler && !handler) { config_error(c, "Missing module or handler"); goto out; } if (module && handler) { config_error(c, "Handler and module are mutually exclusive"); goto out; } if (handler) { url_map.handler = handler; url_map.flags |= HANDLER_PARSE_MASK; url_map.data = hash; url_map.module = NULL; hash = NULL; } else if (module && module->init_from_hash && module->handle) { url_map.data = module->init_from_hash(hash); if (isolated.file && module->parse_conf) { if (!module->parse_conf(url_map.data, &isolated)) { config_error(c, "Error from module: %s", isolated.error_message ? isolated.error_message : "Unknown"); goto out; } } url_map.handler = module->handle; url_map.flags |= module->flags; url_map.module = module; } else { config_error(c, "Invalid handler"); goto out; } add_url_map(&lwan->url_map_trie, prefix, &url_map); out: hash_free(hash); config_close(&isolated); }
void rgba_palette::parse(std::string const& pal, palette_type type) { unsigned length = pal.length(); if ((type == PALETTE_RGBA && length % 4 > 0) || (type == PALETTE_RGB && length % 3 > 0) || (type == PALETTE_ACT && length != 772)) { throw config_error("invalid palette length"); } if (type == PALETTE_ACT) { length = (pal[768] << 8 | pal[769]) * 3; } sorted_pal_.clear(); rgb_pal_.clear(); alpha_pal_.clear(); if (type == PALETTE_RGBA) { for (unsigned i = 0; i < length; i += 4) { sorted_pal_.push_back(rgba(pal[i], pal[i + 1], pal[i + 2], pal[i + 3])); } } else { for (unsigned i = 0; i < length; i += 3) { sorted_pal_.push_back(rgba(pal[i], pal[i + 1], pal[i + 2], 0xFF)); } } // Make sure we have at least one entry in the palette. if (sorted_pal_.size() == 0) { sorted_pal_.push_back(rgba(0, 0, 0, 0)); } colors_ = sorted_pal_.size(); #ifdef USE_DENSE_HASH_MAP color_hashmap_.resize((colors_*2)); #endif color_hashmap_.clear(); // Sort palette for binary searching in quantization std::sort(sorted_pal_.begin(), sorted_pal_.end(), rgba::mean_sort_cmp()); // Insert all palette colors into the hashmap and into the palette vectors. for (unsigned i = 0; i < colors_; i++) { rgba c = sorted_pal_[i]; unsigned val = c.r | (c.g << 8) | (c.b << 16) | (c.a << 24); if (val != 0) { color_hashmap_[val] = i; } rgb_pal_.push_back(rgb(c)); if (c.a < 0xFF) { alpha_pal_.push_back(c.a); } } }
static int parse_inline_cmds(char** outptr, int* output_is_trimmed, char* in, unsigned int maxout) { config_debug("orig: %s",in); size_t iin = 0, iout = 0; char* out = malloc(maxout); while (iin < strlen(in)) { if (iout == maxout) { //stop!: reached max output size *output_is_trimmed = 1; break; } if (in[iin] == '\n' || in[iin] == '\t') { //replace newlines and tabs with spaces: out[iout++] = ' '; ++iin; } else if (in[iin] < 0x20) { //ignore all other special chars <0x20: ++iin; } else if (in[iin] == '<' || in[iin] == '&') { int i = 0, parsedlen = 0; char addme[32]; while (replacesrc[i] != 0) { //search replacement table: if (strncmp(replacesrc[i],&in[iin], strlen(replacesrc[i])) == 0) { strncpy(addme,replacedst[i],strlen(replacedst[i])+1); parsedlen = strlen(replacesrc[i]); break; } ++i; } if (parsedlen == 0) { //special tags: colorRGB/scolorRGB(0-3) speedN(1-6) if (strncmp("<color",&in[iin],6) == 0 && index(&in[iin+6],'>') == &in[iin+9]) {//<colorRGB> if (parse_color_code(&addme[2],&in[iin+6]) >= 0) { addme[0] = 0x1c; addme[1] = 'Z'; addme[COLOR_LEN+2] = 0; parsedlen = 10; } } else if (strncmp("<scolor",&in[iin],7) == 0 && index(&in[iin+7],'>') == &in[iin+10]) {//<colorRGB> if (parse_color_code(&addme[2],&in[iin+7]) >= 0) { addme[0] = 0x1c; addme[1] = 'Y'; addme[COLOR_LEN+2] = 0; parsedlen = 11; } } else if (strncmp("<speed",&in[iin],6) == 0 && index(&in[iin+6],'>') == &in[iin+7]) {//<speedN> char speedin = in[iin+6]; if (speedin >= '1' && speedin <= '5') { //speeds 1(0x31)-5(0x35) -> char 0x15-0x19 addme[0] = speedin-'0'+0x14; addme[1] = 0; parsedlen = 8; } else if (speedin == '6') { //speed 6 -> char 0x9 (nohold) addme[0] = 0x9; addme[1] = 0; parsedlen = 8; } else { config_error("Found invalid speed \"%c\" in <speedN> (N=1-6).", speedin); } } } if (parsedlen != 0) { int addme_size = strlen(addme); if (addme_size + iout > maxout) { //stop!: too big to fit in buffer *output_is_trimmed = 1; break; } else { memcpy(&out[iout],addme,addme_size); iout += addme_size; iin += parsedlen; } } else { out[iout++] = in[iin++];//nothing found, pass thru the '<' } } else { out[iout++] = in[iin++]; } } //append \0 to result, shrink buffer to match length of result: out = realloc(out,iout+1); out[iout] = '\0'; *outptr = out; config_debug("new (%d): %s",(int)strlen(out),out); return iin;//tell caller how far we got through their data }
static void parse_listener_prefix(struct config *c, struct config_line *l, struct lwan *lwan, const struct lwan_module *module, void *handler) { struct lwan_url_map url_map = {}; struct hash *hash = hash_str_new(free, free); char *prefix = strdupa(l->value); struct config *isolated; isolated = config_isolate_section(c, l); if (!isolated) { config_error(c, "Could not isolate configuration file"); goto out; } while (config_read_line(c, l)) { switch (l->type) { case CONFIG_LINE_TYPE_LINE: hash_add(hash, strdup(l->key), strdup(l->value)); break; case CONFIG_LINE_TYPE_SECTION: if (streq(l->key, "authorization")) { parse_listener_prefix_authorization(c, l, &url_map); } else if (!config_skip_section(c, l)) { config_error(c, "Could not skip section"); goto out; } break; case CONFIG_LINE_TYPE_SECTION_END: goto add_map; } } config_error(c, "Expecting section end while parsing prefix"); goto out; add_map: assert((handler && !module) || (!handler && module)); if (handler) { url_map.handler = handler; url_map.flags |= HANDLER_PARSE_MASK | HANDLER_DATA_IS_HASH_TABLE; url_map.data = hash; url_map.module = NULL; hash = NULL; } else if (module->create_from_hash && module->handle_request) { url_map.data = module->create_from_hash(prefix, hash); if (!url_map.data) { config_error(c, "Could not create module instance"); goto out; } if (module->parse_conf && !module->parse_conf(url_map.data, isolated)) { const char *msg = config_last_error(isolated); config_error(c, "Error from module: %s", msg ? msg : "Unknown"); goto out; } url_map.handler = module->handle_request; url_map.flags |= module->flags; url_map.module = module; } else if (UNLIKELY(!module->create_from_hash)) { config_error(c, "Module isn't prepared to load settings from a file; " "create_from_hash() method isn't present"); goto out; } else if (UNLIKELY(!module->handle_request)) { config_error(c, "Module does not have handle_request() method"); goto out; } add_url_map(&lwan->url_map_trie, prefix, &url_map); out: hash_free(hash); config_close(isolated); }
int parsefile(struct bb_frame** output, FILE* file) { int error = 0, linenum = 0; char filename = 0; char* line = NULL; ssize_t line_len; struct bb_frame* head = NULL; struct bb_frame* curframe = NULL; struct bb_frame** nextframeptr = &curframe; while ((line_len = readline(&line,file)) > 0) { ++linenum; config_debug("%s",line); char delim[] = {' ','\0'}; char delim_endline[] = {'\n','\0'}; char* tmp; char* cmd = strtok_r(line,delim,&tmp); if (strcmp(cmd,"txt") == 0) { char* mode = strtok_r(NULL,delim,&tmp); char* text = strtok_r(NULL,delim_endline,&tmp); if (checkmode(mode,text,linenum) < 0) { error = 1; break; } *nextframeptr = malloc(sizeof(struct bb_frame)); curframe = *nextframeptr; curframe->next = NULL; curframe->mode = tolower(mode[0]); if (strlen(mode) > 1) { curframe->mode_special = toupper(mode[1]); } else { curframe->mode_special = NO_SPECIAL; } if (text == NULL) { curframe->data = NULL; } else { int is_trimmed = 0; int charsparsed = parse_inline_cmds(&curframe->data,&is_trimmed, text,MAX_TEXTFILE_DATA_SIZE); if (is_trimmed) { config_error("Warning, line %d: Data has been truncated at input index %d to fit %d available output bytes.", linenum,charsparsed,MAX_TEXTFILE_DATA_SIZE); config_error("Input vs output bytecount can vary if you used inline commands in your input."); } } curframe->frame_type = TEXT_FRAME_TYPE; filename = packet_next_filename(filename); if (filename <= 0) { error = 1; break; } curframe->filename = filename; nextframeptr = &curframe->next; } else if (strcmp(cmd,"cmd") == 0) { char* mode = strtok_r(NULL,delim,&tmp); char* command = strtok_r(NULL,delim_endline,&tmp); if (checkmode(mode,command,linenum) < 0) { error = 1; break; } char* raw_result; if (runcmd(&raw_result,command) < 0) { error = 1; break; } //data for the TEXT frame which will reference these STRING frames: char refchar = 0x10;//format for each reference is 2 bytes: "0x10, filename" (pg55) char* textrefs = (char*)calloc(2*MAX_STRINGFILE_GROUP_COUNT+1,sizeof(char));//include \0 in size textrefs[2*MAX_STRINGFILE_GROUP_COUNT] = 0;//set \0 //Create and append STRING frames: int i, cumulative_parsed = 0; for (i = 0; i < MAX_STRINGFILE_GROUP_COUNT; i++) { *nextframeptr = malloc(sizeof(struct bb_frame)); curframe = *nextframeptr; curframe->next = NULL; if (head == NULL) { head = curframe; } int is_trimmed = 0; char* parsed_result; int charsparsed = parse_inline_cmds((char**)&parsed_result,&is_trimmed, &raw_result[cumulative_parsed], MAX_STRINGFILE_DATA_SIZE); cumulative_parsed += charsparsed; if (is_trimmed && i+1 == MAX_STRINGFILE_GROUP_COUNT) { config_error("Warning, line %d: Data has been truncated at input index %d to fit %d available output bytes.", linenum,cumulative_parsed,MAX_STRINGFILE_GROUP_COUNT*MAX_STRINGFILE_DATA_SIZE); config_error("Input vs output bytecount can vary if you used inline commands in your input."); } curframe->data = malloc(MAX_STRINGFILE_DATA_SIZE+1); strncpy(curframe->data,parsed_result, MAX_STRINGFILE_DATA_SIZE); curframe->data[MAX_STRINGFILE_DATA_SIZE] = 0; free(parsed_result); config_debug(">%d %s",i,curframe->data); filename = packet_next_filename(filename); if (filename <= 0) { error = 1; break; } curframe->filename = filename; //add a reference for ourselves to the TEXT frame: textrefs[2*i] = refchar; textrefs[2*i+1] = filename; curframe->frame_type = STRING_FRAME_TYPE; nextframeptr = &curframe->next; } free(raw_result); if (error == 1) { break; } //Append TEXT frame containing references to those STRINGs: *nextframeptr = malloc(sizeof(struct bb_frame)); curframe = *nextframeptr; curframe->next = NULL; curframe->mode = mode[0]; if (strlen(mode) > 1) { curframe->mode_special = mode[1]; } else { curframe->mode_special = NO_SPECIAL; } curframe->data = textrefs; curframe->frame_type = TEXT_FRAME_TYPE; filename = packet_next_filename(filename); if (filename <= 0) { error = 1; break; } curframe->filename = filename; nextframeptr = &curframe->next; } else if ((strlen(cmd) >= 2 && cmd[0] == '/' && cmd[1] == '/') || (strlen(cmd) >= 1 && cmd[0] == '#')) { //comment in input file, do nothing } else { config_error("Syntax error, line %d: Unknown command.",linenum); error = 1; break; } if (head == NULL) { head = curframe; } free(line); line = NULL; } if (line != NULL) { free(line); line = NULL; } *output = head; return (error == 0) ? 0 : -1; }
static bool setup_from_config(struct lwan *lwan, const char *path) { struct config *conf; struct config_line line; bool has_listener = false; char path_buf[PATH_MAX]; if (!path) path = lwan_get_config_path(path_buf, sizeof(path_buf)); lwan_status_info("Loading configuration file: %s", path); conf = config_open(path); if (!conf) return false; if (!lwan_trie_init(&lwan->url_map_trie, destroy_urlmap)) return false; while (config_read_line(conf, &line)) { switch (line.type) { case CONFIG_LINE_TYPE_LINE: if (streq(line.key, "keep_alive_timeout")) { lwan->config.keep_alive_timeout = (unsigned short)parse_long( line.value, default_config.keep_alive_timeout); } else if (streq(line.key, "quiet")) { lwan->config.quiet = parse_bool(line.value, default_config.quiet); } else if (streq(line.key, "reuse_port")) { lwan->config.reuse_port = parse_bool(line.value, default_config.reuse_port); } else if (streq(line.key, "proxy_protocol")) { lwan->config.proxy_protocol = parse_bool(line.value, default_config.proxy_protocol); } else if (streq(line.key, "allow_cors")) { lwan->config.allow_cors = parse_bool(line.value, default_config.allow_cors); } else if (streq(line.key, "expires")) { lwan->config.expires = parse_time_period(line.value, default_config.expires); } else if (streq(line.key, "error_template")) { free(lwan->config.error_template); lwan->config.error_template = strdup(line.value); } else if (streq(line.key, "threads")) { long n_threads = parse_long(line.value, default_config.n_threads); if (n_threads < 0) config_error(conf, "Invalid number of threads: %ld", n_threads); lwan->config.n_threads = (unsigned short int)n_threads; } else if (streq(line.key, "max_post_data_size")) { long max_post_data_size = parse_long( line.value, (long)default_config.max_post_data_size); if (max_post_data_size < 0) config_error(conf, "Negative maximum post data size"); else if (max_post_data_size > 128 * (1 << 20)) config_error(conf, "Maximum post data can't be over 128MiB"); lwan->config.max_post_data_size = (size_t)max_post_data_size; } else if (streq(line.key, "allow_temp_files")) { lwan->config.allow_post_temp_file = !!strstr(line.value, "post"); } else { config_error(conf, "Unknown config key: %s", line.key); } break; case CONFIG_LINE_TYPE_SECTION: if (streq(line.key, "listener")) { if (!has_listener) { parse_listener(conf, &line, lwan); has_listener = true; } else { config_error(conf, "Only one listener supported"); } } else if (streq(line.key, "straitjacket")) { lwan_straitjacket_enforce_from_config(conf); } else { config_error(conf, "Unknown section type: %s", line.key); } break; case CONFIG_LINE_TYPE_SECTION_END: config_error(conf, "Unexpected section end"); } } if (config_last_error(conf)) { lwan_status_critical("Error on config file \"%s\", line %d: %s", path, config_cur_line(conf), config_last_error(conf)); } config_close(conf); return true; }
static int config_ldap(void) { int i = 0, j = 0; char *value; option_list *mapping; if (!config.configured) { /* syslog(LOG_NOTICE, "Configuring the LDAP settings for the first time"); */ /* Search Base */ value = option_get("", opt_ldap_searchbase, 1, NULL); if (value) { config.searchbase = strdup(value); } else { config_error(err_ldap_missing, opt_ldap_searchbase); return -1; } /* Scope */ value = option_get("", opt_ldap_scope, 1, NULL); if (value) { if (strcasecmp(value, "subtree") == 0) { config.scope = LDAP_SCOPE_SUBTREE; } else if (strcasecmp(value, "base") == 0) { config.scope = LDAP_SCOPE_BASE; } else if (strcasecmp(value, "onelevel") == 0) { config.scope = LDAP_SCOPE_ONELEVEL; } else { config_error(err_ldap_badvalue, opt_ldap_scope); return -1; } } else { config_error(err_ldap_missing, opt_ldap_scope); return -1; } /* LDAP Server Hostname */ value = option_get("", opt_ldap_ldaphost, 1, NULL); if (value) { config.ldaphost = strdup(value); } else { config_error(err_ldap_missing, opt_ldap_ldaphost); return -1; } /* LDAP Server Port Number */ value = option_get("", opt_ldap_ldapport, 1); if (value) { config.ldapport = atoi(value); } else { config.ldapport = LDAP_PORT; } /* Fullname Attribute */ value = option_get("", opt_ldap_fullnameattr, 1, NULL); if (value) { config.fullnameattr = strdup(value); } else { config_error(err_ldap_missing, opt_ldap_fullnameattr); return -1; } /* Unique Attribute */ value = option_get("", opt_ldap_uniqueattr, 1, NULL); if (value) { config.uniqueattr = strdup(value); } else { config_error(err_ldap_missing, opt_ldap_uniqueattr); return -1; } /* Default Search Filter */ value = option_get("", opt_ldap_defaultfilter, 1, NULL); if (value) { config.defaultfilter = strdup(value); } else { config_error(err_ldap_missing, opt_ldap_defaultfilter); return -1; } /* Mapping from IMSP fields to LDAP attributes */ mapping = option_getlist("", opt_ldap_attrmap, 1); if (mapping == NULL) { config_error(err_ldap_missing, opt_ldap_attrmap); return -1; } /* there must be an even number of items to form pairs */ if (mapping->count == 0 || (mapping->count % 2) != 0 || (mapping->count / 2) > ATTRMAPSIZE) { config_error(err_ldap_badvalue, opt_ldap_attrmap); return -1; } /* step through the items in the map option, assigning them alternatively to the "field" and "value" halfs of the map structure. */ for (i = 0; i < mapping->count; i++) { if (strcasecmp(mapping->item[i], "null") == 0) value = NULL; else value = strdup(mapping->item[i]); if (i % 2 == 0) config.map[i / 2].field = value; else config.map[i / 2].attr = value; config.map[i / 2].append = NULL; } /* add a null terminator pair at the end */ config.map[i / 2].field = NULL; config.map[i / 2].attr = NULL; /* appendmap */ mapping = option_getlist("", opt_ldap_appendmap, 1); if (mapping != NULL) { if (mapping->count == 0 || (mapping->count % 2) != 0 || (mapping->count / 2) > ATTRMAPSIZE) { config_error(err_ldap_badvalue, opt_ldap_appendmap); return -1; } /* * step through the items in the appendmap, * assigning them to the "append" field of the * map structure, where necessary */ for (i = 0; i < mapping->count; i++) { for (j = 0; config.map[j].field != NULL ; j++) { if (strcmp(mapping->item[i], config.map[j].field) == 0) { i++; config.map[j].append = strdup(mapping->item[i]); } } } } /* Secondary search settings, if applicable */ value = option_get("", opt_ldap_secondary_searchbase, 1, NULL); if (value) { secondaryconfig.searchbase = strdup(value); /* Scope */ value = option_get("", opt_ldap_secondary_scope, 1, NULL); if (value) { if (strcasecmp(value, "subtree") == 0) { secondaryconfig.scope = LDAP_SCOPE_SUBTREE; } else if (strcasecmp(value, "base") == 0) { secondaryconfig.scope = LDAP_SCOPE_BASE; } else if (strcasecmp(value, "onelevel") == 0) { secondaryconfig.scope = LDAP_SCOPE_ONELEVEL; } else { config_error(err_ldap_badvalue, opt_ldap_secondary_scope); return -1; } } else { secondaryconfig.scope = config.scope; } /* LDAP Server Hostname */ value = option_get("", opt_ldap_secondary_ldaphost, 1, NULL); if (value) { secondaryconfig.ldaphost = strdup(value); } else { secondaryconfig.ldaphost = strdup(config.ldaphost); } /* LDAP Server Port Number */ value = option_get("", opt_ldap_secondary_ldapport, 1); if (value) { secondaryconfig.ldapport = atoi(value); } else { secondaryconfig.ldapport = config.ldapport; } /* Fullname Attribute */ value = option_get("", opt_ldap_secondary_fullnameattr, 1, NULL); if (value) { secondaryconfig.fullnameattr = strdup(value); } else { secondaryconfig.fullnameattr = strdup(config.fullnameattr); } /* Unique Attribute */ value = option_get("", opt_ldap_secondary_uniqueattr, 1, NULL); if (value) { secondaryconfig.uniqueattr = strdup(value); } else { secondaryconfig.uniqueattr = strdup(config.uniqueattr); } /* Default Search Filter */ value = option_get("", opt_ldap_secondary_defaultfilter, 1, NULL); if (value) { secondaryconfig.defaultfilter = strdup(value); } else { secondaryconfig.defaultfilter = strdup(config.defaultfilter); } /* Mapping from IMSP fields to LDAP attributes */ mapping = option_getlist("", opt_ldap_secondary_attrmap, 1); if (mapping == NULL) { mapping = mapping; } /* there must be an even number of items to form pairs */ if (mapping->count == 0 || (mapping->count % 2) != 0 || (mapping->count / 2) > ATTRMAPSIZE) { config_error(err_ldap_badvalue, opt_ldap_secondary_attrmap); return -1; } /* step through the items in the map option, assigning them alternatively to the "field" and "value" halfs of the map structure. */ for (i = 0; i < mapping->count; i++) { if (strcasecmp(mapping->item[i], "null") == 0) value = NULL; else value = strdup(mapping->item[i]); if (i % 2 == 0) secondaryconfig.map[i / 2].field = value; else secondaryconfig.map[i / 2].attr = value; secondaryconfig.map[i / 2].append = NULL; } /* add a null terminator pair at the end */ secondaryconfig.map[i / 2].field = NULL; secondaryconfig.map[i / 2].attr = NULL; /* appendmap */ mapping = option_getlist("", opt_ldap_secondary_appendmap, 1); if (mapping != NULL) { if (mapping->count == 0 || (mapping->count % 2) != 0 || (mapping->count / 2) > ATTRMAPSIZE) { config_error(err_ldap_badvalue, opt_ldap_secondary_appendmap); return -1; } /* * step through the items in the appendmap, * assigning them to the "append" field of the * map structure, where necessary */ for (i = 0; i < mapping->count; i++) { for (j = 0; secondaryconfig.map[j].field != NULL ; j++) { if (strcmp(mapping->item[i], secondaryconfig.map[j].field) == 0) { i++; secondaryconfig.map[j].append = strdup(mapping->item[i]); } } } } secondaryconfig.configured = 1; } else { /* no secondary search defined */ } config.configured = 1; } return 0; }
static ConfigFile * config_parse(char *filename, char *confdata) { char *ptr; char *start; int linenumber = 1; ConfigEntry *curce; ConfigEntry **lastce; ConfigEntry *cursection; ConfigFile *curcf; ConfigFile *lastcf; lastcf = curcf = (ConfigFile *)calloc(1, sizeof(ConfigFile)); memset(curcf, 0, sizeof(ConfigFile)); curcf->cf_filename = strdup(filename); lastce = &(curcf->cf_entries); curce = NULL; cursection = NULL; for (ptr = confdata; *ptr; ptr++) { switch (*ptr) { case '#': while (*++ptr && (*ptr != '\n')) ; if (!*ptr) { /* make for(;;) exit from the loop */ ptr--; continue; } linenumber++; break; case ';': if (!curce) { config_error("%s:%i Ignoring extra semicolon\n", filename, linenumber); break; } if (!strcmp(curce->ce_varname, "include")) { ConfigFile *cfptr; if (!curce->ce_vardata) { config_error ("%s:%i Ignoring \"include\": No filename given\n", filename, linenumber); config_entry_free(curce); curce = NULL; continue; } if (strlen(curce->ce_vardata) > 255) curce->ce_vardata[255] = '\0'; cfptr = config_load(curce->ce_vardata); if (cfptr) { lastcf->cf_next = cfptr; lastcf = cfptr; } config_entry_free(curce); curce = NULL; continue; } *lastce = curce; lastce = &(curce->ce_next); curce->ce_fileposend = (ptr - confdata); curce = NULL; break; case '{': if (!curce) { config_error("%s:%i: No name for section start\n", filename, linenumber); continue; } else if (curce->ce_entries) { config_error("%s:%i: Ignoring extra section start\n", filename, linenumber); continue; } curce->ce_sectlinenum = linenumber; lastce = &(curce->ce_entries); cursection = curce; curce = NULL; break; case '}': if (curce) { config_error ("%s:%i: Missing semicolon before close brace\n", filename, linenumber); config_entry_free(curce); config_free(curcf); return NULL; } else if (!cursection) { config_error("%s:%i: Ignoring extra close brace\n", filename, linenumber); continue; } curce = cursection; cursection->ce_fileposend = (ptr - confdata); cursection = cursection->ce_prevlevel; if (!cursection) lastce = &(curcf->cf_entries); else lastce = &(cursection->ce_entries); for (; *lastce; lastce = &((*lastce)->ce_next)) continue; break; case '/': if (*(ptr + 1) == '/') { ptr += 2; while (*ptr && (*ptr != '\n')) ptr++; if (!*ptr) break; ptr--; /* grab the \n on next loop thru */ continue; } else if (*(ptr + 1) == '*') { int commentstart = linenumber; for (ptr += 2; *ptr; ptr++) { if ((*ptr == '*') && (*(ptr + 1) == '/')) { ptr++; break; } else if (*ptr == '\n') linenumber++; } if (!*ptr) { config_error ("%s:%i Comment on this line does not end\n", filename, commentstart); config_entry_free(curce); config_free(curcf); return NULL; } } break; case '\"': start = ++ptr; for (; *ptr; ptr++) { if ((*ptr == '\\') && (*(ptr + 1) == '\"')) { char *tptr = ptr; while ((*tptr = *(tptr + 1))) tptr++; } else if ((*ptr == '\"') || (*ptr == '\n')) break; } if (!*ptr || (*ptr == '\n')) { config_error("%s:%i: Unterminated quote found\n", filename, linenumber); config_entry_free(curce); config_free(curcf); return NULL; } if (curce) { if (curce->ce_vardata) { config_error("%s:%i: Ignoring extra data\n", filename, linenumber); } else { char *eptr; curce->ce_vardata = (char *)calloc(1, ptr - start + 1); strncpy(curce->ce_vardata, start, ptr - start); curce->ce_vardata[ptr - start] = '\0'; curce->ce_vardatanum = strtol(curce->ce_vardata, &eptr, 0) & 0xffffffff; /* we only want 32bits and long is 64bit on 64bit compiles */ if (eptr != (curce->ce_vardata + (ptr - start))) { curce->ce_vardatanum = 0; } } } else { curce = (ConfigEntry *)calloc(1, sizeof(ConfigEntry)); memset(curce, 0, sizeof(ConfigEntry)); curce->ce_varname = (char *)calloc(1, ptr - start + 1); strncpy(curce->ce_varname, start, ptr - start); curce->ce_varname[ptr - start] = '\0'; curce->ce_varlinenum = linenumber; curce->ce_fileptr = curcf; curce->ce_prevlevel = cursection; curce->ce_fileposstart = (start - confdata); } break; case '\n': linenumber++; break; case '\t': case ' ': case '=': case '\r': break; default: if ((*ptr == '*') && (*(ptr + 1) == '/')) { config_error("%s:%i Ignoring extra end comment\n", filename, linenumber); ptr++; break; } start = ptr; for (; *ptr; ptr++) { if ((*ptr == ' ') || (*ptr == '\t') || (*ptr == '\n') || (*ptr == ';')) break; } if (!*ptr) { if (curce) config_error ("%s: Unexpected EOF for variable starting at %i\n", filename, curce->ce_varlinenum); else if (cursection) config_error ("%s: Unexpected EOF for section starting at %i\n", filename, curce->ce_sectlinenum); else config_error("%s: Unexpected EOF.\n", filename); config_entry_free(curce); config_free(curcf); return NULL; } if (curce) { if (curce->ce_vardata) { config_error("%s:%i: Ignoring extra data\n", filename, linenumber); } else { char *eptr; curce->ce_vardata = (char *)calloc(1, ptr - start + 1); strncpy(curce->ce_vardata, start, ptr - start); curce->ce_vardata[ptr - start] = '\0'; curce->ce_vardatanum = strtol(curce->ce_vardata, &eptr, 0) & 0xffffffff; /* we only want 32bits and long is 64bit on 64bit compiles */ if (eptr != (curce->ce_vardata + (ptr - start))) { curce->ce_vardatanum = 0; } } } else { curce = (ConfigEntry *)calloc(1, sizeof(ConfigEntry)); memset(curce, 0, sizeof(ConfigEntry)); curce->ce_varname = (char *)calloc(1, ptr - start + 1); strncpy(curce->ce_varname, start, ptr - start); curce->ce_varname[ptr - start] = '\0'; curce->ce_varlinenum = linenumber; curce->ce_fileptr = curcf; curce->ce_prevlevel = cursection; curce->ce_fileposstart = (start - confdata); } if ((*ptr == ';') || (*ptr == '\n')) ptr--; break; } /* switch */ } /* for */ if (curce) { config_error("%s: Unexpected EOF for variable starting on line %i\n", filename, curce->ce_varlinenum); config_entry_free(curce); config_free(curcf); return NULL; } else if (cursection) { config_error("%s: Unexpected EOF for section starting on line %i\n", filename, cursection->ce_sectlinenum); config_free(curcf); return NULL; } return curcf; }
DLLFUNC int htm_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs) { ConfigEntry *cep; int errors = 0; if (type != CONFIG_SET) return 0; if (!strcmp(ce->ce_varname, "htm")) { for (cep = ce->ce_entries; cep; cep = cep->ce_next) { if (!cep->ce_varname) { config_error("%s:%i: blank set::htm item", cep->ce_fileptr->cf_filename, cep->ce_varlinenum); errors++; continue; } if (!cep->ce_vardata) { config_error("%s:%i: set::htm::%s item without value", cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname); errors++; continue; } if (!strcmp(cep->ce_varname, "mode")) { if (stricmp(cep->ce_vardata, "noisy") && stricmp(cep->ce_vardata, "quiet")) { config_error("%s%i: set::htm::mode: illegal mode", cep->ce_fileptr->cf_filename, cep->ce_varlinenum); errors++; } } else if (!strcmp(cep->ce_varname, "incoming-rate")) { int value = config_checkval(cep->ce_vardata, CFG_SIZE); if (value < 10240) { config_error("%s%i: set::htm::incoming-rate: must be at least 10kb", cep->ce_fileptr->cf_filename, cep->ce_varlinenum); errors++; } } else { config_error("%s:%i: unknown directive set::htm::%s", cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname); errors++; } } *errs = errors; return errors ? -1 : 1; } else return 0; }
worker_config::worker_config(const YAML::Node &config) { try { if (config["broker-uri"] && config["broker-uri"].IsScalar()) { broker_uri_ = config["broker-uri"].as<std::string>(); } else { throw config_error("Item broker-uri not defined properly"); } if (config["broker-ping-interval"] && config["broker-ping-interval"].IsScalar()) { broker_ping_interval_ = std::chrono::milliseconds(config["broker-ping-interval"].as<size_t>()); } if (config["max-broker-liveness"] && config["max-broker-liveness"].IsScalar()) { max_broker_liveness_ = config["max-broker-liveness"].as<size_t>(); } if (!config["headers"].IsMap()) { throw config_error("Headers are not a map"); } for (auto entry : config["headers"]) { if (!entry.first.IsScalar()) { throw config_error("A header key is not scalar"); } if (entry.second.IsSequence()) { for (auto value : entry.second) { if (!value.IsScalar()) { throw config_error("A header value is not scalar"); } headers_.insert(std::make_pair(entry.first.as<std::string>(), value.as<std::string>())); } } else if (entry.second.IsScalar()) { headers_.insert(std::make_pair(entry.first.as<std::string>(), entry.second.as<std::string>())); } else { throw config_error("A header value is not scalar"); } } // load hwgroup if (config["hwgroup"] && config["hwgroup"].IsScalar()) { hwgroup_ = config["hwgroup"].as<std::string>(); } else { throw config_error("Item hwgroup not defined properly"); } // load file-cache item if (config["file-cache"] && config["file-cache"].IsMap()) { auto &cache = config["file-cache"]; if (cache["cache-dir"] && cache["cache-dir"].IsScalar()) { cache_dir_ = config["file-cache"]["cache-dir"].as<std::string>(); } } // load worker-id if (config["worker-id"] && config["worker-id"].IsScalar()) { worker_id_ = config["worker-id"].as<size_t>(); } else { throw config_error("Item worker-id not defined properly"); } // load worker-description if (config["worker-description"] && config["worker-description"].IsScalar()) { worker_description_ = config["worker-description"].as<std::string>(); } // can be omitted... no throw // load working directory path if (config["working-directory"] && config["working-directory"].IsScalar()) { working_directory_ = config["working-directory"].as<std::string>(); } // can be omitted... no throw // load file-managers if (config["file-managers"] && config["file-managers"].IsSequence()) { for (auto &fileman : config["file-managers"]) { fileman_config fileman_conf; if (fileman.IsMap()) { if (fileman["hostname"] && fileman["hostname"].IsScalar()) { fileman_conf.remote_url = fileman["hostname"].as<std::string>(); } // no throw... can be omitted if (fileman["username"] && fileman["username"].IsScalar()) { fileman_conf.username = fileman["username"].as<std::string>(); } // no throw... can be omitted if (fileman["password"] && fileman["password"].IsScalar()) { fileman_conf.password = fileman["password"].as<std::string>(); } // no throw... can be omitted } // no throw... can be omitted filemans_configs_.push_back(fileman_conf); } } else { throw config_error("File managers not defined properly"); } // load logger if (config["logger"] && config["logger"].IsMap()) { if (config["logger"]["file"] && config["logger"]["file"].IsScalar()) { fs::path tmp = config["logger"]["file"].as<std::string>(); log_config_.log_basename = tmp.filename().string(); log_config_.log_path = tmp.parent_path().string(); } // no throw... can be omitted if (config["logger"]["level"] && config["logger"]["level"].IsScalar()) { log_config_.log_level = config["logger"]["level"].as<std::string>(); } // no throw... can be omitted if (config["logger"]["max-size"] && config["logger"]["max-size"].IsScalar()) { log_config_.log_file_size = config["logger"]["max-size"].as<size_t>(); } // no throw... can be omitted if (config["logger"]["rotations"] && config["logger"]["rotations"].IsScalar()) { log_config_.log_files_count = config["logger"]["rotations"].as<size_t>(); } // no throw... can be omitted } // no throw... can be omitted // load limits if (config["limits"] && config["limits"].IsMap()) { auto limits = config["limits"]; if (limits["time"] && limits["time"].IsScalar()) { limits_.cpu_time = limits["time"].as<float>(); } // no throw... can be omitted if (limits["wall-time"] && limits["wall-time"].IsScalar()) { limits_.wall_time = limits["wall-time"].as<float>(); } // no throw... can be omitted if (limits["extra-time"] && limits["extra-time"].IsScalar()) { limits_.extra_time = limits["extra-time"].as<float>(); } // no throw... can be omitted if (limits["stack-size"] && limits["stack-size"].IsScalar()) { limits_.stack_size = limits["stack-size"].as<size_t>(); } // no throw... can be omitted if (limits["memory"] && limits["memory"].IsScalar()) { limits_.memory_usage = limits["memory"].as<size_t>(); } // no throw... can be omitted if (limits["parallel"] && limits["parallel"].IsScalar()) { limits_.processes = limits["parallel"].as<size_t>(); } // no throw... can be omitted if (limits["disk-size"] && limits["disk-size"].IsScalar()) { limits_.disk_size = limits["disk-size"].as<size_t>(); } // no throw... can be omitted if (limits["disk-files"] && limits["disk-files"].IsScalar()) { limits_.disk_files = limits["disk-files"].as<size_t>(); } // no throw... can be omitted try { limits_.bound_dirs = helpers::get_bind_dirs(limits); } catch (helpers::config_exception e) { throw config_error(e.what()); } if (limits["environ-variable"] && limits["environ-variable"].IsMap()) { for (const auto &var : limits["environ-variable"]) { limits_.environ_vars.push_back( std::make_pair(var.first.as<std::string>(), var.second.as<std::string>())); } } // no throw... can be omitted } else { throw config_error("Map of limits not defined properly"); } } catch (YAML::Exception &ex) { throw config_error("Default worker configuration was not loaded: " + std::string(ex.what())); } }
int main(int argc, char* argv[]) { config_fout = stdout; config_ferr = stderr; if (argc == 1) { help(argv[0]); return -1; } int mode_specified = 0, do_init = 0; char* configpath = NULL; FILE* configfile; int c; while (1) { static struct option long_options[] = { {"help", 0, NULL, 'h'}, {"verbose", 0, NULL, 'v'}, {"log", required_argument, NULL, 'l'}, {"init", 0, NULL, 'i'}, {"update", 0, NULL, 'u'}, {0,0,0,0} }; int option_index = 0; c = getopt_long(argc, argv, "hvl:iu", long_options, &option_index); if (c == -1) {//unknown arg (doesnt match -x/--x format) if (optind >= argc) { //at end of successful parse break; } //getopt refuses to continue, so handle infile manually: int i = optind; for (; i < argc; ++i) { configpath = argv[i]; //debug("%d %d %s", argc, i, arg); configfile = fopen(configpath,"r"); if (configfile == NULL) { config_error("Unable to open config file %s: %s", configpath, strerror(errno)); mini_help(argv[0]); return -1; } } break; } switch (c) { case 'h': help(argv[0]); return -1; case 'v': config_debug_enabled = 1; break; case 'l': { FILE* logfile = fopen(optarg, "a"); if (logfile == NULL) { config_error("Unable to open log file %s: %s", optarg, strerror(errno)); return -1; } config_fout = logfile; config_ferr = logfile; } break; case 'i': mode_specified = 1; do_init = 1; break; case 'u': mode_specified = 1; do_init = 0; break; default: mini_help(argv[0]); return -1; } } if (!mode_specified) { config_error("-i/-u mode argument required."); mini_help(argv[0]); } int error = -1; if (configpath == NULL) { configpath = "<stdin>"; configfile = stdin; } config_log("Parsing %s",configpath); //Get and parse bb_frames (both STRINGs and TEXTs) from config: struct bb_frame* startframe = NULL; if (parsefile(&startframe,configfile) < 0) { fclose(configfile); config_error("Error encountered when parsing config file. "); mini_help(argv[0]); goto end_noclose; } fclose(configfile); if (startframe == NULL) { config_error("Empty config file, nothing to do. "); mini_help(argv[0]); goto end_noclose; } usbsign_handle* devh = NULL; if (hardware_init(&devh) < 0) { config_error("USB init failed: Exiting. "); mini_help(argv[0]); goto end_noclose; } char* packet = NULL; int pktsize; config_log("Writing to sign"); //send sequence header before we start sending packets if (!hardware_seqstart(devh)) { //try resetting device once config_error("Initial write failed, attempting reset."); if (!hardware_reset(&devh)) { config_error("Reset failed: Exiting."); goto end; } if (!hardware_seqstart(devh)) { config_error("Initial write retry failed, giving up."); goto end; } config_log("Reset successful, continuing"); } if (do_init) { //this packet allocates sign memory for messages: if ((pktsize = packet_buildmemconf(&packet,startframe)) < 0) { goto end; } if (hardware_sendpkt(devh,packet,pktsize) != pktsize) { goto end; } free(packet); packet = NULL; } //now on to the real messages: struct bb_frame* curframe = startframe; while (curframe != NULL) { config_debug("result: data=%s",curframe->data); if (curframe->frame_type == STRING_FRAME_TYPE) { //data will be updated often, store in a STRING file pktsize = packet_buildstring(&packet,curframe->filename, curframe->data); } else if (curframe->frame_type == TEXT_FRAME_TYPE) { if (!do_init) { curframe = curframe->next; config_debug(" ^-- SKIPPING: init-only packet"); continue; } //data wont be updated often, use a TEXT file pktsize = packet_buildtext(&packet,curframe->filename, curframe->mode,curframe->mode_special, curframe->data); } else { config_error("Internal error: Unknown frame type %d",curframe->frame_type); goto end; } if (hardware_sendpkt(devh,packet,pktsize) != pktsize) { goto end; } free(packet); packet = NULL; curframe = curframe->next; } if (do_init) { //set display order for the messages: pktsize = packet_buildrunseq(&packet,startframe); if (hardware_sendpkt(devh,packet,pktsize) != pktsize) { goto end; } free(packet); packet = NULL; } //finish it off with a sequence footer if (!hardware_seqend(devh)) { goto end; } error = 0; end: hardware_close(devh); end_noclose: if (startframe != NULL) { packet_delete(startframe); free(startframe); } return error; }
datasource_ptr datasource_cache::create(const parameters& params) { boost::optional<std::string> type = params.get<std::string>("type"); if ( ! type) { throw config_error(std::string("Could not create datasource. Required ") + "parameter 'type' is missing"); } #ifdef MAPNIK_THREADSAFE mutex::scoped_lock lock(mutex_); #endif datasource_ptr ds; std::map<std::string,boost::shared_ptr<PluginInfo> >::iterator itr=plugins_.find(*type); if ( itr == plugins_.end() ) { std::string s("Could not create datasource for type: '"); s += *type + "'"; if (plugin_directories_.empty()) { s + " (no datasource plugin directories have been successfully registered)"; } else { s + " (searched for datasource plugins in '" + plugin_directories() + "')"; } throw config_error(s); } if ( ! itr->second->handle()) { throw std::runtime_error(std::string("Cannot load library: ") + lt_dlerror()); } // http://www.mr-edd.co.uk/blog/supressing_gcc_warnings #ifdef __GNUC__ __extension__ #endif create_ds* create_datasource = reinterpret_cast<create_ds*>(lt_dlsym(itr->second->handle(), "create")); if (! create_datasource) { throw std::runtime_error(std::string("Cannot load symbols: ") + lt_dlerror()); } #ifdef MAPNIK_LOG MAPNIK_LOG_DEBUG(datasource_cache) << "datasource_cache: Size=" << params.size(); parameters::const_iterator i = params.begin(); for (; i != params.end(); ++i) { MAPNIK_LOG_DEBUG(datasource_cache) << "datasource_cache: -- " << i->first << "=" << i->second; } #endif ds = datasource_ptr(create_datasource(params), datasource_deleter()); MAPNIK_LOG_DEBUG(datasource_cache) << "datasource_cache: Datasource=" << ds << " type=" << type; return ds; }
static void help(char* appname) { version(); config_error(""); config_error("Usage: %s <mode> [options] [configfile]", appname); config_error(""); config_error("Modes:"); config_error(" -i/--init:\tre-initialize the sign (required when configfile changes)"); config_error(" -u/--update:\tupdate the sign contents without init (smoother than --init)"); config_error(""); config_error("Options:"); config_error(" configfile:\tPath to a Config File (see syntax below)."); config_error(" \tIf configfile is unspecified, stdin will be used."); config_error(" -h/--help This help text."); config_error(" -v/--verbose Show verbose output."); config_error(" --log <file> Append any output to <file>."); config_error(""); config_error("Config File Syntax:"); config_error(" #comment"); config_error(" //comment"); config_error(" txt <mode> [text (optional if mode=nX)]"); config_error(" cmd <mode> <shell command>"); config_error(""); config_error("Available Mode Codes (spec pg89-90)"); config_error(" Note: Some \"nX\" modes don't work for \"cmd\" commands."); config_error(" Get around this by prefixing with an empty \"txt\" (ex: txt nx\\ncmd ...)"); config_error(" a rotate \tp rollin \tn8 welcome"); config_error(" b hold \tq rollout \tn9 sale"); config_error(" c flash \tr wipein \tna newsflash"); config_error(" e rollup \ts wipeout \tnb happy4th"); config_error(" f rolldn \tt comprotate \tnc cyclecolor"); config_error(" g rolleft \tn0 twinkle \tns thankyou"); config_error(" h rollright \tn1 sparkle \tnu nosmoking"); config_error(" i wipeup \tn2 snow \tnv dontdrink"); config_error(" j wipedn \tn3 interlock \tnw fish"); config_error(" k wipeleft \tn4 switch \tnx fireworks"); config_error(" l wiperight \tn5 cyclecolor \tny xmas"); config_error(" m scroll \tn6 spray \tnz smile"); config_error(" o automode \tn7 starburst"); config_error(""); config_error("Inline Text Format Syntax (spec pg81-82):"); config_error(" <left> -- Left-align the text in this frame."); config_error(" Only works in some frame modes (eg \"hold\")"); config_error(" <speedN> -- Set frame display speed. speed1 = slowest, speed6 = fastest."); config_error(" <br> -- Start of next display frame (allows multiple frames in one command)."); config_error(" <blink>,</blink> -- Enable/disable blinking text."); config_error(" Only works in some frame modes (eg \"hold\")."); config_error(" <small> -- Switch to a smaller font."); config_error(" <normal> -- Switch back to normal size."); config_error(" <wide>,</wide> -- Widen the text."); config_error(" <dblwide>,</dblwide> -- Widen the text more."); config_error(" <serif>,</serif> -- Switch to a serif font."); config_error(" <shadow>,</shadow> -- Apply a shadow to the text."); config_error(" <colorRGB> -- Change the text foreground color. R,G,B may each be any number between 0 and 3"); config_error(" Examples: <color303> for bright purple, <color101> for dim purple."); config_error(" <scolorRGB> -- Change the text shadow color (for text with <shadow> applied)."); config_error(" Uses same RGB codes as <colorRGB>."); config_error(""); config_error("Some Special Character Entities (pg84-87):"); config_error(" ↑ ↓ ← →"); config_error(" ¢ &gbp; ¥ €"); config_error(" &disk; &printer; ☎ &satdish;"); config_error(" &car; &boat; ♂ ♀"); config_error(" &heart; &pacman; &ball; ¬e;"); config_error(" &mug; &bottle; &handicap; ©"); config_error(" &rhino; &infinity;"); config_error(""); }
static void parse_listener_prefix(config_t *c, config_line_t *l, lwan_t *lwan) { lwan_url_map_t url_map = {0}; struct hash *hash = hash_str_new(free, free); lwan_handler_t *handler = NULL; void *callback = NULL; char *prefix = strdupa(l->line.value); void *data = NULL; while (config_read_line(c, l)) { switch (l->type) { case CONFIG_LINE_TYPE_LINE: if (!strcmp(l->line.key, "handler")) { handler = find_symbol(l->line.value); if (!handler) { config_error(c, "Could not find handler \"%s\"", l->line.value); goto out; } } else if (!strcmp(l->line.key, "callback")) { callback = find_symbol(l->line.value); if (!callback) { config_error(c, "Could not find callback \"%s\"", l->line.value); goto out; } } else { hash_add(hash, strdup(l->line.key), strdup(l->line.value)); } break; case CONFIG_LINE_TYPE_SECTION: if (!strcmp(l->section.name, "authorization")) { parse_listener_prefix_authorization(c, l, &url_map); } else { config_error(c, "Unknown section type: \"%s\"", l->section.name); goto out; } break; case CONFIG_LINE_TYPE_SECTION_END: goto add_map; } } config_error(c, "Expecting section end while parsing prefix"); goto out; add_map: if (handler == callback && !callback) { config_error(c, "Missing callback or handler"); goto out; } if (handler && callback) { config_error(c, "Callback and handler are mutually exclusive"); goto out; } if (callback) { url_map.callback = callback; url_map.flags |= HANDLER_PARSE_MASK; url_map.data = data; url_map.handler = NULL; } else if (handler && handler->init_from_hash && handler->handle) { url_map.data = handler->init_from_hash(hash); url_map.callback = handler->handle; url_map.flags |= handler->flags; url_map.handler = handler; } else { config_error(c, "Invalid handler"); goto out; } add_url_map(lwan->url_map_trie, prefix, &url_map); out: hash_free(hash); }