#!/bin/bash
# Need bash because we use "for (( ... ))" and "local"
#
# ifupdown ACTION [INTERFACE]
#

[ -x /sbin/ifup ] || exit 0
[ -x /sbin/ifdown ] || exit 0

MYNAME="${0##*/}"
report() { echo "${MYNAME}: $*" ; }
report_err() { report "Error: $*" >&2 ; }
report_debug() { [ "$DEBUG" != yes ] || report "$*" ; }
IFUPDOWN_TIMEOUT=60
# Once the improved readlink program has made it into coreutils,
# /lib/init/ can be removed from the PATH.
PATH=/lib/init:/sbin:/bin:/usr/sbin:/usr/bin
RUN_DIR=/etc/network/run
[ -r /etc/default/ifupdown ] && . /etc/default/ifupdown

# Note: The state file location is hardcoded in ifup|ifdown
# it is used as a variable in this script order to ease transitions
# to other locations by the package (not by the sysadmin), if you want
# to setup an alternate location please use a symlink
IFSTATE=/etc/network/ifstate

ifupdown_is_available() { [ -f "$IFSTATE" ] ; }

wait_for_ifupdown()
{ # Wait $1 seconds for ifupdown to become ready
  #
  # Typical waiting scenario is: hotplug generates net-add event
  # which leads to "/etc/init.d/ifupdown start INTERFACE"
  # before init has run "/etc/init.d/ifupdown start"
	local T
	ifupdown_is_available && return 0
	report_debug "Waiting for ifupdown"
	for (( T=$1 ; T > 0 ; T-- )) ; do
		sleep 1
		ifupdown_is_available && return 0
	done
	echo "failed."
	report_err "ifupdown is not available"
	return 1
}

do_ifup()
{
	wait_for_ifupdown "$IFUPDOWN_TIMEOUT" || return 1
	ifup "$1"
}

do_ifdown()
{
	wait_for_ifupdown 0 || return 1
	ifdown "$1"
}

do_ifup_safely()
{
	if ps -C ifup ho args | sed 's/$/ /' | grep -q " $1 "; then
		echo "failed."
		report_err "Omitting ifup because $1 is already being ifup'ped"
	else
		do_ifup "$1"
	fi
}

do_ifdown_safely()
{
	if ps -C ifdown ho args | sed 's/$/ /' | grep -q " $1 "; then
		echo "failed."
		report_err "Omitting ifdown because $1 is already being ifdown'ed"
	else
		do_ifdown "$1"
	fi
}

case "$1" in
start)
	if [ "$2" ] ; then
		echo -n "Bringing up interface: "
		do_ifup_safely "$2" || exit 1
		echo "${2}."
	else
		echo -n "Setting up networking..."
		umask 022
		#
		# /etc/network/run can be either a directory or a symlink to a directory
		# where state information for the ifupdown utility can be stored.
		# In the latter case we try here to create the directory if it doesn't
		# already exist; this makes it possible for /etc/network/run to be a
		# symlink into a filesystem that is empty at boot time.  The parent of
		# the directory must already exist.
		#
		if [ -L "$RUN_DIR" ] && [ ! -d "$RUN_DIR" ] ; then
			# Target of symlink is not a dir
			# Create directory at the target
			if RUN_CANONICALDIR="$(readlink -f "$RUN_DIR")" && [ "$RUN_CANONICALDIR" ] ; then
				echo -n "${RUN_CANONICALDIR}/..."
				if ! mkdir "$RUN_CANONICALDIR" ; then
					echo "failed."
					report_err "Failure creating directory $RUN_CANONICALDIR"
					exit 1
				fi
			else
				echo "failed."
				report_err "The canonical path of the run directory could not be determined"
				exit 1
			fi
		fi
		# Create the state file
		# This signals that ifupdown is available for use
		if ! : > "$IFSTATE" ; then
			echo "failed."
			report_err "Failure initializing $IFSTATE"
			exit 1
		fi 
		echo "done."
		exit 0
	fi
	;;
stop)
	if [ "$2" ] ; then
		echo -n "Bringing down: "
		do_ifdown_safely "$2" || exit 1
		echo "${2}."
	else
		[ -x /etc/init.d/ifupdown-clean ] && /etc/init.d/ifupdown-clean start
	fi
	;;
force-reload)
	;;
restart)
	$0 start
	;;
*)
	echo "Usage: $0 {start [INTERFACE]|stop [INTERFACE]|restart|force-reload}" >&2
	exit 3
	;;
esac

exit 0
