#!/bin/sh -efu

alterator_api_version=1
. alterator-sh-functions

# udevadm trigger
# udevadm settle

unset \
	LANG \
	LANGUAGE \
	LC_CTYPE \
	LC_NUMERIC \
	LC_TIME \
	LC_COLLATE \
	LC_MONETARY \
	LC_MESSAGES \
	LC_PAPER \
	LC_NAME \
	LC_ADDRESS \
	LC_TELEPHONE \
	LC_MEASUREMENT \
	LC_IDENTIFICATION \
	LC_ALL \
	||:

PATH="/usr/share/alterator-lilo/helpers:$PATH"
lilo_tmpl="/usr/share/alterator-lilo/template/lilo.conf"
lilo_conf="/etc/lilo.conf"
tmpconf="/tmp/lilo.conf"
confonly=
workdir=
target_dir="${target_dir:-/mnt/destination}"

############
# use lilo.conf from $LILO_DESTDIR and run lilo in chroot $LILO_DESTDIR
LILO_DESTDIR=
if [ -d "$target_dir/etc/" ]; then
  LILO_DESTDIR="$target_dir"
  lilo_conf="$LILO_DESTDIR/$lilo_conf"
  for i in proc dev sys; do
    mkdir -p -- "$LILO_DESTDIR/$i"
    mountpoint -q "$LILO_DESTDIR/$i" ||
      mount --bind /$i "$LILO_DESTDIR/$i"
  done
fi
############

exit_handler() {
	local rc=$?
	trap - EXIT
	rm -rf -- "$workdir"
	exit $rc
}

trap exit_handler HUP PIPE INT QUIT TERM EXIT
workdir="$(mktemp -dt "${0##*/}.XXXXXXXXXX")" || exit 1

globals="$workdir/globals"
sections="$workdir/sections"
tmp_section="$workdir/section.tmp" # for section editing 
order="$workdir/label.order"
conf="$workdir/lilo.conf"
fdisk_out="$workdir/fdisk.out"

others_list="$workdir/others"

liloopts="-H"

. lilo-disk.sh
. lilo-raid-boot.sh
. lilo-parser.sh
. lilo-other-system.sh
. lilo-bootable-flag.sh
. lilo-fix-cdrom.sh
. lilo-conf.sh
. lilo-evms.sh

conf_exists="yes"
[ -f $lilo_conf ] || conf_exists="no";

normalize_liloconf "$lilo_conf" "$lilo_tmpl" > "$conf"
# remove bootdev protection
sed -i 's/^\([[:space:]]*boot[[:space:]]*="\?\)#disabled#/\1/' "$conf"
find_others > "$others_list"

# add other kernels and OS to lilo.conf
if [ "$conf_exists" != "yes" ]; then
  add_kernels  >> "$conf"
  add_others   >> "$conf" < "$others_list"
  # fast boot if there are no other systems
  [ -s "$others_list" ] || subst 's/timeout="100"/timeout="10"/' "$conf"
fi
update_rootdev     "$conf"

parse_liloconf     "$conf" "$conf_exists"

DEBUG=
on_message() {

    case "$in_action" in
	list)
	  case "$in__objects" in
	    bootloader_places)

              SIZE_DEC_PT="$(LC_NUMERIC="$in_language" locale decimal_point)"
              SIZE_b="`_ "b"`"
              SIZE_kb="`_ "kb"`"
              SIZE_Mb="`_ "Mb"`"
              SIZE_Gb="`_ "Gb"`"
              SIZE_Tb="`_ "Tb"`"

	      local hd_label="`_ "Hard drive"`"
	      local lp_label="`_ "Linux partition"`"
	      list_bootloader_places |\
	        sed -e "s/Hard drive/$hd_label/"\
	            -e "s/Linux partition/$lp_label/" | \
	        write_enum
	    ;;
	    others)
	      # test_other_section needs fresh "$tmpconf"!
              if ! generate_liloconf "$tmpconf"; then
                write_error "can't generate liloconf"
                return
              fi
	      # show all bootable partitions with boot loaders
	      # enabled parameter - is this partition appeares in config file
	      list_others "$tmpconf" < "$others_list"
	    ;;
	    sections)
	      local def= def_label= label= sect_type=
	      def_label="$(show_default)"

	      while read -r sect_type label; do
	        [ -n "$label" -a -f "$sections/$label" ] || continue
		[ "$label" != "$def_label" ] && def="no" || def="yes"

		label="$(quote_shell "$label")"
                _write_begin
                write_string_param "name"    "$label"
                write_string_param "label"    "$label"
                write_string_param "type"    "$sect_type"
                write_bool_param   "default" "$def"
                [ "$label" = "failsafe" ] && write_string_param "label" "`_ "failsafe"`"
                _write_end
	      done < "$order"
	    ;;
	    install_list)
	      write_enum_item "menu" "`_ "graphics"`"
	      write_enum_item "text" "`_ "text"`"
	    ;;
	    raid_extra_boot_list)
	      write_enum_item "" ""
	      write_enum_item "none"     "`_ "none"`"
	      write_enum_item "auto"     "`_ "auto"`"
	      write_enum_item "mbr"      "`_ "mbr"`"
	      write_enum_item "mbr-only" "`_ "mbr-only"`"
	    ;;
	    std_timeouts)
	      write_enum_item "0"      "`_ "no wait"`"
	      write_enum_item "10"     "`_ "1 second"`"
	      write_enum_item "50"     "`_ "5 seconds"`"
	      write_enum_item "100"    "`_ "10 seconds"`"
	      write_enum_item "200"    "`_ "20 seconds"`"
	      write_enum_item "600"    "`_ "1 minute"`"
	      write_enum_item ""       "`_ "infinite"`"
	    ;;
	  esac
	  ;;
	read)
	  case "$in__objects" in
	    dev)
	      # currently selected boot device
	      local current_dev=$(get_curr_dev)
	      # current_dev_cnv must be eq boot_cnv or be in disk list.
	      # If it is not so, simple interface will make it #f!
	      # So let's use fix_boot util
	      write_string_param "current" "$(fix_boot $current_dev)"
	      ;;
	    globals)
	      [ -f "$globals" ] && show_params_list "$globals"
	      ;;
	    sections)
	      [ -f "$sections/$in_section" ] && show_params_list "$sections/$in_section"
	      ;;
	    source)
	      if ! generate_liloconf "$tmpconf"; then
	        write_error "can't generate liloconf"
	        return
	      fi
	      write_string_param "source"   "$(cat "$tmpconf")"
	      write_string_param "liloopts" "$liloopts"
	      ;;
	  esac
	  ;;
	write)
	  case "$in__objects" in
	    source)
	      if [ -n "$in_source" ]; then
	        printf '%s\n' "$in_source" > "$tmpconf"
	        [ ! -f "$globals" ]  || rm -f -- "$globals"
	        [ ! -f "$sections" ] || rm -f -- "$sections"
	        [ ! -f "$order" ]    || rm -f -- "$order"
	        normalize_liloconf "$tmpconf" "$lilo_tmpl" > "$conf"
	        parse_liloconf     "$conf" "yes"
	      fi
	      liloopts="$in_liloopts"
	    ;;
	    timeout) # for new simple interface
	      write_globals "timeout"
	    ;;
	    globals)
#	      write_debug "Writing %s\n" "$in_target"
	      write_globals "$in_target"
	    ;;
	    section)
#	      write_debug "Writing section %s\n" "$in_label"
	      write_section "$in_oldlabel" "$in_label"
	    ;;
	    section-remove)
#	      write_debug "Removing section %s\n" "$in_label"
	      remove_section "$in_label"
	    ;;
	    reset)
	      reset_changes "$conf" "$in_part"
	    ;;
	    simple_sections)
	      # test_other_section needs fresh "$tmpconf"!
              if ! generate_liloconf "$tmpconf"; then
                write_error "can't generate liloconf"
                return
              fi

	      for s in ${in_sections//;/ }; do
	        # if section is on but is not in conf -- add it
	        if [ -z "${s%%+*}" ]; then
	          local dev="${s#+}"
	          local label="$(test_other_section "$dev" "$tmpconf")"
	          if [ -z "$label" ]; then
	            # find right label in $others_list
	            while read d l; do
	              [ "$d" = "$dev" ] && label="$l"
	              echo "Adding $d $dev - $l $label"
	            done < "$others_list"
	            echo "Adding $dev - $label"
	            if [ -n "$label" ]; then
	              in_type="other"
	              in_other="$dev"
	              in_label="$label"
	              in_alias=""
	              in_table=""
	              [ -n "${label##Windows*}" ] || in_master_boot="#t"
	              write_section "" "$label"
	            fi
	          fi
	        fi
	        # if section is off but is in conf -- remove it
	        if [ -z "${s%%-*}" ]; then
	          local dev="${s#-}"
	          local label="$(test_other_section "$dev" "$tmpconf")"
	          if [ -n "$label" ]; then
	            echo "Removing $dev - $label"
	            remove_section "$label"
	          fi
	        fi
	      done
	    ;;
	    commit)
	      if ! generate_liloconf "$tmpconf"; then
	        write_error "`_ "Unable to create temp config file"`"
	        return
	      fi
	      if test_bool "$in_confonly"; then
#	        write_debug "Installing lilo.conf to system\n"
	        mv -f -- "$tmpconf" "$lilo_conf" ||
	          write_error "`_ "Unable to write new lilo.conf"`"
	        # add bootdev protection
	        sed -i 's/^\([[:space:]]*boot[[:space:]]*="\?\)/\1#disabled#/' "$lilo_conf"
	      else
#	        write_debug "Installing lilo.conf to system and running lilo\n"

		# Broken evms workaround.
		# We must install lilo to /dev/evms/sda5, not /dev/sda5!
		local boot_dev="$(get_curr_dev)"
		local evms_dev="$(evms_protection $boot_dev)"

		write_debug "running lilo with options: $liloopts"

		write_liloconf "$tmpconf" "$lilo_conf" "$liloopts ${evms_dev:+ -b $evms_dev}"
	      fi
	    ;;
	  esac
	  ;;
    esac
}

message_loop
