|
ali@352
|
1 |
/*
|
|
ali@352
|
2 |
* Copyright (C) 2009 J. Ali Harlow <ali@juiblex.co.uk>
|
|
ali@352
|
3 |
*
|
|
ali@352
|
4 |
* This program is free software; you can redistribute it and/or modify
|
|
ali@352
|
5 |
* it under the terms of the GNU General Public License as published by
|
|
ali@352
|
6 |
* the Free Software Foundation; either version 2 of the License, or
|
|
ali@352
|
7 |
* (at your option) any later version.
|
|
ali@352
|
8 |
*
|
|
ali@352
|
9 |
* This program is distributed in the hope that it will be useful,
|
|
ali@352
|
10 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
ali@352
|
11 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
ali@352
|
12 |
* GNU General Public License for more details.
|
|
ali@352
|
13 |
*
|
|
ali@352
|
14 |
* You should have received a copy of the GNU General Public License along
|
|
ali@352
|
15 |
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
ali@352
|
16 |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
ali@352
|
17 |
*/
|
|
ali@352
|
18 |
|
|
ali@352
|
19 |
#include "config.h"
|
|
ali@352
|
20 |
|
|
ali@352
|
21 |
#include <stdlib.h>
|
|
ali@352
|
22 |
#include <string.h>
|
|
ali@352
|
23 |
#include <stdio.h>
|
|
ali@352
|
24 |
#include <errno.h>
|
|
ali@352
|
25 |
#include <sys/stat.h>
|
|
ali@352
|
26 |
#include <sys/types.h>
|
|
ali@352
|
27 |
#include <lua.h>
|
|
ali@352
|
28 |
#include <lualib.h>
|
|
ali@352
|
29 |
#include <lauxlib.h>
|
|
ali@352
|
30 |
|
|
ali@352
|
31 |
#include "razor.h"
|
|
ali@352
|
32 |
#include "razor-internal.h"
|
|
ali@352
|
33 |
|
|
ali@352
|
34 |
#define MAX_ARGS 2
|
|
ali@352
|
35 |
|
|
ali@352
|
36 |
#define ARG_FLAG_OPT 0x1
|
|
ali@352
|
37 |
#define ARG_FLAG_BYPASS 0x2
|
|
ali@352
|
38 |
|
|
ali@352
|
39 |
#define ARG(flags, swtch, index, type) \
|
|
ali@352
|
40 |
((flags) << 26 | (swtch) << 21 | \
|
|
ali@352
|
41 |
(index) << 16 | type)
|
|
ali@352
|
42 |
#define ARG_FLAGS(arg) ((unsigned)(arg) >> 26)
|
|
ali@352
|
43 |
#define ARG_SWTCH(arg) ((unsigned)(arg) >> 21 & 0x1F)
|
|
ali@352
|
44 |
#define ARG_INDEX(arg) ((unsigned)(arg) >> 16 & 0x1F)
|
|
ali@352
|
45 |
#define ARG_TYPE(arg) ((unsigned)(arg) & 0xFFFF)
|
|
ali@352
|
46 |
|
|
ali@352
|
47 |
#define ARG_NONE 0
|
|
ali@352
|
48 |
#define ARG_STRING(n) ARG(0, 0, n, LUA_TSTRING)
|
|
ali@352
|
49 |
#define ARG_OPT_STRING(n) ARG(ARG_FLAG_OPT, 0, n, LUA_TSTRING)
|
|
ali@352
|
50 |
#define ARG_BYP_STRING(n, s) ARG(ARG_FLAG_BYPASS, s, n, LUA_TSTRING)
|
|
ali@352
|
51 |
|
|
ali@352
|
52 |
struct razor_proxy {
|
|
ali@352
|
53 |
char *table, *name;
|
|
ali@352
|
54 |
int result;
|
|
ali@352
|
55 |
unsigned args[MAX_ARGS];
|
|
ali@352
|
56 |
};
|
|
ali@352
|
57 |
|
|
ali@352
|
58 |
static struct razor_proxy proxy[] = {
|
|
ali@352
|
59 |
{ NULL, "dofile", LUA_TNONE, { ARG_STRING(1) } },
|
|
ali@352
|
60 |
{ NULL, "loadfile", LUA_TNONE, { ARG_OPT_STRING(1) } },
|
|
ali@352
|
61 |
{ "io", "input", LUA_TNONE, { ARG_OPT_STRING(1) } },
|
|
ali@352
|
62 |
{ "io", "output", LUA_TNONE, { ARG_OPT_STRING(1) } },
|
|
ali@352
|
63 |
{ "io", "lines", LUA_TNONE, { ARG_OPT_STRING(1) } },
|
|
ali@352
|
64 |
{ "io", "open", LUA_TNONE, { ARG_STRING(1) } },
|
|
ali@352
|
65 |
{ "io", "popen", LUA_TNONE, { ARG_STRING(1) } },
|
|
ali@352
|
66 |
/*
|
|
ali@352
|
67 |
* Note: We do not proxy os.execute
|
|
ali@352
|
68 |
* We can't do it properly (there is no way to distinguish filenames
|
|
ali@352
|
69 |
* in arguments from any other strings) so it's better not to try.
|
|
ali@352
|
70 |
* Scripts that attempt to be portable should use posix.exec[p]
|
|
ali@352
|
71 |
*/
|
|
ali@352
|
72 |
{ "os", "remove", LUA_TNONE, { ARG_STRING(1) } },
|
|
ali@352
|
73 |
{ "os", "rename", LUA_TNONE, { ARG_STRING(1), ARG_STRING(2) } },
|
|
ali@352
|
74 |
/*
|
|
ali@352
|
75 |
* Note: We do not proxy os.tmpname
|
|
ali@352
|
76 |
* It should never be used. scripts should use io.tmpfile instead
|
|
ali@352
|
77 |
* if the rather limited functionality it provides suffices. The
|
|
ali@352
|
78 |
* proper solution is to implement posix.mkstemp
|
|
ali@352
|
79 |
*/
|
|
ali@352
|
80 |
{ "posix", "access", LUA_TNONE, { ARG_STRING(1) } },
|
|
ali@352
|
81 |
{ "posix", "chdir", LUA_TNONE, { ARG_STRING(1) } },
|
|
ali@352
|
82 |
{ "posix", "chmod", LUA_TNONE, { ARG_STRING(1) } },
|
|
ali@352
|
83 |
{ "posix", "chown", LUA_TNONE, { ARG_STRING(1) } },
|
|
ali@352
|
84 |
{ "posix", "dir", LUA_TNONE, { ARG_OPT_STRING(1) } },
|
|
ali@352
|
85 |
{ "posix", "exec", LUA_TNONE, { ARG_STRING(1) } },
|
|
ali@352
|
86 |
{ "posix", "execp", LUA_TNONE, { ARG_STRING(1) } },
|
|
ali@352
|
87 |
{ "posix", "files", LUA_TNONE, { ARG_OPT_STRING(1) } },
|
|
ali@352
|
88 |
{ "posix", "getcwd", LUA_TSTRING, { ARG_NONE } },
|
|
ali@352
|
89 |
{ "posix", "glob", LUA_TTABLE, { ARG_STRING(1) } },
|
|
ali@352
|
90 |
{ "posix", "link", LUA_TNONE, { ARG_BYP_STRING(1, 3), ARG_STRING(2) } },
|
|
ali@352
|
91 |
{ "posix", "mkdir", LUA_TNONE, { ARG_STRING(1) } },
|
|
ali@352
|
92 |
{ "posix", "mkfifo", LUA_TNONE, { ARG_STRING(1) } },
|
|
ali@352
|
93 |
{ "posix", "pathconf", LUA_TNONE, { ARG_STRING(1) } },
|
|
ali@352
|
94 |
{ "posix", "readlink", LUA_TNONE, { ARG_STRING(1) } },
|
|
ali@352
|
95 |
{ "posix", "rmdir", LUA_TNONE, { ARG_STRING(1) } },
|
|
ali@352
|
96 |
{ "posix", "stat", LUA_TNONE, { ARG_STRING(1) } },
|
|
ali@352
|
97 |
{ "posix", "unlink", LUA_TNONE, { ARG_STRING(1) } },
|
|
ali@352
|
98 |
{ "posix", "utime", LUA_TNONE, { ARG_STRING(1) } },
|
|
ali@352
|
99 |
};
|
|
ali@352
|
100 |
|
|
ali@352
|
101 |
static lua_CFunction execp_handler;
|
|
ali@352
|
102 |
|
|
ali@352
|
103 |
struct razor_lua {
|
|
ali@352
|
104 |
const char *root;
|
|
ali@352
|
105 |
lua_CFunction handler[ARRAY_SIZE(proxy)];
|
|
ali@352
|
106 |
};
|
|
ali@352
|
107 |
|
|
ali@352
|
108 |
static void *alloc_lua(void *user_data, void *ptr, size_t osize, size_t nsize)
|
|
ali@352
|
109 |
{
|
|
ali@352
|
110 |
if (!nsize) {
|
|
ali@352
|
111 |
free(ptr);
|
|
ali@352
|
112 |
return NULL;
|
|
ali@352
|
113 |
} else
|
|
ali@352
|
114 |
return realloc(ptr, nsize);
|
|
ali@352
|
115 |
}
|
|
ali@352
|
116 |
|
|
ali@352
|
117 |
static int proxy_execp(lua_State *L)
|
|
ali@352
|
118 |
{
|
|
ali@352
|
119 |
int r, n, err, got_eacces = 0;
|
|
ali@352
|
120 |
char *file = strdup(luaL_checkstring(L, 1));
|
|
ali@352
|
121 |
char *exe;
|
|
ali@352
|
122 |
const char *s, *e, *path;
|
|
ali@352
|
123 |
struct razor_lua *rl;
|
|
ali@352
|
124 |
|
|
ali@352
|
125 |
if (*file == '\0' || strchr(file, '/')) {
|
|
ali@352
|
126 |
r = execp_handler(L);
|
|
ali@352
|
127 |
free(file);
|
|
ali@352
|
128 |
return r;
|
|
ali@352
|
129 |
}
|
|
ali@352
|
130 |
|
|
ali@352
|
131 |
(void)lua_getallocf(L, (void **)&rl);
|
|
ali@352
|
132 |
|
|
ali@352
|
133 |
path = getenv("PATH");
|
|
ali@352
|
134 |
if (!path)
|
|
ali@352
|
135 |
path = ":/bin:/usr/bin";
|
|
ali@352
|
136 |
|
|
ali@352
|
137 |
s = path;
|
|
ali@352
|
138 |
for (;;) {
|
|
ali@352
|
139 |
e = strchr(s, ':');
|
|
ali@352
|
140 |
if (!e)
|
|
ali@352
|
141 |
e = s + strlen(s);
|
|
ali@352
|
142 |
if (*s == '/') {
|
|
ali@352
|
143 |
n = strlen(rl->root);
|
|
ali@352
|
144 |
exe = malloc(n + (e - s) + 1 + strlen(file) + 1);
|
|
ali@352
|
145 |
memcpy(exe, rl->root, n);
|
|
ali@352
|
146 |
memcpy(exe + n, s, e - s);
|
|
ali@352
|
147 |
n += e - s;
|
|
ali@352
|
148 |
exe[n++] = '/';
|
|
ali@352
|
149 |
strcpy(exe + n, file);
|
|
ali@352
|
150 |
} else if (e != s) {
|
|
ali@352
|
151 |
exe = malloc((e - s) + 1 + strlen(file) + 1);
|
|
ali@352
|
152 |
memcpy(exe, s, e - s);
|
|
ali@352
|
153 |
n = e - s;
|
|
ali@352
|
154 |
exe[n++] = '/';
|
|
ali@352
|
155 |
strcpy(exe + n, file);
|
|
ali@352
|
156 |
} else {
|
|
ali@352
|
157 |
/* Ensure exe contains a slash to avoid PATH search */
|
|
ali@352
|
158 |
exe = malloc(2 + strlen(file) + 1);
|
|
ali@352
|
159 |
exe[0] = '.';
|
|
ali@352
|
160 |
exe[1] = '/';
|
|
ali@352
|
161 |
strcpy(exe + 2, file);
|
|
ali@352
|
162 |
}
|
|
ali@352
|
163 |
lua_pushstring(L, exe);
|
|
ali@352
|
164 |
lua_replace(L, 1);
|
|
ali@352
|
165 |
free(exe);
|
|
ali@352
|
166 |
n = lua_gettop(L);
|
|
ali@352
|
167 |
r = execp_handler(L);
|
|
ali@352
|
168 |
|
|
ali@352
|
169 |
err = lua_tointeger(L, -1);
|
|
ali@352
|
170 |
switch (err) {
|
|
ali@352
|
171 |
case EACCES:
|
|
ali@352
|
172 |
got_eacces = 1;
|
|
ali@352
|
173 |
/* Fall through */
|
|
ali@352
|
174 |
case ENOENT:
|
|
ali@352
|
175 |
case ESTALE:
|
|
ali@352
|
176 |
case ENOTDIR:
|
|
ali@352
|
177 |
case ENODEV:
|
|
ali@352
|
178 |
case ETIMEDOUT:
|
|
ali@352
|
179 |
lua_pop(L, lua_gettop(L) - n);
|
|
ali@352
|
180 |
break;
|
|
ali@352
|
181 |
default:
|
|
ali@352
|
182 |
free(file);
|
|
ali@352
|
183 |
return r;
|
|
ali@352
|
184 |
}
|
|
ali@352
|
185 |
|
|
ali@352
|
186 |
if (*e)
|
|
ali@352
|
187 |
s = e + 1;
|
|
ali@352
|
188 |
else
|
|
ali@352
|
189 |
break;
|
|
ali@352
|
190 |
}
|
|
ali@352
|
191 |
|
|
ali@352
|
192 |
if (got_eacces)
|
|
ali@352
|
193 |
err = EACCES;
|
|
ali@352
|
194 |
|
|
ali@352
|
195 |
lua_pushnil(L);
|
|
ali@352
|
196 |
lua_pushfstring(L, "%s: %s", file, strerror(err));
|
|
ali@352
|
197 |
lua_pushinteger(L, err);
|
|
ali@352
|
198 |
|
|
ali@352
|
199 |
free(file);
|
|
ali@352
|
200 |
return 3;
|
|
ali@352
|
201 |
}
|
|
ali@352
|
202 |
|
|
ali@352
|
203 |
static int real2fake(lua_State *L, struct razor_lua *rl, int indx)
|
|
ali@352
|
204 |
{
|
|
ali@352
|
205 |
const char *path;
|
|
ali@352
|
206 |
|
|
ali@352
|
207 |
if (indx < 0)
|
|
ali@352
|
208 |
indx += lua_gettop(L) + 1;
|
|
ali@352
|
209 |
|
|
ali@352
|
210 |
if (lua_type(L, indx) == LUA_TSTRING) {
|
|
ali@352
|
211 |
path = lua_tostring(L, indx);
|
|
ali@352
|
212 |
if (path && !strncmp(path, rl->root, strlen(rl->root)) &&
|
|
ali@352
|
213 |
(path[strlen(rl->root)] == '/' || !path[strlen(rl->root)])) {
|
|
ali@352
|
214 |
lua_pushstring(L, path + strlen(rl->root));
|
|
ali@352
|
215 |
lua_replace(L, indx);
|
|
ali@352
|
216 |
return 1;
|
|
ali@352
|
217 |
}
|
|
ali@352
|
218 |
}
|
|
ali@352
|
219 |
|
|
ali@352
|
220 |
return 0;
|
|
ali@352
|
221 |
}
|
|
ali@352
|
222 |
|
|
ali@352
|
223 |
static int proxy_handler(lua_State *L)
|
|
ali@352
|
224 |
{
|
|
ali@352
|
225 |
int i, retval, cond;
|
|
ali@352
|
226 |
unsigned arg;
|
|
ali@352
|
227 |
const char *path;
|
|
ali@352
|
228 |
struct razor_lua *rl;
|
|
ali@352
|
229 |
int method = lua_tointeger(L, lua_upvalueindex(1));
|
|
ali@352
|
230 |
struct razor_proxy *rp = proxy + method;
|
|
ali@352
|
231 |
|
|
ali@352
|
232 |
(void)lua_getallocf(L, (void **)&rl);
|
|
ali@352
|
233 |
|
|
ali@352
|
234 |
for(i = 0; i < MAX_ARGS; i++) {
|
|
ali@352
|
235 |
arg = rp->args[i];
|
|
ali@352
|
236 |
if (arg == ARG_NONE)
|
|
ali@352
|
237 |
continue;
|
|
ali@352
|
238 |
switch (ARG_TYPE(arg)) {
|
|
ali@352
|
239 |
case LUA_TSTRING:
|
|
ali@352
|
240 |
if (ARG_FLAGS(arg) & ARG_FLAG_BYPASS)
|
|
ali@352
|
241 |
cond = !lua_toboolean(L, ARG_SWTCH(arg));
|
|
ali@352
|
242 |
else
|
|
ali@352
|
243 |
cond = 1;
|
|
ali@352
|
244 |
if (ARG_FLAGS(arg) & ARG_FLAG_OPT) {
|
|
ali@352
|
245 |
if (lua_isstring(L, ARG_INDEX(arg)))
|
|
ali@352
|
246 |
path = lua_tostring(L, ARG_INDEX(arg));
|
|
ali@352
|
247 |
else
|
|
ali@352
|
248 |
path = NULL;
|
|
ali@352
|
249 |
} else
|
|
ali@352
|
250 |
path = luaL_checkstring(L, ARG_INDEX(arg));
|
|
ali@352
|
251 |
if (cond && path && *path == '/') {
|
|
ali@352
|
252 |
lua_pushfstring(L, "%s%s", rl->root, path);
|
|
ali@352
|
253 |
lua_replace(L, ARG_INDEX(arg));
|
|
ali@352
|
254 |
}
|
|
ali@352
|
255 |
break;
|
|
ali@352
|
256 |
default:
|
|
ali@352
|
257 |
lua_pushfstring(L, "razor proxy: Unhandled type (%d)",
|
|
ali@352
|
258 |
ARG_TYPE(arg));
|
|
ali@352
|
259 |
lua_error(L);
|
|
ali@352
|
260 |
}
|
|
ali@352
|
261 |
}
|
|
ali@352
|
262 |
|
|
ali@352
|
263 |
retval = rl->handler[method](L);
|
|
ali@352
|
264 |
|
|
ali@352
|
265 |
if (rp->result != LUA_TNONE && !lua_isnil(L, 1)) {
|
|
ali@352
|
266 |
switch (rp->result) {
|
|
ali@352
|
267 |
case LUA_TNONE:
|
|
ali@352
|
268 |
break;
|
|
ali@352
|
269 |
case LUA_TSTRING:
|
|
ali@352
|
270 |
real2fake(L, rl, -1);
|
|
ali@352
|
271 |
break;
|
|
ali@352
|
272 |
case LUA_TTABLE:
|
|
ali@352
|
273 |
lua_pushnil(L);
|
|
ali@352
|
274 |
while (lua_next(L, -2)) {
|
|
ali@352
|
275 |
if (real2fake(L, rl, -1)) {
|
|
ali@352
|
276 |
i = lua_tonumber(L, -2);
|
|
ali@352
|
277 |
lua_rawseti(L, -3, i);
|
|
ali@352
|
278 |
} else
|
|
ali@352
|
279 |
lua_pop(L, 1);
|
|
ali@352
|
280 |
}
|
|
ali@352
|
281 |
break;
|
|
ali@352
|
282 |
default:
|
|
ali@352
|
283 |
lua_pushfstring(L, "razor proxy: Unhandled type (%d)",
|
|
ali@352
|
284 |
rp->result);
|
|
ali@352
|
285 |
lua_error(L);
|
|
ali@352
|
286 |
}
|
|
ali@352
|
287 |
}
|
|
ali@352
|
288 |
|
|
ali@352
|
289 |
return retval;
|
|
ali@352
|
290 |
}
|
|
ali@352
|
291 |
|
|
ali@361
|
292 |
struct razor_lua_loader {
|
|
ali@361
|
293 |
uint32_t name;
|
|
ali@361
|
294 |
lua_CFunction func;
|
|
ali@361
|
295 |
};
|
|
ali@361
|
296 |
|
|
ali@361
|
297 |
static struct razor_preload {
|
|
ali@361
|
298 |
int init;
|
|
ali@361
|
299 |
struct hashtable modules;
|
|
ali@361
|
300 |
struct array name_pool;
|
|
ali@361
|
301 |
struct array loaders;
|
|
ali@361
|
302 |
} razor_preload = {0};
|
|
ali@361
|
303 |
|
|
ali@361
|
304 |
RAZOR_EXPORT void razor_set_lua_loader(const char *modname, void (*loader)())
|
|
ali@361
|
305 |
{
|
|
ali@361
|
306 |
uint32_t name;
|
|
ali@361
|
307 |
struct razor_lua_loader *ploader, *end;
|
|
ali@361
|
308 |
|
|
ali@361
|
309 |
if (!razor_preload.init) {
|
|
ali@361
|
310 |
razor_preload.init = 1;
|
|
ali@361
|
311 |
array_init(&razor_preload.name_pool);
|
|
ali@361
|
312 |
array_init(&razor_preload.loaders);
|
|
ali@361
|
313 |
hashtable_init(&razor_preload.modules,
|
|
ali@361
|
314 |
&razor_preload.name_pool);
|
|
ali@361
|
315 |
}
|
|
ali@361
|
316 |
|
|
ali@361
|
317 |
name = hashtable_tokenize(&razor_preload.modules, modname);
|
|
ali@361
|
318 |
|
|
ali@361
|
319 |
end = razor_preload.loaders.data + razor_preload.loaders.size;
|
|
ali@361
|
320 |
for(ploader = razor_preload.loaders.data; ploader < end; ploader++)
|
|
ali@361
|
321 |
if (ploader->name == name) {
|
|
ali@361
|
322 |
ploader->func = loader;
|
|
ali@361
|
323 |
return;
|
|
ali@361
|
324 |
}
|
|
ali@361
|
325 |
|
|
ali@361
|
326 |
ploader = array_add(&razor_preload.loaders, sizeof(*ploader));
|
|
ali@361
|
327 |
ploader->name = name;
|
|
ali@361
|
328 |
ploader->func = loader;
|
|
ali@361
|
329 |
}
|
|
ali@361
|
330 |
|
|
ali@368
|
331 |
RAZOR_EXPORT void (*razor_get_lua_loader(const char *modname))()
|
|
ali@368
|
332 |
{
|
|
ali@368
|
333 |
uint32_t name;
|
|
ali@368
|
334 |
struct razor_lua_loader *ploader, *end;
|
|
ali@368
|
335 |
|
|
ali@368
|
336 |
if (!razor_preload.init)
|
|
ali@368
|
337 |
return 0;
|
|
ali@368
|
338 |
|
|
ali@368
|
339 |
name = hashtable_lookup(&razor_preload.modules, modname);
|
|
ali@368
|
340 |
|
|
ali@368
|
341 |
end = razor_preload.loaders.data + razor_preload.loaders.size;
|
|
ali@368
|
342 |
for(ploader = razor_preload.loaders.data; ploader < end; ploader++)
|
|
ali@368
|
343 |
if (ploader->name == name)
|
|
ali@368
|
344 |
return ploader->func;
|
|
ali@368
|
345 |
|
|
ali@368
|
346 |
return 0;
|
|
ali@368
|
347 |
}
|
|
ali@368
|
348 |
|
|
ali@361
|
349 |
static void razor_lua_preload(lua_State *L)
|
|
ali@361
|
350 |
{
|
|
ali@361
|
351 |
struct razor_lua_loader *ploader, *end;
|
|
ali@361
|
352 |
|
|
ali@361
|
353 |
if (!razor_preload.init)
|
|
ali@361
|
354 |
return;
|
|
ali@361
|
355 |
|
|
ali@361
|
356 |
lua_getfield(L, LUA_GLOBALSINDEX, "package");
|
|
ali@361
|
357 |
lua_getfield(L, -1, "preload");
|
|
ali@361
|
358 |
lua_remove(L, -2);
|
|
ali@361
|
359 |
|
|
ali@361
|
360 |
end = razor_preload.loaders.data + razor_preload.loaders.size;
|
|
ali@361
|
361 |
for(ploader = razor_preload.loaders.data; ploader < end; ploader++) {
|
|
ali@361
|
362 |
lua_pushcfunction(L, ploader->func);
|
|
ali@361
|
363 |
lua_setfield(L, -2,
|
|
ali@361
|
364 |
razor_preload.name_pool.data + ploader->name);
|
|
ali@361
|
365 |
}
|
|
ali@361
|
366 |
|
|
ali@361
|
367 |
lua_pop(L, 1);
|
|
ali@361
|
368 |
}
|
|
ali@361
|
369 |
|
|
ali@352
|
370 |
int run_lua_script(const char *root, const char *name, const char *body,
|
|
ali@376
|
371 |
ssize_t len, int arg1)
|
|
ali@352
|
372 |
{
|
|
ali@352
|
373 |
int i, n;
|
|
ali@352
|
374 |
lua_State *L;
|
|
ali@352
|
375 |
struct razor_lua rl;
|
|
ali@352
|
376 |
|
|
ali@352
|
377 |
if (root && strcmp(root, "/"))
|
|
ali@352
|
378 |
rl.root = root;
|
|
ali@352
|
379 |
else
|
|
ali@352
|
380 |
rl.root = NULL;
|
|
ali@352
|
381 |
|
|
ali@352
|
382 |
L = lua_newstate(alloc_lua, &rl);
|
|
ali@352
|
383 |
luaL_openlibs(L);
|
|
ali@361
|
384 |
razor_lua_preload(L);
|
|
ali@352
|
385 |
lua_getglobal(L, "require");
|
|
ali@352
|
386 |
lua_pushstring(L, "posix");
|
|
ali@352
|
387 |
if (lua_pcall(L, 1, 1, 0)) {
|
|
ali@352
|
388 |
fprintf(stderr, "lua posix: %s\n", lua_tostring(L, -1));
|
|
ali@352
|
389 |
lua_pop(L, 1);
|
|
ali@352
|
390 |
lua_close(L);
|
|
ali@352
|
391 |
return -1;
|
|
ali@352
|
392 |
}
|
|
ali@352
|
393 |
|
|
ali@352
|
394 |
if (rl.root)
|
|
ali@352
|
395 |
for(i = 0; i < ARRAY_SIZE(proxy); i++) {
|
|
ali@352
|
396 |
if (proxy[i].table) {
|
|
ali@352
|
397 |
lua_getglobal(L, proxy[i].table);
|
|
ali@352
|
398 |
n = lua_gettop(L);
|
|
ali@352
|
399 |
} else
|
|
ali@352
|
400 |
n = LUA_GLOBALSINDEX;
|
|
ali@352
|
401 |
lua_getfield(L, n, proxy[i].name);
|
|
ali@352
|
402 |
rl.handler[i] = lua_tocfunction(L, -1);
|
|
ali@352
|
403 |
lua_getfenv(L, -1);
|
|
ali@352
|
404 |
lua_remove(L, -2);
|
|
ali@352
|
405 |
if (proxy[i].table &&
|
|
ali@352
|
406 |
!strcmp(proxy[i].table, "posix") &&
|
|
ali@352
|
407 |
!strcmp(proxy[i].name, "execp")) {
|
|
ali@352
|
408 |
execp_handler = rl.handler[i];
|
|
ali@352
|
409 |
rl.handler[i] = proxy_execp;
|
|
ali@352
|
410 |
}
|
|
ali@352
|
411 |
lua_pushinteger(L, i);
|
|
ali@352
|
412 |
lua_pushcclosure(L, proxy_handler, 1);
|
|
ali@352
|
413 |
lua_pushvalue(L, -2);
|
|
ali@352
|
414 |
lua_setfenv(L, -2);
|
|
ali@352
|
415 |
lua_setfield(L, n, proxy[i].name);
|
|
ali@352
|
416 |
if (proxy[i].table)
|
|
ali@352
|
417 |
lua_pop(L, 2);
|
|
ali@352
|
418 |
else
|
|
ali@352
|
419 |
lua_pop(L, 1);
|
|
ali@352
|
420 |
}
|
|
ali@352
|
421 |
|
|
ali@352
|
422 |
if (len < 0)
|
|
ali@352
|
423 |
len = strlen(body);
|
|
ali@352
|
424 |
|
|
ali@352
|
425 |
if (luaL_loadbuffer(L, body, len, name)) {
|
|
ali@352
|
426 |
fprintf(stderr, "failed to load lua script\n");
|
|
ali@352
|
427 |
lua_close(L);
|
|
ali@352
|
428 |
return -1;
|
|
ali@352
|
429 |
}
|
|
ali@352
|
430 |
|
|
ali@376
|
431 |
lua_newtable(L);
|
|
ali@376
|
432 |
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
|
ali@376
|
433 |
lua_pushliteral(L, "arg");
|
|
ali@376
|
434 |
lua_pushvalue(L, -3);
|
|
ali@376
|
435 |
lua_rawset(L, -3);
|
|
ali@376
|
436 |
lua_pop(L, 1);
|
|
ali@376
|
437 |
lua_pushliteral(L, "<lua>");
|
|
ali@376
|
438 |
lua_rawseti(L, -2, 1);
|
|
ali@376
|
439 |
if (arg1 >= 0) {
|
|
ali@376
|
440 |
lua_pushinteger(L, arg1);
|
|
ali@376
|
441 |
lua_rawseti(L, -2, 2);
|
|
ali@376
|
442 |
}
|
|
ali@376
|
443 |
lua_pop(L, 1);
|
|
ali@376
|
444 |
|
|
ali@352
|
445 |
if (lua_pcall(L, 0, 0, 0)) {
|
|
ali@352
|
446 |
fprintf(stderr, "lua script failed: %s\n", lua_tostring(L, -1));
|
|
ali@352
|
447 |
lua_pop(L, 1);
|
|
ali@352
|
448 |
lua_close(L);
|
|
ali@352
|
449 |
return -1;
|
|
ali@352
|
450 |
}
|
|
ali@352
|
451 |
|
|
ali@352
|
452 |
lua_close(L);
|
|
ali@352
|
453 |
return 0;
|
|
ali@352
|
454 |
}
|