17cafeaa1SWarner Losh /*- 27cafeaa1SWarner Losh * Copyright (c) 2011 Wojciech A. Koszek <wkoszek@FreeBSD.org> 37cafeaa1SWarner Losh * Copyright (c) 2014 Pedro Souza <pedrosouza@freebsd.org> 47cafeaa1SWarner Losh * All rights reserved. 57cafeaa1SWarner Losh * 67cafeaa1SWarner Losh * Redistribution and use in source and binary forms, with or without 77cafeaa1SWarner Losh * modification, are permitted provided that the following conditions 87cafeaa1SWarner Losh * are met: 97cafeaa1SWarner Losh * 1. Redistributions of source code must retain the above copyright 107cafeaa1SWarner Losh * notice, this list of conditions and the following disclaimer. 117cafeaa1SWarner Losh * 2. Redistributions in binary form must reproduce the above copyright 127cafeaa1SWarner Losh * notice, this list of conditions and the following disclaimer in the 137cafeaa1SWarner Losh * documentation and/or other materials provided with the distribution. 147cafeaa1SWarner Losh * 157cafeaa1SWarner Losh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 167cafeaa1SWarner Losh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 177cafeaa1SWarner Losh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 187cafeaa1SWarner Losh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 197cafeaa1SWarner Losh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 207cafeaa1SWarner Losh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 217cafeaa1SWarner Losh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 227cafeaa1SWarner Losh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 237cafeaa1SWarner Losh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 247cafeaa1SWarner Losh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 257cafeaa1SWarner Losh * SUCH DAMAGE. 267cafeaa1SWarner Losh */ 277cafeaa1SWarner Losh 287cafeaa1SWarner Losh #include <sys/cdefs.h> 297cafeaa1SWarner Losh __FBSDID("$FreeBSD$"); 307cafeaa1SWarner Losh 317cafeaa1SWarner Losh #include <stand.h> 327cafeaa1SWarner Losh #include "bootstrap.h" 337cafeaa1SWarner Losh 347cafeaa1SWarner Losh #define lua_c 357cafeaa1SWarner Losh 367cafeaa1SWarner Losh #include "lstd.h" 377cafeaa1SWarner Losh 387cafeaa1SWarner Losh #include <lua.h> 397cafeaa1SWarner Losh #include <ldebug.h> 407cafeaa1SWarner Losh #include <lauxlib.h> 417cafeaa1SWarner Losh #include <lualib.h> 427cafeaa1SWarner Losh #include <lutils.h> 43*77d4be50SConrad Meyer #include <lfs.h> 447cafeaa1SWarner Losh 457cafeaa1SWarner Losh struct interp_lua_softc { 467cafeaa1SWarner Losh lua_State *luap; 477cafeaa1SWarner Losh }; 487cafeaa1SWarner Losh 497cafeaa1SWarner Losh static struct interp_lua_softc lua_softc; 507cafeaa1SWarner Losh 517cafeaa1SWarner Losh #ifdef LUA_DEBUG 527cafeaa1SWarner Losh #define LDBG(...) do { \ 537cafeaa1SWarner Losh printf("%s(%d): ", __func__, __LINE__); \ 547cafeaa1SWarner Losh printf(__VA_ARGS__); \ 557cafeaa1SWarner Losh printf("\n"); \ 567cafeaa1SWarner Losh } while (0) 577cafeaa1SWarner Losh #else 587cafeaa1SWarner Losh #define LDBG(...) 597cafeaa1SWarner Losh #endif 607cafeaa1SWarner Losh 617cafeaa1SWarner Losh 627cafeaa1SWarner Losh static void * 637cafeaa1SWarner Losh interp_lua_realloc(void *ud __unused, void *ptr, size_t osize __unused, size_t nsize) 647cafeaa1SWarner Losh { 657cafeaa1SWarner Losh 667cafeaa1SWarner Losh if (nsize == 0) { 677cafeaa1SWarner Losh free(ptr); 687cafeaa1SWarner Losh return NULL; 697cafeaa1SWarner Losh } 707cafeaa1SWarner Losh return realloc(ptr, nsize); 717cafeaa1SWarner Losh } 727cafeaa1SWarner Losh 737cafeaa1SWarner Losh /* 747cafeaa1SWarner Losh * The libraries commented out below either lack the proper 757cafeaa1SWarner Losh * support from libsa, or they are unlikely to be useful 767cafeaa1SWarner Losh * in the bootloader, so have been commented out. 777cafeaa1SWarner Losh */ 787cafeaa1SWarner Losh static const luaL_Reg loadedlibs[] = { 797cafeaa1SWarner Losh {"_G", luaopen_base}, 807cafeaa1SWarner Losh {LUA_LOADLIBNAME, luaopen_package}, 817cafeaa1SWarner Losh // {LUA_COLIBNAME, luaopen_coroutine}, 827cafeaa1SWarner Losh // {LUA_TABLIBNAME, luaopen_table}, 837cafeaa1SWarner Losh {LUA_STRLIBNAME, luaopen_string}, 847cafeaa1SWarner Losh // {LUA_IOLIBNAME, luaopen_io}, 857cafeaa1SWarner Losh // {LUA_OSLIBNAME, luaopen_os}, 867cafeaa1SWarner Losh // {LUA_MATHLIBNAME, luaopen_math}, 877cafeaa1SWarner Losh // {LUA_UTF8LIBNAME, luaopen_utf8}, 887cafeaa1SWarner Losh // {LUA_DBLIBNAME, luaopen_debug}, 896771d4a8SConrad Meyer {"io", luaopen_io}, 90*77d4be50SConrad Meyer {"lfs", luaopen_lfs}, 916771d4a8SConrad Meyer {"loader", luaopen_loader}, 927cafeaa1SWarner Losh {NULL, NULL} 937cafeaa1SWarner Losh }; 947cafeaa1SWarner Losh 957cafeaa1SWarner Losh void 967cafeaa1SWarner Losh interp_init(void) 977cafeaa1SWarner Losh { 987cafeaa1SWarner Losh lua_State *luap; 997cafeaa1SWarner Losh struct interp_lua_softc *softc = &lua_softc; 1007cafeaa1SWarner Losh const char *filename; 1017cafeaa1SWarner Losh const luaL_Reg *lib; 1027cafeaa1SWarner Losh 1037cafeaa1SWarner Losh setenv("script.lang", "lua", 1); 1047cafeaa1SWarner Losh LDBG("creating context"); 1057cafeaa1SWarner Losh 1067cafeaa1SWarner Losh luap = lua_newstate(interp_lua_realloc, NULL); 1077cafeaa1SWarner Losh if (luap == NULL) { 1087cafeaa1SWarner Losh printf("problem initializing the Lua interpreter\n"); 1097cafeaa1SWarner Losh abort(); 1107cafeaa1SWarner Losh } 1117cafeaa1SWarner Losh softc->luap = luap; 1127cafeaa1SWarner Losh 1137cafeaa1SWarner Losh /* "require" functions from 'loadedlibs' and set results to global table */ 1147cafeaa1SWarner Losh for (lib = loadedlibs; lib->func; lib++) { 1157cafeaa1SWarner Losh luaL_requiref(luap, lib->name, lib->func, 1); 1167cafeaa1SWarner Losh lua_pop(luap, 1); /* remove lib */ 1177cafeaa1SWarner Losh } 1187cafeaa1SWarner Losh 1197cafeaa1SWarner Losh filename = "/boot/lua/loader.lua"; 1207cafeaa1SWarner Losh if (interp_include(filename) != 0) { 1217cafeaa1SWarner Losh const char *errstr = lua_tostring(luap, -1); 1227cafeaa1SWarner Losh errstr = errstr == NULL ? "unknown" : errstr; 1237cafeaa1SWarner Losh printf("Startup errorr in %s:\nLUA ERROR: %s.\n", filename, errstr); 1247cafeaa1SWarner Losh lua_pop(luap, 1); 1257cafeaa1SWarner Losh } 1267cafeaa1SWarner Losh } 1277cafeaa1SWarner Losh 1287cafeaa1SWarner Losh int 1297cafeaa1SWarner Losh interp_run(const char *line) 1307cafeaa1SWarner Losh { 1317cafeaa1SWarner Losh int argc; 1327cafeaa1SWarner Losh char **argv; 1337cafeaa1SWarner Losh lua_State *luap; 1347cafeaa1SWarner Losh struct interp_lua_softc *softc = &lua_softc; 1357cafeaa1SWarner Losh int status; 1367cafeaa1SWarner Losh 1377cafeaa1SWarner Losh luap = softc->luap; 1387cafeaa1SWarner Losh LDBG("executing line..."); 1397cafeaa1SWarner Losh if ((status = luaL_dostring(luap, line)) != 0) { 1407cafeaa1SWarner Losh /* 1417cafeaa1SWarner Losh * If we could not parse the line as Lua syntax, 1427cafeaa1SWarner Losh * try parsing it as a loader command. 1437cafeaa1SWarner Losh */ 1447cafeaa1SWarner Losh lua_pop(luap, 1); 1457cafeaa1SWarner Losh if (parse(&argc, &argv, line) == 0) { 1467cafeaa1SWarner Losh status = interp_builtin_cmd(argc, argv); 1477cafeaa1SWarner Losh if (status != CMD_OK) 1487cafeaa1SWarner Losh printf("Command failed\n"); 1497cafeaa1SWarner Losh free(argv); 1507cafeaa1SWarner Losh } else { 1517cafeaa1SWarner Losh printf("Failed to parse \'%s\'\n", line); 1527cafeaa1SWarner Losh status = -1; 1537cafeaa1SWarner Losh } 1547cafeaa1SWarner Losh } 1557cafeaa1SWarner Losh 1567cafeaa1SWarner Losh return (status == 0 ? CMD_OK : CMD_ERROR); 1577cafeaa1SWarner Losh } 1587cafeaa1SWarner Losh 1597cafeaa1SWarner Losh int 1607cafeaa1SWarner Losh interp_include(const char *filename) 1617cafeaa1SWarner Losh { 1627cafeaa1SWarner Losh struct interp_lua_softc *softc = &lua_softc; 1637cafeaa1SWarner Losh 1647cafeaa1SWarner Losh LDBG("loading file %s", filename); 1657cafeaa1SWarner Losh 1667cafeaa1SWarner Losh return (luaL_dofile(softc->luap, filename)); 1677cafeaa1SWarner Losh } 168