00001
00002 #include "system.h"
00003
00004 #ifdef WITH_LUA
00005 #define _RPMIOB_INTERNAL
00006 #include <rpmiotypes.h>
00007 #include <rpmio.h>
00008 #include <rpmmacro.h>
00009 #include <rpmlog.h>
00010 #include <rpmurl.h>
00011 #include <rpmhook.h>
00012 #include <rpmcb.h>
00013 #include <argv.h>
00014 #include <popt.h>
00015
00016 #include <lua.h>
00017 #include <lualib.h>
00018 #include <lauxlib.h>
00019 #ifdef WITH_SYCK
00020 LUALIB_API int luaopen_syck(lua_State *L)
00021 ;
00022 #endif
00023 #ifdef WITH_LUA_INTERNAL
00024 #include <llocal.h>
00025 #include <lposix.h>
00026 #include <lrexlib.h>
00027 #include <luuid.h>
00028 #include <lwrs.h>
00029 #ifdef USE_LUA_CRYPTO
00030 #include <lcrypto.h>
00031 #include <lxplib.h>
00032 #endif
00033 #ifdef USE_LUA_SOCKET
00034 #include <luasocket.h>
00035 #endif
00036 #endif
00037
00038 #include <unistd.h>
00039 #include <assert.h>
00040
00041 #define _RPMLUA_INTERNAL
00042 #include "rpmlua.h"
00043
00044 #include "debug.h"
00045
00046
00047
00048 #else
00049 #include <rpmio.h>
00050 #endif
00051
00052
00053 int _rpmlua_debug = 0;
00054
00055
00056 rpmioPool _rpmluaPool = NULL;
00057
00058
00059 rpmioPool _rpmluavPool = NULL;
00060
00061 #ifdef WITH_LUA
00062
00063 #if !defined(HAVE_VSNPRINTF)
00064 static inline int vsnprintf(char * buf, size_t nb,
00065 const char * fmt, va_list ap)
00066 {
00067 return vsprintf(buf, fmt, ap);
00068 }
00069 #endif
00070
00071 #define INITSTATE(_lua, lua) \
00072 rpmlua lua = _lua ? _lua : \
00073 (globalLuaState ? globalLuaState : \
00074 \
00075 (globalLuaState = rpmluaNew()) \
00076 \
00077 )
00078
00079
00080 static rpmlua globalLuaState;
00081
00082 static int luaopen_rpm(lua_State *L)
00083 ;
00084 static int rpm_print(lua_State *L)
00085
00086 ;
00087
00088
00089 const char * rpmluaFiles = RPMLUAFILES;
00090
00091
00092 const char * rpmluaPath = "%{?_rpmhome}%{!?_rpmhome:" USRLIBRPM "}/lua/?.lua";
00093
00094 rpmlua rpmluaGetGlobalState(void)
00095 {
00096
00097 return globalLuaState;
00098
00099 }
00100
00101 static void rpmluaFini(void * _lua)
00102
00103
00104 {
00105 rpmlua lua = _lua;
00106
00107 if (lua->L) lua_close(lua->L);
00108 lua->L = NULL;
00109 lua->printbuf = _free(lua->printbuf);
00110 }
00111
00112 static rpmlua rpmluaGetPool( rpmioPool pool)
00113
00114
00115 {
00116 rpmlua lua;
00117
00118 if (_rpmluaPool == NULL) {
00119 _rpmluaPool = rpmioNewPool("lua", sizeof(*lua), -1, _rpmlua_debug,
00120 NULL, NULL, rpmluaFini);
00121 pool = _rpmluaPool;
00122 }
00123 return (rpmlua) rpmioGetPool(pool, sizeof(*lua));
00124 }
00125
00126 void *rpmluaFree(rpmlua lua)
00127 {
00128 if (lua == NULL) lua = globalLuaState;
00129 (void)rpmioFreePoolItem((rpmioItem)lua, __FUNCTION__, __FILE__, __LINE__);
00130 if (lua == globalLuaState) globalLuaState = NULL;
00131 return NULL;
00132 }
00133
00134
00135 rpmlua rpmluaNew(void)
00136 {
00137 rpmlua lua = rpmluaGetPool(_rpmluaPool);
00138 lua_State *L = lua_open();
00139
00140
00141 static const luaL_reg lualibs[] = {
00142
00143 {"", luaopen_base},
00144 {LUA_LOADLIBNAME, luaopen_package},
00145 {LUA_TABLIBNAME, luaopen_table},
00146 {LUA_IOLIBNAME, luaopen_io},
00147 {LUA_OSLIBNAME, luaopen_os},
00148 {LUA_STRLIBNAME, luaopen_string},
00149 {LUA_MATHLIBNAME, luaopen_math},
00150 {LUA_DBLIBNAME, luaopen_debug},
00151 #ifdef WITH_SYCK
00152 {"lsyck", luaopen_syck},
00153 #endif
00154
00155 #ifdef WITH_LUA_INTERNAL
00156 {"posix", luaopen_posix},
00157 {"rex_posix", luaopen_rex_posix},
00158 {"rex_pcre", luaopen_rex_pcre},
00159 {"uuid", luaopen_uuid},
00160 {"wrs", luaopen_wrs},
00161 #ifdef USE_LUA_CRYPTO
00162 {"crypto", luaopen_crypto},
00163 {"lxp", luaopen_lxp},
00164 #endif
00165 #ifdef USE_LUA_SOCKET
00166 {"socket", luaopen_socket_core},
00167 #endif
00168 {"local", luaopen_local},
00169 #endif
00170 {"rpm", luaopen_rpm},
00171 {NULL, NULL},
00172 };
00173
00174
00175 const luaL_reg *lib = lualibs;
00176 char *path_buf;
00177 char *path_next;
00178 char *path;
00179
00180 lua->L = L;
00181 for (; lib->name; lib++) {
00182
00183 lua_pushcfunction(L, lib->func);
00184 lua_pushstring(L, lib->name);
00185 lua_call(L, 1, 0);
00186
00187 }
00188 { const char * _lua_path = rpmGetPath(rpmluaPath, NULL);
00189 if (_lua_path != NULL) {
00190 lua_pushliteral(L, "LUA_PATH");
00191 lua_pushstring(L, _lua_path);
00192 _lua_path = _free(_lua_path);
00193 }
00194 }
00195 lua_rawset(L, LUA_GLOBALSINDEX);
00196 lua_pushliteral(L, "print");
00197 lua_pushcfunction(L, rpm_print);
00198 lua_rawset(L, LUA_GLOBALSINDEX);
00199 rpmluaSetData(lua, "lua", lua);
00200
00201
00202 path_buf = xstrdup(rpmluaFiles);
00203 for (path = path_buf; path != NULL && *path != '\0'; path = path_next) {
00204 const char **av;
00205 struct stat st;
00206 int ac, i;
00207
00208
00209 path_next = strchr(path, ':');
00210 if (path_next != NULL && *path_next == ':')
00211 *path_next++ = '\0';
00212 else
00213 path_next = path + strlen(path);
00214
00215
00216 ac = 0;
00217 av = NULL;
00218 if ((i = rpmGlob(path, &ac, &av)) != 0)
00219 continue;
00220
00221
00222 for (i = 0; i < ac; i++) {
00223 const char *fn = av[i];
00224 if (fn[0] == '@' ) {
00225 fn++;
00226 #if defined(RPM_VENDOR_OPENPKG) || \
00227 !defined(POPT_ERROR_BADCONFIG)
00228 if (!rpmSecuritySaneFile(fn))
00229 #else
00230 if (!poptSaneFile(fn))
00231 #endif
00232 {
00233 rpmlog(RPMLOG_WARNING, "existing RPM Lua script file \"%s\" considered INSECURE -- not loaded\n", fn);
00234 continue;
00235 }
00236 }
00237 if (Stat(fn, &st) != -1)
00238 (void)rpmluaRunScriptFile(lua, fn);
00239 av[i] = _free(av[i]);
00240 }
00241 av = _free(av);
00242 }
00243 path_buf = _free(path_buf);
00244
00245 return ((rpmlua)rpmioLinkPoolItem((rpmioItem)lua, __FUNCTION__, __FILE__, __LINE__));
00246 }
00247
00248
00249 void rpmluaSetData(rpmlua _lua, const char *key, const void *data)
00250 {
00251 INITSTATE(_lua, lua);
00252 lua_State *L = lua->L;
00253 lua_pushliteral(L, "rpm_");
00254 lua_pushstring(L, key);
00255 lua_concat(L, 2);
00256 if (data == NULL)
00257 lua_pushnil(L);
00258 else
00259 lua_pushlightuserdata(L, (void *)data);
00260 lua_rawset(L, LUA_REGISTRYINDEX);
00261 }
00262
00263
00264 static void *getdata(lua_State *L, const char *key)
00265
00266 {
00267 void *ret = NULL;
00268 lua_pushliteral(L, "rpm_");
00269 lua_pushstring(L, key);
00270 lua_concat(L, 2);
00271 lua_rawget(L, LUA_REGISTRYINDEX);
00272 if (lua_islightuserdata(L, -1))
00273 ret = lua_touserdata(L, -1);
00274 lua_pop(L, 1);
00275 return ret;
00276 }
00277
00278 void *rpmluaGetData(rpmlua _lua, const char *key)
00279 {
00280 INITSTATE(_lua, lua);
00281 return getdata(lua->L, key);
00282 }
00283
00284 void rpmluaSetPrintBuffer(rpmlua _lua, int flag)
00285 {
00286 INITSTATE(_lua, lua);
00287 lua->storeprint = flag;
00288 lua->printbuf = _free(lua->printbuf);
00289 lua->printbufsize = 0;
00290 lua->printbufused = 0;
00291 }
00292
00293 const char *rpmluaGetPrintBuffer(rpmlua _lua)
00294 {
00295 INITSTATE(_lua, lua);
00296 return lua->printbuf;
00297 }
00298
00299 static int pushvar(lua_State *L, rpmluavType type, void *value)
00300
00301 {
00302 int ret = 0;
00303 switch (type) {
00304 case RPMLUAV_NIL:
00305 lua_pushnil(L);
00306 break;
00307 case RPMLUAV_STRING:
00308 lua_pushstring(L, *((char **)value));
00309 break;
00310 case RPMLUAV_NUMBER:
00311 lua_pushnumber(L, *((double *)value));
00312 break;
00313 default:
00314 ret = -1;
00315 break;
00316 }
00317 return ret;
00318 }
00319
00320 void rpmluaSetVar(rpmlua _lua, rpmluav var)
00321 {
00322 INITSTATE(_lua, lua);
00323 lua_State *L = lua->L;
00324 if (var->listmode && lua->pushsize > 0) {
00325 if (var->keyType != RPMLUAV_NUMBER || var->key.num == (double)0) {
00326 var->keyType = RPMLUAV_NUMBER;
00327 var->key.num = (double) luaL_getn(L, -1);
00328 }
00329 var->key.num++;
00330 }
00331 if (!var->listmode || lua->pushsize > 0) {
00332 if (lua->pushsize == 0)
00333 lua_pushvalue(L, LUA_GLOBALSINDEX);
00334 if (pushvar(L, var->keyType, &var->key) != -1) {
00335 if (pushvar(L, var->valueType, &var->value) != -1)
00336 lua_rawset(L, -3);
00337 else
00338 lua_pop(L, 1);
00339 }
00340 if (lua->pushsize == 0)
00341 lua_pop(L, 1);
00342 }
00343 }
00344
00345 static void popvar(lua_State *L, rpmluavType *type, void *value)
00346
00347 {
00348 switch (lua_type(L, -1)) {
00349 case LUA_TSTRING:
00350 *type = RPMLUAV_STRING;
00351
00352 *((const char **)value) = lua_tostring(L, -1);
00353
00354 break;
00355 case LUA_TNUMBER:
00356 *type = RPMLUAV_NUMBER;
00357 *((double *)value) = lua_tonumber(L, -1);
00358 break;
00359 default:
00360 *type = RPMLUAV_NIL;
00361 *((void **)value) = NULL;
00362 break;
00363 }
00364 lua_pop(L, 1);
00365 }
00366
00367 void rpmluaGetVar(rpmlua _lua, rpmluav var)
00368 {
00369 INITSTATE(_lua, lua);
00370 lua_State *L = lua->L;
00371 if (!var->listmode) {
00372 if (lua->pushsize == 0)
00373 lua_pushvalue(L, LUA_GLOBALSINDEX);
00374 if (pushvar(L, var->keyType, &var->key) != -1) {
00375 lua_rawget(L, -2);
00376 popvar(L, &var->valueType, &var->value);
00377 }
00378 if (lua->pushsize == 0)
00379 lua_pop(L, 1);
00380 } else if (lua->pushsize > 0) {
00381 (void) pushvar(L, var->keyType, &var->key);
00382 if (lua_next(L, -2) != 0)
00383 popvar(L, &var->valueType, &var->value);
00384 }
00385 }
00386
00387 #define FINDKEY_RETURN 0
00388 #define FINDKEY_CREATE 1
00389 #define FINDKEY_REMOVE 2
00390 static int findkey(lua_State *L, int oper, const char *key, va_list va)
00391
00392 {
00393 char buf[BUFSIZ];
00394 const char *s, *e;
00395 int ret = 0;
00396 (void) vsnprintf(buf, sizeof(buf), key, va);
00397 s = e = buf;
00398 lua_pushvalue(L, LUA_GLOBALSINDEX);
00399 for (;;) {
00400 if (*e == '\0' || *e == '.') {
00401 if (e != s) {
00402 lua_pushlstring(L, s, e-s);
00403 switch (oper) {
00404 case FINDKEY_REMOVE:
00405 if (*e == '\0') {
00406 lua_pushnil(L);
00407 lua_rawset(L, -3);
00408 lua_pop(L, 1);
00409 break;
00410 }
00411
00412 case FINDKEY_RETURN:
00413 lua_rawget(L, -2);
00414 lua_remove(L, -2);
00415 break;
00416 case FINDKEY_CREATE:
00417 lua_rawget(L, -2);
00418 if (!lua_istable(L, -1)) {
00419 lua_pop(L, 1);
00420 lua_newtable(L);
00421 lua_pushlstring(L, s, e-s);
00422 lua_pushvalue(L, -2);
00423 lua_rawset(L, -4);
00424 }
00425 lua_remove(L, -2);
00426 break;
00427 }
00428 }
00429 if (*e == '\0')
00430 break;
00431 if (!lua_istable(L, -1)) {
00432 lua_pop(L, 1);
00433 ret = -1;
00434 break;
00435 }
00436 s = e+1;
00437 }
00438 e++;
00439 }
00440
00441 return ret;
00442 }
00443
00444 void rpmluaDelVar(rpmlua _lua, const char *key, ...)
00445 {
00446 INITSTATE(_lua, lua);
00447 va_list va;
00448 va_start(va, key);
00449 (void) findkey(lua->L, FINDKEY_REMOVE, key, va);
00450 va_end(va);
00451 }
00452
00453 int rpmluaVarExists(rpmlua _lua, const char *key, ...)
00454 {
00455 INITSTATE(_lua, lua);
00456 lua_State *L = lua->L;
00457 int ret = 0;
00458 va_list va;
00459 va_start(va, key);
00460 if (findkey(L, FINDKEY_RETURN, key, va) == 0) {
00461 if (!lua_isnil(L, -1))
00462 ret = 1;
00463 lua_pop(L, 1);
00464 }
00465 va_end(va);
00466 return ret;
00467 }
00468
00469 void rpmluaPushTable(rpmlua _lua, const char *key, ...)
00470 {
00471 INITSTATE(_lua, lua);
00472 va_list va;
00473 va_start(va, key);
00474 (void) findkey(lua->L, FINDKEY_CREATE, key, va);
00475 lua->pushsize++;
00476 va_end(va);
00477 }
00478
00479 void rpmluaPop(rpmlua _lua)
00480 {
00481 INITSTATE(_lua, lua);
00482 assert(lua->pushsize > 0);
00483 lua->pushsize--;
00484 lua_pop(lua->L, 1);
00485 }
00486
00487 void *rpmluavFree(rpmluav var)
00488 {
00489 (void)rpmioFreePoolItem((rpmioItem)var, __FUNCTION__, __FILE__, __LINE__);
00490 return NULL;
00491 }
00492
00493 static rpmluav rpmluavGetPool( rpmioPool pool)
00494
00495
00496 {
00497 rpmluav luav;
00498
00499 if (_rpmluavPool == NULL) {
00500 _rpmluavPool = rpmioNewPool("luav", sizeof(*luav), -1, _rpmlua_debug,
00501 NULL, NULL, NULL);
00502 pool = _rpmluavPool;
00503 }
00504 return (rpmluav) rpmioGetPool(pool, sizeof(*luav));
00505 }
00506
00507 rpmluav rpmluavNew(void)
00508 {
00509 rpmluav var = rpmluavGetPool(_rpmluavPool);
00510 return ((rpmluav)rpmioLinkPoolItem((rpmioItem)var, __FUNCTION__, __FILE__, __LINE__));
00511 }
00512
00513 void rpmluavSetListMode(rpmluav var, int flag)
00514 {
00515 var->listmode = flag;
00516 var->keyType = RPMLUAV_NIL;
00517 }
00518
00519 void rpmluavSetKey(rpmluav var, rpmluavType type, const void *value)
00520 {
00521 var->keyType = type;
00522
00523 switch (type) {
00524 case RPMLUAV_NUMBER:
00525 var->key.num = *((double *)value);
00526 break;
00527 case RPMLUAV_STRING:
00528 var->key.str = (char *)value;
00529 break;
00530 default:
00531 break;
00532 }
00533
00534 }
00535
00536 void rpmluavSetValue(rpmluav var, rpmluavType type, const void *value)
00537 {
00538 var->valueType = type;
00539
00540 switch (type) {
00541 case RPMLUAV_NUMBER:
00542 var->value.num = *((const double *)value);
00543 break;
00544 case RPMLUAV_STRING:
00545 var->value.str = (const char *)value;
00546 break;
00547 default:
00548 break;
00549 }
00550
00551 }
00552
00553 void rpmluavGetKey(rpmluav var, rpmluavType *type, void **value)
00554 {
00555 *type = var->keyType;
00556
00557 switch (var->keyType) {
00558 case RPMLUAV_NUMBER:
00559 *((double **)value) = &var->key.num;
00560 break;
00561 case RPMLUAV_STRING:
00562 *((const char **)value) = var->key.str;
00563 break;
00564 default:
00565 break;
00566 }
00567
00568 }
00569
00570 void rpmluavGetValue(rpmluav var, rpmluavType *type, void **value)
00571 {
00572 *type = var->valueType;
00573
00574 switch (var->valueType) {
00575 case RPMLUAV_NUMBER:
00576 *((double **)value) = &var->value.num;
00577 break;
00578 case RPMLUAV_STRING:
00579 *((const char **)value) = var->value.str;
00580 break;
00581 default:
00582 break;
00583 }
00584
00585 }
00586
00587 void rpmluavSetKeyNum(rpmluav var, double value)
00588 {
00589 rpmluavSetKey(var, RPMLUAV_NUMBER, &value);
00590 }
00591
00592 void rpmluavSetValueNum(rpmluav var, double value)
00593 {
00594 rpmluavSetValue(var, RPMLUAV_NUMBER, &value);
00595 }
00596
00597 double rpmluavGetKeyNum(rpmluav var)
00598 {
00599 rpmluavType type;
00600 void *value;
00601 rpmluavGetKey(var, &type, &value);
00602 if (type == RPMLUAV_NUMBER)
00603 return *((double *)value);
00604 return (double) 0;
00605 }
00606
00607 double rpmluavGetValueNum(rpmluav var)
00608 {
00609 rpmluavType type;
00610 void *value;
00611 rpmluavGetValue(var, &type, &value);
00612 if (type == RPMLUAV_NUMBER)
00613 return *((double *)value);
00614 return (double) 0;
00615 }
00616
00617 int rpmluavKeyIsNum(rpmluav var)
00618 {
00619 return (var->keyType == RPMLUAV_NUMBER) ? 1 : 0;
00620 }
00621
00622 int rpmluavValueIsNum(rpmluav var)
00623 {
00624 return (var->valueType == RPMLUAV_NUMBER) ? 1 : 0;
00625 }
00626
00627 int rpmluaCheckScript(rpmlua _lua, const char *script, const char *name)
00628 {
00629 INITSTATE(_lua, lua);
00630 lua_State *L = lua->L;
00631 int ret = 0;
00632 if (name == NULL)
00633 name = "<lua>";
00634 if (luaL_loadbuffer(L, script, strlen(script), name) != 0) {
00635 rpmlog(RPMLOG_ERR,
00636 _("invalid syntax in Lua scriptlet: %s\n"),
00637 lua_tostring(L, -1));
00638 ret = -1;
00639 }
00640 lua_pop(L, 1);
00641 return ret;
00642 }
00643
00644 int rpmluaRunScript(rpmlua _lua, const char *script, const char *name)
00645 {
00646 INITSTATE(_lua, lua);
00647 lua_State *L = lua->L;
00648 int ret = 0;
00649 if (name == NULL)
00650 name = "<lua>";
00651 if (luaL_loadbuffer(L, script, strlen(script), name) != 0) {
00652 rpmlog(RPMLOG_ERR, _("invalid syntax in Lua script: %s\n"),
00653 lua_tostring(L, -1));
00654 lua_pop(L, 1);
00655 ret = -1;
00656 } else if (lua_pcall(L, 0, 0, 0) != 0) {
00657 rpmlog(RPMLOG_ERR, _("Lua script failed: %s\n"),
00658 lua_tostring(L, -1));
00659 lua_pop(L, 1);
00660 ret = -1;
00661 }
00662 return ret;
00663 }
00664
00665 int rpmluaRunScriptFile(rpmlua _lua, const char *filename)
00666 {
00667 INITSTATE(_lua, lua);
00668 lua_State *L = lua->L;
00669 int ret = 0;
00670 if (luaL_loadfile(L, filename) != 0) {
00671 rpmlog(RPMLOG_ERR, _("invalid syntax in Lua file: %s\n"),
00672 lua_tostring(L, -1));
00673 lua_pop(L, 1);
00674 ret = -1;
00675 } else if (lua_pcall(L, 0, 0, 0) != 0) {
00676 rpmlog(RPMLOG_ERR, _("Lua script failed: %s\n"),
00677 lua_tostring(L, -1));
00678 lua_pop(L, 1);
00679 ret = -1;
00680 }
00681 return ret;
00682 }
00683
00684
00685 static int rpmluaReadline(lua_State *L, const char *prompt)
00686
00687
00688 {
00689 static char buffer[1024];
00690 if (prompt) {
00691 (void) fputs(prompt, stdout);
00692 (void) fflush(stdout);
00693 }
00694 if (fgets(buffer, (int)sizeof(buffer), stdin) == NULL) {
00695 return 0;
00696 } else {
00697 lua_pushstring(L, buffer);
00698 return 1;
00699 }
00700 }
00701
00702
00703 static void _rpmluaInteractive(lua_State *L)
00704
00705
00706 {
00707 (void) fputs("\n", stdout);
00708 printf("RPM Interactive %s Interpreter\n", LUA_VERSION);
00709 for (;;) {
00710 int rc = 0;
00711
00712 if (rpmluaReadline(L, "> ") == 0)
00713 break;
00714 if (lua_tostring(L, -1)[0] == '=') {
00715
00716 (void) lua_pushfstring(L, "print(%s)", lua_tostring(L, -1)+1);
00717
00718 lua_remove(L, -2);
00719 }
00720 for (;;) {
00721
00722 rc = luaL_loadbuffer(L, lua_tostring(L, -1),
00723 lua_strlen(L, -1), "<lua>");
00724
00725 if (rc == LUA_ERRSYNTAX &&
00726 strstr(lua_tostring(L, -1), "near `<eof>'") != NULL) {
00727 if (rpmluaReadline(L, ">> ") == 0)
00728 break;
00729 lua_remove(L, -2);
00730 lua_concat(L, 2);
00731 continue;
00732 }
00733 break;
00734 }
00735 if (rc == 0)
00736 rc = lua_pcall(L, 0, 0, 0);
00737 if (rc != 0) {
00738
00739 fprintf(stderr, "%s\n", lua_tostring(L, -1));
00740
00741 lua_pop(L, 1);
00742 }
00743 lua_pop(L, 1);
00744 }
00745 (void) fputs("\n", stdout);
00746 }
00747
00748
00749 void rpmluaInteractive(rpmlua _lua)
00750 {
00751 INITSTATE(_lua, lua);
00752 _rpmluaInteractive(lua->L);
00753 }
00754
00755
00756
00757
00758
00759 static int rpm_macros(lua_State *L)
00760
00761 {
00762 const char ** av = NULL;
00763 int ac = 0;
00764 int i;
00765
00766
00767 lua_newtable(L);
00768
00769
00770
00771 ac = rpmGetMacroEntries(NULL, NULL, -1, &av);
00772
00773
00774 if (av != NULL)
00775 for (i = 0; i < ac; i++) {
00776 char *n, *o, *b;
00777
00778
00779 n = (char *) av[i];
00780 b = strchr(n, '\t');
00781 assert(b != NULL);
00782 o = ((b > n && b[-1] == ')') ? strchr(n, '(') : NULL);
00783 if (*n == '%') n++;
00784 if (o != NULL && *o == '(') {
00785 b[-1] = '\0';
00786 o++;
00787 o[-1] = '\0';
00788 }
00789 else
00790 b[0] = '\0';
00791 b++;
00792
00793
00794 lua_pushstring(L, n);
00795 lua_newtable(L);
00796 if (o) {
00797 lua_pushstring(L, "opts");
00798 lua_pushstring(L, o);
00799 lua_settable(L, -3);
00800 }
00801 if (b) {
00802 lua_pushstring(L, "body");
00803 lua_pushstring(L, b);
00804 lua_settable(L, -3);
00805 }
00806 lua_settable(L, -3);
00807
00808 }
00809 av = argvFree(av);
00810 return 1;
00811 }
00812
00813 static int rpm_expand(lua_State *L)
00814
00815
00816 {
00817 const char *str = luaL_checkstring(L, 1);
00818 lua_pushstring(L, rpmExpand(str, NULL));
00819 return 1;
00820 }
00821
00822 static int rpm_define(lua_State *L)
00823
00824
00825 {
00826 const char *str = luaL_checkstring(L, 1);
00827 (void) rpmDefineMacro(NULL, str, 0);
00828 return 0;
00829 }
00830
00831 static int rpm_undefine(lua_State *L)
00832
00833
00834 {
00835 const char *str = luaL_checkstring(L, 1);
00836 (void) rpmUndefineMacro(NULL, str);
00837 return 0;
00838 }
00839
00840 static int rpm_interactive(lua_State *L)
00841
00842
00843 {
00844 _rpmluaInteractive(L);
00845 return 0;
00846 }
00847
00848 typedef struct rpmluaHookData_s {
00849
00850 lua_State *L;
00851 int funcRef;
00852 int dataRef;
00853 } * rpmluaHookData;
00854
00855 static int rpmluaHookWrapper(rpmhookArgs args, void *data)
00856
00857 {
00858 rpmluaHookData hookdata = (rpmluaHookData)data;
00859 lua_State *L = hookdata->L;
00860 int ret = 0;
00861 int i;
00862 lua_rawgeti(L, LUA_REGISTRYINDEX, hookdata->funcRef);
00863 lua_newtable(L);
00864 for (i = 0; i != args->argc; i++) {
00865 switch (args->argt[i]) {
00866 case 's':
00867 lua_pushstring(L, args->argv[i].s);
00868 lua_rawseti(L, -2, i+1);
00869 break;
00870 case 'i':
00871 lua_pushnumber(L, (lua_Number)args->argv[i].i);
00872 lua_rawseti(L, -2, i+1);
00873 break;
00874 case 'f':
00875 lua_pushnumber(L, (lua_Number)args->argv[i].f);
00876 lua_rawseti(L, -2, i+1);
00877 break;
00878 case 'p':
00879 lua_pushlightuserdata(L, args->argv[i].p);
00880 lua_rawseti(L, -2, i+1);
00881 break;
00882 default:
00883 (void) luaL_error(L, "unsupported type '%c' as "
00884 "a hook argument\n", args->argt[i]);
00885 break;
00886 }
00887 }
00888 if (lua_pcall(L, 1, 1, 0) != 0) {
00889 rpmlog(RPMLOG_ERR, _("lua hook failed: %s\n"),
00890 lua_tostring(L, -1));
00891 lua_pop(L, 1);
00892 } else {
00893 if (lua_isnumber(L, -1))
00894 ret = (int)lua_tonumber(L, -1);
00895 lua_pop(L, 1);
00896 }
00897 return ret;
00898 }
00899
00900 static int rpm_register(lua_State *L)
00901
00902
00903 {
00904 if (!lua_isstring(L, 1)) {
00905 (void) luaL_argerror(L, 1, "hook name expected");
00906 } else if (!lua_isfunction(L, 2)) {
00907 (void) luaL_argerror(L, 2, "function expected");
00908 } else {
00909 rpmluaHookData hookdata =
00910 lua_newuserdata(L, sizeof(struct rpmluaHookData_s));
00911 lua_pushvalue(L, -1);
00912 hookdata->dataRef = luaL_ref(L, LUA_REGISTRYINDEX);
00913 lua_pushvalue(L, 2);
00914 hookdata->funcRef = luaL_ref(L, LUA_REGISTRYINDEX);
00915
00916 hookdata->L = L;
00917
00918 rpmhookRegister(lua_tostring(L, 1), rpmluaHookWrapper, hookdata);
00919 return 1;
00920 }
00921 return 0;
00922 }
00923
00924 static int rpm_unregister(lua_State *L)
00925
00926 {
00927 if (!lua_isstring(L, 1)) {
00928 (void) luaL_argerror(L, 1, "hook name expected");
00929 } else if (!lua_islightuserdata(L, 2)) {
00930 (void) luaL_argerror(L, 2, "hook information expected");
00931 } else {
00932 rpmluaHookData hookdata = (rpmluaHookData)lua_touserdata(L, 2);
00933 luaL_unref(L, LUA_REGISTRYINDEX, hookdata->funcRef);
00934 luaL_unref(L, LUA_REGISTRYINDEX, hookdata->dataRef);
00935 rpmhookUnregister(lua_tostring(L, 1), rpmluaHookWrapper, hookdata);
00936 }
00937 return 0;
00938 }
00939
00940 static int rpm_call(lua_State *L)
00941
00942
00943 {
00944 if (!lua_isstring(L, 1)) {
00945 (void) luaL_argerror(L, 1, "hook name expected");
00946 } else {
00947 rpmhookArgs args = rpmhookArgsNew(lua_gettop(L)-1);
00948 const char *name = lua_tostring(L, 1);
00949 char *argt = (char *)xmalloc(args->argc+1);
00950 int i;
00951 for (i = 0; i != args->argc; i++) {
00952 switch (lua_type(L, i+1)) {
00953 case LUA_TNIL:
00954 argt[i] = 'p';
00955 args->argv[i].p = NULL;
00956 break;
00957 case LUA_TNUMBER: {
00958 float f = (float)lua_tonumber(L, i+1);
00959
00960 if (f == (int)f) {
00961 argt[i] = 'i';
00962 args->argv[i].i = (int)f;
00963 } else {
00964 argt[i] = 'f';
00965 args->argv[i].f = f;
00966 }
00967
00968 } break;
00969 case LUA_TSTRING:
00970 argt[i] = 's';
00971 args->argv[i].s = lua_tostring(L, i+1);
00972 break;
00973 case LUA_TUSERDATA:
00974 case LUA_TLIGHTUSERDATA:
00975 argt[i] = 'p';
00976 args->argv[i].p = lua_touserdata(L, i+1);
00977 break;
00978 default:
00979 (void) luaL_error(L, "unsupported Lua type passed to hook");
00980 argt[i] = 'p';
00981 args->argv[i].p = NULL;
00982 break;
00983 }
00984 }
00985
00986 args->argt = argt;
00987 rpmhookCallArgs(name, args);
00988 argt = _free(argt);
00989 (void) rpmhookArgsFree(args);
00990
00991 }
00992 return 0;
00993 }
00994
00995
00996 static int rpm_print (lua_State *L)
00997
00998
00999 {
01000 rpmlua lua = (rpmlua)getdata(L, "lua");
01001 int n = lua_gettop(L);
01002 int i;
01003 if (!lua) return 0;
01004 lua_getglobal(L, "tostring");
01005 for (i = 1; i <= n; i++) {
01006 const char *s;
01007 lua_pushvalue(L, -1);
01008 lua_pushvalue(L, i);
01009 lua_call(L, 1, 1);
01010 s = lua_tostring(L, -1);
01011 if (s == NULL)
01012 return luaL_error(L, "`tostring' must return a string to `print'");
01013 if (lua->storeprint) {
01014 size_t sl = lua_strlen(L, -1);
01015 if ((size_t)(lua->printbufused+sl+1) > lua->printbufsize) {
01016 lua->printbufsize += sl+512;
01017 lua->printbuf = xrealloc(lua->printbuf, lua->printbufsize);
01018 }
01019 if (i > 1)
01020 lua->printbuf[lua->printbufused++] = '\t';
01021 memcpy(lua->printbuf+lua->printbufused, s, sl+1);
01022 lua->printbufused += sl;
01023 } else {
01024 if (i > 1)
01025 (void) fputs("\t", stdout);
01026 (void) fputs(s, stdout);
01027 }
01028 lua_pop(L, 1);
01029 }
01030 if (!lua->storeprint) {
01031 (void) fputs("\n", stdout);
01032 } else {
01033 if ((size_t)(lua->printbufused+1) > lua->printbufsize) {
01034 lua->printbufsize += 512;
01035 lua->printbuf = xrealloc(lua->printbuf, lua->printbufsize);
01036 }
01037 lua->printbuf[lua->printbufused] = '\0';
01038 }
01039 return 0;
01040 }
01041
01042 static int rpm_source(lua_State *L)
01043
01044
01045 {
01046 if (!lua_isstring(L, 1)) {
01047 (void)luaL_argerror(L, 1, "filename expected");
01048 } else {
01049 rpmlua lua = (rpmlua)getdata(L, "lua");
01050 const char *filename = lua_tostring(L, 1);
01051 (void)rpmluaRunScriptFile(lua, filename);
01052 }
01053 return 0;
01054 }
01055
01056 static int rpm_load(lua_State *L)
01057
01058
01059 {
01060 if (!lua_isstring(L, 1)) {
01061 (void)luaL_argerror(L, 1, "filename expected");
01062 } else {
01063 const char *filename = lua_tostring(L, 1);
01064
01065 (void)rpmLoadMacroFile(NULL, filename);
01066
01067 }
01068 return 0;
01069 }
01070
01071 static int rpm_verbose(lua_State *L)
01072
01073
01074 {
01075 lua_pushboolean(L, rpmIsVerbose());
01076 return 1;
01077 }
01078
01079 static int rpm_debug(lua_State *L)
01080
01081
01082 {
01083 lua_pushboolean(L, rpmIsDebug());
01084 return 1;
01085 }
01086
01087 static int rpm_slurp(lua_State *L)
01088
01089
01090 {
01091 rpmiob iob = NULL;
01092 const char *fn;
01093 int rc;
01094
01095 if (lua_isstring(L, 1))
01096 fn = lua_tostring(L, 1);
01097 else {
01098 (void)luaL_argerror(L, 1, "filename");
01099 return 0;
01100 }
01101
01102 rc = rpmiobSlurp(fn, &iob);
01103
01104 if (rc || iob == NULL) {
01105 (void)luaL_error(L, "failed to slurp data");
01106 return 0;
01107 }
01108 lua_pushlstring(L, (const char *)rpmiobStr(iob), rpmiobLen(iob));
01109 iob = rpmiobFree(iob);
01110 return 1;
01111 }
01112
01113 static int rpm_sleep(lua_State *L)
01114
01115
01116 {
01117 unsigned sec;
01118
01119 if (lua_isnumber(L, 1))
01120 sec = (unsigned) lua_tonumber(L, 1);
01121 else {
01122 (void)luaL_argerror(L, 1, "seconds");
01123 return 0;
01124 }
01125 (void) sleep(sec);
01126 return 0;
01127 }
01128
01129 static int rpm_realpath(lua_State *L)
01130
01131
01132 {
01133 const char *pn;
01134 char rp_buf[PATH_MAX];
01135 char *rp = "";
01136
01137 if (lua_isstring(L, 1))
01138 pn = lua_tostring(L, 1);
01139 else {
01140 (void)luaL_argerror(L, 1, "pathname");
01141 return 0;
01142 }
01143 if ((rp = Realpath(pn, rp_buf)) == NULL) {
01144 (void)luaL_error(L, "failed to resolve path via realpath(3): %s", strerror(errno));
01145 return 0;
01146 }
01147 lua_pushstring(L, (const char *)rp);
01148 return 1;
01149 }
01150
01151 static int rpm_hostname(lua_State *L)
01152
01153
01154 {
01155 char hostname[1024];
01156 struct hostent *hbn;
01157 char *h;
01158
01159
01160 (void)gethostname(hostname, sizeof(hostname));
01161 if ((hbn = gethostbyname(hostname)) != NULL)
01162 h = hbn->h_name;
01163 else
01164 h = hostname;
01165
01166 lua_pushstring(L, (const char *)h);
01167 return 1;
01168 }
01169
01170
01171
01172 static const luaL_reg rpmlib[] = {
01173 {"macros", rpm_macros},
01174 {"expand", rpm_expand},
01175 {"define", rpm_define},
01176 {"undefine", rpm_undefine},
01177 {"register", rpm_register},
01178 {"unregister", rpm_unregister},
01179 {"call", rpm_call},
01180 {"interactive", rpm_interactive},
01181 {"source", rpm_source},
01182 {"load", rpm_load},
01183 {"verbose", rpm_verbose},
01184 {"debug", rpm_debug},
01185 {"slurp", rpm_slurp},
01186 {"sleep", rpm_sleep},
01187 {"realpath", rpm_realpath},
01188 {"hostname", rpm_hostname},
01189 {NULL, NULL}
01190 };
01191
01192
01193 static int luaopen_rpm(lua_State *L)
01194
01195 {
01196 lua_pushvalue(L, LUA_GLOBALSINDEX);
01197 luaL_openlib(L, "rpm", rpmlib, 0);
01198 return 0;
01199 }
01200 #endif
01201
01202