daemon and stuff
This commit is contained in:
parent
2cdedd9591
commit
022699f899
10
example.cfg
Normal file
10
example.cfg
Normal file
@ -0,0 +1,10 @@
|
||||
local config = {}
|
||||
|
||||
config.path = "/var/gopher" -- the root path of the dir to be served
|
||||
config.hostname = "shadowkat.net" -- the hostname of the server
|
||||
config.port = 70 -- the external port of the server
|
||||
config.bindport = 7000 -- the port to actually bind to
|
||||
config.dirinfo = true -- whether to output some extra info in automatic directory indexes
|
||||
config.timer = 0.1 -- main loop timer
|
||||
|
||||
return config
|
134
gopherd.lua
Normal file
134
gopherd.lua
Normal file
@ -0,0 +1,134 @@
|
||||
local socket = require "socket"
|
||||
local fs = require "lfs"
|
||||
|
||||
local tArgs = {...}
|
||||
|
||||
local pcount = 0
|
||||
local threads = {}
|
||||
|
||||
-- initial configuration
|
||||
local config = {}
|
||||
config.path = "/var/gopher"
|
||||
config.hostname = "shadowkat.net"
|
||||
config.port = 70
|
||||
config.bindport = 7000
|
||||
config.dirinfo = true
|
||||
config.timer = 0.1
|
||||
|
||||
-- load the config as a lua script
|
||||
if tArgs[1] then
|
||||
local f = io.open(tArgs[1],"rb")
|
||||
local fn = load(f:read("*a"))
|
||||
f:close()
|
||||
if fn then
|
||||
for k,v in pairs(fn()) do
|
||||
config[k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function cleanPath(p) -- canonicalizes the path in theory
|
||||
local t,o = {},""
|
||||
for s in p:gmatch("[^/]+") do
|
||||
if s == ".." then
|
||||
t[#t] = nil
|
||||
else
|
||||
t[#t+1] = s
|
||||
end
|
||||
end
|
||||
for k,v in pairs(t) do
|
||||
o=o.."/"..v
|
||||
end
|
||||
return o
|
||||
end
|
||||
|
||||
local function logerr(msg)
|
||||
-- todo: proper error logging logic
|
||||
print("error: "..msg)
|
||||
end
|
||||
|
||||
local function detectft(path) -- tries to detect the file type
|
||||
local attr = fs.attributes(path)
|
||||
if attr.mode:sub(1,3) == "dir" then
|
||||
return "1"
|
||||
end
|
||||
if path:sub(-4) == ".png" or path:sub(-4) == ".jpg" or path:sub(-5) == ".jpeg" or path:sub(-4) == ".bmp" or path:sub(-4) == "gif" then
|
||||
return "I"
|
||||
end
|
||||
if path:sub(-5) == ".html" or path:sub(-4) == ".htm" then
|
||||
return "h"
|
||||
end
|
||||
return "0"
|
||||
end
|
||||
|
||||
local function handleConnect(client)
|
||||
client:settimeout(0)
|
||||
threads[pcount+1] = coroutine.create(function() local w,err = pcall(function()
|
||||
repeat
|
||||
coroutine.yield()
|
||||
line=client:receive()
|
||||
until line
|
||||
print(line)
|
||||
local path,args = config.path .. cleanPath(line)
|
||||
local attr = fs.attributes(path)
|
||||
if attr then
|
||||
if attr.mode:sub(1,3) == "dir" then
|
||||
if lfs.attributes(path.."/.gopherdir.cgi") then
|
||||
local f = io.popen(path.."/.gopherdir.cgi")
|
||||
coroutine.yield()
|
||||
client:send(f:read("*a"))
|
||||
f:close()
|
||||
elseif lfs.attributes(path.."/.gopherdir") then
|
||||
local f = io.open(path.."/.gopherdir")
|
||||
client:send(f:read("*a"))
|
||||
f:close()
|
||||
else
|
||||
if config.dirinfo then
|
||||
client:send(string.format("i%s\ni%s\n",config.hostname,cleanPath(line)))
|
||||
end
|
||||
for file in lfs.dir(path) do
|
||||
if file:sub(1,1) ~= "." then
|
||||
client:send(string.format("%s%s\t%s\t%s\t%d\n",detectft(path.."/"..file),file,string.format("%s/%s",cleanPath(line),file),config.hostname,config.port))
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if path:sub(-4) == ".cgi" then
|
||||
local f = io.popen(path)
|
||||
coroutine.yield()
|
||||
client:send(f:read("*a"))
|
||||
f:close()
|
||||
else
|
||||
local f = io.open(path)
|
||||
client:send(f:read("*a"))
|
||||
f:close()
|
||||
end
|
||||
end
|
||||
else
|
||||
client:send("Not found.")
|
||||
end
|
||||
client:close()
|
||||
end)
|
||||
if not w then
|
||||
logerr(err)
|
||||
client:close()
|
||||
end
|
||||
end)
|
||||
pcount=pcount+1
|
||||
end
|
||||
|
||||
local server = socket.bind("*",config.bindport)
|
||||
server:settimeout(config.timer)
|
||||
while true do -- totally not a scheduler
|
||||
client = server:accept()
|
||||
if client then
|
||||
handleConnect(client)
|
||||
end
|
||||
for k,v in pairs(threads) do
|
||||
if coroutine.status(v) == "dead" then
|
||||
threads[k] = nil
|
||||
else
|
||||
coroutine.resume(v)
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user