#!/bin/sh
# Utility functions

count_words () {
  echo "$#"
}

first () {
  echo "$1"
}

second () {
  echo "$2"
}

third () {
  echo "$3"
}

fourth () {
  echo "$4"
}

last () {
  eval echo $"$#"
}

mkmodulevarname () {
    echo $1 | $sed 's/[-+,]/_/g'
}

basemodulename () {
  local module=$1
  # strip off .o suffix
  module=${module%.o}
  # strip off path prefix
  module=${module##*/}
  echo $module
}

write_it_down () {
  local reply
  echo ""
  echo "$1"
  echo ""
  echo $bold"$msg_Something_went_wrong"$norm
  read reply
  return $?
}

build_lists () {
    if [ -f /proc/modules ]; then
	installed_module_list="$(sed -e 's/\([^ 	]\)[ 	].*/\1/' < /proc/modules)"
    fi
    return 0;
}

in_list () {
  local a=$1
  local i
  shift

  for i in $*; do
    if [ "$i" = "$a" ]; then
      return 0
    fi
  done
  return 1
}

module_is_installed () {
  in_list $1 "$installed_module_list"
  return $?
}

module_args () {
  local module=$1

  if [ ! -e $ModuleHelpDir/descr.gz ]; then
    return
  fi
  zcat $ModuleHelpDir/descr.gz | $sed -e 's/^#.*//' \
    | (IFS=\n; retcode=0;
        while read line ; do
          case $line in
            "Module: $module")
              while read line; do
                case "$line" in
                  " "*)
                    echo "$line"
                    ;;
                  "NoParams:")
                    retcode=3
                    ;;
                  *)
                    return $retcode
                    ;;
                esac
              done
              return $retcode
          esac
        done
        return 1)
	
  return $?
}

module_summary () {
  local summary=""
  local modulevarname=$(mkmodulevarname $1)

  eval "summary=$`echo summary_$modulevarname`"
  if [ -n "$summary" ]; then
    echo -n "$summary"
  else
    echo -n "$msg_Desc_not_avail"
  fi
}

build_module_directory_menu () {
  local directory="$1"
  local list

  if [ "$Source" = "floppy" ]; then
    eval "list=$`echo dir_content_$directory`"
  else
    list="$Dir_Prefix/$directory/*.o"
  fi

  for i in $list; do
    # Strip directory and .o suffix
    local module=$(basemodulename $i)
    
    if [ "$module" != '*' ]; then
      local selected=" -"

      if module_is_installed $module; then
        selected=" +"
      fi

      echo -n \"
      echo -n $module |$sed -e 's/^\(...............\).*$/\1/'
      echo -n \" \"$selected" "
      module_summary $module
      echo \" \\
    fi
  done
  echo ""
}

module_directory_menu () {
  local directory="$1"
  local text="$2"
  local title="$3"

  while true; do

    build_lists

    echo 'menu "$text" "$title" \' > $TempFile.1
    echo '"$msg_Exit" "   $msg_Finished_these" \' >> $TempFile.1
    echo '" " " " \' >> $TempFile.1
    
    infoBox "$msg_Please_wait_l" "$msg_Please_wait"

    build_module_directory_menu $directory >> $TempFile.1

    local result
    result="$(. $TempFile.1)"
    if [ $? -ne 0 ]; then return 1; fi

    case "$result" in
      " ")
        ;;
      "$msg_Exit")
        return 0;;
      *)
        if [ $Source = floppy ]; then
          local list
          eval "list=$`echo dir_content_$directory`"
          for i in $list; do
            case "$i" in
              $result*)
                result=$i;
                break;
                ;;
            esac
          done
        else
          result=$(basemodulename $Dir_Prefix/$directory/$result*.o)
        fi

        edit_module "$result"
        ;;
    esac
    rm -f $TempFile.1
  done
}

edit_module () {
  local module="$1"
  local help="`module_summary $module`"
  local selected=" -"
  local text="$help
$msg_module_not_installed"

  if module_is_installed $module; then
    selected=" +"
    text="$help
$msg_module_installed"
  fi

  if [ "$selected" = " +" ]; then
    if yesNoBox "$msg_Remove_l" "$module"; then
      remove_module $module
    fi
  else
    if yesNoBox "$msg_Install_l" "$module"; then
      install_module $module
    fi
  fi
  return 1
}

parse_arguments () {
  local module="$1"

  for i in $MODUTILSDIR/* ; do
    if [ -d $i ]; then
      continue
    fi
    cat $i | \
      ( while read line; do
        set -- $line; 
        if [ "$1" = options -a "$2" = "$module" ]; then
          shift; shift; echo $@; break;
        fi; 
      done)
  done
}


edit_arguments () {
  local module="$1"
  local old_arguments="$(parse_arguments $module)"

  local arguments
  module_args $module >$TempFile.3
  local status=$?
  if [ $status -eq 2 ]; then
    echo -n "msgBox \"" >$TempFile.2
    cat $TempFile.3 >>$TempFile.2
    echo "\" \"Module info\"">>$TempFile.2
    arguments="`. $TempFile.2`"
    return 0
  fi
  if [ $status -ne 3 ]; then
    echo -n "inputBox \"" >$TempFile.2
    cat $TempFile.3 >>$TempFile.2 
    echo "">>$TempFile.2
    echo "$msg_enter_arguments_l\" \\" >>$TempFile.2
    echo "\"$msg_enter_arguments\" \\" >>$TempFile.2
    echo "\"$old_arguments\"" >>$TempFile.2

    arguments="`. $TempFile.2`"
    if [ $? -ne 0 ]; then return 1; fi
  else
    arguments=''
  fi

  arguments=$(echo $arguments|$sed 's/ *= */=/g')
  update_modules_conf "$module" "$arguments"
}

install_module () {
  local module="$1"
  sync

  edit_arguments $module
  if [ $? -ne 0 ]; then return 1; fi  

  echo $clear$bold"`eval echo \\\"$msg_Installing_module\\\"`"$norm
  echo ""
  sync

  get_and_insmod $module
  local status=$?

  echo ""
  if [ $status -eq 0 ]; then
    echo "$msg_Installation_succeeded"
    if [ ! -f $MODULESFILE ]; then
      touch $MODULESFILE
    fi
    echo "$module" >> $MODULESFILE
  else
    echo "$msg_Installation_failed"
  fi

  echo ""
  echo $bold"$msg_Please_press_ENTER"$norm
  local reply
  read reply

}

get_and_insmod () {
  local module=$1
  local file
  local i

  case "$Source" in
  floppy)
    echo -n $clear "`eval echo \\\"$msg_Extracting_module\\\"`"
    if [ ! -f /floppy/modules.tgz ]; then
      write_it_down "$msg_tgz_does_not_exist"
    fi
    (cd /; zcat < /floppy/modules.tgz | $extract \*/$module.o)
    file="/lib/modules/*/*/$module.o"
    echo "$msg_done"
    depmod -a
    $SIMULATE modprobe $module -C $Target/etc/modules.conf
    local status=$?
    rm -f $file
    ;;
  mounted)
    $SIMULATE modprobe $module -C $Target/etc/modules.conf
    local status=$?
    ;;
  esac

  for i in $Run_Shell; do
    local script
    local modulevarname=$(mkmodulevarname $1)
    eval "script=\$$shell_${i}_$modulevarname"
    if [ -n "$script" ]; then
      echo 
      echo "`eval echo \\\"$msg_Executing_postinst\\\"`"
      echo script: $script
      eval $script
      if [ $? -ne 0 ]; then
        write_it_down "`eval echo \\\"$msg_postinst_failed\\\"`"
      fi
      echo "`eval echo \\\"$msg_postinst_done\\\"`"
    fi
  done
  return $status
}

remove_module () {
  sync
  local module="$1"

  echo $clear$bold"`eval echo \\\"$msg_Removing_module\\\"`"$norm
  echo ""
  sync
  $SIMULATE modprobe -r $module
  if [ $? -ne 0 ]; then
    write_it_down "`eval echo \\\"$msg_not_removed\\\"`"
    return 1
  fi
  if [ -f $MODULESFILE ]; then
    rm -f $MODULESFILE.tmp
    $sed -e /^$module\$/d < $MODULESFILE >$MODULESFILE.tmp
    if [ $? -ne 0 ]; then return 1; fi
    chown 0.0 $MODULESFILE.tmp
    chmod 644 $MODULESFILE.tmp
    sync
    rm -f $MODULESFILE.old
    ln $MODULESFILE $MODULESFILE.old
    mv $MODULESFILE.tmp $MODULESFILE
    sync
        fi

  return 0
}

check_modules () {
  if [ ! -f $MODULESFILE ]; then
    cat > $MODULESFILE <<EOF
# /etc/modules: kernel modules to load at boot time.
#
# This file should contain the names of kernel modules that are
# to be loaded at boot time, one per line.  Comments begin with
# a #, and everything on the line after them are ignored.
EOF
  fi
}

check_modules_conf () {
  if [ -f $CFGFILE ]; then
    grep -q "$CFGHEADER" $CFGFILE
    if [ $? -eq 1 ]; then
      echo "Error: the current $CFGFILE is not automatically generated."
      echo "Use \"update-modules force\" to force (re)generation."
      exit 1
    fi
  fi
}

check_dirs () {
  if [ -f $MODUTILSDIR ]; then
    echo "Warning! $MODUTILSDIR is a file rather than a directory. Moving it aside"
    mv -f $MODUTILSDIR $MODUTILSDIR.0
    mkdir -p $MODUTILSDIR
  elif [ ! -d $MODUTILSDIR ]; then
    mkdir -p $MODUTILSDIR
  fi
}

update_modules () {
  local moved_modules_conf=""
  local moved_modutils_dir=""
  local moved_modules=""
  local modules_conf=${CFGFILE#$Target}
  local modutils_dir=${MODUTILSDIR#$Target}
  local modules=${MODULESFILE#$Target}
  local foo=""
  
  if [ ! -x /sbin/update-modules -a ! -x $Target/sbin/update-modules ]; then
    logger -t 'modconf' -p 'user.err' 'update-modules not found!'
    return
  fi

  if [ -n "$Target" ]; then
    if [ -e $modutils_dir ]; then
      $SIMULATE mv $modutils_dir $modutils_dir.$$
      moved_modutils_dir=1
    fi
    if [ -e $modules ]; then
      $SIMULATE mv $modules $modules.$$
      moved_modules=1
    fi

    test -e $MODULESFILE || touch $MODULESFILE
    test -d $MODUTILSDIR || mkdir -p $MODUTILSDIR

    $SIMULATE ln -sf $MODULESFILE $modules
    $SIMULATE ln -sf $MODUTILSDIR $modutils_dir
  fi
  
  if [ -x /sbin/update-modules ]; then
    $SIMULATE /sbin/update-modules force
  elif [ -x $Target/sbin/update-modules ]; then
    $SIMULATE $Target/sbin/update-modules force
  fi

  if [ -n "$Target" ]; then
    $SIMULATE cp -f $modules_conf $CFGFILE
    $SIMULATE rm -f $modules
    $SIMULATE rm -f $modutils_dir
    test -z "$moved_modules" || $SIMULATE mv $modules.$$ $modules
    test -z "$moved_modutils_dir" || $SIMULATE mv $modutils_dir.$$ $modutils_dir
  fi

  if [ -n "$SIMULATE" ]; then
    echo "Press enter to continue"
    read foo
  fi
}

update_modules_conf () {
  local module="$1"; shift;
  local arguments="$@"
  local done=""
  local modd=""

  if [ -n "module" ]; then
    for i in $MODUTILSDIR/* ; do
      if [ -d $i ]; then
        continue
      fi
      cat $i | \
      ( while read line; do
        set -- $line; 
        if [ "$1" = options -a "$2" = "$module" ]; then
          if [ -n "$arguments" ] ; then
            shift; shift; modd=true; done=true;
            echo options $module "$arguments" ;
          fi; 
        else 
          echo $line;
        fi; 
        done; 
      )   > $TempFile.4
      if [ $modd ]; then
        cat $TempFile.4 > $i
        modd=""
      fi
    done
    rm -f $TempFile.4
    if [ -z "$done" -a -n "$arguments" ]; then
      echo options $module "$arguments" > $MODUTILSDIR/$module
      chown 0.0 $MODUTILSDIR/$module
      chmod 644 $MODUTILSDIR/$module
    fi;
  fi
  
  update_modules
}
