#!/bin/awk -f

BEGIN {
	SERVICE = "/sbin/service"
	XINETD_DIR = "/etc/xinetd.d"
	XINETD_CONF = "/etc/xinetd.conf"
	# split input fields by a colon
	FS=":"
	# set default language
	LANGUAGE="en_US.UTF8"
	# set translation domain
	TEXTDOMAIN = "alterator-xinetd"
	readmsg=0
	LOGFILE="/var/log/configd.log"
}

# error reporting function
function debug(text, errno) {
	printf "%s " TEXTDOMAIN ": %s: %s\n", strftime("%B %d %H:%M:%S"), text, errno >> LOGFILE
	fflush(LOGFILE)
}

# remove leading and trailing spaces
function trim(arg) {
	gsub(/^[[:space:]]+/,"", arg)
	gsub(/[[:space:]]+$/,"", arg)
	return arg
}

# search a regular expression in a file
function grep(regex, file,		line) {
	while ((error = getline line <file) > 0)
		if (line ~ regex) {
			close(file)
			return 1
		}
	if (error == -1)
		debug("Error reading file '" file "'", ERRNO)
	close(file)
	return 0
}

# get Xinetd config variable
function xinetd_conf_read(file, name,	 	inside, error, line, regex, list, result) {
	inside = 0
	while ((error = getline line <file) > 0) {
#		debug("got line", line)
		if (line ~ /^{$/) {
			inside = 1
			continue
		}
		if (!inside)
			continue
		regex = "^[[:space:]]*" name "[[:space:]]*=[[:space:]]*(.*)$"
		if (match(line, regex, list) > 0) {
			result = list[1]
			break
		}
		if (line ~ /}/)
			inside = 0
	}
	if (error == -1)
		debug("Error reading file '" file "'", ERRNO)
	close(file)
	return result
}

# set Xinetd config variable
function xinetd_conf_write(file, name, value,	cmd, tempfile, inside, error, line, regex, result) {
        cmd = "mktemp"
        cmd | getline tempfile
        close(cmd)

	inside = 0
	while ((error = getline line <file) > 0) {
#		debug("got line", line)
		if (line ~ /^{$/) {
			inside = 1
			print line >> tempfile
			if (value != "")
				print "\t" name "\t\t= " value >> tempfile
			continue
		}
		regex = "^[[:space:]]*" name "[[:space:]]*=[[:space:]]*(.*)$"
		if (!inside || line !~ regex)
			print line >> tempfile
		if (line ~ /}/)
			inside = 0
	}
	if (error == -1)
		debug("Error reading file '" file "'", ERRNO)
	close(file)
	close(tempfile)
	system("cat " tempfile " > " file)
        system("rm -f " tempfile)
}

# get Xinetd module description
function xinetd_get_description(file,		error, line, is_desc, text) {
	is_desc = 0
	text = ""
	while ((error = getline line <file) > 0) {
		if (line ~ /^#[[:space:]]*description:/) {
			is_desc = 1
			sub(/description:[[:space:]]*/, "description \"", line)
		}
		if (line ~ /^#/) {
			if (is_desc == 1) {
				sub(/^#[[:space:]]*/,"", line)
				if (sub(/[[:space:]]*\\$/,"", line) < 1) {
					is_desc=0
				}
				text = text " " line;
				if (is_desc == 0) {
					text = text "\""
					break
				}
			}
		}
	}
	if (error == -1)
		debug("Error reading file '" file "'", ERRNO)
	close(file)
	return text
}

# list Xinetd services
function xinetd_list_services(dir,	cmd, error, line, list) {
	cmd = "ls -1 " dir
	while ((error = cmd | getline line) > 0) {
		if (line ~ /~$/ || line ~ /\.rpm/)
			continue
		if (match(line, /\/?(.*)$/, list) > 0) {
			print "("
			print "\"" list[1] "\" "
			print xinetd_get_description(dir "/" list[1])
			print " state "
			switch (xinetd_conf_read(dir "/" list[1], "disable")) {
				case "yes":
					printf "\"%s\"", N_("disabled")
					break
				case "no":
					printf "\"%s\"", N_("enabled")
					break
				default:
					print "\"\""
			}
			print ")"
		}
	}
	if (error == -1)
		debug("Error reading service list '" cmd "'", ERRNO)
	close(cmd)
}

# show translation
# overwriting locale settings
function N_(text,			list, cmd, line) {
	split(LANGUAGE, list, /:/)
	cmd = "LANGUAGE=\"" LANGUAGE "\" LANG=\"" list[1] ".UTF8\" gettext " TEXTDOMAIN " \"" text "\""
	cmd | getline line
	close(cmd)
	return line
}

# start message reading
/^_message:begin$/ {
	readmsg=1
	next
}

# stop message reading
/^_message:end$/ {
	readmsg=0
	#debug("==========", "==========")
	#for (attribute in params)
	#	debug("params[" attribute "]", params[attribute])
	# overwrite current language
	if (params["language"] != "")
		LANGUAGE = gensub(/;/, ":", "g", params["language"])

	switch (params["action"]) {
		case "constraints":
			print "("
			printf " instances (match \"^([[:digit:]]+|UNLIMITED)$\" label \"%s\")", N_("Instances")
			printf " per_source (match \"^([[:digit:]]+|UNLIMITED)$\" label \"%s\")", N_("Per source")
			printf " only_from (label \"%s\")", N_("Only from")
			printf " state (label \"%s\")", N_("State")
			printf " chkconfig (label \"%s\")", N_("start, stop or restart service")
			if (params["_objects"] == "/") {
				printf " name (label \"%s\")", N_("Service")
				printf " description (label \"%s\")", N_("Description")

			}
			else {
				printf " name (label \"%s\")", params["_objects"]
				printf " user (label \"%s\")", N_("User")
				printf " group (label \"%s\")", N_("Group")
				printf " server (label \"%s\")", N_("Server")
				printf " server_args (label \"%s\")", N_("Server arguments")
				printf " rlimit_as (match \"^([[:digit:]]+[K|M]?|UNLIMITED)$\"label \"%s\")", N_("Address space limit")
				printf " disable (label \"%s\")", N_("Disable")
			}
			print ")"
			break
		case "list":
			print "("
			switch (params["_objects"]) {
				case "/":
					xinetd_list_services(XINETD_DIR)
					break
				case /\yavail_action$/:
					printf "( \"enable\" label \"%s\")", N_("enable")
					printf "( \"disable\" label \"%s\")", N_("disable")
					break
				case /\ystate$/:
					printf "( \"disabled\" label \"%s\")", N_("disabled")
					printf "( \"enabled\" label \"%s\")", N_("enabled")
					break
			}
			print ")"
			break
		case "read":
			if (params["_objects"] == "/"){
				print "("
				print " instances \"" xinetd_conf_read(XINETD_CONF, "instances") "\""
				print " per_source \"" xinetd_conf_read(XINETD_CONF, "per_source") "\""
				print " only_from \"" xinetd_conf_read(XINETD_CONF, "only_from") "\""
				print ")"
			}
			else {
				config = XINETD_DIR "/" params["_objects"]
				print "("
				print " user \"" xinetd_conf_read(config, "user") "\""
				print " group \"" xinetd_conf_read(config, "group") "\""
				print " server \"" xinetd_conf_read(config, "server") "\""
				print " server_args \"" xinetd_conf_read(config, "server_args") "\""
				print " rlimit_as \"" xinetd_conf_read(config, "rlimit_as") "\""
				print " instances \"" xinetd_conf_read(config, "instances") "\""
				print " per_source \"" xinetd_conf_read(config, "per_source") "\""
				print " only_from \"" xinetd_conf_read(config, "only_from") "\""
				switch (xinetd_conf_read(config, "disable")) {
					case "no":
						print " state \"enabled\""
						break
					case "yes":
						print " state \"disabled\""
						break
				}
				print ")"
			}
			break
		case "write":
			if (params["_objects"] == "/"){
				xinetd_conf_write(XINETD_CONF, "instances", params["instances"])
				xinetd_conf_write(XINETD_CONF, "per_source", params["per_source"])
				xinetd_conf_write(XINETD_CONF, "only_from", params["only_from"])
			}
			else {
				config = XINETD_DIR "/" params["_objects"]
				xinetd_conf_write(config, "user", params["user"])
				xinetd_conf_write(config, "group", params["group"])
				xinetd_conf_write(config, "server", params["server"])
				xinetd_conf_write(config, "server_args", params["server_args"])
				xinetd_conf_write(config, "rlimit_as", params["rlimit_as"])
				xinetd_conf_write(config, "instances", params["instances"])
				xinetd_conf_write(config, "per_source", params["per_source"])
				xinetd_conf_write(config, "only_from", params["only_from"])
				switch (params["state"]) {
					case "enabled":
						xinetd_conf_write(config, "disable", "no")
						break
					case "disabled":
						xinetd_conf_write(config, "disable", "yes")
						break
				}
			}	
			system(SERVICE " xinetd reload &> /dev/null")
			print "()"
			break
		case "new":
		case "delete":
			print "()"
			break
		case "enable":
			if (params["_objects"] != "/")
				xinetd_conf_write(XINETD_DIR "/" params["_objects"], "disable", "no")
			system(SERVICE " xinetd reload &> /dev/null")
			print "()"
			break
		case "disable":
			if (params["_objects"] != "/")
				xinetd_conf_write(XINETD_DIR "/" params["_objects"], "disable", "yes")
			system(SERVICE " xinetd reload &> /dev/null")
			print "()"
			break
		default:
			print "#f"
	}
	fflush()
	# delete attribute/value pairs before next cycle
	delete params
	#exit
	next
}

# save attribute/value pairs
{
	if (! readmsg)
		next
	attribute=$1
	value=$2
	# join the rest of fields with a colon
	for (n = 3; n <= NF; n++)
		value=value ":" $n
	value = gensub(/([^\\])\\n/, "\\1\n", "g", value)
	params[attribute]=value
}
