#!/bin/sh -e
# ifscheme changes network configuration schemes using ifup and ifdown

# File locations
IFSTATE=/etc/network/ifstate
INTERFACES=/etc/network/interfaces
SCHEME=/etc/network/scheme

usage ()
{
	echo "Usage: ifscheme [-v] [-l] [[-s] newscheme]" >&2
}

reload_iface()
{
	ifdown $verbose $1 && ifup $verbose $1
}

list()
{
	# Sed magic...
	sed -ne "/^[[:space:]]*\(iface\|map\)[[:space:]].*-/{s:^[ ]*::;s:-: :;p;}" < $INTERFACES | cut -d' ' -f3 | sort -u

	# Easier to read, slower :
	#grep "^[[:space:]]*\(iface\|map\)[[:space:]].*-" $INTERFACES | sed -e"s/^[ ]*//" | sed -e"s/-/ /" | cut -d' ' -f3 | sort -u
}

if [ $# -gt 3 ] ; then
	echo "Too many arguments."
	usage
	exit 1
fi

quiet="-q"
while [ ! -z "$1" ] ; do
	case "$1" in
		-s|--set) # Allows disambiguation of awkward scheme names
			newscheme="$2"
			shift
		;;
		-l|--list)
			list
			exit 0
		;;
		-v|--verbose)
			verbose="-v"
			quiet=""
		;;
		-*)
			usage
			exit 1
		;;
		*)
			newscheme="$1"
		;;
	esac
	shift
done

if [ ! -z "$newscheme" ]; then
	# Change to a new scheme
	if [ -e $SCHEME ]; then
		oldscheme=$(cat $SCHEME)
		if [ "$oldscheme" = "$newscheme" ]; then
			echo "Scheme unchanged."
			exit
		fi
	fi
	
	# Does it look like this scheme exists ? Or does a wildcard scheme
	# exist ?
	if grep $quiet "^[[:space:]]*\(iface\|map\)[[:space:]].*-\($newscheme\|\*\)" $INTERFACES
	then
		echo $newscheme > $SCHEME
		echo "Scheme changed to $newscheme."
	else
		echo "Did not find scheme $newscheme in $INTERFACES."
		echo "Scheme unchanged."
		exit 1
	fi

	# The stored scheme has changed, now change the running interfaces.
	if [ ! -z "$oldscheme" ] && [ -e $IFSTATE ]; then
		active_ifaces=$(grep -- "-$oldscheme" $IFSTATE | cut -d = -f 1)
		for iface in $active_ifaces ; do
			echo "Reinitializing $iface.."
			if ! reload_iface $iface ; then
				bad_scheme=1
				echo "Failed!"
			fi
		done
		if [ ! -z $bad_scheme ] ; then
			# Whoops.
			echo "Reinitialization failed."
			echo "Reverting to scheme $oldscheme."
			echo $oldscheme > $SCHEME
			for iface in $active_ifaces ; do
				if ! reload_iface $iface ; then
					echo "Reverting $iface failed!"
				fi
			done
		fi
	fi
	exit 0
else
	# Just reporting the current scheme.
	if [ ! -e $SCHEME ]; then
		echo "Scheme not set."
	else
		echo "Current scheme is $(cat $SCHEME)."
	fi
	exit 0
fi
