#!/bin/sh
#
# Copyright (C) 2008 Manuel Mausz (manuel@mausz.at)
# http://manuel.mausz.at/coding/autoresponder/
#
# 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 the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.


cfx_conf=""
debug=0
alwaysyes=0
nobackup=0
arbin="autoresponder.pl"
arsql="autoresponder.sql"
arbackup=".old"

aruid=""
argid=""
archmod="0550"
smrsh="/etc/smrsh /etc/mail/smrsh"

#-------------------------------------------------------------------------------

cfx_getconf()
{
  file="$1"
  name="$2"
  var="$3"
  maybezero="$4"
  value=$(grep "$name" "$file" | tail -n 1 | cut -d"'" -f2 2>/dev/null)
  eval "$var=\"$value\""
  if [ -z "$maybezero" ] && [ -z "$value" ]
  then
    echo "ERROR: Unable to get configuration value for $name from $cfx_conf"
    exit 1
  fi
}

askuser()
{
  yes=$1
  if [ $yes -ne 1 ]
  then
    read -p "OK (y/n)? " ok
    if [ "$ok" != "y" ]
    then
      echo "Aborting..."
      exit
    fi
  fi
}

echodbg()
{
  if [ "$debug" -eq 1 ]
  then
    echo "DEBUG: $*"
  fi
}

print_usage()
{
  echo "Usage: ./autoresponder.run /path/to/confixx_main.conf"
  echo "       ./autoresponder.run -- [-y] [-d] [-nb] /path/to/confixx_main.conf"
  echo "Options:"
  echo "  -y,  --yes        enter yes to all questions"
  echo "  -nb, --nobackup   don't do any backups"
  echo "  -d,  --debug      enable debug messages"
}

#-------------------------------------------------------------------------------

echo ""
echo "Running setup..."

# fetch OS
arch=$(uname -s)

# parse additional commandline parameters
while [ $# -gt 0 ]
do
  case "$1" in
    -d|--debug)
    debug=1
    ;;
    -y|--yes)
    alwaysyes=1
    ;;
    -nb|--nobackup)
    nobackup=1
    ;;
    *)
    if [ -z "$cfx_conf" ]
    then
      cfx_conf="$1"
    fi
    ;;
  esac
  shift
done

# disabled as it might confuse users
# fallback to default path
#[ -z "$cfx_conf" ] && cfx_conf="/root/confixx/confixx_main.conf"

# check confixx config
if [ -z "$cfx_conf" ]
then
  print_usage
  exit 1
fi
if [ ! -r "$cfx_conf" ]
then
  echo "ERROR: Unable to read $cfx_conf. Maybe wrong path."
  echo ""
  print_usage
  exit 1
fi

# check package file exists
if [ ! -f "$arbin" ] || [ ! -f "$arsql" ]
then
  echo "ERROR: Couldn't find package files. Setup run manually?"
  exit 1
fi

# get some configuration values
echo "Fetching confixx variables from $cfx_conf..."
cfx_getconf "$cfx_conf" '$ServerID ='        "cfx_serverid"
cfx_getconf "$cfx_conf" '$dbType ='          "cfx_db_type"
cfx_getconf "$cfx_conf" '$dbServer ='        "cfx_db_address"
cfx_getconf "$cfx_conf" '$dbPort ='          "cfx_db_port"
cfx_getconf "$cfx_conf" '$db_address ='      "cfx_db_dsn"
cfx_getconf "$cfx_conf" '$dbUser ='          "cfx_db_user"
cfx_getconf "$cfx_conf" '$dbPw ='            "cfx_db_pass"
cfx_getconf "$cfx_conf" '$dbDB ='            "cfx_db_name"
cfx_getconf "$cfx_conf" '$bin_autorespond =' "cfx_bin_autorespond"
cfx_getconf "$cfx_conf" '$bin_mysql ='       "cfx_bin_mysql"  1
cfx_getconf "$cfx_conf" '$bin_psql ='        "cfx_bin_psql"   1
cfx_getconf "$cfx_conf" '$bin_sendmail ='    "cfx_bin_sendmail"
cfx_getconf "$cfx_conf" '$mta ='             "cfx_mta"
cfx_getconf "$cfx_conf" '$mta_uid ='         "cfx_mta_uid"    1
cfx_getconf "$cfx_conf" '$mta_gid ='         "cfx_mta_gid"    1
cfx_getconf "$cfx_conf" '$MailConfigFile ='  "cfx_mta_config" 1
cfx_getconf "$cfx_conf" '$passwdDir ='       "cfx_passwd"

echodbg "cfx_serverid        = $cfx_serverid"
echodbg "cfx_db_type         = $cfx_db_type"
echodbg "cfx_db_address      = $cfx_db_address"
echodbg "cfx_db_port         = $cfx_db_port"
echodbg "cfx_db_dsn          = $cfx_db_dsn"
echodbg "cfx_db_user         = $cfx_db_user"
echodbg "cfx_db_pass         = $cfx_db_pass"
echodbg "cfx_db_name         = $cfx_db_name"
echodbg "cfx_bin_autorespond = $cfx_bin_autorespond"
echodbg "cfx_bin_sendmail    = $cfx_bin_sendmail"
echodbg "cfx_bin_mysql       = $cfx_bin_mysql"
echodbg "cfx_bin_psql        = $cfx_bin_psql"
echodbg "cfx_mta             = $cfx_mta"
echodbg "cfx_mta_uid         = $cfx_mta_uid"
echodbg "cfx_mta_gid         = $cfx_mta_gid"
echodbg "cfx_mta_config      = $cfx_mta_config"
echodbg "cfx_passwd          = $cfx_passwd"

#-------------------------------------------------------------------------------

# check for an existing autoresponder backup
echo "Checking for an existing autoresponder backup..."
if [ $nobackup -eq 0 ] && [ -f "${cfx_bin_autorespond}${arbackup}" ]
then
  echo "ERROR: Autoresponder backup ${cfx_bin_autorespond}${arbackup} already exist."
  echo "       In order to run this setup you've to move or remove this file."
  exit 1
fi

#-------------------------------------------------------------------------------

# check/build database commandline
echo ""
echo "Checking database settings..."
dbtool=""
dbbin=""
if [ "$cfx_db_type" = "mysql" ]
then
  dbbin="$cfx_bin_mysql"
  dbtool='$cfx_bin_mysql -u"$cfx_db_user" -p"$cfx_db_pass" -D"$cfx_db_name"'
  if [ "$cfx_db_port" -ge 0 2>/dev/null ]
  then
    dbtool=$dbtool' -h"$cfx_db_address" -P"$cfx_db_port"'
  else
    dbtool=$dbtool' -S"$cfx_db_port"'
  fi
elif [ "$cfx_db_type" = "pgsql" ]
then
  # TODO this isn't tested!
  dbbin="$cfx_bin_psql"
  dbtool='$cfx_bin_psql -U"$cfx_db_user" -d"$cfx_db_name"'
  if [ "$cfx_db_port" -ge 0 2>/dev/null ]
  then
    dbtool=$dbtool' -h"$cfx_db_address" -p"$cfx_db_port"'
  else
    dbtool=$dbtool' -S"$cfx_db_port"'
  fi
else
  echo "ERROR: Unknown database type ($cfx_db_type)."
  exit 1
fi
if [ -z "$dbbin" ]
then
  echo "ERROR: Database is $cfx_db_type but commandline tool (\$bin_mysql/\$bin_psql) is not defined."
  exit 1
fi

# display results and ask user
eval "cmdstr=\"$dbtool\""
echo "Found database type \"$cfx_db_type\". Trying to execute:"
echo "  $cmdstr < $arsql"
askuser $alwaysyes

# create password for pgsql and execute command
if [ "$cfx_db_type" = "pgsql" ]
then
  export PGPASSFILE="$HOME/.pgpasscfx"
  touch "$PGPASSFILE"
  chmod 0600 "$PGPASSFILE"
  echo "*:*:$cfx_db_name:$cfx_db_user:$cfx_db_pass" > "$PGPASSFILE"
fi
eval $dbtool < $arsql
ret=$?
[ ! -z "$PGPASSFILE" ] && [ -e "$PGPASSFILE" ] && rm -f "$PGPASSFILE"
if [ $ret != 0 ]
then
  echo "ERROR: Unable to create/update autoresponder database table."
  exit 1
fi
echo "Created/updated database table successfully."

#-------------------------------------------------------------------------------

# first change file permissions
chmod 0600 "$arbin"

# replace placeholders in our autoresponder
echo ""
echo "Trying to replace the following variables in enhanced autoresponder:"
echo "  Database DSN     = $cfx_db_dsn"
echo "  Database user    = $cfx_db_user"
echo "  Database pass    = $cfx_db_pass"
echo "  Confixx ServerID = $cfx_serverid"
echo "  Mailer Binary    = $cfx_bin_sendmail"
askuser $alwaysyes

sed -i -e "s%INSERT VALUE OF \$db_address FROM confixx_main\.conf%${cfx_db_dsn}%"         "$arbin"
sed -i -e "s%INSERT VALUE OF \$dbUser FROM confixx_main\.conf%${cfx_db_user}%"            "$arbin"
sed -i -e "s%INSERT VALUE OF \$dbPw FROM confixx_main\.conf%${cfx_db_pass}%"              "$arbin"
sed -i -e "s%INSERT VALUE OF \$ServerID FROM confixx_main\.conf%${cfx_serverid}%"         "$arbin"
sed -i -e "s%INSERT VALUE OF \$bin_sendmail FROM confixx_main\.conf%${cfx_bin_sendmail}%" "$arbin"
echo "Replaced variables successfully."

#-------------------------------------------------------------------------------

# check for old autoresponder
echo ""
echo "Trying to determine uid/gid/chmod from origin autoresponder..."
if [ ! -f "$cfx_bin_autorespond" ]
then
  echo "WARNING: Origin autoresponder ($cfx_bin_autorespond) doesn't exist."

  # the following block contains some ugly stuff
  if [ "$cfx_mta" = "postfix" ]
  then
    echo "Trying to determine values from postfix configuration..."

    defuser=""
    if [ -f "$cfx_mta_config" ]
    then
      defuser=$(awk -F'=' '{
        if ($1 ~ /^\s*default_privs\s*/) {
          str="";
          for(i=2; i<=NF; i++) {
            str=str""$i;
            if (i < NF) str=str""FS
          };
          sub(/^ */, "", str);
          sub(/ *$/, "", str);
          print str
        };
      }' "$cfx_mta_config")
      if [ $? != 0 ]
      then
        echo "ERROR: Unable to read setting 'default_privs' from $cfx_mta_config."
        exit 1
      fi

      echo "Using value from setting 'default_privs' from $cfx_mta_config..."
    fi
    if [ -z "$defuser" ]
    then
      echo "WARNING: Unable to read postfix configuration ($cfx_mta_config)."
      echo "Fallback to unprivileged user (nobody)..."
      defuser="nobody"
    fi

    # someone know a better way to do this without using
    # arrays from bash?
    line=$(grep "$defuser" "$cfx_passwd")
    aruid=$(echo "$line" | awk -F':' '{print $3}')
    argid=$(echo "$line" | awk -F':' '{print $4}')
  else
    echo "Using values from confixx_main.conf..."
    aruid="$cfx_mta_uid"
    argid="$cfx_mta_gid"
  fi
else
  echo "Using values from origin autoresponder..."
  if [ "$arch" = "Linux" ]
  then
    stat=$(stat -c '%u %g %a' "$cfx_bin_autorespond")
  else
    stat=$(stat -f "%u %g %OMp%OLp" "$cfx_bin_autorespond")
  fi
  aruid=$(echo "$stat" | awk '{print $1}')
  argid=$(echo "$stat" | awk '{print $2}')
  archmod=$(echo "$stat" | awk '{print $3}')
fi

# sanity check
if [ -z "$aruid" ] || [ -z "$argid" ]
then
  echo "ERROR: Unable to read uid and/or gid for user $defuser from $cfx_passwd."
  exit 1
fi

# display results and ask user
echo "Trying to install enhanced autoresponder using the following parameters:"
echo "  Destination  = $cfx_bin_autorespond"
[ $nobackup -eq 0 ] && echo "  Backup       = ${cfx_bin_autorespond}${arbackup}"
echo "  UID          = $aruid"
echo "  GID          = $argid"
echo "  CHMOD        = $archmod"
echo "  shmrsh       = $smrsh"
askuser $alwaysyes

# chown + chmod
chown -h $aruid:$argid "$arbin" && chmod $archmod "$arbin"
if [ $? != 0 ]
then
  echo "ERROR: Unable to change ownership or change file permissions for file $arbin."
  exit 1
fi

# create backup
if [ $nobackup -eq 0 ] && [ -f "$cfx_bin_autorespond" ]
then
  mv "$cfx_bin_autorespond" "${cfx_bin_autorespond}${arbackup}"
  if [ $? != 0 ]
  then
    echo "ERROR: Unable to create backup of origin autoresponder in ${cfx_bin_autorespond}${arbackup}."
    exit 1
  fi
fi

# move enchanced autoresponder to destination
mv "$arbin" "$cfx_bin_autorespond"
if [ $? != 0 ]
then
  echo "ERROR: Unable to move enhanced autoresponder from setup directory to $cfx_bin_autorespond."
  exit 1
fi

# create symlinks for smrsh
for dir in $smrsh; do
  if [ ! -d "$dir" ] || [ -e "$dir/$arbin" ]
  then
    continue
  fi
  ln -s "$cfx_bin_autorespond" "$dir/$arbin"
  echo "Created symlinks for smrsh in $dir."
done

# additional info for sendmail
if [ "$cfx_mta" = "sendmail" ]
then
  cat <<"EOF"

NOTES FOR SENDMAIL
==================
Sendmail is not passing the envelope sender (also known as the value of header
"Return-Path") to the executable. Although it won't be a fatal error, the header
should be checked to detect bounces more easily.
In order to let sendmail pass the header, you need to modify your sendmail config
(sendmail.cf) and add the char "P" to the field "F" in line "prog".
e.g from:
  Mprog,   P=/usr/sbin/smrsh, F=lsDFMoqeu9, S=EnvFromL/HdrFromL, ....
to
  Mprog,   P=/usr/sbin/smrsh, F=lsDFMoqeu9P, S=EnvFromL/HdrFromL, ....
"P" should already be defined as "HP?Return-Path: <$g>" (in sendmail.cf too).
Don't forget to restart sendmail afterwards.
EOF
fi

# we're done
echo ""
echo "Installation completed successfully."
