#!/bin/sh

add_service_to_list() {
	echo "Add Service ${1}" >&2
	echo "${1}"
}

add_services_to_list() {
	list="${1}"
	shift
	for s
	do	add_service_to_list "${list}" "${s}"
	done
}

# something like which, but simplier
find_exe() {
	for p in ${search_path}
	do
		if [ -e "${p}/${1}" ]
		then
			return 0
		fi
	done
	return 1
}

# This function works fine on Fedora. Feel free to use it, just don't
# sabotage it ;-)
get_default_sysvinit_runlevel() {
	if [ -f /etc/inittab ]
	then
		deflevel=`grep ":initdefault:" /etc/inittab`
		deflevel=${deflevel#id:}
		return ${deflevel%:initdefault:}
	fi
}

# See comment above
# Usage:
#	Send sysvinit runlevel as first argument. The function will scan through
#	the runlevel and add all started services to initng's runlevels (depending
#	on the second argument, which is normally "default" or "system". The third
#	argument is the directory in which to check if the initng service exists,
#	this would normally be "daemon" or "system"
copy_sysvinit_services() {
	if [ -d "/etc/rc${2}.d" ]
	then
		for i in /etc/rc${2}.d/S*
		do
			sname=`basename ${i}`
			sname=${sname##S[0-9][0-9]}
			[ -f "/etc/initng/${1}/${sname}.i" ] && \
				echo "${1}/${sname}"
		done
	fi
}

copy_gentoo_services() {
	for s in /etc/runlevels/${2}/*
	do
		[ -f "/etc/initng/${1}/${s}.i" ] && \
			echo "${1}/${s}"
	done
}

# On what distro's does this function do anything good?
# On Fedora it's just crap...
check_and_add() {
	[ "${dist}" = fedora ] && return 0

	TARGET=""
	ls /etc/rc2.d/S*${2}* >/dev/null 2>&1 TARGET="${1}"
	ls /etc/runlevels/*/*${2}* >/dev/null 2>&1 && TARGET="${1}"

	echo "${TARGET}"
}

gen_system() {
	local services="system/udev system/clock net/lo system/swap \
		system/hostname system/modules system/urandom system/usb"

	if [ \( -x /usr/sbin/readahead -o -x /sbin/readahead \) -a -e /etc/readahead ]
	then
		services="${services} system/readahead"
		echo "NOTE, if you have /usr mounted on another partition:" >&2
		echo "  cp /usr/sbin/readahead /sbin/readahead" >&2
	fi

	[ -e /etc/raidtab ] && services="${services} system/sraid"

	if [ -f /etc/debian_version ]
	then
		services="${services} system/console-screen"
		[ -x /etc/init.d/ifupdown ] && \
			services="${services} system/ifupdown-debian"
	else
		services="${services} system/consolefont"
	fi

	# Getty:
	if find_exe agetty
	then services="${services} daemon/agetty"
	elif find_exe getty
	then services="${services} daemon/getty"
	elif find_exe mingetty
	then services="${services} daemon/mingetty"
	else
		echo "Failed to find getty/agetty/mingetty, you must set that " \
			"manually in /etc/initng/system.virtual" >&2
	fi

	if [ "${dist}" = gentoo ]
	then
		copy_gentoo_services system boot
	else
		get_default_sysvinit_runlevel
		copy_sysvinit_services system ${?}
	fi

	echo ${services} | tr ' ' '\n' | sort -u
}

gen_default() {
	local services="system"

	# Add ${1} services for Fedora
	case "${dist}" in
	fedora)
		services="${services} daemon/dcron daemon/hald daemon/klogd daemon/portmap"

		# Check network interfaces
		for i in $(ls /etc/sysconfig/network-scripts/ifcfg* | \
			LANG=C sed -e '/\(ifcfg-lo\|rpmsave\|:\|rpmorig\|rpmnew\)/d' \
				-e '/\(~\|\.bak\)$/d')
		do
			if grep "ONBOOT=yes" "${i}" >/dev/null
			then
				i=$(basename "${i}")
				services="${services} net/${i#ifcfg-}"
			fi
		done

		# Check SELinux status
		selinuxfs=`LC_ALL=C awk '/ selinuxfs / { print $2 }' /proc/mounts`
		SELINUX=
		[ "${selinuxfs}" -a -r /proc/self/attr/current \
			-a "`cat /proc/self/attr/current`" != 'kernel' \
			-a -r "${selinuxfs}/enforce" \
			-a "`cat ${selinuxfs}/enforce`" -eq 1 ] && \
				services="${services} system/selinux/dev system/selinux/relabel"

		# Below is because dm isn't started as SysVinit service in fedora :-/
		get_default_sysvinit_runlevel
		if [ $? == "5" ]
		then
			preferred=
			if [ -f /etc/sysconfig/desktop ]
			then
				. /etc/sysconfig/desktop
				if [ "${DISPLAYMANAGER}" = GNOME ] && find_exe gdm >/dev/null
				then
					preferred=gdm
				elif [ "${DISPLAYMANAGER}" = KDE ] && find_exe kdm >/dev/null
				then
					preferred=kdm
				elif [ -n "${DISPLAYMANAGER}" ]
				then
					preferred="${DISPLAYMANAGER}"
				fi
			fi
			[ "${preferred}" ] || preferred=gdm
			services="${services} daemon/${preferred}"
		fi
	;;
	# Add the 
	gentoo)
	;;
	# Add the correct dm for Debian/Ubuntu
	debian)
		dm=`sed -ne 's:^/usr/bin/::p' /etc/X11/default-display-manager`
		case "${dm}" in
			gdm) services="${services} daemon/gdm" ;;
			kdm) services="${services} daemon/kdm" ;;
			xdm) services="${services} daemon/xdm" ;;
		esac  
	;;
	*)
		services="${services}
			$(check_and_add daemon/gdm gdm)
			$(check_and_add daemon/kdm kdm)
			$(check_and_add daemon/xdm xdm)"
	;;
	esac

	services="${services}
		$(check_and_add daemon/sshd ssh)
		$(check_and_add daemon/samba samba)"

	# add acpid
	find_exe acpid >/dev/null && services="${services} daemon/acpid"

	# add dbus
	find_exe dbus-daemon >/dev/null && services="${services} daemon/dbus"

	# add hald
	ls /etc/dbus*/event.d/*hal* >/dev/null 2>&1 && \
			services="${services} daemon/hald"

	# Add cron
	if find_exe cron
	then
		services="${services} $(check_and_add daemon/vixie-cron cron)"
	elif find_exe dcron
	then
		services="${services} $(check_and_add daemon/dcron cron)"
	fi

	# Networks thru ifplugd
	find_exe ifplugd && \
		services="${services} daemon/ifplugd"
	if [ "${dist}" = debian ]
	then
		services="${services} net/all"
	elif [ ! "${dist}" = fedora ]
	then
		services="${services} net/eth0"
	fi
		
	# Alsasound
	[ -d /proc/asound ] && \
			services="${services} system/alsasound"
	if echo "${services}" | grep -q 'system/alsasound'
	then
		echo ${services} | grep -q 'system/coldplug' || 
			services="${services} system/alsasound/cards"
		services="${services} system/alsasound/mixerstate"
	fi

	# Speed freq.
	[ -d /sys/devices/system/cpu/cpu0/cpufreq ] && \
			services="${services} system/speedstep"

	# Laptop Mode (Less hardrive on battery)
	if find_exe laptop-mode || find_exe laptop_mode
	then services="${services} system/laptop-mode"
	fi

	# Syslogd
	if find_exe syslog-ng >/dev/null
	then services="${services} daemon/syslog-ng"
	elif find_exe metalog >/dev/null
	then services="${services} daemon/metalog"
	elif find_exe syslogd >/dev/null
	then services="${services} daemon/syslogd"
	fi

	# These calls SHOULD work on every distro, I've just tested it on Fedora
	# this far. If/when this works on all other thistros, we should be able
	# to obsolete some of the crap above. /Daniel
	if ! [ "${dist}" = debian -o "${dist}" = gentoo ]
	then
		get_default_sysvinit_runlevel
		copy_sysvinit_services daemon ${?}
	fi

	echo "${services}" | sed -e 's/[ 	][ 	]*/\n/g' | grep -v '^$' | sort -u
}

gen_gentoo_list() {
	echo 'Not implemented' >&2
	return 1
}

create_list() {
	if
		if [ "${overwrite}" ]
		then true
		else [ \! -e "${CONFDIR}/${1}" ]
		fi
	then
		echo "Automatically generating ${1}" >&2
		if [ "${1}" = system.virtual ]
		then gen_system  >"${CONFDIR}/${1}"
		elif [ "${1}" = default.runlevel ]
		then gen_default >"${CONFDIR}/${1}"
		elif [ "${dist}" = gentoo ]
		then gen_gentoo_list ${1}
		else return 1
		fi
	else
		echo "${1} already exists, skipping..."
		return 1
	fi
}

overwrite=
all=
search_path=
dist=
# DESTDIR=${DESTDIR}

[ -e /etc/gentoo-release ] && dist=gentoo
[ -e /etc/debian_version ] && dist=debian
[ -e /etc/fedora-release ] && dist=fedora

[ ${#} -eq 0 ] && set -e -- -help

while [ ${#} -gt 0 ]
do
	case "${1}" in
	-all) all=true ;;
	-overwrite) overwrite=true ;;
	-dist=*) dist=${1#-dist=} ;;
	-dist)
		shift
		dist=${1}
		;;
	-path=*) search_path=${1#-path=} ;;
	-path)
		shift
		search_path=${1}
		;;
	-destdir=*) DESTDIR=${1#-destdir=} ;;
	-destdir)
		shift
		DESTDIR=${1}
		;;
	-confdir=*) CONFDIR=${1#-confdir=} ;;
	-confdir)
		shift
		CONFDIR=${1}
		;;
	-help)
		exe=$(basename "${0}")
		echo 'USAGE:' >&2
		echo " ${exe} [-overwrite] [-path=PATH] [-destdir=PATH] [-confdir=PATH] -all" >&2
		echo " ${exe} [-overwrite] [-path=PATH] [-destdir=PATH] [-confdir=PATH] FILE" >&2
		echo " ${exe} -help" >&2
		exit 0
		;;
	--)
		shift
		break
		;;
	*) break ;;
	esac
	shift
done

[ "${CONFDIR}" ] || CONFDIR="${DESTDIR}/etc/initng"
mkdir -p "${CONFDIR}"

# for find_exe
[ "${search_path}" ] || search_path=$(echo $(
	for dir in $()/bin /sbin /usr/bin /usr/sbin /usr/kde/\*/bin \
			/usr/kde/\*/sbin /opt/bin /opt/sbin /opt/\*/bin /opt/\*/sbin
	do [ "$(echo ${dir})" ] && echo ${dir}
	done | grep -v '*')
)

if [ "${all}" ]
then 
	if [ "${dist}" = gentoo ]
	then
		set -- $({
			ls --color=none /etc/runlevels | sed -e 's/$/.runlevel/'
			echo system.virtual
		} | grep -v boot.runlevel | sort -u)
	else set -- system.virtual default.runlevel
	fi
fi

for l
do create_list ${l}
done

[ "${skipped}" ] && \
	echo "Runlevels already exists, force overwrite with: '${0}' -overwrite"

echo "Done generating files."
