Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100755 749 lines (640 sloc) 22.711 kB
3837fab Ask and ye shall receive
John Peacock authored
1 #!/usr/bin/perl -Tw
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
2 # High performance pre-forking qpsmtpd daemon, Copyright (C) 2006 SoftScan
3 # http://www.softscan.co.uk
4 #
5 # Based on qpsmtpd-forkserver Copyright (C) 2001 Ask Bjoern Hansen
6 # See the LICENSE file for details.
7 #
ff0c613 @abh Update URL
abh authored
8 # For more information see http://smtpd.develooper.com/
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
9
10 # safety guards
11 use strict;
12
6b81c68 Sanitize the shell environment before loading modules
Devin Carraway authored
13 BEGIN {
14 # secure shell
15 $ENV{'PATH'} = '/bin:/usr/bin';
16 delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
17 }
18
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
19 # includes
20 use IO::Socket;
19a0f5d @aqua [PATCH] prefork: add multi-address support
aqua authored
21 use IO::Select;
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
22 use POSIX;
23 use IPC::Shareable(':all');
b2c3fd5 @rspier Add back the use lib 'lib' to qpsmtpd-prefork.
rspier authored
24 use lib 'lib';
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
25 use Qpsmtpd::TcpServer::Prefork;
26 use Qpsmtpd::Constants;
27 use Getopt::Long;
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
28
f4afd7a Diego warned me that the construct I used, signal sent to negative PI…
Radu Greab authored
29 use Config;
30 defined $Config{sig_name} || die "No signals?";
31
ccf990e IPv6 support from issue #7.
Matt Sergeant authored
32 my $has_ipv6 = Qpsmtpd::TcpServer::has_ipv6;
33
34 if ($has_ipv6) {
35 use Socket6;
36 }
37
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
38 #use Time::HiRes qw(gettimeofday tv_interval);
39
f4afd7a Diego warned me that the construct I used, signal sent to negative PI…
Radu Greab authored
40 #get available signals
41 my %sig_num;
42 my $i = 0;
43 foreach my $sig_name ( split( /\s/, $Config{sig_name} ) )
44 {
45 $sig_num{$sig_name} = $i++;
46 }
47
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
48 # version
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
49 my $VERSION = "1.0";
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
50
85cd1aa @vetinari prefork: clear a previously running instance by cloning the base inst…
vetinari authored
51 # qpsmtpd instances
0b0e4e9 @vetinari prefork: use new instance instead of cloning
vetinari authored
52 my ($qpsmtpd);
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
53
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
54 # cmd's needed by IPC
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
55 my $ipcrm = '/usr/bin/ipcrm';
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
56 my $ipcs = '/usr/bin/ipcs';
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
57 my $xargs = '/usr/bin/xargs';
58
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
59 # vars we need
60 my $chld_shmem; # shared mem to keep track of children (and their connections)
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
61 my %children;
62 my $chld_pool;
63 my $chld_busy;
e4f0cb0 Inside the main loop skip the sleep when children have exited. Instea…
Radu Greab authored
64 my @children_term; # terminated children, their death pending processing
65 # by the main loop
19a0f5d @aqua [PATCH] prefork: add multi-address support
aqua authored
66 my $select = new IO::Select; # socket(s)
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
67
68 # default settings
f0a27f8 @vetinari prefork: --pid-file option now works
vetinari authored
69 my $pid_file;
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
70 my $d_port = 25;
19a0f5d @aqua [PATCH] prefork: add multi-address support
aqua authored
71 my @d_addr; # default applied after getopt call
ccf990e IPv6 support from issue #7.
Matt Sergeant authored
72
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
73 my $debug = 0;
74 my $max_children = 15; # max number of child processes to spawn
75 my $idle_children = 5; # number of idle child processes to spawn
76 my $maxconnip = 10;
77 my $child_lifetime = 100; # number of times a child may be reused
04f8f7d More robust child spawning for prefork
Jared Johnson authored
78 my $loop_sleep = 15; # seconds main_loop sleeps before checking children
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
79 my $re_nice = 5; # substracted from parents current nice level
80 my $d_start = 0;
81 my $quiet = 0;
82 my $status = 0;
83 my $signal = '';
b7f4684 Fixup qpsmtpd-prefork, et al, to correctly load Constants.
John Peacock authored
84 my $pretty = 0;
502e1d2 @vetinari prefork: - add --detach option to daemonize like forkserver
vetinari authored
85 my $detach = 0;
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
86 my $user;
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
87
88 # help text
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
89 sub usage {
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
90 print <<"EOT";
91 Usage: qpsmtpd-prefork [ options ]
e8ee72a @aqua prefork: support --listen-address for consistency with forkserver
aqua authored
92 --quiet : Be quiet (even errors are suppressed)
93 --version : Show version information
94 --debug : Enable debug output
19a0f5d @aqua [PATCH] prefork: add multi-address support
aqua authored
95 --listen-address addr: Listen for connections on the address 'addr' (either
96 an IP address or ip:port pair). Listens on all
97 interfaces by default; may be specified multiple
98 times.
e8ee72a @aqua prefork: support --listen-address for consistency with forkserver
aqua authored
99 --port int : TCP port daemon should listen on (default: $d_port)
100 --max-from-ip int : Limit number of connections from single IP (default: $maxconnip, 0 to disable)
101 --children int : Max number of children that can be spawned (default: $max_children)
102 --idle-children int : Number of idle children to spawn (default: $idle_children, 0 to disable)
103 --pretty-child : Change child process name (default: 0)
104 --user username : User the daemon should run as
105 --pid-file path : Path to pid file
106 --renice-parent int : Subtract value from parent process nice level (default: $re_nice)
107 --detach : detach from controlling terminal (daemonize)
108 --help : This message
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
109 EOT
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
110 exit 0;
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
111 }
112
113 # get arguments
114 GetOptions(
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
115 'quiet' => \$quiet,
116 'version' => sub { print "Qpsmtpd Daemon - version $VERSION\n"; exit 0; },
117 'debug' => \$debug,
19a0f5d @aqua [PATCH] prefork: add multi-address support
aqua authored
118 'interface|listen-address=s' => \@d_addr,
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
119 'port=i' => \$d_port,
120 'max-from-ip=i' => \$maxconnip,
121 'children=i' => \$max_children,
122 'idle-children=i' => \$idle_children,
b7f4684 Fixup qpsmtpd-prefork, et al, to correctly load Constants.
John Peacock authored
123 'pretty-child' => \$pretty,
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
124 'user=s' => \$user,
125 'renice-parent=i' => \$re_nice,
502e1d2 @vetinari prefork: - add --detach option to daemonize like forkserver
vetinari authored
126 'detach' => \$detach,
f0a27f8 @vetinari prefork: --pid-file option now works
vetinari authored
127 'pid-file=s' => \$pid_file,
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
128 'help' => \&usage,
129 ) || &usage;
130
19a0f5d @aqua [PATCH] prefork: add multi-address support
aqua authored
131 if ($user && $user =~ /^([\w\-]+)$/) { $user = $1 } else { &usage }
132
133 if (@d_addr) {
134 for my $i (0..$#d_addr) {
135 if ($d_addr[$i] =~ /^(\[.*\]|[\d\w\-.]+)(?::(\d+))?$/) {
136 $d_addr[$i] = { 'addr' => $1, 'port' => $2 || $d_port };
137 } else {
138 print STDERR "Malformed listen address '$d_addr[$i]'\n";
139 &usage;
140 }
141 }
142 } else {
8527f78 @aqua prefork: Fix startup when no interface addresses are specified
aqua authored
143 @d_addr = ( { addr => $has_ipv6 ? "[::]" : "0.0.0.0", port => $d_port } );
19a0f5d @aqua [PATCH] prefork: add multi-address support
aqua authored
144 }
3837fab Ask and ye shall receive
John Peacock authored
145
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
146 # set max from ip to max number of children if option is set to disabled
147 $maxconnip = $max_children if ($maxconnip == 0);
148
149 #to fix limit counter error in plugin <hosts_allow>
150 $maxconnip++;
151
152 #ensure that idle_children matches value given to max_children
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
153 $idle_children = $max_children
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
154 if (!$idle_children || $idle_children > $max_children || $idle_children < -1);
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
155 $chld_pool = $idle_children;
156
f0a27f8 @vetinari prefork: --pid-file option now works
vetinari authored
157 if ($pid_file) {
158 if ($pid_file =~ m#^(/[\w\d/\-.]+)$#) { $pid_file = $1 } else { &usage }
159 if (-e $pid_file) {
160 open PID, "+<$pid_file"
161 or die "open pid_file: $!\n";
162 my $running_pid = <PID> || ''; chomp $running_pid;
163 if ($running_pid =~ /(\d+)/) {
164 $running_pid = $1;
165 die "Found an already running qpsmtpd with pid $running_pid.\n"
166 if (kill 0, $running_pid);
167 }
168 seek PID, 0, 0
169 or die "Could not seek back to beginning of $pid_file: $!\n";
170 truncate PID, 0
171 or die "Could not truncate $pid_file at 0: $!";
172 }
173 else {
174 open PID, ">$pid_file"
175 or die "open pid_file: $!\n";
176 }
177 }
178
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
179 run();
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
180
181 #start daemon
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
182 sub run {
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
183 # get UUID/GUID
502e1d2 @vetinari prefork: - add --detach option to daemonize like forkserver
vetinari authored
184 my ($quid, $qgid, $groups);
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
185 if ($user) {
502e1d2 @vetinari prefork: - add --detach option to daemonize like forkserver
vetinari authored
186 (undef, undef, $quid, $qgid) = getpwnam $user
187 or die "unable to determine uid/gid for $user\n";
188 $groups = "$qgid $qgid";
189 while (my ($name,$passwd,$gid,$members) = getgrent()) {
190 my @m = split(/ /, $members);
191 if (grep {$_ eq $user} @m) {
192 $groups .= " $gid";
193 }
194 }
195 endgrent;
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
196 }
197
19a0f5d @aqua [PATCH] prefork: add multi-address support
aqua authored
198 for my $addr (@d_addr) {
199 my @Socket_opts = (
200 LocalPort => $addr->{port},
201 LocalAddr => $addr->{addr},
202 Proto => 'tcp',
203 Listen => SOMAXCONN,
204 Reuse => 1,
205 );
206 # create new socket (used by clients to communicate with daemon)
207 my $s;
208 if ($has_ipv6) {
209 $s = IO::Socket::INET6->new(@Socket_opts);
210 }
211 else {
212 $s = IO::Socket::INET->new(@Socket_opts);
213 }
214 die "FATAL: Failed to open socket on $addr->{addr}:$addr->{port} ($@)"
215 . "\nIt may be necessary to wait 20 secs before starting daemon"
216 . " again."
217 unless $s;
218 $select->add($s);
ccf990e IPv6 support from issue #7.
Matt Sergeant authored
219 }
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
220
19a0f5d @aqua [PATCH] prefork: add multi-address support
aqua authored
221 info("qpsmtpd-prefork daemon, version: $VERSION, staring on host: "
222 . join(', ', map { "$_->{addr}:$_->{port}"} @d_addr)
223 . " (user: $user [$<])");
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
224
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
225 # reset priority
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
226 my $old_nice = getpriority(0, 0);
227 my $new_nice = $old_nice - $re_nice;
228 if ($new_nice < 20 && $new_nice > -20) {
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
229 setpriority(0, 0, $1) if ($new_nice =~ /(\-?\d+)/);
230 info("parent daemon nice level: $1");
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
231 }
232 else {
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
233 die "FATAL: new nice level: $new_nice is not between -19 and 19 "
234 . "(old level = $old_nice, renice value = $re_nice)";
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
235 }
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
236
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
237 if ($user) {
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
238 # change UUID/UGID
502e1d2 @vetinari prefork: - add --detach option to daemonize like forkserver
vetinari authored
239 $) = $groups;
240 POSIX::setgid($qgid) or die "unable to change gid: $!\n";
241 POSIX::setuid($quid) or die "unable to change uid: $!\n";
242 $> = $quid;
243 die "FATAL: failed to setuid to user: $user, uid: $quid\n"
244 if ($> != $quid and $> != ($quid - 2**32));
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
245 }
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
246
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
247 # setup shared memory
2a5c554 @vetinari prefork: support two or more parallel running instances (on different…
vetinari authored
248 $chld_shmem = shmem($d_port."qpsmtpd", 1);
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
249 untie $chld_shmem;
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
250
251 # Interrupt handler
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
252 $SIG{INT} = $SIG{TERM} = sub {
253 # terminate daemon (and children)
254 my $sig = shift;
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
255
256 # prevent another signal and disable reaper
257 $SIG{$sig} = $SIG{CHLD} = $SIG{HUP} = 'IGNORE';
258
f4afd7a Diego warned me that the construct I used, signal sent to negative PI…
Radu Greab authored
259 # a notice, before the sleep below
260 info("shutting down");
261
19a0f5d @aqua [PATCH] prefork: add multi-address support
aqua authored
262 # close socket(s)
263 $_->close for $select->handles;
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
264
03c2bf7 prefork: improve shutdown of parent (and children) on very busy systems
Diego d'Ambra authored
265 # send signal to process group
f4afd7a Diego warned me that the construct I used, signal sent to negative PI…
Radu Greab authored
266 kill -$sig_num{$sig} => $$;
03c2bf7 prefork: improve shutdown of parent (and children) on very busy systems
Diego d'Ambra authored
267
268 # cleanup
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
269 IPC::Shareable->clean_up;
03c2bf7 prefork: improve shutdown of parent (and children) on very busy systems
Diego d'Ambra authored
270 unlink($pid_file) if $pid_file;
271
272 info("shutdown of daemon");
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
273 exit;
274 };
275
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
276 # Hup handler
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
277 $SIG{HUP} = sub {
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
278 # reload qpmstpd plugins
0b0e4e9 @vetinari prefork: use new instance instead of cloning
vetinari authored
279 $qpsmtpd = qpsmtpd_instance('restart' => 1); # reload plugins...
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
280 $qpsmtpd->load_plugins;
281 kill 'HUP' => keys %children;
282 info("reload daemon requested");
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
283 };
284
0b0e4e9 @vetinari prefork: use new instance instead of cloning
vetinari authored
285 # setup qpsmtpd_instance
286 $qpsmtpd = qpsmtpd_instance();
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
287
18d1b9f Detach and daemonize only after reading the configuration and loading…
Diego d'Ambra authored
288 if ($detach) {
289 open STDIN, '/dev/null' or die "/dev/null: $!";
290 open STDOUT, '>/dev/null' or die "/dev/null: $!";
291 open STDERR, '>&STDOUT' or die "open(stderr): $!";
292 defined (my $pid = fork) or die "fork: $!";
293 exit 0 if $pid;
294 }
75decb1 Always call setsid, even when we're not daemonizing.
Charlie Brady authored
295 POSIX::setsid or die "setsid: $!";
18d1b9f Detach and daemonize only after reading the configuration and loading…
Diego d'Ambra authored
296
297 if ($pid_file) {
298 print PID $$,"\n";
299 close PID;
300 }
301
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
302 # child reaper
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
303 $SIG{CHLD} = \&reaper;
304 spawn_children();
305 main_loop();
306 exit;
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
307 }
308
309 # initialize children (only done at daemon startup)
310 sub spawn_children {
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
311 # block signals while new children are being spawned
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
312 my $sigset = block_signal(SIGCHLD);
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
313 for (1 .. $chld_pool) {
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
314 new_child();
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
315 }
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
316
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
317 # reset block signals
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
318 unblock_signal($sigset);
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
319 }
320
321 # cleanup after child dies
322 sub reaper {
323 my $stiff;
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
324 while (($stiff = waitpid(-1, &WNOHANG)) > 0) {
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
325 my $res = WEXITSTATUS($?);
326 info("child terminated, pid: $stiff (status $?, res: $res)");
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
327 delete $children{$stiff}; # delete pid from children
328 # add pid to array so it later can be removed from shared memory
e4f0cb0 Inside the main loop skip the sleep when children have exited. Instea…
Radu Greab authored
329 push @children_term, $stiff;
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
330 }
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
331
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
332 $SIG{CHLD} = \&reaper;
333 }
334
e4f0cb0 Inside the main loop skip the sleep when children have exited. Instea…
Radu Greab authored
335 #main_loop: main loop. Either processes children that have exited or
336 # periodically scans the shared memory for children that are not longer
337 # alive. Spawns new children when necessary.
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
338 #arg0: void
339 #ret0: void
340 sub main_loop {
04f8f7d More robust child spawning for prefork
Jared Johnson authored
341 my $created_children = $idle_children;
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
342 while (1) {
e4f0cb0 Inside the main loop skip the sleep when children have exited. Instea…
Radu Greab authored
343 # if there is no child death to process, then sleep EXPR seconds
344 # or until signal (i.e. child death) is received
04f8f7d More robust child spawning for prefork
Jared Johnson authored
345 sleep $loop_sleep / ($created_children * 2 + 1) unless @children_term;
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
346
e4f0cb0 Inside the main loop skip the sleep when children have exited. Instea…
Radu Greab authored
347 # block CHLD signals to avoid race
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
348 my $sigset = block_signal(SIGCHLD);
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
349
e4f0cb0 Inside the main loop skip the sleep when children have exited. Instea…
Radu Greab authored
350 # get number of busy children
351 if (@children_term) {
352 # remove dead children info from shared memory
353 $chld_busy = shmem_opt(undef, \@children_term, undef, undef);
354 @children_term = ();
355 }
356 else {
357 # just check the shared memory
358 $chld_busy = shmem_opt(undef, undef, undef, undef, 1);
359 }
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
360
361 # calculate children in pool (if valid busy children number)
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
362 if (defined($chld_busy)) {
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
363 info("busy children: $chld_busy");
364 $chld_pool = $chld_busy + $idle_children;
409372c Detect and reset locked shared memory.
Diego d'Ambra authored
365
366 # ensure pool limit is max_children
367 $chld_pool = $max_children if ($chld_pool > $max_children);
368 info( "children pool: $chld_pool, spawned: "
369 . scalar(keys %children)
370 . ", busy: $chld_busy");
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
371 }
409372c Detect and reset locked shared memory.
Diego d'Ambra authored
372 else {
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
373
409372c Detect and reset locked shared memory.
Diego d'Ambra authored
374 # reset shared memory
375 warn("unable to access shared memory - resetting it");
376 IPC::Shareable->clean_up;
377 my $shmem = shmem($d_port . "qpsmtpd", 1);
378 untie $shmem;
379 }
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
380
381 # spawn children
04f8f7d More robust child spawning for prefork
Jared Johnson authored
382 $created_children = $chld_pool - keys %children;
383 $created_children = 0 if $created_children < 0;
384 new_child() for 1..$created_children;
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
385
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
386 # unblock signals
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
387 unblock_signal($sigset);
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
388 }
389 }
390
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
391 # block_signal: block signals
392 # arg0..n: int with signal(s) to block
393 # ret0: ref str with sigset (used to later unblock signal)
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
394 sub block_signal {
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
395 my @signal = @_; #arg0..n
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
396
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
397 my ($sigset, $blockset);
398
399 $sigset = POSIX::SigSet->new();
400 $blockset = POSIX::SigSet->new(@signal);
401 sigprocmask(SIG_BLOCK, $blockset, $sigset)
402 or die "Could not block @signal signals: $!\n";
403
404 return ($sigset);
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
405 }
406
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
407 # unblock_signal: unblock/reset and receive pending signals
408 # arg0: ref str with sigset
409 # ret0: void
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
410 sub unblock_signal {
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
411 my $sigset = shift; # arg0
412 sigprocmask(SIG_SETMASK, $sigset)
413 or die "Could not restore signals: $!\n";
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
414 }
415
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
416 # new_child: initialize new child
417 # arg0: void
418 # ret0: void
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
419 sub new_child {
420 # daemonize away from the parent process
421 my $pid;
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
422 die "Cannot fork child: $!\n" unless defined($pid = fork);
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
423 if ($pid) {
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
424 # in parent
425 $children{$pid} = 1;
426 info("new child, pid: $pid");
427 return;
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
428 }
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
429
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
430 # in child
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
431
432 # reset priority
433 setpriority 0, 0, getpriority(0, 0) + $re_nice;
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
434
435 # reset signals
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
436 my $sigset = POSIX::SigSet->new();
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
437 my $blockset = POSIX::SigSet->new(SIGCHLD);
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
438 sigprocmask(SIG_UNBLOCK, $blockset, $sigset)
ab6dd83 Clean up exit codes.
Radu Greab authored
439 or die "Could not unblock SIGCHLD signal: $!\n";
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
440 $SIG{CHLD} = $SIG{INT} = $SIG{TERM} = $SIG{ALRM} = 'DEFAULT';
441
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
442 # child should exit if it receives HUP signal (note: blocked while child
443 # is busy, but restored once done)
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
444 $SIG{HUP} = sub {
445 info("signal HUP received, going to exit");
ab6dd83 Clean up exit codes.
Radu Greab authored
446 exit;
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
447 };
448
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
449 # continue to accept connections until "old age" is reached
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
450 for (my $i = 0 ; $i < $child_lifetime ; $i++) {
451 # accept a connection
19a0f5d @aqua [PATCH] prefork: add multi-address support
aqua authored
452 if ( $pretty ) {
453 $ENV{PROCESS} = $0 if not defined $ENV{PROCESS}; # 1st time only
454 $0 = 'qpsmtpd child'; # set pretty child name in process listing
455 }
456 my @ready = $select->can_read();
457 next unless @ready;
458 my $socket = $ready[0];
459 my ($client, $iinfo) = $socket->accept()
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
460 or die
461 "failed to create new object - $!"; # wait here until client connects
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
462 info("connect from: " . $client->peerhost . ":" . $client->peerport);
85cd1aa @vetinari prefork: clear a previously running instance by cloning the base inst…
vetinari authored
463
0b0e4e9 @vetinari prefork: use new instance instead of cloning
vetinari authored
464 # clear a previously running instance by creating a new instance
465 $qpsmtpd = qpsmtpd_instance();
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
466
467 # set STDIN/STDOUT and autoflush
0be3400 @vetinari prefork: using POSIX::dup2 failed after a few million connections, so
vetinari authored
468 # ... no longer use POSIX::dup2: it failes after a few
469 # million connections
470 close(STDIN);
471 open(STDIN, "+<&".fileno($client))
472 or die "unable to duplicate filehandle to STDIN - $!";
473
474 close(STDOUT);
475 open(STDOUT, "+>&".fileno($client))
476 or die "unable to duplicate filehandle to STDOUT - $!";
477 select(STDOUT);
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
478 $| = 1;
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
479
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
480 # connection recieved, block signals
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
481 my $sigset = block_signal(SIGHUP);
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
482
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
483 # start a session if connection looks valid
19a0f5d @aqua [PATCH] prefork: add multi-address support
aqua authored
484 qpsmtpd_session($socket, $client, $iinfo, $qpsmtpd) if ($iinfo);
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
485
486 # close connection and cleanup
487 $client->shutdown(2);
488
489 # unset block and receive pending signals
490 unblock_signal($sigset);
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
491 }
492 exit; # this child has reached its end-of-life
493 }
494
495 # respond to client
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
496 # arg0: ref to socket object (client)
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
497 # arg1: int with SMTP reply code
498 # arg2: arr with message
499 # ret0: int 0|1 (0 = failure, 1 = success)
500 sub respond_client {
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
501 my ($client, $code, @message) = @_;
502 $client->autoflush(1);
503 while (my $msg = shift @message) {
504 my $line = $code . (@message ? "-" : " ") . $msg;
505 info("reply to client: <$line>");
506 print $client "$line\r\n"
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
507 or (info("Could not print [$line]: $!"), return 0);
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
508 }
509 return 1;
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
510 }
511
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
512 # qpsmtpd_instance: setup qpsmtpd instance
513 # arg0: void
514 # ret0: ref to qpsmtpd_instance
85cd1aa @vetinari prefork: clear a previously running instance by cloning the base inst…
vetinari authored
515 sub qpsmtpd_instance {
a64742c @vetinari prefork, forkserver: restart on SIGHUP: * reset to defaults * clear c…
vetinari authored
516 my %args = @_;
517 my $qpsmtpd = Qpsmtpd::TcpServer::Prefork->new(%args);
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
518 $qpsmtpd->load_plugins;
519 $qpsmtpd->spool_dir;
520 $qpsmtpd->size_threshold;
521
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
522 return ($qpsmtpd);
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
523 }
524
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
525 # shmem: tie to shared memory hash
526 # arg0: str with glue
527 # arg1: int 0|1 (0 = don't create shmem, 1 = create shmem)
528 # ret0: ref to shared hash
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
529 sub shmem {
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
530 my $glue = shift; #arg0
531 my $create = shift || 0; #arg1
532
533 my %options = (
534 create => $create,
535 exclusive => 0,
536 mode => 0640,
537 destroy => 0,
538 );
539
540 my %shmem_hash;
541 eval {
542 tie %shmem_hash, 'IPC::Shareable', $glue, {%options}
543 || die "unable to tie to shared memory - $!";
544 };
545 if ($@) {
546 info("$@");
547 return;
548 }
549
550 return (\%shmem_hash);
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
551 }
552
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
553 # shmem_opt: connect to shared memory and perform options
554 # arg0: ref to hash where shared memory should be copied to
555 # arg1: ref to arr with pid(s) to delete
556 # arg2: int with pid to add (key)
557 # arg3: str with packed iaddr to add (value)
558 # arg4: int 0|1 check and cleanup shared memory (0 = no, 1 = yes - default 0)
559 # ret0: int with number of busy children (undef if error)
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
560 sub shmem_opt {
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
561 my $ref_shmem = shift; #arg0
562 my $ref_pid_del = shift; #arg1
563 my $pid_add_key = shift; #arg2
564 my $pid_add_value = shift; #arg3
565 my $check = shift || 0; #arg4
566
567 # check arguments
568 if ( (defined($pid_add_key) && !defined($pid_add_value))
569 || (!defined($pid_add_key) && defined($pid_add_value)))
570 {
571 return;
572 }
573
574 my ($chld_shmem, $chld_busy);
575 eval {
2a5c554 @vetinari prefork: support two or more parallel running instances (on different…
vetinari authored
576 $chld_shmem = &shmem($d_port."qpsmtpd", 0); #connect to shared memory hash
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
577
578 if (tied %{$chld_shmem}) {
409372c Detect and reset locked shared memory.
Diego d'Ambra authored
579
580 # lock shared memory
581 eval {
582 # ensure that hung shared memory is noticed
583 local $SIG{ALRM} = sub {
584 die "locking timed out\n";
585 };
586 alarm 15;
587
588 (tied %{$chld_shmem})->shlock(LOCK_EX);
589
590 alarm 0;
591 };
592 die $@ if $@;
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
593
594 # delete
595 if ($ref_pid_del) {
596 foreach my $pid_del (@{$ref_pid_del}) {
597 delete $$chld_shmem{$pid_del};
598 }
599 }
600 # add
601 $$chld_shmem{$pid_add_key} = $pid_add_value if ($pid_add_key);
602 # copy
603 %{$ref_shmem} = %{$chld_shmem} if ($ref_shmem);
409372c Detect and reset locked shared memory.
Diego d'Ambra authored
604
605 # check
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
606 if ($check) {
607 # loop through pid list and delete orphaned processes
608 foreach my $pid (keys %{$chld_shmem}) {
609 if (!kill 0, $pid) {
610 delete $$chld_shmem{$pid};
611 warn("orphaned child, pid: $pid removed from memory");
612 }
613 }
614 }
615
409372c Detect and reset locked shared memory.
Diego d'Ambra authored
616 # number of busy children
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
617 $chld_busy = scalar(keys %{$chld_shmem});
409372c Detect and reset locked shared memory.
Diego d'Ambra authored
618
619 # unlock shared memory
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
620 (tied %{$chld_shmem})->shunlock;
621
622 # untie from shared memory
623 untie $chld_shmem || die "unable to untie from shared memory";
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
624 }
409372c Detect and reset locked shared memory.
Diego d'Ambra authored
625 else {
626 die "failed to connect to shared memory";
627 }
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
628 };
629
630 # check for error
631 if ($@) {
632 undef($chld_busy);
633 warn("$@");
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
634 }
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
635
636 return ($chld_busy);
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
637 }
638
639 # info: write info
640 # arg0: str with debug text
641 sub info {
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
642 my $text = shift; #arg0
643 return if (!$debug);
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
644
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
645 my ($sec, $min, $hour, $mday, $mon, $year) = localtime(time);
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
646 my $nowtime = sprintf "%02d/%02d/%02d %02d:%02d:%02d", $mday, $mon + 1,
647 $year + 1900, $hour, $min, $sec;
648
649 chomp($text);
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
650 print STDERR "$nowtime:$$: $text\n";
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
651 }
652
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
653 # start qpmstpd session
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
654 # arg0: ref to socket object
ccf990e IPv6 support from issue #7.
Matt Sergeant authored
655 # arg1: ref to socket object
656 # arg2: ref to qpsmtpd instance
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
657 # ret0: void
658 sub qpsmtpd_session {
19a0f5d @aqua [PATCH] prefork: add multi-address support
aqua authored
659 my $socket = shift; #arg0
660 my $client = shift; #arg1
661 my $iinfo = shift; #arg2
662 my $qpsmtpd = shift; #arg3
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
663
664 # get local/remote hostname, port and ip address
19a0f5d @aqua [PATCH] prefork: add multi-address support
aqua authored
665 my ($port, $iaddr, $lport, $laddr, $nto_iaddr, $nto_laddr) =
666 Qpsmtpd::TcpServer::lrpip($socket, $client, $iinfo);
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
667
668 # get current connected ip addresses (from shared memory)
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
669 my %children;
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
670 shmem_opt(\%children, undef, $$, $iaddr);
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
671
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
672 my ($rc, @msg) =
673 $qpsmtpd->run_hooks(
674 "pre-connection",
ccf990e IPv6 support from issue #7.
Matt Sergeant authored
675 remote_ip => $nto_iaddr,
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
676 remote_port => $port,
ccf990e IPv6 support from issue #7.
Matt Sergeant authored
677 local_ip => $nto_laddr,
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
678 local_port => $lport,
679 max_conn_ip => $maxconnip,
680 child_addrs => [values %children],
681 );
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
682 if ( $rc == DENYSOFT
683 || $rc == DENYSOFT_DISCONNECT
684 || $rc == DENY
685 || $rc == DENY_DISCONNECT)
686 {
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
687 #smtp return code to reply client with (seed with soft deny)
688 my $rc_reply = 451;
689 unless ($msg[0]) {
690 if ($rc == DENYSOFT || $rc == DENYSOFT_DISCONNECT) {
691 @msg = ("Sorry, try again later");
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
692 }
693 else {
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
694 @msg = ("Sorry, service not available to you");
695 $rc_reply = 550;
696 }
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
697 }
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
698 respond_client($client, $rc_reply, @msg);
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
699
700 # remove pid from shared memory
701 shmem_opt(undef, [$$], undef, undef);
702
703 # retur so child can be reused
704 return;
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
705 }
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
706
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
707 # all children should have different seeds, to prevent conflicts
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
708 srand(time ^ ($$ + ($$ << 15)));
709
710 # ALRM handler
711 $SIG{ALRM} = sub {
712 print $client "421 Connection Timed Out\n";
e9e95dd Patch to qpsmtpd-prefork from Matt Sergeant:
John Peacock authored
713 info("Connection Timed Out");
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
714
ab6dd83 Clean up exit codes.
Radu Greab authored
715 # child terminates
716 exit;
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
717 };
718
719 # set enviroment variables
ccf990e IPv6 support from issue #7.
Matt Sergeant authored
720 ($ENV{TCPLOCALIP}, $ENV{TCPREMOTEIP}, $ENV{TCPREMOTEHOST}) = Qpsmtpd::TcpServer::tcpenv($nto_laddr, $nto_iaddr);
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
721
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
722 # run qpmsptd functions
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
723 $SIG{__DIE__} = 'DEFAULT';
724 eval {
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
725 $qpsmtpd->start_connection(
726 local_ip => $ENV{TCPLOCALIP},
727 local_port => $lport,
728 remote_ip => $ENV{TCPREMOTEIP},
729 remote_port => $client->peerport,
730 );
59b826d Fix to check client is writable before writing to it.
Matt Sergeant authored
731 $qpsmtpd->run($client);
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
732 $qpsmtpd->run_hooks("post-connection");
ea243c2 @vetinari add reset() to Qpsmtpd::Connection to clear the connection notes after
vetinari authored
733 $qpsmtpd->connection->reset;
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
734 };
9bb950d Additional patch to qpsmtpd-prefork from Lars Roland:
John Peacock authored
735 if ($@ !~ /^(disconnect_tcpserver|died while reading from STDIN)/) {
736 warn("$@");
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
737 }
738
409372c Detect and reset locked shared memory.
Diego d'Ambra authored
739 # child is now idle again
740 info("disconnect from: $nto_iaddr:$port");
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
741
409372c Detect and reset locked shared memory.
Diego d'Ambra authored
742 # remove pid from shared memory
743 unless (defined(shmem_opt(undef, [$$], undef, undef))) {
744 # exit because parent is down or shared memory is corrupted
745 info("parent seems to be down, going to exit");
746 exit 1;
747 }
67dc86e New pre-forking qpsmtpd daemon, courtesy of Lars Roland at SoftScan.
John Peacock authored
748 }
Something went wrong with that request. Please try again.