/usr/sbin/alter

     1	#!/bin/bash
     2	
     3	############################################################
     4	# Copyright 2004 Seth Woolley                              #
     5	# Released under the GPL                                   #
     6	############################################################
     7	# alter handles post-spell spell handling                  #
     8	############################################################
     9	
    10	function alter_alter() {
    11	
    12	  if [ -z "$1" ]; then
    13	    cat <<EOF > /dev/stderr && return 1
    14	alter [ -a|--alter ] [ -n|--spell spellname ]
    15	                     [ -v|--version version ]
    16	                     command [ args ... ]
    17	EOF
    18	  fi
    19	
    20	
    21	  if [ "$1" == "-n" -o "$1" == "--spell" ]; then SPELL="$2";shift;shift; fi
    22	  if [ "$1" == "-v" -o "$1" == "--version" ]; then VERSION="$2";shift;shift; fi
    23	
    24	  source /etc/sorcery/config
    25	  SPELL=${SPELL:=alter}
    26	  lock_resources "cast" "$SPELL"
    27	  VERSION="$(gaze -q installed "$SPELL" | grep -v 'not installed')"
    28	  [ -z "$VERSION" ] && VERSION=$$
    29	  TMP_LOG=$TMP_DIR/$SPELL-$VERSION
    30	  IW_LOG=$TMP_DIR/$SPELL-$VERSION.iw
    31	  INST_LOG=$INSTALL_LOGS/$SPELL-$VERSION
    32	  MD5_LOG=$MD5SUM_LOGS/$SPELL-$VERSION
    33	  C_LOG=$TMP_DIR/$SPELL-$VERSION.compile.log
    34	  C_LOG_COMP=$COMPILE_LOGS/$SPELL-$VERSION$EXTENSION
    35	  construct_cache_name "$INSTALL_CACHE/$SPELL-$VERSION-$HOST" CACHE
    36	  CACHE_COMP=${CACHE}${EXTENSION}
    37	  rm -f  "$C_LOG" 2> /dev/null
    38	  touch  "$C_LOG"
    39	  message "${MESSAGE_COLOR}Gathering metadata for ${SPELL_COLOR}$SPELL${DEFAULT_COLOR}${MESSAGE_COLOR}.${DEFAULT_COLOR}"
    40	  DATA="$(gaze compile $SPELL 2> /dev/null)" && COM_DATA="$DATA" || COM_DATA=""
    41	  DATA="$(gaze install $SPELL 2> /dev/null)" && INS_DATA="$DATA" || INS_DATA=""
    42	  DATA="$(gaze md5sum  $SPELL 2> /dev/null)" && MD5_DATA="$DATA" || MD5_DATA=""
    43	  [ -n "$COM_DATA" ] && echo "$COM_DATA" > "$C_LOG"
    44	  message "${MESSAGE_COLOR}Altering...${DEFAULT_COLOR}"
    45	
    46	  if [ "$VOYEUR" == "on" -a -z "$SILENT" ]; then
    47	    VOYEUR_STDOUT=/dev/stdout
    48	    VOYEUR_STDERR=/dev/stderr
    49	  else
    50	    VOYEUR_STDOUT=/dev/null
    51	    VOYEUR_STDERR=/dev/null
    52	  fi
    53	
    54	  invoke_installwatch
    55	  (
    56	    echo "$@"
    57	    echo "$@" | bash
    58	  ) 2> >(tee -a $C_LOG 1>&2 > $VOYEUR_STDERR) > >(tee -a $C_LOG > $VOYEUR_STDOUT)
    59	  devoke_installwatch
    60	  touch $IW_LOG $MD5_LOG $C_LOG_COMP
    61	  create_install_log $IW_LOG $INST_LOG
    62	  [ -n "$MD5_DATA" ] && echo "$MD5_DATA" | cut -c35- |
    63	    exists | grep -v "^$LOG_DIRECTORY" > "$TMP_LOG.2" &&
    64	    cat "$TMP_LOG.2" "$INST_LOG" | sort -u > "$TMP_LOG.3" ||
    65	    cp "$INST_LOG" "$TMP_LOG.3"
    66	  rm "$TMP_LOG.2" 2> /dev/null
    67	  mv "$TMP_LOG.3" "$INST_LOG"
    68	  create_compile_log
    69	  create_md5list $INST_LOG $MD5_LOG
    70	  create_cache_archive $INST_LOG $CACHE $CACHE_COMP
    71	  add_spell "$SPELL" installed "$VERSION"
    72	  OLD_VERSION=$VERSION
    73	  (
    74	    [[ $SPELL != alter ]] && codex_set_current_spell_by_name $SPELL
    75	    add_version_cache "$VERSION_STATUS" "$SPELL" "$OLD_VERSION" "${PATCHLEVEL:-0}" "${SECURITY_PATCH:-0}" "${UPDATED:-0}"
    76	  )
    77	
    78	  rm $C_LOG
    79	  report_install
    80	  unlock_resources "cast" "$SPELL"
    81	
    82	  return 0
    83	
    84	}
    85	
    86	function alter_md5_mend() {
    87	
    88	  SINGLE=       #grab a single conflict only instead of all conflicts
    89	  STORE_BASE=${STORE_BASE:=/var/log/sorcery/tmp} # */tmp are often small
    90	                                  # by default for the backup
    91	  SPELL="$1"
    92	  VERSION="$(gaze -q installed "$SPELL")"
    93	
    94	  MD5S="$(
    95	    (
    96	      echo "$MASTER_MD5S" | grep -v " $SPELL-$VERSION$"
    97	      cat "$MD5SUM_LOGS/$SPELL-$VERSION" | cut -c35- | sed -e 's/.*/& -/'
    98	    )
    99	  )"
   100	
   101	  TOTAL=$(echo -n "$MD5S" | wc -l)
   102	  message "${MESSAGE_COLOR}Checking $TOTAL files for conflicts with ${SPELL_COLOR}$SPELL-$VERSION${DEFAULT_COLOR}${MESSAGE_COLOR}...${DEFAULT_COLOR}" > /dev/stderr
   103	  RESULTS="$(
   104	    echo -n "$MD5S" | sort -s -k1 | sed -e 's/\(.*\) \(.*\)/\2 \1/' |
   105	    (
   106	      FILE=
   107	      COUNT=0
   108	      while read LINE; do
   109	        if [ "${LINE:0:2}" == '- ' ]; then
   110	          FILE="${LINE:2}"
   111	        else
   112	          if [ "${LINE#* }" == "$FILE" ]; then
   113	            echo "$LINE"
   114	            [ -n "$SINGLE" ] && FILE=
   115	          fi
   116	        fi
   117	        [ "$((++COUNT))" != "${COUNT%%000}" ] && # increment and check for mod 1000
   118	        progress_bar $COUNT $TOTAL 60 > /dev/stderr
   119	      done
   120	      clear_line > /dev/stderr
   121	    ) | sort
   122	  )"
   123	
   124	  if [ -n "$RESULTS" ]; then
   125	    TOTAL="$(echo "$RESULTS" | wc -l)"
   126	    SPELLS="$(echo "$RESULTS" | cut -d' ' -f1 | sort -u)"
   127	    TOTSP="$(echo "$SPELLS" | wc -l)"
   128	    FILES="$(echo "$RESULTS" | cut -d' ' -f2 | sort -u)"
   129	    if [ "$ARCHIVE" != "off" ]; then
   130	      STORE=$STORE_BASE/$SPELL-$VERSION.$$
   131	      mkdir -p "$STORE"
   132	      mkdir -p "$STORE/tmp/sorcery"
   133	      message "${MESSAGE_COLOR}Cleaning $TOTAL old md5sums from $TOTSP spells and creating $SPELL-undo-$VERSION store.${DEFAULT_COLOR}" > /dev/stderr
   134	    else
   135	      message "${MESSAGE_COLOR}Cleaning $TOTAL old md5sums from $TOTSP spells.${DEFAULT_COLOR}" > /dev/stderr
   136	    fi
   137	    echo "$SPELLS" |
   138	    (
   139	      COUNT=0
   140	      while read SPVER; do
   141	        SPFLS="$(echo "$RESULTS" | grep "^$SPVER " | cut -d' ' -f2)"
   142	        echo "$SPFLS" |
   143	        sed -e 's/[^a-zA-Z0-9*.+]/\\&/g' |
   144	        sed -e 's/.*/\\:&: d/' |
   145	        sed -i -f - "$MD5SUM_LOGS/$SPVER"
   146	        if [ "$ARCHIVE" != "off" ]; then
   147	          local cache
   148	          find_cache "$INSTALL_CACHE/$SPVER-" cache
   149	          local compressor=$(guess_compressor "$cache")
   150	          if [[ $compressor == tar ]]; then
   151	            echo "$SPFLS" |
   152	              tar -f $cache \
   153	              -kx -T /dev/stdin -C "$STORE" 2> /dev/null
   154	          else
   155	            echo "$SPFLS" |
   156	              tar --use-compress-program $compressor -f $cache \
   157	              -kx -T /dev/stdin -C "$STORE" 2> /dev/null
   158	          fi
   159	        fi
   160	        progress_bar $((++COUNT)) $TOTSP 60 > /dev/stderr
   161	      done
   162	      clear_line > /dev/stderr
   163	    )
   164	    if [ "$ARCHIVE" != "off" ]; then
   165	      message "${MESSAGE_COLOR}Creating ${SPELL_COLOR}$SPELL-undo${DEFAULT_COLOR}${MESSAGE_COLOR} spell for ${SPELL_COLOR}$SPELL-$VERSION${DEFAULT_COLOR}${MESSAGE_COLOR}.${DEFAULT_COLOR}" > /dev/stderr
   166	      ORIGSPELL="$SPELL"
   167	      SPELL="$SPELL-undo"
   168	      cd "$STORE"
   169	      INST_LOG="$STORE.log"
   170	      mkdir -p "$STORE$MD5SUM_LOGS"
   171	      MD5S_LOG="$STORE$MD5SUM_LOGS/$SPELL-$VERSION"
   172	      touch "$MD5S_LOG"
   173	      echo -n "$RESULTS" > "$STORE/tmp/sorcery/$SPELL-$VERSION-backup.md5"
   174	      find * > "$INST_LOG"
   175	      create_md5list "$INST_LOG" "$MD5S_LOG" # relative to STORE instead of absolute
   176	      construct_cache_name "$INSTALL_CACHE/$SPELL-$VERSION-$HOST" CACHE
   177	      CACHE_COMP="${CACHE}${EXTENSION}"
   178	      # No install log nor compile cache needed or wanted since we are
   179	      # only doing md5sum deletions from other spells, the undeleted
   180	      # form should only restore the md5sums to the proper location.
   181	      create_cache_archive $INST_LOG $CACHE $CACHE_COMP
   182	      rm -rf "$STORE"
   183	    fi
   184	    return 1
   185	  else
   186	    message "${MESSAGE_COLOR}No md5sum conflicts with ${SPELL_COLOR}$SPELL-$VERSION${DEFAULT_COLOR}${MESSAGE_COLOR} detected.${DEFAULT_COLOR}" > /dev/stderr
   187	    return 0
   188	  fi
   189	
   190	}
   191	
   192	function alter_gather_md5s() {
   193	
   194	  [ -n "$MASTER_MD5S" ] && return 0
   195	
   196	  TOTAL=$(gaze installed | wc -l)
   197	
   198	  message "${MESSAGE_COLOR}Gathering md5sums from $TOTAL spells...${DEFAULT_COLOR}" > /dev/stderr
   199	  MASTER_MD5S="$(
   200	    (
   201	      COUNT=0
   202	      for i in $(
   203	        gaze installed |
   204	        cut -d: -f1,4 | tr : -
   205	      ); do
   206	        cat "$MD5SUM_LOGS/$i" | sed -e 's/.*/'"$i"':&/'
   207	        progress_bar $((++COUNT)) $TOTAL 60 > /dev/stderr
   208	      done | sed -e 's/\(.*\):\(.*\)  \(.*\)/\3 \1/'
   209	      clear_line > /dev/stderr
   210	    )
   211	  )"
   212	
   213	}
   214	
   215	function alter_md5mend() {
   216	
   217	  [ -z "$1" ] && echo "Please provide spells to mend as arguments" > /dev/stderr && return 1
   218	
   219	  alter_gather_md5s
   220	
   221	  for spell in $*; do
   222	    alter_md5_mend "$spell"
   223	  done
   224	  return 0
   225	
   226	}
   227	
   228	function alter_gather_bins() {
   229	
   230	  if [ ! -f "/etc/prelink.conf" ]; then
   231	    message "${MESSAGE_COLOR}Gathering binary directories for altering (this could take a long while)...${DEFAULT_COLOR}"
   232	    find / -perm -001 2> /dev/null |
   233	    while read LINE; do
   234	      [ ! -h "$LINE" ] && file $LINE 2> /dev/null |
   235	      grep -q ELF && echo "$LINE"
   236	    done |
   237	    grep -v '/src/\|/lib/modules\|/root/\|/home/' |
   238	    sed -e 's/[^/]*$//' | uniq |
   239	    sort -u > /etc/prelink.conf
   240	  fi
   241	
   242	}
   243	
   244	function alter_pre_link() {
   245	
   246	  ARGS="$@"
   247	
   248	  alter_gather_bins
   249	
   250	  alter_alter -n smgl-prelink '
   251	    /usr/sbin/prelink -v '"$ARGS"' | tee $TMP_DIR/prelink.$$.output
   252	    grep "Prelinking\\|Linking" $TMP_DIR/prelink.$$.output |cut -d" " -f2 |
   253	    sort -u |
   254	    while read PRELINKED; do
   255	       touch "$PRELINKED"
   256	    done
   257	    rm $TMP_DIR/prelink.$$.output
   258	  '
   259	
   260	}
   261	
   262	function alter_prelink {
   263	
   264	  if gaze -q installed prelink | grep -q 'not installed'; then
   265	    cast prelink || (
   266	      message "${MESSAGE_COLOR}Unable to statisfy prelink dependency, quitting.${DEFAULT_COLOR}"
   267	      return 1
   268	    )
   269	  fi
   270	
   271	  if [ -z "$1" ]; then
   272	    alter_pre_link -afmR
   273	  else
   274	    alter_pre_link "$@"
   275	  fi
   276	  alter_md5mend smgl-prelink
   277	
   278	}
   279	
   280	function alter_strip_all_do() {
   281	
   282	  ARGS="$@"
   283	
   284	  alter_gather_bins
   285	
   286	  alter_alter -n smgl-strip '
   287	    find $(cat /etc/prelink.conf) -perm -001 2> /dev/null |
   288	    while read LINE; do
   289	      [ ! -h "$LINE" ] && file $LINE 2> /dev/null |
   290	      grep -q ELF && echo "$LINE"
   291	    done |
   292	    while read STRIPFILE; do
   293	      cp "$STRIPFILE" $TMP_DIR/tostrip.$$
   294	      strip '"$ARGS"' $TMP_DIR/tostrip.$$
   295	      if [ "$(md5sum < $TMP_DIR/tostrip.$$)" == "$(md5sum < "$STRIPFILE")"    ]; then
   296	        echo "$STRIPFILE" already stripped, skipping.
   297	        rm $TMP_DIR/tostrip.$$
   298	      else
   299	        if [ "$(ldd $TMP_DIR/tostrip.$$ | md5sum)" == "$(ldd "$STRIPFILE"    | md5sum)" ]; then
   300	          echo "$STRIPFILE stripped and verified."
   301	          # uncomment the following to make backups before mving stripped bins
   302	          # mkdir -p "/var/log/sorcery/tmp/smgl-strip.$$/${STRIPFILE%/*}"
   303	          # cp "$STRIPFILE" "/var/log/sorcery/tmp/smgl-strip.$$/$STRIPFILE"
   304	          mv $TMP_DIR/tostrip.$$ "$STRIPFILE"
   305	        else
   306	          echo "$STRIPFILE corrupted by strip, skipping"
   307	          rm $TMP_DIR/tostrip.$$
   308	        fi
   309	      fi
   310	    done
   311	  '
   312	
   313	}
   314	
   315	function alter_strip_do() {
   316	
   317	  SPELL="$1"; shift
   318	  ARGS="$@"
   319	
   320	  if [ "${SPELL% *}" != "$SPELL" ]; then
   321	    NAME=smgl-strip
   322	    VERSION=$$
   323	  else
   324	    NAME="$SPELL"
   325	    VERSION="$(gaze -q installed "$NAME")"
   326	  fi
   327	
   328	  alter_alter -n "$NAME" -v "$VERSION" '
   329	    for sp in '"$SPELL"'; do gaze install "$sp"; done 2> /dev/null |
   330	    while read LINE; do
   331	      [ ! -h "$LINE" ] && file $LINE 2> /dev/null |
   332	      grep -q ELF && echo "$LINE"
   333	    done |
   334	    while read STRIPFILE; do
   335	      cp "$STRIPFILE" $TMP_DIR/tostrip.$$
   336	      strip '"$ARGS"' $TMP_DIR/tostrip.$$
   337	      if [ "$(md5sum < $TMP_DIR/tostrip.$$)" == "$(md5sum < "$STRIPFILE")"    ]; then
   338	        echo "$STRIPFILE" already stripped, skipping.
   339	        rm $TMP_DIR/tostrip.$$
   340	      else
   341	        if [ "$(ldd $TMP_DIR/tostrip.$$ | md5sum)" == "$(ldd "$STRIPFILE"    | md5sum)" ]; then
   342	          echo "$STRIPFILE stripped and verified."
   343	          # uncomment the following to make backups before mving stripped bins
   344	          # mkdir -p "/var/log/sorcery/tmp/smgl-strip.$$/${STRIPFILE%/*}"
   345	          # cp "$STRIPFILE" "/var/log/sorcery/tmp/smgl-strip.$$/$STRIPFILE"
   346	          mv $TMP_DIR/tostrip.$$ "$STRIPFILE"
   347	        else
   348	          echo "$STRIPFILE corrupted by strip, skipping"
   349	          rm $TMP_DIR/tostrip.$$
   350	        fi
   351	      fi
   352	    done
   353	  '
   354	
   355	}
   356	
   357	function alter_strip_all {
   358	
   359	  if [ -z "$1" ]; then
   360	    alter_strip_all_do
   361	  else
   362	    alter_strip_all_do "$@"
   363	  fi
   364	  alter_md5mend smgl-strip
   365	
   366	}
   367	
   368	function alter_strip {
   369	
   370	  if [ -z "$1" ]; then
   371	    alter_strip_do
   372	  else
   373	    alter_strip_do "$@"
   374	  fi
   375	  [ "$1" != "$NAME" ] && alter_md5mend "$NAME"
   376	
   377	}
   378	
   379	function alter_about() {
   380	
   381	cat <<EOF | less && exit 0
   382	alter: about: alter is a utility to modify and add to spells' installs.
   383	
   384	(C) 2004 Seth Alan Woolley and The Source Mage Team, initial release.
   385	LICENSE: GPL v2 or higher.
   386	
   387	Run alter without arguments to see a basic syntax guide.
   388	
   389	Alter has two main">main">main">main">main uses:
   390	
   391	"alter":
   392	    This is the basic use of alter.  Any command run on its command line
   393	will be run as if it was run at the end of the cast, inside the cast of
   394	the spell that is being altered.  By default, it operates on the spell
   395	"alter".  If the spell doesn't exist, it is "created".  This is useful
   396	for adding files to spells.  See md5mend to modify files in spells by
   397	replacing them with in an alter session.  When used together, with alter
   398	run first, then md5mend run second, you should end up with a rather
   399	clean system.  Running alter to touch a file, then md5mending, then
   400	dispelling the alter spell will remove a file from the sytem cleanly.
   401	In all, any modification of an installed spell couild be done while
   402	maintaining somewhat logical md5sum logs.
   403	
   404	"md5mend":
   405	    This is a secondary use of alter.  Any spells specified on its
   406	command line get analyzed in the order specified.  If "environmental"
   407	spells installed on the machine have conflicting md5 entries with the
   408	"analyzed" spell, md5mend will remove them from the environmental spells
   409	but keep them in the analyzed spell.  For example, if you run it on
   410	coreutils, psmisc and util-linux will have their /bin/kill purged from
   411	their md5sum records.  This however leaves them in the install logs of
   412	the environmental spells because they actually were installed by the
   413	spell.  The purpose is to enable a more intelligent cast --fix.  a
   414	forced dispel -d env_spell env_version will restore the environmental
   415	md5log and restore the binary from the environmental spell, so this is
   416	undoable piecemeal, or, you can use the shotgun undo cache created,
   417	however if more than three spells had the same file, it will use the
   418	version appearing in the environmental spell that is first in
   419	alphabetical order.
   420	
   421	Alter has three shortcut uses:
   422	
   423	"prelink", "strip-all", or "strip":
   424	    These are two commonly used alter shortcuts.  Prelinking optimizes
   425	the link space among all the binaries on the system.  Strip-all strips
   426	all the binaries on the system one by one, and confirms that they are
   427	sane before installing them.
   428	    The first time you run either prelink or strip, alter creates the
   429	/etc/prelink.conf file if you don't already have one.  This part can
   430	take up to an hour depending on processor speed and how full your disks
   431	are, or as little as five minutes.  The content of the file is merely a
   432	listing, one directory per line, of all the directories that contain
   433	binaries that should be touched by prelink or this version of strip.
   434	Feel free to ctrl-c this process and make it yourself if you are
   435	impatient. The script, however, is very thorough and accurate, so it's
   436	not a bad idea to simply let the script run its course.
   437	    Both prelink and strip take quite a while to run everything through
   438	because the md5mend process will essentially have to touch every archive
   439	and md5sum file on your system.  Be sure you have plenty of space
   440	available for the caches (if you have ARCHIVE=on).  1.5 times the
   441	installed uncompressed binary size (averages about 1-2 gigs on most
   442	installs, less for servers, more for desktops).
   443	    If you want to both strip and prelink, strip before you prelink
   444	seems to work better.
   445	    If you run prelink and get lots of -fPIC warnings, try upgrading
   446	some of the spells, if it doesn't work, file a bug and CC
   447	seth@tautology.org on it and he will add -fPIC to the CFLAGS of the spell
   448	(alternatively, do this yourself and append an attachment to the bug).
   449	zlib needs -DPIC -fPIC.  Prelinking doesn't like non-PIC'd binaries.  It
   450	won't hurt anything, it will just ignore them.
   451	    In my experience (Seth), stripping decreases file size, but doesn't
   452	increase the speed, and prelink makes the files slightly bigger
   453	(negligible), but decreases load time, often dramatically for C++ apps
   454	with many links (read: KDE).
   455	
   456	    For further study, RTFS or drop into the freenode #sourcemage
   457	channel and ask swoolley or the room for some urls or questions.
   458	
   459	FAQ:
   460	
   461	    Q: How do I prelink my whole system?
   462	    A: alter -p
   463	
   464	    Q: How do I strip debugging info from my whole system?
   465	    A: alter -z
   466	
   467	    Q: I recompiled some libraries, and it slowed down.
   468	    A: Recompiling makes prelinking pointless, rerun alter -p upon each update.
   469	
   470	    Q: How do I add a file /bin/file to a spell coreutils?
   471	    A: mv /tmp/file /bin/file; alter -n coreutils touch /bin/file
   472	
   473	    Q: How do I delete a file /bin/file from coreutils?
   474	    A: alter -n coreutils-removed touch /bin/file; alter -m coreutils-removed; dispel coreutils-removed
   475	
   476	    Q: How do I modify a file /bin/file from coreutils?
   477	    A: patch /bin/file < /tmp/file.patch; alter -n coreutils touch /bin/file
   478	
   479	    Q: How do I undo an alter?
   480	    A: There's no exact undo, but it's good enough if you've been using
   481	       only spells and alter:
   482	
   483	       # you did this but regretted it
   484	       alter -n alter-to-remove -v 31337 touch /bin/file # an alter
   485	       alter -m alter-to-remove              # md5mend it
   486	
   487	       # undo the above
   488	       dispel alter-to-remove                # do this step only if the files
   489	                                             # it touched aren't critical.  If
   490	                                             # they are, set REAP=no before.
   491	       dispel -d alter-to-remove-undo 31337  # to unpack the undo cache
   492	
   493	    Q: How do I prelink just one file and its dependents?
   494	    A: alter -p -fmR /bin/kill
   495	
   496	    Q: How do I prelink just one spell and its dependents?
   497	    A: alter -p -fmR \$(gaze install coreutils)
   498	
   499	    Q: How do I prelink two spells and their dependents?
   500	    A: alter -p -fmR \$(for sp in coreutils psmisc; do gaze install \$sp; done)
   501	
   502	    Q: How do I strip just one file?
   503	    A: alter -n smgl-strip strip /bin/kill
   504	
   505	    Q: How do I strip just one spell?
   506	    A: alter -s coreutils
   507	
   508	    Q: How do I strip two spells?
   509	    A: alter -s 'coreutils psmisc'
   510	
   511	EOF
   512	
   513	}
   514	
   515	function main">main">main">main">main() {
   516	
   517	  [ -z "$1" ] && cat <<EOF > /dev/stderr && exit 1
   518	alter: usage:
   519	  alter [ { -a | --alter   } ] # -a/--alter are ignored as this is default
   520	        [ { -n | --spell   } spell:=alter ]
   521	        [ { -v | --version } version:=<installed> ] command [ args  ... ]
   522	  alter   { -m | --md5mend        }     spell     [ spell ... ]
   523	  alter   { -p | --prelink        }     [ prelink_args:=-afmR ]
   524	  alter   { -z | --strip-all      } # shortcut to strip all binaries
   525	        [ strip_args:=        ]
   526	  alter   { -s | --strip          } # shortcut to strip binaries in spell(s)
   527	        spell_list                  # space-delimited list of spells as one arg
   528	        [ strip_args:=        ]
   529	  alter   { -h | --help | --about } # learn about alter and what it does
   530	
   531	  default environment variables:
   532	    STORE_BASE=/var/log/sorcery/tmp
   533	  To drastically save space, turn ARCHIVE=off in /etc/sorcery/local/config
   534	  To undo with ARCHIVE=on:
   535	    dispel -d <spell-name>-undo <spell-version>
   536	    alter -m <spell-name>-undo
   537	  NOTE:  Never directly dispel an alter with REAP=on unless
   538	  ****:  you want to delete everything the alter touched!
   539	  ****:  Use the undo archives as they have no install log.
   540	EOF
   541	
   542	  case "$1" in
   543	    -m|--md5mend              ) shift; alter_md5mend   "$@" ;;
   544	    -p|--prelink              ) shift; alter_prelink   "$@" ;;
   545	    -s|--strip                ) shift; alter_strip     "$@" ;;
   546	    -z|--strip-all            ) shift; alter_strip_all "$@" ;;
   547	    -a|--alter                ) shift; alter_alter     "$@" ;;
   548	    -h|--about|--help         ) shift; alter_about     "$@" ;;
   549	    -n|--spell|-v|--version|* )        alter_alter     "$@" ;;
   550	  esac
   551	
   552	}
   553	
   554	function verify_parameters()
   555	{
   556	  while [[ $# -gt 0 ]]; do
   557	    case "$1" in
   558	      -m|--md5mend|-p|--prelink) true ;;
   559	      -s|--strip|-z|--strip-all) true ;;
   560	                     -a|--alter) true ;;
   561	        -n|--spell|-v|--version) true ;;
   562	                             -*) main">main">main">main">main ;;
   563	                              *) true ;;
   564	    esac
   565	    shift
   566	  done
   567	}
   568	
   569	#include sorcery configuration (and thus subroutines)
   570	. /etc/sorcery/config
   571	
   572	#check if root. If not, become root
   573	if    [  "$UID"  ==  0  ] ; then
   574	  if  [[  $NICE != "0"  ]] ; then
   575	    renice $NICE -p $$  >/dev/null
   576	  fi
   577	
   578	  mk_tmp_dirs alter
   579	  main">main">main">main">main  "$@"
   580	  rc=$?
   581	  cleanup_tmp_dir $TMP_DIR
   582	  exit $rc
   583	elif  [[  "$1" == -h       ]]  ||
   584	      [[  "$1" == --about  ]]  ||
   585	      [[  "$1" == --help   ]]  ||
   586	      [[       -z "$1"     ]]; then
   587	  main">main">main">main">main "$1"
   588	else
   589	  # validate the parameters before su-ing, since we may still drop out
   590	  verify_parameters "$@"
   591	
   592	  echo  "Enter the root password, please."  1>&2
   593	  PARAMS=$(consolidate_params "$@")
   594	  exec su -c "alter $PARAMS" root
   595	fi
   596	
   597	
   598	#---------------------------------------------------------------------
   599	##=back
   600	##
   601	##=head1 LICENSE
   602	##
   603	## This software is free software; you can redistribute it and/or modify
   604	## it under the terms of the GNU General Public License as published by
   605	## the Free Software Foundation; either version 2 of the License, or
   606	## (at your option) any later version.
   607	##
   608	## This software is distributed in the hope that it will be useful,
   609	## but WITHOUT ANY WARRANTY; without even the implied warranty of
   610	## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   611	## GNU General Public License for more details.
   612	##
   613	## You should have received a copy of the GNU General Public License
   614	## along with this software; if not, write to the Free Software
   615	## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   616	##
   617	#---------------------------------------------------------------------