- 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
This commit is contained in:
niemeyer 2004-03-19 20:08:20 +00:00
parent a1a283837a
commit 635edd9523
11 changed files with 823 additions and 331 deletions

View File

@ -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

View File

@ -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 */
@ -559,6 +560,78 @@ exit:
return rc;
}
/**
* 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@*/
@ -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;

View File

@ -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
*/

View File

@ -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
*/

View File

@ -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;

View File

@ -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");

View File

@ -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

View File

@ -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)

View File

@ -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) ||

588
rpmio/rpmlua.c Normal file
View File

@ -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
*/

84
rpmio/rpmlua.h Normal file
View File

@ -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
*/