Add paths to Lua package.path so require works for user scripts

This adds the global and personal plugins directories to the
package.path setting in Lua, so doing 'require' will work
properly.

Change-Id: Iec33bc60cd7d41aa122da456db91d4ccc3085f82
Reviewed-on: https://code.wireshark.org/review/841
Reviewed-by: Hadriel Kaplan <hadrielk@yahoo.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
Hadriel Kaplan 2014-03-26 19:12:04 -04:00 committed by Anders Broman
parent 09055f18a5
commit f3fe29f0fc
2 changed files with 64 additions and 3 deletions

View File

@ -413,8 +413,12 @@ static int lua_script_push_args(const int script_num) {
#define FILE_NAME_KEY "__FILE__"
#define DIR_NAME_KEY "__DIR__"
#define DIR_SEP_NAME_KEY "__DIR_SEPARATOR__"
/* assumes a loaded chunk's function is on top of stack */
static void set_file_environment(const gchar* filename, const gchar* dirname) {
const char* path;
char* personal = get_plugins_pers_dir();
lua_newtable(L); /* environment for script (index 3) */
lua_pushstring(L, filename); /* tell the script about its filename */
@ -423,14 +427,28 @@ static void set_file_environment(const gchar* filename, const gchar* dirname) {
lua_pushstring(L, dirname); /* tell the script about its dirname */
lua_setfield(L, -2, DIR_NAME_KEY); /* make it accessible at __DIR__ */
lua_newtable(L); /* metatable */
lua_pushstring(L, G_DIR_SEPARATOR_S); /* tell the script the directory separator */
lua_setfield(L, -2, DIR_SEP_NAME_KEY); /* make it accessible at __DIR__ */
lua_newtable(L); /* new metatable */
#if LUA_VERSION_NUM >= 502
lua_pushglobaltable(L);
#else
lua_pushvalue(L, LUA_GLOBALSINDEX);
#endif
lua_setfield(L, -2, "__index"); /* __index points to global environment */
/* prepend the directory name to _G.package.path */
lua_getfield(L, -1, "package"); /* get the package table from the global table */
lua_getfield(L, -1, "path"); /* get the path field from the package table */
path = luaL_checkstring(L, -1); /* get the path string */
lua_pop(L, 1); /* pop the path string */
/* prepend the various paths */
lua_pushfstring(L, "%s" G_DIR_SEPARATOR_S "?.lua;%s" G_DIR_SEPARATOR_S "?.lua;%s" G_DIR_SEPARATOR_S "?.lua;%s",
dirname, personal, get_plugin_dir(), path);
lua_setfield(L, -2, "path"); /* set the new string to be the path field of the package table */
lua_setfield(L, -2, "package"); /* set the package table to be the package field of the global */
lua_setfield(L, -2, "__index"); /* make metatable's __index point to global table */
lua_setmetatable(L, -2); /* pop metatable, set it as metatable of environment */
@ -439,6 +457,8 @@ static void set_file_environment(const gchar* filename, const gchar* dirname) {
#else
lua_setfenv(L, -2); /* pop environment and set it as the func's environment */
#endif
g_free(personal);
}
/* If file_count > 0 then it's a command-line-added user script, and the count

View File

@ -64,12 +64,53 @@ function typeof(obj)
return mt and mt.__typeof or obj.__typeof or type(obj)
end
-- the following function is since 1.11.3
-- the following function checks if a file exists
-- since 1.11.3
function file_exists(name)
local f = io.open(name,"r")
if f ~= nil then io.close(f) return true else return false end
end
-- the following function prepends the given directory name to
-- the package.path, so that a 'require "foo"' will work if 'foo'
-- is in the directory name given to this function. For example,
-- if your Lua file will do a 'require "foo"' and the foo.lua
-- file is in a local directory (local to your script) named 'bar',
-- then call this function before doing your 'require', by doing
-- package.prepend_path("bar")
-- and that will let Wireshark's Lua find the file "bar/foo.lua"
-- when you later do 'require "foo"'
--
-- Because this function resides here in init.lua, it does not
-- have the same environment as your script, so it has to get it
-- using the debug library, which is why the code appears so
-- cumbersome.
--
-- since 1.11.3
function package.prepend_path(name)
local debug = require "debug"
-- get the function calling this package.prepend_path function
local dt = debug.getinfo(2, "f")
if not dt then
error("could not retrieve debug info table")
end
-- get its upvalue
local _, val = debug.getupvalue(dt.func, 1)
if not val or type(val) ~= 'table' then
error("No calling function upvalue or it is not a table")
end
-- get the __DIR__ field in its upvalue table
local dir = val["__DIR__"]
-- get the platform-specific directory separator character
local sep = package.config:sub(1,1)
-- prepend the dir and given name to path
if dir and dir:len() > 0 then
package.path = dir .. sep .. name .. sep .. "?.lua;" .. package.path
end
-- also prepend just the name as a directory
package.path = name .. sep .. "?.lua;" .. package.path
end
-- %WTAP_ENCAPS%
-- %WTAP_FILETYPES%