#!/bin/bash
#
# see if we can implement a gui network device selector
# using zenity
#
# after the initial device selection,
# wrap most of the script in a "progress" window to allow
# updating as we go w/out the user having to deal w/"OK"
# button
#

set -o nounset

WIFIDRIVER="ipw2100"
MODEMDRIVER="slamr"
MODEMDAEMON="slmodemd"
DISPDELAY=1

FULLPATH="/etc/sysconfig/network-scripts/"
DEVPREFIX="ifcfg-"
DEVLIST=""
UPDEVLIST=""
DEVCHOICE=""
DEVMENU="stopall none none"
LASTSTATUS=""
INDEX=""

# arrays device names, types, and dhcp/ip add
declare -a DEVARRAY
declare -a TYPEARRAY
declare -a ADDARRAY

# get list of all the ifcfg- devices
dev_list()
{
    FULLDEVLIST=$( ls $FULLPATH$DEVPREFIX* )

    # clip the path and ifcfg-, and discard lo
    for FULLDEV in $FULLDEVLIST
    do
        DEV=${FULLDEV/"$FULLPATH$DEVPREFIX"}
        [ $DEV != "lo" ] && DEVLIST="$DEVLIST $DEV"
    done
}

#make arrays of devices, types, and bootproto/ipadds
make_dev_arrays()
{
    DEVARRAY=($DEVLIST)
    ARRAYSIZE="${#DEVARRAY[*]}"

    # get each device's type and ip add/dhcp setting
    # convert all to lower case
    # save triads of info in menu list for zenity --list display

    let INDEX=0
    while [ $INDEX -lt $ARRAYSIZE ]
    do
        . $FULLPATH$DEVPREFIX${DEVARRAY[$INDEX]}
        TYPEARRAY[$INDEX]=$(echo "$TYPE" | tr '[:upper:]' '[:lower:]')
        ADDARRAY[$INDEX]=$(echo "$BOOTPROTO" | tr '[:upper:]' '[:lower:]')
        [ ${ADDARRAY[$INDEX]} = "none" ] && ADDARRAY[$INDEX]=$IPADDR
        DEVMENU="$DEVMENU ${DEVARRAY[$INDEX]} ${TYPEARRAY[$INDEX]} ${ADDARRAY[$INDEX]}"
        let INDEX=INDEX+1
    done
}

#given an device choice, set index into array
get_index()
{
    let INDEX=0
    while [ ${DEVARRAY[$INDEX]} != $DEVCHOICE ]
    do
        let INDEX=INDEX+1
    done
}

# display choices w/add'l info and make selection
# may select more than one - but probably not a
# good idea - may hose routing
display_and_choose()
{
    DEVCHOICE=$( zenity --list --title="$0: select from available interfaces  " \
            --separator=" " --column="device" --column="type" --column="ip add" \
            $DEVMENU 2>&1)
    LASTSTATUS=$?

    if [ $(echo "$DEVCHOICE" | wc -w) -gt 1 ]
    then
        zenity --warning --text="bringing up more than one interface\nmay confuse routing"
        [ $? -ne 0 ] && exit 1
    fi
}

# "down" all interfaces that are up, except lo
everybody_down()
{
UPDEVLIST=$(/sbin/ifconfig | awk '/^[^\ ]/ {print $1}')
    for DEV in $UPDEVLIST
    do
        [ $DEV = "lo" ] && continue
        echo "# ifdown $DEV"
        /sbin/ifdown $DEV
    done
}

# unload modem driver and daemon if running
unload_modem_driver_and_daemon()
{
    echo "# pkill $MODEMDAEMON"
    pkill $MODEMDAEMON
    sleep $DISPDELAY
    echo "# rmmod $MODEMDRIVER"
    if awk '{print $1}' /proc/modules | grep -q $MODEMDRIVER
    then
        /sbin/rmmod $MODEMDRIVER
    fi
}

# unload wifi driver if running
unload_wifi_driver()
{
    echo "# rmmod $WIFIDRIVER"
    if awk '{print $1}' /proc/modules | grep -q $WIFIDRIVER
    then
        /sbin/rmmod $WIFIDRIVER
    fi
}

# load modem driver and start daemon
load_modem_driver_daemon()
{
    echo "# modprobe $MODEMDRIVER"
    /sbin/modprobe $MODEMDRIVER
    LASTSTATUS=$?
    [ $LASTSTATUS -ne 0 ] && return

    echo "# starting modem daemon"
    /usr/sbin/$MODEMDAEMON &
    # allow time for daemon to start
    sleep 3
    LASTSTATUS=0
}

# load the wifi driver
load_wifi_driver()
{
    echo "# modprobe $WIFIDRIVER"
    /sbin/modprobe $WIFIDRIVER
    LASTSTATUS=$?

    # there is a strange interaction that causes the following
    # ifup to hang a _very_ long time before it returns failure
    # status (if it is doomed to fail) if ifup is called immediately
    # after this modprobe

    # if it is going to succeed, no delay seems necessary
    # this is probably an ipw bug -- for now wait 8 seconds

    echo "# pausing 8 seconds"
    sleep 8
}




# -main- starts here
# better be root at this point
if [ $UID -ne 0 ]
then
    zenity --error --text="$0 requires root privileges"
    exit 1
fi

# get list of devices
dev_list
if [ "$DEVLIST" = "" ]
then
zenity --error --text="no valid devices found in $FULLPATH!"
exit 1
fi

# get device names, types, ip adds
make_dev_arrays

# if an arg - use it for device name
if [ $# != "0" ]
then
    for DEVTRY in $DEVLIST
    do
        [ "$DEVTRY" = "$1" ] && DEVCHOICE=$DEVTRY
    done
    if [ "$DEVCHOICE" = "" ]
    then
        zenity --error --text="invalid device choice "$1"!"
        exit 1
    fi
else
# display choices, and return choice
# may be more than one
display_and_choose
[ "$LASTSTATUS" -ne 0 ] && exit 1
fi

# wrap the down and up code in zenity progress window so we
# can update messages and (maybe) exit on error w/out having
# to pop up another window (use 100% as exit)
(
    # "down" anything that is up except lo
    # and turn off any stray device drivers
    everybody_down
    # dhcp interfaces leave multiple copies of dhclient running
    # i don't know if that is bad or good but kill them for now
    pkill dhclient
    echo "20"

    # unload wifi driver and modem driver and daemon
    unload_wifi_driver
    unload_modem_driver_and_daemon
    echo "40"

    # if choice was stopall, we are done
    if [ "$DEVCHOICE" = "stopall" ]
    then
        echo "100"
        echo "# $DEVCHOICE SUCCESS\nclick OK to exit"
        exit 0
    fi

    # get index into devarray for this interface
    get_index

    # if TYPE is modem, start modem driver & daemon
    if [ "${TYPEARRAY[$INDEX]}" = "modem" ]
    then
        load_modem_driver_daemon
        if [ $LASTSTATUS -ne 0 ]
        then
            echo "# load modem driver/daemon FAILURE\nclick OK to exit"
            exit 1
        fi
    fi

    # if TYPE is wifi, load wireless driver
    if [ "${TYPEARRAY[$INDEX]}" = "wireless" ]
    then
        load_wifi_driver
        if [ $LASTSTATUS -ne 0 ]
        then
            echo "# load wifi driver FAILURE\nclick OK to exit"
            exit 1
        fi
    fi

    echo "60"

    # start up the chosen interface
    # NOTE for modems, using wvdial $DEVCHOICE directly
    # instead of ifup in an xterm gets you a "log" for debugging
    echo "# ifup $DEVCHOICE"
    /sbin/ifup $DEVCHOICE
    if [ "$?" -ne 0 ]
    then
        # try to shut down gracefully
        unload_wifi_driver
        unload_modem_driver_and_daemon
        # when modem fails, it leaves pppd and wvdial running...
        pkill -KILL pppd
        # dhcp interfaces leave multiple copies of dhclient running
        # i don't know if that is bad or good but kill them for now
        pkill dhclient
        echo "100"
        echo "# ifup $DEVCHOICE FAILURE\n- all devices shut down -\nclick OK to exit"
        exit 1
    fi
    echo "100"
    echo "# ifup $DEVCHOICE SUCCESS\nclick OK to exit\nmodem will be shut down\nwifi or ethernet stay up"
    exit 0
) | zenity --progress --title="$0: working..." --text="" --percentage=0

# unload modem driver and daemon if running
unload_modem_driver_and_daemon >/dev/null
exit 0