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