• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ll_unloadlib(void * lib)133 static void ll_unloadlib (void *lib) {
134   dlclose(lib);
135 }
136 
137 
ll_load(lua_State * L,const char * path,int seeglb)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 
ll_sym(lua_State * L,void * lib,const char * sym)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 
setprogdir(lua_State * L)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 
pusherror(lua_State * L)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 
ll_unloadlib(void * lib)197 static void ll_unloadlib (void *lib) {
198   FreeLibrary((HMODULE)lib);
199 }
200 
201 
ll_load(lua_State * L,const char * path,int seeglb)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 
ll_sym(lua_State * L,void * lib,const char * sym)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 
ll_unloadlib(void * lib)228 static void ll_unloadlib (void *lib) {
229   module_unload ((struct elf_module *)lib);
230 }
231 
232 
ll_load(lua_State * L,const char * path,int seeglb)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 
ll_sym(lua_State * L,void * lib,const char * sym)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 
ll_unloadlib(void * lib)278 static void ll_unloadlib (void *lib) {
279   (void)(lib);  /* not used */
280 }
281 
282 
ll_load(lua_State * L,const char * path,int seeglb)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 
ll_sym(lua_State * L,void * lib,const char * sym)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 
ll_checkclib(lua_State * L,const char * path)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 
ll_addtoclib(lua_State * L,const char * path,void * plib)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 */
gctm(lua_State * L)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 
ll_loadfunc(lua_State * L,const char * path,const char * sym)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 
ll_loadlib(lua_State * L)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 
readable(const char * filename)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 
pushnexttemplate(lua_State * L,const char * path)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 
searchpath(lua_State * L,const char * name,const char * path,const char * sep,const char * dirsep)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 
ll_searchpath(lua_State * L)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 
findfile(lua_State * L,const char * name,const char * pname,const char * dirsep)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 
checkload(lua_State * L,int stat,const char * filename)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 
searcher_Lua(lua_State * L)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 
loadfunc(lua_State * L,const char * filename,const char * modname)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 
searcher_C(lua_State * L)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 
searcher_Croot(lua_State * L)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 
searcher_preload(lua_State * L)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 
findloader(lua_State * L,const char * name)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 
ll_require(lua_State * L)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 */
set_env(lua_State * L)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 
dooptions(lua_State * L,int n)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 
modinit(lua_State * L,const char * modname)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 
ll_module(lua_State * L)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 
ll_seeall(lua_State * L)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
setpath(lua_State * L,const char * fieldname,const char * envname1,const char * envname2,const char * def)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 */
noenv(lua_State * L)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 
setpath(lua_State * L,const char * fieldname,const char * envname1,const char * envname2,const char * def)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 
createsearcherstable(lua_State * L)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 
luaopen_package(lua_State * L)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