2 * Sherlock Library -- Reading of configuration files
4 * (c) 2001 Robert Spalek <robert@ucw.cz>
5 * (c) 2003 Martin Mares <mj@ucw.cz>
7 * This software may be freely distributed and used according to the terms
8 * of the GNU Lesser General Public License.
12 #include "lib/chartype.h"
13 #include "lib/fastbuf.h"
14 #include "lib/pools.h"
28 static struct cfitem *cfsection;
29 struct mempool *cfpool;
31 byte *cfdeffile = DEFAULT_CONFIG;
33 static void CONSTRUCTOR
36 cfpool = mp_new(4096);
42 return mp_alloc(cfpool, size);
49 byte *k = cfg_malloc(l + 1);
54 void cf_register(struct cfitem *items)
56 if(items[0].type!=CT_SECTION && items[0].type!=CT_INCOMPLETE_SECTION)
57 die("cf_register: Invalid section type");
58 items[0].var=cfsection;
62 int cf_item_count(void)
64 struct cfitem *sect, *item;
66 for (sect = cfsection; sect; sect = sect->var)
67 for (item = sect+1; item->type; item++)
72 struct cfitem *cf_get_item(byte *sect, byte *name)
74 struct cfitem *item, *section;
77 while(item && strcasecmp(item->name,sect))
79 if(!item) /* unknown section */
83 for(item++; item->type && strcasecmp(item->name,name); item++);
84 if (!item->type && section->type == CT_INCOMPLETE_SECTION)
87 return item; /* item->type == 0 if not found */
91 uns name; /* One-letter name of the unit */
92 uns num, den; /* Fraction */
95 static const struct unit units[] = {
100 { 'g', 1000000000, 1 },
103 { 'G', 1073741824, 1 },
108 static const struct unit *cf_lookup_unit(byte *value, byte *end, char **msg)
111 if (end == value || end[1] || *end >= '0' && *end <= '9')
112 *msg = "Invalid number";
114 for (const struct unit *u=units; u->name; u++)
117 *msg = "Invalid unit";
123 static char cf_rngerr[] = "Number out of range";
125 byte *cf_parse_int(byte *value, uns *varp)
128 const struct unit *u;
131 msg = "Missing number";
135 uns x = strtoul(value, &end, 0);
138 else if (u = cf_lookup_unit(value, end, &msg)) {
139 u64 y = (u64)x * u->num;
141 msg = "Number is not an integer";
154 byte *cf_parse_u64(byte *value, u64 *varp)
157 const struct unit *u;
160 msg = "Missing number";
164 u64 x = strtoull(value, &end, 0);
167 else if (u = cf_lookup_unit(value, end, &msg)) {
168 if (x > ~(u64)0 / u->num)
169 msg = "Number out of range";
173 msg = "Number is not an integer";
183 byte *cf_parse_double(byte *value, double *varp)
186 const struct unit *u;
189 msg = "Missing number";
193 double x = strtoul(value, &end, 0);
196 else if (u = cf_lookup_unit(value, end, &msg))
197 *varp = x * u->num / u->den;
204 byte *cf_set_item(byte *sect, byte *name, byte *value)
210 return "Empty section name";
211 item=cf_get_item(sect,name);
212 if(!item) /* ignore unknown section */
217 msg = cf_parse_int(value, (uns *) item->var);
220 *((byte **) item->var) = cfg_stralloc(value);
223 msg = ((ci_func) item->var)(item, cfg_stralloc(value));
226 msg = cf_parse_double(value, (double *) item->var);
229 msg = cf_parse_u64(value, (u64 *) item->var);
232 msg = "Unknown keyword";
238 static int cf_subread(byte *filename,int level)
242 byte def_section[BUFFER];
246 if(level>=MAX_LEVEL){
247 log(L_ERROR,"Too many (%d) nested files when reading %s",level,filename);
251 fd=open(filename,O_RDONLY, 0666);
253 log(L_ERROR,"Cannot open configuration file %s: %m",filename);
264 if(!bgets(b,buf,BUFFER))
269 while(c>buf && Cspace(c[-1]))
272 while(*c && Cspace(*c))
278 strcpy(def_section,c+1);
279 c=strchr(def_section,']');
283 msg="Garbage after ]";
292 byte *sect,*name,*value;
295 while(*c && !Cspace(*c))
297 while(*c && Cspace(*c))
301 if(!strcasecmp(name,"include")){
302 if(!cf_subread(value,level+1)){
303 msg="Included from here";
316 msg=cf_set_item(sect,name,value);
322 } /* for every line */
325 log(L_ERROR,"%s, line %d: %s",filename,line,msg);
330 void cf_read(byte *filename)
332 if(!cf_subread(filename,0))
333 die("Reading config file %s failed",filename);
337 int cf_getopt(int argc,char * const argv[],
338 const char *shortopts,const struct option *longopts,
344 res=getopt_long(argc,argv,shortopts,longopts,longindex);
346 byte *sect,*name,*value;
353 msg="Missing argument";
370 msg=cf_set_item(sect,name,value);
373 die("Invalid command line argument %s.%s=%s: %s",sect,name,value,msg);
378 /* unhandled option or end of options */