#!/bin/sh
# Utility functions

count_words () {
  echo "$#"
}

first () {
  echo "$1"
}

second () {
  echo "$2"
}

third () {
  echo "$3"
}

fourth () {
  echo "$4"
}

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

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

modul_suffix () {
   case "$(uname -r | cut -f2 -d.)" in
      0|1|2|3|4)
      modsuffix=".o"
      using_mit=1
      ;;
      *) 	modsuffix=".ko" ;;
   esac
   modend=\*$modsuffix
}

basemodulename () {
  local module
  module=$1
  # strip off the apropriate suffix
  module=${module%$modsuffix}
  # 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="$(cut -f1 "-d " /proc/modules)"
    fi
    return 0;
}

build_chandev_list () {
    kver=`uname -r`
    chandev_module_list="$(for file in `find /lib/modules/$kver -name $modend`; do grep -q "chandev_register" $file;  if [ $? -eq 0 ]; then basemodulename $file; fi; done | sort -u)"
    return 0;
}

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

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

module_is_installed () {
  local module
  module=$1
  in_list $(mkmodulevarname $module) $(mkmodulevarname $installed_module_list)
  return $?
}

module_args () {
  local module
  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
  summary=""
  local modulevarname
  modulevarname=$(mkmodulevarname $1)

  eval "summary=$`echo summary_$modulevarname`"
  if [ -n "$summary" ]; then
    echo -n "$summary" | sed s/\"/\\\\\"/g
  else
    echo -n "$msg_Desc_not_avail"
  fi
}

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

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

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

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

      echo -n \"
      echo -n $module
      echo -n \" \"$selected" "
      module_summary $module
      echo \" \\
    fi
  done
  echo ""
}

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

  while true; do
    local defaultitem

    build_lists

    echo 'menu "$text" "$title" "$defaultitem" \' > $TempFile1
    echo '"$msg_Exit" "   $msg_Finished_these" \' >> $TempFile1
    echo '" " " " \' >> $TempFile1
    
    infoBox "$msg_Please_wait_l" "$msg_Please_wait"

    build_module_directory_menu $directory >> $TempFile1

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

    case "$result" in
      " ")
        ;;
      "$msg_Exit")
        return 0;;
      *)
        defaultitem=result
        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$modsuffix)
        fi

        edit_module "$result"
        ;;
    esac
  done
}

edit_module () {
  local module
  module="$1"
  local help
  help="`module_summary $module`"
  local selected
  selected=" -"
  local text
  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
  module="$1"

  machine=`uname -m`
  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;
        elif [ "$machine" = "s390" -a "$i" = "$MODUTILSDIR/$module.chandev" ] && echo $1 | grep -q "^[^#]" ; then
          echo $@; break;
        fi; 
      done)
  done
}


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

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

    arguments="`. $TempFile2`"
    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
  module="$1"
  sync

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

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

  local status
  get_and_insmod $module
  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"
    remove_from_modules_conf $module
  fi

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

  if ( echo "$module" | grep "uhci\|ohci" >/dev/null 2>&1 ) ; then
     echo
     echo "$msg_usb_keyboard_failure"
     (sleep 15 ;
     get_and_insmod hid && echo "hid" >> $MODULESFILE
     get_and_insmod input && echo "input" >> $MODULESFILE
     get_and_insmod keybdev && echo "keybdev" >> $MODULESFILE
     get_and_insmod usbkbd && echo "usbkbd" >> $MODULESFILE
     ) >/dev/null 2>&1 &
     usb_pid=$!
  fi

  read reply
  kill $usb_pid >/dev/null 2>&1
}

get_and_insmod () {
  local module
  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$modsuffix)
    file="/lib/modules/*/*/$module.o"
    echo "$msg_done"
    depmod -a
    local status
    $SIMULATE modprobe $module -C $CFGFILE
    status=$?
    rm -f $file
    ;;
  mounted)
    local status
    $SIMULATE modprobe $module -C $CFGFILE
    status=$?
    ;;
  esac

  for i in $Run_Shell; do
    local script
    local modulevarname
    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
  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
  remove_from_modules_conf $module

  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 -a "$using_mit" ] ; 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
  moved_modules_conf=""
  local moved_modutils_dir
  moved_modutils_dir=""
  local moved_modules
  moved_modules=""
  local modules_conf
  modules_conf=${CFGFILE#$Target}
  local modutils_dir
  modutils_dir=${MODUTILSDIR#$Target}
  local modules
  modules=${MODULESFILE#$Target}
  local foo
  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
    if [ `uname -m` = "s390" ]; then
      $SIMULATE cp -f /etc/chandev.conf $Target/etc/chandev.conf
    fi
    $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
  module="$1"; shift;
  local arguments
  arguments="$@"
  local done
  done=""
  local modd
  modd=""

  machine=`uname -m`
  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
          shift; shift; modd=true; done=true;
          if [ -n "$arguments" ] ; then
            echo options $module "$arguments" ;
          fi; 
	elif [ "$machine" = "s390" -a "$i" = "$MODUTILSDIR/$module.chandev" ] && echo $1 | grep -q "^[^#]"; then
          if [ -n "$arguments" ] ; then
            modd=true; done=true;
            echo "$arguments" ;
          fi; 
        else 
          echo $line;
        fi; 
        done;
        # save environment
        echo "modd=$modd; done=$done" > $TempFile5
      )   > $TempFile4
      # restore environment
      . $TempFile5
      
      if [ "$modd" ]; then
         if [ -s $TempFile4 ] ; then
            cat $TempFile4 > $i
         else
            # remove the file instead of creating empty one
            rm $i
         fi
        modd=""
      fi
    done
    if [ -z "$done" -a -n "$arguments" ]; then
      if [ "$machine" = "s390" ]; then
        build_chandev_list
        in_list "$module" "$chandev_module_list"
        if [ $? -eq 0 ]; then 
          echo "$arguments" > $MODUTILSDIR/$module.chandev
          chown 0.0 $MODUTILSDIR/$module.chandev
          chmod 644 $MODUTILSDIR/$module.chandev
        else
          echo options $module "$arguments" > $MODUTILSDIR/$module
          chown 0.0 $MODUTILSDIR/$module
          chmod 644 $MODUTILSDIR/$module
        fi
      else
        echo options $module "$arguments" > $MODUTILSDIR/$module
        chown 0.0 $MODUTILSDIR/$module
        chmod 644 $MODUTILSDIR/$module
      fi
    fi;
  fi
  
  update_modules
}

remove_from_modules_conf () {
  local module
  module="$1"

  machine=`uname -m`
  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
	  echo "# $line"
	  modd=true
	elif [ "$machine" = "s390" -a "$i" = "$MODUTILSDIR/$module.chandev" ] && echo $1 | grep -q "^[^#]"; then
	  echo "# $line"
	  modd=true
	else 
	  echo $line;
	fi; 
	done; 
      )   > $TempFile4
      if [ $modd ]; then
	cat $TempFile4 > $i
	modd=""
      fi
    done
  fi

  update_modules
}

get_modules_dirs () {
  local mdir
  mdir="$1"
  local dir

  for dir in $(cd $mdir; find -type d); do
    if [ "$dir" != "." ]; then
      echo ${dir#./}
    fi
  done
}
