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