#!/bin/bash
#	A LinHES development script to enter a chroot tree.
#########################################################################
# Configuration:							#
#-----------------------------------------------------------------------#
chrootBaseDir='build_root'	# basename of chroot tree.		#
repoBaseDir='pkg_repo'		# basename of package repository tree.	#
toolsDir='LinHES-dev'		# directory name of development tools.	#
packageDir='LinHES-PKGBUILD'	# package development directory.	#
C_B='\e[1m'			# set bold : comment out for no bold.	#
#########################################################################
C_N='\e[0m'			# back to normal text output.		#
myDir=$(pwd)			# initial working directory.		#
ARCH=${0##*.}			# pick off the architecture part.	#
BROOT="$myDir/$chrootBaseDir.$ARCH"	# chroot subdir for $ARCH	#
#########################################################################
# Proceedures / Functions:						#
#-----------------------------------------------------------------------#
# Acquire the lock and modify the value, use: V=$(Modify +|-)
Modify() { # $1 is + for up and - for down.
    local LOCKFILE=.lock
    local VALUFILE=.inst
    (	# Acquire the lock:
	flock -e -w 2 200
	[ -e $VALUFILE ] || echo 0 > $VALUFILE
	VAL=$(cat $VALUFILE)
	NEW=$(expr $VAL $1 1)
	echo "$NEW" > $VALUFILE
	echo "$NEW"
    ) 200>$LOCKFILE
}
#-----------------------------------------------------------------------#
# set the title bar for an xterm or Konsole.
title() { # args are the title
    echo -en  "\e]0;$@\a"	# for xterm,
    echo -en "\e]30;$@\a"	# for Konsole.
}
#-----------------------------------------------------------------------#
# check if a filesystem/directory is already mounted & if not, mount it.
#   ckMount -t     <fstype> <mntDir>
#   ckMount --bind <srcDir> <dstDir>
ckMount() { # $1= -t|--bind, $2= fstype|srcDir $3= mntDir|dstDir
    grep -q /$BROOT/$3 /proc/mounts || {
	[ -d "$3" ] || mkdir -p $3
	echo -e "mounting ${C_B}$3${C_N}"
	case $1 in
	    -t)		mount $1 $2 $2     $3	;;
	    --bind)	mount $1 $myDir/$2 $3	;;
	esac
    }
}
#-----------------------------------------------------------------------#
# if this is the last incident, unmount all.
cleanUp() { # no arguments
    # mark the exit to normal operation:
    title Normal

    V=$(Modify -)
    [ "$V" -ne "0" ] && exit 0

    # unmount all:
    local mnts1="data/$repoBaseDir data/$packageDir build_tools"
    local mnts2="dev/pts sys proc"
    for i in $mnts1 $mnts2 ; do
	grep -q $BROOT/$i /proc/mounts && {
	    echo -e "unMounting ${C_B}$i${C_N}"
	    umount $BROOT/$i  # >& /dev/null
	}
    done
}
#=======================================================================#
# make certain that the chroot contains some files:
copyIn() { # no arguments
    local F=etc/resolv.conf
    [ -e "$BROOT/$F" ] || cp -f /$F $F
    [ -f etc/bashrc ]  || {
	local D="$myDir/$toolsDir/templates/etc"
	cp -f $D/bashrc		etc/
	cp -f $D/kmdev.sh	etc/profile.d/
	cp -f $D/.bashrc	root/
	cp -f $D/.bash_profile	root/
	chmod 0755 root/.bashrc root/.bash_profile etc/profile.d/kmdev.sh
    }
}
#########################################################################
# Prerequisites:							#
#-----------------------------------------------------------------------#
#  must be root:
[ $EUID -ne 0 ] && {
    echo -e "${C_B}chroot needs root priv's.${C_N}" 1>&2
    exit 1
}

# must have the chroot subdirectory:
[ -d $BROOT ] || {
    echo -e "${C_B}$BROOT${C_N} directory not found!"
    exit 2
}

# if building packages, needs $packageDir
if [ -d "$packageDir" ]; then
    echo -e "Found ${C_B}$packageDir${C_N}"
else
    printf "%s\n"        "**********************************************************************"
    printf "* %-66s *\n" "Could Not find $packageDir"
    printf "* %-66s *\n" "If you wish to be able to build packages within the chroot, then"
    printf "* %-66s *\n" "Please checkout the package repository into the current directory."
    printf "* %-66s *\n" "Its located @ knoppmyth.net/mount/repository/${packageDir}.git"
    printf "%s\n"        "**********************************************************************"
fi

# change to the chroot subdirectory:
cd $BROOT || {
    echo -e "Could NOT cd to ${C_B}$BROOT${C_N} !"
    exit 3
}
#########################################################################
# Main:									#
#-----------------------------------------------------------------------#
V=$(Modify +)			# bump the instance count.
trap cleanUp 1 2 15 EXIT

ckMount -t proc   proc
ckMount -t sysfs  sys
ckMount -t devpts dev/pts

[ -e dev/random ]  || mknod dev/random  c  1 8
[ -e dev/urandom ] || mknod dev/urandom c  1 9
[ -e dev/tty ]     || mknod dev/tty     c  5 0
[ -e dev/ptmx ]    || mknod dev/ptmx    c  5 2

ckMount --bind $toolsDir/build_tools build_tools
ckMount --bind $packageDir           data/$packageDir
ckMount --bind $repoBaseDir          data/$repoBaseDir

copyIn

# change the titlebar to indicate chroot:
title "CHROOT : $ARCH"

# The actual chroot:
env -i  TERM="$TERM" DISPLAY="$DISPLAY" /usr/sbin/chroot . /bin/bash --login

# Note: the unMounts take place within the 'cleanUp' proceedure.
#########################################################################
# End