Add -lole32 to link libraries.
This fixes a problem when compiling with mingw-headers version 3.3
where the use of SHGetFolderPath() expands to a call to CoTaskMemFree()
which is defined in libole32.dll:
/usr/x86_64-w64-mingw32/sys-root/mingw/include/shobjidl.h:29954: undefined reference to `__imp_CoTaskMemFree'
2 * Copyright (C) 2009 J. Ali Harlow <ali@juiblex.co.uk>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <sys/types.h>
32 #include "razor-internal.h"
36 #define ARG_FLAG_OPT 0x1
37 #define ARG_FLAG_BYPASS 0x2
39 #define ARG(flags, swtch, index, type) \
40 ((flags) << 26 | (swtch) << 21 | \
42 #define ARG_FLAGS(arg) ((unsigned)(arg) >> 26)
43 #define ARG_SWTCH(arg) ((unsigned)(arg) >> 21 & 0x1F)
44 #define ARG_INDEX(arg) ((unsigned)(arg) >> 16 & 0x1F)
45 #define ARG_TYPE(arg) ((unsigned)(arg) & 0xFFFF)
48 #define ARG_STRING(n) ARG(0, 0, n, LUA_TSTRING)
49 #define ARG_OPT_STRING(n) ARG(ARG_FLAG_OPT, 0, n, LUA_TSTRING)
50 #define ARG_BYP_STRING(n, s) ARG(ARG_FLAG_BYPASS, s, n, LUA_TSTRING)
55 unsigned args[MAX_ARGS];
58 static struct razor_proxy proxy[] = {
59 { NULL, "dofile", LUA_TNONE, { ARG_STRING(1) } },
60 { NULL, "loadfile", LUA_TNONE, { ARG_OPT_STRING(1) } },
61 { "io", "input", LUA_TNONE, { ARG_OPT_STRING(1) } },
62 { "io", "output", LUA_TNONE, { ARG_OPT_STRING(1) } },
63 { "io", "lines", LUA_TNONE, { ARG_OPT_STRING(1) } },
64 { "io", "open", LUA_TNONE, { ARG_STRING(1) } },
65 { "io", "popen", LUA_TNONE, { ARG_STRING(1) } },
67 * Note: We do not proxy os.execute
68 * We can't do it properly (there is no way to distinguish filenames
69 * in arguments from any other strings) so it's better not to try.
70 * Scripts that attempt to be portable should use posix.exec[p]
72 { "os", "remove", LUA_TNONE, { ARG_STRING(1) } },
73 { "os", "rename", LUA_TNONE, { ARG_STRING(1), ARG_STRING(2) } },
75 * Note: We do not proxy os.tmpname
76 * It should never be used. scripts should use io.tmpfile instead
77 * if the rather limited functionality it provides suffices. The
78 * proper solution is to implement posix.mkstemp
80 { "posix", "access", LUA_TNONE, { ARG_STRING(1) } },
81 { "posix", "chdir", LUA_TNONE, { ARG_STRING(1) } },
82 { "posix", "chmod", LUA_TNONE, { ARG_STRING(1) } },
83 { "posix", "chown", LUA_TNONE, { ARG_STRING(1) } },
84 { "posix", "dir", LUA_TNONE, { ARG_OPT_STRING(1) } },
85 { "posix", "exec", LUA_TNONE, { ARG_STRING(1) } },
86 { "posix", "execp", LUA_TNONE, { ARG_STRING(1) } },
87 { "posix", "files", LUA_TNONE, { ARG_OPT_STRING(1) } },
88 { "posix", "getcwd", LUA_TSTRING, { ARG_NONE } },
89 { "posix", "glob", LUA_TTABLE, { ARG_STRING(1) } },
90 { "posix", "link", LUA_TNONE, { ARG_BYP_STRING(1, 3), ARG_STRING(2) } },
91 { "posix", "mkdir", LUA_TNONE, { ARG_STRING(1) } },
92 { "posix", "mkfifo", LUA_TNONE, { ARG_STRING(1) } },
93 { "posix", "pathconf", LUA_TNONE, { ARG_STRING(1) } },
94 { "posix", "readlink", LUA_TNONE, { ARG_STRING(1) } },
95 { "posix", "rmdir", LUA_TNONE, { ARG_STRING(1) } },
96 { "posix", "stat", LUA_TNONE, { ARG_STRING(1) } },
97 { "posix", "unlink", LUA_TNONE, { ARG_STRING(1) } },
98 { "posix", "utime", LUA_TNONE, { ARG_STRING(1) } },
101 static lua_CFunction execp_handler;
105 lua_CFunction handler[ARRAY_SIZE(proxy)];
108 static void *alloc_lua(void *user_data, void *ptr, size_t osize, size_t nsize)
114 return realloc(ptr, nsize);
117 static int proxy_execp(lua_State *L)
119 int r, n, err, got_eacces = 0;
120 char *file = strdup(luaL_checkstring(L, 1));
122 const char *s, *e, *path;
123 struct razor_lua *rl;
125 if (*file == '\0' || strchr(file, '/')) {
126 r = execp_handler(L);
131 (void)lua_getallocf(L, (void **)&rl);
133 path = getenv("PATH");
135 path = ":/bin:/usr/bin";
143 n = strlen(rl->root);
144 exe = malloc(n + (e - s) + 1 + strlen(file) + 1);
145 memcpy(exe, rl->root, n);
146 memcpy(exe + n, s, e - s);
149 strcpy(exe + n, file);
151 exe = malloc((e - s) + 1 + strlen(file) + 1);
152 memcpy(exe, s, e - s);
155 strcpy(exe + n, file);
157 /* Ensure exe contains a slash to avoid PATH search */
158 exe = malloc(2 + strlen(file) + 1);
161 strcpy(exe + 2, file);
163 lua_pushstring(L, exe);
167 r = execp_handler(L);
169 err = lua_tointeger(L, -1);
183 lua_pop(L, lua_gettop(L) - n);
200 lua_pushfstring(L, "%s: %s", file, strerror(err));
201 lua_pushinteger(L, err);
207 static int real2fake(lua_State *L, struct razor_lua *rl, int indx)
212 indx += lua_gettop(L) + 1;
214 if (lua_type(L, indx) == LUA_TSTRING) {
215 path = lua_tostring(L, indx);
216 if (path && !strncmp(path, rl->root, strlen(rl->root)) &&
217 (path[strlen(rl->root)] == '/' || !path[strlen(rl->root)])) {
218 lua_pushstring(L, path + strlen(rl->root));
219 lua_replace(L, indx);
227 static int proxy_handler(lua_State *L)
232 struct razor_lua *rl;
233 int method = lua_tointeger(L, lua_upvalueindex(1));
234 struct razor_proxy *rp = proxy + method;
236 (void)lua_getallocf(L, (void **)&rl);
238 for(i = 0; i < MAX_ARGS; i++) {
242 switch (ARG_TYPE(arg)) {
244 if (ARG_FLAGS(arg) & ARG_FLAG_BYPASS)
245 cond = !lua_toboolean(L, ARG_SWTCH(arg));
248 if (ARG_FLAGS(arg) & ARG_FLAG_OPT) {
249 if (lua_isstring(L, ARG_INDEX(arg)))
250 path = lua_tostring(L, ARG_INDEX(arg));
254 path = luaL_checkstring(L, ARG_INDEX(arg));
255 if (cond && path && *path == '/') {
256 lua_pushfstring(L, "%s%s", rl->root, path);
257 lua_replace(L, ARG_INDEX(arg));
261 lua_pushfstring(L, "razor proxy: Unhandled type (%d)",
267 retval = rl->handler[method](L);
269 if (rp->result != LUA_TNONE && !lua_isnil(L, 1)) {
270 switch (rp->result) {
274 real2fake(L, rl, -1);
278 while (lua_next(L, -2)) {
279 if (real2fake(L, rl, -1)) {
280 i = lua_tonumber(L, -2);
281 lua_rawseti(L, -3, i);
287 lua_pushfstring(L, "razor proxy: Unhandled type (%d)",
296 struct razor_lua_loader {
301 static struct razor_preload {
303 struct hashtable modules;
304 struct array name_pool;
305 struct array loaders;
306 } razor_preload = {0};
308 RAZOR_EXPORT void razor_set_lua_loader(const char *modname, void (*loader)())
311 struct razor_lua_loader *ploader, *end;
313 if (!razor_preload.init) {
314 razor_preload.init = 1;
315 array_init(&razor_preload.name_pool);
316 array_init(&razor_preload.loaders);
317 hashtable_init(&razor_preload.modules,
318 &razor_preload.name_pool);
321 name = hashtable_tokenize(&razor_preload.modules, modname);
323 end = razor_preload.loaders.data + razor_preload.loaders.size;
324 for(ploader = razor_preload.loaders.data; ploader < end; ploader++)
325 if (ploader->name == name) {
326 ploader->func = (lua_CFunction)loader;
330 ploader = array_add(&razor_preload.loaders, sizeof(*ploader));
331 ploader->name = name;
332 ploader->func = (lua_CFunction)loader;
335 RAZOR_EXPORT void (*razor_get_lua_loader(const char *modname))()
338 struct razor_lua_loader *ploader, *end;
340 if (!razor_preload.init)
343 name = hashtable_lookup(&razor_preload.modules, modname);
345 end = razor_preload.loaders.data + razor_preload.loaders.size;
346 for(ploader = razor_preload.loaders.data; ploader < end; ploader++)
347 if (ploader->name == name)
348 return (void (*)())ploader->func;
353 static void razor_lua_preload(lua_State *L)
355 struct razor_lua_loader *ploader, *end;
357 if (!razor_preload.init)
360 lua_getfield(L, LUA_GLOBALSINDEX, "package");
361 lua_getfield(L, -1, "preload");
364 end = razor_preload.loaders.data + razor_preload.loaders.size;
365 for(ploader = razor_preload.loaders.data; ploader < end; ploader++) {
366 lua_pushcfunction(L, ploader->func);
368 razor_preload.name_pool.data + ploader->name);
374 int run_lua_script(const char *root, const char *name, const char *body,
375 ssize_t len, int arg1)
381 if (root && strcmp(root, "/"))
386 L = lua_newstate(alloc_lua, &rl);
388 razor_lua_preload(L);
389 lua_getglobal(L, "require");
390 lua_pushstring(L, "posix");
391 if (lua_pcall(L, 1, 1, 0)) {
392 fprintf(stderr, "lua posix: %s\n", lua_tostring(L, -1));
399 for(i = 0; i < ARRAY_SIZE(proxy); i++) {
400 if (proxy[i].table) {
401 lua_getglobal(L, proxy[i].table);
404 n = LUA_GLOBALSINDEX;
405 lua_getfield(L, n, proxy[i].name);
406 rl.handler[i] = lua_tocfunction(L, -1);
409 if (proxy[i].table &&
410 !strcmp(proxy[i].table, "posix") &&
411 !strcmp(proxy[i].name, "execp")) {
412 execp_handler = rl.handler[i];
413 rl.handler[i] = proxy_execp;
415 lua_pushinteger(L, i);
416 lua_pushcclosure(L, proxy_handler, 1);
417 lua_pushvalue(L, -2);
419 lua_setfield(L, n, proxy[i].name);
429 if (luaL_loadbuffer(L, body, len, name)) {
430 fprintf(stderr, "failed to load lua script\n");
436 lua_pushvalue(L, LUA_GLOBALSINDEX);
437 lua_pushliteral(L, "arg");
438 lua_pushvalue(L, -3);
441 lua_pushliteral(L, "<lua>");
442 lua_rawseti(L, -2, 1);
444 lua_pushinteger(L, arg1);
445 lua_rawseti(L, -2, 2);
449 if (lua_pcall(L, 0, 0, 0)) {
450 fprintf(stderr, "lua script failed: %s\n", lua_tostring(L, -1));