ponymap/plugins/nut.lua

79 lines
2.4 KiB
Lua

--
-- nut.lua: Network UPS Tools service detection plugin
--
-- Copyright (c) 2017, Přemysl Eric Janouch <p@janouch.name>
--
-- Permission to use, copy, modify, and/or distribute this software for any
-- purpose with or without fee is hereby granted.
--
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-- SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-- OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
--
ponymap.check_api_version (1)
local NUT = {}
NUT.__index = NUT
function NUT.new (unit)
unit:write ("LIST UPS\n")
return setmetatable ({ unit = unit, buf = "", in_list = false }, NUT)
end
-- Bare words and quoted strings with escape sequences, separated by spaces;
-- unfortunately Lua patterns are too weak to use them for this trivial task
function NUT.parse (line)
local result, state, field, c = {}, 0, ""
for c in (line .. " "):gmatch (".") do
if state == 0 then
if c == "\"" then state = 2
elseif c ~= " " then field = c state = 1 end
elseif state == 1 then
if c == " " then table.insert (result, field) field = "" state = 0
elseif c == "\"" then state = 2
else field = field .. c end
elseif state == 2 then
if c == "\\" then state = 3
elseif c == "\"" then state = 1
else field = field .. c end
elseif state == 3 then field = field .. c state = 2 end
end
return result
end
function NUT:process (line)
if not self.in_list then
if line:match ("^BEGIN LIST UPS$") then
self.unit:add_info ("no authentication required")
self.unit:set_success (true)
self.in_list = true
return true
elseif line:match ("^ERR ACCESS-DENIED") then
self.unit:set_success (true)
end
else
local fields = self.parse (line)
if #fields == 3 and fields[1] == "UPS" then
self.unit:add_info ("UPS: " .. fields[2] .. " - " .. fields[3])
return true
end
end
end
function NUT:on_data (data)
self.buf = self.buf .. data
repeat
local line, rest = self.buf:match ("([^\n]*)\n(.*)")
if not line then return end
self.buf = rest
until not self:process (line)
self.unit:stop ()
end
ponymap.register_service { name="NUT", flags=0, new_scan=NUT.new }