aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2007-04-24 15:44:01 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2007-04-24 15:44:01 +0000
commit23c190d057f68de84cb17bf8555397642fc6f6a9 (patch)
tree48272c668c3c1986fefd49ab657396b8a2976247
parent2e708415a056624b4845467c9eebbbab7c1ef0f2 (diff)
downloadmailfromd-23c190d057f68de84cb17bf8555397642fc6f6a9.tar.gz
mailfromd-23c190d057f68de84cb17bf8555397642fc6f6a9.tar.bz2
* src/lex.l (parse_require): Bugfix
* src/bi_mail.m4: Bugfix * src/mtasim.c: Implement help, fix directory removal at exit, implement readline history file. Bugfixes in smtp() * tests/testsuite.at, tests/accept.at, tests/greylist.at, tests/arg.at, tests/reject.at, tests/numrcpt.at, tests/tempfail.at: Use mtasim -Xauto when necessary * configure.ac, NEWS: Raise patchlevel to 92 * doc/mailfromd.texi: Update * doc/mtasim.texi: mtasim documentation * doc/Makefile.am: Add mtasim.texi * gacopyz/gacopyz_priv.h (struct gacopyz_conn): Keep information about children pids * gacopyz/proc.c (gacopyz_register_child) (gacopyz_unregister_child): New functions (cleanup_children): Call gacopyz_unregister_child (gacopyz_cleanup_conn): Terminate children individualy instead of sending TERM to the whole process group, because we might be not the group leader. * gacopyz/gacopyz.c (gacopyz_handle_connection): Register child pid after startup. * bootstrap: Require save-cwd. Test if lib/daemon.c exists before attempting to create it. git-svn-id: file:///svnroot/mailfromd/trunk@1379 7a8a7f39-df28-0410-adc6-e0d955640f24
-rw-r--r--ChangeLog26
-rw-r--r--NEWS8
-rw-r--r--bootstrap5
-rw-r--r--configure.ac2
-rw-r--r--doc/Makefile.am1
-rw-r--r--doc/mailfromd.texi119
-rw-r--r--doc/mtasim.texi251
-rw-r--r--gacopyz/gacopyz.c6
-rw-r--r--gacopyz/gacopyz_priv.h5
-rw-r--r--gacopyz/proc.c44
-rw-r--r--src/bi_mail.m414
-rw-r--r--src/lex.l4
-rw-r--r--src/mtasim.c215
-rw-r--r--tests/accept.at7
-rw-r--r--tests/arg.at7
-rw-r--r--tests/greylist.at6
-rw-r--r--tests/numrcpt.at7
-rw-r--r--tests/reject.at7
-rw-r--r--tests/tempfail.at8
-rw-r--r--tests/testsuite.at7
20 files changed, 635 insertions, 114 deletions
diff --git a/ChangeLog b/ChangeLog
index 5f3a0933..b7ff9931 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2007-04-24 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * src/lex.l (parse_require): Bugfix
+ * src/bi_mail.m4: Bugfix
+ * src/mtasim.c: Implement help, fix directory removal at exit,
+ implement readline history file. Bugfixes in smtp()
+ * tests/testsuite.at, tests/accept.at, tests/greylist.at,
+ tests/arg.at, tests/reject.at, tests/numrcpt.at,
+ tests/tempfail.at: Use mtasim -Xauto when necessary
+ * configure.ac, NEWS: Raise patchlevel to 92
+ * doc/mailfromd.texi: Update
+ * doc/mtasim.texi: mtasim documentation
+ * doc/Makefile.am: Add mtasim.texi
+ * gacopyz/gacopyz_priv.h (struct gacopyz_conn): Keep information
+ about children pids
+ * gacopyz/proc.c (gacopyz_register_child)
+ (gacopyz_unregister_child): New functions
+ (cleanup_children): Call gacopyz_unregister_child
+ (gacopyz_cleanup_conn): Terminate children individualy instead of
+ sending TERM to the whole process group, because we might be not
+ the group leader.
+ * gacopyz/gacopyz.c (gacopyz_handle_connection): Register child
+ pid after startup.
+ * bootstrap: Require save-cwd. Test if lib/daemon.c exists before
+ attempting to create it.
+
2007-04-23 Sergey Poznyakoff <gray@gnu.org.ua>
* src/mtasim.c: Implement --port=auto, a special mode, where
diff --git a/NEWS b/NEWS
index 6abbc79b..05112365 100644
--- a/NEWS
+++ b/NEWS
@@ -1,11 +1,15 @@
-Mailfromd NEWS -- history of user-visible changes. 2007-04-23
+Mailfromd NEWS -- history of user-visible changes. 2007-04-24
Copyright (C) 2005, 2006, 2007 Sergey Poznyakoff
See the end of file for copying conditions.
Please send mailfromd bug reports to <bug-mailfromd@gnu.org.ua>
+
+
+Version 3.1.92, SVN
+
-Version 3.1.91, SVN
+Version 3.1.91, 2007-04-23
* Non-blocking syslog
diff --git a/bootstrap b/bootstrap
index 55641751..f5b54a9c 100644
--- a/bootstrap
+++ b/bootstrap
@@ -3,13 +3,14 @@ MODLIST="argp\
fprintftime\
malloc\
memrchr\
- mkdtemp\
+ mkdtemp\
obstack\
realloc\
regex\
+ save-cwd\
snprintf\
strtok_r"
gnulib-tool --import --avoid xalloc-die $MODLIST
-ln src/daemon.c lib/
+test -f lib/daemon.c || ln src/daemon.c lib/
autoreconf -i -f -s
diff --git a/configure.ac b/configure.ac
index 0d963010..cbdf2fdf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -19,7 +19,7 @@
AC_PREREQ(2.59)
m4_define([MF_VERSION_MAJOR], 3)
m4_define([MF_VERSION_MINOR], 1)
-m4_define([MF_VERSION_PATCH], 91)
+m4_define([MF_VERSION_PATCH], 92)
AC_INIT([mailfromd],
MF_VERSION_MAJOR.MF_VERSION_MINOR[]m4_ifdef([MF_VERSION_PATCH],.MF_VERSION_PATCH),
[bug-mailfromd@gnu.org.ua])
diff --git a/doc/Makefile.am b/doc/Makefile.am
index a46527d7..e85247e6 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -21,6 +21,7 @@ mailfromd_TEXINFOS=\
fdl.texi\
gacopyz.texi\
macros.texi\
+ mtasim.texi\
rendition.texi\
strftime.texi\
values.texi
diff --git a/doc/mailfromd.texi b/doc/mailfromd.texi
index eb4ce3a9..adacdfd6 100644
--- a/doc/mailfromd.texi
+++ b/doc/mailfromd.texi
@@ -63,9 +63,9 @@ Software Foundation raise funds for GNU development.''
@page
@quotation
-Dedico aquesta obra a Lluis Llach, un hom qui ha canviat la meva vida.
+Dedico aquesta obra a Lluis Llach, un home qui ha canviat la meva vida.
No puc dedicar-li ni una poesia, ni una can@,c@'o, ho sento molt. Ara,
-commogut per el seu concert de comiat, li dedico ho que puc: aquest programa
+commogut pel seu concert de comiat, li dedico ho que puc: aquest programa
senzill.
@end quotation
@@ -90,6 +90,7 @@ documents @command{mailfromd} Version @value{VERSION}.
* MFL:: The Mail Filtering Language.
* Mailfromd Configuration:: Configuring @command{mailfromd}.
* Sendmail Configuration:: Configuring Sendmail to use @command{mailfromd}.
+* mtasim:: MTA simulator.
* Reporting Bugs:: How to Report a Bug.
Appendices
@@ -134,6 +135,7 @@ Tutorial
* Databases::
* Testing Filter Scripts::
* Logging and Debugging::
+* Runtime errors::
Databases
@@ -173,7 +175,7 @@ Comments
Constants
-* Built-in constants
+* Built-in constants::
Variables
@@ -241,6 +243,11 @@ Command Line Options.
* Logging and Debugging Options::
* Informational Options::
+@command{mtasim} --- a tesing tool
+
+* stdio mode::
+* daemon mode::
+
@end detailmenu
@end menu
@@ -2427,10 +2434,11 @@ Measured in words.
@item References
A comma-separated list of locations where the variable was
references. Each location is represented as @var{file}:@var{line}.
-If several locations pertain to the same @var{file}, it is listed only once.
+If several locations pertain to the same @var{file}, the file name is
+listed only once.
@end table
-Here is the example cross-reference output:
+Here is an example of the cross-reference output:
@smallexample
@group
@@ -2516,27 +2524,75 @@ it is important that it be given immediately after the option, without
any intervening white space, for example @kbd{mailfromd --test=helo},
or @kbd{mailfromd -thelo}.
- This method may not suite for some sophisticated configurations,
-for example if some values are passed between the handlers via global
-variables. To test such configurations we recommend the following
-approach:
+@cindex @command{mtasim}, introduced
+ This method allows to test one handler at a time. To test the
+script as a whole, use @command{mtasim} utility. It is described in
+detail in @FIXME-ref{}. It is an @dfn{@acronym{MTA} simulator}, useful
+for testing purposes. When started it enters interactive mode,
+similar to that of @command{sendmail -bs}, where it expects
+@acronym{SMTP} commands on its standard input and sends answers to the
+standard output. The @option{--port=auto} command line option
+instructs it to start @command{mailfromd} and to create a unique
+socket for communication with it. Thus, the simplest way to
+run it is:
-@enumerate 1
-@item
-Prepare both @command{mailfromd} and @command{sendmail} configuration
-files.
+@smallexample
+$ @kbd{mtasim --port=auto}
+@end smallexample
-@item
-Start @command{mailfromd}, preferably in foreground mode
-(@pxref{--foreground}) with the desired debugging options.
+ When you exit @command{mtasim} (by typing @code{quit} command or
+simply by entering the end-of-file symbol), it will stop the mailfromd
+instance it created. This allows to test filter scripts without
+interrupting the running @command{mailfromd} instance, if you already
+have one.
-@item
-On another console, start @kbd{sendmail -bs}. This will start the
-@acronym{SMTP} conversation on standard input and output. Enter
-@acronym{SMTP} commands and see if the @acronym{MTA} reaction is
-appropriate. To check @command{mailfromd} diagnostics, flip to the
-@code{tty} where it runs.
-@end enumerate
+ Additional arguments to the @command{mailfromd} utility may be
+supplied on the command line after @samp{--} marker:
+
+@smallexample
+$ @kbd{mtasim --port=auto -- -I. --stderr newconf.rc}
+@end smallexample
+
+ To illustrate this, suppose you wish to test the greylisting
+functionality of the filter script described in @ref{Filter Script
+Example}. To do this, you start @command{mtasim}:
+
+@smallexample
+$ @kbd{mtasim -Xauto -- -I. -I../mflib test.rc}
+220 localhost bitbucket ready
+(mtasim)
+@end smallexample
+
+ The string @samp{(mtasim) } is the input prompt.
+
+ The script in @file{test.rc} needs to know @code{client_addr} macro.
+You have to define it manually. The @command{mtasim} utility provides
+a special command for this (@code{\D}, @FIXME-pxref{mtasim escapes}):
+
+@smallexample
+(mtasim) \Dclient_addr=213.130.0.1
+@end smallexample
+
+Now, let's start @acronym{SMTP} session:
+
+@smallexample
+(mtasim) ehlo yahoo.com
+250-pleased to meet you
+250 HELP
+(mtasim) mail from: <gray@@yahoo.com>
+250 Sender OK
+(mtasim) rcpt to: <gray@@localhost>
+450 4.7.0 You are greylisted for 300 seconds
+@end smallexample
+
+OK, this shows that the greylisting works. Now quit the session:
+
+@smallexample
+(mtasim) quit
+221 Done
+@end smallexample
+
+ The @command{mtasim} utility is discussed in detail in @FIXME-ref{}.
@node Logging and Debugging
@section Logging and Debugging
@@ -3335,6 +3391,7 @@ Stopping}.
Sets the communication port data. The @var{string} value is a port
setting in @command{Milter} notation:
+@anchor{milter port specification}
@table @asis
@item unix:@var{file}
@itemx local:@var{file}
@@ -8426,13 +8483,13 @@ Each section is prefaced with a comment explaining its function.
#pragma option relay /etc/mail/sendmail.cw
#pragma option relay /etc/mail/relay-domains
#pragma option timeout 33
-#pragma option retry 3
-#pragma option mailfrom ""
-#pragma option ehlo "gnu.org.ua"
#pragma regex +extended +icase
#pragma database cache negative-expire-interval 1 day
#pragma database cache positive-expire-interval 2 weeks
+
+set mailfrom_address "<>"
+set ehlo_domain "gnu.org.ua"
@end group
@end smallexample
@@ -9277,7 +9334,7 @@ is called during the system startup and shut down. The exact
instructions on how to do so depend on the operating system you use
and are beyond the scope of this manual.
-@node Sendmail Configuration, Reporting Bugs, Mailfromd Configuration, Top
+@node Sendmail Configuration, mtasim, Mailfromd Configuration, Top
@chapter Configuring Sendmail to use @command{mailfromd}
This chapter assumes you are familiar with Sendmail configuration in
@@ -9400,8 +9457,12 @@ O Milter.macros.envrcpt=@{rcpt_mailer@}, @{rcpt_host@}, @{rcpt_addr@} ,i,
f, @{client_addr@}
@end group
@end smallexample
-
-@node Reporting Bugs, Gacopyz, Sendmail Configuration, Top
+
+@node mtasim, Reporting Bugs, Sendmail Configuration, Top
+@chapter @command{mtasim} --- a tesing tool
+@include mtasim.texi
+
+@node Reporting Bugs, Gacopyz, mtasim, Top
@chapter How to Report a Bug
@quotation
diff --git a/doc/mtasim.texi b/doc/mtasim.texi
new file mode 100644
index 00000000..70fd8109
--- /dev/null
+++ b/doc/mtasim.texi
@@ -0,0 +1,251 @@
+@c This file is part of the Mailfromd manual.
+@c Copyright (C) 2007 Sergey Pozniakoff
+@c See file mailfromd.texi for copying conditions.
+@c *******************************************************************
+ The @command{mtasim} utility is a @acronym{MTA} simulator for testing
+@command{mailfromd} filter scripts. By default it operates in
+@dfn{stdio} mode, similar to that of @command{sendmail -bs}. In this
+mode it reads @acronym{SMTP} commands from standard input and sends
+its responses to the standard output. There is also another mode,
+called @dfn{daemon}, where @command{mtasim} opens a @acronym{TCP}
+socket and listens on it much like any @acronym{MTA} does. In both
+modes no actual delivery is performed, the tool only simulates the
+actions an @acronym{MTA} would do and responses it would give.
+
+ This tool is derived from the program @command{mta}, which I wrote
+for GNU Anubis testsuite.
+
+@menu
+* stdio mode::
+* daemon mode::
+@end menu
+
+@node stdio mode
+@section @command{mtasim} stdio mode
+@UNREVISED{}
+
+ If you start @command{mtasim} without options, you will see the
+following:
+
+@smallexample
+@group
+220 mtasim (mailfromd @value{VERSION}) ready
+(mtasim) _
+@end group
+@end smallexample
+
+ The first line is usual @acronym{RFC} 2821 reply. The second one is
+a prompt, indicating that @command{mtasim} is in interactive mode and
+ready for input. The prompt appears only if the package is compiled
+with GNU Readline and @command{mtasim} determines that its standard
+input is connected to the terminal. This is called @dfn{interactive
+mode} and is intended to save the human user some typing by offering
+line editing and history facilities (@FIXME-pxref{}). If the package
+is compiled without GNU Readline, you will see:
+
+@smallexample
+@group
+220 mtasim (mailfromd @value{VERSION}) ready
+_
+@end group
+@end smallexample
+
+@noindent
+where @samp{_} represents the cursor. Whatever the mode,
+@command{mtasim} waits for further input.
+
+ The input is expected to consist of valid @acronym{SMTP} commands
+and special @command{mtasim} statements. The utility will act exactly
+like a @acronym{RFC} 2821-compliant @acronym{MTA}, except that it will
+not do actual message delivery or relaying. Try typing @code{HELP} to
+get the list of supported commands. You will see something similar
+to:
+
+@smallexample
+250-mtasim (mailfromd @value{VERSION}); supported SMTP commands:
+250- EHLO
+250- HELO
+250- MAIL
+250- RCPT
+250- DATA
+250- HELP
+250- QUIT
+250- HELP
+250 RSET
+@end smallexample
+
+ You can try a simple @acronym{SMTP} session now:
+
+@smallexample
+220 mtasim (mailfromd 3.1.92) ready
+(mtasim) ehlo localhost
+250-pleased to meet you
+250 HELP
+(mtasim) mail from: <me@@localhost>
+250 Sender OK
+(mtasim) rcpt to: <him@@domain>
+250 Recipient OK
+(mtasim) data
+354 Enter mail, end with `.' on a line by itself
+(mtasim) .
+250 Mail accepted for delivery
+(mtasim) quit
+221 Done
+@end smallexample
+
+ Notice, that @command{mtasim} does no domain checking, so such thing
+as @samp{rcpt to: <him@@domain>} was eaten without complains.
+
+ So far so good, but what all this has to do with
+@command{mailfromd}? Well, that's what we are going to explain. To
+make @command{mtasim} consult any milter, use @option{--port}
+(@option{-X}) command line option. This option takes a single
+argument that specifies a milter port to use. The port can be given
+either in the usual Milter format (@xref{milter port specification},
+for a short description), or as a full @file{sendmail.cf} style
+@code{X} command, in which case it allows to set timeouts as well:
+
+@smallexample
+$ mtasim --port=inet:999@@localhost
+# @r{This is also valid}:
+$ mtasim --port='mailfrom, S=inet:999@@localhost, F=T, T=C:100m;R:180s'
+@end smallexample
+
+ If the milter is actually listening on this port, @command{mtasim}
+will connect to it and you will get the following initial prompt:
+
+@smallexample
+@group
+220-mtasim (mailfromd 3.1.92) ready
+220 Connected to milter inet:999@@localhost
+(mtasim)
+@end group
+@end smallexample
+
+ Notice, that it makes no difference what implementation is listening
+on that port, it may well be some other filter, not necessarily
+@command{mailfromd}.
+
+ However, let's return to @command{mailfromd}. If you do not want to
+connect to an existing @command{mailfromd} instance, but prefer
+instead to create a new one and run your tests with it (a preferred
+way, if you already have a stable filter running but wish to test a
+new script, without disturbing it), use @option{--port=auto}. This
+option instructs @command{mtasim} to do the following:
+
+@enumerate 1
+@item Create a unique temporary directory in @file{/tmp} and create a
+communication socket within it.
+@item Spawn new instance of @command{mailfromd}. The arguments and
+options for that instance may be given in the invocation of
+@command{mtasim} after a double-dash marker (@samp{--})
+@item Connect to that filter.
+@end enumerate
+
+ When @command{mtasim} exits, it terminates the subsidiary
+@command{mailfromd} process and removes the temporary directory it has
+created. For example, the following command will start
+@command{mailfromd -I. -I../mflib test.rc}:
+
+@smallexample
+@group
+$ @kbd{mtasim -Xauto -- -I. -I../mflib test.rc}
+220-mtasim (mailfromd @value{VERSION}) ready
+220 Connected to milter unix:/tmp/mtasim-j6tRLC/socket
+(mtasim)
+@end group
+@end smallexample
+
+ The @file{/tmp/mtasim-j6tRLC} directory and any files within it will
+exist as long as @command{mtasim} is running and will be removed if
+you exit from it.@footnote{However, this is true only if the program
+is exited the usual way (via @code{QUIT} or end-of-file). If it is
+aborted with a signal like @code{SIGINTR}, the temporary directory is
+not removed.} You can also instruct the subsidiary
+@command{mailfromd} to use this directory as its state directory
+(@pxref{statedir}). This is done by @option{--statedir} command line
+option:
+
+@smallexample
+$ @kbd{mtasim -Xauto --statedir -- -I. -I../mflib test.rc}
+@end smallexample
+
+@noindent
+(notice that @option{--statedir} is the @command{mtasim} option,
+therefore it must appear @emph{before} @samp{--})
+
+ Now, let's try @code{HELP} command again:
+
+@smallexample
+250-mtasim (mailfromd @value{VERSION}); supported SMTP commands:
+250- EHLO
+250- HELO
+250- MAIL
+250- RCPT
+250- DATA
+250- HELP
+250- QUIT
+250- HELP
+250- RSET
+250-Supported administrative commands:
+250- \Dname=value [name=value...] Define Sendmail macros
+250- \Ecode Expect given SMTP reply code
+250- \L[name] [name...] List macros
+250 \Uname [name...] Undefine Sendmail macros
+@end smallexample
+
+ While the @acronym{SMTP} do not need any clarification, some words
+about the @dfn{administrative commands} are in place. These commands
+allow to define, undefine and list arbitrary Sendmail macros. Each
+administrative command consists of a backslash followed by a command
+letter. Just like @acronym{SMTP} ones, administrative commans are
+case-insensitive. If a command takes arguments, the first argument
+must follow the command letter without intervening whitespace.
+Subsequent arguments can be delimited by arbitrary amount of
+whitespace.
+
+For example, the @code{\D} command defines Sendmail macros:
+
+@smallexample
+(mtasim) \Dclient_addr=192.168.10.1 f=sergiusz@@localhost i=testmsg
+(mtasim)
+@end smallexample
+
+@noindent
+Notice that @command{mailfromd} does not send any response to the
+command, except if there was some syntactic error, in which case it
+will return a 502 response.
+
+ Now, you can list all available macros:
+
+@smallexample
+(mtasim) \L
+220-client_addr=192.168.10.1
+220-f=sergiusz@@localhost
+220 i=testmsg
+(mtasim)
+@end smallexample
+
+@noindent
+or just some of them:
+
+@smallexample
+(mtasim) \Lclient_addr
+220 client_addr=192.168.10.1
+(mtasim)
+@end smallexample
+
+ To undefine a macro, use @command{\U} command:
+
+@smallexample
+(mtasim) \Ui
+(mtasim) \l
+220-client_addr=192.168.10.1
+220 f=sergiusz@@localhost
+(mtasim)
+@end smallexample
+
+
+@node daemon mode
+@section Running @command{mtasim} in daemon mode
+@UNREVISED{}
diff --git a/gacopyz/gacopyz.c b/gacopyz/gacopyz.c
index f61673cc..a7a50177 100644
--- a/gacopyz/gacopyz.c
+++ b/gacopyz/gacopyz.c
@@ -68,7 +68,10 @@ gacopyz_init(gacopyz_conn_t *pconn, struct smfiDesc *desc)
void
gacopyz_free(gacopyz_conn_t conn)
{
- free(conn);
+ if (conn) {
+ free(conn->pidtab);
+ free(conn);
+ }
}
int
@@ -1361,6 +1364,7 @@ gacopyz_handle_connection(gacopyz_conn_t conn)
return MI_FAILURE;
}
if (pid > 0) {
+ gacopyz_register_child(conn, pid);
close(fd);
return MI_SUCCESS;
}
diff --git a/gacopyz/gacopyz_priv.h b/gacopyz/gacopyz_priv.h
index 9ec99ff2..30486f42 100644
--- a/gacopyz/gacopyz_priv.h
+++ b/gacopyz/gacopyz_priv.h
@@ -59,6 +59,8 @@ struct gacopyz_conn {
struct timeval master_timeout;
struct timeval ctx_timeout;
struct smfiDesc desc;
+ pid_t *pidtab;
+ size_t pidcount;
};
#define GACOPYZ_TIMEOUT 7210
@@ -88,3 +90,6 @@ int gacopyz_send_command(gacopyz_iod_t iod,
int cmd, const void *data, size_t size);
int gacopyz_read_command(gacopyz_iod_t iod, unsigned char *cmd,
size_t *pcount, char **pbuf, size_t *psize);
+int gacopyz_register_child(gacopyz_conn_t conn, pid_t pid);
+int gacopyz_unregister_child(gacopyz_conn_t conn, pid_t pid);
+
diff --git a/gacopyz/proc.c b/gacopyz/proc.c
index 5df987e1..d388c1fa 100644
--- a/gacopyz/proc.c
+++ b/gacopyz/proc.c
@@ -20,6 +20,42 @@
static int cleanup_needed;
+#define PIDTAB_INCR 256
+
+int
+gacopyz_register_child(gacopyz_conn_t conn, pid_t pid)
+{
+ size_t i, newcount;
+ pid_t *p;
+
+ for (i = 0; i < conn->pidcount; i++)
+ if (conn->pidtab[i] == 0) {
+ conn->pidtab[i] = pid;
+ return 0;
+ }
+
+ newcount = conn->pidcount + PIDTAB_INCR;
+ p = realloc(conn->pidtab, newcount * sizeof(conn->pidtab[0]));
+ if (!p)
+ return 1;
+ memset(p + i, 0, PIDTAB_INCR * sizeof(conn->pidtab[0]));
+ conn->pidcount = newcount;
+ conn->pidtab = p;
+
+ conn->pidtab[i++] = pid;
+ return 0;
+}
+
+int
+gacopyz_unregister_child(gacopyz_conn_t conn, pid_t pid)
+{
+ size_t i;
+
+ for (i = 0; i < conn->pidcount; i++)
+ if (conn->pidtab[i] == pid)
+ conn->pidtab[i] = 0;
+}
+
static void
print_status(gacopyz_conn_t conn, pid_t pid, int status, int expect_term)
{
@@ -68,6 +104,7 @@ cleanup_children(gacopyz_conn_t conn, int expect_term)
pid_t pid = waitpid((pid_t)-1, &status, WNOHANG);
if (pid <= 0)
break;
+ gacopyz_unregister_child(conn, pid);
print_status(conn, pid, status, expect_term);
}
cleanup_needed = 0;
@@ -82,9 +119,12 @@ gacopyz_cleanup_children(gacopyz_conn_t conn)
void
gacopyz_cleanup_conn(gacopyz_conn_t conn)
{
+ size_t i;
gacopyz_log(conn, SMI_LOG_DEBUG, "terminating subprocesses");
- signal(SIGTERM, SIG_IGN);
- kill(0, SIGTERM);
+
+ for (i = 0; i < conn->pidcount; i++)
+ if (conn->pidtab[i])
+ kill(conn->pidtab[i], SIGTERM);
cleanup_children(conn, 1);
}
diff --git a/src/bi_mail.m4 b/src/bi_mail.m4
index 4bdfaff1..c87c08b3 100644
--- a/src/bi_mail.m4
+++ b/src/bi_mail.m4
@@ -97,8 +97,8 @@ MF_DEFUN(send_mail, VOID, STRING text, STRING to,
mu_message_get_stream(msg, &stream);
mu_stream_write(stream, text, strlen(text), 0, NULL);
- _send(env, MF_OPTVAL(mailer_url), to,
- MF_OPTVAL(from), msg, _destroy_msg, msg);
+ _send(env, MF_OPTVAL(mailer_url, NULL), to,
+ MF_OPTVAL(from, NULL), msg, _destroy_msg, msg);
}
END
@@ -138,8 +138,8 @@ MF_DEFUN(send_text, VOID, STRING text, STRING headers, STRING to,
mu_stream_write(stream, text, strlen(text), 0, NULL);
add_headers(msg, headers);
- _send(env, MF_OPTVAL(mailer_url), to,
- MF_OPTVAL(from), msg, _destroy_msg, msg);
+ _send(env, MF_OPTVAL(mailer_url, NULL), to,
+ MF_OPTVAL(from, NULL), msg, _destroy_msg, msg);
}
END
@@ -306,9 +306,9 @@ MF_DEFUN(send_dsn, VOID, STRING to,
mu_strerror(status));
mu_mime_get_message(mime, &newmsg);
- add_headers(newmsg, MF_OPTVAL(headers));
- _send(env, MF_OPTVAL(mailer_url), to,
- MF_OPTVAL(from), newmsg, _destroy_mime, mime);
+ add_headers(newmsg, MF_OPTVAL(headers, NULL));
+ _send(env, MF_OPTVAL(mailer_url, NULL), to,
+ MF_OPTVAL(from, NULL), newmsg, _destroy_mime, mime);
}
END
diff --git a/src/lex.l b/src/lex.l
index cb7b10d4..1111f74a 100644
--- a/src/lex.l
+++ b/src/lex.l
@@ -400,8 +400,8 @@ parse_require()
p++;
}
- if (len > sizeof DEFAULT_SUFFIX
- && memcmp(p + len - sizeof DEFAULT_SUFFIX - 1,
+ if (len < sizeof DEFAULT_SUFFIX
+ || memcmp(p + len - sizeof DEFAULT_SUFFIX - 1,
DEFAULT_SUFFIX,
sizeof DEFAULT_SUFFIX - 1)) {
fname = xmalloc(len + sizeof DEFAULT_SUFFIX);
diff --git a/src/mtasim.c b/src/mtasim.c
index f08174d6..c2313806 100644
--- a/src/mtasim.c
+++ b/src/mtasim.c
@@ -57,6 +57,8 @@
#include <stdarg.h>
#include <ctype.h>
#include <fcntl.h>
+#include <sys/types.h>
+#include <dirent.h>
#ifdef HAVE_READLINE_READLINE_H
# include <readline/readline.h>
#endif
@@ -74,6 +76,7 @@
#include <obstack.h>
#include <argp.h>
#include <xalloc.h>
+#include <save-cwd.h>
#if defined(USE_GNUTLS) && defined(HAVE_GNUTLS_GNUTLS_H)
# include <gnutls/gnutls.h>
@@ -227,6 +230,7 @@ enum {
OPTION_MILTER_VERSION,
OPTION_NO_INTERACTIVE,
OPTION_PROMPT,
+ OPTION_STATEDIR
};
#ifndef WITH_READLINE
@@ -258,6 +262,9 @@ static struct argp_option options[] = {
{ "port", 'X', N_("PORT"), 0,
N_("Communicate with Milter PORT"),
GRP+1 },
+ { "statedir", OPTION_STATEDIR, NULL, 0,
+ N_("Pass temporary directory to mailfromd as its state dir (with -Xauto)"),
+ GRP+1 },
{ "body-chunk", OPTION_BODY_CHUNK, N_("NUMBER"), 0,
N_("Set the body chunk for xxfi_body calls"),
GRP+1 },
@@ -303,9 +310,10 @@ static struct argp_option options[] = {
{ NULL }
};
-int (*mta_mode) (void) = NULL;
+int (*mta_mode) (void) = mta_stdio;
char *trace_name = NULL;
int append;
+int statedir_option;
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
@@ -402,6 +410,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
break;
#endif
+ case OPTION_STATEDIR:
+ statedir_option = 1;
+ break;
+
default:
return ARGP_ERR_UNKNOWN;
}
@@ -456,21 +468,88 @@ sig_child (int sig)
waitpid((pid_t)-1, &status, 0);
}
+static int rmdir_r (const char *name);
+
+static int
+recursive_rmdir (const char *name)
+{
+ int rc;
+ DIR *dir;
+ struct dirent *ent;
+
+ if (chdir (name))
+ {
+ mu_error ("cannot change to directory %s: %s",
+ name, mu_strerror (errno));
+ return 1;
+ }
+
+ dir = opendir (".");
+ if (!dir)
+ {
+ mu_error ("cannot open directory %s: %s", name, mu_strerror (errno));
+ return 1;
+ }
+
+ for (rc = 0; rc == 0 && (ent = readdir (dir));)
+ {
+ struct stat st;
+
+ if (strcmp (ent->d_name, ".") == 0
+ || strcmp (ent->d_name, "..") == 0)
+ continue;
+
+ if (stat (ent->d_name, &st) && errno != ENOENT)
+ {
+ mu_error ("cannot stat file `%s': %s",
+ name, mu_strerror (errno));
+ rc = 1;
+ }
+ else if (S_ISDIR (st.st_mode))
+ rc = rmdir_r (ent->d_name);
+ else if ((rc = unlink (ent->d_name)) != 0)
+ mu_error ("cannot unlink %s: %s", ent->d_name, mu_strerror (errno));
+ }
+ closedir (dir);
+ return rc;
+}
+
+static int
+rmdir_r (const char *name)
+{
+ int rc;
+ struct saved_cwd cwd;
+
+ if (save_cwd (&cwd))
+ {
+ mu_error ("cannot save current directory: %s", mu_strerror (errno));
+ return 1;
+ }
+ rc = recursive_rmdir (name);
+ if (restore_cwd (&cwd))
+ {
+ mu_error ("cannot restore current directory: %s", mu_strerror (errno));
+ rc = 1;
+ }
+
+ if (rc == 0 && rmdir (name))
+ {
+ mu_error ("cannot remove directory %s: %s", name, mu_strerror (errno));
+ return 1;
+ }
+
+ return rc;
+}
+
void
stop_mailfromd (void)
{
- if (child_pid)
+ if (child_pid > 0)
{
kill (child_pid, SIGTERM);
}
- if (unlink (milter_port + 5) && errno != ENOENT)
- {
- mu_error ("cannot unlink %s: