]> granicus.if.org Git - apache/blob - modules/lua/lua_vmprep.c
Be more verbose when logging syntax errors
[apache] / modules / lua / lua_vmprep.c
1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 #include "mod_lua.h"
18 #include "http_log.h"
19 #include "apr_uuid.h"
20 #include "lua_config.h"
21 #include "apr_file_info.h"
22
23 APLOG_USE_MODULE(lua);
24
25 /* forward dec'l from this file */
26
27 #if 0
28 static void pstack_dump(lua_State *L, apr_pool_t *r, int level,
29                         const char *msg)
30 {
31     int i;
32     int top = lua_gettop(L);
33
34     ap_log_perror(APLOG_MARK, level, 0, r, "Lua Stack Dump: [%s]", msg);
35
36     for (i = 1; i <= top; i++) {
37         int t = lua_type(L, i);
38         switch (t) {
39         case LUA_TSTRING:{
40                 ap_log_perror(APLOG_MARK, level, 0, r,
41                               "%d:  '%s'", i, lua_tostring(L, i));
42                 break;
43             }
44         case LUA_TUSERDATA:{
45                 ap_log_perror(APLOG_MARK, level, 0, r, "%d:  userdata", i);
46                 break;
47             }
48         case LUA_TLIGHTUSERDATA:{
49                 ap_log_perror(APLOG_MARK, level, 0, r, "%d:  lightuserdata",
50                               i);
51                 break;
52             }
53         case LUA_TNIL:{
54                 ap_log_perror(APLOG_MARK, level, 0, r, "%d:  NIL", i);
55                 break;
56             }
57         case LUA_TNONE:{
58                 ap_log_perror(APLOG_MARK, level, 0, r, "%d:  None", i);
59                 break;
60             }
61         case LUA_TBOOLEAN:{
62                 ap_log_perror(APLOG_MARK, level, 0, r,
63                               "%d:  %s", i, lua_toboolean(L,
64                                                           i) ? "true" :
65                               "false");
66                 break;
67             }
68         case LUA_TNUMBER:{
69                 ap_log_perror(APLOG_MARK, level, 0, r,
70                               "%d:  %g", i, lua_tonumber(L, i));
71                 break;
72             }
73         case LUA_TTABLE:{
74                 ap_log_perror(APLOG_MARK, level, 0, r, "%d:  <table>", i);
75                 break;
76             }
77         case LUA_TTHREAD:{
78                 ap_log_perror(APLOG_MARK, level, 0, r, "%d:  <thread>", i);
79                 break;
80             }
81         case LUA_TFUNCTION:{
82                 ap_log_perror(APLOG_MARK, level, 0, r, "%d:  <function>", i);
83                 break;
84             }
85         default:{
86                 ap_log_perror(APLOG_MARK, level, 0, r,
87                               "%d:  unknown: [%s]", i, lua_typename(L, i));
88                 break;
89             }
90         }
91     }
92 }
93 #endif
94
95 /* BEGIN modules*/
96
97 /* BEGIN apache lmodule  */
98
99 AP_LUA_DECLARE(void) ap_lua_load_apache2_lmodule(lua_State *L)
100 {
101     lua_getglobal(L, "package");
102     lua_getfield(L, -1, "loaded");
103     lua_newtable(L);
104     lua_setfield(L, -2, "apache2");
105     lua_setglobal(L, "apache2");
106     lua_pop(L, 1);              /* empty stack */
107
108     lua_getglobal(L, "apache2");
109     lua_pushinteger(L, OK);
110     lua_setfield(L, -2, "OK");
111
112     lua_pushinteger(L, DECLINED);
113     lua_setfield(L, -2, "DECLINED");
114
115     lua_pushinteger(L, DONE);
116     lua_setfield(L, -2, "DONE");
117
118     lua_pushstring(L, ap_get_server_banner());
119     lua_setfield(L, -2, "version");
120
121     lua_pushinteger(L, HTTP_MOVED_TEMPORARILY);
122     lua_setfield(L, -2, "HTTP_MOVED_TEMPORARILY");
123
124     lua_pushinteger(L, PROXYREQ_NONE);
125     lua_setfield(L, -2, "PROXYREQ_NONE");
126
127     lua_pushinteger(L, PROXYREQ_PROXY);
128     lua_setfield(L, -2, "PROXYREQ_PROXY");
129
130     lua_pushinteger(L, PROXYREQ_REVERSE);
131     lua_setfield(L, -2, "PROXYREQ_REVERSE");
132
133     lua_pushinteger(L, PROXYREQ_RESPONSE);
134     lua_setfield(L, -2, "PROXYREQ_RESPONSE");
135
136     /*
137        lua_pushinteger(L, HTTP_CONTINUE);
138        lua_setfield(L, -2, "HTTP_CONTINUE");
139        lua_pushinteger(L, HTTP_SWITCHING_PROTOCOLS);
140        lua_setfield(L, -2, "HTTP_SWITCHING_PROTOCOLS");
141        lua_pushinteger(L, HTTP_PROCESSING);
142        lua_setfield(L, -2, "HTTP_PROCESSING");
143        lua_pushinteger(L, HTTP_OK);
144        lua_setfield(L, -2, "HTTP_OK");
145        lua_pushinteger(L, HTTP_CREATED);
146        lua_setfield(L, -2, "HTTP_CREATED");
147        lua_pushinteger(L, HTTP_ACCEPTED);
148        lua_setfield(L, -2, "HTTP_ACCEPTED");
149        lua_pushinteger(L, HTTP_NON_AUTHORITATIVE);
150        lua_setfield(L, -2, "HTTP_NON_AUTHORITATIVE");
151        lua_pushinteger(L, HTTP_NO_CONTENT);
152        lua_setfield(L, -2, "HTTP_NO_CONTENT");
153        lua_pushinteger(L, HTTP_RESET_CONTENT);
154        lua_setfield(L, -2, "HTTP_RESET_CONTENT");
155        lua_pushinteger(L, HTTP_PARTIAL_CONTENT);
156        lua_setfield(L, -2, "HTTP_PARTIAL_CONTENT");
157        lua_pushinteger(L, HTTP_MULTI_STATUS);
158        lua_setfield(L, -2, "HTTP_MULTI_STATUS");
159        lua_pushinteger(L, HTTP_MULTIPLE_CHOICES);
160        lua_setfield(L, -2, "HTTP_MULTIPLE_CHOICES");
161        lua_pushinteger(L, HTTP_MOVED_PERMANENTLY);
162        lua_setfield(L, -2, "HTTP_MOVED_PERMANENTLY");
163        lua_pushinteger(L, HTTP_SEE_OTHER);
164        lua_setfield(L, -2, "HTTP_SEE_OTHER");
165        lua_pushinteger(L, HTTP_NOT_MODIFIED);
166        lua_setfield(L, -2, "HTTP_NOT_MODIFIED");
167        lua_pushinteger(L, HTTP_USE_PROXY);
168        lua_setfield(L, -2, "HTTP_USE_PROXY");
169        lua_pushinteger(L, HTTP_TEMPORARY_REDIRECT);
170        lua_setfield(L, -2, "HTTP_TEMPORARY_REDIRECT");
171        lua_pushinteger(L, HTTP_BAD_REQUEST);
172        lua_setfield(L, -2, "HTTP_BAD_REQUEST");
173        lua_pushinteger(L, HTTP_UNAUTHORIZED);
174        lua_setfield(L, -2, "HTTP_UNAUTHORIZED");
175        lua_pushinteger(L, HTTP_PAYMENT_REQUIRED);
176        lua_setfield(L, -2, "HTTP_PAYMENT_REQUIRED");
177        lua_pushinteger(L, HTTP_FORBIDDEN);
178        lua_setfield(L, -2, "HTTP_FORBIDDEN");
179        lua_pushinteger(L, HTTP_NOT_FOUND);
180        lua_setfield(L, -2, "HTTP_NOT_FOUND");
181        lua_pushinteger(L, HTTP_METHOD_NOT_ALLOWED);
182        lua_setfield(L, -2, "HTTP_METHOD_NOT_ALLOWED");
183        lua_pushinteger(L, HTTP_NOT_ACCEPTABLE);
184        lua_setfield(L, -2, "HTTP_NOT_ACCEPTABLE");
185        lua_pushinteger(L, HTTP_PROXY_AUTHENTICATION_REQUIRED);
186        lua_setfield(L, -2, "HTTP_PROXY_AUTHENTICATION_REQUIRED");
187        lua_pushinteger(L, HTTP_REQUEST_TIME_OUT);
188        lua_setfield(L, -2, "HTTP_REQUEST_TIME_OUT");
189        lua_pushinteger(L, HTTP_CONFLICT);
190        lua_setfield(L, -2, "HTTP_CONFLICT");
191        lua_pushinteger(L, HTTP_GONE);
192        lua_setfield(L, -2, "HTTP_GONE");
193        lua_pushinteger(L, HTTP_LENGTH_REQUIRED);
194        lua_setfield(L, -2, "HTTP_LENGTH_REQUIRED");
195        lua_pushinteger(L, HTTP_PRECONDITION_FAILED);
196        lua_setfield(L, -2, "HTTP_PRECONDITION_FAILED");
197        lua_pushinteger(L, HTTP_REQUEST_ENTITY_TOO_LARGE);
198        lua_setfield(L, -2, "HTTP_REQUEST_ENTITY_TOO_LARGE");
199        lua_pushinteger(L, HTTP_REQUEST_URI_TOO_LARGE);
200        lua_setfield(L, -2, "HTTP_REQUEST_URI_TOO_LARGE");
201        lua_pushinteger(L, HTTP_UNSUPPORTED_MEDIA_TYPE);
202        lua_setfield(L, -2, "HTTP_UNSUPPORTED_MEDIA_TYPE");
203        lua_pushinteger(L, HTTP_RANGE_NOT_SATISFIABLE);
204        lua_setfield(L, -2, "HTTP_RANGE_NOT_SATISFIABLE");
205        lua_pushinteger(L, HTTP_EXPECTATION_FAILED);
206        lua_setfield(L, -2, "HTTP_EXPECTATION_FAILED");
207        lua_pushinteger(L, HTTP_UNPROCESSABLE_ENTITY);
208        lua_setfield(L, -2, "HTTP_UNPROCESSABLE_ENTITY");
209        lua_pushinteger(L, HTTP_LOCKED);
210        lua_setfield(L, -2, "HTTP_LOCKED");
211        lua_pushinteger(L, HTTP_FAILED_DEPENDENCY);
212        lua_setfield(L, -2, "HTTP_FAILED_DEPENDENCY");
213        lua_pushinteger(L, HTTP_UPGRADE_REQUIRED);
214        lua_setfield(L, -2, "HTTP_UPGRADE_REQUIRED");
215        lua_pushinteger(L, HTTP_INTERNAL_SERVER_ERROR);
216        lua_setfield(L, -2, "HTTP_INTERNAL_SERVER_ERROR");
217        lua_pushinteger(L, HTTP_NOT_IMPLEMENTED);
218        lua_setfield(L, -2, "HTTP_NOT_IMPLEMENTED");
219        lua_pushinteger(L, HTTP_BAD_GATEWAY);
220        lua_setfield(L, -2, "HTTP_BAD_GATEWAY");
221        lua_pushinteger(L, HTTP_SERVICE_UNAVAILABLE);
222        lua_setfield(L, -2, "HTTP_SERVICE_UNAVAILABLE");
223        lua_pushinteger(L, HTTP_GATEWAY_TIME_OUT);
224        lua_setfield(L, -2, "HTTP_GATEWAY_TIME_OUT");
225        lua_pushinteger(L, HTTP_VERSION_NOT_SUPPORTED);
226        lua_setfield(L, -2, "HTTP_VERSION_NOT_SUPPORTED");
227        lua_pushinteger(L, HTTP_VARIANT_ALSO_VARIES);
228        lua_setfield(L, -2, "HTTP_VARIANT_ALSO_VARIES");
229        lua_pushinteger(L, HTTP_INSUFFICIENT_STORAGE);
230        lua_setfield(L, -2, "HTTP_INSUFFICIENT_STORAGE");
231        lua_pushinteger(L, HTTP_NOT_EXTENDED);
232        lua_setfield(L, -2, "HTTP_NOT_EXTENDED");
233      */
234 }
235
236 /* END apache2 lmodule */
237
238 /*  END library functions */
239
240 /* callback for cleaning up a lua vm when pool is closed */
241 static apr_status_t cleanup_lua(void *l)
242 {
243     lua_close((lua_State *) l);
244     return APR_SUCCESS;
245 }
246
247 /*
248         munge_path(L, 
249                    "path", 
250                    "?.lua", 
251                    "./?.lua", 
252                    lifecycle_pool,
253                    spec->package_paths, 
254                    spec->file);
255 */
256 /**
257  * field -> "path" or "cpath"
258  * sub_pat -> "?.lua"
259  * rep_pat -> "./?.lua"
260  * pool -> lifecycle pool for allocations
261  * paths -> things to add
262  * file -> ???
263  */
264 static void munge_path(lua_State *L,
265                        const char *field,
266                        const char *sub_pat,
267                        const char *rep_pat,
268                        apr_pool_t *pool,
269                        apr_array_header_t *paths,
270                        const char *file)
271 {
272     const char *current;
273     const char *parent_dir;
274     const char *pattern;
275     const char *modified;
276     char *part;
277
278     lua_getglobal(L, "package");
279     lua_getfield(L, -1, field);
280     
281     current = lua_tostring(L, -1);
282
283     parent_dir = ap_make_dirstr_parent(pool, file);
284  
285     pattern = apr_pstrcat(pool, parent_dir, sub_pat, NULL);
286
287     luaL_gsub(L, current, rep_pat, pattern);
288     lua_setfield(L, -3, field);
289     lua_getfield(L, -2, field);
290     modified = lua_tostring(L, -1);
291
292
293     lua_pop(L, 2);
294
295     part = apr_pstrcat(pool, modified, ";", apr_array_pstrcat(pool, paths, ';'),
296                        NULL);
297
298     lua_pushstring(L, part);
299     lua_setfield(L, -2, field);
300     lua_pop(L, 1);              /* pop "package" off the stack     */
301 }
302
303 #ifdef AP_ENABLE_LUAJIT
304 static int loadjitmodule(lua_State *L, apr_pool_t *lifecycle_pool) {
305     lua_getglobal(L, "require");
306     lua_pushliteral(L, "jit.");
307     lua_pushvalue(L, -3);
308     lua_concat(L, 2);
309     if (lua_pcall(L, 1, 1, 0)) {
310         const char *msg = lua_tostring(L, -1);
311         ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, lifecycle_pool, APLOGNO(01480)
312                       "Failed to init LuaJIT: %s", msg);
313         return 1;
314     }
315     lua_getfield(L, -1, "start");
316     lua_remove(L, -2);  /* drop module table */
317     return 0;
318 }
319
320 #endif
321
322 static apr_status_t vm_construct(void **vm, void *params, apr_pool_t *lifecycle_pool)
323 {
324     lua_State* L;
325
326     ap_lua_vm_spec *spec = params;
327
328     L = luaL_newstate();
329 #ifdef AP_ENABLE_LUAJIT
330     luaopen_jit(L);
331 #endif
332     luaL_openlibs(L);
333     if (spec->package_paths) {
334         munge_path(L, 
335                    "path", "?.lua", "./?.lua", 
336                    lifecycle_pool,
337                    spec->package_paths, 
338                    spec->file);
339     }
340     if (spec->package_cpaths) {
341         munge_path(L, "cpath", "?.so", "./?.so", lifecycle_pool,
342             spec->package_cpaths, spec->file);
343     }
344
345     if (spec->cb) {
346         spec->cb(L, lifecycle_pool, spec->cb_arg);
347     }
348
349
350     if (spec->bytecode && spec->bytecode_len > 0) {
351         luaL_loadbuffer(L, spec->bytecode, spec->bytecode_len, spec->file);
352         lua_pcall(L, 0, LUA_MULTRET, 0);
353     }
354     else {
355         int rc;
356         ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, lifecycle_pool, APLOGNO(01481)
357             "loading lua file %s", spec->file);
358         rc = luaL_loadfile(L, spec->file);
359         if (rc != 0) {
360             ap_log_perror(APLOG_MARK, APLOG_ERR, 0, lifecycle_pool, APLOGNO(01482)
361                           "Error loading %s: %s", spec->file,
362                           rc == LUA_ERRMEM ? "memory allocation error"
363                                            : lua_tostring(L, 0));
364             return APR_EBADF;
365         }
366         lua_pcall(L, 0, LUA_MULTRET, 0);
367     }
368
369 #ifdef AP_ENABLE_LUAJIT
370     loadjitmodule(L, lifecycle_pool);
371 #endif
372     lua_pushlightuserdata(L, lifecycle_pool);
373     lua_setfield(L, LUA_REGISTRYINDEX, "Apache2.Wombat.pool");
374     *vm = L;
375
376     return APR_SUCCESS;
377 }
378
379 /**
380  * Function used to create a lua_State instance bound into the web
381  * server in the appropriate scope.
382  */
383 AP_LUA_DECLARE(lua_State*)ap_lua_get_lua_state(apr_pool_t *lifecycle_pool,
384                                                ap_lua_vm_spec *spec)
385 {
386     lua_State *L = NULL;
387
388     if (apr_pool_userdata_get((void **)&L, spec->file,
389                               lifecycle_pool) == APR_SUCCESS) {
390       
391       if(L==NULL) {
392         ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, lifecycle_pool, APLOGNO(01483)
393                       "creating lua_State with file %s", spec->file);
394         /* not available, so create */
395         
396         if(!vm_construct((void **)&L, spec, lifecycle_pool)) {
397           apr_pool_userdata_set(L, 
398                                 spec->file, 
399                                 cleanup_lua,
400                                 lifecycle_pool);
401         }
402       }
403     }
404         /*}*/
405
406     return L;
407 }