| 1 |
#!/usr/bin/perl -w
|
| 2 |
|
| 3 |
$| = 1;
|
| 4 |
|
| 5 |
# (c) 2002 Peter Palfrader <peter@palfrader.org>
|
| 6 |
# $Id: pingd,v 1.61 2002/08/12 03:28:06 weasel Exp $
|
| 7 |
#
|
| 8 |
|
| 9 |
=pod
|
| 10 |
|
| 11 |
=head1 NAME
|
| 12 |
|
| 13 |
pingd - echolot ping daemon
|
| 14 |
|
| 15 |
=head1 SYNOPSIS
|
| 16 |
|
| 17 |
=over
|
| 18 |
|
| 19 |
=item B<pingd> B<start>
|
| 20 |
|
| 21 |
=item B<pingd> B<stop>
|
| 22 |
|
| 23 |
=item B<pingd> B<process>
|
| 24 |
|
| 25 |
=item B<pingd> B<add> I<address> [I<address> ...]
|
| 26 |
|
| 27 |
=item B<pingd> B<delete> I<address> [I<address> ...]
|
| 28 |
|
| 29 |
=item B<pingd> B<set> option=value [option=value..] I<address> [I<address> ...]
|
| 30 |
|
| 31 |
=item B<pingd> B<setremailercaps> I<capsstring>
|
| 32 |
|
| 33 |
=item B<pingd> B<deleteremailercaps> I<address>
|
| 34 |
|
| 35 |
=item B<pingd> B<getkeyconf> [I<address> [I<address> ...]]
|
| 36 |
|
| 37 |
=item B<pingd> B<buildstats>
|
| 38 |
|
| 39 |
=item B<pingd> B<buildkeys>
|
| 40 |
|
| 41 |
=item B<pingd> B<buildthesaurus>
|
| 42 |
|
| 43 |
=item B<pingd> B<dumpconf>
|
| 44 |
|
| 45 |
=back
|
| 46 |
|
| 47 |
=head1 DESCRIPTION
|
| 48 |
|
| 49 |
pingd is a the heart of echolot. Echolot is a pinger for anonymous remailers.
|
| 50 |
|
| 51 |
A Pinger in the context of anonymous remailers is a program that regularily
|
| 52 |
sends messages through remailers to check their reliability. It then calculates
|
| 53 |
reliability statistics which are used by remailer clients to choose the chain
|
| 54 |
of remailers to use.
|
| 55 |
|
| 56 |
Additionally it collects configuration parameters and keys of all remailers and
|
| 57 |
offers them in a format readable by remailer clients.
|
| 58 |
|
| 59 |
When called without parameters pingd schedules tasks like sending pings,
|
| 60 |
processing incoming mail and requesting remailer-xxx data and runs them in
|
| 61 |
configurable intervalls.
|
| 62 |
|
| 63 |
=head1 COMMANDS
|
| 64 |
|
| 65 |
=over
|
| 66 |
|
| 67 |
=item B<start>
|
| 68 |
|
| 69 |
Start the ping daemon.
|
| 70 |
|
| 71 |
=item B<stop>
|
| 72 |
|
| 73 |
Send the running pingd process a SIGTERM.
|
| 74 |
|
| 75 |
=item B<process>
|
| 76 |
|
| 77 |
Sends a HUP signal to the daemon which instructs it to process the commands.
|
| 78 |
|
| 79 |
For other affects of sending the HUP Signal see the SIGNALS section below.
|
| 80 |
|
| 81 |
=item B<add> I<address> [I<address> ...]
|
| 82 |
|
| 83 |
Add I<address> to the list of remailers to query for
|
| 84 |
keys and confs.
|
| 85 |
|
| 86 |
=item B<delete> I<address> [I<address> ...]
|
| 87 |
|
| 88 |
Delete I<address> from the list of remailers to query for
|
| 89 |
keys and confs. Delete all statistics and keys for that remailer.
|
| 90 |
|
| 91 |
=item B<set> option=value [option=value..] I<address> [I<address> ...]
|
| 92 |
|
| 93 |
Possible options and values:
|
| 94 |
|
| 95 |
=over
|
| 96 |
|
| 97 |
=item B<showit=>{B<on>,B<off>}
|
| 98 |
|
| 99 |
Set B<showit> (show remailer in mlist, rlist etc.) for remailer I<address> to
|
| 100 |
either B<on> or B<off>.
|
| 101 |
|
| 102 |
=item B<pingit=>{B<on>,B<off>}
|
| 103 |
|
| 104 |
Set B<pingit> (send out pings to that remailer) for remailer I<address> to
|
| 105 |
either B<on> or B<off>.
|
| 106 |
|
| 107 |
=item B<fetch=>{B<on>,B<off>}
|
| 108 |
|
| 109 |
Set B<fetch> (fetch remailer-key and remailer-conf) for remailer I<address> to
|
| 110 |
either B<on> or B<off>.
|
| 111 |
|
| 112 |
=back
|
| 113 |
|
| 114 |
=item B<setremailercaps> I<capsstring>
|
| 115 |
|
| 116 |
Some remailers (Mixmaster V2 - currently lcs and passthru2) don't return a
|
| 117 |
useable remailer-conf message. For such remailers you need to set it manually.
|
| 118 |
|
| 119 |
For instance:
|
| 120 |
|
| 121 |
./pingd setremailercaps '$remailer{"passthru2"} = "<mixer@immd1.informatik.uni-erlangen.de> mix middle";'
|
| 122 |
./pingd setremailercaps '$remailer{"lcs"} = "<mix@anon.lcs.mit.edu> mix klen1000";'
|
| 123 |
|
| 124 |
=item B<deleteremailercaps> I<address>
|
| 125 |
|
| 126 |
Delete remailer-conf data for I<address>. The config data will be reset from
|
| 127 |
the next valid remailer-conf reply by the remailer.
|
| 128 |
|
| 129 |
=item B<getkeyconf> [I<address> [I<address> ...]]
|
| 130 |
|
| 131 |
Send a command to immediatly request keys and configuration from remailers.
|
| 132 |
If no addresses are given, then requests will be sent to all remailers.
|
| 133 |
|
| 134 |
=item B<buildstats>
|
| 135 |
|
| 136 |
Send a command to immediatly rebuild stats.
|
| 137 |
|
| 138 |
=item B<buildkeys>
|
| 139 |
|
| 140 |
Send a command to immediatly rebuild the keyrings.
|
| 141 |
|
| 142 |
=item B<buildthesaurus>
|
| 143 |
|
| 144 |
Send a command to immediatly rebuild the Thesaurus.
|
| 145 |
|
| 146 |
=item B<dumpconf>
|
| 147 |
|
| 148 |
Dumps the current configuration to standard output.
|
| 149 |
|
| 150 |
=back
|
| 151 |
|
| 152 |
=head1 OPTIONS
|
| 153 |
|
| 154 |
=over
|
| 155 |
|
| 156 |
=item B<--basedir>
|
| 157 |
|
| 158 |
The home directory to which everything else is relative to. See the BASE
|
| 159 |
DIRECTORY section below.
|
| 160 |
|
| 161 |
=item B<--verbose>
|
| 162 |
|
| 163 |
Verbose mode. Causes B<pingd> to print debugging messages about its progress.
|
| 164 |
|
| 165 |
=item B<--quiet>
|
| 166 |
|
| 167 |
Quiet mode. Be even more quient than normally.
|
| 168 |
|
| 169 |
=item B<--help>
|
| 170 |
|
| 171 |
Print a short help and exit sucessfully.
|
| 172 |
|
| 173 |
=item B<--version>
|
| 174 |
|
| 175 |
Print version number and exit sucessfully.
|
| 176 |
|
| 177 |
=item B<--nohup>
|
| 178 |
|
| 179 |
Usefull only with the B<add>, B<set>, B<setremailercaps>,
|
| 180 |
B<deleteremailercaps>, B<getkeyconf>, B<buildstats>, B<buildkeys>,
|
| 181 |
or B<buildthesaurus> command.
|
| 182 |
|
| 183 |
Don't send a HUP signal to the daemon which instructs it to process the
|
| 184 |
commands after adding the command to the task list.
|
| 185 |
|
| 186 |
Per default such a signal is sent.
|
| 187 |
|
| 188 |
=item B<--process>
|
| 189 |
|
| 190 |
Usefull only with the B<start> command.
|
| 191 |
|
| 192 |
Read and process the commands file on startup.
|
| 193 |
|
| 194 |
=item B<--detach>
|
| 195 |
|
| 196 |
Usefull only with the B<start> command.
|
| 197 |
|
| 198 |
Tell B<pingd> to detach.
|
| 199 |
|
| 200 |
=back
|
| 201 |
|
| 202 |
=head1 BASE DIRECTORY
|
| 203 |
|
| 204 |
The home directory to which everything else is relative to.
|
| 205 |
|
| 206 |
Basedir defaults to whatever directory the B<pingd> binary is located. It can
|
| 207 |
get overridden by the B<ECHOLOT_HOME> environment variable which in turn is
|
| 208 |
weaker than the B<--basedir> setting.
|
| 209 |
|
| 210 |
This directory is then used to locate the configuration file B<pingd.conf> (see
|
| 211 |
FILES below).
|
| 212 |
|
| 213 |
The B<homedir> setting in B<pingd.conf> finally sets the base directory.
|
| 214 |
|
| 215 |
=head1 FILES
|
| 216 |
|
| 217 |
The configuration file is searched in those places in that order:
|
| 218 |
|
| 219 |
=over
|
| 220 |
|
| 221 |
=item the file pointed to by the B<ECHOLOT_CONF> environment variable
|
| 222 |
|
| 223 |
=item <basedir>/pingd.conf
|
| 224 |
|
| 225 |
=item $HOME/echolot/pingd.conf
|
| 226 |
|
| 227 |
=item $HOME/pingd.conf
|
| 228 |
|
| 229 |
=item $HOME/.pingd.conf
|
| 230 |
|
| 231 |
=item /etc/echolot/pingd.conf
|
| 232 |
|
| 233 |
=item /etc/pingd.conf
|
| 234 |
|
| 235 |
=back
|
| 236 |
|
| 237 |
=head1 ENVIRONMENT
|
| 238 |
|
| 239 |
=over
|
| 240 |
|
| 241 |
=item ECHOLOT_CONF echolot config file (see section FILES)
|
| 242 |
|
| 243 |
=item ECHOLOT_HOME echolot base directory (see section BASE DIRECTORY)
|
| 244 |
|
| 245 |
=back
|
| 246 |
|
| 247 |
=head1 SIGNALS
|
| 248 |
|
| 249 |
On B<SIGINT>, B<SIGQUIT>, and B<SIGTERM> B<pingd> will schedule a shutdown
|
| 250 |
for as soon as the current actions are finished or immediatly if no actions are
|
| 251 |
currently beeing processed. It will then write all metadata and pingdata to
|
| 252 |
disk and close all files cleanly before exiting.
|
| 253 |
|
| 254 |
On B<SIGHUP> <pingd> will execute any pending commands from the commands file
|
| 255 |
(B<commands.txt> per default). It also closes and reopens the file 'output'
|
| 256 |
which is used for stdout and stderr in case the daemon was told to detach.
|
| 257 |
This can be used if you want to rotate that file.
|
| 258 |
|
| 259 |
=head1 AUTHOR
|
| 260 |
|
| 261 |
Peter Palfrader E<lt>peter@palfrader.orgE<gt>
|
| 262 |
|
| 263 |
=head1 BUGS
|
| 264 |
|
| 265 |
Please report them at E<lt>URL:http://savannah.gnu.org/bugs/?group=echolotE<gt>
|
| 266 |
|
| 267 |
=cut
|
| 268 |
|
| 269 |
use strict;
|
| 270 |
use FindBin qw{ $Bin };
|
| 271 |
use lib ( $Bin, "$Bin/lib" );
|
| 272 |
use Getopt::Long;
|
| 273 |
use English;
|
| 274 |
use Carp;
|
| 275 |
use Echolot::Config;
|
| 276 |
use Echolot::Globals;
|
| 277 |
use Echolot::Storage::File;
|
| 278 |
use Echolot::Scheduler;
|
| 279 |
use Echolot::Conf;
|
| 280 |
use Echolot::Mailin;
|
| 281 |
use Echolot::Pinger;
|
| 282 |
use Echolot::Stats;
|
| 283 |
use Echolot::Commands;
|
| 284 |
use Echolot::Thesaurus;
|
| 285 |
use POSIX qw(setsid);
|
| 286 |
|
| 287 |
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
|
| 288 |
|
| 289 |
|
| 290 |
my $VERSION = '2.0beta25';
|
| 291 |
|
| 292 |
|
| 293 |
my $redirected_stdio = 0;
|
| 294 |
|
| 295 |
sub setSigHandlers() {
|
| 296 |
$SIG{'HUP'} = sub {
|
| 297 |
print "Got SIGHUP. scheduling readcommands\n";
|
| 298 |
Echolot::Globals::get()->{'scheduler'}->schedule('readcommands', time() );
|
| 299 |
if ($redirected_stdio) {
|
| 300 |
close STDOUT;
|
| 301 |
close STDERR;
|
| 302 |
open (STDOUT, ">>output") or die ("Cannot open 'output' as STDOUT\n");
|
| 303 |
open (STDERR, ">&STDOUT") or die ("Cannot dup STDOUT as STDERR\n");
|
| 304 |
};
|
| 305 |
};
|
| 306 |
$SIG{'INT'} = sub {
|
| 307 |
print "Got SIGINT. scheduling exit\n";
|
| 308 |
Echolot::Globals::get()->{'scheduler'}->schedule('exit', time() );
|
| 309 |
};
|
| 310 |
$SIG{'QUIT'} = sub {
|
| 311 |
print "Got SIGQUIT. scheduling exit\n";
|
| 312 |
Echolot::Globals::get()->{'scheduler'}->schedule('exit', time() );
|
| 313 |
};
|
| 314 |
$SIG{'TERM'} = sub {
|
| 315 |
print "Got SIGTERM. scheduling exit\n";
|
| 316 |
Echolot::Globals::get()->{'scheduler'}->schedule('exit', time() );
|
| 317 |
};
|
| 318 |
};
|
| 319 |
|
| 320 |
|
| 321 |
|
| 322 |
sub commit_prospective_address() {
|
| 323 |
Echolot::Globals::get()->{'storage'}->commit_prospective_address();
|
| 324 |
};
|
| 325 |
sub expire() {
|
| 326 |
Echolot::Globals::get()->{'storage'}->expire();
|
| 327 |
};
|
| 328 |
|
| 329 |
|
| 330 |
|
| 331 |
|
| 332 |
|
| 333 |
sub command_adddelete(@) {
|
| 334 |
my $command = shift @_;
|
| 335 |
my @argv = @_;
|
| 336 |
|
| 337 |
die ("command_adddelete requires command\n") unless defined $command;
|
| 338 |
die ("add requires argument <address>\n") unless scalar @argv;
|
| 339 |
my @addresses;
|
| 340 |
for my $address (@argv) {
|
| 341 |
die ("argument <address> is not a valid email address\n") unless ($address =~ /^[a-zA-Z0-9+._-]+\@[a-zA-Z0-9+.-]+$/ );
|
| 342 |
push @addresses, $address;
|
| 343 |
};
|
| 344 |
for my $address (@addresses) {
|
| 345 |
Echolot::Commands::addCommand("$command $address");
|
| 346 |
};
|
| 347 |
};
|
| 348 |
|
| 349 |
sub command_set(@) {
|
| 350 |
my @argv = @_;
|
| 351 |
|
| 352 |
my @settings;
|
| 353 |
while (scalar @argv && $argv[0] =~ /^(showit|pingit|fetch)=(on|off)$/) {
|
| 354 |
push @settings, $argv[0];
|
| 355 |
shift @argv;
|
| 356 |
};
|
| 357 |
|
| 358 |
my @addresses;
|
| 359 |
for my $address (@argv) {
|
| 360 |
die ("argument $address is not a valid email address\n") unless ($address =~ /^[a-zA-Z0-9+._-]+\@[a-zA-Z0-9+.-]+$/ );
|
| 361 |
push @addresses, $address;
|
| 362 |
};
|
| 363 |
|
| 364 |
for my $address (@argv) {
|
| 365 |
for my $setting (@settings) {
|
| 366 |
Echolot::Commands::addCommand("set $address $setting");
|
| 367 |
};
|
| 368 |
};
|
| 369 |
};
|
| 370 |
|
| 371 |
sub command_setremailercaps(@) {
|
| 372 |
my @argv = @_;
|
| 373 |
|
| 374 |
my @caps;
|
| 375 |
for my $caps (@argv) {
|
| 376 |
my ($remailer_nick, $remailer_address) = ($caps =~ /^\s* \$remailer{"(.*)"} \s*=\s* "<(.*@.*)>.*"; \s*$/ix);
|
| 377 |
die ("caps '$caps' is not a valid remailer caps line\n") unless (defined $remailer_nick && defined $remailer_address);
|
| 378 |
push @caps, {
|
| 379 |
address => $remailer_address,
|
| 380 |
caps => $caps };
|
| 381 |
};
|
| 382 |
for my $caps (@caps) {
|
| 383 |
Echolot::Commands::addCommand("setremailercaps ".$caps->{'address'}." ".$caps->{'caps'});
|
| 384 |
};
|
| 385 |
};
|
| 386 |
|
| 387 |
sub command_deleteremailercaps(@) {
|
| 388 |
my @argv = @_;
|
| 389 |
|
| 390 |
my @addresses;
|
| 391 |
for my $address (@argv) {
|
| 392 |
die ("argument $address is not a valid email address\n") unless ($address =~ /^[a-zA-Z0-9+._-]+\@[a-zA-Z0-9+.-]+$/ );
|
| 393 |
push @addresses, $address;
|
| 394 |
};
|
| 395 |
|
| 396 |
for my $address (@addresses) {
|
| 397 |
Echolot::Commands::addCommand("deleteremailercaps $address");
|
| 398 |
};
|
| 399 |
};
|
| 400 |
|
| 401 |
sub command_getkeyconf(@) {
|
| 402 |
my @argv = @_;
|
| 403 |
|
| 404 |
my @addresses;
|
| 405 |
for my $address (@argv) {
|
| 406 |
die ("argument $address is not a valid email address\n") unless ($address =~ /^[a-zA-Z0-9+._-]+\@[a-zA-Z0-9+.-]+$/ );
|
| 407 |
push @addresses, $address;
|
| 408 |
};
|
| 409 |
|
| 410 |
push @addresses, 'all' unless (scalar @addresses);
|
| 411 |
|
| 412 |
for my $address (@addresses) {
|
| 413 |
Echolot::Commands::addCommand("getkeyconf $address");
|
| 414 |
};
|
| 415 |
};
|
| 416 |
|
| 417 |
|
| 418 |
sub pid_exists() {
|
| 419 |
return (-e Echolot::Config::get()->{'pidfile'});
|
| 420 |
};
|
| 421 |
|
| 422 |
sub daemon_run($) {
|
| 423 |
my ($process) = @_;
|
| 424 |
|
| 425 |
die ("Pidfile '".Echolot::Config::get()->{'pidfile'}."' exists\n")
|
| 426 |
if pid_exists();
|
| 427 |
open (PIDFILE, '>'.Echolot::Config::get()->{'pidfile'}) or
|
| 428 |
confess ("Cannot open pidfile '".Echolot::Config::get()->{'pidfile'}."': $!\n");
|
| 429 |
print PIDFILE "$PROCESS_ID ".Echolot::Globals::get()->{'hostname'}." ".time()."\n";
|
| 430 |
close PIDFILE;
|
| 431 |
|
| 432 |
Echolot::Globals::initStorage();
|
| 433 |
setSigHandlers();
|
| 434 |
|
| 435 |
Echolot::Globals::get()->{'scheduler'} = new Echolot::Scheduler;
|
| 436 |
my $scheduler = Echolot::Globals::get()->{'scheduler'};
|
| 437 |
$scheduler->add('exit' , -1 , 0, 'exit' );
|
| 438 |
$scheduler->add('readcommands' , -1 , 0, \&Echolot::Commands::processCommands );
|
| 439 |
|
| 440 |
$scheduler->add('processmail' , Echolot::Config::get()->{'processmail'} , 0, \&Echolot::Mailin::process );
|
| 441 |
$scheduler->add('ping' , Echolot::Config::get()->{'pinger_interval'} , 0, \&Echolot::Pinger::send_pings );
|
| 442 |
$scheduler->add('buildstats' , Echolot::Config::get()->{'buildstats'} , 0, \&Echolot::Stats::build_stats );
|
| 443 |
$scheduler->add('buildkeys' , Echolot::Config::get()->{'buildkeys'} , 0, \&Echolot::Stats::build_keys );
|
| 444 |
$scheduler->add('buildthesaurus' , Echolot::Config::get()->{'buildthesaurus'} , 0, \&Echolot::Thesaurus::build_thesaurus );
|
| 445 |
|
| 446 |
$scheduler->add('commitprospectives' , Echolot::Config::get()->{'commitprospectives'} , 0, \&commit_prospective_address );
|
| 447 |
$scheduler->add('expire' , Echolot::Config::get()->{'expire'} , 0, \&expire );
|
| 448 |
$scheduler->add('getkeyconf' , Echolot::Config::get()->{'getkeyconf_interval'}, 0, \&Echolot::Conf::send_requests );
|
| 449 |
$scheduler->add('check_resurrection' , Echolot::Config::get()->{'check_resurrection'} , 0, \&Echolot::Conf::check_resurrection );
|
| 450 |
|
| 451 |
Echolot::Globals::get()->{'scheduler'}->schedule('readcommands', time() )
|
| 452 |
if ($process);
|
| 453 |
|
| 454 |
$scheduler->run();
|
| 455 |
|
| 456 |
Echolot::Globals::get()->{'storage'}->commit();
|
| 457 |
Echolot::Globals::get()->{'storage'}->finish();
|
| 458 |
|
| 459 |
unlink (Echolot::Config::get()->{'pidfile'}) or
|
| 460 |
cluck ("Cannot unlink pidfile ".Echolot::Config::get()->{'pidfile'});
|
| 461 |
};
|
| 462 |
|
| 463 |
sub send_sig($) {
|
| 464 |
my ($sig) = @_;
|
| 465 |
|
| 466 |
die ("Pidfile '".Echolot::Config::get()->{'pidfile'}."' does not exist\n")
|
| 467 |
unless pid_exists();
|
| 468 |
open (PIDFILE, '<'.Echolot::Config::get()->{'pidfile'}) or
|
| 469 |
confess ("Cannot open pidfile '".Echolot::Config::get()->{'pidfile'}."': $!\n");
|
| 470 |
my $line = <PIDFILE>;
|
| 471 |
close PIDFILE;
|
| 472 |
|
| 473 |
my ($pid, $host, $time) = $line =~ /^(\d+) \s+ (\S+) \s+ (\d+) \s* $/x or
|
| 474 |
confess ("Cannot parse pidfile '$line'\n");
|
| 475 |
my $sent = kill $sig, $pid;
|
| 476 |
($sent == 1) or
|
| 477 |
confess ("Did not send signal $sig to exactly one process but $sent. (pidfile reads $line)\n");
|
| 478 |
};
|
| 479 |
|
| 480 |
sub daemon_hup() {
|
| 481 |
send_sig(1);
|
| 482 |
};
|
| 483 |
|
| 484 |
sub daemon_stop() {
|
| 485 |
send_sig(15);
|
| 486 |
};
|
| 487 |
|
| 488 |
sub make_dirs() {
|
| 489 |
for my $dir (
|
| 490 |
Echolot::Config::get()->{'resultdir'},
|
| 491 |
Echolot::Config::get()->{'thesaurusdir'},
|
| 492 |
Echolot::Config::get()->{'private_resultdir'},
|
| 493 |
Echolot::Config::get()->{'gnupghome'},
|
| 494 |
Echolot::Config::get()->{'mixhome'},
|
| 495 |
Echolot::Config::get()->{'tmpdir'},
|
| 496 |
Echolot::Config::get()->{'storage'}->{'File'}->{'basedir'}
|
| 497 |
) {
|
| 498 |
if ( ! -d $dir ) {
|
| 499 |
mkdir ($dir, 0755) or
|
| 500 |
confess ("Cannot create directory $dir: $!\n");
|
| 501 |
};
|
| 502 |
};
|
| 503 |
my @dirs = (
|
| 504 |
Echolot::Config::get()->{'mailerrordir'},
|
| 505 |
Echolot::Config::get()->{'mailerrordir'}.'/cur',
|
| 506 |
Echolot::Config::get()->{'mailerrordir'}.'/tmp',
|
| 507 |
Echolot::Config::get()->{'mailerrordir'}.'/new');
|
| 508 |
push @dirs, (
|
| 509 |
Echolot::Config::get()->{'mailin'}.'/cur',
|
| 510 |
Echolot::Config::get()->{'mailin'}.'/tmp',
|
| 511 |
Echolot::Config::get()->{'mailin'}.'/new' )
|
| 512 |
if (-d Echolot::Config::get()->{'mailin'});
|
| 513 |
|
| 514 |
for my $dir (@dirs) {
|
| 515 |
if ( ! -d $dir ) {
|
| 516 |
mkdir ($dir, 0700) or
|
| 517 |
confess ("Cannot create directory $dir: $!\n");
|
| 518 |
};
|
| 519 |
};
|
| 520 |
};
|
| 521 |
|
| 522 |
sub hup_if_wanted($) {
|
| 523 |
my ($nohup) = @_;
|
| 524 |
if (!$nohup && pid_exists()) {
|
| 525 |
daemon_hup()
|
| 526 |
} else {
|
| 527 |
print "Don't forget to run $PROGRAM_NAME process.\n";
|
| 528 |
};
|
| 529 |
};
|
| 530 |
|
| 531 |
|
| 532 |
|
| 533 |
|
| 534 |
|
| 535 |
|
| 536 |
|
| 537 |
|
| 538 |
|
| 539 |
|
| 540 |
my $params = { basedir => $Bin };
|
| 541 |
$params->{'basedir'} = $ENV{'ECHOLOT_HOME'} if (defined $ENV{'ECHOLOT_HOME'});
|
| 542 |
|
| 543 |
Getopt::Long::config('bundling');
|
| 544 |
if (!GetOptions (
|
| 545 |
'help' => \$params->{'help'},
|
| 546 |
'version' => \$params->{'version'},
|
| 547 |
'verbose+' => \$params->{'verbose'},
|
| 548 |
'nohup' => \$params->{'nohup'},
|
| 549 |
'detach' => \$params->{'detach'},
|
| 550 |
'process' => \$params->{'process'},
|
| 551 |
'basedir' => \$params->{'basedir'},
|
| 552 |
'quiet' => \$params->{'quiet'},
|
| 553 |
)) {
|
| 554 |
die ("$PROGRAM_NAME: Usage: $PROGRAM_NAME [-fwhv]\n");
|
| 555 |
};
|
| 556 |
if ($params->{'help'}) {
|
| 557 |
print ("Usage: $PROGRAM_NAME [options] command\n");
|
| 558 |
print ("See man pingd or perldoc pingd for more info.\n");
|
| 559 |
print ("echolot $VERSION - (c) 2002 Peter Palfrader <peter\@palfrader.org>\n");
|
| 560 |
print ("http://savannah.gnu.org/projects/echolot/\n");
|
| 561 |
print ("\n");
|
| 562 |
print ("Commands:\n");
|
| 563 |
print (" start starts echolot pingd\n");
|
| 564 |
print (" signals pingd to ... \n");
|
| 565 |
print (" stop ... shutdown\n");
|
| 566 |
print (" process ... reopen outfile and process commands\n");
|
| 567 |
print (" add ... add a remailer address\n");
|
| 568 |
print (" delete ... delete a remailer address\n");
|
| 569 |
print (" set ... set remailer options\n");
|
| 570 |
print (" setremailercaps ... set remailer capabilities manually\n");
|
| 571 |
print (" deleteremailercaps ... delete remailer capabilities manually\n");
|
| 572 |
print (" getkeyconf ... request remailer-xxx data immediatly\n");
|
| 573 |
print (" buildstats ... build remailer stats immediatly\n");
|
| 574 |
print (" buildkeys ... buid keyrings immediatly\n");
|
| 575 |
print (" buildthesaurus ... build thesaurus immediatly\n");
|
| 576 |
print (" dumpconf dump configuration\n");
|
| 577 |
exit 0;
|
| 578 |
};
|
| 579 |
if ($params->{'version'}) {
|
| 580 |
print ("echolot $VERSION\n");
|
| 581 |
print ("(c) 2002 Peter Palfrader <peter\@palfrader.org>\n");
|
| 582 |
print ("http://savannah.gnu.org/projects/echolot/\n");
|
| 583 |
exit 0;
|
| 584 |
};
|
| 585 |
$params->{'quiet'} = undef if ($params->{'verbose'});
|
| 586 |
|
| 587 |
my $COMMAND = shift @ARGV;
|
| 588 |
die ("command required\n") unless defined $COMMAND;
|
| 589 |
|
| 590 |
|
| 591 |
Echolot::Config::init( $params );
|
| 592 |
chdir( Echolot::Config::get()->{'homedir'} );
|
| 593 |
Echolot::Globals::init( version => $VERSION);
|
| 594 |
|
| 595 |
|
| 596 |
if ($COMMAND eq 'add' || $COMMAND eq 'delete') {
|
| 597 |
command_adddelete($COMMAND, @ARGV);
|
| 598 |
hup_if_wanted($params->{'nohup'});
|
| 599 |
} elsif ($COMMAND eq 'set') {
|
| 600 |
command_set(@ARGV);
|
| 601 |
hup_if_wanted($params->{'nohup'});
|
| 602 |
} elsif ($COMMAND eq 'deleteremailercaps') {
|
| 603 |
command_deleteremailercaps(@ARGV);
|
| 604 |
hup_if_wanted($params->{'nohup'});
|
| 605 |
} elsif ($COMMAND eq 'setremailercaps') {
|
| 606 |
command_setremailercaps(@ARGV);
|
| 607 |
hup_if_wanted($params->{'nohup'});
|
| 608 |
} elsif ($COMMAND eq 'getkeyconf') {
|
| 609 |
command_getkeyconf(@ARGV);
|
| 610 |
hup_if_wanted($params->{'nohup'});
|
| 611 |
} elsif ($COMMAND eq 'buildstats') {
|
| 612 |
Echolot::Commands::addCommand("buildstats");
|
| 613 |
hup_if_wanted($params->{'nohup'});
|
| 614 |
} elsif ($COMMAND eq 'buildkeys') {
|
| 615 |
Echolot::Commands::addCommand("buildkeys");
|
| 616 |
hup_if_wanted($params->{'nohup'});
|
| 617 |
} elsif ($COMMAND eq 'buildthesaurus') {
|
| 618 |
Echolot::Commands::addCommand("buildthesaurus");
|
| 619 |
hup_if_wanted($params->{'nohup'});
|
| 620 |
} elsif ($COMMAND eq 'process') {
|
| 621 |
daemon_hup();
|
| 622 |
} elsif ($COMMAND eq 'stop') {
|
| 623 |
daemon_stop();
|
| 624 |
} elsif ($COMMAND eq 'start') {
|
| 625 |
die ("Pidfile '".Echolot::Config::get()->{'pidfile'}."' exists\n")
|
| 626 |
if pid_exists();
|
| 627 |
make_dirs();
|
| 628 |
if ($params->{'detach'}) {
|
| 629 |
print "Detaching.\n" unless ($params->{'quiet'});
|
| 630 |
exit(0) if (fork());
|
| 631 |
POSIX::setsid();
|
| 632 |
exit(0) if (fork());
|
| 633 |
close STDOUT;
|
| 634 |
close STDERR;
|
| 635 |
open (STDOUT, ">>output") or die ("Cannot open 'output' as STDOUT\n");
|
| 636 |
open (STDERR, ">&STDOUT") or die ("Cannot dup STDOUT as STDERR\n");
|
| 637 |
close STDIN;
|
| 638 |
$redirected_stdio = 1;
|
| 639 |
print "Startup at ".scalar localtime().".\n";
|
| 640 |
daemon_run( $params->{'process'} );
|
| 641 |
print "done at ".scalar localtime().".\n";
|
| 642 |
} else {
|
| 643 |
daemon_run( $params->{'process'} );
|
| 644 |
};
|
| 645 |
} elsif ($COMMAND eq 'dumpconf') {
|
| 646 |
Echolot::Config::dump();
|
| 647 |
} elsif ($COMMAND eq 'convert') {
|
| 648 |
Echolot::Globals::initStorage();
|
| 649 |
setSigHandlers();
|
| 650 |
|
| 651 |
Echolot::Globals::get()->{'storage'}->convert();
|
| 652 |
|
| 653 |
Echolot::Globals::get()->{'storage'}->commit();
|
| 654 |
Echolot::Globals::get()->{'storage'}->finish();
|
| 655 |
} else {
|
| 656 |
die ("Command $COMMAND unknown");
|
| 657 |
};
|
| 658 |
|
| 659 |
exit 0;
|
| 660 |
|
| 661 |
# vim: set ts=4 shiftwidth=4:
|