11
#define lua_open() luaL_newstate()
15
#define lua_strlen(L,i) lua_rawlen(L, (i))
18
#ifndef lua_pushglobaltable
19
#define lua_pushglobaltable(L) lua_pushvalue(L, LUA_GLOBALSINDEX)
25
#include <rpm/rpmio.h>
26
#include <rpm/rpmmacro.h>
27
#include <rpm/rpmlog.h>
28
#include <rpm/rpmurl.h>
29
#include <rpm/rpmfileutil.h>
30
#include <rpm/rpmbase64.h>
31
#include "rpmio/rpmhook.h"
33
#define _RPMLUA_INTERNAL
34
#include "rpmio/rpmlua.h"
38
#define INITSTATE(_lua, lua) \
39
rpmlua lua = _lua ? _lua : \
40
(globalLuaState ? globalLuaState : \
42
(globalLuaState = rpmluaNew()) \
53
static rpmlua globalLuaState = NULL;
55
static int luaopen_rpm(lua_State *L);
56
static int rpm_print(lua_State *L);
58
rpmlua rpmluaGetGlobalState(void)
66
rpmlua lua = (rpmlua) xcalloc(1, sizeof(*lua));
69
char *initlua = rpmGenPath(rpmConfigDir(), "init.lua", NULL);
71
static const luaL_Reg extlibs[] = {
72
{"posix", luaopen_posix},
75
{"os", luaopen_rpm_os},
79
lua_State *L = lua_open();
83
for (lib = extlibs; lib->name; lib++) {
84
lua_pushcfunction(L, lib->func);
85
lua_pushstring(L, lib->name);
89
#ifndef LUA_GLOBALSINDEX
90
lua_pushglobaltable(L);
92
lua_pushliteral(L, "LUA_PATH");
93
lua_pushfstring(L, "%s/%s", rpmConfigDir(), "/lua/?.lua");
94
#ifdef LUA_GLOBALSINDEX
95
lua_rawset(L, LUA_GLOBALSINDEX);
99
lua_pushliteral(L, "print");
100
lua_pushcfunction(L, rpm_print);
101
#ifdef LUA_GLOBALSINDEX
102
lua_rawset(L, LUA_GLOBALSINDEX);
106
#ifndef LUA_GLOBALSINDEX
109
rpmluaSetData(lua, "lua", lua);
110
if (stat(initlua, &st) != -1)
111
(void)rpmluaRunScriptFile(lua, initlua);
116
rpmlua rpmluaFree(rpmlua lua)
119
if (lua->L) lua_close(lua->L);
122
if (lua == globalLuaState) globalLuaState = NULL;
127
void rpmluaSetData(rpmlua _lua, const char *key, const void *data)
129
INITSTATE(_lua, lua);
130
lua_State *L = lua->L;
131
lua_pushliteral(L, "rpm_");
132
lua_pushstring(L, key);
137
lua_pushlightuserdata(L, (void *)data);
138
lua_rawset(L, LUA_REGISTRYINDEX);
141
static void *getdata(lua_State *L, const char *key)
144
lua_pushliteral(L, "rpm_");
145
lua_pushstring(L, key);
147
lua_rawget(L, LUA_REGISTRYINDEX);
148
if (lua_islightuserdata(L, -1))
149
ret = lua_touserdata(L, -1);
154
void *rpmluaGetData(rpmlua _lua, const char *key)
156
INITSTATE(_lua, lua);
157
return getdata(lua->L, key);
160
void rpmluaPushPrintBuffer(rpmlua _lua)
162
INITSTATE(_lua, lua);
163
rpmluapb prbuf = xcalloc(1, sizeof(*prbuf));
167
prbuf->next = lua->printbuf;
169
lua->printbuf = prbuf;
172
char *rpmluaPopPrintBuffer(rpmlua _lua)
174
INITSTATE(_lua, lua);
175
rpmluapb prbuf = lua->printbuf;
180
lua->printbuf = prbuf->next;
187
static int pushvar(lua_State *L, rpmluavType type, void *value)
195
lua_pushstring(L, *((char **)value));
198
lua_pushnumber(L, *((double *)value));
207
void rpmluaSetVar(rpmlua _lua, rpmluav var)
209
INITSTATE(_lua, lua);
210
lua_State *L = lua->L;
211
if (var->listmode && lua->pushsize > 0) {
212
if (var->keyType != RPMLUAV_NUMBER || var->key.num == (double)0) {
213
var->keyType = RPMLUAV_NUMBER;
214
var->key.num = (double) luaL_getn(L, -1);
218
if (!var->listmode || lua->pushsize > 0) {
219
if (lua->pushsize == 0)
220
lua_pushglobaltable(L);
221
if (pushvar(L, var->keyType, &var->key) != -1) {
222
if (pushvar(L, var->valueType, &var->value) != -1)
227
if (lua->pushsize == 0)
232
static void popvar(lua_State *L, rpmluavType *type, void *value)
234
switch (lua_type(L, -1)) {
236
*type = RPMLUAV_STRING;
237
*((const char **)value) = lua_tostring(L, -1);
240
*type = RPMLUAV_NUMBER;
241
*((double *)value) = lua_tonumber(L, -1);
245
*((void **)value) = NULL;
251
void rpmluaGetVar(rpmlua _lua, rpmluav var)
253
INITSTATE(_lua, lua);
254
lua_State *L = lua->L;
255
if (!var->listmode) {
256
if (lua->pushsize == 0)
257
lua_pushglobaltable(L);
258
if (pushvar(L, var->keyType, &var->key) != -1) {
260
popvar(L, &var->valueType, &var->value);
262
if (lua->pushsize == 0)
264
} else if (lua->pushsize > 0) {
265
(void) pushvar(L, var->keyType, &var->key);
266
if (lua_next(L, -2) != 0)
267
popvar(L, &var->valueType, &var->value);
271
#define FINDKEY_RETURN 0
272
#define FINDKEY_CREATE 1
273
#define FINDKEY_REMOVE 2
274
static int findkey(lua_State *L, int oper, const char *key, va_list va)
281
blen = vsnprintf(NULL, 0, key, va);
286
buf = xmalloc(blen + 1);
287
vsnprintf(buf, blen + 1, key, va);
290
lua_pushglobaltable(L);
292
if (*e == '\0' || *e == '.') {
294
lua_pushlstring(L, s, e-s);
309
if (!lua_istable(L, -1)) {
312
lua_pushlstring(L, s, e-s);
313
lua_pushvalue(L, -2);
322
if (!lua_istable(L, -1)) {
336
void rpmluaDelVar(rpmlua _lua, const char *key, ...)
338
INITSTATE(_lua, lua);
341
(void) findkey(lua->L, FINDKEY_REMOVE, key, va);
345
int rpmluaVarExists(rpmlua _lua, const char *key, ...)
347
INITSTATE(_lua, lua);
348
lua_State *L = lua->L;
352
if (findkey(L, FINDKEY_RETURN, key, va) == 0) {
353
if (!lua_isnil(L, -1))
361
void rpmluaPushTable(rpmlua _lua, const char *key, ...)
363
INITSTATE(_lua, lua);
366
(void) findkey(lua->L, FINDKEY_CREATE, key, va);
371
void rpmluaPop(rpmlua _lua)
373
INITSTATE(_lua, lua);
374
assert(lua->pushsize > 0);
379
rpmluav rpmluavNew(void)
381
rpmluav var = (rpmluav) xcalloc(1, sizeof(*var));
385
rpmluav rpmluavFree(rpmluav var)
391
void rpmluavSetListMode(rpmluav var, int flag)
393
var->listmode = flag;
394
var->keyType = RPMLUAV_NIL;
397
void rpmluavSetKey(rpmluav var, rpmluavType type, const void *value)
402
var->key.num = *((double *)value);
405
var->key.str = (char *)value;
412
void rpmluavSetValue(rpmluav var, rpmluavType type, const void *value)
414
var->valueType = type;
417
var->value.num = *((const double *)value);
420
var->value.str = (const char *)value;
427
void rpmluavGetKey(rpmluav var, rpmluavType *type, void **value)
429
*type = var->keyType;
430
switch (var->keyType) {
432
*((double **)value) = &var->key.num;
435
*((const char **)value) = var->key.str;
442
void rpmluavGetValue(rpmluav var, rpmluavType *type, void **value)
444
*type = var->valueType;
445
switch (var->valueType) {
447
*((double **)value) = &var->value.num;
450
*((const char **)value) = var->value.str;
457
void rpmluavSetKeyNum(rpmluav var, double value)
459
rpmluavSetKey(var, RPMLUAV_NUMBER, &value);
462
void rpmluavSetValueNum(rpmluav var, double value)
464
rpmluavSetValue(var, RPMLUAV_NUMBER, &value);
467
double rpmluavGetKeyNum(rpmluav var)
471
rpmluavGetKey(var, &type, &value);
472
if (type == RPMLUAV_NUMBER)
473
return *((double *)value);
477
double rpmluavGetValueNum(rpmluav var)
481
rpmluavGetValue(var, &type, &value);
482
if (type == RPMLUAV_NUMBER)
483
return *((double *)value);
487
int rpmluavKeyIsNum(rpmluav var)
489
return (var->keyType == RPMLUAV_NUMBER) ? 1 : 0;
492
int rpmluavValueIsNum(rpmluav var)
494
return (var->valueType == RPMLUAV_NUMBER) ? 1 : 0;
497
int rpmluaCheckScript(rpmlua _lua, const char *script, const char *name)
499
INITSTATE(_lua, lua);
500
lua_State *L = lua->L;
504
if (luaL_loadbuffer(L, script, strlen(script), name) != 0) {
506
_("invalid syntax in lua scriptlet: %s\n"),
507
lua_tostring(L, -1));
510
lua_pop(L, 1); /* Error or chunk. */
514
int rpmluaRunScript(rpmlua _lua, const char *script, const char *name)
516
INITSTATE(_lua, lua);
517
lua_State *L = lua->L;
521
if (luaL_loadbuffer(L, script, strlen(script), name) != 0) {
522
rpmlog(RPMLOG_ERR, _("invalid syntax in lua script: %s\n"),
523
lua_tostring(L, -1));
526
} else if (lua_pcall(L, 0, 0, 0) != 0) {
527
rpmlog(RPMLOG_ERR, _("lua script failed: %s\n"),
528
lua_tostring(L, -1));
535
int rpmluaRunScriptFile(rpmlua _lua, const char *filename)
537
INITSTATE(_lua, lua);
538
lua_State *L = lua->L;
540
if (luaL_loadfile(L, filename) != 0) {
541
rpmlog(RPMLOG_ERR, _("invalid syntax in lua file: %s\n"),
542
lua_tostring(L, -1));
545
} else if (lua_pcall(L, 0, 0, 0) != 0) {
546
rpmlog(RPMLOG_ERR, _("lua script failed: %s\n"),
547
lua_tostring(L, -1));
555
static int rpmluaReadline(lua_State *L, const char *prompt)
557
static char buffer[1024];
559
(void) fputs(prompt, stdout);
560
(void) fflush(stdout);
562
if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
563
return 0; /* read fails */
565
lua_pushstring(L, buffer);
571
static void _rpmluaInteractive(lua_State *L)
573
(void) fputs("\n", stdout);
574
printf("RPM Interactive %s Interpreter\n", LUA_VERSION);
578
if (rpmluaReadline(L, "> ") == 0)
580
if (lua_tostring(L, -1)[0] == '=') {
581
(void) lua_pushfstring(L, "print(%s)", lua_tostring(L, -1)+1);
585
rc = luaL_loadbuffer(L, lua_tostring(L, -1),
586
lua_strlen(L, -1), "<lua>");
587
if (rc == LUA_ERRSYNTAX &&
588
strstr(lua_tostring(L, -1), "near `<eof>'") != NULL) {
589
if (rpmluaReadline(L, ">> ") == 0)
591
lua_remove(L, -2); /* Remove error */
598
rc = lua_pcall(L, 0, 0, 0);
600
fprintf(stderr, "%s\n", lua_tostring(L, -1));
603
lua_pop(L, 1); /* Remove line */
605
(void) fputs("\n", stdout);
608
void rpmluaInteractive(rpmlua _lua)
610
INITSTATE(_lua, lua);
611
_rpmluaInteractive(lua->L);
614
/* ------------------------------------------------------------------ */
617
static int rpm_b64encode(lua_State *L)
619
const char *str = luaL_checkstring(L, 1);
620
size_t len = lua_strlen(L, 1);
622
if (lua_gettop(L) == 2)
623
linelen = luaL_checkinteger(L, 2);
625
char *data = rpmBase64Encode(str, len, linelen);
626
lua_pushstring(L, data);
632
static int rpm_b64decode(lua_State *L)
634
const char *str = luaL_checkstring(L, 1);
638
if (rpmBase64Decode(str, &data, &len) == 0) {
639
lua_pushlstring(L, data, len);
648
static int rpm_expand(lua_State *L)
650
const char *str = luaL_checkstring(L, 1);
651
char *val = rpmExpand(str, NULL);
652
lua_pushstring(L, val);
657
static int rpm_define(lua_State *L)
659
const char *str = luaL_checkstring(L, 1);
660
(void) rpmDefineMacro(NULL, str, 0);
664
static int rpm_interactive(lua_State *L)
666
_rpmluaInteractive(L);
670
typedef struct rpmluaHookData_s {
676
static int rpmluaHookWrapper(rpmhookArgs args, void *data)
678
rpmluaHookData hookdata = (rpmluaHookData)data;
679
lua_State *L = hookdata->L;
682
lua_rawgeti(L, LUA_REGISTRYINDEX, hookdata->funcRef);
684
for (i = 0; i != args->argc; i++) {
685
switch (args->argt[i]) {
687
lua_pushstring(L, args->argv[i].s);
688
lua_rawseti(L, -2, i+1);
691
lua_pushnumber(L, (lua_Number)args->argv[i].i);
692
lua_rawseti(L, -2, i+1);
695
lua_pushnumber(L, (lua_Number)args->argv[i].f);
696
lua_rawseti(L, -2, i+1);
699
lua_pushlightuserdata(L, args->argv[i].p);
700
lua_rawseti(L, -2, i+1);
703
(void) luaL_error(L, "unsupported type '%c' as "
704
"a hook argument\n", args->argt[i]);
708
if (lua_pcall(L, 1, 1, 0) != 0) {
709
rpmlog(RPMLOG_ERR, _("lua hook failed: %s\n"),
710
lua_tostring(L, -1));
713
if (lua_isnumber(L, -1))
714
ret = (int)lua_tonumber(L, -1);
720
static int rpm_register(lua_State *L)
722
if (!lua_isstring(L, 1)) {
723
(void) luaL_argerror(L, 1, "hook name expected");
724
} else if (!lua_isfunction(L, 2)) {
725
(void) luaL_argerror(L, 2, "function expected");
727
rpmluaHookData hookdata =
728
lua_newuserdata(L, sizeof(struct rpmluaHookData_s));
729
lua_pushvalue(L, -1);
730
hookdata->dataRef = luaL_ref(L, LUA_REGISTRYINDEX);
732
hookdata->funcRef = luaL_ref(L, LUA_REGISTRYINDEX);
734
rpmhookRegister(lua_tostring(L, 1), rpmluaHookWrapper, hookdata);
740
static int rpm_unregister(lua_State *L)
742
if (!lua_isstring(L, 1)) {
743
(void) luaL_argerror(L, 1, "hook name expected");
744
} else if (!lua_isuserdata(L, 2)) {
745
(void) luaL_argerror(L, 2, "hook information expected");
747
rpmluaHookData hookdata = (rpmluaHookData)lua_touserdata(L, 2);
748
luaL_unref(L, LUA_REGISTRYINDEX, hookdata->funcRef);
749
luaL_unref(L, LUA_REGISTRYINDEX, hookdata->dataRef);
750
rpmhookUnregister(lua_tostring(L, 1), rpmluaHookWrapper, hookdata);
755
static int rpm_call(lua_State *L)
757
if (!lua_isstring(L, 1)) {
758
(void) luaL_argerror(L, 1, "hook name expected");
760
rpmhookArgs args = rpmhookArgsNew(lua_gettop(L)-1);
761
const char *name = lua_tostring(L, 1);
762
char *argt = (char *)xmalloc(args->argc+1);
764
for (i = 0; i != args->argc; i++) {
765
switch (lua_type(L, i+1)) {
768
args->argv[i].p = NULL;
771
float f = (float)lua_tonumber(L, i+1);
774
args->argv[i].i = (int)f;
782
args->argv[i].s = lua_tostring(L, i+1);
785
case LUA_TLIGHTUSERDATA:
787
args->argv[i].p = lua_touserdata(L, i+1);
790
(void) luaL_error(L, "unsupported Lua type passed to hook");
792
args->argv[i].p = NULL;
797
rpmhookCallArgs(name, args);
799
(void) rpmhookArgsFree(args);
804
/* Based on luaB_print. */
805
static int rpm_print (lua_State *L)
807
rpmlua lua = (rpmlua)getdata(L, "lua");
808
int n = lua_gettop(L); /* number of arguments */
811
lua_getglobal(L, "tostring");
812
for (i = 1; i <= n; i++) {
814
lua_pushvalue(L, -1); /* function to be called */
815
lua_pushvalue(L, i); /* value to print */
817
s = lua_tostring(L, -1); /* get result */
819
return luaL_error(L, "`tostring' must return a string to `print'");
821
rpmluapb prbuf = lua->printbuf;
822
int sl = lua_strlen(L, -1);
823
if (prbuf->used+sl+1 > prbuf->alloced) {
824
prbuf->alloced += sl+512;
825
prbuf->buf = xrealloc(prbuf->buf, prbuf->alloced);
828
prbuf->buf[prbuf->used++] = '\t';
829
memcpy(prbuf->buf+prbuf->used, s, sl+1);
833
(void) fputs("\t", stdout);
834
(void) fputs(s, stdout);
836
lua_pop(L, 1); /* pop result */
838
if (!lua->printbuf) {
839
(void) fputs("\n", stdout);
841
rpmluapb prbuf = lua->printbuf;
842
if (prbuf->used+1 > prbuf->alloced) {
843
prbuf->alloced += 512;
844
prbuf->buf = xrealloc(prbuf->buf, prbuf->alloced);
846
prbuf->buf[prbuf->used] = '\0';
851
static const luaL_Reg rpmlib[] = {
852
{"b64encode", rpm_b64encode},
853
{"b64decode", rpm_b64decode},
854
{"expand", rpm_expand},
855
{"define", rpm_define},
856
{"register", rpm_register},
857
{"unregister", rpm_unregister},
859
{"interactive", rpm_interactive},
863
static int luaopen_rpm(lua_State *L)
865
lua_pushglobaltable(L);
866
luaL_openlib(L, "rpm", rpmlib, 0);
869
#endif /* WITH_LUA */