#!/bin/bash
# GLOBAL MAIN UNCONFIGURABLE #
LOCATION="http://ftp2.fr.debian.org/debian"
DIST="sid"
VARIANT="buildd"
ARCH="i386"
INCLUDE="apt-utils,dialog,locales,vim-nox,psmisc,procps,man-db,openssh-server,less,xauth"
EXCLUDE="nano"
UNKNOW=""
UNO=0
# GLOBAL MAIN __CONFIGURABLE #
BASEDIR="/srv"
IN_DIR=""
INSTALL=ok
SYSUP=""
PARSE="$(getopt -n chroot-install.sh -s bash "s:d:n:D:L:i:I:e:E:V:U:Rh" -- $@)"
function help_msg()
{
cat << EOF
This script must be run as root:root .
usage: 
	$0 arguments
  Arguments:
-s arch : architecture (default: i386)
-d dir	: base directory
-D dist : distribution (default: sid)
-L "mir": mirror to use
-i inc	: coma separated list of package to include 
-I inc	: same as -i but remove initial
-e ex	: as -i but exclude
-E ex	: as -I but exclude
-V var	: varriant used (default:buildd)
-n name	: chroot path name
-R	: remove chroot
-U "arg": unknow arg, debootstrap with "bash -c, (Not tested)"
-h 	: this message
EOF
}
function awk_fs_uninit()
{
awk -v a="$1" -v d="$2" -v t=$3 ' BEGIN{
	i=0;
	j=0;
	pr=1;
	reg1="#+[\t ]*START[\t ]*:[\t ]*"d" - "a
	reg2="#+[\t ]*END[\t ]*:[\t ]*"d" - "a
}
{
	if ( $0 ~ reg1 )
	{
		pr=0;
		i++;
	}else{
		if ( $0 ~ reg2 )
		{
			pr=1
			j++;
		}else{
			if ( t == 1  && pr == 1)
			{
				print $0
			}
		}
	}
}
END{
	if ( i != j)
	{
		print "WARNING: sed update: failure on /etc/{fstab,inittab,init.d/chroot.sh}"
		exit 0;
	}
	exit i;
}' $4
	[ $? -eq 0 ] && exit 1
}
function fs_init()
{
#local TTY=0
local nTTY=1
for f in "/etc/fstab" "/etc/inittab"
do
	sed -n -e "/#\?[\t ]\?START[\t ]\?:[\t ]\?$1 - $2/ { /#\?[\t ]\?END[\t ]\?:[\t ]\?$1 - $2/ { Q 1 } }" -e '${ Q 0 }' $f
	if [ $? -eq 1 ]
	then
		printf "files not clean.\n$f:\n"
		sed -n "/#\?[\t ]\?START[\t ]\?:[\t ]\?$1 - $2/, /#\?[\t ]\?END[\t ]\?:[\t ]\?$1 - $2/p" $f
		printf "chroot exist in files.\n"
		exit 1
	fi
done
cat << EOF >> /etc/fstab
# START: $1 - $2
# You can add something here for this systeme
proc	$3/proc		proc	defaults	0	0
sysfs	$3/sys		sysfs	defaults	0	0
devpts	$3/dev/pts	devpts	defaults	0	0
# END  : $1 - $2
EOF
cat << EOF
Vous pouvez aussi monter des périphériques suplémentaires
exemple le joystique
mount -B /dev/input/js0 /$3/dev/input/js0
EOF
# Voir avec awk
# Version 1
#sed -n 's/.*tty\([0-9]\+\).*/\1/p' /etc/inittab | sort -n | sed ':start; N; s/\([0-9]\+\)\n\1/\1/; $!{b start};' |
#while read TTY
#do
#  [ "$nTTY" != "$TTY" ] && \
#	printf "G:$nTTY\n" >> /tmp/chroot-tty_get.tmp || \
#	printf "S:$nTTY\n" >> /tmp/chroot-tty_get.tmp
#  nTTY=$(($nTTY+1))
#done
#nTTY=`sed -n '/G:/{s/G://;p; Q 0}; ${ q 1 }' /tmp/chroot-tty_get.tmp; [ $? -eq 1  ] && sed -n '$ {s/S:// ; s/$/+1/p}' /tmp/chroot-tty_get.tmp | bc`
#rm /tmp/chroot-tty_get.tmp
awk '	BEGIN{
		tty=0;
		tmp=0;
	}
	{
		if( $0 ~/tty[0-9]+/  )
		{
			for( i = 1; i < NF && $i !~ /tty[0-9]+/; i++ ){}
			sub("tty","",$i);
			array[tty] = $i;
			tty++;
		}
	}
	END{
		for( i = 0; i < tty; i++)
		{
			for( j = i+1; j < tty; j++ )
			{
				if( array[i] == array[j] )
				{
					for( k = j; k < tty-1; k++ )
					{
						array[k] = array[k+1]
					}
					tty--;
				}
				if( array[i]/1 > array[j]/1 )
				{
					tmp = array[i];
					array[i] = array[j];
					array[j] = tmp;
				}
			}
		}
		for( i = 0; i < tty && array[i]/1 == i+1; i++ )
		{}
		exit i+1
	}' /etc/inittab
nTTY=$?
if [ $nTTY -eq 63 ]
then
cat << EOF
I read tty open: 63.
I can't create new tty in inittab.
EOF
exit 1
fi
cat << EOF >> /etc/inittab
# START: $1 - $2
# You can add something here for this systeme
$nTTY:23:wait:/usr/sbin/chroot $3 /sbin/getty 38400 tty$nTTY	#pour eviter le respawn too fast
# END  : $1 - $2
EOF
}
function files_integrity()
{
	case $1
	in 
	check)
		case $2 in
		R)
			printf "\tINFO: diff on /etc/inittab /etc/inittab.bak:\n"
			diff -n /etc/inittab /etc/inittab.bak
			printf "\tINFO: diff on /etc/fstab /etc/fstab.bak:\n"
			diff -n /etc/fstab /etc/fstab.bak
			if [ -f /etc/init.d/chroot.sh ]
			then
				printf "\tINFO: diff on /etc/init.d/chroot.sh /etc/init.d/chroot.sh.bak:\n"
				diff -n /etc/init.d/chroot.sh /etc/init.d/chroot.sh.bak
			fi
		;;
		I)
			printf "\tINFO: diff /etc/inittab.bak /etc/inittab:\n"
			diff -n /etc/inittab.bak /etc/inittab
			printf "\tINFO: diff on /etc/fstab.bak /etc/fstab:\n"
			diff -n /etc/fstab.bak /etc/fstab
			if [ -f /etc/init.d/chroot.sh ]
			then
				printf "\tINFO: diff on /etc/init.d/chroot.sh.bak /etc/init.d/chroot.sh:\n"
				diff -n /etc/init.d/chroot.sh.bak /etc/init.d/chroot.sh
			fi
		;;
		esac
	;;
	copy)
		printf "sed : copy: /etc/{inittab,fstab} /etc/{inittab,fstab}.bak\n"
		sed '1,$ !d' /etc/{inittab,fstab} -i.bak || exit 1
		[ -f /etc/init.d/chroot.sh ] && cp -v /etc/init.d/chroot.sh /etc/init.d/chroot.sh.bak

	;;
	esac
}
function chroot_msg()
{
case $1
in
	0)
cat << EOF >> /etc/init.d/chroot.sh
#!/bin/bash
### BEGIN INIT INFO
# Provides:          chroot.sh
# Required-Start:    $syslog
# Required-Stop:     $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: access to chroot env with ssh
# Description:       access to chroot env with ssh
#
### END INIT INFO
EOF
	;;
	1)
cat << EOF >> /etc/init.d/chroot.sh
# START: $2 - $3
chroot $BASEDIR/$IN_DIR /etc/init.d/ssh \$1
# END  : $2 - $3
EOF
	;;
esac
}
function end_msg()
{
grep -e "tty[0-9]\+" /etc/inittab
cat << EOF
	WARNING: check for no duplicated tty.
	System installed.
	INFO: You run this system over ssh with X forwarding
	WARNING: sshd NOT configured.
	sshd: not running (chroot "$BASEDIR"/"$IN_DIR" /etc/init.d/ssh start)
	If you use Debian, add in comment 'tty6' in inittab, because it is used by syslog-ng.
	Or/And change tty6 in inittab.
EOF

}
# # # # # # # # # # # # # # # #
while getopts "d:s:n:D:L:i:I:e:E:V:U:Rh" VAL
do
	case $VAL
	in
	s)
		ARCH="$OPTARG"
	;;
	d)
		if [ ! -d "$OPTARG" ]
		then
			printf "$OPTARG : not exist.\n"
			exit 1
		fi
		BASEDIR="$OPTARG"
	;;
	D)
		DIST="$OPTARG"
	;;
	n)
		IN_DIR="$OPTARG"
	;;
	R)
		INSTALL=""
	;;
	L)
		LOCATION="$OPTARG"
	;;
	i)
		INCLUDE="$INCLUDE,$OPTARG"
	;;
	I)
		INCLUDE="$OPTARG"
	;;
	e)
		EXCLUDE="$EXCLUDE,$OPTARG"
	;;
	E)
		EXCLUDE="$OPTARG"
	;;
	V)
		VARIANT="$OPTARG"
	;;
	U)
		UNKNOW="$OPTARG"
		UNO=1
	;;
	h)
		help_msg
		exit 0
	;;
	*)
		exit 1
	;;
	esac
done
if [ $USER != root ]
then
	printf "You are not 'root'.\n"
	exit 1
fi
files_integrity copy
case $INSTALL
in
ok)
	SYSUP="$(printf "$INCLUDE" | grep "locales")"
	if [ $UNO -eq 0 ]
	then
		[ -z "$INCLUDE" ] && OP=0 || OP=1
		[ -n "$EXCLUDE" ] && OP=$(($OP+2))
	else
		OP=10
	fi
	[ -z "$IN_DIR" ] && IN_DIR=$ARCH
	if [ ! -d "$BASEDIR"/"$IN_DIR" ]
	then
		mkdir "$BASEDIR"/"$IN_DIR" || exit 1
	else
		ls -Al "$BASEDIR"/"$IN_DIR" | \
		sed -n	-e '/total 0/{ Q 0}' \
			-e '1 {Q 1}'
		if [ $? -eq 1 ]
		then
			printf "$BASEDIR/$IN_DIR: not empity.\n"
			exit 1
		fi
	fi
	case $OP
	in
	0)
		debootstrap --arch=$ARCH $DIST "$BASEDIR"/"$IN_DIR" $LOCATION || exit 1
	;;
	1)
		debootstrap --arch=$ARCH --exclude=$EXCLUDE $DIST "$BASEDIR"/"$IN_DIR" $LOCATION || exit 1
	;;
	2)
		debootstrap --arch=$ARCH --exclude=$EXCLUDE $DIST "$BASEDIR"/"$IN_DIR" $LOCATION || exit 1
	;;
	3)
		debootstrap --arch=$ARCH --variant=$VARIANT --include=$INCLUDE --exclude=$EXCLUDE $DIST "$BASEDIR"/"$IN_DIR" $LOCATION || exit 1
	;;
	10)
		[ -n "$INCLUDE" ] && INCLUDE="--include=$INCLUDE"
		[ -n "$EXCLUDE" ] && EXCLUDE="--exclude=$EXCLUDE"
		bash -c "debootstrap --arch=$ARCH $UNKNOW $INCLUDE $EXCLUDE $DIST "$BASEDIR"/"$IN_DIR" $LOCATION && exit 0 || exit 1"
		if [ $? -eq 1 ] ; then
		 echo "debootstrap exit failure"
		 exit 1
		fi
	;;
	esac
# FILE EDIT & COPY
	fs_init $IN_DIR $ARCH "$BASEDIR"/"$IN_DIR"
	cp -v /etc/{hosts,resolv.conf,locale.gen} "$BASEDIR"/"$IN_DIR"/etc/
	sed -i 's/^deb\( .*\)$/deb\1\ndeb-src\1/' "$BASEDIR"/"$IN_DIR"/etc/apt/sources.list
# SYSTEM SMOLE UP
	[ -n "$SYSUP" ] && \
		chroot "$BASEDIR"/"$IN_DIR" /bin/bash -c "/usr/bin/apt-get clean; /usr/bin/apt-get autoclean; /usr/bin/apt-get update; locale-gen"
	mount -a -v
	telinit q
	chroot "$BASEDIR"/"$IN_DIR" /usr/bin/passwd
	sed -i 's|\(^.*PS1=.*\)|\1\nPS1=\"(chroot)\\\[\\e\[36m\\\]\\u@\\h\\w\$ \\\[\\e\[0;30;47m\\\]\"| ' "$BASEDIR"/"$IN_DIR"/root/.bashrc
# CHROOT STARTUP
	if [ ! -f /etc/init.d/chroot.sh ]
	then 
		printf "\tWARNING: update-rc.d /etc/init.d/chroot.sh not done.\n"
		touch /etc/init.d/chroot.sh
		chroot_msg 0 "$IN_DIR" "$ARCH"
	fi
	[ -n "$SYSUP" ] && \
		chroot_msg 1 "$IN_DIR" "$ARCH"
	[ ! -x /etc/init.d/chroot.sh ] && chmod +x /etc/init.d/chroot.sh
	end_msg
	files_integrity check I
	printf "Install ok???\n"
	;;
	*)
	printf "On failure remove lines in /etc/fstab, /etc/inittab, /etc/init.d/chroot.sh.\n"
# UMOUNT NEEDED
	for FILE_INI in "proc" "sys" "dev/pts"
	do
		umount -v "$BASEDIR"/"$IN_DIR"/"$FILE_INI" || exit 1
	done
	chroot "$BASEDIR"/"$IN_DIR" /etc/init.d/ssh stop
# DELETE from files
	printf "try to remove: $ARCH - $IN_DIR\n"
	# awk à venir
	#[ $(grep -e "#\?[\t ]\?START[\t ]\?:[\t ]\?$IN_DIR - $ARCH" /etc/{fstab,inittab,init.d/chroot.sh} | cat -n | sed -n 's/^\ *\([0-9]\+\) *.*/\1/p' | tail -n 1) -eq 3 ] \
	#&&	sed -i "/#\?[\t ]\?START[\t ]\?:[\t ]\?$IN_DIR - $ARCH$/, /#\?[\t ]\?END[\t ]\?:[\t ]\?$IN_DIR - $ARCH$/d" /etc/{fstab,inittab,init.d/chroot.sh} \
	#||	printf "WARNING: sed update: failure on /etc/{fstab,inittab,init.d/chroot.sh}\n"
	# avec awk
	awk_fs_uninit $ARCH $IN_DIR 0 /etc/{fstab,inittab,init.d/chroot.sh}
	sed -i "/#[\t ]*START[\t ]*:[\t ]*$IN_DIR - $ARCH$/, /#*[\t ]*END[\t ]*:[\t ]*$IN_DIR - $ARCH$/d" /etc/{fstab,inittab,init.d/chroot.sh} \
# CHECK IF chroot.sh: needed
	[ -z "$(grep "START" /etc/init.d/chroot.sh)" ] && printf "/etc/init.d/chroot.sh should be empty, maybe you can update-rc.d and remove it\n"
	rm -R "$BASEDIR"/"$IN_DIR" &>/dev/null || printf "ERROR: rm: failure\n"
	telinit q
	files_integrity check R
	printf "Remove: Success???\n"
	;;
	esac
