lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Sat, 2006-05-06 at 09:22 -0500, Javier Guerra wrote:
> On Friday 05 May 2006 10:47 pm, Raymond Jacobs wrote:
> > I am trying to do all of this from C,
> > so that example doesn't really help me,
> > I especially don't know what __index is =/
> >
> > as I understand it, i want to set my environment to a, 'temporary' one,
> > load the code, and then set it back (so i get all of my nice global
> > variables and registred C functions and such)
> > is that right?  and if so how would I acomplish that in C?
> 
> in fact, it's easiest to do all from Lua, if you REALLY need it from C, you 
> could do a prototype in Lua and then port it to C.
> 
...
> now......... you want to do this from C?  the easiest way is to just call 
> scriptloader()
> 

That is an excellent explanation of how to sandbox scripts.  I
considered good enough to bookmark in my mailreader.  It ought to go
into the Wiki.

I'll probably end up using it, though it may be nice to be able to
specify different cages for different scripts.

Separate the cage and scriptloader section as follows:

-- Define the scriptloader function like this:
function scriptloader (scriptname,cage)
  local scriptenv = {}

  setmetatable (scriptenv, {__index=cage})
  
  local chunk  = loadfile (scriptname)
  setfenv (chunk, scriptenv)
  
  chunk ()

  return scriptenv
end


-- use the scriptloader function elsewhere like this:
local mycage = {
  -- import some packages:
  string = string,  coroutine = coroutine,
  table = table, math = math,
  
  -- some 'global' functions:
  next = next, ipairs = ipairs, pairs = pairs,
  require = require, type = type,
  tonumber = tonumber, tostring = tostring,
  unpack = unpack, 
  setmetatable = setmetatable,
  getmetatable = getmetatable,

  -- modified global functions:
  print = myprint,
  error = myerror

  -- my own api:
  move = move
  kill = kill
}

allscripts  = {}

allscripts[1] = scriptloader ("script.lua",mycage)
allscripts[2] = scriptloader ("secondscript.lua",mycage)

script[1].foo(x)      -- call the loaded function from first script
script[2].foo(x)      -- from second script

This allows you to create different cages/sandboxes depending on how
much access you want to give to the script.

Now, as to the question of making this in C...

Use bin2c to convert the scriptloader function into a .h file.  Include
this .h file to load the scriptloader function into your lua_State's
globals.  Then call the scriptloader function as follows:

lua_getfield(L,LUA_GLOBALSINDEX,"scriptloader");
lua_pushstring(L,"script.lua");
lua_getfield(L,LUA_GLOBALSINDEX,"mycage");
lua_call(L, 2, 1);

Note that you can use any method for getting the cage object into the
right stack position.  For instance, if you have the cage stored in the
Lua Registry, you could use:

lua_getfield(L,LUA_GLOBALSINDEX,"scriptloader");
lua_pushstring(L,"script.lua");
lua_getfield(L,LUA_REGISTRYINDEX,"myapp.mycage");
lua_call(L, 2, 1);

You could also modify it to use a Lua value on the stack, or modify it
to use lua_pcall instead.  The end result of the lua_call/lua_pcall is a
value on the stack, which is the return value of the scriptloader
function.

-- 


JJS
"If Ignorance is Bliss, I'll take the Pain."