/[echolot]/trunk/pingd
ViewVC logotype

Contents of /trunk/pingd

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.5