17cafeaa1SWarner Losh /*-
27cafeaa1SWarner Losh * Copyright (c) 2014 Pedro Souza <pedrosouza@freebsd.org>
37cafeaa1SWarner Losh * All rights reserved.
47cafeaa1SWarner Losh *
57cafeaa1SWarner Losh * Redistribution and use in source and binary forms, with or without
67cafeaa1SWarner Losh * modification, are permitted provided that the following conditions
77cafeaa1SWarner Losh * are met:
87cafeaa1SWarner Losh * 1. Redistributions of source code must retain the above copyright
97cafeaa1SWarner Losh * notice, this list of conditions and the following disclaimer.
107cafeaa1SWarner Losh * 2. Redistributions in binary form must reproduce the above copyright
117cafeaa1SWarner Losh * notice, this list of conditions and the following disclaimer in the
127cafeaa1SWarner Losh * documentation and/or other materials provided with the distribution.
137cafeaa1SWarner Losh *
147cafeaa1SWarner Losh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
157cafeaa1SWarner Losh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
167cafeaa1SWarner Losh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
177cafeaa1SWarner Losh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
187cafeaa1SWarner Losh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
197cafeaa1SWarner Losh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
207cafeaa1SWarner Losh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
217cafeaa1SWarner Losh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
227cafeaa1SWarner Losh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
237cafeaa1SWarner Losh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
247cafeaa1SWarner Losh * SUCH DAMAGE.
257cafeaa1SWarner Losh *
267cafeaa1SWarner Losh */
277cafeaa1SWarner Losh
282630b89bSKyle Evans #include <sys/param.h>
292630b89bSKyle Evans
307cafeaa1SWarner Losh #include "lua.h"
317cafeaa1SWarner Losh #include "lauxlib.h"
327cafeaa1SWarner Losh #include "lstd.h"
337cafeaa1SWarner Losh #include "lutils.h"
347cafeaa1SWarner Losh #include "bootstrap.h"
357cafeaa1SWarner Losh
36a83546e5SWarner Losh /*
37a83546e5SWarner Losh * Like loader.perform, except args are passed already parsed
38a83546e5SWarner Losh * on the stack.
39a83546e5SWarner Losh */
40a83546e5SWarner Losh static int
lua_command(lua_State * L)41a83546e5SWarner Losh lua_command(lua_State *L)
42a83546e5SWarner Losh {
43a83546e5SWarner Losh int i;
44a83546e5SWarner Losh int res = 1;
45a83546e5SWarner Losh int argc = lua_gettop(L);
46a83546e5SWarner Losh char **argv;
47a83546e5SWarner Losh
48a83546e5SWarner Losh argv = malloc(sizeof(char *) * (argc + 1));
49a83546e5SWarner Losh if (argv == NULL)
50a83546e5SWarner Losh return 0;
51a83546e5SWarner Losh for (i = 0; i < argc; i++)
52a83546e5SWarner Losh argv[i] = (char *)(intptr_t)luaL_checkstring(L, i + 1);
53a83546e5SWarner Losh argv[argc] = NULL;
54a83546e5SWarner Losh res = interp_builtin_cmd(argc, argv);
55a83546e5SWarner Losh free(argv);
56a83546e5SWarner Losh lua_pushinteger(L, res);
57a83546e5SWarner Losh
58a83546e5SWarner Losh return 1;
59a83546e5SWarner Losh }
60a83546e5SWarner Losh
617cafeaa1SWarner Losh static int
lua_has_command(lua_State * L)6229fc4075SWarner Losh lua_has_command(lua_State *L)
6329fc4075SWarner Losh {
6429fc4075SWarner Losh const char *cmd;
6529fc4075SWarner Losh
667fc95c31SWarner Losh cmd = luaL_checkstring(L, 1);
677fc95c31SWarner Losh if (interp_has_builtin_cmd(cmd)) {
687fc95c31SWarner Losh lua_pushboolean(L, 1);
6929fc4075SWarner Losh return 1;
7029fc4075SWarner Losh }
7129fc4075SWarner Losh
727fc95c31SWarner Losh lua_pushnil(L);
737fc95c31SWarner Losh lua_pushstring(L, "Builtin command not found");
747fc95c31SWarner Losh return 2;
7529fc4075SWarner Losh }
7629fc4075SWarner Losh
7729fc4075SWarner Losh static int
lua_has_feature(lua_State * L)781631382cSKyle Evans lua_has_feature(lua_State *L)
791631382cSKyle Evans {
801631382cSKyle Evans const char *feature;
811631382cSKyle Evans char *msg;
821631382cSKyle Evans
831631382cSKyle Evans feature = luaL_checkstring(L, 1);
841631382cSKyle Evans
851631382cSKyle Evans if (feature_name_is_enabled(feature)) {
861631382cSKyle Evans lua_pushboolean(L, 1);
871631382cSKyle Evans return 1;
881631382cSKyle Evans }
891631382cSKyle Evans
901631382cSKyle Evans lua_pushnil(L);
911631382cSKyle Evans lua_pushstring(L, "Feature not enabled");
921631382cSKyle Evans return 2;
931631382cSKyle Evans }
941631382cSKyle Evans
951631382cSKyle Evans
961631382cSKyle Evans static int
lua_perform(lua_State * L)977cafeaa1SWarner Losh lua_perform(lua_State *L)
987cafeaa1SWarner Losh {
997cafeaa1SWarner Losh int argc;
1007cafeaa1SWarner Losh char **argv;
1017cafeaa1SWarner Losh int res = 1;
1027cafeaa1SWarner Losh
1037cafeaa1SWarner Losh if (parse(&argc, &argv, luaL_checkstring(L, 1)) == 0) {
1047cafeaa1SWarner Losh res = interp_builtin_cmd(argc, argv);
1057cafeaa1SWarner Losh free(argv);
1067cafeaa1SWarner Losh }
1077cafeaa1SWarner Losh lua_pushinteger(L, res);
1087cafeaa1SWarner Losh
1097cafeaa1SWarner Losh return 1;
1107cafeaa1SWarner Losh }
1117cafeaa1SWarner Losh
1123078173cSKyle Evans static int
lua_exit(lua_State * L)113*9398a495SWarner Losh lua_exit(lua_State *L)
114*9398a495SWarner Losh {
115*9398a495SWarner Losh exit(luaL_checkinteger(L, 1));
116*9398a495SWarner Losh return 0;
117*9398a495SWarner Losh }
118*9398a495SWarner Losh
119*9398a495SWarner Losh static int
lua_command_error(lua_State * L)1203078173cSKyle Evans lua_command_error(lua_State *L)
1213078173cSKyle Evans {
1223078173cSKyle Evans
1233078173cSKyle Evans lua_pushstring(L, command_errbuf);
1243078173cSKyle Evans return 1;
1253078173cSKyle Evans }
1263078173cSKyle Evans
127dc4e0284SKyle Evans /*
128dc4e0284SKyle Evans * Accepts a space-delimited loader command and runs it through the standard
129dc4e0284SKyle Evans * loader parsing, as if it were executed at the loader prompt by the user.
130dc4e0284SKyle Evans */
131dc4e0284SKyle Evans static int
lua_interpret(lua_State * L)132dc4e0284SKyle Evans lua_interpret(lua_State *L)
133dc4e0284SKyle Evans {
134dc4e0284SKyle Evans const char *interp_string;
135dc4e0284SKyle Evans
136dc4e0284SKyle Evans if (lua_gettop(L) != 1) {
137dc4e0284SKyle Evans lua_pushnil(L);
138dc4e0284SKyle Evans return 1;
139dc4e0284SKyle Evans }
140dc4e0284SKyle Evans
141dc4e0284SKyle Evans interp_string = luaL_checkstring(L, 1);
142dc4e0284SKyle Evans lua_pushinteger(L, interp_run(interp_string));
143dc4e0284SKyle Evans return 1;
144dc4e0284SKyle Evans }
145dc4e0284SKyle Evans
1467cafeaa1SWarner Losh static int
lua_parse(lua_State * L)147697f127dSKyle Evans lua_parse(lua_State *L)
148697f127dSKyle Evans {
149697f127dSKyle Evans int argc, nargc;
150697f127dSKyle Evans char **argv;
151697f127dSKyle Evans
152697f127dSKyle Evans if (parse(&argc, &argv, luaL_checkstring(L, 1)) == 0) {
153697f127dSKyle Evans for (nargc = 0; nargc < argc; ++nargc) {
154697f127dSKyle Evans lua_pushstring(L, argv[nargc]);
155697f127dSKyle Evans }
156697f127dSKyle Evans free(argv);
157697f127dSKyle Evans return nargc;
158697f127dSKyle Evans }
159697f127dSKyle Evans
160697f127dSKyle Evans lua_pushnil(L);
161697f127dSKyle Evans return 1;
162697f127dSKyle Evans }
163697f127dSKyle Evans
164697f127dSKyle Evans static int
lua_getchar(lua_State * L)1657cafeaa1SWarner Losh lua_getchar(lua_State *L)
1667cafeaa1SWarner Losh {
1677cafeaa1SWarner Losh
1687cafeaa1SWarner Losh lua_pushinteger(L, getchar());
1697cafeaa1SWarner Losh return 1;
1707cafeaa1SWarner Losh }
1717cafeaa1SWarner Losh
1727cafeaa1SWarner Losh static int
lua_ischar(lua_State * L)1737cafeaa1SWarner Losh lua_ischar(lua_State *L)
1747cafeaa1SWarner Losh {
1757cafeaa1SWarner Losh
1767cafeaa1SWarner Losh lua_pushboolean(L, ischar());
1777cafeaa1SWarner Losh return 1;
1787cafeaa1SWarner Losh }
1797cafeaa1SWarner Losh
1807cafeaa1SWarner Losh static int
lua_gets(lua_State * L)1817cafeaa1SWarner Losh lua_gets(lua_State *L)
1827cafeaa1SWarner Losh {
1837cafeaa1SWarner Losh char buf[129];
1847cafeaa1SWarner Losh
1857cafeaa1SWarner Losh ngets(buf, 128);
1867cafeaa1SWarner Losh lua_pushstring(L, buf);
1877cafeaa1SWarner Losh return 1;
1887cafeaa1SWarner Losh }
1897cafeaa1SWarner Losh
1907cafeaa1SWarner Losh static int
lua_time(lua_State * L)1917cafeaa1SWarner Losh lua_time(lua_State *L)
1927cafeaa1SWarner Losh {
1937cafeaa1SWarner Losh
1947cafeaa1SWarner Losh lua_pushinteger(L, time(NULL));
1957cafeaa1SWarner Losh return 1;
1967cafeaa1SWarner Losh }
1977cafeaa1SWarner Losh
1987cafeaa1SWarner Losh static int
lua_delay(lua_State * L)1997cafeaa1SWarner Losh lua_delay(lua_State *L)
2007cafeaa1SWarner Losh {
2017cafeaa1SWarner Losh
2027cafeaa1SWarner Losh delay((int)luaL_checknumber(L, 1));
2037cafeaa1SWarner Losh return 0;
2047cafeaa1SWarner Losh }
2057cafeaa1SWarner Losh
2067cafeaa1SWarner Losh static int
lua_getenv(lua_State * L)2077cafeaa1SWarner Losh lua_getenv(lua_State *L)
2087cafeaa1SWarner Losh {
2097cafeaa1SWarner Losh lua_pushstring(L, getenv(luaL_checkstring(L, 1)));
2107cafeaa1SWarner Losh
2117cafeaa1SWarner Losh return 1;
2127cafeaa1SWarner Losh }
2137cafeaa1SWarner Losh
2147cafeaa1SWarner Losh static int
lua_setenv(lua_State * L)2157cafeaa1SWarner Losh lua_setenv(lua_State *L)
2167cafeaa1SWarner Losh {
2177cafeaa1SWarner Losh const char *key, *val;
2187cafeaa1SWarner Losh
2197cafeaa1SWarner Losh key = luaL_checkstring(L, 1);
2207cafeaa1SWarner Losh val = luaL_checkstring(L, 2);
2217cafeaa1SWarner Losh lua_pushinteger(L, setenv(key, val, 1));
2227cafeaa1SWarner Losh
2237cafeaa1SWarner Losh return 1;
2247cafeaa1SWarner Losh }
2257cafeaa1SWarner Losh
2267cafeaa1SWarner Losh static int
lua_unsetenv(lua_State * L)2277cafeaa1SWarner Losh lua_unsetenv(lua_State *L)
2287cafeaa1SWarner Losh {
2297cafeaa1SWarner Losh const char *ev;
2307cafeaa1SWarner Losh
2317cafeaa1SWarner Losh ev = luaL_checkstring(L, 1);
2327cafeaa1SWarner Losh lua_pushinteger(L, unsetenv(ev));
2337cafeaa1SWarner Losh
2347cafeaa1SWarner Losh return 1;
2357cafeaa1SWarner Losh }
2367cafeaa1SWarner Losh
2377cafeaa1SWarner Losh static int
lua_printc(lua_State * L)2387cafeaa1SWarner Losh lua_printc(lua_State *L)
2397cafeaa1SWarner Losh {
240a16664ceSKyle Evans ssize_t cur, l;
2417cafeaa1SWarner Losh const char *s = luaL_checklstring(L, 1, &l);
2427cafeaa1SWarner Losh
243a16664ceSKyle Evans for (cur = 0; cur < l; ++cur)
244a16664ceSKyle Evans putchar((unsigned char)*(s++));
2457cafeaa1SWarner Losh
246a16664ceSKyle Evans return 1;
2477cafeaa1SWarner Losh }
2487cafeaa1SWarner Losh
2497cafeaa1SWarner Losh static int
lua_openfile(lua_State * L)2507cafeaa1SWarner Losh lua_openfile(lua_State *L)
2517cafeaa1SWarner Losh {
25282c85a42SKyle Evans const char *mode, *str;
25382c85a42SKyle Evans int nargs;
2547cafeaa1SWarner Losh
25582c85a42SKyle Evans nargs = lua_gettop(L);
25682c85a42SKyle Evans if (nargs < 1 || nargs > 2) {
2577cafeaa1SWarner Losh lua_pushnil(L);
2587cafeaa1SWarner Losh return 1;
2597cafeaa1SWarner Losh }
2607cafeaa1SWarner Losh str = lua_tostring(L, 1);
26182c85a42SKyle Evans mode = "r";
26282c85a42SKyle Evans if (nargs > 1) {
26382c85a42SKyle Evans mode = lua_tostring(L, 2);
26482c85a42SKyle Evans if (mode == NULL) {
26582c85a42SKyle Evans lua_pushnil(L);
26682c85a42SKyle Evans return 1;
26782c85a42SKyle Evans }
26882c85a42SKyle Evans }
26982c85a42SKyle Evans FILE * f = fopen(str, mode);
2707cafeaa1SWarner Losh if (f != NULL) {
2717cafeaa1SWarner Losh FILE ** ptr = (FILE**)lua_newuserdata(L, sizeof(FILE**));
2727cafeaa1SWarner Losh *ptr = f;
2737cafeaa1SWarner Losh } else
2747cafeaa1SWarner Losh lua_pushnil(L);
2757cafeaa1SWarner Losh return 1;
2767cafeaa1SWarner Losh }
2777cafeaa1SWarner Losh
2787cafeaa1SWarner Losh static int
lua_closefile(lua_State * L)2797cafeaa1SWarner Losh lua_closefile(lua_State *L)
2807cafeaa1SWarner Losh {
2817cafeaa1SWarner Losh FILE ** f;
2827cafeaa1SWarner Losh if (lua_gettop(L) != 1) {
2837cafeaa1SWarner Losh lua_pushboolean(L, 0);
2847cafeaa1SWarner Losh return 1;
2857cafeaa1SWarner Losh }
2867cafeaa1SWarner Losh
2877cafeaa1SWarner Losh f = (FILE**)lua_touserdata(L, 1);
2887cafeaa1SWarner Losh if (f != NULL && *f != NULL) {
2897cafeaa1SWarner Losh lua_pushboolean(L, fclose(*f) == 0 ? 1 : 0);
2907cafeaa1SWarner Losh *f = NULL;
2917cafeaa1SWarner Losh } else
2927cafeaa1SWarner Losh lua_pushboolean(L, 0);
2937cafeaa1SWarner Losh
2947cafeaa1SWarner Losh return 1;
2957cafeaa1SWarner Losh }
2967cafeaa1SWarner Losh
2977cafeaa1SWarner Losh static int
lua_readfile(lua_State * L)2987cafeaa1SWarner Losh lua_readfile(lua_State *L)
2997cafeaa1SWarner Losh {
3007cafeaa1SWarner Losh FILE **f;
3017cafeaa1SWarner Losh size_t size, r;
3027cafeaa1SWarner Losh char * buf;
3037cafeaa1SWarner Losh
3047cafeaa1SWarner Losh if (lua_gettop(L) < 1 || lua_gettop(L) > 2) {
3057cafeaa1SWarner Losh lua_pushnil(L);
3067cafeaa1SWarner Losh lua_pushinteger(L, 0);
3077cafeaa1SWarner Losh return 2;
3087cafeaa1SWarner Losh }
3097cafeaa1SWarner Losh
3107cafeaa1SWarner Losh f = (FILE**)lua_touserdata(L, 1);
3117cafeaa1SWarner Losh
3127cafeaa1SWarner Losh if (f == NULL || *f == NULL) {
3137cafeaa1SWarner Losh lua_pushnil(L);
3147cafeaa1SWarner Losh lua_pushinteger(L, 0);
3157cafeaa1SWarner Losh return 2;
3167cafeaa1SWarner Losh }
3177cafeaa1SWarner Losh
3187cafeaa1SWarner Losh if (lua_gettop(L) == 2)
3197cafeaa1SWarner Losh size = (size_t)lua_tonumber(L, 2);
3207cafeaa1SWarner Losh else
3217cafeaa1SWarner Losh size = (*f)->size;
3227cafeaa1SWarner Losh
3237cafeaa1SWarner Losh
3247cafeaa1SWarner Losh buf = (char*)malloc(size);
3257cafeaa1SWarner Losh r = fread(buf, 1, size, *f);
3267cafeaa1SWarner Losh lua_pushlstring(L, buf, r);
3277cafeaa1SWarner Losh free(buf);
3287cafeaa1SWarner Losh lua_pushinteger(L, r);
3297cafeaa1SWarner Losh
3307cafeaa1SWarner Losh return 2;
3317cafeaa1SWarner Losh }
3327cafeaa1SWarner Losh
33382c85a42SKyle Evans /*
33482c85a42SKyle Evans * Implements io.write(file, ...)
33582c85a42SKyle Evans * Any number of string and number arguments may be passed to it,
33682c85a42SKyle Evans * and it will return the number of bytes written, or nil, an error string, and
33782c85a42SKyle Evans * the errno.
33882c85a42SKyle Evans */
33982c85a42SKyle Evans static int
lua_writefile(lua_State * L)34082c85a42SKyle Evans lua_writefile(lua_State *L)
34182c85a42SKyle Evans {
34282c85a42SKyle Evans FILE **f;
34382c85a42SKyle Evans const char *buf;
34482c85a42SKyle Evans int i, nargs;
34582c85a42SKyle Evans size_t bufsz, w, wrsz;
34682c85a42SKyle Evans
34782c85a42SKyle Evans buf = NULL;
34882c85a42SKyle Evans bufsz = 0;
34982c85a42SKyle Evans w = 0;
35082c85a42SKyle Evans wrsz = 0;
35182c85a42SKyle Evans nargs = lua_gettop(L);
35282c85a42SKyle Evans if (nargs < 2) {
35382c85a42SKyle Evans errno = EINVAL;
35482c85a42SKyle Evans return luaL_fileresult(L, 0, NULL);
35582c85a42SKyle Evans }
35682c85a42SKyle Evans
35782c85a42SKyle Evans f = (FILE**)lua_touserdata(L, 1);
35882c85a42SKyle Evans
35982c85a42SKyle Evans if (f == NULL || *f == NULL) {
36082c85a42SKyle Evans errno = EINVAL;
36182c85a42SKyle Evans return luaL_fileresult(L, 0, NULL);
36282c85a42SKyle Evans }
36382c85a42SKyle Evans
36482c85a42SKyle Evans /* Do a validation pass first */
36582c85a42SKyle Evans for (i = 0; i < nargs - 1; i++) {
36682c85a42SKyle Evans /*
36782c85a42SKyle Evans * With Lua's API, lua_isstring really checks if the argument
36882c85a42SKyle Evans * is a string or a number. The latter will be implicitly
36982c85a42SKyle Evans * converted to a string by our later call to lua_tolstring.
37082c85a42SKyle Evans */
37182c85a42SKyle Evans if (!lua_isstring(L, i + 2)) {
37282c85a42SKyle Evans errno = EINVAL;
37382c85a42SKyle Evans return luaL_fileresult(L, 0, NULL);
37482c85a42SKyle Evans }
37582c85a42SKyle Evans }
37682c85a42SKyle Evans for (i = 0; i < nargs - 1; i++) {
37782c85a42SKyle Evans /* We've already validated; there's no chance of failure */
37882c85a42SKyle Evans buf = lua_tolstring(L, i + 2, &bufsz);
37982c85a42SKyle Evans wrsz = fwrite(buf, 1, bufsz, *f);
38082c85a42SKyle Evans if (wrsz < bufsz)
38182c85a42SKyle Evans return luaL_fileresult(L, 0, NULL);
38282c85a42SKyle Evans w += wrsz;
38382c85a42SKyle Evans }
38482c85a42SKyle Evans lua_pushinteger(L, w);
38582c85a42SKyle Evans return 1;
38682c85a42SKyle Evans }
38782c85a42SKyle Evans
388f276951aSConrad Meyer #define REG_SIMPLE(n) { #n, lua_ ## n }
389f276951aSConrad Meyer static const struct luaL_Reg loaderlib[] = {
390a83546e5SWarner Losh REG_SIMPLE(command),
391*9398a495SWarner Losh REG_SIMPLE(command_error),
392*9398a495SWarner Losh REG_SIMPLE(delay),
393*9398a495SWarner Losh REG_SIMPLE(exit),
394f276951aSConrad Meyer REG_SIMPLE(getenv),
39529fc4075SWarner Losh REG_SIMPLE(has_command),
3961631382cSKyle Evans REG_SIMPLE(has_feature),
397*9398a495SWarner Losh REG_SIMPLE(interpret),
398*9398a495SWarner Losh REG_SIMPLE(parse),
399f276951aSConrad Meyer REG_SIMPLE(perform),
40029fc4075SWarner Losh REG_SIMPLE(printc), /* Also registered as the global 'printc' */
401f276951aSConrad Meyer REG_SIMPLE(setenv),
402f276951aSConrad Meyer REG_SIMPLE(time),
403f276951aSConrad Meyer REG_SIMPLE(unsetenv),
4041dac5a34SWarner Losh { NULL, NULL },
4051dac5a34SWarner Losh };
4061dac5a34SWarner Losh
407f276951aSConrad Meyer static const struct luaL_Reg iolib[] = {
408f276951aSConrad Meyer { "close", lua_closefile },
409f276951aSConrad Meyer REG_SIMPLE(getchar),
410f276951aSConrad Meyer REG_SIMPLE(gets),
411f276951aSConrad Meyer REG_SIMPLE(ischar),
412f276951aSConrad Meyer { "open", lua_openfile },
413f276951aSConrad Meyer { "read", lua_readfile },
41482c85a42SKyle Evans { "write", lua_writefile },
415f276951aSConrad Meyer { NULL, NULL },
416f276951aSConrad Meyer };
417f276951aSConrad Meyer #undef REG_SIMPLE
418f276951aSConrad Meyer
4191631382cSKyle Evans static void
lua_add_feature(void * cookie,const char * name,const char * desc,bool enabled)4201631382cSKyle Evans lua_add_feature(void *cookie, const char *name, const char *desc, bool enabled)
4211631382cSKyle Evans {
4221631382cSKyle Evans lua_State *L = cookie;
4231631382cSKyle Evans
4241631382cSKyle Evans /*
4251631382cSKyle Evans * The feature table consists solely of features that are enabled, and
4261631382cSKyle Evans * their associated descriptions for debugging purposes.
4271631382cSKyle Evans */
4281631382cSKyle Evans lua_pushstring(L, desc);
4291631382cSKyle Evans lua_setfield(L, -2, name);
4301631382cSKyle Evans }
4311631382cSKyle Evans
4321631382cSKyle Evans static void
lua_add_features(lua_State * L)4331631382cSKyle Evans lua_add_features(lua_State *L)
4341631382cSKyle Evans {
4351631382cSKyle Evans
4361631382cSKyle Evans lua_newtable(L);
4371631382cSKyle Evans feature_iter(&lua_add_feature, L);
4381631382cSKyle Evans
4391631382cSKyle Evans /*
4401631382cSKyle Evans * We should still have just the table on the stack after we're done
4411631382cSKyle Evans * iterating.
4421631382cSKyle Evans */
4431631382cSKyle Evans lua_setfield(L, -2, "features");
4441631382cSKyle Evans }
4451631382cSKyle Evans
4466771d4a8SConrad Meyer int
luaopen_loader(lua_State * L)4476771d4a8SConrad Meyer luaopen_loader(lua_State *L)
4487cafeaa1SWarner Losh {
449f276951aSConrad Meyer luaL_newlib(L, loaderlib);
4502630b89bSKyle Evans /* Add loader.machine and loader.machine_arch properties */
4512630b89bSKyle Evans lua_pushstring(L, MACHINE);
4522630b89bSKyle Evans lua_setfield(L, -2, "machine");
4532630b89bSKyle Evans lua_pushstring(L, MACHINE_ARCH);
4542630b89bSKyle Evans lua_setfield(L, -2, "machine_arch");
45563172bf6SKyle Evans lua_pushstring(L, LUA_PATH);
45663172bf6SKyle Evans lua_setfield(L, -2, "lua_path");
457a50d73d5SStephen J. Kiernan lua_pushinteger(L, bootprog_rev);
458a50d73d5SStephen J. Kiernan lua_setfield(L, -2, "version");
45962a52c15SWarner Losh lua_pushinteger(L, CMD_OK);
46062a52c15SWarner Losh lua_setfield(L, -2, "CMD_OK");
46162a52c15SWarner Losh lua_pushinteger(L, CMD_WARN);
46262a52c15SWarner Losh lua_setfield(L, -2, "CMD_WARN");
46362a52c15SWarner Losh lua_pushinteger(L, CMD_ERROR);
46462a52c15SWarner Losh lua_setfield(L, -2, "CMD_ERROR");
46562a52c15SWarner Losh lua_pushinteger(L, CMD_CRIT);
46662a52c15SWarner Losh lua_setfield(L, -2, "CMD_CRIT");
46762a52c15SWarner Losh lua_pushinteger(L, CMD_FATAL);
46862a52c15SWarner Losh lua_setfield(L, -2, "CMD_FATAL");
4691631382cSKyle Evans lua_add_features(L);
47059cccc5bSKyle Evans /* Set global printc to loader.printc */
47159cccc5bSKyle Evans lua_register(L, "printc", lua_printc);
4726771d4a8SConrad Meyer return 1;
4737cafeaa1SWarner Losh }
4746771d4a8SConrad Meyer
4756771d4a8SConrad Meyer int
luaopen_io(lua_State * L)4766771d4a8SConrad Meyer luaopen_io(lua_State *L)
4776771d4a8SConrad Meyer {
4786771d4a8SConrad Meyer luaL_newlib(L, iolib);
4796771d4a8SConrad Meyer return 1;
480929c9bd0SKyle Evans }
481