summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2019-10-12 09:43:24 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2019-10-12 12:55:18 (GMT)
commit739c6ee525a4f7bb76b8fe2bd75e81a122764ced (patch) (side-by-side diff)
treeb90dfed5972048513d2076e5562a77e4e862d8b0
parent6ec886e647516e800febddee3f70491edfb561b0 (diff)
downloadmailutils-739c6ee525a4f7bb76b8fe2bd75e81a122764ced.tar.gz
mailutils-739c6ee525a4f7bb76b8fe2bd75e81a122764ced.tar.bz2
Split maidag into three single-purpose tools
Maidag operated in three modes: mda, url and lmtp. In mda mode it is normally started by sendmail with non-root privileges. In order to be able to write to other users' mailboxes, the binary must be setuid, which creates certain security threats. As these appear to be impossible to avoid in a single multi-purpose program, it has been decided to replace maidag with three single-purpose tools: mda, putmail, and lmtpd. The mda tool is a local mail delivery agent. It is the only one for which the setuid bit is required, so special measures have been taken to secure it. In particular, to avoid unverified user inputs it disallows to override any configuration settings from the command line. The two other tools provide the functionality of the url and lmtp mode. * Makefile.am (MAIDAG_DIR): Replace with MDA_DIR * configure.ac (MU_COND_MAILBOX_QUOTA): New conditional. Use names relative to ${top_builddir} instead of ".". * maidag: Remove. * mda/.gitignore: New file. * mda/Makefile.am: New file. * mda/lib/Makefile.am: New file. * mda/lib/deliver.c: New file. * mda/lib/forward.c: New file. * mda/lib/libmda.h: New file. * mda/lib/mailquota.c: New file. * mda/lib/script.c: New file. * mda/lib/util.c: New file. * mda/lmtpd.c: New file. * mda/mda.c: New file. * mda/putmail.c: New file. * mda/tests/.gitignore: New file. * mda/tests/Makefile.am: New file. * mda/tests/atlocal.in: New file. * mda/tests/input.msg: New file. * mda/tests/lmtpd.at: New file. * mda/tests/putmail.at: New file. * mda/tests/testsuite.at: New file. * doc/texinfo/programs/maidag.texi: Remove. * doc/texinfo/programs/mda.texi: New file. * doc/texinfo/programs/lmtpd.texi: New file.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--Makefile.am6
-rw-r--r--configure.ac16
-rw-r--r--doc/texinfo/Makefile.am4
-rw-r--r--doc/texinfo/mailutils.texi61
-rw-r--r--doc/texinfo/programs.texi20
-rw-r--r--doc/texinfo/programs/lmtpd.texi66
-rw-r--r--doc/texinfo/programs/mda.texi (renamed from doc/texinfo/programs/maidag.texi)515
-rw-r--r--doc/texinfo/programs/putmail.texi83
-rw-r--r--doc/texinfo/sieve.texi6
-rw-r--r--maidag/.gitignore6
-rw-r--r--maidag/maidag.c592
-rw-r--r--maidag/maidag.h205
-rw-r--r--maidag/script.c135
-rw-r--r--maidag/tests/forward.at79
-rw-r--r--maidag/tests/mda.at50
-rw-r--r--mda/.gitignore3
-rw-r--r--mda/Makefile.am (renamed from maidag/Makefile.am)55
-rw-r--r--mda/lib/Makefile.am (copied from maidag/tests/testsuite.at)32
-rw-r--r--mda/lib/deliver.c (renamed from maidag/deliver.c)206
-rw-r--r--mda/lib/forward.c (renamed from maidag/forward.c)79
-rw-r--r--mda/lib/libmda.h129
-rw-r--r--mda/lib/mailquota.c (renamed from maidag/mailquota.c)70
-rw-r--r--mda/lib/script.c260
-rw-r--r--mda/lib/util.c (renamed from maidag/util.c)75
-rw-r--r--mda/lmtpd.c (renamed from maidag/lmtp.c)284
-rw-r--r--mda/mda.c143
-rw-r--r--mda/putmail.c76
-rw-r--r--mda/tests/.gitignore (renamed from maidag/tests/.gitignore)0
-rw-r--r--mda/tests/Makefile.am (renamed from maidag/tests/Makefile.am)8
-rw-r--r--mda/tests/atlocal.in (renamed from maidag/tests/atlocal.in)4
-rw-r--r--mda/tests/input.msg (renamed from maidag/tests/input.msg)0
-rw-r--r--mda/tests/lmtpd.at (renamed from maidag/tests/lmtp.at)10
-rw-r--r--mda/tests/putmail.at (renamed from maidag/tests/url-mbox.at)10
-rw-r--r--mda/tests/testsuite.at (renamed from maidag/tests/testsuite.at)19
34 files changed, 1680 insertions, 1627 deletions
diff --git a/Makefile.am b/Makefile.am
index a0fb57c..716be7a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -32,8 +32,8 @@ if MU_COND_IMAP4D
IMAP4D_DIR = imap4d
endif
-if MU_COND_MAIDAG
- MAIDAG_DIR = maidag
+if MU_COND_MDA
+ MDA_DIR = mda
endif
if MU_COND_MAIL
@@ -105,7 +105,7 @@ SUBDIRS = . \
$(FRM_DIR)\
$(POP3D_DIR)\
$(IMAP4D_DIR)\
- $(MAIDAG_DIR)\
+ $(MDA_DIR)\
$(MAIL_DIR)\
$(SIEVE_DIR)\
$(MESSAGES_DIR)\
diff --git a/configure.ac b/configure.ac
index c841acf..5c77172 100644
--- a/configure.ac
+++ b/configure.ac
@@ -933,7 +933,7 @@ if test -n "$SQL_MODULES"; then
USE_SQL=1
AC_DEFINE(USE_SQL)
BUILD_SQL=libsql.la
- SQLLIB=../sql/libsql.la
+ SQLLIB='${top_builddir}/sql/libsql.la'
for module in $SQL_MODULES
do
@@ -957,7 +957,6 @@ if test -n "$SQL_MODULES"; then
SQL_MODULES="$SQL_MODULES"
fi])
fi
-
# LDAP support
AC_ARG_WITH(ldap,
@@ -980,6 +979,10 @@ if test $status_ldap = maybe; then
fi
+# Mailbox quota support
+AM_CONDITIONAL([MU_COND_MAILBOX_QUOTA],[test -n "$status_dbm$status_mysql"])
+
+
# Virtual domain support
MU_ENABLE_SUPPORT(virtual-domains)
AC_SUBST(SITE_VIRTUAL_PWDDIR)
@@ -1182,7 +1185,7 @@ GINT_INIT([gint],[2.2.0 with-guile],
if test -z "$GUILE_BINDIR"; then
GUILE_BINDIR="`guile-config info prefix`/bin"
fi
- LIBMU_SCM=../libmu_scm/libmu_scm.la
+ LIBMU_SCM='${top_builddir}/libmu_scm/libmu_scm.la'
LIBMU_SCM_DEPS='${MU_LIB_MAILBOX} ${MU_LIB_MAILER}'
MU_GUILE_SIEVE_MOD_DIR='$(GUILE_SITE)/$(PACKAGE)/sieve-modules'
GINT_INCLUDES='${MU_APP_COMMON_INCLUDES}'
@@ -1324,7 +1327,7 @@ MU_ENABLE_BUILD(imap4d,,,["$mu_build_servers" = yes],,[server_list])
MU_ENABLE_BUILD(comsat,,,["$mu_build_servers" = yes],,[server_list])
MU_ENABLE_BUILD(frm,,,["$mu_build_clients" = yes],,[client_list])
-MU_ENABLE_BUILD(maidag,,,["$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}')
@@ -1363,7 +1366,7 @@ AC_CONFIG_FILES([testsuite/Makefile testsuite/atlocal])
MU_CONFIG_TESTSUITE(libmailutils)
MU_CONFIG_TESTSUITE(frm)
-MU_CONFIG_TESTSUITE(maidag)
+MU_CONFIG_TESTSUITE(mda)
MU_CONFIG_TESTSUITE(mail)
MU_CONFIG_TESTSUITE(messages)
MU_CONFIG_TESTSUITE(readmsg)
@@ -1518,7 +1521,8 @@ AC_CONFIG_FILES([
libproto/Makefile
libproto/mbox/Makefile
libproto/mailer/Makefile
- maidag/Makefile
+ mda/Makefile
+ mda/lib/Makefile
mail/Makefile
mail/testsuite/Makefile
libmailutils/auth/Makefile
diff --git a/doc/texinfo/Makefile.am b/doc/texinfo/Makefile.am
index 453997f..95438eb 100644
--- a/doc/texinfo/Makefile.am
+++ b/doc/texinfo/Makefile.am
@@ -36,7 +36,9 @@ programs_TEXINFOS = \
programs/readmsg.texi\
programs/sieve.texi\
programs/guimb.texi\
- programs/maidag.texi\
+ programs/mda.texi\
+ programs/lmtpd.texi\
+ programs/putmail.texi\
programs/mimeview.texi\
programs/pop3d.texi\
programs/imap4d.texi\
diff --git a/doc/texinfo/mailutils.texi b/doc/texinfo/mailutils.texi
index b1a0a27..f93f233 100644
--- a/doc/texinfo/mailutils.texi
+++ b/doc/texinfo/mailutils.texi
@@ -141,7 +141,9 @@ Mailutils Programs
* sieve:: Mail Filtering Utility.
* guimb:: Mailbox Scanning and Processing Language.
-* maidag:: General-purpose Mail Delivery Agent.
+* mda:: Local Mail Delivery Agent.
+* lmtpd:: LMTP Daemon.
+* putmail:: Incorporate a Message to a Mailbox.
* mimeview:: Universal File Viewer.
@@ -202,29 +204,13 @@ Debugging
@command{mail} --- Send and Receive Mail
* Invoking Mail:: Command Line Options.
+* Reading Mail:: Reading Mail.
* Composing Mail:: Composing Mail.
* MIME:: How to Attach Files.
-* Reading Mail:: Reading Mail.
* Scripting:: Scripting.
* Mail Variables:: How to Alter the Behavior of @command{mail}.
* Mail Configuration Files:: Personal and System-wide Configuration Files.
-Composing Mail
-
-* Quitting Compose Mode::
-* Getting Help on Compose Escapes::
-* Editing the Message::
-* Modifying the Headers::
-* Enclosing Another Message::
-* Adding a File to the Message::
-* Attaching a File to the Message::
-* Printing And Saving the Message::
-* Signing the Message::
-* Printing Another Message::
-* Inserting Value of a Mail Variable::
-* Executing Other Mail Commands::
-* Executing Shell Commands::
-
Reading Mail
* Command Syntax:: Syntax of mail internal commands.
@@ -245,6 +231,22 @@ Reading Mail
* Incorporating New Mail::
* Shell Escapes::
+Composing Mail
+
+* Quitting Compose Mode::
+* Getting Help on Compose Escapes::
+* Editing the Message::
+* Modifying the Headers::
+* Enclosing Another Message::
+* Adding a File to the Message::
+* Attaching a File to the Message::
+* Printing And Saving the Message::
+* Signing the Message::
+* Printing Another Message::
+* Inserting Value of a Mail Variable::
+* Executing Other Mail Commands::
+* Executing Shell Commands::
+
@command{movemail} --- Moves Mail from the User Maildrop to the Local File
* Movemail Configuration::
@@ -274,28 +276,27 @@ A Sieve Interpreter
* Passing Options to Scheme::
* Command Line Option Summary::
-maidag
+mda
-* Sendmail-maidag:: Using @command{maidag} with Sendmail.
-* Exim-maidag:: Using @command{maidag} with Exim.
-* MeTA1-maidag:: Using @command{maidag} with MeTA1.
+* Sendmail-mda:: Using @command{mda} with Sendmail.
+* Exim-mda:: Using @command{mda} with Exim.
+* MeTA1-mda:: Using @command{mda} with MeTA1.
* Mailbox Quotas::
-* Maidag Scripting::
+* MDA Scripting::
* Forwarding::
-* Url-mode:: Delivering Messages to a URL.
-* Remote Mailbox Delivery::
-* Conf-maidag:: Maidag Configuration File Summary
+* Conf-mda:: @command{mda} Configuration File Summary.
+* Mailing lists:: How to implement Mailing Lists with @command{mda}.
Mailbox Quotas
* DBM Quotas:: Keeping Quotas in DBM File.
* SQL Quotas:: Keeping Quotas in SQL Database.
-Maidag Scripting
+Scripting in @command{mda}
-* Sieve Maidag Filters::
-* Scheme Maidag Filters::
-* Python Maidag Filters::
+* Sieve MDA Filters::
+* Scheme MDA Filters::
+* Python MDA Filters::
mimeview
diff --git a/doc/texinfo/programs.texi b/doc/texinfo/programs.texi
index c8c3b97..f2de687 100644
--- a/doc/texinfo/programs.texi
+++ b/doc/texinfo/programs.texi
@@ -32,7 +32,9 @@ syntax.
* sieve:: Mail Filtering Utility.
* guimb:: Mailbox Scanning and Processing Language.
-* maidag:: General-purpose Mail Delivery Agent.
+* mda:: Local Mail Delivery Agent.
+* lmtpd:: LMTP Daemon.
+* putmail:: Incorporate a Message to a Mailbox.
* mimeview:: Universal File Viewer.
@@ -2890,9 +2892,19 @@ Show payload information
@include programs/guimb.texi
@page
-@node maidag
-@section maidag
-@include programs/maidag.texi
+@node mda
+@section mda
+@include programs/mda.texi
+
+@page
+@node lmtpd
+@section lmtpd
+@include programs/lmtpd.texi
+
+@page
+@node putmail
+@section putmail
+@include programs/putmail.texi
@page
@node mimeview
diff --git a/doc/texinfo/programs/lmtpd.texi b/doc/texinfo/programs/lmtpd.texi
new file mode 100644
index 0000000..e0212db
--- a/dev/null
+++ b/doc/texinfo/programs/lmtpd.texi
@@ -0,0 +1,66 @@
+@c This is part of the GNU Mailutils manual.
+@c Copyright (C) 1999-2019 Free Software Foundation, Inc.
+@c See file mailutils.texi for copying conditions.
+@comment *******************************************************************
+@pindex lmtpd
+The @acronym{LMTP} is a local mail transport protocol defined in RFC
+2033. GNU Mailutils is shipped with @command{lmtpd} - a daemon for
+delivering messages using this protocol.
+
+The daemon shares most of its codebase and configuration with
+@command{mda} and consequently provides the same features.
+@xref{mda}, for a detailed description of these.
+
+The behavior of @command{lmtpd} is affected by the following configuration
+statements:
+
+@multitable @columnfractions 0.3 0.6
+@headitem Statement @tab Reference
+@item server @tab @xref{Server Settings}
+@item acl @tab @xref{acl statement}.
+@item tcp-wrappers @tab @xref{tcp-wrappers statement}.
+@item debug @tab @xref{debug statement}.
+@item mailbox @tab @xref{mailbox statement}.
+@item locking @tab @xref{locking statement}.
+@item pam @tab @xref{pam statement}.
+@item sql @tab @xref{sql statement}.
+@item virtdomain @tab @xref{virtdomain statement}.
+@item radius @tab @xref{radius statement}.
+@item ldap @tab @xref{ldap statement}.
+@item auth @tab @xref{auth statement}.
+@item mailer @tab @xref{mailer statement}.
+@end multitable
+
+@menu
+* MeTA1-lmtpd:: Using @command{lmtpd} with MeTA1.
+@end menu
+
+@node MeTA1-lmtpd
+@subsection Using @command{lmtpd} with MeTA1.
+MeTA1 (@uref{http://meta1.org}) communicates with the delivery agent
+using @acronym{LMTP}.
+
+The socket to listen for LMTP requests must be specified using the
+@code{server} statement (@pxref{Server Settings}). For the purposes of
+this section, let's suppose @command{lmtpd} will listen on a
+@acronym{UNIX} socket @file{/var/spool/meta1/lmtpsock}. Then, the
+following (minimal) @command{lmtpd} configuration will do the job:
+
+@example
+# @r{Run as daemon.}
+mode daemon;
+# @r{Switch to this group after startup.}
+group meta1c;
+# @r{Configure server:}
+server unix:///var/spool/meta1/lmtpsock @{
+ transcript no;
+@};
+@end example
+
+To configure MeTA1 to use this socket, add the following statement to
+the @samp{smtpc} section in @file{/etc/meta1/meta1.conf}:
+
+@example
+ LMTP_socket="lmtpsock";
+@end example
+
diff --git a/doc/texinfo/programs/maidag.texi b/doc/texinfo/programs/mda.texi
index c66d4ae..acce830 100644
--- a/doc/texinfo/programs/maidag.texi
+++ b/doc/texinfo/programs/mda.texi
@@ -2,54 +2,50 @@
@c Copyright (C) 1999-2019 Free Software Foundation, Inc.
@c See file mailutils.texi for copying conditions.
@comment *******************************************************************
-@pindex maidag
-@UNREVISED
-
-The name @samp{maidag} stands for @i{Mai}l @i{d}elivery @i{ag}ent. It
-is a general-purpose @acronym{MDA} offering a rich set of
-features. It can operate both in traditional mode, reading the message
-from its standard input, and in @acronym{LMTP} mode. @command{Maidag}
-is able to deliver mail to any mailbox format, supported by GNU
-Mailutils. These formats, among others, include @samp{smtp://},
-@samp{prog://} and @samp{sendmail://} which are
+@pindex mda
+GNU local mail delivery agent reads a message from its standard input
+and delivers it to one or more local recipients listed in the command
+line. When we speak about @i{local} recipients, we mean that these
+are system users that are known to the system that runs @command{mda}.
+However, the mailboxes of these users can be local as well as remote
+ones. @command{mda} is able to deliver mail to any mailbox format,
+supported by GNU Mailutils. These formats, among others, include
+@samp{smtp://}, @samp{prog://} and @samp{sendmail://} which are
equivalent to forwarding a message over @acronym{SMTP} to a remote
-node. Thus, @command{maidag} supersedes both @command{mail.local} and
-@command{mail.remote} utilities from GNU Mailutils versions prior to
-2.0.
+node.
-@command{Maidag} is also able to process incoming messages using
+@command{Mda} is also able to process incoming messages using
Sieve, Scheme or Python scripts and, based on results of this
processing, to take a decision on whether to actually deliver and
where to deliver them. Due to its extensive scripting facilities,
-@command{maidag} offers much more flexibility than other popular
-@acronym{MDA}s, such as @command{procmail}.
+@command{mda} offers much more flexibility than other popular
+@acronym{MDA}s.
@menu
-* Sendmail-maidag:: Using @command{maidag} with Sendmail.
-* Exim-maidag:: Using @command{maidag} with Exim.
-* MeTA1-maidag:: Using @command{maidag} with MeTA1.
+* Sendmail-mda:: Using @command{mda} with Sendmail.
+* Exim-mda:: Using @command{mda} with Exim.
+* MeTA1-mda:: Using @command{mda} with MeTA1.
* Mailbox Quotas::
-* Maidag Scripting::
+* MDA Scripting::
* Forwarding::
-* Url-mode:: Delivering Messages to a URL.
-* Remote Mailbox Delivery::
-* Conf-maidag:: Maidag Configuration File Summary
+* Conf-mda:: @command{mda} Configuration File Summary.
+* Mailing lists:: How to implement Mailing Lists with @command{mda}.
@end menu
-@node Sendmail-maidag
-@subsection Using @command{maidag} with Sendmail.
+@node Sendmail-mda
+@subsection Using @command{mda} with Sendmail.
@cindex Sendmail
-When used as a @acronym{MDA} with Sendmail, @command{maidag} must be
-invoked from the local mailer definition in the @file{sendmail.cf}
-file. It must have the following flags set: @samp{lswS}. These mean:
-the mailer is local, quote characters should be stripped off the
-address before invoking the mailer, the user must have a valid account
-on this machine and the userid should not be reset before calling the
-mailer. Additionally, the flags @samp{fn} may be specified to allow
-@command{maidag} to generate the usual @samp{From } envelope instead
+When used with Sendmail, @command{mda} must be invoked from the local
+mailer definition in the @file{sendmail.cf} file. The flags
+@samp{lswS} must be set for the mailer. These mean: the mailer is
+local, quote characters should be stripped off the address before
+invoking the mailer, the user must have a valid account on this
+machine and the userid should not be reset before calling the mailer.
+Additionally, the @samp{fn} flags may be specified to allow
+@command{mda} to generate the usual @samp{From } envelope instead
of the one supplied by @command{sendmail}.
-If you wish to use @command{maidag} with non-local authentication,
+If you wish to use @command{mda} with non-local authentication,
such as @acronym{SQL} or @acronym{LDAP}, you also need to remove the
@samp{w} flag, since in that case the user is not required to have a
valid account on the machine that runs @command{sendmail}.
@@ -57,7 +53,7 @@ valid account on the machine that runs @command{sendmail}.
Here is an example of mailer definition in @file{sendmail.cf}
@example
-Mlocal, P=/usr/local/sbin/maidag,
+Mlocal, P=/usr/local/sbin/mda,
F=lsDFMAw5:/|@@qSPfhn9,
S=EnvFromL/HdrFromL, R=EnvToL/HdrToL,
T=DNS/RFC822/X-Unix,
@@ -68,72 +64,46 @@ To define local mailer in @samp{mc} source file, it will suffice to
set:
@example
-define(`LOCAL_MAILER_PATH', `/usr/local/sbin/maidag')
+define(`LOCAL_MAILER_PATH', `/usr/local/sbin/mda')
define(`LOCAL_MAILER_ARGS', `mail $u')
@end example
-@node Exim-maidag
-@subsection Using @command{maidag} with Exim.
+@node Exim-mda
+@subsection Using @command{mda} with Exim.
@cindex Exim
-Using @command{maidag} with Exim is quite straightforward. The
+Using @command{mda} with Exim is quite straightforward. The
following example illustrates the definition of the appropriate transport
and director in @file{exim.conf}:
@example
# transport
-maidag_pipe:
+mda_pipe:
driver = pipe
- command = /usr/local/sbin/maidag $local_part
+ command = /usr/local/sbin/mda $local_part
return_path_add
delivery_date_add
envelope_to_add
# director
-maidag:
+mda:
driver = localuser
- transport = maidag_pipe
+ transport = mda_pipe
@end example
-@node MeTA1-maidag
-@subsection Using @command{maidag} with MeTA1.
-@cindex LMTP
+@node MeTA1-mda
+@subsection Using @command{mda} with MeTA1.
@cindex MeTA1
MeTA1 (@uref{http://meta1.org}) communicates with the delivery agent
-using @acronym{LMTP}.
-
-LMTP mode is enabled in @command{maidag} by the @samp{delivery-mode lmtp}
-statement. The socket to listen on must be specified using
-@code{server} statement (@pxref{Server Settings}). For the purposes of
-this section, let's suppose @command{maidag} will listen on a
-@acronym{UNIX} socket @file{/var/spool/meta1/lmtpsock}. Then, the
-following (minimal) @command{maidag} configuration will do the job:
-
-@example
-# @r{Start in LMTP mode.}
-delivery-mode lmtp;
-# @r{Run as daemon.}
-mode daemon;
-# @r{Switch to this group after startup.}
-group meta1c;
-# @r{Configure server:}
-server unix:///var/spool/meta1/lmtpsock @{
- transcript no;
-@};
-@end example
-
-To configure MeTA1 to use this socket, add the following statement to
-the @samp{smtpc} section in @file{/etc/meta1/meta1.conf}:
-
-@example
- LMTP_socket="lmtpsock";
-@end example
+using @acronym{LMTP}. Instead of using @command{mda} you will have to
+start the @acronym{LMTP} daemon @command{lmtpd} and configure MeTA1 to
+communicate with it. @xref{MeTA1-lmtpd}, for details.
@node Mailbox Quotas
@subsection Mailbox Quotas
@dfn{Mailbox quota} is a limit on the size of the mailbox. When a
-mailbox size reaches this limit, @command{maidag} stops accepting
+mailbox size reaches this limit, @command{mda} stops accepting
messages for this recipient and returns an error condition to the
sender. The error code is accompanied by the following error message:
@@ -155,7 +125,9 @@ unavailable} (corresponding to the @acronym{SMTP} return code
@command{maidag} configuration file:
@example
-exit-quota-tempfail yes;
+quota @{
+ exit-tempfail yes;
+@}
@end example
@noindent
@@ -181,7 +153,7 @@ To use @acronym{DBM} quota database, GNU Mailutils must
be compiled with one of the following command line options:
@option{--with-gdbm}, @option{--with-berkeley-db}, @option{--with-ndbm},
@option{--with-tokyocabinet}, or @option{--with-kyotocabinet}.
-Examine the output of @command{maidag --show-config-options}, if not sure.
+Examine the output of @command{mda --show-config-options}, if not sure.
The quota database should have the following structure:
@@ -199,7 +171,7 @@ maximum mailbox size in bytes. A number may optionally be followed by
A special value @samp{NONE} means no mailbox size limit for this user.
@end table
-Here is an example of a valid quota database
+Here is an example of a quota database in text form:
@example
# Default quota value:
@@ -215,17 +187,19 @@ karin 10mB
@end example
To use the @acronym{DBM} quota database, specify its absolute name using
-@code{quota-db} configuration statement, e.g.:
+the @code{database} configuration statement in the @code{quota}
+section, e.g.:
@example
-quota-db /etc/mail/quota.db;
+quota @{
+ database /etc/mail/quota.db;
+@}
@end example
@node SQL Quotas
@subsubsection Keeping Quotas in SQL Database
-Configuration statement @code{quota-query} allows to specify a special
-query to retrieve the quota from the database. Currently (as of mailutils
+User quotas can be kept in an SQL table as well. Currently (as of mailutils
version @value{VERSION}) it is assumed that this table can be accessed
using the credentials set in @samp{sql} configuration statement
(@pxref{SQL Statement}).
@@ -248,11 +222,21 @@ To retrieve user quota the following query can be used:
SELECT quota FROM mailbox_quota WHERE user_name='$@{user@}'
@end example
+To define this query use the @code{sql-query} statement:
+
+@example
+quota @{
+ sql-query "SELECT quota "
+ "FROM mailbox_quota "
+ "WHERE user_name='$@{user@}'";
+@}
+@end example
+
There are no special provisions for specifying group quotas, similar to
@samp{DEFAULT} in @acronym{DBM} databases. This is because group quotas can
-easily be implemented using @acronym{SQL} language. @command{Maidag}
+easily be implemented using @acronym{SQL} language. @command{Mda}
always uses the first tuple from the set returned by mailbox quota
-query. So, you may add a special entry to the @code{mailbox_quota}
+query. So, you can add a special entry to the @code{mailbox_quota}
table that would keep the group quota. In the discussion below we assume
that the @code{user_name} column for this entry is lexicographically
less than any other user name in the table. Let's suppose the group
@@ -268,8 +252,8 @@ ORDER BY user_name DESC
@noindent
will return two tuples if the user is found in
@code{mailbox_quota}. Due to @code{ORDER} statement, the first tuple
-will contain the quota for the user, which will be used by
-@command{maidag}. On the other hand, if the requested user name is not
+will contain quota for the user, which will be used by
+@command{mda}. On the other hand, if the requested user name is not
present in the table, the above query will return a single tuple
containing the group quota.
@@ -277,15 +261,17 @@ The following configuration statement instructs @command{maidag} to
use this query for retrieving the user quota:
@example
-quota-query "SELECT quota "
+quota @{
+ sql-query "SELECT quota "
"FROM mailbox_quota "
"WHERE user_name IN ('$@{user@}','00DEFAULT') "
"ORDER BY user_name DESC";
+@}
@end example
-@node Maidag Scripting
-@subsection Maidag Scripting
-@command{Maidag} can use global or per-user @dfn{mail filters} to
+@node MDA Scripting
+@subsection Scripting in @command{mda}
+@command{Mda} can use global or per-user @dfn{mail filters} to
decide whether to deliver the message, and where to deliver it. As of
Mailutils version @value{VERSION}, such mail filters may be written in
the following languages:
@@ -310,30 +296,35 @@ Expands to the recipient home directory.
Expands to the recipient user name.
@end table
+@anchor{scripting language}
By default, the filename extension decides which scripting language will
be used. User can alter the choice using @samp{language} configuration
statement. For example:
@example
-language "python"
-script "~/.maidag-py-filter"
+script @{
+ language python;
+ pattern "~/.maidag-py-filter";
+@}
@end example
@menu
-* Sieve Maidag Filters::
-* Scheme Maidag Filters::
-* Python Maidag Filters::
+* Sieve MDA Filters::
+* Scheme MDA Filters::
+* Python MDA Filters::
@end menu
-@node Sieve Maidag Filters
-@subsubsection Sieve Maidag Filters
+@node Sieve MDA Filters
+@subsubsection Sieve MDA Filters
@kwindex script
The file name of the Sieve filter to use is specified using
@samp{script} configuration statement. For example, the following
configuration statement:
@example
-script "~/.maidag.sv"
+script @{
+ pattern "~/.maidag.sv";
+@}
@end example
@noindent
@@ -350,23 +341,25 @@ example, to deliver message to another mailbox, use the
Any modifications to headers or body of the message performed by the
Sieve code will be visible in the delivered message.
-@node Scheme Maidag Filters
-@subsubsection Scheme Maidag Filters
+@node Scheme MDA Filters
+@subsubsection Scheme MDA Filters
@kwindex script
The file name of the Scheme mail filter is specified using
@samp{script} configuration statement. For example, the following
configuration statement:
@example
-script "~/.maidag.scm"
+script @{
+ pattern "~/.maidag.scm";
+@}
@end example
@noindent
-instructs `maidag' to use file `.maidag.scm' in the recipient home
-directory as a Scheme filter.
+instructs @command{mda} to use file @file{.maidag.scm} in the
+recipient home directory as a Scheme filter.
-@node Python Maidag Filters
-@subsubsection Python Maidag Filters
+@node Python MDA Filters
+@subsubsection Python MDA Filters
@kwindex script
The file name of the Python mail filter is specified using
@@ -374,12 +367,14 @@ The file name of the Python mail filter is specified using
configuration statement:
@example
-script "~/.maidag.py"
+script @{
+ pattern "~/.maidag.py";
+@}
@end example
@noindent
-instructs `maidag' to use file `.maidag.py' in the recipient home
-directory as a Python filter.
+instructs @command{mda} to use the file @file{.maidag.py} in the
+recipient home directory as a Python filter.
@noindent
A simple example of a mail filter written in Python:
@@ -416,30 +411,49 @@ except Exception:
@node Forwarding
@subsection Forwarding
@cindex forward
-@dfn{Forward file} is a special file in the user's home directory that
+A @dfn{forward file} is a special file in the user's home directory that
contains the email address of the mailbox where the user wants to
forward his mail. Normally, forward files are processed by
@acronym{MTA}. However, there are some @acronym{MTA} that lack this
feature. One of them is MeTA1.
-@command{Maidag} provides a forwarding feature that is useful to
-compensate the lack of it.
+@command{Mda} provides a forwarding feature that is useful to
+compensate the lack of it. This feature is controlled by the
+@code{forward} section in the configuration file:
-@kwindex forward-file
-Name of the forward file is given using @code{forward-file}
-configuration statement. A common usage is:
+@example
+forward @{
+ # Process forward file.
+ file @var{name};
+ # Configure safety checks for the forward file.
+ file-checks (@var{list});
+@}
+@end example
+
+@kwindex file, forward
+The name of the forward file is given by the @code{file}
+statement in the @code{forward} section. A common usage is:
@example
-forward-file .forward;
+forward @{
+ file .forward;
+@}
@end example
The forward file is always searched in the recipient home directory.
-@kwindex forward-file-checks
-Before actually using the file, a number of safety checks are
+Before actually using the forward file, a number of safety checks are
performed on it. If the file fails to pass one of these checks, no
forwarding is performed and the message is delivered as usual. These
-checks can be configured using @code{forward-file-checks} statement.
+checks are configured using the @code{forward.file-checks} statement:
+
+@example
+forward @{
+ file .forward;
+ file-checks (@var{list});
+@}
+@end example
+
Its argument is a list of the following keywords:
@table @asis
@@ -467,48 +481,156 @@ The file cannot reside in a world writable directory.
All of the above checks.
@end table
-The default is @samp{forward-file-checks all}.
+The default is @samp{file-checks all}.
Each of these keywords may be prefixed by @samp{no} to disable this
particular check. For example:
@example
-forward-file-checks (nodir_iwoth, nodir_iwgrp);
+forward @{
+ file-checks (nodir_iwoth, nodir_iwgrp);
+ file .forward;
+@}
@end example
-@node Url-mode
-@subsection Delivering Messages to a URL.
-When invoked with the @option{--url} command line option,
-@command{maidag} treats its arguments as a list of mailbox
-@acronym{URL}s and attempts to deliver the message to each of them.
+@node Conf-mda
+@subsection MDA Configuration File Summary
-For example:
+The behavior of @command{mda} is affected by the following configuration
+statements:
+
+@multitable @columnfractions 0.3 0.6
+@headitem Statement @tab Reference
+@item debug @tab @xref{debug statement}.
+@item mailbox @tab @xref{mailbox statement}.
+@item locking @tab @xref{locking statement}.
+@item pam @tab @xref{pam statement}.
+@item sql @tab @xref{sql statement}.
+@item virtdomain @tab @xref{virtdomain statement}.
+@item radius @tab @xref{radius statement}.
+@item ldap @tab @xref{ldap statement}.
+@item auth @tab @xref{auth statement}.
+@item mailer @tab @xref{mailer statement}.
+@end multitable
+
+@deffn {MDA Config} stderr @var{bool}
+If @var{bool} is true, log to standard error instead of syslog.
+@end deffn
+
+@deffn {MDA Config} deliver @{ ... @}
+This section contains general delivery settings:
@example
-$ maidag --url maildir:///home/smith/Mail
+deliver @{
+ domain @var{string};
+ exit-multiple-delivery-success @var{arg};
+@};
@end example
+@end deffn
+
+@deffn {deliver} domain @var{name}
+Default email domain.
+@end deffn
+
+@deffn {deliver} exit-multiple-delivery-success @var{arg};
+In case of multiple delivery, exit with code 0 if at least
+one delivery succeeded.
+@end deffn
-The same effect has the @samp{delivery-mode url} configuration statement.
-@node Remote Mailbox Delivery
-@subsection Remote Mailbox Delivery
-@command{Maidag} can be used to deliver mail to remote mailboxes, such
-as @samp{imap} or @samp{smtp}. If the mailbox @acronym{URL}
-is @samp{smtp} or @samp{sendmail}, the message is
-actually forwarded over @acronym{SMTP} to the remote node, so
-@command{maidag} acts as a message transfer agent. For example:
+@deffn {MDA Config} forward @{ ... @}
+Controls the forwarding support:
@example
-$ maidag --url smtp://10.10.1.100:24
+forward @{
+ file @var{name};
+ file-checks (@var{list});
+@}
+@end example
+@end deffn
+
+@deffn {forward} file @var{name}
+Defines the name of the forward file. E.g.:
+
+@example
+forward @{
+ file .forward;
+@}
@end example
-This command line will send the message to the machine
-@samp{10.10.1.100} using port @samp{24} (private mail system).
+@xref{Forwarding}, for a detailed description.
+@end deffn
-The @samp{prog} mailbox may be of special use. Delivering to
-this mailbox results in invoking the specified command with the given
-arguments and passing the message to its standard input. There are two
-ways to specify a @samp{prog} mailbox:
+@deffn {forward} file-checks (@var{list})
+Configures safety checks to be performed on the forward file prior to
+using it. @xref{Forwarding}, for a detailed description.
+@end deffn
+
+@deffn {MDA Config} quota @{ ... @}
+This section configures mail quota support. @xref{Mailbox Quotas},
+for a detailed description.
+
+@example
+quota @{
+ database @var{name};
+ sql-query @var{query};
+ exit-tempfail @var{bool};
+@}
+@end example
+@end deffn
+
+@deffn {quota} database @var{name}
+Sets the name of the quota database in DBM format. @xref{DBM Quotas}.
+@end deffn
+
+@deffn {quota} sql-query @var{query}
+If the quotas are kept in a SQL table, this statement defines the SQL
+query to retrieve the quota for a given user name. @xref{SQL Quotas}.
+@end deffn
+
+@deffn {quota} exit-tempfail @var{bool}
+By default, if a message cannot be delivered because the user has
+exceeded its mail quota, or its delivery would cause it to be
+exceeded, @command{MDA} exits with the @samp{service unavailable}
+status, which causes MTA to return the 550 code. If
+@code{exit-tempfail} is set to true, it will return a temporary error
+instead.
+@end deffn
+
+@deffn {MDA Config} script @{ ... @}
+Controls scripting. @xref{MDA Scripting}.
+
+@example
+script @{
+ language @var{lang};
+ pattern @var{glob};
+@}
+@end example
+@end deffn
+
+@deffn {script} language @var{lang}
+Defines the language that is used for scripting. Allowed values for
+@var{lang} are: @samp{sieve}, @samp{scheme}, or @samp{python}.
+@xref{scripting language}.
+@end deffn
+
+@deffn {script} pattern @var{pat}
+Defines the pattern for the script file name. The @samp{~} at the
+begiining of the pattern will be replaced with the name of the home
+directory of the recipient user. The @samp{%u} in pattern will be
+replaced with the recipient user name, and @samp{%h} with the home
+directory for that user.
+@end deffn
+
+@node Mailing lists
+@subsection Mailing list implementation
+
+This subsection explains how to implement mailing lists in
+@command{mda} using the @samp{prog} mailbox scheme.
+
+Delivery to the @samp{prog} mailbox results in invoking the specified
+command with the given arguments and passing the message to its
+standard input. There are two ways to specify a @samp{prog} mailbox:
@table @asis
@item prog://@var{program}?@var{args}
@@ -522,15 +644,14 @@ white space.
In both cases, @var{args} do not include @code{argv[0]}.
-The @samp{prog} mailbox may be used, in particular, to implement
-mailing lists with MeTA1.
+The @samp{prog} mailbox can be used to implement mailing lists.
-For example, suppose that the @command{maidag} configuration contains:
+For example, suppose that the @command{mda} configuration contains:
@example
auth @{
- authorization sql:system;
- authentication generic:system;
+ authorization (sql, system);
+ authentication (generic, system);
@}
sql @{
@@ -544,7 +665,7 @@ sql @{
@}
@end example
-Then, the following entries in the @samp{userdb} table implement
+Then, the following entries in the @samp{userdb} table implement the
@email{mailman@@yourdomain} mailing list:
@example
@@ -565,107 +686,9 @@ mysql> select * from userdb;
+---------------------+---------------------------------------+
@end example
-@node Conf-maidag
-@subsection Maidag Configuration File Summary
-
-The behavior of @command{maidag} is affected by the following configuration
-statements:
-
-@multitable @columnfractions 0.3 0.6
-@headitem Statement @tab Reference
-@item debug @tab @xref{debug statement}.
-@item mailbox @tab @xref{mailbox statement}.
-@item locking @tab @xref{locking statement}.
-@item pam @tab @xref{pam statement}.
-@item sql @tab @xref{sql statement}.
-@item virtdomain @tab @xref{virtdomain statement}.
-@item radius @tab @xref{radius statement}.
-@item ldap @tab @xref{ldap statement}.
-@item auth @tab @xref{auth statement}.
-@item mailer @tab @xref{mailer statement}.
-@item server @tab @xref{Server Settings}. Used only in
-@acronym{LMTP} mode.
-@item acl @tab @xref{acl statement}.
-@item tcp-wrappers @tab @xref{tcp-wrappers statement}.
-@end multitable
-
-@deffn {Maidag Config} delivery-mode @var{mode}
-Configure delivery mode. The argument is one of: @samp{mda} (default),
-@samp{url}, or @samp{lmtp}.
-@end deffn
-
-@deffn {Maidag Config} ex-multiple-delivery-success @var{bool}
-In case of multiple delivery, exit with code 0 if at least one
-delivery has succeeded.
-@end deffn
-
-@deffn {Maidag Config} ex-quota-tempfail @var{bool}
-Indicate temporary failure if the recipient is over his mail quota.
-By default, permanent failure is returned. @xref{Mailbox Quotas}.
-@end deffn
-
-@deffn {Maidag Config} quota-db @var{file}
-Set the name of DBM quota database file. @xref{DBM Quotas}.
-@end deffn
-
-@deffn {Maidag Config} sieve-filter @var{pattern}
-Set file name or name pattern of the Sieve filter file.
-@xref{Sieve Maidag Filters}.
-@end deffn
-@deffn {Maidag Config} message-id-header @var{name}
-When logging Sieve actions, identify messages by the value of this
-header.
-@end deffn
-@deffn {Maidag Config} guile-filter @var{pattern}
-File name or name pattern for Guile filter file.
-@xref{Scheme Maidag Filters}.
-@end deffn
-@deffn {Maidag Config} debug @var{flags}
-Set additional debugging flags. Valid flags are:
-@table @asis
-@item g
-Print @command{guimb} stack traces.
-@item t
-Enable @command{sieve} trace (@code{MU_SIEVE_DEBUG_TRACE}).
-@item i
-Enable @command{sieve} instructions trace
-(@code{MU_SIEVE_DEBUG_INSTR}).
-
-@item l
-Log executed Sieve actions.
-@end table
-@end deffn
-
-@deffn {Maidag Config} stderr @var{bool}
-Log to stderr instead of syslog.
-@end deffn
-
-@deffn {Maidag Config} forward-file @var{file}
-Process forward file @var{file}. @xref{Forwarding}.
-@end deffn
-
-@deffn {Maidag Config} forward-file-checks @var{list}
-Configure safety checks for the forward file.
-@xref{Forwarding, forward-file-checks}.
-@end deffn
-
-@deffn {Maidag Config} group @var{list}
-In @acronym{LMTP} mode, retain supplementary groups from @var{list}.
-@end deffn
-
-@deffn {Maidag Config} listen @var{url}
-In @acronym{LMTP} mode, listen on @var{url}. Valid @acronym{URL}s are:
-@samp{tcp://@var{host}:@var{port}} (note that port is mandatory),
-@samp{file://@var{socket-file-name}} or
-@samp{socket://@var{socket-file-name}}.
-@end deffn
-
-@deffn {Maidag Config} reuse-address @var{bool}
-Reuse existing address (@acronym{LMTP} mode). Default is @samp{yes}.
-@end deffn
diff --git a/doc/texinfo/programs/putmail.texi b/doc/texinfo/programs/putmail.texi
new file mode 100644
index 0000000..9c6a024
--- a/dev/null
+++ b/doc/texinfo/programs/putmail.texi
@@ -0,0 +1,83 @@
+@c This is part of the GNU Mailutils manual.
+@c Copyright (C) 1999-2019 Free Software Foundation, Inc.
+@c See file mailutils.texi for copying conditions.
+@comment *******************************************************************
+@pindex putmail
+The @command{putmail} utility reads a message from its standard input
+and delivers it to the specified mailbox URL. The usage is:
+
+@example
+putmail @var{URL}
+@end example
+
+For example, to deliver mail to a local mailbox
+@file{/var/spool/mail/test}:
+
+@example
+putmail /var/spool/mail/test
+@end example
+
+Of course, this would work only it the @file{test} mailbox is writable
+for the user invoking @command{putmail}.
+
+The @code{smtp} mailbox scheme can be used for remote delivery. For
+example:
+
+@example
+putmail 'smtp://mail.example.org;to=ovr'
+@end example
+
+The program will initiate SMTP dialog with the server
+@samp{mail.example.org} and will send the message from its standard
+input to the user @samp{ovr} on that server.
+
+@menu
+* putmail options::
+* putmail configuration::
+@end menu
+
+@node putmail options
+@subsection putmail options
+
+@table @option
+@item -f @var{email}
+@itemx -r @var{email}
+@itemx --from=@var{email}
+Specify the sender address. If not used, the current user name
+will be used.
+
+@item -l @var{name}
+@itemx --language=@var{name}
+Define scripting language for the next @option{--script} option.
+Valid arguments are @samp{sieve}, @samp{scheme} and @samp{python}.
+
+@item --message-id-header=@var{header}
+Use this header to identify messages when logging Sieve actions
+
+@item -s @var{name}
+@itemx --script=@var{name}
+Set the name of the user-defined mail filter. @xref{MDA Scripting},
+for a detailed discussion of the scripting feature.
+@end table
+
+@node putmail configuration
+@subsection putmail configuration
+
+The behavior of @command{putmail} is affected by the following configuration
+statements:
+
+@multitable @columnfractions 0.3 0.6
+@headitem Statement @tab Reference
+@item debug @tab @xref{debug statement}.
+@item mailbox @tab @xref{mailbox statement}.
+@item locking @tab @xref{locking statement}.
+@item pam @tab @xref{pam statement}.
+@item sql @tab @xref{sql statement}.
+@item virtdomain @tab @xref{virtdomain statement}.
+@item radius @tab @xref{radius statement}.
+@item ldap @tab @xref{ldap statement}.
+@item auth @tab @xref{auth statement}.
+@item mailer @tab @xref{mailer statement}.
+@end multitable
+
+The utility also accepts all MDA configuration statements: @xref{Conf-mda}.
diff --git a/doc/texinfo/sieve.texi b/doc/texinfo/sieve.texi
index 7d0a916..57f5980 100644
--- a/doc/texinfo/sieve.texi
+++ b/doc/texinfo/sieve.texi
@@ -1472,14 +1472,14 @@ and @code{:body} control what parts of the message to pipe to the
command.
@*Example:
-The example below uses the @command{maidag} utility
-(@pxref{maidag}) to forward the message to user @samp{gray} on
+The example below uses the @command{putmail} utility
+(@pxref{putmail}) to forward the message to user @samp{gray} on
the machine @samp{mail.gnu.org}.
@smallexample
require "pipe";
-pipe "/usr/sbin/maidag --url smtp://gray@@mail.gnu.org"
+pipe "/usr/bin/putmail smtp://gray@@mail.gnu.org"
@end smallexample
@end deftypefn
diff --git a/maidag/.gitignore b/maidag/.gitignore
deleted file mode 100644
index 6e29f25..0000000
--- a/maidag/.gitignore
+++ b/dev/null
@@ -1,6 +0,0 @@
-.deps
-.gdbinit
-.libs
-Makefile
-Makefile.in
-maidag
diff --git a/maidag/maidag.c b/maidag/maidag.c
deleted file mode 100644
index b5f5504..0000000
--- a/maidag/maidag.c
+++ b/dev/null
@@ -1,592 +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 <http://www.gnu.org/licenses/>. */
-
-#include "maidag.h"
-#include "mailutils/cli.h"
-
-enum maidag_mode maidag_mode = mode_mda;
-int multiple_delivery; /* Don't return errors when delivering to multiple
- recipients */
-int ex_quota_tempfail; /* Return temporary failure if mailbox quota is
- exceeded. If this variable is not set, maidag
- will return "service unavailable" */
-int exit_code = EX_OK; /* Exit code to be used */
-uid_t current_uid; /* Current user id */
-
-char *quotadbname = NULL; /* Name of mailbox quota database */
-char *quota_query = NULL; /* SQL query to retrieve mailbox quota */
-
-char *sender_address = NULL;
-char *default_domain;
-mu_script_t script_handler;
-
-mu_list_t script_list;
-
-char *forward_file = NULL;
-#define FORWARD_FILE_PERM_CHECK ( \
- MU_FILE_SAFETY_OWNER_MISMATCH | \
- MU_FILE_SAFETY_GROUP_WRITABLE | \
- MU_FILE_SAFETY_WORLD_WRITABLE | \
- MU_FILE_SAFETY_LINKED_WRDIR | \
- MU_FILE_SAFETY_DIR_IWGRP | \
- MU_FILE_SAFETY_DIR_IWOTH )
-int forward_file_checks = FORWARD_FILE_PERM_CHECK;
-
-/* Debuggig options */
-int debug_level; /* General debugging level */
-char *message_id_header; /* Use the value of this header as message
- identifier when logging Sieve actions */
-
-/* For LMTP mode */
-mu_m_server_t server;
-char *lmtp_url_string;
-int reuse_lmtp_address = 1;
-int maidag_transcript;
-
-const char *program_version = "maidag (" PACKAGE_STRING ")";
-
-static void
-set_debug_flags (const char *arg)
-{
- while (*arg)
- {
- if (mu_script_debug_flags (arg, (char**)&arg) == 0)
- break;
- else if (mu_isdigit (*arg))
- debug_level = strtoul (arg, (char**)&arg, 10);
- else
- {
- mu_error (_("%c is not a valid debug flag"), *arg);
- break;
- }
-
- if (*arg == ',')
- arg++;
- else if (*arg)
- {
- mu_error (_("expected comma, but found %c"), *arg);
- exit (1);
- }
- }
-}
-
-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 void
-set_foreground (struct mu_parseopt *po, struct mu_option *opt,
- char const *arg)
-{
- mu_m_server_set_foreground (server, 1);
-}
-
-static void
-set_delivery_url (struct mu_parseopt *po, struct mu_option *opt,
- char const *arg)
-{
- maidag_mode = mode_url;
- mu_log_syslog = 0;
-}
-
-static void
-set_delivery_mda (struct mu_parseopt *po, struct mu_option *opt,
- char const *arg)
-{
- maidag_mode = mode_mda;
-}
-
-static void
-set_sender_address (struct mu_parseopt *po, struct mu_option *opt,
- char const *arg)
-{
- if (sender_address != NULL)
- {
- mu_parseopt_error (po, _("multiple --from options"));
- exit (po->po_exit_error);
- }
- else
- {
- char *errmsg;
- int rc = mu_str_to_c (arg, opt->opt_type, opt->opt_ptr, &errmsg);
- if (rc)
- {
- mu_parseopt_error (po, _("can't set sender address: %s"),
- errmsg ? errmsg : mu_strerror (rc));
- exit (po->po_exit_error);
- }
- }
-}
-
-static void
-set_lmtp_mode (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
-{
- maidag_mode = mode_lmtp;
- if (arg)
- {
- struct mu_sockaddr *s;
-
- if (mu_m_server_parse_url (server, arg, &s))
- {
- mu_parseopt_error (po, _("%s: invalid URL"), arg);
- exit (po->po_exit_error);
- }
- mu_m_server_listen (server, s, MU_IP_TCP);
- }
-}
-
-static void
-set_debug (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
-{
- set_debug_flags (arg);
-}
-
-static void
-set_stderr (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
-{
- mu_log_syslog = 0;
-}
-
-static void
-set_script_lang (struct mu_parseopt *po, struct mu_option *opt,
- char const *arg)
-{
- script_handler = mu_script_lang_handler (arg);
- if (!script_handler)
- {
- mu_parseopt_error (po, _("unknown or unsupported language: %s"), arg);
- exit (po->po_exit_error);
- }
-}
-
-static void
-set_script_pattern (struct mu_parseopt *po, struct mu_option *opt,
- char const *arg)
-{
- switch (script_register (arg))
- {
- case 0:
- return;
-
- case EINVAL:
- mu_parseopt_error (po, _("%s has unknown file suffix"), arg);
- break;
-
- default:
- mu_parseopt_error (po, _("error registering script"));
- }
- exit (po->po_exit_error);
-}
-
-static struct mu_option maidag_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 },
- { "url", 0, NULL, MU_OPTION_DEFAULT,
- N_("deliver to given URLs"),
- mu_c_string, NULL, set_delivery_url },
- { "mda", 0, NULL, MU_OPTION_DEFAULT,
- N_("force MDA mode even if not started as root"),
- mu_c_string, NULL, set_delivery_mda },
- { "from", 'f', N_("EMAIL"), MU_OPTION_DEFAULT,
- N_("specify the sender's name"),
- mu_c_string, &sender_address, set_sender_address },
- { NULL, 'r', NULL, MU_OPTION_ALIAS },
- { "lmtp", 0, N_("URL"), MU_OPTION_ARG_OPTIONAL,
- N_("operate in LMTP mode"),
- mu_c_string, NULL, set_lmtp_mode },
- { "debug", 'x', N_("FLAGS"), MU_OPTION_DEFAULT,
- N_("enable debugging"),
- mu_c_string, NULL, set_debug },
- { "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, &maidag_transcript },
-
- MU_OPTION_GROUP (N_("Scripting options")),
- { "language", 'l', N_("STRING"), MU_OPTION_DEFAULT,
- N_("define scripting language for the next --script option"),
- mu_c_string, NULL, set_script_lang },
- { "script", 's', N_("PATTERN"), MU_OPTION_DEFAULT,
- N_("set name pattern for user-defined mail filter"),
- mu_c_string, NULL, set_script_pattern },
- { "message-id-header", 0, N_("STRING"), MU_OPTION_DEFAULT,
- N_("use this header to identify messages when logging Sieve actions"),
- mu_c_string, &message_id_header },
- MU_OPTION_END
-}, *options[] = { maidag_options, NULL };
-
-static char *capa[] = {
- "auth",
- "debug",
- "logging",
- "mailbox",
- "locking",
- "mailer",
- "sieve",
- NULL
-};
-
-static int
-cb_debug (void *data, mu_config_value_t *val)
-{
- if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
- return 1;
- set_debug_flags (val->v.string);
- return 0;
-}
-
-static int
-cb_stderr (void *data, mu_config_value_t *val)
-{
- int res;
-
- if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
- return 1;
- if (mu_str_to_c (val->v.string, mu_c_bool, &res, NULL))
- mu_error (_("not a boolean"));
- else
- mu_log_syslog = !res;
- return 0;
-}
-
-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
-cb2_forward_file_checks (const char *name, void *data)
-{
- if (mu_file_safety_compose (data, name, FORWARD_FILE_PERM_CHECK))
- mu_error (_("unknown keyword: %s"), name);
- return 0;
-}
-
-static int
-cb_forward_file_checks (void *data, mu_config_value_t *arg)
-{
- return mu_cfg_string_value_cb (arg, cb2_forward_file_checks,
- &forward_file_checks);
-}
-
-static int
-cb_script_language (void *data, mu_config_value_t *val)
-{
- if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
- return 1;
- script_handler = mu_script_lang_handler (val->v.string);
- if (!script_handler)
- {
- mu_error (_("unsupported language: %s"), val->v.string);
- return 1;
- }
- return 0;
-}
-
-static int
-cb_script_pattern (void *data, mu_config_value_t *val)
-{
- if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
- return 1;
-
- switch (script_register (val->v.string))
- {
- case 0:
- break;
-
- case EINVAL:
- mu_error (_("%s has unknown file suffix"), val->v.string);
- break;
-
- default:
- mu_error (_("error registering script"));
- }
- return 0;
-}
-
-struct mu_cfg_param filter_cfg_param[] = {
- { "language", mu_cfg_callback, NULL, 0, cb_script_language,
- N_("Set script language."),
- /* TRANSLATORS: words to the right of : are keywords - do not translate */
- N_("arg: python|guile") },
- { "pattern", mu_cfg_callback, NULL, 0, cb_script_pattern,
- N_("Set script pattern."),
- N_("arg: glob") },
- { NULL }
-};
-
-static int
-cb_delivery_mode (void *data, mu_config_value_t *val)
-{
- static mu_kwd_t mode_tab[] = {
- { "mda", mode_mda },
- { "url", mode_url },
- { "lmtp", mode_lmtp },
- { NULL }
- };
- int n;
-
- if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
- return 1;
-
- if (mu_kwd_xlat_name (mode_tab, val->v.string, &n) == 0)
- {
- maidag_mode = n;
- if (maidag_mode == mode_url)
- mu_log_syslog = 0;
- }
- else
- mu_error (_("%s is unknown"), val->v.string);
- return 0;
-}
-
-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;
-}
-
-struct mu_cfg_param maidag_cfg_param[] = {
- { "delivery-mode", mu_cfg_callback, NULL, 0, cb_delivery_mode,
- N_("Set delivery mode"),
- /* TRANSLATORS: words to the right of : are keywords - do not translate */
- N_("mode: mda|url|lmtp") },
- { "exit-multiple-delivery-success", mu_c_bool, &multiple_delivery, 0, NULL,
- N_("In case of multiple delivery, exit with code 0 if at least one "
- "delivery succeeded.") },
- { "exit-quota-tempfail", mu_c_bool, &ex_quota_tempfail, 0, NULL,
- N_("Indicate temporary failure if the recipient is over his mail quota.")
- },
-#ifdef ENABLE_DBM
- { "quota-db", mu_c_string, &quotadbname, 0, NULL,
- N_("Name of DBM quota database file."),
- N_("file") },
-#endif
-#ifdef USE_SQL
- { "quota-query", mu_c_string, &quota_query, 0, NULL,
- N_("SQL query to retrieve mailbox quota. This is deprecated, use "
- "sql { ... } instead."),
- N_("query") },
-#endif
- { "message-id-header", mu_c_string, &message_id_header, 0, NULL,
- N_("When logging Sieve actions, identify messages by the value of "
- "this header."),
- N_("name") },
- { "debug", mu_cfg_callback, NULL, 0, cb_debug,
- N_("Set maidag debug level. Debug level consists of one or more "
- "of the following letters:\n"
- " g - guile stack traces\n"
- " t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n"
- " i - sieve instructions trace (MU_SIEVE_DEBUG_INSTR)\n"
- " l - sieve action logs\n"),
- N_("arg: string") },
- { "stderr", mu_cfg_callback, NULL, 0, cb_stderr,
- N_("Log to stderr instead of syslog."),
- N_("arg: bool") },
- { "forward-file", mu_c_string, &forward_file, 0, NULL,
- N_("Process forward file.") },
- { "forward-file-checks", mu_cfg_callback, NULL, 0, cb_forward_file_checks,
- N_("Configure safety checks for the forward file."),
- N_("arg: list") },
- { "domain", mu_c_string, &default_domain, 0, NULL,
- N_("Default email domain") },
-/* LMTP support */
- { "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://<address: string>:<port: number> (note that port is "
- "mandatory)\n"
- " file://<socket-file-name>\n"
- "or socket://<socket-file-name>"),
- 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 void
-maidag_cfg_init ()
-{
- struct mu_cfg_section *section;
- if (mu_create_canned_section ("filter", &section) == 0)
- {
- section->docstring = N_("Add new message filter.");
- mu_cfg_section_add_params (section, filter_cfg_param);
- }
-}
-
-struct mu_cli_setup cli = {
- options,
- maidag_cfg_param,
- N_("GNU maidag -- the mail delivery agent."),
- N_("[recipient...]"),
- NULL,
- N_("Debug flags are:\n\
- g - guile stack traces\n\
- t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n\
- i - sieve instructions trace (MU_SIEVE_DEBUG_INSTR)\n\
- l - sieve action logs\n\
- 0-9 - Set maidag debugging level\n")
-};
-
-int
-main (int argc, char *argv[])
-{
- maidag_delivery_fn delivery_fun = NULL;
-
- /* Preparative work: close inherited fds, force a reasonable umask
- and prepare a logging. */
- close_fds ();
- 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);
-
- mu_tcpwrapper_cfg_init ();
- mu_acl_cfg_init ();
- maidag_cfg_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);
-
- mu_log_syslog = -1;
- mu_log_print_severity = 1;
-
- /* Parse command line */
-
- mu_cli_capa_register (&mu_cli_capa_sieve);
- mu_cli (argc, argv, &cli, capa, server, &argc, &argv);
-
- current_uid = getuid ();
-
- if (mu_log_syslog == -1)
- {
- mu_log_syslog = !(maidag_mode == mode_url);
- mu_stdstream_strerr_setup (mu_log_syslog ?
- MU_STRERR_SYSLOG : MU_STRERR_STDERR);
- }
-
- switch (maidag_mode)
- {
- case mode_lmtp:
- if (argc)
- {
- mu_error (_("too many arguments"));
- return EX_USAGE;
- }
- return maidag_lmtp_server ();
-
- case mode_url:
- /* FIXME: Verify if the urls are deliverable? */
- delivery_fun = deliver_to_url;
- break;
-
- case mode_mda:
- if (argc == 0)
- {
- mu_error (_("recipients not given"));
- return EX_USAGE;
- }
- delivery_fun = deliver_to_user;
- break;
- }
- return maidag_stdio_delivery (delivery_fun, argc, argv);
-}
-
-
diff --git a/maidag/maidag.h b/maidag/maidag.h
deleted file mode 100644
index 00709b7..0000000
--- a/maidag/maidag.h
+++ b/dev/null
@@ -1,205 +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 <http://www.gnu.org/licenses/>. */
-
-#if defined(HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-#include <errno.h>
-#include <grp.h>
-#include <netdb.h>
-#include <pwd.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
-
-#ifdef HAVE_SYSEXITS_H
-# include <sysexits.h>
-#else
-# define EX_OK 0 /* successful termination */
-# define EX__BASE 64 /* base value for error messages */
-# define EX_USAGE 64 /* command line usage error */
-# define EX_DATAERR 65 /* data format error */
-# define EX_NOINPUT 66 /* cannot open input */
-# define EX_NOUSER 67 /* addressee unknown */
-# define EX_NOHOST 68 /* host name unknown */
-# define EX_UNAVAILABLE 69 /* service unavailable */
-# define EX_SOFTWARE 70 /* internal software error */
-# define EX_OSERR 71 /* system error (e.g., can't fork) */
-# define EX_OSFILE 72 /* critical OS file missing */
-# define EX_CANTCREAT 73 /* can't create (user) output file */
-# define EX_IOERR 74 /* input/output error */
-# define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
-# define EX_PROTOCOL 76 /* remote error in protocol */
-# define EX_NOPERM 77 /* permission denied */
-# define EX_CONFIG 78 /* configuration error */
-# define EX__MAX 78 /* maximum listed value */
-#endif
-
-#ifndef INADDR_LOOPBACK
-# define INADDR_LOOPBAK 0x7f000001
-#endif
-
-#include <mailutils/attribute.h>
-#include <mailutils/errno.h>
-#include <mailutils/error.h>
-#include <mailutils/list.h>
-#include <mailutils/locker.h>
-#include <mailutils/mailbox.h>
-#include <mailutils/message.h>
-#include <mailutils/util.h>
-#include <mailutils/registrar.h>
-#include <mailutils/stream.h>
-#include <mailutils/url.h>
-#include <mailutils/mu_auth.h>
-#include <mailutils/sieve.h>
-#include <mailutils/nls.h>
-#include <mailutils/daemon.h>
-#include <mailutils/acl.h>
-#include <mailutils/server.h>
-#include <mailutils/cctype.h>
-#include <mailutils/io.h>
-#include <mailutils/dbm.h>
-
-#if defined (ENABLE_DBM) || defined (USE_SQL)
-# define USE_MAILBOX_QUOTAS 1
-#endif
-
-#include "tcpwrap.h"
-#include "muscript.h"
-
-/* Debug */
-extern int debug_level;
-#define dbg() if (debug_level) debug
-
-/* mailquota settings */
-#define MQUOTA_OK 0
-#define MQUOTA_EXCEEDED 1
-#define MQUOTA_UNLIMITED 2
-
-#define MAXFD 64
-#define EX_QUOTA() (ex_quota_tempfail ? EX_TEMPFAIL : EX_UNAVAILABLE)
-
-enum maidag_mode
- {
- mode_mda,
- mode_url,
- mode_lmtp
- };
-
-extern enum maidag_mode maidag_mode;
-extern int exit_code;
-extern int log_to_stderr;
-extern int multiple_delivery;
-extern int ex_quota_tempfail;
-extern uid_t current_uid;
-extern char *quotadbname;
-extern char *quota_query;
-
-extern char *forward_file;
-extern int forward_file_checks;
-
-extern char *sender_address;
-extern char *default_domain;
-extern mu_list_t script_list;
-extern char *message_id_header;
-extern int sieve_debug_flags;
-extern int sieve_enable_log;
-
-extern mu_m_server_t server;
-extern char *lmtp_url_string;
-extern int reuse_lmtp_address;
-extern mu_list_t lmtp_groups;
-extern mu_acl_t maidag_acl;
-extern int maidag_transcript;
-
-void close_fds (void);
-int switch_user_id (struct mu_auth_data *auth, int user);
-
-typedef int (*maidag_delivery_fn) (mu_message_t, char *, char **);
-
-int deliver_to_url (mu_message_t msg, char *dest_id, char **errp);
-int deliver_to_user (mu_message_t msg, char *dest_id, char **errp);
-
-int maidag_stdio_delivery (maidag_delivery_fn fun, int argc, char **argv);
-int maidag_lmtp_server (void);
-int lmtp_connection (int fd, struct sockaddr *sa, int salen,
- struct mu_srv_config *pconf,
- void *data);
-
-void maidag_error (const char *fmt, ...) MU_PRINTFLIKE(1, 2);
-void notify_biff (mu_mailbox_t mbox, char *name, size_t size);
-void guess_retval (int ec);
-
-int sieve_test (struct mu_auth_data *auth, mu_message_t msg);
-int check_quota (struct mu_auth_data *auth, mu_off_t size, mu_off_t *rest);
-
-enum maidag_forward_result
- {
- maidag_forward_none,
- maidag_forward_ok,
- maidag_forward_metoo,
- maidag_forward_error
- };
-
-enum maidag_forward_result maidag_forward (mu_message_t msg,
- struct mu_auth_data *auth,
- char *fwfile);
-
-/* Scripting support */
-typedef int (*maidag_script_fun) (mu_message_t msg,
- struct mu_auth_data *auth,
- const char *prog);
-
-extern mu_script_t script_handler;
-
-struct maidag_script
-{
- mu_script_t scr; /* Handler script */
- const char *pat; /* Script name pattern */
-};
-
-maidag_script_fun script_lang_handler (const char *lang);
-maidag_script_fun script_suffix_handler (const char *name);
-int script_register (const char *pattern);
-int script_apply (mu_message_t msg, struct mu_auth_data *auth);
-
-/* guile.c */
-extern int debug_guile;
-int scheme_check_msg (mu_message_t msg, struct mu_auth_data *auth,
- const char *prog);
-
-/* python.c */
-int python_check_msg (mu_message_t msg, struct mu_auth_data *auth,
- const char *prog);
-
-/* sieve.c */
-int sieve_check_msg (mu_message_t msg, struct mu_auth_data *auth,
- const char *prog);
-
diff --git a/maidag/script.c b/maidag/script.c
deleted file mode 100644
index 628331d..0000000
--- a/maidag/script.c
+++ b/dev/null
@@ -1,135 +0,0 @@
-/* GNU Mailutils -- a suite of utilities for electronic mail
- Copyright (C) 1999-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 <http://www.gnu.org/licenses/>. */
-
-#include "maidag.h"
-
-int
-script_register (const char *pattern)
-{
- mu_script_t scr;
- struct maidag_script *p;
-
- if (script_handler)
- scr = script_handler;
- else
- {
- scr = mu_script_suffix_handler (pattern);
- if (!scr)
- return EINVAL;
- }
-
- p = malloc (sizeof (*p));
- if (!p)
- return MU_ERR_FAILURE;
-
- p->scr = scr;
- p->pat = pattern;
-
- if (!script_list)
- {
- if (mu_list_create (&script_list))
- return MU_ERR_FAILURE;
- }
-
- if (mu_list_append (script_list, p))
- return MU_ERR_FAILURE;
-
- return 0;
-}
-
-
-struct apply_script_closure
-{
- struct mu_auth_data *auth;
- mu_message_t msg;
-};
-
-static char const *script_env[] = { "location=MDA", "phase=during", NULL };
-
-static int
-apply_script (void *item, void *data)
-{
- struct maidag_script *scr = item;
- struct apply_script_closure *clos = data;
- char *progfile;
- int rc;
- struct stat st;
- mu_script_descr_t sd;
-
- progfile = mu_expand_path_pattern (scr->pat, clos->auth->name);
- if (stat (progfile, &st))
- {
- if (debug_level > 2)
- mu_diag_funcall (MU_DIAG_DEBUG, "stat", progfile, errno);
- else if (errno != ENOENT)
- mu_diag_funcall (MU_DIAG_NOTICE, "stat", progfile, errno);
- free (progfile);
- return 0;
- }
-
- rc = mu_script_init (scr->scr, progfile, script_env, &sd);
- if (rc)
- mu_error (_("initialization of script %s failed: %s"),
- progfile, mu_strerror (rc));
- else
- {
- if (mu_script_sieve_log)
- mu_script_log_enable (scr->scr, sd, clos->auth->name,
- message_id_header);
- rc = mu_script_process_msg (scr->scr, sd, clos->msg);
- if (rc)
- mu_error (_("script %s failed: %s"), progfile, mu_strerror (rc));
- mu_script_done (scr->scr, sd);
- }
-
- free (progfile);
-
- return rc;
-}
-
-int
-script_apply (mu_message_t msg, struct mu_auth_data *auth)
-{
- int rc = 0;
-
- if (script_list)
- {
- mu_attribute_t attr;
- struct apply_script_closure clos;
-
- clos.auth = auth;
- clos.msg = msg;
-
- mu_message_get_attribute (msg, &attr);
- mu_attribute_unset_deleted (attr);
- if (switch_user_id (auth, 1) == 0)
- {
- chdir (auth->dir);
- rc = mu_list_foreach (script_list, apply_script, &clos);
- chdir ("/");
- switch_user_id (auth, 0);
- if (rc == 0)
- {
- mu_attribute_t attr;
- mu_message_get_attribute (msg, &attr);
- rc = mu_attribute_is_deleted (attr);
- }
- else
- rc = 0;
- }
- }
- return rc;
-}
diff --git a/maidag/tests/forward.at b/maidag/tests/forward.at
deleted file mode 100644
index c67b7a5..0000000
--- a/maidag/tests/forward.at
+++ b/dev/null
@@ -1,79 +0,0 @@
-# This file is part of GNU Mailutils. -*- Autotest -*-
-# 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 <http://www.gnu.org/licenses/>.
-
-AT_SETUP([forwarding support])
-AT_KEYWORDS([maidag forward])
-
-m4_pushdef([FORWARD_OPTIONS],[dnl
- --set "^mailer^url=sendmail:$abs_top_builddir/examples/mta" dnl
- --set "^forward-file=$forward" dnl
- --set "^forward-file-checks=none"])
-
-AT_CHECK([
-test -w / && AT_SKIP_TEST
-forward=`pwd`/my.forward
-namelist=`sed '/^#/d;s/:.*//' /etc/passwd | sed '3,$d'`
-test -n "$namelist" || AT_SKIP_TEST
-
-cat > my.forward <<EOT
-foo@bar.baz
-\\$namelist
-EOT
-
-set -- $namelist
-
-cat > experr <<EOT
-maidag: notice: skipping forward file $forward: already processed
-EOT
-
-echo ENVELOPE > expout.0
-cat $abs_top_srcdir/maidag/tests/input.msg >> expout.0
-echo "" >> expout.0
-
-echo "ENVELOPE FROM: gulliver@example.net" > expout.1
-echo "ENVELOPE TO: <foo@bar.baz>" >> expout.1
-awk '{printf("% 4d:",NR-1); if (NF!=0) printf(" %s",$0); print ""}' $abs_top_srcdir/maidag/tests/input.msg >> expout.1
-echo "END OF MESSAGE" >> expout.1
-
-MTA_DIAG=mta.diag
-export MTA_DIAG
-mkdir spool
-maidag MAIDAG_OPTIONS FORWARD_OPTIONS --from gulliver@example.net $1 < \
- $abs_top_srcdir/maidag/tests/input.msg || exit $?
-
-for name in $namelist
-do
- if test -f spool/$name; then
- sed '1s/From gulliver@example.net.*/ENVELOPE/' spool/$name | \
- cmp expout.0 - >/dev/null || echo "$name mailbox mismatch" >&2
- else
- echo "$name missed message" >&2
- fi
-done
-
-if test -f mta.diag; then
- cmp mta.diag expout.1 >/dev/null || echo "remote copy mismatch" >&2
-else
- echo "remote delivery failed" >&2
-fi
-],
-[0],
-[],
-[experr])
-
-m4_popdef([FORWARD_OPTIONS])
-
-AT_CLEANUP
diff --git a/maidag/tests/mda.at b/maidag/tests/mda.at
deleted file mode 100644
index 4ed2dbe..0000000
--- a/maidag/tests/mda.at
+++ b/dev/null
@@ -1,50 +0,0 @@
-# This file is part of GNU Mailutils. -*- Autotest -*-
-# 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 <http://www.gnu.org/licenses/>.
-
-AT_SETUP([MDA mode])
-AT_KEYWORDS([maidag mda0])
-
-AT_CHECK([
-echo ENVELOPE > expout
-cat $abs_top_srcdir/maidag/tests/input.msg >> expout
-echo "" >> expout
-mkdir spool
-maidag MAIDAG_OPTIONS --mda --from gulliver@example.net root < dnl
- $abs_top_srcdir/maidag/tests/input.msg || exit $?
-sed '1s/From gulliver@example.net.*/ENVELOPE/' spool/root
-],
-[0],
-[expout])
-
-AT_CLEANUP
-
-#
-AT_SETUP([MDA mode, explicit envelope])
-AT_KEYWORDS([maidag mda1])
-
-AT_CHECK([
-echo "From gulliver Thu Oct 7 19:10:57 2010" > expout
-cat $abs_top_srcdir/maidag/tests/input.msg >> expout
-mkdir spool
-maidag MAIDAG_OPTIONS --mda --from gulliver@example.net root < expout || exit $?
-echo "" >> expout
-cat spool/root
-],
-[0],
-[expout])
-
-AT_CLEANUP
-
diff --git a/mda/.gitignore b/mda/.gitignore
new file mode 100644
index 0000000..f0e6495
--- a/dev/null
+++ b/mda/.gitignore
@@ -0,0 +1,3 @@
+lmtpd
+mda
+putmail
diff --git a/maidag/Makefile.am b/mda/Makefile.am
index db53c09..866dc71 100644
--- a/maidag/Makefile.am
+++ b/mda/Makefile.am
@@ -13,25 +13,40 @@
# You should have received a copy of the GNU General Public License
# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
-SUBDIRS = . tests
-
-sbin_PROGRAMS=maidag
-maidag_SOURCES=\
- deliver.c\
- forward.c\
- lmtp.c\
- maidag.c\
- maidag.h\
- mailquota.c\
- script.c\
- util.c
+SUBDIRS = lib . tests
+sbin_PROGRAMS = mda lmtpd
+bin_PROGRAMS = putmail
+
+mda_SOURCES = mda.c
+lmtpd_SOURCES = lmtpd.c
+putmail_SOURCES = putmail.c
if MU_COND_DBM
- LIBMU_DBM=../libmu_dbm/libmu_dbm.la
+ LIBMU_DBM=${top_builddir}/libmu_dbm/libmu_dbm.la
endif
-maidag_LDADD = \
- ../lib/libmuscript.a\
+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}\
@@ -49,11 +64,9 @@ maidag_LDADD = \
@DBMLIBS@\
@MU_TCPWRAP_LIBRARIES@
-AM_CPPFLAGS = -I${top_srcdir} @MU_APP_COMMON_INCLUDES@ @GUILE_INCLUDES@ \
- @PYTHON_INCLUDES@
+AM_CPPFLAGS = -I${top_srcdir} @MU_APP_COMMON_INCLUDES@ -Ilib
install-exec-hook:
- for i in $(sbin_PROGRAMS); do\
- chown root:mail $(DESTDIR)$(sbindir)/$$i;\
- chmod 4755 $(DESTDIR)$(sbindir)/$$i;\
- done
+ chown root:mail $(DESTDIR)$(sbindir)/mda
+ chmod 4755 $(DESTDIR)$(sbindir)/mda
+
diff --git a/maidag/tests/testsuite.at b/mda/lib/Makefile.am
index d82d400..8f78331 100644
--- a/maidag/tests/testsuite.at
+++ b/mda/lib/Makefile.am
@@ -1,5 +1,4 @@
-# This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2010-2019 Free Software Foundation, Inc.
+# 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
@@ -14,19 +13,22 @@
# You should have received a copy of the GNU General Public License
# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
-m4_include([testsuite.inc])
+noinst_LIBRARIES = libmda.a
+libmda_a_SOURCES = \
+ deliver.c\
+ forward.c\
+ script.c\
+ util.c
-m4_define([MAIDAG_OPTIONS],[dnl
-MUT_DEFAULT_OPTIONS dnl
---set '|mailbox|mailbox-pattern='`pwd`/spool/'${user}' dnl
---set .auth.authorization=system dnl
---stderr])
+noinst_HEADERS = libmda.h
-AT_INIT
-AT_TESTED([maidag])
-MUT_VERSION(maidag)
-m4_include([mda.at])
-m4_include([lmtp.at])
-m4_include([url-mbox.at])
-m4_include([forward.at])
+# # FIXME @MU_TCPWRAP_LIBRARIES@
+
+AM_CPPFLAGS = -I${top_srcdir} @MU_APP_COMMON_INCLUDES@ @GUILE_INCLUDES@ \
+ @PYTHON_INCLUDES@
+
+if MU_COND_MAILBOX_QUOTA
+ libmda_a_SOURCES += mailquota.c
+ AM_CPPFLAGS += "-DUSE_MAILBOX_QUOTAS=1"
+endif
diff --git a/maidag/deliver.c b/mda/lib/deliver.c
index b074abe..2bbfe99 100644
--- a/maidag/deliver.c
+++ b/mda/lib/deliver.c
@@ -14,7 +14,52 @@
You should have received a copy of the GNU General Public License
along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
-#include "maidag.h"
+#include "libmda.h"
+
+static char *default_domain;
+int multiple_delivery; /* Don't return errors when delivering to multiple
+ recipients */
+static char *sender_address = NULL;
+
+static void
+set_sender_address (struct mu_parseopt *po, struct mu_option *opt,
+ char const *arg)
+{
+ if (sender_address != NULL)
+ {
+ mu_parseopt_error (po, _("multiple --from options"));
+ exit (po->po_exit_error);
+ }
+ else
+ {
+ char *errmsg;
+ int rc = mu_str_to_c (arg, opt->opt_type, opt->opt_ptr, &errmsg);
+ if (rc)
+ {
+ mu_parseopt_error (po, _("can't set sender address: %s"),
+ errmsg ? errmsg : mu_strerror (rc));
+ exit (po->po_exit_error);
+ }
+ }
+}
+
+struct mu_cfg_param mda_deliver_cfg[] = {
+ { "domain", mu_c_string, &default_domain, 0, NULL,
+ N_("Default email domain") },
+ { "exit-multiple-delivery-success", mu_c_bool, &multiple_delivery, 0, NULL,
+ N_("In case of multiple delivery, exit with code 0 if at least one "
+ "delivery succeeded.") },
+ { NULL }
+};
+
+struct mu_option mda_deliver_options[] = {
+ MU_OPTION_GROUP (N_("Delivery options")),
+ { "from", 'f', N_("EMAIL"), MU_OPTION_DEFAULT,
+ N_("specify the sender's name"),
+ mu_c_string, &sender_address, set_sender_address },
+ { NULL, 'r', NULL, MU_OPTION_ALIAS },
+ MU_OPTION_END
+};
static mu_message_t
make_tmp (const char *from)
@@ -24,76 +69,76 @@ make_tmp (const char *from)
char *buf = NULL;
size_t size = 0, n;
mu_message_t mesg;
-
+
rc = mu_stdio_stream_create (&in, MU_STDIN_FD, MU_STREAM_READ);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_stdio_stream_create",
- "MU_STDIN_FD", rc);
+ "MU_STDIN_FD", rc);
exit (EX_TEMPFAIL);
- }
+ }
rc = mu_temp_file_stream_create (&out, NULL, 0);
if (rc)
{
- maidag_error (_("unable to open temporary file: %s"), mu_strerror (rc));
+ mda_error (_("unable to open temporary file: %s"), mu_strerror (rc));
exit (EX_TEMPFAIL);
}
rc = mu_stream_getline (in, &buf, &size, &n);
if (rc)
{
- maidag_error (_("read error: %s"), mu_strerror (rc));
+ mda_error (_("read error: %s"), mu_strerror (rc));
mu_stream_destroy (&in);
mu_stream_destroy (&out);
exit (EX_TEMPFAIL);
}
if (n == 0)
{
- maidag_error (_("unexpected EOF on input"));
+ mda_error (_("unexpected EOF on input"));
mu_stream_destroy (&in);
mu_stream_destroy (&out);
exit (EX_TEMPFAIL);
- }
+ }
if (n >= 5 && memcmp (buf, "From ", 5))
{
struct mu_auth_data *auth = NULL;
if (!from)
- {
- auth = mu_get_auth_by_uid (getuid ());
- if (auth)
- from = auth->name;
- }
+ {
+ auth = mu_get_auth_by_uid (getuid ());
+ if (auth)
+ from = auth->name;
+ }
if (from)
- {
- time_t t;
- struct tm *tm;
-
- time (&t);
- tm = gmtime (&t);
- mu_stream_printf (out, "From %s ", from);
- mu_c_streamftime (out, "%c%n", tm, NULL);
- }
+ {
+ time_t t;
+ struct tm *tm;
+
+ time (&t);
+ tm = gmtime (&t);
+ mu_stream_printf (out, "From %s ", from);
+ mu_c_streamftime (out, "%c%n", tm, NULL);
+ }
else
- {
- maidag_error (_("cannot determine sender address"));
- mu_stream_destroy (&in);
- mu_stream_destroy (&out);
- exit (EX_TEMPFAIL);
- }
+ {
+ mda_error (_("cannot determine sender address"));
+ mu_stream_destroy (&in);
+ mu_stream_destroy (&out);
+ exit (EX_TEMPFAIL);
+ }
if (auth)
- mu_auth_data_free (auth);
+ mu_auth_data_free (auth);
}
mu_stream_write (out, buf, n, NULL);
free (buf);
-
+
rc = mu_stream_copy (out, in, 0, NULL);
mu_stream_destroy (&in);
if (rc)
{
- maidag_error (_("copy error: %s"), mu_strerror (rc));
+ mda_error (_("copy error: %s"), mu_strerror (rc));
mu_stream_destroy (&out);
exit (EX_TEMPFAIL);
}
@@ -102,8 +147,8 @@ make_tmp (const char *from)
mu_stream_destroy (&out);
if (rc)
{
- maidag_error (_("error creating temporary message: %s"),
- mu_strerror (rc));
+ mda_error (_("error creating temporary message: %s"),
+ mu_strerror (rc));
exit (EX_TEMPFAIL);
}
@@ -111,10 +156,10 @@ make_tmp (const char *from)
}
int
-maidag_stdio_delivery (maidag_delivery_fn delivery_fun, int argc, char **argv)
+mda_run_delivery (mda_delivery_fn delivery_fun, int argc, char **argv)
{
mu_message_t mesg = make_tmp (sender_address);
-
+
if (multiple_delivery)
multiple_delivery = argc > 1;
@@ -122,12 +167,12 @@ maidag_stdio_delivery (maidag_delivery_fn delivery_fun, int argc, char **argv)
{
delivery_fun (mesg, *argv, NULL);
if (multiple_delivery)
- exit_code = EX_OK;
+ exit_code = EX_OK;
}
return exit_code;
}
-int
+static int
deliver_to_mailbox (mu_mailbox_t mbox, mu_message_t msg,
struct mu_auth_data *auth,
char **errp)
@@ -137,14 +182,15 @@ deliver_to_mailbox (mu_mailbox_t mbox, mu_message_t msg,
mu_url_t url = NULL;
mu_locker_t lock;
int failed = 0;
-
+ int exit_code = EX_OK;
+
mu_mailbox_get_url (mbox, &url);
path = (char*) mu_url_to_string (url);
status = mu_mailbox_open (mbox, MU_STREAM_APPEND|MU_STREAM_CREAT);
if (status != 0)
{
- maidag_error (_("cannot open mailbox %s: %s"),
+ mda_error (_("cannot open mailbox %s: %s"),
path, mu_strerror (status));
return EX_TEMPFAIL;
}
@@ -159,9 +205,8 @@ deliver_to_mailbox (mu_mailbox_t mbox, mu_message_t msg,
if (status)
{
- maidag_error (_("cannot lock mailbox `%s': %s"), path,
+ mda_error (_("cannot lock mailbox `%s': %s"), path,
mu_strerror (status));
- exit_code = EX_TEMPFAIL;
return EX_TEMPFAIL;
}
}
@@ -175,7 +220,7 @@ deliver_to_mailbox (mu_mailbox_t mbox, mu_message_t msg,
if ((status = mu_mailbox_get_size (mbox, &mbsize)))
{
- maidag_error (_("cannot get size of mailbox %s: %s"),
+ mda_error (_("cannot get size of mailbox %s: %s"),
path, mu_strerror (status));
if (status == ENOSYS)
mbsize = 0; /* Try to continue anyway */
@@ -183,15 +228,15 @@ deliver_to_mailbox (mu_mailbox_t mbox, mu_message_t msg,
return EX_TEMPFAIL;
}
- switch (check_quota (auth, mbsize, &n))
+ switch (mda_check_quota (auth, mbsize, &n))
{
case MQUOTA_EXCEEDED:
- maidag_error (_("%s: mailbox quota exceeded for this recipient"),
+ mda_error (_("%s: mailbox quota exceeded for this recipient"),
auth->name);
if (errp)
mu_asprintf (errp, "%s: mailbox quota exceeded for this recipient",
auth->name);
- exit_code = EX_QUOTA();
+ exit_code = EX_QUOTA;
failed++;
break;
@@ -201,14 +246,14 @@ deliver_to_mailbox (mu_mailbox_t mbox, mu_message_t msg,
default:
if ((status = mu_message_size (msg, &msg_size)))
{
- maidag_error (_("cannot get message size (input message %s): %s"),
+ mda_error (_("cannot get message size (input message %s): %s"),
path, mu_strerror (status));
exit_code = EX_UNAVAILABLE;
failed++;
}
else if (msg_size > n)
{
- maidag_error (_("%s: message would exceed maximum mailbox size for "
+ mda_error (_("%s: message would exceed maximum mailbox size for "
"this recipient"),
auth->name);
if (errp)
@@ -216,7 +261,7 @@ deliver_to_mailbox (mu_mailbox_t mbox, mu_message_t msg,
"%s: message would exceed maximum mailbox size "
"for this recipient",
auth->name);
- exit_code = EX_QUOTA();
+ exit_code = EX_QUOTA;
failed++;
}
break;
@@ -229,7 +274,7 @@ deliver_to_mailbox (mu_mailbox_t mbox, mu_message_t msg,
status = mu_mailbox_append_message (mbox, msg);
if (status)
{
- maidag_error (_("error writing to mailbox %s: %s"),
+ mda_error (_("error writing to mailbox %s: %s"),
path, mu_strerror (status));
failed++;
}
@@ -238,7 +283,7 @@ deliver_to_mailbox (mu_mailbox_t mbox, mu_message_t msg,
status = mu_mailbox_sync (mbox);
if (status)
{
- maidag_error (_("error flushing mailbox %s: %s"),
+ mda_error (_("error flushing mailbox %s: %s"),
path, mu_strerror (status));
failed++;
}
@@ -276,7 +321,7 @@ do_delivery (mu_url_t url, mu_message_t msg, const char *name, char **errp)
auth = mu_get_auth_by_name (name);
if (!auth)
{
- maidag_error (_("%s: no such user"), name);
+ mda_error (_("%s: no such user"), name);
if (errp)
mu_asprintf (errp, "%s: no such user", name);
exit_code = EX_NOUSER;
@@ -287,36 +332,37 @@ do_delivery (mu_url_t url, mu_message_t msg, const char *name, char **errp)
if (status)
mu_error (_("%s: invalid email: %s"), name, mu_strerror (status));
- if (current_uid)
+ if (getuid ())
auth->change_uid = 0;
- if (switch_user_id (auth, 1))
- return EX_TEMPFAIL;
- status = script_apply (msg, auth);
- if (switch_user_id (auth, 0))
- return EX_TEMPFAIL;
- if (status)
+ switch (mda_filter_message (msg, auth))
{
+ case MDA_FILTER_OK:
+ break;
+
+ case MDA_FILTER_FILTERED:
exit_code = EX_OK;
mu_auth_data_free (auth);
return 0;
+
+ case MDA_FILTER_FAILURE:
+ return exit_code = EX_TEMPFAIL;
}
- if (forward_file)
- switch (maidag_forward (msg, auth, forward_file))
- {
- case maidag_forward_none:
- case maidag_forward_metoo:
- break;
+ switch (mda_forward (msg, auth))
+ {
+ case mda_forward_none:
+ case mda_forward_metoo:
+ break;
- case maidag_forward_ok:
- mu_auth_data_free (auth);
- return 0;
-
- case maidag_forward_error:
- mu_auth_data_free (auth);
- return exit_code = EX_TEMPFAIL;
- }
+ case mda_forward_ok:
+ mu_auth_data_free (auth);
+ return 0;
+
+ case mda_forward_error:
+ mu_auth_data_free (auth);
+ return exit_code = EX_TEMPFAIL;
+ }
}
else
mu_set_user_email (NULL);
@@ -326,7 +372,7 @@ do_delivery (mu_url_t url, mu_message_t msg, const char *name, char **errp)
status = mu_url_create (&url, auth->mailbox);
if (status)
{
- maidag_error (_("cannot create URL for %s: %s"),
+ mda_error (_("cannot create URL for %s: %s"),
auth->mailbox, mu_strerror (status));
return exit_code = EX_UNAVAILABLE;
}
@@ -336,7 +382,7 @@ do_delivery (mu_url_t url, mu_message_t msg, const char *name, char **errp)
if (status)
{
- maidag_error (_("cannot open mailbox %s: %s"),
+ mda_error (_("cannot open mailbox %s: %s"),
mu_url_to_string (url),
mu_strerror (status));
mu_url_destroy (&url);
@@ -353,10 +399,10 @@ do_delivery (mu_url_t url, mu_message_t msg, const char *name, char **errp)
/* Actually open the mailbox. Switch to the user's euid to make
sure the maildrop file will have right privileges, in case it
will be created */
- if (switch_user_id (auth, 1))
+ if (mda_switch_user_id (auth, 1))
return EX_TEMPFAIL;
status = deliver_to_mailbox (mbox, msg, auth, errp);
- if (switch_user_id (auth, 0))
+ if (mda_switch_user_id (auth, 0))
return EX_TEMPFAIL;
mu_auth_data_free (auth);
@@ -366,7 +412,7 @@ do_delivery (mu_url_t url, mu_message_t msg, const char *name, char **errp)
}
int
-deliver_to_url (mu_message_t msg, char *dest_id, char **errp)
+mda_deliver_to_url (mu_message_t msg, char *dest_id, char **errp)
{
int status;
const char *name;
@@ -375,7 +421,7 @@ deliver_to_url (mu_message_t msg, char *dest_id, char **errp)
status = mu_url_create (&url, dest_id);
if (status)
{
- maidag_error (_("%s: cannot create url: %s"), dest_id,
+ mda_error (_("%s: cannot create url: %s"), dest_id,
mu_strerror (status));
return EX_NOUSER;
}
@@ -384,7 +430,7 @@ deliver_to_url (mu_message_t msg, char *dest_id, char **errp)
name = NULL;
else if (status)
{
- maidag_error (_("%s: cannot get user name from url: %s"),
+ mda_error (_("%s: cannot get user name from url: %s"),
dest_id, mu_strerror (status));
mu_url_destroy (&url);
return EX_NOUSER;
@@ -393,7 +439,7 @@ deliver_to_url (mu_message_t msg, char *dest_id, char **errp)
}
int
-deliver_to_user (mu_message_t msg, char *dest_id, char **errp)
+mda_deliver_to_user (mu_message_t msg, char *dest_id, char **errp)
{
return do_delivery (NULL, msg, dest_id, errp);
}
diff --git a/maidag/forward.c b/mda/lib/forward.c
index 1b17244..bec485d 100644
--- a/maidag/forward.c
+++ b/mda/lib/forward.c
@@ -14,9 +14,46 @@
You should have received a copy of the GNU General Public License
along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
-/* ".forward" support for GNU Maidag */
+/* ".forward" support for GNU MDA */
-#include "maidag.h"
+#include "libmda.h"
+
+static char *forward_file;
+
+#define FORWARD_FILE_PERM_CHECK ( \
+ MU_FILE_SAFETY_OWNER_MISMATCH | \
+ MU_FILE_SAFETY_GROUP_WRITABLE | \
+ MU_FILE_SAFETY_WORLD_WRITABLE | \
+ MU_FILE_SAFETY_LINKED_WRDIR | \
+ MU_FILE_SAFETY_DIR_IWGRP | \
+ MU_FILE_SAFETY_DIR_IWOTH )
+
+static int forward_file_checks = FORWARD_FILE_PERM_CHECK;
+
+
+static int
+cb2_forward_file_checks (const char *name, void *data)
+{
+ if (mu_file_safety_compose (data, name, FORWARD_FILE_PERM_CHECK))
+ mu_error (_("unknown keyword: %s"), name);
+ return 0;
+}
+
+static int
+cb_forward_file_checks (void *data, mu_config_value_t *arg)
+{
+ return mu_cfg_string_value_cb (arg, cb2_forward_file_checks,
+ &forward_file_checks);
+}
+
+struct mu_cfg_param mda_forward_cfg[] = {
+ { "file", mu_c_string, &forward_file, 0, NULL,
+ N_("Process forward file.") },
+ { "file-checks", mu_cfg_callback, NULL, 0, cb_forward_file_checks,
+ N_("Configure safety checks for the forward file."),
+ N_("arg: list") },
+ { NULL }
+};
/* Auxiliary functions */
@@ -44,7 +81,7 @@ forward_to_email (mu_message_t msg, mu_address_t from,
}
/* Create a mailer if it does not already exist.*/
-int
+static int
forward_mailer_create (mu_mailer_t *pmailer)
{
int rc;
@@ -61,7 +98,6 @@ forward_mailer_create (mu_mailer_t *pmailer)
return 1;
}
-
rc = mu_mailer_open (*pmailer, 0);
if (rc)
{
@@ -110,14 +146,14 @@ create_from_address (mu_message_t msg, mu_address_t *pfrom)
/* Forward message MSG as requested by file FILENAME.
MYNAME gives local user name. */
-enum maidag_forward_result
+static enum mda_forward_result
process_forward (mu_message_t msg, char *filename, const char *myname)
{
int rc;
mu_stream_t file;
size_t size = 0, n;
char *buf = NULL;
- enum maidag_forward_result result = maidag_forward_ok;
+ enum mda_forward_result result = mda_forward_ok;
mu_mailer_t mailer = NULL;
mu_address_t from = NULL;
@@ -126,7 +162,7 @@ process_forward (mu_message_t msg, char *filename, const char *myname)
{
mu_error (_("%s: cannot open forward file: %s"),
filename, mu_strerror (rc));
- return maidag_forward_error;
+ return mda_forward_error;
}
while (mu_stream_getline (file, &buf, &size, &n) == 0 && n > 0)
@@ -143,7 +179,7 @@ process_forward (mu_message_t msg, char *filename, const char *myname)
if (create_from_address (msg, &from)
|| forward_mailer_create (&mailer)
|| forward_to_email (msg, from, mailer, p))
- result = maidag_forward_error;
+ result = mda_forward_error;
}
else
{
@@ -151,11 +187,11 @@ process_forward (mu_message_t msg, char *filename, const char *myname)
p++;
if (strcmp (p, myname) == 0)
{
- if (result == maidag_forward_ok)
- result = maidag_forward_metoo;
+ if (result == mda_forward_ok)
+ result = mda_forward_metoo;
}
- else if (deliver_to_user (msg, p, NULL))
- result = maidag_forward_error;
+ else if (mda_deliver_to_user (msg, p, NULL))
+ result = mda_forward_error;
}
}
}
@@ -176,15 +212,18 @@ static mu_list_t idlist;
/* Check if the forward file FWFILE for user given by AUTH exists, and if
so, use to to forward message MSG. */
-enum maidag_forward_result
-maidag_forward (mu_message_t msg, struct mu_auth_data *auth, char *fwfile)
+enum mda_forward_result
+mda_forward (mu_message_t msg, struct mu_auth_data *auth)
{
struct stat st;
char *filename;
- enum maidag_forward_result result = maidag_forward_none;
+ enum mda_forward_result result = mda_forward_none;
int rc;
+
+ if (!forward_file)
+ return mda_forward_none;
- if (fwfile[0] != '/')
+ if (forward_file[0] != '/')
{
if (stat (auth->dir, &st))
{
@@ -195,17 +234,17 @@ maidag_forward (mu_message_t msg, struct mu_auth_data *auth, char *fwfile)
else
mu_error (_("%s: cannot stat directory: %s"),
auth->dir, mu_strerror (errno));
- return maidag_forward_none;
+ return mda_forward_none;
}
- filename = mu_make_file_name (auth->dir, fwfile);
+ filename = mu_make_file_name (auth->dir, forward_file);
}
else
- filename = strdup (fwfile);
+ filename = strdup (forward_file);
if (!filename)
{
mu_error ("%s", mu_strerror (errno));
- return maidag_forward_error;
+ return mda_forward_error;
}
if (!idlist)
diff --git a/mda/lib/libmda.h b/mda/lib/libmda.h
new file mode 100644
index 0000000..65f0b20
--- a/dev/null
+++ b/mda/lib/libmda.h
@@ -0,0 +1,129 @@
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#if defined(HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <errno.h>
+#include <grp.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_SYSEXITS_H
+# include <sysexits.h>
+#else
+# define EX_OK 0 /* successful termination */
+# define EX__BASE 64 /* base value for error messages */
+# define EX_USAGE 64 /* command line usage error */
+# define EX_DATAERR 65 /* data format error */
+# define EX_NOINPUT 66 /* cannot open input */
+# define EX_NOUSER 67 /* addressee unknown */
+# define EX_NOHOST 68 /* host name unknown */
+# define EX_UNAVAILABLE 69 /* service unavailable */
+# define EX_SOFTWARE 70 /* internal software error */
+# define EX_OSERR 71 /* system error (e.g., can't fork) */
+# define EX_OSFILE 72 /* critical OS file missing */
+# define EX_CANTCREAT 73 /* can't create (user) output file */
+# define EX_IOERR 74 /* input/output error */
+# define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
+# define EX_PROTOCOL 76 /* remote error in protocol */
+# define EX_NOPERM 77 /* permission denied */
+# define EX_CONFIG 78 /* configuration error */
+# define EX__MAX 78 /* maximum listed value */
+#endif
+
+#include <mailutils/mailutils.h>
+#include "muscript.h"
+
+/* mailquota settings */
+enum {
+ MQUOTA_OK,
+ MQUOTA_EXCEEDED,
+ MQUOTA_UNLIMITED
+};
+
+#ifdef USE_MAILBOX_QUOTAS
+# define EX_QUOTA ex_quota ()
+#else
+# define EX_QUOTA EX_UNAVAILABLE
+#endif
+
+int ex_quota (void);
+
+extern struct mu_cfg_param mda_mailquota_cfg[];
+
+/* .forward support */
+enum mda_forward_result
+ {
+ mda_forward_none,
+ mda_forward_ok,
+ mda_forward_metoo,
+ mda_forward_error
+ };
+
+enum mda_forward_result mda_forward (mu_message_t msg, struct mu_auth_data *auth);
+
+extern struct mu_cfg_param mda_forward_cfg[];
+
+enum {
+ MDA_FILTER_OK,
+ MDA_FILTER_FILTERED,
+ MDA_FILTER_FAILURE
+};
+
+int mda_filter_message (mu_message_t msg, struct mu_auth_data *auth);
+
+extern struct mu_option mda_script_options[];
+extern struct mu_cfg_param mda_script_cfg[];
+
+void mda_filter_cfg_init (void);
+
+
+typedef int (*mda_delivery_fn) (mu_message_t, char *, char **);
+
+int mda_run_delivery (mda_delivery_fn delivery_fun, int argc, char **argv);
+int mda_deliver_to_url (mu_message_t msg, char *dest_id, char **errp);
+int mda_deliver_to_user (mu_message_t msg, char *dest_id, char **errp);
+int mda_check_quota (struct mu_auth_data *auth, mu_off_t size, mu_off_t *rest);
+
+extern struct mu_cfg_param mda_deliver_cfg[];
+extern struct mu_option mda_deliver_options[];
+
+extern int exit_code;
+void mda_close_fds (void);
+int mda_switch_user_id (struct mu_auth_data *auth, int user);
+void mda_error (const char *fmt, ...);
+
+void mda_cli_capa_init (void);
+
+
+
+
+
diff --git a/maidag/mailquota.c b/mda/lib/mailquota.c
index a5ad95b..33fb550 100644
--- a/maidag/mailquota.c
+++ b/mda/lib/mailquota.c
@@ -14,16 +14,43 @@
You should have received a copy of the GNU General Public License
along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
-#include "maidag.h"
+#include "libmda.h"
+#include <mailutils/dbm.h>
+
+static char *quotadbname;
+#ifdef USE_SQL
+static char *quota_query;
+#endif
+
+static int ex_quota_tempfail;
+
+int
+ex_quota ()
+{
+ return (ex_quota_tempfail ? EX_TEMPFAIL : EX_UNAVAILABLE);
+}
-#if defined (USE_MAILBOX_QUOTAS)
+
+struct mu_cfg_param mda_mailquota_cfg[] = {
+ { "database", mu_c_string, &quotadbname, 0, NULL,
+ N_("Name of DBM quota database file."),
+ N_("file") },
+#ifdef USE_SQL
+ { "sql-query", mu_c_string, &quota_query, 0, NULL,
+ N_("SQL query to retrieve mailbox quota."),
+ N_("query") },
+#endif
+ { "exit-tempfail", mu_c_bool, &ex_quota_tempfail, 0, NULL,
+ N_("Indicate temporary failure if the recipient is over his mail quota.")
+ },
+ { NULL }
+};
#define DEFRETVAL MQUOTA_UNLIMITED
mu_off_t groupquota = 5*1024*1024UL;
-static int get_size (char *, mu_off_t *, char **);
-int
+static int
get_size (char *str, mu_off_t *size, char **endp)
{
mu_off_t s;
@@ -52,19 +79,14 @@ get_size (char *str, mu_off_t *size, char **endp)
return 0;
}
-#define RETR_OK 0
-#define RETR_UNLIMITED -1
-#define RETR_FAILURE 1
-
-int
-fail_retrieve_quota (char *name, mu_off_t *quota)
-{
- mu_error (_("no quota retrieving mechanism"));
- return RETR_FAILURE;
-}
+enum {
+ RETR_OK,
+ RETR_UNLIMITED,
+ RETR_FAILURE
+};
#ifdef ENABLE_DBM
-int
+static int
dbm_retrieve_quota (char *name, mu_off_t *quota)
{
mu_dbm_file_t db;
@@ -111,7 +133,7 @@ dbm_retrieve_quota (char *name, mu_off_t *quota)
/* User not in database, try default quota */
mu_dbm_datum_free (&named);
named.mu_dptr = "DEFAULT";
- named.mu_dsize = strlen ("DEFAULT");
+ named.mu_dsize = strlen (named.mu_dptr);
rc = mu_dbm_fetch (db, &named, &contentd);
if (rc == MU_ERR_NOENT)
{
@@ -158,16 +180,19 @@ dbm_retrieve_quota (char *name, mu_off_t *quota)
# define default_retrieve_quota dbm_retrieve_quota
#else
-# define default_retrieve_quota fail_retrieve_quota
+static int
+default_retrieve_quota (char *name, mu_off_t *quota)
+{
+ mu_error (_("no quota retrieving mechanism"));
+ return RETR_FAILURE;
+}
#endif
#ifdef USE_SQL
#include <mailutils/sql.h>
-
-/* FIXME: defined in libmu_auth/sql.c */
#include <libmu_auth/sql.h>
-int
+static int
sql_retrieve_quota (char *name, mu_off_t *quota)
{
mu_sql_connection_t conn;
@@ -270,7 +295,6 @@ sql_retrieve_quota (char *name, mu_off_t *quota)
}
#endif
-
static int
retrieve_quota (struct mu_auth_data *auth, mu_off_t *quota)
{
@@ -290,7 +314,7 @@ retrieve_quota (struct mu_auth_data *auth, mu_off_t *quota)
}
int
-check_quota (struct mu_auth_data *auth, mu_off_t size, mu_off_t *rest)
+mda_check_quota (struct mu_auth_data *auth, mu_off_t size, mu_off_t *rest)
{
mu_off_t quota;
@@ -315,5 +339,3 @@ check_quota (struct mu_auth_data *auth, mu_off_t size, mu_off_t *rest)
return MQUOTA_OK;
}
-
-#endif /* USE_MAIL_QUOTA */
diff --git a/mda/lib/script.c b/mda/lib/script.c
new file mode 100644
index 0000000..ec36cba
--- a/dev/null
+++ b/mda/lib/script.c
@@ -0,0 +1,260 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-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 <http://www.gnu.org/licenses/>. */
+
+#include "libmda.h"
+
+static mu_script_t script_handler;
+static mu_list_t script_list;
+static char *message_id_header;
+
+struct mda_script
+{
+ mu_script_t scr; /* Handler script */
+ const char *pat; /* Script name pattern */
+};
+
+
+static int
+script_register (const char *pattern)
+{
+ mu_script_t scr;
+ struct mda_script *p;
+
+ if (script_handler)
+ scr = script_handler;
+ else
+ {
+ scr = mu_script_suffix_handler (pattern);
+ if (!scr)
+ return EINVAL;
+ }
+
+ p = malloc (sizeof (*p));
+ if (!p)
+ return MU_ERR_FAILURE;
+
+ p->scr = scr;
+ p->pat = pattern;
+
+ if (!script_list)
+ {
+ if (mu_list_create (&script_list))
+ return MU_ERR_FAILURE;
+ }
+
+ if (mu_list_append (script_list, p))
+ return MU_ERR_FAILURE;
+
+ return 0;
+}
+
+static void
+set_script_lang (struct mu_parseopt *po, struct mu_option *opt,
+ char const *arg)
+{
+ script_handler = mu_script_lang_handler (arg);
+ if (!script_handler)
+ {
+ mu_parseopt_error (po, _("unknown or unsupported language: %s"), arg);
+ exit (po->po_exit_error);
+ }
+}
+
+static void
+set_script_pattern (struct mu_parseopt *po, struct mu_option *opt,
+ char const *arg)
+{
+ switch (script_register (arg))
+ {
+ case 0:
+ return;
+
+ case EINVAL:
+ mu_parseopt_error (po, _("%s has unknown file suffix"), arg);
+ break;
+
+ default:
+ mu_parseopt_error (po, _("error registering script"));
+ }
+ exit (po->po_exit_error);
+}
+
+struct mu_option mda_script_options[] = {
+ MU_OPTION_GROUP (N_("Scripting options")),
+ { "language", 'l', N_("STRING"), MU_OPTION_DEFAULT,
+ N_("define scripting language for the next --script option"),
+ mu_c_string, NULL, set_script_lang },
+ { "script", 's', N_("PATTERN"), MU_OPTION_DEFAULT,
+ N_("set name pattern for user-defined mail filter"),
+ mu_c_string, NULL, set_script_pattern },
+ { "message-id-header", 0, N_("STRING"), MU_OPTION_DEFAULT,
+ N_("use this header to identify messages when logging Sieve actions"),
+ mu_c_string, &message_id_header },
+ MU_OPTION_END
+};
+
+static int
+cb_script_language (void *data, mu_config_value_t *val)
+{
+ if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+ return 1;
+ script_handler = mu_script_lang_handler (val->v.string);
+ if (!script_handler)
+ {
+ mu_error (_("unsupported language: %s"), val->v.string);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+cb_script_pattern (void *data, mu_config_value_t *val)
+{
+ if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+ return 1;
+
+ switch (script_register (val->v.string))
+ {
+ case 0:
+ break;
+
+ case EINVAL:
+ mu_error (_("%s has unknown file suffix"), val->v.string);
+ break;
+
+ default:
+ mu_error (_("error registering script"));
+ }
+ return 0;
+}
+
+struct mu_cfg_param mda_script_cfg[] = {
+ { "language", mu_cfg_callback, NULL, 0, cb_script_language,
+ N_("Set script language."),
+ /* TRANSLATORS: words to the right of : are keywords - do not translate */
+ N_("arg: python|guile") },
+ { "pattern", mu_cfg_callback, NULL, 0, cb_script_pattern,
+ N_("Set script pattern."),
+ N_("arg: glob") },
+ { NULL }
+};
+
+struct apply_script_closure
+{
+ struct mu_auth_data *auth;
+ mu_message_t msg;
+};
+
+static char const *script_env[] = { "location=MDA", "phase=during", NULL };
+
+static int
+apply_script (void *item, void *data)
+{
+ struct mda_script *scr = item;
+ struct apply_script_closure *clos = data;
+ char *progfile;
+ int rc;
+ struct stat st;
+ mu_script_descr_t sd;
+
+ progfile = mu_expand_path_pattern (scr->pat, clos->auth->name);
+ if (stat (progfile, &st))
+ {
+ if (errno != ENOENT)
+ mu_diag_funcall (MU_DIAG_NOTICE, "stat", progfile, errno);
+ free (progfile);
+ return 0;
+ }
+
+ rc = mu_script_init (scr->scr, progfile, script_env, &sd);
+ if (rc)
+ mu_error (_("initialization of script %s failed: %s"),
+ progfile, mu_strerror (rc));
+ else
+ {
+ if (mu_script_sieve_log)
+ mu_script_log_enable (scr->scr, sd, clos->auth->name,
+ message_id_header);
+ rc = mu_script_process_msg (scr->scr, sd, clos->msg);
+ if (rc)
+ mu_error (_("script %s failed: %s"), progfile, mu_strerror (rc));
+ mu_script_done (scr->scr, sd);
+ }
+
+ free (progfile);
+
+ return rc;
+}
+
+int
+mda_filter_message (mu_message_t msg, struct mu_auth_data *auth)
+{
+ if (script_list)
+ {
+ mu_attribute_t attr;
+ struct apply_script_closure clos;
+ int rc;
+
+ clos.auth = auth;
+ clos.msg = msg;
+
+ mu_message_get_attribute (msg, &attr);
+ mu_attribute_unset_deleted (attr);
+ if (mda_switch_user_id (auth, 1))
+ return MDA_FILTER_FAILURE;
+
+ chdir (auth->dir);
+ rc = mu_list_foreach (script_list, apply_script, &clos);
+ chdir ("/");
+
+ if (mda_switch_user_id (auth, 0))
+ return MDA_FILTER_FAILURE;
+
+ if (rc == 0)
+ {
+ mu_attribute_t attr;
+ mu_message_get_attribute (msg, &attr);
+ if (mu_attribute_is_deleted (attr))
+ return MDA_FILTER_FILTERED;
+ }
+ else
+ return MDA_FILTER_FAILURE;
+ }
+ return MDA_FILTER_OK;
+}
+
+static struct mu_cfg_param filter_cfg_param[] = {
+ { "language", mu_cfg_callback, NULL, 0, cb_script_language,
+ N_("Set script language."),
+ /* TRANSLATORS: words to the right of : are keywords - do not translate */
+ N_("arg: sieve|python|scheme") },
+ { "pattern", mu_cfg_callback, NULL, 0, cb_script_pattern,
+ N_("Set script pattern."),
+ N_("arg: glob") },
+ { NULL }
+};
+
+void
+mda_filter_cfg_init (void)
+{
+ struct mu_cfg_section *section;
+ if (mu_create_canned_section ("filter", &section) == 0)
+ {
+ section->docstring = N_("Add new message filter.");
+ mu_cfg_section_add_params (section, filter_cfg_param);
+ }
+ mu_cli_capa_register (&mu_cli_capa_sieve);
+}
diff --git a/maidag/util.c b/mda/lib/util.c
index f06f966..147da68 100644
--- a/maidag/util.c
+++ b/mda/lib/util.c
@@ -14,26 +14,21 @@
You should have received a copy of the GNU General Public License
along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
-#include "maidag.h"
+#include "libmda.h"
+
+int exit_code;
void
-close_fds ()
+mda_close_fds (void)
{
int i;
- long fdlimit = MAXFD;
-
-#if defined (HAVE_SYSCONF) && defined (_SC_OPEN_MAX)
- fdlimit = sysconf (_SC_OPEN_MAX);
-#elif defined (HAVE_GETDTABLESIZE)
- fdlimit = getdtablesize ();
-#endif
-
+ long fdlimit = sysconf (_SC_OPEN_MAX);
for (i = 3; i < fdlimit; i++)
close (i);
}
int
-switch_user_id (struct mu_auth_data *auth, int user)
+mda_switch_user_id (struct mu_auth_data *auth, int user)
{
int rc;
uid_t uid;
@@ -56,30 +51,12 @@ switch_user_id (struct mu_auth_data *auth, int user)
# error "No way to reset user privileges?"
#endif
if (rc < 0)
- maidag_error ("setreuid(0, %d): %s (r=%d, e=%d)",
- uid, strerror (errno), getuid (), geteuid ());
+ mda_error ("setreuid(0, %d): %s (r=%d, e=%d)",
+ uid, strerror (errno), getuid (), geteuid ());
return rc;
}
-void
-maidag_error (const char *fmt, ...)
-{
- va_list ap;
-
- guess_retval (errno);
- va_start (ap, fmt);
- if (!mu_log_syslog)
- {
- vfprintf (stderr, fmt, ap);
- fputc ('\n', stderr);
- }
- va_end (ap);
- va_start (ap, fmt);
- mu_verror (fmt, ap);
- va_end (ap);
-}
-
-int temp_errors[] = {
+static int temp_errors[] = {
#ifdef EAGAIN
EAGAIN, /* Try again */
#endif
@@ -154,8 +131,7 @@ int temp_errors[] = {
#endif
};
-
-void
+static void
guess_retval (int ec)
{
int i;
@@ -165,7 +141,7 @@ guess_retval (int ec)
#ifdef EDQUOT
if (ec == EDQUOT)
{
- exit_code = EX_QUOTA();
+ exit_code = EX_QUOTA;
return;
}
#endif
@@ -178,3 +154,32 @@ guess_retval (int ec)
}
exit_code = EX_UNAVAILABLE;
}
+
+void
+mda_error (const char *fmt, ...)
+{
+ va_list ap;
+ guess_retval (errno);
+ va_start (ap, fmt);
+ mu_verror (fmt, ap);
+ va_end (ap);
+}
+
+static struct mu_cli_capa mda_cli_capa[] = {
+ { "forward", NULL, mda_forward_cfg },
+ { "deliver", mda_deliver_options, mda_deliver_cfg },
+#ifdef USE_MAILBOX_QUOTAS
+ { "quota", NULL, mda_mailquota_cfg },
+#endif
+ { "script", mda_script_options, mda_script_cfg },
+ { NULL }
+};
+
+void
+mda_cli_capa_init (void)
+{
+ size_t i;
+
+ for (i = 0; mda_cli_capa[i].name; i++)
+ mu_cli_capa_register (&mda_cli_capa[i]);
+}
diff --git a/maidag/lmtp.c b/mda/lmtpd.c
index dcc3481..2ffdd6a 100644
--- a/maidag/lmtp.c
+++ b/mda/lmtpd.c
@@ -14,17 +14,215 @@
You should have received a copy of the GNU General Public License
along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
-#include "maidag.h"
+#include "libmda.h"
+#include <mailutils/server.h>
+#include <mailutils/daemon.h>
+#include <tcpwrap.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/un.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include <mu_umaxtostr.h>
-mu_list_t lmtp_groups;
+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://<address: string>:<port: number> (note that port is "
+ "mandatory)\n"
+ " file://<socket-file-name>\n"
+ "or socket://<socket-file-name>"),
+ 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)
{
@@ -52,7 +250,7 @@ lmtp_transcript (mu_stream_t iostream)
return iostream;
}
-void
+static void
lmtp_reply (mu_stream_t iostr, char *code, char *enh, char *fmt, ...)
{
va_list ap;
@@ -135,7 +333,7 @@ enum lmtp_command
#define SDT state_dot
#define SEN state_end
-int transtab[NCMD][NSTATE] = {
+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 },
@@ -150,13 +348,13 @@ int transtab[NCMD][NSTATE] = {
/* Delivery data */
-char *lhlo_domain; /* Sender domain */
-char *mail_from; /* Sender address */
-mu_list_t rcpt_list; /* Recipient addresses */
-mu_message_t mesg; /* Collected message */
+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 */
-int
+static int
cfun_unknown (mu_stream_t iostr, char *arg)
{
lmtp_reply (iostr, "500", "5.5.1", "Command unrecognized");
@@ -180,7 +378,7 @@ add_default_domain (char *str, int len, char **pret)
#define MAILER_DAEMON "MAILER-DAEMON"
-int
+static int
check_address (char *arg, int with_domain, char **pret)
{
if (strchr (arg, '@') == 0)
@@ -243,9 +441,8 @@ check_address (char *arg, int with_domain, char **pret)
}
return 0;
}
-
-int
+static int
cfun_mail_from (mu_stream_t iostr, char *arg)
{
if (*arg == 0)
@@ -262,9 +459,8 @@ cfun_mail_from (mu_stream_t iostr, char *arg)
lmtp_reply (iostr, "250", "2.1.0", "Go ahead");
return 0;
}
-
-int
+static int
cfun_rcpt_to (mu_stream_t iostr, char *arg)
{
char *user;
@@ -299,9 +495,8 @@ cfun_rcpt_to (mu_stream_t iostr, char *arg)
lmtp_reply (iostr, "250", "2.1.5", "Go ahead");
return 0;
}
-
-int
+static int
dot_temp_fail (void *item, void *cbdata)
{
char *name = item;
@@ -310,14 +505,14 @@ dot_temp_fail (void *item, void *cbdata)
return 0;
}
-int
+static int
dot_deliver (void *item, void *cbdata)
{
char *name = item;
mu_stream_t iostr = cbdata;
char *errp = NULL;
- switch (deliver_to_user (mesg, name, &errp))
+ switch (mda_deliver_to_user (mesg, name, &errp))
{
case 0:
lmtp_reply (iostr, "250", "2.0.0", "%s: delivered", name);
@@ -343,7 +538,7 @@ dot_deliver (void *item, void *cbdata)
return 0;
}
-int
+static int
cfun_data (mu_stream_t iostr, char *arg)
{
int rc;
@@ -362,7 +557,7 @@ cfun_data (mu_stream_t iostr, char *arg)
MU_STREAM_READ|MU_STREAM_WRTHRU);
if (rc)
{
- maidag_error (_("unable to open filter: %s"),
+ mda_error (_("unable to open filter: %s"),
mu_strerror (rc));
lmtp_reply (iostr, "450", "4.1.0", "Temporary failure, try again later");
return 1;
@@ -371,7 +566,7 @@ cfun_data (mu_stream_t iostr, char *arg)
rc = mu_temp_file_stream_create (&tempstr, NULL, 0);
if (rc)
{
- maidag_error (_("unable to open temporary file: %s"), mu_strerror (rc));
+ mda_error (_("unable to open temporary file: %s"), mu_strerror (rc));
mu_stream_destroy (&flt);
return 1;
}
@@ -384,7 +579,7 @@ cfun_data (mu_stream_t iostr, char *arg)
rc = mu_c_streamftime (tempstr, "%c%n", tm, NULL);
if (rc)
{
- maidag_error (_("copy error: %s"), mu_strerror (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);
@@ -402,7 +597,7 @@ cfun_data (mu_stream_t iostr, char *arg)
MU_IOCTL_XSCRIPTSTREAM_LEVEL, &xlev);
if (rc)
{
- maidag_error (_("copy error: %s"), mu_strerror (rc));
+ mda_error (_("copy error: %s"), mu_strerror (rc));
mu_list_foreach (rcpt_list, dot_temp_fail, iostr);
}
@@ -410,7 +605,7 @@ cfun_data (mu_stream_t iostr, char *arg)
mu_stream_unref (tempstr);
if (rc)
{
- maidag_error (_("error creating temporary message: %s"),
+ mda_error (_("error creating temporary message: %s"),
mu_strerror (rc));
mu_list_foreach (rcpt_list, dot_temp_fail, iostr);
}
@@ -423,9 +618,8 @@ cfun_data (mu_stream_t iostr, char *arg)
return 0;
}
-
-int
+static int
cfun_rset (mu_stream_t iostr, char *arg)
{
free (lhlo_domain);
@@ -435,14 +629,13 @@ cfun_rset (mu_stream_t iostr, char *arg)
lmtp_reply (iostr, "250", "2.0.0", "OK, forgotten");
return 0;
}
-
-char *capa_str = "ENHANCEDSTATUSCODES\n\
+static char *capa_str = "ENHANCEDSTATUSCODES\n\
PIPELINING\n\
8BITMIME\n\
HELP";
-int
+static int
cfun_lhlo (mu_stream_t iostr, char *arg)
{
if (*arg == 0)
@@ -461,25 +654,22 @@ cfun_lhlo (mu_stream_t iostr, char *arg)
lmtp_reply (iostr, "250", NULL, capa_str);
return 0;
}
-
-int
+static int
cfun_quit (mu_stream_t iostr, char *arg)
{
lmtp_reply (iostr, "221", "2.0.0", "Bye");
return 0;
}
-
-int
+static int
cfun_help (mu_stream_t iostr, char *arg)
{
lmtp_reply (iostr, "200", "2.0.0", "Man, help yourself");
return 0;
}
-
-struct command_tab
+static struct command_tab
{
char *cmd_verb;
int cmd_len;
@@ -497,7 +687,7 @@ struct command_tab
{ NULL, 0, cmd_unknown, cfun_unknown }
};
-struct command_tab *
+static struct command_tab *
getcmd (char *buf, char **sp)
{
struct command_tab *cp;
@@ -526,7 +716,7 @@ to_fgets (mu_stream_t iostr, char **pbuf, size_t *psize, size_t *pnread,
return rc;
}
-int
+static int
lmtp_loop (mu_stream_t iostr, unsigned int timeout)
{
size_t size = 0, n;
@@ -569,7 +759,7 @@ typedef union
struct sockaddr_un s_un;
} all_addr_t;
-int
+static int
lmtp_connection (int fd, struct sockaddr *sa, int salen,
struct mu_srv_config *pconf,
void *data)
@@ -585,7 +775,7 @@ lmtp_connection (int fd, struct sockaddr *sa, int salen,
}
mu_stream_set_buffer (str, mu_buffer_line, 0);
- if (pconf->transcript || maidag_transcript)
+ if (pconf->transcript || mda_transcript)
str = lmtp_transcript (str);
lmtp_loop (str, pconf->timeout);
mu_stream_destroy (&str);
@@ -593,7 +783,7 @@ lmtp_connection (int fd, struct sockaddr *sa, int salen,
}
static int
-lmtp_set_privs ()
+lmtp_set_privs (void)
{
gid_t gid;
@@ -654,8 +844,8 @@ lmtp_set_privs ()
return 0;
}
-int
-maidag_lmtp_server ()
+static int
+lmtp_server (void)
{
int rc = lmtp_set_privs ();
@@ -700,7 +890,7 @@ maidag_lmtp_server ()
return 1;
}
- if (maidag_transcript)
+ if (mda_transcript)
str = lmtp_transcript (str);
rc = lmtp_loop (str, 0);
@@ -708,3 +898,5 @@ maidag_lmtp_server ()
}
return rc;
}
+
+
diff --git a/mda/mda.c b/mda/mda.c
new file mode 100644
index 0000000..89951b8
--- a/dev/null
+++ b/mda/mda.c
@@ -0,0 +1,143 @@
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include "libmda.h"
+
+static void
+set_stderr (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
+{
+ mu_log_syslog = 0;
+}
+
+static struct mu_option mda_options[] = {
+ MU_OPTION_GROUP (N_("General options")),
+ { "stderr", 0, NULL, MU_OPTION_DEFAULT,
+ N_("log to standard error"),
+ mu_c_string, NULL, set_stderr },
+ MU_OPTION_END
+}, *options[] = { mda_options, NULL };
+
+static char *capa[] = {
+ "auth",
+ "debug",
+ "logging",
+ "mailbox",
+ "locking",
+ "mailer",
+ "sieve",
+ "deliver",
+ "forward",
+ "quota",
+ "script",
+ NULL
+};
+
+static int
+cb_stderr (void *data, mu_config_value_t *val)
+{
+ int res;
+
+ if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+ return 1;
+ if (mu_str_to_c (val->v.string, mu_c_bool, &res, NULL))
+ mu_error (_("not a boolean"));
+ else
+ mu_log_syslog = !res;
+ return 0;
+}
+
+struct mu_cfg_param mda_cfg_param[] = {
+ { "stderr", mu_cfg_callback, NULL, 0, cb_stderr,
+ N_("Log to stderr instead of syslog."),
+ N_("arg: bool") },
+ { NULL }
+};
+
+struct mu_cli_setup cli = {
+ options,
+ mda_cfg_param,
+ N_("mda -- the GNU local mail delivery agent."),
+ N_("[recipient...]"),
+};
+
+int
+main (int argc, char **argv)
+{
+ struct mu_parseopt pohint;
+ struct mu_cfg_parse_hints cfhint;
+
+ 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_log_syslog = 1;
+ mu_log_print_severity = 1;
+
+ /* Parse command line */
+ mda_cli_capa_init ();
+
+ pohint.po_flags = 0;
+
+ pohint.po_package_name = PACKAGE_NAME;
+ pohint.po_flags |= MU_PARSEOPT_PACKAGE_NAME;
+
+ pohint.po_package_url = PACKAGE_URL;
+ pohint.po_flags |= MU_PARSEOPT_PACKAGE_URL;
+
+ pohint.po_bug_address = PACKAGE_BUGREPORT;
+ pohint.po_flags |= MU_PARSEOPT_BUG_ADDRESS;
+
+ pohint.po_extra_info = mu_general_help_text;
+ pohint.po_flags |= MU_PARSEOPT_EXTRA_INFO;
+
+ pohint.po_version_hook = mu_version_hook;
+ pohint.po_flags |= MU_PARSEOPT_VERSION_HOOK;
+
+ pohint.po_negation = "no-";
+ pohint.po_flags |= MU_PARSEOPT_NEGATION;
+
+ cfhint.site_file = mu_site_config_file ();
+ cfhint.flags = MU_CFHINT_SITE_FILE | MU_CFHINT_NO_CONFIG_OVERRIDE;
+
+ mu_cli_ext (argc, argv, &cli, &pohint, &cfhint,
+ capa, NULL, &argc, &argv);
+ if (argc == 0)
+ {
+ mu_error (_("recipients not given"));
+ return EX_USAGE;
+ }
+
+ mu_stdstream_strerr_setup (mu_log_syslog ?
+ MU_STRERR_SYSLOG : MU_STRERR_STDERR);
+
+ return mda_run_delivery (mda_deliver_to_user, argc, argv);
+}
diff --git a/mda/putmail.c b/mda/putmail.c
new file mode 100644
index 0000000..55cc18c
--- a/dev/null
+++ b/mda/putmail.c
@@ -0,0 +1,76 @@
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include "libmda.h"
+
+static char *capa[] = {
+ "auth",
+ "debug",
+ "mailbox",
+ "locking",
+ "mailer",
+ "sieve",
+ "deliver",
+ "script",
+ NULL
+};
+
+struct mu_cli_setup cli = {
+ NULL,
+ NULL,
+ N_("putmail -- incorporates mail to a mailbox."),
+ N_("[URL...]"),
+};
+
+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_log_syslog = 0;
+ mu_log_print_severity = 1;
+
+ /* Parse command line */
+ mda_cli_capa_init ();
+ mu_cli (argc, argv, &cli, capa, NULL, &argc, &argv);
+ if (argc == 0)
+ {
+ mu_error (_("recipients not given"));
+ return EX_USAGE;
+ }
+
+ return mda_run_delivery (mda_deliver_to_url, argc, argv);
+}
+
+
diff --git a/maidag/tests/.gitignore b/mda/tests/.gitignore
index 93f8f46..93f8f46 100644
--- a/maidag/tests/.gitignore
+++ b/mda/tests/.gitignore
diff --git a/maidag/tests/Makefile.am b/mda/tests/Makefile.am
index 2dbc4c0..8e6c105 100644
--- a/maidag/tests/Makefile.am
+++ b/mda/tests/Makefile.am
@@ -39,11 +39,9 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac
## ------------ ##
TESTSUITE_AT = \
- forward.at\
- lmtp.at\
- mda.at\
- testsuite.at\
- url-mbox.at
+ lmtpd.at\
+ putmail.at\
+ testsuite.at
TESTSUITE = $(srcdir)/testsuite
M4=m4
diff --git a/maidag/tests/atlocal.in b/mda/tests/atlocal.in
index 9bf1f01..3bd76a1 100644
--- a/maidag/tests/atlocal.in
+++ b/mda/tests/atlocal.in
@@ -2,5 +2,5 @@
# Configurable variable values for Mailutils test suite.
# Copyright (C) 2004-2019 Free Software Foundation, Inc.
-PATH=@abs_builddir@:@abs_top_builddir@/maidag:$top_srcdir:$srcdir:$PATH
-
+PATH=@abs_builddir@:@abs_top_builddir@/mda:$top_srcdir:$srcdir:$PATH
+INPUT_MSG=$abs_top_srcdir/mda/tests/input.msg
diff --git a/maidag/tests/input.msg b/mda/tests/input.msg
index e72ad7b..e72ad7b 100644
--- a/maidag/tests/input.msg
+++ b/mda/tests/input.msg
diff --git a/maidag/tests/lmtp.at b/mda/tests/lmtpd.at
index acfd2c9..ab892a1 100644
--- a/maidag/tests/lmtp.at
+++ b/mda/tests/lmtpd.at
@@ -14,8 +14,8 @@
# You should have received a copy of the GNU General Public License
# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
-AT_SETUP([LMTP mode])
-AT_KEYWORDS([maidag lmtp])
+AT_SETUP([lmtpd])
+AT_KEYWORDS([lmtpd])
m4_pushdef([tocrlf],[dnl
$abs_top_builddir/libmailutils/tests/fltst crlf encode read])
@@ -31,13 +31,13 @@ QUIT
])
echo ENVELOPE > expout
-cat $abs_top_srcdir/maidag/tests/input.msg >> expout
+cat $INPUT_MSG >> expout
echo "" >> expout
-cat session_start $abs_top_srcdir/maidag/tests/input.msg session_end | tocrlf > session || exit $?
+cat session_start $INPUT_MSG session_end | tocrlf > session || exit $?
mkdir spool
-maidag MAIDAG_OPTIONS --set 'group=()' --lmtp < session >transcript || exit $?
+lmtpd MDA_OPTIONS --stderr --set 'group=()' < session > transcript || exit $?
sed '1s/From gulliver@example.net.*/ENVELOPE/' spool/root
cat transcript | tr -d '\r' | sed '/...-/d;s/ .*//' >&2
diff --git a/maidag/tests/url-mbox.at b/mda/tests/putmail.at
index a36f2f4..d0fe28a 100644
--- a/maidag/tests/url-mbox.at
+++ b/mda/tests/putmail.at
@@ -14,17 +14,17 @@
# You should have received a copy of the GNU General Public License
# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
-AT_SETUP([URL mode])
-AT_KEYWORDS([maidag url-mbox url])
+AT_SETUP([putmail])
+AT_KEYWORDS([putmail])
AT_CHECK([
echo ENVELOPE > expout
-cat $abs_top_srcdir/maidag/tests/input.msg >> expout
+cat $INPUT_MSG >> expout
echo "" >> expout
mkdir spool
-maidag MAIDAG_OPTIONS --from 'gulliver@example.net' --url mbox:spool/out < dnl
- $abs_top_srcdir/maidag/tests/input.msg || exit $?
+putmail MDA_OPTIONS --from 'gulliver@example.net' mbox:spool/out < dnl
+ $INPUT_MSG || exit $?
sed '1s/From gulliver@example.net.*/ENVELOPE/' spool/out
],
[0],
diff --git a/maidag/tests/testsuite.at b/mda/tests/testsuite.at
index d82d400..aa7e597 100644
--- a/maidag/tests/testsuite.at
+++ b/mda/tests/testsuite.at
@@ -16,17 +16,18 @@
m4_include([testsuite.inc])
-m4_define([MAIDAG_OPTIONS],[dnl
+m4_define([MDA_OPTIONS],[dnl
MUT_DEFAULT_OPTIONS dnl
--set '|mailbox|mailbox-pattern='`pwd`/spool/'${user}' dnl
---set .auth.authorization=system dnl
---stderr])
+--set .auth.authorization=system])
AT_INIT
-AT_TESTED([maidag])
-MUT_VERSION(maidag)
-m4_include([mda.at])
-m4_include([lmtp.at])
-m4_include([url-mbox.at])
-m4_include([forward.at])
+AT_TESTED([lmtpd])
+MUT_VERSION(lmtpd)
+m4_include([lmtpd.at])
+
+AT_TESTED([putmail])
+MUT_VERSION(putmail)
+m4_include([putmail.at])
+

Return to:

Send suggestions and report system problems to the System administrator.