#! /bin/bash
# create_prepsdb -- Create a new PRepS database
# Copyright (c) 1999-2001 Kenneth W. Sodemann (stufflehead@bigfoot.com)
#
# $Id: create_prepsdb.in,v 1.20 2001/08/26 18:45:14 stuffle Exp $
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to 
# Free Software Foundation, Inc. 
# 59 Temple Place, Suite 330 
# Boston, MA  02111-1307  USA
#

PG_PATH=""
PSQL=`which psql`
CREATEDB=`which createdb`
DESTROYDB=`which dropdb`
DB_NAME=""
DESCR=""
QUIET="No"
TARG_VERSION=
PLPGSQL_PATH=
DB_OWNER=""
POSTGRES_SU=`whoami`
OUTPUT_DIR=""

#-------------------------------------------------------------------------
# check_output_dir
#
# Check that the output dir was set, either by the set_output_dir()
# function or by the user via an option.  Check that the user can
# write to that directory.
#-------------------------------------------------------------------------
check_output_dir() {
  if [ -z "$OUTPUT_DIR" ]
  then
    echo -e "\a\nFailed to find a writable output directory."
    echo    "Please use -o to specify a writable diretory."
    echo -e "Aborting...\n"
    exit 1
  fi

  if [ ! -d "$OUTPUT_DIR" ]
  then
    echo -e "\a\nThere is no directory named $OUTPUT_DIR"
    echo    "Please use -o to specify a writable diretory."
    echo -e "Aborting...\n"
    exit 1
  fi

  if [ ! -w "$OUTPUT_DIR" ]
  then
    echo -e "\a\nYou cannot write to $OUTPUT_DIR"
    echo    "Please use -o to specify a writable diretory."
    echo -e "Aborting...\n"
    exit 1
  fi

  return 0
}

#-------------------------------------------------------------------------
# set_output_dir
#
# If an output directory was not specified by the user, attempt to 
# find one that will work.
#
# Start with the user's home directory, then try tmp, then try the
# current directory.
#-------------------------------------------------------------------------
set_output_dir() {
  if [ -n "$HOME" -a -d "$HOME" -a -w "$HOME" ]
  then
    OUTPUT_DIR="$HOME"
    return 0
  fi

  if [ -d "/tmp" -a -w "/tmp" ]
  then
    OUTPUT_DIR="/tmp"
    return 0
  fi

  PWD=`pwd`
  if [ -w "$PWD" ]
  then
    OUTPUT_DIR="$PWD"
    return 0
  fi

  ## we failed....
  return 1
}

#-------------------------------------------------------------------------
# show_version()
#
# Show the version and copyright information.
#-------------------------------------------------------------------------
show_version() {
  echo -e "\ncreate_prepsdb version 3.1 (Schema version $TARG_VERSION)"
  echo -e "Copyright (c) 2000-2001 Kenneth W. Sodemann (stufflehead@bigfoot.com)\n"
  return 0 
}

#-------------------------------------------------------------------------
# show_final_msg()
#
# Show the final success message.
#-------------------------------------------------------------------------
show_final_msg() {
  echo -e "\n$DB_NAME has been created successfully."
  echo "Review the $OUTPUT_DIR/$DB_NAME.log file for details."
  return 0
}

#-------------------------------------------------------------------------
# show_help()
#
# Show some simple usage text.
#-------------------------------------------------------------------------
show_help() {
  echo -e "\nCreates a PRepS database (schema version $TARG_VERSION)"
  echo -e "Usage: create_prepsdb [options]"
  echo -e "\t-d : use default DB name of 'myprs' and default description"
  echo -e "\t-h : show the help information and exit"
  echo -e "\t-o path : specify writable path for output and temp files"
  echo -e "\t-P path : supply the path to PL/pgSQL (plpgsql.so)"
  echo -e "\t-p path : supply the path to the PostgreSQL tools"
  echo -e "\t-u user_name : the user who will own the database"
  echo -e "\t-v : show the version information and exit\n"
}

#-------------------------------------------------------------------------
# check_user()
#
# See if the user is 'postgres'.  If not, ask them if they are a 
# PostgreSQL superuser.
#------------------------------------------------------------------------- 
check_user() {
  if [ "$POSTGRES_SU" = "postgres" ]
  then
    return 0;
  fi

  echo -e "\nThis script MUST be run by the PostgreSQL super user.  You are currently"
  echo "logged in as $POSTGRES_SU.  Is this the PostgreSQL superuser on your system?"
  echo -e "(yes/no)> \c"

  while true
  do
    read X
    case "$X" in
      y | Y | yes | Yes | YES )
        return 0;;
      n | N | no | No | NO )
        return 1;;
      *) echo "Please enter yes or no";;
    esac
  done
}


#-------------------------------------------------------------------------
# get_confirm()
#
# Echo out the data about to be used to setup the database, and get
# confirmation from the user that they wish to proceed.
#
# Return a "no error" condition if they wish to preceed and an "error"
# condition if they do not wish to proceed.
#------------------------------------------------------------------------- 
get_confirm() {
  echo -e "\nAbout to create a PRepS database as follows\n"
  echo "Name:  $DB_NAME"
  echo "Descr: $DESCR"
  echo "Owner: $DB_OWNER"
  echo -e "\nAre you sure? \c"

  while true
  do
    read X
    case "$X" in
      y | Y | yes | Yes | YES )
        return 0;;
      n | N | no | No | NO )
        return 1;;
      *) echo "Please enter yes or no";;
    esac
  done
}


#------------------------------------------------------------------------- 
# mainline
#------------------------------------------------------------------------- 
if ! getopt dho:P:p:u:v $@ > /dev/null
then
   exit 1
fi

eval set -- `getopt dho:P:p:u:v "$@"`
while true
do
  case "$1" in
    -d) DB_NAME="myprs"; DESCR="Default PRepS Database";
        break;;
    -h) show_help; shift; exit 0;;
    -o) OUTPUT_DIR="$2"; shift 2;;
    -P) PLPGSQL_PATH="$2"; shift 2;;
    -p) PG_PATH="$2"; shift 2;;
    -u) DB_OWNER="$2"; shift 2;;
    -v) show_version; shift; exit 0;;
    --) shift; break;;
     *) echo "Internal error!" ; exit 1 ;;
  esac
done

if ! check_user
then
  echo -e "\nPlease login as the PostgreSQL superuser, and attempt to run this"
  echo "script again."
  exit 99 
fi


##
## If we do not have an output directory specified by the user,
## attempt to find one.  Either way, check it.
if [ -z "$OUTPUT_DIR" ]
then
  set_output_dir
fi
check_output_dir


##
## if a path to the tools was specified, prefix each tool with it.
if [ ! -z "$PG_PATH" ]
then
  PSQL="$PG_PATH/psql"
  DROPDB="$PG_PATH/dropdb"
  CREATEDB="$PG_PATH/createdb"
fi

#
# Make sure we will be able to run $PSQL and $CREATEDB
if [ -z "$PSQL" ] || [ ! -x "$PSQL" ]
then
  echo -e "\a\nERROR: psql is missing or is not executable\n"
  exit 2
fi

if [ -z "$CREATEDB" ] || [ ! -x "$CREATEDB" ]
then
  echo -e "\a\nERROR: createdb is missing or is not executable\n"
  exit 2
fi

#
# Make sure that the files we are going to need exist
if [ ! -f "/schema.in" ]
then
  echo -e "\a/schema.in is missing"
  echo "aborting..."
  exit 5
fi

if [ ! -f "/create_defdata.in" ]
then
  echo -e "\a/create_defdata.in is missing"
  echo "aborting..."
  exit 6
fi

if [ ! -f "$PLPGSQL_PATH/plpgsql.so" ]
then
  echo -e "\aPL/pgSQL (plpgsql.so) not found in $PLPGSQL_PATH"
  echo "You may need to use -P to specify the path"
  echo "aborting..."
  exit 7
fi

#
# Get the name of the database from the user.  It must be non-NULL.
while [ -z "$DB_NAME" ]
do
  echo -e "Please enter a name for the database (no spaces, no quotes): \c"
  read TEMP
  DB_NAME="${TEMP%%" "}"
  if [ -z "$DB_NAME" ]
  then
    echo -e "\a***ERROR*** You MUST supply a name."
  fi
done

#
# Get a description for the database from the user.  It must be non-NULL.
while [ -z "$DESCR" ]
do
  echo  "Please enter a short description for the database (no quotes):"
  read TEMP
  DESCR="${TEMP%%" "}"
  if [ -z "$DESCR" ]
  then
    echo -e "\a***ERROR*** You MUST supply a description."
  fi
done

#
# Get an owner for the database.
while [ -z "$DB_OWNER" ]
do
  echo "Please enter an owner for the database [default: $POSTGRES_SU]:"
  read TEMP
  DB_OWNER="${TEMP%%" "}"
  if [ -z "$DB_OWNER" ]
  then
    DB_OWNER="$POSTGRES_SU"
  fi
done

#
# Confirm with the entered data with the user, and make sure they want
# to go on.  Abort if they do not.
if ! get_confirm
then
  echo "Aborting..."
  exit 3
fi

#
# Create the database.  Abort if we fail.
echo "Creating the database"
if ! $CREATEDB -U $DB_OWNER $DB_NAME
then
  echo -e "\aAborting..."
  exit 4
fi

#
# Create the schema script, and then run it
echo "Creating the database schema installation file"
if ! sed -e "s#XXDBOWNERXX#$DB_OWNER#g" \
         -e "s#XXPOSTGRESSUXX#$POSTGRES_SU#g" \
         -e "s#XXLIBDIRXX##g" \
         -e "s#XXPGLIBDIRXX#$PLPGSQL_PATH#g" \
         /schema.in > $OUTPUT_DIR/schema.sql
then
  echo -e "\aFailed to create schema definition file"
  exit 8
fi

echo "Installing the database schema"
if ! $PSQL -e $DB_NAME < $OUTPUT_DIR/schema.sql > $OUTPUT_DIR/$DB_NAME.log 2>&1
then
  rm $OUTPUT_DIR/schema.sql
  echo -e "\aSchema install failure.  Aborting..."
  exit 9
fi

rm $OUTPUT_DIR/schema.sql

#
# Insert the default data.
echo "Creating the default data installation file"
if ! sed -e "s#XXDBOWNERXX#$DB_OWNER#g" \
         -e "s#XXPOSTGRESSUXX#$POSTGRES_SU#g" \
         /create_defdata.in > $OUTPUT_DIR/create_defdata.sql
then
  echo -e "\aFailed to create default data file"
  exit 10
fi

echo "Installing the default data"
if ! $PSQL -U $DB_OWNER -e $DB_NAME < $OUTPUT_DIR/create_defdata.sql >> $OUTPUT_DIR/$DB_NAME.log 2>&1
then
  rm $OUTPUT_DIR/create_defdata.sql
  echo -e "\aDefault data install failure.  Aborting..."
  exit 11
fi

rm $OUTPUT_DIR/create_defdata.sql 

#
# Insert the version information.
if $PSQL -q -U $DB_OWNER \
         -c "insert \
               into version \
             values ($TARG_VERSION, \
                     '$DB_NAME', \
                     '$DESCR', \
                     now())"  $DB_NAME
then
  echo -e "\aDone..."
  ERRORS=`grep -c '^ERROR' $OUTPUT_DIR/$DB_NAME.log`
  if [ $ERRORS -gt 0 ]
  then
    grep '^ERROR' $OUTPUT_DIR/$DB_NAME.log
    echo -e "\a\nThe $OUTPUT_DIR/$DB_NAME.log file shows $ERRORS errors..."
  else
    show_final_msg
  fi

  exit 0
fi

##
## If we are here, something must have went wrong, and we did not 
## catch it.
echo -e "\a\nERROR: Unknown Error!!!\n"
exit 99

