#!/bin/sh
# mkswlinks - create links under /usr/local for a software package

PATH=/bin:/usr/bin
export PATH

display_usage() {
  /bin/cat << 'usage_eof'

    Usage:
      mkswlinks [options] <package_name>
    Options:
      -h		get help
      -dest <dir>	link under <dir> instead of /usr/local
      -src <dir>	package is in <dir> rather than /sw
      -n		don't really install, just print actions
      -y		pre-answer all questions "yes"
      -q		quiet mode (don't print READMEs, etc.)
    Examples:
      mkswlinks mh-6.8.3
      mkswlinks -n tk-4.0
      mkswlinks -y -dest /usr/testing elm-2.4
usage_eof
}

display_help() {
  display_usage
  /bin/cat << 'help_eof'
  There must be a directory /sw/<package_name>.  For any well-known
  subdirectory names under <package_name> (such as bin, sbin, lib,
  etc.), that subdirectory's _contents_ will be symlinked to the
  corresponding subdirectory under /usr/local.  (For instance,
  /sw/mh-6.8.3/bin/inc would be symlinked to /usr/local/bin/inc.) Note
  that typically the contents of a packages lib directory should be
  another subdirectory, so that for instance /sw/mh-6.8.3/lib/mh-6.8.3
  will be symlinked to /usr/local/lib/mh-6.8.3 .  (man and catman
  directories are treated specially, to Do The Right Thing(TM).)

  Subdirectories under /usr/local are created as needed.

  Non-well-known subdirectories are an error, and probably mean that
  this script needs to be updated.

  If a file "link.sh" exists, it will be executed instead to create the
  links.

  If a file "install.sh" exists, the user will be given the option to
  execute it _in addition to_ making the symlinks.  This would
  typically be used to copy some of the files to local disk, e.g.  so
  there can be a copy of tcsh in /bin .

help_eof
}

error() {
  echo $* 1>&2
}

die() {
  error $*
  exit 1
}

process_args() {
  original_args="$@"			# to pass to children (UNUSED)
  really=''				# 'echo' if just testing
  help=0				# 1 -> just display (long) help
  yes=0					# 1 -> noninteractive (go ahead)
  quiet=0				# 1 -> don't cat files
  package=''				# name of package (directory)
  destdir='/usr/local'			# where to install the links
  srcbase='/sw'		# where the package directory is
  
  arg=$1
  
  if [ $# != "0" ] ; then
    while ( [ -n "$arg" ] )
    do
      case "$arg"
      in
      -h*)		help=1;
  			;;
      -dest*)		destdir=$2;
      			shift;
      			;;
      -src*)		srcbase=$2;
      			shift;
      			;;
      -n*)		really=echo;
  			;;
      -y*)		yes=1;
  			;;
      -q*)		quiet=1;
  			;;
      /*)		srcbase=`dirname $arg`;
      			package=`basename $arg`;
  			;;
      *)		package=$arg;
  			;;
      esac
      shift
      arg=$1
    done
  fi
  
  if [ $help = 1 ]
  then
    display_help
    exit 0
  fi
  
  if [ -z "$package" ]
  then
  echo $package
    display_usage
    exit 1
  fi
  
  srcdir=$srcbase/$package
}

show_file() {
  # DEPENDENCIES: quiet, package
  if [ "$quiet" = "0" ]
  then
    echo " "
    echo "$1 for ${package}:"
    sed "s/^/  /" $1
    echo " "
  fi
}

maybe_create_directory() {
  # DEPENDENCIES: really
  if [ ! -d $1 ]
  then
    $really mkdir -p $1 || die "Unable to create directory \"$1\"."
  fi
}

delete_if_symlink() {			# NOT YET USED
  # DEPENDENCIES: really
  if test -L $1				# builtin works in bash, not in sh
  then
    $really rm $1
  fi
}

link_normal_directory() {
  lnd_dirname=$1
  # DEPENDENCIES: srcdir, destdir, really
  maybe_create_directory $destdir/$lnd_dirname
  for lnd_subfile in $srcdir/$lnd_dirname/*
  do
    lnd_name=`basename $lnd_subfile`
    lnd_destpath=$destdir/$lnd_dirname/$lnd_name
    delete_if_symlink $lnd_destpath
    $really ln -fs $lnd_subfile $lnd_destpath
  done
}

link_doc_directory() {
  # NOTE: $1 is ignored (it should always be "doc")
  # DEPENDENCIES: srcdir, destdir, really, package
  maybe_create_directory $destdir/doc
  delete_if_symlink $destdir/doc/$package
  $really ln -fs $srcdir/doc $destdir/doc/$package
}

link_man_directory() {
  # DEPENDENCIES: srcdir, destdir, really
  for lnd_subdir in $1/*
  do
    link_normal_directory $lnd_subdir
  done
}

link_app_defaults_directory() {
  maybe_create_directory $destdir/lib/X11/app-defaults
  for lnd_subfile in $srcdir/$1/*
  do
    $really ln -fs $lnd_subfile $destdir/lib/X11/app-defaults
  done
}

link_info_directory() {
  error "CAN'T DO INFO DIRECTORIES YET!"
}

######################################################################

process_args $1 $2 $3 $4 $5 $6 $7 $8 $9

######################################################################

if [ ! -d $srcdir ]
then
  error "No package called $package in /sw - can't install."
  exit 1
fi

cd $srcdir

# display the package README if there is one:
[ "$quiet" != "1" -a -r README ] && show_file README

# see if they still want to make links
if [ "$yes" != "1" ]
then
  echo "Install links for this package? (y|n)"
  read yn
else
  yn=y
fi

case "$yn"
in
n*)  		exit 0;
		;;
*)		;;
esac

# see if there's a special link.sh file to do instead of default actions:
if [ -r link.sh ]
then
  [ "$quiet" != "1" -a -r link.README ] && show_file link.README
  if [ "$yes" != "1" ]
  then
    echo "Execute this link.sh file? (y|n)"
    read yn
  else
    yn=y
  fi
  
  case "$yn"
  in
  y*)		$really sh link.sh;
  		exit 0;
  		;;
  *)		echo "No links made.";
  		exit 0;
  		;;
  esac
fi

# default behaviour: process each of the directories in the package:
for file in *
do
  case "$file" in
  README|link.*|install.*|BUILD*)
  			;;
  man|catman)
  			link_man_directory $file
  			;;
  bin|sbin|lib|libexec|include|etc)
  			link_normal_directory $file
  			;;
  doc)
  			link_doc_directory $file
  			;;
  app-defaults)
  			link_app_defaults_directory $file
  			;;
  info)
  			error "######################################";
  			error "# Can't handle info directories yet! #";
  			error "######################################";
  			;;
  root)
  			echo "This package contains files that must be ";
  			echo "installed to local disk.  To do so, you ";
  			echo "must let this program run the package's ";
  			echo "install.sh script."
  			;;
  *)
  			error "I don't know what to do with \"$file\"!"
  			;;
  esac
done

# see if there's a special install.sh script to run at the end:
if [ -r install.sh ]
then
  [ "$quiet" != "1" -a -r install.README ] && show_file install.README
  if [ "$yes" != "1" ]
  then
    echo "Execute this install.sh file? (y|n)"
    read yn
  else
    yn=y
  fi
  
  case "$yn"
  in
  y*)		$really sh install.sh;
  		;;
  *)		echo "OK, install.sh not run.";
  		;;
  esac
fi

exit 0