summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Palfrader <peter@palfrader.org>2002-07-02 23:54:20 +0000
committerPeter Palfrader <peter@palfrader.org>2002-07-02 23:54:20 +0000
commitce1c300f67781f5f7b7fb9da9e32245dca047004 (patch)
treea8b768311ae7f536327219cc4a2214d7842878d8
parentba6bde3b43fc7a057fb8d0d7752eac3745a24893 (diff)
Implemented stop and process command
Implemented detaching of daemon
-rw-r--r--TODO2
-rwxr-xr-xpingd204
2 files changed, 161 insertions, 45 deletions
diff --git a/TODO b/TODO
index 68a437c..31f3f4d 100644
--- a/TODO
+++ b/TODO
@@ -1,7 +1,5 @@
for 2.0:
make setup easy/document setup
- have reload command and send HUP
- have stop command
for later:
rotate secret
diff --git a/pingd b/pingd
index 4901063..82351c2 100755
--- a/pingd
+++ b/pingd
@@ -1,7 +1,7 @@
#!/usr/bin/perl -wT
# (c) 2002 Peter Palfrader <peter@palfrader.org>
-# $Id: pingd,v 1.11 2002/07/02 17:17:56 weasel Exp $
+# $Id: pingd,v 1.12 2002/07/02 23:54:20 weasel Exp $
#
=pod
@@ -18,6 +18,8 @@ pingd - echolot ping daemon
=item B<pingd> B<stop>
+=item B<pingd> B<process>
+
=item B<pingd> B<add> I<address> [I<address> ...]
=item B<pingd> B<set> option=value [option=value..] I<address> [I<address> ...]
@@ -54,6 +56,12 @@ Start the ping daemon.
Send the running pingd process a SIGTERM.
+=item B<process>
+
+Sends a HUP signal to the daemon which instructs it to process the commands.
+
+For other affects of sending the HUP Signal see the SIGNALS section below.
+
=item B<add> I<address> [I<address> ...]
Add I<address> to the list of remailers to query for
@@ -98,12 +106,37 @@ Verbose mode. Causes B<pingd> to print debugging messages about its progress.
Print a short help and exit sucessfully.
+=item --hup
+
+Usefull only when passwd with the B<add> or B<set> command.
+
+Sends a HUP signal to the daemon which instructs it to process the commands
+after adding the command to the task list.
+
+=item --detach
+
+Usefull only when passwd with the B<start> command.
+
+Tell B<pingd> to detach.
+
=back
=head1 FILES
F<pingd.conf>
+=head1 SIGNALS
+
+On B<SIGINT>, B<SIGQUIT>, and B<SIGTERM> B<pingd> will schedule an exist
+for after the current actions are finished or immediatly if no actions are
+currently beeing processed. It will then write all metadata and metadata to
+disk and close all files cleanly before exiting.
+
+On B<SIGHUP> <pingd> will execute any pending commands from the commands file
+(B<commands.txt> per default). It also closes and reopens the file 'output'
+which is used for stdout and stderr in case the daemon was told to detach.
+This can be used if you want to rotate that file.
+
=head1 AUTHOR
Peter Palfrader E<lt>peter@palfrader.org<gt>
@@ -139,11 +172,18 @@ delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
my $scheduler;
+my $redirected_stdio = 0;
sub setSigHandlers() {
$SIG{'HUP'} = sub {
print "Got SIGINT. scheduling readcommands\n";
$scheduler->schedule('readcommands', time() );
+ if ($redirected_stdio) {
+ close STDOUT;
+ close STDERR;
+ open (STDOUT, ">>output") or die ("Cannot open 'output' as STDOUT\n");
+ open (STDERR, ">&STDOUT") or die ("Cannot dup STDOUT as STDERR\n");
+ };
};
$SIG{'INT'} = sub {
print "Got SIGINT. scheduling exit\n";
@@ -159,6 +199,8 @@ sub setSigHandlers() {
};
};
+
+
sub commit_prospective_address() {
Echolot::Globals::get()->{'storage'}->commit_prospective_address();
};
@@ -169,69 +211,55 @@ sub expire() {
-#Echolot::Mailin::process();
-#Echolot::Pinger::send_pings();
-#Echolot::Mailin::process();
-#Echolot::Conf::send_requests();
-#Echolot::Stats::build();
-
+sub command_add(@) {
+ my @argv = @_;
-my $params;
-Getopt::Long::config('bundling');
-if (!GetOptions (
- 'help' => \$params->{'help'},
- 'verbose' => \$params->{'verbose'}
- )) {
- die ("$PROGRAM_NAME: Usage: $PROGRAM_NAME [-fwhv]\n");
-};
-if ($params->{'help'}) {
- print ("Usage: $PROGRAM_NAME [options]\n"); #FIXME
- exit 0;
-};
-
-my $COMMAND = shift @ARGV;
-die ("command required\n") unless defined $COMMAND;
-
-
-Echolot::Config::init( $params );
-chdir( Echolot::Config::get()->{'homedir'} );
-Echolot::Globals::init();
-
-
-if ($COMMAND eq 'add') {
- die ("add requires argument <address>\n") unless scalar @ARGV;
+ die ("add requires argument <address>\n") unless scalar @argv;
my @addresses;
- for my $address (@ARGV) {
+ for my $address (@argv) {
die ("argument <address> is not a valid email address\n") unless ($address =~ /^[a-zA-Z0-9+._-]+\@[a-zA-Z0-9+.-]+$/ );
push @addresses, $address;
};
for my $address (@addresses) {
Echolot::Commands::addCommand("add $address");
};
- # FIXME send hup
-} elsif ($COMMAND eq 'set') {
+};
+
+sub command_set(@) {
+ my @argv = @_;
+
my @settings;
- while (scalar @ARGV && $ARGV[0] =~ /^(showit|pingit|fetch)=(on|off)$/) {
- push @settings, $ARGV[0];
- shift @ARGV;
+ while (scalar @argv && $argv[0] =~ /^(showit|pingit|fetch)=(on|off)$/) {
+ push @settings, $argv[0];
+ shift @argv;
};
my @addresses;
- for my $address (@ARGV) {
+ for my $address (@argv) {
die ("argument $address is not a valid email address\n") unless ($address =~ /^[a-zA-Z0-9+._-]+\@[a-zA-Z0-9+.-]+$/ );
push @addresses, $address;
};
- for my $address (@ARGV) {
+ for my $address (@argv) {
for my $setting (@settings) {
Echolot::Commands::addCommand("set $address $setting");
};
};
- # FIXME send hup
-} elsif ($COMMAND eq 'stop') {
- die ("stop not implemented yet");
-} elsif ($COMMAND eq 'start') {
+};
+
+sub pid_exists() {
+ return (-e Echolot::Config::get()->{'pidfile'});
+};
+
+sub daemon_run() {
+ die ("Pidfile '".Echolot::Config::get()->{'pidfile'}."' exists\n")
+ if pid_exists();
+ open (PIDFILE, '>'.Echolot::Config::get()->{'pidfile'}) or
+ carp ("Cannot open pidfile '".Echolot::Config::get()->{'pidfile'}."': $!\n");
+ print PIDFILE "$PROCESS_ID ".Echolot::Globals::get()->{'hostname'}." ".time()."\n";
+ close PIDFILE;
+
Echolot::Globals::initStorage();
setSigHandlers();
@@ -251,6 +279,96 @@ if ($COMMAND eq 'add') {
Echolot::Globals::get()->{'storage'}->commit();
Echolot::Globals::get()->{'storage'}->finish();
+
+ unlink (Echolot::Config::get()->{'pidfile'}) or
+ cluck ("Cannot unlink pidfile ".Echolot::Config::get()->{'pidfile'});
+};
+
+sub send_sig($) {
+ my ($sig) = @_;
+
+ die ("Pidfile '".Echolot::Config::get()->{'pidfile'}."' does exist\n")
+ unless pid_exists();
+ open (PIDFILE, '<'.Echolot::Config::get()->{'pidfile'}) or
+ carp ("Cannot open pidfile '".Echolot::Config::get()->{'pidfile'}."': $!\n");
+ my $line = <PIDFILE>;
+ close PIDFILE;
+
+ my ($pid, $host, $time) = $line =~ /^(\d+) \s+ (\S+) \s+ (\d+) \s* $/x or
+ carp ("Cannot parse pidfile '$line'\n");
+ my $sent = kill $sig, $pid;
+ ($sent == 1) or
+ carp ("Did not send signal $sig to exactly one process but $sent. (pidfile reads $line)\n");
+};
+
+sub daemon_hup() {
+ send_sig(1);
+};
+
+sub daemon_stop() {
+ send_sig(15);
+};
+
+
+my $params;
+Getopt::Long::config('bundling');
+if (!GetOptions (
+ 'help' => \$params->{'help'},
+ 'verbose' => \$params->{'verbose'},
+ 'hup' => \$params->{'hup'},
+ 'detach' => \$params->{'detach'},
+ )) {
+ die ("$PROGRAM_NAME: Usage: $PROGRAM_NAME [-fwhv]\n");
+};
+if ($params->{'help'}) {
+ print ("Usage: $PROGRAM_NAME [options]\n"); #FIXME
+ exit 0;
+};
+
+my $COMMAND = shift @ARGV;
+die ("command required\n") unless defined $COMMAND;
+
+
+Echolot::Config::init( $params );
+chdir( Echolot::Config::get()->{'homedir'} );
+Echolot::Globals::init();
+
+
+if ($COMMAND eq 'add') {
+ command_add(@ARGV);
+ if ($params->{'hup'} && pid_exists()) {
+ daemon_hup()
+ } else {
+ print "Don't forget to run $PROGRAM_NAME process. You may also use --hup in the future\n";
+ };
+} elsif ($COMMAND eq 'set') {
+ command_set(@ARGV);
+ if ($params->{'hup'} && pid_exists()) {
+ daemon_hup()
+ } else {
+ print "Don't forget to run $PROGRAM_NAME process. You may also use --hup in the future\n";
+ };
+} elsif ($COMMAND eq 'process') {
+ daemon_hup();
+} elsif ($COMMAND eq 'stop') {
+ daemon_stop();
+} elsif ($COMMAND eq 'start') {
+ if ($params->{'detach'}) {
+ print "Detaching.\n";
+ unless (fork()) {
+ close STDOUT;
+ close STDERR;
+ open (STDOUT, ">>output") or die ("Cannot open 'output' as STDOUT\n");
+ open (STDERR, ">&STDOUT") or die ("Cannot dup STDOUT as STDERR\n");
+ close STDIN;
+ $redirected_stdio = 1;
+ print "Startup at ".scalar localtime()."\n";
+ daemon_run();
+ print "done.\n";
+ };
+ } else {
+ daemon_run();
+ };
} elsif ($COMMAND eq 'dumpconf') {
Echolot::Config::dump();
} elsif ($COMMAND eq 'convert') {