#!/bin/bash
# vim: cindent:shiftwidth=4:tabstop=4:smarttab:textwidth=100

function service_control {
	local command=$1
	local unit=$2

	if command -v systemctl >/dev/null; then
		# systemd
		echo systemctl "$command" "$unit"
		systemctl "$command" "$unit"
	elif command -v service >/dev/null; then
		# sysvinit
		service "$unit" "$command"
	else
		echo 'unable to find a supported service control utility'
		exit 1
	fi
}

function OLD_LIBRARY_IN_USE {
	local PROCESS_NAMES_LIST=$1

	declare -A PROCESS_TO_SERVICE_MAP
	PROCESS_TO_SERVICE_MAP[vmtoolsd]='open-vm-tools'
	PROCESS_TO_SERVICE_MAP[qemu-system-i38]='xen'
	PROCESS_TO_SERVICE_MAP[sshd]='ssh'
	PROCESS_TO_SERVICE_MAP[dump1090-mutabi]='dump1090-mutability'
	PROCESS_TO_SERVICE_MAP[cleanupd]=''
	PROCESS_TO_SERVICE_MAP[smbd-notifyd]=''
	PROCESS_TO_SERVICE_MAP[lpqd]=''
	PROCESS_TO_SERVICE_MAP[logger]=''
	PROCESS_TO_SERVICE_MAP[systemd-udevd]='udev'
	PROCESS_TO_SERVICE_MAP[supervisord]=''
	PROCESS_TO_SERVICE_MAP[rpc.statd]='nfs-common'
	PROCESS_TO_SERVICE_MAP[ntpd]='ntp'
	PROCESS_TO_SERVICE_MAP[fail2ban-server]='fail2ban'
	PROCESS_TO_SERVICE_MAP[clamd]='clamav-daemon'
	PROCESS_TO_SERVICE_MAP[freshclam]='clamav-freshclam'
	PROCESS_TO_SERVICE_MAP[/usr/sbin/amavi]='amavis'
	PROCESS_TO_SERVICE_MAP[tcsd]='trousers'
	PROCESS_TO_SERVICE_MAP[master]='postfix'
	PROCESS_TO_SERVICE_MAP[BackupPC]='backuppc'
	PROCESS_TO_SERVICE_MAP[BackupPC_trashC]=''
	PROCESS_TO_SERVICE_MAP[mysqld]='mysql'
	PROCESS_TO_SERVICE_MAP[qemu-ga]='qemu-guest-agent'
	PROCESS_TO_SERVICE_MAP[named]='bind9'
	PROCESS_TO_SERVICE_MAP[postgres]=''
	PROCESS_TO_SERVICE_MAP[authdaemond]='courier-authdaemon'
	PROCESS_TO_SERVICE_MAP[htcacheclean]='apache-htcacheclean'
	PROCESS_TO_SERVICE_MAP[watchfrr]='frr'
	PROCESS_TO_SERVICE_MAP[zebra]=''
	PROCESS_TO_SERVICE_MAP[bgpd]=''
	PROCESS_TO_SERVICE_MAP[staticd]=''
	PROCESS_TO_SERVICE_MAP[entropyd]='entropy'
	PROCESS_TO_SERVICE_MAP[ulogd]='ulogd2'
	PROCESS_TO_SERVICE_MAP[squeezeboxserve]='logitechmediaserver'
	PROCESS_TO_SERVICE_MAP[openskyd-dump10]='opensky-feeder'
	PROCESS_TO_SERVICE_MAP[in.tftpd]='tftpd-hpa'
	PROCESS_TO_SERVICE_MAP[/usr/sbin/smoke]='smokeping'
	PROCESS_TO_SERVICE_MAP[dbus-daemon]='dbus.service'
	PROCESS_TO_SERVICE_MAP[systemd-timesyn]='systemd-timesyncd.service'
	PROCESS_TO_SERVICE_MAP[systemd-resolve]='systemd-resolved.service'
	PROCESS_TO_SERVICE_MAP[systemd-network]='systemd-networkd.service'
	PROCESS_TO_SERVICE_MAP['(sd-pam)']=''
	PROCESS_TO_SERVICE_MAP[systemd-journal]='systemd-journald.service'
	PROCESS_TO_SERVICE_MAP[zsh]=''
	PROCESS_TO_SERVICE_MAP[oxenstored]='xen'
	PROCESS_TO_SERVICE_MAP[xenconsoled]='xen'
	PROCESS_TO_SERVICE_MAP[xl]=''
	PROCESS_TO_SERVICE_MAP[imapd]='courier-imap,courier-imap-ssl'
	PROCESS_TO_SERVICE_MAP[systemd-journal]='systemd-journald,systemd-journal-upload'

	# restart these services automatically from sysfix.timer
	declare -A UNATTENDED_WHITELIST
	UNATTENDED_WHITELIST[gpsd]=1
	UNATTENDED_WHITELIST[auditd]=1
	UNATTENDED_WHITELIST[ssh]=1
	UNATTENDED_WHITELIST[ser2net]=1
	UNATTENDED_WHITELIST[bind9]=1
	UNATTENDED_WHITELIST[tftpd-hpa]=1
	UNATTENDED_WHITELIST[systemd-journald]=1
	UNATTENDED_WHITELIST[systemd-journal-upload]=1
	UNATTENDED_WHITELIST[vsftpd]=1

	declare -i FAILED_COUNT=0
	declare -i OK_COUNT=0
	if [[ ${BASH_VERSINFO[0]} -eq 4 ]]; then
		readarray -t PROCESS_NAMES <<< "${PROCESS_NAMES_LIST//;/$'\n'}"
	else
		readarray -d ';' -t PROCESS_NAMES <<< "$PROCESS_NAMES_LIST"
	fi
	if [[ ${PROCESS_NAMES[-1]} = $'\n' ]]; then
		unset 'PROCESS_NAMES[-1]'
	fi

	declare -a service_names
	for process_name in "${PROCESS_NAMES[@]}"; do
		if [[ -z "$process_name" ]]; then
			continue
		fi
		if [[ -n ${PROCESS_TO_SERVICE_MAP["$process_name"]+xxx} ]]; then
			service_list=${PROCESS_TO_SERVICE_MAP["$process_name"]}
			if [[ -z "$service_list" ]]; then
				continue
			fi
			IFS=',' read -r -a service_list <<< "$service_list"
		else
			service_list=("$process_name")
		fi
		service_names+=(${service_list[@]})
	done

	for service in "${service_names[@]}"; do 
		FUNCNAME_CURRENT=${FUNCNAME[0]}
		if [[ "$FUNCNAME_CURRENT" != "${FUNCNAME_CURRENT%_super}" ]]; then
			if [[ -z "${UNATTENDED_WHITELIST[$service]+xxx}" ]]; then
				# unattended run, not whitelisted
				continue
			fi
		fi

		# pre actions
		case $service in
			syslog-ng)
				if [[ -x '/etc/init.d/watchdog' ]]; then
					service watchdog stop
				fi
				;;
		esac

		case $service in
			systemd)
				systemctl daemon-reexec
				;;
			getty|agetty|ethtool-gstats)
				# GSTATS collector will be restarted by Munin node
				# agetty will be restarted by init/systemd
				pkill "$service"
				;;
			*)
				service_control restart "$service"
				;;
		esac
		if [[ $? -eq 0 ]]; then
			OK_COUNT=$((OK_COUNT+1))
		else
			FAILED_COUNT=$((FAILED_COUNT+1))
		fi

		# post actions
		case $service in
			syslog-ng)
				if [[ -x '/etc/init.d/watchdog' ]]; then
					service watchdog start
				fi
				;;
		esac
	done

	if [[ $OK_COUNT -gt 0 ]] && [[ $FAILED_COUNT -eq 0 ]]; then
		return 0
	else
		return 1
	fi
}

copy_function OLD_LIBRARY_IN_USE OLD_LIBRARY_IN_USE_super
