cvs commit: qpsmtpd qpsmtpd-forkserver

[email protected] (Robert Spier)
Newsgroups perl.cvs.qpsmtpd
Message-ID <[email protected]>
cvsuser     04/04/14 19:19:02

  Modified:    .        qpsmtpd-forkserver
  Log:
  - move configuration to top.  (still suboptimal)
  - child limiting
  - logging helper
  
  Revision  Changes    Path
  1.3       +39 -18    qpsmtpd/qpsmtpd-forkserver
  
  Index: qpsmtpd-forkserver
  ===================================================================
  RCS file: /cvs/public/qpsmtpd/qpsmtpd-forkserver,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -w -r1.2 -r1.3
  --- qpsmtpd-forkserver	18 Mar 2004 23:02:43 -0000	1.2
  +++ qpsmtpd-forkserver	15 Apr 2004 02:19:01 -0000	1.3
  @@ -15,38 +15,39 @@
   use strict;
   $| = 1;
   
  +# Configuration
  +my $MAXCONN   = 15;				# max simultaneous connections
  +my $PORT      = 25;				# port number
  +my $LOCALADDR = '0.0.0.0';		# ip address to bind to
  +my $USER      = 'smtpd';		# user to suid to
  +
   delete $ENV{ENV};
   $ENV{PATH} = '/bin:/usr/bin:/var/qmail/bin';
   
  +my %childstatus = ();
  +
   sub REAPER {
  -    while (defined(my $child = waitpid(-1, WNOHANG)) ) {
  -        if ($child == -1) {
  -            # No child here? Loop back
  -        }
  -        elsif (WIFEXITED($?)) {
  -            # Process exited
  -            last;
  -        }
  -        else {
  -            # Possibly SIGSTOP on child...
  -            last;
  -        }
  +  while ( defined(my $chld = waitpid(-1, WNOHANG)) ){
  +    last unless $chld > 0;
  +    warn("$$ cleaning up after $chld\n");
  +    delete $childstatus{$chld};
       }
   }
   
   $SIG{CHLD} = \&REAPER;
   
   # establish SERVER socket, bind and listen.
  -my $server = IO::Socket::INET->new(LocalPort => 25,
  +my $server = IO::Socket::INET->new(LocalPort => $PORT,
  +				   LocalAddr => $LOCALADDR,
                                      Proto     => 'tcp',
                                      Reuse     => 1,
                                      Listen    => SOMAXCONN )
     or die "making socket: $@\n";
   
   # Drop priviledges
  -my $user = 'smtpd';
  -my (undef, undef, $quid, $qgid) = getpwnam $user or
  -      die "unable to determine uid/gid for $user\n";
  +my $user = 'mailfw';
  +my (undef, undef, $quid, $qgid) = getpwnam $USER or
  +      die "unable to determine uid/gid for $USER\n";
   $) = "";
   POSIX::setgid($qgid) or
         die "unable to change gid: $!\n";
  @@ -58,9 +59,15 @@
   my $plugin_loader = Qpsmtpd::TcpServer->new();
   $plugin_loader->load_plugins;
   
  -# $plugin_loader->log(LOGINFO, "Listening on port 25");
  +::log(LOGINFO,"Listening on port $PORT\n");
   
   while (1) {
  +  my $running = scalar keys %childstatus;
  +  while ($running >= $MAXCONN) { 
  +    ::log(LOGINFO,"Too many connections: $running >= $MAXCONN.  Waiting one second.");
  +    sleep(1) ;
  +    $running = scalar keys %childstatus;
  +  }
       my $hisaddr = accept(my $client, $server);
       if (!$hisaddr) {
           # possible something condition...
  @@ -68,6 +75,9 @@
       }
       my $pid = fork;
       if ($pid) {
  +        # parent
  +        $childstatus{$pid} = 1;	# add to table
  +        $running++;
           close($client);
           next;
       }
  @@ -86,6 +96,11 @@
       $ENV{TCPREMOTEIP} = inet_ntoa($iaddr);
       $ENV{TCPREMOTEHOST} = gethostbyaddr($iaddr, AF_INET) || "Unknown";
       
  +    # don't do this!
  +    #$0 = "qpsmtpd-forkserver: $ENV{TCPREMOTEIP} / $ENV{TCPREMOTEHOST}";
  +
  +    ::log(LOGINFO, "Accepted connection $running/$MAXCONN from $ENV{TCPREMOTEIP} / $ENV{TCPREMOTEHOST}");
  +    
       # dup to STDIN/STDOUT
       POSIX::dup2(fileno($client), 0);
       POSIX::dup2(fileno($client), 1);
  @@ -95,6 +110,12 @@
       $qpsmtpd->run();
   
       exit;                                   # child leaves
  +}
  +
  +sub log {
  +  my ($level,$message) = @_;
  +  # $level not used yet.  this is reimplemented from elsewhere anyway
  +  warn("$$ $message\n");
   }
   
   __END__
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.