#!/bin/bash
#---------------------------------------------------------------------
##
##=head1 SYNOPSIS
##
##  Sorcery is a spell management utility
##
##=head1 DESCRIPTION
##
## ...
##
##=head1 COPYRIGHT
##
## Original version Copyright 2001 by Kyle Sallee
## Additions/corrections Copyright 2002 by the Source Mage Team
##
##=head1 FUNCTIONS
##
##=over 4
##
#---------------------------------------------------------------------

help() {

  cat << EOF

Sorcery is the menu interface for changing system settings, and used
for updating the system.

Example:        sorcery
Usage:          sorcery [parameters]

Optional Parameters:

-h  |  --help  |  help	Display this help screen

-s  |  system-update	Perform a system update (updates sorcery, grimoire,
			  and spells).
			  [ scribe update, sorcery queue, cast --queue ]
-u  |  update		Update the sorcery scripts only.
-g  |  upgrade		Do not update grimoire, just any spells that need to
			  be upgraded.  [ sorcery queue, cast --queue ]

-r  |  rebuild		rebuild all spells

-q  |  queue		Compare installed grimoire to installed spells,
			  generate queue of spells needing to be updated.
       queue-security	Same as queue, but only for spells that need
			  updating due to security fixes.

review-queue		Review the install queue for each spell's history 
			  since each was last installed.

add-queue <spell|s>	Add spell(s) to install queue
remove-queue <spell|s>	Remove spell(s) from install queue

hold   <spell|s>   Sets spells' status to held.
unhold <spell|s>   Sets spells' status to installed.

exile   <spell|s>   Sets spells' status to exiled.
unexile <spell|s>   Removes spells' exiled status (to not installed at all).


default add spell_1 spell_2 on/off	If "spell_1" optionally depends
					on "spell_2" the default answer
					is on/off.

default add "" spell on/off	If anything optionally depends on "spell" the
				default answer is on/off.

default add spell "" on/off	If "spell" optionally depends on anything
				the default answer is on/off.

default add spell PROVIDER on/off	"Spell" is the provder for
					PROVIDER bydefault, in the
					case of optional_depends, if
					on/off is off, none is chosen
					by default instead.

default remove [spell|""] [spell|PROVIDER|""] Remove entry from defaults
default search [spell|""] [spell|PROVIDER|""] [on|off] Search defaults

-v  | --version		Print the sorcery version

EOF

  exit 1
#' <-- fix for syntax highlighting in nedit
}

mirror_list()  {

  sort  $MIRRORS/$1 | awk '{print "\""$NF"\""; NF-- ; print $0; }'

}


select_mirror()  {

  local MIRROR_LIST=`mirror_list  $1`

  eval $DIALOG '  --title "Select Mirror Please"  \
           --ok-label  "Select"            \
           --menu                          \
           ""                              \
           0 0 0                           \
           '$MIRROR_LIST

}


mirror_menu()  {

  local A_HELP="Select mirror for downloading APACHE sources."
  local C_HELP="Select mirror for downloading CTAN sources."
  local K_HELP="Select mirror for downloading KDE sources."
  local L_HELP="Select mirror for downloading kernel related sources."
  local N_HELP="Select mirror for downloading GNOME sources."
  local G_HELP="Select mirror for downloading GNU sources."
  local S_HELP="Select mirror for downloading Sorcery itself"
  local SF_HELP="Select mirror for downloading Sourceforge"
  local X_HELP="Select mirror for downloading XFree86 related sources."
  local HELP="Selecting a mirror site can speed your downloads."

  while


    COMMAND=`eval $DIALOG '  --title "Mirror Menu"        \
                      --ok-label      "Select"     \
                      --cancel-label  "Exit"       \
                      --item-help                  \
                      --menu        ""  0 0 0      \
                      "APACHE"      ""  "$A_HELP"  \
                      "CTAN"        ""  "$C_HELP"  \
                      "KDE"         ""  "$K_HELP"  \
                      "KERNEL"      ""  "$L_HELP"  \
                      "GNOME"       ""  "$N_HELP"  \
                      "GNU"         ""  "$G_HELP"  \
		      "SOURCEFORGE" "" "$SF_HELP"  \
		      "SORCERY"     ""  "$S_HELP"  \
                      "XFREE86"     ""  "$X_HELP"'`
  do

    case  $COMMAND in
      APACHE)       MIRROR="      APACHE_URL"  ;;
      CTAN)         MIRROR="        CTAN_URL"  ;;
      KDE)          MIRROR="         KDE_URL"  ;;
      KERNEL)       MIRROR="      KERNEL_URL"  ;;
      GNOME)        MIRROR="       GNOME_URL"  ;;
      GNU)          MIRROR="         GNU_URL"  ;;
      SORCERY)      MIRROR="     SORCERY_URL"  ;;
      SOURCEFORGE)  MIRROR=" SOURCEFORGE_URL"  ;;
      XFREE86)      MIRROR="     XFREE86_URL"  ;;
    esac

    if  MIRROR_URL=`select_mirror  $COMMAND`;  then

      if  [  "$MIRROR_URL" == "Custom"  ];  then
         MIRROR_URL=`eval $DIALOG '  --inputbox  "Please enter the URL."  0 0'`
      fi  &&

      remove_config $LOCAL_CONFIG "$MIRROR" &&
      modify_config $LOCAL_URL_CONFIG "$MIRROR" "$MIRROR_URL" &&

      eval $DIALOG  '--msgbox  "$MIRROR=$MIRROR_URL saved in $LOCAL_CONFIG" 0 0'

    fi

  done

}


show_spells()	{ (

  local  SECTION=`codex_find_section_by_name $1`
  local  SPELLS=`codex_get_spells_in_section  $SECTION`

  for  SPELL  in  $SPELLS;  do

    SPELLNAME=$( basename  $SPELL )
    if  !  spell_installed  $SPELLNAME  &&
        !  spell_held       $SPELLNAME  &&
        !  spell_exiled     $SPELLNAME
    then

      codex_set_current_spell  $SPELL
      echo  -en   '"'${SPELL:="Unknown"}'"'
      echo  -en '\t"'${VERSION:="-"}'"'
      echo  -e  '\t"'${SHORT:="Description Unavailable"}'"'

    fi

  done

) }


show_sections()  {

  LIST=`codex_get_all_section_names | sort | uniq`

  for  LINE in $LIST;  do
    echo  $LINE
    echo  "section"
  done

}


select_section() {

  eval $DIALOG  '--title "Section Selection Menu"  \
           --default-item  "$SECTION"        \
           --ok-label      "Select"          \
           --cancel-label  "Exit"            \
           --menu                            \
           ""                                \
           0 0 0                             \
           `show_sections`'

}


add_pkgs()  { (

  while

    SECTION=`select_section`

  do

    while

      SPELLS=`show_spells $SECTION`  &&
      ! [ -z "$SPELLS" ]             &&
      SPELL=`eval $DIALOG '  --title "Select spell to install please"  \
                       --item-help                               \
                       --menu                                    \
                       "$SECTION"                                \
                       0 0 0                                     \
                       '$SPELLS`

    do

      codex_set_current_spell_by_name  $SPELL
      SPELL_DESCRIPTION=`codex_get_spell_description $SPELL_DIRECTORY`

      if  eval $DIALOG  '--title      "Install $SPELL"  \
                   --yesno      "$SPELL_DESCRIPTION"    \
                   0 0'
      then

        push_install_queue  $SPELL
        eval $DIALOG  '--msgbox  "$SPELL added to the install queue."  0 0'

      else

        eval '$DIALOG  --msgbox  "$SPELL will not be installed."  0 0'

      fi
    done
  done

) }


show_file()	{

  if  [  -f  $1  ];  then

    if  [  "`file  -b  $1  |  cut  -d ' '  -f1`"  == "bzip2" ];  then
      bzcat  $1  |  $PAGER
    elif  [  "`file  -b  $1  |  cut  -d ' '  -f1`"  == "gzip" ];  then
      gzip  -cd  $1  |  $PAGER
    else
      eval $DIALOG  '--textbox  $1  0  0'
    fi

  else
    eval $DIALOG  '--msgbox  "File not found."  0  0'
    return  1
  fi

}


file_list() {

  LIST=`ls  $1`
  for  LINE  in  $LIST;  do
    echo  $LINE
    echo  `file  -b  $1/$LINE  |  cut  -d ' ' -f1`
  done

}


file_menu() {

  FILE_LIST=`file_list $1`
  echo  $1/`eval $DIALOG '  --title  "Please select a file."  \
                     --menu  "" 0 0 0                  \
                     $FILE_LIST'`

}


show_installed_spells()  {

  for  LINE  in  `sort  $SPELL_STATUS`;  do

      SPELL=`echo  "$LINE"    |  cut  -d : -f1`
     STATUS=`echo  "$LINE"    |  cut  -d : -f3`
    VERSION=`echo  "$LINE"    |  cut  -d : -f4`

    if  [  "$STATUS"  ==  "installed"  ]  ||
        [  "$STATUS"  ==  "held"       ];  then

      if  codex_set_current_spell_by_name  $SPELL;  then
        echo -en   '"'${SPELL:="Unknown"}'"'
        echo -en '\t"'${VERSION:="-"}'"'
        echo  -e '\t"'${SHORT:="Description Unavailable"}'"'
      fi

    fi
  done

}


remove_pkgs()	{

  while

    if  [  -z  "$INSTALLED_SPELLS"  ];  then
      echo  "Discovering installed spells..."
      INSTALLED_SPELLS=`show_installed_spells`
    fi

    SPELL=`eval $DIALOG '  --title "Select spell to remove please."  \
                    --item-help                               \
                    --ok-label      "Select"                  \
                    --cancel-label  "Exit"                    \
                    --menu  "" 0 0 0                          \
                    '$INSTALLED_SPELLS`

  do

    local  DESCRIPTION="Description unavailable"

    codex_set_current_spell_by_name  $SPELL
    DESCRIPTION=`codex_get_spell_description  $SPELL_DIRECTORY`

    if  $DIALOG  --title      "Remove $SPELL?"  \
                 --yesno      "$DESCRIPTION"    \
                 0 0
    then
      push_remove_queue  $SPELL                                    &&
      $DIALOG  --msgbox  "$SPELL added to the remove queue."  0 0  ||
      $DIALOG  --msgbox  "$SPELL is not really installed?"    0 0
    fi

  done

}


update_pkgs() {

  if  ps  -C  cast  >  /dev/null;  then
    echo    "Unable to update sorcery concurrently while casting."
    sleep   5
    return  1
  fi

  message  "${CHECK_COLOR}Updating ... please wait ... ${DEFAULT_COLOR}"

  local UPDATE_SCRIPT=$TMP_DIR/sorcery.update
  rm -rf $UPDATE_SCRIPT
  cat  << EOF >  $UPDATE_SCRIPT
#!/bin/bash
############################################################
# Copyright 2001 by Kyle Sallee                            #
############################################################
# This helper script $UPDATE_SCRIPT is                     #
# created and executed when sorcery updates                #
############################################################

. /etc/sorcery/config

if [[ \$1 == "autoupdate" ]]; then
    message  "${MESSAGE_COLOR}"
    message  "Interrupting while upgrading the sorcery scripts may"
    message  "cause the sorcery scripts to be lost.  If the sorcery,"
    message  "scripts are lost, Source Mage can be restored by"
    message  "running the following script:"
    message  "${FILE_COLOR}"
    message  "            bash ${RESTORE_SCRIPT}"
    message  "${MESSAGE_COLOR}"
    message  "If for some reason this does not work, see the"
    message  "Source Mage website at http://www.sourcemage.org/"
    message  "${DEFAULT_COLOR}"
    message  "${MESSAGE_COLOR}Updating grimoire...${DEFAULT_COLOR}"
    scribe update
    message  "${MESSAGE_COLOR}Ensuring sorcery-$SORCERY_BRANCH is at it's latest version...${DEFAULT_COLOR}"
    update_sorcery_scripts $SORCERY_BRANCH
fi

clean_logs
update_install_queue         # generate $INSTALL_QUEUE file
list_install_queue

message  "${MESSAGE_COLOR}Casting updated spells...${DEFAULT_COLOR}"
cast --queue

fix_installed_spells     # check integrity of installed spells

EOF

  make_restore_script

  chmod  100     $RESTORE_SCRIPT
  chmod  100     $UPDATE_SCRIPT
  exec           bash  $UPDATE_SCRIPT  $1
  # run it via bash to bypass /tmp mounted with noexec option


}

function make_restore_script() {
# note the lines:
#SORCERY_SPOOL=${SOURCE_CACHE}
#SORCERY_BRANCH=${SORCERY_BRANCH}
# actually have their values filed in at script generation time
# everything else must be back-quoted to work properly

  rm -f $RESTORE_SCRIPT
  cat  << EOF >  $RESTORE_SCRIPT
#!/bin/bash
############################################################
# This helper script /tmp/sorcery.restore can              #
# be run to restore the sorcery scripts if they            #
# are lost during a sorcery update.                        #
############################################################

echo  "Restoring the sorcery scripts, please wait ..."
SORCERY_SPOOL=${SOURCE_CACHE}
SORCERY_BRANCH=${SORCERY_BRANCH}

if [[ \$1 ]]; then
  SORCERY_BRANCH=\$1
fi

if  cd /usr/src                                             &&
    bunzip2 -c \$SORCERY_SPOOL/sorcery-\$SORCERY_BRANCH.tar.bz2 | tar xf - &&
    cd sorcery                                              &&
  ./install;                                              then
  cd ..
  rm -rf /usr/src/sorcery
  echo  "Sorcery was successfully restored."
else
  echo  "Unable to restore sorcery.  Try running this file with"
  echo  "the name of the branch you had previously installed as"
  echo  "the command-line parameter: (e.g. stable, or devel)."
  echo
  echo  "For more help, see the Source Mage website "
  echo  "(http://www.sourcemage.org/)."
fi

EOF
}


update_sorcery () {

    make_restore_script

    message  "${MESSAGE_COLOR}"
    message  "Interrupting while upgrading the sorcery scripts may"
    message  "cause the sorcery scripts to be lost.  If the sorcery,"
    message  "scripts are lost, Source Mage can be restored by"
    message  "running the following script:"
    message  "${FILE_COLOR}"
    message  "            bash ${RESTORE_SCRIPT}"
    message  "${MESSAGE_COLOR}"
    message  "If for some reason this does not work, see the"
    message  "Source Mage website at http://www.sourcemage.org/"
    message  "${DEFAULT_COLOR}"

    update_sorcery_scripts $SORCERY_BRANCH

}


update_queue () {
    update_install_queue
    list_install_queue
}

update_security_queue () {
    update_security_install_queue
    list_install_queue
}

rebuild()  {

  lock_file $INSTALL_QUEUE
  rm  -rf  $INSTALL_QUEUE
  get_all_spells_with_status installed >> $INSTALL_QUEUE
  unlock_file $INSTALL_QUEUE
  cast -c -b --queue

}


make_checklist()  {


  local  SECTION=`codex_find_section_by_name  $1`
  local   SPELLS=`codex_get_spells_in_section  $SECTION`

  for  SPELL in $SPELLS;  do

    if  codex_set_current_spell  $SPELL;  then

      STATUS="OFF"

      if    spell_installed  $SPELL  ||
            spell_held       $SPELL
      then  STATUS="on"
      else  STATUS="off"
      fi

      echo -en   '"'${SPELL:="Unknown"}'"'
      echo -en '\t"'${VERSION:="-"}'"'
      echo -en '\t"'$STATUS'"'
      echo -e  '\t"'${SHORT:="Description Unavailable"}'"'

    fi

  done

}


process_section()  {

  local    SECTION=`codex_find_section_by_name $1`
  local  KEEP_LIST=$2
  local     SPELLS=`ls  $GRIMOIRE/$SECTION`

  for  SPELL  in  $SPELLS;  do

    LINE=$( basename  $SPELL )
    if  echo  -e  "$KEEP_LIST"  |
        grep  -q  "^$LINE\$"
    then  push_install_queue  $LINE
    else  push_remove_queue   $LINE
    fi

  done

}


select_pkgs()  {

  local SELECT_TITLE="Spell Toggle Selection Menu"
  local SELECT_HELP="[X]=install  [ ]=remove"

  while  SECTION=`select_section`;  do

    CHECKLIST=`make_checklist  $SECTION`

    if  OUTLIST=`eval $DIALOG '  --title "$SELECT_TITLE"   \
                          --ok-label  "Commit"      \
                          --item-help               \
                          --separate-output         \
                          --checklist               \
                          "$SELECT_HELP  $SECTION"  \
                          0 0 0                     \
                          '$CHECKLIST`

    then  process_section  "$SECTION"  "$OUTLIST"
    fi
  done

}


make_hold_checklist()  {

  array=()

  for  LINE in `sort  $SPELL_STATUS`;  do

    explode "$LINE" ":" "array"

      SPELL="${array[0]}"
     STATUS="${array[2]}"
    VERSION="${array[3]}"

    if  [  "$STATUS"  ==  "installed"  ]   ||
        [  "$STATUS"  ==  "held"       ];  then

      [  "$STATUS"  ==  "held"  ]  &&
      HELD="on"                    ||
      HELD="off"

      if  codex_set_current_spell_by_name  $SPELL;  then

        echo  -en   "\"${SPELL:="Unknown"}\""
        echo  -en "\t\"${VERSION:="-"}\""
        echo  -en "\t\"$HELD\""
        echo  -e  "\t\"${SHORT:="Description Unavailable"}\""

      fi
    fi
  done

}


hold_pkgs()  {

  local array=()
  local tSPELL_STATUS

  local CHECKLIST=`make_hold_checklist`

  local HOLD_TITLE="Select spells to hold or unhold"
  local HOLD_HELP="[X]=held  [ ]=installed"

  if  OUTLIST=`eval $DIALOG '  --title "$HOLD_TITLE"  \
                        --item-help            \
                        --ok-label  "Commit"   \
                        --separate-output      \
                        --checklist            \
                        "$HOLD_HELP"           \
                        0 0 0                  \
                        '$CHECKLIST`
  then
        set_unheld $(get_all_spells_with_status "held")
        set_held   $OUTLIST
  fi

}


spell_menu() {

  local U_HELP="Current software hinders crackers' attempts to infiltrate your box"
  local S_HELP="Install and remove multiple spells from a section using a single selection"
  local A_HELP="Simple safe, verbose way of selecting spells for installation"
  local R_HELP="Simple safe, verbose way of selecting spells for removal"
  local B_HELP="Rebuild all installed spells"
  local H_HELP="Held spells will not be upgraded until unheld or broken"
  local E_HELP="Done managing spells"
  local TITLE="Spell Menu"
  local OK="Select"
  local CANCEL="Exit"

  while


    COMMAND=`eval $DIALOG '  --title "$TITLE"           \
                      --item-help                \
                      --ok-label      "$OK"      \
                      --cancel-label  "$CANCEL"  \
                      --menu  ""  0 0 0          \
                      "A"  "Add"      "$A_HELP"  \
                      "B"  "Rebuild"  "$B_HELP"  \
                      "H"  "Hold"     "$H_HELP"  \
                      "R"  "Remove"   "$R_HELP"  \
                      "S"  "Select"   "$S_HELP"  \
                      "U"  "Update"   "$U_HELP"'`
  do

    case  $COMMAND in
      U)  ( sorcery    system-update; ) ;;
      S)  select_pkgs  ;;
      A)  add_pkgs     ;;
      R)  remove_pkgs  ;;
      B)  rebuild      ;;
      H)  hold_pkgs    ;;
      E)  break        ;;
    esac

  done

}


grep_install_logs() {

  local WHAT
  if  WHAT=`eval $DIALOG '  --inputbox                                \
                    "Please enter full path and name of file"  \
                    0 0'`
  then
    cd  $INSTALL_LOGS
    grep  "$WHAT\$"  *  | $PAGER
  fi

}


optimize_architecture()  {
  architecture_menu  ARCHITECTURE  "Build system selection"
  if [[ $CROSS_INSTALL == on ]]; then
    architecture_menu  TARGET      "Target system selection"
  fi
  optimization_menu
  custom_optimization_menu
  . $LOCAL_CONFIG
  optimize
}

architecture_menu() {

  debug "sorcery" "architecture_menu()"
  local  SPECFILE
  local  LIST CPUNAME specname
  local specname CPUNAME
  hash_reset archspec_hash
  # this loop finds archspecs, it uses a hash table to ensure that theres
  # only one entry per archspec (there could be several archspecs with the
  # same name), it reverses the output from tac so that the first archspecs
  # found are the last added to the hash table and thus are prefered over
  # ones found later
  for  SPECFILE  in  $(find  $ARCH_SPECS  -not  -name '*~'|tac); do
    if  test -x  "$SPECFILE"   && grep  -q  "CPUNAME"  $SPECFILE; then
      specname=$(basename $SPECFILE)
      hash_put archspec_hash $specname $SPECFILE
    fi
  done
  
  # now that there archspecs have been found, build the dialog list
  for specname in $(hash_get_table_fields archspec_hash|sort); do
    CPUNAME=""
    SPECFILE=$(hash_get archspec_hash $specname) &&
    debug  "sorcery" "architecture_menu() - $specname found at $SPECFILE"
    CPUNAME=$( .  $SPECFILE  &&  echo $CPUNAME )  &&
    LIST="$LIST $specname  \"$CPUNAME\"    \"$CPUNAME\""
  done
  hash_reset archspec_hash
  debug  "sorcery" "architecture_menu() - Dialog options are $LIST"

  local ARCH_TITLE="$2"
  local ARCH_HELP="Please select a microprocessor category"

# CURRENT_ARCH is the currently selected architecture

# NEW_ARCH is the new architecture selected (can be an empty string if
# the user press cancel).

# do not use ARCHITECTURE or TARGET variable since they are already
# used by sorcery configuration

  local CURRENT_ARCH="${!1}"
  local NEW_ARCH

  if NEW_ARCH=`eval $DIALOG '  --title  "$ARCH_TITLE"     \
                              --item-help                \
                              --default-item "${CURRENT_ARCH}"   \
                              --menu                     \
                              "$ARCH_HELP"               \
                               0 0 0                     \
			       '$LIST              `; then

    # remove spurious ""
    NEW_ARCH=`echo "${NEW_ARCH}" | sed -e 's/^"//' -e 's/"$//'`

    debug "sorcery" "architecture_menu() - NEW_ARCH='$NEW_ARCH'"

    modify_local_config "$1" "${NEW_ARCH}"
  fi


}

optimization_menu(){

  local OPTIMIZATIONS=${OPTIMIZATIONS}
  # this is here so COMBRELOC, PRELINK, RISKY, etc. are set
  # and appear in the menu
  optimize
  local      OPT_TITLE="Optimization Menu"
  local       OPT_HELP="Please select optimizations"

  local COMBRELOC_HELP="Speed up loading libs, also needed for prelink (LDFLAGS=-z combreloc)"
  local   PRELINK_HELP="Speed up loading applications by pre-linking libraries (CFLAGS=-DPIC -fPIC)"
  local     RISKY_HELP="Optimize by violating ANSI/IEEE (unsafe) (CFLAGS=-ffast-math -funroll-loops)"
  local    SPEEDY_HELP="Optimize generated code, conflicts with 'tiny' (CFLAGS=$FAST)"
  local     STRIP_HELP="Remove all symbol table and relocation (debugging) information (LDFLAGS=-s)"
  local      TINY_HELP="Optimize to smaller generated code, conflicts with 'speedy' (CFLAGS=$SMALL)"

  if  OPTIMIZATIONS=`eval $DIALOG '  --title  "$OPT_TITLE"     \
                              --no-cancel               \
                              --item-help               \
                              --separate-output         \
                              --checklist               \
                              "$OPT_HELP"               \
                               0 0 0                    \
        "combreloc" "         ++speed"  "$COMBRELOC" "$COMBRELOC_HELP" \
        "prelink"   "          +speed"  "$PRELINK"   "$PRELINK_HELP"   \
        "risky"     "          +speed"  "$RISKY"     "$RISKY_HELP"     \
        "speedy"    "  +size  ++speed"  "$SPEEDY"    "$SPEEDY_HELP"    \
        "strip"     " --size"           "$STRIP"     "$STRIP_HELP"     \
        "tiny"      "  -size   +speed"  "$TINY"      "$TINY_HELP"'`
  then

    OPTIMIZATIONS=`echo  ${OPTIMIZATIONS}  |  tr  '\n'  ' '`
    debug "sorcery" "optimization_menu() - OPTIMIZATIONS='${OPTIMIZATIONS}'"

    modify_local_config "OPTIMIZATIONS" "$OPTIMIZATIONS"

  fi
}

custom_optimization_menu() {
  local RESULTS KEY rc

  while true ; do
    # input box returns things of the form "RENAMED CFLAGS -O3 -march=foo ..."
    # the ( ) interprits as an array, then using the magic power of set we
    # get to use shift and $@ to get things done
    RESULTS=(`eval $DIALOG ' --extra-label Adjust --inputmenu \
                            "Custom Optimizations Menu" \
                             17 50 9 \
                             CFLAGS "$CUSTOM_CFLAGS" \
                             CXXFLAGS "$CUSTOM_CXXFLAGS" \
                             LDFLAGS "$CUSTOM_LDFLAGS"'`)
    rc=$?
    [[ $rc == 0 ]] || [[ $rc == 1 ]] && break
    set ${RESULTS[*]}
    KEY=$2
    shift 2
    case "$KEY" in
      CFLAGS) CUSTOM_CFLAGS="$@"  ;;
      CXXFLAGS) CUSTOM_CXXFLAGS="$@" ;;
      LDFLAGS) CUSTOM_LDFLAGS="$@" ;;
    esac
  done
  
  # only commit values if user selected "OK"
  if [ $rc == 0 ] ; then
    modify_local_config CUSTOM_CFLAGS "$CUSTOM_CFLAGS"
    modify_local_config CUSTOM_CXXFLAGS "$CUSTOM_CXXFLAGS"
    modify_local_config CUSTOM_LDFLAGS "$CUSTOM_LDFLAGS"
  fi
}

integrity_fix_menu()  {

  local INT_TITLE="Integrity Checking Selection Menu"
  local INT_HELP="Please select the tests which cleanse --fix should execute."
  local FIND_HELP="Discover missing  binary executables, libraries, and header files"
  local LDD_HELP="Discover broken   binary executables, and libraries"
  local SYM_HELP="Discover misowned symbolic links to files"
  local MD5SUM_HELP="Discover modified binary executables, and libraries"

  if  INT_FIX_CHECKS=`eval $DIALOG '  --title  "$INT_TITLE"  \
                           --no-cancel            \
                           --item-help            \
                           --separate-output      \
                           --checklist            \
                           "$INT_HELP"            \
                           0 0 0                  \
        "FIND_CHECK"    ""  "$FIND_CHECK"    "$FIND_HELP"    \
        "MD5SUM_CHECK"  ""  "$MD5SUM_CHECK"  "$MD5SUM_HELP"  \
        "LDD_CHECK"     ""  "$LDD_CHECK"     "$LDD_HELP"     \
        "SYM_CHECK"     ""  "$SYM_CHECK"     "$SYM_HELP"'`
  then

        FIND_CHECK=off
      MD5SUM_CHECK=off
         LDD_CHECK=off
         SYM_CHECK=off

    for  CHECK  in  $INT_FIX_CHECKS;  do
      case  $CHECK  in
          FIND_CHECK)    FIND_CHECK=on  ;;
        MD5SUM_CHECK)  MD5SUM_CHECK=on  ;;
           LDD_CHECK)     LDD_CHECK=on  ;;
           SYM_CHECK)     SYM_CHECK=on  ;;
      esac
    done

    modify_local_config "FIND_CHECK" "$FIND_CHECK"
    modify_local_config "MD5SUM_CHECK" "$MD5SUM_CHECK"
    modify_local_config "LDD_CHECK" "$LDD_CHECK"
    modify_local_config "SYM_CHECK" "$SYM_CHECK"

  fi

}


integrity_download_menu()  {

  local INT_DL_TITLE="Archive Integrity Checking Level Menu"
  local INT_DL_HELP="On bad archive integrity checks:
c = continue, a = abort, n = ask default abort no,
y = ask default abort yes, - = doesn't get checked, continues.
K MD5SUM_DL . good bad IGNORE missing
- ----------- ---- --- ------ -------
P all_abort . . c . a . . a . . . a .
A on|*. . . . . c . a . . y . . . a .
B ask_abort . . c . y . . y . . . y .
U ask_risky . . c . y . . n . . . y .
G ask_ignore. . c . n . . n . . . n .
I off . . . . . - . - . . - . . . - .
"
  local ABORT_ALL_HELP="Abort use of the file. Do not prompt. Period. PARANOID"
  local ABORT_HELP="Abort use of the file. Do not prompt unless the MD5 is set to IGNORE. SAFER"
  local ABORT_ASK_HELP="Ask, but default to abort. SAFE"
  local ABORT_IGN_HELP="Ask, but default to abort unless the MD5 is set to IGNORE. RISKY"
  local IGNORE_ASK_HELP="Ask, but default to ignore. UNSAFE"
  local IGNORE_HELP="Ignore (do not check) integrity of downloads. DANGEROUS!"

  if  INT_DL_CHECK=`eval $DIALOG '  --title  "$INT_DL_TITLE"        \
   			     --no-cancel                            \
			     --ok-label    "Commit"                 \
			     --item-help                            \
			     --menu                                 \
			     "$INT_DL_HELP"                         \
			     0 0 0                                  \
	"P"  "Abort unpack paranoid"             "$ABORT_ALL_HELP"  \
	"A"  "Abort unpack but ask on ignore"    "$ABORT_HELP"      \
	"B"  "Ask (default abort)"               "$ABORT_ASK_HELP"  \
	"U"  "Ask (default abort save ignore)"   "$ABORT_IGN_HELP"  \
	"G"  "Ask (default ignore)"              "$IGNORE_ASK_HELP" \
	"I"  "Ignore (do not check)"             "$IGNORE_HELP"'`
  then
    case $INT_DL_CHECK in
      P) modify_local_config "MD5SUM_DL" "abort_all" ;;
      A) modify_local_config "MD5SUM_DL" "on" ;;
      B) modify_local_config "MD5SUM_DL" "ask_abort" ;;
      U) modify_local_config "MD5SUM_DL" "ask_risky" ;;
      G) modify_local_config "MD5SUM_DL" "ask_ignore" ;;
      I) modify_local_config "MD5SUM_DL" "off" ;;
    esac
  fi

}

function gpg_download_menu() {
  local CHECK CHECKS
  local INT_TITLE="GnuPG Signature Checking Selection Menu"
  local INT_HELP="Enable/Disable GnuPG signature checking here"
  local SRY_HELP="Toggle sorcery gpg signature checking on sorcery update"
  local GRM_HELP="Toggle grimoire gpg signature checking on scribe update"

  if  CHECKS=`eval $DIALOG '  --title  "$INT_TITLE"  \
                           --no-cancel            \
                           --item-help            \
                           --separate-output      \
                           --checklist            \
                           "$INT_HELP"            \
                           0 0 0                  \
        "GPG_VERIFY_SORCERY"    ""  "$GPG_VERIFY_SORCERY"    "$SRY_HELP"    \
        "GPG_VERIFY_GRIMOIRE"   ""  "$GPG_VERIFY_GRIMOIRE"   "$GRM_HELP"'`
  then
    GPG_VERIFY_SORCERY=off
    GPG_VERIFY_GRIMOIRE=off

    for  CHECK  in  $CHECKS;  do
      case  $CHECK  in
         GPG_VERIFY_SORCERY)  GPG_VERIFY_SORCERY=on ;;
        GPG_VERIFY_GRIMOIRE) GPG_VERIFY_GRIMOIRE=on ;;
      esac
    done

    modify_local_config "GPG_VERIFY_SORCERY" "$GPG_VERIFY_SORCERY"
    modify_local_config "GPG_VERIFY_GRIMOIRE" "$GPG_VERIFY_GRIMOIRE"
  fi
}

function vrf_select_hashes() {
  local DIALOG_TITLE="Select the source hashes you would like to use"
  local DIALOG_HELP="Select the source hashes you would like to consider valid hashes"
  local DEFAULT_LIST=$(gpg_get_hashes)
  local rc=0
  local CHECKS=""
  local check=""
  local hash=""
  local DIALOG_LIST=""
  if [ -z "$DEFAULT_LIST" ] ; then
    eval $DIALOG '--title "ERROR" \
                  --msgbox        \
                  "ERROR: gpg isn't installed or isn't in your PATH. Please cast gnupg." 20 20' &&
    return 1
  else
    # move old values (named with GPG) to new ones
    # this can be removed after 11/26/05 (afk -- 10/26/05)
    if [[ -n "$GPG_ALLOWED_HASHES" ]] ; then
      VRF_ALLOWED_HASHES=$GPG_ALLOWED_HASHES
      modify_config $LOCAL_CONFIG "VRF_ALLOWED_HASHES" "$VRF_ALLOWED_HASHES"
    fi
    if [[ -n "$GPG_ALLOW_NEW_HASHES" ]] ; then
      VRF_ALLOW_NEW_HASHES=$GPG_ALLOW_NEW_HASHES
      modify_config $LOCAL_CONFIG "VRF_ALLOW_NEW_HASHES" "$VRF_ALLOW_NEW_HASHES"
    fi
    remove_config $LOCAL_CONFIG "GPG_ALLOWED_HASHES"
    remove_config $LOCAL_CONFIG "GPG_ALLOW_NEW_HASHES"

    DIALOG_LIST=""
    if [[ -z "$VRF_ALLOWED_HASHES" ]]
    then
      for hash in $DEFAULT_LIST
      do
        DIALOG_LIST="${DIALOG_LIST}${hash} '${hash} was selected' on "
      done
    else
      for hash in $DEFAULT_LIST
      do
        if list_find "$VRF_ALLOWED_HASHES" "${hash}:on"
        then
          DIALOG_LIST="${DIALOG_LIST}${hash} '${hash} was selected' on "
        else
          DIALOG_LIST="${DIALOG_LIST}${hash} '${hash} was not selected' off "
        fi
      done
    fi
    if [[ "$VRF_ALLOW_NEW_HASHES" == "on" ]]
    then
      DIALOG_LIST="new 'Allow new hashes was selected' on ${DIALOG_LIST}"
    else
      DIALOG_LIST="new 'Allow new hashes was not selected' off ${DIALOG_LIST}"
    fi
    CHECKS=$(eval $DIALOG ' --title "$DIALOG_TITLE"          \
                            --checklist "$DIALOG_HELP"       \
                            0 0 0 ' \
                            ${DIALOG_LIST})
    rc="$?"
    if [[ "$rc" == "0" ]]
    then
      VRF_ALLOWED_HASHES=""
      CHECKS=${CHECKS//\"/}
      if list_find "${CHECKS}" new
      then
        VRF_ALLOW_NEW_HASHES=on
      else
        VRF_ALLOW_NEW_HASHES=off
      fi
      for hash in ${DEFAULT_LIST}
      do
        if list_find "${CHECKS}" $hash
        then
          VRF_ALLOWED_HASHES="${VRF_ALLOWED_HASHES}${hash}:on "
        else
          VRF_ALLOWED_HASHES="${VRF_ALLOWED_HASHES}${hash}:off "
        fi
      done
      modify_local_config VRF_ALLOWED_HASHES "${VRF_ALLOWED_HASHES}"
      modify_local_config VRF_ALLOW_NEW_HASHES "${VRF_ALLOW_NEW_HASHES}"
    fi
  fi
  return 0
}

function vrf_select_level()  {
  local DIALOG_TITLE="Source Verification Level Checking"
  local DIALOG_HELP="Select the minimum level for source verification"
  local DIALOG_LIST=""
  local CHECKS level
  local rc=0

  # move old values (named with GPG) to new ones
  # this can be removed after 11/26/05 (afk -- 10/26/05)
  if [[ -n "$GPG_ALLOWED_LEVELS" ]] ; then
    VRF_ALLOWED_LEVELS=$GPG_ALLOWED_LEVELS
    modify_config $LOCAL_CONFIG "VRF_ALLOWED_LEVELS" "$VRF_ALLOWED_LEVELS"
  fi
  if [[ -n "$GPG_ALLOW_NEW_LEVELS" ]] ; then
    VRF_ALLOW_NEW_LEVELS=$GPG_ALLOW_NEW_LEVELS
    modify_config $LOCAL_CONFIG "VRF_ALLOW_NEW_LEVELS" "$VRF_ALLOW_NEW_LEVELS"
  fi
  remove_config $LOCAL_CONFIG "GPG_ALLOWED_LEVELS"
  remove_config $LOCAL_CONFIG "GPG_ALLOW_NEW_LEVELS"

  DIALOG_LIST=""
  if [[ -z "$VRF_ALLOWED_LEVELS" ]]
  then
    for level in $VERIFY_SPELL_LEVELS
    do
      DIALOG_LIST="${DIALOG_LIST}${level} '${level} was selected' on "
    done
  else
    for level in $VERIFY_SPELL_LEVELS
    do
      if list_find "$VRF_ALLOWED_LEVELS" "${level}:on"
      then
          DIALOG_LIST="${DIALOG_LIST}${level} '${level} was selected' on "
        else
          DIALOG_LIST="${DIALOG_LIST}${level} '${level} was not selected' off "
        fi
      done
  fi
  if [[ "$VRF_ALLOW_NEW_LEVELS" == "on" ]]
  then
    DIALOG_LIST="new 'Allow new levels was selected' on ${DIALOG_LIST}"
  else
    DIALOG_LIST="new 'Allow new levels was not selected' off ${DIALOG_LIST}"
  fi
  CHECKS=$(eval $DIALOG ' --title "$DIALOG_TITLE"     \
                                          --checklist "$DIALOG_HELP"  \
                                          0 0 0                       \
                                          '${DIALOG_LIST})
  rc="$?"
  if [[ "$rc" == "0" ]]
  then
    VRF_ALLOWED_LEVELS=""
    CHECKS=${CHECKS//\"/}
    if list_find "${CHECKS}" new
    then
      VRF_ALLOW_NEW_LEVELS=on
    else
      VRF_ALLOW_NEW_LEVELS=off
    fi
    for level in ${VERIFY_SPELL_LEVELS}
    do
      if list_find "${CHECKS}" $level
      then
        VRF_ALLOWED_LEVELS="${VRF_ALLOWED_LEVELS}${level}:on "
      else
        VRF_ALLOWED_LEVELS="${VRF_ALLOWED_LEVELS}${level}:off "
      fi
    done
    modify_local_config VRF_ALLOWED_LEVELS "${VRF_ALLOWED_LEVELS}"
    modify_local_config VRF_ALLOW_NEW_LEVELS "${VRF_ALLOW_NEW_LEVELS}"
  fi
  return 0
}

integrity_menu()  {

  local INT_TITLE="Integrity Checking Selection Menu"
  local INT_HELP="Options involving integrity checking, including --fix and download options."
  local FIX_HELP="Set cleanse --fix checks"
  local DL_HELP="Discover corrupted or modified archives during cast"
  local GPG_HELP="Verify GnuPG signatures on sorcery/grimoire tarballs"
  local SGPG_HELP="Verify GnuPG signatures on spell source tarballs"
  local HGPG_HELP="Verify GnuPG signatures with selected hashs"

  while  INT_CHECKS=`eval $DIALOG '  --title  "$INT_TITLE"     \
                           --cancel-label  "Exit"              \
			   --ok-label      "Select"            \
                           --item-help                         \
                           --menu                              \
                           "$INT_HELP"                         \
                           0 0 0                               \
        "F"  "System integrity"               "$FIX_HELP"      \
        "D"  "Download integrity"             "$DL_HELP"       \
        "G"  "Sorcery GPG Signature Checking" "$GPG_HELP"      \
        "S"  "Spell Source Verification Level Checking"   "$SGPG_HELP"     \
        "M"  "Spell Source Hash List"            "$HGPG_HELP"'`
  do
    case $INT_CHECKS in
      F)  integrity_fix_menu       ;;
      D)  integrity_download_menu  ;;
      G)  gpg_download_menu  ;;
      S)  vrf_select_level ;;
      M)  vrf_select_hashes ;;
    esac
  done

}

set_email()  {

  if  SORCERER=`eval $DIALOG '  --ok-label  "Commit"         \
                         --inputbox                   \
                "Please enter the email address of the person or role account
that should receive reports from this box."  \
                0 0  "$SORCERER"'`
  then

    modify_local_config "SORCERER" "$SORCERER"

  fi

}

function service_defaults() {
  local INSTALL_INIT_HELP="Install init.d scripts by default?"
  local ENABLE_INIT_HELP="If an init.d script is being installed, also enable it by default?"
  local INSTALL_XINETD_HELP="Install xinetd scripts by default?"
  local ENABLE_XINETD_HELP="If an xinetd script is being installed, also enable it by default?"
  local INIT_VS_XINETD="If both xinetd or init.d scripts exist, prefer xinetd over init.d?"
  
  local MENU_TITLE="Init.d/Xinetd Default Answer Selection Menu"
  local MENU_INFO="Choose your defaults\nPer spell answers are remembered on recasts"
  local RESULT RESULTS TMP i
  if RESULTS=`eval $DIALOG '--item-help \
                               --backtitle backtitle \
                               --separate-output       \
                               --title "$MENU_TITLE" \
                               --checklist "$MENU_INFO" \
                               0 0 0 \
       "INSTALL_INIT"        "Install init.d scripts by default" \
       "$DEF_INSTALL_INIT"   "$INSTALL_INIT_HELP" \
       "ENABLE_INIT"         "Enable init.d scripts by default" \
       "$DEF_ENABLE_INIT"    "$ENABLE_INIT_HELP" \
       "INSTALL_XINETD"      "Install xinetd scripts by default" \
       "$DEF_INSTALL_XINETD" "$INSTALL_XINETD_HELP" \
       "ENABLE_XINETD"       "Enable xinetd scripts by default" \
       "$DEF_ENABLE_XINETD"  "$INSTALL_XINETD_HELP" \
       "INIT_VS_XINETD"      "Prefer xinetd over init.d" \
       "$DEF_INIT_VS_XINETD" "$INIT_VS_XINETD"'`
  then

    TEMP=(DEF_INSTALL_INIT DEF_ENABLE_INIT DEF_INSTALL_XINETD DEF_ENABLE_XINETD DEF_INIT_VS_XINETD)
    for i in ${TEMP[*]} ; do
      eval $i=off
    done

    for RESULT in  $RESULTS;  do

      case  $RESULT in
          INSTALL_INIT) DEF_INSTALL_INIT=on   ;;
           ENABLE_INIT) DEF_ENABLE_INIT=on    ;;
        INSTALL_XINETD) DEF_INSTALL_XINETD=on ;;
         ENABLE_XINETD) DEF_ENABLE_XINETD=on  ;;
        INIT_VS_XINETD) DEF_INIT_VS_XINETD=on ;;
      esac

    done
    for i in ${TEMP[*]} ; do
      modify_local_config "$i" "${!i}"
    done
  fi
}

function parallel_compilation_menu() {
  local RESULTS KEY rc
  local TITLE="Parallel/Distributed Compilation Options Menu"
  local HELP="Number of make jobs is\n((length of DISTCC_HOSTS)*JOBS_PER_HOST+EXTRA_JOBS)\nIf distcc is disabled by a spell, then the number of make jobs is EXTRA_JOBS, it is recommended that you dont set it to zero. If the number of jobs totals to zero make will run an unlimited number of jobs."

  while true ; do
    # input box returns things of the form "RENAMED CFLAGS -O3 -march=foo ..."
    # the ( ) interprits as an array, then using the magic power of set we
    # get to use shift and $@ to get things done
    RESULTS=(`eval $DIALOG ' --extra-label Adjust --inputmenu \
                          "$TITLE\n$HELP" \
                          23 70 9 \
                          DISTCC_HOSTS "$DISTCC_HOSTS" \
                          JOBS_PER_HOST "$JOBS_PER_HOST" \
                          EXTRA_JOBS "$MAKE_NJOBS" \
                          CCACHE_DIR "$CCACHE_DIR"'`)
    rc=$?

    [[ $rc == 0 ]] || [[ $rc == 1 ]] && break
    set ${RESULTS[*]}
    KEY=$2
    shift 2
    case "$KEY" in
      DISTCC_HOSTS) DISTCC_HOSTS="$@"  ;;
      JOBS_PER_HOST) JOBS_PER_HOST="$@" ;;
      EXTRA_JOBS) MAKE_NJOBS="$@" ;;
      CCACHE_DIR) CCACHE_DIR="$@" ;;
    esac
  done

  # only commit values if user selected "OK"
  if [ $rc == 0 ] ; then
    modify_config $LOCAL_COMPILE_CONFIG DISTCC_HOSTS "$DISTCC_HOSTS"
    modify_config $LOCAL_COMPILE_CONFIG JOBS_PER_HOST "$JOBS_PER_HOST"
    modify_config $LOCAL_COMPILE_CONFIG MAKE_NJOBS "$MAKE_NJOBS"
    modify_config $LOCAL_COMPILE_CONFIG CCACHE_DIR "$CCACHE_DIR"
  fi
}

set_branch() {

  local D_HELP="Nightly devel snapshots"
  local T_HELP="Current release candidate or stable release"
  local S_HELP="Current stable version"
  local C_HELP="Choose a custom version"

  while


    COMMAND=`eval $DIALOG '  --title "Currently tracking : $SORCERY_BRANCH "  \
                      --item-help                               \
                      --ok-label      "Select"                  \
                      --cancel-label  "Exit"                    \
                      --menu                                    \
                      ""                                        \
                      0 0 0                                     \
                      "S"  "Stable Branch"            "$S_HELP" \
                      "T"  "Test Branch"              "$T_HELP" \
                      "D"  "Devel Branch"             "$D_HELP" \
                      "C"  "Custom Branch"             "$C_HELP"'`

  do

    case  $COMMAND in

      S)  modify_local_config "SORCERY_BRANCH" "stable"  &&
          SORCERY_BRANCH="stable"                        ;;
      T)  modify_local_config "SORCERY_BRANCH" "test"    &&
          SORCERY_BRANCH="test"                          ;;
      D)  modify_local_config "SORCERY_BRANCH" "devel"   &&
          SORCERY_BRANCH="devel"                         ;;
      C)  set_custom_branch                              ;;

    esac

  done

}

set_custom_branch() {

  local C_HELP="Please choose the sorcery release/version you want to use, this can be anything you want from download.sourcemage.org/sorcery/sorcery-<version>.tar.bz2"
  while

    COMMAND=`eval $DIALOG '  --title "Currently tracking : $SORCERY_BRANCH "  \
                      --item-help                               \
                      --ok-label      "Select"                  \
                      --cancel-label  "Exit"                    \
                      --inputbox                                \
                      "$C_HELP"                                 \
                      0 0                                       \
                      "$SORCERY_BRANCH"'`

   do

     modify_local_config "SORCERY_BRANCH" "$COMMAND"   &&
     SORCERY_BRANCH="$COMMAND"

  done


}



set_delay()  {

  if  PROMPT_DELAY=`eval $DIALOG '  --ok-label  "Commit"  \
                             --inputbox            \
                             "Please enter the time in seconds to wait for a response when prompted with a question."  \
                              0 0  "$PROMPT_DELAY"'`
  then

    modify_local_config "PROMPT_DELAY" "$PROMPT_DELAY"

  fi

}


set_download_rate()  {

  local PROMPT="Please enter the maximum bytes per second for summoning"

  if  DOWNLOAD_RATE=`eval $DIALOG '  --ok-label  "Commit"  \
                              --inputbox            \
                              "$PROMPT"             \
                               0 0  "$DOWNLOAD_RATE"'`
  then

    modify_local_config "DOWNLOAD_RATE" "$DOWNLOAD_RATE"

  fi

}

set_http_ftp_timeout()  {

  local PROMPT="Please enter maximum time (seconds) summon is to wait for each download server"

  if  URL_HTTP_FTP_TIMEOUT=`eval $DIALOG '  --ok-label  "Commit"  \
                                            --inputbox            \
                                            "$PROMPT"             \
                                            0 0  "$URL_HTTP_FTP_TIMEOUT"'`
  then

    modify_local_config "URL_HTTP_FTP_TIMEOUT" "$URL_HTTP_FTP_TIMEOUT"

  fi

}

queue_menu()  {

  local I_HELP="View the list of spells selected for installation"
  local i_HELP="Edit the list of spells selected for installation"
  local R_HELP="View the list of spells selected for removal"
  local r_HELP="Edit the list of spells selected for removal"
  local S_HELP="View the datafile of installed spells"
  local s_HELP="Edit the datafile of installed spell"

  while

    COMMAND=`eval $DIALOG '  --title "Queue Menu"                           \
                      --ok-label      "Select"                       \
                      --cancel-label  "Exit"                         \
                      --default-item  $COMMAND                       \
                      --item-help                                    \
                      --menu                                         \
                      ""                                             \
                      0 0 0                                          \
                      "I"     "View     install  queue"   "$I_HELP"  \
                      "i"     "Edit     install  queue"   "$i_HELP"  \
                      "R"     "View     removal  queue"   "$R_HELP"  \
                      "r"     "Edit     removal  queue"   "$r_HELP"  \
                      "S"     "View     spell    status"  "$S_HELP"  \
                      "s"     "Edit     spell    status"  "$s_HELP"'`

  do

    case  $COMMAND in

      S)  show_file  $SPELL_STATUS         ;;
      s)  edit_file  $SPELL_STATUS         ;;
      I)  show_file  $INSTALL_QUEUE        ;;
      i)  edit_file  $INSTALL_QUEUE        ;;
      R)  show_file  $REMOVE_QUEUE         ;;
      r)  edit_file  $REMOVE_QUEUE         ;;

    esac

  done

}


log_menu()  {

  local C_HELP="View compile logs of previously installed software"
  local G_HELP="Discover a file's origin"
  local I_HELP="View logs of files previously installed"
  local c_HELP="Remove a compile log"
  local i_HELP="Edit a log of files previously installed"

  while

    COMMAND=`eval $DIALOG '  --title "Log Menu"                          \
                      --ok-label      "Select"                    \
                      --cancel-label  "Exit"                      \
                      --default-item  $COMMAND                    \
                      --item-help                                 \
                      --menu                                      \
                      ""                                          \
                      0 0 0                                       \
                      "G"     "Grep    install logs"  "$G_HELP"   \
                      "I"     "View    install log"   "$I_HELP"   \
                      "i"     "Edit    install log"   "$i_HELP"   \
                      "C"     "View    compile log"   "$C_HELP"   \
                      "c"     "Remove  compile log"   "$c_HELP"'`

  do

    case  $COMMAND in

      G)  grep_install_logs                      ;;
      I)  show_file  `file_menu  $INSTALL_LOGS`  ;;
      i)  edit_file  `file_menu  $INSTALL_LOGS`  ;;
      C)  show_file  `file_menu  $COMPILE_LOGS`  ;;
      c)  rm         `file_menu  $COMPILE_LOGS`  ;;

    esac

  done

}

sorcery_devel_settings()   {

  local D_HELP="Set the debugging file for normal debugging."
  local S_HELP="Turn on Super Debug. You probably don't want to do this."

  while

  COMMAND=`eval $DIALOG '--title      "Sorcery Development"    \
            --ok-label      "Select"          \
            --cancel-label  "Exit"            \
            --default-item  $COMMAND          \
            --item-help                  \
            --menu                    \
            ""                      \
            0 0 0                    \
            "D"  "Debug file"        "$D_HELP"  \
            "S"  "Super debugging toggle"  "$S_HELP"'`
  do

    case $COMMAND in

    D) TEXT="Note: if you turn this on, don't forget to empty the log file occasionaly.\nWhat file do you want the debugging logged to?"
        FILE=`eval $DIALOG --ok-label "Commit" --inputbox \"$TEXT\" 0 0 \"$DEBUG\"` &&
        modify_local_config "DEBUG" "$FILE" ;;
    S) TEXT="Note: You don't want to do this probably. Don't forget to 2>/root/debug.out.\nDo you want super debugging on?"
        TOGGLE=`eval $DIALOG --yesno \"$TEXT\" 0 0` &&
        ( modify_local_config "SUPER_DEBUG" "on" ; modify_local_config "set" "-x" "command" ) ||
      ( modify_local_config "SUPER_DEBUG" ""   ; modify_local_config "set" "+x" "command" ) ;;

  esac

  done

}


feature_menu()  {

  local B_HELP="Administrate groups of Unix/Linux boxes?"
  local C_HELP="Colorized messages on cast and dispel?"
  local D_HELP="Automatically gather miscellaneous documentation from spells"
  local E_HELP="Remove files when dispelling?"
  local F_HELP="Check for and repair broken programs after updating sorcery?"
  local G_HELP="Slower initial compilation, accelerated upgrade compilation?"
  local I_HELP="Create archives of installed software?"
  local L_HELP="Locally customize SPELL configuration?"
  local M_HELP="Email reports?"
  local P_HELP="Preserve modified files or backup them up and overwrite with defaults?"
  local R_HELP="Prompt to view reports?"
  local SCL_HELP="Store config.log in compile log?"
  local TMP_HELP="Attempt to compile entirely in RAM?"
  local T_HELP="Disallow dispelling of spells that would cause terrible malfunctions?"
  local U_HELP="Automatically remove old sources and install caches upon sorcery update?"
  local V_HELP="View compilation as it happens?"
  local NS_HELP="Use netselect to try fastest mirrors first if netselect is available?"
  local CS_HELP="Clean up source directories after failures?"
  local CI_HELP="Non-native installation / cross compilation"
  local ST_HELP="Set xterm title/screen window title on cast?"
  local UF_HELP="Ensure a sane environment before sorcery update"
  local SCR_HELP="Toggle usage of screen in cast"

       ARCHIVE=${ARCHIVE:=on}
       AUTOFIX=${AUTOFIX:=on}
     UPDATEFIX=${UPDATEFIX:=off}
     AUTOPRUNE=${AUTOPRUNE:=off}
        CCACHE=${CCACHE:=off}
         COLOR=${COLOR:=on}
    CONFIG_LOC=${CONFIG_LOC:=on}
   GATHER_DOCS=${GATHER_DOCS:=on}
  MAIL_REPORTS=${MAIL_REPORTS:=off}
         TMPFS=${TMPFS:=on}
  VIEW_REPORTS=${VIEW_REPORTS:=off}
      PRESERVE=${PRESERVE:=on}
       SUSTAIN=${SUSTAIN:on}
        VOYEUR=${VOYEUR:=on}
          REAP=${REAP:=on}
STORE_CONF_LOG=${STORE_CONF_LOG:-off}
    NET_SELECT=${NET_SELECT:=off}
  CLEAN_SOURCE=${CLEAN_SOURCE:=off}
 CROSS_INSTALL=${CROSS_INSTALL:=off}
SET_TERM_TITLE=${SET_TERM_TITLE:=off}
        SCREEN=${SCREEN:-off}

  if  TOGGLES=`eval $DIALOG '  --title "Feature Menu"  \
                        --no-cancel             \
                        --item-help             \
                        --separate-output       \
                        --checklist             \
                        ""                      \
                        0 0 0                   \
      "ARCHIVE"        "Toggle"  "$ARCHIVE"        "$I_HELP"   \
      "AUTOFIX"        "Toggle"  "$AUTOFIX"        "$F_HELP"   \
      "UPDATEFIX"      "Toggle"  "$UPDATEFIX"      "$UF_HELP"  \
      "AUTOPRUNE"      "Toggle"  "$AUTOPRUNE"      "$U_HELP"   \
      "CCACHE"         "Toggle"  "$CCACHE"         "$G_HELP"   \
      "COLOR"          "Toggle"  "$COLOR"          "$C_HELP"   \
      "CONFIG_LOC"     "Toggle"  "$CONFIG_LOC"     "$L_HELP"   \
      "GATHER_DOCS"    "Toggle"  "$GATHER_DOCS"    "$D_HELP"   \
      "MAIL_REPORTS"   "Toggle"  "$MAIL_REPORTS"   "$M_HELP"   \
      "PRESERVE"       "Toggle"  "$PRESERVE"       "$P_HELP"   \
      "SUSTAIN"        "Toggle"  "$SUSTAIN"        "$T_HELP"   \
      "TMPFS"          "Toggle"  "$TMPFS"          "$TMP_HELP" \
      "VIEW_REPORTS"   "Toggle"  "$VIEW_REPORTS"   "$R_HELP"   \
      "VOYEUR"         "Toggle"  "$VOYEUR"         "$V_HELP"   \
      "REAP"           "Toggle"  "$REAP"           "$E_HELP"   \
      "STORE_CONF_LOG" "Toggle"  "$STORE_CONF_LOG" "$SCL_HELP" \
      "NET_SELECT"     "Toggle"  "$NET_SELECT"     "$NS_HELP"  \
      "CLEAN_SOURCE"   "Toggle"  "$CLEAN_SOURCE"   "$CS_HELP"  \
      "CROSS_INSTALL"  "Toggle"  "$CROSS_INSTALL"  "$CI_HELP"  \
      "SET_TERM_TITLE" "Toggle"  "$SET_TERM_TITLE" "$ST_HELP"  \
      "SCREEN"         "Toggle"  "$SCREEN"         "$SCR_HELP"'`
  then
    TEMP=(ARCHIVE AUTOFIX UPDATEFIX AUTOPRUNE COLOR GATHER_DOCS MAIL_REPORTS VIEW_REPORTS PRESERVE SUSTAIN TMPFS VOYEUR REAP NET_SELECT CONFIG_LOC CLEAN_SOURCE CROSS_INSTALL SET_TERM_TITLE SCREEN)
    for i in ${TEMP[*]} ; do
      eval $i=off
    done

    for  TOGGLE  in  $TOGGLES;  do

      case  $TOGGLE  in

             ARCHIVE)        ARCHIVE=on  ;;
             AUTOFIX)        AUTOFIX=on  ;;
           UPDATEFIX)      UPDATEFIX=on  ;;
           AUTOPRUNE)      AUTOPRUNE=on  ;;
              CCACHE)         CCACHE=on  ;;
               COLOR)          COLOR=on  ;;
          CONFIG_LOC)     CONFIG_LOC=on  ;;
         GATHER_DOCS)    GATHER_DOCS=on  ;;
        MAIL_REPORTS)   MAIL_REPORTS=on  ;;
            PRESERVE)       PRESERVE=on  ;;
             SUSTAIN)        SUSTAIN=on  ;;
               TMPFS)          TMPFS=on  ;;
        VIEW_REPORTS)   VIEW_REPORTS=on  ;;
              VOYEUR)         VOYEUR=on  ;;
                REAP)           REAP=on  ;;
      STORE_CONF_LOG) STORE_CONF_LOG=on  ;;
          NET_SELECT)     NET_SELECT=on  ;;
        CLEAN_SOURCE)   CLEAN_SOURCE=on  ;;
       CROSS_INSTALL)  CROSS_INSTALL=on  ;;
      SET_TERM_TITLE) SET_TERM_TITLE=on  ;;
              SCREEN)         SCREEN=on  ;;
      esac

    done

    TEMP=(ARCHIVE AUTOFIX UPDATEFIX AUTOPRUNE GATHER_DOCS MAIL_REPORTS VIEW_REPORTS PRESERVE SUSTAIN TMPFS VOYEUR REAP STORE_CONF_LOG NET_SELECT CONFIG_LOC CLEAN_SOURCE CROSS_INSTALL SET_TERM_TITLE SCREEN)
    for i in ${TEMP[*]} ; do
      modify_local_config "$i" "${!i}"
    done

    modify_local_config "color" "$COLOR" "command"

    TEMP=`cat       $LOCAL_COMPILE_CONFIG  |
          grep  -v  "CCACHE="`

    echo  "$TEMP"           >   $LOCAL_COMPILE_CONFIG
    echo  "CCACHE=$CCACHE"  >>  $LOCAL_COMPILE_CONFIG
  fi

}

option_menu()  {

  local B_HELP="Specify the sorcery branch you would like to track"
  local H_HELP="Specify the color scheme for messages"
  local D_HELP="Enter the default delay time for prompts"
  local E_HELP="Enter the email address for this box's sorcerer"
  local F_HELP="Select many options on or off at once"
  local M_HELP="Select ftp and http mirrors for faster downloads"
  local O_HELP="Select architecture optimizations"
  local I_HELP="Select the test that cleanse --fix, and AUTOFIX execute"
  local J_HELP="User defined defaults for depends following"
  local C_HELP="Setup distributed compilation"
  local R_HELP="Enter the maximum rate for downloading"
  local T_HELP="Select compression program for logs and archives"
  local N_HELP="Enter the process priority (nice value) to use for sorcery"
  local U_HELP="Enter the permissions mask (umask value) to use for sorcery"
  local S_HELP="Sorcery development options (debugging)"
  local W_HELP="Enter maximum timeout (seconds) for summoning sources"
  local X_HELP="Init.d/Xinetd Default Answer Selection Menu"
  local Z_HELP="Select sorcery sound scheme"

  while

    COMMAND=`eval $DIALOG '  --title "Option Menu"              \
                      --item-help                               \
                      --ok-label      "Select"                  \
                      --cancel-label  "Exit"                    \
                      --menu                                    \
                      ""                                        \
                      0 0 0                                     \
                      "B"  "Sorcery Branch"           "$B_HELP" \
                      "H"  "Color Scheme"             "$H_HELP" \
                      "D"  "Prompt Delay"             "$D_HELP" \
                      "R"  "Download Rate"            "$R_HELP" \
                      "N"  "Nice Level"               "$N_HELP" \
                      "U"  "Umask Value"              "$U_HELP" \
                      "E"  "Email of Sorcerer"        "$E_HELP" \
                      "F"  "Feature Menu"             "$F_HELP" \
                      "I"  "Integrity Checking"       "$I_HELP" \
                      "C"  "Parallel/Cached/Distributed Compiling"  "$C_HELP" \
                      "J"  "Dependency Following"     "$J_HELP" \
                      "M"  "Software Mirrors"         "$M_HELP" \
                      "O"  "Optimize Architecture"    "$O_HELP" \
                      "T"  "Compression Type"         "$T_HELP" \
                      "S"  "Sorcery Development"      "$S_HELP" \
                      "W"  "Summon Timeout Value"     "$W_HELP" \
                      "X"  "init.d xinetd.d defaults" "$X_HELP" \
                      "Z"  "Select Sound Scheme"      "$Z_HELP"'`

  do

    case  $COMMAND in

      B)  set_branch                ;;
      H)  color_schemes_menu        ;;
      D)  set_delay                 ;;
      R)  set_download_rate         ;;
      N)  set_nice                  ;;
      U)  set_umask                 ;;
      E)  set_email                 ;;
      F)  feature_menu              ;;
      I)  integrity_menu            ;;
      J)  dispel_depends_defaults_menu ;;
      C)  parallel_compilation_menu ;;
      M)  mirror_menu               ;;
      O)  optimize_architecture     ;;
      S)  sorcery_devel_settings    ;;
      T)  set_compression_type      ;;
      W)  set_http_ftp_timeout      ;;
      X)  service_defaults          ;;
      Z)  sound_schemes_menu        ;;

    esac

  done

}


goodbye() {

  echo  "Have a sorcerous day."
  exit

}


background_execute() {

  eval "$DIALOG  --msgbox  \"Processing queues in the background.\" 0 0"

  [  -f         $REMOVE_QUEUE  ]  &&
  dispel  `cat  $REMOVE_QUEUE`   1>/dev/null 2>&1
  rm  -f        $REMOVE_QUEUE

  if  [  -f             $INSTALL_QUEUE  ];  then
    cast  --deps  `cat  $INSTALL_QUEUE`
    (  cast       `cat  $INSTALL_QUEUE` 1>/dev/null 2>&1  &&
         rm             $INSTALL_QUEUE
    )  &
  fi

  goodbye

}


foreground_execute() {

  [  -f         $REMOVE_QUEUE  ]  &&
  dispel  `cat  $REMOVE_QUEUE`
  rm  -f        $REMOVE_QUEUE

  [  -f         $INSTALL_QUEUE  ]  &&
  cast `cat  $INSTALL_QUEUE`
  rm  -f        $INSTALL_QUEUE

  goodbye

}


main_menu()  {

  local S_HELP="Easy spell management."
  local O_HELP="Change sorcery options and features."
  local L_HELP="View and edit sorcery generated log files."
  local Q_HELP="View and edit sorcery queues."
  local F_HELP="Process queues while you watch and wait."
  local B_HELP="Process queues in the background."
  local E_HELP="Exit without processing queues."
  local I_HELP="Setting your install/state/track root locations"
  local C_HELP="Administrate groups of Unix/Linux boxes."
  local OK="Select"
  local CANCEL="Exit"

  while
    COMMAND=`eval $DIALOG ' --title "Main Menu"               \
                     --item-help                              \
                     --ok-label      "$OK"                    \
                     --cancel-label  "$CANCEL"                \
                     --menu                                   \
                     "Sorcery Version  $SORCERY_VERSION"      \
                     0 0 0                                    \
                     "S"  "Spell        Menu"     "$S_HELP"     \
                     "O"  "Option       Menu"     "$O_HELP"     \
                     "L"  "Log          Menu"     "$L_HELP"     \
                     "Q"  "Queue        Menu"     "$Q_HELP"     \
                     "F"  "Foreground   Execute"  "$F_HELP"     \
                     "B"  "Background   Execute"  "$B_HELP"     \
                     "I"  "Install Root Menu"   "$I_HELP"'`
  do

    case  $COMMAND in
      S)  spell_menu          ;;
      O)  option_menu         ;;
      L)  log_menu            ;;
      Q)  queue_menu          ;;
      F)  foreground_execute  ;;
      B)  background_execute  ;;
      I)  install_root_menu   ;;
    esac

  done

}



#---------------------------------------------------------------------
#-item sorcery_hold_spells <spells>
##
## sets <spells>'s status to held
##
## cli function
#---------------------------------------------------------------------
sorcery_hold_spells () {
    set_held $@
}


#---------------------------------------------------------------------
#-item sorcery_unhold_spells <spells>
##
## unholds <spells>'s status. (Sets it to installed)
##
## cli function
#---------------------------------------------------------------------
sorcery_unhold_spells () {
    set_unheld $@
}


#---------------------------------------------------------------------
#-item sorcery_set_default <spells>
##
## Used for setting default_depends/providers
##
## cli function
#---------------------------------------------------------------------
sorcery_cli_defaults () {
  local cmd=$1
  shift
  case $cmd in
    add) sorcery_add_defaults "$@" ;;
    search) sorcery_search_defaults "$@" ;;
    remove) sorcery_remove_defaults "$@" ;;
    *) help ;;
  esac
}

#---------------------------------------------------------------------
#-item sorcery_add_default <spells>
##
## Used for setting default_depends/providers
##
## cli function
#---------------------------------------------------------------------
sorcery_add_defaults () {
    if [ $# -ne 3 ] ; then
      message "${PROBLEM_COLOR}Wrong number of arguments.${DEFAULT_COLOR}"
      help
    fi


    # check for this first as a slight optimization
    if [[ $3 != on ]] && [[ $3 != off ]] ; then
      message "${PROBLEM_COLOR}Please choose on or off.${DEFAULT_COLOR}"
      help
    fi

    if [[ ! $1 ]] && [[ ! $2 ]] ; then
      message "${PROBLEM_COLOR}Can't set anything to be the default" \
              "for everything!${DEFAULT_COLOR}"
    fi

    if [[ $1 ]] && ! codex_does_spell_exist $1; then
      #echo "$1 is not a spell" # already printed by codex_does_spell_exist
      help
    fi

    if [[ ! $2 ]] || codex_does_spell_exist $2 &>/dev/null; then
      add_default_depends $DEFAULT_DEPENDS "$@"
    elif codex_does_service_exist $2 ; then
      add_default_provider $DEFAULT_PROVIDERS "$@"
    else
      message "${SPELL_COLOR}$2${PROBLEM_COLOR} is not a valid choice." \
              "Please choose a spell, provider, or \"\".${DEFAULT_COLOR}"
      help
    fi || echo "Unknown error occured, contact the sorcery team"
}

#---------------------------------------------------------------------
#-item sorcery_search_default <spells>
##
## Used for searching default_depends/providers
##
## cli function
#---------------------------------------------------------------------
sorcery_search_defaults () {
  # it wont hurt to look in both
  search_default_depends $DEFAULT_DEPENDS "$@"
  search_default_provider $DEFAULT_PROVIDERS "$@"
}

#---------------------------------------------------------------------
#-item sorcery_remove_default <spells>
##
## Used for removing default_depends/providers
##
## cli function
#---------------------------------------------------------------------
sorcery_remove_defaults () {
  remove_default_depends $DEFAULT_DEPENDS "$@"
  remove_default_provider $DEFAULT_PROVIDERS "$@"
}

#---------------------------------------------------------------------
#-item sorcery_queue_add <spells>
##
## Used for adding spells to install queue
##
## cli function
#---------------------------------------------------------------------
sorcery_queue_add() {
  tINSTALL_QUEUE=`lock_start_transaction "$INSTALL_QUEUE"`
  for SPELL in "$@"; do
    grep -qE "^$SPELL\$" "$tINSTALL_QUEUE" || echo "$SPELL" >> "$tINSTALL_QUEUE"
  done
  lock_commit_transaction "$INSTALL_QUEUE"
}

#---------------------------------------------------------------------
#-item sorcery_queue_remove <spells>
##
## Used for removing spells from install queue
##
## cli function
#---------------------------------------------------------------------
sorcery_queue_remove() {
  tINSTALL_QUEUE=`lock_start_transaction "$INSTALL_QUEUE"`
  for SPELL in "$@"; do
    if grep -qE "^$SPELL\$" "$tINSTALL_QUEUE"; then
      grep -vE "^$SPELL\$" "$tINSTALL_QUEUE" > "$TMP_DIR/tmp_queue"
      mv "$TMP_DIR/tmp_queue" "$tINSTALL_QUEUE"
    else
      message "${PROBLEM_COLOR}Spell ${SPELL_COLOR}$SPELL${PROBLEM_COLOR} not found in install queue!${DEFAULT_COLOR}"
    fi
  done
  lock_commit_transaction "$INSTALL_QUEUE"
}

main() {

  rm  -f  $UPDATE_SCRIPT

  if [ -z $1 ]; then
    main_menu
  else
    case  $1  in
            -u|update)  update_sorcery                          ;;
     -s|system-update)  update_pkgs  autoupdate                 ;;
           -g|upgrade)  update_pkgs  upgrade                    ;;
             -q|queue)  update_queue                            ;;
       queue-security)  update_security_queue                   ;;
           -r|rebuild)  rebuild                                 ;;
         review-queue)  install_queue_history                   ;;
            add-queue) shift; sorcery_queue_add "$@"            ;;
         remove-queue) shift; sorcery_queue_remove "$@"         ;;
                 hold) shift; sorcery_hold_spells   "$@"        ;;
               unhold) shift; sorcery_unhold_spells "$@"        ;;
                exile) shift; set_exiled $@                     ;;
              unexile) shift; set_unexiled $@                   ;;
              default*) shift; sorcery_cli_defaults "$@"        ;;

       -h|--help|help)  help                                    ;;
 -v|--version|version)  echo $SORCERY_VERSION                   ;;
                    *)  help                                    ;;
    esac
  fi

}


. /etc/sorcery/config
if  [  "$UID"  ==  0  ];  then
  DIALOG='$DIALOGPROG  --backtitle "Sorcery Spell Management Utility" --stdout'

  SORCERY_VERSION=`cat /etc/sorcery/version`
  SORCERY_DIR=`codex_find_spell_by_name  sorcery-$SORCERY_BRANCH`
  mk_tmp_dirs sorcery
  main  "$@"
  rc=$?
  cleanup_tmp_dir $TMP_DIR
  exit $rc
else
  if [[ $1 == -h ]] || [[ $1 == --help ]] || [[ $1 == help ]]; then 
    help
  else
    if [[ $1 == -v ]] || [[ $1 == --version ]] || [[ $1 == version ]]; then
      echo  $( cat /etc/sorcery/version )
    else
      echo  "Enter the root password, please."
      PARAMS=$(consolidate_params "$@")
      su -c "$0 $PARAMS" root
    fi
  fi
fi


#---------------------------------------------------------------------
##=back
##
##=head1 LICENSE
##
## This software 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 software 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 software; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
##
#---------------------------------------------------------------------
