diff options
author | niemeyer <devnull@localhost> | 2004-03-19 20:08:20 +0000 |
---|---|---|
committer | niemeyer <devnull@localhost> | 2004-03-19 20:08:20 +0000 |
commit | 635edd95230e17e8ada5793719d7e385e729df30 (patch) | |
tree | 09290ba08b74c4ad43a9d67b6f0f8eaa18413006 | |
parent | a1a283837a6b70c9ee4731f9172cfc614a1a7c6b (diff) | |
download | librpm-tizen-635edd95230e17e8ada5793719d7e385e729df30.tar.gz librpm-tizen-635edd95230e17e8ada5793719d7e385e729df30.tar.bz2 librpm-tizen-635edd95230e17e8ada5793719d7e385e729df30.zip |
- New internal Lua support scheme, laying under rpmio.
- New API abstracting access to Lua state (rpmlua is
abstract to everyone but rpmlua.c).
- New %{lua: ... } macro.
Modified Files:
lib/Makefile.am lib/psm.c lib/rpmts.c lua/local/linit.lch
lua/local/linit.lua rpmio/Makefile.am rpmio/macro.c
Added Files:
rpmio/rpmlua.c rpmio/rpmlua.h
Removed Files:
lib/rpmlua.c lib/rpmlua.h
CVS patchset: 7178
CVS date: 2004/03/19 20:08:20
-rw-r--r-- | lib/Makefile.am | 7 | ||||
-rw-r--r-- | lib/psm.c | 77 | ||||
-rw-r--r-- | lib/rpmlua.c | 253 | ||||
-rw-r--r-- | lib/rpmlua.h | 31 | ||||
-rw-r--r-- | lib/rpmts.c | 2 | ||||
-rw-r--r-- | lua/local/linit.lch | 67 | ||||
-rw-r--r-- | lua/local/linit.lua | 10 | ||||
-rw-r--r-- | rpmio/Makefile.am | 8 | ||||
-rw-r--r-- | rpmio/macro.c | 27 | ||||
-rw-r--r-- | rpmio/rpmlua.c | 588 | ||||
-rw-r--r-- | rpmio/rpmlua.h | 84 |
11 files changed, 823 insertions, 331 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 37c503a4a..317659eba 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -11,8 +11,6 @@ INCLUDES = -I. \ -I$(top_srcdir)/rpmio \ @WITH_BEECRYPT_INCLUDE@ \ -I$(top_srcdir)/popt \ - -I$(top_builddir)/lua/include \ - -I$(top_builddir)/lua/local \ @INCPATH@ EXTRA_DIST = getdate.y @@ -22,7 +20,7 @@ pkginc_HEADERS = \ misc.h rpmcli.h rpmlib.h \ rpmal.h rpmds.h rpmfi.h rpmps.h rpmsx.h rpmte.h rpmts.h stringbuf.h noinst_HEADERS = \ - cpio.h fsm.h manifest.h psm.h rpmlead.h signature.h rpmlock.h rpmlua.h + cpio.h fsm.h manifest.h psm.h rpmlead.h signature.h rpmlock.h mylibs = librpm.la LIBS = @@ -38,12 +36,11 @@ librpm_la_SOURCES = \ rpmal.c rpmchecksig.c rpmds.c rpmfi.c rpminstall.c \ rpmlead.c rpmlibprov.c rpmps.c rpmrc.c rpmsx.c rpmte.c rpmts.c \ rpmvercmp.c signature.c stringbuf.c transaction.c \ - verify.c rpmlock.c rpmlua.c + verify.c rpmlock.c librpm_la_LDFLAGS = -release 4.3 $(LDFLAGS) \ $(top_builddir)/rpmdb/librpmdb.la \ $(top_builddir)/rpmio/librpmio.la \ $(top_builddir)/popt/libpopt.la \ - $(top_builddir)/lua/liblua.la \ @WITH_SELINUX_LIB@ getdate.c: getdate.y @@ -9,6 +9,7 @@ #include <rpmlib.h> #include <rpmmacro.h> #include <rpmurl.h> +#include <rpmlua.h> #include "cpio.h" #include "fsm.h" /* XXX CPIO_FOO/FSM_FOO constants */ @@ -560,6 +561,78 @@ exit: } /** + * Run internal Lua script. + */ +rpmRC runLuaScript(rpmlua lua, Header h, const char *sln, + int progArgc, const char **progArgv, + const char *script, int arg1, int arg2) +{ + int rootFd = -1; + const char *n, *v, *r; + rpmRC rc = RPMRC_OK; + int i; + int xx; + rpmts ts; + rpmluav var; + + xx = headerNVR(h, &n, &v, &r); + + ts = rpmluaGetData(lua, "ts"); + if (ts && !rpmtsChrootDone(ts)) { + const char *rootDir = rpmtsRootDir(ts); + if (rootDir != NULL && !(rootDir[0] == '/' && rootDir[1] == '\0')) { + chdir("/"); + rootFd = open(".", O_RDONLY, 0); + if (rootFd >= 0) { + chroot(rootDir); + rpmtsSetChrootDone(ts, 1); + } + } + } + + /* Create arg variable */ + rpmluaPushTable(lua, "arg"); + var = rpmluavNew(); + rpmluavSetListMode(var, 1); + if (progArgv) { + for (i = 0; i < progArgc && progArgv[i]; i++) { + rpmluavSetValue(var, RPMLUAV_STRING, progArgv[i]); + rpmluaSetVar(lua, var); + } + } + if (arg1 >= 0) { + rpmluavSetValueNum(var, arg1); + rpmluaSetVar(lua, var); + } + if (arg2 >= 0) { + rpmluavSetValueNum(var, arg2); + rpmluaSetVar(lua, var); + } + var = rpmluavFree(var); + rpmluaPop(lua); + + { + char buf[BUFSIZ]; + snprintf(buf, BUFSIZ, "%s(%s-%s-%s)", sln, n, v, r); + if (rpmluaRunScript(lua, script, buf) == -1) + rc = RPMRC_FAIL; + } + + rpmluaDelVar(lua, "arg"); + + if (rootFd >= 0) { + fchdir(rootFd); + close(rootFd); + chroot("."); + rpmtsSetChrootDone(ts, 0); + } + +exit: + return rc; +} + + +/** */ /*@unchecked@*/ static int ldconfig_done = 0; @@ -619,8 +692,8 @@ static rpmRC runScript(rpmpsm psm, Header h, const char * sln, return rc; if (progArgv && strcmp(progArgv[0], "<lua>") == 0) { - return rpmluaRunScript(ts->lua, h, sln, progArgc, progArgv, - script, arg1, arg2); + return runLuaScript(ts->lua, h, sln, progArgc, progArgv, + script, arg1, arg2); } psm->sq.reaper = 1; diff --git a/lib/rpmlua.c b/lib/rpmlua.c deleted file mode 100644 index 48f8ca6eb..000000000 --- a/lib/rpmlua.c +++ /dev/null @@ -1,253 +0,0 @@ -#include "system.h" -#include "rpmlib.h" -#include <rpmmacro.h> -#include <rpmurl.h> - -#include <lua.h> -#include <lualib.h> -#include <lauxlib.h> -#include <lposix.h> -#include <lrexlib.h> - -#include <unistd.h> - -#define _RPMLUA_INTERNAL -#include "rpmlua.h" - -static int luaopen_rpm(lua_State *L); - -rpmlua rpmluaNew() -{ - rpmlua lua = (rpmlua) xcalloc(1, sizeof(struct rpmlua_s)); - lua_State *L = lua_open(); - const luaL_reg lualibs[] = { - {"base", luaopen_base}, - {"table", luaopen_table}, - {"io", luaopen_io}, - {"string", luaopen_string}, - {"debug", luaopen_debug}, - {"loadlib", luaopen_loadlib}, - {"posix", luaopen_posix}, - {"rex", luaopen_rex}, - {"rpm", luaopen_rpm}, - {NULL, NULL}, - }; - const luaL_reg *lib = lualibs; - for (; lib->name; lib++) { - lib->func(L); - lua_settop(L, 0); - } - lua_pushliteral(L, "LUA_PATH"); - lua_pushstring(L, RPMCONFIGDIR "/lua/?.lua"); - lua_rawset(L, LUA_GLOBALSINDEX); - lua->L = L; - return lua; -} - -void *rpmluaFree(rpmlua lua) -{ - if (lua) { - if (lua->L) lua_close(lua->L); - free(lua); - } - return NULL; -} - -void rpmluaSetTS(rpmlua lua, rpmts ts) -{ - lua->ts = ts; -} - -rpmRC rpmluaCheckScript(rpmlua lua, const char *script, const char *name) -{ - lua_State *L = lua->L; - rpmRC rc = RPMRC_OK; - if (!name) - name = "<lua>"; - if (luaL_loadbuffer(L, script, strlen(script), name) != 0) { - rpmError(RPMERR_SCRIPT, - _("invalid syntax in lua scriptlet: %s\n"), - lua_tostring(L, -1)); - rc = RPMRC_FAIL; - } - lua_pop(L, 1); /* Error or chunk. */ - return rc; -} - -rpmRC rpmluaRunScript(rpmlua lua, Header h, const char *sln, - int progArgc, const char **progArgv, - const char *script, int arg1, int arg2) -{ - lua_State *L = lua->L; - int rootFd = -1; - const char *n, *v, *r; - rpmRC rc = RPMRC_OK; - int i; - int xx; - if (!L) { - rpmError(RPMERR_SCRIPT, - _("internal lua interpreter not available\n")); - rc = RPMRC_FAIL; - goto exit; - } - xx = headerNVR(h, &n, &v, &r); - if (luaL_loadbuffer(L, script, strlen(script), "<lua>") != 0) { - rpmError(RPMERR_SCRIPT, - _("%s(%s-%s-%s) lua scriptlet failed loading: %s\n"), - sln, n, v, r, lua_tostring(L, -1)); - lua_pop(L, 1); - rc = RPMRC_FAIL; - goto exit; - } - - if (lua->ts && !rpmtsChrootDone(lua->ts)) { - const char *rootDir = rpmtsRootDir(lua->ts); - if (rootDir != NULL && !(rootDir[0] == '/' && rootDir[1] == '\0')) { - chdir("/"); - rootFd = open(".", O_RDONLY, 0); - if (rootFd >= 0) { - chroot(rootDir); - rpmtsSetChrootDone(lua->ts, 1); - } - } - } - - /* Create arg variable */ - lua_pushliteral(L, "arg"); - lua_newtable(L); - i = 0; - if (progArgv) { - while (i < progArgc && progArgv[i]) { - lua_pushstring(L, progArgv[i]); - lua_rawseti(L, -2, ++i); - } - } - if (arg1 >= 0) { - lua_pushnumber(L, arg1); - lua_rawseti(L, -2, ++i); - } - if (arg2 >= 0) { - lua_pushnumber(L, arg2); - lua_rawseti(L, -2, ++i); - } - lua_rawset(L, LUA_GLOBALSINDEX); - - if (lua_pcall(L, 0, 0, 0) != 0) { - rpmError(RPMERR_SCRIPT, _("%s(%s-%s-%s) lua scriptlet failed: %s\n"), - sln, n, v, r, lua_tostring(L, -1)); - lua_pop(L, 1); - rc = RPMRC_FAIL; - } - - /* Remove 'arg' global. */ - lua_pushliteral(L, "arg"); - lua_pushnil(L); - lua_rawset(L, LUA_GLOBALSINDEX); - - if (rootFd >= 0) { - fchdir(rootFd); - close(rootFd); - chroot("."); - rpmtsSetChrootDone(lua->ts, 0); - } - -exit: - return rc; -} - -/* From lua.c */ -static int rpmluaReadline(lua_State *l, const char *prompt) { - static char buffer[1024]; - if (prompt) { - fputs(prompt, stdout); - fflush(stdout); - } - if (fgets(buffer, sizeof(buffer), stdin) == NULL) { - return 0; /* read fails */ - } else { - lua_pushstring(l, buffer); - return 1; - } -} - -/* Based on lua.c */ -static void _rpmluaInteractive(lua_State *L) -{ - fputs("\n", stdout); - printf("RPM Interactive %s Interpreter\n", LUA_VERSION); - for (;;) { - if (rpmluaReadline(L, "> ") == 0) - break; - if (lua_tostring(L, -1)[0] == '=') { - lua_pushfstring(L, "print(%s)", lua_tostring(L, -1)+1); - lua_remove(L, -2); - } - int rc = 0; - for (;;) { - rc = luaL_loadbuffer(L, lua_tostring(L, -1), - lua_strlen(L, -1), "<lua>"); - if (rc == LUA_ERRSYNTAX && - strstr(lua_tostring(L, -1), "near `<eof>'") != NULL) { - if (rpmluaReadline(L, ">> ") == 0) - break; - lua_remove(L, -2); // Remove error - lua_concat(L, 2); - continue; - } - break; - } - if (rc == 0) - rc = lua_pcall(L, 0, 0, 0); - if (rc != 0) { - fprintf(stderr, "%s\n", lua_tostring(L, -1)); - lua_pop(L, 1); - } - lua_pop(L, 1); // Remove line - } - fputs("\n", stdout); -} - -void rpmluaInteractive(rpmlua lua) -{ - _rpmluaInteractive(lua->L); -} - -/* ------------------------------------------------------------------ */ -/* Lua API */ - -static int rpm_expand(lua_State *L) -{ - const char *str = luaL_checkstring(L, 1); - lua_pushstring(L, rpmExpand(str, NULL)); - return 1; -} - -static int rpm_define(lua_State *L) -{ - const char *str = luaL_checkstring(L, 1); - rpmDefineMacro(NULL, str, 0); - return 0; -} - -static int rpm_interactive(lua_State *L) -{ - _rpmluaInteractive(L); - return 0; -} - -static const luaL_reg rpmlib[] = { - {"expand", rpm_expand}, - {"define", rpm_define}, - {"interactive", rpm_interactive}, - {NULL, NULL} -}; - -static int luaopen_rpm(lua_State *L) -{ - lua_pushvalue(L, LUA_GLOBALSINDEX); - luaL_openlib(L, "rpm", rpmlib, 0); - return 0; -} - -/* vim:sts=4:sw=4 -*/ diff --git a/lib/rpmlua.h b/lib/rpmlua.h deleted file mode 100644 index 724ce039a..000000000 --- a/lib/rpmlua.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef RPMLUA_H -#define RPMLUA_H - -#if defined(_RPMLUA_INTERNAL) - -#include "rpmts.h" - -#include <lua.h> - -struct rpmlua_s { - lua_State *L; - rpmts ts; -}; - -#endif /* _RPMLUA_INTERNAL */ - -typedef struct rpmlua_s * rpmlua; - -rpmlua rpmluaNew(void); -void *rpmluaFree(rpmlua lua); -void rpmluaSetTS(rpmlua lua, rpmts ts); -rpmRC rpmluaCheckScript(rpmlua lua, const char *script, const char *name); -rpmRC rpmluaRunScript(rpmlua lua, Header h, const char *sln, - int progArgc, const char **progArgv, - const char *script, int arg1, int arg2); -void rpmluaInteractive(rpmlua lua); - -#endif /* RPMLUA_H */ - -/* vim:sts=4:sw=4 -*/ diff --git a/lib/rpmts.c b/lib/rpmts.c index 1a6e3fbd0..2d0819818 100644 --- a/lib/rpmts.c +++ b/lib/rpmts.c @@ -1512,7 +1512,7 @@ rpmts rpmtsCreate(void) ts->score = NULL; ts->lua = rpmluaNew(); - rpmluaSetTS(ts->lua, ts); + rpmluaSetData(ts->lua, "ts", ts); ts->nrefs = 0; diff --git a/lua/local/linit.lch b/lua/local/linit.lch index 862d04efd..56ced87cf 100644 --- a/lua/local/linit.lch +++ b/lua/local/linit.lch @@ -6,39 +6,40 @@ /* local/linit.lua */ static const unsigned char B1[]={ 10,114,101,120, 46,110,101,119, 32, 61, 32,114,101,120, 46,110,101,119, 80, 79, - 83, 73, 88, 10, 10,102,117,110, 99,116,105,111,110, 32,114,101,120, 46,103,114, -101,112, 40,102,105,108,101,110, 97,109,101, 44, 32,101,120,112,114, 41, 10, 9, -105,102, 32,110,111,116, 32,112,111,115,105,120, 46,115,116, 97,116, 40,102,105, -108,101,110, 97,109,101, 44, 32, 34,109,111,100,101, 34, 41, 32,116,104,101,110, - 10, 9, 9,114,101,116,117,114,110, 32,110,105,108, 10, 9,101,110,100, 10, 9, -108,111, 99, 97,108, 32,108,105,110,101,115, 32, 61, 32,123,125, 10, 9,108,111, - 99, 97,108, 32,112, 97,116, 32, 61, 32,114,101,120, 46,110,101,119, 40,101,120, -112,114, 41, 10, 9,108,111, 99, 97,108, 32,112,111,115, 32, 61, 32, 49, 10, 9, -102,111,114, 32,108,105,110,101, 32,105,110, 32,105,111, 46,108,105,110,101,115, - 40,102,105,108,101,110, 97,109,101, 41, 32,100,111, 10, 9, 9,105,102, 32,112, - 97,116, 58,109, 97,116, 99,104, 40,108,105,110,101, 41, 32,116,104,101,110, 10, - 9, 9, 9,116, 97, 98,108,101, 46,105,110,115,101,114,116, 40,108,105,110,101, -115, 44, 32,112,111,115, 44, 32,108,105,110,101, 41, 10, 9, 9,101,110,100, 10, - 9, 9,112,111,115, 32, 61, 32,112,111,115, 32, 43, 32, 49, 10, 9,101,110,100, - 10, 9,105,102, 32,116, 97, 98,108,101, 46,103,101,116,110, 40,108,105,110,101, -115, 41, 32, 61, 61, 32, 48, 32,116,104,101,110, 10, 9, 9,114,101,116,117,114, -110, 32,110,105,108, 10, 9,101,110,100, 10, 9,114,101,116,117,114,110, 32,108, -105,110,101,115, 10,101,110,100, 10, 10,102,117,110, 99,116,105,111,110, 32,114, -101,120, 46,105,103,114,101,112, 40,102,105,108,101,110, 97,109,101, 44, 32,101, -120,112,114, 41, 10, 9,114,101,116,117,114,110, 32,105,112, 97,105,114,115, 40, -114,101,120, 46,103,114,101,112, 40,102,105,108,101,110, 97,109,101, 44, 32,101, -120,112,114, 41, 41, 10,101,110,100, 10, 10,102,117,110, 99,116,105,111,110, 32, -114,101,120, 46, 98,103,114,101,112, 40,102,105,108,101,110, 97,109,101, 44, 32, -101,120,112,114, 41, 10, 9,105,102, 32,110,111,116, 32,112,111,115,105,120, 46, -115,116, 97,116, 40,102,105,108,101,110, 97,109,101, 44, 32, 34,109,111,100,101, - 34, 41, 32,116,104,101,110, 10, 9, 9,114,101,116,117,114,110, 32,110,105,108, - 10, 9,101,110,100, 10, 9,108,111, 99, 97,108, 32,112, 97,116, 32, 61, 32,114, -101,120, 46,110,101,119, 40,101,120,112,114, 41, 10, 9,102,111,114, 32,108,105, -110,101, 32,105,110, 32,105,111, 46,108,105,110,101,115, 40,102,105,108,101,110, - 97,109,101, 41, 32,100,111, 10, 9, 9,105,102, 32,112, 97,116, 58,109, 97,116, - 99,104, 40,108,105,110,101, 41, 32,116,104,101,110, 10, 9, 9, 9,114,101,116, -117,114,110, 32,116,114,117,101, 10, 9, 9,101,110,100, 10, 9,101,110,100, 10, - 9,114,101,116,117,114,110, 32,102, 97,108,115,101, 10,101,110,100, 10, 10, + 83, 73, 88, 10, 10,117,116,105,108, 32, 61, 32,123,125, 10, 10,102,117,110, 99, +116,105,111,110, 32,117,116,105,108, 46,103,114,101,112, 40,101,120,112,114, 44, + 32,102,105,108,101,110, 97,109,101, 41, 10, 9,105,102, 32,110,111,116, 32,112, +111,115,105,120, 46,115,116, 97,116, 40,102,105,108,101,110, 97,109,101, 44, 32, + 34,109,111,100,101, 34, 41, 32,116,104,101,110, 10, 9, 9,114,101,116,117,114, +110, 32,110,105,108, 10, 9,101,110,100, 10, 9,108,111, 99, 97,108, 32,108,105, +110,101,115, 32, 61, 32,123,125, 10, 9,108,111, 99, 97,108, 32,112, 97,116, 32, + 61, 32,114,101,120, 46,110,101,119, 40,101,120,112,114, 41, 10, 9,108,111, 99, + 97,108, 32,112,111,115, 32, 61, 32, 49, 10, 9,102,111,114, 32,108,105,110,101, + 32,105,110, 32,105,111, 46,108,105,110,101,115, 40,102,105,108,101,110, 97,109, +101, 41, 32,100,111, 10, 9, 9,105,102, 32,112, 97,116, 58,109, 97,116, 99,104, + 40,108,105,110,101, 41, 32,116,104,101,110, 10, 9, 9, 9,116, 97, 98,108,101, + 46,105,110,115,101,114,116, 40,108,105,110,101,115, 44, 32,112,111,115, 44, 32, +108,105,110,101, 41, 10, 9, 9,101,110,100, 10, 9, 9,112,111,115, 32, 61, 32, +112,111,115, 32, 43, 32, 49, 10, 9,101,110,100, 10, 9,105,102, 32,116, 97, 98, +108,101, 46,103,101,116,110, 40,108,105,110,101,115, 41, 32, 61, 61, 32, 48, 32, +116,104,101,110, 10, 9, 9,114,101,116,117,114,110, 32,110,105,108, 10, 9,101, +110,100, 10, 9,114,101,116,117,114,110, 32,108,105,110,101,115, 10,101,110,100, + 10, 10,102,117,110, 99,116,105,111,110, 32,117,116,105,108, 46,105,103,114,101, +112, 40,101,120,112,114, 44, 32,102,105,108,101,110, 97,109,101, 41, 10, 9,114, +101,116,117,114,110, 32,105,112, 97,105,114,115, 40,114,101,120, 46,103,114,101, +112, 40,101,120,112,114, 44, 32,102,105,108,101,110, 97,109,101, 41, 41, 10,101, +110,100, 10, 10,102,117,110, 99,116,105,111,110, 32,117,116,105,108, 46, 98,103, +114,101,112, 40,101,120,112,114, 44, 32,102,105,108,101,110, 97,109,101, 41, 10, + 9,105,102, 32,110,111,116, 32,112,111,115,105,120, 46,115,116, 97,116, 40,102, +105,108,101,110, 97,109,101, 44, 32, 34,109,111,100,101, 34, 41, 32,116,104,101, +110, 10, 9, 9,114,101,116,117,114,110, 32,110,105,108, 10, 9,101,110,100, 10, + 9,108,111, 99, 97,108, 32,112, 97,116, 32, 61, 32,114,101,120, 46,110,101,119, + 40,101,120,112,114, 41, 10, 9,102,111,114, 32,108,105,110,101, 32,105,110, 32, +105,111, 46,108,105,110,101,115, 40,102,105,108,101,110, 97,109,101, 41, 32,100, +111, 10, 9, 9,105,102, 32,112, 97,116, 58,109, 97,116, 99,104, 40,108,105,110, +101, 41, 32,116,104,101,110, 10, 9, 9, 9,114,101,116,117,114,110, 32,116,114, +117,101, 10, 9, 9,101,110,100, 10, 9,101,110,100, 10, 9,114,101,116,117,114, +110, 32,102, 97,108,115,101, 10,101,110,100, 10, 10, }; lua_dobuffer(L,(const char*)B1,sizeof(B1),"local/linit.lua"); diff --git a/lua/local/linit.lua b/lua/local/linit.lua index a63316cd7..7b134ba75 100644 --- a/lua/local/linit.lua +++ b/lua/local/linit.lua @@ -1,7 +1,9 @@ rex.new = rex.newPOSIX -function rex.grep(filename, expr) +util = {} + +function util.grep(expr, filename) if not posix.stat(filename, "mode") then return nil end @@ -20,11 +22,11 @@ function rex.grep(filename, expr) return lines end -function rex.igrep(filename, expr) - return ipairs(rex.grep(filename, expr)) +function util.igrep(expr, filename) + return ipairs(rex.grep(expr, filename)) end -function rex.bgrep(filename, expr) +function util.bgrep(expr, filename) if not posix.stat(filename, "mode") then return nil end diff --git a/rpmio/Makefile.am b/rpmio/Makefile.am index b1ddd5bec..c3f72a3ee 100644 --- a/rpmio/Makefile.am +++ b/rpmio/Makefile.am @@ -12,13 +12,15 @@ INCLUDES = -I. \ -I$(top_srcdir) \ @WITH_BEECRYPT_INCLUDE@ \ -I$(top_srcdir)/popt \ + -I$(top_srcdir)/lua/include \ + -I$(top_srcdir)/lua/local \ @INCPATH@ pkgincdir = $(pkgincludedir) pkginc_HEADERS = \ argv.h fts.h \ rpmio.h rpmurl.h rpmmacro.h rpmlog.h rpmmessages.h rpmerr.h rpmpgp.h \ - rpmsq.h rpmsw.h ugid.h + rpmsq.h rpmsw.h ugid.h rpmlua.h noinst_HEADERS = rpmio_internal.h BEECRYPTLOBJS = $(shell test X"@WITH_BEECRYPT_SUBDIR@" != X && cat $(top_builddir)/@WITH_BEECTYPT_SUBDIR@/listobjs) @@ -30,10 +32,12 @@ usrlib_LTLIBRARIES = librpmio.la librpmio_la_SOURCES = \ argv.c digest.c fts.c macro.c \ rpmio.c rpmlog.c rpmmalloc.c \ - rpmpgp.c rpmrpc.c rpmsq.c rpmsw.c strcasecmp.c stubs.c url.c ugid.c + rpmpgp.c rpmrpc.c rpmsq.c rpmsw.c strcasecmp.c stubs.c url.c ugid.c \ + rpmlua.c librpmio_la_LDFLAGS = -release 4.3 $(LDFLAGS) \ @WITH_BEECRYPT_LIB@ \ $(top_builddir)/file/src/libfmagic.la \ + $(top_builddir)/lua/liblua.la \ @WITH_ZLIB_LIB@ \ -lrt -lpthread librpmio_la_LIBADD = # $(BEECRYPTLOBJS) diff --git a/rpmio/macro.c b/rpmio/macro.c index 1d11a46c6..d8e4859e9 100644 --- a/rpmio/macro.c +++ b/rpmio/macro.c @@ -43,6 +43,7 @@ typedef FILE * FD_t; #include <rpmio_internal.h> #include <rpmmessages.h> #include <rpmerr.h> +#include <rpmlua.h> #endif @@ -1363,6 +1364,32 @@ expandMacro(MacroBuf mb) continue; } + if (STREQ("lua", f, fn)) { + rpmlua lua = rpmluaNew(); + const char *ls = s+sizeof("{lua:")-1; + const char *lse = se-sizeof("}")+1; + char *scriptbuf = (char *)xmalloc((lse-ls)+1); + const char *printbuf; + memcpy(scriptbuf, ls, lse-ls); + scriptbuf[lse-ls] = '\0'; + rpmluaSetPrintBuffer(lua, 1); + if (rpmluaRunScript(lua, scriptbuf, NULL) == -1) + rc = 1; + printbuf = rpmluaGetPrintBuffer(lua); + if (printbuf) { + int len = strlen(printbuf); + if (len > mb->nb) + len = mb->nb; + memcpy(mb->t, printbuf, len); + mb->t += len; + mb->nb -= len; + } + free(scriptbuf); + lua = rpmluaFree(lua); + s = se; + continue; + } + /* XXX necessary but clunky */ if (STREQ("basename", f, fn) || STREQ("suffix", f, fn) || diff --git a/rpmio/rpmlua.c b/rpmio/rpmlua.c new file mode 100644 index 000000000..6b545b4a1 --- /dev/null +++ b/rpmio/rpmlua.c @@ -0,0 +1,588 @@ +#include "system.h" +#include <rpmio.h> +#include <rpmmacro.h> +#include <rpmerr.h> +#include <rpmurl.h> + +#include <lua.h> +#include <lualib.h> +#include <lauxlib.h> +#include <lposix.h> +#include <lrexlib.h> + +#include <unistd.h> +#include <assert.h> + +#define _RPMLUA_INTERNAL +#include "rpmlua.h" + +#if !defined(HAVE_VSNPRINTF) +static inline int vsnprintf(char * buf, /*@unused@*/ int nb, + const char * fmt, va_list ap) +{ + return vsprintf(buf, fmt, ap); +} +#endif + +static int luaopen_rpm(lua_State *L); +static int rpm_print(lua_State *L); + +rpmlua rpmluaNew() +{ + rpmlua lua = (rpmlua) xcalloc(1, sizeof(struct rpmlua_s)); + lua_State *L = lua_open(); + lua->L = L; + const luaL_reg lualibs[] = { + {"base", luaopen_base}, + {"table", luaopen_table}, + {"io", luaopen_io}, + {"string", luaopen_string}, + {"debug", luaopen_debug}, + {"loadlib", luaopen_loadlib}, + {"posix", luaopen_posix}, + {"rex", luaopen_rex}, + {"rpm", luaopen_rpm}, + {NULL, NULL}, + }; + const luaL_reg *lib = lualibs; + for (; lib->name; lib++) { + lib->func(L); + lua_settop(L, 0); + } + lua_pushliteral(L, "LUA_PATH"); + lua_pushstring(L, RPMCONFIGDIR "/lua/?.lua"); + lua_rawset(L, LUA_GLOBALSINDEX); + lua_pushliteral(L, "print"); + lua_pushcfunction(L, rpm_print); + lua_rawset(L, LUA_GLOBALSINDEX); + rpmluaSetData(lua, "lua", lua); + return lua; +} + +void *rpmluaFree(rpmlua lua) +{ + if (lua) { + if (lua->L) lua_close(lua->L); + free(lua->printbuf); + free(lua); + } + return NULL; +} + +void rpmluaSetData(rpmlua lua, const char *key, const void *data) +{ + lua_State *L = lua->L; + lua_pushliteral(L, "rpm_"); + lua_pushstring(L, key); + lua_concat(L, 2); + if (data == NULL) + lua_pushnil(L); + else + lua_pushlightuserdata(L, (void *)data); + lua_rawset(L, LUA_REGISTRYINDEX); +} + +static void *getdata(lua_State *L, const char *key) +{ + void *ret = NULL; + lua_pushliteral(L, "rpm_"); + lua_pushstring(L, key); + lua_concat(L, 2); + lua_rawget(L, LUA_REGISTRYINDEX); + if (lua_islightuserdata(L, -1)) + ret = lua_touserdata(L, -1); + lua_pop(L, 1); + return ret; +} + +void *rpmluaGetData(rpmlua lua, const char *key) +{ + return getdata(lua->L, key); +} + +void rpmluaSetPrintBuffer(rpmlua lua, int flag) +{ + lua->storeprint = flag; + free(lua->printbuf); + lua->printbuf = NULL; + lua->printbufsize = 0; +} + +const char *rpmluaGetPrintBuffer(rpmlua lua) +{ + return lua->printbuf; +} + +static int pushvar(lua_State *L, rpmluavType type, void *value) +{ + int ret = 0; + switch (type) { + case RPMLUAV_NIL: + lua_pushnil(L); + break; + case RPMLUAV_STRING: + lua_pushstring(L, *((char **)value)); + break; + case RPMLUAV_NUMBER: + lua_pushnumber(L, *((double *)value)); + break; + default: + ret = -1; + break; + } + return ret; +} + +void rpmluaSetVar(rpmlua lua, rpmluav var) +{ + lua_State *L = lua->L; + if (var->listmode && lua->pushsize > 0) { + if (var->keyType != RPMLUAV_NUMBER || var->key.num == 0) { + var->keyType = RPMLUAV_NUMBER; + var->key.num = luaL_getn(L, -1); + } + var->key.num++; + } + if (!var->listmode || lua->pushsize > 0) { + if (lua->pushsize == 0) + lua_pushvalue(L, LUA_GLOBALSINDEX); + if (pushvar(L, var->keyType, &var->key) != -1) { + if (pushvar(L, var->valueType, &var->value) != -1) + lua_rawset(L, -3); + else + lua_pop(L, 1); + } + if (lua->pushsize == 0) + lua_pop(L, 1); + } +} + +static void popvar(lua_State *L, rpmluavType *type, void *value) +{ + switch (lua_type(L, -1)) { + case LUA_TSTRING: + *type = RPMLUAV_STRING; + *((const char **)value) = lua_tostring(L, -1); + break; + case LUA_TNUMBER: + *type = RPMLUAV_NUMBER; + *((double *)value) = lua_tonumber(L, -1); + break; + default: + *type = RPMLUAV_NIL; + *((void **)value) = NULL; + break; + } + lua_pop(L, 1); +} + +void rpmluaGetVar(rpmlua lua, rpmluav var) +{ + lua_State *L = lua->L; + if (!var->listmode) { + if (lua->pushsize == 0) + lua_pushvalue(L, LUA_GLOBALSINDEX); + if (pushvar(L, var->keyType, &var->key) != -1) { + lua_rawget(L, -2); + popvar(L, &var->valueType, &var->value); + } + if (lua->pushsize == 0) + lua_pop(L, 1); + } else if (lua->pushsize > 0) { + pushvar(L, var->keyType, &var->key); + if (lua_next(L, -2) != 0) + popvar(L, &var->valueType, &var->value); + } +} + +#define FINDKEY_RETURN 0 +#define FINDKEY_CREATE 1 +#define FINDKEY_REMOVE 2 +static int findkey(lua_State *L, int oper, const char *key, va_list va) +{ + char buf[BUFSIZ]; + const char *s, *e; + int ret = 0; + vsnprintf(buf, BUFSIZ, key, va); + s = e = buf; + lua_pushvalue(L, LUA_GLOBALSINDEX); + for (;;) { + if (*e == '\0' || *e == '.') { + if (e != s) { + lua_pushlstring(L, s, e-s); + switch (oper) { + case FINDKEY_REMOVE: + if (*e == '\0') { + lua_pushnil(L); + lua_rawset(L, -3); + lua_pop(L, 1); + break; + } + /* @fallthrough@ */ + case FINDKEY_RETURN: + lua_rawget(L, -2); + lua_remove(L, -2); + break; + case FINDKEY_CREATE: + lua_rawget(L, -2); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + lua_newtable(L); + lua_pushlstring(L, s, e-s); + lua_pushvalue(L, -2); + lua_rawset(L, -4); + } + lua_remove(L, -2); + break; + } + } + if (*e == '\0') + break; + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + ret = -1; + break; + } + s = e+1; + } + e++; + } + + return ret; +} + +void rpmluaDelVar(rpmlua lua, const char *key, ...) +{ + va_list va; + va_start(va, key); + findkey(lua->L, FINDKEY_REMOVE, key, va); + va_end(va); +} + +int rpmluaVarExists(rpmlua lua, const char *key, ...) +{ + int ret = 0; + va_list va; + va_start(va, key); + if (findkey(lua->L, FINDKEY_RETURN, key, va) == 0) { + if (!lua_isnil(lua->L, -1)) + ret = 1; + lua_pop(lua->L, 1); + } + va_end(va); + return ret; +} + +void rpmluaPushTable(rpmlua lua, const char *key, ...) +{ + va_list va; + va_start(va, key); + findkey(lua->L, FINDKEY_CREATE, key, va); + lua->pushsize++; + va_end(va); +} + +void rpmluaPop(rpmlua lua) +{ + assert(lua->pushsize > 0); + lua->pushsize--; + lua_pop(lua->L, 1); +} + +rpmluav rpmluavNew(void) +{ + rpmluav var = (rpmluav) xcalloc(1, sizeof(struct rpmluav_s)); + return var; +} + +void *rpmluavFree(rpmluav var) +{ + free(var); + return NULL; +} + +void rpmluavSetListMode(rpmluav var, int flag) +{ + var->listmode = flag; + var->keyType = RPMLUAV_NIL; +} + +void rpmluavSetKey(rpmluav var, rpmluavType type, const void *value) +{ + var->keyType = type; + switch (type) { + case RPMLUAV_NUMBER: + var->key.num = *((double *)value); + break; + case RPMLUAV_STRING: + var->key.str = (char *)value; + break; + default: + break; + } +} + +void rpmluavSetValue(rpmluav var, rpmluavType type, const void *value) +{ + var->valueType = type; + switch (type) { + case RPMLUAV_NUMBER: + var->value.num = *((const double *)value); + break; + case RPMLUAV_STRING: + var->value.str = (const char *)value; + break; + default: + break; + } +} + +void rpmluavGetKey(rpmluav var, rpmluavType *type, void **value) +{ + *type = var->keyType; + switch (var->keyType) { + case RPMLUAV_NUMBER: + *((double **)value) = &var->key.num; + break; + case RPMLUAV_STRING: + *((const char **)value) = var->key.str; + break; + default: + break; + } +} + +void rpmluavGetValue(rpmluav var, rpmluavType *type, void **value) +{ + *type = var->valueType; + switch (var->valueType) { + case RPMLUAV_NUMBER: + *((double **)value) = &var->value.num; + break; + case RPMLUAV_STRING: + *((const char **)value) = var->value.str; + break; + default: + break; + } +} + +void rpmluavSetKeyNum(rpmluav var, double value) +{ + rpmluavSetKey(var, RPMLUAV_NUMBER, &value); +} + +void rpmluavSetValueNum(rpmluav var, double value) +{ + rpmluavSetValue(var, RPMLUAV_NUMBER, &value); +} + +double rpmluavGetKeyNum(rpmluav var) +{ + rpmluavType type; + void *value; + rpmluavGetKey(var, &type, &value); + if (type == RPMLUAV_NUMBER) + return *((double *)value); + return 0; +} + +double rpmluavGetValueNum(rpmluav var) +{ + rpmluavType type; + void *value; + rpmluavGetValue(var, &type, &value); + if (type == RPMLUAV_NUMBER) + return *((double *)value); + return 0; +} + +int rpmluavKeyIsNum(rpmluav var) +{ + return (var->keyType == RPMLUAV_NUMBER) ? 1 : 0; +} + +int rpmluavValueIsNum(rpmluav var) +{ + return (var->valueType == RPMLUAV_NUMBER) ? 1 : 0; +} + +int rpmluaCheckScript(rpmlua lua, const char *script, const char *name) +{ + lua_State *L = lua->L; + int ret = 0; + if (!name) + name = "<lua>"; + if (luaL_loadbuffer(L, script, strlen(script), name) != 0) { + rpmError(RPMERR_SCRIPT, + _("invalid syntax in lua scriptlet: %s\n"), + lua_tostring(L, -1)); + ret = -1; + } + lua_pop(L, 1); /* Error or chunk. */ + return ret; +} + +int rpmluaRunScript(rpmlua lua, const char *script, const char *name) +{ + lua_State *L = lua->L; + int ret = 0; + if (!name) + name = "<lua>"; + if (luaL_loadbuffer(L, script, strlen(script), name) != 0) { + rpmError(RPMERR_SCRIPT, _("invalid syntax in lua script: %s\n"), + lua_tostring(L, -1)); + lua_pop(L, 1); + ret = -1; + } else if (lua_pcall(L, 0, 0, 0) != 0) { + rpmError(RPMERR_SCRIPT, _("lua script failed: %s\n"), + lua_tostring(L, -1)); + lua_pop(L, 1); + ret = -1; + } + return ret; +} + +/* From lua.c */ +static int rpmluaReadline(lua_State *l, const char *prompt) { + static char buffer[1024]; + if (prompt) { + fputs(prompt, stdout); + fflush(stdout); + } + if (fgets(buffer, sizeof(buffer), stdin) == NULL) { + return 0; /* read fails */ + } else { + lua_pushstring(l, buffer); + return 1; + } +} + +/* Based on lua.c */ +static void _rpmluaInteractive(lua_State *L) +{ + fputs("\n", stdout); + printf("RPM Interactive %s Interpreter\n", LUA_VERSION); + for (;;) { + if (rpmluaReadline(L, "> ") == 0) + break; + if (lua_tostring(L, -1)[0] == '=') { + lua_pushfstring(L, "print(%s)", lua_tostring(L, -1)+1); + lua_remove(L, -2); + } + int rc = 0; + for (;;) { + rc = luaL_loadbuffer(L, lua_tostring(L, -1), + lua_strlen(L, -1), "<lua>"); + if (rc == LUA_ERRSYNTAX && + strstr(lua_tostring(L, -1), "near `<eof>'") != NULL) { + if (rpmluaReadline(L, ">> ") == 0) + break; + lua_remove(L, -2); // Remove error + lua_concat(L, 2); + continue; + } + break; + } + if (rc == 0) + rc = lua_pcall(L, 0, 0, 0); + if (rc != 0) { + fprintf(stderr, "%s\n", lua_tostring(L, -1)); + lua_pop(L, 1); + } + lua_pop(L, 1); // Remove line + } + fputs("\n", stdout); +} + +void rpmluaInteractive(rpmlua lua) +{ + _rpmluaInteractive(lua->L); +} + +/* ------------------------------------------------------------------ */ +/* Lua API */ + +static int rpm_expand(lua_State *L) +{ + const char *str = luaL_checkstring(L, 1); + lua_pushstring(L, rpmExpand(str, NULL)); + return 1; +} + +static int rpm_define(lua_State *L) +{ + const char *str = luaL_checkstring(L, 1); + rpmDefineMacro(NULL, str, 0); + return 0; +} + +static int rpm_interactive(lua_State *L) +{ + _rpmluaInteractive(L); + return 0; +} + +/* Based on luaB_print. */ +static int rpm_print (lua_State *L) +{ + rpmlua lua = (rpmlua)getdata(L, "lua");; + int n = lua_gettop(L); /* number of arguments */ + int i; + if (!lua) return 0; + lua_getglobal(L, "tostring"); + for (i = 1; i <= n; i++) { + const char *s; + lua_pushvalue(L, -1); /* function to be called */ + lua_pushvalue(L, i); /* value to print */ + lua_call(L, 1, 1); + s = lua_tostring(L, -1); /* get result */ + if (s == NULL) + return luaL_error(L, "`tostring' must return a string to `print'"); + if (lua->storeprint) { + int sl = lua_strlen(L, -1); + if (lua->printbufused+sl+1 > lua->printbufsize) { + lua->printbufsize += sl+512; + lua->printbuf = xrealloc(lua->printbuf, lua->printbufsize); + } + if (i > 1) + lua->printbuf[lua->printbufused++] = '\t'; + memcpy(lua->printbuf+lua->printbufused, s, sl+1); + lua->printbufused += sl; + } else { + if (i > 1) + fputs("\t", stdout); + fputs(s, stdout); + } + lua_pop(L, 1); /* pop result */ + } + lua_pop(L, 1); + if (!lua->storeprint) { + fputs("\n", stdout); + } else { + if (lua->printbufused+1 >= lua->printbufsize) { + lua->printbufsize += 512; + lua->printbuf = xrealloc(lua->printbuf, lua->printbufsize); + } + lua->printbuf[lua->printbufused++] = '\n'; + lua->printbuf[lua->printbufused] = '\0'; + } + return 0; +} + +static const luaL_reg rpmlib[] = { + {"expand", rpm_expand}, + {"define", rpm_define}, + {"interactive", rpm_interactive}, + {NULL, NULL} +}; + +static int luaopen_rpm(lua_State *L) +{ + lua_pushvalue(L, LUA_GLOBALSINDEX); + luaL_openlib(L, "rpm", rpmlib, 0); + return 0; +} + +/* vim:sts=4:sw=4 +*/ diff --git a/rpmio/rpmlua.h b/rpmio/rpmlua.h new file mode 100644 index 000000000..fad02efc6 --- /dev/null +++ b/rpmio/rpmlua.h @@ -0,0 +1,84 @@ +#ifndef RPMLUA_H +#define RPMLUA_H + +typedef enum rpmluavType_e { + RPMLUAV_NIL = 0, + RPMLUAV_STRING = 1, + RPMLUAV_NUMBER = 2 +} rpmluavType; + +#if defined(_RPMLUA_INTERNAL) + +#include <stdarg.h> +#include <lua.h> + +struct rpmlua_s { + lua_State *L; + int pushsize; + int storeprint; + int printbufsize; + int printbufused; + char *printbuf; +}; + +struct rpmluav_s { + rpmluavType keyType; + rpmluavType valueType; + union { + const char *str; + const void *ptr; + double num; + } key; + union { + const char *str; + const void *ptr; + double num; + } value; + int listmode; +}; + +#endif /* _RPMLUA_INTERNAL */ + +typedef struct rpmlua_s * rpmlua; +typedef struct rpmluav_s * rpmluav; + +rpmlua rpmluaNew(void); +void *rpmluaFree(rpmlua lua); + +int rpmluaCheckScript(rpmlua lua, const char *script, const char *name); +int rpmluaRunScript(rpmlua lua, const char *script, const char *name); +void rpmluaInteractive(rpmlua lua); + +void rpmluaSetData(rpmlua lua, const char *key, const void *data); +void *rpmluaGetData(rpmlua lua, const char *key); + +void rpmluaSetPrintBuffer(rpmlua lua, int flag); +const char *rpmluaGetPrintBuffer(rpmlua lua); + +void rpmluaSetVar(rpmlua lua, rpmluav var); +void rpmluaGetVar(rpmlua lua, rpmluav var); +void rpmluaDelVar(rpmlua lua, const char *key, ...); +int rpmluaVarExists(rpmlua lua, const char *key, ...); +void rpmluaPushTable(rpmlua lua, const char *key, ...); +void rpmluaPop(rpmlua lua); + +rpmluav rpmluavNew(void); +void *rpmluavFree(rpmluav var); +void rpmluavSetListMode(rpmluav var, int flag); +void rpmluavSetKey(rpmluav var, rpmluavType type, const void *value); +void rpmluavSetValue(rpmluav var, rpmluavType type, const void *value); +void rpmluavGetKey(rpmluav var, rpmluavType *type, void **value); +void rpmluavGetValue(rpmluav var, rpmluavType *type, void **value); + +/* Optional helpers for numbers. */ +void rpmluavSetKeyNum(rpmluav var, double value); +void rpmluavSetValueNum(rpmluav var, double value); +double rpmluavGetKeyNum(rpmluav var); +double rpmluavGetValueNum(rpmluav var); +int rpmluavKeyIsNum(rpmluav var); +int rpmluavValueIsNum(rpmluav var); + +#endif /* RPMLUA_H */ + +/* vim:sts=4:sw=4 +*/ |