]> mj.ucw.cz Git - libucw.git/blob - lib/conf.c
Renamed memory pool functions to "mp_*", so they don't clobber name space.
[libucw.git] / lib / conf.c
1 /*
2  *      Sherlock Library -- Reading configuration files
3  *
4  *      (c) 2001 Robert Spalek <robert@ucw.cz>
5  */
6
7 #include "lib/lib.h"
8
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <fcntl.h>
13 #include <getopt.h>
14
15 #include "lib/chartype.h"
16 #include "lib/fastbuf.h"
17 #include "lib/lfs.h"
18
19 #include "lib/conf.h"
20
21 #define BUFFER          1024
22 #define MAX_LEVEL       8
23
24 static struct cfitem *cfsection;
25
26 void cf_register(struct cfitem *items)
27 {
28         if(items[0].type!=CT_SECTION)
29                 die("Invalid configuration section, first item must be of type CT_SECTION");
30         items[0].var=cfsection;
31         cfsection=items;
32 }
33
34 byte *cf_set_item(byte *sect, byte *name, byte *value)
35 {
36         struct cfitem *item;
37         byte *msg=NULL;
38
39         item=cfsection;
40         while(item && strcasecmp(item->name,sect))
41                 item=item->var;
42         if(!item)       /* ignore unknown section */
43                 return NULL;
44
45         for(item++; item->type && strcasecmp(item->name,name); item++);
46
47         switch(item->type){
48                 case CT_INT:
49                         {
50                                 char *end;
51                                 *((uns *) item->var) = strtoul(value, &end, 0);
52                                 if (end && *end)
53                                         msg = "Invalid number";
54                                 break;
55                         }
56                 case CT_STRING:
57                         *((byte **) item->var) = stralloc(value);
58                         break;
59                 case CT_FUNCTION:
60                         msg = ((ci_func) item->var)(item, value);
61                         break;
62                 default:
63                         msg = "Unknown keyword";
64                         break;
65         }
66
67         return msg;
68 }
69
70 static int cf_subread(byte *filename,int level)
71 {
72         int fd;
73         struct fastbuf *b;
74         byte def_section[BUFFER];
75         int line;
76         byte *msg=NULL;
77
78         if(level>=MAX_LEVEL){
79                 log(L_ERROR,"Too many (%d) nested files when reading %s",level,filename);
80                 return 0;
81         }
82                 
83         fd=sh_open(filename,O_RDONLY, 0666);
84         if(fd<0){
85                 log(L_ERROR,"Cannot open configuration file %s: %m",filename);
86                 return 0;
87         }
88         b=bfdopen(fd,4096);
89
90         def_section[0]=0;
91         line=0;
92         while(1){
93                 byte buf[BUFFER];
94                 byte *c;
95
96                 if(!bgets(b,buf,BUFFER))
97                         break;
98                 line++;
99
100                 c=buf;
101                 while(*c && Cspace(*c))
102                         c++;
103                 if(!*c || *c=='#')
104                         continue;
105
106                 if(*c=='['){
107                         strcpy(def_section,c+1);
108                         c=strchr(def_section,']');
109                         if(c)
110                                 *c=0;
111                         else{
112                                 msg="Missing ]";
113                                 break;
114                         }
115
116                 }else if(*c=='<'){
117                         if(!cf_subread(c+1,level+1)){
118                                 msg="";
119                                 break;
120                         }
121                 
122                 }else{
123                         byte *sect,*name,*value;
124
125                         name=c;
126                         c=strpbrk(c," \t");
127                         while(c && *c && Cspace(*c))
128                                 *c++=0;
129                         if(!c || !*c){
130                                 msg="Missing argument";
131                                 break;
132                         }
133                         value=c;
134
135                         c=strchr(name,'.');
136                         if(!c)
137                                 sect=def_section;
138                         else{
139                                 sect=name;
140                                 *c++=0;
141                                 name=c;
142                         }
143
144                         msg=cf_set_item(sect,name,value);
145                         if(msg)
146                                 break;
147                 }
148
149         }       /* for every line */
150
151         if(msg)
152                 log(L_ERROR,"%s, line %d: %s",filename,line,msg);
153         bclose(b);
154         return !msg;
155 }
156
157 void cf_read(byte *filename)
158 {
159         if(!cf_subread(filename,0))
160                 die("Reading config file %s failed",filename);
161 }
162
163 int cf_getopt(int argc,char * const argv[],
164                 const char *shortopts,const struct option *longopts,
165                 int *longindex)
166 {
167         int res;
168
169         do{
170                 res=getopt_long(argc,argv,shortopts,longopts,longindex);
171                 if(res=='S'){
172                         byte *sect,*name,*value;
173                         byte *c;
174                         byte *msg=NULL;
175
176                         name=optarg;
177                         c=strchr(name,'=');
178                         if(!c){
179                                 msg="Missing argument";
180                                 sect=value="";
181                         }else{
182                                 *c++=0;
183                                 value=c;
184
185                                 c=strchr(name,'.');
186                                 if(!c)
187                                         sect="";
188                                 else{
189                                         sect=name;
190                                         *c++=0;
191                                         name=c;
192                                 }
193
194                                 msg=cf_set_item(sect,name,value);
195                         }
196                         if(msg)
197                                 die("Invalid command line argument %s.%s=%s: %s",sect,name,value,msg);
198
199                 }else if(res=='C'){
200                         cf_read(optarg);
201                 }else{  /* unhandled option */
202                         return res;
203                 }
204         }while(1);
205 }
206