From b666b297dd3bce7fd3ccd8d350858bc2a737315f Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Sat, 9 Nov 2019 15:51:19 +0200 Subject: Reorganize testsuite Simplify Makefile.am's in tests subdirectories by moving the common part in a separate file and including it where necessary. Build only one copy of package.m4. Both package.m4 and include file testsuite.am reside in the testsuite directory. Also provide configure options for selecting mda components to build: --disable-build-mda do not build mda --disable-build-lmtpd do not build lmtpd --disable-build-putmail do not build putmail * .gitignore: Update. * Makefile.am [MU_COND_MDA]: Change to MU_COND_MDA_TOOLS * configure.ac: Provide a way to enable/disable building of mda, lmtpd and putmail separately. Build testsuite/package.m4 * testsuite/testsuite.am * testsuite/Makefile.am: Distribute both package.m4.in and package.m4. Include main part from testsuite.am * testsuite/package.m4.in: New file. * comsat/tests/Makefile.am: Include main part from testsuite.am * frm/tests/Makefile.am: Likewise. * imap4d/tests/Makefile.am: Likewise. * libmailutils/tests/Makefile.am: Likewise. * libmu_scm/tests/Makefile.am: Likewise. * libproto/dotmail/tests/Makefile.am: Likewise. * mail/tests/Makefile.am: Likewise. * messages/tests/Makefile.am: Likewise. * mh/tests/Makefile.am: Likewise. * mimeview/tests/Makefile.am: Likewise. * readmsg/tests/Makefile.am: Likewise. * sieve/tests/Makefile.am: Likewise. * mda/.gitignore: Remove. * mda/tests/Makefile.am: Remove. * mda/tests/testsuite.at: Remove. * mda/tests/.gitignore: Remove. * mda/tests/atlocal.in: Remove. * mda/tests/mda.inc: New file. * mda/Makefile.am: Add extra directory level. Add subdirs depending on whether the corresponding component is selected for building. * mda/lmtpd/.gitignore: New file. * mda/lmtpd/Makefile.am: New file. * mda/lmtpd.c: Move to mda/lmtpd/lmtpd.c * mda/lmtpd/tests/.gitignore: New file. * mda/lmtpd/tests/Makefile.am: New file. * mda/lmtpd/tests/atlocal.in: New file. * mda/tests/lmtpd.at: Move to mda/lmtpd/tests/lmtpd.at * mda/lmtpd/tests/testsuite.at: New file. * mda/mda/.gitignore: New file. * mda/mda/Makefile.am: New file. * mda/mda.c: Move to mda/mda/mda.c * mda/mda/tests/.gitignore: New file. * mda/mda/tests/Makefile.am: New file. * mda/mda/tests/atlocal.in: New file. * mda/tests/forward.at: Move to mda/mda/tests/forward.at * mda/tests/mda.at: Move to mda/mda/tests/mda.at * mda/mda/tests/testsuite.at: New file. * mda/putmail/.gitignore: New file. * mda/putmail/Makefile.am: New file. * mda/putmail.c: Move to mda/putmail/putmail.c * mda/putmail/tests/.gitignore: New file. * mda/putmail/tests/Makefile.am: New file. * mda/putmail/tests/atlocal.in: New file. * mda/tests/putmail.at: Move to mda/putmail/tests/putmail.at * mda/putmail/tests/testsuite.at: New file * po/POTFILES.in: Update pathnames * maint/fullcheck.mk: Minor fixes. --- .gitignore | 3 + Makefile.am | 2 +- comsat/tests/Makefile.am | 65 +-- configure.ac | 14 +- frm/tests/Makefile.am | 65 +-- imap4d/tests/Makefile.am | 48 +- libmailutils/tests/Makefile.am | 53 +-- libmailutils/tests/testsuite.at | 3 + libmu_scm/tests/Makefile.am | 47 +- libproto/dotmail/tests/Makefile.am | 39 +- mail/tests/Makefile.am | 48 +- maint/fullcheck.mk | 11 +- mda/.gitignore | 3 - mda/Makefile.am | 64 +-- mda/lmtpd.c | 902 ------------------------------------- mda/lmtpd/.gitignore | 1 + mda/lmtpd/Makefile.am | 48 ++ mda/lmtpd/lmtpd.c | 902 +++++++++++++++++++++++++++++++++++++ mda/lmtpd/tests/.gitignore | 5 + mda/lmtpd/tests/Makefile.am | 19 + mda/lmtpd/tests/atlocal.in | 6 + mda/lmtpd/tests/lmtpd.at | 58 +++ mda/lmtpd/tests/testsuite.at | 22 + mda/mda.c | 160 ------- mda/mda/.gitignore | 1 + mda/mda/Makefile.am | 50 ++ mda/mda/mda.c | 160 +++++++ mda/mda/tests/.gitignore | 8 + mda/mda/tests/Makefile.am | 55 +++ mda/mda/tests/atlocal.in | 6 + mda/mda/tests/forward.at | 84 ++++ mda/mda/tests/mda.at | 73 +++ mda/mda/tests/testsuite.at | 26 ++ mda/putmail.c | 76 ---- mda/putmail/.gitignore | 1 + mda/putmail/Makefile.am | 43 ++ mda/putmail/putmail.c | 76 ++++ mda/putmail/tests/.gitignore | 5 + mda/putmail/tests/Makefile.am | 20 + mda/putmail/tests/atlocal.in | 6 + mda/putmail/tests/putmail.at | 34 ++ mda/putmail/tests/testsuite.at | 21 + mda/tests/.gitignore | 7 - mda/tests/Makefile.am | 102 ----- mda/tests/atlocal.in | 35 -- mda/tests/forward.at | 84 ---- mda/tests/lmtpd.at | 58 --- mda/tests/mda.at | 73 --- mda/tests/mda.inc | 30 ++ mda/tests/putmail.at | 34 -- mda/tests/testsuite.at | 39 -- messages/tests/Makefile.am | 65 +-- mh/tests/Makefile.am | 50 +- mimeview/tests/Makefile.am | 50 +- po/POTFILES.in | 6 +- readmsg/tests/Makefile.am | 71 +-- sieve/tests/Makefile.am | 53 +-- testsuite/Makefile.am | 55 +-- testsuite/cwdrepl.c | 2 +- testsuite/package.m4.in | 7 + testsuite/testsuite.am | 47 ++ 61 files changed, 1886 insertions(+), 2315 deletions(-) delete mode 100644 mda/.gitignore delete mode 100644 mda/lmtpd.c create mode 100644 mda/lmtpd/.gitignore create mode 100644 mda/lmtpd/Makefile.am create mode 100644 mda/lmtpd/lmtpd.c create mode 100644 mda/lmtpd/tests/.gitignore create mode 100644 mda/lmtpd/tests/Makefile.am create mode 100644 mda/lmtpd/tests/atlocal.in create mode 100644 mda/lmtpd/tests/lmtpd.at create mode 100644 mda/lmtpd/tests/testsuite.at delete mode 100644 mda/mda.c create mode 100644 mda/mda/.gitignore create mode 100644 mda/mda/Makefile.am create mode 100644 mda/mda/mda.c create mode 100644 mda/mda/tests/.gitignore create mode 100644 mda/mda/tests/Makefile.am create mode 100644 mda/mda/tests/atlocal.in create mode 100644 mda/mda/tests/forward.at create mode 100644 mda/mda/tests/mda.at create mode 100644 mda/mda/tests/testsuite.at delete mode 100644 mda/putmail.c create mode 100644 mda/putmail/.gitignore create mode 100644 mda/putmail/Makefile.am create mode 100644 mda/putmail/putmail.c create mode 100644 mda/putmail/tests/.gitignore create mode 100644 mda/putmail/tests/Makefile.am create mode 100644 mda/putmail/tests/atlocal.in create mode 100644 mda/putmail/tests/putmail.at create mode 100644 mda/putmail/tests/testsuite.at delete mode 100644 mda/tests/.gitignore delete mode 100644 mda/tests/Makefile.am delete mode 100644 mda/tests/atlocal.in delete mode 100644 mda/tests/forward.at delete mode 100644 mda/tests/lmtpd.at delete mode 100644 mda/tests/mda.at create mode 100644 mda/tests/mda.inc delete mode 100644 mda/tests/putmail.at delete mode 100644 mda/tests/testsuite.at create mode 100644 testsuite/package.m4.in create mode 100644 testsuite/testsuite.am diff --git a/.gitignore b/.gitignore index e4d9c7afc..5271624b4 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ *.pyo *.so *~ +*.bak .bootstrap .deps .emacs* @@ -39,3 +40,5 @@ stamp-h1 tmp/ /patch/ .gdbinit +conf.*.sh +_fullcheck diff --git a/Makefile.am b/Makefile.am index 716be7a72..2b4920004 100644 --- a/Makefile.am +++ b/Makefile.am @@ -32,7 +32,7 @@ if MU_COND_IMAP4D IMAP4D_DIR = imap4d endif -if MU_COND_MDA +if MU_COND_MDA_TOOLS MDA_DIR = mda endif diff --git a/comsat/tests/Makefile.am b/comsat/tests/Makefile.am index 57c8bd325..cc1e08b02 100644 --- a/comsat/tests/Makefile.am +++ b/comsat/tests/Makefile.am @@ -1,64 +1 @@ -# This file is part of GNU Mailutils. -# Copyright (C) 2010-2019 Free Software Foundation, Inc. -# -# GNU Mailutils 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 3, or (at -# your option) any later version. -# -# GNU Mailutils 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 GNU Mailutils. If not, see . - -EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 -DISTCLEANFILES = atconfig $(check_SCRIPTS) -MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE) - -## ------------ ## -## package.m4. ## -## ------------ ## - -$(srcdir)/package.m4: $(top_srcdir)/configure.ac - $(AM_V_GEN){ \ - echo '# Signature of the current package.'; \ - echo 'm4_define([AT_PACKAGE_NAME], [@PACKAGE_NAME@])'; \ - echo 'm4_define([AT_PACKAGE_TARNAME], [@PACKAGE_TARNAME@])'; \ - echo 'm4_define([AT_PACKAGE_VERSION], [@PACKAGE_VERSION@])'; \ - echo 'm4_define([AT_PACKAGE_STRING], [@PACKAGE_STRING@])'; \ - echo 'm4_define([AT_PACKAGE_BUGREPORT], [@PACKAGE_BUGREPORT@])'; \ - } >$(srcdir)/package.m4 - -# - -## ------------ ## -## Test suite. ## -## ------------ ## - -TESTSUITE_AT = testsuite.at - -TESTSUITE = $(srcdir)/testsuite -M4=m4 - -AUTOTEST = $(AUTOM4TE) --language=autotest -$(TESTSUITE): package.m4 $(TESTSUITE_AT) $(top_srcdir)/testsuite/testsuite.inc - $(AM_V_GEN)$(AUTOTEST) -I $(srcdir) -I $(top_srcdir)/testsuite testsuite.at -o $@.tmp - $(AM_V_at)mv $@.tmp $@ - -atconfig: $(top_builddir)/config.status - cd $(top_builddir) && ./config.status tests/$@ - -clean-local: - @test ! -f $(TESTSUITE) || $(SHELL) $(TESTSUITE) --clean - -check-local: atconfig atlocal $(TESTSUITE) - @$(SHELL) $(TESTSUITE) - -# Run the test suite on the *installed* tree. -#installcheck-local: -# $(SHELL) $(TESTSUITE) AUTOTEST_PATH=$(exec_prefix)/bin - - +include $(top_srcdir)/testsuite/testsuite.am diff --git a/configure.ac b/configure.ac index 175214576..f74b10e02 100644 --- a/configure.ac +++ b/configure.ac @@ -1326,8 +1326,12 @@ MU_ENABLE_BUILD(pop3d,,,["$mu_build_servers" = yes],,[server_list]) MU_ENABLE_BUILD(imap4d,,,["$mu_build_servers" = yes],,[server_list]) MU_ENABLE_BUILD(comsat,,,["$mu_build_servers" = yes],,[server_list]) +MU_ENABLE_BUILD(mda,[mu_build_mda_tools=yes],,["$mu_build_servers" = yes],,[server_list]) +MU_ENABLE_BUILD(lmtpd,[mu_build_mda_tools=yes],,["$mu_build_servers" = yes],,[server_list]) +MU_ENABLE_BUILD(putmail,[mu_build_mda_tools=yes],,["$mu_build_clients" = yes],,[client_list]) +AM_CONDITIONAL([MU_COND_MDA_TOOLS],[test "$mu_build_mda_tools" = yes]) + MU_ENABLE_BUILD(frm,,,["$mu_build_clients" = yes],,[client_list]) -MU_ENABLE_BUILD(mda,,,["$mu_build_clients" = yes],,[client_list]) MU_ENABLE_BUILD(mail,,,["$mu_build_clients" = yes],,[client_list]) AC_SUBST([MAILBINDIR],'${bindir}') @@ -1364,9 +1368,12 @@ test -z "$client_list" && client_list=" [NONE]" AC_CONFIG_TESTDIR(testsuite) AC_CONFIG_FILES([testsuite/Makefile testsuite/atlocal]) +AC_CONFIG_FILES([testsuite/package.m4]) MU_CONFIG_TESTSUITE(libmailutils) MU_CONFIG_TESTSUITE(frm) -MU_CONFIG_TESTSUITE(mda) +MU_CONFIG_TESTSUITE(mda/lmtpd) +MU_CONFIG_TESTSUITE(mda/mda) +MU_CONFIG_TESTSUITE(mda/putmail) MU_CONFIG_TESTSUITE(mail) MU_CONFIG_TESTSUITE(messages) MU_CONFIG_TESTSUITE(readmsg) @@ -1523,6 +1530,9 @@ AC_CONFIG_FILES([ libproto/mailer/Makefile mda/Makefile mda/lib/Makefile + mda/lmtpd/Makefile + mda/mda/Makefile + mda/putmail/Makefile mail/Makefile mail/testsuite/Makefile libmailutils/auth/Makefile diff --git a/frm/tests/Makefile.am b/frm/tests/Makefile.am index 72959ebbd..cc1e08b02 100644 --- a/frm/tests/Makefile.am +++ b/frm/tests/Makefile.am @@ -1,64 +1 @@ -# This file is part of GNU Mailutils. -# Copyright (C) 2007-2019 Free Software Foundation, Inc. -# -# GNU Mailutils 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 3, or (at -# your option) any later version. -# -# GNU Mailutils 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 GNU Mailutils. If not, see . - -EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 -DISTCLEANFILES = atconfig $(check_SCRIPTS) -MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE) - -## ------------ ## -## package.m4. ## -## ------------ ## - -$(srcdir)/package.m4: $(top_srcdir)/configure.ac - $(AM_V_GEN){ \ - echo '# Signature of the current package.'; \ - echo 'm4_define([AT_PACKAGE_NAME], [@PACKAGE_NAME@])'; \ - echo 'm4_define([AT_PACKAGE_TARNAME], [@PACKAGE_TARNAME@])'; \ - echo 'm4_define([AT_PACKAGE_VERSION], [@PACKAGE_VERSION@])'; \ - echo 'm4_define([AT_PACKAGE_STRING], [@PACKAGE_STRING@])'; \ - echo 'm4_define([AT_PACKAGE_BUGREPORT], [@PACKAGE_BUGREPORT@])'; \ - } >$(srcdir)/package.m4 - -# - -## ------------ ## -## Test suite. ## -## ------------ ## - -TESTSUITE_AT = testsuite.at - -TESTSUITE = $(srcdir)/testsuite -M4=m4 - -AUTOTEST = $(AUTOM4TE) --language=autotest -$(TESTSUITE): package.m4 $(TESTSUITE_AT) $(top_srcdir)/testsuite/testsuite.inc - $(AM_V_GEN)$(AUTOTEST) -I $(srcdir) -I $(top_srcdir)/testsuite testsuite.at -o $@.tmp - $(AM_V_at)mv $@.tmp $@ - -atconfig: $(top_builddir)/config.status - cd $(top_builddir) && ./config.status tests/$@ - -clean-local: - @test ! -f $(TESTSUITE) || $(SHELL) $(TESTSUITE) --clean - -check-local: atconfig atlocal $(TESTSUITE) - @$(SHELL) $(TESTSUITE) - -# Run the test suite on the *installed* tree. -#installcheck-local: -# $(SHELL) $(TESTSUITE) AUTOTEST_PATH=$(exec_prefix)/bin - - +include $(top_srcdir)/testsuite/testsuite.am diff --git a/imap4d/tests/Makefile.am b/imap4d/tests/Makefile.am index 2e471c20d..50d09833c 100644 --- a/imap4d/tests/Makefile.am +++ b/imap4d/tests/Makefile.am @@ -14,23 +14,7 @@ # You should have received a copy of the GNU General Public License # along with GNU Mailutils. If not, see . -EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 -DISTCLEANFILES = atconfig $(check_SCRIPTS) -MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE) - -## ------------ ## -## package.m4. ## -## ------------ ## - -$(srcdir)/package.m4: $(top_srcdir)/configure.ac - $(AM_V_GEN){ \ - echo '# Signature of the current package.'; \ - echo 'm4_define([AT_PACKAGE_NAME], [@PACKAGE_NAME@])'; \ - echo 'm4_define([AT_PACKAGE_TARNAME], [@PACKAGE_TARNAME@])'; \ - echo 'm4_define([AT_PACKAGE_VERSION], [@PACKAGE_VERSION@])'; \ - echo 'm4_define([AT_PACKAGE_STRING], [@PACKAGE_STRING@])'; \ - echo 'm4_define([AT_PACKAGE_BUGREPORT], [@PACKAGE_BUGREPORT@])'; \ - } >$(srcdir)/package.m4 +include $(top_srcdir)/testsuite/testsuite.am ## -------------------------- ## ## Non-installable programs @@ -40,11 +24,7 @@ AM_CPPFLAGS = @MU_LIB_COMMON_INCLUDES@ noinst_PROGRAMS = ckiconv LDADD = ${MU_LIB_MAILUTILS} -## ------------ ## -## Test suite. ## -## ------------ ## - -TESTSUITE_AT = \ +TESTSUITE_AT += \ anystate.at\ append00.at\ append01.at\ @@ -60,28 +40,6 @@ TESTSUITE_AT = \ list.at\ search.at\ select.at\ - status.at\ - testsuite.at - -TESTSUITE = $(srcdir)/testsuite -M4=m4 - -AUTOTEST = $(AUTOM4TE) --language=autotest -$(TESTSUITE): package.m4 $(TESTSUITE_AT) $(top_srcdir)/testsuite/testsuite.inc - $(AM_V_GEN)$(AUTOTEST) -I $(srcdir) -I $(top_srcdir)/testsuite testsuite.at -o $@.tmp - $(AM_V_at)mv $@.tmp $@ - -atconfig: $(top_builddir)/config.status - cd $(top_builddir) && ./config.status tests/$@ - -clean-local: - @test ! -f $(TESTSUITE) || $(SHELL) $(TESTSUITE) --clean - -check-local: atconfig atlocal $(TESTSUITE) - @$(SHELL) $(TESTSUITE) - -# Run the test suite on the *installed* tree. -#installcheck-local: -# $(SHELL) $(TESTSUITE) AUTOTEST_PATH=$(exec_prefix)/bin + status.at diff --git a/libmailutils/tests/Makefile.am b/libmailutils/tests/Makefile.am index bc839c3d6..a933152f6 100644 --- a/libmailutils/tests/Makefile.am +++ b/libmailutils/tests/Makefile.am @@ -14,25 +14,8 @@ # You should have received a copy of the GNU General Public License # along with GNU Mailutils. If not, see . -EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 -DISTCLEANFILES = atconfig $(check_SCRIPTS) -MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE) - -## ------------ ## -## package.m4. ## -## ------------ ## - -$(srcdir)/package.m4: $(top_srcdir)/configure.ac - $(AM_V_GEN){ \ - echo '# Signature of the current package.'; \ - echo 'm4_define([AT_PACKAGE_NAME], [@PACKAGE_NAME@])'; \ - echo 'm4_define([AT_PACKAGE_TARNAME], [@PACKAGE_TARNAME@])'; \ - echo 'm4_define([AT_PACKAGE_VERSION], [@PACKAGE_VERSION@])'; \ - echo 'm4_define([AT_PACKAGE_STRING], [@PACKAGE_STRING@])'; \ - echo 'm4_define([AT_PACKAGE_BUGREPORT], [@PACKAGE_BUGREPORT@])'; \ - } >$(srcdir)/package.m4 - -# +include $(top_srcdir)/testsuite/testsuite.am +AUTOTEST_INCLUDES += -I $(top_srcdir)/libmailutils/wordsplit ## -------------------------- ## ## Non-installable programs @@ -97,11 +80,7 @@ LDADD = ${MU_LIB_MAILUTILS} EXTRA_DIST += Encode Decode Wicketfile -## ------------ ## -## Test suite. ## -## ------------ ## - -TESTSUITE_AT = \ +TESTSUITE_AT += \ address.at\ base64d.at\ base64e.at\ @@ -188,7 +167,6 @@ TESTSUITE_AT = \ strin.at\ strout.at\ strtoc.at\ - testsuite.at\ url.at\ url-comp.at\ xml.at\ @@ -199,31 +177,6 @@ TESTSUITE_AT = \ wordwrap03.at\ xscript.at -TESTSUITE = $(srcdir)/testsuite -M4=m4 - -AUTOTEST = $(AUTOM4TE) --language=autotest -$(TESTSUITE): package.m4 $(TESTSUITE_AT) $(top_srcdir)/testsuite/testsuite.inc - $(AM_V_GEN)$(AUTOTEST) \ - -I $(srcdir)\ - -I $(top_srcdir)/testsuite\ - -I $(top_srcdir)/libmailutils/wordsplit\ - testsuite.at -o $@.tmp - $(AM_V_at)mv $@.tmp $@ - -atconfig: $(top_builddir)/config.status - cd $(top_builddir) && ./config.status tests/$@ - -clean-local: - @test ! -f $(TESTSUITE) || $(SHELL) $(TESTSUITE) --clean - -check-local: atconfig atlocal $(TESTSUITE) - @$(SHELL) $(TESTSUITE) - -# Run the test suite on the *installed* tree. -#installcheck-local: -# $(SHELL) $(TESTSUITE) AUTOTEST_PATH=$(exec_prefix)/bin - # ########################### # Wordsplit testsuite # ########################### diff --git a/libmailutils/tests/testsuite.at b/libmailutils/tests/testsuite.at index 05b77b116..39fdfa71e 100644 --- a/libmailutils/tests/testsuite.at +++ b/libmailutils/tests/testsuite.at @@ -182,6 +182,9 @@ m4_include([xscript.at]) m4_include([list.at]) m4_include([address.at]) + +AT_BANNER(Wordsplit) + m4_include([wordsplit.at]) m4_include([exp.at]) m4_include([url.at]) diff --git a/libmu_scm/tests/Makefile.am b/libmu_scm/tests/Makefile.am index 26b6d4938..d429146d1 100644 --- a/libmu_scm/tests/Makefile.am +++ b/libmu_scm/tests/Makefile.am @@ -14,32 +14,9 @@ # You should have received a copy of the GNU General Public License # along with GNU Mailutils. If not, see . -EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 -DISTCLEANFILES = atconfig $(check_SCRIPTS) -MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE) +include $(top_srcdir)/testsuite/testsuite.am -## ------------ ## -## package.m4. ## -## ------------ ## - -$(srcdir)/package.m4: $(top_srcdir)/configure.ac - $(AM_V_GEN){ \ - echo '# Signature of the current package.'; \ - echo 'm4_define([AT_PACKAGE_NAME], [@PACKAGE_NAME@])'; \ - echo 'm4_define([AT_PACKAGE_TARNAME], [@PACKAGE_TARNAME@])'; \ - echo 'm4_define([AT_PACKAGE_VERSION], [@PACKAGE_VERSION@])'; \ - echo 'm4_define([AT_PACKAGE_STRING], [@PACKAGE_STRING@])'; \ - echo 'm4_define([AT_PACKAGE_BUGREPORT], [@PACKAGE_BUGREPORT@])'; \ - } >$(srcdir)/package.m4 - -# - -## ------------ ## -## Test suite. ## -## ------------ ## - -TESTSUITE_AT = \ - testsuite.at\ +TESTSUITE_AT += \ const.at\ mailbox-open.at\ mailbox-open-exc.at\ @@ -85,25 +62,5 @@ TESTSUITE_AT = \ mime-get-part.at\ mime-add-part.at -TESTSUITE = $(srcdir)/testsuite -M4=m4 - -AUTOTEST = $(AUTOM4TE) --language=autotest -$(TESTSUITE): package.m4 $(TESTSUITE_AT) $(top_srcdir)/testsuite/testsuite.inc - $(AM_V_GEN)$(AUTOTEST) -I $(srcdir) -I $(top_srcdir)/testsuite testsuite.at -o $@.tmp - $(AM_V_at)mv $@.tmp $@ - -atconfig: $(top_builddir)/config.status - cd $(top_builddir) && ./config.status tests/$@ - -clean-local: - @test ! -f $(TESTSUITE) || $(SHELL) $(TESTSUITE) --clean - -check-local: atconfig atlocal $(TESTSUITE) - @$(SHELL) $(TESTSUITE) - -# Run the test suite on the *installed* tree. -#installcheck-local: -# $(SHELL) $(TESTSUITE) AUTOTEST_PATH=$(exec_prefix)/bin diff --git a/libproto/dotmail/tests/Makefile.am b/libproto/dotmail/tests/Makefile.am index cdf76c8eb..ab383921c 100644 --- a/libproto/dotmail/tests/Makefile.am +++ b/libproto/dotmail/tests/Makefile.am @@ -14,25 +14,7 @@ # You should have received a copy of the GNU General Public License # along with GNU Mailutils. If not, see . -EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 -DISTCLEANFILES = atconfig $(check_SCRIPTS) -MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE) - -## ------------ ## -## package.m4. ## -## ------------ ## - -$(srcdir)/package.m4: $(top_srcdir)/configure.ac - $(AM_V_GEN){ \ - echo '# Signature of the current package.'; \ - echo 'm4_define([AT_PACKAGE_NAME], [@PACKAGE_NAME@])'; \ - echo 'm4_define([AT_PACKAGE_TARNAME], [@PACKAGE_TARNAME@])'; \ - echo 'm4_define([AT_PACKAGE_VERSION], [@PACKAGE_VERSION@])'; \ - echo 'm4_define([AT_PACKAGE_STRING], [@PACKAGE_STRING@])'; \ - echo 'm4_define([AT_PACKAGE_BUGREPORT], [@PACKAGE_BUGREPORT@])'; \ - } >$(srcdir)/package.m4 - -# +include $(top_srcdir)/testsuite/testsuite.am ## -------------------------- ## ## Non-installable programs @@ -52,8 +34,7 @@ LDADD = ${MU_LIB_DOTMAIL} ${MU_LIB_MAILUTILS} ## Test suite. ## ## ------------ ## -TESTSUITE_AT = \ - testsuite.at\ +TESTSUITE_AT += \ autodetect.at\ count.at\ env.at\ @@ -69,21 +50,5 @@ TESTSUITE_AT = \ delete.at\ setattr.at -TESTSUITE = $(srcdir)/testsuite -M4=m4 - -AUTOTEST = $(AUTOM4TE) --language=autotest -$(TESTSUITE): package.m4 $(TESTSUITE_AT) $(top_srcdir)/testsuite/testsuite.inc - $(AM_V_GEN)$(AUTOTEST) -I $(srcdir) -I $(top_srcdir)/testsuite testsuite.at -o $@.tmp - $(AM_V_at)mv $@.tmp $@ - -atconfig: $(top_builddir)/config.status - cd $(top_builddir) && ./config.status tests/$@ - -clean-local: - @test ! -f $(TESTSUITE) || $(SHELL) $(TESTSUITE) --clean - -check-local: atconfig atlocal $(TESTSUITE) - @$(SHELL) $(TESTSUITE) diff --git a/mail/tests/Makefile.am b/mail/tests/Makefile.am index bf3762f7f..4f805b5b5 100644 --- a/mail/tests/Makefile.am +++ b/mail/tests/Makefile.am @@ -14,31 +14,9 @@ # You should have received a copy of the GNU General Public License # along with GNU Mailutils. If not, see . -EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 -DISTCLEANFILES = atconfig $(check_SCRIPTS) -MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE) +include $(top_srcdir)/testsuite/testsuite.am -## ------------ ## -## package.m4. ## -## ------------ ## - -$(srcdir)/package.m4: $(top_srcdir)/configure.ac - $(AM_V_GEN){ \ - echo '# Signature of the current package.'; \ - echo 'm4_define([AT_PACKAGE_NAME], [@PACKAGE_NAME@])'; \ - echo 'm4_define([AT_PACKAGE_TARNAME], [@PACKAGE_TARNAME@])'; \ - echo 'm4_define([AT_PACKAGE_VERSION], [@PACKAGE_VERSION@])'; \ - echo 'm4_define([AT_PACKAGE_STRING], [@PACKAGE_STRING@])'; \ - echo 'm4_define([AT_PACKAGE_BUGREPORT], [@PACKAGE_BUGREPORT@])'; \ - } >$(srcdir)/package.m4 - -# - -## ------------ ## -## Test suite. ## -## ------------ ## - -TESTSUITE_AT =\ +TESTSUITE_AT +=\ D.at\ align.at\ cols00.at\ @@ -53,25 +31,3 @@ TESTSUITE_AT =\ testsuite.at\ version.at -TESTSUITE = $(srcdir)/testsuite -M4=m4 - -AUTOTEST = $(AUTOM4TE) --language=autotest -$(TESTSUITE): package.m4 $(TESTSUITE_AT) $(top_srcdir)/testsuite/testsuite.inc - $(AM_V_GEN)$(AUTOTEST) -I $(srcdir) -I $(top_srcdir)/testsuite testsuite.at -o $@.tmp - $(AM_V_at)mv $@.tmp $@ - -atconfig: $(top_builddir)/config.status - cd $(top_builddir) && ./config.status tests/$@ - -clean-local: - @test ! -f $(TESTSUITE) || $(SHELL) $(TESTSUITE) --clean - -check-local: atconfig atlocal $(TESTSUITE) - @$(SHELL) $(TESTSUITE) - -# Run the test suite on the *installed* tree. -#installcheck-local: -# $(SHELL) $(TESTSUITE) AUTOTEST_PATH=$(exec_prefix)/bin - - diff --git a/maint/fullcheck.mk b/maint/fullcheck.mk index 038a30cf5..c636380f4 100644 --- a/maint/fullcheck.mk +++ b/maint/fullcheck.mk @@ -8,9 +8,10 @@ # FORMATS = mbox dotmail mh maildir DISTNAME = $(PACKAGE)-$(PACKAGE_VERSION) +FULLCHECKDIR = _fullcheck fullcheck: $(foreach fmt,$(FORMATS),check-$(fmt)) - @rmdir fullcheck + @rmdir $(FULLCHECKDIR) @text="$(DISTNAME) passed all tests";\ echo $$text | sed -e 's/./=/g';\ echo $$text;\ @@ -23,20 +24,20 @@ $(DISTNAME).tar.gz: ChangeLog define fullcheckdir_tmpl fullcheckdir-$(1): - rm -rf fullcheckdir/$(1) - mkdir -p fullcheckdir/$(1) + rm -rf $(FULLCHECKDIR)/$(1) + mkdir -p $(FULLCHECKDIR)/$(1) endef define fullcheck_tmpl check-$(fmt): fullcheck_dist fullcheckdir-$(fmt) - cd fullcheckdir/$(fmt) && \ + cd $(FULLCHECKDIR)/$(fmt) && \ tar xf ../../$(DISTNAME).tar.gz && \ cd $(DISTNAME) && \ mkdir .build && \ cd .build && \ ../configure MU_DEFAULT_SCHEME=$(fmt) && \ make check - rm -rf fullcheckdir/$(fmt) + rm -rf $(FULLCHECKDIR)/$(fmt) endef $(foreach fmt,$(FORMATS),$(eval $(call fullcheckdir_tmpl,$(fmt)))) diff --git a/mda/.gitignore b/mda/.gitignore deleted file mode 100644 index f0e6495e9..000000000 --- a/mda/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -lmtpd -mda -putmail diff --git a/mda/Makefile.am b/mda/Makefile.am index 7a05036dc..9191641bc 100644 --- a/mda/Makefile.am +++ b/mda/Makefile.am @@ -13,60 +13,16 @@ # You should have received a copy of the GNU General Public License # along with GNU Mailutils. If not, see . -SUBDIRS = lib . tests -sbin_PROGRAMS = mda lmtpd -bin_PROGRAMS = putmail +SUBDIRS = lib -mda_SOURCES = mda.c -lmtpd_SOURCES = lmtpd.c -putmail_SOURCES = putmail.c - -if MU_COND_DBM - LIBMU_DBM=${top_builddir}/libmu_dbm/libmu_dbm.la +if MU_COND_MDA + SUBDIRS += mda +endif +if MU_COND_LMTPD + SUBDIRS += lmtpd +endif +if MU_COND_PUTMAIL + SUBDIRS += putmail endif -LDADD = \ - lib/libmda.a\ - ${top_builddir}/lib/libmuscript.a\ - ${MU_APP_LIBRARIES}\ - ${MU_LIB_SIEVE}\ - ${MU_LIB_MAILBOX}\ - ${MU_LIB_AUTH}\ - ${MU_LIB_MAILER}\ - @MU_AUTHLIBS@\ - ${MU_LIB_MAILUTILS} \ - @MU_COMMON_LIBRARIES@\ - @LIBMU_SCM@\ - @LIBMU_SCM_DEPS@\ - @MU_LIB_PY@\ - $(LIBMU_DBM)\ - @GUILE_LIBS@\ - @PYTHON_LIBS@\ - @DBMLIBS@ - -lmtpd_LDADD = \ - lib/libmda.a\ - ${top_builddir}/lib/libmuscript.a\ - ${MU_APP_LIBRARIES}\ - ${MU_LIB_SIEVE}\ - ${MU_LIB_MAILBOX}\ - ${MU_LIB_AUTH}\ - ${MU_LIB_MAILER}\ - @MU_AUTHLIBS@\ - ${MU_LIB_MAILUTILS} \ - @MU_COMMON_LIBRARIES@\ - @LIBMU_SCM@\ - @LIBMU_SCM_DEPS@\ - @MU_LIB_PY@\ - $(LIBMU_DBM)\ - @GUILE_LIBS@\ - @PYTHON_LIBS@\ - @DBMLIBS@\ - @MU_TCPWRAP_LIBRARIES@ - -AM_CPPFLAGS = -I${top_srcdir} @MU_APP_COMMON_INCLUDES@ -I${srcdir}/lib - -install-exec-hook: - -chown root:mail $(DESTDIR)$(sbindir)/mda &&\ - chmod 4755 $(DESTDIR)$(sbindir)/mda - +EXTRA_DIST = tests/input.msg tests/mda.inc diff --git a/mda/lmtpd.c b/mda/lmtpd.c deleted file mode 100644 index 2ffdd6ab5..000000000 --- a/mda/lmtpd.c +++ /dev/null @@ -1,902 +0,0 @@ -/* GNU Mailutils -- a suite of utilities for electronic mail - Copyright (C) 2007-2019 Free Software Foundation, Inc. - - GNU Mailutils 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 3, or (at your option) - any later version. - - GNU Mailutils 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 GNU Mailutils. If not, see . */ - -#include "libmda.h" -#include -#include -#include -#include -#include -#include -#include - -static const char *program_version = "lmtpd (" PACKAGE_STRING ")"; - -static mu_m_server_t server; -static int reuse_lmtp_address = 1; -static int mda_transcript; -static mu_list_t lmtp_groups; - -static int -cb2_group (const char *gname, void *data) -{ - mu_list_t list = data; - struct group *group; - - group = getgrnam (gname); - if (!group) - mu_error (_("unknown group: %s"), gname); - else - mu_list_append (list, (void*) (intptr_t) group->gr_gid); - return 0; -} - -static int -cb_group (void *data, mu_config_value_t *arg) -{ - mu_list_t *plist = data; - - if (!*plist) - mu_list_create (plist); - return mu_cfg_string_value_cb (arg, cb2_group, *plist); -} - -static int -cb_listen (void *data, mu_config_value_t *val) -{ - struct mu_sockaddr *s; - - if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) - return 1; - if (mu_m_server_parse_url (server, val->v.string, &s)) - return 1; - mu_m_server_listen (server, s, MU_IP_TCP); - return 0; -} - -static void -set_foreground (struct mu_parseopt *po, struct mu_option *opt, - char const *arg) -{ - mu_m_server_set_foreground (server, 1); -} - -static void -set_stderr (struct mu_parseopt *po, struct mu_option *opt, char const *arg) -{ - mu_log_syslog = 0; -} - -static void -set_inetd_mode (struct mu_parseopt *po, struct mu_option *opt, - char const *arg) -{ - mu_m_server_set_mode (server, MODE_INTERACTIVE); -} - -static void -set_daemon_mode (struct mu_parseopt *po, struct mu_option *opt, - char const *arg) -{ - mu_m_server_set_mode (server, MODE_DAEMON); - if (arg) - { - size_t max_children; - char *errmsg; - int rc = mu_str_to_c (arg, mu_c_size, &max_children, &errmsg); - if (rc) - { - mu_parseopt_error (po, _("%s: bad argument"), arg); - exit (po->po_exit_error); - } - mu_m_server_set_max_children (server, max_children); - } -} - -static struct mu_option lmtpd_options[] = { - MU_OPTION_GROUP (N_("General options")), - { "foreground", 0, NULL, MU_OPTION_DEFAULT, - N_("remain in foreground"), - mu_c_bool, NULL, set_foreground }, - { "inetd", 'i', NULL, MU_OPTION_DEFAULT, - N_("run in inetd mode"), - mu_c_bool, NULL, set_inetd_mode }, - { "daemon", 'd', N_("NUMBER"), MU_OPTION_ARG_OPTIONAL, - N_("runs in daemon mode with a maximum of NUMBER children"), - mu_c_string, NULL, set_daemon_mode }, - { "stderr", 0, NULL, MU_OPTION_DEFAULT, - N_("log to standard error"), - mu_c_string, NULL, set_stderr }, - { "transcript", 0, NULL, MU_OPTION_DEFAULT, - N_("enable session transcript"), - mu_c_bool, &mda_transcript }, - MU_OPTION_END -}, *options[] = { lmtpd_options, NULL }; - -struct mu_cfg_param lmtp_cfg_param[] = { - { "group", mu_cfg_callback, &lmtp_groups, 0, cb_group, - N_("In LMTP mode, retain these supplementary groups."), - N_("groups: list of string") }, - { "listen", mu_cfg_callback, NULL, 0, cb_listen, - N_("In LMTP mode, listen on the given URL. Valid URLs are:\n" - " tcp://: (note that port is " - "mandatory)\n" - " file://\n" - "or socket://"), - N_("url: string") }, - { "reuse-address", mu_c_bool, &reuse_lmtp_address, 0, NULL, - N_("Reuse existing address (LMTP mode). Default is \"yes\".") }, - { "filter", mu_cfg_section, NULL, 0, NULL, - N_("Add a message filter") }, - { ".server", mu_cfg_section, NULL, 0, NULL, - N_("LMTP server configuration.") }, - TCP_WRAPPERS_CONFIG - { NULL } -}; - -static char *capa[] = { - "auth", - "debug", - "logging", - "mailbox", - "locking", - "mailer", - "sieve", - "deliver", - "forward", - "quota", - "script", - NULL -}; - -static struct mu_cli_setup cli = { - options, - lmtp_cfg_param, - N_("GNU lmtpd -- local mail transfer protocol daemon."), -}; - -static int lmtp_connection (int fd, struct sockaddr *sa, int salen, - struct mu_srv_config *pconf, - void *data); -static int lmtp_server (void); - - -int -main (int argc, char **argv) -{ - umask (0077); - - /* Native Language Support */ - MU_APP_INIT_NLS (); - - /* Default locker settings */ - mu_locker_set_default_flags (MU_LOCKER_PID|MU_LOCKER_RETRY, - mu_locker_assign); - mu_locker_set_default_retry_timeout (1); - mu_locker_set_default_retry_count (300); - - /* Register needed modules */ - MU_AUTH_REGISTER_ALL_MODULES (); - - /* Register all supported mailbox and mailer formats */ - mu_register_all_formats (); - mu_registrar_record (mu_smtp_record); - - mda_filter_cfg_init (); - mu_tcpwrapper_cfg_init (); - mu_acl_cfg_init (); - mda_cli_capa_init (); - - mu_m_server_create (&server, program_version); - mu_m_server_set_conn (server, lmtp_connection); - mu_m_server_set_prefork (server, mu_tcp_wrapper_prefork); - mu_m_server_set_mode (server, MODE_INTERACTIVE); - mu_m_server_set_max_children (server, 20); - mu_m_server_set_timeout (server, 600); - mu_m_server_cfg_init (server, NULL); - - /* Parse command line */ - mu_cli (argc, argv, &cli, capa, server, &argc, &argv); - - mu_stdstream_strerr_setup (mu_log_syslog ? - MU_STRERR_SYSLOG : MU_STRERR_STDERR); - - if (argc) - { - mu_error (_("too many arguments")); - return EX_USAGE; - } - - return lmtp_server (); -} - -static mu_stream_t -lmtp_transcript (mu_stream_t iostream) -{ - int rc; - mu_stream_t dstr, xstr; - - rc = mu_dbgstream_create (&dstr, MU_DIAG_DEBUG); - if (rc) - mu_error (_("cannot create debug stream; transcript disabled: %s"), - mu_strerror (rc)); - else - { - rc = mu_xscript_stream_create (&xstr, iostream, dstr, NULL); - if (rc) - mu_error (_("cannot create transcript stream: %s"), - mu_strerror (rc)); - else - { - /* FIXME: Would do a mu_stream_unref (iostream) here, - however mu_xscript_stream_create *may* steal the reference. - This should be fixed in mu_xscript_stream_create. */ - iostream = xstr; - } - } - return iostream; -} - -static void -lmtp_reply (mu_stream_t iostr, char *code, char *enh, char *fmt, ...) -{ - va_list ap; - char *str = NULL; - size_t size = 0; - - va_start (ap, fmt); - mu_vasnprintf (&str, &size, fmt, ap); - va_end (ap); - - if (!str) - { - mu_error (_("not enough memory")); - exit (EX_TEMPFAIL); - } - - while (*str) - { - char *end = strchr (str, '\n'); - - if (end) - { - size_t len = end - str; - mu_stream_printf (iostr, "%s-", code); - if (enh) - mu_stream_printf (iostr, "%s ", enh); - mu_stream_printf (iostr, "%.*s\r\n", (int) len, str); - for (str = end; *str && *str == '\n'; str++); - } - else - { - mu_stream_printf (iostr, "%s ", code); - if (enh) - mu_stream_printf (iostr, "%s ", enh); - mu_stream_printf (iostr, "%s\r\n", str); - str += strlen (str); - } - } -} - -enum lmtp_state - { - state_none, - - state_init, - state_lhlo, - state_mail, - state_rcpt, - state_data, - state_quit, - state_dot, - - state_end - }; - -#define NSTATE ((int) state_end + 1) - -enum lmtp_command - { - cmd_unknown, - cmd_lhlo, - cmd_mail, - cmd_rcpt, - cmd_data, - cmd_quit, - cmd_rset, - cmd_help, - cmd_dot - }; - -#define NCMD ((int)cmd_dot + 1) - -#define SNO state_none -#define SIN state_init -#define SHL state_lhlo -#define SML state_mail -#define SRC state_rcpt -#define SDA state_data -#define SQT state_quit -#define SDT state_dot -#define SEN state_end - -static int transtab[NCMD][NSTATE] = { -/* state_ SNO SIN SHL SML SRC SDA SQT SDT SEN */ -/* unkn */ { SNO, SNO, SNO, SNO, SNO, SNO, SNO, SNO, SEN }, -/* lhlo */ { SNO, SHL, SNO, SNO, SNO, SNO, SNO, SNO, SNO }, -/* mail */ { SNO, SNO, SML, SNO, SNO, SNO, SNO, SNO, SNO }, -/* rcpt */ { SNO, SNO, SNO, SRC, SRC, SNO, SNO, SNO, SNO }, -/* data */ { SNO, SNO, SNO, SNO, SDA, SNO, SNO, SNO, SNO }, -/* quit */ { SNO, SEN, SEN, SEN, SEN, SEN, SEN, SEN, SEN }, -/* rset */ { SNO, SIN, SIN, SIN, SIN, SIN, SIN, SIN, SNO }, -/* help */ { SNO, SIN, SHL, SML, SRC, SDT, SQT, SDT, SEN }, -/* dot */ { SNO, SNO, SNO, SNO, SNO, SQT, SNO, SNO, SNO }, -}; - - -/* Delivery data */ -static char *lhlo_domain; /* Sender domain */ -static char *mail_from; /* Sender address */ -static mu_list_t rcpt_list; /* Recipient addresses */ -static mu_message_t mesg; /* Collected message */ - - -static int -cfun_unknown (mu_stream_t iostr, char *arg) -{ - lmtp_reply (iostr, "500", "5.5.1", "Command unrecognized"); - return 0; -} - - -static void -add_default_domain (char *str, int len, char **pret) -{ - *pret = malloc (len + 1 + strlen (lhlo_domain) + 1); - if (!*pret) - { - mu_error (_("not enough memory")); - exit (EX_SOFTWARE); - } - memcpy (*pret, str, len); - (*pret)[len] = '@'; - strcpy (*pret + len + 1, lhlo_domain); -} - -#define MAILER_DAEMON "MAILER-DAEMON" - -static int -check_address (char *arg, int with_domain, char **pret) -{ - if (strchr (arg, '@') == 0) - { - char *addr = NULL; - size_t addrlen = 0; - - if (*arg == '<') - { - size_t len = strlen (arg); - if (arg[len - 1] == '>') - { - if (len == 2) /* null address */ - { - if (!with_domain) - /* Null address is only legal in mail from */ - return 1; - addr = MAILER_DAEMON; - addrlen = sizeof MAILER_DAEMON - 1; - } - else - { - addr = arg + 1; - addrlen = len - 2; - } - } - else - return 1; - } - else - { - addr = arg; - addrlen = strlen (arg); - } - - if (with_domain) - add_default_domain (addr, addrlen, pret); - else - { - *pret = malloc (addrlen + 1); - memcpy (*pret, addr, addrlen); - (*pret)[addrlen] = 0; - } - } - else - { - mu_address_t addr; - char *s; - int rc = mu_address_create (&addr, arg); - if (rc) - return 1; - if (with_domain) - rc = mu_address_aget_email (addr, 1, &s); - else - rc = mu_address_aget_local_part (addr, 1, &s); - mu_address_destroy (&addr); - if (rc || !s) - return 1; - *pret = s; - } - return 0; -} - -static int -cfun_mail_from (mu_stream_t iostr, char *arg) -{ - if (*arg == 0) - { - lmtp_reply (iostr, "501", "5.5.2", "Syntax error"); - return 1; - } - - if (check_address (arg, 1, &mail_from)) - { - lmtp_reply (iostr, "553", "5.1.8", "Address format error"); - return 1; - } - lmtp_reply (iostr, "250", "2.1.0", "Go ahead"); - return 0; -} - -static int -cfun_rcpt_to (mu_stream_t iostr, char *arg) -{ - char *user; - struct mu_auth_data *auth; - - if (*arg == 0) - { - lmtp_reply (iostr, "501", "5.5.2", "Syntax error"); - return 1; - } - - /* FIXME: Check if domain is OK */ - if (check_address (arg, 0, &user)) - { - lmtp_reply (iostr, "553", "5.1.8", "Address format error"); - return 1; - } - auth = mu_get_auth_by_name (user); - if (!auth) - { - lmtp_reply (iostr, "550", "5.1.1", "User unknown"); - free (user); - return 1; - } - mu_auth_data_free (auth); - if (!rcpt_list) - { - mu_list_create (&rcpt_list); - mu_list_set_destroy_item (rcpt_list, mu_list_free_item); - } - mu_list_append (rcpt_list, user); - lmtp_reply (iostr, "250", "2.1.5", "Go ahead"); - return 0; -} - -static int -dot_temp_fail (void *item, void *cbdata) -{ - char *name = item; - mu_stream_t iostr = cbdata; - lmtp_reply (iostr, "450", "4.1.0", "%s: temporary failure", name); - return 0; -} - -static int -dot_deliver (void *item, void *cbdata) -{ - char *name = item; - mu_stream_t iostr = cbdata; - char *errp = NULL; - - switch (mda_deliver_to_user (mesg, name, &errp)) - { - case 0: - lmtp_reply (iostr, "250", "2.0.0", "%s: delivered", name); - break; - - case EX_UNAVAILABLE: - if (errp) - lmtp_reply (iostr, "553", "5.1.8", "%s", errp); - else - lmtp_reply (iostr, "553", "5.1.8", "%s: delivery failed", name); - break; - - default: - if (errp) - lmtp_reply (iostr, "450", "4.1.0", "%s", errp); - else - lmtp_reply (iostr, "450", "4.1.0", - "%s: temporary failure, try again later", - name); - break; - } - free (errp); - return 0; -} - -static int -cfun_data (mu_stream_t iostr, char *arg) -{ - int rc; - mu_stream_t flt, tempstr; - time_t t; - struct tm *tm; - int xlev = MU_XSCRIPT_PAYLOAD, xlev_switch = 0; - - if (*arg) - { - lmtp_reply (iostr, "501", "5.5.2", "Syntax error"); - return 1; - } - - rc = mu_filter_create (&flt, iostr, "CRLFDOT", MU_FILTER_DECODE, - MU_STREAM_READ|MU_STREAM_WRTHRU); - if (rc) - { - mda_error (_("unable to open filter: %s"), - mu_strerror (rc)); - lmtp_reply (iostr, "450", "4.1.0", "Temporary failure, try again later"); - return 1; - } - - rc = mu_temp_file_stream_create (&tempstr, NULL, 0); - if (rc) - { - mda_error (_("unable to open temporary file: %s"), mu_strerror (rc)); - mu_stream_destroy (&flt); - return 1; - } - - /* Write out envelope */ - time (&t); - tm = gmtime (&t); - rc = mu_stream_printf (tempstr, "From %s ", mail_from); - if (rc == 0) - rc = mu_c_streamftime (tempstr, "%c%n", tm, NULL); - if (rc) - { - mda_error (_("copy error: %s"), mu_strerror (rc)); - mu_stream_destroy (&flt); - mu_stream_destroy (&tempstr); - mu_list_foreach (rcpt_list, dot_temp_fail, iostr); - } - - lmtp_reply (iostr, "354", NULL, "Go ahead"); - - if (mu_stream_ioctl (iostr, MU_IOCTL_XSCRIPTSTREAM, - MU_IOCTL_XSCRIPTSTREAM_LEVEL, &xlev) == 0) - xlev_switch = 1; - rc = mu_stream_copy (tempstr, flt, 0, NULL); - mu_stream_destroy (&flt); - if (xlev_switch) - mu_stream_ioctl (iostr, MU_IOCTL_XSCRIPTSTREAM, - MU_IOCTL_XSCRIPTSTREAM_LEVEL, &xlev); - if (rc) - { - mda_error (_("copy error: %s"), mu_strerror (rc)); - mu_list_foreach (rcpt_list, dot_temp_fail, iostr); - } - - rc = mu_stream_to_message (tempstr, &mesg); - mu_stream_unref (tempstr); - if (rc) - { - mda_error (_("error creating temporary message: %s"), - mu_strerror (rc)); - mu_list_foreach (rcpt_list, dot_temp_fail, iostr); - } - - rc = mu_list_foreach (rcpt_list, dot_deliver, iostr); - - mu_message_destroy (&mesg, mu_message_get_owner (mesg)); - if (rc) - mu_list_foreach (rcpt_list, dot_temp_fail, iostr); - - return 0; -} - -static int -cfun_rset (mu_stream_t iostr, char *arg) -{ - free (lhlo_domain); - free (mail_from); - mu_list_destroy (&rcpt_list); - mu_message_destroy (&mesg, mu_message_get_owner (mesg)); - lmtp_reply (iostr, "250", "2.0.0", "OK, forgotten"); - return 0; -} - -static char *capa_str = "ENHANCEDSTATUSCODES\n\ -PIPELINING\n\ -8BITMIME\n\ -HELP"; - -static int -cfun_lhlo (mu_stream_t iostr, char *arg) -{ - if (*arg == 0) - { - lmtp_reply (iostr, "501", "5.0.0", "Syntax error"); - return 1; - } - lhlo_domain = strdup (arg); - if (!lhlo_domain) - { - lmtp_reply (iostr, "410", "4.0.0", - "Local error; please try again later"); - return 1; - } - lmtp_reply (iostr, "250", NULL, "Hello\n"); - lmtp_reply (iostr, "250", NULL, capa_str); - return 0; -} - -static int -cfun_quit (mu_stream_t iostr, char *arg) -{ - lmtp_reply (iostr, "221", "2.0.0", "Bye"); - return 0; -} - -static int -cfun_help (mu_stream_t iostr, char *arg) -{ - lmtp_reply (iostr, "200", "2.0.0", "Man, help yourself"); - return 0; -} - -static struct command_tab -{ - char *cmd_verb; - int cmd_len; - enum lmtp_command cmd_code; - int (*cmd_fun) (mu_stream_t, char *); -} command_tab[] = { -#define S(s) #s, (sizeof #s - 1) - { S(lhlo), cmd_lhlo, cfun_lhlo }, - { S(mail from:), cmd_mail, cfun_mail_from }, - { S(rcpt to:), cmd_rcpt, cfun_rcpt_to }, - { S(data), cmd_data, cfun_data }, - { S(quit), cmd_quit, cfun_quit }, - { S(rset), cmd_rset, cfun_rset }, - { S(help), cmd_help, cfun_help }, - { NULL, 0, cmd_unknown, cfun_unknown } -}; - -static struct command_tab * -getcmd (char *buf, char **sp) -{ - struct command_tab *cp; - size_t len = strlen (buf); - for (cp = command_tab; cp->cmd_verb; cp++) - { - if (cp->cmd_len <= len - && mu_c_strncasecmp (cp->cmd_verb, buf, cp->cmd_len) == 0) - { - *sp = buf + cp->cmd_len; - return cp; - } - } - return cp; -} - -static int -to_fgets (mu_stream_t iostr, char **pbuf, size_t *psize, size_t *pnread, - unsigned int timeout) -{ - int rc; - - alarm (timeout); - rc = mu_stream_getline (iostr, pbuf, psize, pnread); - alarm (0); - return rc; -} - -static int -lmtp_loop (mu_stream_t iostr, unsigned int timeout) -{ - size_t size = 0, n; - char *buf = NULL; - enum lmtp_state state = state_init; - - lmtp_reply (iostr, "220", NULL, "At your service"); - while (to_fgets (iostr, &buf, &size, &n, timeout) == 0 && n) - { - char *sp; - struct command_tab *cp = getcmd (buf, &sp); - enum lmtp_command cmd = cp->cmd_code; - enum lmtp_state next_state = transtab[cmd][state]; - - mu_rtrim_class (sp, MU_CTYPE_ENDLN); - - if (next_state != state_none) - { - if (cp->cmd_fun) - { - sp = mu_str_skip_class (sp, MU_CTYPE_SPACE); - if (cp->cmd_fun (iostr, sp)) - continue; - } - state = next_state; - } - else - lmtp_reply (iostr, "503", "5.0.0", "Syntax error"); - - if (state == state_end) - break; - } - return 0; -} - -typedef union -{ - struct sockaddr sa; - struct sockaddr_in s_in; - struct sockaddr_un s_un; -} all_addr_t; - -static int -lmtp_connection (int fd, struct sockaddr *sa, int salen, - struct mu_srv_config *pconf, - void *data) -{ - mu_stream_t str; - int rc; - - rc = mu_fd_stream_create (&str, NULL, fd, MU_STREAM_RDWR); - if (rc) - { - mu_diag_funcall (MU_DIAG_ERROR, "mu_fd_stream_create", NULL, rc); - return rc; - } - mu_stream_set_buffer (str, mu_buffer_line, 0); - - if (pconf->transcript || mda_transcript) - str = lmtp_transcript (str); - lmtp_loop (str, pconf->timeout); - mu_stream_destroy (&str); - return 0; -} - -static int -lmtp_set_privs (void) -{ - gid_t gid; - - if (lmtp_groups) - { - gid_t *gidset = NULL; - size_t size = 0; - size_t j = 0; - mu_iterator_t itr; - int rc; - - rc = mu_list_count (lmtp_groups, &size); - if (rc) - { - mu_diag_funcall (MU_DIAG_ERROR, "mu_list_count", NULL, rc); - return EX_UNAVAILABLE; - } - if (size == 0) - return 0; /* nothing to do */ - gidset = calloc (size, sizeof (gidset[0])); - if (!gidset) - { - mu_error (_("not enough memory")); - return EX_UNAVAILABLE; - } - if (mu_list_get_iterator (lmtp_groups, &itr) == 0) - { - for (mu_iterator_first (itr); - !mu_iterator_is_done (itr); mu_iterator_next (itr)) - mu_iterator_current (itr, - (void **)(gidset + j++)); - mu_iterator_destroy (&itr); - } - gid = gidset[0]; - rc = setgroups (j, gidset); - free (gidset); - if (rc) - { - mu_diag_funcall (MU_DIAG_ERROR, "setgroups", NULL, errno); - return EX_UNAVAILABLE; - } - } - else - { - struct group *gr = getgrnam ("mail"); - if (gr == NULL) - { - mu_diag_funcall (MU_DIAG_ERROR, "getgrnam", "mail", errno); - return EX_UNAVAILABLE; - } - gid = gr->gr_gid; - } - if (setgid (gid) == -1) - { - mu_diag_funcall (MU_DIAG_ERROR, "setgid", "mail", errno); - return EX_UNAVAILABLE; - } - return 0; -} - -static int -lmtp_server (void) -{ - int rc = lmtp_set_privs (); - - if (rc) - return rc; - - if (mu_m_server_mode (server) == MODE_DAEMON) - { - mu_m_server_begin (server); - rc = mu_m_server_run (server); - if (rc) - rc = EX_CONFIG; - mu_m_server_end (server); - mu_m_server_destroy (&server); - } - else - { - mu_stream_t str, istream, ostream; - - rc = mu_stdio_stream_create (&istream, MU_STDIN_FD, MU_STREAM_READ); - if (rc) - { - mu_diag_funcall (MU_DIAG_ERROR, "mu_stdio_stream_create", - "MU_STDIN_FD", rc); - return EX_UNAVAILABLE; - } - - rc = mu_stdio_stream_create (&ostream, MU_STDOUT_FD, MU_STREAM_WRITE); - if (rc) - { - mu_diag_funcall (MU_DIAG_ERROR, "mu_stdio_stream_create", - "MU_STDOUT_FD", rc); - return 1; - } - - rc = mu_iostream_create (&str, istream, ostream); - mu_stream_unref (istream); - mu_stream_unref (ostream); - if (rc) - { - mu_diag_funcall (MU_DIAG_ERROR, "mu_iostream_create", NULL, rc); - return 1; - } - - if (mda_transcript) - str = lmtp_transcript (str); - - rc = lmtp_loop (str, 0); - mu_stream_destroy (&str); - } - return rc; -} - - diff --git a/mda/lmtpd/.gitignore b/mda/lmtpd/.gitignore new file mode 100644 index 000000000..6c8868b04 --- /dev/null +++ b/mda/lmtpd/.gitignore @@ -0,0 +1 @@ +lmtpd diff --git a/mda/lmtpd/Makefile.am b/mda/lmtpd/Makefile.am new file mode 100644 index 000000000..4e9927762 --- /dev/null +++ b/mda/lmtpd/Makefile.am @@ -0,0 +1,48 @@ +# Copyright (C) 2007-2019 Free Software Foundation, Inc. +# +# GNU Mailutils 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 3, or (at +# your option) any later version. +# +# GNU Mailutils 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 GNU Mailutils. If not, see . + +SUBDIRS = . tests + +sbin_PROGRAMS = lmtpd + +lmtpd_SOURCES = lmtpd.c + +AM_CPPFLAGS = -I${top_srcdir} @MU_APP_COMMON_INCLUDES@ -I${srcdir}/../lib + +if MU_COND_DBM + LIBMU_DBM=${top_builddir}/libmu_dbm/libmu_dbm.la +endif + +lmtpd_LDADD = \ + ../lib/libmda.a\ + ${top_builddir}/lib/libmuscript.a\ + ${MU_APP_LIBRARIES}\ + ${MU_LIB_SIEVE}\ + ${MU_LIB_MAILBOX}\ + ${MU_LIB_AUTH}\ + ${MU_LIB_MAILER}\ + @MU_AUTHLIBS@\ + ${MU_LIB_MAILUTILS} \ + @MU_COMMON_LIBRARIES@\ + @LIBMU_SCM@\ + @LIBMU_SCM_DEPS@\ + @MU_LIB_PY@\ + $(LIBMU_DBM)\ + @GUILE_LIBS@\ + @PYTHON_LIBS@\ + @DBMLIBS@\ + @MU_TCPWRAP_LIBRARIES@ + + diff --git a/mda/lmtpd/lmtpd.c b/mda/lmtpd/lmtpd.c new file mode 100644 index 000000000..2ffdd6ab5 --- /dev/null +++ b/mda/lmtpd/lmtpd.c @@ -0,0 +1,902 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 2007-2019 Free Software Foundation, Inc. + + GNU Mailutils 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 3, or (at your option) + any later version. + + GNU Mailutils 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 GNU Mailutils. If not, see . */ + +#include "libmda.h" +#include +#include +#include +#include +#include +#include +#include + +static const char *program_version = "lmtpd (" PACKAGE_STRING ")"; + +static mu_m_server_t server; +static int reuse_lmtp_address = 1; +static int mda_transcript; +static mu_list_t lmtp_groups; + +static int +cb2_group (const char *gname, void *data) +{ + mu_list_t list = data; + struct group *group; + + group = getgrnam (gname); + if (!group) + mu_error (_("unknown group: %s"), gname); + else + mu_list_append (list, (void*) (intptr_t) group->gr_gid); + return 0; +} + +static int +cb_group (void *data, mu_config_value_t *arg) +{ + mu_list_t *plist = data; + + if (!*plist) + mu_list_create (plist); + return mu_cfg_string_value_cb (arg, cb2_group, *plist); +} + +static int +cb_listen (void *data, mu_config_value_t *val) +{ + struct mu_sockaddr *s; + + if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) + return 1; + if (mu_m_server_parse_url (server, val->v.string, &s)) + return 1; + mu_m_server_listen (server, s, MU_IP_TCP); + return 0; +} + +static void +set_foreground (struct mu_parseopt *po, struct mu_option *opt, + char const *arg) +{ + mu_m_server_set_foreground (server, 1); +} + +static void +set_stderr (struct mu_parseopt *po, struct mu_option *opt, char const *arg) +{ + mu_log_syslog = 0; +} + +static void +set_inetd_mode (struct mu_parseopt *po, struct mu_option *opt, + char const *arg) +{ + mu_m_server_set_mode (server, MODE_INTERACTIVE); +} + +static void +set_daemon_mode (struct mu_parseopt *po, struct mu_option *opt, + char const *arg) +{ + mu_m_server_set_mode (server, MODE_DAEMON); + if (arg) + { + size_t max_children; + char *errmsg; + int rc = mu_str_to_c (arg, mu_c_size, &max_children, &errmsg); + if (rc) + { + mu_parseopt_error (po, _("%s: bad argument"), arg); + exit (po->po_exit_error); + } + mu_m_server_set_max_children (server, max_children); + } +} + +static struct mu_option lmtpd_options[] = { + MU_OPTION_GROUP (N_("General options")), + { "foreground", 0, NULL, MU_OPTION_DEFAULT, + N_("remain in foreground"), + mu_c_bool, NULL, set_foreground }, + { "inetd", 'i', NULL, MU_OPTION_DEFAULT, + N_("run in inetd mode"), + mu_c_bool, NULL, set_inetd_mode }, + { "daemon", 'd', N_("NUMBER"), MU_OPTION_ARG_OPTIONAL, + N_("runs in daemon mode with a maximum of NUMBER children"), + mu_c_string, NULL, set_daemon_mode }, + { "stderr", 0, NULL, MU_OPTION_DEFAULT, + N_("log to standard error"), + mu_c_string, NULL, set_stderr }, + { "transcript", 0, NULL, MU_OPTION_DEFAULT, + N_("enable session transcript"), + mu_c_bool, &mda_transcript }, + MU_OPTION_END +}, *options[] = { lmtpd_options, NULL }; + +struct mu_cfg_param lmtp_cfg_param[] = { + { "group", mu_cfg_callback, &lmtp_groups, 0, cb_group, + N_("In LMTP mode, retain these supplementary groups."), + N_("groups: list of string") }, + { "listen", mu_cfg_callback, NULL, 0, cb_listen, + N_("In LMTP mode, listen on the given URL. Valid URLs are:\n" + " tcp://: (note that port is " + "mandatory)\n" + " file://\n" + "or socket://"), + N_("url: string") }, + { "reuse-address", mu_c_bool, &reuse_lmtp_address, 0, NULL, + N_("Reuse existing address (LMTP mode). Default is \"yes\".") }, + { "filter", mu_cfg_section, NULL, 0, NULL, + N_("Add a message filter") }, + { ".server", mu_cfg_section, NULL, 0, NULL, + N_("LMTP server configuration.") }, + TCP_WRAPPERS_CONFIG + { NULL } +}; + +static char *capa[] = { + "auth", + "debug", + "logging", + "mailbox", + "locking", + "mailer", + "sieve", + "deliver", + "forward", + "quota", + "script", + NULL +}; + +static struct mu_cli_setup cli = { + options, + lmtp_cfg_param, + N_("GNU lmtpd -- local mail transfer protocol daemon."), +}; + +static int lmtp_connection (int fd, struct sockaddr *sa, int salen, + struct mu_srv_config *pconf, + void *data); +static int lmtp_server (void); + + +int +main (int argc, char **argv) +{ + umask (0077); + + /* Native Language Support */ + MU_APP_INIT_NLS (); + + /* Default locker settings */ + mu_locker_set_default_flags (MU_LOCKER_PID|MU_LOCKER_RETRY, + mu_locker_assign); + mu_locker_set_default_retry_timeout (1); + mu_locker_set_default_retry_count (300); + + /* Register needed modules */ + MU_AUTH_REGISTER_ALL_MODULES (); + + /* Register all supported mailbox and mailer formats */ + mu_register_all_formats (); + mu_registrar_record (mu_smtp_record); + + mda_filter_cfg_init (); + mu_tcpwrapper_cfg_init (); + mu_acl_cfg_init (); + mda_cli_capa_init (); + + mu_m_server_create (&server, program_version); + mu_m_server_set_conn (server, lmtp_connection); + mu_m_server_set_prefork (server, mu_tcp_wrapper_prefork); + mu_m_server_set_mode (server, MODE_INTERACTIVE); + mu_m_server_set_max_children (server, 20); + mu_m_server_set_timeout (server, 600); + mu_m_server_cfg_init (server, NULL); + + /* Parse command line */ + mu_cli (argc, argv, &cli, capa, server, &argc, &argv); + + mu_stdstream_strerr_setup (mu_log_syslog ? + MU_STRERR_SYSLOG : MU_STRERR_STDERR); + + if (argc) + { + mu_error (_("too many arguments")); + return EX_USAGE; + } + + return lmtp_server (); +} + +static mu_stream_t +lmtp_transcript (mu_stream_t iostream) +{ + int rc; + mu_stream_t dstr, xstr; + + rc = mu_dbgstream_create (&dstr, MU_DIAG_DEBUG); + if (rc) + mu_error (_("cannot create debug stream; transcript disabled: %s"), + mu_strerror (rc)); + else + { + rc = mu_xscript_stream_create (&xstr, iostream, dstr, NULL); + if (rc) + mu_error (_("cannot create transcript stream: %s"), + mu_strerror (rc)); + else + { + /* FIXME: Would do a mu_stream_unref (iostream) here, + however mu_xscript_stream_create *may* steal the reference. + This should be fixed in mu_xscript_stream_create. */ + iostream = xstr; + } + } + return iostream; +} + +static void +lmtp_reply (mu_stream_t iostr, char *code, char *enh, char *fmt, ...) +{ + va_list ap; + char *str = NULL; + size_t size = 0; + + va_start (ap, fmt); + mu_vasnprintf (&str, &size, fmt, ap); + va_end (ap); + + if (!str) + { + mu_error (_("not enough memory")); + exit (EX_TEMPFAIL); + } + + while (*str) + { + char *end = strchr (str, '\n'); + + if (end) + { + size_t len = end - str; + mu_stream_printf (iostr, "%s-", code); + if (enh) + mu_stream_printf (iostr, "%s ", enh); + mu_stream_printf (iostr, "%.*s\r\n", (int) len, str); + for (str = end; *str && *str == '\n'; str++); + } + else + { + mu_stream_printf (iostr, "%s ", code); + if (enh) + mu_stream_printf (iostr, "%s ", enh); + mu_stream_printf (iostr, "%s\r\n", str); + str += strlen (str); + } + } +} + +enum lmtp_state + { + state_none, + + state_init, + state_lhlo, + state_mail, + state_rcpt, + state_data, + state_quit, + state_dot, + + state_end + }; + +#define NSTATE ((int) state_end + 1) + +enum lmtp_command + { + cmd_unknown, + cmd_lhlo, + cmd_mail, + cmd_rcpt, + cmd_data, + cmd_quit, + cmd_rset, + cmd_help, + cmd_dot + }; + +#define NCMD ((int)cmd_dot + 1) + +#define SNO state_none +#define SIN state_init +#define SHL state_lhlo +#define SML state_mail +#define SRC state_rcpt +#define SDA state_data +#define SQT state_quit +#define SDT state_dot +#define SEN state_end + +static int transtab[NCMD][NSTATE] = { +/* state_ SNO SIN SHL SML SRC SDA SQT SDT SEN */ +/* unkn */ { SNO, SNO, SNO, SNO, SNO, SNO, SNO, SNO, SEN }, +/* lhlo */ { SNO, SHL, SNO, SNO, SNO, SNO, SNO, SNO, SNO }, +/* mail */ { SNO, SNO, SML, SNO, SNO, SNO, SNO, SNO, SNO }, +/* rcpt */ { SNO, SNO, SNO, SRC, SRC, SNO, SNO, SNO, SNO }, +/* data */ { SNO, SNO, SNO, SNO, SDA, SNO, SNO, SNO, SNO }, +/* quit */ { SNO, SEN, SEN, SEN, SEN, SEN, SEN, SEN, SEN }, +/* rset */ { SNO, SIN, SIN, SIN, SIN, SIN, SIN, SIN, SNO }, +/* help */ { SNO, SIN, SHL, SML, SRC, SDT, SQT, SDT, SEN }, +/* dot */ { SNO, SNO, SNO, SNO, SNO, SQT, SNO, SNO, SNO }, +}; + + +/* Delivery data */ +static char *lhlo_domain; /* Sender domain */ +static char *mail_from; /* Sender address */ +static mu_list_t rcpt_list; /* Recipient addresses */ +static mu_message_t mesg; /* Collected message */ + + +static int +cfun_unknown (mu_stream_t iostr, char *arg) +{ + lmtp_reply (iostr, "500", "5.5.1", "Command unrecognized"); + return 0; +} + + +static void +add_default_domain (char *str, int len, char **pret) +{ + *pret = malloc (len + 1 + strlen (lhlo_domain) + 1); + if (!*pret) + { + mu_error (_("not enough memory")); + exit (EX_SOFTWARE); + } + memcpy (*pret, str, len); + (*pret)[len] = '@'; + strcpy (*pret + len + 1, lhlo_domain); +} + +#define MAILER_DAEMON "MAILER-DAEMON" + +static int +check_address (char *arg, int with_domain, char **pret) +{ + if (strchr (arg, '@') == 0) + { + char *addr = NULL; + size_t addrlen = 0; + + if (*arg == '<') + { + size_t len = strlen (arg); + if (arg[len - 1] == '>') + { + if (len == 2) /* null address */ + { + if (!with_domain) + /* Null address is only legal in mail from */ + return 1; + addr = MAILER_DAEMON; + addrlen = sizeof MAILER_DAEMON - 1; + } + else + { + addr = arg + 1; + addrlen = len - 2; + } + } + else + return 1; + } + else + { + addr = arg; + addrlen = strlen (arg); + } + + if (with_domain) + add_default_domain (addr, addrlen, pret); + else + { + *pret = malloc (addrlen + 1); + memcpy (*pret, addr, addrlen); + (*pret)[addrlen] = 0; + } + } + else + { + mu_address_t addr; + char *s; + int rc = mu_address_create (&addr, arg); + if (rc) + return 1; + if (with_domain) + rc = mu_address_aget_email (addr, 1, &s); + else + rc = mu_address_aget_local_part (addr, 1, &s); + mu_address_destroy (&addr); + if (rc || !s) + return 1; + *pret = s; + } + return 0; +} + +static int +cfun_mail_from (mu_stream_t iostr, char *arg) +{ + if (*arg == 0) + { + lmtp_reply (iostr, "501", "5.5.2", "Syntax error"); + return 1; + } + + if (check_address (arg, 1, &mail_from)) + { + lmtp_reply (iostr, "553", "5.1.8", "Address format error"); + return 1; + } + lmtp_reply (iostr, "250", "2.1.0", "Go ahead"); + return 0; +} + +static int +cfun_rcpt_to (mu_stream_t iostr, char *arg) +{ + char *user; + struct mu_auth_data *auth; + + if (*arg == 0) + { + lmtp_reply (iostr, "501", "5.5.2", "Syntax error"); + return 1; + } + + /* FIXME: Check if domain is OK */ + if (check_address (arg, 0, &user)) + { + lmtp_reply (iostr, "553", "5.1.8", "Address format error"); + return 1; + } + auth = mu_get_auth_by_name (user); + if (!auth) + { + lmtp_reply (iostr, "550", "5.1.1", "User unknown"); + free (user); + return 1; + } + mu_auth_data_free (auth); + if (!rcpt_list) + { + mu_list_create (&rcpt_list); + mu_list_set_destroy_item (rcpt_list, mu_list_free_item); + } + mu_list_append (rcpt_list, user); + lmtp_reply (iostr, "250", "2.1.5", "Go ahead"); + return 0; +} + +static int +dot_temp_fail (void *item, void *cbdata) +{ + char *name = item; + mu_stream_t iostr = cbdata; + lmtp_reply (iostr, "450", "4.1.0", "%s: temporary failure", name); + return 0; +} + +static int +dot_deliver (void *item, void *cbdata) +{ + char *name = item; + mu_stream_t iostr = cbdata; + char *errp = NULL; + + switch (mda_deliver_to_user (mesg, name, &errp)) + { + case 0: + lmtp_reply (iostr, "250", "2.0.0", "%s: delivered", name); + break; + + case EX_UNAVAILABLE: + if (errp) + lmtp_