Matt Sergeant wrote:
On 3-Oct-07, at 5:25 PM, James Turnbull wrote:

Chris Lewis wrote:
I've hacked qpsmtpd-async to support daemonization and pid locking
files.  Rather than dig into SVN, who should I send the modified copy
to?  Matt?

Chris

Since no one else answered the question I'd recommend logging a ticket
at http://code.google.com/p/smtpd/issues/list and attaching the patch there.

Sorry, yes please do that. Or just mail the patch to the list. Either works.

Sending here.  Code shamelessly stolen from qpsmtpd-forkserver

You probably won't want the first chunk. Tho, I think you need to parameterize the #! lines in the mainline scripts sooner or later.

Note that the HUNTSMAN invocation of unlink will usually fail, since the PID file is created as root before setuid'ing to the -u option (for compatibility with /var/subsys or whatever that thing is). In which case you probably want to remove the error print.
*** ../qpsmtpd-0.40/qpsmtpd-async       Wed Sep 26 15:09:15 2007
--- qpsmtpd-async.unconfig      Wed Oct  3 12:02:56 2007
***************
*** 1,6 ****
! #!/opt/NTM/bin/perl
  
  use lib "./lib";
  BEGIN {
      delete $ENV{ENV};
      delete $ENV{BASH_ENV};
--- 1,7 ----
! #!%%PERL%%
  
  use lib "./lib";
+ use lib './lib/perl5/site_perl/5.8.8';
  BEGIN {
      delete $ENV{ENV};
      delete $ENV{BASH_ENV};
***************
*** 41,46 ****
--- 42,49 ----
  my $PAUSED      = 0;
  my $NUMACCEPT   = 20;
  my $ACCEPT_RSET = Danga::Socket->AddTimer(30, \&reset_num_accept);
+ my $PID_FILE   = '';
+ my $DETACH;       # daemonize on startup
  
  # make sure we don't spend forever doing accept()
  use constant ACCEPT_MAX => 1000;
***************
*** 59,64 ****
--- 62,70 ----
   -p, --port P              : listen on a specific port; default 2525
   -u, --user U              : run as a particular user; defualt 'smtpd'
   -j, --procs J             : spawn J processes; default 1
+  -d, --detach              : detach from controlling terminal (daemonize)
+      --pid-file P          : print main servers PID to file P
+ 
   -h, --help                : this page
       --use-poll            : force use of poll() instead of epoll()/kqueue()
  EOT
***************
*** 71,76 ****
--- 77,84 ----
      'j|procs=i'             => \$PROCS,
      'd|debug+'              => \$DEBUG,
      'u|user=s'              => \$USER,
+     'pid-file=s'            => \$PID_FILE,
+     'd|detach'              => \$DETACH,
      'h|help'                => \&help,
  ) || help();
  
***************
*** 92,98 ****
--- 100,118 ----
  my $CONFIG_SERVER;
  
  my %childstatus = ();
+ if ($PID_FILE && -r $PID_FILE) {
+     open PID, "<$PID_FILE"
+       or die "open_pidfile $PID_FILE: $!\n";
+     my $running_pid = <PID> || ''; chomp $running_pid;
+     if ($running_pid =~ /^(\d+)/) {
+       if (kill 0, $running_pid) {
+           die "Found an already running qpsmtpd with pid $running_pid.\n";
+       }
+     }
+     close(PID);
+ }
  
+ 
  run_as_server();
  exit(0);
  
***************
*** 164,169 ****
--- 184,193 ----
  sub HUNTSMAN {
      $SIG{CHLD} = 'DEFAULT';
      kill 'INT' => keys %childstatus;
+     if ($PID_FILE && -e $PID_FILE) {
+         unlink $PID_FILE or ::log(LOGERROR, "unlink: $PID_FILE: $!");
+     }
+ 
      exit(0);
  }
  
***************
*** 193,198 ****
--- 217,237 ----
      IO::Handle::blocking($CONFIG_SERVER, 0);
      binmode($CONFIG_SERVER, ':raw');
  
+     if ($DETACH) {
+       open STDIN, '/dev/null' or die "/dev/null: $!";
+       open STDOUT, '>/dev/null' or die "/dev/null: $!";
+       open STDERR, '>&STDOUT' or die "open(stderr): $!";
+       defined (my $pid = fork) or die "fork: $!";
+       exit 0 if $pid;
+       POSIX::setsid or die "setsid: $!";
+     }
+ 
+     if ($PID_FILE) {
+       open PID, ">$PID_FILE" || die "$PID_FILE: $!";
+       print PID $$,"\n";
+         close PID;
+     }
+ 
      # Drop priviledges
      my (undef, undef, $quid, $qgid) = getpwnam $USER or
            die "unable to determine uid/gid for $USER\n";

Reply via email to