#!/bin/ash

# This file is part of PLD batch-installer
# Copyright (C) 2001 CYBER Service
# 
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
# Author: Rafa Kleger-Rudomin, Micha Moskal
# Contributors: 

# returns, in global variables, paths of some config files:
# conffile - file name of installer.conf, default or given by -C option
# pkgsfile - file name of installer.pkgs, default or given by -P option
# groupsfile - file name of installer.groups, default or given by -G option
# pkgsetsdir - name of installer.pkgsets directory, default or given by -Z option

script_name=`basename $0`

find_config_paths () {
    # defaults
    conffile=/etc/installer.conf
    pkgsfile=/etc/installer.pkgs
    groupsfile=/etc/installer.groups
    helpfile=/doc/ui-help.txt
    sysconffile=/etc/installer.sysconf
    pkgsetsdir=/etc/installer.pkgsets

    while test "$#" -gt 0; do
    case "$1" in 
    "-C")
        test "$2" || { echo "$script_name: use -C config_file"; exit 1; }
        conffile="$2"
        shift
	;;
    "-P")
        test "$2" || { echo "$script_name: use -P pkgs_config_file"; exit 1; }
        pkgsfile="$2"
        shift
	;;
    "-S")
        test "$2" || { echo "$script_name: use -S sysconfig_file"; exit 1; }
        sysconffile="$2"
        shift
	;;
    "-G")
        test "$2" || { echo "$script_name: use -G groups_file"; exit 1; }
	groupsfile="$2"
        shift
	;;
    "-Z")
        test "$2" || { echo "$script_name: use -Z pkgsets_dir"; exit 1; }
	pkgsetsdir="$2"
        shift
	;;
    "-H")
        test "$2" || { echo "$script_name: use -H help_file"; exit 1; }
        helpfile="$2"
        shift
	;;
    esac
    shift
    done
}

load_installer_rc () {
  # defaults, should be overridden
  INSTALLER_DIR="/inst/pkg"
  KERNEL_VER="2.2.20"
  KERNEL_VERCODE="2"
  FTP_DIST_DIR="/dists/ra/PLD"
  
  if test -r /etc/installer-rc ; then
    . /etc/installer-rc
  fi
}

load_config () {
  local id
  
  if test -r "$conffile" ; then
    id=1
    while [ "$id" -lt 100 ] ; do
      eval dest_part${id}_mnt_point=
      eval dest_part${id}_device=
      id=$(($id+1))
    done
    PATH=$PATH:. . "$conffile"
  else
    die "$script_name: cannot open $conffile" 
  fi

  load_installer_rc
}

# set source_dir to actuall name if it if set to 'auto' (find PLD directory on src)
# to be called after load_config, by modules, that needs source_dir
find_source_dir () {
  local dirs

  if [ "$source_dir" = auto ] ; then
    if test ! -d $source_mountpoint ; then
      die "cannot find $inst_dir on $source_mountpoint, since it ain't dir"
    fi
    dirs=`find "$source_mountpoint" -type d -name PLD || :`
    # choose first one if multiple found
    for i in $dirs; do 
	test -d "$i/RPMS" || continue
	test -d "$i/../$inst_dir" || continue
	source_dir=`echo "$i" | sed "s@^$source_mountpoint@@" | sed 's@/PLD$@@' || :`
	break
    done
    test "x$source_dir" != "xauto" || die "die cannot find $inst_dir and PLD/RPMS dirs on source"
  fi
}


load_or_create_config () {
    if test -r "$conffile"; then
         id=1
         while [ "$id" -lt 100 ] ; do
           eval dest_part${id}_mnt_point=
           eval dest_part${id}_device=
           id=$(($id+1))
         done
	 PATH=$PATH:. . "$conffile"
    else
	 echo -n >"$conffile"
    fi
    
    load_installer_rc
}

load_pkgs_config () {
    test -r "$pkgsfile" || { echo "cannot open $pkgsfile"; exit 1; }
    PATH=$PATH:. . "$pkgsfile"
}

load_or_create_pkgs_config () {
    if test -r "$pkgsfile"; then
	 PATH=$PATH:. . "$pkgsfile"
    else
	 echo -n >"$pkgsfile"
    fi
}

load_sys_config () {
    if test -r "$sysconffile" ; then
      PATH=$PATH:. . "$sysconffile"
    else
      log warn "cannot open $sysconffile"
    fi
}

load_or_create_sys_config () {
    if test -r "$sysconffile"; then
	 PATH=$PATH:. . "$sysconffile"
    else
	 echo -n >"$sysconffile"
    fi
}

has_rpm () {
  if grep -q "^${1}\$" $pkgsfile ; then
    return 0
  else
    return 1
  fi
}

add_rpm () {
  if has_rpm $1 ; then
    : ok
  else
    # check to see if there is final newline in the file...
    # some braindead editors tends to leave line with no \n
    if [ "$( (cat $pkgsfile; echo foo) | tail -n 1)" != \
         "$( (cat $pkgsfile; echo; echo foo) | tail -n 1)" ] ; then
       echo >> $pkgsfile
    fi
    echo "$1" >> $pkgsfile
  fi
}


# return first element (car) of the list
list_car () { echo "$1"; }

# return the tail (cdr) of the list
list_cdr () { shift || : ; echo "$@"; }

########


if test "$DEBUG" ; then
  screen_lev=0
  file_lev=0
else
  screen_lev=1
  file_lev=1
fi


# if we are run from bootdisk, send output into 'system' file
if test -w /var/log/; then
    # if the file is not writable, delete it
    # (may be orphaned link for example)
    test -w /var/log/installer || rm -f /var/log/installer
    log_file=/var/log/installer
else
    log_file=`pwd`/debug.log
fi

log_console=/dev/tty6

if test -w $log_console ; then
  : ok
else
  log_console=/dev/null
fi

# log the output to file and display
log_wrap_verb () {
    log debug "Run: $*"
    # I hate subshells ...
    rm -f /tmp/log_wrap_status_ok
    if $@ 2>&1; then echo >/tmp/log_wrap_status_ok; fi | \
      	tee -a "$log_file" | \
      	tee -a "$log_console"
    if test -f /tmp/log_wrap_status_ok ; then
      rm -f /tmp/log_wrap_status_ok
      return 0
    else
      log warn "running $* failed."
      return 1
    fi
}

# log the output to file
log_wrap () {
    log debug "Run: $*"
    # I hate subshells ...
    rm -f /tmp/log_wrap_status_ok /tmp/log_wrap_log
    if $@ 2>&1; then echo >/tmp/log_wrap_status_ok; fi | \
	tee -a /tmp/log_wrap_log | \
      	tee -a "$log_console" >> $log_file
    if test -f /tmp/log_wrap_status_ok ; then
      rm -f /tmp/log_wrap_status_ok /tmp/log_wrap_log
      return 0
    else
      cat /tmp/log_wrap_log 1>&2
      rm -f /tmp/log_wrap_log
      log warn "running $* failed."
      return 1
    fi
}


# usage: log {DEBUG|VERBOSE|INFO|WARNING|ERROR} msg
# with no parameters, read stdin and send to log_file
log () {
  local lev msg name

  if test -z "$1"; then
    cat >>$log_file
    return 0
  fi
  
  msg=$2
  case "$1" in
  D* | d* ) 
    lev=0
    name="       "
    ;;
  V* | v* ) 
    lev=1
    name="     "
    ;;
  I* | i* ) 
    lev=2
    name="   "
    ;;
  W* | w* )
    lev=3
    name="***"
    ;;
  E* | e* )
    lev=4
    name="!!!"
    ;;
  * )
    # possibly error of some kind
    lev=1
    msg="$1 $2"
    name="???"
    ;;
  esac

  if [ $lev -ge $screen_lev ] ; then
    echo >&2 "$name $msg"
  fi
  
  if [ $lev -ge $file_lev ] ; then
    echo "[$script_name `date +%T` $lev] $msg" >> $log_file
  fi

  echo "[$script_name `date +%T` $lev] $name $msg" >> $log_console
}

die () {
  log err "$@"
  exit 1
}

is_dest_mounted () {
  mount | grep -q " on /dest" || { 
    log err "/dest not mounted"
    exit 1
  }
}

# for a given partition number, eval variables dest_part_mnt_point...
eval_partition_info () {
	eval "dest_part_mnt_point=\$dest_part${1}_mnt_point"
	eval "dest_part_device=\$dest_part${1}_device"
        eval "dest_part_size=\$dest_part${1}_size"
	eval "dest_part_filesystem=\$dest_part${1}_filesystem"
	eval "dest_part_format_partition=\$dest_part${1}_format_partition"
	eval "dest_part_options=\$dest_part${1}_options"
	eval "dest_part_format_options=\$dest_part${1}_format_options"
}


# wrapper to busybox printf patched by malekith to behave like gettext command
nls () {
    local printf message_file lang
    if test "$LANG"; then 
	lang=`echo $LANG | cut -c 1-2`
    else
	lang=en
    fi
    if test -x /bin/busybox; then
	# we are run from bootdisk
	printf="printf"
	message_file=/usr/lib/installer/${lang}.mo
    elif test -x /usr/bin/busybox ; then
	printf="busybox printf"
	message_file=po/${lang}.gmo
	test -f $message_file || message_file=../$message_file || :
    else
        printf=printf
	message_file=/file/that/doesnt/exist
    fi
    if test -f "$message_file"; then
	$printf -n $message_file "$@"
    else
	$printf "$@"
    fi
}

dial() { eval `dml "$@" || :`; }


# set VARIABLE=VALUE in file from /dest/etc/
# args: file var value
# create file if does not exist
set_var () {
    local file
    local var=$2
    local val=$3
    file0=/etc/$1
    file=/dest${file0}
    test -f $file || echo "# File created by installer" >$file
    if grep -q "^${var}=" $file; then
	cp $file $file.tmp
	sed "s@^${var}=.*@${var}=\"${val}\"@g" $file.tmp >$file
	rm -f $file.tmp
    else
	echo "# Added by installer" >>$file
	echo "${var}=\"${val}\"" >>$file
	chmod 644 $file
    fi
    log info "`nls "Setting %s=%s in file %s" "$var" "$val" "$file0"`"
}


set_module_alias () {
    local var=$1
    local val=$2
    local opt="$3"
    file=/etc/modules.conf
    test -f $file || echo "# File created by installer" >$file
    if grep -q "^alias ${var} " $file; then
	cp $file $file.tmp
	sed "s@^alias ${var} .*@$alias ${var} ${val}@g" $file.tmp >$file
	rm -f $file.tmp
    else
	echo "# Added by installer" >>$file
	echo "alias ${var} ${val}" >>$file
	chmod 644 $file
    fi
    if test "$opt" ; then
      if grep -q "^options ${val} " $file; then
	cp $file $file.tmp
	sed "s@^options ${val} .*@$options ${val} ${opt}@g" $file.tmp >$file
	rm -f $file.tmp
      else
	echo "# Added by installer" >>$file
	echo "options ${val} ${opt}" >>$file
	chmod 644 $file
      fi
    fi
}

make_ide_cd_devfs_links () {
  # we have /dev/hd[a-h] broken links, in case they are cdroms
  if [ $KERNEL_VERCODE -ge 4 ] ; then
    for f in /dev/ide/host*/bus*/target*/lun*/cd ; do
      if test -r `dirname $f`/disc ; then
        : skip
      else
        ln -s cd `dirname $f`/disc
      fi
    done
  fi
}

make_scsi_cd_devfs_links () {
  if [ $KERNEL_VERCODE -ge 4 ] ; then
    for f in /dev/cdroms/cdrom* ; do
      lnk=$(echo $f | sed -e 's|/dev/cdroms/cdrom|/dev/scd|')
      if test -r $lnk ; then
        : skip
      else
        ln -s $f $lnk
      fi
    done
  fi
}

if test -x /bin/busybox -a -d /dest -a -d /src ; then
  real_system=no
else
  real_system=yes
fi

# hmm, ash have some problems with '.', let's eval
if [ $real_system = no ] ; then
    # we are run from bootdisk, set language then
    if test -f /etc/profile; then
	eval `cat /etc/profile`
    fi
fi

arch=`uname -m | sed -e 's/i.86/ia32/; s/athlon/ia32/'`

mega_to_kilo () {
    local fixed fraction
    fixed=`echo $1 | sed 's/\..*//'`
    test "$fixed" -ge 0 || die "fixed part of $1 must be non negative number"
    test "$fixed" -le 2000000 || die "so huge disks unsupported (above 2TB), sorry"
    if echo $1 | grep -q '\.'; then 
	fraction=`echo $1 | sed 's/.*\.//'` 
    else
	fraction=0
    fi
    test "$fraction" -ge 0 || die "fraction part of $1 must be non negative number"

    expr $fixed '*' 1000 + $fraction || die "problems evaluating numeric expression"
}

kilo_to_mega () {
    if test $1 -le 10; then 
	echo "0.00$1"
    elif test $1 -le 100; then 
	echo "0.0$1"
    elif test $1 -le 1000; then 
	echo "0.$1"
    else
	echo "$1" | sed 's/[0-9][0-9][0-9]$/.&/'
    fi
}

# usage: part DEVICE MINOR -> make partiton name
part () {
  if echo $1 | grep -q '/dev/\(ida\|rd\|cciss\|ataraid\)/' ; then
    echo "${1}p${2}"
  else
    echo "$1$2"
  fi
}

save_var () { 
  eval "echo \"\$$1\" >/tmp/saved-var-$1" 
}

load_var () { 
  eval "$1=\`cat /tmp/saved-var-$1\`"
}

# usage: eval $(parse_boot_loader_entry "$ble")
parse_boot_loader_entry () {
  entry="$1"
  echo "$entry" | (
    kernel=
    initrd=
    IFS=:
    case "$entry" in
      linux:*:*:*:* )
	read kind label kernel initrd root
        ;;
      linux:*:*:* )
        read kind label kernel root
	;;
      bsd:* | dos:* )
	read kind label root
	;;
      * )
	kind=evil
	root=
	label=
	;;
    esac
    echo "img_os=$kind img_label=$label img_root=$root img_initrd=$initrd"
    echo "img_kernel=$kernel"
  )
}

is_mini_iso () {
  case "$source" in
    cdrom )
      if test -f /src/pld-*-MINI ; then
        return 0
      fi
      ;;
  esac
  return 1
}

count_cpus () {
  if echo "$pkgs_cpus" | grep -q '^[0-9][0-9]*$' ; then
    echo $pkgs_cpus
  else
    # uh... there is no wc on bootdisk
    echo $(grep '^processor[ 	]*:' /proc/cpuinfo | (
      count=0
      while read LINE ; do
        count=$(($count+1))
      done
      echo $count))
  fi
}

is_smp () {
  if [ $(count_cpus) -gt 1 ] ; then
    return 0
  else
    return 1
  fi
}

export ASH_REPORT_EFLAG=1

# vim:ft=sh
