# Copyright 1999-2007 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/eclass/eutils.eclass,v 1.285 2007/07/07 17:30:45 vapier Exp $

# @ECLASS: qmail.eclass
# @MAINTAINER: qmail@gentoo.org
# @BLURB: some common and ugly qmail functions

inherit flag-o-matic prime toolchain-funcs
DESCRIPTION="Based on the ${ECLASS} eclass"

# env vars
GENQMAIL_F=genqmail-${GENQMAIL_PV}.tar.bz2
GENQMAIL_S="${WORKDIR}"/genqmail-${GENQMAIL_PV}

QMAIL_F=qmail-${QMAIL_PV}.tar.gz
QMAIL_S="${WORKDIR}"/qmail-${QMAIL_PV}

NETQMAIL_F=netqmail-${NETQMAIL_PV}.tar.gz
NETQMAIL_S="${WORKDIR}"/netqmail-${NETQMAIL_PV}/netqmail-${NETQMAIL_PV}

QMAIL_SPP_F=qmail-spp-${QMAIL_SPP_PV}.tar.gz
QMAIL_SPP_S="${WORKDIR}"/qmail-spp-${QMAIL_SPP_PV}

QMAIL_TLS_F=netqmail-${NETQMAIL_PV}-tls-smtpauth-${QMAIL_TLS_PV}.patch
QMAIL_BIGTODO_F=big-todo.${QMAIL_BIGTODO_PV}.patch

# TODO: ucscpi.eclass?
TCPRULES_DIR=/etc/tcprules.d

# @FUNCTION: qmail_mini
# @DESCRIPTION:
# Check if the current ebuild is mini-qmail
qmail_mini() {
	test "${PN}" == "mini-qmail"
}

# common sources and patches
SRC_URI="${SRC_URI} mirror://gentoo/${GENQMAIL_F}"

if [[ -n ${NETQMAIL_PV} ]]; then
	SRC_URI="${SRC_URI} mirror://qmail/${NETQMAIL_F}"
fi

if [[ -n ${QMAIL_PV} ]]; then
	SRC_URI="${SRC_URI} mirror://qmail/${QMAIL_F}"
fi

if [[ -n ${QMAIL_SPP_PV} ]]; then
	SRC_URI="${SRC_URI}
		!vanilla? (
			qmail-spp? (
				mirror://sourceforge/qmail-spp/${QMAIL_SPP_F}
			)
		)"
fi

if [[ ${QMAIL_TLS_PV:-0} -ne 0 ]]; then
	SRC_URI="${SRC_URI}
		!vanilla? (
			ssl? (
				http://shupp.org/patches/${QMAIL_TLS_F}
			)
		)"
fi

if [[ ${QMAIL_BIGTODO_PV:-0} -ne 0 ]]; then
	SRC_URI="${SRC_URI}
		!vanilla? (
			highvolume? (
				mirror://qmail/${QMAIL_BIGTODO_F}
			)
		)"
fi

# use flags
IUSE="${IUSE} mailwrapper"

if ! qmail_mini; then
	IUSE="${IUSE} gencertdaily vanilla"

	if [[ -n ${QMAIL_SPP_PV} ]]; then
		IUSE="${IUSE} qmail-spp"
	fi

	if [[ -n ${QMAIL_TLS_PV} ]]; then
		IUSE="${IUSE} ssl"
	fi

	if [[ -n ${QMAIL_BIGTODO_PV} ]]; then
		IUSE="${IUSE} highvolume"
	fi
fi

# depend atoms
if ! qmail_mini; then
	DEPEND="${DEPEND} net-mail/queue-repair"

	if [[ -n ${QMAIL_TLS_PV} ]]; then
		DEPEND="${DEPEND} ssl? ( dev-libs/openssl )"
	fi

	RDEPEND="${DEPEND}
		sys-apps/ucspi-tcp
		sys-process/daemontools
		net-mail/dot-forward"
fi

RDEPEND="${RDEPEND}
	!mailwrapper? ( !virtual/mta )
	mailwrapper? ( net-mail/mailwrapper )"

PROVIDE="${PROVIDE} virtual/mta virtual/mda"

# set qmail home directory
if qmail_mini; then
	QMAIL_HOME=/var/mini-qmail
else
	QMAIL_HOME=/var/qmail
fi

# @FUNCTION: qmail_set_cc
# @DESCRIPTION:
# The following commands patch the conf-{cc,ld} files to use the user's
# specified CFLAGS and LDFLAGS. These rather complex commands are needed
# because a user supplied patch might apply changes to these files, too.
# @SEE: #165981
qmail_set_cc() {
	append-ldflags $(bindnow-flags)
	cc=$(head -n 1 ./conf-cc | sed -e "s#^g\?cc\s\+\(-O2\)\?#$(tc-getCC) #")
	ld=$(head -n 1 ./conf-ld | sed -e "s#^g\?cc\s\+\(-s\)\?#$(tc-getCC) #")

	echo "${cc} ${CFLAGS}"  > ./conf-cc || die 'Patching conf-cc failed.'
	echo "${ld} ${LDFLAGS}" > ./conf-ld || die 'Patching conf-ld failed.'
}

# @FUNCTION: qmail_create_users
# @DESCRIPTION:
# Keep qmail users and groups in sync across ebuilds
qmail_create_users() {
	einfo "Creating groups and users"
	enewgroup nofiles 200
	enewgroup qmail 201
	enewuser alias 200 -1  ${QMAIL_HOME}/alias 200
	enewuser qmaild 201 -1 ${QMAIL_HOME} 200
	enewuser qmaill 202 -1 ${QMAIL_HOME} 200
	enewuser qmailp 203 -1 ${QMAIL_HOME} 200
	enewuser qmailq 204 -1 ${QMAIL_HOME} 201
	enewuser qmailr 205 -1 ${QMAIL_HOME} 201
	enewuser qmails 206 -1 ${QMAIL_HOME} 201
}

# @FUNCTION: netqmail_src_unpack
# @DESCRIPTION:
# Unpack and patch netqmail
qmail_src_unpack() {
	cd "${WORKDIR}"

	if [[ -n ${NETQMAIL_PV} ]]; then
		unpack ${NETQMAIL_F}
		cd netqmail-${NETQMAIL_PV}
		./collate.sh || die "patching failed"
		ht_fix_file "${NETQMAIL_S}"/Makefile*
	elif [[ -n ${QMAIL_PV} ]]; then
		unpack ${QMAIL_F}
		ht_fix_file "${QMAIL_S}"/Makefile*
	else
		die "neither qmail or netqmail will be built"
	fi
}

# @FUNCTION: spp_src_unpack
# @DESCRIPTION:
# Unpack qmail spp
qmail_spp_src_unpack() {
	cd "${WORKDIR}"
	use qmail-spp && unpack qmail-spp-${QMAIL_SPP_PV}.tar.gz
}

# @FUNCTION: spp_src_unpack
# @DESCRIPTION:
# Unpack qmail spp
genqmail_src_unpack() {
	cd "${WORKDIR}"
	unpack genqmail-${GENQMAIL_PV}.tar.bz2
}

# @FUNCTION: qmail_src_postunpack
# @DESCRIPTION:
# Unpack common config files, apply custom patches if supplied and
# set built configuration (CFLAGS, LDFLAGS, etc)
qmail_src_postunpack() {
	cd "${S}"

	if [[ -n "${QMAIL_PATCH_DIR}" && -d "${QMAIL_PATCH_DIR}" ]]; then
		echo
		ewarn "You enabled custom patches from ${QMAIL_PATCH_DIR}."
		ewarn "Be warned that you won't get any support when using "
		ewarn "this feature. You're on your own from now!"
		ebeep
		epatch "${QMAIL_PATCH_DIR}/"*
		echo
	fi

	qmail_set_cc

	mysplit="${QMAIL_CONF_SPLIT:-23}"
	is_prime ${mysplit} || die 'QMAIL_CONF_SPLIT is not a prime number.'
	einfo "Using conf-split value of ${mysplit}."
	echo -n "${mysplit}" > ./conf-split
}

# @FUNCTION: qmail_src_install
# @DESCRIPTION:
# This ugly function tries to install qmail binaries, config files and man pages
# with sane permissions in ${QMAIL_HOME}. It will only install a subset of files
# for mini-qmail.
qmail_base_install() {
	einfo "Setting up directory hierarchy ..."
	diropts -m 755 -o root -g qmail
	keepdir ${QMAIL_HOME}/{,control}
	qmail_mini || keepdir ${QMAIL_HOME}/{bin,boot,users}

	diropts -m 755 -o alias -g qmail
	qmail_mini || keepdir ${QMAIL_HOME}/alias

	einfo "Installing the qmail software ..."
	insinto ${QMAIL_HOME}/bin
	insopts -o root -g qmail -m 711

	doins datemail elq forward maildir2mbox maildirmake \
		maildirwatch mailsubj pinq predate qail \
		qmail-{inject,qmqpc,showctl} sendmail

	if qmail_mini; then
		dosym qmail-qmqpc ${QMAIL_HOME}/bin/qmail-queue

		newins config-mini.sh config-mini
		dosed "s:QMAIL:${QMAIL_HOME}:g" ${QMAIL_HOME}/bin/config-mini
	else
		doins bouncesaying condredirect config-fast except \
		preline qbiff qmail-{pop3d,popup,qmqpd,qmtpd,qread} \
		qmail-{qstat,smtpd,tcpok,tcpto} qreceipt qsmhook tcp-env

		insopts -o root -g qmail -m 700
		doins qmail-{lspawn,start,newu,newmrh}

		insopts -o qmailq -g qmail -m 4711
		doins qmail-queue

		insopts -o root -g qmail -m 711
		doins qmail-{getpw,local,remote,rspawn,clean,send,pw2u} splogger

		insinto ${QMAIL_HOME}/boot
		insopts -o root -g qmail -m 755
		doins {home,proc,binm1,binm2,binm3}{,+df}
	fi

	einfo "Installing manpages ..."
	into /usr
	doman *.[1-8]
	dodoc BLURB* CHANGES FAQ INSTALL* PIC* README* REMOVE* SECURITY \
		SENDMAIL SYSDEPS TARGETS TEST* THANKS* THOUGHTS TODO* \
		UPGRADE VERSION*

	einfo "Adding env.d entry for qmail"
	insopts -m 644
	doenvd "${GENQMAIL_S}"/conf/99qmail

	einfo "Creating sendmail replacement ..."
	diropts -m 755
	dodir /usr/sbin /usr/lib

	if use mailwrapper; then
		insinto /etc/mail
		doins "${GENQMAIL_S}"/conf/mailer.conf
	else
		dosym ${QMAIL_HOME}/bin/sendmail /usr/sbin/sendmail
		dosym ${QMAIL_HOME}/bin/sendmail /usr/lib/sendmail
	fi
}

qmail_maildir_install() {
	# use the correct maildirmake
	# the courier-imap one has some extensions that are nicer
	[[ -e /usr/bin/maildirmake ]] && \
		MAILDIRMAKE="/usr/bin/maildirmake" || \
		MAILDIRMAKE="${D}${QMAIL_HOME}/bin/maildirmake"

	einfo "Setting up the default aliases ..."
	diropts -m 700 -o alias -g qmail
	${MAILDIRMAKE} ${D}${QMAIL_HOME}/alias/.maildir
	keepdir ${QMAIL_HOME}/alias/.maildir/{cur,new,tmp}

	for i in ${QMAIL_HOME}/alias/.qmail-{mailer-daemon,postmaster,root}; do
		if [[ ! -f ${i} ]]; then
			touch ${D}${i}
			fowners alias:qmail ${i}
		fi
	done

	einfo "Setting up maildirs by default in the account skeleton ..."
	diropts -m 755 -o root -g root
	insinto /etc/skel
	newins "${GENQMAIL_S}"/control/defaultdelivery .qmail.sample
	fperms 644 /etc/skel/.qmail.sample
	${MAILDIRMAKE} ${D}/etc/skel/.maildir
	keepdir /etc/skel/.maildir/{cur,new,tmp}
}

qmail_supervise_install() {
	einfo "Setting up all services (send, smtp, qmtp, qmqp, pop3) ..."
	insopts -o root -g root -m 755
	diropts -m 755 -o root -g root
	dodir ${QMAIL_HOME}/supervise

	for i in qmail-{send,smtpd,qmtpd,qmqpd,pop3d}; do
		insopts -o root -g root -m 755
		diropts -m 755 -o root -g root

		dodir ${QMAIL_HOME}/supervise/${i}{,/log}
		fperms +t ${QMAIL_HOME}/supervise/${i}{,/log}

		insinto ${QMAIL_HOME}/supervise/${i}
		newins ${GENQMAIL_S}/supervise/${i} run

		insinto ${QMAIL_HOME}/supervise/${i}/log
		newins ${GENQMAIL_S}/supervise/${i}-log run

		diropts -m 755 -o qmaill
		keepdir /var/log/qmail/${i}
	done
}

qmail_config_install() {
	einfo "Installing some stock configuration files"
	insinto ${QMAIL_HOME}/control
	insopts -o root -g root -m 644
	doins "${GENQMAIL_S}"/control/conf-{common,send,qmtpd,qmqpd,pop3d,smtpd}
	doins "${GENQMAIL_S}"/control/defaultdelivery

	einfo "Configuration sanity checker and launcher"
	insinto ${QMAIL_HOME}/bin
	insopts -o root -g root -m 644
	doins "${GENQMAIL_S}"/control/qmail-config-system
}

qmail_spp_install() {
	einfo "Installing files for qmail-spp"
	keepdir ${QMAIL_HOME}/plugins/
	insinto ${QMAIL_HOME}/control/
	insopts -o root -g root -m 644
	doins "${QMAIL_SPP_S}"/samples/smtpplugins
}

qmail_ssl_install() {
	CRON_FOLDER=cron.hourly
	gencertdaily && CRON_FOLDER=cron.daily

	einfo "Installing SSL Certificate creation script"
	insinto ${QMAIL_HOME}/control
	insopts -o root -g root -m 644
	doins "${GENQMAIL_S}"/ssl/servercert.cnf

	insinto ${QMAIL_HOME}/bin
	insopts -o root -g root -m 700
	doins "${GENQMAIL_S}"/ssl/mkservercert

	einfo "Installing RSA key generation cronjob"
	insinto /etc/${CRON_FOLDER}
	insopts -o root -g root -m 755
	doins "${GENQMAIL_S}"/ssl/qmail-genrsacert.sh

	keepdir ${QMAIL_HOME}/control/tlshosts
}

qmail_ssl_generate() {
	CRON_FOLDER=cron.hourly
	gencertdaily && CRON_FOLDER=cron.daily

	ebegin "Generating RSA keys for SSL/TLS, this can take some time"
	${ROOT}/etc/${CRON_FOLDER}/qmail-genrsacert.sh
	eend $?

	einfo "Creating a self-signed ssl-certificate:"
	${ROOT}${QMAIL_HOME}/bin/mkservercert

	einfo "If you want to have a properly signed certificate "
	einfo "instead, do the following:"
	# space at the end of the string because of the current implementation
	# of einfo
	einfo "openssl req -new -nodes -out req.pem \\ "
	einfo "  -config ${QMAIL_HOME}/control/servercert.cnf \\ "
	einfo "  -keyout ${QMAIL_HOME}/control/servercert.pem"
	einfo "Send req.pem to your CA to obtain signed_req.pem, and do:"
	einfo "cat signed_req.pem >> ${QMAIL_HOME}/control/servercert.pem"
}

qmail_tcprules_install() {
	dodir ${TCPRULES_DIR}
	insinto ${TCPRULES_DIR}
	doins "${GENQMAIL_S}"/tcprules/Makefile.qmail
	doins "${GENQMAIL_S}"/tcprules/tcp.qmail-{smtp,qmtp,qmqp,pop3}
}

qmail_tcprules_config() {
	einfo "Accepting relaying by default from all ips configured on this machine."
	LOCALIPS=$(/sbin/ifconfig | grep inet | cut -d' ' -f 12 -s | cut -b 6-20)
	TCPSTRING=":allow,RELAYCLIENT=\"\",RBLSMTPD=\"\""
	for ip in $LOCALIPS; do
		myline="${ip}${TCPSTRING}"
		for proto in smtp qmtp qmqp; do
			f="${ROOT}${TCPRULES_DIR}/tcp.qmail-${proto}"
			egrep -q "${myline}" ${f} || echo "${myline}" >> ${f}
		done
	done
}

qmail_tcprules_build() {
	for f in tcp.qmail-{smtp,qmtp,qmqp,pop3}; do
		# please note that we don't check if it exists
		# as we want it to make the cdb files anyway!
		src=${ROOT}${TCPRULES_DIR}/${f}
		cdb=${ROOT}${TCPRULES_DIR}/${f}.cdb
		tmp=${ROOT}${TCPRULES_DIR}/.${f}.tmp
		[[ -e ${src} ]] && tcprules ${cdb} ${tmp} < ${src}
	done
}

qmail_tcprules_fixup() {
	mkdir -p ${TCPRULES_DIR}
	for f in {smtp,qmtp,qmqp,pop3}{,.cdb}; do
		old="/etc/tcp.${f}"
		new="${TCPRULES_DIR}/tcp.qmail-${f}"
		fail=0
		if [[ -f "$old" && ! -f "$new" ]]; then
			einfo "Moving $old to $new"
			cp $old $new || fail=1
		else
			fail=1
		fi
		if [[ "${fail}" = 1 && -f ${old} ]]; then
			eerror "Error moving $old to $new, be sure to check the"
			eerror "configuration! You may have already moved the files,"
			eerror "in which case you can delete $old"
		fi
	done
}

qmail_rootmail_fixup() {
	local TMPCMD="ln -sf ${QMAIL_HOME}/alias/.maildir/ ${ROOT}/root/.maildir"

	if [[ -d "${ROOT}/root/.maildir" && ! -L "${ROOT}/root/.maildir" ]] ; then
		elog "Previously the qmail ebuilds created /root/.maildir/ but not"
		elog "every mail was delivered there. If the directory does not"
		elog "contain any mail, please delete it and run:"
		elog "${TMPCMD}"
	else
		${TMPCMD}
	fi

	chown -R alias:qmail ${ROOT}${QMAIL_HOME}/alias/.maildir 2>/dev/null
}

qmail_queue_setup() {
	if [[ -n ${QMAIL_BIGTODO_PV} ]] && use highvolume; then
		myconf="--bigtodo"
	else
		myconf="--no-bigtodo"
	fi

	mysplit="${QMAIL_CONF_SPLIT:-23}"
	is_prime ${mysplit} || die 'QMAIL_CONF_SPLIT is not a prime number.'
	einfo "Using conf-split value of ${mysplit}."
	echo -n "${mysplit}" > ./conf-split

	einfo "Setting up the message queue hierarchy ..."

	/usr/bin/queue-repair.py --create ${myconf} \
		--split "${mysplit}" \
		${ROOT}${QMAIL_HOME} >/dev/null || \
		die 'queue-repair failed'
}

qmail_config_notice() {
	elog "To setup qmail to run out-of-the-box on your system, run:"
	elog "emerge --config =${CATEGORY}/${PF}"
	elog
	elog "To start qmail at boot you have to add svscan to your startup"
	elog "and create the following links:"
	elog "ln -s ${QMAIL_HOME}/supervise/qmail-send /service/qmail-send"
	elog "ln -s ${QMAIL_HOME}/supervise/qmail-smtpd /service/qmail-smtpd"
	elog
	elog "To start the pop3 server as well, create the following link:"
	elog "ln -s ${QMAIL_HOME}/supervise/qmail-pop3d /service/qmail-pop3d"
	elog
	elog "Additionally, the QMTP and QMQP protocols are supported, "
	elog "and can be started as:"
	elog "ln -s ${QMAIL_HOME}/supervise/qmail-qmtpd /service/qmail-qmtpd"
	elog "ln -s ${QMAIL_HOME}/supervise/qmail-qmqpd /service/qmail-qmqpd"
	elog
	elog "Additionally, if you wish to run qmail right now, you should "
	elog "run this before anything else:"
	elog "source /etc/profile"
}

qmail_config_fast() {
	if [[ ${ROOT} = / ]] ; then
		if [[ ! -f ${ROOT}${QMAIL_HOME}/control/me ]] ; then
			${ROOT}${QMAIL_HOME}/bin/config-fast $(hostname --fqdn)
		fi
	else
		ewarn "Skipping some configuration as it MUST be run on the final host"
	fi
}
