#!/bin/bash

# Relinux is a remastering script based on remastersys
# It is made to be simpler, better, more customizable,
# better documented, up to date with the latest systems,
# user friendly, and accessable by many linux distributions

# Copyright 2011/2012 under the GNU GPLv3 license
# Joel Leclerc (lkjoel)

# A few useful variables
export DIR=/etc/relinux/
export VERSIONFILE=$DIR/relinux/version
export CONFIGFILE=$DIR/relinux.conf
# Load the version file
. $VERSIONFILE
# Prints out the usage of Relinux
usage()
{
	 thesudo=
	 command=
	 if [ `id -u` -ne 0 ]
	 then
	   thesudo="sudo "
	   command="exit 1"
	 fi
	 count=0
	 thspace=
	 progname=
	 while [ $count -lt ${#thesudo} ]
	 do
	   thspace="$thspace "
	   count=$(($count+1))
	 done
	 count=0
	 while [ $count -lt ${#PROGNAME} ]
	 do
	   progname="$progname "
	   count=$(($count+1))
	 done
     echo -e "Usage of $PROGNAME is as follows:"
     echo -e " "
     echo -e "   ${thesudo}$PROGNAME clean|iso|squashfs|onlyiso " \
"[configfile]"
     echo -e " "
     echo -e " "
     echo -e "Examples:"
     echo -e " "
     echo -e "   ${thesudo}$PROGNAME clean [configfile]              " \
" Cleans up files made by $PROGNAME"
     echo -e " "
     echo -e "   ${thesudo}$PROGNAME squashfs [configfile]           " \
" Generates a .squashfs file from your system"
     echo -e " "
     echo -e "   ${thesudo}$PROGNAME onlyiso [configfile]            " \
" Generates a .iso file based on the .squashfs file generated by" \
" the previous listed command"
     echo -e "   ${thspace}$progname                                 " \
" If configfile is given, settings will be used from that file"
     echo -e " "
     echo -e "   ${thesudo}$PROGNAME iso [configfile]                " \
" Runs the last 2 listed commands"
     $command
}
# Checks if a package is installed, and if not, install it.
checkbin()
{
	if [ $# -lt 3 ]
	then
	  if [ $# -lt 2 ]
	  then
	    app=$1
	    set $app $app $app
	  else
	    app=$1
	    package=$2
	    set $app $app $package
	  fi
	fi
	echo -en 'Checking for '"$2"' \t '
	which $1 > /dev/null 2>&1
	if [ $? -eq 0 ]
	then
	  echo '[  OK  ]'
	else
	  echo '[ FAIL ]'
	  echo -en 'Installing   '"$2"' \t '
	  thesudo=
	  if [ `id -u` -ne 0 ]
	  then
	    thesudo="sudo "
	  fi
	  ${thesudo}apt-get install -y --force-yes -qq $3 > /dev/null 2>&1
	  if [ $? -eq 0 ]
	  then
	    echo '[  OK  ]'
	  else
	    echo '[ FAIL ]'
	  fi
	fi
}
# Checks if a package is installed by a file, and if not, install it
checkfile()
{
	echo -en 'Checking for '"$2"' \t '
	if [ -f $1 ]
	then
	  echo '[  OK  ]'
	else
	  echo '[ FAIL ]'
	  echo -en 'Installing  '"$2"' \t '
	  thesudo=
	  if [ `id -u` -ne 0 ]
	  then
	    thesudo="sudo "
	  fi
	  ${thesudo}apt-get install -y --force-yes -qq $3 > /dev/null 2>&1
	  if [ $? -eq 0 ]
	  then
	    echo '[  OK  ]'
	  else
	    echo '[ FAIL ]'
	  fi
	fi
}
# Checks if a package is installed
checkpackage()
{
	dpkg -l | awk '{print $2}' | grep '^'"$1"'$' > /dev/null 2>&1
	return $?
}
# Installs a package
installpackage()
{
	echo -en 'Installing  '"$2"' \t '
	apt-get install -y --force-yes -qq $1 > /dev/null 2>&1
	if [ $? -eq 0 ]
	then
	  echo '[  OK  ]'
	else
	  echo '[ FAIL ]'
	  exit 1
	fi
}
# Removes a package
removepackage()
{
	echo -en 'Removing    '"$2"' \t '
	apt-get purge -y --force-yes -qq $1 > /dev/null 2>&1
	if [ $? -eq 0 ]
	then
	  echo '[  OK  ]'
	else
	  echo '[ FAIL ]'
	  exit 1
	fi
}
# Boxes text
box()
{
	export count=${#1}
	export HASH=$(($count+6))
	printhash()
	{
		x=0
		while [ $x -lt $1 ]
		do
		  echo -n '#'
		  x=$(($x+1))
		done
	}
	printhash $HASH
	echo
	echo '## '$1' ##'
	printhash $HASH
	echo
}
# Check if all apps needed are installed
checkbin bash "bash                " bash
checkbin sed "sed                 " sed
checkbin find "find                " findutils
checkbin passwd "passwd              " passwd
checkbin rsync "rsync               " rsync
checkbin mount "mount               " mount
checkbin eject "eject               " eject
checkfile /usr/lib/libdebian-installer.so.4.0.7 "libdebian-installer4" libdebian-installer4
checkfile /boot/memtest86+.bin "memtest86+           " memtest86+
checkbin casper-login "casper               " casper
checkbin mksquashfs "mksquashfs          " squashfs-tools
checkbin unsquashfs "unsquashfs          " squashfs-tools
checkbin genisoimage "genisoimage         " genisoimage
checkbin os-prober "os-prober           " os-prober
checkbin discover-config "discover-config     " discover
checkbin laptop-detect "laptop-detect       " laptop-detect
checkbin xterm "xterm               " xterm
checkbin syslinux "syslinux            " syslinux
checkbin fsck "util-linux           " util-linux
checkbin xresprobe "xresprobe           " xresprobe
checkbin archdetect "archdetect          " archdetect-deb
# Check if the User configuration file is loaded
if [ $# -lt 2 ]
then
  export USERCONFIGFILE=$CONFIGFILE
else
  export USERCONFIGFILE=$2
fi
# If the user is not root, then give usage message
if [ `id -u` -ne 0 ]; then
     usage
fi
# Load the relinux configuration file for defaults
. $CONFIGFILE
# Load the user configuration file
. $USERCONFIGFILE
# Making sure that the correct options are selected
case $1  in
  clean)
     echo "Cleaning temporary workdir..."
     rm -rf $WORKDIR
     echo "Done."
     exit 0
     ;;
  iso)
     # 
     ;;
  squashfs)
     #
     ;;
  onlyiso)
     #
     ;;
  *)
     usage
     exit 1
     ;;
esac
# The SquashFS option
cdfs() {
  ############
  ## STEP 1 ##
  ############
  # Install all/remove all packages needed automatically
  #
  # Remove popularity-contest as it can break ubiquity
  checkpackage popularity-contest && removepackage popularity-contest

  ############
  ## STEP 2 ##
  ############
  #
  # Create CD tree in $WORKDIR
  echo -n "Creating the CD tree... "
  if [ -d "$WORKDIR" ]; then
    rm -rf $WORKDIR/dummysys/var/*
    rm -rf $WORKDIR/dummysys/etc/*
    rm -rf $WORKDIR/ISOTMP/isolinux
    rm -rf $WORKDIR/ISOTMP/grub
    rm -rf $WORKDIR/ISOTMP/.disk
  else
    mkdir -p $WORKDIR/ISOTMP/casper
    mkdir -p $WORKDIR/ISOTMP/preseed
    mkdir -p $WORKDIR/dummysys/dev
    mkdir -p $WORKDIR/dummysys/etc
    mkdir -p $WORKDIR/dummysys/proc
    mkdir -p $WORKDIR/dummysys/tmp
    mkdir -p $WORKDIR/dummysys/sys
    mkdir -p $WORKDIR/dummysys/mnt
    mkdir -p $WORKDIR/dummysys/media/cdrom
    mkdir -p $WORKDIR/dummysys/var
    chmod ug+rwx,o+rwt $WORKDIR/dummysys/tmp
  fi
  mkdir -p $WORKDIR/ISOTMP/isolinux
  mkdir -p $WORKDIR/ISOTMP/.disk
  echo "Done"
  ############
  ## STEP 3 ##
  ############
  #
  # Copy /var and /etc to $WORKDIR/dummysys, and exclude $EXCLUDES
  echo "Copying /var and /etc to a temporary directory, "\
"and removing all uneeded files"
  if [ "$EXCLUDES" != "" ]; then
    for addvar in $EXCLUDES ; do
      VAREXCLUDES="$VAREXCLUDES --exclude='$addvar' "
    done
  fi
  rsync --exclude='*.log.*' --exclude='*.pid' --exclude='*.bak' \
--exclude='*.[0-9].gz' --exclude='*.deb' $VAREXCLUDES-a /var/. \
$WORKDIR/dummysys/var/.
  rsync $VAREXCLUDES-a /etc/. $WORKDIR/dummysys/etc/.
  rm -rf $WORKDIR/dummysys/etc/X11/xorg.conf*
  rm -rf $WORKDIR/dummysys/etc/resolv.conf
  rm -rf $WORKDIR/dummysys/etc/hosts
  rm -rf $WORKDIR/dummysys/etc/hostname
  rm -rf $WORKDIR/dummysys/etc/timezone
  rm -rf $WORKDIR/dummysys/etc/mtab
  rm -rf $WORKDIR/dummysys/etc/fstab
  rm -rf $WORKDIR/dummysys/etc/udev/rules.d/70-persistent*
  ls $WORKDIR/dummysys/var/lib/apt/lists | grep -v ".gpg" | \
grep -v "lock" | grep -v "partial" | \
xargs -i rm $WORKDIR/dummysys/var/lib/apt/lists/{} ; 
  echo "  " > $WORKDIR/dummysys/etc/gdm/gdm.conf-custom
  rm -rf $WORKDIR/dummysys/etc/wicd/wired-settings.conf
  rm -rf $WORKDIR/dummysys/etc/wicd/wireless-settings.conf
  ls $WORKDIR/dummysys/etc/NetworkManager/system-connections | \
xargs -i rm \
$WORKDIR/dummysys/etc/NetworkManager/system-connections/{} ;
  find $WORKDIR/dummysys/var/run $WORKDIR/dummysys/var/log \
$WORKDIR/dummysys/var/mail $WORKDIR/dummysys/var/spool \
$WORKDIR/dummysys/var/lock $WORKDIR/dummysys/var/backups \
$WORKDIR/dummysys/var/tmp $WORKDIR/dummysys/var/crash \ ;
  for i in dpkg.log lastlog mail.log syslog auth.log daemon.log \
faillog lpr.log mail.warn user.log boot debug mail.err messages wtmp \
bootstrap.log dmesg kern.log mail.info
  do
    touch $WORKDIR/dummysys/var/log/${i}
  done
  ############
  ## STEP 4 ##
  ############
  #
  # Setup ISOLINUX
  #
  # Make sure that adduser and autologin have the correct permissions
  [ ! -d $WORKDIR/dummysys/home ] && mkdir $WORKDIR/dummysys/home
  chmod 755 /usr/share/initramfs-tools/scripts/casper-bottom/*adduser \
/usr/share/initramfs-tools/scripts/casper-bottom/*autologin 
  # Copy the Preseed files
  cp $PRESEED $WORKDIR/ISOTMP/preseed/
  # Copy MemTest86+
  cp /boot/memtest86+.bin $WORKDIR/ISOTMP/isolinux/memtest
  # Check for some files that can come in handy
  if [ ! -f $DIR/customisolinux/isolinux.cfg ]; then
    find /usr -name 'isolinux.bin' -exec cp {} \
$WORKDIR/ISOTMP/isolinux/ \;
    find /usr -name 'vesamenu.c32' -exec cp {} \
$WORKDIR/ISOTMP/isolinux/ \;
    # System version, e.g. 11.10
    SYSVERSION=`lsb_release -rs`
    sed -e 's/__LIVECDLABEL__/'"$LIVECDLABEL"'/g' \
$ISOLINUX > $WORKDIR/ISOTMP/isolinux/isolinux.cfg
    # Add the splash image
    # Sed script simply renames the file, while keeping the extension
    SPLASHIMAGE=`echo \`basename $SPLASHIMAGE\` | \
sed 's:.*\(\..*\):splash\1:g'`
    cp $SPLASHIMAGE $WORKDIR/ISOTMP/isolinux/$SPLASHIMAGE
    sed -i 's/__SPLASHIMAGE__/'"$SPLASHIMAGE"'/g' \
$WORKDIR/ISOTMP/isolinux/isolinux.cfg
  else
    cp $DIR/customisolinux/* $WORKDIR/ISOTMP/isolinux/
  fi
  # Checks the architecture of the system e.g. i386 or amd64
  ARCH=`archdetect | awk -F "/" '{print $1}'`
  cat > $WORKDIR/ISOTMP/README.diskdefines << EOF
#define DISKNAME  $LIVECDLABEL
#define TYPE  binary
#define TYPEbinary  1
#define ARCH  $ARCH
#define ARCH$ARCH  1
#define DISKNUM  1
#define DISKNUM1  1
#define TOTALNUM  0
#define TOTALNUM0  1
EOF
  cp $WORKDIR/ISOTMP/README.diskdefines \
$WORKDIR/ISOTMP/casper/README.diskdefines
  sleep 1
  # Make filesystem.manifest (package list)
  echo "Creating filesystem.manifest and filesystem.manifest-desktop"
  dpkg-query -W --showformat='${Package} ${Version}\n' \
        > $WORKDIR/ISOTMP/casper/filesystem.manifest
  cp $WORKDIR/ISOTMP/casper/filesystem.manifest $WORKDIR/ISOTMP/casper/filesystem.manifest-desktop
  # Make casper.conf
  echo "# This file should go in /etc/casper.conf" > /etc/casper.conf
  echo "# Supported variables are:" >> /etc/casper.conf
  echo "# USERNAME, USERFULLNAME, HOST, BUILD_SYSTEM" >> /etc/casper.conf
  echo " " >> /etc/casper.conf
  echo "export USERNAME=\"$LIVEUSER\"" >> /etc/casper.conf
  echo "export USERFULLNAME=\"$LIVENAME\"" >> /etc/casper.conf
  echo "export HOST=\"$HOSTNAME\"" >> /etc/casper.conf
  echo "export BUILD_SYSTEM=\"$SYSNAME\"" >> /etc/casper.conf
  cp /etc/casper.conf $WORKDIR/dummysys/etc/
  # Make sure user-setup-apply is present

  echo "Setting up casper options for $1 mode"
  # make a new initial ramdisk including the casper scripts
  mkinitramfs -o $WORKDIR/ISOTMP/casper/initrd.gz `uname -r`
  echo "Copying your kernel and initrd for the livecd"
  cp /boot/vmlinuz-`uname -r` $WORKDIR/ISOTMP/casper/vmlinuz
  # Step 6 - Make filesystem.squashfs
  if [ -f $WORKDIR/ISOTMP/casper/filesystem.squashfs ]; then
    rm -f $WORKDIR/ISOTMP/casper/filesystem.squashfs
  fi
  echo "Creating filesystem.squashfs   ... this will take a while so be patient"
  SQUASHFSOPTSHIGH="-no-recovery -always-use-fragments"
  echo "Adding stage 1 files/folders that the livecd requires."
  # add the blank folders and trimmed down /var to the cd filesystem
  mksquashfs $WORKDIR/dummysys/ $WORKDIR/ISOTMP/casper/filesystem.squashfs -b 1M -no-duplicates $SQUASHFSOPTSHIGH 2>/dev/null
  sleep 1
  echo "Adding stage 2 files/folders that the livecd requires."
  # add the rest of the system depending on the mode selected
    mksquashfs / $WORKDIR/ISOTMP/casper/filesystem.squashfs -b 1M -no-duplicates $SQUASHFSOPTSHIGH -e \
    .thumbnails \
    .cache \
    .bash_history \
    Cache \
    boot/grub \
    dev \
    etc \
    home \
    media \
    mnt \
    proc \
    sys \
    tmp \
    var \
    $WORKDIR $EXCLUDES 2>/dev/null
  #checking the size of the compressed filesystem to ensure it meets the iso9660 spec for a single file" 
  SQUASHFSSIZE=`ls -s $WORKDIR/ISOTMP/casper/filesystem.squashfs | awk -F " " '{print $1}'`
  if [ "$SQUASHFSSIZE" -ge "4000000" ]; then
    echo " The compressed filesystem is larger than the iso9660 specification allows for a single file. You must try to reduce the amount of data you are backing up and try again."
    exit 1
  fi
  #add filesystem size for lucid
  echo " Calculating the installed filesystem size for the installer"
  unsquashfs -lls $WORKDIR/ISOTMP/casper/filesystem.squashfs | grep -v " inodes " | grep -v "unsquashfs:" | awk '{print $3}' | grep -v "," > /tmp/size.tmp
  for i in `cat /tmp/size.tmp`; do a=$(($a+$i)); done
  echo $a > $WORKDIR/ISOTMP/casper/filesystem.size
}

iso (){
  CREATEISO="`which mkisofs`"
  if [ "$CREATEISO" = "" ]; then
    CREATEISO="`which genisoimage`"
  fi
  # check to see if the cd filesystem exists
  if [ ! -f "$WORKDIR/ISOTMP/casper/filesystem.squashfs" ]; then
    echo "The cd filesystem is missing.  Either there was a problem creating the compressed filesystem or you are trying to run sudo remastersys dist iso before sudo remastersys dist cdfs"
    exit 1
  fi
  #checking the size of the compressed filesystem to ensure it meets the iso9660 spec for a single file 
  SQUASHFSSIZE=`ls -s $WORKDIR/ISOTMP/casper/filesystem.squashfs | awk -F " " '{print $1}'`
  if [ "$SQUASHFSSIZE" -ge "4000000" ]; then
    echo " The compressed filesystem is larger than the iso9660 specification allows for a single file. You must try to reduce the amount of data you are backing up and try again."
    exit 1
  fi
  #Step 6.5 - Added by Tim Farley. Make ISO compatible with Ubuntu Startup Disk Creator (Karmic).
  echo "Making disk compatible with Ubuntu Startup Disk Creator."
  touch $WORKDIR/ISOTMP/ubuntu
  touch $WORKDIR/ISOTMP/.disk/base_installable
  echo "full_cd/single" > $WORKDIR/ISOTMP/.disk/cd_type
  ARCH=`archdetect | awk -F "/" '{print $1}'`
  echo $LIVECDLABEL - Release $ARCH > $WORKDIR/ISOTMP/.disk/info
  echo $LIVECDURL > $WORKDIR/ISOTMP/.disk/release_notes_url
  # Step 7 - Make md5sum.txt for the files on the livecd - this is used during the
  # checking function of the livecd
  echo "Creating md5sum.txt for the livecd/dvd"
  cd $WORKDIR/ISOTMP && find . -type f -print0 | xargs -0 md5sum > md5sum.txt
  #isolinux mode
  # remove files that change and cause problems with checking the disk
  sed -e '/isolinux/d' md5sum.txt > md5sum.txt.new
  sed -e '/md5sum/d' md5sum.txt.new > md5sum.txt
  rm -f md5sum.txt.new
  sleep 1
  # Step 8 - Make the ISO file
  echo "Creating $CUSTOMISO in $WORKDIR"
  $CREATEISO    \
 -quiet \
 -r    \
 -V "$LIVECDLABEL"    \
 -cache-inodes    \
 -J    \
 -l    \
 -b isolinux/isolinux.bin    \
 -c isolinux/boot.cat    \
 -no-emul-boot    \
 -boot-load-size 4    \
 -boot-info-table    \
 -o $WORKDIR/$CUSTOMISO "$WORKDIR/ISOTMP" 2>/dev/null 1>/dev/null
  # create the md5 sum file so the user doesn't have to
  # this is good so the iso file can later be tested to ensure it
  # hasn't become corrupted
  echo "Creating $CUSTOMISO.md5 in $WORKDIR"
  cd $WORKDIR
  md5sum $CUSTOMISO > $CUSTOMISO.md5
  sleep 1
  echo "$WORKDIR/$CUSTOMISO is generated. It is recommended to run it" \
  " inside a virtual machine before you release it."
  echo " "
  echo "The size of $WORKDIR/$CUSTOMISO is " \
  "`ls -hs $WORKDIR/$CUSTOMISO | awk '{print $1}'`"
  ISOSIZE=`wc -c $WORKDIR/$CUSTOMISO`
  if [ $ISOSIZE -ge 734003200 ]
  then
    echo "You will need to burn a DVD/USB/Blu-Ray disk instead of a CD."
  fi
  echo " " 
  echo "It is recommended to run 'sudo relinux clean' once you have burned and tested $CUSTOMISO"
  echo "It will not delete $CUSTOMISO or $CUSTOMISO.md5"
  echo " "
}

if [[ "$1" == "clean" ]]
then
  rm -rf $WORKDIR/dummysys
  rm -rf $WORKDIR/ISOTMP
fi
if [[ "$1" == "squashfs" ]]
then
  cdfs $@
  exit 0
fi
if [[ "$1" == "onlyiso" ]]
then
  iso $@
  exit 0
fi
cdfs $@
iso $@
exit 0
