Home | History | Annotate | Download | only in src
      1 /*
      2 ** $Id: loadlib.c,v 1.111.1.1 2013/04/12 18:48:47 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 Windows, and a stub for other
      8 ** systems.
      9 */
     10 
     11 
     12 /*
     13 ** if needed, includes windows header before everything else
     14 */
     15 #if defined(_WIN32)
     16 #include <windows.h>
     17 #endif
     18 
     19 /* Base the Lua paths on the Syslinux path */
     20 #ifdef SYSLINUX
     21 #include <fs.h>
     22 #endif
     23 
     24 #include <stdlib.h>
     25 #include <string.h>
     26 
     27 
     28 #define loadlib_c
     29 #define LUA_LIB
     30 
     31 #include "lua.h"
     32 
     33 #include "lauxlib.h"
     34 #include "lualib.h"
     35 
     36 
     37 /*
     38 ** LUA_PATH and LUA_CPATH are the names of the environment
     39 ** variables that Lua check to set its paths.
     40 */
     41 #if !defined(LUA_PATH)
     42 #define LUA_PATH	"LUA_PATH"
     43 #endif
     44 
     45 #if !defined(LUA_CPATH)
     46 #define LUA_CPATH	"LUA_CPATH"
     47 #endif
     48 
     49 #define LUA_PATHSUFFIX		"_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
     50 
     51 #define LUA_PATHVERSION		LUA_PATH LUA_PATHSUFFIX
     52 #define LUA_CPATHVERSION	LUA_CPATH LUA_PATHSUFFIX
     53 
     54 /*
     55 ** LUA_PATH_SEP is the character that separates templates in a path.
     56 ** LUA_PATH_MARK is the string that marks the substitution points in a
     57 ** template.
     58 ** LUA_EXEC_DIR in a Windows path is replaced by the executable's
     59 ** directory.
     60 ** LUA_IGMARK is a mark to ignore all before it when building the
     61 ** luaopen_ function name.
     62 */
     63 #if !defined (LUA_PATH_SEP)
     64 #define LUA_PATH_SEP		";"
     65 #endif
     66 #if !defined (LUA_PATH_MARK)
     67 #define LUA_PATH_MARK		"?"
     68 #endif
     69 #if !defined (LUA_EXEC_DIR)
     70 #define LUA_EXEC_DIR		"!"
     71 #endif
     72 #if !defined (LUA_IGMARK)
     73 #define LUA_IGMARK		"-"
     74 #endif
     75 
     76 
     77 /*
     78 ** LUA_CSUBSEP is the character that replaces dots in submodule names
     79 ** when searching for a C loader.
     80 ** LUA_LSUBSEP is the character that replaces dots in submodule names
     81 ** when searching for a Lua loader.
     82 */
     83 #if !defined(LUA_CSUBSEP)
     84 #define LUA_CSUBSEP		LUA_DIRSEP
     85 #endif
     86 
     87 #if !defined(LUA_LSUBSEP)
     88 #define LUA_LSUBSEP		LUA_DIRSEP
     89 #endif
     90 
     91 
     92 /* prefix for open functions in C libraries */
     93 #define LUA_POF		"luaopen_"
     94 
     95 /* separator for open functions in C libraries */
     96 #define LUA_OFSEP	"_"
     97 
     98 
     99 /* table (in the registry) that keeps handles for all loaded C libraries */
    100 #define CLIBS		"_CLIBS"
    101 
    102 #define LIB_FAIL	"open"
    103 
    104 
    105 /* error codes for ll_loadfunc */
    106 #define ERRLIB		1
    107 #define ERRFUNC		2
    108 
    109 #define setprogdir(L)		((void)0)
    110 
    111 
    112 /*
    113 ** system-dependent functions
    114 */
    115 static void ll_unloadlib (void *lib);
    116 static void *ll_load (lua_State *L, const char *path, int seeglb);
    117 static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym);
    118 
    119 
    120 
    121 #if defined(LUA_USE_DLOPEN)
    122 /*
    123 ** {========================================================================
    124 ** This is an implementation of loadlib based on the dlfcn interface.
    125 ** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
    126 ** NetBSD, AIX 4.2, HPUX 11, and  probably most other Unix flavors, at least
    127 ** as an emulation layer on top of native functions.
    128 ** =========================================================================
    129 */
    130 
    131 #include <dlfcn.h>
    132 
    133 static void ll_unloadlib (void *lib) {
    134   dlclose(lib);
    135 }
    136 
    137 
    138 static void *ll_load (lua_State *L, const char *path, int seeglb) {
    139   void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL));
    140   if (lib == NULL) lua_pushstring(L, dlerror());
    141   return lib;
    142 }
    143 
    144 
    145 static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
    146   lua_CFunction f = (lua_CFunction)dlsym(lib, sym);
    147   if (f == NULL) lua_pushstring(L, dlerror());
    148   return f;
    149 }
    150 
    151 /* }====================================================== */
    152 
    153 
    154 
    155 #elif defined(LUA_DL_DLL)
    156 /*
    157 ** {======================================================================
    158 ** This is an implementation of loadlib for Windows using native functions.
    159 ** =======================================================================
    160 */
    161 
    162 #undef setprogdir
    163 
    164 /*
    165 ** optional flags for LoadLibraryEx
    166 */
    167 #if !defined(LUA_LLE_FLAGS)
    168 #define LUA_LLE_FLAGS	0
    169 #endif
    170 
    171 
    172 static void setprogdir (lua_State *L) {
    173   char buff[MAX_PATH + 1];
    174   char *lb;
    175   DWORD nsize = sizeof(buff)/sizeof(char);
    176   DWORD n = GetModuleFileNameA(NULL, buff, nsize);
    177   if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL)
    178     luaL_error(L, "unable to get ModuleFileName");
    179   else {
    180     *lb = '\0';
    181     luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff);
    182     lua_remove(L, -2);  /* remove original string */
    183   }
    184 }
    185 
    186 
    187 static void pusherror (lua_State *L) {
    188   int error = GetLastError();
    189   char buffer[128];
    190   if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
    191       NULL, error, 0, buffer, sizeof(buffer)/sizeof(char), NULL))
    192     lua_pushstring(L, buffer);
    193   else
    194     lua_pushfstring(L, "system error %d\n", error);
    195 }
    196 
    197 static void ll_unloadlib (void *lib) {
    198   FreeLibrary((HMODULE)lib);
    199 }
    200 
    201 
    202 static void *ll_load (lua_State *L, const char *path, int seeglb) {
    203   HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS);
    204   (void)(seeglb);  /* not used: symbols are 'global' by default */
    205   if (lib == NULL) pusherror(L);
    206   return lib;
    207 }
    208 
    209 
    210 static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
    211   lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym);
    212   if (f == NULL) pusherror(L);
    213   return f;
    214 }
    215 
    216 /* }====================================================== */
    217 
    218 
    219 #elif defined(SYSLINUX)
    220 /*
    221 ** {=========================================================================
    222 ** This is an implementation of loadlib for the Syslinux COM32 module system.
    223 ** ==========================================================================
    224 */
    225 
    226 #include <sys/module.h>
    227 
    228 static void ll_unloadlib (void *lib) {
    229   module_unload ((struct elf_module *)lib);
    230 }
    231 
    232 
    233 static void *ll_load (lua_State *L, const char *path, int seeglb) {
    234   int err;
    235   struct elf_module *lib = module_alloc (path);
    236   if (lib == NULL) {
    237     lua_pushstring (L, "module not found");
    238     return NULL;
    239   }
    240   (void)seeglb; /* gcc, ignore it */
    241   err = module_load (lib);
    242   if (err) {
    243     printf ("module load error: %d\n", err);
    244     lua_pushstring (L, "failed to load module");
    245     return NULL;
    246   }
    247   return (void *)lib;
    248 }
    249 
    250 
    251 static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
    252   Elf_Sym *p = module_find_symbol (sym, (struct elf_module *)lib);
    253   if (p == NULL) {
    254     lua_pushstring (L, "symbol not found in module");
    255     return NULL;
    256   }
    257   return (lua_CFunction)module_get_absolute(p->st_value, (struct elf_module *)lib);
    258 }
    259 
    260 /* }====================================================== */
    261 
    262 
    263 
    264 #else
    265 /*
    266 ** {======================================================
    267 ** Fallback for other systems
    268 ** =======================================================
    269 */
    270 
    271 #undef LIB_FAIL
    272 #define LIB_FAIL	"absent"
    273 
    274 
    275 #define DLMSG	"dynamic libraries not enabled; check your Lua installation"
    276 
    277 
    278 static void ll_unloadlib (void *lib) {
    279   (void)(lib);  /* not used */
    280 }
    281 
    282 
    283 static void *ll_load (lua_State *L, const char *path, int seeglb) {
    284   (void)(path); (void)(seeglb);  /* not used */
    285   lua_pushliteral(L, DLMSG);
    286   return NULL;
    287 }
    288 
    289 
    290 static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
    291   (void)(lib); (void)(sym);  /* not used */
    292   lua_pushliteral(L, DLMSG);
    293   return NULL;
    294 }
    295 
    296 /* }====================================================== */
    297 #endif
    298 
    299 
    300 static void *ll_checkclib (lua_State *L, const char *path) {
    301   void *plib;
    302   lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
    303   lua_getfield(L, -1, path);
    304   plib = lua_touserdata(L, -1);  /* plib = CLIBS[path] */
    305   lua_pop(L, 2);  /* pop CLIBS table and 'plib' */
    306   return plib;
    307 }
    308 
    309 
    310 static void ll_addtoclib (lua_State *L, const char *path, void *plib) {
    311   lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
    312   lua_pushlightuserdata(L, plib);
    313   lua_pushvalue(L, -1);
    314   lua_setfield(L, -3, path);  /* CLIBS[path] = plib */
    315   lua_rawseti(L, -2, luaL_len(L, -2) + 1);  /* CLIBS[#CLIBS + 1] = plib */
    316   lua_pop(L, 1);  /* pop CLIBS table */
    317 }
    318 
    319 
    320 /*
    321 ** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib
    322 ** handles in list CLIBS
    323 */
    324 static int gctm (lua_State *L) {
    325   int n = luaL_len(L, 1);
    326   for (; n >= 1; n--) {  /* for each handle, in reverse order */
    327     lua_rawgeti(L, 1, n);  /* get handle CLIBS[n] */
    328     ll_unloadlib(lua_touserdata(L, -1));
    329     lua_pop(L, 1);  /* pop handle */
    330   }
    331   return 0;
    332 }
    333 
    334 
    335 static int ll_loadfunc (lua_State *L, const char *path, const char *sym) {
    336   void *reg = ll_checkclib(L, path);  /* check loaded C libraries */
    337   if (reg == NULL) {  /* must load library? */
    338     reg = ll_load(L, path, *sym == '*');
    339     if (reg == NULL) return ERRLIB;  /* unable to load library */
    340     ll_addtoclib(L, path, reg);
    341   }
    342   if (*sym == '*') {  /* loading only library (no function)? */
    343     lua_pushboolean(L, 1);  /* return 'true' */
    344     return 0;  /* no errors */
    345   }
    346   else {
    347     lua_CFunction f = ll_sym(L, reg, sym);
    348     if (f == NULL)
    349       return ERRFUNC;  /* unable to find function */
    350     lua_pushcfunction(L, f);  /* else create new function */
    351     return 0;  /* no errors */
    352   }
    353 }
    354 
    355 
    356 static int ll_loadlib (lua_State *L) {
    357   const char *path = luaL_checkstring(L, 1);
    358   const char *init = luaL_checkstring(L, 2);
    359   int stat = ll_loadfunc(L, path, init);
    360   if (stat == 0)  /* no errors? */
    361     return 1;  /* return the loaded function */
    362   else {  /* error; error message is on stack top */
    363     lua_pushnil(L);
    364     lua_insert(L, -2);
    365     lua_pushstring(L, (stat == ERRLIB) ?  LIB_FAIL : "init");
    366     return 3;  /* return nil, error message, and where */
    367   }
    368 }
    369 
    370 
    371 
    372 /*
    373 ** {======================================================
    374 ** 'require' function
    375 ** =======================================================
    376 */
    377 
    378 
    379 static int readable (const char *filename) {
    380   FILE *f = fopen(filename, "r");  /* try to open file */
    381   if (f == NULL) return 0;  /* open failed */
    382   fclose(f);
    383   return 1;
    384 }
    385 
    386 
    387 static const char *pushnexttemplate (lua_State *L, const char *path) {
    388   const char *l;
    389   while (*path == *LUA_PATH_SEP) path++;  /* skip separators */
    390   if (*path == '\0') return NULL;  /* no more templates */
    391   l = strchr(path, *LUA_PATH_SEP);  /* find next separator */
    392   if (l == NULL) l = path + strlen(path);
    393   lua_pushlstring(L, path, l - path);  /* template */
    394   return l;
    395 }
    396 
    397 
    398 static const char *searchpath (lua_State *L, const char *name,
    399                                              const char *path,
    400                                              const char *sep,
    401                                              const char *dirsep) {
    402   luaL_Buffer msg;  /* to build error message */
    403   luaL_buffinit(L, &msg);
    404   if (*sep != '\0')  /* non-empty separator? */
    405     name = luaL_gsub(L, name, sep, dirsep);  /* replace it by 'dirsep' */
    406   while ((path = pushnexttemplate(L, path)) != NULL) {
    407     const char *filename = luaL_gsub(L, lua_tostring(L, -1),
    408                                      LUA_PATH_MARK, name);
    409     lua_remove(L, -2);  /* remove path template */
    410     if (readable(filename))  /* does file exist and is readable? */
    411       return filename;  /* return that file name */
    412     lua_pushfstring(L, "\n\tno file " LUA_QS, filename);
    413     lua_remove(L, -2);  /* remove file name */
    414     luaL_addvalue(&msg);  /* concatenate error msg. entry */
    415   }
    416   luaL_pushresult(&msg);  /* create error message */
    417   return NULL;  /* not found */
    418 }
    419 
    420 
    421 static int ll_searchpath (lua_State *L) {
    422   const char *f = searchpath(L, luaL_checkstring(L, 1),
    423                                 luaL_checkstring(L, 2),
    424                                 luaL_optstring(L, 3, "."),
    425                                 luaL_optstring(L, 4, LUA_DIRSEP));
    426   if (f != NULL) return 1;
    427   else {  /* error message is on top of the stack */
    428     lua_pushnil(L);
    429     lua_insert(L, -2);
    430     return 2;  /* return nil + error message */
    431   }
    432 }
    433 
    434 
    435 static const char *findfile (lua_State *L, const char *name,
    436                                            const char *pname,
    437                                            const char *dirsep) {
    438   const char *path;
    439   lua_getfield(L, lua_upvalueindex(1), pname);
    440   path = lua_tostring(L, -1);
    441   if (path == NULL)
    442     luaL_error(L, LUA_QL("package.%s") " must be a string", pname);
    443   return searchpath(L, name, path, ".", dirsep);
    444 }
    445 
    446 
    447 static int checkload (lua_State *L, int stat, const char *filename) {
    448   if (stat) {  /* module loaded successfully? */
    449     lua_pushstring(L, filename);  /* will be 2nd argument to module */
    450     return 2;  /* return open function and file name */
    451   }
    452   else
    453     return luaL_error(L, "error loading module " LUA_QS
    454                          " from file " LUA_QS ":\n\t%s",
    455                           lua_tostring(L, 1), filename, lua_tostring(L, -1));
    456 }
    457 
    458 
    459 static int searcher_Lua (lua_State *L) {
    460   const char *filename;
    461   const char *name = luaL_checkstring(L, 1);
    462   filename = findfile(L, name, "path", LUA_LSUBSEP);
    463   if (filename == NULL) return 1;  /* module not found in this path */
    464   return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename);
    465 }
    466 
    467 
    468 static int loadfunc (lua_State *L, const char *filename, const char *modname) {
    469   const char *funcname;
    470   const char *mark;
    471   modname = luaL_gsub(L, modname, ".", LUA_OFSEP);
    472   mark = strchr(modname, *LUA_IGMARK);
    473   if (mark) {
    474     int stat;
    475     funcname = lua_pushlstring(L, modname, mark - modname);
    476     funcname = lua_pushfstring(L, LUA_POF"%s", funcname);
    477     stat = ll_loadfunc(L, filename, funcname);
    478     if (stat != ERRFUNC) return stat;
    479     modname = mark + 1;  /* else go ahead and try old-style name */
    480   }
    481   funcname = lua_pushfstring(L, LUA_POF"%s", modname);
    482   return ll_loadfunc(L, filename, funcname);
    483 }
    484 
    485 
    486 static int searcher_C (lua_State *L) {
    487   const char *name = luaL_checkstring(L, 1);
    488   const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP);
    489   if (filename == NULL) return 1;  /* module not found in this path */
    490   return checkload(L, (loadfunc(L, filename, name) == 0), filename);
    491 }
    492 
    493 
    494 static int searcher_Croot (lua_State *L) {
    495   const char *filename;
    496   const char *name = luaL_checkstring(L, 1);
    497   const char *p = strchr(name, '.');
    498   int stat;
    499   if (p == NULL) return 0;  /* is root */
    500   lua_pushlstring(L, name, p - name);
    501   filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP);
    502   if (filename == NULL) return 1;  /* root not found */
    503   if ((stat = loadfunc(L, filename, name)) != 0) {
    504     if (stat != ERRFUNC)
    505       return checkload(L, 0, filename);  /* real error */
    506     else {  /* open function not found */
    507       lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS,
    508                          name, filename);
    509       return 1;
    510     }
    511   }
    512   lua_pushstring(L, filename);  /* will be 2nd argument to module */
    513   return 2;
    514 }
    515 
    516 
    517 static int searcher_preload (lua_State *L) {
    518   const char *name = luaL_checkstring(L, 1);
    519   lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD");
    520   lua_getfield(L, -1, name);
    521   if (lua_isnil(L, -1))  /* not found? */
    522     lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
    523   return 1;
    524 }
    525 
    526 
    527 static void findloader (lua_State *L, const char *name) {
    528   int i;
    529   luaL_Buffer msg;  /* to build error message */
    530   luaL_buffinit(L, &msg);
    531   lua_getfield(L, lua_upvalueindex(1), "searchers");  /* will be at index 3 */
    532   if (!lua_istable(L, 3))
    533     luaL_error(L, LUA_QL("package.searchers") " must be a table");
    534   /*  iterate over available searchers to find a loader */
    535   for (i = 1; ; i++) {
    536     lua_rawgeti(L, 3, i);  /* get a searcher */
    537     if (lua_isnil(L, -1)) {  /* no more searchers? */
    538       lua_pop(L, 1);  /* remove nil */
    539       luaL_pushresult(&msg);  /* create error message */
    540       luaL_error(L, "module " LUA_QS " not found:%s",
    541                     name, lua_tostring(L, -1));
    542     }
    543     lua_pushstring(L, name);
    544     lua_call(L, 1, 2);  /* call it */
    545     if (lua_isfunction(L, -2))  /* did it find a loader? */
    546       return;  /* module loader found */
    547     else if (lua_isstring(L, -2)) {  /* searcher returned error message? */
    548       lua_pop(L, 1);  /* remove extra return */
    549       luaL_addvalue(&msg);  /* concatenate error message */
    550     }
    551     else
    552       lua_pop(L, 2);  /* remove both returns */
    553   }
    554 }
    555 
    556 
    557 static int ll_require (lua_State *L) {
    558   const char *name = luaL_checkstring(L, 1);
    559   lua_settop(L, 1);  /* _LOADED table will be at index 2 */
    560   lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
    561   lua_getfield(L, 2, name);  /* _LOADED[name] */
    562   if (lua_toboolean(L, -1))  /* is it there? */
    563     return 1;  /* package is already loaded */
    564   /* else must load package */
    565   lua_pop(L, 1);  /* remove 'getfield' result */
    566   findloader(L, name);
    567   lua_pushstring(L, name);  /* pass name as argument to module loader */
    568   lua_insert(L, -2);  /* name is 1st argument (before search data) */
    569   lua_call(L, 2, 1);  /* run loader to load module */
    570   if (!lua_isnil(L, -1))  /* non-nil return? */
    571     lua_setfield(L, 2, name);  /* _LOADED[name] = returned value */
    572   lua_getfield(L, 2, name);
    573   if (lua_isnil(L, -1)) {   /* module did not set a value? */
    574     lua_pushboolean(L, 1);  /* use true as result */
    575     lua_pushvalue(L, -1);  /* extra copy to be returned */
    576     lua_setfield(L, 2, name);  /* _LOADED[name] = true */
    577   }
    578   return 1;
    579 }
    580 
    581 /* }====================================================== */
    582 
    583 
    584 
    585 /*
    586 ** {======================================================
    587 ** 'module' function
    588 ** =======================================================
    589 */
    590 #if defined(LUA_COMPAT_MODULE)
    591 
    592 /*
    593 ** changes the environment variable of calling function
    594 */
    595 static void set_env (lua_State *L) {
    596   lua_Debug ar;
    597   if (lua_getstack(L, 1, &ar) == 0 ||
    598       lua_getinfo(L, "f", &ar) == 0 ||  /* get calling function */
    599       lua_iscfunction(L, -1))
    600     luaL_error(L, LUA_QL("module") " not called from a Lua function");
    601   lua_pushvalue(L, -2);  /* copy new environment table to top */
    602   lua_setupvalue(L, -2, 1);
    603   lua_pop(L, 1);  /* remove function */
    604 }
    605 
    606 
    607 static void dooptions (lua_State *L, int n) {
    608   int i;
    609   for (i = 2; i <= n; i++) {
    610     if (lua_isfunction(L, i)) {  /* avoid 'calling' extra info. */
    611       lua_pushvalue(L, i);  /* get option (a function) */
    612       lua_pushvalue(L, -2);  /* module */
    613       lua_call(L, 1, 0);
    614     }
    615   }
    616 }
    617 
    618 
    619 static void modinit (lua_State *L, const char *modname) {
    620   const char *dot;
    621   lua_pushvalue(L, -1);
    622   lua_setfield(L, -2, "_M");  /* module._M = module */
    623   lua_pushstring(L, modname);
    624   lua_setfield(L, -2, "_NAME");
    625   dot = strrchr(modname, '.');  /* look for last dot in module name */
    626   if (dot == NULL) dot = modname;
    627   else dot++;
    628   /* set _PACKAGE as package name (full module name minus last part) */
    629   lua_pushlstring(L, modname, dot - modname);
    630   lua_setfield(L, -2, "_PACKAGE");
    631 }
    632 
    633 
    634 static int ll_module (lua_State *L) {
    635   const char *modname = luaL_checkstring(L, 1);
    636   int lastarg = lua_gettop(L);  /* last parameter */
    637   luaL_pushmodule(L, modname, 1);  /* get/create module table */
    638   /* check whether table already has a _NAME field */
    639   lua_getfield(L, -1, "_NAME");
    640   if (!lua_isnil(L, -1))  /* is table an initialized module? */
    641     lua_pop(L, 1);
    642   else {  /* no; initialize it */
    643     lua_pop(L, 1);
    644     modinit(L, modname);
    645   }
    646   lua_pushvalue(L, -1);
    647   set_env(L);
    648   dooptions(L, lastarg);
    649   return 1;
    650 }
    651 
    652 
    653 static int ll_seeall (lua_State *L) {
    654   luaL_checktype(L, 1, LUA_TTABLE);
    655   if (!lua_getmetatable(L, 1)) {
    656     lua_createtable(L, 0, 1); /* create new metatable */
    657     lua_pushvalue(L, -1);
    658     lua_setmetatable(L, 1);
    659   }
    660   lua_pushglobaltable(L);
    661   lua_setfield(L, -2, "__index");  /* mt.__index = _G */
    662   return 0;
    663 }
    664 
    665 #endif
    666 /* }====================================================== */
    667 
    668 
    669 
    670 /* auxiliary mark (for internal use) */
    671 #define AUXMARK		"\1"
    672 
    673 
    674 #ifdef SYSLINUX
    675 static void setpath (lua_State *L, const char *fieldname, const char *envname1,
    676                                    const char *envname2, const char *def) {
    677   struct path_entry *entry;
    678   luaL_Buffer b;
    679   luaL_buffinit (L, &b);
    680   (void)envname1;
    681   (void)envname2;
    682   list_for_each_entry(entry, &PATH, list) {
    683     const char *e = entry->str;
    684     int need_slash = e[strlen(e)-1] != '/';
    685     void add (const char *stem) {
    686       luaL_addstring (&b, e);
    687       if (need_slash) luaL_addchar (&b, '/');
    688       luaL_addstring (&b, stem);
    689       luaL_addstring (&b, def);
    690       luaL_addchar (&b, ';');
    691     }
    692     add ("?");
    693     add ("?/init");
    694   }
    695   luaL_addstring (&b, "./?");
    696   luaL_addstring (&b, def);
    697   luaL_pushresult (&b);
    698   lua_setfield(L, -2, fieldname);
    699 }
    700 #else
    701 /*
    702 ** return registry.LUA_NOENV as a boolean
    703 */
    704 static int noenv (lua_State *L) {
    705   int b;
    706   lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
    707   b = lua_toboolean(L, -1);
    708   lua_pop(L, 1);  /* remove value */
    709   return b;
    710 }
    711 
    712 
    713 static void setpath (lua_State *L, const char *fieldname, const char *envname1,
    714                                    const char *envname2, const char *def) {
    715   const char *path = getenv(envname1);
    716   if (path == NULL)  /* no environment variable? */
    717     path = getenv(envname2);  /* try alternative name */
    718   if (path == NULL || noenv(L))  /* no environment variable? */
    719     lua_pushstring(L, def);  /* use default */
    720   else {
    721     /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
    722     path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP,
    723                               LUA_PATH_SEP AUXMARK LUA_PATH_SEP);
    724     luaL_gsub(L, path, AUXMARK, def);
    725     lua_remove(L, -2);
    726   }
    727   setprogdir(L);
    728   lua_setfield(L, -2, fieldname);
    729 }
    730 #endif
    731 
    732 
    733 static const luaL_Reg pk_funcs[] = {
    734   {"loadlib", ll_loadlib},
    735   {"searchpath", ll_searchpath},
    736 #if defined(LUA_COMPAT_MODULE)
    737   {"seeall", ll_seeall},
    738 #endif
    739   {NULL, NULL}
    740 };
    741 
    742 
    743 static const luaL_Reg ll_funcs[] = {
    744 #if defined(LUA_COMPAT_MODULE)
    745   {"module", ll_module},
    746 #endif
    747   {"require", ll_require},
    748   {NULL, NULL}
    749 };
    750 
    751 
    752 static void createsearcherstable (lua_State *L) {
    753   static const lua_CFunction searchers[] =
    754     {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL};
    755   int i;
    756   /* create 'searchers' table */
    757   lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0);
    758   /* fill it with pre-defined searchers */
    759   for (i=0; searchers[i] != NULL; i++) {
    760     lua_pushvalue(L, -2);  /* set 'package' as upvalue for all searchers */
    761     lua_pushcclosure(L, searchers[i], 1);
    762     lua_rawseti(L, -2, i+1);
    763   }
    764 }
    765 
    766 
    767 LUAMOD_API int luaopen_package (lua_State *L) {
    768   /* create table CLIBS to keep track of loaded C libraries */
    769   luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS);
    770   lua_createtable(L, 0, 1);  /* metatable for CLIBS */
    771   lua_pushcfunction(L, gctm);
    772   lua_setfield(L, -2, "__gc");  /* set finalizer for CLIBS table */
    773   lua_setmetatable(L, -2);
    774   /* create `package' table */
    775   luaL_newlib(L, pk_funcs);
    776   createsearcherstable(L);
    777 #if defined(LUA_COMPAT_LOADERS)
    778   lua_pushvalue(L, -1);  /* make a copy of 'searchers' table */
    779   lua_setfield(L, -3, "loaders");  /* put it in field `loaders' */
    780 #endif
    781   lua_setfield(L, -2, "searchers");  /* put it in field 'searchers' */
    782   /* set field 'path' */
    783   setpath(L, "path", LUA_PATHVERSION, LUA_PATH, LUA_PATH_DEFAULT);
    784   /* set field 'cpath' */
    785   setpath(L, "cpath", LUA_CPATHVERSION, LUA_CPATH, LUA_CPATH_DEFAULT);
    786   /* store config information */
    787   lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n"
    788                      LUA_EXEC_DIR "\n" LUA_IGMARK "\n");
    789   lua_setfield(L, -2, "config");
    790   /* set field `loaded' */
    791   luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
    792   lua_setfield(L, -2, "loaded");
    793   /* set field `preload' */
    794   luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
    795   lua_setfield(L, -2, "preload");
    796   lua_pushglobaltable(L);
    797   lua_pushvalue(L, -2);  /* set 'package' as upvalue for next lib */
    798   luaL_setfuncs(L, ll_funcs, 1);  /* open lib into global table */
    799   lua_pop(L, 1);  /* pop global table */
    800   return 1;  /* return 'package' table */
    801 }
    802 
    803