module(..., package.seeall) require("modelfunctions") require("fs") require("format") require("validator") local configfile = "/etc/conf.d/syslog" local packagename = "busybox" local processname = "syslog" local function getloglevels() local loglevels = {} for i=1,8 do table.insert(loglevels,tostring(i)) end return loglevels end local writeconfig = function (config) -- Set variables local variable = "SYSLOGD_OPTS" local variabletranslator = { logfile = "-O", loglevel = "-l", smallerlogs = "-S", maxsize = "-s", numrotate = "-b", localandnetworklog = "-L", remotelogging = "-R", } local configdata = {} for name, entry in pairs(variabletranslator) do if config.value[name] and config.value[name].type == "boolean" then if config.value[name].value then configdata[entry] = "" end elseif config.value[name] and config.value[name].value and #config.value[name].value > 0 then configdata[entry] = config.value[name].value else configdata[entry] = nil end end fs.write_file(configfile, format.update_ini_file(fs.read_file(configfile) or "", "", variable, '"'..format.table_to_opts(configdata) .. '"')) end local makeconfig = function(configcontent) local config = {} configcontent = configcontent or {} -- Next section selects which configurations we should show to the user config["logfile"] = cfe({ label = "Log to given file", descr = "File must be in /var/log directory", value = configcontent["-O"] or "/var/log/messages", }) config["loglevel"] = cfe({ label = "Set local log level", value = configcontent["-l"] or "8", type = "select", option = getloglevels(), descr = "1=Quiet, ... , " .. table.maxn(getloglevels()) .. "=Debug", }) config["smallerlogs"] = cfe({ label = "Smaller logging output", value = (configcontent["-S"] == ""), type = "boolean", }) config["maxsize"] = cfe ({ label = "Max size (KB) before rotate", descr = "Default=200KB, 0=off", value = configcontent["-s"] or "", }) config["numrotate"] = cfe ({ label = "Number of rotated logs to keep", descr = "Default=1, max=99, 0=purge", value = configcontent["-b"] or "", }) config["localandnetworklog"] = cfe ({ label = "Log locally and via network", value = (configcontent["-L"] == ""), type = "boolean", descr = "Default is network only if host[:PORT] is defined", }) config["remotelogging"] = cfe ({ label = "Log to IP or hostname on PORT", descr = "host[:PORT] - Default PORT=514/UDP", value = configcontent["-R"] or "", }) return cfe({ type="group", value=config, label="Configuration" }) end local validateconfig = function(config) local success = true -- Validate entries and create error strings if not validator.is_valid_filename(config.value.logfile.value, "/var/log") then config.value.logfile.errtxt = "Not a valid file name in /var/log" success = false end if not validator.is_integer_in_range(config.value.loglevel.value, 1, 8) then config.value.loglevel.errtxt = "Out of range!" success = false end if config.value.maxsize.value ~= "" and not validator.is_integer(config.value.maxsize.value) then config.value.maxsize.errtxt = "Must be an integer" success = false end if config.value.numrotate.value ~= "" and not validator.is_integer_in_range(config.value.numrotate.value, 0, 99) then config.value.numrotate.errtxt = "Out of range!" success = false end if config.value.localandnetworklog.value == true and config.value.remotelogging.value == "" then config.value.localandnetworklog.errtxt = "Logging to local and network is not possible unless you define a host for remote logging" success = false end local hostport = format.string_to_table(config.value.remotelogging.value, ":") if hostport[2] and not (validator.is_port(hostport[2])) then config.value.remotelogging.errtxt = "Not a valid port" success = false end return success, config end local validate_configfile = function(filedetails) local success = true local configcontent = format.opts_to_table(string.sub((format.parse_ini_file(filedetails.value.filecontent.value, "", "SYSLOGD_OPTS") or ""),2,-2)) local config = makeconfig(configcontent) success, config = validateconfig(config) if not success then local errormessages = {} for x,y in pairs(config.value) do if y.errtxt then errormessages[#errormessages + 1] = y.label .. " - " .. y.errtxt end end filedetails.value.filecontent.errtxt = table.concat(errormessages, "\n") end return success, filedetails end -- ################################################################################ -- PUBLIC FUNCTIONS function startstop_service(action) return modelfunctions.startstop_service(processname, action) end function getstatus() return modelfunctions.getstatus(processname, packagename, "Syslog Status") end function getlogging() local status = {} local opts = getconfig() if (opts.value.remotelogging.value == "") or (opts.value.localandnetworklog.value) then status.logfile = cfe({ label="Locally logging to", value=opts.value.logfile.value, }) end if (opts.value.remotelogging.value ~= "") then status.remote = cfe({ label="Remote logging to", value=opts.value.remotelogging.value, }) end return cfe({ type="group", value=status }) end function get_filedetails() return modelfunctions.getfiledetails(configfile) end function getconfig() local config = {} if (fs.is_file(configfile)) then local configcontent = format.opts_to_table(string.sub((format.parse_ini_file(fs.read_file(configfile) or "", "", "SYSLOGD_OPTS") or ""),2,-2)) config = makeconfig(configcontent) else config = makeconfig() config["errtxt"] = "Config file '".. configfile .. "' is missing!" end return config end function updateconfig (config) local success = true success, config = validateconfig(config) if success == true then writeconfig(config) else config.errtxt = "Failed to save config!" end return config end function update_filedetails (filedetails) return modelfunctions.setfiledetails(filedetails, {configfile}, validate_configfile) end