#!/sbin/runscript
# Charlie's modified version /etc/init.d/eagle-adsl
# should allow to have other ppp links up at the same time.
# should have got rid of the race condition which seemed to show when 
#   doing a restart

PPP=$(which pppd 2>/dev/null)
EAGLECTRL=$(which eaglectrl 2>/dev/null)
UMOUNT=$(which umount 2>/dev/null)
IFCONFIG=$(which ifconfig 2>/dev/null)
GREP=$(which grep 2>/dev/null)
LSMOD=$(which lsmod 2>/dev/null)
MAX_LOOP=160
EAGLESTAT=$(which eaglestat 2>/dev/null)
DHCPCD=$(which dhcpcd 2>/dev/null)
ROUTE=$(which route 2>/dev/null)
LOGGER=$(which logger 2>/dev/null)

LINKPIDFILE="/var/run/ppp-$LINKNAME.pid"  
# pipe output to $LOGGERCMD to either get it to go to logger or to /dev/null
LOGGERCMD="cat"
case "$DEBUG" in 
  YES|yes)
      [ -x ${LOGGER} ] && LOGGERCMD="${LOGGER} -t eagle-adsl" 
      ;;
esac

check_pre_run () {
    # Check module is loaded
    (${LSMOD} | ${GREP} -q 'eagle-usb'); eend $? "Module eagle-usb is not loaded." || return 1

    # Check for eaglectrl
    [ -x ${EAGLECTRL} ] ; eend $? "Cannot find eaglectrl" || return 1

    # And showstat
    [ -x ${EAGLESTAT} ] ; eend $? "Cannot find eaglestat" || return 1        

    # And options
    [ "${OPTIONS:-set}" != set ] ; eend $? "Please define OPTIONS in /etc/conf.d/eagle-usb" || return 1
    [ -f ${OPTIONS} ] ; eend $? "Can't find OPTIONS file ${OPTIONS}" || return 1

    # And DSP
    [ "${DSP:-set}" != set ] ; eend $? "Please define DSP in /etc/conf.d/eagle-usb" || return 1
    [ -a ${DSP} ] ; eend $? "Can't find DSP file ${DSP}" || return 1

    # And synchro timeout
    [ "${SYNCHRO_TIMEOUT:-set}" != set ] ; eend $? "Please define SYNCHRO_TIMEOUT in /etc/conf.d/eagle-usb" || return 1

    # And linkname
    [ "${LINKNAME:-set}" != set ] ; eend $? "Please define LINKNAME=\"eagle\" in /etc/conf.d/eagle-usb" || return 1
    
    # Check usbdevfs is up and running  ?should we eend if mount fails?
    ( ${MOUNT} | ${GREP} -q usbdevfs) || ${MOUNT} none /proc/bus/usb -t usbdevfs >/dev/null 2>&1

    return 0
}


check_ppp () {

    # Check for PPP
    [ ! -z ${PPP} ] ; eend $? "failed to find ppp" || return 1

    # Check for PEER file
    [ "${PEER:-set}" != set ] ; eend $? "Please define \$PEER in /etc/conf.d/eagle-usb" || return 1
    [ -f /etc/ppp/peers/${PEER} ]  ; eend $? "Failed to find peer ${PEER} configuration" || return 1

    # Check for IFCONFIG
    [ -x ${IFCONFIG} ]; eend $? "Failed to find 'ifconfig'" || return 1
}

check_dhcpcd () {

    # check for DHCPCD
    [ ! -z ${DHCPCD} ] ; eend $? "failed to find dhcpcd" || return 1
    
    # Check for IFCONFIG
    [ -x ${IFCONFIG} ]; eend $? "Failed to find 'ifconfig'" || return 1

    # Check for ROUTE
    [ -x ${ROUTE} ]; eend $? "Failed to find 'route'" || return 1

}

launch_pppd () {
    local RETURNED=1
    local LOOP=0

    echo "Starting Link $LINKNAME" | ${LOGGERCMD}  > /dev/null
    einfo "Launching PPP daemon ..."

    # Get interface name
    export EAGLE_IF=`${EAGLECTRL} -i`

    # Set network interface
    /sbin/ifconfig ${EAGLE_IF} 192.168.60.30 netmask 255.255.255.0 up

    # have to use a pidfile as well as exec, so we can use pppd for other things
    # pppd will also give us a file containing both interface name and pid if we
    # use the linkname option
    start-stop-daemon --start --pidfile "$LINKPIDFILE"  --exec  ${PPP} call ${PEER} linkname $LINKNAME ${PPPDOPTIONS} | "$LOGGERCMD"  >/dev/null 2>&1

    # Wait for connection to be established
    while [ ${RETURNED} -ne 0 ] && [ ${LOOP} -le ${MAX_LOOP} ] ; do
	let LOOP=LOOP+1
	sleep 1
        #I'm not sure whether to do this every iteration, but it can't hurt...  
        find_eagle_pppif
        TMP=$?
	echo "Waiting for link $LINKNAME (${PPP_INTERFACE}) to start: $LOOP of $MAX_LOOP" |  ${LOGGERCMD} > /dev/null
        if [ $TMP  -eq  0 ] ;  then 
	  # echo "Waiting for link $LINKNAME (${PPP_INTERFACE}) to start"
          # shouldn't confuse ppp1 and ppp10
  	  ${IFCONFIG} | grep -q "${PPP_INTERFACE}[[:space:]]"
	  RETURNED=$? 
	fi
    done
    
    if [ ${LOOP} -gt ${MAX_LOOP} ] && [ ${RETURNED} -ne 0 ] ; then
	echo "Link $LINKNAME (${PPP_INTERFACE}) failed to start" |  ${LOGGERCMD}  > /dev/null
	return 1
    else
	echo "Link $LINKNAME (${PPP_INTERFACE}) started" |  ${LOGGERCMD}  > /dev/null
	return 0
    fi
}

stop_ppp () {

    local RETURNED=1
    local LOOP=0
    echo "Stopping Link $LINKNAME (${PPP_INTERFACE})" |   ${LOGGERCMD} > /dev/null
    find_eagle_pppif ;

    if [ -f $LINKPIDFILE ]
    then
	start-stop-daemon --stop --pidfile $LINKPIDFILE  pppd    

       # Wait for connection to go away
       while [ ${RETURNED} -ne 0 ] && [ ${LOOP} -le ${MAX_LOOP} ] ; do
          let LOOP=LOOP+3
          sleep 1
	  echo "Waiting for link $LINKNAME (${PPP_INTERFACE}) to go away" |  ${LOGGERCMD}  > /dev/null
          find_eagle_pppif ;
	  # could just use return value of find_eagle_pppif? 
	  # but then would have to check whether the interface exists and delete the pidfile if it doesn't? but then would have a race condition?
  	  ${IFCONFIG} | grep -q "${PPP_INTERFACE}[[:space:]]"
          RETURNED=$?
       done
    
       if [ ${LOOP} -gt ${MAX_LOOP} ] && [ ${RETURNED} -ne 0 ] ; then
	   echo "Link $LINKNAME (${PPP_INTERFACE}) failed to stop" | ${LOGGERCMD}  > /dev/null
           return 1
       else
	   echo "Link $LINKNAME (${PPP_INTERFACE}) stopped" |  ${LOGGERCMD}  > /dev/null
           return 0
       fi
    else
      echo "File $LINKPIDFILE not found" |   ${LOGGERCMD} > /dev/null
      return 1
    fi
}


launch_dhcpcd () {
    # Get interface
    export EAGLE_IF=`${EAGLECTRL} -i`

    # Launch dhcpcd
    start-stop-daemon --start --exec ${DHCPCD} ${EAGLE_IF} >/dev/null 2>&1
    ${ROUTE} add default ${EAGLE_IF}

}


stop_dhcpd () {
    # Get interface
    export EAGLE_IF=`${EAGLECTRL} -i`

    # Stop dhcpcd
    start-stop-daemon --stop --quiet --pidfile /var/run/dhcpcd-${EAGLE_IF}.pid


}

modem_is_operational () {
    # To be operational, firmware should be loaded. This mean, /proc/driver/eagle-usb
    # directory is not empty
    if ls /proc/driver/eagle-usb/* 1>/dev/null 2>&1
    then
	# Check "Modem is operational"
	${EAGLESTAT} | grep -q "Modem is operational"
    else
	return 1
    fi
}

load_and_sync () {
    # Load firmware /DSP/ etc only if the modem is not yet operational
    if modem_is_operational 
    then
	einfo "Modem already operational"
    else
	einfo "Loading firmware, DSP and trying to sync ..."
	${EAGLECTRL} -w -o ${OPTIONS} -d ${DSP} -s ${SYNCHRO_TIMEOUT} | \
	                                          ${LOGGERCMD} 1>/dev/null 2>&1
    fi

    return $?
}

depend () {
    after *
}


find_eagle_pppif()
{
   # identify which ppp interface is using the eagle.
   # returns zero for success, 1 if interface not found.
   PPP_INTERFACE=""
   #   LINKPIDFILE is defined at top of script-  "/var/run/ppp-${LINKNAME}.pid"
   # ppp kindly gives us both the PID and the interface name in the file 
   if [ -r "$LINKPIDFILE" ] ; then
       LINKPID=`grep -o -E '^[0-9]+'  "${LINKPIDFILE}"`
       PPP_INTERFACE=` grep -o -E '^ppp[0-9]+' "${LINKPIDFILE}"`
   fi
   if [ -z "$PPP_INTERFACE" ] ; then 
       return 1 ;
   else
       return 0 ;
   fi
}

    
start () {


    
    ebegin "Starting eagle-adsl ..."
    
    # Check everything needed is in place
    check_pre_run ; eend $? "Pre-requesites check failed" || return 1

    # Let's try to upload firmware/dsp and do synchro
    load_and_sync ; eend $? "Failed to load or sync" || return 1


    if [ ${ROUTEDIP} -eq 1 ] ;
    then
	# launching dhcpcd
	launch_dhcpcd ; eend $? "Failed to start dhcpcd daemon." || return 1
    else
        # launching ppp daemon
	launch_pppd ; eend $? "Failed to start pppd daemon." || return 1
    fi

    # Cool .. we're plugged ..
    return 0
}
    
stop () {
    export EAGLE_IF=`${EAGLECTRL} -i`

    ebegin "Shutting down eagle-adsl..."

    if [ ${ROUTEDIP} -eq 1 ] ;
    then
	stop_dhcpd ; eend $? "Failed to stop 'dhcpcd'"
    else
	stop_ppp ; eend $? "Failed to stop 'pppd'"
    fi

    ifconfig ${EAGLE_IF} down 1>/dev/null 2>&1


}



