rev |
line source |
jbe@203
|
1 #!/usr/bin/env moonbridge
|
jbe/bsw@0
|
2
|
jbe@294
|
3 --[[--
|
jbe@294
|
4 WEBMCP_VERSION
|
jbe@294
|
5
|
jbe@294
|
6 A string containing the WebMCP version, e.g. "2.0.0"
|
jbe@294
|
7 --]]--
|
jbe@363
|
8 WEBMCP_VERSION = "2.0.2"
|
jbe@294
|
9 --//--
|
jbe@64
|
10
|
jbe@317
|
11 --[[--
|
jbe@294
|
12 WEBMCP_MODE
|
jbe@294
|
13
|
jbe@294
|
14 A constant set to "listen" in case of a network request, or set to "interactive" in case of interactive mode.
|
jbe@294
|
15 --]]--
|
jbe@323
|
16 if _MOONBRIDGE_VERSION then
|
jbe@203
|
17 WEBMCP_MODE = "listen"
|
jbe@203
|
18 else
|
jbe@203
|
19 WEBMCP_MODE = "interactive"
|
jbe@64
|
20 end
|
jbe@294
|
21 --//--
|
jbe@203
|
22
|
jbe@294
|
23 --[[--
|
jbe@294
|
24 WEBMCP_CONFIG_NAMES
|
jbe@294
|
25
|
jbe@294
|
26 A list of the selected configuration names.
|
jbe@294
|
27 --]]--
|
jbe@294
|
28 -- configuration names are provided as 4th, 5th, etc. command line argument
|
jbe@206
|
29 WEBMCP_CONFIG_NAMES = {select(4, ...)}
|
jbe@294
|
30 --//--
|
jbe@294
|
31
|
jbe@294
|
32 --[[--
|
jbe@294
|
33 WEBMCP_FRAMEWORK_PATH
|
jbe@294
|
34
|
jbe@294
|
35 Directory of the WebMCP framework (always includes a trailing slash).
|
jbe@294
|
36 --]]--
|
jbe@294
|
37 -- set in mcp.lua
|
jbe@294
|
38 --//--
|
jbe@294
|
39
|
jbe@294
|
40 --[[--
|
jbe@294
|
41 WEBMCP_BASE_PATH
|
jbe@294
|
42
|
jbe@294
|
43 Base directory of the application (always includes a trailing slash).
|
jbe@294
|
44 --]]--
|
jbe@294
|
45 -- set in mcp.lua
|
jbe@294
|
46 --//--
|
jbe@294
|
47
|
jbe@294
|
48 --[[--
|
jbe@294
|
49 WEBMCP_APP_NAME
|
jbe@294
|
50
|
jbe@294
|
51 Application name (usually "main"). May be nil in case of interactive mode.
|
jbe@294
|
52 --]]--
|
jbe@294
|
53 -- set in mcp.lua
|
jbe@294
|
54 --//--
|
jbe@203
|
55
|
jbe@203
|
56 -- determine framework and bath path from command line arguments
|
jbe@203
|
57 -- or print usage synopsis (if applicable)
|
jbe@68
|
58 do
|
jbe@206
|
59 local arg1, arg2, arg3 = ...
|
jbe@203
|
60 local helpout
|
jbe@203
|
61 if
|
jbe@203
|
62 arg1 == "-h" or arg1 == "--help" or
|
jbe@206
|
63 arg2 == "-h" or arg2 == "--help" -- if first arg is provided by wrapper
|
jbe@203
|
64 then
|
jbe@203
|
65 helpout = io.stdout
|
jbe@316
|
66 elseif #WEBMCP_CONFIG_NAMES < 1 then
|
jbe@203
|
67 helpout = io.stderr
|
jbe@203
|
68 end
|
jbe@203
|
69 if helpout then
|
jbe@316
|
70 helpout:write("Usage: moonbridge [moonbr opts] -- <framework path>/bin/mcp.lua <framework path> <app base path> <app name> <config name> [<config name> ...]\n")
|
jbe@316
|
71 helpout:write(" or: lua -i [Lua opts] -- <framework path>/bin/mcp.lua <framework path> <app base path> <app name> <config name> [<config name> ...]\n")
|
jbe@203
|
72 if helpout == io.stderr then
|
jbe@203
|
73 return 1
|
jbe@68
|
74 else
|
jbe@203
|
75 return 0
|
jbe@68
|
76 end
|
jbe@68
|
77 end
|
jbe@203
|
78 local function append_trailing_slash(str)
|
jbe@217
|
79 return string.gsub(str, "([^/])$", function(last) return last .. "/" end)
|
jbe@203
|
80 end
|
jbe@203
|
81 WEBMCP_FRAMEWORK_PATH = append_trailing_slash(arg1)
|
jbe@203
|
82 WEBMCP_BASE_PATH = append_trailing_slash(arg2)
|
jbe@316
|
83 WEBMCP_APP_NAME = arg3
|
jbe@68
|
84 end
|
jbe@1
|
85
|
jbe@203
|
86 -- setup search paths for libraries
|
jbe/bsw@0
|
87 do
|
jbe@217
|
88 if string.match(package.path, "^[^;]") then
|
jbe@217
|
89 package.path = ";" .. package.path
|
jbe@217
|
90 end
|
jbe@217
|
91 package.path = WEBMCP_FRAMEWORK_PATH .. "lib/?.lua" .. package.path
|
jbe/bsw@0
|
92 -- find out which file name extension shared libraries have
|
jbe/bsw@0
|
93 local slib_exts = {}
|
jbe/bsw@0
|
94 for ext in string.gmatch(package.cpath, "%?%.([A-Za-z0-9_-]+)") do
|
jbe@217
|
95 if not slib_exts[ext] then
|
jbe@217
|
96 slib_exts[#slib_exts+1] = ext
|
jbe@217
|
97 slib_exts[ext] = true
|
jbe@217
|
98 end
|
jbe/bsw@0
|
99 end
|
jbe/bsw@0
|
100 local paths = {}
|
jbe@217
|
101 for i, ext in ipairs(slib_exts) do
|
jbe@203
|
102 paths[#paths+1] = WEBMCP_FRAMEWORK_PATH .. "accelerator/?." .. ext
|
jbe/bsw@0
|
103 end
|
jbe@217
|
104 for i, ext in ipairs(slib_exts) do
|
jbe@203
|
105 paths[#paths+1] = WEBMCP_FRAMEWORK_PATH .. "lib/?." .. ext
|
jbe/bsw@0
|
106 end
|
jbe/bsw@0
|
107 paths[#paths+1] = package.cpath
|
jbe/bsw@0
|
108 package.cpath = table.concat(paths, ";")
|
jbe/bsw@0
|
109 end
|
jbe/bsw@0
|
110
|
jbe@352
|
111 -- load "extos" library (needed by function "loadcached")
|
jbe@352
|
112 _G.extos = require "extos"
|
jbe@352
|
113
|
jbe@352
|
114 --[[--
|
jbe@352
|
115 _G
|
jbe@352
|
116
|
jbe@352
|
117 A reference to the global namespace. To avoid accidental programming errors, global variables cannot be set directly, but they must be set through the _G reference, e.g. use _G.foo = true to set the variable "foo" to a value of true.
|
jbe@352
|
118
|
jbe@352
|
119 Note that the global namespace may or may not be shared between requests (Moonbridge creates multiple forks of the Lua machine). To set variables that are to be cleared after the request has been finished, an application may use the "app" table, e.g. app.foo = true to set the variable app.foo to a value of true, which will be cleared automatically when the request has ended.
|
jbe@352
|
120
|
jbe@352
|
121 --]]--
|
jbe@352
|
122 local _G = _G
|
jbe@352
|
123 local allowed_globals = {}
|
jbe@352
|
124 local protected_environment = setmetatable(
|
jbe@352
|
125 {}, -- proxy environment used all chunks loaded through loadcached(...)
|
jbe@352
|
126 {
|
jbe@352
|
127 __index = _G,
|
jbe@352
|
128 __newindex = function(self, key, value)
|
jbe@352
|
129 if allowed_globals[key] then
|
jbe@352
|
130 _G[key] = value
|
jbe@352
|
131 else
|
jbe@352
|
132 if type(key) == "string" and string.match(key, "^[A-Za-z_][A-Za-z_0-9]*$") then
|
jbe@352
|
133 error('Attempt to set global variable "' .. key .. '" (Hint: missing local statement? Use _G.' .. key .. '=<value> to really set global variable.)', 2)
|
jbe@352
|
134 else
|
jbe@352
|
135 error('Attempt to set global variable', 2)
|
jbe@352
|
136 end
|
jbe@352
|
137 end
|
jbe@352
|
138 end
|
jbe@352
|
139 }
|
jbe@352
|
140 )
|
jbe@352
|
141 --//--
|
jbe@352
|
142
|
jbe@352
|
143 --[[--
|
jbe@354
|
144 lua_func, -- compiled Lua function, nil if the file does not exist
|
jbe@354
|
145 errmsg = -- error message (only for non-existing file, other errors are thrown)
|
jbe@352
|
146 loadcached(
|
jbe@352
|
147 filename -- path to a Lua source or byte-code file
|
jbe@352
|
148 )
|
jbe@352
|
149
|
jbe@352
|
150 Loads, compiles and caches a Lua chunk. The cached value (i.e. the compiled function) is returned. If the file does not exist, nil and an error string are returned. Any other errors are thrown using error(...). Unsuccessful attempts are not cached (to prohibit cache pollution).
|
jbe@352
|
151
|
jbe@352
|
152 --]]--
|
jbe@352
|
153 do
|
jbe@352
|
154 local cache = {}
|
jbe@352
|
155 function loadcached(filename)
|
jbe@352
|
156 local cached_func = cache[filename]
|
jbe@352
|
157 if cached_func then
|
jbe@352
|
158 return cached_func
|
jbe@352
|
159 end
|
jbe@352
|
160 local stat, errmsg = extos.stat(filename)
|
jbe@352
|
161 if stat == nil then
|
jbe@352
|
162 error(errmsg)
|
jbe@352
|
163 elseif stat == false then
|
jbe@352
|
164 return nil, 'File "' .. filename .. '" does not exist'
|
jbe@352
|
165 elseif stat.isdir then
|
jbe@352
|
166 error('File "' .. filename .. '" is a directory')
|
jbe@352
|
167 elseif not stat.isreg then
|
jbe@352
|
168 error('File "' .. filename .. '" is not a regular file')
|
jbe@352
|
169 end
|
jbe@352
|
170 local func, compile_error = loadfile(filename, nil, protected_environment)
|
jbe@352
|
171 if func then
|
jbe@352
|
172 cache[filename] = func
|
jbe@352
|
173 return func
|
jbe@352
|
174 end
|
jbe@352
|
175 error(compile_error, 0)
|
jbe@352
|
176 end
|
jbe@352
|
177 end
|
jbe@352
|
178 --//--
|
jbe@352
|
179
|
jbe@352
|
180 -- check if framework path is correct
|
jbe@352
|
181 do
|
jbe@352
|
182 local file, errmsg = io.open(WEBMCP_FRAMEWORK_PATH .. "webmcp_version", "r")
|
jbe@352
|
183 if not file then
|
jbe@352
|
184 error('Could not find "webmcp_version" file: ' .. errmsg, 0)
|
jbe@352
|
185 end
|
jbe@352
|
186 local version = assert(file:read())
|
jbe@352
|
187 assert(file:close())
|
jbe@352
|
188 if version ~= WEBMCP_VERSION then
|
jbe@352
|
189 error('Version mismatch in file "' .. WEBMCP_FRAMEWORK_PATH .. 'webmcp_version"')
|
jbe@352
|
190 end
|
jbe@352
|
191 end
|
jbe@352
|
192
|
jbe@203
|
193 -- autoloader system for WebMCP environment "$WEBMCP_FRAMEWORK_PATH/env/",
|
jbe@203
|
194 -- application environment extensions "$WEBMCP_BASE_PATH/env/"
|
jbe@203
|
195 -- and models "$WEBMCP_BASE_PATH/model/"
|
jbe/bsw@0
|
196 do
|
jbe/bsw@0
|
197 local weakkey_mt = { __mode = "k" }
|
jbe/bsw@0
|
198 local autoloader_category = setmetatable({}, weakkey_mt)
|
jbe/bsw@0
|
199 local autoloader_path = setmetatable({}, weakkey_mt)
|
jbe/bsw@0
|
200 local autoloader_mt = {}
|
jbe@219
|
201 local function install_autoloader(self, category, path_fragment)
|
jbe/bsw@0
|
202 autoloader_category[self] = category
|
jbe@219
|
203 autoloader_path[self] = path_fragment
|
jbe/bsw@0
|
204 setmetatable(self, autoloader_mt)
|
jbe/bsw@0
|
205 end
|
jbe/bsw@0
|
206 local function try_exec(filename)
|
jbe@309
|
207 local func = loadcached(filename)
|
jbe@309
|
208 if func then
|
jbe@309
|
209 func()
|
jbe@309
|
210 return true
|
jbe/bsw@0
|
211 else
|
jbe/bsw@0
|
212 return false
|
jbe/bsw@0
|
213 end
|
jbe/bsw@0
|
214 end
|
jbe/bsw@0
|
215 function autoloader_mt.__index(self, key)
|
jbe/bsw@0
|
216 local category, base_path, merge_base_path, file_key
|
jbe/bsw@0
|
217 local merge = false
|
jbe/bsw@0
|
218 if
|
jbe/bsw@0
|
219 string.find(key, "^[a-z_][A-Za-z0-9_]*$") and
|
jbe/bsw@0
|
220 not string.find(key, "^__")
|
jbe/bsw@0
|
221 then
|
jbe/bsw@0
|
222 category = "env"
|
jbe@203
|
223 base_path = WEBMCP_FRAMEWORK_PATH .. "env/"
|
jbe/bsw@0
|
224 merge = true
|
jbe@203
|
225 merge_base_path = WEBMCP_BASE_PATH .. "env/"
|
jbe/bsw@0
|
226 file_key = key
|
jbe/bsw@0
|
227 elseif string.find(key, "^[A-Z][A-Za-z0-9]*$") then
|
jbe/bsw@0
|
228 category = "model"
|
jbe@203
|
229 base_path = WEBMCP_BASE_PATH .. "model/"
|
jbe/bsw@0
|
230 local first = true
|
jbe/bsw@0
|
231 file_key = string.gsub(key, "[A-Z]",
|
jbe/bsw@0
|
232 function(c)
|
jbe/bsw@0
|
233 if first then
|
jbe/bsw@0
|
234 first = false
|
jbe/bsw@0
|
235 return string.lower(c)
|
jbe/bsw@0
|
236 else
|
jbe/bsw@0
|
237 return "_" .. string.lower(c)
|
jbe/bsw@0
|
238 end
|
jbe/bsw@0
|
239 end
|
jbe/bsw@0
|
240 )
|
jbe/bsw@0
|
241 else
|
jbe/bsw@0
|
242 return
|
jbe/bsw@0
|
243 end
|
jbe/bsw@0
|
244 local required_category = autoloader_category[self]
|
jbe/bsw@0
|
245 if required_category and required_category ~= category then return end
|
jbe@219
|
246 local path_fragment = autoloader_path[self]
|
jbe@219
|
247 local path = base_path .. path_fragment .. file_key
|
jbe@219
|
248 local merge_path
|
jbe/bsw@0
|
249 if merge then
|
jbe@219
|
250 merge_path = merge_base_path .. path_fragment .. file_key
|
jbe/bsw@0
|
251 end
|
jbe/bsw@0
|
252 local function try_dir(dirname)
|
jbe/bsw@0
|
253 local dir = io.open(dirname)
|
jbe/bsw@0
|
254 if dir then
|
jbe/bsw@0
|
255 io.close(dir)
|
jbe/bsw@0
|
256 local obj = {}
|
jbe@219
|
257 install_autoloader(obj, category, path_fragment .. file_key .. "/")
|
jbe/bsw@0
|
258 rawset(self, key, obj)
|
jbe@219
|
259 try_exec(path .. "/__init.lua")
|
jbe@219
|
260 if merge then try_exec(merge_path .. "/__init.lua") end
|
jbe/bsw@0
|
261 return true
|
jbe/bsw@0
|
262 else
|
jbe/bsw@0
|
263 return false
|
jbe/bsw@0
|
264 end
|
jbe/bsw@0
|
265 end
|
jbe@238
|
266 if self == _G then
|
jbe@237
|
267 allowed_globals[key] = true
|
jbe@233
|
268 end
|
jbe@219
|
269 if merge and try_exec(merge_path .. ".lua") then
|
jbe@219
|
270 elseif merge and try_dir(merge_path .. "/") then
|
jbe@219
|
271 elseif try_exec(path .. ".lua") then
|
jbe@219
|
272 elseif try_dir(path .. "/") then
|
jbe/bsw@0
|
273 else end
|
jbe@238
|
274 if self == _G then
|
jbe@237
|
275 allowed_globals[key] = nil
|
jbe@233
|
276 end
|
jbe@237
|
277 return rawget(self, key)
|
jbe/bsw@0
|
278 end
|
jbe@219
|
279 install_autoloader(_G, nil, "")
|
jbe@324
|
280 try_exec(WEBMCP_FRAMEWORK_PATH .. "env/__init.lua")
|
jbe@324
|
281 try_exec(WEBMCP_BASE_PATH .. "env/__init.lua")
|
jbe@214
|
282 end
|
jbe@214
|
283
|
jbe@286
|
284 -- define post-fork initialization function (including loading of "multirand" library)
|
jbe@286
|
285 local function postfork_init()
|
jbe@324
|
286 multirand = require "multirand"
|
jbe@286
|
287 execute.postfork_initializers()
|
jbe@286
|
288 end
|
jbe@286
|
289
|
jbe@336
|
290 --[[--
|
jbe@336
|
291 listen{
|
jbe@336
|
292 {
|
jbe@336
|
293 proto = proto, -- "local", "tcp4", "tcp6", or "interval"
|
jbe@336
|
294 path = path, -- path to unix domain socket if proto == "local"
|
jbe@336
|
295 port = port, -- TCP port number
|
jbe@336
|
296 localhost = localhost_only, -- set to true to only listen on localhost (127.0.0.1 or ::1) interface
|
jbe@336
|
297 name = interval_name, -- optional interval name (may be useful for log output)
|
jbe@336
|
298 handler = interval_handler -- interval handler if proto == "interval"
|
jbe@336
|
299 },
|
jbe@336
|
300 {
|
jbe@336
|
301 ... -- second listener
|
jbe@336
|
302 },
|
jbe@336
|
303 ... -- more listeners
|
jbe@336
|
304 -- the following options are all optional and have default values:
|
jbe@336
|
305 pre_fork = pre_fork, -- desired number of spare (idle) processes
|
jbe@336
|
306 min_fork = min_fork, -- minimum number of processes
|
jbe@336
|
307 max_fork = max_fork, -- maximum number of processes (hard limit)
|
jbe@336
|
308 fork_delay = fork_delay, -- delay (seconds) between creation of spare processes
|
jbe@336
|
309 fork_error_delay = fork_error_delay, -- delay (seconds) before retry of failed process creation
|
jbe@336
|
310 exit_delay = exit_delay, -- delay (seconds) between destruction of excessive spare processes
|
jbe@336
|
311 idle_timeout = idle_timeout, -- idle time (seconds) after a fork gets terminated (0 for no timeout)
|
jbe@336
|
312 memory_limit = memory_limit, -- maximum memory consumption (bytes) before process gets terminated
|
jbe@336
|
313 min_requests_per_fork = min_requests_per_fork, -- minimum count of requests handled before fork is terminated
|
jbe@336
|
314 max_requests_per_fork = max_requests_per_fork, -- maximum count of requests handled before fork is terminated
|
jbe@336
|
315 http_options = {
|
jbe@337
|
316 static_headers = static_headers, -- string or table of static headers to be returned with every request
|
jbe@337
|
317 request_header_size_limit = request_header_size_limit, -- maximum size of request headers sent by client
|
jbe@337
|
318 request_body_size_limit = request_body_size_limit, -- maximum size of request body sent by client
|
jbe@366
|
319 request_idle_timeout = request_idle_timeout, -- maximum time until receiving the first byte of the request header
|
jbe@366
|
320 request_header_timeout = request_header_timeout, -- maximum time until receiving the remaining bytes of the request header
|
jbe@366
|
321 response_timeout = response_timeout, -- time in which request body and response must be sent
|
jbe@338
|
322 maximum_input_chunk_size = maximum_input_chunk_size, -- tweaks behavior of request-body parser
|
jbe@337
|
323 minimum_output_chunk_size = minimum_output_chunk_size -- chunk size for chunked-transfer-encoding
|
jbe@336
|
324 }
|
jbe@336
|
325 }
|
jbe@336
|
326
|
jbe@336
|
327 The listen{...} function determines on which TCP port an application is answering requests. A typical call looks as follows:
|
jbe@336
|
328
|
jbe@336
|
329 listen{
|
jbe@336
|
330 { proto = "tcp4", port = 8080, localhost = true },
|
jbe@336
|
331 { proto = "tcp6", port = 8080, localhost = true }
|
jbe@336
|
332 }
|
jbe@336
|
333
|
jbe@336
|
334 This function must be called in a configuration file (in the config/ directory) or in pre-fork initializers (in the app/_prefork/ or app/<application name>/_prefork/ directories), unless WebMCP is invoked in interactive mode (in which case any calls of listen{...} are ignored).
|
jbe@336
|
335
|
jbe@336
|
336 This function is a variant of Moonbridge's listen{...} function which has been wrapped for WebMCP. No "prepare", "conenct", or "finish" handler can be set. Instead WebMCP automatically dispatches incoming connections. For interval timers, an interval handler may be specified in each listener.
|
jbe@336
|
337
|
jbe@336
|
338 --]]--
|
jbe@317
|
339 -- prepare for interactive or listen mode
|
jbe@203
|
340 if WEBMCP_MODE == "interactive" then
|
jbe@317
|
341 function listen() -- overwrite Moonbridge's listen function
|
jbe@317
|
342 -- ignore listen function calls for interactive mode
|
jbe@317
|
343 end
|
jbe@317
|
344 trace.disable() -- avoids memory leakage when scripts are running endlessly
|
jbe@317
|
345 else
|
jbe@317
|
346 local moonbridge_listen = listen
|
jbe@207
|
347 local http = require("moonbridge_http")
|
jbe@317
|
348 function listen(args) -- overwrite Moonbridge's listen function
|
jbe@322
|
349 assert(args, "No argument passed to listen function")
|
jbe@322
|
350 local min_requests_per_fork = args.min_requests_per_fork or 50
|
jbe@335
|
351 local max_requests_per_fork = args.max_requests_per_fork or 200
|
jbe@316
|
352 local interval_handlers = {}
|
jbe@317
|
353 for j, listener in ipairs(args) do
|
jbe@317
|
354 if listener.proto == "interval" then
|
jbe@317
|
355 local name = listener.name or "Unnamed interval #" .. #interval_handlers+1
|
jbe@336
|
356 if interval_handlers[name] ~= nil then
|
jbe@336
|
357 error('Interval handler with duplicate name "' .. name .. '"')
|
jbe@336
|
358 end
|
jbe@317
|
359 interval_handlers[name] = listener.handler
|
jbe@317
|
360 listener.name = name
|
jbe@316
|
361 end
|
jbe@316
|
362 end
|
jbe@264
|
363 local request_count = 0
|
jbe@266
|
364 local function inner_handler(http_request)
|
jbe@328
|
365 request_count = request_count + 1
|
jbe@328
|
366 if request_count >= max_requests_per_fork then
|
jbe@328
|
367 http_request:close_after_finish()
|
jbe@328
|
368 end
|
jbe@317
|
369 request.initialize()
|
jbe@328
|
370 return request.handler(http_request)
|
jbe@264
|
371 end
|
jbe@326
|
372 local outer_handler = http.generate_handler(inner_handler, args.http_options)
|
jbe@317
|
373 args.prepare = postfork_init
|
jbe@317
|
374 args.connect = function(socket)
|
jbe@316
|
375 if socket.interval then
|
jbe@328
|
376 request_count = request_count + 1
|
jbe@317
|
377 request.initialize()
|
jbe@316
|
378 interval_handlers[socket.interval]()
|
jbe@316
|
379 else
|
jbe@327
|
380 local success = outer_handler(socket)
|
jbe@327
|
381 if not success then
|
jbe@327
|
382 return false
|
jbe@327
|
383 end
|
jbe@316
|
384 end
|
jbe@288
|
385 return request_count < min_requests_per_fork
|
jbe@264
|
386 end
|
jbe@317
|
387 args.finish = execute.finalizers
|
jbe@317
|
388 moonbridge_listen(args)
|
jbe@204
|
389 end
|
jbe@204
|
390 end
|
jbe@336
|
391 --//--
|
jbe@317
|
392
|
jbe@317
|
393 -- execute configurations and pre-fork initializers
|
jbe@317
|
394 for i, config_name in ipairs(WEBMCP_CONFIG_NAMES) do
|
jbe@317
|
395 execute.config(config_name)
|
jbe@317
|
396 end
|
jbe@317
|
397 execute.prefork_initializers()
|
jbe@317
|
398
|
jbe@324
|
399 -- perform post-fork initializations (once) in case of interactive mode
|
jbe@317
|
400 if WEBMCP_MODE == "interactive" then
|
jbe@317
|
401 postfork_init()
|
jbe@317
|
402 end
|