#!/bin/sh
 
#
# "SystemImager" - Copyright (C) 1999-2001 Brian Elliott Finley <brian@systemimager.org> 
#
# Others who have contributed to this code (in alphabetical order):
#   Jose AP Celestino <japc@sl.pt>
#
# This file: prepareclient
#            (prepareclient is used to, well, prepare a client to have it's
#             image retrieved by an imageserver)
#


# set version
version_number=2.0.1

# configuration directory
systemimagerdir="/etc/systemimager"

# set path
PATH=/bin:/usr/bin:/sbin:/usr/sbin

 
### BEGIN functions
# SystemImager specific functions
create_rsyncd_conf() {
  echo '#'                                                      > $rsyncd_conf_file
  echo '# Copyright (C) 1999-2001 Brian Elliott Finley <brian@systemimager.org>'    >> $rsyncd_conf_file
  echo '#'                                                      >> $rsyncd_conf_file
  echo '# This file: /tmp/rsyncd.conf'                          >> $rsyncd_conf_file
  echo '#'                                                      >> $rsyncd_conf_file
  echo ''                                                       >> $rsyncd_conf_file
  echo 'list = yes'                                             >> $rsyncd_conf_file
  echo 'timeout = 600'                                          >> $rsyncd_conf_file
  echo 'dont compress = *.gz *.tgz *.zip *.Z *.ZIP *.bz2 *.deb *.rpm *.dbf'  >> $rsyncd_conf_file
  echo 'uid = root'                                             >> $rsyncd_conf_file
  echo 'gid = root'                                             >> $rsyncd_conf_file
  echo ''                                                       >> $rsyncd_conf_file
  echo '[root]'                                                 >> $rsyncd_conf_file
  echo '    path = /'                                           >> $rsyncd_conf_file
  echo ''                                                       >> $rsyncd_conf_file
}

show_version() {
  echo "prepareclient (part of SystemImager) version $version_number"
  echo ""
  echo "Copyright (C) 1999-2001 Brian Elliott Finley <brian@systemimager.org>"
  echo "This is free software; see the source for copying conditions.  There is NO"
  echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
}

show_usage() {
  show_version
  echo ''
  echo 'Usage: prepareclient [OPTION]...'
  echo ''
  echo 'Options: (only one option is taken)'
  echo ' -version                 Display version and copyright information.'
  echo ' -h, -help                Display this output.'
  echo ' -e, -explicit-geometry   Leave partition information for getimage'
  echo '                          using explicit disk geometry.  The default'
  echo '                          is to use megabytes which allows getimage'
  echo '                          to create an autoinstall script that will'
  echo '                          work with client disks of different geometries'
  echo '                          and sizes (within reason).'
  echo ' -n, -no-rsyncd           Do not start the rsync daemon.'
  echo ' -q, -quiet               Run silently.  Return an exit status of 0 for'
  echo '                          success or a non-zero exit status for failure.'
  echo ' -r, -rpm-install         This is only used when building an RPM.'
  echo ''
  echo 'Download, report bugs, and make suggestions at:'
  echo 'http://systemimager.org/'

}

create_devices_by_label_file() {

  rm -f /etc/systemimager/ext2_devices_by_label.txt
  rm -f /etc/systemimager/devices_by_label.txt

  # sed command below uses a literal tab: <ctrl>+<v>, then <tab>
  LABELS=`
	  sed 's/	/ /' /etc/fstab | \
	  grep -v '^ *#'                | \
	  grep 'LABEL='                 | \
	  awk '{print $1}'
	 `
  for LABEL in $LABELS; do
    # sed command below uses a literal tab: <ctrl>+<v>, then <tab>
    MOUNT_POINT=`
		 sed 's/	/ /' /etc/fstab | \
		 grep -v '^ *#'                 | \
                 grep "$LABEL "                 | \
		 awk '{print $2}'
		`

    # sed command below uses a literal tab: <ctrl>+<v>, then <tab>
    DEVICE=`
            sed 's/	/ /' /etc/systemimager/mounted_filesystems | \
            grep "$MOUNT_POINT "                                   | \
	    awk '{print $1}'
	   `
    echo $LABEL $DEVICE >> /etc/systemimager/devices_by_label.txt
  done
}
### END functions
 

# default is an interactive install (nothing goes over the network any more)
QUIET="false"
HELP="false"
NO_RSYNCD="false"
SHOW_VERSION="false"
EXPLICIT="no"

# if only one option is given, verify it as a proper one
for cl_option ; do
  case $cl_option in
    -r | -rpm-install | --rpm-install          	) QUIET="true" ;;
    -q | -quiet | --quiet                      	) QUIET="true" ;;
    -e | -explicit-geometry | --explicit-geometry	) EXPLICIT="yes" ;;
    -h | -help | --help                        	) HELP="true" ;;
    -n | -no-rsyncd | --no-rsyncd              	) NO_RSYNCD="true" ;;
    -version | --version                       	) SHOW_VERSION="true" ;;
  esac
done

# show version if requested
if [ "$SHOW_VERSION" = "true" ]; then
    show_version
    exit 0
fi

# give help if requested
if [ "$HELP" = "true" ]; then
    show_usage
    exit 0
fi

# if not run as root, install will surely fail
[ "$QUIET" = "false" ] && [ `whoami` != "root" ] && echo "Must be run as root!" && exit 1
[ "$QUIET" = "true" ] && [ `whoami` != "root" ] && exit 1

 
# do introduction
if [ "$QUIET" = "false" ]; then
 clear
 cat << 'EOF'
Welcome to the SystemImager prepareclient command.  This command
may modify the following files to prepare your client for having it's
image retrieved by the imageserver.  It will also create the 
/etc/systemimager directory and fill it with information about your 
golden client, such as the disk partitioning scheme(s). 
 
 /etc/services    -- add rsync line if necessary
 /etc/inetd.conf  -- comment out rsync line if necessary
                     (rsync will run as a daemon until shutdown)
 /tmp/rsyncd.conf -- create a temporary rsyncd.conf file with a
                     [root] entry in it.
 
All modified files will be backed up with the .beforesystemimager 
extension.

See "prepareclient -help" for command line options.

EOF

 # you sure you want to install?
 echo -n "Prepare client for SystemImager? (y/[n]): "
 read REPLY
 case $REPLY in
  y|Y|Yes|yes|YES ) echo Ok.  Preparing client for SystemImager... ;;
  * ) echo Client preparation cancelled.  No files modified. && exit 1 ;;
 esac
 echo
 sleep 2
fi

# verify that rsync entry is in /etc/services
egrep -q ^rsync /etc/services
if [ $? != "0" ]; then
  if [ ! -f /etc/services.beforesystemimager ]; then
    [ "$QUIET" = "false" ] && echo "Backing up /etc/services to /etc/services.beforesystemimager ..."
    cp /etc/services /etc/services.beforesystemimager
  fi
  echo "rsync           873/tcp                         # rsync" >> /etc/services
  echo "rsync           873/udp                         # rsync" >> /etc/services
fi 

# comment out rsync entry in inetd.conf if it exists
RESTART_INETD="false"
egrep -q ^rsync /etc/inetd.conf > /dev/null 2>&1
if [ $? = "0" ]; then
  if [ ! -f /etc/inetd.conf.beforesystemimager ]; then
    [ "$QUIET" = "false" ] && echo "Backing up /etc/inetd.conf to /etc/inetd.conf.beforesystemimager ..."
    cp /etc/inetd.conf /etc/inetd.conf.beforesystemimager
  fi
  sed 's/^rsync/#rsync/' /etc/inetd.conf > /tmp/.systemimager
  cp /tmp/.systemimager /etc/inetd.conf
  rm /tmp/.systemimager
  RESTART_INETD="true"
fi 
# comment out rsync entry in inetd.conf if it exists


# location of rsyncd.conf file
rsyncd_conf_file="/tmp/rsyncd.conf"

# install SystemImager brand rsyncd.conf file ($rsyncd_conf_file)
[ "$QUIET" = "false" ] && [ "$NO_RSYNCD" = "false" ] && echo "Creating $rsyncd_conf_file ..."
[ "$NO_RSYNCD" = "false" ] && create_rsyncd_conf
# install SystemImager brand rsyncd.conf file


# signal inetd to re-read /etc/inetd.conf
if [ "$RESTART_INETD" = "true" ]; then
    if [ "$QUIET" = "false" ]; then
      echo -n "Signalling inetd to re-read /etc/inetd.conf: "
      echo
    fi
    PID_OF_INETD=`pidof inetd`
    [ ! -z $PID_OF_INETD ] && kill -HUP $PID_OF_INETD
fi
# signal inetd to re-read /etc/inetd.conf

# test for hostname in hosts file -- this is necessary for rsyncd to run
HOSTNAME=`uname -n`
egrep -q $HOSTNAME /etc/hosts
if [ "$?" != "0" ]; then
   echo
   echo "******************************* WARNING *******************************"
   echo "This hosts name: \"$HOSTNAME\" must appear in the /etc/hosts file in"
   echo "order for me to crank up the rsyncd daemon.  rsync doesn't seem to be"
   echo "particular about the hostname being associated with an appropriate IP"
   echo "address, it just wants to see the hostname in there somewhere..."
   echo 
   echo "-The Mgmt."
   echo "******************************* WARNING *******************************"
   echo
   echo "An entry like the one below will usually work fine:"
   echo "127.0.0.1  \"$HOSTNAME\""
   echo
   echo -n "Would you like me to add this entry for you? (y/[n]): "

   read REPLY
   case $REPLY in
     y|Y|Yes|yes|YES ) echo Ok.  Adding entry to /etc/hosts...
                       echo "127.0.0.1  $HOSTNAME" >> /etc/hosts
                       ;;

     * ) echo Please add an entry for \"$HOSTNAME\" and run "prepareclient" again.
         exit 1
	 ;;

   esac
fi

# restart rsync as a daemon
killall rsync rsyncd > /dev/null 2>&1
[ "$QUIET" = "false" ] && [ "$NO_RSYNCD" = "false" ] && echo -n Starting or re-starting rsync as a daemon
for i in 1 2 3 4 5; do 
    [ "$QUIET" = "false" ] && [ "$NO_RSYNCD" = "false" ] && echo -n .
    [ "$NO_RSYNCD" = "false" ] && sleep 1s
done
[ "$QUIET" = "false" ] && [ "$NO_RSYNCD" = "false" ] && echo done!
[ "$NO_RSYNCD" = "false" ] && rsync --daemon --config=$rsyncd_conf_file
# restart rsync as a daemon


### BEGIN get list of IDE and SCSI disks ###
ide_and_scsi_disks=`

# extract SCSI and IDE disk device partitions
egrep [hs]d[a-z][0-9] /proc/partitions | awk '{print $4}' | \

# strip out partition numbers
sed -e 's/[0-9]//g' | \

# show each unique device only once
sort -u
`
### END get list of IDE and SCSI disks ###


### BEGIN get list of hardware RAID "disks" ###
hardware_raid_disks=`

# extract hardware RAID disk device partitions
egrep c[0-9]+d[0-9]+p /proc/partitions | awk '{print $4}' | \

# strip out partition numbers
sed -e 's/p[0-9][0-9]*//' | \

# show each unique device only once
sort -u
`
### END get list of hardware RAID "disks" ###


### BEGIN leave disk info behind for "getimage" script ###
# clean up after last "prepare"
rm -fr $systemimagerdir/partitionschemes/

# create receiving directory for SCSI and IDE disk info
[ "x$ide_and_scsi_disks" != "x" ] && mkdir -p $systemimagerdir/partitionschemes

# create receiving directory for Hardware RAID disk info
[ "x$hardware_raid_disks" != "x" ] && mkdir -p $systemimagerdir/partitionschemes/rd

# get sfdisk to report IDE and SCSI disk partition info
for disk in $ide_and_scsi_disks
do
 # Specify sectors explicitly -- this format may be used in the future
 # for partitioning with MB.
 if [ "$EXPLICIT" = "yes" ]; then
   sfdisk -l -uS /dev/$disk > $systemimagerdir/partitionschemes/$disk
 else
   sfdisk -l -uM /dev/$disk > $systemimagerdir/partitionschemes/$disk
 fi
done

# get sfdisk to report Hardware RAID disk info
for disk in $hardware_raid_disks
do
 # must do some funkification for sfdisk to report properly
 ln -s /dev/$disk /dev/$disk"p"

 # Specify sectors explicitly -- this format may be used in the future
 # for partitioning with MB.
 if [ "$EXPLICIT" = "yes" ]; then
   sfdisk -l -uS /dev/$disk"p" > $systemimagerdir/partitionschemes/$disk
 else
   sfdisk -l -uM /dev/$disk"p" > $systemimagerdir/partitionschemes/$disk
 fi

 # get rid of the funkification
 rm -f /dev/$disk"p"
done
### END leave disk info behind for the getimage command ###

# A list of mounted filesystems is needed to determine which 
# filesystems to exclude when getting an image.  This list is 
# also used to determine the actual hardware device used when
# a LABEL= statment is made in /etc/fstab.
#
# In the case that /etc/mtab is a symlink to /proc/mounts.  This 
# method should still work.  This file is also left behind 
# for getimage.
mount > /etc/systemimager/mounted_filesystems

# get a list of LABELled devices if any
create_devices_by_label_file

# wrap up
if [ "$QUIET" = "false" ] && [ "$NO_RSYNCD" = "false" ]; then
 echo
 echo "This client is ready to have it's image retrieved."
 echo "You must now run the \"getimage\" command on the imageserver."
fi

if [ "$QUIET" = "false" ] && [ "$NO_RSYNCD" = "true" ]; then
 echo "Warning:  The rsync daemon was not started.  You must run"
 echo "prepareclient again, without the -n option, before you can"
 echo "pull it's image to an imageserver."
 echo
fi
exit 0
