module XinetdParser
def parse_xinetd(raw) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
def parse_xinetd(raw) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity return {} if raw.nil? res = {} cur_group = nil simple_conf = [] rest = raw + "\n" until rest.empty? # extract content line nl = rest.index("\n") || (rest.length-1) comment = rest.index('#') || (rest.length-1) dst_idx = comment < nl ? comment : nl inner_line = dst_idx == 0 ? '' : rest[0..dst_idx-1].strip # update unparsed content rest = rest[nl+1..-1] next if inner_line.empty? if inner_line == '}' if cur_group == 'defaults' res[cur_group] = SimpleConfig.new(simple_conf.join("\n")) else res[cur_group] ||= [] res[cur_group].push(SimpleConfig.new(simple_conf.join("\n"))) end cur_group = nil elsif rest.lstrip[0] == '{' cur_group = inner_line simple_conf = [] rest = rest[rest.index("\n")+1..-1] elsif cur_group.nil? # parse all included files others = xinetd_include_dir(inner_line[/includedir (.+)/, 1]) # complex merging of included configurations, as multiple services # may be defined with the same name but different configuration others.each { |ores| ores.each { |k, v| res[k] ||= [] res[k].concat(v) } } else simple_conf.push(inner_line) end end res end
def xinetd_include_dir(dir)
def xinetd_include_dir(dir) return [] if dir.nil? unless inspec.file(dir).directory? raise Inspec::Exceptions::ResourceSkipped, "Can't find folder: #{dir}" end files = inspec.command("find #{dir} -type f").stdout.split("\n") files.map { |file| parse_xinetd(read_content(file)) } end