#!/bin/sh
# Copyright 1994, 1998, 2000  Patrick Volkerding, Concord, CA, USA 
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
#  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
#  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
#  EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
#  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
#  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
#  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
#  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Sun Nov 26 12:38:25 CST 1995
# Added patch from Glenn Moloney <glenn@physics.unimelb.edu.au> to allow
# packages to be installed to directories other than /.
#
# Wed Mar 18 15:15:51 CST 1998
# Changed $TMP directory to /var/log/setup/tmp, and chmod'ed it 700 to close
# some security holes.

# If installpkg encounters a problem, it will return a non-zero error code.
# If it finds more than one problem (i.e. with a list of packages) you'll only
# hear about the most recent one. :)
# 1 = tar returned error code
# 2 = failed 'gzip -l package'
# 3 = does not end in .tgz
# 4 = not a file
EXITSTATUS=0

usage() {
 cat << EOF
Usage: installpkg [options] package_name

Installpkg is used to install a .tgz package like this:
   installpkg xf_bin.tgz

options:      -warn (warn if files will be overwritten, but do not install)
              -root /mnt (install someplace else, like /mnt)
              -infobox (use dialog to draw an info box)
              -menu (confirm package installation with a menu, unless
                    the priority is [required] or ADD)
              -priority ADD|REC|OPT|SKP  (provide a priority for the entire
                    package list to use instead of the priority in the
                    tagfile)
              -tagfile /somedir/tagfile (specify a different file to use
                    for package priorities.  The default is "tagfile" in
                    the package's directory)

EOF
}

# Make sure there's a proper temp directory:
TMP=/var/log/setup/tmp
# If the $TMP directory doesn't exist, create it:
if [ ! -d $TMP ]; then
  rm -rf $TMP # make sure it's not a symlink or something stupid
  mkdir $TMP
  chmod 700 $TMP # no need to leave it open
fi

# Parse options:
MODE=install # standard text-mode
while [ 0 ]; do
  if [ "$1" = "-warn" ]; then
    MODE=warn
    shift 1
  elif [ "$1" = "-infobox" ]; then
    MODE=infobox
    shift 1
  elif [ "$1" = "-menu" ]; then
    MODE=menu
    shift 1
  elif [ "$1" = "-tagfile" ]; then
    if [ -r "$2" ]; then
      USERTAGFILE="$2"
    elif [ -r "`pwd`/$2" ]; then
      USERTAGFILE="`pwd`/$2"
    else
      usage
      exit
    fi
    shift 2
  elif [ "$1" = "-priority" ]; then
    if [ "$2" = "" ]; then
      usage
      exit
    fi
    USERPRIORITY="$2"
    shift 2
  elif [ "$1" = "-root" ]; then
    if [ "$2" = "" ]; then
      usage
      exit
    fi
    ROOT="$2"
    shift 2
  else
    break
  fi
done

# usage(), exit if called with no agruments:
if [ $# = 0 ]; then
  usage;
  exit
fi

# If -warn mode was requested, produce the output and then exit:
if [ "$MODE" = "warn" ]; then
  while [ -f "$1" ]; do
    echo "#### Scanning the contents of $1..."
    mkdir -p $TMP/scan
    ( cd $TMP/scan ; tar xzf - install/doinst.sh ) < $1 2> /dev/null 
    if [ -r $TMP/scan/install/doinst.sh ]; then
      if cat $TMP/scan/install/doinst.sh | fgrep ' rm -rf ' 1>/dev/null 2>/dev/null ; then
        cat $TMP/scan/install/doinst.sh | fgrep ' rm -rf ' > $TMP/scan/install/delete
        echo "The following locations will be completely WIPED OUT to allow symbolic"
        echo "links to be made. (We're talking 'rm -rf') These locations may be files,"
        echo "or entire directories.  Be sure you've backed up anything at these"
        echo "locations that you want to save before you install this package:"
        cat $TMP/scan/install/delete | cut -f 3,7 -d ' ' | tr ' ' '/'
      fi
      if [ -d $TMP/scan ]; then
        ( cd $TMP/scan ; rm -rf install ) 2> /dev/null
        ( cd $TMP ; rmdir scan ) 2> /dev/null
      fi
    fi
    echo "The following files will be overwritten when installing this package."
    echo "Be sure they aren't important before you install this package:"
    ( tar tzvvf - ) < $1 | fgrep -v 'drwx'
    echo
    shift 1
  done
  exit
fi

# Main loop:
for package in $* ; do

  # If someone left off the .tgz, try to figure that out:
  if [ ! -e "$package" -a -e "$package.tgz" ]; then
    package=$package.tgz
  fi

  shortname=`basename $package .tgz`
  packagedir="`dirname $package`"
  ADM_DIR="$ROOT/var/log"

  # Reject package if it does not end in '.tgz':
  if [ ! -e "`dirname $package`/$shortname.tgz" ]; then
    EXITSTATUS=3
    if [ "$MODE" = "install" ]; then
      echo "Cannot install $package: package does not end in .tgz"
    fi
    continue;
  fi

  # Determine package's priority:
  unset PRIORITY
  if [ "$USERPRIORITY" = "" ]; then
    if [ "$USERTAGFILE" = "" ]; then
      TAGFILE="`dirname $package`/tagfile"   
    else
      TAGFILE="$USERTAGFILE"
    fi
    if [ ! -r "$TAGFILE" ]; then
      TAGFILE=/dev/null
    fi
    if fgrep "$shortname:" "$TAGFILE" | fgrep ADD > /dev/null 2> /dev/null ; then
      PRIORITY="ADD"
    elif fgrep "$shortname:" "$TAGFILE" | fgrep REC > /dev/null 2> /dev/null ; then
      PRIORITY="REC"
    elif fgrep "$shortname:" "$TAGFILE" | fgrep OPT > /dev/null 2> /dev/null ; then
      PRIORITY="OPT"
    elif fgrep "$shortname:" "$TAGFILE" | fgrep SKP > /dev/null 2> /dev/null ; then
      PRIORITY="SKP"
    fi
  else
    PRIORITY="$USERPRIORITY"
  fi
  if [ "$PRIORITY" = "ADD" ]; then
    PMSG="Priority: [required]"
  elif [ "$PRIORITY" = "REC" ]; then
    PMSG="Priority: [recommended]"
  elif [ "$PRIORITY" = "OPT" ]; then
    PMSG="Priority: [optional]"
  elif [ "$PRIORITY" = "SKP" ]; then
    PMSG="Priority: [skip]"
  else
    PMSG="Priority: [unknown]"
  fi

  # Locate package description file:
  DESCRIPTION="/dev/null"
  for file in $packagedir/package_descriptions $packagedir/disk* ; do
    if fgrep "$shortname:" "$file" 1> /dev/null 2> /dev/null ; then
      DESCRIPTION="$file"
    fi
  done

  # Simple package integrity check:
  if [ ! -f $package ]; then
    EXITSTATUS=4
    if [ "$MODE" = "install" ]; then
      echo "Cannot install $package: package is not a regular file"
    fi
    continue;
  fi
  gzip -l $package 1> /dev/null 2> /dev/null
  if [ ! "$?" = "0" ]; then
    EXITSTATUS=2 # failed gzip -l
    if [ "$MODE" = "install" ]; then
      echo "Cannot install $package: package is corrupt (failed 'gzip -l $package')"
    fi
    continue;
  fi

  # Collect the package information into a temp file:
  COMPRESSED=`gzip -l $package | fgrep -v uncompressed_name | cut -b0-9`
  UNCOMPRESSED=`gzip -l $package | fgrep -v uncompressed_name | cut -b10-19`
  COMPRESSED="`expr $COMPRESSED / 1024` K"
  UNCOMPRESSED="`expr $UNCOMPRESSED / 1024` K"
  MD5SUM=`md5sum $package | cut -f 1 -d ' '`
  echo > $TMP/tmpmsg
  cat $DESCRIPTION | fgrep "$shortname:" | cut -f 2- -d : | cut -b2- 1>> $TMP/tmpmsg 2> /dev/null
  echo "Size: Compressed: $COMPRESSED, uncompressed: $UNCOMPRESSED." >> $TMP/tmpmsg

  # Emit information to the console:
  if [ "$MODE" = "install" ]; then
    echo "Installing package $package ($PMSG)... "
    echo "PACKAGE DESCRIPTION:"
    cat $DESCRIPTION | fgrep "$shortname:" | uniq
  elif [ "$MODE" = "infobox" ]; then
    dialog --title "Auto-installing package ==>$shortname<==  $PMSG" --infobox "`cat $TMP/tmpmsg`" 15 75
  elif [ "$MODE" = "menu" -a "$PRIORITY" = "ADD" ]; then # ADD overrides menu mode
    dialog --title "Auto-installing package ==>$shortname<==  $PMSG" --infobox "`cat $TMP/tmpmsg`" 15 75
  elif [ "$MODE" = "menu" -a "$PRIORITY" = "SKP" ]; then # SKP overrides menu mode
    continue # next package
  else # we must need a full menu:
    dialog --title "Package Name: ==>$shortname<==  $PMSG" --menu "`cat $TMP/tmpmsg`" 22 75 3 \
    "Yes" "Install package $shortname" \
    "No" "Do not install package $shortname" \
    "Quit" "Abort software installation completely" 2> $TMP/reply
    if [ $? = 1 -o $? = 255 ]; then
      echo "No" > $TMP/reply
    fi
    REPLY="`cat $TMP/reply`"
    if [ "$REPLY" = "Yes" ]; then
      dialog --title "Installing package ==>$shortname<==  $PMSG" --infobox "`cat $TMP/tmpmsg`" 15 75
    elif [ "$REPLY" = "Quit" ]; then
      rm -f $TMP/reply $TMP/tmpmsg
      exit 99 # EXIT STATUS 99 = ABORT!
    else
      dialog --title "SKIPPING PACKAGE" --infobox "Skipping package $shortname" 3 50
      continue
    fi
  fi

  # Test tarball integrity, and make sure we're not installing files on top of existing symbolic links:
  tar tzf $package 1> $TMP/tmplist 2> /dev/null
  TARERROR=$?
  if [ ! "$TARERROR" = "0" ]; then
    EXITSTATUS=1 # tar file corrupt
    if [ "$MODE" = "install" ]; then
      echo "Unable to install $package: tar archive is corrupt (tar returned error code $TARERROR)"
    fi
    rm -f $TMP/tmplist
    continue
  fi
  cat $TMP/tmplist | grep -v "/$" | while read file ; do
    if [ -L "$ROOT/$file" ]; then
      rm -f "$ROOT/$file"
    fi
  done
  rm -f $TMP/tmplist

  # Write the package file database entry and install the package:
  echo "PACKAGE NAME:     $shortname" > $ROOT/var/log/packages/$shortname
  echo "COMPRESSED PACKAGE SIZE:     $COMPRESSED" >> $ROOT/var/log/packages/$shortname
  echo "UNCOMPRESSED PACKAGE SIZE:     $UNCOMPRESSED" >> $ROOT/var/log/packages/$shortname
  echo "PACKAGE LOCATION: $package" >> $ROOT/var/log/packages/$shortname
  echo "PACKAGE MD5SUM: $MD5SUM" >> $ROOT/var/log/packages/$shortname
  echo "PACKAGE DESCRIPTION:" >> $ROOT/var/log/packages/$shortname
  cat $DESCRIPTION | fgrep "$shortname:" >> $ROOT/var/log/packages/$shortname 2> /dev/null
  echo "FILE LIST:" >> $ROOT/var/log/packages/$shortname
  ( cd $ROOT/ ; tar -xzlUpvf - ) < $package >> $ROOT/var/log/packages/$shortname 2> /dev/null
  if [ -x /sbin/ldconfig ]; then
    /sbin/ldconfig
  fi
  if [ -f $ROOT/install/doinst.sh ]; then
    if [ "$MODE" = "install" ]; then
      echo "Executing install script for $package..."
    fi
    ( cd $ROOT/ ; sh install/doinst.sh -install; )
  fi 
  # Clean up the mess...
  if [ -d $ROOT/install ]; then
    cp $ROOT/install/doinst.sh $ROOT/var/log/scripts/$shortname
    chmod 755 $ROOT/var/log/scripts/$shortname
    ( cd $ROOT/install ; rm -r -f doin* 1> /dev/null 2>&1 )
    rmdir $ROOT/install 1> /dev/null 2>&1
  fi
  if [ "$MODE" = "install" ]; then
    echo
  fi
  rm -f $TMP/tmpmsg $TMP/reply
done

exit $EXITSTATUS
