meson.eclass: Don't mix host *FLAGS with build *FLAGS
[gentoo.git] / eclass / qmail.eclass
1 # Copyright 1999-2012 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3
4 # @ECLASS: qmail.eclass
5 # @MAINTAINER:
6 # qmail-bugs@gentoo.org
7 # @BLURB: common qmail functions
8
9 inherit flag-o-matic toolchain-funcs fixheadtails user
10
11 # hardcoded paths
12 QMAIL_HOME="/var/qmail"
13 TCPRULES_DIR="/etc/tcprules.d"
14 SUPERVISE_DIR="/var/qmail/supervise"
15
16 # source files and directories
17 GENQMAIL_F=genqmail-${GENQMAIL_PV}.tar.bz2
18 GENQMAIL_S="${WORKDIR}"/genqmail-${GENQMAIL_PV}
19
20 QMAIL_SPP_F=qmail-spp-${QMAIL_SPP_PV}.tar.gz
21 QMAIL_SPP_S="${WORKDIR}"/qmail-spp-${QMAIL_SPP_PV}
22
23 # @FUNCTION: primes
24 # @USAGE: <min> <max>
25 # @DESCRIPTION:
26 # Prints a list of primes between min and max inclusive
27 # Note: this functions gets very slow when used with large numbers.
28 primes() {
29         local min=${1} max=${2}
30         local result= primelist=2 i p
31
32         [[ ${min} -le 2 ]] && result="${result} 2"
33
34         for ((i = 3; i <= max; i += 2))
35         do
36                 for p in ${primelist}
37                 do
38                         [[ $[i % p] == 0 || $[p * p] -gt ${i} ]] && \
39                                 break
40                 done
41                 if [[ $[i % p] != 0 ]]
42                 then
43                         primelist="${primelist} ${i}"
44                         [[ ${i} -ge ${min} ]] && \
45                                 result="${result} ${i}"
46                 fi
47         done
48
49         echo ${result}
50 }
51
52 # @FUNCTION: is_prima
53 # @USAGE: <number>
54 # @DESCRIPTION:
55 # Checks wether a number is a prime number
56 is_prime() {
57         local number=${1} i
58         for i in $(primes ${number} ${number})
59         do
60                 [[ ${i} == ${number} ]] && return 0
61         done
62         return 1
63 }
64
65 dospp() {
66         insinto "${QMAIL_HOME}"/plugins/
67         insopts -o root -g "$GROUP_ROOT" -m 0755
68         newins $1 ${2:-$(basename $1)}
69 }
70
71 # @FUNCTION: dosupervise
72 # @USAGE: dosupervise <service> [<runfile> <logfile>]
73 # @DESCRIPTION:
74 # Install runfiles for services and logging to supervise directory
75 dosupervise() {
76         local service=$1
77         local runfile=${2:-${service}} logfile=${3:-${service}-log}
78         [[ -z "${service}" ]] && die "no service given"
79
80         insopts -o root -g "$GROUP_ROOT" -m 0755
81         diropts -o root -g "$GROUP_ROOT" -m 0755
82
83         dodir ${SUPERVISE_DIR}/${service}{,/log}
84         fperms +t ${SUPERVISE_DIR}/${service}{,/log}
85
86         insinto ${SUPERVISE_DIR}/${service}
87         newins ${runfile} run
88
89         insinto ${SUPERVISE_DIR}/${service}/log
90         newins ${logfile} run
91 }
92
93 # @FUNCTION: qmail_set_cc
94 # @DESCRIPTION:
95 # The following commands patch the conf-{cc,ld} files to use the user's
96 # specified CFLAGS and LDFLAGS. These rather complex commands are needed
97 # because a user supplied patch might apply changes to these files, too.
98 # See bug #165981.
99 qmail_set_cc() {
100         local cc=$(head -n 1 ./conf-cc | sed -e "s#^g\?cc\s\+\(-O2\)\?#$(tc-getCC) #")
101         local ld=$(head -n 1 ./conf-ld | sed -e "s#^g\?cc\s\+\(-s\)\?#$(tc-getCC) #")
102
103         echo "${cc} ${CFLAGS} ${CPPFLAGS}"  > ./conf-cc || die 'Patching conf-cc failed.'
104         echo "${ld} ${LDFLAGS}" > ./conf-ld || die 'Patching conf-ld failed.'
105 }
106
107 # @FUNCTION: qmail_create_groups
108 # @DESCRIPTION:
109 # Keep qmail groups in sync across ebuilds
110 qmail_create_groups() {
111         einfo "Creating qmail groups"
112         enewgroup nofiles 200
113         enewgroup qmail 201
114 }
115
116 # @FUNCTION: qmail_create_users
117 # @DESCRIPTION:
118 # Keep qmail users in sync across ebuilds
119 qmail_create_users() {
120         qmail_create_groups
121
122         einfo "Creating qmail users"
123         enewuser alias 200 -1  "${QMAIL_HOME}"/alias 200
124         enewuser qmaild 201 -1 "${QMAIL_HOME}" 200
125         enewuser qmaill 202 -1 "${QMAIL_HOME}" 200
126         enewuser qmailp 203 -1 "${QMAIL_HOME}" 200
127         enewuser qmailq 204 -1 "${QMAIL_HOME}" 201
128         enewuser qmailr 205 -1 "${QMAIL_HOME}" 201
129         enewuser qmails 206 -1 "${QMAIL_HOME}" 201
130 }
131
132 genqmail_src_unpack() {
133         cd "${WORKDIR}"
134         [[ -n ${GENQMAIL_PV} ]] && unpack "${GENQMAIL_F}"
135 }
136
137 qmail_spp_src_unpack() {
138         cd "${WORKDIR}"
139         [[ -n ${QMAIL_SPP_PV} ]] && unpack "${QMAIL_SPP_F}"
140 }
141
142 # @FUNCTION: qmail_src_postunpack
143 # @DESCRIPTION:
144 # Unpack common config files, apply custom patches if supplied and
145 # set built configuration (CFLAGS, LDFLAGS, etc)
146 qmail_src_postunpack() {
147         cd "${S}"
148
149         qmail_set_cc
150
151         mysplit=${QMAIL_CONF_SPLIT:-23}
152         is_prime ${mysplit} || die "QMAIL_CONF_SPLIT is not a prime number."
153         einfo "Using conf-split value of ${mysplit}."
154         echo -n ${mysplit} > "${S}"/conf-split
155 }
156
157 qmail_src_compile() {
158         cd "${S}"
159         emake it man "$@" || die "make failed"
160 }
161
162 qmail_spp_src_compile() {
163         cd "${GENQMAIL_S}"/spp/
164         emake || die "make spp failed"
165 }
166
167 qmail_base_install() {
168         einfo "Setting up basic directory hierarchy"
169         diropts -o root -g qmail -m 755
170         keepdir "${QMAIL_HOME}"/{,bin,control}
171
172         einfo "Installing basic qmail software"
173         insinto "${QMAIL_HOME}"/bin
174
175         insopts -o root -g qmail -m 755
176         doins datemail elq forward maildir2mbox maildirmake \
177                 maildirwatch mailsubj pinq predate qail \
178                 qmail-{inject,qmqpc,showctl} sendmail
179
180         einfo "Adding env.d entry for qmail"
181         doenvd "${GENQMAIL_S}"/conf/99qmail
182
183         declare -F qmail_base_install_hook >/dev/null && \
184                 qmail_base_install_hook
185 }
186
187 qmail_full_install() {
188         einfo "Setting up full directory hierarchy"
189         keepdir "${QMAIL_HOME}"/users
190         diropts -o alias -g qmail -m 755
191         keepdir "${QMAIL_HOME}"/alias
192
193         einfo "Installing all qmail software"
194         insopts -o root -g qmail -m 755
195         doins bouncesaying condredirect config-fast except preline qbiff \
196                 qmail-{pop3d,qmqpd,qmtpd,qread,qstat,smtpd,tcpok,tcpto} \
197                 qreceipt qsmhook tcp-env
198
199         insopts -o root -g qmail -m 711
200         doins qmail-{clean,getpw,local,popup,pw2u,remote,rspawn,send} splogger
201
202         insopts -o root -g qmail -m 700
203         doins qmail-{lspawn,newmrh,newu,start}
204
205         insopts -o qmailq -g qmail -m 4711
206         doins qmail-queue
207
208         declare -F qmail_full_install_hook >/dev/null && \
209                 qmail_full_install_hook
210 }
211
212 qmail_config_install() {
213         einfo "Installing stock configuration files"
214         insinto "${QMAIL_HOME}"/control
215         insopts -o root -g "$GROUP_ROOT" -m 644
216         doins "${GENQMAIL_S}"/control/{conf-*,defaultdelivery}
217
218         einfo "Installing configuration sanity checker and launcher"
219         insinto "${QMAIL_HOME}"/bin
220         insopts -o root -g "$GROUP_ROOT" -m 644
221         doins "${GENQMAIL_S}"/control/qmail-config-system
222
223         declare -F qmail_config_install_hook >/dev/null && \
224                 qmail_config_install_hook
225 }
226
227 qmail_man_install() {
228         einfo "Installing manpages and documentation"
229
230         # those are tagged for section 8 but named for
231         # section 9 (which does not exist anyway)
232         for i in *.9; do
233                 mv ${i} ${i/.9/.8}
234         done
235
236         into /usr
237         doman *.[1578]
238         dodoc BLURB* CHANGES FAQ INSTALL* PIC* README* REMOVE* SECURITY \
239                 SENDMAIL SYSDEPS TEST* THANKS* THOUGHTS TODO* \
240                 UPGRADE VERSION*
241
242         declare -F qmail_man_install_hook >/dev/null && \
243                 qmail_man_install_hook
244 }
245
246 qmail_sendmail_install() {
247         einfo "Installing sendmail replacement"
248         diropts -m 755
249         dodir /usr/sbin /usr/lib
250
251         dosym "${QMAIL_HOME}"/bin/sendmail /usr/sbin/sendmail
252         dosym "${QMAIL_HOME}"/bin/sendmail /usr/lib/sendmail
253
254         declare -F qmail_sendmail_install_hook >/dev/null && \
255                 qmail_sendmail_install_hook
256 }
257
258 qmail_maildir_install() {
259         # use the correct maildirmake
260         # the courier-imap one has some extensions that are nicer
261         MAILDIRMAKE="${D}${QMAIL_HOME}/bin/maildirmake"
262         [[ -e /usr/bin/maildirmake ]] && \
263                 MAILDIRMAKE="/usr/bin/maildirmake"
264
265         einfo "Setting up the default aliases"
266         diropts -o alias -g qmail -m 700
267         "${MAILDIRMAKE}" "${D}${QMAIL_HOME}"/alias/.maildir
268         keepdir "${QMAIL_HOME}"/alias/.maildir/{cur,new,tmp}
269
270         for i in "${QMAIL_HOME}"/alias/.qmail-{mailer-daemon,postmaster,root}; do
271                 if [[ ! -f "${ROOT}${i}" ]]; then
272                         touch "${D}${i}"
273                         fowners alias:qmail "${i}"
274                 fi
275         done
276
277         einfo "Setting up default maildirs in the account skeleton"
278         diropts -o root -g "$GROUP_ROOT" -m 755
279         insinto /etc/skel
280         insopts -o root -g "$GROUP_ROOT" -m 644
281         newins "${GENQMAIL_S}"/control/defaultdelivery .qmail.sample
282         "${MAILDIRMAKE}" "${D}"/etc/skel/.maildir
283         keepdir /etc/skel/.maildir/{cur,new,tmp}
284
285         declare -F qmail_maildir_install_hook >/dev/null && \
286                 qmail_maildir_install_hook
287 }
288
289 qmail_tcprules_install() {
290         dodir "${TCPRULES_DIR}"
291         insinto "${TCPRULES_DIR}"
292         insopts -o root -g "$GROUP_ROOT" -m 0644
293         doins "${GENQMAIL_S}"/tcprules/Makefile.qmail
294         doins "${GENQMAIL_S}"/tcprules/tcp.qmail-*
295         use ssl || rm -f "${D}${TCPRULES_DIR}"/tcp.qmail-pop3sd
296 }
297
298 qmail_supervise_install() {
299         einfo "Installing supervise scripts"
300
301         cd "${GENQMAIL_S}"/supervise
302
303         for i in qmail-{send,smtpd,qmtpd,qmqpd,pop3d}; do
304                 dosupervise ${i}
305                 diropts -o qmaill -g "$GROUP_ROOT" -m 755
306                 keepdir /var/log/qmail/${i}
307         done
308
309         if use ssl; then
310                 dosupervise qmail-pop3sd
311                 diropts -o qmaill -g "$GROUP_ROOT" -m 755
312                 keepdir /var/log/qmail/qmail-pop3sd
313         fi
314
315         declare -F qmail_supervise_install_hook >/dev/null && \
316                 qmail_supervise_install_hook
317 }
318
319 qmail_spp_install() {
320         einfo "Installing qmail-spp configuration files"
321         insinto "${QMAIL_HOME}"/control/
322         insopts -o root -g "$GROUP_ROOT" -m 0644
323         doins "${GENQMAIL_S}"/spp/smtpplugins
324
325         einfo "Installing qmail-spp plugins"
326         keepdir "${QMAIL_HOME}"/plugins/
327         for i in authlog mfdnscheck ifauthnext tarpit; do
328                 dospp "${GENQMAIL_S}"/spp/${i}
329         done
330
331         declare -F qmail_spp_install_hook >/dev/null && \
332                 qmail_spp_install_hook
333 }
334
335 qmail_ssl_install() {
336         use gencertdaily && \
337                 CRON_FOLDER=cron.daily || \
338                 CRON_FOLDER=cron.hourly
339
340         einfo "Installing SSL Certificate creation script"
341         insinto "${QMAIL_HOME}"/control
342         insopts -o root -g "$GROUP_ROOT" -m 0644
343         doins "${GENQMAIL_S}"/ssl/servercert.cnf
344
345         insinto "${QMAIL_HOME}"/bin
346         insopts -o root -g "$GROUP_ROOT" -m 0755
347         doins "${GENQMAIL_S}"/ssl/mkservercert
348
349         einfo "Installing RSA key generation cronjob"
350         insinto /etc/${CRON_FOLDER}
351         insopts -o root -g "$GROUP_ROOT" -m 0755
352         doins "${GENQMAIL_S}"/ssl/qmail-genrsacert.sh
353
354         keepdir "${QMAIL_HOME}"/control/tlshosts
355
356         declare -F qmail_ssl_install_hook >/dev/null && \
357                 qmail_ssl_install_hook
358 }
359
360 qmail_src_install() {
361         export GROUP_ROOT="$(id -gn root)"
362         qmail_base_install
363         qmail_full_install
364         qmail_config_install
365         qmail_man_install
366         qmail_sendmail_install
367         qmail_maildir_install
368         qmail_tcprules_install
369         qmail_supervise_install
370
371         use qmail-spp && qmail_spp_install
372         use ssl && qmail_ssl_install
373 }
374
375 qmail_queue_setup() {
376         if use highvolume; then
377                 myconf="--bigtodo"
378         else
379                 myconf="--no-bigtodo"
380         fi
381
382         mysplit=${QMAIL_CONF_SPLIT:-23}
383         is_prime ${mysplit} || die "QMAIL_CONF_SPLIT is not a prime number."
384
385         einfo "Setting up the message queue hierarchy"
386         /usr/bin/queue-repair.py --create ${myconf} \
387                 --split ${mysplit} \
388                 "${ROOT}${QMAIL_HOME}" >/dev/null || \
389                 die 'queue-repair failed'
390 }
391
392 qmail_rootmail_fixup() {
393         local TMPCMD="ln -sf ${QMAIL_HOME}/alias/.maildir/ ${ROOT}/root/.maildir"
394
395         if [[ -d "${ROOT}"/root/.maildir && ! -L "${ROOT}"/root/.maildir ]] ; then
396                 elog "Previously the qmail ebuilds created /root/.maildir/ but not"
397                 elog "every mail was delivered there. If the directory does not"
398                 elog "contain any mail, please delete it and run:"
399                 elog "${TMPCMD}"
400         else
401                 ${TMPCMD}
402         fi
403
404         chown -R alias:qmail "${ROOT}${QMAIL_HOME}"/alias/.maildir 2>/dev/null
405 }
406
407 qmail_tcprules_fixup() {
408         mkdir -p "${TCPRULES_DIR}"
409         for f in {smtp,qmtp,qmqp,pop3}{,.cdb}; do
410                 old="/etc/tcp.${f}"
411                 new="${TCPRULES_DIR}/tcp.qmail-${f}"
412                 fail=0
413                 if [[ -f "${old}" && ! -f "${new}" ]]; then
414                         einfo "Moving ${old} to ${new}"
415                         cp "${old}" "${new}" || fail=1
416                 else
417                         fail=1
418                 fi
419                 if [[ "${fail}" = 1 && -f "${old}" ]]; then
420                         eerror "Error moving ${old} to ${new}, be sure to check the"
421                         eerror "configuration! You may have already moved the files,"
422                         eerror "in which case you can delete ${old}"
423                 fi
424         done
425 }
426
427 qmail_tcprules_build() {
428         for f in tcp.qmail-{smtp,qmtp,qmqp,pop3,pop3s}; do
429                 # please note that we don't check if it exists
430                 # as we want it to make the cdb files anyway!
431                 src="${ROOT}${TCPRULES_DIR}/${f}"
432                 cdb="${ROOT}${TCPRULES_DIR}/${f}.cdb"
433                 tmp="${ROOT}${TCPRULES_DIR}/.${f}.tmp"
434                 [[ -e "${src}" ]] && tcprules "${cdb}" "${tmp}" < "${src}"
435         done
436 }
437
438 qmail_config_notice() {
439         elog
440         elog "To setup ${PN} to run out-of-the-box on your system, run:"
441         elog "emerge --config =${CATEGORY}/${PF}"
442 }
443
444 qmail_supervise_config_notice() {
445         elog
446         elog "To start qmail at boot you have to add svscan to your startup"
447         elog "and create the following links:"
448         elog "ln -s ${SUPERVISE_DIR}/qmail-send /service/qmail-send"
449         elog "ln -s ${SUPERVISE_DIR}/qmail-smtpd /service/qmail-smtpd"
450         elog
451         elog "To start the pop3 server as well, create the following link:"
452         elog "ln -s ${SUPERVISE_DIR}/qmail-pop3d /service/qmail-pop3d"
453         elog
454         if use ssl; then
455                 elog "To start the pop3s server as well, create the following link:"
456                 elog "ln -s ${SUPERVISE_DIR}/qmail-pop3sd /service/qmail-pop3sd"
457                 elog
458         fi
459         elog "Additionally, the QMTP and QMQP protocols are supported, "
460         elog "and can be started as:"
461         elog "ln -s ${SUPERVISE_DIR}/qmail-qmtpd /service/qmail-qmtpd"
462         elog "ln -s ${SUPERVISE_DIR}/qmail-qmqpd /service/qmail-qmqpd"
463         elog
464         elog "Additionally, if you wish to run qmail right now, you should "
465         elog "run this before anything else:"
466         elog "source /etc/profile"
467 }
468
469 qmail_config_fast() {
470         if [[ ${ROOT} = / ]]; then
471                 local host=$(hostname --fqdn)
472
473                 if [[ -z "${host}" ]]; then
474                         eerror
475                         eerror "Cannot determine your fully-qualified hostname"
476                         eerror "Please setup your /etc/hosts as described in"
477                         eerror "https://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=1&chap=8#doc_chap2_sect4"
478                         eerror
479                         die "cannot determine FQDN"
480                 fi
481
482                 if [[ ! -f "${ROOT}${QMAIL_HOME}"/control/me ]]; then
483                         "${ROOT}${QMAIL_HOME}"/bin/config-fast ${host}
484                 fi
485         else
486                 ewarn "Skipping some configuration as it MUST be run on the final host"
487         fi
488 }
489
490 qmail_tcprules_config() {
491         local localips ip tcpstring line proto f
492
493         einfo "Accepting relaying by default from all ips configured on this machine."
494
495         # Start with iproute2 as ifconfig is deprecated, and ifconfig does not handle
496         # additional addresses added via iproute2.
497         # Note: We have to strip off the packed netmask w/e.g. 192.168.0.2/24
498         localips=$(ip address show 2>/dev/null | awk '$1 == "inet" {print $2}' | sed 's:/.*::')
499         if [[ -z ${localips} ]] ; then
500                 # Hello old friend.  Maybe you can tell us at least something.
501                 localips=$(ifconfig | awk '$1 == "inet" {print $2}')
502         fi
503
504         tcpstring=':allow,RELAYCLIENT="",RBLSMTPD=""'
505
506         for ip in ${localips}; do
507                 line="${ip}${tcpstring}"
508                 for proto in smtp qmtp qmqp; do
509                         f="${EROOT}${TCPRULES_DIR}/tcp.qmail-${proto}"
510                         egrep -qs "${line}" "${f}" || echo "${line}" >> "${f}"
511                 done
512         done
513 }
514
515 qmail_ssl_generate() {
516         CRON_FOLDER=cron.hourly
517         use gencertdaily && CRON_FOLDER=cron.daily
518
519         ebegin "Generating RSA keys for SSL/TLS, this can take some time"
520         "${ROOT}"/etc/${CRON_FOLDER}/qmail-genrsacert.sh
521         eend $?
522
523         einfo "Creating a self-signed ssl-certificate:"
524         "${ROOT}${QMAIL_HOME}"/bin/mkservercert
525
526         einfo "If you want to have a properly signed certificate "
527         einfo "instead, do the following:"
528         # space at the end of the string because of the current implementation
529         # of einfo
530         einfo "openssl req -new -nodes -out req.pem \\ "
531         einfo "  -config ${QMAIL_HOME}/control/servercert.cnf \\ "
532         einfo "  -keyout ${QMAIL_HOME}/control/servercert.pem"
533         einfo "Send req.pem to your CA to obtain signed_req.pem, and do:"
534         einfo "cat signed_req.pem >> ${QMAIL_HOME}/control/servercert.pem"
535 }