#!/bin/bash
#******************************************************************
#$ident: @(#) netenv 0.94 Time-stamp: <03/07/31 21:35:06 bav> $
#******************************************************************
#                            Gerd Bavendiek  bav@epost.de  97-05-00
#
# This script is used to set up a file containing information about
# the actual network environment. This can be esp. useful for a
# laptop being used in multiple environments: at home, in the office,
# at a customer site.
#
# After the comment section has become quite large, I swapped it to a
# netenv.html file. 
#
# netenv will fail when there is no dialog(1) or gdialog found !
#
# As of version 0.81 netenv will try to use "math" when setting up a
# new environment. math is work of Bruce Perens <Bruce@Pixar.com>. To
# avoid conflicts with e.g. Mathematica it has been renamed to trpnc.
#-------------------------------------------------------------------
NETENV_VERSION="0.94"

# Security check
NO_NOT_BY_ROOT_OWNED_FILES=`find /etc/netenv ! -user 0 | wc -l | awk '{print $1}'`
NO_GROUP_WRITABLE_FILES=`find /etc/netenv -type f -perm -060 | wc -l | awk '{print $1}'`
NO_WORLD_WRITABLE_FILES=`find /etc/netenv -type f -perm -006 | wc -l | awk '{print $1}'`
if [ $NO_NOT_BY_ROOT_OWNED_FILES != "0" -o $NO_GROUP_WRITABLE_FILES != "0" -o $NO_WORLD_WRITABLE_FILES != "0" ]; then
   echo netenv: Security check failed, fix permissions in /etc/netenv !
   echo NO_NOT_BY_ROOT_OWNED_FILES=$NO_NOT_BY_ROOT_OWNED_FILES NO_GROUP_WRITABLE_FILES=$NO_GROUP_WRITABLE_FILES NO_WORLD_WRITABLE_FILES=$NO_WORLD_WRITABLE_FILES
   exit 1
fi

###set -x
# When located in /tmp, script must be called
# AFTER wiping out /tmp has been done ...
NETENV_FIL=`tempfile -n /tmp/netenv 2>/dev/null`
# At least older Debian system don't know tempfile; the following
# statement should deal with this situation
if [ $? -ne 0 ]; then NETENV_FIL=/tmp/netenv; fi

NETENV_BASE=/etc/netenv
COLS=68

TMPFIL=`tempfile -d /tmp -p dialo > /dev/null 2>&1`
if [ $? -ne 0 ]; then TMPFIL=/tmp/netenv.tmp.$$; fi

MATH=/usr/bin/trpnc # Needed only when setting up a new environment, see
	            # function get_netenvdata()

###TERM=linux; export TERM # We are called from init, so we need to know

# Some functions ...
DIALOG=gdialog
if ! type gdialog > /dev/null 2>&1; then
   if ! type dialog > /dev/null 2>&1; then
      echo Neither gdialog nor dialog found, aborting ...
      echo Install packages gnome-utils or dialog to fix !
      exit 1
   fi
   DIALOG=dialog
fi
ExitOnCancel() { echo "You have canceled the setup routine. No Network \
configuration will be done !"; exit 1; }
ExitOnError() { echo "An unknown error ocurred during setup. No Network \
configuration will be done !"; exit 1; }

first() { echo $* | cut -f1 -d" "; }
second() { echo $* | cut -f2 -d" "; }
third() { echo $* | cut -f3 -d" "; }
fourth() { echo $* | cut -f4 -d" "; }

CheckReturnVal()
{
   case $? in
      0) ;;
      1) ExitOnCancel;;
      *) ExitOnError;;
   esac
}
CheckNoInput()
{
   if [ "$1" = "" ]; then 
      echo "You did not respond with input. No Network \
       configuration will be done !"
      exit 1
   fi
}


get_netenvdata()
{   
   # Executable assigned by $MATH is being used. If it's not available,
   # don't panic, just a loss of convenience ...

   while true
   do
      
      $DIALOG --inputbox "IP-Address\nEnter the current IP-address or the keyword dhcp ..." \
       9 $COLS $IPADDR 2>$TMPFIL
      CheckReturnVal
      IPADDR=`cat $TMPFIL`
      case $IPADDR in 
         [dD][hH][cC][pP])
            # Maybe this is SuSE specific. RedHat / Debian users feedback appreciated !
            BOOTPROTO='dhcp'
            # This is a rather crude attempt to distinguish between
            # onboard and PCMCIA-NIC's.
            STARTMODE='hotplug' # Default is PCMCIA-NIC
	    # cardmgr is (hopefully) not running at this time, so if
	    # there is a eth0, it must be onboard
            if dmesg | grep eth0 >/dev/null 2>&1; then STARTMODE='onboot'; fi
           ;;
         *)      
      CheckNoInput $IPADDR
      ipa=`echo $IPADDR | sed 's/\./ /g'`
      I1=`first $ipa`
      I2=`second $ipa`
      I3=`third $ipa`
      I4=`fourth $ipa`

      # Just a wild guess ...
      NETMASK=255.255.255.0
      
      $DIALOG --inputbox "Netmask\nEnter the netmask of the current subnet ..." \
       9 $COLS $NETMASK 2>$TMPFIL
      CheckReturnVal
      NETMASK=`cat $TMPFIL`
      CheckNoInput $NETMASK

      netm=`echo $NETMASK | sed 's/\./ /g'`
      N1=`first $netm`
      N2=`second $netm`
      N3=`third $netm`
      N4=`fourth $netm`
      R1=`$MATH $I1 $N1 and`
      R2=`$MATH $I2 $N2 and`
      R3=`$MATH $I3 $N3 and`
      R4="0"
      NETWORK="$R1.$R2.$R3.$R4"
      
      $DIALOG --inputbox "Network\nEnter the IP-Address of the current network ..." \
       9 $COLS $NETWORK 2>$TMPFIL
      CheckReturnVal
      NETWORK=`cat $TMPFIL`
      CheckNoInput $NETWORK

      R1=`$MATH $N1 not 255 and $I1 or`
      R2=`$MATH $N2 not 255 and $I2 or`
      R3=`$MATH $N3 not 255 and $I3 or`
      R4=`$MATH $N4 not 255 and $I4 or`
      BROADCAST="$R1.$R2.$R3.$R4"
      
      $DIALOG --inputbox "Broadcast\nEnter the broadcast-Address of the current network ..." \
       9 $COLS $BROADCAST 2>$TMPFIL
      CheckReturnVal
      BROADCAST=`cat $TMPFIL`
      CheckNoInput $BROADCAST

      R1=`$MATH $I1 $N1 and`
      R2=`$MATH $I2 $N2 and`
      R3=`$MATH $I3 $N3 and`
      GATEWAY="$R1.$R2.$R3.1"
      
      $DIALOG --inputbox "Gateway\nEnter the Gateway-Address of the current network ..." \
       9 $COLS $GATEWAY 2>$TMPFIL
      CheckReturnVal
      GATEWAY=`cat $TMPFIL`
      # Don't check for GATEWAY, no input simply means closed shop -
      # which may be useful.

      # As of 0.92 I remove PROFILE. It's confusing people ...

      # As of 0.92 add Nameserver. Comes in handy from time to
      # time. Useful only when GATEWAY is set.
      if [ -n "$GATEWAY" ]; then 
         $DIALOG --inputbox "Nameserver\nEnter the IP-address of the current nameserver ..." \
         9 $COLS $GATEWAY 2>$TMPFIL
         CheckReturnVal
         DNS_1=`cat $TMPFIL`
         # Don't check for input - there may be no nameserver
      fi      
      ;;
esac
      (
      echo "The current contents of your /tmp/netenv is as follows:"
      echo
      echo "# Networkenvironment: netask"

      if [ "$BOOTPROTO" = "dhcp" ] ; then
         echo export BOOTPROTO=$BOOTPROTO
         echo export STARTMODE=$STARTMODE
      else
         echo export IPADDR=$IPADDR
         echo export NETWORK=$NETWORK
         echo export NETMASK=$NETMASK
         echo export BROADCAST=$BROADCAST
         if [ ! -z "$GATEWAY" ]; then
            echo export GATEWAY=$GATEWAY
         fi
         if [ ! -z "$DNS_1" ]; then
            echo export DNS_1=$DNS_1
         fi
      fi
      echo -e "\n\n\n\n\n"
      echo "Answer <Yes> if that looks ok, otherwise <No>"
      echo
      ) > $TMPFIL
	 
      $DIALOG --yesno "`cat $TMPFIL`" 20 72
	 
      if [ $? -eq 0 ]; then
	 (
	 echo "# Networkenvironment: netask"
         if [ "$BOOTPROTO" = "dhcp" ] ; then
            echo export BOOTPROTO=$BOOTPROTO
            echo export STARTMODE=$STARTMODE
         else
	    echo export IPADDR=$IPADDR
	    echo export NETWORK=$NETWORK
	    echo export NETMASK=$NETMASK
	    echo export BROADCAST=$BROADCAST
	    if [ ! -z "$GATEWAY" ]; then
	       echo export GATEWAY=$GATEWAY
	    fi
 	    if [ ! -z "$DNS_1" ]; then
 	       echo export DNS_1=$DNS_1
 	    fi
         fi
	 ) > $NETENV_FIL
	 rm -f $TMPFIL
         break
      else	
	 $DIALOG --yesno "Do you want to repeat the setup process ? " 5 72
	 if [ $? -eq 1 ]; then exit 1; fi		   
      fi
   done

   chmod 644 $NETENV_FIL

   $DIALOG --yesno "Do you want to save this configuration ?" 5 72
   if [ $? -eq 0 ]; then
      $DIALOG --inputbox "Configuration name\nEnter the name under which\
 the configuration should be stored ..." \
       9 $COLS  2>$TMPFIL
      CheckReturnVal
      NETENV=`cat $TMPFIL`
      CheckNoInput $NETENV
      NETCONF_FIL="$NETENV_BASE/"$NODE"-"$NETENV
      cp $NETENV_FIL $NETCONF_FIL # As of 0.92 omit -p (scripts clean /tmp)  
   fi
} # End Function get_confdata

choose_network_environment()
{
   ITEM_LIST="" # have to be reentrant as of 0.93 ...
   # The ls gives a list of files starting with the current node name,
   # excluding emacs backup files. The list starts with the default
   # and ends with ask.
   for i in `ls $NETENV_BASE/$NODE $NETENV_BASE/$NODE-*[0-9a-zA-Z]`
   do
      netenv_id="unknown"
      eval `grep netenv_id $i`
      SUFFIX=`basename $i | cut -d '-' -f2-`
      # Maybe something like lulu or foo-bar or lulu-no-eth or foo-bar-no-eth
      SUFFIX=`basename $i`
      if [ $SUFFIX != $NODE ]; then
         LENGTH=$((${#NODE}+1))
         SUFFIX=${SUFFIX:$LENGTH}
      fi
      ITEM_LIST=$ITEM_LIST" "$SUFFIX" "$netenv_id
   done
   
   ITEM_LIST=$ITEM_LIST" "new" "Set_up_new_environment
   $DIALOG --menu "netenv $NETENV_VERSION on $NODE running `uname -s` `uname -r`\n\nChoose your current network-environment !" \
    20 $COLS 12 $ITEM_LIST 2>$TMPFIL
} # End Function choose_network_environment

# End of function defining

# Let's do the work ...
case $1 in
   '-h'|'--help'|'-?'|'help')
      echo Version $NETENV_VERSION
      echo Docs and examples in /usr/share/doc/packages/netenv
      echo Latest versions see http://netenv.sourceforge.net
      exit 0
   ;;
esac

NODE=`uname -n`
###NODE=foo-bar  # TODO
# The following block will hopefully get us a valid NETENV. It is
# skipped for those, who still prefer input at the boot prompt 
if [ -z "$NETENV" ]; then
   choose_network_environment
   if [ $? -ne 0 ]; then
      $DIALOG --yesno "Do you want to enter expert mode ? " 5 72
      if [ $? -eq 0 ]; then
         /bin/sh
	 choose_network_environment
      else
         echo "You didn't choose a network environment - good luck !"
	 rm -f $TMPFIL
         exit 0
      fi
   fi
   NETENV=`cat $TMPFIL` && rm -f $TMPFIL
   # Deal with special cases
   if [ "$NETENV" = new ]; then
      :
   elif [ "$NETENV" = $NODE ]; then
      NETENV=""
      echo "netenv: File $NETENV_BASE/$NODE will be used for setting up the network environment ..."
   else	
      echo "netenv: File $NETENV_BASE/$NODE"-"$NETENV will be used for setting up the network environment ..."
   fi
else
   # Continue here, if variable NETENV has been set up as boot argument
   echo "netenv: Using provided NETENV=$NETENV ..."
fi

# Define the file holding the current network-environment
# configuration. Directory is $NETENV_BASE, filename is e.g. foo-off
# for the current system named "foo" and the Variable NETENV=off
# (Laptop "foo" used in the office). If NETENV has not been defined,
# look for file <nodename>, e.g. "foo".

# Handle special case: ask for environment
if [ "$NETENV" = new ]; then
   NETCONF_FIL="$NETENV_BASE/"$NODE"-"$NETENV
   if [ -r $NETCONF_FIL ]; then
      . $NETCONF_FIL
   fi

   get_netenvdata

   # At this point we assume to have a valid NETENV_FIL, eventually a
   # NETCONF_FIL too. The latter is not a must. If the user decided
   # not to store the data it may be a once-and-never-again environment.

elif [ -z "$NETENV" ]; then
   # Variable NETENV has not been defined or assigned, probably on
   # home tower or something like that ...
   # This is the default !
   NETCONF_FIL="$NETENV_BASE/"$NODE
else
   NETCONF_FIL="$NETENV_BASE/"$NODE"-"$NETENV
fi	

if [ -r $NETCONF_FIL ]; then
   cp $NETCONF_FIL $NETENV_FIL # As of 0.92 omit -p (scripts clean /tmp)   
   chmod 644 $NETENV_FIL
else
   echo "netenv: Using temporary configuration data ..."
fi

. $NETENV_FIL

# If NETENV_SCRIPT has been defined, run it. Of course this is done as
# root. There is no NIC configured yet !
if [ -r "$NETENV_SCRIPT" ]; then
   if [ -z "$NETENV" ]; then
      PROFILE=default
   else
      PROFILE=$NETENV
   fi
   echo "executing $NETENV_SCRIPT $PROFILE ..."
   . $NETENV_SCRIPT $PROFILE
fi

rm -f $TMPFIL

# New as of 0.93. If netenv is not run during boot but on the fly, ask the user, if
# he wants to restart the network
if [ `tty` != /dev/console ]; then
   $DIALOG --yesno "Do you want to activate changes by restarting the network ? " 5 72
   if [ $? -eq 0 ]; then
      if grep 'Red Hat' /etc/issue > /dev/null; then
	 /etc/init.d/network restart 
      elif grep SuSE /etc/issue > /dev/null; then
         /etc/init.d/network restart
         # As of SuSE 8.0 route has gone. Still here for 7.3 Users ...
         if [ -x /etc/init.d/route ]; then /etc/init.d/route restart; fi
      fi
   fi
fi
