#!/bin/sh
#
# (c) Copyright 2002, 2003, 2005 Stichting Wireless Leiden, all
#     rights reserved. More information can be found on
#     http://wwww.wirelessleiden.nl and the license is at:
#     http://wleiden.webweaving.org:8080/svn/node-config/LICENSE
#
# 1.00 
# ??    Marten Vijn 24-03-03
# ??    new version 14-11-2003 
# 1.03  proxy cleanup, detect faulty files, generalize
#       file list, check node name to be valid, '-n' mode.
#	make moving of final files a bit safer. (dirkx)
# 1.04  Add auto read-only detection. (dirkx)
# 1.05  Cope with WHOST containing a port number. (dirkx).
# 1.06  Better diff (dirkx)
# 1.07  Check versions of OS and Script
#
# If there is a global system configuration file, suck it in.
#

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
TMPDIR=${TMPDIR:-/tmp}
TMPPREFIX=${TMPDIR}/wl-tmp-$$
WHOST=${WHOST:-rambo.wleiden.net}
HTTP_PROXY_DEFAULT=${HTTP_PROXY:-http://proxy.wleiden.net:3128}
HTTP_USER_AGENT=${HTTP_USER_AGENT:-curl.faked.fetch/0.0}
VERSION=1.07
QUIET=${QUIET:-}
PRETEND=no
FORCE=no
CMD=do_move
DLV=no

# Genesis master location.
link=${GENESIS:-http://${WHOST}/cgi-bin/g_list.pl/}
list=filelist

# Location for private config
lcd=${LCDIR:-/lcd}
dir=${lcd}

FETCH=${FETCH:-/usr/bin/fetch}
test -e ${FETCH} || FETCH="curl"

if echo ${FETCH} | grep -q curl; then
	FETCH="${FETCH} --silent"
else
	FETCH="${FETCH} -q"
fi

usage() {
	echo Usage $0 [-q] [-p proxy] [-d] [-D] [-n] [hostname]
	echo "-p <proxy>	Set a proxy"
	echo "-P		Use ${HTTP_PROXY_DEFAULT} as a proxy"
	echo "-D		Use DHCP to get an address"
	echo "-n		Show what would happen - but do not do it"
	echo "-d		Diff met hudiige config (maar doe niets)"
	echo "-q		Suppress all output and user interaction"
	echo "-F		Force disk to write"
	echo "-i		Ignore all safety checks checks"
	exit 1
}

for i in $*
do
	case "$i"
	in
		-D)	connset || exit 1
			;;
		-q)
			QUIET=yes
			;;
		-i)
			DLV=
			;;
		-d)	
			CMD=do_diff
  			dir=${TMPDIR}
			;;
		-p)
			shift;
			HTTP_PROXY=$1
			export HTTP_PROXY
			;;
		-p)
			HTTP_PROXY=HTTP_PROXY_DEFAULT
			export HTTP_PROXY
			;;
		-n)
			PRETEND=yes
			;;
		-F)
			FORCE=yes
			;;
		*)
			test $# -eq 1 || usage
			nodename=$i
			break;
			;;
	esac
	shift
done

HOST=`echo ${WHOST} | sed -e 's/:.*//'`
set `echo $VERSION | sed -e 's/\./ /'`
VERSION_MAJOR=$1
VERSION_MINOR=$2
VERSION_OTHER=$3

# connection test function
connset()
{
	if [ `ps ax | grep -c dhclient` != "1" ] ; then
	        killall dhclient
	fi
  
	echo "Enter an IP address of a nearby Nameserver or use:"
	echo "  1 to use COPE \(on Wleiden\)"
	echo "  2 to use XS4All  \(on the internet\)"
	echo "  3 to use the LCP server \(on the internal LCP networ\)"

	echo -n "IP address or 1/2/3: "
	read dns_list

	case $dns_list in 
	1) 
		resolver="172.17.8.1"
    		;;
	2)   
		resolver="194.109.9.99"
		;;
	3)
		resolver="10.0.0.1"
		;;
	*)
  		resolver=$dns_list 
  	;;
	esac

	cp /etc/resolv.conf /etc/resolv.bak || exit 1
	echo "nameserver ${resolver}" > /etc/resolv.conf


	for nic in `ifconfig -l`
	do
	case ${nic} in
	lo0 | wi*) 
		;;
  	*) 
		if ping -qnoc ${HOST}; then
			echo Connection on interface ${nic} to ${HOST} ok.
  		else
			killall dhclient
			echo Trying to get a DHCP lease on ${nic}
			dhclient -1 ${nic}
  		fi
  		;; 
  	esac
	done
}

log()
{
	if [ -z ${QUIET} ]; then  
  		echo "$*"
  	fi
}
lognlr()
{
  	if [ -z ${QUIET} ]; then  
  		echo -n "$*"
  	fi
}

cleanse()
{
	rm -f ${TMPPREFIX}.?
}

# Normal exit; but make sure
# we also clean up any tmp files
#
cleanexit()
{
	E=1
	if [ $# -gt 0 ]; then
		E=$1
	fi
	cleanse
	log Exit
	exit $E
	# Trap any weird exit codes.
	exit 1
}

safefetch() 
{
	url=$1
	file=$2
	${FETCH} -o - ${url} > ${TMPPREFIX}.x \
		    || cleanexit 1

	# Genesis can provide us with corrupted/empty files
	# with a 200 OK - so insist that they are at least
	# a few lines long.
	#
	set `wc -l ${TMPPREFIX}.x`
	if [ $1 -lt 2 ]; then
		echo File ${link}${nodename} is less than 2 lines long.
		echo Assuming a problem with Genesis.
		cleanexit 2
	fi

	cp ${TMPPREFIX}.x ${file} \
	    || cleanexit 1
	rm -f ${TMPPREFIX}.x

	return 0
}

getvalidnodenames()
{
	log Fetching list of nodes from ${link}
	safefetch ${link} ${nlist} || cleanexit 1
}

getvalidnodename()
{
while ! grep -q "^${nodename}\$" ${nlist}
do
  echo Nodes:
  if [ -x /usr/bin/column ]; then
	column  ${nlist}
  else
  	cat ${nlist}
  fi
  echo
  echo -n enter nodename \[default: ${default}\]:
  if [ -z ${QUIET} ]; then  
    read nodename
  else
    nodename=${default}
  fi

  if [ "x${nodename}" = "x" ]; then
    nodename=${default}
  fi
done

echo Node Selected: ${nodename}
}


do_diff() {
	if test -e $lcd/$1; then
		diff -uwbB $lcd/$1 $dir/$1.new
	else
		echo Warning: $lcd/$1 does not yet exist - no DIFF
	fi
}

do_move() {
	if [ -e $dir/$1 ]; then
		mv $dir/$1 $dir/$1.bak  || cleanexit 1
	fi
	cp $dir/$1.new $dir/$1 || cleanexit 1
	rm $dir/$1.new || cleanexit 1
}

linkin() {
  symdir=$1
  file=$2

  if [ ${PRETEND} = 'yes' ]; then
	echo "** $CMD $*"
   else
  	$CMD $file || exit 1
   fi

   test -e $symdir/$file || (
		echo WARNING: Symlink $symdir/$file not in place.
		echo use:   ln -s $dir/$file $symdir/$file  
		echo to fix if appropriate.
	)
}

log Config Node -- Version: $VERSION '$Rev: 5004 $'

# Make sure we clean up our mess when needed.
trap "rm -f ${TMPPREFIX}.?; echo Failed; exit 1;" 2 3

if [ ${PRETEND} != 'yes' -a ${CMD} != 'do_diff' ]; then
	if mount | grep "on / " | grep -q read-only; then
		if [ ${FORCE} = "yes" ]; then
			echo Forcing read-only disk into rw.
			fsck / || exit 2
			mount -o noatime -u -w / || exit 2 || exit 1
			trap "mount -u -r /; rm -f ${TMPPREFIX}.?; echo Failed; exit 1;" 2 3
			FORCE=rw
		else
			echo ERROR - disk / is mounted read only. Aborting.
			exit 1
		fi
	fi
fi

export HTTP_USER_AGENT
export TMPDIR


#check config dir
#
if  [ ! -d ${dir}  ]; then 
  mkdir -p ${dir} || cleanexit 1
fi

if [ -z ${HTTP_PROXY} ]; then
  	(
		log Checking DNS for ${HOST}
		host ${HOST} > /dev/null || exit 1
		log Checking if ${HOST} can be reached
		ping -qnoc 1 ${HOST} > /dev/null || exit 1
		log Connection: Ok
		exit 0
	) || connset
else
	log Connection not checked because there is an http proxy configured: ${HTTP_PROXY}.
fi

if [ -r ${lcd}/myname ]; then
    default=`cat ${lcd}/myname`
else
    default=`hostname -s`
    test -z $default && default=none
fi

if [ ! -z ${QUIET} ]; then
	if [ -z ${nodename} ]; then
		nodename=${default}
	fi
fi


nlist=${TMPPREFIX}.l

test -z $default && default=$nodename

getvalidnodenames || exit 1

test -z $nodename && getvalidnodename

while test -z $nodename || ! grep -q ${nodename} ${nlist}
do
	echo
	echo Error: Node named \"$nodename\" not known.
  	if [ -z ${QUIET} ]; then  
		exit 1
	fi
	echo Please select one from the list.
	echo
	getvalidnodename
done

lognlr "Checking release and OS versions: "

safefetch ${link}${nodename}/info $dir/info.last \
	|| cleanexit 1

OS=`uname -s`
REL=`uname -r`
set -- `head -1 $dir/info.last`

# FreeBSD 5.0-RELEASE 1 YES
if [ $# != 4 ]; then
	echo Info verification failed.
	cleanexit 1
fi
if [ x$4 != 'xYES' ]; then
	echo Genesis marked as disabled for this machine.
	test -z ${DLV} || cleanexit 1
fi
if [ 0$3 -ne $VERSION_MAJOR ]; then
	echo This script is version $VERSION, genesis info is for version $3.xx
	test -z ${DLV} || cleanexit 1
fi
if [ x$1 != x$OS ]; then
	echo Operating system mismatch; this machine: $OS, but config is for $1
	test -z ${DLV} || cleanexit 1
fi
if [ x$2 != x$REL ]; then
	echo This machine runs $REL, but the configuration is for $2
	test -z ${DLV} || cleanexit 2
fi

log Ok

log Fetching file list from $link for $nodename

safefetch ${link}${nodename} ${dir}/${list}  

lognlr "Fetching:"
for i in `cat ${dir}/${list}`
do
  lognlr " ${i}"
#  $FETCH -o - ${link}${nodename}/${i} > ${dir}/${i}.new || cleanexit 1
   safefetch ${link}${nodename}/${i} ${dir}/${i}.new 
done
log .

for i in  `cat ${dir}/${list}`
do
	case ${i} in
	linux.sh | config | txtconfig ) 
		# log obsolete file: ${i} - skipped
		;; 
	resolv.conf | rc.node.local | rc.local)
		linkin /etc ${i}
		;;
	snmpd.local.conf)
		linkin /usr/local/share/snmp ${i}
		;;
	named.conf)
		linkin /etc/namedb ${i}
		;;
	dhcpd.conf)
	 	linkin /usr/local/etc ${i}
		;;
	zebra.conf | ospfd.conf)
        	linkin /usr/local/etc/zebra ${i}
		;;
	authorized_keys)
		linkin /root/.ssh ${i}
		;;
	ssh_known_hosts)
		linkin /etc/ssh ${i}
		;;
	daemons.sh)
		linkin /wl ${i}
		;;
	*)
		echo Script cannot cope with ${i} - ignoring..
		;;
	esac
done

if [ -e /etc/rc.local ]; then
  # See if we are in rc.local
  if grep -q /config-node.sh /etc/rc.local; then

    echo As this node now has real configs - do enter a root password
    echo
    passwd \
      || cleanexit 1

    echo Removing /etc/rc.local
    rm -f /etc/rc.local
  
    echo Will drop write perms on the next reboot.
  fi
fi

# Record our name.
echo ${nodename} > ${dir}/myname

# Rebuild reverse lookups
if test -e /etc/rc.node.local; then
	H=`cat /etc/rc.node.local | grep hostname | sed -e s/hostname=// | sed -e s/[\"\']//g`
	hostname $H
else
	echo Warning: rc.node.local missing.
fi

if [ -r  /etc/namedb/make-localhost -a ${CMD} != 'do_diff'  ]; then
  (
    cd /etc/namedb || exit 1
    sh /etc/namedb/make-localhost || exit 1
  ) || exit 1
fi

cleanse || exit 1

if [ -e /etc/rc.empty.conf ] ; then
	rm /etc/rc.empty.conf || exit 1
	echo removed /etc/rc.empty.conf - and rebooting in 30 seconds \(or press ctrl-C to abort\)
	read -t 30 DUMMY
	reboot
fi

test ${FORCE} = 'rw' && mount -u -r /
exit 0
