-rw-r--r-- | lib/configuration.cc | 9 |
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,474 +1,475 @@ | |||
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 | ||
15 | namespace sitecing { | 16 | namespace 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; |
105 | dcc->cf->flags |= configuration::flag_group; | 106 | dcc->cf->flags |= configuration::flag_group; |
106 | return NULL; | 107 | return NULL; |
107 | } | 108 | } |
108 | static DOTCONF_CB(dco_chroot) { dc_context *dcc = (dc_context*)ctx; | 109 | static DOTCONF_CB(dco_chroot) { dc_context *dcc = (dc_context*)ctx; |
109 | dcc->cf->chroot = cmd->data.str; | 110 | dcc->cf->chroot = cmd->data.str; |
110 | dcc->cf->flags |= configuration::flag_chroot; | 111 | dcc->cf->flags |= configuration::flag_chroot; |
111 | return NULL; | 112 | return NULL; |
112 | } | 113 | } |
113 | static DOTCONF_CB(dco_pid_file) { dc_context *dcc = (dc_context*)ctx; | 114 | static DOTCONF_CB(dco_pid_file) { dc_context *dcc = (dc_context*)ctx; |
114 | dcc->cf->pid_file = cmd->data.str; | 115 | dcc->cf->pid_file = cmd->data.str; |
115 | dcc->cf->flags |= configuration::flag_pid_file; | 116 | dcc->cf->flags |= configuration::flag_pid_file; |
116 | return NULL; | 117 | return NULL; |
117 | } | 118 | } |
118 | static DOTCONF_CB(dco_daemonize) { dc_context *dcc = (dc_context*) ctx; | 119 | static DOTCONF_CB(dco_daemonize) { dc_context *dcc = (dc_context*) ctx; |
119 | dcc->cf->daemonize = cmd->data.value; | 120 | dcc->cf->daemonize = cmd->data.value; |
120 | dcc->cf->flags |= configuration::flag_daemonize; | 121 | dcc->cf->flags |= configuration::flag_daemonize; |
121 | return NULL; | 122 | return NULL; |
122 | } | 123 | } |
123 | 124 | ||
124 | static DOTCONF_CB(dco_path) { dc_context *dcc = (dc_context*)ctx; | 125 | static DOTCONF_CB(dco_path) { dc_context *dcc = (dc_context*)ctx; |
125 | string path = cmd->data.str; | 126 | string path = cmd->data.str; |
126 | if(path[path.length()-1]=='>') | 127 | if(path[path.length()-1]=='>') |
127 | path.erase(path.length()-1); | 128 | path.erase(path.length()-1); |
128 | // TODO: normalize path | 129 | // TODO: normalize path |
129 | dcc->co.push_front(&(dcc->cf->specs[path])); | 130 | dcc->co.push_front(&(dcc->cf->specs[path])); |
130 | dcc->ctx = DCC_PATH; // TODO: stack it, instead | 131 | dcc->ctx = DCC_PATH; // TODO: stack it, instead |
131 | return NULL; | 132 | return NULL; |
132 | } | 133 | } |
133 | static DOTCONF_CB(dco__path) { dc_context *dcc = (dc_context*)ctx; | 134 | static DOTCONF_CB(dco__path) { dc_context *dcc = (dc_context*)ctx; |
134 | dcc->co.pop_front(); | 135 | dcc->co.pop_front(); |
135 | assert(dcc->co.size()); | 136 | assert(dcc->co.size()); |
136 | dcc->ctx = DCC_ROOT; // TODO: stack it, instead | 137 | dcc->ctx = DCC_ROOT; // TODO: stack it, instead |
137 | return NULL; | 138 | return NULL; |
138 | } | 139 | } |
139 | 140 | ||
140 | static DOTCONF_CB(dco_skeleton) { dc_context *dcc = (dc_context*)ctx; | 141 | static DOTCONF_CB(dco_skeleton) { dc_context *dcc = (dc_context*)ctx; |
141 | dcc->co.front()->skeleton = cmd->data.str; | 142 | dcc->co.front()->skeleton = cmd->data.str; |
142 | dcc->co.front()->flags |= config_options::flag_skeleton; | 143 | dcc->co.front()->flags |= config_options::flag_skeleton; |
143 | return NULL; | 144 | return NULL; |
144 | } | 145 | } |
145 | static DOTCONF_CB(dco_cpp_flags) { dc_context *dcc = (dc_context*)ctx; | 146 | static DOTCONF_CB(dco_cpp_flags) { dc_context *dcc = (dc_context*)ctx; |
146 | for(char **arg=cmd->data.list;*arg;arg++) | 147 | for(char **arg=cmd->data.list;*arg;arg++) |
147 | dcc->co.front()->cpp_flags.push_back(*arg); | 148 | dcc->co.front()->cpp_flags.push_back(*arg); |
148 | dcc->co.front()->flags |= config_options::flag_cpp_flags; | 149 | dcc->co.front()->flags |= config_options::flag_cpp_flags; |
149 | return NULL; | 150 | return NULL; |
150 | } | 151 | } |
151 | static DOTCONF_CB(dco_ld_flags) { dc_context *dcc = (dc_context*)ctx; | 152 | static DOTCONF_CB(dco_ld_flags) { dc_context *dcc = (dc_context*)ctx; |
152 | for(char **arg=cmd->data.list;*arg;arg++) | 153 | for(char **arg=cmd->data.list;*arg;arg++) |
153 | dcc->co.front()->ld_flags.push_back(*arg); | 154 | dcc->co.front()->ld_flags.push_back(*arg); |
154 | dcc->co.front()->flags |= config_options::flag_ld_flags; | 155 | dcc->co.front()->flags |= config_options::flag_ld_flags; |
155 | return NULL; | 156 | return NULL; |
156 | } | 157 | } |
157 | static DOTCONF_CB(dco_intermediate_deps) { dc_context *dcc = (dc_context*) ctx; | 158 | static DOTCONF_CB(dco_intermediate_deps) { dc_context *dcc = (dc_context*) ctx; |
158 | for(char **arg=cmd->data.list;*arg;arg++) | 159 | for(char **arg=cmd->data.list;*arg;arg++) |
159 | dcc->co.front()->intermediate_deps.push_back(*arg); | 160 | dcc->co.front()->intermediate_deps.push_back(*arg); |
160 | dcc->co.front()->flags |= config_options::flag_intermediate_deps; | 161 | dcc->co.front()->flags |= config_options::flag_intermediate_deps; |
161 | return NULL; | 162 | return NULL; |
162 | } | 163 | } |
163 | static DOTCONF_CB(dco_so_deps) { dc_context *dcc = (dc_context*) ctx; | 164 | static DOTCONF_CB(dco_so_deps) { dc_context *dcc = (dc_context*) ctx; |
164 | for(char **arg=cmd->data.list;*arg;arg++) | 165 | for(char **arg=cmd->data.list;*arg;arg++) |
165 | dcc->co.front()->so_deps.push_back(*arg); | 166 | dcc->co.front()->so_deps.push_back(*arg); |
166 | dcc->co.front()->flags |= config_options::flag_so_deps; | 167 | dcc->co.front()->flags |= config_options::flag_so_deps; |
167 | return NULL; | 168 | return NULL; |
168 | } | 169 | } |
169 | static DOTCONF_CB(dco_build) { dc_context *dcc = (dc_context*)ctx; | 170 | static DOTCONF_CB(dco_build) { dc_context *dcc = (dc_context*)ctx; |
170 | dcc->co.front()->build = cmd->data.value; | 171 | dcc->co.front()->build = cmd->data.value; |
171 | dcc->co.front()->flags |= config_options::flag_build; | 172 | dcc->co.front()->flags |= config_options::flag_build; |
172 | return NULL; | 173 | return NULL; |
173 | } | 174 | } |
174 | static DOTCONF_CB(dco_cpp_deps) { dc_context *dcc = (dc_context*)ctx; | 175 | 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()->cpp_deps = cmd->data.value; |
176 | dcc->co.front()->flags |= config_options::flag_cpp_deps; | 177 | dcc->co.front()->flags |= config_options::flag_cpp_deps; |
177 | return NULL; | 178 | return NULL; |
178 | } | 179 | } |
179 | static DOTCONF_CB(dco_exception_handler) { dc_context *dcc = (dc_context*)ctx; | 180 | 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()->exception_handler = cmd->data.str; |
181 | dcc->co.front()->flags |= config_options::flag_exception_handler; | 182 | dcc->co.front()->flags |= config_options::flag_exception_handler; |
182 | return NULL; | 183 | return NULL; |
183 | } | 184 | } |
184 | static DOTCONF_CB(dco_http_status_handler) { dc_context *dcc = (dc_context*)ctx; | 185 | static DOTCONF_CB(dco_http_status_handler) { dc_context *dcc = (dc_context*)ctx; |
185 | if(cmd->arg_count!=2) | 186 | if(cmd->arg_count!=2) |
186 | return "Invalid number of arguments"; | 187 | return "Invalid number of arguments"; |
187 | dcc->co.front()->http_status_handlers[cmd->data.list[0]] = cmd->data.list[1]; | 188 | 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 | dcc->co.front()->flags |= config_options::flag_http_status_handlers; |
189 | return NULL; | 190 | return NULL; |
190 | } | 191 | } |
191 | static DOTCONF_CB(dco_action) { dc_context *dcc = (dc_context*)ctx; | 192 | static DOTCONF_CB(dco_action) { dc_context *dcc = (dc_context*)ctx; |
192 | if(cmd->arg_count<2) | 193 | if(cmd->arg_count<2) |
193 | return "Invalid number of arguments"; | 194 | return "Invalid number of arguments"; |
194 | try { | 195 | try { |
195 | char **arg=cmd->data.list; | 196 | char **arg=cmd->data.list; |
196 | dcc->co.front()->action_handlers.push_back(config_options::action_handler_t(arg[0],arg[1])); | 197 | dcc->co.front()->action_handlers.push_back(config_options::action_handler_t(arg[0],arg[1])); |
197 | for(arg+=2;*arg;arg++) | 198 | for(arg+=2;*arg;arg++) |
198 | dcc->co.front()->action_handlers.back().args.push_back(*arg); | 199 | dcc->co.front()->action_handlers.back().args.push_back(*arg); |
199 | dcc->co.front()->flags |= config_options::flag_action_handlers; | 200 | dcc->co.front()->flags |= config_options::flag_action_handlers; |
200 | }catch(exception& e) { | 201 | }catch(exception& e) { |
201 | return "Error processing Action directive"; // XXX: could be done better | 202 | return "Error processing Action directive"; // XXX: could be done better |
202 | } | 203 | } |
203 | return NULL; | 204 | return NULL; |
204 | } | 205 | } |
205 | static DOTCONF_CB(dco_auto_build_files) { dc_context *dcc = (dc_context*)ctx; | 206 | static DOTCONF_CB(dco_auto_build_files) { dc_context *dcc = (dc_context*)ctx; |
206 | if(!( dcc->cf && dcc->cf->autobuild)) | 207 | if(!( dcc->cf && dcc->cf->autobuild)) |
207 | return NULL; | 208 | return NULL; |
208 | for(char **arg=cmd->data.list;*arg;arg++) | 209 | for(char **arg=cmd->data.list;*arg;arg++) |
209 | dcc->co.front()->auto_build_files.push_back(*arg); | 210 | dcc->co.front()->auto_build_files.push_back(*arg); |
210 | dcc->co.front()->flags |= config_options::flag_auto_build_files; | 211 | dcc->co.front()->flags |= config_options::flag_auto_build_files; |
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 | } |