+++ /dev/null
-/* Test for configuration parser */
-
-#include "lib/lib.h"
-#include "lib/conf.h"
-
-#include <stdio.h>
-#include <string.h>
-
-static u64 robert=14;
-static int spalek=-3;
-static char *heslo="prazdne";
-static int nastaveni1=0,nastaveni2=1;
-static double decker = 0; /* The famous London buses :-) */
-
-static byte *set_nastaveni(struct cfitem *item, byte *value)
-{
- int id;
- if(!strcasecmp(value,"one"))
- id=1;
- else if(!strcasecmp(value,"two"))
- id=2;
- else if(!strcasecmp(value,"three"))
- id=3;
- else if(!strcasecmp(value,"four"))
- id=4;
- else
- return "Invalid value of nastaveni";
- if(!strcasecmp(item->name,"nastaveni1"))
- nastaveni1=id;
- else if(!strcasecmp(item->name,"nastaveni2"))
- nastaveni2=id;
- else
- return "Internal error of nastaveni";
- return NULL;
-}
-
-static struct cfitem jmeno[]={
- {"jmeno", CT_SECTION, NULL},
- {"robert", CT_U64, &robert},
- {"spalek", CT_INT, &spalek},
- {"heslo", CT_STRING, &heslo},
- {"nastaveni1", CT_FUNCTION, &set_nastaveni},
- {"nastaveni2", CT_FUNCTION, &set_nastaveni},
- {"decker", CT_DOUBLE, &decker},
- {NULL, CT_STOP, NULL}
-};
-
-static int vek=22;
-static int vyska=178;
-static int vaha=66;
-
-static struct cfitem telo[]={
- {"telo", CT_SECTION, NULL},
- {"vek", CT_INT, &vek},
- {"vyska", CT_INT, &vyska},
- {"vaha", CT_INT, &vaha},
- {NULL, CT_STOP, NULL}
-};
-
-static byte shortopts[] = CF_SHORT_OPTS "abcp:q:r::";
-static struct option longopts[] =
-{
- CF_LONG_OPTS
- {"ahoj", 0, 0, 'a'},
- {"bida", 0, 0, 'b'},
- {"citron", 0, 0, 'c'},
- {"pivo", 1, 0, 'p'},
- {"qwerty", 1, 0, 'q'},
- {"rada", 2, 0, 'r'},
- {NULL, 0, 0, 0}
-};
-
-int main(int argc, char *argv[])
-{
- int c;
-
- log_init(argv[0]);
-
- cf_register(jmeno);
- cf_register(telo);
-
- while(1){
- c=cf_getopt(argc,argv,shortopts,longopts,NULL);
- if(c==-1)
- break;
- else switch(c){
- case 'a':
- case 'b':
- case 'c':
- printf("option %c\n",c);
- break;
-
- case 'p':
- case 'q':
- printf("option %c with parameter %s\n",c,optarg);
- break;
- case 'r':
- if(optarg)
- printf("option r with optional parameter %s\n",optarg);
- else
- printf("option r without optional parameter\n");
- break;
- case '?':
- //printf("invalid parameter %d: %s\n",optind,argv[optind]);
- break;
- case ':':
- //printf("missing parameter for %d: %s\n",optind,argv[optind]);
- break;
- default:
- printf("getopt is confused, it returns %c\n",c);
- break;
- }
- }
-
- if (optind < argc)
- {
- printf ("non-option ARGV-elements: ");
- while (optind < argc)
- printf ("%s ", argv[optind++]);
- printf ("\n");
- }
-
- printf("robert=%Ld, spalek=%d, heslo=%s, nastaveni1/2=%d/%d decker=%f\n",
- (long long)robert,spalek,heslo,nastaveni1,nastaveni2,decker);
- printf("vek=%d, vyska=%d, vaha=%d\n",
- vek,vyska,vaha);
-
- return 0;
-}
+++ /dev/null
-/*
- * UCW Library -- Reading of configuration files
- *
- * (c) 2001 Robert Spalek <robert@ucw.cz>
- * (c) 2003--2005 Martin Mares <mj@ucw.cz>
- *
- * This software may be freely distributed and used according to the terms
- * of the GNU Lesser General Public License.
- */
-
-#include "lib/lib.h"
-#include "lib/chartype.h"
-#include "lib/fastbuf.h"
-#include "lib/mempool.h"
-
-#include "lib/conf.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <errno.h>
-
-#define BUFFER 1024
-#define MAX_LEVEL 8
-
-static struct cfitem *cfsection;
-struct mempool *cfpool;
-
-#ifndef DEFAULT_CONFIG
-#define DEFAULT_CONFIG NULL
-#endif
-
-byte *cfdeffile = DEFAULT_CONFIG;
-
-static void CONSTRUCTOR
-conf_init(void)
-{
- cfpool = mp_new(4096);
-}
-
-void *
-cfg_malloc(uns size)
-{
- return mp_alloc(cfpool, size);
-}
-
-void *
-cfg_malloc_zero(uns size)
-{
- return mp_alloc_zero(cfpool, size);
-}
-
-byte *
-cfg_strdup(byte *s)
-{
- return mp_strdup(cfpool, s);
-}
-
-byte *
-cfg_printf(char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- byte *res = mp_vprintf(cfpool, fmt, args);
- va_end(args);
- return res;
-}
-
-void cf_register(struct cfitem *items)
-{
- if(items[0].type!=CT_SECTION && items[0].type!=CT_INCOMPLETE_SECTION)
- die("cf_register: Invalid section type");
- items[0].var=cfsection;
- cfsection=items;
-}
-
-int cf_item_count(void)
-{
- struct cfitem *sect, *item;
- int count = 0;
- for (sect = cfsection; sect; sect = sect->var)
- for (item = sect+1; item->type; item++)
- count++;
- return count;
-}
-
-struct cfitem *cf_get_item(byte *sect, byte *name)
-{
- struct cfitem *item, *section;
-
- item=cfsection;
- while(item && strcasecmp(item->name,sect))
- item=item->var;
- if(!item) /* unknown section */
- return NULL;
- section = item;
-
- for(item++; item->type && strcasecmp(item->name,name); item++);
- if (!item->type && section->type == CT_INCOMPLETE_SECTION)
- return NULL;
-
- return item; /* item->type == 0 if not found */
-}
-
-struct unit {
- uns name; /* One-letter name of the unit */
- uns num, den; /* Fraction */
-};
-
-static const struct unit units[] = {
- { 'd', 86400, 1 },
- { 'h', 3600, 1 },
- { 'k', 1000, 1 },
- { 'm', 1000000, 1 },
- { 'g', 1000000000, 1 },
- { 'K', 1024, 1 },
- { 'M', 1048576, 1 },
- { 'G', 1073741824, 1 },
- { '%', 1, 100 },
- { 0, 0, 0 }
-};
-
-#if 0
-static const struct unit *cf_lookup_unit(byte *value, byte *end, char **msg)
-{
- if (end && *end) {
- if (end == value || end[1] || *end >= '0' && *end <= '9')
- *msg = "Invalid number";
- else {
- for (const struct unit *u=units; u->name; u++)
- if (u->name == *end)
- return u;
- *msg = "Invalid unit";
- }
- }
- return NULL;
-}
-
-static char cf_rngerr[] = "Number out of range";
-
-byte *cf_parse_int(byte *value, uns *varp)
-{
- char *msg = NULL;
- const struct unit *u;
-
- if (!*value)
- msg = "Missing number";
- else {
- errno = 0;
- char *end;
- uns x = strtoul(value, &end, 0);
- if (errno == ERANGE)
- msg = cf_rngerr;
- else if (u = cf_lookup_unit(value, end, &msg)) {
- u64 y = (u64)x * u->num;
- if (y % u->den)
- msg = "Number is not an integer";
- else {
- y /= u->den;
- if (y > 0xffffffff)
- msg = cf_rngerr;
- *varp = y;
- }
- } else
- *varp = x;
- }
- return msg;
-}
-
-byte *cf_parse_u64(byte *value, u64 *varp)
-{
- char *msg = NULL;
- const struct unit *u;
-
- if (!*value)
- msg = "Missing number";
- else {
- errno = 0;
- char *end;
- u64 x = strtoull(value, &end, 0);
- if (errno == ERANGE)
- msg = cf_rngerr;
- else if (u = cf_lookup_unit(value, end, &msg)) {
- if (x > ~(u64)0 / u->num)
- msg = "Number out of range";
- else {
- x *= u->num;
- if (x % u->den)
- msg = "Number is not an integer";
- else
- *varp = x / u->den;
- }
- } else
- *varp = x;
- }
- return msg;
-}
-
-byte *cf_parse_double(byte *value, double *varp)
-{
- char *msg = NULL;
- const struct unit *u;
-
- if (!*value)
- msg = "Missing number";
- else {
- errno = 0;
- char *end;
- double x = strtoul(value, &end, 0);
- if (errno == ERANGE)
- msg = cf_rngerr;
- else if (u = cf_lookup_unit(value, end, &msg))
- *varp = x * u->num / u->den;
- else
- *varp = x;
- }
- return msg;
-}
-
-byte *
-cf_parse_ip(byte **p, u32 *varp)
-{
- while (Cspace(**p))
- (*p)++;
- if (!**p)
- return "Missing IP address";
- uns x = 0;
- if (**p == '0' && *(*p + 1) | 32 == 'X')
- {
- errno = 0;
- x = strtoul(*p + 2, (char **)p, 16);
- if (errno == ERANGE || x > 0xffffffff)
- goto error;
- }
- else
- for (uns i = 0; i < 4; i++)
- {
- if (i)
- {
- while (Cspace(**p))
- (*p)++;
- if (*(*p)++ != '.')
- goto error;
- }
- while (Cspace(**p))
- (*p)++;
- errno = 0;
- uns y = strtoul(*p, (char **)p, 10);
- if (errno == ERANGE || y > 255)
- goto error;
- x = (x << 8) + y;
- }
- *varp = x;
- return NULL;
-error:
- return "Invalid IP address";
-}
-#endif
-
-byte *cf_set_item(byte *sect, byte *name, byte *value)
-{
- struct cfitem *item;
- byte *msg=NULL;
-
- if (!*sect)
- return "Empty section name";
- item=cf_get_item(sect,name);
- if(!item) /* ignore unknown section */
- return NULL;
-
- switch(item->type){
- case CT_INT:
- msg = cf_parse_int(value, (uns *) item->var);
- break;
- case CT_STRING:
- *((byte **) item->var) = cfg_strdup(value);
- break;
- case CT_FUNCTION:
- msg = ((ci_func) item->var)(item, cfg_strdup(value));
- break;
- case CT_DOUBLE:
- msg = cf_parse_double(value, (double *) item->var);
- break;
- case CT_U64:
- msg = cf_parse_u64(value, (u64 *) item->var);
- break;
- default:
- msg = "Unknown keyword";
- }
-
- return msg;
-}
-
-static int cf_subread(byte *filename,int level)
-{
- int fd;
- struct fastbuf *b;
- byte def_section[BUFFER];
- int line;
- byte *msg=NULL;
-
- if(level>=MAX_LEVEL){
- log(L_ERROR,"Too many (%d) nested files when reading %s",level,filename);
- return 0;
- }
-
- fd=open(filename,O_RDONLY, 0666);
- if(fd<0){
- log(L_ERROR,"Cannot open configuration file %s: %m",filename);
- return 0;
- }
- b=bfdopen(fd,4096);
-
- def_section[0]=0;
- line=0;
- while(1){
- byte buf[BUFFER];
- byte *c;
-
- if(!bgets(b,buf,BUFFER))
- break;
- line++;
-
- c=buf+strlen(buf);
- while(c>buf && Cspace(c[-1]))
- *--c=0;
- c=buf;
- while(*c && Cspace(*c))
- c++;
- if(!*c || *c=='#')
- continue;
-
- if(*c=='['){
- strcpy(def_section,c+1);
- c=strchr(def_section,']');
- if(c){
- *c=0;
- if(c[1]){
- msg="Garbage after ]";
- break;
- }
- }else{
- msg="Missing ]";
- break;
- }
-
- }else{
- byte *sect,*name,*value;
-
- name=c;
- while(*c && !Cspace(*c))
- c++;
- while(*c && Cspace(*c))
- *c++=0;
- value=c;
-
- if(!strcasecmp(name,"include")){
- if(!cf_subread(value,level+1)){
- msg="Included from here";
- break;
- }
- }else{
- c=strchr(name,'.');
- if(!c)
- sect=def_section;
- else{
- sect=name;
- *c++=0;
- name=c;
- }
-
- msg=cf_set_item(sect,name,value);
- }
- if(msg)
- break;
- }
-
- } /* for every line */
-
- if(msg)
- log(L_ERROR,"%s, line %d: %s",filename,line,msg);
- bclose(b);
- return !msg;
-}
-
-void cf_read(byte *filename)
-{
- if(!cf_subread(filename,0))
- die("Reading config file %s failed",filename);
- cfdeffile = NULL;
-}
-
-static void cf_opt_S(void)
-{
- byte *sect,*name,*value;
- byte *c;
- byte *msg=NULL;
- byte arg[strlen(optarg)+1];
-
- strcpy(arg, optarg);
- name = arg;
- c=strchr(name,'=');
- if(!c){
- msg="Missing argument";
- sect=value="";
- }else{
- *c++=0;
- value=c;
-
- c=strchr(name,'.');
- if(!c)
- sect="";
- else{
- sect=name;
- *c++=0;
- name=c;
- }
-
- if (cfdeffile)
- cf_read(cfdeffile);
- msg=cf_set_item(sect,name,value);
- }
- if(msg)
- die("Invalid command line argument -S%s.%s=%s: %s",sect,name,value,msg);
-
-}
-
-int cf_getopt(int argc,char * const argv[],
- const char *shortopts,const struct option *longopts,
- int *longindex)
-{
- int res;
- static int other_options;
-
- do{
- res=getopt_long(argc,argv,shortopts,longopts,longindex);
- if(res == 'S' || res == 'C') {
- if(other_options)
- die("The -S and -C options must precede all other arguments");
- }
- if(res=='S'){
- cf_opt_S();
- }else if(res=='C'){
- cf_read(optarg);
- }else{
- /* unhandled option or end of options */
- if(cfdeffile)
- cf_read(cfdeffile);
- other_options++;
- return res;
- }
- }while(1);
-}
+++ /dev/null
-/*
- * UCW Library -- Reading of configuration files
- *
- * (c) 2001 Robert Spalek <robert@ucw.cz>
- * (c) 2003--2005 Martin Mares <mj@ucw.cz>
- *
- * This software may be freely distributed and used according to the terms
- * of the GNU Lesser General Public License.
- */
-
-#ifndef _LIB_CONF_H
-#define _LIB_CONF_H
-
-#include <getopt.h>
-
-/*
- * Allocation in configuration memory pool.
- */
-
-extern struct mempool *cfpool;
-void *cfg_malloc(uns size);
-void *cfg_malloc_zero(uns size);
-byte *cfg_strdup(byte *s);
-byte *cfg_printf(char *fmt, ...) FORMAT_CHECK(printf,1,2);
-
-/*
- * Every module places its configuration setting into some section. Section is
- * an array of cfitem, whose first record is of type CT_SECTION and contains
- * the name of the section. The configuration sections are registered by
- * calling cf_register().
- *
- * CT_INCOMPLETE_SECTION is identical to CT_SECTION, but when an unknown variable
- * is spotted, we ignore it instead of bailing out with an error message.
- *
- * item->var is a pointer to the destination variable or to the special parsing
- * function.
- */
-
-enum cftype { CT_STOP, CT_SECTION, CT_INCOMPLETE_SECTION, CT_INT, CT_STRING, CT_FUNCTION, CT_DOUBLE, CT_U64 };
-
-struct cfitem {
- byte *name;
- enum cftype type;
- void *var;
-};
-
-typedef byte *(*ci_func)(struct cfitem *, byte *);
-
-void cf_register(struct cfitem *items);
-
-/*
- * Direct setting of configuration items and parsing the configuration file.
- */
-
-int cf_item_count(void);
-struct cfitem *cf_get_item(byte *sect, byte *name);
-byte *cf_set_item(byte *sect, byte *name, byte *value);
-void cf_read(byte *filename);
-
-/*
- * Number parsing functions which could be useful in CT_FUNCTION callbacks.
- */
-
-#if 0
-byte *cf_parse_int(byte *value, uns *varp);
-byte *cf_parse_u64(byte *value, u64 *varp);
-byte *cf_parse_double(byte *value, double *varp);
-
-/*
- * Some useful parsing functions.
- */
-
-byte *cf_parse_ip(byte **value, u32 *varp);
-#endif
-
-/*
- * When using cf_getopt, you must prefix your own short/long options by the
- * CF_(SHORT|LONG)_OPTS.
- *
- * cfdeffile contains filename of config file automatically loaded before a
- * first --set option is executed. If none --set option occures, it will be
- * loaded after getopt returns -1 (at the end of configuration options). It
- * will be ignored, if another config file is set by --config option at first.
- * Its initial value is DEFAULT_CONFIG from config.h, but you can override it
- * manually.
- */
-
-#define CF_SHORT_OPTS "S:C:"
-#define CF_LONG_OPTS \
- {"set", 1, 0, 'S'},\
- {"config", 1, 0, 'C'},
-#define CF_NO_LONG_OPTS (const struct option []){ CF_LONG_OPTS { NULL, 0, 0, 0 } }
-#define CF_USAGE_TAB ""
-#define CF_USAGE \
-"-S, --set sec.item=val\t" CF_USAGE_TAB "Manual setting of a configuration item\n\
--C, --config filename\t" CF_USAGE_TAB "Overwrite default config filename\n"
-
-extern byte *cfdeffile;
-
-int cf_getopt(int argc,char * const argv[],
- const char *shortopts,const struct option *longopts,
- int *longindex);
-
-#endif