summaryrefslogtreecommitdiffabout
path: root/lib/configuration.cc
Unidiff
Diffstat (limited to 'lib/configuration.cc') (more/less context) (ignore whitespace changes)
-rw-r--r--lib/configuration.cc9
1 files changed, 5 insertions, 4 deletions
diff --git a/lib/configuration.cc b/lib/configuration.cc
index 4ee1526..6b21690 100644
--- a/lib/configuration.cc
+++ b/lib/configuration.cc
@@ -1,104 +1,105 @@
1#ifdef USE_PCH 1#ifdef USE_PCH
2 #include "pch.h" 2 #include "pch.h"
3#else 3#else
4 #include <unistd.h> 4 #include <unistd.h>
5 #include <fnmatch.h> 5 #include <fnmatch.h>
6 #include <cassert> 6 #include <cassert>
7 #include <stdexcept> 7 #include <stdexcept>
8 using namespace std; 8 using namespace std;
9 #include <konforka/util.h>
9 #include <dotconf.h> 10 #include <dotconf.h>
10 #include "sitecing/configuration.h" 11 #include "sitecing/configuration.h"
11 #include "sitecing/sitecing_util.h" 12 #include "sitecing/sitecing_util.h"
12 #include "sitecing/scoreboard.h" 13 #include "sitecing/scoreboard.h"
13#endif 14#endif
14 15
15namespace sitecing { 16namespace sitecing {
16 17
17 configuration::configuration() 18 configuration::configuration()
18 : flags(0), autobuild(false) { } 19 : flags(0), autobuild(false) { }
19 configuration::configuration(const string& cfile,bool ab) 20 configuration::configuration(const string& cfile,bool ab)
20 : flags(0), autobuild(ab) { 21 : flags(0), autobuild(ab) {
21 parse(cfile); 22 parse(cfile);
22 } 23 }
23 24
24 enum dc_ctx { 25 enum dc_ctx {
25 DCC_ROOT = 1, 26 DCC_ROOT = 1,
26 DCC_PATH = 2, 27 DCC_PATH = 2,
27 DCC_SCRC = 4 28 DCC_SCRC = 4
28 }; 29 };
29 struct dc_context { 30 struct dc_context {
30 dc_ctx ctx; 31 dc_ctx ctx;
31 configuration* cf; 32 configuration* cf;
32 list<config_options*> co; 33 list<config_options*> co;
33 }; 34 };
34 35
35 static DOTCONF_CB(dco_root_source) { dc_context *dcc = (dc_context*)ctx; 36 static DOTCONF_CB(dco_root_source) { dc_context *dcc = (dc_context*)ctx;
36 dcc->cf->root_source = cmd->data.str; 37 dcc->cf->root_source = cmd->data.str;
37 dcc->cf->flags |= configuration::flag_root_source; 38 dcc->cf->flags |= configuration::flag_root_source;
38 return NULL; 39 return NULL;
39 } 40 }
40 static DOTCONF_CB(dco_root_intermediate) { dc_context *dcc = (dc_context*)ctx; 41 static DOTCONF_CB(dco_root_intermediate) { dc_context *dcc = (dc_context*)ctx;
41 dcc->cf->root_intermediate = cmd->data.str; 42 dcc->cf->root_intermediate = cmd->data.str;
42 dcc->cf->flags |= configuration::flag_root_intermediate; 43 dcc->cf->flags |= configuration::flag_root_intermediate;
43 return NULL; 44 return NULL;
44 } 45 }
45 static DOTCONF_CB(dco_root_so) { dc_context *dcc = (dc_context*)ctx; 46 static DOTCONF_CB(dco_root_so) { dc_context *dcc = (dc_context*)ctx;
46 dcc->cf->root_so = cmd->data.str; 47 dcc->cf->root_so = cmd->data.str;
47 dcc->cf->flags |= configuration::flag_root_so; 48 dcc->cf->flags |= configuration::flag_root_so;
48 return NULL; 49 return NULL;
49 } 50 }
50 static DOTCONF_CB(dco_listen_socket) { dc_context *dcc = (dc_context*)ctx; 51 static DOTCONF_CB(dco_listen_socket) { dc_context *dcc = (dc_context*)ctx;
51 dcc->cf->listen_socket = cmd->data.str; 52 dcc->cf->listen_socket = cmd->data.str;
52 dcc->cf->flags |= configuration::flag_listen_socket; 53 dcc->cf->flags |= configuration::flag_listen_socket;
53 return NULL; 54 return NULL;
54 } 55 }
55 static DOTCONF_CB(dco_rc_file_name) { dc_context *dcc = (dc_context*)ctx; 56 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->rc_file_name = cmd->data.str;
57 dcc->cf->flags |= configuration::flag_rc_file_name; 58 dcc->cf->flags |= configuration::flag_rc_file_name;
58 return NULL; 59 return NULL;
59 } 60 }
60 static DOTCONF_CB(dco_min_children) { dc_context *dcc = (dc_context*)ctx; 61 static DOTCONF_CB(dco_min_children) { dc_context *dcc = (dc_context*)ctx;
61 if(cmd->data.value>=MAX_SITECING_SCOREBOARD_SLOTS) 62 if(cmd->data.value>=MAX_SITECING_SCOREBOARD_SLOTS)
62 return "MinChildren is too big"; 63 return "MinChildren is too big";
63 dcc->cf->min_children = cmd->data.value; 64 dcc->cf->min_children = cmd->data.value;
64 dcc->cf->flags |= configuration::flag_min_children; 65 dcc->cf->flags |= configuration::flag_min_children;
65 return NULL; 66 return NULL;
66 } 67 }
67 static DOTCONF_CB(dco_max_children) { dc_context *dcc = (dc_context*)ctx; 68 static DOTCONF_CB(dco_max_children) { dc_context *dcc = (dc_context*)ctx;
68 if(cmd->data.value>=MAX_SITECING_SCOREBOARD_SLOTS) 69 if(cmd->data.value>=MAX_SITECING_SCOREBOARD_SLOTS)
69 return "MaxChildren is too big"; 70 return "MaxChildren is too big";
70 dcc->cf->max_children = cmd->data.value; 71 dcc->cf->max_children = cmd->data.value;
71 dcc->cf->flags |= configuration::flag_max_children; 72 dcc->cf->flags |= configuration::flag_max_children;
72 return NULL; 73 return NULL;
73 } 74 }
74 static DOTCONF_CB(dco_min_spare_children) { dc_context *dcc = (dc_context*)ctx; 75 static DOTCONF_CB(dco_min_spare_children) { dc_context *dcc = (dc_context*)ctx;
75 if(cmd->data.value>=MAX_SITECING_SCOREBOARD_SLOTS) 76 if(cmd->data.value>=MAX_SITECING_SCOREBOARD_SLOTS)
76 return "MinSpareChildren is too big"; 77 return "MinSpareChildren is too big";
77 dcc->cf->min_spare_children = cmd->data.value; 78 dcc->cf->min_spare_children = cmd->data.value;
78 dcc->cf->flags |= configuration::flag_min_spare_children; 79 dcc->cf->flags |= configuration::flag_min_spare_children;
79 return NULL; 80 return NULL;
80 } 81 }
81 static DOTCONF_CB(dco_max_spare_children) { dc_context *dcc = (dc_context*)ctx; 82 static DOTCONF_CB(dco_max_spare_children) { dc_context *dcc = (dc_context*)ctx;
82 if(cmd->data.value>=MAX_SITECING_SCOREBOARD_SLOTS) 83 if(cmd->data.value>=MAX_SITECING_SCOREBOARD_SLOTS)
83 return "MaxSpareChildren is too big"; 84 return "MaxSpareChildren is too big";
84 dcc->cf->max_spare_children = cmd->data.value; 85 dcc->cf->max_spare_children = cmd->data.value;
85 dcc->cf->flags |= configuration::flag_max_spare_children; 86 dcc->cf->flags |= configuration::flag_max_spare_children;
86 return NULL; 87 return NULL;
87 } 88 }
88 static DOTCONF_CB(dco_requests_per_child) { dc_context *dcc = (dc_context*)ctx; 89 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->requests_per_child = cmd->data.value;
90 dcc->cf->flags |= configuration::flag_requests_per_child; 91 dcc->cf->flags |= configuration::flag_requests_per_child;
91 return NULL; 92 return NULL;
92 } 93 }
93 static DOTCONF_CB(dco_multi_process) { dc_context *dcc = (dc_context*)ctx; 94 static DOTCONF_CB(dco_multi_process) { dc_context *dcc = (dc_context*)ctx;
94 dcc->cf->multi_process = cmd->data.value; 95 dcc->cf->multi_process = cmd->data.value;
95 dcc->cf->flags |= configuration::flag_multi_process; 96 dcc->cf->flags |= configuration::flag_multi_process;
96 return NULL; 97 return NULL;
97 } 98 }
98 static DOTCONF_CB(dco_user) { dc_context *dcc = (dc_context*)ctx; 99 static DOTCONF_CB(dco_user) { dc_context *dcc = (dc_context*)ctx;
99 dcc->cf->user = cmd->data.str; 100 dcc->cf->user = cmd->data.str;
100 dcc->cf->flags |= configuration::flag_user; 101 dcc->cf->flags |= configuration::flag_user;
101 return NULL; 102 return NULL;
102 } 103 }
103 static DOTCONF_CB(dco_group) { dc_context *dcc = (dc_context*)ctx; 104 static DOTCONF_CB(dco_group) { dc_context *dcc = (dc_context*)ctx;
104 dcc->cf->group = cmd->data.str; 105 dcc->cf->group = cmd->data.str;
@@ -211,264 +212,264 @@ namespace sitecing {
211 return NULL; 212 return NULL;
212 } 213 }
213 214
214 static const configoption_t dc_options[] = { 215 static const configoption_t dc_options[] = {
215 { "RootSource", ARG_STR, dco_root_source, NULL, DCC_ROOT }, 216 { "RootSource", ARG_STR, dco_root_source, NULL, DCC_ROOT },
216 { "RootIntermediate", ARG_STR, dco_root_intermediate, NULL, DCC_ROOT }, 217 { "RootIntermediate", ARG_STR, dco_root_intermediate, NULL, DCC_ROOT },
217 { "RootSO", ARG_STR, dco_root_so, NULL, DCC_ROOT }, 218 { "RootSO", ARG_STR, dco_root_so, NULL, DCC_ROOT },
218 { "ListenSocket", ARG_STR, dco_listen_socket, NULL, DCC_ROOT }, 219 { "ListenSocket", ARG_STR, dco_listen_socket, NULL, DCC_ROOT },
219 { "RCFileName", ARG_STR, dco_rc_file_name, NULL, DCC_ROOT }, 220 { "RCFileName", ARG_STR, dco_rc_file_name, NULL, DCC_ROOT },
220 { "MinChildren", ARG_INT, dco_min_children, NULL, DCC_ROOT }, 221 { "MinChildren", ARG_INT, dco_min_children, NULL, DCC_ROOT },
221 { "MaxChildren", ARG_INT, dco_max_children, NULL, DCC_ROOT }, 222 { "MaxChildren", ARG_INT, dco_max_children, NULL, DCC_ROOT },
222 { "MinSpareChildren", ARG_INT, dco_min_spare_children, NULL, DCC_ROOT }, 223 { "MinSpareChildren", ARG_INT, dco_min_spare_children, NULL, DCC_ROOT },
223 { "MaxSpareChildren", ARG_INT, dco_max_spare_children, NULL, DCC_ROOT }, 224 { "MaxSpareChildren", ARG_INT, dco_max_spare_children, NULL, DCC_ROOT },
224 { "RequestsPerChild", ARG_INT, dco_requests_per_child, NULL, DCC_ROOT }, 225 { "RequestsPerChild", ARG_INT, dco_requests_per_child, NULL, DCC_ROOT },
225 { "MultiProcess", ARG_TOGGLE, dco_multi_process, NULL, DCC_ROOT }, 226 { "MultiProcess", ARG_TOGGLE, dco_multi_process, NULL, DCC_ROOT },
226 { "User", ARG_STR, dco_user, NULL, DCC_ROOT }, 227 { "User", ARG_STR, dco_user, NULL, DCC_ROOT },
227 { "Group", ARG_STR, dco_group, NULL, DCC_ROOT }, 228 { "Group", ARG_STR, dco_group, NULL, DCC_ROOT },
228 { "Chroot", ARG_STR, dco_chroot, NULL, DCC_ROOT }, 229 { "Chroot", ARG_STR, dco_chroot, NULL, DCC_ROOT },
229 { "PidFile", ARG_STR, dco_pid_file, NULL, DCC_ROOT }, 230 { "PidFile", ARG_STR, dco_pid_file, NULL, DCC_ROOT },
230 { "Daemonize", ARG_TOGGLE, dco_daemonize, NULL, DCC_ROOT }, 231 { "Daemonize", ARG_TOGGLE, dco_daemonize, NULL, DCC_ROOT },
231 { "<Path", ARG_STR, dco_path, NULL, DCC_ROOT }, 232 { "<Path", ARG_STR, dco_path, NULL, DCC_ROOT },
232 { "Skeleton", ARG_STR, dco_skeleton, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, 233 { "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 { "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 { "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 { "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 { "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 { "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 { "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 { "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 { "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 { "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 { "AutoBuildFiles", ARG_LIST, dco_auto_build_files, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC },
243 { "</Path>", ARG_NONE, dco__path, NULL, DCC_PATH }, 244 { "</Path>", ARG_NONE, dco__path, NULL, DCC_PATH },
244 LAST_OPTION 245 LAST_OPTION
245 }; 246 };
246 247
247 static const char *dc_context_checker(command_t *cmd,unsigned long mask) { 248 static const char *dc_context_checker(command_t *cmd,unsigned long mask) {
248 dc_context *dcc = (dc_context*)cmd->context; 249 dc_context *dcc = (dc_context*)cmd->context;
249 if( (mask==CTX_ALL) || ((mask&dcc->ctx)==dcc->ctx) ) 250 if( (mask==CTX_ALL) || ((mask&dcc->ctx)==dcc->ctx) )
250 return NULL; 251 return NULL;
251 return "misplaced option"; 252 return "misplaced option";
252 } 253 }
253 static FUNC_ERRORHANDLER(dc_error_handler) { 254 static FUNC_ERRORHANDLER(dc_error_handler) {
254 throw konforka::exception(CODEPOINT,string("error parsing config file: ")+msg); 255 throw konforka::exception(CODEPOINT,string("error parsing config file: ")+msg);
255 } 256 }
256 257
257 bool loaded_options::is_valid() { 258 bool loaded_options::is_valid() {
258 struct stat nst; 259 struct stat nst;
259 if(stat(source_file.c_str(),&nst)) 260 if(stat(source_file.c_str(),&nst))
260 return false; 261 return false;
261 if(st.st_mtime!=nst.st_mtime) 262 if(st.st_mtime!=nst.st_mtime)
262 return false; 263 return false;
263 return true; 264 return true;
264 } 265 }
265 266
266 loaded_options *configuration::lookup_loaded_options(const string& target) { 267 loaded_options *configuration::lookup_loaded_options(const string& target) {
267 // we assume 'target' is a directory with trailing slash appended 268 // we assume 'target' is a directory with trailing slash appended
268 string scrc = root_source+target; 269 string scrc = root_source+target;
269 if(flags&flag_rc_file_name) 270 if(flags&flag_rc_file_name)
270 scrc += rc_file_name; 271 scrc += rc_file_name;
271 else 272 else
272 scrc += ".scrc"; 273 scrc += ".scrc";
273 // TODO: normalize me, anyway. 274 // TODO: normalize me, anyway.
274 if(access(scrc.c_str(),R_OK)) 275 if(access(scrc.c_str(),R_OK))
275 return 0; // TODO FIXME: this approach leaves already loaded .scrcs around in case of removal 276 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 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() || !i->second.is_valid()) {
278 if(i!=loaded_specs.end()) 279 if(i!=loaded_specs.end())
279 loaded_specs.erase(i); 280 loaded_specs.erase(i);
280 pair<loaded_specs_t::iterator,bool> ii = loaded_specs.insert(loaded_specs_t::value_type(target,loaded_options())); 281 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 assert(ii.first!=loaded_specs.end());
282 ii.first->second.parse(this,scrc); 283 ii.first->second.parse(this,scrc);
283 i = ii.first; 284 i = ii.first;
284 } 285 }
285 assert(i!=loaded_specs.end()); 286 assert(i!=loaded_specs.end());
286 return &(i->second); 287 return &(i->second);
287 } 288 }
288 289
289 config_options::action_handler_t *config_options::lookup_action_handler(const string& target) { 290 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 for(action_handlers_t::iterator i=action_handlers.begin();i!=action_handlers.end();++i) {
291 if(i->regex.search(target)) 292 if(i->regex.search(target))
292 return &*i; 293 return &*i;
293 } 294 }
294 return NULL; 295 return NULL;
295 } 296 }
296 297
297 string config_options::lookup_http_status_handler(const string& status) { 298 string config_options::lookup_http_status_handler(const string& status) {
298 http_status_handlers_t::const_iterator i = http_status_handlers.find(status); 299 http_status_handlers_t::const_iterator i = http_status_handlers.find(status);
299 string rv; 300 string rv;
300 if(i!=http_status_handlers.end()) 301 if(i!=http_status_handlers.end())
301 rv = i->second; 302 rv = i->second;
302 return rv; 303 return rv;
303 } 304 }
304 305
305 string configuration::lookup_http_status_handler(const string& target,const string& status) { 306 string configuration::lookup_http_status_handler(const string& target,const string& status) {
306 string t = "/"; 307 string t = "/";
307 t += normalize_path(target,strip_leading_slash); 308 t += konforka::normalize_path(target,konforka::strip_leading_slash);
308 string rv; 309 string rv;
309 for(;;) { 310 for(;;) {
310 if(t[t.length()-1]=='/') { 311 if(t[t.length()-1]=='/') {
311 loaded_options* lo = lookup_loaded_options(t); 312 loaded_options* lo = lookup_loaded_options(t);
312 if( lo && (lo->flags&config_options::flag_http_status_handlers) ) { 313 if( lo && (lo->flags&config_options::flag_http_status_handlers) ) {
313 rv = lo->lookup_http_status_handler(status); 314 rv = lo->lookup_http_status_handler(status);
314 if(!rv.empty()) 315 if(!rv.empty())
315 return rv; 316 return rv;
316 } 317 }
317 } 318 }
318 specs_t::iterator i = specs.find(t); 319 specs_t::iterator i = specs.find(t);
319 if( i!=specs.end() && (i->second.flags&&config_options::flag_http_status_handlers) ) { 320 if( i!=specs.end() && (i->second.flags&&config_options::flag_http_status_handlers) ) {
320 rv = i->second.lookup_http_status_handler(status); 321 rv = i->second.lookup_http_status_handler(status);
321 if(!rv.empty()) 322 if(!rv.empty())
322 return rv; 323 return rv;
323 } 324 }
324 if(t.empty()) 325 if(t.empty())
325 return rv; 326 return rv;
326 string::size_type sl=t.rfind('/'); 327 string::size_type sl=t.rfind('/');
327 if(sl==string::npos) { 328 if(sl==string::npos) {
328 t.erase(); 329 t.erase();
329 }else{ 330 }else{
330 if(sl==(t.length()-1)) 331 if(sl==(t.length()-1))
331 t.erase(sl); 332 t.erase(sl);
332 else 333 else
333 t.erase(sl+1); 334 t.erase(sl+1);
334 } 335 }
335 } 336 }
336 } 337 }
337 338
338 config_options::action_handler_t *configuration::lookup_action_handler(const string& target) { 339 config_options::action_handler_t *configuration::lookup_action_handler(const string& target) {
339 string t = "/"; 340 string t = "/";
340 t += normalize_path(target,strip_leading_slash); 341 t += konforka::normalize_path(target,konforka::strip_leading_slash);
341 for(;;) { 342 for(;;) {
342 if(t[t.length()-1]=='/') { 343 if(t[t.length()-1]=='/') {
343 loaded_options* lo = lookup_loaded_options(t); 344 loaded_options* lo = lookup_loaded_options(t);
344 if( lo && (lo->flags&config_options::flag_action_handlers) ) { 345 if( lo && (lo->flags&config_options::flag_action_handlers) ) {
345 config_options::action_handler_t *rv = lo->lookup_action_handler(target); 346 config_options::action_handler_t *rv = lo->lookup_action_handler(target);
346 if(rv) 347 if(rv)
347 return rv; 348 return rv;
348 } 349 }
349 } 350 }
350 specs_t::iterator i = specs.find(t); 351 specs_t::iterator i = specs.find(t);
351 if( i!=specs.end() && (i->second.flags&&config_options::flag_action_handlers) ) { 352 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 config_options::action_handler_t *rv = i->second.lookup_action_handler(target);
353 if(rv) 354 if(rv)
354 return rv; 355 return rv;
355 } 356 }
356 if(t.empty()) 357 if(t.empty())
357 return NULL; 358 return NULL;
358 string::size_type sl=t.rfind('/'); 359 string::size_type sl=t.rfind('/');
359 if(sl==string::npos) { 360 if(sl==string::npos) {
360 t.erase(); 361 t.erase();
361 }else{ 362 }else{
362 if(sl==(t.length()-1)) 363 if(sl==(t.length()-1))
363 t.erase(sl); 364 t.erase(sl);
364 else 365 else
365 t.erase(sl+1); 366 t.erase(sl+1);
366 } 367 }
367 } 368 }
368 } 369 }
369 370
370 config_options* configuration::lookup_config(const string& target,int flag) { 371 config_options* configuration::lookup_config(const string& target,int flag) {
371 string t = "/"; // always assume leading slash 372 string t = "/"; // always assume leading slash
372 t += normalize_path(target,strip_leading_slash); 373 t += konforka::normalize_path(target,konforka::strip_leading_slash);
373 // XXX: reconsider precedence 374 // XXX: reconsider precedence
374 for(;;) { 375 for(;;) {
375 if(t[t.length()-1]=='/') { 376 if(t[t.length()-1]=='/') {
376 loaded_options* lo = lookup_loaded_options(t); 377 loaded_options* lo = lookup_loaded_options(t);
377 if( lo && (lo->flags&flag)==flag ) 378 if( lo && (lo->flags&flag)==flag )
378 return lo; 379 return lo;
379 } 380 }
380 specs_t::iterator i = specs.find(t); 381 specs_t::iterator i = specs.find(t);
381 if( i!=specs.end() && (i->second.flags&flag)==flag ) 382 if( i!=specs.end() && (i->second.flags&flag)==flag )
382 return &(i->second); 383 return &(i->second);
383 if(t.empty()) 384 if(t.empty())
384 return NULL; 385 return NULL;
385 string::size_type sl=t.rfind('/'); 386 string::size_type sl=t.rfind('/');
386 if(sl==string::npos) { 387 if(sl==string::npos) {
387 t.erase(); 388 t.erase();
388 }else{ 389 }else{
389 if(sl==(t.length()-1)) 390 if(sl==(t.length()-1))
390 t.erase(sl); 391 t.erase(sl);
391 else 392 else
392 t.erase(sl+1); 393 t.erase(sl+1);
393 } 394 }
394 } 395 }
395 } 396 }
396 397
397 bool config_options::match_autobuild_files(const char *fn,bool &rv) { 398 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 for(list<string>::reverse_iterator i=auto_build_files.rbegin();i!=auto_build_files.rend();++i) {
399 const char *pat = i->c_str(); 400 const char *pat = i->c_str();
400 bool plus = true; 401 bool plus = true;
401 if((*pat)=='+') 402 if((*pat)=='+')
402 pat++; 403 pat++;
403 else if((*pat)=='-') { 404 else if((*pat)=='-') {
404 plus = false; 405 plus = false;
405 pat++; 406 pat++;
406 } 407 }
407 if(!fnmatch(pat,fn,FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD)) { 408 if(!fnmatch(pat,fn,FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD)) {
408 rv = plus; 409 rv = plus;
409 return true; 410 return true;
410 } 411 }
411 } 412 }
412 return false; 413 return false;
413 } 414 }
414 415
415 bool configuration::match_autobuild_files(const string& target,const char *fn) { 416 bool configuration::match_autobuild_files(const string& target,const char *fn) {
416 string t = "/"; 417 string t = "/";
417 t += normalize_path(target,strip_leading_slash|strip_trailing_slash); 418 t += konforka::normalize_path(target,konforka::strip_leading_slash|konforka::strip_trailing_slash);
418 t += "/"; 419 t += "/";
419 bool rv = false; 420 bool rv = false;
420 for(;;) { 421 for(;;) {
421 if(t[t.length()-1]=='/') { 422 if(t[t.length()-1]=='/') {
422 loaded_options* lo = lookup_loaded_options(t); 423 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 if(lo && (lo->flags&config_options::flag_auto_build_files) && lo->match_autobuild_files(fn,rv) )
424 return rv; 425 return rv;
425 } 426 }
426 specs_t::iterator i = specs.find(t); 427 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 if( i!=specs.end() && (i->second.flags&config_options::flag_auto_build_files) && i->second.match_autobuild_files(fn,rv) )
428 return rv; 429 return rv;
429 if(t.empty()) 430 if(t.empty())
430 return rv; 431 return rv;
431 string::size_type sl=t.rfind('/'); 432 string::size_type sl=t.rfind('/');
432 if(sl==string::npos) { 433 if(sl==string::npos) {
433 t.erase(); 434 t.erase();
434 }else{ 435 }else{
435 if(sl==(t.length()-1)) 436 if(sl==(t.length()-1))
436 t.erase(sl); 437 t.erase(sl);
437 else 438 else
438 t.erase(sl+1); 439 t.erase(sl+1);
439 } 440 }
440 } 441 }
441 } 442 }
442 443
443 void configuration::parse(const string& cfile) { 444 void configuration::parse(const string& cfile) {
444 struct dc_context dcc; 445 struct dc_context dcc;
445 dcc.cf = this; 446 dcc.cf = this;
446 dcc.ctx = DCC_ROOT; 447 dcc.ctx = DCC_ROOT;
447 dcc.co.push_front(&root_options()); 448 dcc.co.push_front(&root_options());
448 configfile_t *cf = dotconf_create((char*)cfile.c_str(),dc_options,(context_t*)&dcc,CASE_INSENSITIVE); 449 configfile_t *cf = dotconf_create((char*)cfile.c_str(),dc_options,(context_t*)&dcc,CASE_INSENSITIVE);
449 if(!cf) 450 if(!cf)
450 throw konforka::exception(CODEPOINT,"failed to dotconf_create()"); 451 throw konforka::exception(CODEPOINT,"failed to dotconf_create()");
451 cf->errorhandler = (dotconf_errorhandler_t) dc_error_handler; 452 cf->errorhandler = (dotconf_errorhandler_t) dc_error_handler;
452 cf->contextchecker = (dotconf_contextchecker_t) dc_context_checker; 453 cf->contextchecker = (dotconf_contextchecker_t) dc_context_checker;
453 if(!dotconf_command_loop(cf)) 454 if(!dotconf_command_loop(cf))
454 throw konforka::exception(CODEPOINT,"failed to dotconf_command_loop()"); 455 throw konforka::exception(CODEPOINT,"failed to dotconf_command_loop()");
455 dotconf_cleanup(cf); 456 dotconf_cleanup(cf);
456 } 457 }
457 458
458 void loaded_options::parse(configuration *config,const string& cfile) { 459 void loaded_options::parse(configuration *config,const string& cfile) {
459 struct dc_context dcc; 460 struct dc_context dcc;
460 dcc.cf = config; 461 dcc.cf = config;
461 dcc.ctx = DCC_SCRC; 462 dcc.ctx = DCC_SCRC;
462 dcc.co.push_front(this); 463 dcc.co.push_front(this);
463 configfile_t *cf = dotconf_create((char*)cfile.c_str(),dc_options,(context_t*)&dcc,CASE_INSENSITIVE); 464 configfile_t *cf = dotconf_create((char*)cfile.c_str(),dc_options,(context_t*)&dcc,CASE_INSENSITIVE);
464 if(!cf) 465 if(!cf)
465 throw konforka::exception(CODEPOINT,"failed to dotconf_create()"); 466 throw konforka::exception(CODEPOINT,"failed to dotconf_create()");
466 cf->errorhandler = (dotconf_errorhandler_t) dc_error_handler; 467 cf->errorhandler = (dotconf_errorhandler_t) dc_error_handler;
467 cf->contextchecker = (dotconf_contextchecker_t) dc_context_checker; 468 cf->contextchecker = (dotconf_contextchecker_t) dc_context_checker;
468 if(!dotconf_command_loop(cf)) 469 if(!dotconf_command_loop(cf))
469 throw konforka::exception(CODEPOINT,"failed to dotconf_command_loop()"); 470 throw konforka::exception(CODEPOINT,"failed to dotconf_command_loop()");
470 dotconf_cleanup(cf); 471 dotconf_cleanup(cf);
471 source_file = cfile; 472 source_file = cfile;
472 stat(cfile.c_str(),&st); // TODO: handle errors? 473 stat(cfile.c_str(),&st); // TODO: handle errors?
473 } 474 }
474} 475}