Beispiel #1
0
int parse_script(char *filename, script_ent_t * script) {
    cfg_t *pcfg;
    int i;

    memset(script, 0, sizeof(script_ent_t));

    printf("eins\n");
    pcfg = cfg_init(script_opts, CFGF_NONE);
    printf("zwei\n");
    if (cfg_parse(pcfg, filename) == CFG_PARSE_ERROR)
	return -1;

    strcpy(script->name, cfg_getstr(pcfg, "name"));	/* max 28 chars !!! */
    strcpy(script->org_name, cfg_getstr(pcfg, "org_name"));	/* max 64 chars !!! */
    strcpy(script->comment, cfg_getstr(pcfg, "comment"));	/* max 128 chars !!! */

    script->script_num = cfg_getint(pcfg, "id");
    script->version = cfg_getint(pcfg, "version");
    script->unused1 = cfg_getint(pcfg, "unused1");

    script->script_length = cfg_size(pcfg, "script");
    if (script->script_length & 1) {
	printf("WARNING: odd number of bytes in script ... truncating\n");
    }
    script->script_length >>= 1;
    for (i = 0; i < (script->script_length << 1); i++)
	script->script[i] = (uint8_t) cfg_getnint(pcfg, "script", i);

    cfg_free(pcfg);
    return 0;
}
Beispiel #2
0
glong config_getnint(const gchar *key, const guint idx)
{
	glong temp;

	config_mutex_lock ();
	temp = cfg_getnint (tc, key, idx);
	config_mutex_unlock ();

	return temp;
}
Beispiel #3
0
/**
 * @brief parses a downstream {} config entry from a server { } config.
 *
 * @param cfg
 *
 * @return
 */
downstream_cfg_t *
downstream_cfg_parse(cfg_t * cfg) {
    downstream_cfg_t * dscfg;

    assert(cfg != NULL);

    dscfg                        = downstream_cfg_new();
    assert(dscfg != NULL);

    dscfg->name                  = strdup(cfg_title(cfg));
    dscfg->enabled               = cfg_getbool(cfg, "enabled");
    dscfg->host                  = strdup(cfg_getstr(cfg, "addr"));
    dscfg->port                  = cfg_getint(cfg, "port");
    dscfg->n_connections         = cfg_getint(cfg, "connections");
    dscfg->high_watermark        = cfg_getint(cfg, "high-watermark");

    dscfg->read_timeout.tv_sec   = cfg_getnint(cfg, "read-timeout", 0);
    dscfg->read_timeout.tv_usec  = cfg_getnint(cfg, "read-timeout", 1);
    dscfg->write_timeout.tv_sec  = cfg_getnint(cfg, "write-timeout", 0);
    dscfg->write_timeout.tv_usec = cfg_getnint(cfg, "write-timeout", 1);
    dscfg->retry_ival.tv_sec     = cfg_getnint(cfg, "retry", 0);
    dscfg->retry_ival.tv_usec    = cfg_getnint(cfg, "retry", 1);

    if (dscfg->enabled == true) {
        _rusage.total_num_connections += dscfg->n_connections;
    }

    return dscfg;
}
Beispiel #4
0
int parse_device(char *filename, device_ent_t * device) {
    cfg_t *pcfg;
    int i;

    memset(device, 0, sizeof(device_ent_t));

    pcfg = cfg_init(device_opts, CFGF_NONE);
    if (cfg_parse(pcfg, filename) == CFG_PARSE_ERROR)
	return -1;

    strcpy(device->part_name, cfg_getstr(pcfg, "part_name"));
    device->family = get_family_by_name(cfg_getstr(pcfg, "family"));
    device->device_id = strtoul(cfg_getstr(pcfg, "device_id"), NULL, 16);
    device->program_mem = cfg_getint(pcfg, "program_mem");
    device->ee_mem = cfg_getint(pcfg, "ee_mem");
    device->ee_addr = cfg_getint(pcfg, "ee_addr");
    device->config_words = cfg_getint(pcfg, "config_words");
    device->config_addr = cfg_getint(pcfg, "config_addr");
    device->user_id_words = cfg_getint(pcfg, "user_id_words");
    device->user_id_addr = cfg_getint(pcfg, "user_id_addr");
    device->bandgap_mask = cfg_getint(pcfg, "bandgap_mask");

    if (cfg_size(pcfg, "config_masks") != 8)
	printf("WARNING : size of \"config_masks\" array is wrong! (%d)\n", cfg_size(pcfg, "config_masks"));
    for (i = 0; i < 8; i++)
	device->config_masks[i] = (uint16_t) cfg_getnint(pcfg, "config_masks", i);

    if (cfg_size(pcfg, "config_blank") != 8)
	printf("WARNING : size of \"config_blank\" array is wrong!\n");
    for (i = 0; i < 8; i++)
	device->config_blank[i] = (uint16_t) cfg_getnint(pcfg, "config_blank", i);

    device->cp_mask = cfg_getint(pcfg, "cp_mask");
    device->cp_config = cfg_getint(pcfg, "cp_config");
    device->osscal_save = cfg_getint(pcfg, "osscal_save");
    device->ignore_address = cfg_getint(pcfg, "ignore_address");
    device->vdd_min = cfg_getfloat(pcfg, "vdd_min");
    device->vdd_max = cfg_getfloat(pcfg, "vdd_max");
    device->vdd_erase = cfg_getfloat(pcfg, "vdd_erase");
    device->calibration_words = cfg_getint(pcfg, "calibration_words");
    device->chip_erase_script = get_script_by_name(cfg_getstr(pcfg, "chip_erase_script"));
    device->progmem_addr_set_script = get_script_by_name(cfg_getstr(pcfg, "progmem_addr_set_script"));
    device->progmem_addr_bytes = cfg_getint(pcfg, "progmem_addr_bytes");
    device->progmem_rd_script = get_script_by_name(cfg_getstr(pcfg, "progmem_rd_script"));
    device->progmem_rd_words = cfg_getint(pcfg, "progmem_rd_words");
    device->eerd_prep_script = get_script_by_name(cfg_getstr(pcfg, "eerd_prep_script"));
    device->eerd_script = get_script_by_name(cfg_getstr(pcfg, "eerd_script"));
    device->eerd_locations = cfg_getint(pcfg, "eerd_locations");
    device->user_id_rd_prep_script = get_script_by_name(cfg_getstr(pcfg, "user_id_rd_prep_script"));
    device->user_id_rd_script = get_script_by_name(cfg_getstr(pcfg, "user_id_rd_script"));
    device->config_rd_prep_script = get_script_by_name(cfg_getstr(pcfg, "config_rd_prep_script"));
    device->config_rd_script = get_script_by_name(cfg_getstr(pcfg, "config_rd_script"));
    device->progmem_wr_prep_script = get_script_by_name(cfg_getstr(pcfg, "progmem_wr_prep_script"));
    device->progmem_wr_script = get_script_by_name(cfg_getstr(pcfg, "progmem_wr_script"));
    device->progmem_wr_words = cfg_getint(pcfg, "progmem_wr_words");
    device->progmem_panel_bufs = cfg_getint(pcfg, "progmem_panel_bufs");
    device->progmem_panel_offset = cfg_getint(pcfg, "progmem_panel_offset");
    device->eewr_prep_script = get_script_by_name(cfg_getstr(pcfg, "eewr_prep_script"));
    device->eewr_script = get_script_by_name(cfg_getstr(pcfg, "eewr_script"));
    device->eewr_locations = cfg_getint(pcfg, "eewr_locations");
    device->user_id_wr_prep_script = get_script_by_name(cfg_getstr(pcfg, "user_id_wr_prep_script"));
    device->user_id_wr_script = get_script_by_name(cfg_getstr(pcfg, "user_id_wr_script"));
    device->config_wr_prep_script = get_script_by_name(cfg_getstr(pcfg, "config_wr_prep_script"));
    device->config_wr_script = get_script_by_name(cfg_getstr(pcfg, "config_wr_script"));
    device->osccal_rd_script = get_script_by_name(cfg_getstr(pcfg, "osccal_rd_script"));
    device->osccal_wr_script = get_script_by_name(cfg_getstr(pcfg, "osccal_wr_script"));
    device->dp_mask = cfg_getint(pcfg, "dp_mask");
    device->write_cfg_on_erase = cfg_getint(pcfg, "write_cfg_on_erase");
    device->blank_check_skip_usr_ids = cfg_getint(pcfg, "blank_check_skip_usr_ids");
    device->ignore_bytes = cfg_getint(pcfg, "ignore_bytes");
    device->chip_erase_prep_script = get_script_by_name(cfg_getstr(pcfg, "chip_erase_prep_script"));
    device->boot_flash = cfg_getint(pcfg, "boot_flash");
    device->config9_mask = cfg_getint(pcfg, "config9_mask");
    device->config9_blank = cfg_getint(pcfg, "config9_blank");
    device->progmem_erase_script = get_script_by_name(cfg_getstr(pcfg, "progmem_erase_script"));
    device->eemem_erase_script = get_script_by_name(cfg_getstr(pcfg, "eemem_erase_script"));
    device->configmem_erase_script = get_script_by_name(cfg_getstr(pcfg, "configmem_erase_script"));
    device->reserved1_erase_script = get_script_by_name(cfg_getstr(pcfg, "reserved1_erase_script"));
    device->reserved2_erase_script = get_script_by_name(cfg_getstr(pcfg, "reserved2_erase_script"));
    device->test_memory_rd_script = get_script_by_name(cfg_getstr(pcfg, "test_memory_rd_script"));
    device->test_memory_rd_words = cfg_getint(pcfg, "test_memory_rd_words");
    device->eerow_erase_script = get_script_by_name(cfg_getstr(pcfg, "eerow_erase_script"));
    device->eerow_erase_words = cfg_getint(pcfg, "eerow_erase_words");
    device->export_to_mplab = cfg_getint(pcfg, "export_to_mplab");
    device->debug_halt_script = get_script_by_name(cfg_getstr(pcfg, "debug_halt_script"));
    device->debug_run_script = get_script_by_name(cfg_getstr(pcfg, "debug_run_script"));
    device->debug_status_script = get_script_by_name(cfg_getstr(pcfg, "debug_status_script"));
    device->debug_read_exec_ver_script = get_script_by_name(cfg_getstr(pcfg, "debug_read_exec_ver_script"));
    device->debug_single_step_script = get_script_by_name(cfg_getstr(pcfg, "debug_single_step_script"));
    device->debug_bulk_wr_data_script = get_script_by_name(cfg_getstr(pcfg, "debug_bulk_wr_data_script"));
    device->debug_bulk_rd_data_script = get_script_by_name(cfg_getstr(pcfg, "debug_bulk_rd_data_script"));
    device->debug_write_vector_script = get_script_by_name(cfg_getstr(pcfg, "debug_write_vector_script"));
    device->debug_read_vector_script = get_script_by_name(cfg_getstr(pcfg, "debug_read_vector_script"));
    device->debug_row_erase_script = get_script_by_name(cfg_getstr(pcfg, "debug_row_erase_script"));
    device->debug_row_erase_size = cfg_getint(pcfg, "debug_row_erase_size");
    device->debug_reserved5_script = get_script_by_name(cfg_getstr(pcfg, "debug_reserved5_script"));
    device->debug_reserved6_script = get_script_by_name(cfg_getstr(pcfg, "debug_reserved6_script"));
    device->debug_reserved7_script = get_script_by_name(cfg_getstr(pcfg, "debug_reserved7_script"));
    device->debug_reserved8_script = get_script_by_name(cfg_getstr(pcfg, "debug_reserved8_script"));
    device->lvp_script = get_script_by_name(cfg_getstr(pcfg, "lvp_script"));

    cfg_free(pcfg);
    return 0;
}
int
configuration(struct app_parent *app_p,
              const char *configfile,
              char **policy_file,
              char **syslog_ident,
              int *syslog_flags,
              int *syslog_facility) {
    unsigned int i, j;
    struct tq_listener_s *p_listener = NULL;
    struct tq_service_s *p_service = NULL;
    char *buf = NULL;
    cfg_t *cfg;
    cfg_t *syslog_sec;
    unsigned n_listener, n_services;
    int ret;
    static cfg_opt_t syslog_opts[] = {
        CFG_STR("ident", NULL, CFGF_NONE),
        CFG_INT_CB("facility", NONE, CFGF_NONE, &cb_syslog_facility),
        CFG_INT_LIST_CB("options", NULL, CFGF_NONE, &cb_syslog_options),
        CFG_END()
    };
    static cfg_opt_t service_opts[] = {
        CFG_INT_CB("type", NONE, CFGF_NONE, &cb_service_type),
        CFG_STR("uri", 0, CFGF_NONE),
        CFG_INT("threads", 4, CFGF_NONE),
        CFG_END()
    };
    static cfg_opt_t listener_opts[] = {
        CFG_STR("bindaddress", 0, CFGF_NONE),
        CFG_INT("port", 9001, CFGF_NONE),
        CFG_INT("backlog", 1024, CFGF_NONE),
        CFG_STR("cert", 0, CFGF_NONE),
        CFG_STR("key", 0, CFGF_NONE),
        CFG_STR("cafile", 0, CFGF_NONE),
        CFG_STR("capath", 0, CFGF_NONE),
        CFG_STR("crlpath", 0, CFGF_NONE),
        CFG_STR("password", 0, CFGF_NONE),
        CFG_STR("cipherlist", 0, CFGF_NONE),
        CFG_INT_CB("clientauth", NONE, CFGF_NONE, &cb_answer),
        CFG_INT_CB("rfc3820", NONE, CFGF_NONE, &cb_answer),
        CFG_STR("whitelist", 0, CFGF_NONE),
        CFG_STR("blacklist", 0, CFGF_NONE),
        CFG_SEC("service", service_opts, CFGF_MULTI),
        CFG_END()
    };
    cfg_opt_t opts[] = {
        CFG_INT_CB("debug", NONE, CFGF_NONE, &cb_answer),
        CFG_STR("policyfile", 0, CFGF_NONE),
        CFG_SEC("syslog", syslog_opts, CFGF_NONE),
        CFG_SEC("listener", listener_opts, CFGF_MULTI),
        CFG_END()
    };

    cfg = cfg_init(opts, CFGF_NOCASE);

    /* set a validating callback function for bookmark sections */
    /* cfg_set_validate_func(cfg, "bookmark", &cb_validate_bookmark); */

    ret = cfg_parse(cfg, configfile);
    if (ret == CFG_FILE_ERROR) {
        fprintf(stderr, "Error: could not open or read the configuration file "
               "\"%s\".\n", configfile);
        return GA_BAD;
    } else if (ret == CFG_PARSE_ERROR) {
        fprintf(stderr, "Error: parse error in the configuration file "
               "\"%s\".\n", configfile);
        return GA_BAD;
    }

    /* Generic */
    app_p->debug = cfg_getint(cfg, "debug");
    if (app_p->debug == MAYBE || app_p->debug == OPTIONAL) {
        printf("Overriding debug setting to 'yes'\n");
        app_p->debug = YES;
    } else if (app_p->debug == YES) {
        printf("= Service running in DEBUG mode =\n");
    }

    /* XACML Rules file */
    *policy_file = strdup(cfg_getstr(cfg, "policyfile"));
    if (*policy_file == NULL) {
        fprintf(stderr, "Error: no \"policyfile\" set in the configuration file\n");
        return GA_BAD;
    } else {
        if (app_p->verbose) {
            printf("Using XACML Policy file: \"%s\"\n", *policy_file);
        }
    }

    /* Syslog */
    syslog_sec = cfg_getsec(cfg, "syslog");
    if (syslog_sec == NULL) {
        fprintf(stderr, "Error: no \"syslog\" section found in the "
                        "configuration file \"%s\"\n", configfile);
    } else {
        *syslog_ident = strdup(cfg_getstr(syslog_sec, "ident"));
        *syslog_facility = cfg_getint(syslog_sec, "facility");

        if (app_p->debug == YES) {
            printf("found syslog\n");
            printf("    ident = %s\n", cfg_getstr(syslog_sec, "ident"));
            printf("    facility = %ld\n", cfg_getint(syslog_sec, "facility"));
            printf("BUG\n");

            for (i = 0; i < cfg_size(syslog_sec, "options"); i++) {
                printf("options[%d] == %ld\n", i, cfg_getnint(syslog_sec, "options", i));
            }
            printf("BUG\n");
        }

        /* Hardwired the settings */
        *syslog_flags = LOG_PID|LOG_NDELAY;

        if (app_p->verbose > 1) {
            *syslog_flags |= LOG_PERROR;
        }
    }

    /* Listeners */
    n_listener = cfg_size(cfg, "listener");
    if (app_p->verbose) {
        printf("%d configured listeners:\n", n_listener);
    }
    for (i = 0; i < n_listener; i++) {
        cfg_t *ls = cfg_getnsec(cfg, "listener", i);
        if (ls == NULL) {
            goto cleanup;
        }

        p_listener = malloc(sizeof(struct tq_listener_s));
        if (p_listener == NULL) {
            fprintf(stderr, "Error: memory allocation problem, couldn't allocate %lu bytes\n",
                    sizeof(struct tq_listener_s));
            goto cleanup;
        }
        memset(p_listener, 0, sizeof(struct tq_listener_s));
        TAILQ_INIT(&(p_listener->services_head));

        /* Settings */
        STRDUP_OR_GOTO_CLEANUP(p_listener->bindip,          cfg_getstr(ls, "bindaddress"));
        p_listener->port                           = (short)cfg_getint(ls, "port");
        p_listener->backlog                        = (short)cfg_getint(ls, "backlog");
        STRDUP_OR_GOTO_CLEANUP(p_listener->cert,            cfg_getstr(ls, "cert"));
        STRDUP_OR_GOTO_CLEANUP(p_listener->key,             cfg_getstr(ls, "key"));
        STRDUP_OR_GOTO_CLEANUP(p_listener->cafile,          cfg_getstr(ls, "cafile"));
        STRDUP_OR_GOTO_CLEANUP(p_listener->capath,          cfg_getstr(ls, "capath"));
        STRDUP_OR_GOTO_CLEANUP(p_listener->crlpath,         cfg_getstr(ls, "crlpath"));
        STRDUP_OR_GOTO_CLEANUP(p_listener->cipherlist,      cfg_getstr(ls, "cipherlist") ?
                                                                cfg_getstr(ls, "cipherlist") :
                                                                "HIGH");
        STRDUP_OR_GOTO_CLEANUP(p_listener->cert_password,   cfg_getstr(ls, "password"));
        STRDUP_OR_GOTO_CLEANUP(p_listener->whitelist_path,  cfg_getstr(ls, "whitelist"));
        STRDUP_OR_GOTO_CLEANUP(p_listener->blacklist_path,  cfg_getstr(ls, "blacklist"));
        p_listener->clientauth                     = (short)cfg_getint(ls, "clientauth");
        p_listener->rfc3820                        = (short)cfg_getint(ls, "rfc3820");

        /* Normalizer */
        if (p_listener->clientauth == MAYBE)
            p_listener->clientauth = OPTIONAL;
        if (p_listener->rfc3820 == MAYBE || p_listener->rfc3820 == OPTIONAL)
            p_listener->rfc3820 = YES;

        /* Create evhtp_ssl_cfg_t */
        if (create_evhtp_ssl_cfg_from_tq_listener(p_listener) == GA_BAD) {
            goto cleanup;
        }


        /* Services per listener */
        n_services = cfg_size(ls, "service");
        if (app_p->verbose) {
            printf("      %d\n", n_services);
        }
        for (j = 0; j < n_services; j++) {
            cfg_t *serv = cfg_getnsec(ls, "service", j);
            if (serv == NULL) {
                goto cleanup;
            }

            p_service = malloc(sizeof(struct tq_service_s));
            if (p_service == NULL) {
                fprintf(stderr, "Error: memory allocation problem, couldn't allocate %lu bytes\n",
                        sizeof(struct tq_service_s));
                goto cleanup;
            }
            memset(p_service, 0, sizeof(struct tq_service_s));

            p_service->parent_listener = p_listener;

            /* Thread count override in Debug mode - max is 1 worker thread */
            if (app_p->debug == YES) {
                p_service->thread_cnt = 1;
            } else {
                p_service->thread_cnt = (short)cfg_getint(serv, "threads");
            }

            p_service->ltype = cfg_getint(serv, "type");
            p_service->uri = cfg_getstr(serv, "uri");
            if (p_service->uri && p_service->uri[0] == '/') {
                p_service->uri = strdup(p_service->uri);
            } else {
                buf = malloc(strlen(p_service->uri) + 2);
                if (buf == NULL) {
                    goto cleanup;
                }
                snprintf(buf, strlen(p_service->uri) + 2, "/%s", p_service->uri);
                p_service->uri = buf;
            }
            if (app_p->verbose) {
                printf("       uri = %s\n", p_service->uri);
                printf("       type = %s\n", p_service->ltype == PDP ? "PDP" : p_service->ltype == PAP ? "PAP" : p_service->ltype == PEP ? "PEP" : "unknown");
            }

            TAILQ_INSERT_TAIL(&(p_listener->services_head), p_service, next);
        }

        TAILQ_INSERT_TAIL(&(app_p->listener_head), p_listener, next);
    }

    cfg_free(cfg);
    return GA_GOOD;
cleanup:
    cfg_free(cfg);
    return GA_BAD;

}
Beispiel #6
0
DLLIMPORT signed long cfg_getint(cfg_t *cfg, const char *name)
{
    return cfg_getnint(cfg, name, 0);
}
Beispiel #7
0
//
// E_ProcessBossTypes
//
// Gets the thing type entries in the boss_spawner_types list,
// for use by the SpawnFly codepointer.
//
// modified by schepe to remove 11-type limit
//
static void E_ProcessBossTypes(cfg_t *cfg)
{
   int i, a = 0;
   int numTypes = cfg_size(cfg, SEC_BOSSTYPES);
   int numProbs = cfg_size(cfg, SEC_BOSSPROBS);
   bool useProbs = true;

   E_EDFLogPuts("\t* Processing boss spawn types\n");

   if(!numTypes)
   {
      // haleyjd 05/31/06: allow zero boss types
      E_EDFLogPuts("\t\tNo boss types defined\n");
      return;
   }

   // haleyjd 11/19/03: allow defaults for boss spawn probs
   if(!numProbs)
      useProbs = false;

   if(useProbs ? numTypes != numProbs : numTypes != 11)
   {
      E_EDFLoggedErr(2, 
         "E_ProcessBossTypes: %d boss types, %d boss probs\n",
         numTypes, useProbs ? numProbs : 11);
   }

   // haleyjd 11/21/11: allow multiple runs
   if(BossSpawnTypes)
   {
      efree(BossSpawnTypes);
      BossSpawnTypes = NULL;
   }
   if(BossSpawnProbs)
   {
      efree(BossSpawnProbs);
      BossSpawnProbs = NULL;
   }

   NumBossTypes = numTypes;
   BossSpawnTypes = ecalloc(int *, numTypes, sizeof(int));
   BossSpawnProbs = ecalloc(int *, numTypes, sizeof(int));

   // load boss spawn probabilities
   for(i = 0; i < numTypes; ++i)
   {
      if(useProbs)
      {
         a += cfg_getnint(cfg, SEC_BOSSPROBS, i);
         BossSpawnProbs[i] = a;
      }
      else
         BossSpawnProbs[i] = BossDefaults[i];
   }

   // check that the probabilities total 256
   if(useProbs && a != 256)
   {
      E_EDFLoggedErr(2, 
         "E_ProcessBossTypes: boss spawn probs do not total 256\n");
   }

   for(i = 0; i < numTypes; ++i)
   {
      const char *typeName = cfg_getnstr(cfg, SEC_BOSSTYPES, i);
      int typeNum = E_ThingNumForName(typeName);

      if(typeNum == -1)
      {
         E_EDFLoggedWarning(2, "Warning: invalid boss type '%s'\n", typeName);

         typeNum = UnknownThingType;
      }

      BossSpawnTypes[i] = typeNum;

      E_EDFLogPrintf("\t\tAssigned type %s(#%d) to boss type %d\n",
                     mobjinfo[typeNum]->name, typeNum, i);
   }
}
Beispiel #8
0
/**
 * @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 */
Beispiel #9
0
/**
 * @brief parses and creates a new ssl_cfg_t resource
 *
 * @param cfg the libconfuse structure for the ssl opts
 *
 * @return evhtp_ssl_cfg_t * on success, NULL on error.
 */
evhtp_ssl_cfg_t *
ssl_cfg_parse(cfg_t * cfg) {
    evhtp_ssl_cfg_t * scfg;
    long              ssl_opts        = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1;
    int               ssl_verify_mode = 0;
    int               proto_on_count;
    int               proto_off_count;
    int               i;
    struct stat       file_stat;

    if (cfg == NULL) {
        return NULL;
    }

    if (cfg_getbool(cfg, "enabled") == cfg_false) {
        return NULL;
    }

    if (!(scfg = ssl_cfg_new())) {
        return NULL;
    }

    if (cfg_getstr(cfg, "cert")) {
        scfg->pemfile = strdup(cfg_getstr(cfg, "cert"));
        if (stat(scfg->pemfile, &file_stat) != 0) {
            fprintf(stderr, "Cannot find SSL cert file '%s'\n", scfg->pemfile);
            exit(EXIT_FAILURE);
        }
    }

    if (cfg_getstr(cfg, "key")) {
        scfg->privfile = strdup(cfg_getstr(cfg, "key"));
        if (stat(scfg->privfile, &file_stat) != 0) {
            fprintf(stderr, "Cannot find SSL key file '%s'\n", scfg->privfile);
            exit(EXIT_FAILURE);
        }
    }

    if (cfg_getstr(cfg, "ca")) {
        scfg->cafile = strdup(cfg_getstr(cfg, "ca"));
        if (stat(scfg->cafile, &file_stat) != 0) {
            fprintf(stderr, "Cannot find SSL ca file '%s'\n", scfg->cafile);
            exit(EXIT_FAILURE);
        }
    }

    if (cfg_getstr(cfg, "capath")) {
        scfg->capath = strdup(cfg_getstr(cfg, "capath"));
        if (stat(scfg->capath, &file_stat) != 0) {
            fprintf(stderr, "Cannot find SSL capath file '%s'\n", scfg->capath);
            exit(EXIT_FAILURE);
        }
    }

    if (cfg_getstr(cfg, "ciphers")) {
        scfg->ciphers = strdup(cfg_getstr(cfg, "ciphers"));
    }

    if (cfg_getbool(cfg, "verify-peer") == cfg_true) {
        ssl_verify_mode |= SSL_VERIFY_PEER;
    }

    if (cfg_getbool(cfg, "enforce-peer-cert") == cfg_true) {
        ssl_verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
    }

    if (ssl_verify_mode != 0) {
        scfg->verify_peer        = ssl_verify_mode;
        scfg->verify_depth       = cfg_getint(cfg, "verify-depth");
        scfg->x509_verify_cb     = ssl_x509_verifyfn;
        scfg->x509_chk_issued_cb = NULL;
    }

    if (cfg_getbool(cfg, "cache-enabled") == cfg_true) {
        scfg->scache_type    = evhtp_ssl_scache_type_internal;
        scfg->scache_size    = cfg_getint(cfg, "cache-size");
        scfg->scache_timeout = cfg_getint(cfg, "cache-timeout");
    }

    proto_on_count  = cfg_size(cfg, "protocols-on");
    proto_off_count = cfg_size(cfg, "protocols-off");

    for (i = 0; i < proto_on_count; i++) {
        const char * proto_str = cfg_getnstr(cfg, "protocols-on", i);

        if (!strcasecmp(proto_str, "SSLv2")) {
            ssl_opts &= ~SSL_OP_NO_SSLv2;
        } else if (!strcasecmp(proto_str, "SSLv3")) {
            ssl_opts &= ~SSL_OP_NO_SSLv3;
        } else if (!strcasecmp(proto_str, "TLSv1")) {
            ssl_opts &= ~SSL_OP_NO_TLSv1;
        } else if (!strcasecmp(proto_str, "ALL")) {
            ssl_opts = 0;
        }
    }

    for (i = 0; i < proto_off_count; i++) {
        const char * proto_str = cfg_getnstr(cfg, "protocols-off", i);

        if (!strcasecmp(proto_str, "SSLv2")) {
            ssl_opts |= SSL_OP_NO_SSLv2;
        } else if (!strcasecmp(proto_str, "SSLv3")) {
            ssl_opts |= SSL_OP_NO_SSLv3;
        } else if (!strcasecmp(proto_str, "TLSv1")) {
            ssl_opts |= SSL_OP_NO_TLSv1;
        } else if (!strcasecmp(proto_str, "ALL")) {
            ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1;
        }
    }

    scfg->ssl_ctx_timeout = cfg_getint(cfg, "context-timeout");
    scfg->ssl_opts        = ssl_opts;

    if (cfg_getsec(cfg, "crl")) {
        ssl_crl_cfg_t * crl_config;
        cfg_t         * crl_cfg;

        crl_cfg = cfg_getsec(cfg, "crl");
        assert(crl_cfg != NULL);

        if (!(crl_config = calloc(sizeof(ssl_crl_cfg_t), 1))) {
            fprintf(stderr, "Could not allocate crl cfg %s\n", strerror(errno));
            exit(EXIT_FAILURE);
        }

        if (cfg_getstr(crl_cfg, "file")) {
            crl_config->filename = strdup(cfg_getstr(crl_cfg, "file"));

            if (stat(crl_config->filename, &file_stat) == -1 || !S_ISREG(file_stat.st_mode)) {
                fprintf(stderr, "Cannot find CRL file '%s'\n", crl_config->filename);
                exit(EXIT_FAILURE);
            }
        }

        if (cfg_getstr(crl_cfg, "dir")) {
            crl_config->dirname = strdup(cfg_getstr(crl_cfg, "dir"));

            if (stat(crl_config->dirname, &file_stat) != 0 || !S_ISDIR(file_stat.st_mode)) {
                fprintf(stderr, "Cannot find CRL directory '%s'\n", crl_config->dirname);
                exit(EXIT_FAILURE);
            }
        }

        crl_config->reload_timer.tv_sec  = cfg_getnint(crl_cfg, "reload", 0);
        crl_config->reload_timer.tv_usec = cfg_getnint(crl_cfg, "reload", 1);

        /* at the moment evhtp does not give us an area where we can store this
         * type of information without breaking the configuration structure. But
         * it does have an optional user-supplied arguments, which we use here
         * to store our CRL configuration.
         */
        scfg->args = (void *)crl_config;
    }

    return scfg;
} /* ssl_cfg_parse */
Beispiel #10
0
/**
 * @brief parses a server {} entry from a config.
 *
 * @param cfg
 *
 * @return
 */
server_cfg_t *
server_cfg_parse(cfg_t * cfg) {
    server_cfg_t * scfg;
    cfg_t        * log_cfg;
    int            i;
    int            res;

    assert(cfg != NULL);

    scfg                          = server_cfg_new();
    assert(scfg != NULL);

    scfg->bind_addr               = strdup(cfg_getstr(cfg, "addr"));
    scfg->bind_port               = cfg_getint(cfg, "port");
    scfg->ssl_cfg                 = ssl_cfg_parse(cfg_getsec(cfg, "ssl"));
    scfg->num_threads             = cfg_getint(cfg, "threads");
    scfg->listen_backlog          = cfg_getint(cfg, "backlog");
    scfg->max_pending             = cfg_getint(cfg, "max-pending");
    scfg->read_timeout.tv_sec     = cfg_getnint(cfg, "read-timeout", 0);
    scfg->read_timeout.tv_usec    = cfg_getnint(cfg, "read-timeout", 1);
    scfg->write_timeout.tv_sec    = cfg_getnint(cfg, "write-timeout", 0);
    scfg->write_timeout.tv_usec   = cfg_getnint(cfg, "write-timeout", 1);
    scfg->pending_timeout.tv_sec  = cfg_getnint(cfg, "pending-timeout", 0);
    scfg->pending_timeout.tv_usec = cfg_getnint(cfg, "pending-timeout", 1);
    scfg->high_watermark          = cfg_getint(cfg, "high-watermark");

    if (cfg_getbool(cfg, "disable-server-nagle") == cfg_true) {
        scfg->disable_server_nagle = 1;
    }

    if (cfg_getbool(cfg, "disable-client-nagle") == cfg_true) {
        scfg->disable_client_nagle = 1;
    }

    if (cfg_getbool(cfg, "disable-downstream-nagle") == cfg_true) {
        scfg->disable_downstream_nagle = 1;
    }

    if ((log_cfg = cfg_getsec(cfg, "logging"))) {
        scfg->req_log_cfg = logger_cfg_parse(cfg_getsec(log_cfg, "request"));
        scfg->err_log_cfg = logger_cfg_parse(cfg_getsec(log_cfg, "error"));
    }

    /* parse and insert all the configured downstreams */
    for (i = 0; i < cfg_size(cfg, "downstream"); i++) {
        lztq_elem        * elem;
        downstream_cfg_t * dscfg;

        dscfg = downstream_cfg_parse(cfg_getnsec(cfg, "downstream", i));
        assert(dscfg != NULL);

        elem  = lztq_append(scfg->downstreams, dscfg, sizeof(dscfg), downstream_cfg_free);
        assert(elem != NULL);
    }

    for (i = 0; i < cfg_size(cfg, "vhost"); i++) {
        lztq_elem   * elem;
        vhost_cfg_t * vcfg;

        vcfg = vhost_cfg_parse(cfg_getnsec(cfg, "vhost", i));
        assert(vcfg != NULL);

        elem = lztq_append(scfg->vhosts, vcfg, sizeof(vcfg), vhost_cfg_free);
        assert(elem != NULL);
    }

    _rusage.total_num_threads += scfg->num_threads;
    _rusage.total_max_pending += scfg->max_pending;

    return scfg;
} /* server_cfg_parse */
Beispiel #11
0
/**
 * Loads the routing data from the config file given in global
 * variable config_data and stores it in routing tree rd.
 *
 * @param rd Pointer to the route data tree where the routing data
 * shall be loaded into
 *
 * @return 0 means ok, -1 means an error occured
 *
 */
int load_config(struct rewrite_data * rd) {
	cfg_t * cfg = NULL;
	int n, m, o, i, j, k,l;
	cfg_t * d, * p, * t;
	const char * domain = NULL, * prefix = NULL;
	double prob;
	const char * rewrite_prefix = NULL, * rewrite_suffix = NULL,
	                              * rewrite_host = NULL, * comment = NULL;
	int backed_up_size = 0;
	int * backed_up = NULL;
	int backup = 0;
	int status, hash_index, max_targets, strip;

	if ((cfg = parse_config()) == NULL) {
		return -1;
	}

	if ((rd->carriers = shm_malloc(sizeof(struct carrier_tree *))) == NULL) {
		LM_ERR("out of shared memory\n");
		return -1;
	}
	memset(rd->carriers, 0, sizeof(struct carrier_tree *));

	rd->tree_num = 1;
	n = cfg_size(cfg, "domain");
	if (add_carrier_tree(default_tree, 1, rd, n) == NULL) {
		LM_ERR("couldn't add carrier tree\n");
		return -1;
	}

	memset(rd->carriers[0]->trees, 0, sizeof(struct route_tree *) * n);
	for (i = 0; i < n; i++) {
		d = cfg_getnsec(cfg, "domain", i);
		domain = cfg_title(d);
		m = cfg_size(d, "prefix");
		LM_INFO("loading domain %s\n", domain);
		for (j = 0; j < m; j++) {
			p = cfg_getnsec(d, "prefix", j);
			prefix = cfg_title(p);
			if (strcasecmp(prefix, SP_EMPTY_PREFIX) == 0) {
				prefix = NULL;
			}
			LM_INFO("loading prefix %s\n", prefix);
			max_targets = cfg_getint(p, "max_targets");
			o = cfg_size(p, "target");
			for (k = 0; k < o; k++) {
				t = cfg_getnsec(p, "target", k);
				rewrite_host = cfg_title(t);
				if (strcasecmp(rewrite_host, SP_EMPTY_PREFIX) == 0) {
					rewrite_host = 0;
				}
				LM_INFO("loading target %s\n", rewrite_host);
				prob = cfg_getfloat(t, "prob");
				strip = cfg_getint(t, "strip");
				rewrite_prefix = cfg_getstr(t, "rewrite_prefix");
				rewrite_suffix = cfg_getstr(t, "rewrite_suffix");
				hash_index = cfg_getint(t, "hash_index");
				comment = cfg_getstr(t, "comment");
				status = cfg_getint(t, "status");
				if ((backed_up_size = cfg_size(t, "backed_up")) > 0) {
					if ((backed_up = pkg_malloc(sizeof(int) * (backed_up_size + 1))) == NULL) {
						LM_ERR("out of private memory\n");
						return -1;
					}
					for (l = 0; l < backed_up_size; l++) {
						backed_up[l] = cfg_getnint(t, "backed_up", l);
					}
					backed_up[backed_up_size] = -1;
				}
				backup = cfg_getint(t, "backup");
				LM_INFO("adding route for prefix %s, to host %s, prob %f, backed up: %i, backup: %i\n",
				    prefix, rewrite_host, prob, backed_up_size, backup);
				if (add_route(rd, 1, domain, prefix, max_targets, prob, rewrite_host,
				              strip, rewrite_prefix, rewrite_suffix, status,
				              hash_index, backup, backed_up, comment) < 0) {
					LM_INFO("Error while adding route\n");
					if (backed_up) {
						pkg_free(backed_up);
					}
					return -1;
				}
				if (backed_up) {
					pkg_free(backed_up);
				}
				backed_up = NULL;
			}
		}

	}
	cfg_free(cfg);
	return 0;
}
Beispiel #12
0
settings *load_settings (const char *conffile)
{
	/* load settings from conffile */

	/* generic purpose counters */
	unsigned int i, j;

	/* declare and initialize the first event */
	event *event_first = calloc(1, sizeof(event));
	event_first->next = NULL;
	event *event_cur = event_first;

	settings *conf = calloc(1, sizeof(settings));

	cfg_opt_t ebk_event_opts[] =
	{
		CFG_INT_LIST("keys", "", CFGF_NONE),
		CFG_STR("action", "", CFGF_NONE),
		CFG_BOOL("onrelease", 0, CFGF_NONE),
		CFG_END()
	};

	cfg_opt_t ebk_opts[] =
	{
		CFG_BOOL("daemon", 1, CFGF_NONE),
		CFG_STR("dev", "", CFGF_NONE | CFGF_NODEFAULT),
		CFG_SEC("event", ebk_event_opts, CFGF_MULTI),
		CFG_END()
	};

	cfg_t *cfg, *cfg_section;

	cfg = cfg_init(ebk_opts, CFGF_NONE);

	if (cfg_parse(cfg, conffile) == CFG_PARSE_ERROR)
		exit(1);

	conf->dev = strdup(cfg_getstr(cfg, "dev"));

	if ( ! cfg_getbool(cfg, "daemon") )
		conf->opts |= EBK_NODAEMON;

	for (i=0; i < cfg_size(cfg, "event"); i++)
	{
		cfg_section = cfg_getnsec(cfg, "event", i);

		/* easy peasy, set the action */
		event_cur->action = strdup(cfg_getstr(cfg_section, "action"));

		/* set the bool that determines if the action should fire on press or release  */
		/* if it's absent the value will be set to cfg_false */
		event_cur->bindToReleaseEvent = cfg_getbool(cfg_section, "onrelease");

		/* set key_count */
		event_cur->key_count = cfg_size(cfg_section, "keys");

		/* set key array */
		event_cur->keys = calloc(sizeof(short), event_cur->key_count);
		for (j=0; j < event_cur->key_count; j++)
		{
			if ( cfg_getnint(cfg_section, "keys", j) == 0 )
			{
				fprintf(stderr, "%s: Invalid key name: %s\n", conffile, cfg_getnstr(cfg_section, "keys", j));
				exit(2);
			}
			event_cur->keys[j] =  cfg_getnint(cfg_section, "keys", j);
		}

		/* prep the next event list item */
		event_cur->next = calloc(1, sizeof(event));
		event_cur = event_cur->next;
		event_cur->next = NULL;
	}


    /*
	 //print the parsed values to another file
    {
        FILE *fp = fopen("/etc/ebindkeys.conf.out", "w");
        cfg_print(cfg, fp);
        fclose(fp);
    }
	*/

	cfg_free(cfg);

	conf->event_first = event_first;

	return(conf);
}
Beispiel #13
0
int main(int argc, char **argv)
{
    unsigned int i;
    cfg_t *cfg;
    unsigned n;
    int ret;
    cfg_opt_t proxy_opts[] = {
        CFG_INT("type", 0, CFGF_NONE),
        CFG_STR("host", 0, CFGF_NONE),
        CFG_STR_LIST("exclude", "{localhost, .localnet}", CFGF_NONE),
        CFG_INT("port", 21, CFGF_NONE),
        CFG_END()
    };
    cfg_opt_t bookmark_opts[] = {
        CFG_STR("machine", 0, CFGF_NONE),
        CFG_INT("port", 21, CFGF_NONE),
        CFG_STR("login", 0, CFGF_NONE),
        CFG_STR("password", 0, CFGF_NONE),
        CFG_STR("directory", 0, CFGF_NONE),
        CFG_BOOL("passive-mode", cfg_false, CFGF_NONE),
        CFG_SEC("proxy", proxy_opts, CFGF_NONE),
        CFG_END()
    };
    cfg_opt_t opts[] = {
        CFG_INT("backlog", 42, CFGF_NONE),
        CFG_STR("probe-device", "eth2", CFGF_NONE),
        CFG_SEC("bookmark", bookmark_opts, CFGF_MULTI | CFGF_TITLE),
        CFG_FLOAT_LIST("delays", "{3.567e2, 0.2, -47.11}", CFGF_NONE),
        CFG_FUNC("func", &cb_func),
        CFG_INT_CB("ask-quit", 3, CFGF_NONE, &cb_verify_ask),
        CFG_INT_LIST_CB("ask-quit-array", "{maybe, yes, no}",
                        CFGF_NONE, &cb_verify_ask),
        CFG_FUNC("include", &cfg_include),
        CFG_END()
    };

#ifndef _WIN32
    /* for some reason, MS Visual C++ chokes on this (?) */
    printf("Using %s\n\n", confuse_copyright);
#endif

    cfg = cfg_init(opts, CFGF_NOCASE);

    /* set a validating callback function for bookmark sections */
    cfg_set_validate_func(cfg, "bookmark", &cb_validate_bookmark);

    ret = cfg_parse(cfg, argc > 1 ? argv[1] : "test.conf");
    printf("ret == %d\n", ret);
    if(ret == CFG_FILE_ERROR) {
        perror("test.conf");
        return 1;
    } else if(ret == CFG_PARSE_ERROR) {
        fprintf(stderr, "parse error\n");
        return 2;
    }

    printf("backlog == %ld\n", cfg_getint(cfg, "backlog"));

    printf("probe device is %s\n", cfg_getstr(cfg, "probe-device"));
    cfg_setstr(cfg, "probe-device", "lo");
    printf("probe device is %s\n", cfg_getstr(cfg, "probe-device"));

    n = cfg_size(cfg, "bookmark");
    printf("%d configured bookmarks:\n", n);
    for(i = 0; i < n; i++) {
        cfg_t *pxy;
        cfg_t *bm = cfg_getnsec(cfg, "bookmark", i);
        printf("  bookmark #%u (%s):\n", i+1, cfg_title(bm));
        printf("    machine = %s\n", cfg_getstr(bm, "machine"));
        printf("    port = %d\n", (int)cfg_getint(bm, "port"));
        printf("    login = %s\n", cfg_getstr(bm, "login"));
        printf("    passive-mode = %s\n",
               cfg_getbool(bm, "passive-mode") ? "true" : "false");
        printf("    directory = %s\n", cfg_getstr(bm, "directory"));
        printf("    password = %s\n", cfg_getstr(bm, "password"));

        pxy = cfg_getsec(bm, "proxy");
        if(pxy) {
            int j, m;
            if(cfg_getstr(pxy, "host") == 0) {
                printf("      no proxy host is set, setting it to 'localhost'...\n");
                /* For sections without CFGF_MULTI flag set, there is
                 * also an extended syntax to get an option in a
                 * subsection:
                 */
                cfg_setstr(bm, "proxy|host", "localhost");
            }
            printf("      proxy host is %s\n", cfg_getstr(pxy, "host"));
            printf("      proxy type is %ld\n", cfg_getint(pxy, "type"));
            printf("      proxy port is %ld\n", cfg_getint(pxy, "port"));

            m = cfg_size(pxy, "exclude");
            printf("      got %d hosts to exclude from proxying:\n", m);
            for(j = 0; j < m; j++) {
                printf("        exclude %s\n", cfg_getnstr(pxy, "exclude", j));
            }
        } else
            printf("    no proxy settings configured\n");
    }

    printf("delays are (%d):\n", cfg_size(cfg, "delays"));
    for(i = 0; i < cfg_size(cfg, "delays"); i++)
        printf(" %G\n", cfg_getnfloat(cfg, "delays", i));

    printf("ask-quit == %ld\n", cfg_getint(cfg, "ask-quit"));

    /* Using cfg_setint(), the integer value for the option ask-quit
     * is not verified by the value parsing callback.
     *
     *
     cfg_setint(cfg, "ask-quit", 4);
     printf("ask-quit == %ld\n", cfg_getint(cfg, "ask-quit"));
    */

    /* The following commented line will generate a failed assertion
     * and abort, since the option "foo" is not declared
     *
     *
     printf("foo == %ld\n", cfg_getint(cfg, "foo"));
    */

    cfg_addlist(cfg, "ask-quit-array", 2, 1, 2);

    for(i = 0; i < cfg_size(cfg, "ask-quit-array"); i++)
        printf("ask-quit-array[%d] == %ld\n",
               i, cfg_getnint(cfg, "ask-quit-array", i));

    /* print the parsed values to another file */
    {
        FILE *fp = fopen("test.conf.out", "w");
        cfg_set_print_func(cfg, "func", print_func);
        cfg_set_print_func(cfg, "ask-quit", print_ask);
        cfg_set_print_func(cfg, "ask-quit-array", print_ask);
        cfg_print(cfg, fp);
        fclose(fp);
    }

    cfg_free(cfg);
    return 0;
}