Initial revision

This commit is contained in:
Evgeniy Kozhuhovskiy
2004-12-30 16:00:36 +00:00
commit 69f117bf78
169 changed files with 50779 additions and 0 deletions
+19
View File
@@ -0,0 +1,19 @@
Данный скрипт предназначен для генерации статистики о работе мейлера
binkleyforce путём анализа создаваемого им файла истории сессий (параметр
`history_file' в bforce.conf). Статистика генерится за предыдущие сутки от
момента запуска скрипта и постится в заданную ньюсгруппу. Доступны два типа
статистики.
Перед первым запуском рекомендуется изменить значение конфигурационных
переменных -- они находятся в начале скрипта.
Известные баги:
1. Hе учитывается случай, когда файл истории сессий повёрнут
logrotate'ом (может потеряться часть статистики)
2. Hеправильно считает cps (завышает), если трафик в обе стороны
Автор скрипта: Serge N. Pokhodyaev, 2:5020/1838, <snp@ru.ru>
Распространяется под GNU GPL.
+575
View File
@@ -0,0 +1,575 @@
#!/usr/bin/perl
#
# bfha -- binkleyforce history analyzer
#
# Copyright (C) 2000 Serge N. Pokhodyaev
#
# E-mail: snp@ru.ru
# Fido: 2:5020/1838
#
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
#
# $Id$
#
#
# çÅÎÅÒÉÔ ÓÔÁÔÉÓÔÉËÕ ÚÁ ÐÒÅÄÙÄÕÝÉÊ ÄÅÎØ
#
#
# TODO:
#
# 1. õÞÅÓÔØ ÓÌÕÞÁÊ, ËÏÇÄÁ ÌÏÇ ÐÏ×£ÒÎÕÔ logrotate'ÏÍ
#
# Known bugs:
#
# 1. HÅÐÒÁ×ÉÌØÎÏ ÓÞÉÔÁÅÔ cps (ÚÁ×ÙÛÁÅÔ) ÅÓÌÉ ÔÒÁÆÉË × ÏÂÅ ÓÔÏÒÏÎÙ
#
use strict;
use Time::Local;
use POSIX qw(strftime);
my $PROGNAME = 'bfha';
my $VERSION = '$Revision$ ';
######## Configurable part ###################################################
my $inews = "/usr/bin/inews -h -O -S";
my $log = "/var/spool/fido/history";
my $rep_newsgroups = "ftn.1838.stat";
my $rep_from = "\"Statistics generator\" <snp\@gloom.intra.eu.org>";
my $rep1_subj = "Sessions history";
my $rep2_subj = "Sessions history";
my $rep3_subj = "Links statistics";
my $count_failed = 1;
#my %line_names = (
# "ttyS1" => "Modem",
# "tcpip" => "IP"
#);
##############################################################################
my $devel = 0;
my (%st, %lines, %nodes, @nodes_sorted);
my @tm;
my $time;
die "Usage: $PROGNAME [-d]\n" if (!((0 == $#ARGV) && ($ARGV[0] eq '-d')) && !(-1 == $#ARGV));
$devel = 1 if ((0 == $#ARGV) && ($ARGV[0] eq '-d'));
$log = "./history" if ($devel);
# Make version string
#
$VERSION =~ s/(\$Rev)ision:\s([\d.]+).*/$PROGNAME\/$2/;
# Get time of 0:00:00 of yesterday
#
@tm = localtime(time - 86400);
$tm[0] = 0; # sec
$tm[1] = 0; # min
$tm[2] = 0; # hours
$time = timelocal(@tm);
# At first read logs
#
undef %st;
undef %lines;
undef %nodes;
die "Log reading error\n" if (0 != log_read($time));
@nodes_sorted = sort(node_cmp keys(%nodes));
# Now generate statistics
#
out_close();
#rep1();
rep2();
rep3();
sub log_read
{
my $i;
my $t;
my @l;
die if (0 != $#_);
$t = $_[0];
open(LOG, "< $log") || die("Can't open $log: $!\n");
while (<LOG>)
{
chomp;
@l = split(/,/);
return 1 if ($#l != 11);
return 1 if (! ($l[4] =~ /[IO]/));
# Check date
#
next if ($l[2] < $t);
last if ($l[2] >= ($t + 86400));
# Entries without address
#
if ($l[1] eq '')
{
next if (0 == $count_failed);
$l[1] = 'failed' if (0 != $count_failed);
}
# Remove domain
#
$l[1] =~ s/@.*$//;
# Add statistics
#
$i = $#{$st{beg}} + 1;
$lines{$l[0]}[$#{$lines{$l[0]}} + 1] = $i;
$nodes{$l[1]}[$#{$nodes{$l[1]}} + 1] = $i;
$st{beg}[$i] = $l[2];
$st{len}[$i] = $l[3];
$st{addr}[$i] = $l[1];
$st{line}[$i] = $l[0];
$st{rc}[$i] = $l[5];
$st{snt_nm}[$i] = $l[6];
$st{snt_am}[$i] = $l[7];
$st{snt_f}[$i] = $l[8];
$st{rcv_nm}[$i] = $l[9];
$st{rcv_am}[$i] = $l[10];
$st{rcv_f}[$i] = $l[11];
$st{islst}[$i] = 0;
$st{islst}[$i] = 1 if ($l[4] =~ /L/);
$st{isprot}[$i] = 0;
$st{isprot}[$i] = 1 if ($l[4] =~ /P/);
$st{type}[$i] = 'I' if ($l[4] =~ /I/);
$st{type}[$i] = 'O' if ($l[4] =~ /O/);
}
}
######## rep1 ################################################################
sub rep1
{
my ($i, $j);
my (%se, %se_t);
my $node;
out_open($rep1_subj);
printf "Date: %s\n\n", strftime("%a, %e %b %Y", localtime($time));
$~ = "rep1_header";
write;
$~ = "rep1_body";
$se_t{num_in} = 0;
$se_t{num_out} = 0;
$se_t{snt} = 0;
$se_t{rcv} = 0;
$se_t{len} = 0;
foreach $node (@nodes_sorted)
{
$se{num_in} = 0;
$se{num_out} = 0;
$se{snt} = 0;
$se{rcv} = 0;
$se{len} = 0;
for ($i = 0; $i <= $#{$nodes{$node}}; ++$i)
{
$j = $nodes{$node}[$i];
++$se{num_in} if ($st{type}[$j] eq 'I');
++$se{num_out} if ($st{type}[$j] eq 'O');
$se{snt} += $st{snt_am}[$j] + $st{snt_nm}[$j] + $st{snt_f}[$j];
$se{rcv} += $st{rcv_am}[$j] + $st{rcv_nm}[$j] + $st{rcv_f}[$j];
$se{len} += $st{len}[$j];
}
$se{time} = time_int2str($se{len});
# FIXME (cps)
$se{cps} = div_int(($se{snt} + $se{rcv}), $se{len});
write;
$se_t{num_in} += $se{num_in};
$se_t{num_out} += $se{num_out};
$se_t{snt} += $se{snt};
$se_t{rcv} += $se{rcv};
$se_t{len} += $se{len};
}
$~ = "rep1_footer";
$se_t{time} = time_int2str($se_t{len});
# FIXME (cps)
$se_t{cps} = div_int(($se_t{snt} + $se_t{rcv}), $se_t{len});
write;
print "\n";
out_close();
format rep1_header =
¥                 ¶          ¶           ¶            ¶           ¶       ¨
¡ System Sessions Sent Received Time CPS ¡
¡ address in out bytes bytes online ¡
±                 ¼          ¼           ¼            ¼           ¼       µ
.
format rep1_body =
¡ @<<<<<<<<<<<<<< @>> @>> @>>>>>>>> @>>>>>>>>> @>>>>>>>> @>>>> ¡
$node, $se{num_in}, $se{num_out}, $se{snt}, $se{rcv}, $se{time}, $se{cps}
.
format rep1_footer =
°€€€€€€€€€€€€€€€€€Š€€€€€€€€€€Š€€€€€€€€€€€Š€€€€€€€€€€€€Š€€€€€€€€€€€Š€€€€€€€´
¡ TOTAL @>> @>> @>>>>>>>> @>>>>>>>>> @>>>>>>>> @>>>> ¡
$se_t{num_in}, $se_t{num_out}, $se_t{snt}, $se_t{rcv}, $se_t{time}, $se_t{cps}
«                 ¹          ¹           ¹            ¹           ¹       ®
.
}
######## rep2 ################################################################
sub rep2
{
my ($i, $j);
my @t;
my ($t1, $t2, $str, $lv);
my $node;
my %se;
out_open($rep2_subj);
printf "Date: %s\n\n", strftime("%a, %e %b %Y", localtime($time));
$~ = "rep2_header";
write;
$~ = "rep2_body";
foreach $node (@nodes_sorted)
{
$se{snt} = 0;
$se{rcv} = 0;
$se{len} = 0;
for ($i = 0; $i <= 95; ++$i)
{
$t[$i] = 0;
}
for ($i = 0; $i <= $#{$nodes{$node}}; ++$i)
{
$j = $nodes{$node}[$i];
# Fill array
#
$t1 = $st{beg}[$j] - $time;
$t2 = $t1 + $st{len}[$j];
$t2 = 86399 if ($t2 > 86399);
$t1 = div_int($t1, 900);
$t2 = div_int($t2, 900);
while ($t1 <= $t2)
{
$t[$t1++] = 1;
}
$se{snt} += $st{snt_am}[$j] + $st{snt_nm}[$j] + $st{snt_f}[$j];
$se{rcv} += $st{rcv_am}[$j] + $st{rcv_nm}[$j] + $st{rcv_f}[$j];
$se{len} += $st{len}[$j];
}
$se{time} = time_int2str($se{len});
# FIXME (cps)
$se{cps} = div_int(($se{snt} + $se{rcv}), $se{len});
# Visualize
#
$i = 0;
$str = "";
if ($t[$i++])
{
$str = $str . "";
}
else
{
$str = $str . "";
}
while ($i < $#t)
{
$lv = 0;
$lv += 1 if ($t[$i++]);
$lv += 2 if ($t[$i++]);
if (0 == $lv)
{
if (div_rest(($i - 1), 8) == 0)
{
$str = $str . "";
}
else
{
$str = $str . " ";
}
}
elsif (1 == $lv)
{
$str = $str . "Ž";
}
elsif (2 == $lv)
{
$str = $str . "";
}
elsif (3 == $lv)
{
$str = $str . "";
}
}
if ($t[$i])
{
$str = $str . "Ž";
}
else
{
$str = $str . "";
}
write;
}
$~ = "rep2_footer";
write;
out_close();
format rep2_header =
0 2 4 6 8 10 12 14 16 18 20 22 24
†€‰€Š€‰€Š€‰€Š€‰€Š€‰€Š€‰€Š€‰€Š€‰€Š€‰€Š€‰€Š€‰€Š€‰€‡
.
format rep2_body =
@<<<<<<<<<<<<<<@||||||||||||||||||||||||||||||||||||||||||||||||
$node, $str
.
format rep2_footer =
†€ˆ€Š€ˆ€Š€ˆ€Š€ˆ€Š€ˆ€Š€ˆ€Š€ˆ€Š€ˆ€Š€ˆ€Š€ˆ€Š€ˆ€Š€ˆ€‡
0 2 4 6 8 10 12 14 16 18 20 22 24
.
}
######## rep3 ################################################################
sub rep3
{
my $node;
my (%se, %se_t);
my ($i, $j);
out_open($rep3_subj);
printf "Date: %s\n\n", strftime("%a, %e %b %Y", localtime($time));
$~ = "rep3_header";
write;
$~ = "rep3_body";
$se_t{num_in} = 0;
$se_t{num_out} = 0;
$se_t{time_in} = 0;
$se_t{time_out} = 0;
$se_t{snt} = 0;
$se_t{rcv} = 0;
$se_t{time} = 0;
foreach $node (@nodes_sorted)
{
$se{num_in} = 0;
$se{num_out} = 0;
$se{time_in} = 0;
$se{time_out} = 0;
$se{snt} = 0;
$se{rcv} = 0;
$se{time} = 0;
for ($i = 0; $i <= $#{$nodes{$node}}; ++$i)
{
$j = $nodes{$node}[$i];
++$se{num_in} if ($st{type}[$j] eq 'I');
++$se{num_out} if ($st{type}[$j] eq 'O');
$se{time_in} += $st{len}[$j] if ($st{type}[$j] eq 'I');
$se{time_out} += $st{len}[$j] if ($st{type}[$j] eq 'O');
$se{snt} += $st{snt_am}[$j] + $st{snt_nm}[$j] + $st{snt_f}[$j];
$se{rcv} += $st{rcv_am}[$j] + $st{rcv_nm}[$j] + $st{rcv_f}[$j];
$se{time} += $st{len}[$j];
}
# Total counters
#
$se_t{num_in} += $se{num_in};
$se_t{num_out} += $se{num_out};
$se_t{snt} += $se{snt};
$se_t{rcv} += $se{rcv};
$se_t{time} += $se{time};
$se_t{time_out} += $se{time_out};
$se_t{time_in} += $se{time_in};
# Output string
#
# FIXME (cps)
$se{cps} = dash_if_zero(div_int(($se{snt} + $se{rcv}), $se{time}));
$se{time} = time_int2str($se{time});
$se{time_in} = time_int2str($se{time_in});
$se{time_out} = time_int2str($se{time_out});
$se{num_in} = dash_if_zero($se{num_in});
$se{num_out} = dash_if_zero($se{num_out});
$se{rcv} = shrink_size(dash_if_zero($se{rcv}));
$se{snt} = shrink_size(dash_if_zero($se{snt}));
write;
}
$~ = "rep3_footer";
# FIXME (cps)
$se_t{cps} = dash_if_zero(div_int(($se_t{snt} + $se_t{rcv}), $se_t{time}));
$se_t{time} = time_int2str($se_t{time});
$se_t{time_in} = time_int2str($se_t{time_in});
$se_t{time_out} = time_int2str($se_t{time_out});
$se_t{num_in} = dash_if_zero($se_t{num_in});
$se_t{num_out} = dash_if_zero($se_t{num_out});
$se_t{rcv} = shrink_size(dash_if_zero($se_t{rcv}));
$se_t{snt} = shrink_size(dash_if_zero($se_t{snt}));
$~ = "rep3_footer";
write;
print "\n";
out_close();
format rep3_header =
¥                ¸                           ¸          ¸             ¸       ¨
¡ ¡ Sessions/Online ¡ Time ¡ Traffic ¡ ¡
¡ Address ±             ¸             µ online ±      ¸      µ CPS ¡
¡ ¡ Incoming ¡ Outgoing ¡ ¡ Rcvd ¡ Sent ¡ ¡
±                ¾   ¶         ¾   ¶         ¾          ¾      ¾      ¾       µ
.
format rep3_body =
¡ @<<<<<<<<<<<<<<¡@>>@>>>>>>> ¡@>>@>>>>>>> ¡@>>>>>>>> ¡@>>>>>¡@>>>>>¡@>>>>> ¡
$node, $se{num_in}, $se{time_in}, $se{num_out}, $se{time_out}, $se{time}, $se{rcv}, $se{snt}, $se{cps}
.
format rep3_footer =
°€€€€€€€€€€€€€€€€½€€€Š€€€€€€€€€½€€€Š€€€€€€€€€½€€€€€€€€€€½€€€€€€½€€€€€€½€€€€€€€´
¡ TOTAL ¡@>>@>>>>>>> ¡@>>@>>>>>>> ¡@>>>>>>>> ¡@>>>>>¡@>>>>>¡@>>>>> ¡
$se_t{num_in}, $se_t{time_in}, $se_t{num_out}, $se_t{time_out}, $se_t{time}, $se_t{rcv}, $se_t{snt}, $se_t{cps}
«                »   ¹         »   ¹         »          »      »      »       ®
.
}
##############################################################################
sub shrink_size
{
die if (0 != $#_);
return $_[0] if ($_[0] < 1024);
return sprintf("%.1fk", $_[0] / 1024) if ($_[0] < 1048576);
return sprintf("%.1fM", $_[0] / 1048576);
}
sub dash_if_zero
{
die if (0 != $#_);
return "-" if (0 == $_[0]);
return $_[0];
}
sub time_int2str
{
my $time;
my $h;
my $m;
my $s;
die if (0 != $#_);
die if (86399 < $time);
return "-:--:--" if (0 == $_[0]);
$time = $_[0];
$h = div_int($time, 3600);
$time = div_rest($time, 3600);
$m = div_int($time, 60);
$s = div_rest($time, 60);
return sprintf("%d:%2.2d:%2.2d", $h, $m, $s);
}
# ãÅÌÏÞÉÓÌÅÎÎÏÅ ÄÅÌÅÎÉÅ
sub div_int
{
use integer;
die if (1 != $#_);
return 0 if ($_[1] == 0);
return $_[0] / $_[1];
}
# ïÓÔÁÔÏË ÏÔ ÃÅÌÏÞÉÓÌÅÎÎÏÇÏ ÄÅÌÅÎÉÑ
sub div_rest
{
die if (1 != $#_);
return 0 if ($_[1] == 0);
return $_[0] - (div_int($_[0], $_[1]) * $_[1]);
}
sub out_open
{
die if (0 != $#_);
open(STDOUT, "| $inews") || die("Can't pipe to inews: $!\n") if (! $devel);
printf "Newsgroups: %s\n", $rep_newsgroups;
printf "From: %s\n", $rep_from;
printf "Subject: %s\n", $_[0];
printf "X-FTN-Tearline: %s\n\n", $VERSION;
}
sub out_close
{
close(STDOUT) if (! $devel);
}
sub node_cmp
{
my (@na, @nb);
@na = split('[:/.]', $::a);
@nb = split('[:/.]', $::b);
# zone
return -1 if ($na[0] < $nb[0]);
return 1 if ($na[0] > $nb[0]);
# net
return -1 if ($na[1] < $nb[1]);
return 1 if ($na[1] > $nb[1]);
# node
return -1 if ($na[2] < $nb[2]);
return 1 if ($na[2] > $nb[2]);
#point
return -1 if ($na[3] < $nb[3]);
return 1 if ($na[3] > $nb[3]);
return 0;
}
+384
View File
@@ -0,0 +1,384 @@
#!/usr/bin/perl
#
# It is a log file analyser for 'binkleyforce' mailer.
#
# Copyright (c) 1998-99 by Alexander Belkin
#
# $Id$:
#
# If you have any questions, suggestions or wishes, feel free to contact
# with me. My address: 2:5020/1398.11@fidonet
#
# To post into news, use bflan |inews -h -O -S
$program_name = "bforce-lan v1.0/Perl/Linux";
$station_name = "My Station";
$log_file = "/var/log/bforce/bf-log.ttyS0";
$news_header = "From: Statistic Robot <postmaster\@fido.xxx.local>\n".
"Newsgroups: junk\n".
"Subject: Sessions statistic.\n";
#main
#{
if( &ReadLog($log_file) == 0 )
{
print $news_header;
print "\n";
print "\"$system_name\" statistic from <$TimeFirst> to <$TimeLast>\n";
print "\n";
&TotalStatistic();
print "\n";
&SessionsStatistic();
}
exit(0);
#}
sub ReadLog
{
my($start);
if( open( FLOG, $_[0] ) == 0 )
{
print "Can't open log \"$_[0]\": $!\n";
return 1;
}
$start = 0;
$cnt = 0;
$TimeFirst = "";
$TimeLast = "";
# Read in information from logfile
while( <FLOG> )
{
chomp;
( $Mon, $Day, $Time, $Pid, $Text ) = split( /[ \t]+/, $_, 5 );
if( $TimeFirst eq "" )
{
$TimeFirst = "$Mon $Day $Time";
}
if( $start == 0 )
{
if( !defined($Connect[$cnt]) )
{
$Address[$cnt] = "";
$Connect[$cnt] = "?????";
$InFiles[$cnt] = 0;
$OutFiles[$cnt] = 0;
$InBytes[$cnt] = 0;
$OutBytes[$cnt] = 0;
$Status[$cnt] = "U";
$Success[$cnt] = " ";
}
if( $Text =~ /^calling/ )
{
$Text =~ /^calling ([\d:\/.]+)/;
$PidsCall{$Pid} = $1;
$Calls{$1} = 0 if (!defined( $Calls{$1} ));
$Calls{$1}++;
}
elsif( $Text =~ /^connect/ )
{
$Text =~ /^connect "\D*(\d+).*$/;
$Connect[$cnt] = $1;
}
elsif( $Text =~ /^TCP\/IP connect/ )
{
$Connect[$cnt] = "TCPIP";
}
elsif( $Text =~ /^outbound (\S+) session/ )
{
$start = 1;
$Time =~ /^(..):(..):(..)$/;
$Start[$cnt] = ( $1 * 60 + $2 ) * 60 + $3;
$Direction[$cnt] = "O";
$Address[$cnt] = $PidsCall{$Pid};
$MySexyPid = $Pid;
next;
}
elsif( $Text =~ /^inbound (\S+) session/ )
{
$start = 1;
$Time =~ /^(..):(..):(..)$/;
$Start[$cnt] = ( $1 * 60 + $2 ) * 60 + $3;
$Direction[$cnt] = "I";
# $kAddress[$cnt] = $PidsCall{$Pid} if( defined($PidsCall{$Pid}) );
$MySexyPid = $Pid;
next;
}
next;
}
if( ($start == 1) && ($Pid eq $MySexyPid) )
{
if( $Text =~ /^remote is password protected system/ )
{
$Status[$cnt] = "P";
}
elsif( $Text =~ /^remote is listed system/ )
{
$Status[$cnt] = "L";
}
elsif( $Text =~ /^remote is unlisted system/ )
{
$Status[$cnt] = "U";
}
elsif( $Text =~ /^[ \t]*Address :/ )
{
next if( $Address[$cnt] ne "" );
$Text =~ /^.+:[ \t]+([\d:.\/]+).*$/;
$Address[$cnt] = $1;
}
elsif( $Text =~ /^rcvd: \".+\" \d+/ )
{
$Text =~ /^rcvd: \".+\" (\d+)/;
$InBytes[$cnt] += $1;
$InFiles[$cnt] ++;
}
elsif( $Text =~ /^sent: \".+\" \d+/ )
{
$Text =~ /^sent: \".+\" (\d+)/;
$OutBytes[$cnt] += $1;
$OutFiles[$cnt] ++;
}
elsif( $Text =~ /^session rc = \d+/ )
{
$Text =~ /^session rc = (\d+)/;
if( $1 != 0 )
{
$Success[$cnt] = "A";
}
$Time =~ /^(..):(..):(..)$/;
$Finish[$cnt] = ( $1 * 60 + $2 ) * 60 + $3;
$OnLine[$cnt] = $Finish[$cnt] - $Start[$cnt];
$OnLine[$cnt] += 86400 if(( $Finish[$cnt] - $Start[$cnt] ) < 0 );
$start = 0;
$cnt++;
}
}
# got another PID!
elsif( $Text =~ /^connect \".+\"/
|| $Text =~ /^inbound (\S+) session/
|| $Text =~ /^outbound (\S+) session/ )
{
# Possible there was incorrectly terminated session
# due to mailer crash or killing, so getting this string
# can mean that we need to break reading session statistic?
# But we can also get it if log file used not only by one
# mailer at the same time, so.. ignore :)
}
} # end of while( <FLOG> )
close(FLOG);
$TimeLast = "$Mon $Day $Time" if( $Mon && $Day && $Time );
}
sub SessionsStatistic
{
local ($addr, $start, $finish, $online, $ibyte, $obyte, $cps, $speed);
my ($i);
$~ = HEADER;
write;
$~ = EACH;
for ($i = 0; $i < $cnt; $i++)
{
$addr = $Address[$i];
$stat = "$Direction[$i]$Status[$i]$Success[$i]";
$start = sec2str($Start[$i], "short");
$finish = sec2str($Finish[$i], "short");
$online = sec2str($OnLine[$i], "long");
$ibyte = $InBytes[$i];
$in = $InFiles[$i];
$obyte = $OutBytes[$i];
$on = $OutFiles[$i];
$cps = int( ($ibyte + $obyte) / $OnLine[$i] ) if ($OnLine[$i] > 0);
$speed = $Connect[$i];
$ibyte = num2siz( $ibyte );
$obyte = num2siz( $obyte );
write;
}
$~ = FOOTER;
write;
}
sub TotalStatistic
{
undef( %hSystems );
undef( %hCalls );
undef( %hTimes );
undef( %hSessions );
undef( %hInBytes );
undef( %hOutBytes );
undef( %hInFiles );
undef( %hOutFiles );
local($cal, $ses, $time, $ibyte, $obyte, $inum, $onum, $icps, $ocps);
local($acal, $ases, $atime, $aibyte, $aobyte, $ainum, $aonum, $aicps, $aocps);
local($sys);
my($i);
$acal = 0;
$ases = 0;
$atime = 0;
$aibyte = 0;
$aobyte = 0;
$ainum = 0;
$aonum = 0;
$aicps = 0;
$aocps = 0;
for( $i = 0; $i < $cnt; $i++ )
{
$sys = $Address[$i];
if( !defined($hSystems{$sys}) )
{
$hSystems{$sys} = 1;
$hCalls{$sys} = $Calls{$sys}; $Calls{$sys} = 0;
$hTimes{$sys} = 0;
$hSessions{$sys} = 0;
$hInBytes{$sys} = 0;
$hOutBytes{$sys} = 0;
$hInFiles{$sys} = 0;
$hOutFiles{$sys} = 0;
}
$hTimes{$sys} += $OnLine[$i];
$hSessions{$sys} += 1;
$hInBytes{$sys} += $InBytes[$i];
$hOutBytes{$sys} += $OutBytes[$i];
$hInFiles{$sys} += $InFiles[$i];
$hOutFiles{$sys} += $OutFiles[$i];
}
@Syst = sort( keys( %hSystems ));
$~ = hHEADER;
write;
$~ = hEACH;
for( $i = 0; $i <= $#Syst; $i++ )
{
$sys = $Syst[$i];
$cal = ( $hCalls{$sys} || 0 ); $acal += $cal;
$ses = $hSessions{$sys}; $ases += $ses;
$time = sec2str($hTimes{$sys}, "long"); $atime += $hTimes{$sys};
$ibyte = $hInBytes{$sys}; $aibyte += $ibyte;
$obyte = $hOutBytes{$sys}; $aobyte += $obyte;
$inum = $hInFiles{$sys}; $ainum += $inum;
$onum = $hOutFiles{$sys}; $aonum += $onum;
if( $hInFiles{$sys} > 0 || $hOutFiles{$sys} > 0 )
{
$cps = int( ($hInBytes{$sys} + $hOutBytes{$sys}) / $hTimes{$sys} );
$acps += $cps;
$sess++;
}
else
{
$cps = 0;
}
write;
}
# Now, draw systems without sessions ..
@Syst = sort( keys( %Calls ));
$ses = "-";
$time = "-";
$ibyte = "-";
$obyte = "-";
$inum = "-";
$onum = "-";
$cps = "-";
for( $i = 0; $i <= $#Syst; $i++ )
{
$sys = $Syst[$i];
if( $Calls{$sys} )
{
$sys = $Syst[$i];
$cal = $Calls{$sys}; $acal += $cal;
write;
}
}
$atime = sec2str($atime, "long");
if( $sess > 0 )
{
$acps = int( $acps / $sess );
}
else
{
$acps = 0;
}
$~ = hFOOTER;
write;
}
sub num2siz
{
my($num) = $_[0];
my($siz);
if($num < 1000) {
$siz = $num.' ';
} elsif($num < 10000000) {
$siz = int($num/1024).'k';
} else {
$siz = int($num/(1024*1024)).'M';
}
return $siz;
}
sub sec2str
{
my($sec) = $_[0];
my($tip) = $_[1];
my ($h, $m, $s);
$h = int( $sec / 3600 );
$m = int( ($sec - $h*3600) / 60);
$s = int( $sec % 60 );
if( $tip =~ /short/ ) {
return sprintf("%02d:%02d", $h, $m);
} elsif( $tip =~ /long/ ) {
return sprintf("%03d:%02d:%02d", $h, $m, $s);
}
}
format HEADER =
ª”” Call : 'I' - Incoming, 'O' - Outgoing
ƒª” Status : 'U' - Unlisted, 'L' - Listed, 'P' - Protected
ƒƒª Session : ' ' - Success, 'A' - Aborted
¥¡¡¡¡¡¡¡ˆ
ƒ Time ƒStaƒ FTN ƒ On-Line ƒ Incoming ƒ Outgoing ƒ Avg.ƒSpeedƒ
ƒhh:mm-hh:mmƒtusƒ Address ƒhhh:mm:ssƒ Bytesƒ N ƒ Bytesƒ N ƒ CPS ƒ ƒ
¨¨¨¨¨¨¨¨¨
.
format EACH =
ƒ@<<<<-@<<<<ƒ@<<ƒ@<<<<<<<<<<<<<<ƒ@>>>>>>>>ƒ@>>>>>ƒ@>>ƒ@>>>>>ƒ@>>ƒ@>>>>ƒ@>>>>ƒ
$start,$finish,$stat,$addr, $online, $ibyte, $in,$obyte, $on,$cps, $speed
.
format FOOTER =
¤ŸŸŸŸŸŸŸŸŸŽ
@>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
$Version
.
format hHEADER =
¥¡¡¡¡¡ˆ
ƒ FTN ƒ Total ƒ Time ƒ Incoming ƒ Outgoing ƒ CPS ƒ
ƒ Address ƒCal.ƒSes.ƒ On-Line ƒ Bytes ƒ NN ƒ Bytes ƒ NN ƒ ƒ
¨¨¨¨¨¨¨¨
.
format hEACH =
ƒ@<<<<<<<<<<<<<<ƒ@>>>ƒ@>>>ƒ@||||||||ƒ@>>>>>>>>ƒ@>>>ƒ@>>>>>>>>ƒ@>>>ƒ@>>>>ƒ
$sys, $cal,$ses,$time, $ibyte, $inum,$obyte, $onum,$cps
.
format hFOOTER =
“”””””””””””””””•””””•””””•”””””””””•”””””””””•””””•”””””””””•””””•”””””„
ƒ TOTAL ƒ@>>>ƒ@>>>ƒ@||||||||ƒ@>>>>>>>>ƒ@>>>ƒ@>>>>>>>>ƒ@>>>ƒ@>>>>ƒ
$acal,$ases,$atime, $aibyte, $ainum,$aobyte,$aonum,$acps
¤ŸŸŸŸŸŸŸŸŽ
@>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
$Version
.
+229
View File
@@ -0,0 +1,229 @@
#!/bin/sh
Ver=1.1h
# óËÒÉÐÔ ÄÌÑ ÐÒÏÚ×ÏÎËÉ ÎÁ ÁÐÌÉÎËÏ×
# ðÒÏ ×ÒÅÍÑ ÉÈ ÒÁÂÏÔÙ (É ÔÅÌÅÆÏÎÙ ÈÉÄÄÅÎÏ×) ÄÏÌÖÅÎ ÚÎÁÔØ ÍÅÊÌÅÒ
#
# úÁÔÏÞÅÎ ÄÌÑ ÍÅÊÌÅÒÁ BinkleyForce
# äÌÑ ÄÒÕÇÉÈ ÐÒÁ×ÉÔØ ÆÕÎËÃÉÀ docallout
#
# Copyright (c) 2000 by Georgi Fofanov, 2:5050/29@fidonet
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# ðÕÔØ Ë outbound'Õ ÎÕÖÎÏÊ ÚÏÎÙ (ÐÏËÁ ÚÎÁÅÍ ÔÏÌØËÏ ÐÒÏ ÏÄÎÕ ÚÏÎÕ)
outb=/var/spool/ifmail/outb/
# ðÕÔØ Ë ËÁÔÁÌÏÇÕ Ó lock-ÆÁÊÌÁÍÉ (ÐÏÓÌÅÄÎÉÊ ÓÌÜÛ ÎÕÖÅÎ!)
lock=/var/lock/
# ðÁÕÚÁ ÍÅÖÄÕ Ú×ÏÎËÁÍÉ
# ÷ ÓÅËÕÎÄÁÈ
dialdelay=120
# ðÅÒÉÏÄ ÓËÁÎÉÒÏ×ÁÎÉÑ outbound'Á
# ðÏËÁ ÐÏÓÌÅ ÚÁ×ÅÒÛÅÎÉÑ ËÒÕÇÁ ÐÒÏÚ×ÏÎËÉ ÂÕÄÅÔ 2 ÐÁÕÚÙ - dialdelay É scan
# ÷ ÓÅËÕÎÄÁÈ
scan=60
# ðÁÕÚÁ ÍÅÖÄÕ ÐÒÏ×ÅÒËÁÍÉ lock-ÆÁÊÌÁ
# ÷ ÓÅËÕÎÄÁÈ
lockdelay=10
# òÁÓÐÏÌÏÖÅÎÉÅ ÍÅÊÌÅÒÁ
mailer=/usr/local/bin/bforce
# ëÏÍÁÎÄÁ, ×ÙÐÏÌÎÑÅÍÁÑ ÐÏÓÌÅ ÕÓÐÅÛÎÏÊ ÓÅÓÓÉÉ
after=/usr/local/bin/after_session
# õÓÔÒÏÊÓÔ×Ï, ÎÁ ËÏÔÏÒÏÍ ÓÉÄÉÔ ÍÏÄÅÍ
TTY="ttyS1"
# úÄÅÓØ ÐÅÒÅÞÉÓÌÅÎÙ ÓÉÓÔÅÍÙ, ÎÁ ËÏÔÏÒÙÅ ÍÏÖÎÏ Ú×ÏÎÉÔØ É (ÞÅÒÅÚ ÐÒÏÂÅÌ) ÞÉÓÌÏ
# ÉÈ ÍÏÄÅÍÎÙÈ ÌÉÎÉÊ
# îÁÐÒÉÍÅÒ:
# 2:5050/13 3
# 2:5050/9 2
# 2:5050/33 1
sys_poll=/etc/fido/poll.list
# ðÏÌØÚÏ×ÁÔÅÌØ, ÏÔ ÉÍÅÎÉ ËÏÔÏÒÏÇÏ ÎÁÄÏ ÚÁÐÕÓËÁÔØ
mailer_owner=fido
# ÷ÒÅÍÅÎÎÙÊ ÆÁÊÌ, ËÕÄÁ ÚÁÐÉÓÙ×ÁÅÔÓÑ ÓÐÉÓÏË ?lo É ?ut
list_file=/var/spool/ifmail/list.lst
# ÷ÒÅÍÅÎÎÙÊ ÆÁÊÌ
tmp_file=/var/spool/ifmail/list.tmp
# ÷ÒÅÍÅÎÎÙÊ ÆÁÊÌ, × ËÏÔÏÒÏÍ ÐÅÒÅÞÉÓÌÅÎÙ ÓÉÓÔÅÍÙ, ÎÁ ËÏÔÏÒÙÅ ÂÕÄÅÍ Ú×ÏÎÉÔØ
poll_file=/var/spool/ifmail/polling.list
# íÁËÓÉÍÁÌØÎÏÅ ÞÉÓÌÏ ÐÏÐÙÔÏË ÄÏÚ×ÏÎÉÔØÓÑ ÎÁ ÓÉÓÔÅÍÕ
MAXTRY=25
# óËÏÌØËÏ ×ÒÅÍÅÎÉ ÎÅ Ú×ÏÎÉÔØ ÎÁ ÓÉÓÔÅÍÕ, ÅÓÌÉ ÉÓÞÅÒÐÁÎÏ ÞÉÓÌÏ ÐÏÐÙÔÏË ÄÏÚ×ÏÎÁ
# ÷ ÍÉÎÕÔÁÈ
MAXTIME=60
# ðÒÏÉÚ×ÏÄÉÍ Ú×ÏÎÏË
function docallout ()
{
local zone=$1 net=$2 node=$3 point=$4 curtry=$5 numline=$6 line
let line=${curtry}%${numline}
if [ $point = 0 ] ; then
echo -n `date +%b\ %m\ %T` callout[$$] ú×ÏÎÉÍ ÎÁ ${zone}:${net}/${node} \(try \#${curtry}\)
$mailer ${zone}:${net}/${node} -l $line
let result=$?
else
echo -n `date +%b\ %m.%Y\ %T` callout[$$] ú×ÏÎÉÍ ÎÁ ${zone}:${net}/${node}.${point} \(try \#${curtry}\)
$mailer ${zone}:${net}/${node}.${point} -l $line
let result=$?
fi
case $result in
0 ) echo " ÕÓÐÅÛÎÏ" ;;
* ) echo " ÏÛÉÂËÁ" \#$result ;;
esac
if [ $result = 0 ] ; then
echo `date +%s` 0 0 >$sts
`$after`
else
echo `date +%s` $curtry $result >$sts
fi
}
# ðÒÏ×ÅÒÑÅÍ, ÍÏÖÎÏ ÌÉ Ú×ÏÎÉÔØ ÎÁ ÜÔÕ ÓÉÓÔÅÍÕ
function checkcallout ()
{
local curtry=$1 zone=$2 net=$3 node=$4 point=$5 numline=0
if [ $point = 0 ] ; then
`fgrep "${zone}:${net}/${node}" $sys_poll | awk '{ print "let numline=" $2 }'`
else
`fgrep "${zone}:${net}/${node}.${point}" $sys_poll | awk '{ print "let numline=" $2 }'`
fi
if [ $numline == 0 ] ; then return ; fi
docallout $zone $net $node $point $curtry $numline
}
# óËÁÎÉÒÕÅÍ outbound
function scandir ()
{
find -type f -and \( -name "*.?lo" -o -name "*.?ut" \) > $list_file
for file in `cat $list_file` ; do
eval `echo $file | awk '{ sub(/\.\//, "")
if (substr($0, 9, 4) == ".pnt") {
point = substr($0, 18, 4)
} else {
point = 0
}
printf "zonehex=%s nethex=%s nodehex=%s pointhex=%s let zone=0x%s net=0x%s node=0x%s point=0x%s",
"2", substr($0, 1, 4), substr($0, 5, 4), point,
"2", substr($0, 1, 4), substr($0, 5, 4), point
}'`
ext=${file:${#file}-3}
sts=${file%%?ut}
sts=${sts%%?lo}
bsy=${sts}bsy
sts=${sts}sts
if [ $ext != hlo -a $ext != hut ] ; then
echo ${zone} ${net} ${node} ${point} $sts $bsy >> $tmp_file
fi
done
rm $list_file
if [ -f $tmp_file ] ; then
`cat $tmp_file | sort | uniq > $poll_file`
rm $tmp_file
n=0
for sys in `cat $poll_file` ; do
let n=${n}+1
let tmp=${n}%6
case $tmp in
1 ) let zone=$sys ;;
2 ) let net=$sys ;;
3 ) let node=$sys ;;
4 ) let point=$sys ;;
5 ) sts=$sys ;;
0 ) bsy=$sys ;;
esac
if [ $tmp == 0 ] ; then
while [ -e ${lock}LCK..$TTY ]
do
sleep $lockdelay
done
if [ ! -f $bsy ] ; then
if [ ! -f $sts ] ; then
let lasttime=0 retries=0 errcode=0
else
`cat $sts|awk '{ print "let lasttime=" $1 " retries=" $2 " errcode=" $3 }'`
fi
let curtime=`date +%s`
let timediff=${curtime}-${lasttime}
let curtry=${retries}+1
if [ $curtry -gt $MAXTRY ] ; then
if [ $timediff -gt $MAXTIME ] ; then
let curtry=1
checkcallout $curtry $zone $net $node $point
sleep $dialdelay
fi
else
checkcallout $curtry $zone $net $node $point
sleep $dialdelay
fi
fi
fi
done
rm $poll_file
fi
}
function main ()
{
cd $outb
while [ ! -f /tmp/callout.exit ] ; do
if [ ! -e ${lock}LCK..$TTY ]; then
scandir
sleep $scan
else
sleep $lockdelay
fi
done
rm /tmp/callout.exit
}
if [ `whoami` != "$mailer_owner" ]; then
echo "wrong uid, run as user $mailer_owner (rc=2)"
exit 2
fi
. /etc/profile > /dev/null 2>&1
let MAXTIME=${MAXTIME}*60
main >> /var/log/ifmail/callout.log 2>&1
## éÚÍÅÎÅÎÉÑ
# Ver 1.1, 09 Jul 2000:
#
# ïÂÎÕÌÅÎÉÅ ÞÉÓÌÁ ÐÏÐÙÔÏË ÐÏÓÌÅ ÕÓÐÅÛÎÏÊ ÓÅÓÓÉÉ
#
# îÅ ÒÁÂÏÔÁÌ MAXTIME
# Ver 1.0, 08 Jul 2000:
#
# ðÅÒ×ÁÑ ÓÔÁÂÉÌØÎÁÑ ×ÅÒÓÉÑ
+51
View File
@@ -0,0 +1,51 @@
#!/bin/sh
#
# bforce FTN mailer
#
# chkconfig: 345 94 14
# description: Starts and stops the binkleyforce mailer daemon
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
OWNER=uucp
BFORCE=/usr/local/fido/bin/bforce
# Source function library.
. /etc/init.d/functions
[ -f $BFORCE ] || exit 0
# See how we were called.
case "$1" in
start)
# Start daemon.
echo -n "Starting bforce: "
su $OWNER -c ". /etc/rc.d/init.d/functions; daemon $BFORCE -d"
echo
touch /var/lock/subsys/bforce
;;
stop)
# Stop daemon.
echo -n "Shutting down bforce: "
killproc bforce
rm -f /var/lock/subsys/bforce
echo
;;
status)
status bforce
exit $?
;;
restart)
$0 stop
$0 start
exit $?
;;
*)
echo "Usage: bforce {start|stop|status|restart}"
exit 1
esac
exit 0
+44
View File
@@ -0,0 +1,44 @@
#!/bin/sh
#
# bforce FTN mailer
#
# chkconfig: 345 94 14
# description: Starts and stops the binkleyforce mailer daemon
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
OWNER=uucp
BFORCE=/usr/local/fido/bin/bforce
[ -f $BFORCE ] || exit 0
# See how we were called.
case "$1" in
start)
# Start daemon.
echo -n "Starting bforce. "
su $OWNER -c "daemon $BFORCE -d"
echo
touch /var/lock/subsys/bforce
;;
stop)
# Stop daemon.
echo -n "Shutting down bforce. "
$BFORCE -q
rm -f /var/lock/subsys/bforce
echo
;;
restart)
$0 stop
$0 start
exit $?
;;
*)
echo "Usage: bforce {start|stop|restart}"
exit 1
esac
exit 0
+366
View File
@@ -0,0 +1,366 @@
#!/usr/bin/tclsh
#
# Copyright (c) 2000 by Alexander Belkin <adb@newmail.ru>
#
# $Id$
#
# Tcl script for creating polls, file requests and file attaches
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
##################
# Program settings
# Defaults for address completion
set def_zone 2
set def_net 5020
set def_node 1398
# Path to your main BSO directory (not implemented)
#set bso_dir "/var/spool/ftn/out"
# Path to your ASO directory
set aso_dir "/var/spool/fido/amiga.out"
# Log file name
set logfile "/var/log/bforce/outman.log"
# Uncomment this if you not need logging
#set logfile {}
################################
# The program's body starts here
set LOG {}
proc stupid_user {} {
puts "Usage: outman <\[poll|freq|send]> \[options] <address> \[files]\n"
puts "options:"
puts " -hold set hold flavor"
puts " -normal set normal flavor (default)"
puts " -crash set crash flavor"
puts " -kill kill files after send"
puts " -truncate truncate files after send"
puts ""
puts "Mail bug reports to <adb@newmail.ru>"
exit 1
}
proc log {str} {
global LOG
global logfile
if { $logfile != {} } {
if { $LOG == {} } {
set LOG [open $logfile "a"]
}
set seconds [clock seconds]
puts $LOG "[clock format $seconds -format "%d/%m %H:%M:%S"] $str"
}
}
proc parse_addr {str} {
global def_zone
global def_net
global def_node
set zone $def_zone
set net $def_net
set node $def_node
set point 0
if { [regexp "^\[0-9]+:\[0-9]+/\[0-9]+\\.?\[0-9]*$" $str] } {
regexp "(\[0-9]+):(\[0-9]+)/(\[0-9]+)\\.?(\[0-9]*)$" $str \
{} zone net node point
} elseif { [regexp "^\[0-9]+/\[0-9]+\\.?\[0-9]*$" $str] } {
regexp "(\[0-9]+)/(\[0-9]+)\\.?(\[0-9]*)$" $str \
{} net node point
} elseif { [regexp "^\[0-9]+\\.?\[0-9]*$" $str] } {
regexp "^(\[0-9]*)\\.?(\[0-9]*)$" $str \
{} node point
} elseif { [regexp "^\.\[0-9]+$" $str] } {
regexp "^\.(\[0-9]+)$" $str \
{} point
} else {
puts "invalid address $str"
return {}
}
if { $zone == {} } { set zone [$def_zone] }
if { $net == {} } { set net [$def_net] }
if { $node == {} } { set node [$def_node] }
if { $point == {} } { set point 0 }
# puts "debug: address parse '$str' -> '$zone,$net,$node,$point'"
return "$zone $net $node $point"
}
proc addrstr {addr} {
return [lindex $addr 0]:[lindex $addr 1]/[lindex $addr 2].[lindex $addr 3]
}
#
# TODO: support for outbounds not in the default zone
#
proc filename_bso {addr flavor} {
global bso_dir
set zone [lindex $addr 0]
set net [lindex $addr 1]
set node [lindex $addr 2]
set point [lindex $addr 3]
if { $point } {
set name [format "%04x%04x.pnt/%08x" $net $node $point]
} else {
set name [format "%04x%04x" $net $node]
}
switch $flavor {
"bsy" {
return "$bso_dir/$name.bsy"
}
"freq" {
return "$bso_dir/$name.req"
}
"hold" {
return "$bso_dir/$name.hlo"
}
"crash" {
return "$bso_dir/$name.clo"
}
default {
return "$bso_dir/$name.flo"
}
}
}
proc filename_aso {addr flavor} {
global aso_dir
set name [lindex $addr 0].[lindex $addr 1].[lindex $addr 2].[lindex $addr 3]
switch $flavor {
"bsy" {
return "$aso_dir/$name.bsy"
}
"freq" {
return "$aso_dir/$name.req"
}
"hold" {
return "$aso_dir/$name.hlo"
}
"crash" {
return "$aso_dir/$name.clo"
}
default {
return "$aso_dir/$name.flo"
}
}
}
proc bsy_exist {addr} {
set bsyname [filename_aso $addr "bsy"]
if { [file exists $bsyname] } {
return 1
}
return 0
}
proc command_freq {addr files} {
set reqname [filename_aso $addr "freq"]
set name {}
# puts "debug: file request name is '$reqname'"
set REQ [open $reqname "a"]
foreach name $files {
puts $REQ $name
log "request \"$name\" from [addrstr $addr]"
}
close $REQ
}
proc command_poll {addr flavor} {
set floname [filename_aso $addr $flavor]
if { ![file exists $floname] } {
set FLO [open $floname "a"]
close $FLO
log "poll [addrstr $addr] ($flavor)"
} else {
log "cannot create poll for [addrstr $addr]: allready polled"
}
}
proc command_send {addr files flavor action} {
set floname [filename_aso $addr $flavor]
set name {}
set curdir [exec pwd]
set FLO [open $floname "a"]
foreach name $files {
if { [file exists $name] } {
if { [file pathtype $name] == "relative" } {
if { [string match "./*" $name] } {
set name [string range $name 2 end]
}
set name "$curdir/$name"
}
log "send file \"$name\" ([file size $name] bytes) to [addrstr $addr] ($flavor)"
switch $action {
"kill" {
puts $FLO "^$name"
}
"truncate" {
puts $FLO "#$name"
}
default {
puts $FLO "@$name"
}
}
} else {
puts "skip file \"$name\" to [addrstr $addr]: file not exist"
}
}
close $FLO
}
##############################
# The main program starts here
if { $argc < 2 } {
stupid_user
}
set command {}
set address {}
set addr {}
set files {}
set flavor "normal"
set action "nothing"
for {set i 0} {$i < $argc} {incr i} {
set arg [lindex $argv $i]
if { [string index $arg 0] == "-" } {
switch [string range $arg 1 end] {
"hold" {
set flavor "hold"
}
"normal" {
set flavor "normal"
}
"crash" {
set flavor "crash"
}
"kill" {
set action "kill"
}
"truncate" {
set action "truncate"
}
default {
puts "unknown command line option '$arg'"
stupid_user
}
}
} elseif { $command == {} } {
set command $arg
} elseif { $address == {} } {
set address $arg
set addr [parse_addr $address]
if { $addr == {} } {
stupid_user
}
} else {
lappend files $arg
}
}
if { $command == {} || $address == {} } {
stupid_user
}
if { [bsy_exist $addr] } {
puts "bsy file exist for address [addrstr $addr]"
exit 2
}
switch $command {
"poll" {
command_poll $addr $flavor
}
"freq" {
command_freq $addr $files
}
"send" {
command_send $addr $files $flavor $action
}
default {
puts "unknown command $command"
stupid_user
}
}
if { $LOG != {} } {
close $LOG
}
exit 0
+116
View File
@@ -0,0 +1,116 @@
#!/usr/bin/tclsh
#
# Copyright (c) 2000 by Alexander Belkin <adb@newmail.ru>
#
# $Id$
#
# Time syncronization utility
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
##################
# Program settings
set bforce_log_file "/var/log/bforce/bf-log.ttyS0"
set sync_with_addr "2:450/102"
set max_time_diff 1800
set min_time_diff 20
set news_groups "local.robots"
set from_user "Time Robot <root@fido.xxx.local>"
set inews_cmd "/usr/bin/inews"
################################
# The program's body starts here
set sess_pid ""
set remote_times ""
set local_times ""
set TEXT ""
set INP [open $bforce_log_file "r"]
foreach line [split [read $INP] "\n"] {
set fields [split $line " "]
set pid [lindex $fields 3]
set time [join [lrange $fields 0 2]]
set data [join [lrange $fields 4 end]]
if { [string match "*Address : $sync_with_addr" $data] } {
set sess_pid $pid
set sess_time ""
} elseif { [string match "*Time :*" $data] } {
if { $sess_pid == $pid } {
regexp "Time : (.+)" $data {} timestr
if { $timestr != "" } {
set sess_time $timestr
}
}
} elseif { [string match "remote is*,protected" $data] } {
if { $sess_pid == $pid } {
if { $sess_time != "" && $time != "" } {
lappend remote_times $sess_time
lappend local_times $time
}
set sess_pid ""
set sess_time ""
}
} elseif { [string match "remote is*" $data] } {
if { $sess_pid == $pid } {
set sess_pid ""
set sess_time ""
}
}
}
close $INP
set last_rem_time [lindex $remote_times end]
set last_loc_time [lindex $local_times end]
if { $last_rem_time != "" && $last_loc_time != "" } {
regexp "(\[0-9]+):(\[0-9]+):(\[0-9]+)" $last_rem_time {} rh rm rs
regexp "(\[0-9]+):(\[0-9]+):(\[0-9]+)" $last_loc_time {} lh lm ls
set rem [expr "$rh*3600 + $rm*60 + $rs"]
set loc [expr "$lh*3600 + $lm*60 + $ls"]
set diff [expr "$rem - $loc"]
if { [expr abs($diff)] < $min_time_diff } {
# Do nothing
} elseif { [expr abs($diff)] <= $max_time_diff } {
set old_sec [clock seconds]
set new_sec [expr $old_sec + $diff]
exec /bin/date -s [clock format $new_sec -format "%d-%b-%Y %H:%M:%S"]
exec /sbin/clock -wu
append TEXT "The System time was synchronized with the node $sync_with_addr\n\n"
append TEXT "Old time : [clock format $old_sec]\n"
append TEXT "New time : [clock format $new_sec]\n"
append TEXT "Time difference : $diff second(s)\n"
} else {
set old_sec [clock seconds]
set new_sec [expr $old_sec + $diff]
append TEXT "The System time WAS NOT synchronized with the node $sync_with_addr\n\n"
append TEXT "Current time : [clock format $old_sec]\n"
append TEXT "Want set time : [clock format $new_sec]\n"
append TEXT "Time difference : $diff second(s) (must be lower $max_time_diff seconds)\n"
}
}
if { $TEXT != "" } {
set MSG "From: $from_user\n"
append MSG "Subject: Time synchronization\n"
append MSG "Newsgroups: $news_groups\n\n"
append MSG $TEXT
exec $inews_cmd -h << $MSG
}
exit 0
+6
View File
@@ -0,0 +1,6 @@
License notice for u-srif-py
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
+27
View File
@@ -0,0 +1,27 @@
+-----------+----------------------+----------------------+
| | Statistic | Limits |
| Period +-------------+--------+-------------+--------+
| | Size | Number | Size | Number |
+-----------+-------------+--------+-------------+--------+
| Day | @%-11d,sent_day_size@ | @%-6d,sent_day_num@ | @%-11s,limit_size_day@ | @%-6s,limit_num_day@ |
+-----------+-------------+--------+-------------+--------+
| Week | @%-11d,sent_week_size@ | @%-6d,sent_week_num@ | @%-11s,limit_size_week@ | @%-6s,limit_num_week@ |
+-----------+-------------+--------+-------------+--------+
| Month | @%-11d,sent_month_size@ | @%-6d,sent_month_num@ | @%-11s,limit_size_month@ | @%-6s,limit_num_month@ |
+-----------+-------------+--------+-------------+--------+
| Total | @%-11d,sent_total_size@ | @%-6d,sent_total_num@ |
+-----------+-------------+--------+
******************************************************************************
File requests policy
******************************************************************************
File requests supported at 00:00-05:30 and at least 9600 speed
There are aliases for file requests:
FILES - Happy Station files list
BFORCE - The latest version of the binkleyforce mailer
Bye, call again!
+2
View File
@@ -0,0 +1,2 @@
Hello, @%s,remote_sysop@!
+6
View File
@@ -0,0 +1,6 @@
files /home/ftp/pub/info/happy.zip
filelist /home/ftp/pub/info/happy.lst
test /home/ftp/pub/fileecho/PNT5020/pnt5020.zip
bforce /home/ftp/pub/bforce/bforce-last.tar.gz
+21
View File
@@ -0,0 +1,21 @@
##############################################################################
### u-srif FREQ processor configuration file #################################
##############################################################################
# Spool directory for files index, links statistic, etc.
spool-dir /var/spool/u-srif
# Log file name
log-file /var/log/ftn/u-srif.log
# File with list of freqable directories
dir-list-file /usr/local/etc/u-srif/u-srif.dirs
# File with list of freqable directories
alias-list-file /usr/local/etc/u-srif/u-srif.aliases
freq-policy /usr/local/etc/u-srif/policy.text
freq-magic bforce-cvs /usr/local/etc/u-srif/magic/bforce-cvs
freq-alias = files /home/ftp/pub password
+42
View File
@@ -0,0 +1,42 @@
/home/ftp/pub/bforce/
/home/ftp/pub/fileecho/ADV_FTNSOFT/
/home/ftp/pub/fileecho/AFTNMISC/
/home/ftp/pub/fileecho/AVP/
/home/ftp/pub/fileecho/BOOK/
/home/ftp/pub/fileecho/CRACKER/
/home/ftp/pub/fileecho/CRACKS/
/home/ftp/pub/fileecho/FAR/
/home/ftp/pub/fileecho/FR_CO.FILES/
/home/ftp/pub/fileecho/FWUTILS/
/home/ftp/pub/fileecho/GSS_BETA/
/home/ftp/pub/fileecho/GSS_SOFT/
/home/ftp/pub/fileecho/G_CHEAT/
/home/ftp/pub/fileecho/IT.FILES/
/home/ftp/pub/fileecho/IT.MP3/
/home/ftp/pub/fileecho/IT.MUSIC/
/home/ftp/pub/fileecho/IT.NDL/
/home/ftp/pub/fileecho/LARRY.FILES/
/home/ftp/pub/fileecho/HAPPY.XCK/
/home/ftp/pub/fileecho/MOBIL/
/home/ftp/pub/fileecho/NET5020/
/home/ftp/pub/fileecho/PNT5020/
/home/ftp/pub/fileecho/RUFO/
/home/ftp/pub/fileecho/STICK.FILES/
/home/ftp/pub/fileecho/T-MAIL/
/home/ftp/pub/fileecho/UNKNOWN/
/home/ftp/pub/fileecho/XDOCREF/
/home/ftp/pub/fileecho/XGAMSOL/
/home/ftp/pub/fileecho/XHAMRADIO/
/home/ftp/pub/fileecho/XHRDASUS/
/home/ftp/pub/fileecho/XHRDDOCS/
/home/ftp/pub/fileecho/XHRDIDC/
/home/ftp/pub/fileecho/XHRDUSR/
/home/ftp/pub/fileecho/XPICART/
/home/ftp/pub/fileecho/XPICHUMOR/
/home/ftp/pub/fileecho/XPICMUSIC/
/home/ftp/pub/fileecho/XPICSHIP/
/home/ftp/pub/fileecho/XPICSYSOP/
/home/ftp/pub/fileecho/XPICWEAPON/
/home/ftp/pub/files/uue_files/
/home/ftp/pub/redhat-5.2/RedHat/RPMS/
/home/ftp/pub/redhat-6.1/RedHat/RPMS/
+163
View File
@@ -0,0 +1,163 @@
import gdbm
import string
import os
import ufido
ALIAS_TYPE_NORMAL = 1 # Traditional aliase
ALIAS_TYPE_MAGIC = 2 # "Magic" alias
# TODO: These functions must generate an exception in case of errors
def get_bool(str):
str = string.lower(str)
if str == 'yes' or str == 'true':
return 1
elif str == 'no' or str == 'false':
return 0
return None
def get_size(str):
# TODO: support nice size formats like 64M, 10G
return str
def get_alias(str, type):
args = string.split(str)
if len(args) < 2 or len(args) > 3:
return None
if len(args) == 3:
passwd = args[2]
else:
passwd = None
return Alias(args[0], args[1], passwd, type)
class Alias:
""" Aliases implementation
"""
def __init__(self, name, filename, passwd, type):
""" Alias initialisation
"""
self.name = name
self.filename = filename
self.type = type
def get(self, passwd):
""" Get the list of files to send for this alias
"""
yield = []
if self.type == ALIAS_TYPE_NORMAL:
yield.append(self.filename)
return yield
elif self.type == ALIAS_TYPE_MAGIC:
# Prepare the environment (TODO)
putenv('PASSWORD', passwd)
putenv('ADDRESS', None)
putenv('PROTECTED', 'FALSE')
putenv('LISTED', 'FALSE')
# Execute magic program and process its output
try:
magic = popen(self.filename)
line = magic.readline()
while line:
line = magic.readline()
yield.append(string.strip(line))
if magic.close():
print "Magic return code is non-zero: ", self.filename
return None
return yield
except IOError:
print "Failed to run magic: ", self.filename
return None
class Config:
def read_dir_list(self):
yield = []
fp = open(self.dir_list_file, 'r')
line = fp.readline()
while line:
line = string.strip(line)
if line != '':
yield.append(line)
line = fp.readline()
fp.close()
return yield
def read_alias_list(self):
yield = []
fp = open(self.alias_list_file, 'r')
line = fp.readline()
while line:
line = string.strip(line)
if line != '':
[name, filename] = string.split(line, None, 1)
yield.append(alias(name, filename))
line = fp.readline()
fp.close()
return yield
def read(self, name):
fp = open(name, 'r')
line = fp.readline()
while line:
line = string.strip(line)
args = string.split(line, None, 1)
if line[0:1] == '#' or len(line) == 0:
pass
elif len(args) != 2:
print "Invalid string in config: ", line
else:
key = string.lower(args[0])
val = args[1]
if key == 'dir-list-file':
self.dir_list_file = val
elif key == 'send-report':
self.send_report = get_bool(val)
elif key == 'limit-size-day':
self.limit_size_day = get_size(val)
elif key == 'limit-size-week':
self.limit_size_week = get_size(val)
elif key == 'limit-size-month':
self.limit_size_month = get_size(val)
elif key == 'spool-dir':
self.spool_dir = val
elif key == 'freq-alias':
self.freq_alias.append(get_alias(val, ALIAS_TYPE_NORMAL))
elif key == 'freq-magic':
self.freq_magic.append(get_alias(val, ALIAS_TYPE_MAGIC))
elif key == 'log-file':
self.log_file = val
elif key == 'local-address':
self.local_address.parse(var)
elif key == 'report-header':
self.report_header = val
elif key == 'report-footer':
self.report_footer = val
elif key == 'report-from':
self.report_from = val
elif key == 'report-subj':
self.report_subj = val
elif key == 'stat-dbase':
self.stat_dbase = val
else:
print "unknown config keyword:", key
line = fp.readline()
fp.close()
def __init__(self, name):
self.dir_list_file = ''
self.send_report = 0
self.limit_size_day = 0
self.limit_size_week = 0
self.limit_size_month = 0
self.spool_dir = ''
self.freq_policy = ''
self.freq_alias = []
self.freq_magic = []
self.log_file = ''
self.local_address = ufido.address()
self.report_header = ''
self.report_footer = ''
self.report_from = 'FREQ manager'
self.report_subj = 'FREQ report'
self.stat_dbase = None
self.read(name)
+151
View File
@@ -0,0 +1,151 @@
import os
import gdbm
import string
def get_file_desc(filename):
path, name = os.path.split(filename)
descname = os.path.join(path, '.desc', name + '.desc')
if not os.path.isfile(descname):
return None
try:
fp = open(descname, 'r')
except IOError:
print 'Cannot open', descname
return None
line = fp.readline()
yield = ''
while line:
yield = yield + line
line = fp.readline()
fp.close()
return string.strip(yield)
def get_area_desc(areapath):
descname = os.path.join(areapath, '.desc', '.desc')
if not os.path.isfile(descname):
return None
try:
fp = open(descname, 'r')
except IOError:
print 'Cannot open', descname
return None
line = fp.readline()
yield = ''
while line:
yield = yield + line
line = fp.readline()
fp.close()
return string.strip(yield)
class file:
def stat(self):
if self.fake:
return
try:
statinfo = os.stat(self.fullname)
self.size = statinfo[6]
self.time = statinfo[8]
except OSError:
self.size = -1
self.time = -1
self.desc = 'File is not accessable'
def set(self, fullname, name = None, area = '', dlcnt = 0,\
mode = '', desc = '', fake = 0):
if name == None:
self.name = os.path.split(fullname)[1]
else:
self.name = name
self.fullname = fullname
self.dlcnt = dlcnt
self.size = -1
self.time = -1
self.area = area
self.mode = mode
self.desc = desc
self.fake = fake
def reset(self):
self.name = ''
self.fullname = ''
self.area = ''
self.dlcnt = 0
self.mode = ''
self.desc = ''
self.size = -1
self.time = -1
self.fake = 0
def __init__(self):
self.reset()
class filebase:
""" Index entry format: [fullname, area, dlcnt, accessmode, desc]
"""
def open(self, mode):
self.db = gdbm.open(self.dbfile, mode)
def close(self):
self.db.close()
def sync(self):
self.db.sync()
def clean(self):
for filename in self.db.keys():
file = self.get(filename)
if not os.path.isfile(file.fullname):
print 'Remove file "%s" from index' % file.fullname
del self.db[filename]
def get_all(self, filenames):
""" Lookup files in the database and return list
of file objects
"""
yield = []
for name in filenames:
files = self.get(name)
if files and len(files) > 0:
yield.extend(files)
return yield
def get(self, filename):
""" Lookup file by its name in the database and
return list of file objects for this name
"""
yield = []
if not self.db.has_key(filename):
return None
files_info = eval(self.db[filename])
if files_info == None:
newfile = file()
newfile.set(filename, desc='File not found', fake=1)
yield.append(newfile)
else:
for finfo in files_info:
newfile = file()
finfo = eval(finfo)
newfile.set(finfo[0], area = finfo[1],\
dlcnt = finfo[2], mode = finfo[3],\
desc = finfo[4])
yield.append(newfile)
return yield
def put(self, file):
finfo = []
finfo.append(file.fullname)
finfo.append(file.area)
finfo.append(file.dlcnt)
finfo.append(file.mode)
finfo.append(file.desc)
if self.db.has_key(file.name):
files_info = eval(self.db[file.name])
else:
files_info = []
files_info.append(repr(finfo))
self.db[file.name] = repr(files_info)
def __init__(self, spooldir):
self.dbfile = os.path.join(spooldir, 'filebase.db')
+181
View File
@@ -0,0 +1,181 @@
import string
import re
import struct
import time
#address_1 = re.compile('^\([0-9]+\):\([0-9]+\)/\([0-9]+\)\.?\([0-9]+\)?$')
address_1 = re.compile('^(\d+):(\d+)/(\d+)\.?(\d+)?$')
months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Jan')
class address:
def is_set(self):
if self.zone > 0 and self.net > 0:
return 1
return 0
def string(self):
if self.invalid:
yield = 'Invalid address'
elif self.point > 0:
yield = '%d:%d/%d.%d' % (self.zone, self.net, self.node, self.point)
else:
yield = '%d:%d/%d' % (self.zone, self.net, self.node)
return yield
def parse(self, str):
match = address_1.match(str)
if match:
try:
self.zone = string.atoi(match.group(1))
self.net = string.atoi(match.group(2))
self.node = string.atoi(match.group(3))
tmp = match.group(4)
if tmp and tmp != '-1':
self.point = string.atoi(tmp)
else:
self.point = 0
self.invalid = 0
except IndexError:
self.__init__()
return -1
else:
print "Regexp doesnt match!"
return -1
return 0
def __init__(self):
self.zone = 0
self.net = 0
self.node = 0
self.point = 0
self.invalid = 1
class message:
def newmsg(self, addr_from, user_from, addr_to, user_to, subject):
self.unix_time = time.time()
self.addr_orig = addr_from
self.addr_dest = addr_to
self.user_orig = user_from
self.user_dest = user_to
self.subject = subject
self.msgbody = ''
self.append_line('\001FMPT %d' % self.addr_orig.point)
self.append_line('\001TOPT %d' % self.addr_dest.point)
def append_line(self, string):
self.msgbody = self.msgbody + string + '\r'
def append_text(self, text):
for line in string.split(text, '\n'):
self.append_line(line)
def append_file(self, filename):
try:
fp = open(filename, 'r')
except IOError:
print 'Cannot append file', filename
return
line = fp.readline()
while line:
self.append_line(string.rstrip(line))
line = fp.readline()
fp.close()
def __init__(self):
self.unix_time = 0
self.addr_orig = address()
self.addr_dest = address()
self.user_orig = ''
self.user_dest = ''
self.subject = ''
self.msgbody = ''
self.origin = ''
class packet:
def reset(self):
self.addr_orig = address()
self.addr_dest = address()
self.password = ''
self.messages = []
# TODO
def read(self, filename):
self.reset()
fp = open(filename, "w")
fp.close()
def get_time_string(self, unix_time):
msgtime = time.localtime(unix_time)
return '%02d %s %02d %02d:%02d:%02d' % \
(msgtime[2], months[msgtime[1]], msgtime[0] % 100, \
msgtime[3], msgtime[4], msgtime[5])
def get_message_header(self, message):
return struct.pack('7H20s',\
2,\
message.addr_orig.node,\
message.addr_dest.node,\
message.addr_orig.net,\
message.addr_dest.net,\
0,\
0,\
self.get_time_string(message.unix_time)) + \
message.user_dest[0:36] + '\0' + \
message.user_orig[0:36] + '\0' + \
message.subject[0:72] + '\0'
def get_packet_header(self):
now = time.localtime(time.time())
return struct.pack('13H8s12H',\
self.addr_orig.node,\
self.addr_dest.node,\
now[0], # Year\
now[1], # Month\
now[2], # Day\
now[3], # Hour\
now[4], # Minute\
now[5], # Second\
9600, # Baud\
2, # PKT type\
self.addr_orig.net,\
self.addr_dest.net,\
254, # Prod. code + Rev. number\
self.password,\
self.addr_orig.zone,\
self.addr_dest.zone,\
0, # AuxNet\
0, # CWvalidationCopy\
0, # ProductCode + Revision \
0, # CapabilWord\
self.addr_orig.zone,\
self.addr_dest.zone,\
self.addr_orig.point,\
self.addr_dest.point,\
0,
0)
def write(self, filename):
fp = open(filename, "w")
fp.write(self.get_packet_header())
for msg in self.messages:
fp.write(self.get_message_header(msg))
fp.write(msg.msgbody)
fp.write('\0')
fp.write('\0\0')
fp.close()
def add_message(self, message):
self.messages.append(message)
def __init__(self):
self.reset()
if __name__ == "__main__":
tmp = address()
tmp.parse('2:5020/2120')
print tmp.string()
+102
View File
@@ -0,0 +1,102 @@
import time
import gdbm
import ufido
class nodestat:
""" [[month_id, month_size, month_num, month_time],
[week_id, seek_size, week_num, week_time],
[day_id, day_size, day_num, day_time],
[total_size, total_num, total_time]]
"""
def __init__(self, dbpath, address):
self.addr = address
self.key = address.string()
self.stat_session_size = 0
self.stat_session_num = 0
self.stat_session_time = 0
self.stat_day_size = 0
self.stat_day_num = 0
self.stat_day_time = 0
self.stat_week_size = 0
self.stat_week_num = 0
self.stat_week_time = 0
self.stat_month_size = 0
self.stat_month_num = 0
self.stat_month_time = 0
self.stat_total_size = 0
self.stat_total_num = 0
self.stat_total_time = 0
self.dbpath = dbpath
tt = time.localtime()
self.month_id = time.strftime('%Y%m', tt)
self.week_id = time.strftime('%Y%W', tt)
self.day_id = time.strftime('%Y%j', tt)
self.notexist = 0 # Entry for this node doesn't exist yet?
def upd_stat(self, num, size):
self.stat_session_size = self.stat_session_size + size
self.stat_session_num = self.stat_session_num + num
self.stat_month_size = self.stat_month_size + size
self.stat_month_num = self.stat_month_num + num
self.stat_week_size = self.stat_week_size + size
self.stat_week_num = self.stat_week_num + num
self.stat_day_size = self.stat_day_size + size
self.stat_day_num = self.stat_day_num + num
self.stat_total_size = self.stat_total_size + size
self.stat_total_num = self.stat_total_num + num
def get_stat(self):
try:
db = gdbm.open(self.dbpath, 'r')
except gdbm.error:
return 0
if not db.has_key(self.key):
self.notexist = 1
db.close()
return 0
entry = eval(db[self.key])
# Check month statistic
if entry[0][0] == self.month_id:
self.stat_month_size = entry[0][1]
self.stat_month_num = entry[0][2]
self.stat_month_time = entry[0][3]
# Check week statistic
if entry[1][0] == self.week_id:
self.stat_week_size = entry[1][1]
self.stat_week_num = entry[1][2]
self.stat_week_time = entry[1][3]
# Check day statistic
if entry[2][0] == self.day_id:
self.stat_day_size = entry[2][1]
self.stat_day_num = entry[2][2]
self.stat_day_time = entry[2][3]
# Get total statistic
self.stat_total_size = entry[3][0]
self.stat_total_num = entry[3][1]
self.stat_total_time = entry[3][2]
db.close()
return 0
def put_stat(self):
db = gdbm.open(self.dbpath, 'cf')
# Don't handle exceptions
entry = [[self.month_id, self.stat_month_size, self.stat_month_num, self.stat_month_time],
[self.week_id, self.stat_week_size, self.stat_week_num, self.stat_week_time],
[self.day_id, self.stat_day_size, self.stat_day_num, self.stat_day_time],
[self.stat_total_size, self.stat_total_num, self.stat_total_time]]
db[self.key] = repr(entry)
db.close()
return 0
if __name__ == '__main__':
addr = ufido.address()
addr.parse('2:5020/2120')
ns = nodestat('./tmp.db', addr)
ns.upd_stat(2, 32768)
ns.put_stat()
addr2 = ufido.address()
addr2.parse('2:5020/2120')
ns2 = nodestat('./tmp.db', addr2)
ns2.get_stat()
print ns2.stat_total_num, ns2.stat_total_size
+97
View File
@@ -0,0 +1,97 @@
import string
class template:
def __init__(self):
self.local_address = ''
self.local_sysop = ''
self.local_location = ''
self.local_phone = ''
self.remote_address = ''
self.remote_sysop = ''
self.remote_location = ''
self.remote_phone = ''
self.remote_cid = ''
self.limit_size_day = -1
self.limit_size_week = -1
self.limit_size_month = -1
self.sent_size_day = -1
self.sent_size_week = -1
self.sent_size_month = -1
self.sent_size = -1
self.conn_speed = -1
self.text = None
def set(self, srif=None, conf=None, nodestat=None):
if srif:
self.remote_address = srif.aka.string()
self.remote_sysop = srif.sysop
self.remote_location = srif.site
self.remote_cid = srif.callerid
self.conn_speed = srif.baud
if conf:
self.local_address = conf.local_address.string()
self.limit_size_day = conf.limit_size_day
self.limit_size_week = conf.limit_size_week
self.limit_size_month = conf.limit_size_month
if nodestat:
self.sent_session_size = nodestat.stat_session_size
self.sent_session_num = nodestat.stat_session_num
self.sent_day_size = nodestat.stat_day_size
self.sent_day_num = nodestat.stat_day_num
self.sent_week_size = nodestat.stat_week_size
self.sent_week_num = nodestat.stat_week_num
self.sent_month_size = nodestat.stat_month_size
self.sent_month_num = nodestat.stat_month_num
self.sent_total_size = nodestat.stat_total_size
self.sent_total_num = nodestat.stat_total_num
def __cmd__(self, str):
try:
[fmt, arg] = string.split(str, ',', 1)
return eval('"' + fmt + '" % self.' + arg)
except ValueError:
return '@ValueError@'
except AttributeError:
return '@AttributeError@'
def process(self, text=None):
if text == None:
text = self.text
if text == None:
return None
pos = 0
while 1:
pos = string.find(text, '@', pos)
if pos < 0:
break
end_pos = string.find(text, '@', pos+1)
if end_pos < 0:
break
if end_pos - pos > 1:
# Process escaped command
replace = self.__cmd__(text[pos+1:end_pos])
if replace:
text = text[:pos]+replace+text[end_pos+1:]
# Fix the current position
pos = end_pos + len(replace)-(end_pos-pos+1)
else:
# Leave text untouched
pos = end_pos + 1
else:
# Replace '@@' by the single '@'
text = text[:pos+1]+text[pos+2:]
pos = end_pos
return text
def readfile(self, path):
try:
fp = open(path, 'r')
self.text = fp.read()
fp.close()
except IOError:
pass
if __name__ == "__main__":
test = template()
print test.process("'@@'\n'@@'\n'@%d,conn_speed@'\n'@@@'")
+54
View File
@@ -0,0 +1,54 @@
import string
# Header for the files information
file_info_header = 'File Size Description\n'\
+ '-' * 78
class ULog:
def __init__(self, path):
self.path = path
self.fp = open(path, 'a')
def puts(self, string):
fp.puts(strftime('%b %d %H:%M:%S ', gmtime())+string)
def close(self):
fp.close()
def format_desc(desc, offset, width=78):
""" Format file's description
"""
yield = ''
desc = string.expandtabs(desc, 1)
for line in string.split(desc, '\n'):
line = string.rstrip(line)
if line == '':
continue
pos = 0
endpos = width
while line[pos:endpos]:
if yield:
yield = yield + '\n'
yield = yield + offset * ' '
yield = yield + line[pos:endpos]
pos = endpos
endpos = endpos + width
return yield
def format_file_info(name, size, desc, line_length=78):
""" Format file information to meet human requirements
"""
if size < 0:
yield = '%-20s ' % name + 11 * ' '
else:
yield = '%-20s %-11d' % (name, size)
if desc:
offset = len(yield) + 1
width = line_length - offset
desc = format_desc(desc, offset, width)
yield = yield + ' ' + string.lstrip(desc)
else:
yield = yield + ' Description not available'
return yield
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/python
import sys
import posix
import os
import libconf
import libfbase
USRIF_CONFIG = '/usr/local/etc/u-srif/u-srif.conf'
##############################
# The main program starts here
# Read configuration
Conf = libconf.config(USRIF_CONFIG)
# Open files index for writing
FBase = libfbase.filebase(Conf.spool_dir)
FBase.open('cwf')
file = libfbase.file()
# Process aliases from 'alias-list-file'
for alias in Conf.read_alias_list():
print 'Processing alias "%s": %s' % (alias.name, alias.filename)
file_desc = libfbase.get_file_desc(alias.filename)
file.set(alias.filename, name = alias.name, desc = file_desc)
file.stat()
FBase.put(file)
# Process dirs from 'dir-list-file'
for dir in Conf.read_dir_list():
area_desc = libfbase.get_area_desc(dir)
print 'Processing: %s (%s)' % (dir, area_desc)
files_list = posix.listdir(dir)
for file_name in files_list:
full_name = os.path.join(dir, file_name)
if os.path.isfile(full_name):
file_desc = libfbase.get_file_desc(full_name)
file.set(full_name, area = area_desc, desc = file_desc)
file.stat()
FBase.put(file)
# Purge files index
#print 'Purging removed files from files index'
#FBase.clean()
FBase.close()
sys.exit(0)
+35
View File
@@ -0,0 +1,35 @@
#!/usr/local/bin/python
import sys
# Our own libraries
sys.path.append('./lib')
import uconfig
import udbase
from uutil import *
USRIF_CONFIG = '/usr/local/etc/u-srif/u-srif.conf'
##############################
# The main program starts here
if len(sys.argv) < 2:
print 'usage:', sys.argv[0], '<[file] [file] ..>'
sys.exit(1)
# Read configuration
Conf = uconfig.Config(USRIF_CONFIG)
# Lookup files in the database
FBase = udbase.filebase(Conf.spool_dir)
FBase.open('r')
yield = FBase.get_all(sys.argv[1:])
FBase.close()
# Pretty printing
print file_info_header
for file in yield:
file.stat()
print format_file_info(file.name, file.size, file.desc)
sys.exit(0)
+182
View File
@@ -0,0 +1,182 @@
#!/usr/local/bin/python
import string
import sys
import os
# Our own libraries
sys.path.append('./lib')
import uconfig
import udbase
import ufido
import utmpl
import unodestat
from uutil import *
USRIF_CONFIG = '/usr/local/etc/u-srif/u-srif.conf'
class freq_report(ufido.message):
def write_packet(self, pktname):
self.packet.addr_orig = self.addr_orig
self.packet.addr_dest = self.addr_dest
self.packet.write(pktname)
def add_file(self, name, size, desc):
text = format_file_info(name, size, desc)
self.append_text(text)
def __init__(self):
ufido.message.__init__(self)
self.packet = ufido.packet()
self.packet.add_message(self)
class srif_file:
def read_req_list(self):
yield = []
fp = open(self.requestlist, 'r')
line = fp.readline()
while line:
line = string.strip(line)
yield.append(line)
line = fp.readline()
fp.close()
return yield
def write_resp_list(self, list):
fp = open(self.responselist, 'w')
for file in list:
fp.write('+' + file + '\n')
fp.close()
def read(self, name):
fp = open(name, 'r')
line = fp.readline()
while line:
line = string.strip(line)
args = string.split(line, None, 1)
if len(args) == 2:
if string.lower(args[0]) == 'sysop':
self.sysop = args[1]
if string.lower(args[0]) == 'aka':
self.aka.parse(args[1])
elif string.lower(args[0]) == 'baud':
self.baud = args[1]
elif string.lower(args[0]) == 'requestlist':
self.requestlist = args[1]
elif string.lower(args[0]) == 'responselist':
self.responselist = args[1]
elif string.lower(args[0]) == 'remotestatus':
self.remotestatus = args[1]
elif string.lower(args[0]) == 'systemstatus':
self.systemstatus = args[1]
elif string.lower(args[0]) == 'site':
self.site = args[1]
elif string.lower(args[0]) == 'callerid':
self.callerid = args[1]
elif string.lower(args[0]) == 'password':
self.password = args[1]
else:
print "skipping keyword", args[0], "in SRIF"
line = fp.readline()
fp.close()
def __init__(self, name):
self.sysop = ''
self.aka = ufido.address()
self.baud = 0
self.requestlist = ''
self.responselist = ''
self.remotestatus = ''
self.systemstatus = ''
self.site = ''
self.callerid = ''
self.password = ''
self.read(name)
def remote_addr(self):
return self.aka
def isprotected(self):
if string.lower(self.remotestatus) == 'protected':
return 1
return 0
def islisted(self):
if string.lower(self.systemstatus) == 'listed':
return 1
return 0
def append_new_file(fileslist, file):
TotalFiles = TotalFiles + 1
TotalSize = TotalSize + file.size
fileslist.append(file.fullname)
##############################
# The main program starts here
# Global variables
yield_list = []
if len(sys.argv) <> 2:
print 'usage: u-srif <srif file name>'
sys.exit(1)
# Read configuration
conf = uconfig.Config(USRIF_CONFIG)
# Read SRIF files
srif = srif_file(sys.argv[1])
# Read node's statistic
nodestat = unodestat.nodestat(conf.stat_dbase, srif.aka)
nodestat.get_stat()
# Lookup requested files in the our database
FBase = udbase.filebase(conf.spool_dir)
FBase.open('r')
yield = FBase.get_all(srif.read_req_list())
FBase.close()
# Prepare found files for sending
for file in yield:
if not file.fake:
file.stat()
nodestat.upd_stat(1, file.size)
yield_list.append(file.fullname)
# Store node's statistic
nodestat.put_stat()
# Send FREQ report?
if conf.send_report:
# Prepare templates object
tmpl = utmpl.template()
tmpl.set(srif=srif, conf=conf, nodestat=nodestat)
# Setup report object
report = freq_report()
report.newmsg(conf.local_address, conf.report_from, \
srif.aka, srif.sysop, conf.report_subj)
report.append_line('')
# Append header
tmpl.readfile(conf.report_header)
text = tmpl.process()
if text:
report.append_text(text)
# Append per files statistic
for file in yield:
report.add_file(file.name, file.size, file.desc)
# Append footer
tmpl.readfile(conf.report_footer)
text = tmpl.process()
if text:
report.append_text(text)
# Add empty line to the report
report.append_line('')
# Create netmail packet with the FREQ report
pktname = '/var/tmp/12345678.pkt' # XXX
report.write_packet(pktname)
# Add packet file to the response files list
yield_list.append(pktname)
# Dump reponse list
srif.write_resp_list(yield_list)
sys.exit(0)