xref: /freebsd/stand/liblua/lutils.c (revision 9398a495eb305d5bf240bc998ee2f6128d75f4ca)
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