retex-lua 0.9.0

Embedded Lua and the LuaTeX Lua API for retex
Documentation
-- os.execute and io.popen under LuaTeX's shell escape modes.
--
-- Behaviour observed with luatex: status.shell_escape is 0 (disabled),
-- 1 (enabled) or 2 (restricted to the commands in shell_escape_commands);
-- os.execute() returns that mode; os.execute(cmd) returns the raw wait
-- status (exit code * 256) or nil plus a message; io.popen refuses with
-- its own messages.
local output_directory = ...
local execute, popen = os.execute, io.popen
local find, gsub, sub = string.find, string.gsub, string.sub

local function mode()
  return status.shell_escape
end

-- The words of a command line, honouring single and double quotes.
local function words(cmd)
  local out, cur, i, n, inword = {}, {}, 1, #cmd, false
  while i <= n do
    local c = sub(cmd, i, i)
    if c == "'" or c == '"' then
      local j = find(cmd, c, i + 1, true) or (n + 1)
      cur[#cur + 1] = sub(cmd, i + 1, j - 1)
      inword, i = true, j + 1
    elseif find(c, "^%s$") then
      if inword then out[#out + 1] = table.concat(cur); cur, inword = {}, false end
      i = i + 1
    else
      cur[#cur + 1] = c
      inword, i = true, i + 1
    end
  end
  if inword then out[#out + 1] = table.concat(cur) end
  return out
end

local function allowed(name)
  local list = kpse.var_value("shell_escape_commands") or ""
  for c in list:gmatch("[^,%s]+") do
    if c == name then return true end
  end
  return false
end

-- In restricted mode the command must be an allowed program, and every
-- word is passed quoted, so shell metacharacters cannot start another
-- command.
local function restricted(cmd)
  local w = words(cmd)
  if #w == 0 or not allowed(w[1]) then return nil end
  for i = 1, #w do w[i] = "'" .. gsub(w[i], "'", "'\\''") .. "'" end
  return table.concat(w, " ")
end

-- With an output directory, commands get it in TEXMF_OUTPUT_DIRECTORY, as
-- TeX Live's engines set it for the programs they run (minted, for one,
-- looks for its files there).
local function with_output_directory(cmd)
  local dir = output_directory()
  if not dir then return cmd end
  return "TEXMF_OUTPUT_DIRECTORY='" .. gsub(dir, "'", "'\\''") .. "' " .. cmd
end

local function wait_status(ok, how, code)
  if how == "exit" then return code * 256 end
  if how == "signal" then return code end
  return ok and 0 or 256
end

function os.execute(cmd)
  local m = mode()
  if cmd == nil then return m end
  if m == 0 then return nil, "All command execution disabled." end
  if m == 2 then
    cmd = restricted(cmd)
    if not cmd then return nil, "Command execution disabled via shell_escape='p'" end
  end
  return wait_status(execute(with_output_directory(cmd)))
end

function io.popen(cmd, how)
  local m = mode()
  if m == 0 then return nil, "all command execution is disabled" end
  if m == 2 then
    cmd = restricted(cmd)
    if not cmd then return nil, "specific command execution disabled" end
  end
  return popen(with_output_directory(cmd), how)
end