/usr/sbin/dispel

     1	#!/bin/bash
     2	#---------------------------------------------------------------------
     3	## @Synopsis Dispel is the spell removal utility. It can be called by the user or by intone.
     4	##
     5	## @Copyright Original version Copyright 2001 by Kyle Sallee
     6	## @Copyright Additions/corrections Copyright 2002 by the Source Mage Team
     7	##
     8	## Dispel is the spell removal utility. It can be called by the user or by intone.
     9	##
    10	#---------------------------------------------------------------------
    11	
    12	
    13	help">help">help()  {
    14	
    15	  cat  <<  EOF
    16	
    17	Dispel uninstalls single or multiple spells.
    18	
    19	Example:        dispel  hdparm vim emacs
    20	Usage:          dispel  [parameters]  [spells]
    21	
    22	Optional Parameters:
    23	
    24	-e | --exile spell      Removes spells and blocks them
    25	                        from being automatically reinstalled.
    26	
    27	-d | --downgrade spell [version]
    28	                        Removes the spell and reinstalls
    29	                        the selected version from cache
    30	
    31	--notriggers            Disables triggers for this dispel
    32	--nosustain             Turns off dispel protection for vital spells
    33	                        (you usually don't want to do this)
    34	--noreap                Dispels spells but doesn't remove its files
    35	--no-reap-depends       Dont remove dependency information, dont use this
    36	                        unless you know exactly what you are doing, and
    37	                        dont complain if it breaks your box.
    38	
    39	--total-dispel          Remove everything including config files even
    40	                        if they were modified.
    41	--noqueue               Don't try to remove the spell from the install queue
    42	
    43	The following parameters effect dependency following, if they are not
    44	specified the default action is to do no dependency following. For
    45	a more in-depth explaination refer to the manual
    46	
    47	                        The following 5 parameters accept one of the following
    48	                        4 parameters:
    49	                        ignore, ask-yes, ask-no, always
    50	
    51	--orphan                Default action for dispelling a newly orphaned child
    52	                        spell.
    53	--non-orphan            Default action for dispelling a dependee of
    54	                        another spell, that is not an orphan (doing this
    55	                        will break the spells that still depend on it).
    56	
    57	--child                 Default action for dispelling a child spell that
    58	                        is either an orphan or non-orphan.
    59	
    60	--recast-parent         If a spell has a child removed from under it, the
    61	                        spell is considered broken, if all of the removed
    62	                        children are optional, the spell may be recast
    63	                        without those depends. This option controls the
    64	                        default for this action.
    65	--dispel-parent         Default action for dispelling broken parents,
    66	                        the user is asked for recasting if possible first.
    67	
    68	--user-deps             Use defaults for dependency following from the
    69	--user-child-deps       sorcery menu for child and/or parent dependency
    70	--user-parent-deps      following.
    71	
    72	EOF
    73	
    74	  exit  1
    75	
    76	}
    77	
    78	#-----
    79	## Downgrade a spell to a previously installed version
    80	## @param Spell
    81	## @param Previous version
    82	#-----
    83	function downgrade()  {
    84	  if [[ $SUSTAIN == off ]]; then
    85	    resurrect --nosustain $1 -v "$2"
    86	  else
    87	    resurrect $1 -v "$2"
    88	  fi
    89	  DISPEL_EXIT_STATUS=$?
    90	}
    91	
    92	#-----
    93	## Parse the dispel script's parameters
    94	## @Args Parameters
    95	#-----
    96	function process_parameters">process_parameters">process_parameters()  {
    97	  while  [  -n  "$1"  ];  do
    98	    if  echo  ""  $1  |  grep  -q  "^ -";  then
    99	      case  $1  in
   100	         -e|--exile)
   101	            if [[ -z $2 ]]; then
   102	              message  "${PROBLEM_COLOR}Missing parameters!${DEFAULT_COLOR}"
   103	              help">help">help
   104	            fi
   105	            EXILE="yes"; shift 1
   106	            ;;
   107	     -d|--downgrade)
   108	            if [[ -z $2 ]]; then
   109	              message  "${PROBLEM_COLOR}Missing parameters!${DEFAULT_COLOR}"
   110	              help">help">help
   111	            fi
   112	            DOWNGRADE_SPELL=$2
   113	            if [[ ${3:0:1} != - ]]; then
   114	              DOWNGRADE_VERSION=$3
   115	              shift
   116	            fi
   117	            shift 2
   118	            ;;
   119	           --noreap)  REAP="off";         shift  1  ;;
   120	  --no-reap-depends)  NO_REAP_DEPENDS="on";  shift  1  ;;
   121	        --nosustain)  SUSTAIN="off";      shift  1  ;;
   122	       --notriggers)  TRIGGER="off";      shift  1  ;;
   123	            --child)  validate_param $2 ORPHAN_DEFAULT
   124	                      validate_param $2 NONORPHAN_DEFAULT
   125	                      shift ;;
   126	           --orphan)  validate_param $2 ORPHAN_DEFAULT
   127	                      shift ;;
   128	       --non-orphan)  validate_param $2 NONORPHAN_DEFAULT
   129	                      shift ;;
   130	        --user-deps)  validate_param "$ORPHAN_MENU_DEFAULT" ORPHAN_DEFAULT
   131	                      validate_param "$NONORPHAN_MENU_DEFAULT" NONORPHAN_DEFAULT
   132	                      validate_param "$RECAST_PARENT_MENU_DEFAULT" \
   133	                                     RECAST_PARENT_DEFAULT
   134	                      validate_param "$DISPEL_PARENT_MENU_DEFAULT" \
   135	                                     DISPEL_PARENT_DEFAULT
   136	                      shift 1 ;;
   137	  --user-child-deps)  validate_param "$ORPHAN_MENU_DEFAULT" ORPHAN_DEFAULT
   138	                      validate_param "$NONORPHAN_MENU_DEFAULT" NONORPHAN_DEFAULT
   139	                      shift ;;
   140	    --recast-parent)  validate_param $2 RECAST_PARENT_DEFAULT
   141	                      shift ;;
   142	    --dispel-parent)  validate_param $2 DISPEL_PARENT_DEFAULT
   143	                      shift ;;
   144	 --user-parent-deps)  validate_param "$RECAST_PARENT_MENU_DEFAULT" \
   145	                                     RECAST_PARENT_DEFAULT
   146	                      validate_param "$DISPEL_PARENT_MENU_DEFAULT" \
   147	                                     DISPEL_PARENT_DEFAULT
   148	                      shift ;;
   149	     --debug-dispel)  DEBUG_DISPEL=yes ; shift 1 ;;
   150	     --total-dispel)  TOTAL_DISPEL=yes ; shift 1 ;;
   151	          --noqueue)  DEQUEUE=off; shift  1  ;;
   152	                  *)  help">help">help                       ;;
   153	      esac
   154	    else
   155	      shift
   156	   fi
   157	  done
   158	}
   159	
   160	function validate_param() {
   161	  case $1 in
   162	    ask-yes|ask-no|ignore|always)  eval "$2=\"$1\"" ;;
   163	    *) message "\"$1\" is not a valid option, use ask-yes, ask-no," \
   164	               "ignore or always"
   165	       help">help">help ;;
   166	  esac
   167	}
   168	
   169	#-----
   170	## Remove the parsed parameters
   171	## This is a silly way to do it
   172	## @Args Parameters
   173	#-----
   174	function strip_parameters">strip_parameters()  {
   175	  while  [  -n  "$1"  ];  do
   176	    if  echo  "" $1  |  grep  -q  "^ -";  then
   177	      case  $1  in
   178	            -e|--exile)  shift  1  ;;
   179	        -d|--downgrade)  shift  2; [[ ${3:0:1} == - ]] || shift ;;
   180	              --noreap)  shift  1  ;;
   181	     --no-reap-depends)  shift  1  ;;
   182	           --nosustain)  shift  1  ;;
   183	          --notriggers)  shift  1  ;;
   184	               --child)  shift  2  ;;
   185	              --orphan)  shift  2  ;;
   186	          --non-orphan)  shift  2  ;;
   187	     --user-child-deps)  shift  1  ;;
   188	       --recast-parent)  shift  2  ;;
   189	       --dispel-parent)  shift  2  ;;
   190	    --user-parent-deps)  shift  1  ;;
   191	        --debug-dispel)  shift  1  ;;
   192	        --total-dispel)  shift  1  ;;
   193	             --noqueue)  shift  1  ;;
   194	                     *)  shift  1  ;;
   195	      esac
   196	    else
   197	      echo -n "$1 "
   198	      shift
   199	   fi
   200	  done
   201	}
   202	
   203	#---------------------------------------------------------------------
   204	## Display what dependencies were removed
   205	#---------------------------------------------------------------------
   206	function dispel_parents_list_borkers() {
   207	  local parent=$1
   208	  local optional_borkers=$2
   209	  local runtime_borkers=$3
   210	  local suggested_borkers=$4
   211	  if [[ "$optional_borkers" ]] ; then
   212	    message "${SPELL_COLOR}${parent}${DEFAULT_COLOR}${MESSAGE_COLOR}" \
   213	            "had the following optional dependencies removed:${DEFAULT_COLOR}"
   214	    message "${SPELL_COLOR}"
   215	    echo $optional_borkers | col
   216	    message "${DEFAULT_COLOR}"
   217	  fi
   218	  if [[ "$runtime_borkers" ]] ; then
   219	    message "${SPELL_COLOR}${parent}${DEFAULT_COLOR}${MESSAGE_COLOR}" \
   220	            "had the following runtime dependencies removed:${DEFAULT_COLOR}"
   221	    message "${SPELL_COLOR}"
   222	    echo $runtime_borkers | col
   223	    message "${DEFAULT_COLOR}"
   224	  fi
   225	  if [[ "$suggested_borkers" ]] ; then
   226	    message "${SPELL_COLOR}${parent}${DEFAULT_COLOR}${MESSAGE_COLOR}" \
   227	            "had the following suggested dependencies removed:${DEFAULT_COLOR}"
   228	    message "${SPELL_COLOR}"
   229	    echo $suggested_borkers | col
   230	    message "${DEFAULT_COLOR}"
   231	  fi
   232	}
   233	
   234	#---------------------------------------------------------------------
   235	## @param spell to dispel
   236	##
   237	## Frontend to do common things for dispelling (keep a note of what
   238	## has already been dispelled.
   239	#---------------------------------------------------------------------
   240	function dispel_spell_wrapper() {
   241	  dispel_spell $1 &&
   242	  hash_put ALL_DISPELS $1 yes
   243	}
   244	
   245	#---------------------------------------------------------------------
   246	## @param list of spells to remove the children of
   247	## @param variable name to store list of newly dispelled spells
   248	##
   249	## Move one step down the depends tree for the given spells, return
   250	## list of spells removed.
   251	## The caller is expected to call this in a loop until nothing is returned.
   252	#---------------------------------------------------------------------
   253	function dispel_children() {
   254	  local spells=$1
   255	
   256	  local our_children
   257	  for spell in $spells; do
   258	    # this assumes list_add remains idempotent, which it is
   259	    local dependencies
   260	    hash_get_ref down_deps $spell dependencies
   261	    list_add our_children $dependencies
   262	  done
   263	  debug "children of $1 -> $our_children"
   264	
   265	  local is_orphan is_gone
   266	  local orphan_list non_orphan_list
   267	  for child in $our_children; do
   268	    hash_get_ref ALL_DISPELS $child is_gone
   269	    if [[ $is_gone == yes ]]; then
   270	      debug "someone depends on $child but it was already removed"
   271	      continue
   272	    fi
   273	    # determine if this child is becomming an orphan or not
   274	    is_orphan="yes"
   275	    local parents
   276	    hash_get_ref up_deps $child parents
   277	    for parent in $parents; do
   278	      if ! list_find "$spells" "$parent"; then
   279	        is_orphan=no
   280	        break
   281	      fi
   282	    done
   283	    if [[ "$is_orphan" == yes ]] ; then
   284	      list_add orphan_list $child
   285	    else
   286	      list_add non_orphan_list $child
   287	    fi
   288	  done
   289	
   290	  local removed_children
   291	  for child in $orphan_list; do
   292	    debug dispel "looking at orphan $child:"
   293	    #debug dispel "parents: $(hash_get up_deps $child)"
   294	    #debug "children: $(hash_get down_deps $child)"
   295	    if dispel_child_query "$child" "is an orphan" \
   296	                          "Would you like to dispel it" \
   297	                          "${ORPHAN_DEFAULT}" ; then
   298	      dispel_spell_wrapper $child &&
   299	      list_add removed_children $child
   300	    fi
   301	  done
   302	  for child in $non_orphan_list; do
   303	    debug "looking at non-orphan $child:"
   304	    #debug "parents: $(hash_get up_deps $child)"
   305	    #debug "children: $(hash_get down_deps $child)"
   306	    if dispel_child_query "$child" "is not an orphan" \
   307	                          "Would you like to dispel it" \
   308	                          "${NONORPHAN_DEFAULT}" ; then
   309	      dispel_spell_wrapper $child &&
   310	      list_add removed_children $child
   311	    fi
   312	  done
   313	
   314	  eval "$2=\"$removed_children\""
   315	}
   316	
   317	#---------------------------------------------------------------------
   318	## Common code for querying the user about children to remove
   319	## Prints a message and asks a query, if ask-yes or ask-no is the
   320	## provided action.
   321	##
   322	## @param       Spell in question
   323	## @param       Message a short message about the state of the spell
   324	## @param       Question to ask the user
   325	## @param       quad-option (always, ask-yes, ask-no, ignore)
   326	#---------------------------------------------------------------------
   327	function dispel_child_query() {
   328	  local SPELL=$1
   329	  local MESSAGE=$2
   330	  local QUERY=$3
   331	  local DEFAULT=$4
   332	  local query_default
   333	  if [[ ! $DEFAULT ]] ; then
   334	    return 1
   335	  fi
   336	  if [[ $DEFAULT == ignore ]] ; then
   337	    return 1
   338	  fi
   339	  if [[ $DEFAULT == always ]] ; then
   340	    return 0
   341	  fi
   342	  if [[ $DEFAULT == ask-yes ]] ; then
   343	    query_default=y
   344	  fi
   345	  if [[ $DEFAULT == ask-no ]] ; then
   346	    query_default=n
   347	  fi
   348	  message "${DEFAULT_COLOR}${SPELL_COLOR}${SPELL}${DEFAULT_COLOR}" \
   349	          "${MESSAGE_COLOR}${MESSAGE}.${DEFAULT_COLOR}"
   350	  query "$QUERY" $query_default
   351	}
   352	
   353	#---------------------------------------------------------------------
   354	## Common code for querying the user about parents spells.
   355	## Asks a query, if ask-yes or ask-no is the provided action.
   356	##
   357	## @param       Question to ask the user
   358	## @param       quad-option (always, ask-yes, ask-no, ignore)
   359	#---------------------------------------------------------------------
   360	function dispel_parent_query() {
   361	  local QUERY=$1
   362	  local DEFAULT=$2
   363	  local query_default
   364	  if [[ ! $DEFAULT ]] ; then
   365	    return 1
   366	  fi
   367	  if [[ $DEFAULT == ignore ]] ; then
   368	    return 1
   369	  fi
   370	  if [[ $DEFAULT == always ]] ; then
   371	    return 0
   372	  fi
   373	  if [[ $DEFAULT == ask-yes ]] ; then
   374	    query_default=y
   375	  fi
   376	  if [[ $DEFAULT == ask-no ]] ; then
   377	    query_default=n
   378	  fi
   379	  query "$QUERY" $query_default
   380	}
   381	
   382	
   383	#---------------------------------------------------------------------
   384	## @param Spell in question
   385	## dis-associate with all its children (fix upward dep tree)
   386	## remove spell from the downward tree
   387	#---------------------------------------------------------------------
   388	function remove_from_dep_trees() {
   389	  debug dispel "$FUNCNAME $@"
   390	  local spell=$1
   391	  local down_dep_hash=$2
   392	  local up_dep_hash=$3
   393	  local foo
   394	  local children
   395	  hash_get_ref $down_dep_hash $spell children
   396	  for child in $children; do
   397	    hash_get_ref $up_dep_hash $child foo
   398	    list_remove foo $spell
   399	    hash_put $up_dep_hash $child "$foo"
   400	  done
   401	  hash_unset $down_dep_hash $spell
   402	}
   403	
   404	#---------------------------------------------------------------------
   405	## @param    Spell to find borked parents for
   406	## @param    Name of upward dependency hash
   407	## @param    Name of hash to accumulate borked parents in
   408	##
   409	## Find the spells that the following spell borks.
   410	##
   411	## Bork is a technical term which in this context refers to the situation
   412	## where a spell is removed and spells that depend on it are broken. For
   413	## example xorg borks blackbox.
   414	#---------------------------------------------------------------------
   415	function get_borked_parents() {
   416	  local spell=$1
   417	  local up_dep_hash=$2
   418	  local parent parents
   419	  # get the spells that depend on us
   420	  hash_get_ref $up_dep_hash $spell parents
   421	  for parent in $parents; do
   422	    debug dispel "hash_append $3 $parent $spell"
   423	    hash_append $3 $parent $spell
   424	  done
   425	}
   426	
   427	#---------------------------------------------------------------------
   428	## Main dependency following engine. This will follow the dependency
   429	## tree downwards for all the provided spells, then repair one level of
   430	## borked parents. The caller is expected to call this repeatedly until
   431	## there are no borked parents to remove.
   432	##
   433	## @param        List of spells to remove on this iteration.
   434	#---------------------------------------------------------------------
   435	function dispel_depends_engine() {
   436	
   437	  local CURR_SPELLS SPELL
   438	  for  SPELL  in  $1;  do
   439	    if dispel_spell_wrapper $SPELL ; then
   440	      list_add CURR_SPELLS $SPELL
   441	    else
   442	      DISPEL_EXIT_STATUS=${DISPEL_EXIT_STATUS:-$?}
   443	    fi
   444	  done
   445	
   446	
   447	  if [[ "$CHILD_DEPS" == yes ]] ; then
   448	    # go down the depends tree killing stuff
   449	    # each time dispel_children is called it appends the new children that
   450	    # can be dispelled
   451	    # dispel_children has its own policy of what will be picked, and may
   452	    # prompt the user for input
   453	    local new_children=$CURR_SPELLS
   454	    while [[ $new_children ]] ; do
   455	      curr_children=$new_children
   456	      unset new_children
   457	      debug dispel "in with $curr_children"
   458	      dispel_children "$curr_children" new_children
   459	      debug dispel "out with $new_children"
   460	      list_add CURR_SPELLS $new_children
   461	      for SPELL in $curr_children; do
   462	        remove_from_dep_trees $SPELL down_deps up_deps
   463	      done
   464	    done
   465	  fi
   466	
   467	  if [[ "$PARENT_DEPS" == yes ]] ; then
   468	    # figure out what parents are borked and whats borked them
   469	    hash_reset BORKED_PARENTS
   470	    for SPELL in $CURR_SPELLS; do
   471	      # maps broken spells to the spells that borked them
   472	      get_borked_parents $SPELL up_deps BORKED_PARENTS
   473	    done
   474	
   475	    local NEW_CASTS=""
   476	    local NEW_DISPELS=""
   477	    local borkers
   478	    # for all borked spells either recast, dispel, or ignore
   479	    for parent in $(hash_get_table_fields BORKED_PARENTS) ; do
   480	      hash_get_ref BORKED_PARENTS $parent borkers
   481	      message "$parent is borked because of $borkers"
   482	      local recastable=yes
   483	
   484	      local non_optional_borkers suggested_borkers runtime_borkers type
   485	      # if any of the removed children are required depends of the current
   486	      # spell, the spell is not recastable
   487	      # note: this doesnt take into account the spell changing out from
   488	      # under us. Oh well.
   489	      lock_file $DEPENDS_STATUS
   490	      for child in $borkers; do
   491	        type=$(grep -m 1 "$parent:$child\(([^:]*)\)\?:on" $DEPENDS_STATUS|cut -f4 -d:)
   492	        if [[ "$type" == required ]]; then
   493	          recastable=no
   494	          list_add non_optional_borkers $child
   495	        elif [[ "$type" == "runtime" ]] ; then
   496	          [[ "$recastable" != no ]] && recastable=NA
   497	          list_add runtime_borkers $child
   498	        elif [[ "$type" == "suggest" ]] ; then
   499	          [[ "$recastable" != no ]] && recastable=NA
   500	          list_add suggested_borkers $child
   501	        else
   502	          list_add optional_borkers $child
   503	        fi
   504	      done
   505	      unlock_file $DEPENDS_STATUS
   506	      if [[ $recastable == yes ]] ; then
   507	        dispel_parents_list_borkers $parent "$optional_borkers" \
   508	                                    "$runtime_borkers" "$suggested_borkers"
   509	        if [[ $optional_borkers ]] && dispel_parent_query \
   510	                       "Re-cast $parent without these optional depends?" \
   511	                       "$RECAST_PARENT_DEFAULT" ; then
   512	          # fix up the abandoned depends data for impending recompile
   513	          # this is a bit of a hack but should work:
   514	          # remove any uncommitted data, store our new data in a new abandonded
   515	          # dir with borked optionals disabled, remove those deps
   516	          # from master file so that recasting will see them
   517	          depends_file=$ABANDONED_DEPENDS/$SPELL
   518	          rm -f $UNCOMMITTED_DEPENDS/$parent $depends_file
   519	          touch $depends_file
   520	          local depline
   521	          search_depends_status $DEPENDS_STATUS $parent|while read depline; do
   522	            explode "$depline" : deparray
   523	            # note: we know that all $borkers are optional from
   524	            # the check above
   525	            if list_find "$borkers" "${deparray[1]}"; then
   526	              deparray[2]=off
   527	              # remove this rule so cast will look elsewhere
   528	              # (the abandoned file), the strange regexp at the end
   529	              # is to match providers: xorg(X11-LIBS)
   530	              remove_depends_status $DEPENDS_STATUS $parent \
   531	                                    "${deparray[1]}\(([^:]*)\)\?"
   532	            fi
   533	            add_depends $depends_file "${deparray[@]}"
   534	          done
   535	
   536	          list_add NEW_CASTS $parent
   537	        elif dispel_parent_query "Dispel $parent?" \
   538	                                 "$DISPEL_PARENT_DEFAULT" ; then
   539	
   540	          hash_get_ref down_deps $parent foo
   541	          list_remove foo $borkers
   542	          hash_put down_deps $parent $foo
   543	
   544	          list_add NEW_DISPELS $parent
   545	        else
   546	          message "Please fix broken dependencies with cleanse --prune"
   547	        fi
   548	      else
   549	        dispel_parents_list_borkers $parent "$optional_borkers" \
   550	                                    "$runtime_borkers" "$suggested_borkers"
   551	        if dispel_parent_query "Dispel $parent?" \
   552	                               "$DISPEL_PARENT_DEFAULT"; then
   553	
   554	          hash_get_ref down_deps $parent foo
   555	          list_remove foo $borkers
   556	          hash_put down_deps $parent $foo
   557	
   558	          list_add NEW_DISPELS $parent
   559	        else
   560	          message "Please fix broken dependencies with cleanse --prune"
   561	        fi
   562	      fi
   563	    done
   564	    if [[ $NEW_CASTS ]] ; then
   565	      debug dispel "cast -c $NEW_CASTS"
   566	      cast -c $NEW_CASTS
   567	    fi
   568	  fi
   569	  debug dispel "NEW_DISPELS: $NEW_DISPELS"
   570	  debug dispel "eval $2=\"$NEW_DISPELS\""
   571	  eval "$2=\"$NEW_DISPELS\""
   572	
   573	  return  ${DISPEL_EXIT_STATUS:-0}
   574	}
   575	
   576	#---------------------------------------------------------------------
   577	## Main loop for dispel
   578	## @Args Parameters
   579	#---------------------------------------------------------------------
   580	function main">main">main">main">main() {
   581	
   582	  process_parameters">process_parameters">process_parameters        "$@"
   583	  # handle downgrading specially, since we also want to pass some of the flags
   584	  # but can't rely on input being ordered correctly
   585	  # having this block here allows process_parameters">process_parameters">process_parameters to be used for input verification
   586	  if [[ -n $DOWNGRADE_SPELL ]]; then
   587	    downgrade $DOWNGRADE_SPELL $DOWNGRADE_VERSION
   588	  fi
   589	  SPELLS=`strip_parameters">strip_parameters  "$@"`
   590	
   591	  if [[ $NONORPHAN_DEFAULT ]] ||
   592	     [[ $ORPHAN_DEFAULT ]] ; then
   593	    CHILD_DEPS=yes
   594	    DO_DEPENDS=yes
   595	  fi
   596	
   597	  if [[ $RECAST_PARENT_DEFAULT ]] ||
   598	     [[ $DISPEL_PARENT_DEFAULT ]] ; then
   599	    PARENT_DEPS=yes
   600	    DO_DEPENDS=yes
   601	  fi
   602	  if [[ $DO_DEPENDS ]] ; then
   603	    while [[ $SPELLS ]] ; do
   604	      debug dispel "recomputing depends tree"
   605	      compute_installed_depends down_deps all
   606	      compute_reverse_installed_depends up_deps all
   607	      dispel_depends_engine "$SPELLS" SPELLS
   608	      debug dispel "SPELLS $SPELLS"
   609	    done
   610	  else
   611	    for SPELL in $SPELLS; do
   612	      dispel_spell_wrapper $SPELL ||
   613	      DISPEL_EXIT_STATUS=${DISPEL_EXIT_STATUS:-$?}
   614	    done
   615	  fi
   616	  return $DISPEL_EXIT_STATUS
   617	}
   618	
   619	. /etc/sorcery/config
   620	
   621	if    [  $#      ==  0  ];  then  help">help">help  |  $PAGER
   622	elif  [[  $1 == -h  ]]  ||  [[  $1 == --help  ]] ; then help">help">help
   623	elif  [  "$UID"  ==  0  ];  then
   624	  mk_tmp_dirs dispel
   625	  main">main">main">main">main  "$@"
   626	  rc=$?
   627	  cleanup_tmp_dir $TMP_DIR
   628	  exit $rc
   629	else
   630	  # validate the parameters before su-ing, since we may still drop out
   631	  process_parameters">process_parameters">process_parameters "$@"
   632	
   633	  echo  "Enter the root password, please."  1>&2
   634	  PARAMS=$(consolidate_params "$@")
   635	  exec su -c "dispel $PARAMS" root
   636	fi
   637	
   638	
   639	#---------------------------------------------------------------------
   640	##=back
   641	##
   642	##=head1 LICENSE
   643	##
   644	## This software is free software; you can redistribute it and/or modify
   645	## it under the terms of the GNU General Public License as published by
   646	## the Free Software Foundation; either version 2 of the License, or
   647	## (at your option) any later version.
   648	##
   649	## This software is distributed in the hope that it will be useful,
   650	## but WITHOUT ANY WARRANTY; without even the implied warranty of
   651	## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   652	## GNU General Public License for more details.
   653	##
   654	## You should have received a copy of the GNU General Public License
   655	## along with this software; if not, write to the Free Software
   656	## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   657	##
   658	#---------------------------------------------------------------------