💾 Archived View for gemini.conman.org › sourcecode › Lua › GLV-1 › scgi.lua captured on 2020-11-01 at 00:01:33.

View Raw

More Information

➡️ Next capture (2021-12-03)

-=-=-=-=-=-=-

-- ************************************************************************
--
--    SCGI interace.
--    Copyright 2020 by Sean Conner.  All Rights Reserved.
--
--    This program is free software: you can redistribute it and/or modify
--    it under the terms of the GNU General Public License as published by
--    the Free Software Foundation, either version 3 of the License, or
--    (at your option) any later version.
--
--    This program is distributed in the hope that it will be useful,
--    but WITHOUT ANY WARRANTY; without even the implied warranty of
--    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--    GNU General Public License for more details.
--
--    You should have received a copy of the GNU General Public License
--    along with this program.  If not, see <http://www.gnu.org/licenses/>.
--
--    Comments, questions and criticisms can be sent to: sean@conman.org
--
-- ************************************************************************
-- luacheck: ignore 611

local syslog = require "org.conman.syslog"
local fsys   = require "org.conman.fsys"
local errno  = require "org.conman.errno"
local url    = require "org.conman.parsers.url"
local net    = require "org.conman.net"
local tcp    = require "org.conman.nfl.tcp"
local MSG    = require "GLV-1.MSG"
local gi     = require "GLV-1.gateway"

local pairs    = pairs
local tostring = tostring

-- ************************************************************************

return function(auth,program,directory,base,location)
  local gconf = require "CONF".scgi
  local hconf = require "CONF".hosts[location.host].scgi
  local dconf = directory.scgi
  
  if not gconf and not hconf and not dconf then
    syslog('error',"SCGI called, but SCGI not configured!")
    return 40,MSG[40],""
  end
  
  if dconf == false
  or hconf == false and dconf == nil then
    syslog('error',"SCGI called, but SCGI not configured!")
    return 40,MSG[40],""
  end
  
  local env  = gi.setup_env(auth,program,base,location,directory,'scgi',hconf,gconf)
  local tenv = "CONTENT_LENGTH" .. '\0' .. "0" .. '\0'
            .. "SCGI"           .. '\0' .. "1" .. '\0'
  
  for name,val in pairs(env) do
    tenv = tenv .. name .. '\0' .. val .. '\0'
  end
  
  local scgiurl,err = fsys.readlink(program)
  if not scgiurl then
    syslog('error',"SCGI: readlink() = %s",errno[err])
    return 40,MSG[40],""
  end
  
  local scgiloc = url:match(scgiurl)
  if not scgiloc then
    syslog('error',"SCGI: bad link %q",scgiurl)
    return 40,MSG[40],""
  end
  
  if scgiloc.scheme ~= 'scgi' then
    syslog('error',"SCGI: bad scheme %q",scgiurl)
    return 40,MSG[40],""
  end
  
  local addr
  
  if scgiloc.host then
    if not scgiloc.port then
      syslog('error',"SCGI: %q missing port",scgiurl)
      return 40,MSG[40],''
    end
    
    addr = net.address2(scgiloc.host,'any','tcp',scgiloc.port)[1]
  else
    if scgiloc.path == "" then
      syslog('error',"SCGI: %q missing path",scgiurl)
      return 40,MSG[40],''
    end
    
    addr = net.address(scgiloc.path,'tcp')
  end
  
  local ios = tcp.connecta(addr,5)
  if not ios then
    return 40,MSG[40],""
  end
  
  ios:write(tostring(#tenv),":",tenv,",0:,")
  local hdrs = ios:read("h")
  local data = ios:read("a")
  ios:close()
  
  return gi.handle_output(program,hdrs,data)
end