File Coverage

blib/lib/Sendmail/PMilter.pm
Criterion Covered Total %
statement 234 518 45.1
branch 6 144 4.1
condition 3 44 6.8
subroutine 76 99 76.7
pod 18 19 94.7
total 337 824 40.9


line stmt bran cond sub pod time code
1             =pod
2              
3             =head1 LICENSE
4              
5             Copyright (c) 2016-2022 G.W. Haywood. All rights reserved.
6             With thanks to all those who have trodden these paths before,
7             including
8             Copyright (c) 2002-2004 Todd Vierling. All rights reserved.
9              
10             Redistribution and use in source and binary forms, with or without
11             modification, are permitted provided that the following conditions are met:
12              
13             1. Redistributions of source code must retain the above copyright notices,
14             this list of conditions and the following disclaimer.
15              
16             2. Redistributions in binary form must reproduce the above copyright
17             notices, this list of conditions and the following disclaimer in the
18             documentation and/or other materials provided with the distribution.
19              
20             3. Neither the name of the author nor the names of contributors may be used
21             to endorse or promote products derived from this software without specific
22             prior written permission. In the case of G.W. Haywood this permission is
23             hereby now granted.
24              
25             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26             AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27             IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28             ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29             LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30             CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31             SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32             INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33             CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34             ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35             POSSIBILITY OF SUCH DAMAGE.
36              
37             =cut
38              
39             package Sendmail::PMilter;
40              
41 1     1   69850 use 5.014; # Don't use 5.016 yet. That would enable feature 'unicode_strings', and we
  1         4  
42             # probably aren't quite ready for that. We're counting *characters* passed
43             # between us and Sendmail, and Sendmail thinks that they're *bytes*.
44              
45 1     1   457 use parent 'Exporter';
  1         313  
  1         6  
46 1     1   54 use strict;
  1         1  
  1         18  
47 1     1   5 use warnings;
  1         2  
  1         23  
48 1     1   5 use Carp;
  1         1  
  1         47  
49 1     1   452 use Errno;
  1         1359  
  1         45  
50 1     1   456 use IO::Select;
  1         1720  
  1         47  
51 1     1   497 use POSIX;
  1         6307  
  1         5  
52 1     1   3363 use Socket;
  1         3709  
  1         390  
53 1     1   544 use Symbol;
  1         711  
  1         69  
54 1     1   652 use UNIVERSAL;
  1         16  
  1         3  
55              
56             our $VERSION = '1.24';
57             $VERSION = eval $VERSION;
58              
59             our $DEBUG = 0;
60              
61             =pod
62              
63             =head1 NAME
64              
65             Sendmail::PMilter - Perl binding of Sendmail Milter protocol
66              
67             =head1 SYNOPSIS
68              
69             use Sendmail::PMilter;
70              
71             my $milter = new Sendmail::PMilter;
72              
73             $milter->auto_setconn(NAME);
74             $milter->register(NAME, { CALLBACKS }[, FLAGS]);
75             $milter->main();
76              
77             =head1 DESCRIPTION
78              
79             Sendmail::PMilter is a mail filtering API implementing the Sendmail
80             Milter Protocol in Perl. This allows the administrator of Sendmail
81             (and perhaps other MTAs which implement the Milter Protocol) to use
82             pure Perl code to filter and modify mail during an SMTP connection.
83              
84             Over the years, the protocol which governs the communication between
85             qSendmail and its milters has passed through a number of revisions.
86              
87             This documentation is for Sendmail::PMilter versions 1.20 and later,
88             which now supports Milter Protocol Version 6. This is a substantial
89             upgrade from earlier versions, which at best supported up to Milter
90             Protocol Version 2 - this was first seen in Sendmail version 8.14.0
91             which was released on January 31st 2007.
92              
93             Sendmail::PMilter now uses neither the original Sendmail::Milter (it
94             is obsolete, badly flawed and unmaintained) nor the Sendmail::Milter
95             which was packaged with earlier versions of Sendmail::PMilter as a
96             temporary workaround for the broken original.
97              
98             For communications between the MTA and the milter, a 'dispatcher' acts
99             as a go-between. This must be chosen when the milter is initialized,
100             before it serves requests. Several dispatchers are provided within
101             the Sendmail::PMilter module, but in versions before 1.20 all the
102             dispatchers suffered from issues of varying gravity. The 'prefork'
103             dispatcher (see DISPATCHERS below) has now been extensively exercised
104             by the current maintainer, but although the others have been patched
105             from issue reports going back more than a decade from the time of
106             writing (June 2019) THEY HAVE NOT BEEN TESTED. Feedback via the CPAN
107             issue tracking system is encouraged. If you have developed your own
108             dispatcher you can either pass a code reference to set_dispatcher() or
109             set an environment variable to point to it. Sendmail::PMilter will
110             then use it instead of a built-in dispatcher.
111              
112             =head1 METHODS
113              
114             =cut
115              
116             ##### Protocol constants
117             # The SMFIS_* values here are not the same as those used in the Sendmail sources
118             # (see mfapi.h) so that hopefully "0" and "1" won't be used as response codes by
119             # mistake. The other protocol constants below are unchanged from those used in
120             # the Sendmail sources.
121              
122 1     1   71 use constant SMFIS_CONTINUE => 100;
  1         2  
  1         117  
123 1     1   6 use constant SMFIS_REJECT => 101;
  1         2  
  1         62  
124 1     1   6 use constant SMFIS_DISCARD => 102;
  1         2  
  1         42  
125 1     1   5 use constant SMFIS_ACCEPT => 103;
  1         2  
  1         44  
126 1     1   5 use constant SMFIS_TEMPFAIL => 104;
  1         2  
  1         38  
127 1     1   4 use constant SMFIS_MSG_LOOP => 105;
  1         2  
  1         37  
128 1     1   5 use constant SMFIS_ALL_OPTS => 110;
  1         9  
  1         59  
129              
130             # Milter progessing 'places' (see mfapi.h, values are the same).
131 1     1   6 use constant SMFIM_CONNECT => 0; # connect
  1         2  
  1         45  
132 1     1   5 use constant SMFIM_HELO => 1; # HELO/EHLO
  1         2  
  1         37  
133 1     1   5 use constant SMFIM_ENVFROM => 2; # MAIL FROM
  1         2  
  1         68  
134 1     1   7 use constant SMFIM_ENVRCPT => 3; # RCPT TO
  1         1  
  1         54  
135 1     1   6 use constant SMFIM_DATA => 4; # DATA
  1         2  
  1         44  
136 1     1   6 use constant SMFIM_EOM => 5; # END OF MESSAGE (final dot)
  1         1  
  1         60  
137 1     1   6 use constant SMFIM_EOH => 6; # END OF HEADER
  1         2  
  1         57  
138              
139             # Some of these things have been switched around from their order of
140             # presentation in the Sendmail sources but the values are the same.
141             ######################################################################
142             # Taken from .../sendmail-8.15.2/include/libmilter/mfdef.h
143             ######################################################################
144             #if _FFR_MDS_NEGOTIATE
145             # define MILTER_MDS_64K ((64 * 1024) - 1)
146             # define MILTER_MDS_256K ((256 * 1024) - 1)
147             # define MILTER_MDS_1M ((1024 * 1024) - 1)
148             #endif /* _FFR_MDS_NEGOTIATE */
149             ######################################################################
150             # These so-called 'protocols' apply to the SMFIP_* flags:
151             #define SMFI_V1_PROT 0x0000003FL The protocol of V1 filter. We won't bother with V1, it's obsolete.
152             #define SMFI_V2_PROT 0x0000007FL The protocol of V2 filter
153 1     1   6 use constant SMFI_V2_PROT => 0x0000007F; # The protocol flags available in Milter Protocol Version 2.
  1         2  
  1         56  
154             #use constant SMFI_V4_PROT => 0x000003FF; # The protocol flags available in Milter Protocol Version 4.
155 1     1   6 use constant SMFI_V6_PROT => 0x001FFFFF; # The protocol flags available in Milter Protocol Version 6.
  1         2  
  1         56  
156 1     1   6 use constant SMFI_CURR_PROT => 0x001FFFFF; # The protocol flags available in the current Milter Protocol Version (which at July 2019 is Version 6).
  1         2  
  1         41  
157             ######################################################################
158             # What the MTA can send/filter wants in protocol
159 1     1   6 use constant SMFIP_NOCONNECT => 0x00000001; # MTA should not send connect info
  1         1  
  1         51  
160 1     1   6 use constant SMFIP_NOHELO => 0x00000002; # MTA should not send HELO info
  1         2  
  1         48  
161 1     1   5 use constant SMFIP_NOMAIL => 0x00000004; # MTA should not send MAIL info
  1         20  
  1         57  
162 1     1   6 use constant SMFIP_NORCPT => 0x00000008; # MTA should not send RCPT info
  1         3  
  1         56  
163 1     1   7 use constant SMFIP_NOBODY => 0x00000010; # MTA should not send body
  1         1  
  1         66  
164 1     1   6 use constant SMFIP_NOHDRS => 0x00000020; # MTA should not send headers
  1         2  
  1         43  
165 1     1   5 use constant SMFIP_NOEOH => 0x00000040; # MTA should not send EOH
  1         6  
  1         50  
166 1     1   6 use constant SMFIP_NR_HDR => 0x00000080; # No reply for headers
  1         1  
  1         48  
167 1     1   6 use constant SMFIP_NOHREPL => 0x00000080; # No reply for headers (backward compatibility, do not use, same as SMFIP_NR_HDR)
  1         2  
  1         40  
168 1     1   5 use constant SMFIP_NOUNKNOWN => 0x00000100; # MTA should not send unknown commands
  1         2  
  1         47  
169 1     1   6 use constant SMFIP_NODATA => 0x00000200; # MTA should not send DATA
  1         2  
  1         41  
170 1     1   5 use constant SMFIP_SKIP => 0x00000400; # MTA understands SMFIS_SKIP called from EOM callback.
  1         1  
  1         52  
171 1     1   6 use constant SMFIP_RCPT_REJ => 0x00000800; # MTA should also send rejected RCPTs
  1         2  
  1         60  
172 1     1   6 use constant SMFIP_NR_CONN => 0x00001000; # No reply for connect
  1         2  
  1         40  
173 1     1   5 use constant SMFIP_NR_HELO => 0x00002000; # No reply for HELO
  1         2  
  1         64  
174 1     1   7 use constant SMFIP_NR_MAIL => 0x00004000; # No reply for MAIL
  1         2  
  1         40  
175 1     1   5 use constant SMFIP_NR_RCPT => 0x00008000; # No reply for RCPT
  1         2  
  1         59  
176 1     1   7 use constant SMFIP_NR_DATA => 0x00010000; # No reply for DATA
  1         1  
  1         88  
177 1     1   6 use constant SMFIP_NR_UNKN => 0x00020000; # No reply for UNKN
  1         2  
  1         58  
178 1     1   5 use constant SMFIP_NR_EOH => 0x00040000; # No reply for eoh
  1         2  
  1         91  
179 1     1   7 use constant SMFIP_NR_BODY => 0x00080000; # No reply for body chunk
  1         2  
  1         62  
180 1     1   7 use constant SMFIP_HDR_LEADSPC => 0x00100000; # header value leading space
  1         2  
  1         42  
181 1     1   5 use constant SMFIP_MDS_256K => 0x10000000; # MILTER_MAX_DATA_SIZE=256K
  1         2  
  1         41  
182 1     1   6 use constant SMFIP_MDS_1M => 0x20000000; # MILTER_MAX_DATA_SIZE=1M
  1         1  
  1         79  
183             ######################################################################
184             # If no negotiate callback is registered, these are the defaults. Basically
185             # everything is enabled except SMFIP_RCPT_REJ and MILTER_MAX_DATA_SIZE_*
186             # Sendmail and Postfix behave differently:
187             # Postfix does not use the constants SMFIP_MDS_256K and SMFIP_MDS_1M.
188 1     1   7 use constant SMFIP_ALL_NO_CB => (SMFIP_NOCONNECT|SMFIP_NOHELO|SMFIP_NOMAIL|SMFIP_NORCPT|SMFIP_NOBODY|SMFIP_NOHDRS|SMFIP_NOEOH|SMFIP_NOUNKNOWN|SMFIP_NODATA|SMFIP_SKIP|SMFIP_HDR_LEADSPC);
  1         2  
  1         61  
189 1     1   5 use constant SMFIP_ALL_NO_REPLY => (SMFIP_NR_HDR|SMFIP_NR_CONN|SMFIP_NR_HELO|SMFIP_NR_MAIL|SMFIP_NR_RCPT|SMFIP_NR_DATA|SMFIP_NR_UNKN|SMFIP_NR_EOH|SMFIP_NR_BODY);
  1         1  
  1         83  
190 1     1   7 use constant SMFIP_DEFAULTS => ~(SMFIP_ALL_NO_CB|SMFIP_ALL_NO_REPLY);
  1         2  
  1         53  
191             ######################################################################
192             # Taken from .../sendmail-8.15.2/include/libmilter/mfapi.h, and
193             # reformatted a little.
194             ######################################################################
195             # These so-called 'actions' apply to the SMFIF_* flags:
196             #define SMFI_V1_ACTS 0x0000000FL The actions of V1 filter
197             #define SMFI_V2_ACTS 0x0000003FL The actions of V2 filter
198             #define SMFI_CURR_ACTS 0x000001FFL actions of current version
199             ######################################################################
200             #define SMFIF_NONE 0x00000000L no flags
201             #define SMFIF_ADDHDRS 0x00000001L filter may add headers
202             #define SMFIF_CHGBODY 0x00000002L filter may replace body
203             #define SMFIF_MODBODY SMFIF_CHGBODY backwards compatible
204             #define SMFIF_ADDRCPT 0x00000004L filter may add recipients
205             #define SMFIF_DELRCPT 0x00000008L filter may delete recipients
206             #define SMFIF_CHGHDRS 0x00000010L filter may change/delete headers
207             #define SMFIF_QUARANTINE 0x00000020L filter may quarantine envelope <<========= "envelope"???
208             #define SMFIF_CHGFROM 0x00000040L filter may change "from" (envelope sender)
209             #define SMFIF_ADDRCPT_PAR 0x00000080L add recipients incl. args
210             #define SMFIF_SETSYMLIST 0x00000100L filter can send set of symbols (macros) that it wants
211             ######################################################################
212             # Capability FLAG value Available in milter protocol version (*)
213 1     1   6 use constant SMFIF_NONE => 0x0000; # Unused (*) There's a bit of a muddle about V3,
  1         2  
  1         62  
214 1     1   6 use constant SMFIF_ADDHDRS => 0x0001; # V1 Add headers but nobody's using it any more.
  1         1  
  1         73  
215 1     1   6 use constant SMFIF_MODBODY => 0x0002; # V1 Change body (for compatibility with old code, use SMFIF_CHGBODY in new code)
  1         2  
  1         42  
216 1     1   6 use constant SMFIF_CHGBODY => SMFIF_MODBODY; # V2 Change body
  1         1  
  1         50  
217 1     1   12 use constant SMFIF_ADDRCPT => 0x0004; # V1 Add recipient
  1         11  
  1         41  
218 1     1   5 use constant SMFIF_DELRCPT => 0x0008; # V1 Delete recipient
  1         2  
  1         65  
219 1     1   6 use constant SMFIF_CHGHDRS => 0x0010; # V2 Change headers
  1         2  
  1         86  
220 1     1   6 use constant SMFIF_QUARANTINE => 0x0020; # V2 quarantine entire message - last of the V2 flags
  1         3  
  1         41  
221 1     1   5 use constant SMFIF_CHGFROM => 0x0040; # V6 Change envelope sender
  1         2  
  1         50  
222 1     1   6 use constant SMFIF_ADDRCPT_PAR => 0x0080; # V6 Add recipients incl. args
  1         2  
  1         70  
223 1     1   7 use constant SMFIF_SETSYMLIST => 0x0100; # V6 Filter can send set of symbols (macros) that it wants
  1         2  
  1         52  
224              
225 1     1   5 use constant SMFI_V1_ACTS => SMFIF_ADDHDRS|SMFIF_CHGBODY|SMFIF_ADDRCPT|SMFIF_DELRCPT;
  1         2  
  1         56  
226 1     1   6 use constant SMFI_V2_ACTS => SMFI_V1_ACTS|SMFIF_CHGHDRS|SMFIF_QUARANTINE;
  1         2  
  1         48  
227 1     1   5 use constant SMFI_V6_ACTS => SMFI_V2_ACTS|SMFIF_CHGFROM|SMFIF_ADDRCPT_PAR|SMFIF_SETSYMLIST;
  1         2  
  1         53  
228 1     1   6 use constant SMFI_CURR_ACTS => SMFI_V6_ACTS; # All capabilities. See mfapi.h and mfdef.h
  1         3  
  1         49  
229              
230             # See libmilter/smfi.c
231 1     1   7 use constant MAXREPLYLEN => 980;
  1         1  
  1         41  
232 1     1   5 use constant MAXREPLIES => 32;
  1         2  
  1         2807  
233              
234             ##### Symbols exported to the caller
235              
236             my $smflags =
237             ' SMFIP_DEFAULTS SMFIP_NOCONNECT SMFIP_NOHELO SMFIP_NOMAIL SMFIP_NORCPT SMFIP_NOBODY SMFIP_NOHDRS SMFIP_NOEOH SMFIP_NOUNKNOWN SMFIP_NODATA SMFIP_RCPT_REJ SMFIP_SKIP
238             SMFIP_NR_CONN SMFIP_NR_HELO SMFIP_NR_MAIL SMFIP_NR_RCPT SMFIP_NR_DATA SMFIP_NR_HDR SMFIP_NR_EOH SMFIP_NR_BODY SMFIP_NR_UNKN SMFIP_HDR_LEADSPC SMFIP_MDS_256K SMFIP_MDS_1M
239             SMFIM_CONNECT SMFIM_HELO SMFIM_ENVFROM SMFIM_ENVRCPT SMFIM_DATA SMFIM_EOM SMFIM_EOH
240             SMFIS_CONTINUE SMFIS_REJECT SMFIS_DISCARD SMFIS_ACCEPT SMFIS_TEMPFAIL SMFIS_MSG_LOOP SMFIS_ALL_OPTS
241             SMFIF_NONE SMFIF_ADDHDRS SMFIF_CHGBODY SMFIF_ADDRCPT SMFIF_DELRCPT SMFIF_CHGHDRS SMFIF_QUARANTINE SMFIF_CHGFROM SMFIF_ADDRCPT_PAR SMFIF_SETSYMLIST
242             SMFI_V2_ACTS SMFI_V6_ACTS SMFI_CURR_ACTS SMFI_V2_PROT SMFI_V6_PROT SMFI_CURR_PROT
243             MAXREPLYLEN MAXREPLIES
244             ';
245             my @smflags = eval "qw/ $smflags /;";
246             my @dispatchers = qw/ ithread_dispatcher postfork_dispatcher prefork_dispatcher sequential_dispatcher /;
247             my @callback_names = qw/ negotiate connect helo envfrom envrcpt data header eoh body eom close abort unknown /;
248             my %DEFAULT_CALLBACKS = map { $_ => $_.'_callback' } @callback_names;
249             # Don't export anything by default.
250             our @EXPORT = ();
251             # Everything else is OK. I have tried.
252             our @EXPORT_OK = qw/
253             SMFIP_DEFAULTS SMFIP_NOCONNECT SMFIP_NOHELO SMFIP_NOMAIL SMFIP_NORCPT SMFIP_NOBODY SMFIP_NOHDRS SMFIP_NOEOH SMFIP_NOUNKNOWN SMFIP_NODATA SMFIP_RCPT_REJ SMFIP_SKIP
254             SMFIP_NR_CONN SMFIP_NR_HELO SMFIP_NR_MAIL SMFIP_NR_RCPT SMFIP_NR_DATA SMFIP_NR_HDR SMFIP_NR_EOH SMFIP_NR_BODY SMFIP_NR_UNKN SMFIP_HDR_LEADSPC SMFIP_MDS_256K SMFIP_MDS_1M
255             SMFIM_CONNECT SMFIM_HELO SMFIM_ENVFROM SMFIM_ENVRCPT SMFIM_DATA SMFIM_EOM SMFIM_EOH
256             SMFIS_CONTINUE SMFIS_REJECT SMFIS_DISCARD SMFIS_ACCEPT SMFIS_TEMPFAIL SMFIS_MSG_LOOP SMFIS_ALL_OPTS
257             SMFIF_NONE SMFIF_ADDHDRS SMFIF_CHGBODY SMFIF_ADDRCPT SMFIF_DELRCPT SMFIF_CHGHDRS SMFIF_QUARANTINE SMFIF_CHGFROM SMFIF_ADDRCPT_PAR SMFIF_SETSYMLIST
258             SMFI_V2_ACTS SMFI_V6_ACTS SMFI_CURR_ACTS SMFI_V2_PROT SMFI_V6_PROT SMFI_CURR_PROT
259             MAXREPLYLEN MAXREPLIES
260             ithread_dispatcher postfork_dispatcher prefork_dispatcher sequential_dispatcher
261             negotiate_callback connect_callback helo_callback envfrom_callback envrcpt_callback data_callback header_callback eoh_callback body_callback eom_callback close_callback abort_callback unknown_callback
262             /;
263              
264             # Three export tags for flags, dispatchers and callbacks.
265             our %EXPORT_TAGS = ( all => [ @smflags ], dispatchers => [ @dispatchers ], callbacks => [ (values %DEFAULT_CALLBACKS) ] );
266              
267             our $enable_chgfrom = 0;
268              
269             ##### Methods
270              
271             sub new ($) {
272 1     1 0 1055 bless {}, shift;
273             }
274              
275             =pod
276              
277             =over 4
278              
279             =item get_max_interpreters()
280              
281             Returns the maximum number of interpreters passed to C. This is
282             only useful when called from within the dispatcher, as it is not set before
283             C is called.
284              
285             =cut
286              
287             sub get_max_interpreters ($) {
288 0     0 1 0 my $this = shift;
289              
290 0 0       0 $this->{max_interpreters} || 0;
291             }
292              
293             =pod
294              
295             =item get_max_requests()
296              
297             Returns the maximum number of requests per interpreter passed to C.
298             This is only useful when called from within the dispatcher, as it is not set
299             before C is called.
300              
301             =cut
302              
303             sub get_max_requests ($) {
304 0     0 1 0 my $this = shift;
305              
306 0 0       0 $this->{max_requests} || 0;
307             }
308              
309             =pod
310              
311             =item main([MAXCHILDREN[, MAXREQ]])
312              
313             This is the last method called in the main block of a milter program. If
314             successful, this call never returns; the protocol engine is launched and
315             begins accepting connections.
316              
317             MAXCHILDREN (default 0, meaning unlimited) specifies the maximum number of
318             connections that may be serviced simultaneously. If a connection arrives
319             with the number of active connections above this limit, the milter will
320             immediately return a temporary failure condition and close the connection.
321             Passing a value for MAXCHILDREN is optional.
322              
323             MAXREQ (default 0, meaning unlimited) is the maximum number of requests that
324             a child may service before being recycled. It is not guaranteed that the
325             interpreter will service this many requests, only that it will not go over
326             the limit. MAXCHILDREN must be given if MAXREQ is to be set.
327              
328             Any callback which Cs will have its output sent to C, followed by
329             a clean shutdown of the milter connection. To catch any warnings generated
330             by the callbacks, and any error messages caused by a C, set
331             C<$SIG{__WARN__}> to a user-defined subroutine. (See L.)
332              
333             =cut
334              
335             sub main ($;$$$) {
336 0     0 1 0 require Sendmail::PMilter::Context;
337              
338 0         0 my $this = shift;
339 0 0       0 croak 'main: socket not bound' unless defined($this->{socket});
340 0 0       0 croak 'main: callbacks not registered' unless defined($this->{callbacks});
341 0 0       0 croak 'main: milter protocol version not defined' unless defined($this->{'milter protocol version'});
342              
343 0         0 my $max_interpreters = shift;
344 0         0 my $max_requests = shift;
345              
346 0 0 0     0 $this->{max_interpreters} = $max_interpreters if (defined($max_interpreters) && $max_interpreters =~ /^\d+$/); # This test doesn't permit an empty string.
347 0 0 0     0 $this->{max_requests} = $max_requests if (defined($max_requests) && $max_requests =~ /^\d+$/);
348              
349 0         0 my $dispatcher = $this->{dispatcher};
350              
351 0 0       0 unless (defined($dispatcher)) {
352 0   0     0 my $dispatcher_name = ($ENV{PMILTER_DISPATCHER} || 'postfork').'_dispatcher';
353 0         0 $dispatcher = &{\&{qualify_to_ref($dispatcher_name, 'Sendmail::PMilter')}};
  0         0  
  0         0  
354             }
355              
356             my $handler = sub {
357 0     0   0 my $ctx = new Sendmail::PMilter::Context(shift, $this->{callbacks}, $this->{callback_flags}, $this->{'milter protocol version'});
358              
359 0         0 $ctx->main();
360 0         0 };
361              
362 0         0 &$dispatcher($this, $this->{socket}, $handler);
363 0         0 undef;
364             }
365              
366             =pod
367              
368             =item register(NAME, CALLBACKS[, FLAGS])
369              
370             Sets up the main milter loop configuration.
371              
372             NAME is the name of the milter. This should be the same name as passed to
373             auto_getconn() or auto_setconn(), but this PMilter implementation does not
374             enforce this.
375              
376             CALLBACKS is a hash reference containing one or more callback subroutines.
377             For example
378              
379             my %callbacks =
380             (
381             'negotiate' => \&my_negotiate_callback,
382             'connect' => \&my_connect_callback,
383             'helo' => \&my_helo_callback,
384             'envfrom' => \&my_envfrom_callback,
385             'close' => \&my_close_callback,
386             'abort' => \&my_abort_callback,
387             );
388             $milter->register( $milter_name, \%callbacks );
389              
390             If a callback is not named in this hashref, the caller's package will be
391             searched for subroutines named "CALLBACK_callback", where CALLBACK is the
392             name of the callback function.
393              
394             FLAGS is accepted for backward compatibility with older versions of
395             this module. Consider it deprecated. Set it to SMFI_V6_PROT for all
396             available 'actions' in any recent (last few years) Sendmail version.
397              
398             If no C callback is registered, then by default the protocol
399             steps available are as described in .../libmilter/engine.c in the
400             Sendmail sources. This means all the registered CALLBACKS plus the
401             SKIP function call which is allowed in the End Of Message callback.
402             Note that SMFIP_RCPT_REJ is specifically not included.
403              
404             C must be called successfully exactly once. If called a second
405             time, the previously registered callbacks will be erased.
406              
407             Returns 1 on success, undef on failure.
408              
409             =cut
410              
411             sub register ($$$;$) {
412 0     0 1 0 my $this = shift;
413 0         0 $this->{name} = shift;
414              
415 0 0       0 carp 'register: no name supplied' unless defined($this->{name});
416 0 0       0 carp 'register: passed ref as name argument' if ref($this->{name});
417              
418 0         0 my $callbacks = shift;
419 0         0 my $pkg = caller;
420              
421 0 0       0 croak 'register: callbacks is undef' unless defined($callbacks);
422 0 0       0 croak 'register: callbacks not hash ref' unless UNIVERSAL::isa($callbacks, 'HASH');
423              
424             # make internal copy, and convert to code references
425 0         0 $callbacks = { %$callbacks };
426              
427 0         0 foreach my $cbname (keys %DEFAULT_CALLBACKS) {
428 0         0 my $cb = $callbacks->{$cbname};
429 0 0 0     0 if (defined($cb) && !UNIVERSAL::isa($cb, 'CODE')) {
430 0         0 $cb = qualify_to_ref($cb, $pkg);
431 0 0       0 if (exists(&$cb)) {
432 0         0 $callbacks->{$cbname} = \&$cb;
433             } else {
434 0         0 delete $callbacks->{$cbname};
435             }
436             }
437             }
438              
439 0         0 $this->{callbacks} = $callbacks;
440 0   0     0 $this->{callback_flags} = shift || 0;
441             # MILTER PROTOCOL VERSION
442 0 0       0 $this->{'milter protocol version'} = ($this->{callback_flags} & ~0x3F) ? 6 : 2;
443 0         0 1;
444             }
445              
446             =pod
447              
448             =item setconn(DESC)
449              
450             Sets up the server socket with connection descriptor DESC. This is
451             identical to the descriptor syntax used by the "X" milter configuration
452             lines in sendmail.cf (if using Sendmail). This should be one of the
453             following:
454              
455             =over 2
456              
457             =item local:PATH
458              
459             A local ("UNIX") socket on the filesystem, named PATH. This has some smarts
460             that will auto-delete the pathname if it seems that the milter is not
461             currently running (but this currently contains a race condition that may not
462             be fixable; at worst, there could be two milters running with one never
463             receiving connections).
464              
465             =item inet:PORT[@HOST]
466              
467             An IPv4 socket, bound to address HOST (default INADDR_ANY), on port PORT.
468             It is not recommended to open milter engines to the world, so the @HOST part
469             should be specified.
470              
471             =item inet6:PORT[@HOST]
472              
473             An IPv6 socket, bound to address HOST (default INADDR_ANY), on port PORT.
474             This requires IPv6 support and the Perl IO::Socket::IP package to be installed.
475             It is not recommended to open milter engines to the world, so the @HOST part
476             should be specified.
477              
478             =back
479              
480             Returns a true value on success, undef on failure.
481              
482             =cut
483              
484             sub setconn ($$) {
485 0     0 1 0 my $this = shift;
486 0         0 my $conn = shift;
487 0   0     0 my $backlog = $this->{backlog} || 5;
488 0         0 my $socket;
489              
490 0 0       0 croak "setconn: $conn: unspecified protocol"
491             unless ($conn =~ /^([^:]+):([^:@]+)(?:@([^:@]+|\[[0-9a-f:\.]+\]))?$/);
492              
493 0 0 0     0 if ($1 eq 'local' || $1 eq 'unix') {
    0          
    0          
494 0         0 require IO::Socket::UNIX;
495              
496 0         0 my $path = $2;
497 0         0 my $addr = sockaddr_un($path);
498              
499 0 0       0 croak "setconn: $conn: path not absolute"
500             unless ($path =~ m,^/,,);
501              
502 0 0 0     0 if (-e $path && ! -S $path) { # exists, not a socket
503 0         0 $! = Errno::EEXIST;
504             } else {
505 0         0 $socket = IO::Socket::UNIX->new(Type => SOCK_STREAM);
506             }
507              
508             # Some systems require you to unlink an orphaned inode.
509             # There's a race condition here, but it's unfortunately
510             # not easily fixable. Using an END{} block doesn't
511             # always work, and that's too wonky with fork() anyway.
512              
513 0 0 0     0 if (defined($socket) && !$socket->bind($addr)) {
514 0 0       0 if ($socket->connect($addr)) {
515 0         0 close $socket;
516 0         0 undef $socket;
517 0         0 $! = Errno::EADDRINUSE;
518             } else {
519 0         0 unlink $path; # race condition
520 0 0       0 $socket->bind($addr) || undef $socket;
521             }
522             }
523              
524 0 0       0 if (defined($socket)) {
525 0 0       0 $socket->listen($backlog) || croak "setconn: listen $conn: $!";
526             }
527             } elsif ($1 eq 'inet') {
528 0         0 require IO::Socket::INET;
529              
530 0         0 $socket = IO::Socket::INET->new(
531             Proto => 'tcp',
532             ReuseAddr => 1,
533             Listen => $backlog,
534             LocalPort => $2,
535             LocalAddr => $3
536             );
537             } elsif ($1 eq 'inet6') {
538 0         0 require IO::Socket::IP;
539              
540 0         0 $socket = IO::Socket::IP->new(
541             Proto => 'tcp',
542             ReuseAddr => 1,
543             Listen => $backlog,
544             LocalService => $2,
545             LocalHost => $3
546             );
547             } else {
548 0         0 croak "setconn: $conn: unknown protocol";
549             }
550              
551 0 0       0 if (defined($socket)) {
552 0         0 $this->set_socket($socket);
553             } else {
554 0         0 carp "setconn: $conn: $!";
555 0         0 undef;
556             }
557             }
558              
559             =pod
560              
561             =item set_dispatcher(CODEREF)
562              
563             Sets the dispatcher used to accept socket connections and hand them off to
564             the protocol engine. This allows pluggable resource allocation so that the
565             milter script may use fork, threads, or any other such means of handling
566             milter connections. See C below for more information.
567              
568             The subroutine (code) reference will be called by C when the
569             listening socket object is prepared and ready to accept connections. It
570             will be passed the arguments:
571              
572             MILTER, LSOCKET, HANDLER
573              
574             MILTER is the milter object currently running. LSOCKET is a listening
575             socket (an instance of C), upon which C should be
576             called. HANDLER is a subroutine reference which should be called, passing
577             the socket object returned by C<< LSOCKET->accept() >>.
578              
579             Note that the dispatcher may also be set from one of the off-the-shelf
580             dispatchers noted in this document by setting the PMILTER_DISPATCHER
581             environment variable. See C, below.
582              
583             =cut
584              
585             sub set_dispatcher($&) {
586 0     0 1 0 my $this = shift;
587              
588 0         0 $this->{dispatcher} = shift;
589 0         0 1;
590             }
591              
592             =pod
593              
594             =item set_listen(BACKLOG)
595              
596             Set the socket listen backlog to BACKLOG. The default is 5 connections if
597             not set explicitly by this method. Only useful before calling C.
598              
599             =cut
600              
601             sub set_listen ($$) {
602 0     0 1 0 my $this = shift;
603 0         0 my $backlog = shift;
604              
605 0 0       0 croak 'set_listen: socket already bound' if defined($this->{socket});
606              
607 0         0 $this->{backlog} = $backlog;
608 0         0 1;
609             }
610              
611             =pod
612              
613             =item set_socket(SOCKET)
614              
615             Rather than calling C, this method may be called explicitly to
616             set the C instance used to accept inbound connections.
617              
618             =cut
619              
620             sub set_socket ($$) {
621 0     0 1 0 my $this = shift;
622 0         0 my $socket = shift;
623              
624 0 0       0 croak 'set_socket: socket already bound' if defined($this->{socket});
625 0 0       0 croak 'set_socket: not an IO::Socket instance' unless UNIVERSAL::isa($socket, 'IO::Socket');
626              
627 0         0 $this->{socket} = $socket;
628 0         0 1;
629             }
630              
631             =pod
632              
633             =back
634              
635             =head1 SENDMAIL-SPECIFIC METHODS
636              
637             The following methods are only useful if Sendmail is the MTA connecting to
638             this milter. Other MTAs likely don't use Sendmail's configuration file, so
639             these methods would not be useful with them.
640              
641             =over 4
642              
643             =item auto_getconn(NAME[, CONFIG])
644              
645             Returns the connection descriptor for milter NAME in Sendmail configuration
646             file CONFIG (default C or whatever was set by
647             C). This can then be passed to setconn(), below.
648              
649             Returns a true value on success, undef on failure.
650              
651             =cut
652              
653             sub auto_getconn ($$;$) {
654 5     5 1 9 my $this = shift;
655 5   100     17 my $milter = shift || die "milter name not supplied\n";
656 4   33     15 my $cf = shift || $this->get_sendmail_cf();
657 4         11 local *CF;
658              
659 4 50       160 open(CF, '<'.$cf) || die "open $cf: $!";
660              
661 4         131 while () {
662 4         37 s/\s+$//; # also trims newlines
663              
664 4 50       28 s/^X([^,\s]+),\s*// || next;
665 4 50       21 ($milter eq $1) || next;
666              
667 4         21 while (s/^(.)=([^,\s]+)(,\s*|\Z)//) {
668 4 50       11 if ($1 eq 'S') {
669 4         52 close(CF);
670 4         47 return $2;
671             }
672             }
673             }
674              
675 0         0 close(CF);
676 0         0 undef;
677             }
678              
679             =pod
680              
681             =item auto_setconn(NAME[, CONFIG])
682              
683             Creates the server connection socket for milter NAME in Sendmail
684             configuration file CONFIG.
685              
686             Essentially, does:
687              
688             $milter->setconn($milter->auto_getconn(NAME, CONFIG))
689              
690             Returns a true value on success, undef on failure.
691              
692             =cut
693              
694             sub auto_setconn ($$;$) {
695 0     0 1 0 my $this = shift;
696 0         0 my $name = shift;
697 0         0 my $conn = $this->auto_getconn($name, shift);
698              
699 0 0       0 if (defined($conn)) {
700 0         0 $this->setconn($conn);
701             } else {
702 0         0 carp "auto_setconn: no connection for $name found";
703 0         0 undef;
704             }
705             }
706              
707             =pod
708              
709             =item get_sendmail_cf()
710              
711             Returns the pathname of the Sendmail configuration file. If this has
712             been set by C, then that is the value returned.
713             Otherwise the default pathname C is returned.
714              
715             =cut
716              
717             sub get_sendmail_cf ($) {
718 7     7 1 504 my $this = shift;
719              
720 7 100       41 $this->{sendmail_cf} || '/etc/mail/sendmail.cf';
721             }
722              
723             =pod
724              
725             =item get_sendmail_class(CLASS[, CONFIG])
726              
727             Returns a list containing all members of the Sendmail class CLASS, in
728             Sendmail configuration file CONFIG (default C or
729             whatever is set by C). Typically this is used to look up
730             the entries in class "w", the local hostnames class.
731              
732             =cut
733              
734             sub get_sendmail_class ($$;$) {
735 0     0 1 0 my $this = shift;
736 0         0 my $class = shift;
737 0   0     0 my $cf = shift || $this->get_sendmail_cf();
738 0         0 my %entries;
739 0         0 local *CF;
740              
741 0 0       0 open(CF, '<'.$cf) || croak "get_sendmail_class: open $cf: $!";
742              
743 0         0 while () {
744 0         0 s/\s+$//; # also trims newlines
745              
746 0 0       0 if (s/^C\s*$class\s*//) {
    0          
747 0         0 foreach (split(/\s+/)) {
748 0         0 $entries{$_} = 1;
749             }
750             } elsif (s/^F\s*$class\s*(-o)?\s*//) {
751 0         0 my $required = !defined($1);
752 0         0 local *I;
753              
754 0 0       0 croak "get_sendmail_class: class $class lookup resulted in pipe: $_" if (/^\|/);
755              
756 0 0       0 if (open(I, '<'.$_)) {
    0          
757 0         0 while () {
758 0         0 s/#.*$//;
759 0         0 s/\s+$//;
760 0 0       0 next if /^$/;
761 0         0 $entries{$_} = 1;
762             }
763 0         0 close(I);
764             } elsif ($required) {
765 0         0 croak "get_sendmail_class: class $class lookup: $_: $!";
766             }
767             }
768             }
769              
770 0         0 close(CF);
771 0         0 keys %entries;
772             }
773              
774             =pod
775              
776             =item get_sendmail_option(OPTION[, CONFIG])
777              
778             Returns a list containing the first occurrence of Sendmail option
779             OPTION in Sendmail configuration file CONFIG (default C,
780             or whatever has been set by C). Returns the
781             value of the option or undef if it is not found. This can be used
782             to learn configuration parameters such as Milter.maxdatasize.
783              
784             =cut
785              
786             sub get_sendmail_option ($$;$) {
787 0     0 1 0 my $this = shift;
788 0         0 my $option = shift;
789 0   0     0 my $cf = shift || $this->get_sendmail_cf();
790 0         0 my %entries;
791 0         0 local *CF;
792 0 0       0 open(CF, '<'.$cf) || croak "get_sendmail_option: open $cf: $!";
793 0         0 while () {
794 0         0 s/\s+$//; # also trims newlines
795 0 0       0 if (/^O\s*$option=(\d+)/) { return $1; }
  0         0  
796             }
797 0         0 close(CF);
798 0         0 undef;
799             }
800              
801             =pod
802              
803             =item set_sendmail_cf(FILENAME)
804              
805             Set the default filename used by C, C, and
806             C to find Sendmail-specific configuration data. If not
807             explicitly set by this method, it defaults to C.
808             Returns 1.
809              
810             =cut
811              
812             sub set_sendmail_cf ($) {
813 7     7 1 2554 my $this = shift;
814              
815 7         16 $this->{sendmail_cf} = shift;
816 7         29 1;
817             }
818              
819             ### off-the-shelf dispatchers
820              
821             =pod
822              
823             =back
824              
825             =head1 DISPATCHERS
826              
827             Milter requests may be dispatched to the protocol handler in a pluggable
828             manner (see the description for the C method above).
829             C offers some off-the-shelf dispatchers that use
830             different methods of resource allocation.
831              
832             Each of these is referenced as a non-object function, and return a value
833             that may be passed directly to C.
834              
835             =over 4
836              
837             =item Sendmail::PMilter::ithread_dispatcher()
838              
839             =item (environment) PMILTER_DISPATCHER=ithread
840              
841             June 2019: This dispatcher has not been tested adequately.
842              
843             The C dispatcher spins up a new thread upon each connection to
844             the milter socket. This provides a thread-based model that may be more
845             resource efficient than the similar C dispatcher. This requires
846             that the Perl interpreter be compiled with C<-Duseithreads>, and uses the
847             C module (available on Perl 5.8 or later only).
848              
849             =cut
850              
851             sub ithread_dispatcher {
852 0     0 1   require threads;
853 0           require threads::shared;
854 0           require Thread::Semaphore;
855              
856 0           my $nchildren = 0;
857              
858 0           threads::shared::share($nchildren);
859              
860             sub {
861 0     0     my $this = shift;
862 0           my $lsocket = shift;
863 0           my $handler = shift;
864 0           my $maxchildren = $this->get_max_interpreters();
865 0           my $child_sem;
866              
867 0 0         if ($maxchildren) {
868 0           $child_sem = Thread::Semaphore->new($maxchildren);
869             }
870            
871 0 0         my $siginfo = exists($SIG{INFO}) ? 'INFO' : 'USR1';
872             local $SIG{$siginfo} = sub {
873 0           warn "Number of active children: $nchildren\n";
874 0           };
875              
876             my $child_sub = sub {
877 0           my $socket = shift;
878              
879 0           eval {
880 0           &$handler($socket);
881 0           $socket->close();
882             };
883 0           my $died = $@;
884              
885 0           lock($nchildren);
886 0           $nchildren--;
887 0 0         if ($child_sem) {
888 0           $child_sem->up();
889             }
890 0 0         warn $died if $died;
891 0           };
892              
893 0           while (1) {
894 0           my $socket = $lsocket->accept();
895 0 0         next if $!{EINTR};
896              
897 0 0         warn "$$: incoming connection\n" if ($DEBUG > 0);
898              
899 0 0 0       if ($child_sem and ! $child_sem->down_nb()) {
900 0           warn "pausing for high load: children $nchildren >= max $maxchildren";
901 0           my $start = time();
902 0           $child_sem->down();
903 0           my $end = time();
904 0           warn sprintf("paused for %.1f seconds due to high load", $end - $start);
905             }
906              
907             # scoping block for lock()
908             {
909 0           lock($nchildren);
  0            
910 0   0       my $t = threads->create($child_sub, $socket) || die "thread creation failed: $!\n";
911 0           $t->detach;
912 0           threads->yield();
913 0           $nchildren++;
914             }
915             }
916 0           };
917             }
918              
919             =pod
920              
921             =item Sendmail::PMilter::prefork_dispatcher([PARAMS])
922              
923             =item (environment) PMILTER_DISPATCHER=prefork
924              
925             June 2019: This dispatcher has been tested extensively by the maintainer.
926              
927             The C dispatcher forks the main Perl process before accepting
928             connections, and uses the main process to monitor the children. This
929             should be appropriate for steady traffic flow sites. Note that if
930             MAXINTERP is not set in the call to C or in PARAMS, an internal
931             default of 10 processes will be used; similarly, if MAXREQ is not set, 100
932             requests will be served per child.
933              
934             Currently the child process pool is fixed in size: discarded children will
935             be replaced immediately.
936              
937             PARAMS, if specified, is a hash of key-value pairs defining parameters for
938             the dispatcher. The available parameters that may be set are:
939              
940             =over 2
941              
942             =item child_init
943              
944             subroutine reference that will be called after each child process is forked.
945             It will be passed the C object.
946              
947             =item child_exit
948              
949             subroutine reference that will be called just before each child process
950             terminates. It will be passed the C object.
951              
952             =item max_children
953              
954             Maximum number of child processes active at any time. Equivalent to the
955             MAXINTERP option to main() -- if not set in the main() call, this value
956             will be used.
957              
958             =item max_requests_per_child
959              
960             Maximum number of requests a child process may service before being
961             recycled. Equivalent to the MAXREQ option to main() -- if not set in the
962             main() call, this value will be used.
963              
964             =back
965              
966             =cut
967              
968             sub prefork_dispatcher (@) {
969 0     0 1   my %params = @_;
970 0           my %children;
971              
972             my $child_dispatcher = sub {
973 0     0     my $this = shift;
974 0           my $lsocket = shift;
975 0           my $handler = shift;
976 0   0       my $max_requests = $this->get_max_requests() || $params{max_requests_per_child} || 100;
977 0           my $i = 0;
978              
979 0           local $SIG{PIPE} = 'IGNORE'; # so close_callback will be reached
980              
981 0 0         my $siginfo = exists($SIG{INFO}) ? 'INFO' : 'USR1';
982             local $SIG{$siginfo} = sub {
983 0           warn "$$: requests handled: $i\n";
984 0           };
985              
986             # call child_init handler if present
987 0 0         if (defined $params{child_init}) {
988 0           my $method = $params{child_init};
989 0           $this->$method();
990             }
991              
992 0           while ($i < $max_requests) {
993 0           my $socket = $lsocket->accept();
994 0 0         next if $!{EINTR};
995              
996 0 0         warn "$$: incoming connection\n" if ($DEBUG > 0);
997              
998 0           $i++;
999 0           &$handler($socket);
1000 0           $socket->close();
1001             }
1002              
1003             # call child_exit handler if present
1004 0 0         if (defined $params{child_exit}) {
1005 0           my $method = $params{child_exit};
1006 0           $this->$method();
1007             }
1008 0           };
1009              
1010             # Propagate some signals down to the entire process group.
1011             my $killall = sub {
1012 0     0     my $sig = shift;
1013              
1014 0           kill 'TERM', keys %children;
1015 0           exit 0;
1016 0           };
1017 0           local $SIG{INT} = $killall;
1018 0           local $SIG{QUIT} = $killall;
1019 0           local $SIG{TERM} = $killall;
1020              
1021 0           setpgrp();
1022              
1023             sub {
1024 0     0     my $this = $_[0];
1025 0   0       my $maxchildren = $this->get_max_interpreters() || $params{max_children} || 10;
1026              
1027 0           while (1) {
1028 0           while (scalar keys %children < $maxchildren) {
1029 0           my $pid = fork();
1030 0 0         die "fork: $!" unless defined($pid);
1031              
1032 0 0         if ($pid) {
1033             # Perl reset these to IGNORE. Restore them.
1034 0           $SIG{INT} = $killall;
1035 0           $SIG{QUIT} = $killall;
1036 0           $SIG{TERM} = $killall;
1037 0           $children{$pid} = 1;
1038             } else {
1039             # Perl reset these to IGNORE. Set to defaults.
1040 0           $SIG{INT} = 'DEFAULT';
1041 0           $SIG{QUIT} = 'DEFAULT';
1042 0           $SIG{TERM} = 'DEFAULT';
1043 0           &$child_dispatcher(@_);
1044 0           exit 0;
1045             }
1046             }
1047              
1048             # Wait for a pid to exit, then loop back up to fork.
1049 0           my $pid = wait();
1050 0 0         delete $children{$pid} if ($pid > 0);
1051             }
1052 0           };
1053             }
1054              
1055             =pod
1056              
1057             =item Sendmail::PMilter::postfork_dispatcher()
1058              
1059             =item (environment) PMILTER_DISPATCHER=postfork
1060              
1061             June 2019: This dispatcher has not been tested adequately.
1062              
1063             This is the default dispatcher for PMilter if no explicit dispatcher is set.
1064              
1065             The C dispatcher forks the main Perl process upon each connection
1066             to the milter socket. This is adequate for machines that get bursty but
1067             otherwise mostly idle mail traffic, as the idle-time resource consumption is
1068             very low.
1069              
1070             If the maximum number of interpreters is running when a new connection
1071             comes in, this dispatcher blocks until a slot becomes available for a
1072             new interpreter.
1073              
1074             =cut
1075              
1076             sub postfork_dispatcher () {
1077 0     0 1   my $nchildren = 0;
1078 0           my $sigchld;
1079              
1080             $sigchld = sub {
1081 0     0     my $pid;
1082 0           $nchildren-- while (($pid = waitpid(-1, WNOHANG)) > 0);
1083 0           $SIG{CHLD} = $sigchld;
1084 0           };
1085              
1086             sub {
1087 0     0     my $this = shift;
1088 0           my $lsocket = shift;
1089 0           my $handler = shift;
1090 0           my $maxchildren = $this->get_max_interpreters();
1091              
1092             # Decrement child count on child exit.
1093 0           local $SIG{CHLD} = $sigchld;
1094              
1095 0 0         my $siginfo = exists($SIG{INFO}) ? 'INFO' : 'USR1';
1096             local $SIG{$siginfo} = sub {
1097 0           warn "Number of active children: $nchildren\n";
1098 0           };
1099              
1100 0           while (1) {
1101 0           my $socket = $lsocket->accept();
1102 0 0         next if !$socket;
1103              
1104 0 0         warn "$$: incoming connection\n" if ($DEBUG > 0);
1105              
1106             # If the load's too high, fail and go back to top of loop.
1107 0           my $paused = undef;
1108 0           while ($maxchildren) {
1109 0           my $cnchildren = $nchildren; # make constant
1110              
1111 0 0         if ($cnchildren >= $maxchildren) {
1112 0           warn "pausing for high load: children $cnchildren >= max $maxchildren";
1113 0 0         if ( ! $paused ) { $paused = time(); }
  0            
1114 0           pause();
1115             }
1116             else {
1117 0           last;
1118             }
1119             }
1120 0 0         if ($paused) {
1121 0           warn sprintf( "paused for %.1f seconds due to high load", time() - $paused );
1122             }
1123              
1124 0           my $pid = fork();
1125              
1126 0 0         if ($pid < 0) {
    0          
1127 0           die "fork: $!\n";
1128             } elsif ($pid) {
1129 0           $nchildren++;
1130 0 0         $socket->close() if defined($socket);
1131             } else {
1132 0           $lsocket->close();
1133 0           undef $lsocket;
1134 0           undef $@;
1135 0           $SIG{PIPE} = 'IGNORE'; # so close_callback will be reached
1136 0           $SIG{CHLD} = 'DEFAULT';
1137 0           $SIG{$siginfo} = 'DEFAULT';
1138              
1139 0           &$handler($socket);
1140 0 0         $socket->close() if defined($socket);
1141 0           exit 0;
1142             }
1143             }
1144 0           };
1145             }
1146              
1147             =pod
1148              
1149             =item Sendmail::PMilter::sequential_dispatcher()
1150              
1151             =item (environment) PMILTER_DISPATCHER=sequential
1152              
1153             June 2019: This dispatcher has not been tested adequately.
1154              
1155             The C dispatcher forces one request to be served at a time,
1156             making other requests wait on the socket for the next pass through the loop.
1157             This is not suitable for most production installations, but may be quite
1158             useful for milter debugging or other software development purposes.
1159              
1160             Note that, because the default socket backlog is 5 connections, if you
1161             use this dispatcher it may be wise to increase this backlog by calling
1162             C before entering C.
1163              
1164             =cut
1165              
1166             sub sequential_dispatcher () {
1167             sub {
1168 0     0     my $this = shift;
1169 0           my $lsocket = shift;
1170 0           my $handler = shift;
1171 0           local $SIG{PIPE} = 'IGNORE'; # so close_callback will be reached
1172              
1173 0           while (1) {
1174 0           my $socket = $lsocket->accept();
1175 0 0         next if $!{EINTR};
1176              
1177 0 0         warn "$$: incoming connection\n" if ($DEBUG > 0);
1178              
1179 0           &$handler($socket);
1180 0           $socket->close();
1181             }
1182 0     0 1   };
1183             }
1184              
1185             1;
1186             __END__