1 /* 2 ** $Id: loadlib.c,v 1.52.1.4 2009/09/09 13:17:16 roberto Exp $ 3 ** Dynamic library loader for Lua 4 ** See Copyright Notice in lua.h 5 ** 6 ** This module contains an implementation of loadlib for Unix systems 7 ** that have dlfcn, an implementation for Darwin (Mac OS X), an 8 ** implementation for Windows, and a stub for other systems. 9 */ 10 11 12 #include <stdlib.h> 13 #include <string.h> 14 15 16 #define loadlib_c 17 #define LUA_LIB 18 19 #include "lua.h" 20 21 #include "lauxlib.h" 22 #include "lualib.h" 23 24 25 /* prefix for open functions in C libraries */ 26 #define LUA_POF "luaopen_" 27 28 /* separator for open functions in C libraries */ 29 #define LUA_OFSEP "_" 30 31 32 #define LIBPREFIX "LOADLIB: " 33 34 #define POF LUA_POF 35 #define LIB_FAIL "open" 36 37 38 /* error codes for ll_loadfunc */ 39 #define ERRLIB 1 40 #define ERRFUNC 2 41 42 #define setprogdir(L) ((void)0) 43 44 45 static void ll_unloadlib (void *lib); 46 static void *ll_load (lua_State *L, const char *path); 47 static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); 48 49 50 51 #if defined(LUA_DL_DLOPEN) 52 /* 53 ** {======================================================================== 54 ** This is an implementation of loadlib based on the dlfcn interface. 55 ** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, 56 ** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least 57 ** as an emulation layer on top of native functions. 58 ** ========================================================================= 59 */ 60 61 #include <dlfcn.h> 62 63 static void ll_unloadlib (void *lib) { 64 dlclose(lib); 65 } 66 67 68 static void *ll_load (lua_State *L, const char *path) { 69 void *lib = dlopen(path, RTLD_NOW); 70 if (lib == NULL) lua_pushstring(L, dlerror()); 71 return lib; 72 } 73 74 75 static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { 76 lua_CFunction f = (lua_CFunction)dlsym(lib, sym); 77 if (f == NULL) lua_pushstring(L, dlerror()); 78 return f; 79 } 80 81 /* }====================================================== */ 82 83 84 85 #elif defined(LUA_DL_DLL) 86 /* 87 ** {====================================================================== 88 ** This is an implementation of loadlib for Windows using native functions. 89 ** ======================================================================= 90 */ 91 92 #include <windows.h> 93 94 95 #undef setprogdir 96 97 static void setprogdir (lua_State *L) { 98 char buff[MAX_PATH + 1]; 99 char *lb; 100 DWORD nsize = sizeof(buff)/sizeof(char); 101 DWORD n = GetModuleFileNameA(NULL, buff, nsize); 102 if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) 103 luaL_error(L, "unable to get ModuleFileName"); 104 else { 105 *lb = '\0'; 106 luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff); 107 lua_remove(L, -2); /* remove original string */ 108 } 109 } 110 111 112 static void pusherror (lua_State *L) { 113 int error = GetLastError(); 114 char buffer[128]; 115 if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, 116 NULL, error, 0, buffer, sizeof(buffer), NULL)) 117 lua_pushstring(L, buffer); 118 else 119 lua_pushfstring(L, "system error %d\n", error); 120 } 121 122 static void ll_unloadlib (void *lib) { 123 FreeLibrary((HINSTANCE)lib); 124 } 125 126 127 static void *ll_load (lua_State *L, const char *path) { 128 HINSTANCE lib = LoadLibraryA(path); 129 if (lib == NULL) pusherror(L); 130 return lib; 131 } 132 133 134 static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { 135 lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym); 136 if (f == NULL) pusherror(L); 137 return f; 138 } 139 140 /* }====================================================== */ 141 142 143 144 #elif defined(LUA_DL_DYLD) 145 /* 146 ** {====================================================================== 147 ** Native Mac OS X / Darwin Implementation 148 ** ======================================================================= 149 */ 150 151 #include <mach-o/dyld.h> 152 153 154 /* Mac appends a `_' before C function names */ 155 #undef POF 156 #define POF "_" LUA_POF 157 158 159 static void pusherror (lua_State *L) { 160 const char *err_str; 161 const char *err_file; 162 NSLinkEditErrors err; 163 int err_num; 164 NSLinkEditError(&err, &err_num, &err_file, &err_str); 165 lua_pushstring(L, err_str); 166 } 167 168 169 static const char *errorfromcode (NSObjectFileImageReturnCode ret) { 170 switch (ret) { 171 case NSObjectFileImageInappropriateFile: 172 return "file is not a bundle"; 173 case NSObjectFileImageArch: 174 return "library is for wrong CPU type"; 175 case NSObjectFileImageFormat: 176 return "bad format"; 177 case NSObjectFileImageAccess: 178 return "cannot access file"; 179 case NSObjectFileImageFailure: 180 default: 181 return "unable to load library"; 182 } 183 } 184 185 186 static void ll_unloadlib (void *lib) { 187 NSUnLinkModule((NSModule)lib, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES); 188 } 189 190 191 static void *ll_load (lua_State *L, const char *path) { 192 NSObjectFileImage img; 193 NSObjectFileImageReturnCode ret; 194 /* this would be a rare case, but prevents crashing if it happens */ 195 if(!_dyld_present()) { 196 lua_pushliteral(L, "dyld not present"); 197 return NULL; 198 } 199 ret = NSCreateObjectFileImageFromFile(path, &img); 200 if (ret == NSObjectFileImageSuccess) { 201 NSModule mod = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE | 202 NSLINKMODULE_OPTION_RETURN_ON_ERROR); 203 NSDestroyObjectFileImage(img); 204 if (mod == NULL) pusherror(L); 205 return mod; 206 } 207 lua_pushstring(L, errorfromcode(ret)); 208 return NULL; 209 } 210 211 212 static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { 213 NSSymbol nss = NSLookupSymbolInModule((NSModule)lib, sym); 214 if (nss == NULL) { 215 lua_pushfstring(L, "symbol " LUA_QS " not found", sym); 216 return NULL; 217 } 218 return (lua_CFunction)NSAddressOfSymbol(nss); 219 } 220 221 /* }====================================================== */ 222 223 224 225 #else 226 /* 227 ** {====================================================== 228 ** Fallback for other systems 229 ** ======================================================= 230 */ 231 232 #undef LIB_FAIL 233 #define LIB_FAIL "absent" 234 235 236 #define DLMSG "dynamic libraries not enabled; check your Lua installation" 237 238 239 static void ll_unloadlib (void *lib) { 240 (void)lib; /* to avoid warnings */ 241 } 242 243 244 static void *ll_load (lua_State *L, const char *path) { 245 (void)path; /* to avoid warnings */ 246 lua_pushliteral(L, DLMSG); 247 return NULL; 248 } 249 250 251 static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { 252 (void)lib; (void)sym; /* to avoid warnings */ 253 lua_pushliteral(L, DLMSG); 254 return NULL; 255 } 256 257 /* }====================================================== */ 258 #endif 259 260 261 262 static void **ll_register (lua_State *L, const char *path) { 263 void **plib; 264 lua_pushfstring(L, "%s%s", LIBPREFIX, path); 265 lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */ 266 if (!lua_isnil(L, -1)) /* is there an entry? */ 267 plib = (void **)lua_touserdata(L, -1); 268 else { /* no entry yet; create one */ 269 lua_pop(L, 1); 270 plib = (void **)lua_newuserdata(L, sizeof(const void *)); 271 *plib = NULL; 272 luaL_getmetatable(L, "_LOADLIB"); 273 lua_setmetatable(L, -2); 274 lua_pushfstring(L, "%s%s", LIBPREFIX, path); 275 lua_pushvalue(L, -2); 276 lua_settable(L, LUA_REGISTRYINDEX); 277 } 278 return plib; 279 } 280 281 282 /* 283 ** __gc tag method: calls library's `ll_unloadlib' function with the lib 284 ** handle 285 */ 286 static int gctm (lua_State *L) { 287 void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB"); 288 if (*lib) ll_unloadlib(*lib); 289 *lib = NULL; /* mark library as closed */ 290 return 0; 291 } 292 293 294 static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { 295 void **reg = ll_register(L, path); 296 if (*reg == NULL) *reg = ll_load(L, path); 297 if (*reg == NULL) 298 return ERRLIB; /* unable to load library */ 299 else { 300 lua_CFunction f = ll_sym(L, *reg, sym); 301 if (f == NULL) 302 return ERRFUNC; /* unable to find function */ 303 lua_pushcfunction(L, f); 304 return 0; /* return function */ 305 } 306 } 307 308 309 static int ll_loadlib (lua_State *L) { 310 const char *path = luaL_checkstring(L, 1); 311 const char *init = luaL_checkstring(L, 2); 312 int stat = ll_loadfunc(L, path, init); 313 if (stat == 0) /* no errors? */ 314 return 1; /* return the loaded function */ 315 else { /* error; error message is on stack top */ 316 lua_pushnil(L); 317 lua_insert(L, -2); 318 lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); 319 return 3; /* return nil, error message, and where */ 320 } 321 } 322 323 324 325 /* 326 ** {====================================================== 327 ** 'require' function 328 ** ======================================================= 329 */ 330 331 332 static int readable (const char *filename) { 333 FILE *f = fopen(filename, "r"); /* try to open file */ 334 if (f == NULL) return 0; /* open failed */ 335 fclose(f); 336 return 1; 337 } 338 339 340 static const char *pushnexttemplate (lua_State *L, const char *path) { 341 const char *l; 342 while (*path == *LUA_PATHSEP) path++; /* skip separators */ 343 if (*path == '\0') return NULL; /* no more templates */ 344 l = strchr(path, *LUA_PATHSEP); /* find next separator */ 345 if (l == NULL) l = path + strlen(path); 346 lua_pushlstring(L, path, l - path); /* template */ 347 return l; 348 } 349 350 351 static const char *findfile (lua_State *L, const char *name, 352 const char *pname) { 353 const char *path; 354 name = luaL_gsub(L, name, ".", LUA_DIRSEP); 355 lua_getfield(L, LUA_ENVIRONINDEX, pname); 356 path = lua_tostring(L, -1); 357 if (path == NULL) 358 luaL_error(L, LUA_QL("package.%s") " must be a string", pname); 359 lua_pushliteral(L, ""); /* error accumulator */ 360 while ((path = pushnexttemplate(L, path)) != NULL) { 361 const char *filename; 362 filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); 363 lua_remove(L, -2); /* remove path template */ 364 if (readable(filename)) /* does file exist and is readable? */ 365 return filename; /* return that file name */ 366 lua_pushfstring(L, "\n\tno file " LUA_QS, filename); 367 lua_remove(L, -2); /* remove file name */ 368 lua_concat(L, 2); /* add entry to possible error message */ 369 } 370 return NULL; /* not found */ 371 } 372 373 374 static void loaderror (lua_State *L, const char *filename) { 375 luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s", 376 lua_tostring(L, 1), filename, lua_tostring(L, -1)); 377 } 378 379 380 static int loader_Lua (lua_State *L) { 381 const char *filename; 382 const char *name = luaL_checkstring(L, 1); 383 filename = findfile(L, name, "path"); 384 if (filename == NULL) return 1; /* library not found in this path */ 385 if (luaL_loadfile(L, filename) != 0) 386 loaderror(L, filename); 387 return 1; /* library loaded successfully */ 388 } 389 390 391 static const char *mkfuncname (lua_State *L, const char *modname) { 392 const char *funcname; 393 const char *mark = strchr(modname, *LUA_IGMARK); 394 if (mark) modname = mark + 1; 395 funcname = luaL_gsub(L, modname, ".", LUA_OFSEP); 396 funcname = lua_pushfstring(L, POF"%s", funcname); 397 lua_remove(L, -2); /* remove 'gsub' result */ 398 return funcname; 399 } 400 401 402 static int loader_C (lua_State *L) { 403 const char *funcname; 404 const char *name = luaL_checkstring(L, 1); 405 const char *filename = findfile(L, name, "cpath"); 406 if (filename == NULL) return 1; /* library not found in this path */ 407 funcname = mkfuncname(L, name); 408 if (ll_loadfunc(L, filename, funcname) != 0) 409 loaderror(L, filename); 410 return 1; /* library loaded successfully */ 411 } 412 413 414 static int loader_Croot (lua_State *L) { 415 const char *funcname; 416 const char *filename; 417 const char *name = luaL_checkstring(L, 1); 418 const char *p = strchr(name, '.'); 419 int stat; 420 if (p == NULL) return 0; /* is root */ 421 lua_pushlstring(L, name, p - name); 422 filename = findfile(L, lua_tostring(L, -1), "cpath"); 423 if (filename == NULL) return 1; /* root not found */ 424 funcname = mkfuncname(L, name); 425 if ((stat = ll_loadfunc(L, filename, funcname)) != 0) { 426 if (stat != ERRFUNC) loaderror(L, filename); /* real error */ 427 lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, 428 name, filename); 429 return 1; /* function not found */ 430 } 431 return 1; 432 } 433 434 435 static int loader_preload (lua_State *L) { 436 const char *name = luaL_checkstring(L, 1); 437 lua_getfield(L, LUA_ENVIRONINDEX, "preload"); 438 if (!lua_istable(L, -1)) 439 luaL_error(L, LUA_QL("package.preload") " must be a table"); 440 lua_getfield(L, -1, name); 441 if (lua_isnil(L, -1)) /* not found? */ 442 lua_pushfstring(L, "\n\tno field package.preload['%s']", name); 443 return 1; 444 } 445 446 447 static const int sentinel_ = 0; 448 #define sentinel ((void *)&sentinel_) 449 450 451 static int ll_require (lua_State *L) { 452 const char *name = luaL_checkstring(L, 1); 453 int i; 454 lua_settop(L, 1); /* _LOADED table will be at index 2 */ 455 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); 456 lua_getfield(L, 2, name); 457 if (lua_toboolean(L, -1)) { /* is it there? */ 458 if (lua_touserdata(L, -1) == sentinel) /* check loops */ 459 luaL_error(L, "loop or previous error loading module " LUA_QS, name); 460 return 1; /* package is already loaded */ 461 } 462 /* else must load it; iterate over available loaders */ 463 lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); 464 if (!lua_istable(L, -1)) 465 luaL_error(L, LUA_QL("package.loaders") " must be a table"); 466 lua_pushliteral(L, ""); /* error message accumulator */ 467 for (i=1; ; i++) { 468 lua_rawgeti(L, -2, i); /* get a loader */ 469 if (lua_isnil(L, -1)) 470 luaL_error(L, "module " LUA_QS " not found:%s", 471 name, lua_tostring(L, -2)); 472 lua_pushstring(L, name); 473 lua_call(L, 1, 1); /* call it */ 474 if (lua_isfunction(L, -1)) /* did it find module? */ 475 break; /* module loaded successfully */ 476 else if (lua_isstring(L, -1)) /* loader returned error message? */ 477 lua_concat(L, 2); /* accumulate it */ 478 else 479 lua_pop(L, 1); 480 } 481 lua_pushlightuserdata(L, sentinel); 482 lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */ 483 lua_pushstring(L, name); /* pass name as argument to module */ 484 lua_call(L, 1, 1); /* run loaded module */ 485 if (!lua_isnil(L, -1)) /* non-nil return? */ 486 lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ 487 lua_getfield(L, 2, name); 488 if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */ 489 lua_pushboolean(L, 1); /* use true as result */ 490 lua_pushvalue(L, -1); /* extra copy to be returned */ 491 lua_setfield(L, 2, name); /* _LOADED[name] = true */ 492 } 493 return 1; 494 } 495 496 /* }====================================================== */ 497 498 499 500 /* 501 ** {====================================================== 502 ** 'module' function 503 ** ======================================================= 504 */ 505 506 507 static void setfenv (lua_State *L) { 508 lua_Debug ar; 509 if (lua_getstack(L, 1, &ar) == 0 || 510 lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ 511 lua_iscfunction(L, -1)) 512 luaL_error(L, LUA_QL("module") " not called from a Lua function"); 513 lua_pushvalue(L, -2); 514 lua_setfenv(L, -2); 515 lua_pop(L, 1); 516 } 517 518 519 static void dooptions (lua_State *L, int n) { 520 int i; 521 for (i = 2; i <= n; i++) { 522 lua_pushvalue(L, i); /* get option (a function) */ 523 lua_pushvalue(L, -2); /* module */ 524 lua_call(L, 1, 0); 525 } 526 } 527 528 529 static void modinit (lua_State *L, const char *modname) { 530 const char *dot; 531 lua_pushvalue(L, -1); 532 lua_setfield(L, -2, "_M"); /* module._M = module */ 533 lua_pushstring(L, modname); 534 lua_setfield(L, -2, "_NAME"); 535 dot = strrchr(modname, '.'); /* look for last dot in module name */ 536 if (dot == NULL) dot = modname; 537 else dot++; 538 /* set _PACKAGE as package name (full module name minus last part) */ 539 lua_pushlstring(L, modname, dot - modname); 540 lua_setfield(L, -2, "_PACKAGE"); 541 } 542 543 544 static int ll_module (lua_State *L) { 545 const char *modname = luaL_checkstring(L, 1); 546 int loaded = lua_gettop(L) + 1; /* index of _LOADED table */ 547 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); 548 lua_getfield(L, loaded, modname); /* get _LOADED[modname] */ 549 if (!lua_istable(L, -1)) { /* not found? */ 550 lua_pop(L, 1); /* remove previous result */ 551 /* try global variable (and create one if it does not exist) */ 552 if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL) 553 return luaL_error(L, "name conflict for module " LUA_QS, modname); 554 lua_pushvalue(L, -1); 555 lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */ 556 } 557 /* check whether table already has a _NAME field */ 558 lua_getfield(L, -1, "_NAME"); 559 if (!lua_isnil(L, -1)) /* is table an initialized module? */ 560 lua_pop(L, 1); 561 else { /* no; initialize it */ 562 lua_pop(L, 1); 563 modinit(L, modname); 564 } 565 lua_pushvalue(L, -1); 566 setfenv(L); 567 dooptions(L, loaded - 1); 568 return 0; 569 } 570 571 572 static int ll_seeall (lua_State *L) { 573 luaL_checktype(L, 1, LUA_TTABLE); 574 if (!lua_getmetatable(L, 1)) { 575 lua_createtable(L, 0, 1); /* create new metatable */ 576 lua_pushvalue(L, -1); 577 lua_setmetatable(L, 1); 578 } 579 lua_pushvalue(L, LUA_GLOBALSINDEX); 580 lua_setfield(L, -2, "__index"); /* mt.__index = _G */ 581 return 0; 582 } 583 584 585 /* }====================================================== */ 586 587 588 589 /* auxiliary mark (for internal use) */ 590 #define AUXMARK "\1" 591 592 static void setpath (lua_State *L, const char *fieldname, const char *envname, 593 const char *def) { 594 const char *path = getenv(envname); 595 if (path == NULL) /* no environment variable? */ 596 lua_pushstring(L, def); /* use default */ 597 else { 598 /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ 599 path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP, 600 LUA_PATHSEP AUXMARK LUA_PATHSEP); 601 luaL_gsub(L, path, AUXMARK, def); 602 lua_remove(L, -2); 603 } 604 setprogdir(L); 605 lua_setfield(L, -2, fieldname); 606 } 607 608 609 static const luaL_Reg pk_funcs[] = { 610 {"loadlib", ll_loadlib}, 611 {"seeall", ll_seeall}, 612 {NULL, NULL} 613 }; 614 615 616 static const luaL_Reg ll_funcs[] = { 617 {"module", ll_module}, 618 {"require", ll_require}, 619 {NULL, NULL} 620 }; 621 622 623 static const lua_CFunction loaders[] = 624 {loader_preload, loader_Lua, loader_C, loader_Croot, NULL}; 625 626 627 LUALIB_API int luaopen_package (lua_State *L) { 628 int i; 629 /* create new type _LOADLIB */ 630 luaL_newmetatable(L, "_LOADLIB"); 631 lua_pushcfunction(L, gctm); 632 lua_setfield(L, -2, "__gc"); 633 /* create `package' table */ 634 luaL_register(L, LUA_LOADLIBNAME, pk_funcs); 635 #if defined(LUA_COMPAT_LOADLIB) 636 lua_getfield(L, -1, "loadlib"); 637 lua_setfield(L, LUA_GLOBALSINDEX, "loadlib"); 638 #endif 639 lua_pushvalue(L, -1); 640 lua_replace(L, LUA_ENVIRONINDEX); 641 /* create `loaders' table */ 642 lua_createtable(L, sizeof(loaders)/sizeof(loaders[0]) - 1, 0); 643 /* fill it with pre-defined loaders */ 644 for (i=0; loaders[i] != NULL; i++) { 645 lua_pushcfunction(L, loaders[i]); 646 lua_rawseti(L, -2, i+1); 647 } 648 lua_setfield(L, -2, "loaders"); /* put it in field `loaders' */ 649 setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT); /* set field `path' */ 650 setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */ 651 /* store config information */ 652 lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" 653 LUA_EXECDIR "\n" LUA_IGMARK); 654 lua_setfield(L, -2, "config"); 655 /* set field `loaded' */ 656 luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2); 657 lua_setfield(L, -2, "loaded"); 658 /* set field `preload' */ 659 lua_newtable(L); 660 lua_setfield(L, -2, "preload"); 661 lua_pushvalue(L, LUA_GLOBALSINDEX); 662 luaL_register(L, NULL, ll_funcs); /* open lib into global table */ 663 lua_pop(L, 1); 664 return 1; /* return 'package' table */ 665 } 666 667