-rw-r--r-- | lib/configuration.cc | 474 |
1 files changed, 474 insertions, 0 deletions
diff --git a/lib/configuration.cc b/lib/configuration.cc new file mode 100644 index 0000000..4ee1526 --- a/dev/null +++ b/lib/configuration.cc | |||
@@ -0,0 +1,474 @@ | |||
1 | #ifdef USE_PCH | ||
2 | #include "pch.h" | ||
3 | #else | ||
4 | #include <unistd.h> | ||
5 | #include <fnmatch.h> | ||
6 | #include <cassert> | ||
7 | #include <stdexcept> | ||
8 | using namespace std; | ||
9 | #include <dotconf.h> | ||
10 | #include "sitecing/configuration.h" | ||
11 | #include "sitecing/sitecing_util.h" | ||
12 | #include "sitecing/scoreboard.h" | ||
13 | #endif | ||
14 | |||
15 | namespace sitecing { | ||
16 | |||
17 | configuration::configuration() | ||
18 | : flags(0), autobuild(false) { } | ||
19 | configuration::configuration(const string& cfile,bool ab) | ||
20 | : flags(0), autobuild(ab) { | ||
21 | parse(cfile); | ||
22 | } | ||
23 | |||
24 | enum dc_ctx { | ||
25 | DCC_ROOT = 1, | ||
26 | DCC_PATH = 2, | ||
27 | DCC_SCRC = 4 | ||
28 | }; | ||
29 | struct dc_context { | ||
30 | dc_ctx ctx; | ||
31 | configuration* cf; | ||
32 | list<config_options*> co; | ||
33 | }; | ||
34 | |||
35 | static DOTCONF_CB(dco_root_source) { dc_context *dcc = (dc_context*)ctx; | ||
36 | dcc->cf->root_source = cmd->data.str; | ||
37 | dcc->cf->flags |= configuration::flag_root_source; | ||
38 | return NULL; | ||
39 | } | ||
40 | static DOTCONF_CB(dco_root_intermediate) { dc_context *dcc = (dc_context*)ctx; | ||
41 | dcc->cf->root_intermediate = cmd->data.str; | ||
42 | dcc->cf->flags |= configuration::flag_root_intermediate; | ||
43 | return NULL; | ||
44 | } | ||
45 | static DOTCONF_CB(dco_root_so) { dc_context *dcc = (dc_context*)ctx; | ||
46 | dcc->cf->root_so = cmd->data.str; | ||
47 | dcc->cf->flags |= configuration::flag_root_so; | ||
48 | return NULL; | ||
49 | } | ||
50 | static DOTCONF_CB(dco_listen_socket) { dc_context *dcc = (dc_context*)ctx; | ||
51 | dcc->cf->listen_socket = cmd->data.str; | ||
52 | dcc->cf->flags |= configuration::flag_listen_socket; | ||
53 | return NULL; | ||
54 | } | ||
55 | static DOTCONF_CB(dco_rc_file_name) { dc_context *dcc = (dc_context*)ctx; | ||
56 | dcc->cf->rc_file_name = cmd->data.str; | ||
57 | dcc->cf->flags |= configuration::flag_rc_file_name; | ||
58 | return NULL; | ||
59 | } | ||
60 | static DOTCONF_CB(dco_min_children) { dc_context *dcc = (dc_context*)ctx; | ||
61 | if(cmd->data.value>=MAX_SITECING_SCOREBOARD_SLOTS) | ||
62 | return "MinChildren is too big"; | ||
63 | dcc->cf->min_children = cmd->data.value; | ||
64 | dcc->cf->flags |= configuration::flag_min_children; | ||
65 | return NULL; | ||
66 | } | ||
67 | static DOTCONF_CB(dco_max_children) { dc_context *dcc = (dc_context*)ctx; | ||
68 | if(cmd->data.value>=MAX_SITECING_SCOREBOARD_SLOTS) | ||
69 | return "MaxChildren is too big"; | ||
70 | dcc->cf->max_children = cmd->data.value; | ||
71 | dcc->cf->flags |= configuration::flag_max_children; | ||
72 | return NULL; | ||
73 | } | ||
74 | static DOTCONF_CB(dco_min_spare_children) { dc_context *dcc = (dc_context*)ctx; | ||
75 | if(cmd->data.value>=MAX_SITECING_SCOREBOARD_SLOTS) | ||
76 | return "MinSpareChildren is too big"; | ||
77 | dcc->cf->min_spare_children = cmd->data.value; | ||
78 | dcc->cf->flags |= configuration::flag_min_spare_children; | ||
79 | return NULL; | ||
80 | } | ||
81 | static DOTCONF_CB(dco_max_spare_children) { dc_context *dcc = (dc_context*)ctx; | ||
82 | if(cmd->data.value>=MAX_SITECING_SCOREBOARD_SLOTS) | ||
83 | return "MaxSpareChildren is too big"; | ||
84 | dcc->cf->max_spare_children = cmd->data.value; | ||
85 | dcc->cf->flags |= configuration::flag_max_spare_children; | ||
86 | return NULL; | ||
87 | } | ||
88 | static DOTCONF_CB(dco_requests_per_child) { dc_context *dcc = (dc_context*)ctx; | ||
89 | dcc->cf->requests_per_child = cmd->data.value; | ||
90 | dcc->cf->flags |= configuration::flag_requests_per_child; | ||
91 | return NULL; | ||
92 | } | ||
93 | static DOTCONF_CB(dco_multi_process) { dc_context *dcc = (dc_context*)ctx; | ||
94 | dcc->cf->multi_process = cmd->data.value; | ||
95 | dcc->cf->flags |= configuration::flag_multi_process; | ||
96 | return NULL; | ||
97 | } | ||
98 | static DOTCONF_CB(dco_user) { dc_context *dcc = (dc_context*)ctx; | ||
99 | dcc->cf->user = cmd->data.str; | ||
100 | dcc->cf->flags |= configuration::flag_user; | ||
101 | return NULL; | ||
102 | } | ||
103 | static DOTCONF_CB(dco_group) { dc_context *dcc = (dc_context*)ctx; | ||
104 | dcc->cf->group = cmd->data.str; | ||
105 | dcc->cf->flags |= configuration::flag_group; | ||
106 | return NULL; | ||
107 | } | ||
108 | static DOTCONF_CB(dco_chroot) { dc_context *dcc = (dc_context*)ctx; | ||
109 | dcc->cf->chroot = cmd->data.str; | ||
110 | dcc->cf->flags |= configuration::flag_chroot; | ||
111 | return NULL; | ||
112 | } | ||
113 | static DOTCONF_CB(dco_pid_file) { dc_context *dcc = (dc_context*)ctx; | ||
114 | dcc->cf->pid_file = cmd->data.str; | ||
115 | dcc->cf->flags |= configuration::flag_pid_file; | ||
116 | return NULL; | ||
117 | } | ||
118 | static DOTCONF_CB(dco_daemonize) { dc_context *dcc = (dc_context*) ctx; | ||
119 | dcc->cf->daemonize = cmd->data.value; | ||
120 | dcc->cf->flags |= configuration::flag_daemonize; | ||
121 | return NULL; | ||
122 | } | ||
123 | |||
124 | static DOTCONF_CB(dco_path) { dc_context *dcc = (dc_context*)ctx; | ||
125 | string path = cmd->data.str; | ||
126 | if(path[path.length()-1]=='>') | ||
127 | path.erase(path.length()-1); | ||
128 | // TODO: normalize path | ||
129 | dcc->co.push_front(&(dcc->cf->specs[path])); | ||
130 | dcc->ctx = DCC_PATH; // TODO: stack it, instead | ||
131 | return NULL; | ||
132 | } | ||
133 | static DOTCONF_CB(dco__path) { dc_context *dcc = (dc_context*)ctx; | ||
134 | dcc->co.pop_front(); | ||
135 | assert(dcc->co.size()); | ||
136 | dcc->ctx = DCC_ROOT; // TODO: stack it, instead | ||
137 | return NULL; | ||
138 | } | ||
139 | |||
140 | static DOTCONF_CB(dco_skeleton) { dc_context *dcc = (dc_context*)ctx; | ||
141 | dcc->co.front()->skeleton = cmd->data.str; | ||
142 | dcc->co.front()->flags |= config_options::flag_skeleton; | ||
143 | return NULL; | ||
144 | } | ||
145 | static DOTCONF_CB(dco_cpp_flags) { dc_context *dcc = (dc_context*)ctx; | ||
146 | for(char **arg=cmd->data.list;*arg;arg++) | ||
147 | dcc->co.front()->cpp_flags.push_back(*arg); | ||
148 | dcc->co.front()->flags |= config_options::flag_cpp_flags; | ||
149 | return NULL; | ||
150 | } | ||
151 | static DOTCONF_CB(dco_ld_flags) { dc_context *dcc = (dc_context*)ctx; | ||
152 | for(char **arg=cmd->data.list;*arg;arg++) | ||
153 | dcc->co.front()->ld_flags.push_back(*arg); | ||
154 | dcc->co.front()->flags |= config_options::flag_ld_flags; | ||
155 | return NULL; | ||
156 | } | ||
157 | static DOTCONF_CB(dco_intermediate_deps) { dc_context *dcc = (dc_context*) ctx; | ||
158 | for(char **arg=cmd->data.list;*arg;arg++) | ||
159 | dcc->co.front()->intermediate_deps.push_back(*arg); | ||
160 | dcc->co.front()->flags |= config_options::flag_intermediate_deps; | ||
161 | return NULL; | ||
162 | } | ||
163 | static DOTCONF_CB(dco_so_deps) { dc_context *dcc = (dc_context*) ctx; | ||
164 | for(char **arg=cmd->data.list;*arg;arg++) | ||
165 | dcc->co.front()->so_deps.push_back(*arg); | ||
166 | dcc->co.front()->flags |= config_options::flag_so_deps; | ||
167 | return NULL; | ||
168 | } | ||
169 | static DOTCONF_CB(dco_build) { dc_context *dcc = (dc_context*)ctx; | ||
170 | dcc->co.front()->build = cmd->data.value; | ||
171 | dcc->co.front()->flags |= config_options::flag_build; | ||
172 | return NULL; | ||
173 | } | ||
174 | static DOTCONF_CB(dco_cpp_deps) { dc_context *dcc = (dc_context*)ctx; | ||
175 | dcc->co.front()->cpp_deps = cmd->data.value; | ||
176 | dcc->co.front()->flags |= config_options::flag_cpp_deps; | ||
177 | return NULL; | ||
178 | } | ||
179 | static DOTCONF_CB(dco_exception_handler) { dc_context *dcc = (dc_context*)ctx; | ||
180 | dcc->co.front()->exception_handler = cmd->data.str; | ||
181 | dcc->co.front()->flags |= config_options::flag_exception_handler; | ||
182 | return NULL; | ||
183 | } | ||
184 | static DOTCONF_CB(dco_http_status_handler) { dc_context *dcc = (dc_context*)ctx; | ||
185 | if(cmd->arg_count!=2) | ||
186 | return "Invalid number of arguments"; | ||
187 | dcc->co.front()->http_status_handlers[cmd->data.list[0]] = cmd->data.list[1]; | ||
188 | dcc->co.front()->flags |= config_options::flag_http_status_handlers; | ||
189 | return NULL; | ||
190 | } | ||
191 | static DOTCONF_CB(dco_action) { dc_context *dcc = (dc_context*)ctx; | ||
192 | if(cmd->arg_count<2) | ||
193 | return "Invalid number of arguments"; | ||
194 | try { | ||
195 | char **arg=cmd->data.list; | ||
196 | dcc->co.front()->action_handlers.push_back(config_options::action_handler_t(arg[0],arg[1])); | ||
197 | for(arg+=2;*arg;arg++) | ||
198 | dcc->co.front()->action_handlers.back().args.push_back(*arg); | ||
199 | dcc->co.front()->flags |= config_options::flag_action_handlers; | ||
200 | }catch(exception& e) { | ||
201 | return "Error processing Action directive"; // XXX: could be done better | ||
202 | } | ||
203 | return NULL; | ||
204 | } | ||
205 | static DOTCONF_CB(dco_auto_build_files) { dc_context *dcc = (dc_context*)ctx; | ||
206 | if(!( dcc->cf && dcc->cf->autobuild)) | ||
207 | return NULL; | ||
208 | for(char **arg=cmd->data.list;*arg;arg++) | ||
209 | dcc->co.front()->auto_build_files.push_back(*arg); | ||
210 | dcc->co.front()->flags |= config_options::flag_auto_build_files; | ||
211 | return NULL; | ||
212 | } | ||
213 | |||
214 | static const configoption_t dc_options[] = { | ||
215 | { "RootSource", ARG_STR, dco_root_source, NULL, DCC_ROOT }, | ||
216 | { "RootIntermediate", ARG_STR, dco_root_intermediate, NULL, DCC_ROOT }, | ||
217 | { "RootSO", ARG_STR, dco_root_so, NULL, DCC_ROOT }, | ||
218 | { "ListenSocket", ARG_STR, dco_listen_socket, NULL, DCC_ROOT }, | ||
219 | { "RCFileName", ARG_STR, dco_rc_file_name, NULL, DCC_ROOT }, | ||
220 | { "MinChildren", ARG_INT, dco_min_children, NULL, DCC_ROOT }, | ||
221 | { "MaxChildren", ARG_INT, dco_max_children, NULL, DCC_ROOT }, | ||
222 | { "MinSpareChildren", ARG_INT, dco_min_spare_children, NULL, DCC_ROOT }, | ||
223 | { "MaxSpareChildren", ARG_INT, dco_max_spare_children, NULL, DCC_ROOT }, | ||
224 | { "RequestsPerChild", ARG_INT, dco_requests_per_child, NULL, DCC_ROOT }, | ||
225 | { "MultiProcess", ARG_TOGGLE, dco_multi_process, NULL, DCC_ROOT }, | ||
226 | { "User", ARG_STR, dco_user, NULL, DCC_ROOT }, | ||
227 | { "Group", ARG_STR, dco_group, NULL, DCC_ROOT }, | ||
228 | { "Chroot", ARG_STR, dco_chroot, NULL, DCC_ROOT }, | ||
229 | { "PidFile", ARG_STR, dco_pid_file, NULL, DCC_ROOT }, | ||
230 | { "Daemonize", ARG_TOGGLE, dco_daemonize, NULL, DCC_ROOT }, | ||
231 | { "<Path", ARG_STR, dco_path, NULL, DCC_ROOT }, | ||
232 | { "Skeleton", ARG_STR, dco_skeleton, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | ||
233 | { "CPPFLAGS", ARG_LIST, dco_cpp_flags, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | ||
234 | { "LDFLAGS", ARG_LIST, dco_ld_flags, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | ||
235 | { "Build", ARG_TOGGLE, dco_build, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | ||
236 | { "CPPDeps", ARG_TOGGLE, dco_cpp_deps, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | ||
237 | { "ExceptionHandler", ARG_STR, dco_exception_handler, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | ||
238 | { "HTTPStatusHandler", ARG_LIST, dco_http_status_handler, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | ||
239 | { "IntermediateDeps", ARG_LIST, dco_intermediate_deps, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | ||
240 | { "SODeps", ARG_LIST, dco_so_deps, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | ||
241 | { "Action", ARG_LIST, dco_action, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | ||
242 | { "AutoBuildFiles", ARG_LIST, dco_auto_build_files, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | ||
243 | { "</Path>", ARG_NONE, dco__path, NULL, DCC_PATH }, | ||
244 | LAST_OPTION | ||
245 | }; | ||
246 | |||
247 | static const char *dc_context_checker(command_t *cmd,unsigned long mask) { | ||
248 | dc_context *dcc = (dc_context*)cmd->context; | ||
249 | if( (mask==CTX_ALL) || ((mask&dcc->ctx)==dcc->ctx) ) | ||
250 | return NULL; | ||
251 | return "misplaced option"; | ||
252 | } | ||
253 | static FUNC_ERRORHANDLER(dc_error_handler) { | ||
254 | throw konforka::exception(CODEPOINT,string("error parsing config file: ")+msg); | ||
255 | } | ||
256 | |||
257 | bool loaded_options::is_valid() { | ||
258 | struct stat nst; | ||
259 | if(stat(source_file.c_str(),&nst)) | ||
260 | return false; | ||
261 | if(st.st_mtime!=nst.st_mtime) | ||
262 | return false; | ||
263 | return true; | ||
264 | } | ||
265 | |||
266 | loaded_options *configuration::lookup_loaded_options(const string& target) { | ||
267 | // we assume 'target' is a directory with trailing slash appended | ||
268 | string scrc = root_source+target; | ||
269 | if(flags&flag_rc_file_name) | ||
270 | scrc += rc_file_name; | ||
271 | else | ||
272 | scrc += ".scrc"; | ||
273 | // TODO: normalize me, anyway. | ||
274 | if(access(scrc.c_str(),R_OK)) | ||
275 | return 0; // TODO FIXME: this approach leaves already loaded .scrcs around in case of removal | ||
276 | loaded_specs_t::iterator i = loaded_specs.find(target); | ||
277 | if(i==loaded_specs.end() || !i->second.is_valid()) { | ||
278 | if(i!=loaded_specs.end()) | ||
279 | loaded_specs.erase(i); | ||
280 | pair<loaded_specs_t::iterator,bool> ii = loaded_specs.insert(loaded_specs_t::value_type(target,loaded_options())); | ||
281 | assert(ii.first!=loaded_specs.end()); | ||
282 | ii.first->second.parse(this,scrc); | ||
283 | i = ii.first; | ||
284 | } | ||
285 | assert(i!=loaded_specs.end()); | ||
286 | return &(i->second); | ||
287 | } | ||
288 | |||
289 | config_options::action_handler_t *config_options::lookup_action_handler(const string& target) { | ||
290 | for(action_handlers_t::iterator i=action_handlers.begin();i!=action_handlers.end();++i) { | ||
291 | if(i->regex.search(target)) | ||
292 | return &*i; | ||
293 | } | ||
294 | return NULL; | ||
295 | } | ||
296 | |||
297 | string config_options::lookup_http_status_handler(const string& status) { | ||
298 | http_status_handlers_t::const_iterator i = http_status_handlers.find(status); | ||
299 | string rv; | ||
300 | if(i!=http_status_handlers.end()) | ||
301 | rv = i->second; | ||
302 | return rv; | ||
303 | } | ||
304 | |||
305 | string configuration::lookup_http_status_handler(const string& target,const string& status) { | ||
306 | string t = "/"; | ||
307 | t += normalize_path(target,strip_leading_slash); | ||
308 | string rv; | ||
309 | for(;;) { | ||
310 | if(t[t.length()-1]=='/') { | ||
311 | loaded_options* lo = lookup_loaded_options(t); | ||
312 | if( lo && (lo->flags&config_options::flag_http_status_handlers) ) { | ||
313 | rv = lo->lookup_http_status_handler(status); | ||
314 | if(!rv.empty()) | ||
315 | return rv; | ||
316 | } | ||
317 | } | ||
318 | specs_t::iterator i = specs.find(t); | ||
319 | if( i!=specs.end() && (i->second.flags&&config_options::flag_http_status_handlers) ) { | ||
320 | rv = i->second.lookup_http_status_handler(status); | ||
321 | if(!rv.empty()) | ||
322 | return rv; | ||
323 | } | ||
324 | if(t.empty()) | ||
325 | return rv; | ||
326 | string::size_type sl=t.rfind('/'); | ||
327 | if(sl==string::npos) { | ||
328 | t.erase(); | ||
329 | }else{ | ||
330 | if(sl==(t.length()-1)) | ||
331 | t.erase(sl); | ||
332 | else | ||
333 | t.erase(sl+1); | ||
334 | } | ||
335 | } | ||
336 | } | ||
337 | |||
338 | config_options::action_handler_t *configuration::lookup_action_handler(const string& target) { | ||
339 | string t = "/"; | ||
340 | t += normalize_path(target,strip_leading_slash); | ||
341 | for(;;) { | ||
342 | if(t[t.length()-1]=='/') { | ||
343 | loaded_options* lo = lookup_loaded_options(t); | ||
344 | if( lo && (lo->flags&config_options::flag_action_handlers) ) { | ||
345 | config_options::action_handler_t *rv = lo->lookup_action_handler(target); | ||
346 | if(rv) | ||
347 | return rv; | ||
348 | } | ||
349 | } | ||
350 | specs_t::iterator i = specs.find(t); | ||
351 | if( i!=specs.end() && (i->second.flags&&config_options::flag_action_handlers) ) { | ||
352 | config_options::action_handler_t *rv = i->second.lookup_action_handler(target); | ||
353 | if(rv) | ||
354 | return rv; | ||
355 | } | ||
356 | if(t.empty()) | ||
357 | return NULL; | ||
358 | string::size_type sl=t.rfind('/'); | ||
359 | if(sl==string::npos) { | ||
360 | t.erase(); | ||
361 | }else{ | ||
362 | if(sl==(t.length()-1)) | ||
363 | t.erase(sl); | ||
364 | else | ||
365 | t.erase(sl+1); | ||
366 | } | ||
367 | } | ||
368 | } | ||
369 | |||
370 | config_options* configuration::lookup_config(const string& target,int flag) { | ||
371 | string t = "/"; // always assume leading slash | ||
372 | t += normalize_path(target,strip_leading_slash); | ||
373 | // XXX: reconsider precedence | ||
374 | for(;;) { | ||
375 | if(t[t.length()-1]=='/') { | ||
376 | loaded_options* lo = lookup_loaded_options(t); | ||
377 | if( lo && (lo->flags&flag)==flag ) | ||
378 | return lo; | ||
379 | } | ||
380 | specs_t::iterator i = specs.find(t); | ||
381 | if( i!=specs.end() && (i->second.flags&flag)==flag ) | ||
382 | return &(i->second); | ||
383 | if(t.empty()) | ||
384 | return NULL; | ||
385 | string::size_type sl=t.rfind('/'); | ||
386 | if(sl==string::npos) { | ||
387 | t.erase(); | ||
388 | }else{ | ||
389 | if(sl==(t.length()-1)) | ||
390 | t.erase(sl); | ||
391 | else | ||
392 | t.erase(sl+1); | ||
393 | } | ||
394 | } | ||
395 | } | ||
396 | |||
397 | bool config_options::match_autobuild_files(const char *fn,bool &rv) { | ||
398 | for(list<string>::reverse_iterator i=auto_build_files.rbegin();i!=auto_build_files.rend();++i) { | ||
399 | const char *pat = i->c_str(); | ||
400 | bool plus = true; | ||
401 | if((*pat)=='+') | ||
402 | pat++; | ||
403 | else if((*pat)=='-') { | ||
404 | plus = false; | ||
405 | pat++; | ||
406 | } | ||
407 | if(!fnmatch(pat,fn,FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD)) { | ||
408 | rv = plus; | ||
409 | return true; | ||
410 | } | ||
411 | } | ||
412 | return false; | ||
413 | } | ||
414 | |||
415 | bool configuration::match_autobuild_files(const string& target,const char *fn) { | ||
416 | string t = "/"; | ||
417 | t += normalize_path(target,strip_leading_slash|strip_trailing_slash); | ||
418 | t += "/"; | ||
419 | bool rv = false; | ||
420 | for(;;) { | ||
421 | if(t[t.length()-1]=='/') { | ||
422 | loaded_options* lo = lookup_loaded_options(t); | ||
423 | if(lo && (lo->flags&config_options::flag_auto_build_files) && lo->match_autobuild_files(fn,rv) ) | ||
424 | return rv; | ||
425 | } | ||
426 | specs_t::iterator i = specs.find(t); | ||
427 | if( i!=specs.end() && (i->second.flags&config_options::flag_auto_build_files) && i->second.match_autobuild_files(fn,rv) ) | ||
428 | return rv; | ||
429 | if(t.empty()) | ||
430 | return rv; | ||
431 | string::size_type sl=t.rfind('/'); | ||
432 | if(sl==string::npos) { | ||
433 | t.erase(); | ||
434 | }else{ | ||
435 | if(sl==(t.length()-1)) | ||
436 | t.erase(sl); | ||
437 | else | ||
438 | t.erase(sl+1); | ||
439 | } | ||
440 | } | ||
441 | } | ||
442 | |||
443 | void configuration::parse(const string& cfile) { | ||
444 | struct dc_context dcc; | ||
445 | dcc.cf = this; | ||
446 | dcc.ctx = DCC_ROOT; | ||
447 | dcc.co.push_front(&root_options()); | ||
448 | configfile_t *cf = dotconf_create((char*)cfile.c_str(),dc_options,(context_t*)&dcc,CASE_INSENSITIVE); | ||
449 | if(!cf) | ||
450 | throw konforka::exception(CODEPOINT,"failed to dotconf_create()"); | ||
451 | cf->errorhandler = (dotconf_errorhandler_t) dc_error_handler; | ||
452 | cf->contextchecker = (dotconf_contextchecker_t) dc_context_checker; | ||
453 | if(!dotconf_command_loop(cf)) | ||
454 | throw konforka::exception(CODEPOINT,"failed to dotconf_command_loop()"); | ||
455 | dotconf_cleanup(cf); | ||
456 | } | ||
457 | |||
458 | void loaded_options::parse(configuration *config,const string& cfile) { | ||
459 | struct dc_context dcc; | ||
460 | dcc.cf = config; | ||
461 | dcc.ctx = DCC_SCRC; | ||
462 | dcc.co.push_front(this); | ||
463 | configfile_t *cf = dotconf_create((char*)cfile.c_str(),dc_options,(context_t*)&dcc,CASE_INSENSITIVE); | ||
464 | if(!cf) | ||
465 | throw konforka::exception(CODEPOINT,"failed to dotconf_create()"); | ||
466 | cf->errorhandler = (dotconf_errorhandler_t) dc_error_handler; | ||
467 | cf->contextchecker = (dotconf_contextchecker_t) dc_context_checker; | ||
468 | if(!dotconf_command_loop(cf)) | ||
469 | throw konforka::exception(CODEPOINT,"failed to dotconf_command_loop()"); | ||
470 | dotconf_cleanup(cf); | ||
471 | source_file = cfile; | ||
472 | stat(cfile.c_str(),&st); // TODO: handle errors? | ||
473 | } | ||
474 | } | ||