1 1.15 alnsn /* $NetBSD: lua-bozo.c,v 1.15 2017/05/28 22:37:36 alnsn Exp $ */ 2 1.1 mbalmer 3 1.1 mbalmer /* 4 1.1 mbalmer * Copyright (c) 2013 Marc Balmer <marc (at) msys.ch> 5 1.1 mbalmer * All rights reserved. 6 1.1 mbalmer * 7 1.1 mbalmer * Redistribution and use in source and binary forms, with or without 8 1.1 mbalmer * modification, are permitted provided that the following conditions 9 1.1 mbalmer * are met: 10 1.1 mbalmer * 1. Redistributions of source code must retain the above copyright 11 1.1 mbalmer * notice, this list of conditions and the following disclaimer. 12 1.1 mbalmer * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 mbalmer * notice, this list of conditions and the following disclaimer and 14 1.1 mbalmer * dedication in the documentation and/or other materials provided 15 1.1 mbalmer * with the distribution. 16 1.1 mbalmer * 17 1.1 mbalmer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 1.1 mbalmer * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 1.1 mbalmer * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 1.1 mbalmer * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 1.1 mbalmer * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 22 1.1 mbalmer * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 1.1 mbalmer * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 24 1.1 mbalmer * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 1.1 mbalmer * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 1.1 mbalmer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 1.1 mbalmer * SUCH DAMAGE. 28 1.1 mbalmer * 29 1.1 mbalmer */ 30 1.1 mbalmer 31 1.1 mbalmer /* this code implements dynamic content generation using Lua for bozohttpd */ 32 1.1 mbalmer 33 1.1 mbalmer #ifndef NO_LUA_SUPPORT 34 1.1 mbalmer 35 1.9 mrg #include <sys/param.h> 36 1.9 mrg 37 1.1 mbalmer #include <lua.h> 38 1.1 mbalmer #include <lauxlib.h> 39 1.1 mbalmer #include <lualib.h> 40 1.1 mbalmer #include <stdlib.h> 41 1.1 mbalmer #include <string.h> 42 1.1 mbalmer #include <unistd.h> 43 1.1 mbalmer 44 1.1 mbalmer #include "bozohttpd.h" 45 1.1 mbalmer 46 1.1 mbalmer /* Lua binding for bozohttp */ 47 1.1 mbalmer 48 1.1 mbalmer #if LUA_VERSION_NUM < 502 49 1.1 mbalmer #define LUA_HTTPDLIBNAME "httpd" 50 1.1 mbalmer #endif 51 1.1 mbalmer 52 1.1 mbalmer #define FORM "application/x-www-form-urlencoded" 53 1.1 mbalmer 54 1.15 alnsn static bozohttpd_t * 55 1.15 alnsn httpd_instance(lua_State *L) 56 1.1 mbalmer { 57 1.1 mbalmer bozohttpd_t *httpd; 58 1.1 mbalmer 59 1.1 mbalmer lua_pushstring(L, "bozohttpd"); 60 1.1 mbalmer lua_gettable(L, LUA_REGISTRYINDEX); 61 1.1 mbalmer httpd = lua_touserdata(L, -1); 62 1.1 mbalmer lua_pop(L, 1); 63 1.1 mbalmer 64 1.15 alnsn return httpd; 65 1.15 alnsn } 66 1.15 alnsn 67 1.15 alnsn static int 68 1.15 alnsn lua_flush(lua_State *L) 69 1.15 alnsn { 70 1.15 alnsn bozohttpd_t *httpd = httpd_instance(L); 71 1.15 alnsn 72 1.1 mbalmer bozo_flush(httpd, stdout); 73 1.1 mbalmer return 0; 74 1.1 mbalmer } 75 1.1 mbalmer 76 1.1 mbalmer static int 77 1.1 mbalmer lua_print(lua_State *L) 78 1.1 mbalmer { 79 1.15 alnsn bozohttpd_t *httpd = httpd_instance(L); 80 1.1 mbalmer 81 1.15 alnsn bozo_printf(httpd, "%s\r\n", lua_tostring(L, 1)); 82 1.1 mbalmer return 0; 83 1.1 mbalmer } 84 1.1 mbalmer 85 1.1 mbalmer static int 86 1.1 mbalmer lua_read(lua_State *L) 87 1.1 mbalmer { 88 1.15 alnsn bozohttpd_t *httpd = httpd_instance(L); 89 1.15 alnsn luaL_Buffer lbuf; 90 1.1 mbalmer char *data; 91 1.15 alnsn lua_Integer len; 92 1.15 alnsn ssize_t n; 93 1.1 mbalmer 94 1.15 alnsn len = luaL_checkinteger(L, 1); 95 1.15 alnsn data = luaL_buffinitsize(L, &lbuf, (size_t)len); 96 1.1 mbalmer 97 1.15 alnsn if ((n = bozo_read(httpd, STDIN_FILENO, data, len)) >= 0) { 98 1.15 alnsn luaL_pushresultsize(&lbuf, n); 99 1.15 alnsn return 1; 100 1.15 alnsn } else { 101 1.4 mbalmer lua_pushnil(L); 102 1.15 alnsn lua_pushstring(L, "bozo_read() call failed"); 103 1.15 alnsn return 2; 104 1.15 alnsn } 105 1.1 mbalmer } 106 1.1 mbalmer 107 1.1 mbalmer static int 108 1.1 mbalmer lua_register_handler(lua_State *L) 109 1.1 mbalmer { 110 1.15 alnsn bozohttpd_t *httpd = httpd_instance(L); 111 1.1 mbalmer lua_state_map_t *map; 112 1.1 mbalmer lua_handler_t *handler; 113 1.15 alnsn const char *name; 114 1.15 alnsn int ref; 115 1.1 mbalmer 116 1.1 mbalmer lua_pushstring(L, "lua_state_map"); 117 1.1 mbalmer lua_gettable(L, LUA_REGISTRYINDEX); 118 1.1 mbalmer map = lua_touserdata(L, -1); 119 1.15 alnsn lua_pop(L, 1); 120 1.15 alnsn 121 1.15 alnsn name = luaL_checkstring(L, 1); 122 1.1 mbalmer 123 1.1 mbalmer luaL_checktype(L, 2, LUA_TFUNCTION); 124 1.15 alnsn lua_pushvalue(L, 2); 125 1.15 alnsn ref = luaL_ref(L, LUA_REGISTRYINDEX); 126 1.1 mbalmer 127 1.1 mbalmer handler = bozomalloc(httpd, sizeof(lua_handler_t)); 128 1.15 alnsn handler->name = bozostrdup(httpd, NULL, name); 129 1.15 alnsn handler->ref = ref; 130 1.1 mbalmer SIMPLEQ_INSERT_TAIL(&map->handlers, handler, h_next); 131 1.1 mbalmer httpd->process_lua = 1; 132 1.1 mbalmer return 0; 133 1.1 mbalmer } 134 1.1 mbalmer 135 1.1 mbalmer static int 136 1.1 mbalmer lua_write(lua_State *L) 137 1.1 mbalmer { 138 1.15 alnsn bozohttpd_t *httpd = httpd_instance(L); 139 1.1 mbalmer const char *data; 140 1.15 alnsn size_t len; 141 1.15 alnsn ssize_t n; 142 1.1 mbalmer 143 1.15 alnsn data = luaL_checklstring(L, 1, &len); 144 1.15 alnsn if ((n = bozo_write(httpd, STDIN_FILENO, data, len)) >= 0) { 145 1.15 alnsn lua_pushinteger(L, n); 146 1.15 alnsn return 1; 147 1.15 alnsn } else { 148 1.15 alnsn lua_pushnil(L); 149 1.15 alnsn lua_pushstring(L, "bozo_write() call failed"); 150 1.15 alnsn return 2; 151 1.15 alnsn } 152 1.1 mbalmer } 153 1.1 mbalmer 154 1.1 mbalmer static int 155 1.1 mbalmer luaopen_httpd(lua_State *L) 156 1.1 mbalmer { 157 1.15 alnsn static struct luaL_Reg functions[] = { 158 1.1 mbalmer { "flush", lua_flush }, 159 1.1 mbalmer { "print", lua_print }, 160 1.1 mbalmer { "read", lua_read }, 161 1.1 mbalmer { "register_handler", lua_register_handler }, 162 1.1 mbalmer { "write", lua_write }, 163 1.1 mbalmer { NULL, NULL } 164 1.1 mbalmer }; 165 1.1 mbalmer #if LUA_VERSION_NUM >= 502 166 1.1 mbalmer luaL_newlib(L, functions); 167 1.1 mbalmer #else 168 1.1 mbalmer luaL_register(L, LUA_HTTPDLIBNAME, functions); 169 1.1 mbalmer #endif 170 1.1 mbalmer lua_pushstring(L, "httpd 1.0.0"); 171 1.1 mbalmer lua_setfield(L, -2, "_VERSION"); 172 1.1 mbalmer return 1; 173 1.1 mbalmer } 174 1.1 mbalmer 175 1.1 mbalmer #if LUA_VERSION_NUM < 502 176 1.1 mbalmer static void 177 1.1 mbalmer lua_openlib(lua_State *L, const char *name, lua_CFunction fn) 178 1.1 mbalmer { 179 1.1 mbalmer lua_pushcfunction(L, fn); 180 1.1 mbalmer lua_pushstring(L, name); 181 1.1 mbalmer lua_call(L, 1, 0); 182 1.1 mbalmer } 183 1.1 mbalmer #endif 184 1.1 mbalmer 185 1.1 mbalmer /* bozohttpd integration */ 186 1.1 mbalmer void 187 1.1 mbalmer bozo_add_lua_map(bozohttpd_t *httpd, const char *prefix, const char *script) 188 1.1 mbalmer { 189 1.1 mbalmer lua_state_map_t *map; 190 1.1 mbalmer 191 1.1 mbalmer map = bozomalloc(httpd, sizeof(lua_state_map_t)); 192 1.13 mrg map->prefix = bozostrdup(httpd, NULL, prefix); 193 1.1 mbalmer if (*script == '/') 194 1.13 mrg map->script = bozostrdup(httpd, NULL, script); 195 1.1 mbalmer else { 196 1.9 mrg char cwd[MAXPATHLEN], *path; 197 1.9 mrg 198 1.9 mrg getcwd(cwd, sizeof(cwd) - 1); 199 1.14 mrg bozoasprintf(httpd, &path, "%s/%s", cwd, script); 200 1.1 mbalmer map->script = path; 201 1.1 mbalmer } 202 1.1 mbalmer map->L = luaL_newstate(); 203 1.1 mbalmer if (map->L == NULL) 204 1.14 mrg bozoerr(httpd, 1, "can't create Lua state"); 205 1.1 mbalmer SIMPLEQ_INIT(&map->handlers); 206 1.1 mbalmer 207 1.1 mbalmer #if LUA_VERSION_NUM >= 502 208 1.1 mbalmer luaL_openlibs(map->L); 209 1.10 lneto lua_getglobal(map->L, "package"); 210 1.10 lneto lua_getfield(map->L, -1, "preload"); 211 1.10 lneto lua_pushcfunction(map->L, luaopen_httpd); 212 1.10 lneto lua_setfield(map->L, -2, "httpd"); 213 1.10 lneto lua_pop(map->L, 2); 214 1.1 mbalmer #else 215 1.1 mbalmer lua_openlib(map->L, "", luaopen_base); 216 1.1 mbalmer lua_openlib(map->L, LUA_LOADLIBNAME, luaopen_package); 217 1.1 mbalmer lua_openlib(map->L, LUA_TABLIBNAME, luaopen_table); 218 1.1 mbalmer lua_openlib(map->L, LUA_STRLIBNAME, luaopen_string); 219 1.1 mbalmer lua_openlib(map->L, LUA_MATHLIBNAME, luaopen_math); 220 1.1 mbalmer lua_openlib(map->L, LUA_OSLIBNAME, luaopen_os); 221 1.1 mbalmer lua_openlib(map->L, LUA_IOLIBNAME, luaopen_io); 222 1.1 mbalmer lua_openlib(map->L, LUA_HTTPDLIBNAME, luaopen_httpd); 223 1.1 mbalmer #endif 224 1.1 mbalmer lua_pushstring(map->L, "lua_state_map"); 225 1.1 mbalmer lua_pushlightuserdata(map->L, map); 226 1.1 mbalmer lua_settable(map->L, LUA_REGISTRYINDEX); 227 1.1 mbalmer 228 1.1 mbalmer lua_pushstring(map->L, "bozohttpd"); 229 1.1 mbalmer lua_pushlightuserdata(map->L, httpd); 230 1.1 mbalmer lua_settable(map->L, LUA_REGISTRYINDEX); 231 1.1 mbalmer 232 1.1 mbalmer if (luaL_loadfile(map->L, script)) 233 1.14 mrg bozoerr(httpd, 1, "failed to load script %s: %s", script, 234 1.1 mbalmer lua_tostring(map->L, -1)); 235 1.1 mbalmer if (lua_pcall(map->L, 0, 0, 0)) 236 1.14 mrg bozoerr(httpd, 1, "failed to execute script %s: %s", script, 237 1.1 mbalmer lua_tostring(map->L, -1)); 238 1.1 mbalmer SIMPLEQ_INSERT_TAIL(&httpd->lua_states, map, s_next); 239 1.1 mbalmer } 240 1.1 mbalmer 241 1.1 mbalmer static void 242 1.1 mbalmer lua_env(lua_State *L, const char *name, const char *value) 243 1.1 mbalmer { 244 1.1 mbalmer lua_pushstring(L, value); 245 1.1 mbalmer lua_setfield(L, -2, name); 246 1.1 mbalmer } 247 1.1 mbalmer 248 1.1 mbalmer /* decode query string */ 249 1.1 mbalmer static void 250 1.1 mbalmer lua_url_decode(lua_State *L, char *s) 251 1.1 mbalmer { 252 1.1 mbalmer char *v, *p, *val, *q; 253 1.1 mbalmer char buf[3]; 254 1.1 mbalmer int c; 255 1.1 mbalmer 256 1.1 mbalmer v = strchr(s, '='); 257 1.1 mbalmer if (v == NULL) 258 1.1 mbalmer return; 259 1.1 mbalmer *v++ = '\0'; 260 1.1 mbalmer val = malloc(strlen(v) + 1); 261 1.1 mbalmer if (val == NULL) 262 1.1 mbalmer return; 263 1.1 mbalmer 264 1.1 mbalmer for (p = v, q = val; *p; p++) { 265 1.1 mbalmer switch (*p) { 266 1.1 mbalmer case '%': 267 1.3 mbalmer if (*(p + 1) == '\0' || *(p + 2) == '\0') { 268 1.3 mbalmer free(val); 269 1.1 mbalmer return; 270 1.3 mbalmer } 271 1.1 mbalmer buf[0] = *++p; 272 1.1 mbalmer buf[1] = *++p; 273 1.1 mbalmer buf[2] = '\0'; 274 1.1 mbalmer sscanf(buf, "%2x", &c); 275 1.1 mbalmer *q++ = (char)c; 276 1.1 mbalmer break; 277 1.1 mbalmer case '+': 278 1.1 mbalmer *q++ = ' '; 279 1.1 mbalmer break; 280 1.1 mbalmer default: 281 1.1 mbalmer *q++ = *p; 282 1.1 mbalmer } 283 1.1 mbalmer } 284 1.11 mbalmer *q = '\0'; 285 1.1 mbalmer lua_pushstring(L, val); 286 1.1 mbalmer lua_setfield(L, -2, s); 287 1.1 mbalmer free(val); 288 1.1 mbalmer } 289 1.1 mbalmer 290 1.1 mbalmer static void 291 1.1 mbalmer lua_decode_query(lua_State *L, char *query) 292 1.1 mbalmer { 293 1.1 mbalmer char *s; 294 1.1 mbalmer 295 1.1 mbalmer s = strtok(query, "&"); 296 1.1 mbalmer while (s) { 297 1.1 mbalmer lua_url_decode(L, s); 298 1.1 mbalmer s = strtok(NULL, "&"); 299 1.1 mbalmer } 300 1.1 mbalmer } 301 1.1 mbalmer 302 1.1 mbalmer int 303 1.1 mbalmer bozo_process_lua(bozo_httpreq_t *request) 304 1.1 mbalmer { 305 1.1 mbalmer bozohttpd_t *httpd = request->hr_httpd; 306 1.1 mbalmer lua_state_map_t *map; 307 1.1 mbalmer lua_handler_t *hndlr; 308 1.4 mbalmer int n, ret, length; 309 1.1 mbalmer char date[40]; 310 1.1 mbalmer bozoheaders_t *headp; 311 1.1 mbalmer char *s, *query, *uri, *file, *command, *info, *content; 312 1.1 mbalmer const char *type, *clen; 313 1.1 mbalmer char *prefix, *handler, *p; 314 1.7 christos int rv = 0; 315 1.1 mbalmer 316 1.1 mbalmer if (!httpd->process_lua) 317 1.1 mbalmer return 0; 318 1.1 mbalmer 319 1.12 christos info = NULL; 320 1.12 christos query = NULL; 321 1.12 christos prefix = NULL; 322 1.1 mbalmer uri = request->hr_oldfile ? request->hr_oldfile : request->hr_file; 323 1.1 mbalmer 324 1.1 mbalmer if (*uri == '/') { 325 1.13 mrg file = bozostrdup(httpd, request, uri); 326 1.12 christos if (file == NULL) 327 1.12 christos goto out; 328 1.13 mrg prefix = bozostrdup(httpd, request, &uri[1]); 329 1.1 mbalmer } else { 330 1.12 christos if (asprintf(&file, "/%s", uri) < 0) 331 1.12 christos goto out; 332 1.13 mrg prefix = bozostrdup(httpd, request, uri); 333 1.1 mbalmer } 334 1.12 christos if (prefix == NULL) 335 1.12 christos goto out; 336 1.1 mbalmer 337 1.12 christos if (request->hr_query && request->hr_query[0]) 338 1.13 mrg query = bozostrdup(httpd, request, request->hr_query); 339 1.1 mbalmer 340 1.1 mbalmer p = strchr(prefix, '/'); 341 1.12 christos if (p == NULL) 342 1.12 christos goto out; 343 1.1 mbalmer *p++ = '\0'; 344 1.1 mbalmer handler = p; 345 1.12 christos if (!*handler) 346 1.12 christos goto out; 347 1.1 mbalmer p = strchr(handler, '/'); 348 1.1 mbalmer if (p != NULL) 349 1.1 mbalmer *p++ = '\0'; 350 1.1 mbalmer 351 1.1 mbalmer command = file + 1; 352 1.1 mbalmer if ((s = strchr(command, '/')) != NULL) { 353 1.13 mrg info = bozostrdup(httpd, request, s); 354 1.1 mbalmer *s = '\0'; 355 1.1 mbalmer } 356 1.1 mbalmer 357 1.1 mbalmer type = request->hr_content_type; 358 1.1 mbalmer clen = request->hr_content_length; 359 1.1 mbalmer 360 1.1 mbalmer SIMPLEQ_FOREACH(map, &httpd->lua_states, s_next) { 361 1.1 mbalmer if (strcmp(map->prefix, prefix)) 362 1.1 mbalmer continue; 363 1.1 mbalmer 364 1.1 mbalmer SIMPLEQ_FOREACH(hndlr, &map->handlers, h_next) { 365 1.1 mbalmer if (strcmp(hndlr->name, handler)) 366 1.1 mbalmer continue; 367 1.1 mbalmer 368 1.1 mbalmer lua_rawgeti(map->L, LUA_REGISTRYINDEX, hndlr->ref); 369 1.1 mbalmer 370 1.1 mbalmer /* Create the "environment" */ 371 1.1 mbalmer lua_newtable(map->L); 372 1.1 mbalmer lua_env(map->L, "SERVER_NAME", 373 1.1 mbalmer BOZOHOST(httpd, request)); 374 1.1 mbalmer lua_env(map->L, "GATEWAY_INTERFACE", "Luigi/1.0"); 375 1.1 mbalmer lua_env(map->L, "SERVER_PROTOCOL", request->hr_proto); 376 1.1 mbalmer lua_env(map->L, "REQUEST_METHOD", 377 1.1 mbalmer request->hr_methodstr); 378 1.1 mbalmer lua_env(map->L, "SCRIPT_PREFIX", map->prefix); 379 1.1 mbalmer lua_env(map->L, "SCRIPT_NAME", file); 380 1.1 mbalmer lua_env(map->L, "HANDLER_NAME", hndlr->name); 381 1.1 mbalmer lua_env(map->L, "SCRIPT_FILENAME", map->script); 382 1.1 mbalmer lua_env(map->L, "SERVER_SOFTWARE", 383 1.1 mbalmer httpd->server_software); 384 1.1 mbalmer lua_env(map->L, "REQUEST_URI", uri); 385 1.1 mbalmer lua_env(map->L, "DATE_GMT", 386 1.1 mbalmer bozo_http_date(date, sizeof(date))); 387 1.1 mbalmer if (query && *query) 388 1.1 mbalmer lua_env(map->L, "QUERY_STRING", query); 389 1.1 mbalmer if (info && *info) 390 1.1 mbalmer lua_env(map->L, "PATH_INFO", info); 391 1.1 mbalmer if (type && *type) 392 1.1 mbalmer lua_env(map->L, "CONTENT_TYPE", type); 393 1.1 mbalmer if (clen && *clen) 394 1.1 mbalmer lua_env(map->L, "CONTENT_LENGTH", clen); 395 1.1 mbalmer if (request->hr_serverport && *request->hr_serverport) 396 1.1 mbalmer lua_env(map->L, "SERVER_PORT", 397 1.1 mbalmer request->hr_serverport); 398 1.1 mbalmer if (request->hr_remotehost && *request->hr_remotehost) 399 1.1 mbalmer lua_env(map->L, "REMOTE_HOST", 400 1.1 mbalmer request->hr_remotehost); 401 1.1 mbalmer if (request->hr_remoteaddr && *request->hr_remoteaddr) 402 1.1 mbalmer lua_env(map->L, "REMOTE_ADDR", 403 1.1 mbalmer request->hr_remoteaddr); 404 1.1 mbalmer 405 1.1 mbalmer /* Pass the headers in a separate table */ 406 1.1 mbalmer lua_newtable(map->L); 407 1.1 mbalmer SIMPLEQ_FOREACH(headp, &request->hr_headers, h_next) 408 1.1 mbalmer lua_env(map->L, headp->h_header, 409 1.1 mbalmer headp->h_value); 410 1.1 mbalmer 411 1.1 mbalmer /* Pass the query variables */ 412 1.5 mbalmer if ((query && *query) || 413 1.5 mbalmer (type && *type && !strcmp(type, FORM))) { 414 1.1 mbalmer lua_newtable(map->L); 415 1.1 mbalmer if (query && *query) 416 1.1 mbalmer lua_decode_query(map->L, query); 417 1.1 mbalmer if (type && *type && !strcmp(type, FORM)) { 418 1.1 mbalmer if (clen && *clen && atol(clen) > 0) { 419 1.1 mbalmer length = atol(clen); 420 1.1 mbalmer content = bozomalloc(httpd, 421 1.2 mbalmer length + 1); 422 1.4 mbalmer n = bozo_read(httpd, 423 1.4 mbalmer STDIN_FILENO, content, 424 1.4 mbalmer length); 425 1.4 mbalmer if (n >= 0) { 426 1.4 mbalmer content[n] = '\0'; 427 1.4 mbalmer lua_decode_query(map->L, 428 1.4 mbalmer content); 429 1.5 mbalmer } else { 430 1.5 mbalmer lua_pop(map->L, 1); 431 1.5 mbalmer lua_pushnil(map->L); 432 1.4 mbalmer } 433 1.1 mbalmer free(content); 434 1.1 mbalmer } 435 1.1 mbalmer } 436 1.1 mbalmer } else 437 1.1 mbalmer lua_pushnil(map->L); 438 1.1 mbalmer 439 1.1 mbalmer ret = lua_pcall(map->L, 3, 0, 0); 440 1.1 mbalmer if (ret) 441 1.1 mbalmer printf("<br>Lua error: %s\n", 442 1.1 mbalmer lua_tostring(map->L, -1)); 443 1.1 mbalmer bozo_flush(httpd, stdout); 444 1.7 christos rv = 1; 445 1.7 christos goto out; 446 1.1 mbalmer } 447 1.1 mbalmer } 448 1.7 christos out: 449 1.1 mbalmer free(prefix); 450 1.1 mbalmer free(uri); 451 1.1 mbalmer free(info); 452 1.6 christos free(query); 453 1.7 christos free(file); 454 1.7 christos return rv; 455 1.1 mbalmer } 456 1.1 mbalmer 457 1.1 mbalmer #endif /* NO_LUA_SUPPORT */ 458