#!/bin/bash

. /etc/rc.conf
. /etc/rc.d/functions
[ -f /etc/conf.d/dhcpcd ] && . /etc/conf.d/dhcpcd

NETCFG_VER=0.1
PATH="/bin:/usr/bin:/sbin:/usr/sbin:$PATH"

PROFILE_DIR="/etc/network-profiles"
STATE_DIR="/var/run/net"

version()
{
	echo "netcfg v$NETCFG_VER"
}

usage()
{
	version
	echo
	echo "usage: netcfg [options] <profile_name>"
	echo "       netcfg --stop <interface>"
	echo "       netcfg --menu [--timeout <secs>]"
	echo "       netcfg --stopall"
	echo
	echo "options:"
	echo "  -c    Don't reconfigure an interface if it's already up"
	echo
	echo "Network profiles are stored in $PROFILE_DIR"
	echo
}

stop_profile()
{
	if [ "$1" = "" ]; then
		echo "error: missing interface name (eg, eth0)"
		exit 1
	fi
	INTERFACE=$1
	[ -f $STATE_DIR/$INTERFACE ] || return

	unset GATEWAY IFOPTS
	. $STATE_DIR/$INTERFACE

	stat_busy "Shutting down interface: $INTERFACE"

	# bring down the default route (gateway)
	[ "$GATEWAY" ] && route del default gw $GATEWAY

	# shutdown wpa_supplicant if it's running
	[ "$USEWPA" = "yes" -o "$USEWPA" = "YES" ] && wpa_cli terminate >/dev/null 2>&1

	# bring down dhcpcd if we're using it
	if [ "$IFOPTS" = "dhcp" -o "$IFOPTS" = "DHCP" ]; then
		# if the dhcp client received an unlimited lease then it just exits,
		# so check for .pid file before trying to kill it.
		if [ -f /etc/dhcpc/dhcpcd-${INTERFACE}.pid ]; then
			kill `cat /etc/dhcpc/dhcpcd-${INTERFACE}.pid`
		fi
	fi

	# bring down the interface itself
	ifconfig $INTERFACE down

	rm -f $STATE_DIR/$INTERFACE

	stat_done
}

stop_all()
{
	[ -d $STATE_DIR ] || return
	for prof in `ls $STATE_DIR`; do
		unset INTERFACE
		. $STATE_DIR/$prof
		stop_profile $INTERFACE
	done
}

start_profile()
{
	if [ "$1" = "" ]; then
		echo "error: missing profile name"
		exit 1
	fi
	if [ ! -f $PROFILE_DIR/$1 ]; then
		echo "error: $PROFILE_DIR/$1 is missing" >&2
		exit 1
	fi
	
	# Read the profile
	. $PROFILE_DIR/$1

	[ "$CHECK" = "1" -a  -f $STATE_DIR/$INTERFACE ] && return

	# Shut down any profiles tied to this interface
	stop_profile $INTERFACE

	stat_busy "Starting network profile: $1"

	# Re-read the profile (stop_profile might have overwritten our settings)
	unset DESCRIPTION INTERFACE IFOPTS
	unset IWOPTS WIFI_INTERFACE WIFI_WAIT USEWPA WPAOPTS
	unset GATEWAY HOSTNAME DOMAIN DNS1 DNS2
	. $PROFILE_DIR/$1

	# Configure wireless settings, if necessary
	[ "$WIFI_INTERFACE" ] || WIFI_INTERFACE=$INTERFACE
	
	if [ "$IWOPTS" ]; then
		iwconfig $WIFI_INTERFACE $IWOPTS
		[ $? -ne 0 ] && stat_fail && return
		[ "$WIFI_WAIT" ] && sleep $WIFI_WAIT
	fi

	# Start wpa_supplicant, if necessary
	if [ "$USEWPA" = "yes" -o "$USEWPA" = "YES" ]; then
		ifconfig $WIFI_INTERFACE up
	  
		WPA_CONF="/etc/wpa_supplicant.conf"	
		if [ "$AUTOWPA" = "yes" -o "$AUTOWPA" = "YES" ]; then
			WPA_CONF=`mktemp /tmp/wpa.XXXXXXXX`
			# file will contain PSK, limit reading
			chmod 600 $WPA_CONF
			echo "ctrl_interface=/var/run/wpa_supplicant" > $WPA_CONF
			wpa_passphrase $ESSID "$PASSKEY" >> $WPA_CONF	
  		[ $? -ne 0 ] && cat $WPA_CONF && stat_fail && return
		fi
			
		[ "$WPAOPTS" ] || WPAOPTS="-Dwext"
		wpa_supplicant -wB -i ${WIFI_INTERFACE} -c ${WPA_CONF} $WPAOPTS 
		
	  # I dont know how we could determine if wpa_supplicant is ready	
		sleep 2
		let i=0
		while ! wpa_cli status | grep "wpa_state=COMPLETED" >/dev/null 2>&1; do
			if [ $i -gt 10 ]; then
				wpa_cli terminate >/dev/null 2>&1
				ifconfig $WIFI_INTERFACE down
				stat_fail && return
			fi
			sleep 2
			let i++
		done
	fi

	if [ "$IFOPTS" = "dhcp" -o "$IFOPTS" = "DHCP" ]; then
		# remove the .pid file if it exists
		rm -f /etc/dhcpc/dhcpcd-${INTERFACE}.{pid,cache} >/dev/null 2>&1
		dhcpcd $DHCPCD_ARGS $INTERFACE
		[ $? -ne 0 ] && stat_fail && return
	else
		# bring up the interface
		ifconfig $INTERFACE $IFOPTS up
		[ $? -ne 0 ] && stat_fail && return

		# bring up the default route (gateway)
		if [ "$GATEWAY" ]; then
			route add default gw $GATEWAY
			[ $? -ne 0 ] && stat_fail && return
		fi
	fi

	# set the hostname
	if [ "$HOSTNAME" ]; then
		hostname $HOSTNAME
		[ $? -ne 0 ] && stat_fail && return
	fi

	# Generate a new resolv.conf
	if [ "$DNS1" ]; then
		: >/etc/resolv.conf
		[ $? -ne 0 ] && stat_fail && return
		[ "$DOMAIN" ] && echo "domain $DOMAIN"   >>/etc/resolv.conf
		[ "$DNS1" ]   && echo "nameserver $DNS1" >>/etc/resolv.conf
		[ "$DNS2" ]   && echo "nameserver $DNS2" >>/etc/resolv.conf
	fi

	# Save the info in /var/run so we can shut it down later
	mkdir -p $STATE_DIR
	cp $PROFILE_DIR/$1 $STATE_DIR/$INTERFACE
	stat_done
}

menu()
{
	if [ "`ls $PROFILE_DIR 2>/dev/null | grep -v ^template$`" = "" -o ! -d $PROFILE_DIR ]; then
		echo "No profiles found.  Add profiles in $PROFILE_DIR"
		return
	fi
	# scan all profiles
	unset profiles
	DEFAULT=
	i=0
	for prof in `ls $PROFILE_DIR`; do
		# ignore the template
		[ "$prof" = "template" ] && continue
		NAME=$prof

		# if there's a profile called "main", use that as default
		[ "$NAME" = "main" ] && DEFAULT=$NAME
		unset DESCRIPTION
		. $PROFILE_DIR/$NAME
		if [ "$DESCRIPTION" ]; then
			profiles[$i]=$NAME
			i=$((i+1))
			profiles[$i]=$DESCRIPTION
			i=$((i+1))
		fi
	done

	if [ ${#profiles} -eq 0 ]; then
		echo "No profiles were found in $PROFILE_DIR"
		return
	fi

	# if no default yet, use the first entry
	[ "$DEFAULT" = "" ] && DEFAULT=${profiles[0]}

	ANSWER=`mktemp` || exit 1

	if [ "$TIMEOUT" != "" ]; then
		dialog \
			--output-fd 1 \
			--timeout $TIMEOUT \
			--default-item $DEFAULT \
			--menu "Select the network profile you wish to use\n\n            (timeout in $TIMEOUT seconds)" \
			13 50 6 \
			"${profiles[@]}" >$ANSWER
		ret=$?
	else
		dialog \
			--output-fd 1 \
			--default-item $DEFAULT \
			--menu "Select the network profile you wish to use" \
			13 50 6 \
			"${profiles[@]}" >$ANSWER
		ret=$?
	fi

	case $ret in
		1) ;;                                # cancel - do nothing
		255) start_profile $DEFAULT ;;       # timeout - use default
		0)   start_profile `cat $ANSWER` ;;  # user selection
		# abnormal
		*) echo "abnormal ret code from dialog: $ret" ;;
	esac

	rm $ANSWER
}

#
#  Begin
#

if [ "`id -u`" != "0" ]; then
	echo "This script should be run as root."
	exit 1
fi

# Parse command line
MODE="profile"
CHECK=0
PROFILE=
IFACE=
TIMEOUT=
while [ $# -ne 0 ]; do
	case $1 in
		--version) MODE="ver"     ;;
		--help)    MODE="usage"   ;;
		--menu)    MODE="menu"    ;;
		--stopall) MODE="stopall" ;;
		--stop)    MODE="stop"
		           shift
		           IFACE=$1       ;;
		--timeout) shift
		           TIMEOUT=$1     ;;
		--*)       MODE="usage"   ;;
		-c)        CHECK=1        ;;
		-*)        MODE="usage"   ;;
		*)         PROFILE=$1     ;;
	esac
	shift
done

if [ "$MODE" = "profile" -a "$PROFILE" = "" ]; then
	MODE="usage"
fi

# Figure out what we're doing...
[ "$MODE" = "ver" ]     && version
[ "$MODE" = "usage" ]   && usage
[ "$MODE" = "profile" ] && start_profile $PROFILE
[ "$MODE" = "stop" ]    && stop_profile $IFACE
[ "$MODE" = "stopall" ] && stop_all
[ "$MODE" = "menu" ]    && menu

exit 0

# vim: set ts=2 noet:
