#!/bin/sh
#
#   @(#)$Id: install.sh,v 1.4 1996/12/13 23:35:22 steve Exp steve $
#
#   cddbd - CD Database Protocol Server
#
#   Copyright (C) 1996  Steve Scherf
#   Email: steve@moonsoft.com
#   Moondog Software Productions - makers of fine public domain software.
#
#   Based on the original source by Ti Kan.
#
#   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., 675 Mass Ave, Cambridge, MA 02139, USA.
#

PATH=/bin:/usr/bin:/sbin:/usr/sbin:/etc:/usr/local/bin:/usr/5bin
export PATH

CDDBD_VER=1.4
ERRFILE=/tmp/cddbd.err
TMPFILE=/tmp/cddbd.$$

id=`id`

# Set up access defaults.
DIRPERM=755
FILEPERM=644
PWDPERM=600
DBINPERM1=700
DBINPERM2=6711
UMASK=022
OWNER=`expr "$id" : '.*uid=.*(\(.*\)).*gid'`
GROUP=`expr "$id" : '.*gid=[0-9]*(\([a-zA-Z0-9_]*\))'`
BINOWNER=$OWNER

USERS=100
HANGS=10
LINES=1024
SIZE=102400
XMITS=4
HIWAT=1024000
LOWAT=768000
STRIP=no
FUZZY=900
FUZDV=4
XTIME=600
ITIME=300
ATIME=600
CTIME=3600
ETIME=500
DTIME=250
MTIME=500
HTIME=60
LTIME=250
LWAIT=60
LOGFLAGS="errors hello access info"
DSMTPHOST="localhost"
DEMAILADDR="${OWNER}@`uname -n`"
DFEEDHOST="*.moonsoft.com"
DFEEDNET="198.49.40.0"
ADMINMAIL="cddb-admin@moonsoft.com"


#
# Utility functions
#

doexit()
{
	if [ $1 -eq 0 ]
	then
		$ECHO "\nInstallation of cddbd is now complete."
	else
		$ECHO "\nErrors have occurred in the installation."
		if [ $ERRFILE != /dev/null ]
		then
			$ECHO "See $ERRFILE for an error log."
		fi
	fi
	exit $1
}

logerr()
{
	if [ "$1" = "-p" ]
	then
		$ECHO "Error: $2"
	fi
	$ECHO "$2" >>$ERRFILE
	ERROR=1
}

getstr()
{
	$ECHO "$* \c"
	read ANS
	if [ -n "$ANS" ]
	then
		return 0
	else
		return 1
	fi
}

getyn()
{
	if [ -z "$YNDEF" ]
	then
		YNDEF=y
	fi

	while :
	do
		$ECHO "$*? [${YNDEF}] \c"
		read ANS
		if [ -n "$ANS" ]
		then
			case $ANS in
			[yY])
				RET=0
				break
				;;
			[nN])
				RET=1
				break
				;;
			*)
				$ECHO "Please answer y or n"
				;;
			esac
		else
			if [ $YNDEF = y ]
			then
				RET=0
			else
				RET=1
			fi
			break
		fi
	done

	YNDEF=
	return $RET
}

dolink()
{
	# Try symlink first
	ln -s $1 $2 2>/dev/null
	if [ $? != 0 ]
	then
		# Use hard link
		ln $1 $2 2>/dev/null
	fi
	RETSTAT=$?
	if [ $RETSTAT != 0 ]
	then
		logerr -p "Cannot link $1 -> $2"
	fi
	return $RETSTAT
}

makedir()
{
	$ECHO "\t$1"
	if [ ! -d $1 ]
	then
		mkdir -p $1
	fi
	if [ $2 != default ]
	then
		chmod $2 $1 2>/dev/null
	fi
	if [ $3 != default ]
	then
		chown $3 $1 2>/dev/null
	fi
	if [ $4 != default ]
	then
		chgrp $4 $1 2>/dev/null
	fi
	return 0
}

removedir()
{
	$ECHO "\t$1"
	if [ -d $1 ]
	then
		rmdir $1
	fi
	return 0
}

instfile()
{
	TDIR=`dirname $2`

	if [ -n "$TDIR" -a -d "$TDIR" -a -w "$TDIR" ]
	then
		if [ ! -f $1 ]
		then
			$ECHO "\t$2 NOT installed"
			logerr -n "Cannot install $2: file missing."
			return 1
		fi

		$ECHO "\t$2"
		if [ -f $2 ]
		then
			rm -f $2
		fi

		cp $1 $2
		if [ $? != 0 ]
		then
			logerr -n "Cannot install $2: file copy error."
			return 1
		fi

		if [ -f $2 ]
		then
			if [ $3 != default ]
			then
				chmod $3 $2 2>/dev/null
			fi
			if [ $4 != default ]
			then
				chown $4 $2 2>/dev/null
			fi
			if [ $5 != default ]
			then
				chgrp $5 $2 2>/dev/null
			fi
		fi
		return 0
	else
		$ECHO "\t$2 NOT installed"
		logerr -n "Cannot install $2: target directory not writable."
		return 1
	fi
}

#
# Main execution starts here.
#

# Catch some signals
trap "rm -f $TMPFILE; exit 1" 1 2 3 5 15

# Use Sysv echo if possible
if [ -x /usr/5bin/echo ]
then
	ECHO=/usr/5bin/echo				# SunOS SysV echo
elif [ -z "`(echo -e a) 2>/dev/null | fgrep e`" ]
then
	ECHO="echo -e"					# GNU bash, etc.
else
	ECHO=echo					# generic SysV
fi

# Remove old error log file
ERROR=0
rm -f $ERRFILE
if [ -f $ERRFILE ]
then
	$ECHO "Cannot remove old $ERRFILE: error logging not enabled."
	ERRFILE=/dev/null
fi

if [ ! -f .accessfile ]
then
	$ECHO "You must run configure and make cddbd before installing."
	doexit 1
fi

if [ ! -x cddbd ]
then
	$ECHO "You must make cddbd before installing."
	doexit 1
fi

# Check privilege
if [ "$OWNER" != "root" ]
then
	$ECHO "You are not the super-user. You should be sure to specify"
	$ECHO "install directories that you have the proper write permissions"
	$ECHO "for.\n"

	YNDEF=n
	getyn "Proceed anyway"
	if [ $? -ne 0 ]
	then
		logerr -p "Not super user: installation aborted by user"
		doexit 1
	fi
fi


$ECHO "\nInstalling \"cddbd\" CDDB Protocol Server $CDDBD_VER by Steve Scherf"


# Determine BINDIR

if [ -z "$BINDIR" ]
then
	if [ -d /usr/local/bin ]
	then
		BINDIR=/usr/local/bin
	elif [ -d /usr/lbin ]
	then
		BINDIR=/usr/lbin
	elif [ -d /usr/bin ]
	then
		BINDIR=/usr/bin
	else
		BINDIR=/usr/local/bin
	fi
else
	BINDIR=`echo $BINDIR | sed 's/\/\//\//g'`
fi

while :
do
	if getstr "\nEnter cddbd binary directory\n[${BINDIR}]:"
	then
		if [ -d "$ANS" ]
		then
			BINDIR=$ANS
			break
		else
			$ECHO "Error: $ANS does not exist."
		fi
	else
		break
	fi
done


# Find other directories

BASEDIR=`grep '^ACCESSFILE' .accessfile | awk '{ print $2 }'`
WORKDIR=${BASEDIR}
CDDBDIR=`dirname ${BASEDIR}`

if [ $CDDBDIR = "/" ]
then
	CDDBDIR=""
fi
CDDBDIR=${CDDBDIR}/cddb

while :
do
	if getstr "\nEnter cddbd work directory\n[${WORKDIR}]:"
	then
		if [ -d `dirname "$ANS"` ]
		then
			WORKDIR=$ANS
			break
		else
			$ECHO "Error: `dirname $ANS` does not exist."
		fi
	else
		break
	fi
done

while :
do
	if getstr "\nEnter CD database directory\n[${CDDBDIR}]:"
	then
		if [ -d "$ANS" ]
		then
			CDDBDIR=$ANS
			break
		else
			CDDBTMP=$ANS
			YNDEF=n
			if getyn "Warning: $ANS does not exist. Continue anyway"
			then
				CDDBDIR=$CDDBTMP
				break
			fi
		fi
	else
		break
	fi
done

YNDEF=n
if getyn "\nDo you want to enable server access via HTTP"
then
	CGIDIR="$HOME/public_html"

	while :
	do
		if getstr "\nEnter cddbd CGI directory\n[${CGIDIR}]:"
		then
			if [ -d "$ANS" ]
			then
				CGIDIR=$ANS
				$ECHO ""
				break
			else
				$ECHO "Error: $ANS does not exist."
			fi
		else
			$ECHO ""
			break
		fi
	done
fi

# Make directory names.

SERVDIR="${WORKDIR}/server"
HASHDIR="${WORKDIR}/hash"

# Make file names.

ACCESS="${BASEDIR}/access"
MOTD="${WORKDIR}/motd"
SITE="${WORKDIR}/sites"
PASSWD="${WORKDIR}/passwd"
HISTORY="${WORKDIR}/history"
NHISTORY="${SERVDIR}/history"
FUZZFILE="${HASHDIR}/fuzzy_index"
NFUZZFILE="${SERVDIR}/fuzzy_index"
LOG="${WORKDIR}/log"
NLOG="${SERVDIR}/log"

# Create the access file.

umask $UMASK
rm -f access
cp access.hdr access
chmod $FILEPERM access

# Create the sites file.

rm -f sites
cat sites.hdr > sites
chmod $FILEPERM sites

# Create the passwd file.

rm -f passwd
cat passwd.hdr > passwd
chmod $PWDPERM passwd

YNDEF=y
if getyn "Do you want to enable logging of server accesses"
then
	logging=norm
else
	logging=none
fi

$ECHO "motdfile:     ${MOTD}" >> access
$ECHO "sitefile:     ${SITE}" >> access
$ECHO "pwdfile:      ${PASSWD}" >> access
$ECHO "workdir:      ${WORKDIR}" >> access
$ECHO "cddbdir:      ${CDDBDIR}" >> access

YNDEF=n
if getyn "Do you want configure your site as a master database hub"
then
	logging=post

	POSTDIR=${WORKDIR}/post
	DUPDIR=${WORKDIR}/dup

	$ECHO "postdir:      ${POSTDIR}" >> access
	$ECHO "dupdir:       ${DUPDIR}" >> access
	$ECHO "dup_policy:   compare" >> access
	$ECHO "transmits:    ${XMITS}" >> access

	if getstr "\nEnter your SMTP server host\n[${DSMTPHOST}]:"
	then
		SMTPHOST=$ANS
	else
		SMTPHOST=$DSMTPHOST
	fi

	$ECHO "smtphost:     ${SMTPHOST}" >> access

	if getstr "\nEnter your full email address\n[${DEMAILADDR}]:"
	then
		EMAILADDR=$ANS
	else
		EMAILADDR=$DEMAILADDR
	fi

	$ECHO "admin_email:  ${EMAILADDR}" >> access
	$ECHO "bounce_email: ${EMAILADDR}" >> access
	$ECHO "test_email:   ${EMAILADDR}" >> access
else
	$ECHO "postdir:      ${CDDBDIR}" >> access
	$ECHO "dup_policy:   always" >> access
fi

case $logging in
	norm)
		$ECHO "logging:      ${LOGFLAGS}" >> access
		;;
	post)
		$ECHO "logging:      ${LOGFLAGS} post" >> access
		;;
	*)
		$ECHO "logging:      none" >> access
		;;
esac

$ECHO "post_lines:   ${LINES}" >> access
$ECHO "put_size:     ${SIZE}" >>  access
$ECHO "users:        ${USERS}" >> access
$ECHO "fuzzy_factor: ${FUZZY}" >> access
$ECHO "fuzzy_div:    ${FUZDV}" >> access
$ECHO "xmit_time:    ${XTIME}" >> access
$ECHO "input_time:   ${ITIME}" >> access
$ECHO "access_time:  ${ATIME}" >> access
$ECHO "connect_time: ${CTIME}" >> access
$ECHO "elapse_time:  ${ETIME}" >> access
$ECHO "delay_time:   ${DTIME}" >> access
$ECHO "email_time:   ${MTIME}" >> access
$ECHO "lock_time:    ${LTIME}" >> access
$ECHO "lock_wait:    ${LWAIT}" >> access
$ECHO "hang_time:    ${HTIME}" >> access
$ECHO "max_hangs:    ${HANGS}" >> access
$ECHO "log_hiwat:    ${HIWAT}" >> access
$ECHO "log_lowat:    ${LOWAT}" >> access
$ECHO "strip_ext:    ${STRIP}" >> access

$ECHO "\nEnter user and permission information. In general, you will want"
$ECHO "the server and database user/group/perms to be the same. They MUST"
$ECHO "be the same if you are not root. Note that the server binary perms"
$ECHO "should be setuid/setgid unless you can guarantee that the owner will"
$ECHO "be the only user to run it."

if getstr "\nEnter the user who will own the server directory\n[${OWNER}]:"
then
	OWNID=$ANS
else
	OWNID=$OWNER
fi

if getstr "\nEnter the group of the server directory\n[${GROUP}]:"
then
	GRPID=$ANS
else
	GRPID=$GROUP
fi

if getstr "\nEnter the server file creation mode\n[${FILEPERM}]:"
then
	FPERM=$ANS
else
	FPERM=$FILEPERM
fi

if getstr "\nEnter the server directory creation mode\n[${DIRPERM}]:"
then
	DPERM=$ANS
else
	DPERM=$DIRPERM
fi

if getstr "\nEnter the user who will own the database\n[${OWNID}]:"
then
	DBOWNID=$ANS
else
	DBOWNID=$OWNID
fi

if getstr "\nEnter the group of the database\n[${GRPID}]:"
then
	DBGRPID=$ANS
else
	DBGRPID=$GRPID
fi

if getstr "\nEnter the database file mode\n[${FPERM}]:"
then
	DBFPERM=$ANS
else
	DBFPERM=$FPERM
fi

if getstr "\nEnter the database directory mode\n[${DPERM}]:"
then
	DBDPERM=$ANS
else
	DBDPERM=$DPERM
fi

SECUSERS=`grep '^SECUSERS' .accessfile | awk '{ print $2 }'`

if [ "$OWNID" = "$DBOWNID" -a "$GRPID" = "$DBGRPID" -a $SECUSERS -eq 0 ]
then
	BINPERM=$DBINPERM1
else
	BINPERM=$DBINPERM2
fi

if getstr "\nEnter the server file binary mode\n[${BINPERM}]:"
then
	BINPERM=$ANS
fi

$ECHO "user:         ${OWNID}" >> access
$ECHO "group:        ${GRPID}" >> access
$ECHO "file_mode:    ${FPERM}" >> access
$ECHO "dir_mode:     ${DPERM}" >> access
$ECHO "db_user:      ${DBOWNID}" >> access
$ECHO "db_group:     ${DBGRPID}" >> access
$ECHO "db_file_mode: ${DBFPERM}" >> access
$ECHO "db_dir_mode:  ${DBDPERM}" >> access

$ECHO "\n# Beginning of permissions.\n" >> access

YNDEF=n
if getyn "\nDo you want to allow automatic database updates"
then
	if getstr "\nEnter database feed site\n[${DFEEDHOST}]:"
	then
		FEEDHOST=$ANS
	else
		FEEDHOST=$DFEEDHOST
	fi

	$ECHO "host_perms: sc ${FEEDHOST} connect post update \c" >> access
	$ECHO "get put nopasswd" >> access

	$ECHO "\nIn order for automatic updates to be initiated, you must"
	$ECHO "contact the cddbd administrator at \c"

	if [ "${FEEDHOST}" = "${DFEEDHOST}" ]
	then
		$ECHO "${ADMINMAIL}.\n"

		$ECHO "host_perms: sc ${DFEEDNET} connect post \c" >> access
		$ECHO "update get put nopasswd" >> access
	else
		$ECHO "the site you have specified.\n"
	fi
fi

$ECHO "host_perms: che default connect nopost noupdate noget \c" >> access
$ECHO "noput nopasswd" >> access
$ECHO "host_perms: s default noconnect nopost noupdate noget \c" >> access
$ECHO "noput nopasswd" >> access

YNDEF=y
if getyn "Do you want to create the motd file now"
then
	if [ "$EDITOR" = "" ]
	then
		ED=/usr/bin/vi
	else
		ED=$EDITOR
	fi

	if getstr "\nEnter editor you wish to use\n[${ED}]:"
	then
		ED=$ANS
	fi

	if [ -f $MOTD ]
	then
		cp $MOTD motd
	fi

	$ED motd
else
	$ECHO "\nYou will have to edit $MOTD by hand if you"
	$ECHO "wish to create a message of the day."
	rm -f motd
fi

# Make all necessary directories

$ECHO "\nMaking directories..."

makedir $WORKDIR $DPERM $OWNID $GRPID
makedir $SERVDIR $DPERM $OWNID $GRPID

# Save old important files

$ECHO "\nPreserving old files..."

if [ -f $LOG ]
then
	$ECHO "\t$LOG -> $NLOG"
	mv $LOG $NLOG

	err=$?
	if [ $err -ne 0 ]
	then
		logerr -n "Failed to preserve $LOG."
	fi
fi

if [ -f $HISTORY ]
then
	$ECHO "\t$HISTORY -> $NHISTORY"
	mv $HISTORY $NHISTORY

	err=$?
	if [ $err -ne 0 ]
	then
		logerr -n "Failed to preserve $HISTORY."
	fi
fi

if [ -f $FUZZFILE ]
then
	$ECHO "\t$FUZZFILE -> $NFUZZFILE"
	mv $FUZZFILE $NFUZZFILE

	err=$?
	if [ $err -ne 0 ]
	then
		logerr -n "Failed to preserve $FUZZFILE."
	fi
fi

if [ -f $ACCESS ]
then
	$ECHO "\t$ACCESS -> ${ACCESS}.old"
	mv $ACCESS ${ACCESS}.old

	err=$?
	if [ $err -ne 0 ]
	then
		logerr -n "Failed to preserve $SITE."
	fi
fi

if [ -f $SITE ]
then
	$ECHO "\t$SITE"

	grep "End of header" $SITE > /dev/null
	if [ $? -eq 0 ]
	then
		sed -e "1,/End of header/d" $SITE >> sites
	else
		$ECHO "" >> sites
		cat $SITE >> sites
	fi
fi

if [ -f $PASSWD ]
then
	$ECHO "\t$PASSWD"

	grep "End of header" $PASSWD > /dev/null
	if [ $? -eq 0 ]
	then
		sed -e "1,/End of header/d" $PASSWD >> passwd
	else
		$ECHO "" >> passwd
		cat $PASSWD >> passwd
	fi
fi

if [ -f $MOTD -a -f motd ]
then
	$ECHO "\t$MOTD -> ${MOTD}.old"
	mv $MOTD ${MOTD}.old

	err=$?
	if [ $err -ne 0 ]
	then
		logerr -n "Failed to preserve $MOTD."
	fi
fi

# Install files
$ECHO "\nInstalling files..."

# Binaries
instfile cddbd ${BINDIR}/cddbd $BINPERM $BINOWNER $GROUP

if [ "$CGIDIR" != "" ]
then
	instfile cddbd ${CGIDIR}/cddb.cgi $BINPERM $BINOWNER $GROUP
fi

# Configuration files
instfile access $ACCESS $FPERM $OWNID $GRPID
instfile sites $SITE $FPERM $OWNID $GRPID
instfile passwd $PASSWD $PWDPERM $OWNID $GRPID

if [ -f motd ]
then
	instfile motd $MOTD $FPERM $OWNID $GRPID
fi

# Remove old directories.

$ECHO "\nRemoving old directories..."

removedir $HASHDIR

YNDEF=y
if getyn "\nDo you want to create the fuzzy matching hash file now"
then
	$ECHO "\nPlease wait while the hash file is created."
	$ECHO "This will take a few minutes.\n"

	${BINDIR}/cddbd -fd

	err=$?
	if [ $err -ne 0 ]
	then
		logerr -n "Failed to build the fuzzy matching hash file."
	fi
else
	$ECHO "\nIf you wish to enable fuzzy matching in the future, you will"
	$ECHO "have to run \"cddbd -fd\"."
fi

doexit $ERROR
