Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/stand/common/interp_lua.c
34677 views
1
/*-
2
* Copyright (c) 2011 Wojciech A. Koszek <[email protected]>
3
* Copyright (c) 2014 Pedro Souza <[email protected]>
4
* All rights reserved.
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*/
27
28
#include <stand.h>
29
#include "bootstrap.h"
30
31
#define lua_c
32
33
#include "lstd.h"
34
35
#include <lua.h>
36
#include <ldebug.h>
37
#include <lauxlib.h>
38
#include <lualib.h>
39
40
#include <lerrno.h>
41
#include <lfs.h>
42
#include <lutils.h>
43
44
struct interp_lua_softc {
45
lua_State *luap;
46
};
47
48
static struct interp_lua_softc lua_softc;
49
50
#ifdef LUA_DEBUG
51
#define LDBG(...) do { \
52
printf("%s(%d): ", __func__, __LINE__); \
53
printf(__VA_ARGS__); \
54
printf("\n"); \
55
} while (0)
56
#else
57
#define LDBG(...)
58
#endif
59
60
#define LOADER_LUA LUA_PATH "/loader.lua"
61
62
INTERP_DEFINE("lua");
63
64
static void *
65
interp_lua_realloc(void *ud __unused, void *ptr, size_t osize __unused, size_t nsize)
66
{
67
68
if (nsize == 0) {
69
free(ptr);
70
return NULL;
71
}
72
return realloc(ptr, nsize);
73
}
74
75
/*
76
* The libraries commented out below either lack the proper
77
* support from libsa, or they are unlikely to be useful
78
* in the bootloader, so have been commented out.
79
*/
80
static const luaL_Reg loadedlibs[] = {
81
{"_G", luaopen_base},
82
{LUA_LOADLIBNAME, luaopen_package},
83
// {LUA_COLIBNAME, luaopen_coroutine},
84
// {LUA_TABLIBNAME, luaopen_table},
85
{LUA_STRLIBNAME, luaopen_string},
86
// {LUA_IOLIBNAME, luaopen_io},
87
// {LUA_OSLIBNAME, luaopen_os},
88
// {LUA_MATHLIBNAME, luaopen_math},
89
// {LUA_UTF8LIBNAME, luaopen_utf8},
90
// {LUA_DBLIBNAME, luaopen_debug},
91
{"errno", luaopen_errno},
92
{"io", luaopen_io},
93
{"lfs", luaopen_lfs},
94
{"loader", luaopen_loader},
95
{"pager", luaopen_pager},
96
{NULL, NULL}
97
};
98
99
static bool preinit_done = false;
100
101
void
102
interp_preinit(void)
103
{
104
lua_State *luap;
105
struct interp_lua_softc *softc = &lua_softc;
106
const luaL_Reg *lib;
107
lua_init_md_t **fnpp;
108
109
TSENTER();
110
111
if (preinit_done)
112
return;
113
114
setenv("script.lang", "lua", 1);
115
LDBG("creating context");
116
117
luap = lua_newstate(interp_lua_realloc, NULL);
118
if (luap == NULL) {
119
printf("problem initializing the Lua interpreter\n");
120
abort();
121
}
122
softc->luap = luap;
123
124
/* "require" functions from 'loadedlibs' and set results to global table */
125
for (lib = loadedlibs; lib->func; lib++) {
126
luaL_requiref(luap, lib->name, lib->func, 1);
127
lua_pop(luap, 1); /* remove lib */
128
}
129
130
LUA_FOREACH_SET(fnpp)
131
(*fnpp)(luap);
132
133
preinit_done = true;
134
135
TSEXIT();
136
}
137
138
void
139
interp_init(void)
140
{
141
lua_State *luap;
142
struct interp_lua_softc *softc = &lua_softc;
143
const char *filename;
144
145
TSENTER();
146
147
luap = softc->luap;
148
filename = getenv("loader_lua");
149
if (filename == NULL)
150
filename = LOADER_LUA;
151
if (interp_include(filename) != 0) {
152
const char *errstr = lua_tostring(luap, -1);
153
errstr = errstr == NULL ? "unknown" : errstr;
154
printf("ERROR: %s.\n", errstr);
155
lua_pop(luap, 1);
156
setenv("autoboot_delay", "NO", 1);
157
}
158
159
TSEXIT();
160
}
161
162
int
163
interp_run(const char *line)
164
{
165
int argc, nargc;
166
char **argv;
167
lua_State *luap;
168
struct interp_lua_softc *softc = &lua_softc;
169
int status, ret;
170
171
TSENTER();
172
luap = softc->luap;
173
LDBG("executing line...");
174
if ((status = luaL_dostring(luap, line)) != 0) {
175
lua_pop(luap, 1);
176
/*
177
* The line wasn't executable as lua; run it through parse to
178
* to get consistent parsing of command line arguments, then
179
* run it through cli_execute. If that fails, then we'll try it
180
* as a builtin.
181
*/
182
command_errmsg = NULL;
183
if (parse(&argc, &argv, line) == 0) {
184
lua_getglobal(luap, "cli_execute");
185
for (nargc = 0; nargc < argc; ++nargc) {
186
lua_pushstring(luap, argv[nargc]);
187
}
188
status = lua_pcall(luap, argc, 1, 0);
189
ret = lua_tointeger(luap, 1);
190
lua_pop(luap, 1);
191
if (status != 0 || ret != 0) {
192
/*
193
* Lua cli_execute will pass the function back
194
* through loader.command, which is a proxy to
195
* interp_builtin_cmd. If we failed to interpret
196
* the command, though, then there's a chance
197
* that didn't happen. Call interp_builtin_cmd
198
* directly if our lua_pcall was not successful.
199
*/
200
status = interp_builtin_cmd(argc, argv);
201
}
202
if (status != 0) {
203
if (command_errmsg != NULL)
204
printf("%s\n", command_errmsg);
205
else
206
printf("Command failed\n");
207
status = CMD_ERROR;
208
}
209
free(argv);
210
} else {
211
printf("Failed to parse \'%s\'\n", line);
212
status = CMD_ERROR;
213
}
214
}
215
216
TSEXIT();
217
return (status == 0 ? CMD_OK : CMD_ERROR);
218
}
219
220
int
221
interp_include(const char *filename)
222
{
223
struct interp_lua_softc *softc = &lua_softc;
224
225
LDBG("loading file %s", filename);
226
227
return (luaL_dofile(softc->luap, filename));
228
}
229
230