#!/bin/bash
# Author: Steven Shiau <steven _at_ nchc org tw>
# License: GPL
# Program to create Clonezilla live.

# functions
set_localepurge(){
  # Create en_US.UTF-8, the dialog in clonezilla need that in console.
  # Otherwise dialog will be distorted.
  if [ -z "$(localedef --list-archive | grep -iw "en_US.utf8")" ]; then
    localedef -f UTF-8 -i en_US en_US.UTF-8
  fi
  # keep some locales.
  echo "Set nonepurge locales..."
  debconf-communicate -fnoninteractive localepurge > /dev/null <<EOF
set localepurge/dontbothernew false
set localepurge/mandelete true
set localepurge/none_selected false
set localepurge/nopurge $locale_to_keep
set localepurge/quickndirtycalc true
set localepurge/remove_no false
set localepurge/showfreedspace true
set localepurge/verbose true

fset localepurge/dontbothernew seen true
fset localepurge/mandelete seen true
fset localepurge/none_selected seen true
fset localepurge/nopurge seen true
fset localepurge/quickndirtycalc seen true
fset localepurge/remove_no seen true
fset localepurge/showfreedspace seen true
fset localepurge/verbose seen true
EOF
  # apply it
  LC_ALL=C dpkg-reconfigure --priority=low --unseen-only localepurge
  echo "The content of /etc/locale.nopurge:"
  cat /etc/locale.nopurge
} # end of set_localepurge

# set root passwd, I do not like root without passwd.
set_root_passwd() {
  local passwd=""
  case "$root_passwd_opt" in
    "random")
      # Note! Do not use -y (--symbols, Include at least one special character in the password) with pwgen, since it might contain ' or ", which will cause problem when run in shell and pipe to chpasswd
      passwd="$(pwgen -s -c $random_passwd_length 1)"
      echo "Using random password \"$passwd\" with length $random_passwd_length for account root..."
      ;;
    "none")
      passwd=""
      echo "No password for account root..."
      ;;
    *)
      passwd="$root_passwd_def"
      echo "Using password \"$passwd\" for account root..."
      ;;
  esac
  if [ -n "$passwd" ]; then
    echo "root:$passwd" | chpasswd
  fi
}

#
preseed_autologin_account() {
  # add the account user with UID=999 first, otherwise if we add accounts later, for example, when Debian live boots, scripts/casper-bottom/10adduser will kill casper account first (if it's not UID=999, 10adduser can remove that successfully), then when it try to add it, it will fail. Then there is no casper account at all. This will result client's /sbin/casper-getty fails in /etc/inittab. Therefore we can not login in console 1-6.
  # The password (live) of auto login (say casper) is creaetd runtime when Debian Live boots, 
  # in /usr/share/initramfs-tools/scripts/casper-bottom/10adduser (casper) or
  # /usr/share/initramfs-tools/scripts/live-bottom/10adduser (live-initramfs), 
  # there is:
  # user_crypted="8Ab05sVQ4LLps" # as in `echo "live" | mkpasswd -s`
  # Therefore it's useless to assign password here. Skip setting password.
  useradd -m -u $autologin_account_uid -s /bin/bash $autologin_account
}

# put the clonezilla live script in rcS.d
# The reason we put start scripts in rcS.d instead of rc2.d is because the upstart in Ubuntu will enter command line prompt in rc2.d.
cp_ocs_live_startup_to_rcS.d() {
  cp -af /live-hook-dir/S[0-9][0-9]* /etc/rcS.d/; chown root.root /etc/rcS.d/S[0-9][0-9]*
}

# clean unnecessary backup file to save space
clean_unnecessary_backup_file_in_boot() {
  local orphan_deb
  # (1)
  rm -f /boot/initrd*.bak
  # (2)
  orphan_deb="$(deborphan -n)"
  orphan_deb="$(echo $orphan_deb)"  # put it in one line
  if [ -n "$orphan_deb" ]; then
    apt-get --yes --purge remove $orphan_deb
  fi
  # (3)
  # Thess files in dir /var/lib/apt/lists/ are like:
  # free.nchc.org.tw_debian_dists_etch_main_binary-i386_Packages
  # free.nchc.org.tw_debian-security_dists_etch_updates_main_binary-i386_Packages
  # free.nchc.org.tw_drbl-core_dists_drbl_stable_binary-i386_Packages
  # free.nchc.org.tw_drbl-core_dists_drbl_testing_binary-i386_Packages
  # free.nchc.org.tw_drbl-core_dists_drbl_unstable_binary-i386_Packages
  rm -f /var/lib/apt/lists/*_Packages*
  # (4) lock file. Thanks to Louie Chen.
  rm -f /var/lib/apt/lists/lock
}

# since ssh services is on, and account is known for the whole world, we have to block it.
block_all_clients_by_tcpwrapper() {
  echo 'ALL: ALL EXCEPT localhost' >> /etc/hosts.deny
}

# force to load fuse in live CD to avoid if sshfs is used, no /dev/fuse.
append_mod_in_etc_modules() {
  for imod in $mod_loaded_at_startup; do
    echo "$imod" >> /etc/modules
  done
}

#
clean_ocs_hook_files_in_chroot() {
  # all the file name including ocs and in the / in chroot will be removed.
  echo "Removing DRBL/Clonezilla live related hook files in chroot..."
  find ./ -maxdepth 1 -name "*ocs*" -type f -exec rm -fv {} \;
  find ./ -maxdepth 1 -name "*-live-hook*" -type f -exec rm -fv {} \;
  # drbl.conf is special, remove manually
  [ -f /drbl.conf ] && rm -fv /drbl.conf
}
#
append_start_clonezilla_in_user_bash_profile(){
  local auto_login_id_home
  auto_login_id_home="$(bash -c "echo ~$autologin_account")"
  cat <<-PROFILE_END >> $auto_login_id_home/.bash_profile
# added by Clonezilla live
clear
# start clonezilla in tty1 only
sudo [ -x /opt/drbl/sbin/ocs-live-run-menu ] && sudo /opt/drbl/sbin/ocs-live-run-menu
PROFILE_END
  chown $autologin_account.$autologin_account $auto_login_id_home/.bash_profile
}
#
remove_cdebootstrap-helper-diverts(){
 # we have to use the real start-stop-daemon, therefore remove cdebootstrap-helper-diverts
 # live:~# ls -alF /sbin/start-stop-daemon*
 # -rwxr-xr-x 1 root root    10 2006-10-20 16:07 /sbin/start-stop-daemon*
 # -rwxr-xr-x 1 root root 18504 2007-01-01 23:02 /sbin/start-stop-daemon.REAL*
 # By doing apt-get --purge remove cdebootstrap-helper-diverts, it will
 # Removing `diversion of /sbin/start-stop-daemon to /sbin/start-stop-daemon.REAL by cdebootstrap-helper-diverts'
 # Removing `diversion of /usr/sbin/invoke-rc.d to /usr/sbin/invoke-rc.d.REAL by cdebootstrap-helper-diverts'
 if [ -e /sbin/start-stop-daemon.REAL ]; then
   apt-get -y --purge remove cdebootstrap-helper-diverts
 fi
}
#
turn_off_ssh_service() {
  # for better security
  echo "For better security, do not turn on ssh service..."
  update-rc.d -f ssh remove
}
#
fix_ubuntu_upstart_tty1_6_distorted_if_necessary() {
  # Ref: https://bugs.launchpad.net/ubuntu/+source/upstart/+bug/65230
  # For ubuntu 6.10-7.10 upstart problem.
  # Change the contents of /etc/event.d/tty[1-6] from:
  # start on runlevel 2
  # ->
  # start on stopped rc2
  [ ! -d /etc/event.d ] && return 9
  for i in /etc/event.d/tty[0-9]; do
    perl -pi -e "s/^start on runlevel /start on stopped rc/g" $i
  done
}
#
append_framebuffer_modules_for_ubuntu_if_necessary() {
  # For Ubuntu 7.10 using live-initramfs, if no fbcon and vesafb modules, the /scripts/init-top/framebuffer will fail to modprobe them and during the booting, the screen will be blank if vga=xxx is assigned in kernel param.
  mod_2_be_inserted="fbcon vesafb"
  if [ -f "/etc/initramfs-tools/modules" ]; then
    echo "# The following framebuffer related modules are added by Clonezilla:" >> /etc/initramfs-tools/modules
    for i in $mod_2_be_inserted; do
      echo "$i" >> /etc/initramfs-tools/modules
    done
  fi
  # A workaround to fix the framebuffer not working in Ubuntu 7.10, i.e.
  # Do not let vesafb in the blacklist-framebuffer, otherwise /script/init-top/framebuffer won't be able to modprobe it because it uses "modprobe -Qb vesafb" (-b will honor /etc/modprobe.d/blacklist-framebuffer, and if vesafb is in the list, it won't load it)
  # Ref: https://bugs.launchpad.net/ubuntu/+source/initramfs-tools/+bug/129910
  if [ -e "/etc/modprobe.d/blacklist-framebuffer" ]; then
    perl -pi -e "s|^blacklist vesafb|# blacklist vesafb # Commented by Clonezilla|g" /etc/modprobe.d/blacklist-framebuffer
  fi
  # It's better to run update-initramfs here. However, actually live helper will run it after hook scripts are run.
}
#
update_build_system_in_etc_live_conf() {
  local SYSTEM
  [ ! /etc/live.conf ] && return 1
  [ -e /etc/lsb-release ] && . /etc/lsb-release
  if [ "$DISTRIB_ID" = "Ubuntu" ]; then
    SYSTEM="Ubuntu"
  else
    SYSTEM="Debian"
  fi
  if grep -q "^[[:space:]]*BUILD_SYSTEM=" /etc/live.conf 2>/dev/null; then
    perl -pi -e "s/BUILD_SYSTEM=.*/BUILD_SYSTEM=$SYSTEM/g" /etc/live.conf
  else
    echo "BUILD_SYSTEM=$SYSTEM" >> /etc/live.conf
  fi
} # end of update_build_system_in_etc_live_conf
#
dirty_hacking_rm_files_for_ocs_live() {
  # This is dirty hacking...
  echo "Starting dirty hacking to remove files..."
  unnecessary_packages="man-db manpages info"
  echo "Force to remove some packages ($unnecessary_packages) if installed..."
  for i in $unnecessary_packages; do
   if dpkg -L $i &>/dev/null; then	   
     echo "Force to removing $i..."
     apt-get --yes --force-yes --purge remove $i
   fi
  done

  # List for the file or dir to be removed:
  # /usr/share/
  share_dir_2_be_rm="info man doc-base doc"
  # Keep the parameters.txt, avoid it to be removed later.
  # live-initramfs want to copy parameters.txt to live cd
  [ -e /usr/share/doc/live-initramfs/parameters.txt ] && {
     cp -p /usr/share/doc/live-initramfs/parameters.txt /
  }
  # Remove them
  for i in $share_dir_2_be_rm; do
    rm -rf /usr/share/$i/*
  done
  # put it back
  [ -e /parameters.txt ] && {
    mkdir -p /usr/share/doc/live-initramfs/
    mv -f /parameters.txt /usr/share/doc/live-initramfs/
  }

  # Just clean them
  # Log, clean them, but keep the file name. i.e. make the size 0, otherwise if we clean them, some daemon will complain.
  find /var/log/ -type f | xargs -I % bash -c "echo -n '' > %"
  # CPP
  [ -d /usr/lib/gcc ] && find /usr/lib/gcc/ -name "cc1" -exec rm {} \;
  find /usr/bin/ -name "cpp*" -exec rm {} \;
  if [ -e /usr/share/zoneinfo/UTC ]; then
    rm -f /etc/localtime # The original is a soft link file to UTC
    cp -af /usr/share/zoneinfo/UTC /etc/localtime
    rm -rf /usr/share/zoneinfo/*
  fi
  [ -d /usr/lib/gconv/ ] && rm -rf /usr/lib/gconv/*
  [ -d /var/backups ] && rm -rf /var/backups/*
} # end of dirty_hacking_rm_files_for_ocs_live
#
append_numlock_on_setting() {
  local kbd_cfg=$1
  # /etc/console-tools/config (for console-tools) or /etc/kbd/config (for kbd)
  [ -z "$kbd_cfg" ] && echo "No kbd_cfg!!!" && exit 1
  echo "Appending numlock on setting in $kbd_cfg..."
  cat <<-NUMLOCK_END >> $kbd_cfg

# Turn on numlock by default by DRBL/Clonezilla/GParted.
LEDS=+num
NUMLOCK_END
} # end of append_numlock_on_setting
#
turn_on_numlock_in_booting(){
  # Here we force to append setting for console-tools AND kbd, since sometimes if console-tools is installed first, and then kbd is installed again, the setting of console-tools might still exist (i.e. packkage is removed, but setting still remains).
  if [ -e "/etc/console-tools/config" ]; then
    # for console-tools
    append_numlock_on_setting /etc/console-tools/config
  fi
  if [ -e "/etc/kbd/config" ]; then
    # for kbd
    append_numlock_on_setting /etc/kbd/config
  fi
} # end of turn_on_numlock_in_booting
#
exclude_umount_live_mnt_point_in_umountfs() {
  # Since now we support only live helper, no more live package, so only exclude /live/*.
  perl -pi -e 's@(/sys\|/lib/init/rw)@$1|/live|/live/image|/live/cow|/cow|/filesystem.squashfs\) # Modified by Clonezilla@' /etc/init.d/umountfs
}
