info()
{ echo "This is an installation tool for gnu software on UNIX/LINUX Systems.
When invoked first time, make sure your computer is online to the internet.
Additional calls try to avoid download *.tar.gz files again, in order
to save time & money. 
Use this script on your own risk. There is NO warranty.

-------------- Scope of installation:
 LU: User installs into his local home dir  --> install.gnu product
 LR: Root installs machine wide             --> install.gnu product
 AU: User installs into his AFS home dir    --> install.gnu product
 AR: Root installs machine wide             --> install.gnu product
 AA: AFS admin installs site wide           --> install.gnu -A product

-------I----------I------------------------I-----------I-----------------------
 File  I   who    I                        I           I    Architecture
System I installs I LINK=                  I BINARY=   I     Dependence        
-------I----------I------------------------I-----------I-----------------------
       I          I                        I           I
       I   user   I ~/bin/product          I ~/.gnu    I
       I   (LU)   I                        I           I
 Local I----------I------------------------I-----------I-----------------------
       I          I                        I           I
       I   root   I /usr/local/bin/product I /usr/gnu  I
       I   (LR)   I                        I           I
-------I----------I------------------------I-----------I-----------------------
       I          I                        I           I ~/.gnu -> ~/.gnu.@sys
       I   user   I ~/bin/product          I ~/.gnu    I mkdir ~/.gnu.`sys`
       I   (AU)   I                        I           I
       I----------I------------------------I-----------I-----------------------
       I          I                        I           I
  AFS  I   root   I /usr/sue/bin/product   I /usr/gnu  I
       I   (AR)   I                        I           I
       I----------I------------------------I-----------I-----------------------
       I   AFS    I                        I           I architecture dependent
       I   admin  I /usr/local/bin/product I /afs/...  I link (see AU), not yet
       I   (AA)   I                        I           I implemented
-------I----------I------------------------I-----------I-----------------------

-------------- Known limitations, problems:
 - AFS systems: Machine wide installations doesn't work due to write
   permission problems, but home-dir wide works transparently for various
   platforms as well as machine wide installations for non AFS systems.
   Tested platforms: Linux, SunOS, HP-UX, AIX, IRIX
 - Garbled *.tar.gz files may be produced by erroneous downloads (aborting
   etc.). To recover from garbled files use the -f switch and try again.
   This forces fresh download of *.tar.gz files.
 - Checking prerequisits uncomplete, unsafe ..
 - Verbosity mode TBD (switch '-V 0' not working as expected)
 - Writing to log file yet uncomplete

Author: Ernst-Ludwig Bohnen, E-Mail: Ernst-Ludwig.Bohnen@desy.de"
exit 1 ; }

wr()
{ if [ $VERBOSITY -gt 0 ]; then echo "INFO: $1"; fi;
  echo "INFO: $1" >> ${LOG}; }

usage()
{ echo "usage:
install.gnu [ switches_in_any_order ]
 -f                  = forces new download of *.tar.gz files
 -n                  = prevent final installation (download only)
 -V  0|1|2           = verbosity level (0:silent, 1,2: more verbose)
 --verbose           = same as -V
 -ftp                = select ftp for downloading, default: wget
 -gb gnu_base        = URL base, default: ${GNU_BSE}
 -ck                 = check prerequisites
 -h | --help         = help, this text
 -m                  = print some more info
 -lp                 = list products available
 -lv product         = list versions of product available
 -i  product version = install product"
 echo "Logfile: ${LOG}"
 if [ -n "$1" ]; then echo; echo "$1" ; fi
 exit 2  ; }

check()
{ if [ $1 != 0 ]
  then wr "ERROR, Returncode after $2 is $1"; exit 1; fi; }

which_all()    # which_all ${PATH} "cmnd1 cmnd2 ..."
{ for c in $1  # writes a list of installed commands
  do
    N=0
    FL=''
    for d in `echo $2 | tr ':' ' '`
    do
      if [ -x ${d}/${c} ]
      then (( N=${N}+1 )) ; FL="${FL} ${d}/${c}"
      fi
    done
    echo "${N} $c --> ${FL}"
  done ; }

run()
{ wr "$1"
  case ${VERBOSITY} in
    0) $1 >> ${LOG} 2>&1 ; check $? "$1" ;; # silent (batch mode)
    1) $1 >> ${LOG} ;      check $? "$1" ;;
    2) $1 ;                check $? "$1" ;;
   esac ; }

dl()                  # Download: dl URL my_file_name
{ wr "Downloading $2"
  case ${DOWNLOAD} in
   WGET)case ${VERBOSITY} in
          0) wget "${OUTPUTFILE}" -O $2 $1 >> ${LOG} 2>&1 ; check $? wget ;;
          1) wget "${OUTPUTFILE}" -O $2 $1 >> ${LOG} ;      check $? wget ;;
          2) wget "${OUTPUTFILE}" -O $2 $1 ;                check $? wget ;;
         esac ;;
    FTP) run "ftp $1" ;;
      *) usage "Unknown down load method: ${DOWNLOAD}" ;;
   esac ; }

load_files()          # Load a list of ALL available files
{ if [ ! -f ${FILES} -o ${FORCE_DOWNLOAD} = true ]
    then
      dl "${GNU_BSE}/FILES.bytime.gz" "${FILES}.gz"
      if [ -f ${FILES} ]; then rm ${FILES} ; fi
      gunzip ${FILES}.gz >> ${LOG}; check $? "gunzip ${FILES}.gz"
    fi ; }

list_products()
{ cp /dev/null ${LOG}                                      # init log file
  load_files
    expand ${FILES} | cut -c23- | grep -v "^Manuals/" | grep ".tar.gz$" |\
      tr "/" "\012" | grep -v "tar.gz$" | sort -u
}

list_versions()
{ wr "Looking for existing versions:"
  load_files
  # grep "/${PGM}/${PGM}-" ${FILES} | grep '.tar.gz' | cut -c23-
  cat ${FILES} | tr "/" "\012" | grep '.tar.gz$' | grep "^${PGM}-" | sort |\
  while read W
    do
      echo ${W%.tar.gz}
    done ; }

install_program()
{
SRC="${TMP_BSE}/install.${PGM}.${SYSTEM}"                # Tmp for downloads
PGM_VER="${PGM}-${VER}"                                  # Exammple: sed-3.02
URL="${GNU_BSE}/${PGM}/${PGM_VER}.tar.gz"
OUTPUTFILE=''

case ${INSTALLER} in                                     # installation scope
 LU) LINK=${HOME}/bin/${PGM};    BINARY=${HOME}/.gnu ;;  # Users local home
 LR) LINK=/usr/local/bin/${PGM}; BINARY=/usr/gnu ;;      # Host wide
 AU) LINK=${HOME}/bin/${PGM};    BINARY=${HOME}/.gnu ;;  # Users AFS home dir
 AR) LINK=/usr/sue/bin/${PGM};   BINARY=/usr/gnu ;;      # Host wide
 AA) LINK=/usr/local/bin/${PGM}; BINARY=/afs/products/gnu #AFS adm site wide
     echo "AFS site wide installation not implemented"; exit 98 ;;
  *) echo "Fatal Error"; exit 99 ;;
 esac

if [ ! -d ${SRC} ] ; then mkdir ${SRC} ; fi  # New dir if necessary
cp /dev/null ${LOG}                          # Init log file

# ----------- show info -------------------------------------------------------
load_files                                   # Get a list of gnu products
cd ${SRC}; check $? "cd ${SRC}"              # be very sure cd is ok!!

# ----------- Clean temp files and download -----------------------------------
if [ ${FORCE_DOWNLOAD} = true ]
  then rm -rf *                              # remove everything
  else                                       # rm all but gz files
    for f in `ls | grep -v ${PGM_VER}.tar.gz`
    do wr "Removing: $f"; rm -f -r $f ; check $? "rm $f" ; done
  fi

if [ ! -f ${PGM_VER}.tar.gz ]                # check if PGM exists
  then dl "${URL}" "${PGM_VER}.tar.gz"
  else wr "Use existing ${PGM_VER}.tar.gz"
  fi

# ----------- Installation ----------------------------------------------------
wr "Creating ${PGM_VER}"
gzip -c -d ${PGM_VER}.tar.gz | tar -xvf - >> ${LOG} # unzip & untar
check $? "Creating ${PGM_VER}"

run   "cd ${PGM_VER}"
run   "./configure --prefix=${BINARY}"
run   "make"
run   "make install"

# ----------- make a link to executable ---------------------------------------
if [ -L ${LINK} ]; then rm ${LINK}; fi # make executable visable
ln -s ${BINARY}/bin/${PGM} ${LINK}     # create a new link
wr "Installation of ${PGM} version ${VER} done"      ; }
# -------------------- END OF FUNCTION DEFS -----------------------------------

# ----- MAIN PROGRAM (Set default values) -------------------------------------
GNU_BSE="ftp://ftp.informatik.rwth-aachen.de/pub/gnu" # Nearest GNU server
VERBOSITY=1                                           # verbosity
OUTPUTFILE=''                                         # wget talks 
FORCE_DOWNLOAD=false                                  # try reusing ../tar.gz
SYSTEM=`uname`                                        # System ident
DOWNLOAD=WGET
TMP_BSE="/tmp/${USER}"                                # Prevent conflicts
if [ ! -d ${TMP_BSE} ]; then mkdir ${TMP_BSE} ; fi    # New dir if necessary
FILES=${TMP_BSE}/FILES.bytime                         # reused for other products
LOG="${TMP_BSE}/log.gnu"

if [ -d /afs ]                    # may not be a good indicator for AFS
  then INSTALLER="A" ; SYS=`sys`  # AFS is installed, get system architecture
  else INSTALLER="L"              # Local filesystem
  fi
if [ "$USER" = "root" ]
  then INSTALLER="${INSTALLER}R"  # Root
  else INSTALLER="${INSTALLER}U"  # User
  fi

# ----- Read command line switches, may overwrite defaults --------------------
if [ $# = 0 ]; then usage; fi
while [ $# -gt 0 ]
do
  SWITCH=$1                       # remember current switch (may be shifted)
  case $1 in
   -f) FORCE_DOWNLOAD=true ;;     # force a fresh download
   -n) ESCAPE=exit ;;             # NO final installation
   -V|--verbose)
       shift
       case $1 in
          0) OUTPUTFILE='-o /dev/null';; # be silent (batch)
        1|2) OUTPUTFILE='';;             # see download process
          *) usage "Unknown verbosity level $1" ;;
         esac
       VERBOSITY=$1 ;;
 -ftp) DOWNLOAD=FTP;;
  -gb) shift; GNU_BSE=$1 ;;              # take an other ftp server
  -ck) which_all "make gmake grep sed wget ftp gzip gunzip tar" ${PATH};;
   -h|--help) usage ;;
   -m) info ;;
  -lp) list_products ;;                  # list products
  -lv) shift
       case $# in
         1) PGM=$1 ; list_versions ;;    # list versions
         *) usage "${SWITCH} needs one product name" ;;
         esac ;;
   -i) shift;                            # install program version
       case $# in
         2) PGM=$1 ; shift; VER=$1; install_program ;;
       # 2) PGM=$1 ; shift; VER=$1; echo "install_program $PGM $VER";;
         *) usage "Switch ${SWITCH} needs product & version" ;;
         esac ;;
    *) usage "Unknown switch ${SWITCH}"
  esac
  if [ $# = 0 ]; then usage "Missing parameter after switch ${SWITCH}"; fi
  shift
done
