--- inn-1.7.2q.orig/extra/innreport +++ inn-1.7.2q/extra/innreport @@ -0,0 +1,2596 @@ +#! /usr/bin/perl +require '/usr/lib/news/innshellvars.pl'; + +########################################################################## +# +# innreport: Perl script to summarize news log files +# (with optional HTML output and graphs). +# +# version: 3.0.2 +# +# Copyright (c) 1996-1999, Fabien Tassin (fta@sofaraway.org). +# +########################################################################## +# +# Usage: innreport -f config_file [-[no]options] logfile [logfile2 [...]] +# where options are: +# -h (or -help) : this help page +# -html : HTML output +# -v : display the version number of INNreport +# -f config_file : name of the configuration file +# -config : print INNreport configuration information +# -g : want graphs [default] +# -graph : an alias for option -g +# -d directory : directory for Web pages +# -dir directory : an alias for option -d +# -p directory : pictures path (file space) +# -path directory : an alias for option -p +# -w directory : pictures path (web space) +# -webpath directory : an alias for option -w +# -i : name of index page +# -index : an alias for option -i +# -a : want to archive HTML results +# -archive : an alias for option -a +# -c number : how many report files to keep (0 = all) +# -cycle number : an alias for option -c +# -s char : separator for filename +# -separator char : an alias for option -s +# -unknown : Unknown entries from news log file +# -maxunrec : Max number of unrecognized line to display +# -casesensitive : Case sensitive +# -notdaily : Never perform daily actions +# +# Use no in front of boolean options to unset them. +# For example, "-html" is set by default. Use "-nohtml" to remove this +# feature. +# +########################################################################## +# +# ABSOLUTELY NO WARRANTY WITH THIS PACKAGE. USE IT AT YOUR OWN RISKS. +# +# Note: You need the Perl graphic library GD.pm if you want the graphs. +# GD is available on all good CPAN ftp sites: +# ex: [CPAN_DIR]/authors/id/LDS/GD-1.1_.tar.gz (or greater) +# or directly to: +# +# Note : innreport will create PNG or GIF files depending upon +# the GD version. +# +# Documentation: for a short explaination of the different options, you +# can read the usage (obtained with the -h or -help switch). +# +# Install: - check the Perl location (first line). Require Perl 5.002 +# or greater. +# - look at the parameters in the configuration file (section +# 'default') +# - copy the configuration file into ${PATHETC}/innreport.conf +# - copy the INN module into ${PATHETC}/innreport_inn.pm +# - copy this script into ${PATHETC}/innreport +# - be sure that the news user can run it (chmod 755 or 750) +# - in "scanlog", comment the line containing innlog and add: +# ${PATHETC}/innreport -f ${PATHETC}/innreport.conf ${OLD_SYSLOG} +# or, if you want to change some options: +# ${PATHETC}/innreport -f ${PATHETC}/innreport.conf options ${OLD_SYSLOG} +# +# Report: please report bugs (preferably) to the innreport mailing list +# (see below) or directly to the author (do not forget to +# include the result of the "-config" switch, the parameters +# passed on the command line and the INN version). +# Please also report unknown entries. +# Be sure your are using the latest version of this script before +# any report. +# (check ) +# +########################################################################## + +# remember to add '-w' on the first line and to uncomment the 'use strict' +# below before doing any changes to this file. + +use strict; + +## Do you want to create a Web page. Pick DO or DONT. +my $HTML = "DONT"; + +## Do you want the graphs (need $HTML too). Pick DO or DONT. +my $GRAPH = "DO"; + +## Directory for the Web pages (used only if the previous line is active) +my $HTML_dir = "/var/www/News/stats"; + +## Directory for the pictures (need HTML support) in the file space +my $IMG_dir = "$HTML_dir/pics"; + +## Directory for the pictures (need HTML support) in the Web space +## (can be relative or global) +my $IMG_pth = "pics"; + +## Do you want to archive HTML results (& pics) [ will add a date in each +## name ]. Pick DO or DONT. +my $ARCHIVE = "DO"; + +## index page will be called: +my $index = "index.html"; + +## How many report files to keep (0 = all) (need $ARCHIVE). +my $CYCLE = 30; + +## separator between hours-minutes-seconds in filenames +## (normaly a ":" but some web-browsers (Lynx, MS-IE, Mosaic) can't read it) +## Warning: never use "/". Use only a _valid_ filename char. +my $SEPARATOR = "."; + +## Do you want the "Unknown entries from news log file" report. Pick DO or +## DONT. +my $WANT_UNKNOWN = "DO"; + +## Max number of unrecognized lines to display (if $WANT_UNKNOWN) +## (-1 = no limit) +my $MAX_UNRECOGNIZED = 50; + +## Do you want to be case sensitive. Pick DO or DONT. +my $CASE_SENSITIVE = "DO"; + +## Some actions must only be performed daily (once for a log file). +## (ex: unwanted.log with INN). Default value (DONT) means to perform +## these actions each . Pick DO or DONT. +my $NOT_DAILY = "DONT"; + +############################################### +## THERE'S NOTHING TO CHANGE AFTER THIS LINE ## +############################################### + +my $version = "3.0.2"; +my %output; # content of the configuration file. +my $DEBUG = 0; # set to 1 to verify the structure/content of the conf file. +my $start_time = time; + +# Require Perl 5.002 or greater. +require 5.002; +use Getopt::Long; +use vars qw/$HAVE_GD $GD_FORMAT/; + +my @old_argv = @ARGV; + +# Convert DO/DONT into boolean values. +{ + my $i; + foreach $i (\$HTML, \$GRAPH, \$ARCHIVE, \$WANT_UNKNOWN, + \$CASE_SENSITIVE, \$NOT_DAILY) { + $$i = $$i eq 'DO' ? 1 : 0 ; + } +} + +my %ref; +GetOptions (\%ref, + qw(-h -help + -html! + -config + -f=s + -g! -graph! + -d=s -dir=s + -p=s -path=s + -w=s -webpath=s + -i=s -index=s + -a! -archive! + -c=i -cycle=i + -s=s -separator=s + -unknown! + -html-unknown! + -maxunrec=i + -casesensitive! + -notdaily! + -v + )); + +&Version if $ref{'v'}; + +&Decode_Config_File($ref{'f'}) if defined $ref{'f'}; +&Usage if $ref{'h'} || $ref{'help'} || !defined $ref{'f'}; + +$HTML = 0 if defined $output{'default'}{'html'}; +$HTML = 1 if $output{'default'}{'html'} eq 'true'; +$HTML = 0 if defined $ref{'html'}; +$HTML = 1 if $ref{'html'}; + +$GRAPH = 0 if defined $output{'default'}{'graph'}; +$GRAPH = 1 if $HTML && ($output{'default'}{'graph'} eq 'true'); +$GRAPH = 0 if defined $ref{'g'} || defined $ref{'graph'}; +$GRAPH = 1 if $HTML && ($ref{'g'} || $ref{'graph'}); + +$HTML_dir = &GetValue ($output{'default'}{'html_dir'}) + if defined $output{'default'}{'html_dir'}; +$HTML_dir = $ref{'d'} if defined $ref{'d'}; +$HTML_dir = $ref{'dir'} if defined $ref{'dir'}; + +$IMG_pth = &GetValue ($output{'default'}{'img_dir'}) + if defined $output{'default'}{'img_dir'}; +$IMG_pth = $ref{'w'} if defined $ref{'w'}; +$IMG_pth = $ref{'webpath'} if defined $ref{'webpath'}; + +$IMG_dir = $HTML_dir . "/" . $IMG_pth + if (defined $output{'default'}{'html_dir'} || + defined $ref{'w'} || defined $ref{'webpath'}) + && + (defined $output{'default'}{'html_dir'} || + defined $ref{'d'} || defined $ref{'dir'}); + +$IMG_dir = $ref{'p'} if defined $ref{'p'}; +$IMG_dir = $ref{'path'} if defined $ref{'path'}; + +$index = &GetValue ($output{'default'}{'index'}) + if defined $output{'default'}{'index'}; +$index = $ref{'i'} if defined $ref{'i'}; +$index = $ref{'index'} if defined $ref{'index'}; + +$ARCHIVE = &GetValue ($output{'default'}{'archive'}) + if defined $output{'default'}{'archive'}; +$ARCHIVE = $ARCHIVE eq 'true'; +$ARCHIVE = 0 if defined $ref{'a'} || defined $ref{'archive'}; +$ARCHIVE = 1 if ($ref{'a'} || $ref{'archive'}) && $HTML; +$ARCHIVE = 0 unless $HTML; + +$CYCLE = &GetValue ($output{'default'}{'cycle'}) + if defined $output{'default'}{'cycle'}; +$CYCLE = 0 if $CYCLE eq 'none'; +$CYCLE = $ref{'c'} if defined $ref{'c'}; +$CYCLE = $ref{'cycle'} if defined $ref{'cycle'}; + +$SEPARATOR = &GetValue ($output{'default'}{'separator'}) + if defined $output{'default'}{'separator'}; +$SEPARATOR = $ref{'s'} if defined $ref{'s'}; +$SEPARATOR = $ref{'separator'} if defined $ref{'separator'}; + +if (defined $output{'default'}{'unknown'}) { + $WANT_UNKNOWN = &GetValue ($output{'default'}{'unknown'}); + $WANT_UNKNOWN = $WANT_UNKNOWN eq 'true' ? 1 : 0; +} +$WANT_UNKNOWN = 0 if defined $ref{'unknown'}; +$WANT_UNKNOWN = 1 if $ref{'unknown'}; + +my $WANT_HTML_UNKNOWN = $WANT_UNKNOWN; +if (defined $output{'default'}{'html-unknown'}) { + $WANT_HTML_UNKNOWN = &GetValue ($output{'default'}{'html-unknown'}); + $WANT_HTML_UNKNOWN = $WANT_HTML_UNKNOWN eq 'true' ? 1 : 0; +} +$WANT_HTML_UNKNOWN = 0 if defined $ref{'html-unknown'}; +$WANT_HTML_UNKNOWN = 1 if $ref{'html-unknown'}; + +$NOT_DAILY = 0 if defined $ref{'notdaily'}; +$NOT_DAILY = 1 if $ref{'notdaily'}; + +$MAX_UNRECOGNIZED = &GetValue ($output{'default'}{'max_unknown'}) + if defined $output{'default'}{'max_unknown'}; +$MAX_UNRECOGNIZED = $ref{'maxunrec'} if defined ($ref{'maxunrec'}); + +$CASE_SENSITIVE = &GetValue ($output{'default'}{'casesensitive'}) + if defined $output{'default'}{'casesensitive'}; +$CASE_SENSITIVE = 1 if $CASE_SENSITIVE eq 'true'; +$CASE_SENSITIVE = 0 if defined $ref{'casesensitive'}; +$CASE_SENSITIVE = 1 if $ref{'casesensitive'}; + +my $CLASS = &GetValue ($output{'default'}{'module'}); +my $LIBPATH = &GetValue ($output{'default'}{'libpath'}); + +umask 022; + +BEGIN { + eval "use GD;"; + $HAVE_GD = $@ eq ''; + if ($HAVE_GD) { + my $gd = new GD::Image(1,1); + $GD_FORMAT = "gif" if $gd->can('gif'); + $GD_FORMAT = "png" if $gd->can('png'); + } + $HAVE_GD; +}; +undef $GRAPH unless $HTML; +if ($GRAPH && !$::HAVE_GD) { + print "WARNING: can't make graphs as required.\n" . + " Install GD.pm or disable this option.\n\n"; + undef $GRAPH; +} + +if ($HTML) { + if ($GRAPH) { + $IMG_dir = "." if defined $IMG_dir && $IMG_dir eq ''; + $IMG_pth .= "/" if $IMG_pth; + $IMG_pth =~ s|/+|/|g; + $IMG_dir =~ s|/+|/|g; + unless (-w $IMG_dir) { + print "WARNING: can't write in \"$IMG_dir\" as required by -g " . + "switch.\n Option -g removed. Please see the -p switch.\n\n"; + undef $GRAPH; + } + } + $HTML_dir = "." if defined $HTML_dir && $HTML_dir eq ''; + unless (-w $HTML_dir) { + print "WARNING: can't write in \"$HTML_dir\" as required by -html " . + "switch.\n Option -html and -a removed. Please see the " . + "-d switch.\n\n"; + undef $HTML; + $ARCHIVE = 0; + } +} + +# Now, we are sure that HTML and graphs can be made if options are active. +&Summary if defined $ref{'config'}; + +my $unrecognize_max = 0; +my @unrecognize; +my ($total_line, $total_size) = (0, 0); +my ($suffix, $HTML_output, %config, $first_date, $last_date, + %prog_type, %prog_size); + +my $HTML_header = ''; +my $HTML_footer = ''; + +my $MIN = 1E10; +my $MAX = -1; + +my $xmax = &GetValue ($output{'default'}{'graph_width'}) # Graph size.. + if defined $output{'default'}{'graph_width'}; +$xmax = 550 unless $xmax; + +my $transparent = &GetValue ($output{'default'}{'transparent'}) + if defined $output{'default'}{'transparent'}; +$transparent = (defined $transparent && $transparent eq 'true') ? 1 : 0; + +my $repeated = 1; + +my $first_date_cvt = $MIN; +my $last_date_cvt = $MAX; + + +######################################################################### +my $s = sprintf "use lib qw($LIBPATH); use $CLASS;"; +eval $s; # initialization +die "Can't find/load $CLASS.pm : $@\n" if $@; + +my $save_line = <>; +$_ = $save_line; +local $^W = 0 if $] < 5.004; # to avoid a warning for each '+=' first use. +LINE: while (!eof ()) { + $total_line++; + my $size = length; + $total_size += $size; + + # Syslog optimization + if ($repeated) { + $repeated--; + $_ = $save_line; + } + else { + $_ = <>; + if ($_ =~ /last message repeated (\d+) times?$/o) { + $repeated = $1; + $_ = $save_line; + } + else { + $save_line = $_; + } + } + + # skip empty lines + next LINE if $_ eq ''; + + my $res; + my ($day, $hour, $prog, $left) = + $_ =~ m/^(\S+\s+\S+) (\S+) \S+ (\S+): \[ID \d+ \S+\] (.*)$/o; + ($day, $hour, $prog, $left) = + $_ =~ m/^(\S+\s+\S+) (\S+) \S+ (\S+): (.*)$/o unless $day; + ($day, $hour, $prog, $left) = + $_ =~ m/^(\S+\s+\S+) (\S+) \d+ \S+ (\S+): (.*)$/o unless $day; + + unless ($day) { + ($day, $hour, $res, $left) = $_ =~ m/^(\S+\s+\S+) (\S+)\.\d+ (\S+) (.*)$/o; + if ($day) { + my $cvtdate = &ConvDate ("$day $hour"); + if ($cvtdate < $first_date_cvt) { + $first_date_cvt = $cvtdate; + $first_date = "$day $hour"; + } + elsif ($cvtdate > $last_date_cvt) { + $last_date_cvt = $cvtdate; + $last_date = "$day $hour"; + } + $prog = "inn"; + } + else { + next if $_ =~ /^$/; + # Unrecognize line... skip + $unrecognize[$unrecognize_max] = $_ + unless $unrecognize_max > $MAX_UNRECOGNIZED + && $MAX_UNRECOGNIZED > 0; + $unrecognize_max++; + next LINE; + } + } + else { + my $cvtdate = &ConvDate ("$day $hour"); + if ($cvtdate < $first_date_cvt) { + $first_date_cvt = $cvtdate; + $first_date = "$day $hour"; + } + elsif ($cvtdate > $last_date_cvt) { + $last_date_cvt = $cvtdate; + $last_date = "$day $hour"; + } + } + + ######## + ## Program name + # word[7164] -> word + my ($pid) = $prog =~ s/\[(\d+)\]$//o; + # word: -> word + $prog =~ s/:$//o; + # wordX -> word (where X is a digit) + $prog =~ s/\d+$//o; + + $prog_type{$prog}++; + $prog_size{$prog} = 0 unless defined $prog_size{$prog}; # stupid warning :( + $prog_size{$prog} += $size; + + # The "heart" of the tool. + { + no strict; + next LINE if + &{$CLASS."::collect"} ($day, $hour, $prog, $res, $left, $CASE_SENSITIVE); + } + + $unrecognize[$unrecognize_max] = $_ + unless $unrecognize_max > $MAX_UNRECOGNIZED + && $MAX_UNRECOGNIZED > 0; + $unrecognize_max++; +} + +{ + no strict; + &{$CLASS . "::adjust"} ($first_date, $last_date); +} + +$| = 1; + +die "no data. Abort.\n" unless $total_line; + +my $sec_glob = &ConvDate ("$last_date") - &ConvDate ("$first_date"); +unless ($sec_glob) { + print "WARNING: bad date (\"$last_date\" or \"$first_date\")\n" . + " Please, contact the author of innreport.\n"; + $sec_glob = 24 * 60 * 60; # one day +} + +$HTML_output = ''; + +if ($HTML) { + # Create a new filename (unique and _sortable_) + if ($ARCHIVE) { + # The filename will contain the first date of the log or the current time. + my ($ts, $tm, $th, $dd, $dm, $dy) = localtime; + my ($m, $d, $h, $mn, $s) = + $first_date =~ /^(\S+)\s+(\d+)\s+(\d+):(\d+):(\d+)$/; + if ($m) { + my $ddm = (index "JanFebMarAprMayJunJulAugSepOctNovDec", $m) / 3; + # Adjust the year because syslog doesn't record it. We assume that + # it's the current year unless the last date is in the future. + my $ld = &ConvDate($last_date); + $dy-- if $ld > $ts + 60 * ($tm + 60 * ($th + 24 * ($dd - 1 + + substr("000031059090120151181212243273304334", $dm * 3, 3)))) || + $ld < &ConvDate($first_date); + ($dm, $dd, $th, $tm, $ts) = ($ddm, $d, $h, $mn, $s); + } + $dm++; # because January = 0 and we prefer 1 + $dy += 100 if $dy < 90; # Try to pacify the year 2000 ! + $dy += 1900; + $suffix = sprintf ".%02d.%02d.%02d-%02d$SEPARATOR%02d$SEPARATOR%02d", + $dy, $dm, $dd, $th, $tm, $ts; + } + else { + $suffix = ''; + } + $HTML_output = "$HTML_dir" . "/news-notice" . "$suffix" . ".html"; + $HTML_output =~ s|/+|/|g; + if (defined $output{'default'}{'html_header_file'}) { + my $file = &GetValue ($output{'default'}{'html_header_file'}); + $file = $HTML_dir . "/" . $file; + open (F, $file) && do { + local $/ = undef; + $HTML_header = ; + close F; + }; + } + if (defined $output{'default'}{'html_footer_file'}) { + my $file = &GetValue ($output{'default'}{'html_footer_file'}); + $file = $HTML_dir . "/" . $file; + open (F, $file) && do { + local $/ = undef; + $HTML_footer = ; + close F; + }; + } +} + +&Write_all_results ($HTML_output, \%output); + +&Make_Index ($HTML_dir, $index, "news-notice$suffix.html", \%output) + if $HTML && $index; + +#==================================================================== + +if ($ARCHIVE) { + # rotate html files + &Rotate ($CYCLE, $HTML_dir, "news-notice", ".html"); + + # rotate pictures + my $report; + foreach $report (@{$output{'_order_'}}) { + next if $report =~ m/^(default|index)$/; + next unless defined $output{$report}{'graph'}; + + my $i = 0; + while ($GRAPH && defined ${${$output{$report}{'graph'}}[$i]}{'type'}) { + my $name = $report . ($i ? $i : ''); + &Rotate ($CYCLE, $IMG_dir, $name, '.' . $GD_FORMAT); + $i++; + } + } +} + +# Code needed by INN only. It must be in innreport_inn.pm to keep things clean. +if (!$NOT_DAILY && defined $output{'default'}{'unwanted_log'}) { + my $logfile = &GetValue ($output{'default'}{'unwanted_log'}); + my $logpath = &GetValue ($output{'default'}{'logpath'}); + { + no strict; + &{$CLASS . "::report_unwanted_ng"} ("$logpath/$logfile"); + } +} + +################ +# End of report. +################################################################### + +###### +# Misc... + +# Compare 2 dates (+hour) +sub DateCompare { + # ex: "May 12 06" for May 12, 6:00am + local $[ = 0; + # The 2 dates are near. The range is less than a few days that's why we + # can cheat to determine the order. It is only important if one date + # is in January and the other in December. + + my $date1 = substr ($a, 4, 2) * 24; + my $date2 = substr ($b, 4, 2) * 24; + $date1 += index("JanFebMarAprMayJunJulAugSepOctNovDec",substr($a,0,3)) * 288; + $date2 += index("JanFebMarAprMayJunJulAugSepOctNovDec",substr($b,0,3)) * 288; + if ($date1 - $date2 > 300 * 24) { + $date2 += 288 * 3 * 12; + } + elsif ($date2 - $date1 > 300 * 24) { + $date1 += 288 * 3 * 12; + } + $date1 += substr($a, 7, 2); + $date2 += substr($b, 7, 2); + $date1 - $date2; +} + + +# Convert: seconds to hh:mm:ss +sub second2time { + my $temp; + my $t = shift; + # Hours + $temp = sprintf "%02d", $t / 3600; + my $chaine = "$temp:"; + $t %= 3600; + # Min + $temp = sprintf "%02d", $t / 60; + $chaine .= "$temp:"; + $t %= 60; + # Sec + $chaine .= sprintf "%02d", $t; + return $chaine; +} + +# Convert: milliseconds to hh:mm:ss:mm +sub ms2time { + my $temp; + my $t = shift; + # Hours + $temp = sprintf "%02d", $t / 3600000; + my $chaine = "$temp:"; + $t %= 3600000; + # Min + $temp = sprintf "%02d", $t / 60000; + $chaine .= "$temp:"; + $t %= 60000; + # Sec + $temp = sprintf "%02d", $t / 1000; + $chaine .= "$temp."; + $t %= 1000; + # Millisec + $chaine .= sprintf "%03d", $t; + return $chaine; +} + +# Rotate the archive files.. +sub Rotate { + # Usage: &Rotate ($max_files, "$directory", "prefix", "suffix"); + my ($max, $rep, $prefix, $suffix) = @_; + my ($file, $num, %files); + local ($a, $b); + + return 1 unless $max; + opendir (DIR, "$rep") || die "Error: Cant open directory \"$rep\"\n"; + + FILE : while (defined ($file = readdir (DIR))) { + next FILE + unless $file =~ /^ # e.g. news-notice.1997.05.14-01:34:29.html + $prefix # Prefix : news-notice + \. # dot : . + (\d\d)?\d\d # Year : 1997 (or 97) + \. # dot : . + \d\d # Month : 05 + \. # dot : . + \d\d # Day : 14 + - # Separator : - + \d\d # Hour : 01 + $SEPARATOR # Separator : ":" + \d\d # Minute : 34 + $SEPARATOR # Separator : ":" + \d\d # Second : 29 + $suffix # Suffix : ".html" + $/x; + $files{$file}++; + } + closedir DIR; + $num = 0; + foreach $file (sort {$b cmp $a} (keys (%files))) { + unlink "$rep/$file" if $num++ >= $max && -f "$rep/$file"; + } + return 1; +} + +# convert a date to a number of seconds +sub ConvDate { + # usage: $num = &ConvDate ($date); + # date format is Aug 22 01:49:40 + my $T = shift; + my ($m, $d, $h, $mn, $s) = $T =~ /^(\S+)\s+(\d+)\s+(\d+):(\d+):(\d+)$/; + my $out = $s + 60 * $mn + 3600 * $h + 86400 * ($d - 1); + + $m = substr("000031059090120151181212243273304334", + index ("JanFebMarAprMayJunJulAugSepOctNovDec", $m), 3); + $out += $m * 86400; + return $out; +} + +# Compare 2 filenames +sub filenamecmp { + local $[ = 0; + my ($la, $lb) = ($a, $b); + my ($ya) = $la =~ m/news-notice\.(\d+)\./o; + $ya += 100 if $ya < 90; # Try to pacify the year 2000 ! + $ya += 1900 if $ya < 1900; # xx -> xxxx + my ($yb) = $lb =~ m/news-notice\.(\d+)\./o; + $yb += 100 if $yb < 90; # Try to pacify the year 2000 ! + $yb += 1900 if $yb < 1900; # xx -> xxxx + + $la =~ s/news-notice\.(\d+)\./$ya\./; + $lb =~ s/news-notice\.(\d+)\./$yb\./; + $la =~ s/[\.\-\:html]//g; + $lb =~ s/[\.\-\:html]//g; + + $lb <=> $la; +} + +sub ComputeTotal { + my $h = shift; + my $total = 0; + my $key; + foreach $key (keys (%$h)) { + $total += $$h{$key}; + } + $total; +} + +sub ComputeTotalDouble { + my $h = shift; + my $total = 0; + my ($key1, $key2); + foreach $key1 (keys (%$h)) { + foreach $key2 (keys (%{$$h{$key1}})) { + $total += ${$$h{$key1}}{$key2}; + } + } + $total; +} + +# make an index for archive pages +sub Make_Index { + my ($rep, $index, $filename, $data) = @_; + my %output = %$data; + + $index =~ s/^\"\s*(.*?)\s*\"$/$1/o; + + # add requested data at the end of the database. + open (DATA, ">> $rep/innreport.db") || die "can't open $rep/innreport.db\n"; + my $i = 0; + my $res = "$filename"; + while (defined ${${$output{'index'}{'column'}}[$i]}{'value'}) { + my $data = &GetValue (${${$output{'index'}{'column'}}[$i]}{'value'}); + $data =~ s/\n//sog; + my @list = split /\|/, $data; + my $val; + foreach $val (@list) { + $res .= ($val eq 'date' ? "|$first_date -- $last_date" + : "|" . &EvalExpr($val)); + } + $i++; + } + print DATA "$res\n"; + close DATA; + + # sort the database (reverse order), remove duplicates. + open (DATA, "$rep/innreport.db") || die "can't open $rep/innreport.db\n"; + my %data; + while () { + m/^([^\|]+)\|(.*)$/o; + $data{$1} = $2; + } + close DATA; + open (DATA, "> $rep/innreport.db") || die "can't open $rep/innreport.db\n"; + $i = 0; + foreach (sort {$b cmp $a} (keys %data)) { + print DATA "$_|$data{$_}\n" if $CYCLE == 0 || $i < $CYCLE; + $i++; + } + close DATA; + + my $title = "Daily Usenet report"; + $title = &GetValue ($output{'default'}{'title'}) + if defined $output{'default'}{'title'}; + $title =~ s/\\\"/\"/g; + my $Title = $title; + $Title =~ s/<.*?>//g; + my $body = ''; + $body = &GetValue ($output{'default'}{'html_body'}) + if defined $output{'default'}{'html_body'}; + $body =~ s/\\\"/\"/go; + my $result = sprintf < + +$Title: index + +$HTML_header +
+
+$title - archives +
+
+

+

+EOF + + if ($GRAPH) { + my $i = 0; + while (defined ${${$output{'index'}{'graph'}}[$i]}{'title'}) { + my $title = &GetValue (${${$output{'index'}{'graph'}}[$i]}{'title'}); + my $filename = "index$i.$GD_FORMAT"; + my $color_bg = &GetValue (${${$output{'index'}{'graph'}}[$i]}{'color'}); + my $unit = &GetValue (${${$output{'index'}{'graph'}}[$i]}{'unit'}); + my $date_idx = &GetValue (${${$output{'index'}{'graph'}}[$i]}{'value'}); + $date_idx =~ s/^val(\d+)$/$1/o; + my @c = @{${${$output{'index'}{'graph'}}[$i]}{'data'}}; + my $label_in = &GetValue (${$c[0]}{'name'}); + my $color_in = &GetValue (${$c[0]}{'color'}); + my $value_in = &GetValue (${$c[0]}{'value'}); + my $type_in = 0; + $type_in = $value_in =~ s/^byte\((.*?)\)$/$1/o; + $value_in =~ s/^val(\d+)$/$1/o; + my $label_out = &GetValue (${$c[1]}{'name'}); + my $color_out = &GetValue (${$c[1]}{'color'}); + my $value_out = &GetValue (${$c[1]}{'value'}); + my $type_out = 0; + $type_out = $value_out =~ s/^byte\((.*?)\)$/$1/o; + $value_out =~ s/^val(\d+)$/$1/o; + my (%in, %out, %dates, $k); + foreach $k (keys (%data)) { + my @res = split /\|/, $data{$k}; + my ($year) = $k =~ m/^news-notice\.(\d+)\.\d+\.\d+-\d+.\d+.\d+\.html/; + next unless $year; # bad filename.. strange. + my ($start, $end) = + $res[$date_idx - 1] =~ m/^(\w+\s+\d+ \S+) -- (\w+\s+\d+ \S+)$/o; + next unless $start; # bad date + $start = &ConvDate ($start); + $end = &ConvDate ($end); + # 31/12 - 1/1 ? + my $inc = $end < $start ? 1 : 0; + $start += (($year - 1970) * 365 + + int (($year - 1968) / 4)) * 3600 * 24; + $year += $inc; + $end += (($year - 1970) * 365 + int (($year - 1968) / 4)) * 3600 * 24; + $in{$start} = $type_in ? &kb2i($res[$value_in - 1]) + : $res[$value_in - 1]; + $out{$start} = $type_out ? &kb2i($res[$value_out - 1]) + : $res[$value_out - 1]; + $dates{$start} = $end; + } + my ($xmax, $ymax) = (500, 170); + &Chrono ("$IMG_dir/$filename", $title, $color_bg, $xmax, $ymax, + \%in, \%out, \%dates, $label_in, $label_out, + $color_in, $color_out, $unit); + $result .= "\"Graph\"\n"; + $i++; + } + $result .= "

\n"; + } + $i = 0; + $result .= ""; + my $temp = ''; + while (defined ${${$output{'index'}{'column'}}[$i]}{'title'}) { + my $title = &GetValue (${${$output{'index'}{'column'}}[$i]}{'title'}); + my $name = ''; + $name = &GetValue (${${$output{'index'}{'column'}}[$i]}{'name'}) + if defined ${${$output{'index'}{'column'}}[$i]}{'name'}; + my @list = split /\|/, $name; + if ($name) { + $result .= sprintf "", $#list + 1; + } + else { + $result .= ""; + } + foreach (@list) { + $temp .= ""; + } + $i++; + } + $result .= "\n$temp\n"; + + $i = 0; + foreach (sort {$b cmp $a} (keys %data)) { + if ($CYCLE == 0 || $i < $CYCLE) { + my @list = split /\|/, $data{$_}; + my $str = ""; + while (@list) { + $str .= ""; + } + $str .= "\n"; + $result .= "$str"; + } + $i++; + } + $result .= "
$title$title$_
"; + $str .= "" if -e "$rep/$_"; + $str .= shift @list; + $str .= "" if -e "$rep/$_";; + $str .= ""; + my $t = shift @list; + $t =~ s/^\0+//o; # remove garbage, if any. + $str .= "$t
\n

\n


"; + $result .= "innreport"; + $result .= " $version (c) 1996-1999 "; + $result .= "by Fabien Tassin <"; + $result .= "fta\@sofaraway.org>.\n"; + if (defined ($output{'default'}{'footer'})) { + my ($t) = $output{'default'}{'footer'} =~ m/^\"\s*(.*?)\s*\"$/o; + $t =~ s/\\\"/\"/go; + $result .= "
" . $t; + } + $result .= "$HTML_footer\n\n\n"; + my $name = $rep . "/" . $index; + while ($name =~ m/\/\.\.\//o) { + $name =~ s|^\./||o; # ^./xxx => ^xxx + $name =~ s|/\./|/|go; # xxx/./yyy => xxx/yyy + $name =~ s|/+|/|go; # xxx//yyy => xxx/yyy + $name =~ s|^/\.\./|/|o; # ^/../xxx => ^/xxx + $name =~ s|^[^/]+/\.\./||o; # ^xxx/../ => ^nothing + $name =~ s|/[^/]+/\.\./|/|go; # /yyy/../ => / + } + + open (INDEX, "> $name") || die "Error: Unable to create $name\n"; + print INDEX $result; + close INDEX; + 1; +} + +sub Graph3d { + my $filename = shift; # filename + my $title = shift; # title + my $xmax = shift; # width + my $n = shift; # Number of hash code tables + + no strict; + my ($i, $k, $t); + my @val; + for $i (0 .. $n - 1) { + push @val, shift; # hash code table + } + my $colors = shift; # colors table + my $labels = shift; # labels + + my $max = 0; + my $max_size = 0; + my $size = 0; + foreach $k (sort keys (%{$val[0]})) { + $t = 0; + $size++; + for $i (0 .. $n - 1) { + $t += ${$val[$i]}{$k} if defined ${$val[$i]}{$k}; + } + $max = $t if $max < $t; + $t = length "$k"; + $max_size = $t if $max_size < $t; + } + $max = 1 unless $max; + $max_size *= gdSmallFont->width; + + # relief + my ($rx, $ry) = (15, 5); + + # margins + my ($mt, $mb) = (40, 40); + my $ml = $max_size > 30 ? $max_size + 8 : 30; + + my $mr = 7 + (length "$max") * gdSmallFont->width; + $mr = 30 if $mr < 30; + + # height of each bar + my $h = 12; + + # difference between 2 bars + my $d = 25; + + my $ymax = $size * $d + $mt + $mb; + my $image = new GD::Image ($xmax, $ymax); + + my ($white, $black); + if (defined $output{'default'}{'graph_fg'}) { + my $t = $output{'default'}{'graph_fg'}; + $t =~ s/^\"\s*\#(.*?)\s*\"$/$1/o; + $t =~ m/^[\da-fA-F]{6}$/o || + die "Error in section 'default' section 'graph_fg'. Bad color.\n"; + my @c = map { hex ($_) } ($t =~ m/^(..)(..)(..)$/); + $black = $image->colorAllocate (@c); + } + else { + $black = $image->colorAllocate ( 0, 0, 0); + } + if (defined $output{'default'}{'graph_bg'}) { + my $t = $output{'default'}{'graph_bg'}; + $t =~ s/^\"\s*\#(.*?)\s*\"$/$1/o; + $t =~ m/^[\da-fA-F]{6}$/o || + die "Error in section 'default' section 'graph_bg'. Bad color.\n"; + my @c = map { hex ($_) } ($t =~ m/^(..)(..)(..)$/); + $white = $image->colorAllocate (@c); + } + else { + $white = $image->colorAllocate (255, 255, 255); + } + $image->filledRectangle (0, 0, $xmax, $ymax, $white); + my @col; + for $i (0 .. $n - 1) { + $col[$i][0] = $image->colorAllocate + ($$colors[$i][0], $$colors[$i][1], $$colors[$i][2]); + $col[$i][1] = $image->colorAllocate + ($$colors[$i][0] * 3 / 4, $$colors[$i][1] * 3 / 4, + $$colors[$i][2] * 3 / 4); + $col[$i][2] = $image->colorAllocate + ($$colors[$i][0] * 2 / 3, $$colors[$i][1] * 2 / 3, + $$colors[$i][2] * 2 / 3); + } + + $image->transparent ($white) if $transparent; + + $image->rectangle (0, 0, $xmax - 1, $size * $d + $mt + $mb - 1, $black); + $image->line (0, $mt - 5, $xmax - 1, $mt - 5, $black); + for $i (0 .. $n - 1) { + $image->string (gdSmallFont, $i * $xmax / $n + $mt - 10 + $rx, + ($mt - gdSmallFont->height) / 2, "$$labels[$i]", $black); + $image->filledRectangle ($i * $xmax / $n + 10, 8 + $ry / 2, + $i * $xmax / $n + $mt - 10, $mt - 12, $col[$i][0]); + $image->rectangle ($i * $xmax / $n + 10, 8 + $ry / 2, + $i * $xmax / $n + $mt - 10, $mt - 12, $black); + { + my $poly = new GD::Polygon; + $poly->addPt($i * $xmax / $n + 10, 8 + $ry / 2); + $poly->addPt($i * $xmax / $n + 10 + $rx / 2, 8); + $poly->addPt($i * $xmax / $n + $mt - 10 + $rx / 2, 8); + $poly->addPt($i * $xmax / $n + $mt - 10, 8 + $ry / 2); + + $image->filledPolygon($poly, $col[$i][1]); + $image->polygon($poly, $black); + } + { + my $poly = new GD::Polygon; + $poly->addPt($i * $xmax / $n + $mt - 10 + $rx / 2, 8); + $poly->addPt($i * $xmax / $n + $mt - 10, 8 + $ry / 2); + $poly->addPt($i * $xmax / $n + $mt - 10, $mt - 12); + $poly->addPt($i * $xmax / $n + $mt - 10 + $rx / 2, $mt - 12 - $ry / 2); + + $image->filledPolygon($poly, $col[$i][2]); + $image->polygon($poly, $black); + } + } + # Title + $image->string (gdMediumBoldFont, ($xmax - gdMediumBoldFont->width * + (length "$title")) / 2, $ymax - gdMediumBoldFont->height - 7, + "$title", $black); + + my $e = $mt - $h + $d; + my $r = ($xmax - $ml - $mr - $rx) / $max; + + # Axe Oz + $image->line ($ml + $rx, $mt, $ml + $rx, $size * $d + $mt - $ry, $black); + $image->line ($ml + $rx + $max * $r, $mt, $ml + $rx + $max * $r, + $size * $d + $mt - $ry, $black); + $image->line ($ml, $mt + $ry, $ml, $size * $d + $mt, $black); + # Axe Ox + $image->line ($ml + $rx, $size * $d + $mt - $ry, + $ml + $rx - 2 * $rx, $size * $d + $mt + $ry, $black); + # Axe Oy + $image->line ($ml + $rx, $size * $d + $mt - $ry, + $xmax - $mr / 2, $size * $d + $mt - $ry, $black); + $image->line ($ml, $size * $d + $mt, + $xmax - $mr - $rx, $size * $d + $mt, $black); + + # Graduations.. + my $nn = 10; + for $k (1 .. ($nn - 1)) { + $image->dashedLine ($ml + $rx + $k * ($xmax - $ml - $mr - $rx) / $nn, + $mt + 10, $ml + $rx + $k * ($xmax - $ml - $mr - $rx) / $nn, + $size * $d + $mt - $ry, $black); + $image->dashedLine ($ml + $rx + $k * ($xmax - $ml - $mr - $rx) / $nn, + $size * $d + $mt - $ry, + $ml + $k * ($xmax - $ml - $mr - $rx) / $nn, + $size * $d + $mt, $black); + $image->line ($ml + $k * ($xmax - $ml - $mr - $rx) / $nn, + $size * $d + $mt, + $ml + $k * ($xmax - $ml - $mr - $rx) / $nn, + $size * $d + $mt + 5, $black); + my $t = sprintf "%d%%", $k * 10; + $image->string (gdSmallFont, $ml + $k * ($xmax - $ml - $mr - $rx) / $nn - + (length "$t") * gdSmallFont->width / 2, + $size * $d + $mt + 6, "$t", $black); + } + { + my $t = sprintf "%d%%", 0; + $image->line ($ml, $size * $d + $mt, $ml, $size * $d + $mt + 5, $black); + $image->string (gdSmallFont, $ml - (length "$t") * gdSmallFont->width / 2, + $size * $d + $mt + 6, "$t", $black); + $image->line ($xmax - $mr, $size * $d + $mt - $ry, + $xmax - $mr - $rx, $size * $d + $mt, $black); + $image->line ($xmax - $mr - $rx, $size * $d + $mt, + $xmax - $mr - $rx, $size * $d + $mt + 5, $black); + $t = sprintf "%d%%", 100; + $image->string (gdSmallFont, $xmax - $mr - $rx + - (length "$t") * gdSmallFont->width / 2, + $size * $d + $mt + 6, "$t", $black); + } + foreach $k (sort {${$val[0]}{$b} <=> ${$val[0]}{$a}} keys (%{$val[0]})) { + $image->string (gdSmallFont, $ml - (length "$k") * gdSmallFont->width - 3, + $e + $h / 2 - gdSmallFont->height / 2, "$k", $black); + my $t = 0; + $image->line ($ml + ($t + ${$val[0]}{$k}) * $r + $rx - $rx, $e + $h, + $ml + ($t + ${$val[0]}{$k}) * $r + $rx, $e - $ry + $h, + $black); + for $i (0 .. $n - 1) { + next unless defined ${$val[$i]}{$k}; + { + my $poly = new GD::Polygon; + $poly->addPt($ml + $t * $r, $e); + $poly->addPt($ml + $t * $r + $rx, $e - $ry); + $poly->addPt($ml + ($t + ${$val[$i]}{$k}) * $r + $rx, $e - $ry); + $poly->addPt($ml + ($t + ${$val[$i]}{$k}) * $r, $e); + + $image->filledPolygon($poly, $col[$i][1]); + $image->polygon($poly, $black); + } + unless (${$val[$i + 1]}{$k} || ${$val[$i]}{$k} == 0) { + my $poly = new GD::Polygon; + $poly->addPt($ml + ($t + ${$val[$i]}{$k}) * $r + $rx, $e - $ry); + $poly->addPt($ml + ($t + ${$val[$i]}{$k}) * $r + $rx - $rx, $e); + $poly->addPt($ml + ($t + ${$val[$i]}{$k}) * $r + $rx - $rx, $e + $h); + $poly->addPt($ml + ($t + ${$val[$i]}{$k}) * $r + $rx, $e - $ry + $h); + + $image->filledPolygon($poly, $col[$i][2]); + $image->polygon($poly, $black); + } + $image->filledRectangle ($ml + $t * $r, $e, + $ml + ($t + ${$val[$i]}{$k}) * $r, $e + $h, + $col[$i][0]); + $image->rectangle ($ml + $t * $r, $e, $ml + ($t + ${$val[$i]}{$k}) * $r, + $e + $h, $black); + $t += ${$val[$i]}{$k}; + } + # total length (offered) + $image->filledRectangle ($ml + $t * $r + $rx + 3, + $e - 2 - gdSmallFont->height / 2, + $ml + $t * $r + $rx + 4 + + gdSmallFont->width * length $t, + $e - 6 + gdSmallFont->height / 2, $white); + $image->string (gdSmallFont, $ml + $t * $r + $rx + 5, + $e - 3 - gdSmallFont->height / 2, "$t", $black); + # first value (accepted) + $image->filledRectangle ($ml + $t * $r + $rx + 3, + $e - 4 + gdSmallFont->height / 2, + $ml + $t * $r + $rx + 4 + + gdSmallFont->width * length "${$val[0]}{$k}", + $e - 2 + gdSmallFont->height, $white); + $image->string (gdSmallFont, $ml + $t * $r + $rx + 5, + $e - 5 + gdSmallFont->height / 2, ${$val[0]}{$k}, $black); + $e += $d; + } + open (IMG, "> $filename") || die "Error: Can't open \"$filename\": $!\n"; + if ($GD_FORMAT eq 'png') { + print IMG $image->png; + } + else { + print IMG $image->gif; + } + close IMG; + $ymax; +} + +sub Histo { + my ($filename, $title, $xmax, $factor, + $labelx, $labely, $val1, $labels1) = @_; + + no strict; + my $max = 0; + my $ymax = 300; + my $nb = 0; + # A hugly hack to convert hashes to lists.. + # and to adjust the first and the last value... + # this function should be rewritten.. + my (@a, @b, $kk); + foreach $kk (sort keys (%$val1)) { + if (defined $$val1{$kk}) { + $nb++; + # Arg... the following MUST be removed !!!!!!!!! + $$val1{$kk} = $$val1{$kk} / $innreport_inn::inn_flow_time{$kk} * 3600 + if ($innreport_inn::inn_flow_time{$kk} != 3600) && + ($innreport_inn::inn_flow_time{$kk} != 0); + push @a, $$val1{$kk}; + $max = $$val1{$kk} if $$val1{$kk} > $max; + push @b, $$labels1{$kk}; + } + } + return 0 unless $nb; # strange, no data. + my $val = \@a; + my $labels = \@b; + my ($i, $j); + my ($marginl, $marginr, $margint, $marginb, $shx, $shy); + + my $image = new GD::Image($xmax, $ymax); + my ($white, $black); + if (defined $output{'default'}{'graph_fg'}) { + my $t = $output{'default'}{'graph_fg'}; + $t =~ s/^\"\s*\#(.*?)\s*\"$/$1/o; + $t =~ m/^[\da-fA-F]{6}$/o || + die "Error in section 'default' section 'graph_fg'. Bad color.\n"; + my @c = map { hex ($_) } ($t =~ m/^(..)(..)(..)$/); + $black = $image->colorAllocate (@c); + } + else { + $black = $image->colorAllocate ( 0, 0, 0); + } + if (defined $output{'default'}{'graph_bg'}) { + my $t = $output{'default'}{'graph_bg'}; + $t =~ s/^\"\s*\#(.*?)\s*\"$/$1/o; + $t =~ m/^[\da-fA-F]{6}$/o || + die "Error in section 'default' section 'graph_bg'. Bad color.\n"; + my @c = map { hex $_ } ($t =~ m/^(..)(..)(..)$/); + $white = $image->colorAllocate (@c); + } + else { + $white = $image->colorAllocate (255, 255, 255); + } + $image->filledRectangle (0, 0, $xmax, $ymax, $white); + my $gray = $image->colorAllocate (128, 128, 128); + my $red = $image->colorAllocate (255, 0, 0); + my $red2 = $image->colorAllocate (189, 0, 0); + my $red3 = $image->colorAllocate (127, 0, 0); + my $coltxt = $black; + + $image->transparent ($white) if $transparent; + + my $FontWidth = gdSmallFont->width; + my $FontHeight = gdSmallFont->height; + + $marginl = 60; + $marginr = 30; + $margint = 60; + $marginb = 30; + $shx = 7; + $shy = 7; + + $max = 1 unless $max; + my $part = 8; + $max /= $factor; + + my $old_max = $max; + { + my $t = log ($max) / log 10; + $t = sprintf "%.0f", $t - 1; + $t = exp ($t * log 10); + $max = sprintf "%.0f", $max / $t * 10 + 0.4; + my $t2 = sprintf "%.0f", $max / $part; + unless ($part * $t2 == $max) { + while ($part * $t2 != $max) { + $max++; + $t2 = sprintf "%d", $max / $part; + } + } + $max = $max * $t / 10; + } + + # Title + $image->string (gdMediumBoldFont, + ($xmax - length ($title) * gdMediumBoldFont->width) / 2, + ($margint - $shy - gdMediumBoldFont->height) / 2, + $title, $coltxt); + + # Labels + $image->string (gdSmallFont, $marginl / 2, $margint / 2, $labely, $coltxt); + $image->string (gdSmallFont, $xmax - $marginr / 2 - + $FontWidth * length ($labelx), $ymax - $marginb / 2, + $labelx, $coltxt); + + # Max + $image->line ($marginl, $ymax - $marginb - $shy - + $old_max * ($ymax - $marginb - $margint - $shy) / $max, + $xmax - $marginr, $ymax - $marginb - $shy - + $old_max * ($ymax - $marginb - $margint - $shy) / $max, $red); + $image->line ($marginl, $ymax - $marginb - $shy - + $old_max * ($ymax - $marginb - $margint - $shy) / $max, + $marginl - $shx, $ymax - $marginb - + $old_max * ($ymax - $marginb - $margint - $shy) / $max, $red); + + # Left + $image->line ($marginl - $shx, $margint + $shy, + $marginl - $shx, $ymax - $marginb, $coltxt); + $image->line ($marginl, $margint, + $marginl, $ymax - $marginb - $shy, $coltxt); + $image->line ($marginl, $margint, + $marginl - $shx, $margint + $shy, $coltxt); + $image->line ($marginl - $shx, $ymax - $marginb, + $marginl, $ymax - $marginb - $shy, $coltxt); + + # Right + $image->line ($xmax - $marginr, $margint, + $xmax - $marginr, $ymax - $marginb - $shy, $coltxt); + $image->line ($xmax - $marginr - $shx, $ymax - $marginb, + $xmax - $marginr, $ymax - $marginb - $shy, $coltxt); + + # Bottom + $image->line ($marginl - $shx, $ymax - $marginb, + $xmax - $marginr - $shx, $ymax - $marginb, $coltxt); + $image->line ($marginl, $ymax - $marginb - $shy, + $xmax - $marginr, $ymax - $marginb - $shy, $coltxt); + $image->fill ($xmax / 2, $ymax - $marginb - $shy / 2, $gray); + + # Top + $image->line ($marginl, $margint, + $xmax - $marginr, $margint, $coltxt); + $image->setStyle ($coltxt, $coltxt, &GD::gdTransparent, + &GD::gdTransparent, &GD::gdTransparent); + # Graduations + for ($i = 0; $i <= $part; $i++) { + $j = $max * $i / $part ; # Warning to floor + # $j = ($max / $part) * ($i / 10000); + # $j *= 10000; + + # Little hack... + $j = sprintf "%d", $j if $j > 100; + + $image->line ($marginl - $shx - 3, $ymax - $marginb - + $i * ($ymax - $marginb - $margint - $shy) / $part, + $marginl - $shx, $ymax - $marginb - + $i * ($ymax - $marginb - $margint - $shy) / $part, $coltxt); + $image->line ($marginl - $shx, $ymax - $marginb - + $i * ($ymax - $marginb - $margint - $shy) / $part, + $marginl, $ymax - $marginb - $shy - + $i * ($ymax - $marginb - $margint - $shy) / $part, gdStyled); + $image->line ($marginl, $ymax - $marginb - $shy - + $i * ($ymax - $marginb - $margint - $shy) / $part, + $xmax - $marginr, $ymax - $marginb - $shy - + $i * ($ymax - $marginb - $margint - $shy) / $part, gdStyled); + $image->string (gdSmallFont, + $marginl - $shx - $FontWidth * length ("$j") - 7, + $ymax - $marginb - + ($i) * ($ymax - $marginb - $margint - $shy) / ($part) - + $FontHeight / 2, "$j", $coltxt); + } + + # Graduation (right bottom corner) + $image->line ($xmax - $marginr - $shx, $ymax - $marginb, + $xmax - $marginr - $shx, $ymax - $marginb + 3, $coltxt); + # Bars + $i = 0; + my $w = ($xmax - $marginl - $marginr) / $nb; + my $k = $w / 5; + $$val[$nb - 1] = 0 unless $$val[$nb - 1]; + foreach $j (@$val) { + my $MAX = 1; + if ($i++ <= $nb) { + # Graduation + $image->line ($marginl + ($i - 1) * $w - $shx, $ymax - $marginb, + $marginl + ($i - 1) * $w - $shx, $ymax - $marginb + 3, + $coltxt); + my $ii = sprintf "%d", $i / $MAX; + $image->string (gdSmallFont, + $marginl + ($i - 0.5) * $w + 1 - + ($FontWidth * length ($$labels[$i-1])) / 2 - $shx, + $ymax - $marginb + 3, $$labels[$i-1], $coltxt) + unless ($w < $FontWidth * length ($$labels[$i-1])) + && ($i != $MAX * $ii); + + # Right + my $poly = new GD::Polygon; + $poly->addPt($marginl + ($i) * $w - $k, $ymax - $marginb - $shy - + $j / $factor * ($ymax - $marginb - $margint - $shy) / $max); + $poly->addPt($marginl + ($i) * $w - $k, $ymax - $marginb - $shy); + $poly->addPt($marginl + ($i) * $w - $k - $shx, $ymax - $marginb); + $poly->addPt($marginl + ($i) * $w - $k - $shx, $ymax - $marginb - + $j / $factor * ($ymax - $marginb - $margint - $shy) / $max); + + $image->filledPolygon($poly, $red3); + $image->polygon($poly, $coltxt); + + # Front + $image->filledRectangle ($marginl + ($i - 1) * $w + $k - $shx, + $ymax - $marginb - + $j / $factor * ($ymax - $marginb - $margint - $shy) / $max, + $marginl + ($i) * $w - $k - $shx, + $ymax - $marginb, $red); + $image->rectangle ($marginl + ($i - 1) * $w + $k - $shx, + $ymax - $marginb - + $j / $factor * ($ymax - $marginb - $margint - $shy) / $max, + $marginl + ($i) * $w - $k - $shx, + $ymax - $marginb, $coltxt); + # Top + my $poly2 = new GD::Polygon; + $poly2->addPt($marginl + ($i - 1) * $w + $k, $ymax - $marginb - $shy - + $j / $factor * ($ymax - $marginb - $margint - $shy) / $max); + $poly2->addPt($marginl + ($i) * $w - $k, $ymax - $marginb - $shy - + $j / $factor * ($ymax - $marginb - $margint - $shy) / $max); + $poly2->addPt($marginl + ($i) * $w - $k - $shx, $ymax - $marginb - + $j / $factor * ($ymax - $marginb - $margint - $shy) / $max); + $poly2->addPt($marginl + ($i - 1) * $w + $k - $shx, $ymax - $marginb - + $j / $factor * ($ymax - $marginb - $margint - $shy) / $max); + + $image->rectangle (0, 0, $xmax - 1, $ymax - 1, $coltxt); + $image->filledPolygon($poly2, $red2); + $image->polygon($poly2, $coltxt); + } + } + + open (IMG, "> $filename") || die "Can't create '$filename'\n"; + if ($GD_FORMAT eq 'png') { + print IMG $image->png; + } + else { + print IMG $image->gif; + } + close IMG; + 1; +} + +sub Chrono { + my $filename = shift; # filename + my $title = shift; # title + my $color_bg = shift; # background color + my $xmax = shift; # width + my $ymax = shift; # height + + my $in = shift; + my $out = shift; + my $dates = shift; + + my $legend_in = shift; + my $legend_out = shift; + + my $color_in = shift; + my $color_out = shift; + + my $unit = shift; + + my $key; + my $x_min = 1E30; + my $x_max = 0; + my $y_min = 0; + my $y_max; + my $y_max_in = 0; + my $y_max_out = 0; + + foreach $key (sort keys %$dates) { + $x_min = $key if $x_min > $key; + $x_max = $$dates{$key} if $x_max < $$dates{$key}; + my $t = $$out{$key} / ($$dates{$key} - $key); + $y_max_out = $t if $y_max_out < $t; + $t = $$in{$key} / ($$dates{$key} - $key); + $y_max_in = $t if $y_max_in < $t; + } + $y_max = $y_max_out > $y_max_in ? $y_max_out : $y_max_in; + my $factor = 1; + if ($y_max < 1) { + $factor = 60; + if ($y_max < 4 / 60) { + $y_max = 4 / 60; + } + else { + $y_max = int ($y_max * $factor) + 1; + $y_max += (4 - ($y_max % 4)) % 4; + $y_max /= $factor; + } + } + else { + $y_max = int ($y_max) + 1; + $y_max += (4 - ($y_max % 4)) % 4; + } + + $unit .= "/" . ($factor == 60 ? "min" : "sec"); + + # min range is 4 weeks. + my $delta = $x_max - $x_min; + $x_min = $x_max - 3024000 if $delta < 3024000; + # between 4 weeks and one year, range is a year. + $x_min = $x_max - 31536000 if ($delta < 31536000 && $delta > 3024000); + # max range is 13 months + $x_min = $x_max - 34128000 if $delta > 34128000; + my $image = new GD::Image ($xmax, $ymax); + my ($white, $black); + if (defined $output{'default'}{'graph_fg'}) { + my $t = $output{'default'}{'graph_fg'}; + $t =~ s/^\"\s*\#(.*?)\s*\"$/$1/o; + $t =~ m/^[\da-fA-F]{6}$/o || + die "Error in section 'default' section 'graph_fg'. Bad color.\n"; + my @c = map { hex $_ } ($t =~ m/^(..)(..)(..)$/); + $black = $image->colorAllocate (@c); + } + else { + $black = $image->colorAllocate ( 0, 0, 0); + } + if (defined $output{'default'}{'graph_bg'}) { + my $t = $output{'default'}{'graph_bg'}; + $t =~ s/^\"\s*\#(.*?)\s*\"$/$1/o; + $t =~ m/^[\da-fA-F]{6}$/o || + die "Error in section 'default' section 'graph_bg'. Bad color.\n"; + my @c = map { hex $_ } ($t =~ m/^(..)(..)(..)$/); + $white = $image->colorAllocate (@c); + } + else { + $white = $image->colorAllocate (255, 255, 255); + } + my $bg; + if (defined $color_bg) { + $color_bg =~ m/^\#[\da-fA-F]{6}$/o || + die "Error in section 'index'. Bad color $color_bg.\n"; + my @c = map { hex $_ } ($color_bg =~ m/^\#(..)(..)(..)$/); + $bg = $image->colorAllocate (@c); + } + else { + $bg = $image->colorAllocate (255, 255, 206); + } + my $col_in; + if (defined $color_in) { + $color_in =~ m/^\#[\da-fA-F]{6}$/o || + die "Error in section 'index'. Bad color $color_in.\n"; + my @c = map { hex $_ } ($color_in =~ m/^\#(..)(..)(..)$/); + $col_in = $image->colorAllocate (@c); + } + else { + $col_in = $image->colorAllocate ( 80, 159, 207); + } + my $col_out; + my @col_out = ( 0, 0, 255); + if (defined $color_out) { + $color_out =~ m/^\#[\da-fA-F]{6}$/o || + die "Error in section 'index'. Bad color $color_out.\n"; + my @c = map { hex $_ } ($color_out =~ m/^\#(..)(..)(..)$/); + $col_out = $image->colorAllocate (@c); + @col_out = @c; + } + else { + $col_out = $image->colorAllocate (@col_out); + } + + my $white2 = $image->colorAllocate (255, 255, 255); + my $gray = $image->colorAllocate (192, 192, 192); + my $red = $image->colorAllocate (255, 0, 0); + my $coltxt = $black; + + my $size = 22; # legend + # legend statistics + my ($max_in, $max_out) = (0, 0); # min + my ($min_in, $min_out) = (1E10, 1E10); # max + my ($t_in, $t_out) = (0, 0); # time + my ($s_in, $s_out) = (0, 0); # sum + + $image->filledRectangle (0, 0, $xmax, $ymax, $gray); + $image->transparent ($gray) if $transparent; + + my $FontWidth = gdSmallFont->width; + my $FontHeight = gdSmallFont->height; + $image->setStyle ($black, &GD::gdTransparent, &GD::gdTransparent); + + my $marginl = 13 + $FontWidth * length (sprintf "%d", $y_max * $factor); + my $marginr = 15 + 4 * $FontWidth; # "100%" + my $margint = 2 * $FontHeight + gdMediumBoldFont->height; + my $marginb = 2 * $FontHeight + $size; + my $xratio = ($xmax - $marginl - $marginr) / ($x_max - $x_min); + my $yratio = ($ymax - $margint - $marginb) / ($y_max - $y_min); + + my $frame = new GD::Polygon; + $frame->addPt(2, $margint - $FontHeight -3); + $frame->addPt($xmax - 2, $margint - $FontHeight -3); + $frame->addPt($xmax - 2, $ymax - 3); + $frame->addPt(2, $ymax - 3); + $image->filledPolygon($frame, $white2); + $image->polygon($frame, $black); + + $image->filledRectangle ($marginl, $margint, + $xmax - $marginr, $ymax - $marginb, $bg); + my $brush = new GD::Image(1, 2); + my $b_col = $brush->colorAllocate(@col_out); + $brush->line(0, 0, 0, 1, $b_col); + $image->setBrush($brush); + my ($old_x, $old_y_in, $old_y_out); + foreach $key (sort keys %$dates) { + next if $key < $x_min; + my $delta = $$dates{$key} - $key; + $min_in = $$in{$key} / $delta if $min_in > $$in{$key} / $delta; + $max_in = $$in{$key} / $delta if $max_in < $$in{$key} / $delta; + $min_out = $$out{$key} / $delta if $min_out > $$out{$key} / $delta; + $max_out = $$out{$key} / $delta if $max_out < $$out{$key} / $delta; + $t_in += $delta; + $s_in += $$in{$key}; + $s_out += $$out{$key}; + + my $tt_in = $$in{$key} / ($$dates{$key} - $key) * $yratio; + my $tt_out = $$out{$key} / ($$dates{$key} - $key) * $yratio; + my $new_x = $marginl + ($key - $x_min) * $xratio; + $image->filledRectangle ($marginl + ($key - $x_min) * $xratio, + $ymax - $marginb - $tt_in, + $marginl + ($$dates{$key} - $x_min) * $xratio, + $ymax - $marginb, $col_in); + if (defined $old_x) { + $old_x = $new_x if $old_x > $new_x; + my $poly = new GD::Polygon; + $poly->addPt($old_x, $old_y_in); + $poly->addPt($new_x, $ymax - $marginb - $tt_in); + $poly->addPt($new_x, $ymax - $marginb); + $poly->addPt($old_x, $ymax - $marginb); + $image->filledPolygon($poly, $col_in); + } + $image->line ($marginl + ($key - $x_min) * $xratio, + $ymax - $marginb - $tt_out, + $marginl + ($$dates{$key} - $x_min) * $xratio, + $ymax - $marginb - $tt_out, &GD::gdBrushed); + $image->line ($old_x, $old_y_out, $new_x, + $ymax - $marginb - $tt_out, $col_out) if defined $old_x; + $old_x = $marginl + ($$dates{$key} - $x_min) * $xratio; + $old_y_in = $ymax - $marginb - $tt_in; + $old_y_out = $ymax - $marginb - $tt_out; + } + $t_out = $t_in; + + # main frame + $image->rectangle ($marginl, $margint, + $xmax - $marginr, $ymax - $marginb, $black); + # graduations + my $i; + foreach $i (0, 25, 50, 75, 100) { + my $t = $ymax - $margint - $marginb; + $image->line ($marginl, $ymax - $marginb - $i / 100 * $t, + $xmax - $marginr, $ymax - $marginb - $i / 100 * $t, + &GD::gdStyled); + $image->line ($xmax - $marginr, $ymax - $marginb - $i / 100 * $t, + $xmax - $marginr + 3, $ymax - $marginb - $i / 100 * $t, + $black); + $image->line ($marginl - 3, $ymax - $marginb - $i / 100 * $t, + $marginl, $ymax - $marginb - $i / 100 * $t, + $black); + $image->string (&GD::gdSmallFont, $xmax - $marginr + 8, - $FontHeight / 2 + + $ymax - $marginb - $i / 100 * $t, "$i%", $black); + my $s = sprintf "%d", $y_max * $i / 100 * $factor; + $image->string (&GD::gdSmallFont, $marginl - 5 - $FontWidth * length $s, + - $FontHeight / 2 + + $ymax - $marginb - $i / 100 * $t, $s, $black); + } + ## + my $w = 604800; # number of seconds in a week + my $y = 31536000; # number of seconds in a 365 days year + my $mm = 2592000; # number of seconds in a 30 days month + if ($x_max - $x_min <= 3024000) { # less than five weeks + # unit is a week + # 1/1/1990 is a monday. Use this as a basis. + my $d = 631152000; # number of seconds between 1/1/1970 and 1/1/1990 + my $n = int ($x_min / $y); + my $t = $x_min - $n * $y - int (($n - 2) / 4) * 24 * 3600; + my $f = int ($t / $w); + $n = $d + int (($x_min - $d) / $w) * $w; + while ($n < $x_max) { + $t = $marginl + ($n - $x_min) * $xratio; + if ($n > $x_min) { + $image->line ($t, $margint, $t, $ymax - $marginb, &GD::gdStyled); + $image->line ($t, $ymax - $marginb, $t, $ymax - $marginb + 2, $black); + } + $image->string (&GD::gdSmallFont, $FontWidth * 7 / 2 + $t, + $ymax - $marginb + 4, (sprintf "Week %02d", $f), $black) + if ($n + $w / 2 > $x_min) && ($n + $w / 2 < $x_max); + $f++; + $n += $w; + $t = int ($n / $y); + $f = 0 + if $n - $y * $t - int (($t - 2) / 4) * 24 * 3600 < $w && $f > 50; + } + $d = 86400; # 1 day + $n = int ($x_min / $y); + $t = $n * $y + int (($n - 2) / 4) * 24 * 3600; + $i = 0; + my $x; + while ($t < $x_max) { + $x = $marginl + ($t - $x_min) * $xratio; + $image->line ($x, $margint, $x, $ymax - $marginb + 2, $red) + if $t > $x_min; + $t += $mm; + $t += $d if $i == 0 || $i == 2 || $i == 4 || + $i == 6 || $i == 7 || $i == 9 || $i == 11; # 31 days months + if ($i == 1) { # february ? + $t -= 2 * $d; + $t += $d unless (1970 + int ($t / $y)) % 4; + } + $i++; + $i = 0 if $i == 12; # Happy New Year !! + } + } + else { + # unit is a month + my $n = int ($x_min / $y); + my $t = $n * $y + int (($n - 2) / 4) * 24 * 3600; + my @m = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"); + my $d = 86400; # 1 day + my $i = 0; + my $x; + while ($t < $x_max) { + $x = $marginl + ($t - $x_min) * $xratio; + if ($t > $x_min) { + $image->line ($x, $margint, $x, $ymax - $marginb, &GD::gdStyled); + $image->line ($x, $ymax - $marginb, $x, + $ymax - $marginb + 2, $black); + $image->line ($x, $margint, $x, $ymax - $marginb, $red) unless $i; + } + $image->string (&GD::gdSmallFont, + $mm * $xratio / 2 - $FontWidth * 3 / 2 + + $x, $ymax - $marginb + 4, (sprintf "%s", $m[$i]), + $black) + if ($t + 2 * $w > $x_min) && ($x_max > 2 * $w + $t); + $t += $mm; + $t += $d if ($i == 0 || $i == 2 || $i == 4 || + $i == 6 || $i == 7 || $i == 9 || $i == 11); # 31 days months + if ($i == 1) { # february ? + $t -= 2 * $d; + $t += $d unless (1970 + int ($t / $y)) % 4; + } + $i++; + $i = 0 if $i == 12; # Happy New Year !! + } + } + + # Add the little red arrow + my $poly = new GD::Polygon; + $poly->addPt($xmax - $marginr - 2, $ymax - $marginb - 3); + $poly->addPt($xmax - $marginr + 4, $ymax - $marginb); + $poly->addPt($xmax - $marginr - 2, $ymax - $marginb + 3); + $image->filledPolygon($poly, $red); + + # Title + $image->string (&GD::gdMediumBoldFont, + $xmax / 2 - $FontWidth * length ($title) / 2, 4, + $title, $black); + + # Legend + my $y_in = $ymax - $size - $FontHeight + 5; + $image->string (&GD::gdSmallFont, $marginl, $y_in, $legend_in, $col_in); + $image->string (&GD::gdSmallFont, $xmax / 4, $y_in, + (sprintf "Min: %5.1f $unit", $min_in * $factor), $black); + $image->string (&GD::gdSmallFont, $xmax / 2, $y_in, + (sprintf "Avg: %5.1f $unit", $s_in / $t_in * $factor), $black); + $image->string (&GD::gdSmallFont, 3 * $xmax / 4, $y_in, + (sprintf "Max: %5.1f $unit", $max_in * $factor), $black); + + my $y_out = $ymax - $size + 5; + $image->string (&GD::gdSmallFont, $marginl, $y_out, $legend_out, $col_out); + $image->string (&GD::gdSmallFont, $xmax / 4, $y_out, + (sprintf "Min: %5.1f $unit", $min_out * $factor), $black); + $image->string (&GD::gdSmallFont, $xmax / 2, $y_out, + (sprintf "Avg: %5.1f $unit", $s_out / $t_out * $factor), $black); + $image->string (&GD::gdSmallFont, 3 * $xmax / 4, $y_out, + (sprintf "Max: %5.1f $unit", $max_out * $factor), $black); + + open (IMG, "> $filename") || die "Error: Can't open \"$filename\": $!\n"; + if ($GD_FORMAT eq 'png') { + print IMG $image->png; + } + else { + print IMG $image->gif; + } + close IMG; + return $ymax; +} + +sub Write_all_results { + my $HTML_output = shift; + my $h = shift; + my $k; + + my $title = $$h{'default'}{'title'} ? + $$h{'default'}{'title'} : "Daily Usenet report"; + $title =~ s/^\"\s*(.*?)\s*\"$/$1/o; + $title =~ s/\\\"/\"/go; + my $Title = $title; + $Title =~ s/<.*?>//go; + { + my $Title = $Title; + $Title =~ s/\&/&/go; + $Title =~ s/\<//go; + print "$Title from $first_date to $last_date\n\n"; + } + + if ($HTML) { + my $body = defined $output{'default'}{'html_body'} ? + $output{'default'}{'html_body'} : ''; + $body =~ s/^\"\s*(.*?)\s*\"$/ $1/o; + $body =~ s/\\\"/\"/go; + open (HTML, "> $HTML_output") || die "Error: cant open $HTML_output\n"; + + print HTML "\n" . + "\n\n$Title: $first_date\n" . + "\n\n\n" . + "$HTML_header\n

$title

\n" . + "

$first_date -- $last_date

\n
\n


\n"; + + # Index + print HTML "

    \n"; + foreach $k (@{$$h{'_order_'}}) { + next if $k =~ m/^(default|index)$/; + my ($data) = $$h{$k}{'data'} =~ m/^\"\s*(.*?)\s*\"$/o; + $data =~ s/^\%/\%$CLASS\:\:/ unless $data eq '%prog_type'; + my %data; + { local $^W = 0; no strict; %data = eval $data } + my ($string) = $$h{$k}{'title'} =~ m/^\"\s*(.*?)\s*\"$/o; + $string =~ s/\s*:$//o; + my $want = 1; + + ($want) = $$h{$k}{'skip'} =~ m/^\"?\s*(.*?)\s*\"?$/o + if defined $$h{$k}{'skip'}; + $want = $want eq 'true' ? 0 : 1; + print HTML "
  • $string\n" if %data && $want; + } + print HTML "


\n"; + } + if (@unrecognize && $WANT_UNKNOWN) { + my $mm = $#unrecognize; + print HTML "" if $HTML && $WANT_HTML_UNKNOWN; + print "Unknown entries from news log file:\n"; + print HTML "Unknown entries from news log file:

\n" + if $HTML && $WANT_HTML_UNKNOWN; + $mm = $MAX_UNRECOGNIZED - 1 + if $MAX_UNRECOGNIZED > 0 && $mm > $MAX_UNRECOGNIZED - 1; + if ($mm < $unrecognize_max && $unrecognize_max > 0) { + printf HTML "First %d / $unrecognize_max lines (%3.1f%%)
\n", $mm + 1, + ($mm + 1) / $unrecognize_max * 100 if $HTML && $WANT_HTML_UNKNOWN; + printf "First %d / $unrecognize_max lines (%3.1f%%)\n", $mm + 1, + ($mm + 1) / $unrecognize_max * 100; + } + + my $l; + for $l (0 .. $mm) { + chomp $unrecognize[$l]; # sometimes, the last line need a CR + print "$unrecognize[$l]\n"; # so, we always add one + if ($HTML && $WANT_HTML_UNKNOWN) { + $unrecognize[$l] =~ s/&/\&/g; + $unrecognize[$l] =~ s//\>/g; + print HTML "$unrecognize[$l]
\n"; + } + } + print "\n"; + print HTML "


\n" if $HTML && $WANT_HTML_UNKNOWN; + } + + close HTML if $HTML; + foreach $k (@{$$h{'_order_'}}) { + next if $k =~ m/^(default|index)$/; + &Write_Results($HTML_output, $k, $h); + } + if ($HTML) { + open (HTML, ">> $HTML_output") || die "Error: cant open $HTML_output\n"; + print HTML <innreport +$version (c) 1996-1999 by Fabien Tassin +<fta\@sofaraway.org>. +EOT + if (defined $$h{'default'}{'footer'}) { + my ($t) = $$h{'default'}{'footer'} =~ m/^\"\s*(.*?)\s*\"$/o; + $t =~ s/\\\"/\"/go; + print HTML "
" . $t; + } + print HTML "\n$HTML_footer"; + printf HTML "\n", second2time(time - $start_time); + print HTML "\n\n\n"; + close HTML; + } +} + +sub Write_Results { + my $HTML_output = shift; + my $report = shift; + my $data = shift; + my %output = %$data; + return 0 unless defined $output{$report}; # no data to write + return 0 if defined $output{$report}{'skip'} && + $output{$report}{'skip'} =~ m/^true$/io; + my ($TEXT, $HTML, $DOUBLE); + + # Need a text report ? + $TEXT = defined $output{$report}{'text'} ? $output{$report}{'text'} : + (defined $output{'default'}{'text'} ? $output{'default'}{'text'} : ''); + die "Error in config file. Field 'text' is mandatory.\n" unless $TEXT; + $TEXT = ($TEXT =~ m/^true$/io) ? 1 : 0; + + # Need an html report ? + if ($HTML_output) { + $HTML = defined $output{$report}{'html'} ? $output{$report}{'html'} : + (defined $output{'default'}{'html'} ? $output{'default'}{'html'} : ''); + die "Error in config file. Field 'html' is mandatory.\n" unless $HTML; + $HTML = ($HTML =~ m/^true$/io) ? 1 : 0; + } + # Double table ? + $DOUBLE = defined $output{$report}{'double'} ? + $output{$report}{'double'} : 0; + $DOUBLE = ($DOUBLE =~ m/^true$/io) ? 1 : 0; + + # Want to truncate the report ? + my $TOP = defined $output{$report}{'top'} ? $output{$report}{'top'} : -1; + my $TOP_HTML = defined $output{$report}{'top_html'} ? + $output{$report}{'top_html'} : $TOP; + my $TOP_TEXT = defined $output{$report}{'top_text'} ? + $output{$report}{'top_text'} : $TOP; + + my (%h, %d, $h); + { + my $t = $output{$report}{'data'} || + die "Error in section $report. Need a 'data' field.\n"; + $t =~ s/^\"\s*(.*?)\s*\"$/$1/o; + $t =~ s/^\%/\%$CLASS\:\:/ unless $t eq '%prog_type'; + %d = eval $t; + return unless %d; # nothing to report. exit. + return unless keys (%d); # nothing to report. exit. + } + { + my $t = defined $output{$report}{'sort'} ? $output{$report}{'sort'} : + "\$a cmp \$b"; + $t =~ s/\n/ /smog; + $t =~ s/^\"\s*(.*?)\s*\"$/$1/o; + $t =~ s/([\$\%\@])/$1${CLASS}\:\:/go; + $t =~ s/([\$\%\@])${CLASS}\:\:(prog_(?:size|type)|key|num)/$1$2/go; + $t =~ s/\{\$${CLASS}\:\:(a|b)\}/\{\$$1\}/go; + $t =~ s/\$${CLASS}\:\:(a|b)/\$$1/go; + $h = $t; + } + + if ($HTML) { + open (HTML, ">> $HTML_output") || die "Error: cant open $HTML_output\n"; + } + print "\n" if $TEXT; + my ($key, $key1, $key2); + if (defined $output{$report}{'title'}) { + my $t = $output{$report}{'title'}; + $t =~ s/^\"\s*(.*?)\s*\"$/$1/o; + if ($HTML) { + print HTML ""; + my $html = $t; + $html =~ s/(:?)$/ [Top $TOP_HTML]$1/o if $TOP_HTML > 0; + $html =~ s|^(.*)$|$1|; + print HTML "$html\n

\n

\n\n"; + } + $t =~ s/(:?)$/ [Top $TOP_TEXT]$1/o if $TOP_TEXT > 0; + print "$t\n" if $TEXT; + } + my $numbering = 0; + $numbering = 1 if defined $output{$report}{'numbering'} && + $output{$report}{'numbering'} =~ m/^true$/o; + my $i; + my $s = ''; + my $html = ''; + my $first = 0; + + foreach $i (@{$output{$report}{'column'}}) { + my ($v1, $v2); + + my $wtext = defined $$i{'text'} ? $$i{'text'} : 1; + $wtext = $wtext =~ m/^(1|true)$/io ? 1 : 0; + my $whtml = defined $$i{'html'} ? $$i{'html'} : 1; + $whtml = $whtml =~ m/^(1|true)$/io ? 1 : 0; + + $v1 = defined ($$i{'format_name'}) ? $$i{'format_name'} : + (defined ($$i{'format'}) ? $$i{'format'} : "%s"); + $v1 =~ s/^\"\s*(.*?)\s*\"$/$1/o; + $v2 = $$i{'name'}; + $v2 =~ s/^\"\s*(.*?)\s*\"$/$1/o; + $s .= sprintf $v1 . " ", $v2 if $wtext && !($DOUBLE && $first == 1); + if ($HTML && $whtml) { + my $v1 = $v1; + $v1 =~ s/\%-?(?:\d+(?:\.\d+)?)?(\w)/\%$1/g; + my $temp = $first ? "CENTER" : "LEFT"; + $temp .= "\" COLSPAN=\"2" if $numbering && !$first; + $html .= sprintf "", $v2; + } + $first++; + } + $s =~ s/\s*$//; + print "$s\n" if $TEXT; + $s = ''; + if ($HTML) { + print HTML "$html\n\n"; + $html = ''; + } + my $num = 0; + my $done; + if ($DOUBLE) { + my $num_d = 0; + foreach $key1 (sort keys (%d)) { + $done = 0; + $num = 0; + $num_d++; + $s = ''; + $html = ''; + my @res; + foreach $key2 (sort {$d{$key1}{$b} <=> $d{$key1}{$a}} + keys (%{$d{$key1}})) { + my $first = 0; + $num++; + foreach $i (@{$output{$report}{'column'}}) { + my ($v1, $v2, $p); + + my $wtext = defined $$i{'text'} ? $$i{'text'} : 1; + $wtext = $wtext =~ m/^(1|true)$/io ? 1 : 0; + my $whtml = defined $$i{'html'} ? $$i{'html'} : 1; + $whtml = $whtml =~ m/^(1|true)$/io ? 1 : 0; + + # is it the primary key ? + $p = 0; + $p = 1 if defined $$i{'primary'} && $$i{'primary'} =~ m/true/; + + # format + $v1 = defined ($$i{'format'}) ? $$i{'format'} : "%s"; + $v1 =~ s/^\"\s*(.*?)\s*\"$/$1/o; + + # value + $v2 = $$i{'value'}; + $v2 =~ s/^\"\s*(.*?)\s*\"$/$1/o; + my $r =''; + if ($v2) { + $r = &EvalExpr ($v2, $key2, $num, $key1); + die "Error in section $report column $$i{'name'}. " . + "Invalid 'value' value.\n" unless defined $r; + } + $res[$first] += $r if $v1 =~ m/\%-?(?:\d+(?:\.\d+)?)?d/o; + if ($p) { + $s .= sprintf $v1. "\n", $r unless $done || !$wtext; + if ($HTML && $whtml) { + if ($done) { + $html .= ""; + } + else { + $v1 =~ s/\%-?(?:\d+(?:\.\d+)?)?s/\%s/g; + $html .= $numbering ? "" : ''; + # unless $first; + $html .= sprintf "\n", $r; + $html .= ""; + } + } + } + else { + if ($wtext) { + $s .= " " if $first == 1; + $s .= sprintf $v1 . " ", $r; + } + if ($HTML && $whtml) { + $html .= $numbering ? "" : '' if $first == 1; + $v1 =~ s/\%-?(?:\d+(?:\.\d+)?)?s/\%s/g; + my $temp = $first > 1 ? "RIGHT" : "LEFT"; + $html .= sprintf "", $r; + } + } + $done = 1 if $p; + $first++; + } + $s =~ s/\s*$//; + $s =~ s/\\n/\n/g; + print "$s\n" if $TEXT && ($num <= $TOP_TEXT || $TOP_TEXT == -1); + if ($HTML && ($num <= $TOP_HTML || $TOP_HTML == -1)) { + $html =~ s/\\n//g; + print HTML "$html\n"; + } + $s = ''; + $html = ''; + } + $first = 0; + $s = ''; + $html = ''; + if ($TOP_TEXT != -1 && $TOP_HTML != -1) { + foreach $i (@{$output{$report}{'column'}}) { + if (defined $$i{'primary'} && $$i{'primary'} =~ m/true/o) { + $first++; + $s .= ' '; + $html .= "" if $HTML; + $html .= "" if $HTML && $numbering; + next; + } + my ($v1, $v2); + $v1 = defined ($$i{'format_total'}) ? $$i{'format_total'} : + (defined ($$i{'format'}) ? $$i{'format'} : "%s"); + $v1 =~ s/^\"\s*(.*?)\s*\"$/$1/o; + my $r = $first == 1 ? $num : $res[$first]; + $s .= sprintf $v1 . " ", $r; + if ($HTML) { + my $temp = $first > 1 ? "RIGHT" : "LEFT"; + $v1 =~ s/\%-?(?:\d+(?:\.\d+)?)?s/\%s/g; + $v1 =~ s|(.*)|$1|o unless $first > 1; + $html .= sprintf "", $r; + } + $first++; + } + $s =~ s/\s*$//; + $s =~ s/\\n//g; + print "$s\n" if $TEXT; + print HTML "$html\n" if $HTML; + } + } + print "\n" if $TEXT; + print HTML "\n" if $HTML; + $first = 0; + $num = $num_d; + $s = ''; + $html = ''; + foreach $i (@{$output{$report}{'column'}}) { + my $wtext = defined $$i{'text'} ? $$i{'text'} : 1; + $wtext = $wtext =~ m/^(1|true)$/io ? 1 : 0; + my $whtml = defined $$i{'html'} ? $$i{'html'} : 1; + $whtml = $whtml =~ m/^(1|true)$/io ? 1 : 0; + + my ($v1, $v2); + $v1 = defined $$i{'format_total'} ? $$i{'format_total'} : + (defined $$i{'format'} ? $$i{'format'} : "%s"); + $v1 =~ s/^\"\s*(.*?)\s*\"$/$1/o; + $v2 = $$i{'total'} || + die "Error in section $report column $$i{'name'}. " . + "Need a 'total' field.\n"; + $v2 =~ s/^\"\s*(.*?)\s*\"$/$1/o; + my $r = ''; + if ($v2) { + $r = &EvalExpr ($v2, $key2, $num, 1); + die "Error in section $report column $$i{'name'}. " . + "Invalid 'total' value.\n" unless defined $r; + } + $s .= sprintf $v1 . " ", $r if $wtext && $first != 1; + if ($HTML && $whtml) { + my $temp = $first ? "RIGHT" : "LEFT"; + $temp .= "\" COLSPAN=\"2" if $numbering && !$first; + $v1 =~ s/\%-?(?:\d+(?:\.\d+)?)?s/\%s/g; + $v1 =~ s|(.*)|$1|o unless $first; + $html .= $first == 1 ? "" : + sprintf "", $r; + } + $first++; + } + $s =~ s/\s*$//; + $s =~ s/\\n//g; + print "$s\n" if $TEXT; + print HTML "$html\n
$v1
$num_d$v1
$v1
$v1
$v1
\n
\n

\n


\n" if $HTML; + } + else { + # foreach $key (sort { local $^W = 0; no strict; eval $h } (keys (%d))) + foreach $key ((eval "sort {local \$^W = 0; no strict; $h} (keys (%d))")) { + next unless defined $key; + next unless defined $d{$key}; # to avoid problems after some undef() + $num++; + next unless $num <= $TOP_HTML || $TOP_HTML == -1 || + $num <= $TOP_TEXT || $TOP_TEXT == -1; + my $first = 0; + foreach $i (@{$output{$report}{'column'}}) { + my $wtext = defined $$i{'text'} ? $$i{'text'} : 1; + $wtext = $wtext =~ m/^(1|true)$/io ? 1 : 0; + my $whtml = defined $$i{'html'} ? $$i{'html'} : 1; + $whtml = $whtml =~ m/^(1|true)$/io ? 1 : 0; + + my ($v1, $v2); + $v1 = defined ($$i{'format'}) ? $$i{'format'} : "%s"; + $v1 =~ s/^\"\s*(.*?)\s*\"$/$1/o; + $v2 = $$i{'value'}; + $v2 =~ s/^\"\s*(.*?)\s*\"$/$1/o; + my $r =''; + if ($v2) { + $r = &EvalExpr ($v2, $key, $num); + die "Error in section $report column $$i{'name'}. " . + "Invalid 'value' value.\n" unless defined $r; + } + $s .= sprintf $v1 . " ", $r + if $wtext && (($num <= $TOP_TEXT) || ($TOP_TEXT == -1)); + if ($HTML && $whtml && ($num <= $TOP_HTML || $TOP_HTML == -1)) { + $v1 =~ s/\%-?(?:\d+(?:\.\d+)?)?s/\%s/g; + $html .= "$num" if $numbering && !$first; + my $temp = $first ? "RIGHT" : "LEFT"; + $html .= sprintf "$v1", $r; + } + $first++; + } + $s =~ s/\s*$//; + print "$s\n" if $TEXT && ($num <= $TOP_TEXT || $TOP_TEXT == -1); + $s = ''; + if ($HTML && ($num <= $TOP_HTML || $TOP_HTML == -1)) { + print HTML "$html\n"; + $html = ''; + } + } + print "\n" if $TEXT; + print HTML "\n" if $HTML; + $first = 0; + foreach $i (@{$output{$report}{'column'}}) { + my $wtext = defined $$i{'text'} ? $$i{'text'} : 1; + $wtext = $wtext =~ m/^(1|true)$/io ? 1 : 0; + my $whtml = defined $$i{'html'} ? $$i{'html'} : 1; + $whtml = $whtml =~ m/^(1|true)$/io ? 1 : 0; + + my ($v1, $v2); + $v1 = defined ($$i{'format_total'}) ? $$i{'format_total'} : + (defined ($$i{'format'}) ? $$i{'format'} : "%s"); + $v1 =~ s/^\"\s*(.*?)\s*\"$/$1/o; + $v2 = $$i{'total'} || + die "Error in section $report column $$i{'name'}. " . + "Need a 'total' field.\n"; + $v2 =~ s/^\"\s*(.*?)\s*\"$/$1/o; + my $r = ''; + if ($v2) { + $r = &EvalExpr ($v2, $key, $num); + die "Error in section $report column $$i{'name'}. " . + "Invalid 'total' value.\n" unless defined $r; + } + $s .= sprintf $v1 . " ", $r if $wtext; + if ($HTML && $whtml) { + $v1 =~ s/\%-?(?:\d+(?:\.\d+)?)?s/\%s/g; + my $temp = $first ? "RIGHT" : "LEFT"; + $temp .= "\" COLSPAN=\"2" if $numbering && !$first; + $v1 =~ s|(.*)|$1|o unless $first; + $html .= sprintf "$v1", $r; + } + $first++; + } + $s =~ s/\s*$//; + print "$s\n" if $TEXT; + if ($HTML) { + print HTML "$html\n"; + print HTML "\n

\n"; + + my $i = 0; + while ($GRAPH && defined ${${$output{$report}{'graph'}}[$i]}{'type'}) { + my $type = ${${$output{$report}{'graph'}}[$i]}{'type'}; + my ($title) = ${${$output{$report}{'graph'}}[$i]}{'title'} =~ + m/^\"\s*(.*?)\s*\"$/o; + if ($type eq 'histo3d') { + my (@values, @colors, @labels); + my $num = 0; + my $j; + foreach $j (@{${${$output{$report}{'graph'}}[$i]}{'data'}}) { + $num++; + my ($h) = $$j{'value'} =~ m/^\"\s*(.*?)\s*\"$/o; + my %hh; + $h =~ s/^\%/\%$CLASS\:\:/ unless $h eq '%prog_type'; + { local $^W = 0; no strict; %hh = eval $h } + push @values, \%hh; + my ($t) = $$j{'name'} =~ m/^\"\s*(.*?)\s*\"$/o; + push @labels, $t; + $t = $$j{'color'} || + die "Error in section $report section 'graph'. " . + "No color specified for 'value' $$j{'value'}.\n"; + $t =~ s/^\"\s*\#(.*?)\s*\"$/$1/o; + $t =~ m/^[\da-fA-F]{6}$/o || + die "Error in section $report section 'graph'. " . + "Bad color for 'value' $$j{'value'}.\n"; + my @c = map { hex $_ } ($t =~ m/^(..)(..)(..)$/); + push @colors, \@c; + } + $suffix = '' unless defined $suffix; + my $s = ($i ? $i : '') . $suffix; + print HTML "

\"$title\"> $HTML_output") || + die "Error: cant open $HTML_output\n"; + print HTML "WIDTH=\"$xmax\" HEIGHT=\"$y\" "; + print HTML "SRC=\"$IMG_pth$report$s.$GD_FORMAT\">
\n"; + } + elsif ($type eq 'histo') { + my (%values, %labels); + my $factor = + ${${${${$output{$report}{'graph'}}[$i]}{'data'}}[1]}{'factor'} + || die "Error in section $report section 'graph'. " . + "No factor specified for 'value' " . + ${${${${$output{$report}{'graph'}}[$i]}{'data'}}[1]}{'name'} . + ".\n"; + $factor =~ s/^\"\s*(.*?)\s*\"$/$1/o; + my $labelx = + ${${${${$output{$report}{'graph'}}[$i]}{'data'}}[0]}{'name'} + || die "Error in section $report section 'graph'. " . + "No name specified for value.\n"; + $labelx =~ s/^\"\s*(.*?)\s*\"$/$1/o; + my $labely = + ${${${${$output{$report}{'graph'}}[$i]}{'data'}}[1]}{'name'} + || die "Error in section $report section 'graph'. " . + "No name specified for value.\n"; + $labely =~ s/^\"\s*(.*?)\s*\"$/$1/o; + my $t = ${${${${$output{$report}{'graph'}}[$i]}{'data'}}[0]}{'value'} + || die "Error in section $report section 'graph'. " . + "No 'value' specified for " . + ${${${${$output{$report}{'graph'}}[$i]}{'data'}}[0]}{'name'} . + ".\n"; + $t =~ s/^\"\s*(.*?)\s*\"$/$1/o; + $t =~ s/^\%/\%$CLASS\:\:/ unless $t eq '%prog_type'; + { local $^W = 0; no strict; %labels = eval $t } + + $t = ${${${${$output{$report}{'graph'}}[$i]}{'data'}}[1]}{'value'} || + die "Error in section $report section 'graph'. " . + "No 'value' specified for " . + ${${${${$output{$report}{'graph'}}[$i]}{'data'}}[1]}{'name'} . + ".\n"; + $t =~ s/^\"\s*(.*?)\s*\"$/$1/o; + $t =~ s/^\%/\%$CLASS\:\:/ unless $t eq '%prog_type'; + { local $^W = 0; no strict; %values = eval $t } + my $s = ($i ? $i : '') . $suffix; + { + my $r; + close HTML; + $r = &Histo ("$IMG_dir/$report$s.$GD_FORMAT", $title, $xmax, + $factor, $labelx, $labely, \%values, \%labels); + open (HTML, ">> $HTML_output") || + die "Error: cant open $HTML_output\n"; + print HTML "
\"$title\"
\n" if $r; + } + } + elsif ($type eq 'piechart') { + print "Sorry, graph type 'piechart' not supported yet..\n"; + } + else { + die "Error in section $report section 'graph'. " . + "Invalid 'type' value.\n" + } + $i++; + print HTML "

\n"; + } + print HTML "\n


\n"; + } + } + close HTML if $HTML; +} + +sub EvalExpr { + my $v = shift; + my ($key, $num, $key1) = @_; + my $key2; + + $v =~ s/\n/ /smog; + $v =~ s/^\"(.*?)\"$/$1/o; + if ($key1) { + $key2 = $key; + $v =~ s/([^a-zA-Z_\-]?)total\s*\(\s*%/$1&ComputeTotalDouble\(\\%/og; + } + else { + $v =~ s/([^a-zA-Z_\-]?)total\s*\(\s*%/$1&ComputeTotal\(\\%/og; + # $v =~ s/([^a-zA-Z_\-]?)total\s*\(\s*%([^\)]*)\)/$1&ComputeTotal\("$2"\)/og; + } + $v =~ s/([^a-zA-Z_\-]?)bytes\s*\(\s*/$1&NiceByte\(/og; + $v =~ s/([^a-zA-Z_\-]?)time\s*\(\s*/$1&second2time\(/og; + $v =~ s/([^a-zA-Z_\-]?)time_ms\s*\(\s*/$1&ms2time\(/og; + # $v =~ s/([\$\%\@])/$1${CLASS}\:\:/og; + $v =~ s/([\$\%\@])([^{\s\d])/$1${CLASS}\:\:$2/og; + $v =~ s/([\$\%\@])${CLASS}\:\:(prog_(?:size|type)|key|sec_glob|num)/$1$2/og; + my $r; + # eval { local $^W = 0; no strict; ($r) = eval $v; }; + eval " local \$^W = 0; no strict; (\$r) = $v; "; + $r = 0 unless defined $r; + $r; +} + +sub NiceByte { + my $size = shift; + my $t; + + $size = 0 unless defined $size; + $t = $size / 1024 / 1024 / 1024 > 1 ? + sprintf "%.1f GB", $size / 1024 / 1024 / 1024 : + ($size / 1024 / 1024 > 1 ? sprintf "%.1f MB", $size / 1024 / 1024 : + sprintf "%.1f KB", $size / 1024); + return $t; +} + +sub kb2i { + my $s = shift; + my ($i, $u) = $s =~ m/^(\S+) (\S+)$/; + $i *= 1024 * 8 if $u =~ m/MB/o; + $i *= 1024 * 1024 * 8 if $u =~ m/GB/o; + return $i; +} + +sub Decode_Config_File { + my $file = shift; + my ($line, $section); + my $linenum = 0; + my $info; + my @list; + open (FILE, "$file") || die "Can\'t open config file \"$file\". Abort.\n"; + while (defined ($line = )) { + $linenum++; + last if eof (FILE); + ($info, $linenum, $line) = &read_conf ($linenum, $line, \*FILE); + die "Error in $file line $linenum: must be 'section' instead of '$info'\n" + unless ($info eq 'section'); + ($info, $linenum, $line) = &read_conf ($linenum, $line, \*FILE); + die "Error in $file line $linenum: invalid section name '$info'\n" + unless $info =~ /^\w+$/; + print "section $info {\n" if $DEBUG; + $section = $info; + ($info, $linenum, $line) = &read_conf ($linenum, $line, \*FILE); + die "Error in $file line $linenum: must be a '{' instead of '$info'\n" + unless ($info eq '{'); + ($info, $linenum, $line) = &read_conf ($linenum, $line, \*FILE); + push @list, $section; + while ($info ne '}') { # it is a block + last if eof (FILE); + my $keyword = $info; + ($info, $linenum, $line) = &read_conf ($linenum, $line, \*FILE); + my $value = $info; + if ($info eq '{') { # it is a sub-block + my @a; + $output{$section}{$keyword} = \@a unless $output{$section}{$keyword}; + my %hash; + print "\t$keyword {\n" if $DEBUG; + ($info, $linenum, $line) = &read_conf ($linenum, $line, \*FILE); + my @sublist; # to store the "data" blocks + + while ($info ne '}') { + last if eof (FILE); + my $subkeyword = $info; + ($info, $linenum, $line) = &read_conf ($linenum, $line, \*FILE); + my $subvalue = $info; + if ($info eq '{') { + # it is a sub-sub-block + my %subhash; + print "\t\t$subkeyword {\n" if $DEBUG; + my @b; + $hash{$subkeyword} = \@b unless ${hash}{$subkeyword}; + ($info, $linenum, $line) = &read_conf ($linenum, $line, \*FILE); + while ($info ne '}') { + last if eof (FILE); + my $subsubkeyword = $info; + ($info, $linenum, $line) = &read_conf ($linenum, $line, \*FILE); + my $subsubvalue = $info; + if ($info eq '{') { + die "Error in $file line $linenum: too many blocks.\n"; + } + else { + ($info, $linenum, $line) = + &read_conf ($linenum, $line, \*FILE); + die "Error in $file line $linenum: must be a ';' instead " . + "of '$info'\n" unless ($info eq ';'); + print "\t\t\t$subsubkeyword\t$subsubvalue;\n" if $DEBUG; + $subhash{$subsubkeyword} = $subsubvalue; + ($info, $linenum, $line) = + &read_conf ($linenum, $line, \*FILE); + } + } + ($info, $linenum, $line) = &read_conf ($linenum, $line, \*FILE); + die "Error in $file line $linenum: must be a ';' instead of " . + "'$info'\n" unless $info eq ';'; + push @{$hash{$subkeyword}} , \%subhash; + ($info, $linenum, $line) = &read_conf ($linenum, $line, \*FILE); + print "\t\t};\n" if $DEBUG; + } + else { + ($info, $linenum, $line) = &read_conf ($linenum, $line, \*FILE); + die "Error in $file line $linenum: must be a ';' instead " . + "of '$info'\n" unless $info eq ';'; + print "\t\t$subkeyword\t$subvalue;\n" if $DEBUG; + $hash{$subkeyword} = $subvalue; + ($info, $linenum, $line) = &read_conf ($linenum, $line, \*FILE); + } + } + ($info, $linenum, $line) = &read_conf ($linenum, $line, \*FILE); + die "Error in $file line $linenum: must be a ';' instead of '$info'\n" + unless $info eq ';'; + push @{$output{$section}{$keyword}}, \%hash; + ($info, $linenum, $line) = &read_conf ($linenum, $line, \*FILE); + print "\t};\n" if $DEBUG; + } + else { + ($info, $linenum, $line) = &read_conf ($linenum, $line, \*FILE); + die "Error in $file line $linenum: must be a ';' instead of '$info'\n" + unless $info eq ';'; + print "\t$keyword\t$value;\n" if $DEBUG; + $output{$section}{$keyword} = $value; + ($info, $linenum, $line) = &read_conf ($linenum, $line, \*FILE); + } + } + die "Error in $file line $linenum: must be a '}' instead of '$info'\n" + unless $info eq '}'; + ($info, $linenum, $line) = &read_conf ($linenum, $line, \*FILE); + die "Error in $file line $linenum: must be a ';' instead of '$info'\n" + unless $info eq ';'; + print "};\n\n" if $DEBUG; + } + close FILE; + $output{'_order_'} = \@list; +} + +sub read_conf { + my ($linenum, $line, $file) = @_; + *FILE = *$file; + + $line =~ s,^\s+,,o; # remove useless blanks + $line =~ s,^(\#|//).*$,,o; # remove comments (at the beginning) + while (($line =~ m/^$/o || $line =~ m/^\"[^\"]*$/o) && !(eof (FILE))) { + $line .= ; # read one line + $linenum++; + $line =~ s,^\s*,,om; # remove useless blanks + $line =~ s,^(\#|//).*$,,om; # remove comments (at the beginning) + } + $line =~ s/^( # at the beginning + [{};] # match '{', '}', or ';' + | # OR + \" # a double quoted string + (?:\\.|[^\"\\])* + \" + | # OR + [^{};\"\s]+ # a word + )\s*//mox; + my $info = $1; + if (defined $info && $info) { + chomp $info; + } + else { + warn "Syntax error in conf file line $linenum.\n"; + } + return ($info, $linenum, $line); +} + +sub GetValue { + my $v = shift; + my ($r) = $v =~ m/^(?:\"\s*)?(.*?)(?:\s*\")?$/so; + return $r; +} + +sub Usage { + my ($base) = $0 =~ /([^\/]+)$/; + print "Usage: $base -f innreport.conf [-[no]options]\n"; + print " where options are:\n"; + print " -h (or -help) this help page\n"; + print " -v display the version number of INNreport\n"; + print " -config print INNreport configuration information\n"; + print " -html HTML output"; + print " [default]" if ($HTML); + print "\n"; + print " -g want graphs"; + print " [default]" if ($GRAPH); + print "\n"; + print " -graph an alias for option -g\n"; + print " -d directory directory for Web pages"; + print "\n [default=$HTML_dir]" + if (defined ($HTML_dir)); + print "\n"; + print " -dir directory an alias for option -d\n"; + print " -p directory pictures path (file space)"; + print "\n [default=$IMG_dir]" + if (defined ($IMG_dir)); + print "\n"; + print " -path directory an alias for option -p\n"; + print " -w directory pictures path (web space)"; + print " [default=$IMG_pth]" if (defined ($IMG_pth)); + print "\n"; + print " -webpath directory an alias for option -w\n"; + print "\n"; + print " -i file Name of index file"; + print " [default=$index]" if (defined ($index)); + print "\n"; + print " -index file an alias for option -i\n"; + print " -a want to archive HTML results"; + print " [default]" if ($ARCHIVE); + print "\n"; + print " -archive an alias for option -a\n"; + print " -c number how many report files to keep (0 = all)\n"; + print " [default=$CYCLE]" + if (defined ($CYCLE)); + print "\n"; + print " -cycle number an alias for option -c\n"; + print " -s char separator for filename"; + print " [default=\"$SEPARATOR\"]\n"; + print " -separator char an alias for option -s\n"; + print " -unknown \"Unknown entries from news log file\"\n"; + print " report"; + print " [default]" if ($WANT_UNKNOWN); + print "\n"; + print " -html-unknown Same as above, but in generated HTML output."; + print " [default]" if ($WANT_UNKNOWN); + print "\n"; + print " -maxunrec Max number of unrecognized lines to display\n"; + print " [default=$MAX_UNRECOGNIZED]" + if (defined ($MAX_UNRECOGNIZED)); + print "\n"; + print " -notdaily Never perform daily actions"; + print " [default]" if $NOT_DAILY; + print "\n"; + print " -casesensitive Case sensitive"; + print " [default]" if ($CASE_SENSITIVE); + print "\n\n"; + print "Use no in front of boolean options to unset them.\n"; + print "For example, \"-html\" is set by default. Use \"-nohtml\" to remove this\n"; + print "feature.\n"; + exit 0; +} + +sub Version { + print "\nThis is INNreport version $version\n\n"; + print "Copyright 1996-1999, Fabien Tassin \n"; + exit 0; +} + +sub Summary { + use Config; + + # Convert empty arguments into null string ("") + my $i = 0; + foreach (@old_argv) { + $old_argv[$i] = '""' if $_ eq ''; + $i++; + } + + # Display the summary + print "\nSummary of my INNreport (version $version) configuration:\n"; + print " General options:\n"; + print " command line='@old_argv' (please, check this value)\n"; + print " html=" . ($HTML?"yes":"no") . ", graph=" . + ($GRAPH?"yes":"no") . ", haveGD=" . + ($::HAVE_GD?"yes":"no") . "\n"; + print " archive=" . ($ARCHIVE?"yes":"no") . + ", cycle=$CYCLE, separator=\"" . $SEPARATOR . "\"\n"; + print " case_sensitive=" . + ($CASE_SENSITIVE?"yes":"no") . ", want_unknown=" . + ($WANT_UNKNOWN?"yes":"no") . + ", max_unrecog=$MAX_UNRECOGNIZED\n"; + print " Paths:\n"; + print " html_dir=$HTML_dir\n"; + print " img_dir=$IMG_dir\n"; + print " img_pth=$IMG_pth\n"; + print " index=$index\n"; + print " Platform:\n"; + print " perl version $::Config{baserev} " + . "patchlevel $::Config{patchlevel} " + . "subversion $::Config{subversion}\n"; + print " libperl=$::Config{libperl}, useshrplib=$::Config{useshrplib}, " + . "bincompat3=$::Config{bincompat3}\n"; + print " osname=$::Config{osname}, osvers=$::Config{osvers}, " + . "archname=$::Config{archname}\n"; + print " uname=$::Config{myuname}\n\n"; + + exit 0; +} + +######################### End of File ########################## --- inn-1.7.2q.orig/extra/perl-ccopts +++ inn-1.7.2q/extra/perl-ccopts @@ -0,0 +1,18 @@ +#!/usr/bin/perl + +use warnings; +use strict; +use ExtUtils::Embed; + +my @remove = qw( + -I/usr/local/\S+ + -pipe + -D_LARGEFILE_SOURCE + -D_FILE_OFFSET_BITS=64 + -fstack-protector +); + +my $opts = ccopts; +$opts =~ s/$_\s+// foreach @remove; +print $opts; + --- inn-1.7.2q.orig/extra/gpgverify +++ inn-1.7.2q/extra/gpgverify @@ -0,0 +1,230 @@ +#!/usr/bin/perl -w +require '/usr/lib/news/innshellvars.pl'; + +# written April 1996, tale@isc.org (David C Lawrence) +# mostly rewritten 2001-03-21 by Marco d'Itri +# +# requirements: +# - GnuPG +# - perl 5.004_03 and working Sys::Syslog +# - syslog daemon +# +# There is no locking because gpg is supposed to not need it and controlchan +# will serialize control messages processing anyway. + +require 5.004_03; +use strict; + +# if you keep your keyring somewhere that is not the default used by gpg, +# set appropriately the next line. +my $keyring = '/etc/news/pgp/pubring.pgp'; + +# If you have INN and the script is able to successfully include your +# innshellvars.pl file, the value of the next two variables will be +# overridden. +my $tmpdir = '/var/log/news/'; +my $syslog_facility = 'news'; + +# 1: print PGP output +my $debug = 0; +$debug = 1 if -t 1; + +### Exit value: +### 0 good signature +### 1 no signature +### 2 unknown signature +### 3 bad signature +### 255 problem not directly related to gpg analysis of signature + +############################################################################## +################ NO USER SERVICEABLE PARTS BELOW THIS COMMENT ################ +############################################################################## +my $tmp = ($inn::pathtmp ? $inn::pathtmp : $tmpdir) . "/pgp$$"; +$syslog_facility = $inn::syslog_facility if $inn::syslog_facility; + +my $nntp_format = 0; +$0 =~ s#^.*/##; # trim /path/to/prog to prog + +die "Usage: $0 < message\n" if $#ARGV != -1; + +# Path to gpg binary +my $gpg; +foreach (split(/:/, $ENV{PATH}), qw(/usr/local/bin /opt/gnu/bin)) { + if (-x "$_/gpgv") { + $gpg = "$_/gpgv"; last; + } +} +fail('cannot find the gpgv binary') if not $gpg; + +# this is, by design, case-sensitive with regards to the headers it checks. +# it's also insistent about the colon-space rule. +my ($label, $value, %dup, %header); +while () { + # if a header line ends with \r\n, this article is in the encoding + # it would be in during an NNTP session. some article storage + # managers keep them this way for efficiency. + $nntp_format = /\r\n$/ if $. == 1; + s/\r?\n$//; + + last if /^$/; + if (/^(\S+):[ \t](.+)/) { + ($label, $value) = ($1, $2); + $dup{$label} = 1 if $header{$label}; + $header{$label} = $value; + } elsif (/^\s/) { + fail("non-header at line $.: $_") unless $label; + $header{$label} .= "\n$_"; + } else { + fail("non-header at line $.: $_"); + } +} + +my $pgpheader = 'X-PGP-Sig'; +$_ = $header{$pgpheader}; +exit 1 if not $_; # no signature + +# the $sep value means the separator between the radix64 signature lines +# can have any amount of spaces or tabs, but must have at least one space +# or tab, if there is a newline then the space or tab has to follow the +# newline. any number of newlines can appear as long as each is followed +# by at least one space or tab. *phew* +my $sep = "[ \t]*(\n?[ \t]+)+"; +# match all of the characters in a radix64 string +my $r64 = '[a-zA-Z0-9+/]'; +fail("$pgpheader not in expected format") + unless /^(\S+)$sep(\S+)(($sep$r64{64})+$sep$r64+=?=?$sep=$r64{4})$/; + +my ($version, $signed_headers, $signature) = ($1, $3, $4); +$signature =~ s/$sep/\n/g; + +my $message = "-----BEGIN PGP SIGNED MESSAGE-----\n\n" + . "X-Signed-Headers: $signed_headers\n"; + +foreach $label (split(',', $signed_headers)) { + fail("duplicate signed $label header, can't verify") if $dup{$label}; + $message .= "$label: "; + $message .= $header{$label} if $header{$label}; + $message .= "\n"; +} +$message .= "\n"; # end of headers + +while () { # read body lines + if ($nntp_format) { + # check for end of article; some news servers (eg, Highwind's + # "Breeze") include the dot-CRLF of the NNTP protocol in the + # article data passed to this script + last if $_ eq ".\r\n"; + + # remove NNTP encoding + s/^\.\./\./; + s/\r\n$/\n/; + } + + s/^-/- -/; # pgp quote ("ASCII armor") dashes + $message .= $_; +} + +$message .= + "\n-----BEGIN PGP SIGNATURE-----\n" . + "Version: $version\n" . + $signature . + "\n-----END PGP SIGNATURE-----\n"; + +open(TMP, ">$tmp") or fail("open $tmp: $!"); +print TMP $message; +close TMP or errmsg("close $tmp: $!"); + +my $opts = '--quiet --status-fd=1 --logger-fd=1'; +$opts .= " --keyring=$keyring" if $keyring; + +open(PGP, "$gpg $opts $tmp |") or fail("failed to execute $gpg: $!"); + +undef $/; +$_ = ; + +unlink $tmp or errmsg("unlink $tmp: $!"); + +if (not close PGP) { + if ($? >> 8) { + my $status = $? >> 8; + errmsg("gpg exited status $status") if $status > 1; + } else { + errmsg('gpg died on signal ' . ($? & 255)); + } +} + +print STDERR $_ if $debug; + +my $ok = 255; # default exit status +my $signer; +if (/^\[GNUPG:\]\s+GOODSIG\s+\S+\s+(\S+)/m) { + $ok = 0; + $signer = $1; +} elsif (/^\[GNUPG:\]\s+NODATA/m or /^\[GNUPG:\]\s+UNEXPECTED/m) { + $ok = 1; +} elsif (/^\[GNUPG:\]\s+NO_PUBKEY/m) { + $ok = 2; +} elsif (/^\[GNUPG:\]\s+BADSIG\s+/m) { + $ok = 3; +} + +print "$signer\n" if $signer; +exit $ok; + +sub errmsg { + my $msg = $_[0]; + + eval 'use Sys::Syslog qw(:DEFAULT setlogsock)'; + die "$0: cannot use Sys::Syslog: $@ [$msg]\n" if $@; + + die "$0: cannot set syslog method [$msg]\n" + if not (setlogsock('unix') or setlogsock('inet')); + + $msg .= " processing $header{'Message-ID'}" if $header{'Message-ID'}; + + openlog($0, 'pid', $syslog_facility); + syslog('err', '%s', $msg); + closelog(); +} + +sub fail { + errmsg($_[0]); + unlink $tmp; + exit 255; +} + +__END__ + +# Copyright 2000 by Marco d'Itri + +# License of the original version distributed by David C. Lawrence: + +# Copyright (c) 1996 UUNET Technologies, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by UUNET Technologies, Inc. +# 4. The name of UUNET Technologies ("UUNET") may not be used to endorse or +# promote products derived from this software without specific prior +# written permission. +# +# THIS SOFTWARE IS PROVIDED BY UUNET ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL UUNET BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +# OF THE POSSIBILITY OF SUCH DAMAGE. --- inn-1.7.2q.orig/extra/innreport_inn.pm +++ inn-1.7.2q/extra/innreport_inn.pm @@ -0,0 +1,2102 @@ +########################################################## +# INN module for innreport (3.*). +# +# Sample file tested with INN 2.3, 2.2, 1.7.2 and 1.5.1 +# +# (c) 1997-1999 by Fabien Tassin +# version 3.0.2 +########################################################## + +# TODO: add the map file. + +package innreport_inn; + +my $MIN = 1E10; +my $MAX = -1; + +my %ctlinnd = ('a', 'addhist', 'D', 'allow', + 'b', 'begin', 'c', 'cancel', + 'u', 'changegroup', 'd', 'checkfile', + 'e', 'drop', 'f', 'flush', + 'g', 'flushlogs', 'h', 'go', + 'i', 'hangup', 's', 'mode', + 'j', 'name', 'k', 'newgroup', + 'l', 'param', 'm', 'pause', + 'v', 'readers', 't', 'refile', + 'C', 'reject', 'o', 'reload', + 'n', 'renumber', 'z', 'reserve', + 'p', 'rmgroup', 'A', 'send', + 'q', 'shutdown', 'B', 'signal', + 'r', 'throttle', 'w', 'trace', + 'x', 'xabort', 'y', 'xexec', + 'E', 'logmode', 'F', 'feedinfo', + 'T', 'filter', 'P', 'perl',); + +my %timer_names = (idle => 'idle', + hishave => 'history lookup', + hisgrep => 'history grep', + hiswrite => 'history write', + hissync => 'history sync', + artlink => 'article link', + artwrite => 'article write', + artcncl => 'article cancel', + artctrl => 'article control', + sitesend => 'site send', + perl => 'perl filter', +); + +my %innfeed_timer_names = ( + 'idle' => 'idle', + 'blstats' => 'backlog stats', + 'stsfile' => 'status file', + 'newart' => 'article new', + 'prepart' => 'article prepare', + 'readart' => 'article read', + 'read' => 'data read', + 'write' => 'data write', + 'cb' => 'callbacks', +); + +my %nnrpd_timer_names = ( + 'idle' => 'idle', + 'newnews' => 'newnews', +); + +# init innd timer +foreach (values %timer_names) { + $innd_time_min{$_} = $MIN; + $innd_time_max{$_} = $MAX; + $innd_time_time{$_} = 0; # to avoid a warning... Perl < 5.004 + $innd_time_num{$_} = 0; # ... +} +$innd_time_times = 0; # ... + +# init innfeed timer +foreach (values %innfeed_timer_names) { + $innfeed_time_min{$_} = $MIN; + $innfeed_time_max{$_} = $MAX; + $innfeed_time_time{$_} = 0; # to avoid a warning... Perl < 5.004 + $innfeed_time_num{$_} = 0; # ... +} +$innfeed_time_times = 0; # ... + +# init nnrpd timer +foreach (values %nnrpd_timer_names) { + $nnrpd_time_min{$_} = $MIN; + $nnrpd_time_max{$_} = $MAX; + $nnrpd_time_time{$_} = 0; # to avoid a warning... Perl < 5.004 + $nnrpd_time_num{$_} = 0; # ... +} +$nnrpd_time_times = 0; # ... + +# collect: Used to collect the data. +sub collect { + my ($day, $hour, $prog, $res, $left, $CASE_SENSITIVE) = @_; + + return 1 if $left =~ /Reading config from (\S+)$/o; + + ######## + ## inn (from the "news" log file - not from "news.notice") + ## + if ($prog eq "inn") { + # accepted article + if ($res =~ m/[\+j]/o) { + $hour =~ s/:.*$//o; + $inn_flow{"$day $hour"}++; + $inn_flow_total++; + + # Memorize the size. This can only be done with INN >= 1.5xx and + # DO_LOG_SIZE = DO. + + # server size [feeds] + # or + # server (filename) size [feeds] + + my ($s) = $left =~ /^\S+ \S+ (?:\(\S+\) )?(\d+)(?: |$)/o; + if ($s) { + $inn_flow_size{"$day $hour"} += $s; + $inn_flow_size_total += $s; + } + return 1; + } + + # 437 Duplicate article + if ($left =~ /(\S+) <[^>]+> 437 Duplicate(?: article)?$/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $inn_badart{$server}++; + $inn_duplicate{$server}++; + return 1; + } + # 437 Unapproved for + if ($left =~ /(\S+) <[^>]+> 437 Unapproved for \"([^\"]+)\"$/o) { + my ($server, $group) = ($1, $2); + $server = lc $server unless $CASE_SENSITIVE; + $inn_badart{$server}++; + $inn_unapproved{$server}++; + $inn_unapproved_g{$group}++; + return 1; + } + # 437 Too old -- ... + if ($left =~ /(\S+) <[^>]+> 437 Too old -- /o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $inn_badart{$server}++; + $inn_tooold{$server}++; + return 1; + } + # 437 Unwanted site ... in path + if ($left =~ /(\S+) <[^>]+> 437 Unwanted site (\S+) in path$/o) { + my ($server, $site) = ($1, $2); + $server = lc $server unless $CASE_SENSITIVE; + $inn_badart{$server}++; + $inn_uw_site{$server}++; + $inn_site_path{$site}++; + return 1; + } + # 437 Unwanted newsgroup "..." + if ($left =~ /(\S+) <[^>]+> 437 Unwanted newsgroup \"(\S+)\"$/o) { + my ($server, $group) = ($1, $2); + ($group) = split(/,/, $group); + $server = lc $server unless $CASE_SENSITIVE; + $inn_badart{$server}++; + $inn_uw_ng_s{$server}++; + $inn_uw_ng{$group}++; + return 1; + } + # 437 Unwanted distribution "..." + if ($left =~ /(\S+) <[^>]+> 437 Unwanted distribution \"(\S+)\"$/o) { + my ($server, $dist) = ($1, $2); + $server = lc $server unless $CASE_SENSITIVE; + $inn_badart{$server}++; + $inn_uw_dist_s{$server}++; + $inn_uw_dist{$dist}++; + return 1; + } + # 437 Linecount x != y +- z + if ($left =~ /(\S+) <[^>]+> 437 Linecount/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $inn_badart{$server}++; + $inn_linecount{$server}++; + return 1; + } + # 437 No colon-space in "xxxx" header + if ($left =~ /(\S+) <[^>]+> 437 No colon-space in \"[^\"]+\" header/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $inn_badart{$server}++; + $innd_others{$server}++; + $innd_no_colon_space{$server}++; + return 1; + } + # 437 Article posted in the future -- "xxxxx" + if ($left =~ /(\S+) <[^>]+> 437 Article posted in the future -- \"[^\"]+\"/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $innd_posted_future{$server}++; + $innd_others{$server}++; + $inn_badart{$server}++; + return 1; + } + # 437 article includes "....." + if ($left =~ /(\S+) <[^>]+> 437 article includes/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $innd_strange_strings{$server}++; + $innd_others{$server}++; + $inn_badart{$server}++; + return 1; + } + # Cancelling <...> + if ($left =~ /(\S+) <[^>]+> Cancelling/o) { + return 1; + } + # all others are just counted as "Other" + if ($left =~ /(\S+) /o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $inn_badart{$server}++; + $innd_others{$server}++; + return 1; + } + } + + ######## + ## innd + if ($prog eq "innd") { + ## Note for innd logs: + ## there's a lot of entries detected but still not used + ## (because of a lack of interest). + + # think it's a dotquad + return 1 if $left =~ /^think it\'s a dotquad$/o; + if ($left =~ /^SERVER /o) { + # SERVER perl filtering enabled + return 1 if $left =~ /^SERVER perl filtering enabled$/o; + # SERVER perl filtering disabled + return 1 if $left =~ /^SERVER perl filtering disabled$/o; + # SERVER cancelled +id + return 1 if $left =~ /^SERVER cancelled /o; + } + # rejecting[perl] + if ($left =~ /^rejecting\[perl\] <[^>]+> \d+ (.*)/o) { + $innd_filter_perl{$1}++; + return 1; + } + # closed lost + return 1 if $left =~ /^\S+ closed lost \d+/o; + # control command (by letter) + if ($left =~ /^(\w)$/o) { + my $command = $1; + my $cmd = $ctlinnd{$command}; + $cmd = $command unless $cmd; + return 1 if $cmd eq 'flush'; # to avoid a double count + $innd_control{"$cmd"}++; + return 1; + } + # control command (letter + reason) + if ($left =~ /^(\w):.*$/o) { + my $command = $1; + my $cmd = $ctlinnd{$command}; + $cmd = $command unless $cmd; + return 1 if $cmd eq 'flush'; # to avoid a double count + $innd_control{"$cmd"}++; + return 1; + } + # opened + return 1 if $left =~ /\S+ opened \S+:\d+:file$/o; + # buffered + return 1 if $left =~ /\S+ buffered$/o; + # spawned + return 1 if $left =~ /\S+ spawned \S+:\d+:proc:\d+$/o; + return 1 if $left =~ /\S+ spawned \S+:\d+:file$/o; + # running + return 1 if $left =~ /\S+ running$/o; + # sleeping + if ($left =~ /(\S+):\d+:proc:\d+ sleeping$/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $innd_blocked{$server}++; + return 1; + } + # blocked sleeping + if ($left =~ /(\S+):\d+:proc:\d+ blocked sleeping/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $innd_blocked{$server}++; + return 1; + } + if ($left =~ /(\S+):\d+ blocked sleeping/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $innd_blocked{$server}++; + return 1; + } + # restarted + return 1 if $left =~ m/^\S+ restarted$/o; + # starting + return 1 if $left =~ m/^\S+ starting$/o; + # readclose + return 1 if $left =~ m/^\S+:\d+ readclose+$/o; + # rejected 502 + if ($left =~ m/^(\S+) rejected 502$/) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $innd_no_permission{$server}++; + return 1; + } + # rejected 505 + if ($left =~ m/^(\S+) rejected 505$/) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $innd_too_many_connects_per_minute{$server}++; + return 1; + } + # connected + if ($left =~ /^(\S+) connected \d+/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $innd_connect{$server}++; + return 1; + } + # closed (with times) + if ($left =~ /(\S+):\d+ closed seconds (\d+) accepted (\d+) refused (\d+) rejected (\d+) duplicate (\d+) accepted size (\d+) duplicate size (\d+)$/o) { + my ($server, $seconds, $accepted, $refused, $rejected, $duplicate, $accptsize, $dupsize) = + ($1, $2, $3, $4, $5, $6, $7, $8); + $server = lc $server unless $CASE_SENSITIVE; + $innd_seconds{$server} += $seconds; + $innd_accepted{$server} += $accepted; + $innd_refused{$server} += $refused; + $innd_rejected{$server} += $rejected; + $innd_stored_size{$server} += $accptsize; + $innd_duplicated_size{$server} += $dupsize; + return 1; + } elsif ($left =~ /(\S+):\d+ closed seconds (\d+) accepted (\d+) refused (\d+) rejected (\d+)$/o) { + # closed (with times) + my ($server, $seconds, $accepted, $refused, $rejected) = + ($1, $2, $3, $4, $5); + $server = lc $server unless $CASE_SENSITIVE; + $innd_seconds{$server} += $seconds; + $innd_accepted{$server} += $accepted; + $innd_refused{$server} += $refused; + $innd_rejected{$server} += $rejected; + return 1; + } + # closed (without times (?)) + return 1 if $left =~ m/\S+ closed$/o; + # checkpoint + return 1 if $left =~ m/^\S+:\d+ checkpoint /o; + # if ($left =~ /(\S+):\d+ checkpoint seconds (\d+) accepted (\d+) + # refused (\d+) rejected (\d+)$/) { + # # Skipped... + # my ($server, $seconds, $accepted, $refused, $rejected) = + # ($1, $2, $3, $4, $5); + # $innd_seconds{$server} += $seconds; + # $innd_accepted{$server} += $accepted; + # $innd_refused{$server} += $refused; + # $innd_rejected{$server} += $rejected; + # return 1; + # } + + # flush + if ($left =~ /(\S+) flush$/o) { + $innd_control{"flush"}++; + return 1; + } + # flush-file + if ($left =~ /flush_file/) { + $innd_control{"flush_file"}++; + return 1; + } + # too many connections from site + if ($left =~ /too many connections from (\S+)/o) { + $innd_max_conn{$1}++; + return 1; + } + # overview exit 0 elapsed 23 pid 28461 + return 1 if $left =~ m/\S+ exit \d+ .*$/o; + # internal rejecting huge article + if ($left =~ /(\S+) internal rejecting huge article/o) { + my $server = $1; + $server =~ s/:\d+$//o; + $server = lc $server unless $CASE_SENSITIVE; + $innd_huge{$server}++; + return 1; + } + # internal closing free channel + if ($left =~ /(\S+) internal closing free channel/o) { + $innd_misc{"Free channel"}++; + return 1; + } + # internal (other) + return 1 if $left =~ /\S+ internal/o; + # wakeup + return 1 if $left =~ /\S+ wakeup$/o; + # throttle + if ($left =~ /(\S+) throttled? /) { + $innd_control{"throttle"}++; + return 1; + } + # profile timer + # ME time X nnnn X(X) [...] + # The exact timers change from various versions of INN, so try to deal + # with this in a general fashion. + if ($left =~ m/^\S+\s+ # ME + time\ (\d+)\s+ # time + ((?:\S+\ \d+\(\d+\)\s*)+) # timer values + $/ox) { + $innd_time_times += $1; + my $timers = $2; + + while ($timers =~ /(\S+) (\d+)\((\d+)\)\s*/g) { + my $name = $timer_names{$1} || $1; + my $average = $2 / ($3 || 1); + $innd_time_time{$name} += $2; + $innd_time_num{$name} += $3; + $innd_time_min{$name} = $average + if ($3 && $innd_time_min{$name} > $average); + $innd_time_max{$name} = $average + if ($3 && $innd_time_max{$name} < $average); + } + return 1; + } + # ME time xx idle xx(xx) [ bug ? a part of timer ?] + return 1 if $left =~ m/^ME time \d+ idle \d+\(\d+\)\s*$/o; + # ME HISstats x hitpos x hitneg x missed x dne + # + # from innd/his.c: + # HIShitpos: the entry existed in the cache and in history. + # HIShitneg: the entry existed in the cache but not in history. + # HISmisses: the entry was not in the cache, but was in the history file. + # HISdne: the entry was not in cache or history. + if ($left =~ m/^ME\ HISstats # ME HISstats + \ (\d+)\s+hitpos # hitpos + \ (\d+)\s+hitneg # hitneg + \ (\d+)\s+missed # missed + \ (\d+)\s+dne # dne + $/ox) { + $innd_his{'Positive hits'} += $1; + $innd_his{'Negative hits'} += $2; + $innd_his{'Cache misses'} += $3; + $innd_his{'Do not exist'} += $4; + return 1; + } + # SERVER history cache final: 388656 lookups, 1360 hits + if ($left =~ m/^SERVER history cache final: (\d+) lookups, (\d+) hits$/) { + $innd_cache{'Lookups'} += $1; + $innd_cache{'Hits'} += $2; + return 1; + } + # added by Md 20000122 + return 1 if $left =~ m/^Pre-commit cache initialized/; + # bad_hosts (appears after a "cant gesthostbyname" from a feed) + return 1 if $left =~ m/\S+ bad_hosts /o; + # cant read + return 1 if $left =~ m/\S+ cant read/o; + # cant write + return 1 if $left =~ m/\S+ cant write/o; + # cant flush + return 1 if $left =~ m/\S+ cant flush/o; + # spoolwake + return 1 if $left =~ m/\S+ spoolwake$/o; + # spooling + return 1 if $left =~ m/\S+ spooling/o; + # DEBUG + return 1 if $left =~ m/^DEBUG /o; + # NCmode + return 1 if $left =~ m/\S+ NCmode /o; + # outgoing + return 1 if $left =~ m/\S+ outgoing/o; + # inactive + return 1 if $left =~ m/\S+ inactive/o; + # timeout + return 1 if $left =~ m/\S+ timeout/o; + # lcsetup + return 1 if $left =~ m/\S+ lcsetup/o; + # rcsetup + return 1 if $left =~ m/\S+ rcsetup/o; + # flush_all + return 1 if $left =~ m/\S+ flush_all/o; + # buffered + return 1 if $left =~ m/\S+ buffered$/o; + # descriptors + return 1 if $left =~ m/\S+ descriptors/o; + # ccsetup + return 1 if $left =~ m/\S+ ccsetup/o; + # renumbering + return 1 if $left =~ m/\S+ renumbering/o; + # renumber + return 1 if $left =~ m/\S+ renumber /o; + # ihave from me + if ($left =~ m/\S+ ihave_from_me /o) { + $controlchan_ihave_site{'ME'}++; + return 1; + } + # sendme from me + if ($left =~ m/\S+ sendme_from_me /o) { + $controlchan_sendme_site{'ME'}++; + return 1; + } + # newgroup + if ($left =~ m/\S+ newgroup (\S+) as (\S)/o) { + $innd_newgroup{$1} = $2; + return 1; + } + # rmgroup + if ($left =~ m/\S+ rmgroup (\S+)$/o) { + $innd_rmgroup{$1}++; + return 1; + } + # changegroup + if ($left =~ m/\S+ change_group (\S+) to (\S)/o) { + $innd_changegroup{$1} = $2; + return 1; + } + # paused + if ($left =~ m/(\S+) paused /o) { + $innd_control{"paused"}++; + return 1; + } + # throttled + return 1 if $left =~ m/\S+ throttled/o; + # reload + if ($left =~ m/(\S+) reload/o) { + $innd_control{"reload"}++; + return 1; + } + # shutdown + if ($left =~ m/(\S+) shutdown/o) { + $innd_control{"shutdown"}++; + return 1; + } + # SERVER servermode paused + return 1 if ($left =~ /(\S+) servermode paused$/o); + # SERVER servermode running + return 1 if ($left =~ /(\S+) servermode running$/o); + # SERVER flushlogs paused + if ($left =~ /(\S+) flushlogs /) { + $innd_control{"flushlogs"}++; + return 1; + } + # think it's a dotquad + return 1 if $left =~ /think it\'s a dotquad: /o; + # bad_ihave + if ($left =~ /(\S+) bad_ihave /) { + my $server = $1; + $server =~ s/:\d+$//o; + $server = lc $server unless $CASE_SENSITIVE; + $innd_bad_ihave{$server}++; + return 1; + } + # bad_messageid + if ($left =~ /(\S+) bad_messageid/o) { + my $server = $1; + $server =~ s/:\d+$//o; + $server = lc $server unless $CASE_SENSITIVE; + $innd_bad_msgid{$server}++; + return 1; + } + # bad_sendme + if ($left =~ /(\S+) bad_sendme /o) { + my $server = $1; + $server =~ s/:\d+$//o; + $server = lc $server unless $CASE_SENSITIVE; + $innd_bad_sendme{$server}++; + return 1; + } + # bad_command + if ($left =~ /(\S+) bad_command /o) { + my $server = $1; + $server =~ s/:\d+$//o; + $server = lc $server unless $CASE_SENSITIVE; + $innd_bad_command{$server}++; + return 1; + } + # bad_newsgroup + if ($left =~ /(\S+) bad_newsgroup /o) { + my $server = $1; + $server =~ s/:\d+$//o; + $innd_bad_newsgroup{$server}++; + $server = lc $server unless $CASE_SENSITIVE; + return 1; + } + if ($left =~ m/ cant /o) { + # cant select Bad file number + if ($left =~ / cant select Bad file number/o) { + $innd_misc{"Bad file number"}++; + return 1; + } + # cant gethostbyname + if ($left =~ / cant gethostbyname/o) { + $innd_misc{"gethostbyname error"}++; + return 1; + } + # cant accept RCreader + if ($left =~ / cant accept RCreader /o) { + $innd_misc{"RCreader"}++; + return 1; + } + # cant sendto CCreader + if ($left =~ / cant sendto CCreader /o) { + $innd_misc{"CCreader"}++; + return 1; + } + # cant (other) skipped - not particularly interesting + return 1; + } + # bad_newsfeeds no feeding sites + return 1 if $left =~ /\S+ bad_newsfeeds no feeding sites/o; + # CNFS-sm: cycbuff rollover - possibly interesting + return 1 if $left =~ /CNFS-sm: cycbuff \S+ rollover to cycle/o; + # CNFS-sm: CNFSflushallheads: flushing - possibly interesting + return 1 if $left =~ /CNFS-sm: CNFSflushallheads: flushing /o; + # CNFS-sm: metacycbuff rollover with SEQUENTIAL + return 1 if $left =~ /CNFS-sm: metacycbuff \S+ cycbuff is moved to /o; + # Cleanfeed status reports + return 1 if $left =~ /^filter: status/o; + } + ######## + ## innfeed + if ($prog eq "innfeed") { + # connected + if ($left =~ /(\S+):\d+ connected$/) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $innfeed_connect{$server}++; + return 1; + } + # closed periodic + return 1 if $left =~ m/\S+:\d+ closed periodic$/o; + # periodic close + return 1 if $left =~ m/\S+:\d+ periodic close$/o; + # final (child) + return 1 if $left =~ m/\S+:\d+ final seconds \d+ offered \d+ accepted \d+ refused \d+ rejected \d+/o; + # global (real) + return 1 if $left =~ m/\S+ global seconds \d+ offered \d+ accepted \d+ refused \d+ rejected \d+ missing \d+/o; + # final (real) (new format) + if ($left =~ /(\S+) final seconds (\d+) offered (\d+) accepted (\d+) refused (\d+) rejected (\d+) missing (\d+) accsize (\d+) rejsize (\d+) spooled (\d+)/o) { + my ($server, $seconds, $offered, $accepted, $refused, $rejected, + $missing, $accepted_size, $rejected_size, $spooled) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10); + $server = lc $server unless $CASE_SENSITIVE; + $innfeed_seconds{$server} += $seconds; + $innfeed_offered{$server} += $offered; + $innfeed_accepted{$server} += $accepted; + $innfeed_refused{$server} += $refused; + $innfeed_rejected{$server} += $rejected; + $innfeed_missing{$server} += $missing; + $innfeed_spooled{$server} += $spooled; + $innfeed_accepted_size{$server} += $accepted_size; + $innfeed_rejected_size{$server} += $rejected_size; + return 1; + } elsif ($left =~ /(\S+) final seconds (\d+) offered (\d+) accepted (\d+) refused (\d+) rejected (\d+) missing (\d+) spooled (\d+)/o) { + my ($server, $seconds, $offered, $accepted, $refused, $rejected, + $missing, $spooled) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10); + $server = lc $server unless $CASE_SENSITIVE; + $innfeed_seconds{$server} += $seconds; + $innfeed_offered{$server} += $offered; + $innfeed_accepted{$server} += $accepted; + $innfeed_refused{$server} += $refused; + $innfeed_rejected{$server} += $rejected; + $innfeed_missing{$server} += $missing; + $innfeed_spooled{$server} += $spooled; + return 1; + } + # final (only seconds & spooled) + if ($left =~ /(\S+) final seconds (\d+) spooled (\d+)/o) { + my ($server, $seconds, $spooled) = ($1, $2, $3); + $server = lc $server unless $CASE_SENSITIVE; + $innfeed_seconds{$server} += $seconds; + $innfeed_spooled{$server} += $spooled; + return 1; + } + # checkpoint + return 1 if $left =~ m/\S+ checkpoint seconds/o; + # ME file xxxx shrunk from yyyy to zzz + if ($left =~ /^ME file (.*)\.output shrunk from (\d+) to (\d+)$/) { + my ($file, $s1, $s2) = ($1, $2, $3); + $file =~ s|^.*/([^/]+)$|$1|; # keep only the server name + $innfeed_shrunk{$file} += $s1 - $s2; + return 1; + } + # profile timer + # ME time X nnnn X(X) [...] + return 1 if $left =~ m/backlogstats/; + if ($left =~ m/^\S+\s+ # ME + time\ (\d+)\s+ # time + ((?:\S+\ \d+\(\d+\)\s*)+) # timer values + $/ox) { + $innfeed_time_times += $1; + my $timers = $2; + + while ($timers =~ /(\S+) (\d+)\((\d+)\)\s*/g) { + my $name = $innfeed_timer_names{$1} || $1; + my $average = $2 / ($3 || 1); + $innfeed_time_time{$name} += $2; + $innfeed_time_num{$name} += $3; + $innfeed_time_min{$name} = $average + if ($3 && $innfeed_time_min{$name} > $average); + $innfeed_time_max{$name} = $average + if ($3 && $innfeed_time_max{$name} < $average); + } + return 1; + } + # xxx grabbing external tape file + return 1 if $left =~ m/ grabbing external tape file/o; + # hostChkCxns - maxConnections was + return 1 if $left =~ m/hostChkCxns - maxConnections was /o; + # cxnsleep + return 1 if $left =~ m/\S+ cxnsleep .*$/o; + # idle + return 1 if $left =~ m/\S+ idle tearing down connection$/o; + # remote + return 1 if $left =~ m/\S+ remote .*$/o; + # spooling + return 1 if $left =~ m/\S+ spooling no active connections$/o; + # ME articles total + return 1 if $left =~ m/(?:SERVER|ME) articles total \d+ bytes \d+/o; + # ME articles active + return 1 if $left =~ m/(?:SERVER|ME) articles active \d+ bytes \d+/o; + # connect : Connection refused + return 1 if $left =~ m/connect : Connection refused/o; + # connect : Network is unreachable + return 1 if $left =~ m/connect : Network is unreachable/o; + # connect : Address family not supported by protocol + return 1 if $left =~ m/connect : Address family not supported by protocol/o; + # connect : No route to host + return 1 if $left =~ m/connect : No route to host/o; + # connection vanishing + return 1 if $left =~ m/connection vanishing/o; + # can't resolve hostname + return 1 if $left =~ m/can\'t resolve hostname/o; + # new hand-prepared backlog file + return 1 if $left =~ m/new hand-prepared backlog file/o; + # flush re-connect failed + return 1 if $left =~ m/flush re-connect failed/o; + # internal QUIT while write pending + return 1 if $left =~ m/internal QUIT while write pending/o; + # ME source lost . Exiting + return 1 if $left =~ m/(?:SERVER|ME) source lost . Exiting/o; + # ME starting innfeed (+version & date) + return 1 if $left =~ m/(?:SERVER|ME) starting innfeed/o; + # ME finishing at (date) + return 1 if $left =~ m/(?:SERVER|ME) finishing at /o; + # mode no-CHECK entered + return 1 if $left =~ m/mode no-CHECK entered/o; + # mode no-CHECK exited + return 1 if $left =~ m/mode no-CHECK exited/o; + # closed + return 1 if $left =~ m/^(\S+) closed$/o; + # global (+ seconds offered accepted refused rejected missing) + return 1 if $left =~ m/^(\S+) global/o; + # idle connection still has articles + return 1 if $left =~ m/^(\S+) idle connection still has articles$/o; + # missing article for IHAVE-body + return 1 if $left =~ m/^(\S+) missing article for IHAVE-body$/o; + # cannot continue + return 1 if $left =~ m/^cannot continue/o; + if ($left =~ /^(?:SERVER|ME)/o) { + # ME dropping articles into ... + return 1 if $left = ~/ dropping articles into /o; + # ME dropped ... + return 1 if $left = ~/ dropped /o; + # ME internal bad data in checkpoint file + return 1 if $left =~ m/ internal bad data in checkpoint/o; + # ME two filenames for same article + return 1 if $left =~ m/ two filenames for same article/o; + # ME unconfigured peer + return 1 if $left =~ m/ unconfigured peer/o; + # exceeding maximum article size + return 1 if $left =~ m/ exceeding maximum article byte/o; + # no space left on device errors + return 1 if $left =~ m/ ioerr fclose/o; + return 1 if $left =~ m/ lock failed for host/o; + return 1 if $left =~ m/ lock file pid-write/o; + return 1 if $left =~ m/ locked cannot setup peer/o; + return 1 if $left =~ m/ received shutdown signal/o; + # unconfigured peer + return 1 if $left =~ m/ unconfigured peer/o; + # ME lock + return 1 if $left =~ m/ lock/o; + # ME exception: getsockopt (0): Socket operation on non-socket + return 1 if $left =~ m/ exception: getsockopt /o; + # ME config aborting fopen (...) Permission denied + return 1 if $left =~ m/ config aborting fopen /o; + # ME cant chmod innfeed.pid.... + return 1 if $left =~ m/ cant chmod \S+\/innfeed.pid/o; + return 1 if $left =~ m/ tape open failed /o; + return 1 if $left =~ m/ oserr open checkpoint file:/o; + # ME finishing (quickly) + return 1 if $left =~ m/\(quickly\) /o; + # ME config: value of streaming is not a boolean + return 1 if $left =~ m/config: value of \S+ is not/o; + } + # hostChkCxn - now: x.xx, prev: x.xx, abs: xx, curr: x + return 1 if $left =~ m/ hostChkCxn - now/o; + # loading path_to_config_file/innfeed.conf + return 1 if $left =~ m/loading /o; + # Finnaly, to avoid problems with strange error lines, ignore them. + #return 1 if ($left =~ /ME /); + } + ######## + ## innxmit + if ($prog eq "innxmit") { + # 437 Duplicate article + if ($left =~ /(\S+) rejected [^\s]+ \(.*?\) 437 Duplicate article$/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $innxmit_badart{$server}++; + $innxmit_duplicate{$server}++; + return 1; + } + # 437 Unapproved for + if ($left =~ /(\S+) rejected [^\s]+ \(.*\) 437 Unapproved for \"(.*?)\"$/o) { + my ($server, $group) = ($1, $2); + $server = lc $server unless $CASE_SENSITIVE; + $innxmit_badart{$server}++; + $innxmit_unapproved{$server}++; + $innxmit_unapproved_g{$group}++; + return 1; + } + # 437 Too old -- ... + if ($left =~ /(\S+) rejected [^\s]+ \(.*\) 437 Too old -- \".*?\"$/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $innxmit_badart{$server}++; + $innxmit_tooold{$server}++; + return 1; + } + # 437 Unwanted site ... in path + if ($left =~ + /(\S+) rejected [^\s]+ \(.*?\) 437 Unwanted site (\S+) in path$/o) { + my ($server, $site) = ($1, $2); + $server = lc $server unless $CASE_SENSITIVE; + $innxmit_badart{$server}++; + $innxmit_uw_site{$server}++; + # $innxmit_site_path{$site}++; + return 1; + } + # 437 Unwanted newsgroup "..." + if ($left =~ + /(\S+) rejected [^\s]+ \(.*?\) 437 Unwanted newsgroup \"(\S+)\"$/o) { + my ($server, $group) = ($1, $2); + $server = lc $server unless $CASE_SENSITIVE; + $innxmit_badart{$server}++; + $innxmit_uw_ng_s{$server}++; + $innxmit_uw_ng{$group}++; + return 1; + } + # 437 Unwanted distribution "..." + if ($left =~ + /(\S+) rejected [^\s]+ \(.*?\) 437 Unwanted distribution \"(\S+)\"$/o) { + my ($server, $dist) = ($1, $2); + $server = lc $server unless $CASE_SENSITIVE; + $innxmit_badart{$server}++; + $innxmit_uw_dist_s{$server}++; + $innxmit_uw_dist{$dist}++; + return 1; + } + # xx rejected foo.bar/12345 (foo/bar/12345) 437 Unwanted distribution "..." + if ($left =~ /^(\S+) rejected .* 437 Unwanted distribution \"(\S+)\"$/o) { + my ($server, $dist) = ($1, $2); + $server = lc $server unless $CASE_SENSITIVE; + $innxmit_badart{$server}++; + $innxmit_uw_dist_s{$server}++; + $innxmit_uw_dist{$dist}++; + return 1; + } + # 437 Linecount x != y +- z + if ($left =~ /(\S+) rejected [^\s]+ \(.*?\) 437 Linecount/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $innxmit_badart{$server}++; + $innxmit_linecount{$server}++; + return 1; + } + # 437 Newsgroup name illegal -- "xxx" + if ($left =~ /(\S+) rejected .* 437 Newsgroup name illegal -- "[^\"]*"$/) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $innxmit_others{$server}++; + $innxmit_badart{$server}++; + return 1; + } + # Streaming retries + return 1 if ($left =~ /\d+ Streaming retries$/o); + # ihave failed + if ($left =~ /(\S+) ihave failed/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $innxmit_ihfail{$server} = 1; + if ($left = /436 \S+ NNTP \S+ out of space/o) { + $innxmit_nospace{$server}++; + return 1; + } + if ($left = /400 \S+ space/o) { + $innxmit_nospace{$server}++; + return 1; + } + if ($left = /400 Bad file/o) { + $innxmit_crefused{$server}++; + return 1; + } + if ($left = /480 Transfer permission denied/o) { + $innxmit_crefused{$server}++; + return 1; + } + } + # stats (new format) + if ($left =~ + /(\S+) stats offered (\d+) accepted (\d+) refused (\d+) rejected (\d+) missing (\d+) accsize (\d+) rejsize (\d+)$/o) { + my ($server, $offered, $accepted, $refused, $rejected, $missing, $accbytes, $rejbytes) = + ($1, $2, $3, $4, $5, $6, $7, $8); + $server = lc $server unless $CASE_SENSITIVE; + $innxmit_offered{$server} += $offered; + $innxmit_offered{$server} -= $innxmit_ihfail{$server} + if ($innxmit_ihfail{$server}); + $innxmit_accepted{$server} += $accepted; + $innxmit_refused{$server} += $refused; + $innxmit_rejected{$server} += $rejected; + $innxmit_missing{$server} += $missing; + $innxmit_accepted_size{$server} += $accbytes; + $innxmit_rejected_size{$server} += $rejbytes; + $innxmit_site{$server}++; + $innxmit_ihfail{$server} = 0; + return 1; + } + # stats + if ($left =~ + /(\S+) stats offered (\d+) accepted (\d+) refused (\d+) rejected (\d+)$/o) { + my ($server, $offered, $accepted, $refused, $rejected) = + ($1, $2, $3, $4, $5); + $server = lc $server unless $CASE_SENSITIVE; + $innxmit_offered{$server} += $offered; + $innxmit_offered{$server} -= $innxmit_ihfail{$server} + if ($innxmit_ihfail{$server}); + $innxmit_accepted{$server} += $accepted; + $innxmit_refused{$server} += $refused; + $innxmit_rejected{$server} += $rejected; + $innxmit_site{$server}++; + $innxmit_ihfail{$server} = 0; + return 1; + } + # times + if ($left =~ /(\S+) times user (\S+) system (\S+) elapsed (\S+)$/o) { + my ($server, $user, $system, $elapsed) = ($1, $2, $3, $4); + $server = lc $server unless $CASE_SENSITIVE; + $innxmit_times{$server} += $elapsed; + return 1; + } + # connect & no space + if ($left =~ /(\S+) connect \S+ 400 No space/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $innxmit_nospace{$server}++; + $innxmit_site{$server}++; + return 1; + } + # connect & NNTP no space + if ($left =~ /(\S+) connect \S+ 400 \S+ out of space/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $innxmit_nospace{$server}++; + $innxmit_site{$server}++; + return 1; + } + # connect & loadav + if ($left =~ /(\S+) connect \S+ 400 loadav/o) { + my $server = $1; + if ($left =~ /expir/i) { + $server = lc $server unless $CASE_SENSITIVE; + $innxmit_expire{$server}++; + $innxmit_site{$server}++; + return 1; + } + } + # connect 400 (other) + if ($left =~ /(\S+) connect \S+ 400/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $innxmit_crefused{$server}++; + $innxmit_site{$server}++; + return 1; + } + # connect failed + if ($left =~ /(\S+) connect failed/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $innxmit_cfail_host{$server}++; + $innxmit_site{$server}++; + return 1; + } + # authenticate failed + if ($left =~ /(\S+) authenticate failed/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $innxmit_afail_host{$server}++; + $innxmit_site{$server}++; + return 1; + } + # xxx ihave failed 400 loadav [innwatch:hiload] yyy gt zzz + if ($left =~ /^(\S+) ihave failed 400 loadav/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $innxmit_hiload{$server}++; + return 1; + } + # ihave failed + return 1 if ($left =~ /\S+ ihave failed/o); + # requeued (....) 436 No space + return 1 if ($left =~ /\S+ requeued \S+ 436 No space/o); + # requeued (....) 400 No space + return 1 if ($left =~ /\S+ requeued \S+ 400 No space/o); + # requeued (....) 436 Can't write history + return 1 if ($left =~ /\S+ requeued \S+ 436 Can\'t write history/o); + # unexpected response code + return 1 if ($left =~ /unexpected response code /o); + } + + ######## + ## nntplink + if ($prog eq "nntplink") { + $left =~ s/^(\S+):/$1/; + # EOF + if ($left =~ /(\S+) EOF /o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $nntplink_site{$server}++; + $nntplink_eof{$server}++; + return 1; + } + # Broken pipe + if ($left =~ /(\S+) Broken pipe$/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $nntplink_site{$server}++; + $nntplink_bpipe{$server}++; + return 1; + } + # already running - won't die + return 1 if $left =~ /\S+ nntplink.* already running /o; + # connection timed out + if ($left =~ /(\S+) connection timed out/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $nntplink_site{$server}++; + $nntplink_bpipe{$server}++; + return 1; + } + # greeted us with 400 No space + if ($left =~ /(\S+) greeted us with 400 No space/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $nntplink_site{$server}++; + $nntplink_nospace{$server}++; + return 1; + } + # greeted us with 400 loadav + if ($left =~ /(\S+) greeted us with 400 loadav/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $nntplink_site{$server}++; + $nntplink_hiload{$server}++; + return 1; + } + # greeted us with 400 (other) + if ($left =~ /(\S+) greeted us with 400/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $nntplink_site{$server}++; + if ($left =~ /expir/i) { + $nntplink_expire{$server}++; + } else { + $nntplink_fail{$server}++; + } + return 1; + } + # greeted us with 502 + if ($left =~ /(\S+) greeted us with 502/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $nntplink_site{$server}++; + $nntplink_auth{$server}++; + return 1; + } + # sent authinfo + if ($left =~ /(\S+) sent authinfo/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $nntplink_site{$server}++; + $nntplink_auth{$server}++; + return 1; + } + # socket() + if ($left =~ /(\S+) socket\(\): /o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $nntplink_site{$server}++; + $nntplink_sockerr{$server}++; + return 1; + } + # select() + if ($left =~ /(\S+) select\(\) /o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $nntplink_site{$server}++; + $nntplink_selecterr{$server}++; + return 1; + } + # sent IHAVE + if ($left =~ /(\S+) sent IHAVE/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $nntplink_ihfail{$server}++; + if (($left =~ / 436 /) && ($left =~ / out of space /)) { + $nntplink_fake_connects{$server}++; + $nntplink_nospace{$server}++; + } + return 1; + } + # article .... failed(saved): 436 No space + if ($left =~ /(\S+) .* failed\(saved\): 436 No space$/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $nntplink_nospace{$server}++; + return 1; + } + # article .. 400 No space left on device writing article file -- throttling + if ($left =~ /(\S+) .* 400 No space left on device writing article file -- throttling$/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $nntplink_nospace{$server}++; + return 1; + } + # stats + if ($left =~ /(\S+) stats (\d+) offered (\d+) accepted (\d+) rejected (\d+) failed (\d+) connects$/o) { + my ($server, $offered, $accepted, $rejected, $failed, $connects) = + ($1, $2, $3, $4, $5, $6); + $server = lc $server unless $CASE_SENSITIVE; + $nntplink_offered{$server} += $offered - $nntplink_ihfail{$server}++; + $nntplink_accepted{$server} += $accepted; + $nntplink_rejected{$server} += $rejected; + $nntplink_failed{$server} += $failed; + $nntplink_connects{$server} += $connects; + $nntplink_ihfail{$server} = 0; + if ($nntplink_fake_connects{$server}) { + $nntplink_site{$server} += $nntplink_fake_connects{$server}; + $nntplink_fake_connects{$server} = 0; + } else { + $nntplink_site{$server}++; + } + return 1; + } + # xmit + if ($left =~ /(\S+) xmit user (\S+) system (\S+) elapsed (\S+)$/o) { + my ($server, $user, $system, $elapsed) = ($1, $2, $3, $4); + $server = lc $server unless $CASE_SENSITIVE; + $nntplink_times{$server} += $elapsed; + return 1; + } + # xfer + return 1 if $left =~ /\S+ xfer/o; + # Links down .. x hours + if ($left =~ /(\S+) Links* down \S+ \d+/o) { + # Collected but not used + # my $server = $1; + # $server = lc $server unless $CASE_SENSITIVE; + # $nntplink_down{$server} += $hours; + return 1; + } + # 503 Timeout + if ($left =~ /^(\S+) \S+ \S+ \S+ 503 Timeout/o) { + # Collected but not used + # my $server = $1; + # $server = lc $server unless $CASE_SENSITIVE; + # $nntplink_timeout{$server}++; + return 1; + } + # read() error while reading reply + if ($left =~ /^(\S+): read\(\) error while reading reply/o) { + my $server = $1; + $server = lc $server unless $CASE_SENSITIVE; + $nntplink_failed{$server}++; + return 1; + } + # Password file xxxx not found + return 1 if $left =~ /^\S+ Password file \S+ not found/; + # No such + return 1 if $left =~ /^\S+ \S+ \S+ No such/; + # already running + return 1 if $left =~ /^\S+ \S+ already running/; + # error reading version from datafile + return 1 if $left =~ /error reading version from datafile/; + } + ######## + ## nnrpd + if ($prog eq "nnrpd") + { + # Fix a small bug of nnrpd (inn 1.4*) + $left =~ s/^ /\? /o; + # Another bug (in INN 1.5b1) + return 1 if $left =~ /^\020\002m$/o; # ^P^Bm + # bad_history at num for + return 1 if $left =~ /bad_history at \d+ for /o; + # timeout short + return 1 if $left =~ /\S+ timeout short$/o; + # < or > + (blablabla) + return 1 if $left =~ /^\S+ [\<\>] /o; + # cant opendir ... I/O error + return 1 if $left =~ /\S+ cant opendir \S+ I\/O error$/o; + # perl filtering enabled + return 1 if $left =~ /perl filtering enabled$/o; + # connect + if ($left =~ /(\S+) (\([0-9a-fA-F:.]*\) )?connect$/o) { + my $cust = $1; + $cust = lc $cust unless $CASE_SENSITIVE; + my $dom = &host2dom($cust); + $nnrpd_dom_connect{$dom}++; + $nnrpd_connect{$cust}++; + return 1; + } + # group + if ($left =~ /(\S+) group (\S+) (\d+)$/o) { + my ($cust, $group, $num) = ($1, $2, $3); + if ($num) { + $nnrpd_group{$group} += $num; + my ($hierarchy) = $group =~ /^([^\.]+).*$/o; + $nnrpd_hierarchy{$hierarchy} += $num; + } + return 1; + } + # post failed + if ($left =~ /(\S+) post failed (.*)$/o) { + my ($cust, $error) = ($1, $2); + $nnrpd_post_error{$error}++; + return 1; + } + # post ok + return 1 if $left =~ /\S+ post ok/o; + # posts + if ($left =~ /(\S+) posts received (\d+) rejected (\d+)$/o) { + my ($cust, $received, $rejected) = ($1, $2, $3); + $cust = lc $cust unless $CASE_SENSITIVE; + my $dom = &host2dom($cust); + $nnrpd_dom_post_ok{$dom} += $received; + $nnrpd_dom_post_rej{$dom} += $rejected; + $nnrpd_post_ok{$cust} += $received; + $nnrpd_post_rej{$cust} += $rejected; + return 1; + } + # noperm post without permission + if ($left =~ /(\S+) noperm post without permission/o) { + my $cust = $1; + $cust = lc $cust unless $CASE_SENSITIVE; + my $dom = &host2dom($cust); + $nnrpd_dom_post_rej{$dom} ++; + $nnrpd_post_rej{$cust} ++; + return 1; + } + # no_permission + if ($left =~ /(\S+) no_(permission|access)$/o) { + my $cust = $1; + $cust = lc $cust unless $CASE_SENSITIVE; + my $dom = &host2dom($cust); + $nnrpd_no_permission{$cust}++; + $nnrpd_dom_no_permission{$dom}++; + return 1; + } + # bad_auth + if ($left =~ /(\S+) bad_auth$/o) { + my $cust = $1; + $cust = lc $cust unless $CASE_SENSITIVE; + my $dom = &host2dom($cust); + $nnrpd_dom_no_permission{$dom}++; + $nnrpd_no_permission{$cust}++; + return 1; + } + # authinfo + if ($left =~ /\S+ user (\S+)$/o) { + my $user = $1; + $nnrpd_auth{$user}++; + return 1; + } + # unrecognized + command + if ($left =~ /(\S+) unrecognized (.*)$/o) { + my ($cust, $error) = ($1, $2); + $cust = lc $cust unless $CASE_SENSITIVE; + my $dom = &host2dom($cust); + $error = "_null command_" if ($error !~ /\S/); + $error =~ s/^(xmotd) .*$/$1/i if ($error =~ /^xmotd .*$/i); + $nnrpd_dom_unrecognized{$dom}++; + $nnrpd_unrecognized{$cust}++; + $nnrpd_unrecogn_cmd{$error}++; + return 1; + } + # exit + if ($left =~ /(\S+) exit articles (\d+) groups (\d+)$/o) { + my ($cust, $articles, $groups) = ($1, $2, $3); + $cust = lc $cust unless $CASE_SENSITIVE; + my $dom = &host2dom($cust) || '?'; + $nnrpd_connect{$cust}++, $nnrpd_dom_connect{$dom}++ if $cust eq '?'; + $nnrpd_groups{$cust} += $groups; + $nnrpd_dom_groups{$dom} += $groups; + $nnrpd_articles{$cust} += $articles; + $nnrpd_dom_articles{$dom} += $articles; + return 1; + } + # times + if ($left =~ /(\S+) times user (\S+) system (\S+) idle (\S+) elapsed (\S+)$/o) { + my ($cust, $user, $system, $idle, $elapsed) = ($1, $2, $3, $4, $5); + $cust = lc $cust unless $CASE_SENSITIVE; + my $dom = &host2dom($cust); + $nnrpd_times{$cust} += $elapsed; + $nnrpd_resource_user{$cust} += $user; + $nnrpd_resource_system{$cust} += $system; + $nnrpd_resource_idle{$cust} += $idle; + $nnrpd_resource_elapsed{$cust} += $elapsed; + $nnrpd_dom_times{$dom} += $elapsed; + return 1; + } + # artstats + if ($left =~ /(\S+) artstats get (\d+) time (\d+) size (\d+)$/o) { + my ($cust, $articles, $time, $bytes) = ($1, $2, $3, $4); + $cust = lc $cust unless $CASE_SENSITIVE; + my $dom = &host2dom($cust); + $nnrpd_bytes{$cust} += $bytes; + $nnrpd_dom_bytes{$dom} += $bytes; + return 1; + } + # timeout + if ($left =~ /(\S+) timeout$/o) { + my $cust = $1; + $cust = lc $cust unless $CASE_SENSITIVE; + my $dom = &host2dom($cust); + $nnrpd_dom_timeout{$dom}++; + $nnrpd_timeout{$cust}++; + return 1; + } + # timeout in post + if ($left =~ /(\S+) timeout in post$/o) { + my $cust = $1; + $cust = lc $cust unless $CASE_SENSITIVE; + my $dom = &host2dom($cust); + $nnrpd_dom_timeout{$dom}++; + $nnrpd_timeout{$cust}++; + return 1; + } + # cant read Connection timed out + if ($left =~ /(\S+) cant read Connection timed out$/o) { + my $cust = $1; + $cust = lc $cust unless $CASE_SENSITIVE; + my $dom = &host2dom($cust); + $nnrpd_dom_timeout{$dom}++; + $nnrpd_timeout{$cust}++; + return 1; + } + # cant read Operation timed out + if ($left =~ /(\S+) cant read Operation timed out$/o) { + my $cust = $1; + $cust = lc $cust unless $CASE_SENSITIVE; + my $dom = &host2dom($cust); + $nnrpd_dom_timeout{$dom}++; + $nnrpd_timeout{$cust}++; + return 1; + } + # cant read Connection reset by peer + if ($left =~ /(\S+) cant read Connection reset by peer$/o) { + my $cust = $1; + $cust = lc $cust unless $CASE_SENSITIVE; + my $dom = &host2dom($cust); + $nnrpd_dom_reset_peer{$dom}++; + $nnrpd_reset_peer{$cust}++; + return 1; + } + # gethostbyaddr: xxx.yyy.zzz != a.b.c.d + if ($left =~ /^gethostbyaddr: (.*)$/o) { + my $msg = $1; + $nnrpd_gethostbyaddr{$msg}++; + return 1; + } + # cant gethostbyaddr + if ($left =~ /\? cant gethostbyaddr (\S+) .*$/o) { + my $ip = $1; + $nnrpd_gethostbyaddr{$ip}++; + return 1; + } + # cant getpeername + if ($left =~ /\? cant getpeername/o) { + # $nnrpd_getpeername++; + $nnrpd_gethostbyaddr{"? (can't getpeername)"}++; + return 1; + } + # profile timer + # ME time X nnnn X(X) [...] + # The exact timers change from various versions of INN, so try to deal + # with this in a general fashion. + if ($left =~ m/^\S+\s+ # ME + time\ (\d+)\s+ # time + ((?:\S+\ \d+\(\d+\)\s*)+) # timer values + $/ox) { + $nnrpd_time_times += $1; + my $timers = $2; + + while ($timers =~ /(\S+) (\d+)\((\d+)\)\s*/g) { + my $name = $nnrpd_timer_names{$1} || $1; + my $average = $2 / ($3 || 1); + $nnrpd_time_time{$name} += $2; + $nnrpd_time_num{$name} += $3; + $nnrpd_time_min{$name} = $average + if ($3 && $nnrpd_time_min{$name} > $average); + $nnrpd_time_max{$name} = $average + if ($3 && $nnrpd_time_max{$name} < $average); + } + return 1; + } + # ME dropping articles into ... + return 1 if $left = ~/ME dropping articles into /o; + # newnews (interesting but ignored till now) + return 1 if $left =~ /^\S+ newnews /o; + # cant fopen (ignored too) + return 1 if $left =~ /^\S+ cant fopen /o; + # cant read No route to host + return 1 if $left =~ /cant read No route to host/o; + # cant read Broken pipe + return 1 if $left =~ /cant read Broken pipe/o; + # ioctl: ... + return 1 if $left =~ /^ioctl: /o; + } + ######## + ## inndstart + if ($prog eq "inndstart") { + # cant bind Address already in use + # cant bind Permission denied + return 1 if $left =~ /cant bind /o; + # cant setgroups Operation not permitted + return 1 if $left =~ /cant setgroups /o; + } + ######## + ## overchan + if ($prog eq "overchan") { + # times + if ($left =~ /timings (\d+) arts (\d+) of (\d+) ms$/o) { + my ($articles, $work_time, $run_time) = ($1, $2, $3); + # ??? What to do with numbers + return 1; + } + } + ######## + ## batcher + if ($prog eq "batcher") { + # times + if ($left =~ /(\S+) times user (\S+) system (\S+) elapsed (\S+)$/o) { + my ($server, $user, $system, $elapsed) = ($1, $2, $3, $4); + $server = lc $server unless $CASE_SENSITIVE; + # $batcher_user{$server} += $user; + # $batcher_system{$server} += $system; + $batcher_elapsed{$server} += $elapsed; + return 1; + } + # stats + if ($left =~ /(\S+) stats batches (\d+) articles (\d+) bytes (\d+)$/o) { + my ($server, $batches, $articles, $bytes) = ($1, $2, $3, $4); + $server = lc $server unless $CASE_SENSITIVE; + $batcher_offered{$server} += $batches; + $batcher_articles{$server} += $articles; + $batcher_bytes{$server} += $bytes; + return 1; + } + } + ######## + ## rnews + if ($prog eq "rnews") { + # rejected connection + if ($left =~ /rejected connection (.*)$/o) { + $rnews_rejected{$1}++; + return 1; + } + # cant open_remote + if ($left =~ /(cant open_remote .*)$/o) { + $rnews_rejected{$1}++; + return 1; + } + # rejected 437 Unwanted newsgroup + if ($left =~ /rejected 437 Unwanted newsgroup \"(.*)\"$/o) { + $rnews_bogus_ng{$1}++; + return 1; + } + # rejected 437 Unapproved for "xx" + if ($left =~ /rejected 437 Unapproved for \"(.*)\"$/o) { + $rnews_unapproved{$1}++; + return 1; + } + # rejected 437 Unwanted distribution + if ($left =~ /rejected 437 Unwanted distribution (.*)$/o) { + $rnews_bogus_dist{$1}++; + return 1; + } + # rejected 437 Bad "Date" + if ($left =~ /rejected 437 Bad \"Date\" (.*)$/o) { + $rnews_bogus_date{$1}++; + return 1; + } + # rejected 437 Article posted in the future + if ($left =~ /rejected 437 Article posted in the future -- \"(.*)\"$/o) { + $rnews_bogus_date{"(future) $1"}++; + return 1; + } + # rejected 437 Too old -- "..." + if ($left =~ /rejected 437 Too old -- (.*)$/o) { + $rnews_too_old++; + return 1; + } + # rejected 437 Linecount... + if ($left =~ /rejected 437 (Linecount) \d+ \!= \d+/o) { + $rnews_linecount++; + return 1; + } + # rejected 437 Duplicate + if ($left =~ /rejected 437 Duplicate$/o) { + $rnews_duplicate++; + return 1; + } + # rejected 437 Duplicate article + if ($left =~ /rejected 437 (Duplicate article)/o) { + $rnews_duplicate++; + return 1; + } + # rejected 437 No colon-space ... + if ($left =~ /rejected 437 No colon-space in \"(.*)\" header$/o) { + $rnews_no_colon_space++; + return 1; + } + # duplicate path.. + if ($left =~ /^duplicate /o) { + $rnews_duplicate++; + return 1; + } + # offered feed + if ($left =~ /^offered \S+ (\S+)/o) { + my $host = $1; + $host = lc $host unless $CASE_SENSITIVE; + # Small hack used to join article spooled when innd is throttle. + # In this situation, the hostname is a 8 hex digits string + # To avoid confusions with real feeds, the first character is forced + # to be a '3' or a '4' (will work between 9/7/1995 and 13/7/2012). + $host = "Local postings" if $host =~ /^[34][0-9a-f]{7}$/; + $rnews_host{$host}++; + return 1; + } + # rejected 437 ECP rejected + return 1 if $left =~ m/rejected 437 ECP rejected/o; + # rejected 437 "Subject" header too long + return 1 if $left =~ m/header too long/o; + # bad_article missing Message-ID + return 1 if $left =~ m/bad_article missing Message-ID/o; + # cant unspool saving to xxx + return 1 if $left =~ m/cant unspool saving to/o; + } + + ########### + ## ncmspool + if ($prog eq "ncmspool") { + #
good signature from foo@bar.com + if ($left =~ /good signature from (.*)/o) { + $nocem_goodsigs{$1}++; + $nocem_totalgood++; + $nocem_lastid = $1; + return 1; + } + #
bad signature from foo@bar.com + if ($left =~ /bad signature from (.*)/o) { + $nocem_badsigs{$1}++; + $nocem_goodsigs{$1} = 0 unless ($nocem_goodsigs{$1}); + $nocem_totalbad++; + $nocem_lastid = $1; + return 1; + } + #
contained 123 new 456 total ids + if ($left =~ /contained (\d+) new (\d+) total ids/o) { + $nocem_newids += $1; + $nocem_newids{$nocem_lastid} += $1; + $nocem_totalids += $2; + $nocem_totalids{$nocem_lastid} += $2; + return 1; + } + return 1; + } + + ########### + ## controlchan + if ($prog eq "controlchan") { + # loaded /x/y/z/foo.pl + return 1 if $left =~ m/^loaded /; + # starting + return 1 if $left =~ m/^starting/; + # skipping rmgroup x@y (pgpverify failed) in + if ($left =~ m/^skipping \S+ (\S+) \(pgpverify failed\) in /) { + $controlchan_skippgp{$1}++; + $controlchan_who{$1}++; + return 1; + } + if ($left =~ m/^control_(sendme|ihave), [^,]+, (\S+), doit,/o) { + if ($1 eq "sendme") { + $controlchan_sendme_site{$2}++; + } else { + $controlchan_ihave_site{$2}++; + } + return 1; + } + # control_XXgroup, foo.bar [moderated] who who /x/y/12, peer, action, 1 + # + # Various other random junk can end up in the moderated field, like y, + # unmoderated, m, etc. depending on what the control message says. It + # can even have multiple words, which we still don't handle. + if ($left =~ m/^control_(\S+), # type of msg + \s(?:\S+)? # newsgroup name + (\s\S+)? # optional + \s(\S+) # email + \s\S+ # email + \s\S+, # filename + \s\S+, # server + \s([^=,]+(?:=\S+)?), # action + \s*(.*) # code + /x) { + if ($1 eq 'newgroup') { + $controlchan_new{$3}++; + } elsif ($1 eq 'rmgroup') { + $controlchan_rm{$3}++; + } else { + $controlchan_other{$3}++; + } + $controlchan_who{$3}++; + $controlchan_ok{$3} += $5; + my $action = $4; + my $email = $3; + $action =~ s/=.*//; + $controlchan_doit{$email}++ if $action eq 'doit'; + return 1; + } + } + + ########### + ## crosspost + if ($prog eq "crosspost") { + # seconds 1001 links 3182 0 symlinks 0 0 mkdirs 0 0 + # missing 13 toolong 0 other 0 + if ($left =~ /^seconds\ (\d+) + \ links\ (\d+)\ (\d+) + \ symlinks\ (\d+)\ (\d+) + \ mkdirs\ (\d+)\ (\d+) + \ missing\ (\d+) + \ toolong\ (\d+) + \ other\ (\d+) + $/ox) { + $crosspost_time += $1; + $crosspost{'Links made'} += $2; + $crosspost{'Links failed'} += $3; + $crosspost{'Symlinks made'} += $4; + $crosspost{'Symlinks failed'} += $5; + $crosspost{'Mkdirs made'} += $6; + $crosspost{'Mkdirs failed'} += $7; + $crosspost{'Files missing'} += $8; + $crosspost{'Paths too long'} += $9; + $crosspost{'Others'} += $10; + return 1; + } + } + + ########### + ## cnfsstat + if ($prog eq "cnfsstat") { + # Class ALT for groups matching "alt.*" article size min/max: 0/1048576 + # Buffer T3, len: 1953 Mbytes, used: 483.75 Mbytes (24.8%) 0 cycles + if ($left =~ m|^Class\ (\S+)\ for\ groups\ matching\ \S+ + (\ article\ size\ min/max:\ \d+/\d+)? + \ Buffer\ (\S+), + \ len:\ (\d+)\s+Mbytes, + \ used:\ ([\d.]+)\ Mbytes\ \(\s*[\d.]+%\) + \s+(\d+)\ cycles\s* + $|ox) { + my ($class, $buffer, $size, $used, $cycles) = ($1, $3, $4, $5, $6); + my ($h, $m, $s) = $hour =~ m/^(\d+):(\d+):(\d+)$/; + my $time = $h * 3600 + $m * 60 + $s; + $size *= 1024 * 1024; + $used *= 1024 * 1024; + $cnfsstat{$buffer} = $class; + + # If the size changed, invalidate all of our running fill rate stats. + if ($size != $cnfsstat_size{$buffer}) { + delete $cnfsstat_rate{$buffer}; + delete $cnfsstat_samples{$buffer}; + delete $cnfsstat_time{$buffer}; + $cnfsstat_size{$buffer} = $size; + } + elsif ($cnfsstat_time{$buffer}) { + # We want to gather the rate at which cycbuffs fill. Store a + # running total of bytes/second and a total number of samples. + # Ideally we'd want a weighted average of those samples by the + # length of the sample period, but we'll ignore that and assume + # cnfsstat runs at a roughly consistent interval. + my ($period, $added); + $period = $time - $cnfsstat_time{$buffer}; + $period = 86400 - $cnfsstat_time{$buffer} + $time if $period <= 0; + $added = $used - $cnfsstat_used{$buffer}; + if ($cycles > $cnfsstat_cycles{$buffer}) { + $added += $size * ($cycles - $cnfsstat_cycles{$buffer}); + } + if ($added > 0) { + $cnfsstat_rate{$buffer} += $added / $period; + $cnfsstat_samples{$buffer}++; + } + } + $cnfsstat_used{$buffer} = $used; + $cnfsstat_cycles{$buffer} = $cycles; + $cnfsstat_time{$buffer} = $time; + return 1; + } + } + + # Ignore following programs : + return 1 if ($prog eq "uxfxn"); + return 1 if ($prog eq "beverage"); + return 1 if ($prog eq "newsx"); + return 1 if ($prog eq "demmf"); + return 1 if ($prog eq "nnnn"); + return 1 if ($prog eq "slurp"); + return 0; +} + +################################# +# Adjust some values.. + +sub adjust { + my ($first_date, $last_date) = @_; + + my $nnrpd_doit = 0; + my $curious; + + { + my $serv; + if (%nnrpd_connect) { + my $c = keys (%nnrpd_connect); + foreach $serv (keys (%nnrpd_connect)) { + my $dom = &host2dom($serv); + if ($nnrpd_no_permission{$serv}) { + $nnrpd_dom_connect{$dom} -= $nnrpd_connect{$serv} + if defined $nnrpd_dom_connect{$dom}; + $nnrpd_dom_groups{$dom} -= $nnrpd_groups{$serv} + if defined $nnrpd_dom_groups{$dom}; + $nnrpd_dom_times{$dom} -= $nnrpd_times{$serv} + if defined $nnrpd_dom_times{$dom}; + $nnrpd_connect{$serv} -= $nnrpd_no_permission{$serv}; + $nnrpd_groups{$serv} -= $nnrpd_no_permission{$serv} + if defined $nnrpd_groups{$serv}; + delete $nnrpd_connect{$serv} unless $nnrpd_connect{$serv}; + delete $nnrpd_groups{$serv} unless $nnrpd_groups{$serv}; + delete $nnrpd_times{$serv} unless $nnrpd_times{$serv}; + delete $nnrpd_usr_times{$serv} unless $nnrpd_usr_times{$serv}; + delete $nnrpd_sys_times{$serv} unless $nnrpd_sys_times{$serv}; + delete $nnrpd_dom_connect{$dom} unless $nnrpd_dom_connect{$dom}; + delete $nnrpd_dom_groups{$dom} unless $nnrpd_dom_groups{$dom}; + delete $nnrpd_dom_times{$dom} unless $nnrpd_dom_times{$dom}; + $c--; + } + $nnrpd_doit++ + if $nnrpd_groups{$serv} || $nnrpd_post_ok{$serv}; + } + undef %nnrpd_connect unless $c; + } + foreach $serv (keys (%nnrpd_groups)) { + $curious = "ok" unless $nnrpd_groups{$serv} || $nnrpd_post_ok{$serv} || + $nnrpd_articles{$serv}; + } + } + + # Fill some hashes + { + my $key; + foreach $key (keys (%innd_connect)) { + $innd_offered{$key} = ($innd_accepted{$key} || 0) + + ($innd_refused{$key} || 0) + + ($innd_rejected{$key} || 0); + $innd_offered_size{$key} = ($innd_stored_size{$key} || 0) + + ($innd_duplicated_size{$key} || 0); + } + + + # adjust min/max of innd timer stats. + if (%innd_time_min) { + foreach $key (keys (%innd_time_min)) { + $innd_time_min{$key} = 0 if ($innd_time_min{$key} == $MIN); + $innd_time_max{$key} = 0 if ($innd_time_max{$key} == $MAX); + + #$innd_time_min{$key} /= 1000; + #$innd_time_max{$key} /= 1000; + } + } + if (%innfeed_time_min) { + foreach $key (keys (%innfeed_time_min)) { + $innfeed_time_min{$key} = 0 if ($innfeed_time_min{$key} == $MIN); + $innfeed_time_max{$key} = 0 if ($innfeed_time_max{$key} == $MAX); + } + } + if (%nnrpd_time_min) { + foreach $key (keys (%nnrpd_time_min)) { + $nnrpd_time_min{$key} = 0 if ($nnrpd_time_min{$key} == $MIN); + $nnrpd_time_max{$key} = 0 if ($nnrpd_time_max{$key} == $MAX); + } + } + # remove the innd timer stats if not used. + unless ($innd_time_times) { + undef %innd_time_min; + undef %innd_time_max; + undef %innd_time_num; + undef %innd_time_time; + } + # same thing for innfeed timer + unless ($innfeed_time_times) { + undef %innfeed_time_min; + undef %innfeed_time_max; + undef %innfeed_time_num; + undef %innfeed_time_time; + } + # same thing for nnrpd timer + unless ($nnrpd_time_times) { + undef %nnrpd_time_min; + undef %nnrpd_time_max; + undef %nnrpd_time_num; + undef %nnrpd_time_time; + } + + # adjust the crosspost stats. + if (%crosspost) { + foreach $key (keys (%crosspost)) { + $crosspost_times{$key} = $crosspost_time ? + sprintf "%.2f", $crosspost{$key} / $crosspost_time * 60 : "?"; + } + } + } + + if (%inn_flow) { + my ($prev_dd, $prev_d, $prev_h) = ("", -1, -1); + my $day; + foreach $day (sort datecmp keys (%inn_flow)) { + my ($r, $h) = $day =~ /^(.*) (\d+)$/; + my $d = index ("JanFebMarAprMayJunJulAugSepOctNovDec", + substr ($r,0,3)) / 3 * 31 + substr ($r, 4, 2); + $prev_h = $h if ($prev_h == -1); + if ($prev_d == -1) { + $prev_d = $d; + $prev_dd = $r; + } + if ($r eq $prev_dd) { # Same day and same month ? + if ($h != $prev_h) { + if ($h == $prev_h + 1) { + $prev_h++; + } + else { + my $j; + for ($j = $prev_h + 1; $j < $h; $j++) { + my $t = sprintf "%02d", $j; + $inn_flow{"$r $t"} = 0; + } + $prev_h = $h; + } + } + } + else { + my $j; + # then end of the first day... + for ($j = ($prev_h == 23) ? 24 : $prev_h + 1; $j < 24; $j++) { + my $t = sprintf "%02d", $j; + $inn_flow{"$prev_dd $t"} = 0; + } + + # all the days between (if any) + # well, we can forget them as it is supposed to be a tool + # launched daily. + + # the beginning of the last day.. + for ($j = 0; $j < $h; $j++) { + my $t = sprintf "%02d", $j; + $inn_flow{"$r $t"} = 0; + } + $prev_dd = $r; + $prev_d = $d; + $prev_h = $h; + } + } + my $first = 1; + my (%hash, %hash_time, %hash_size, $date, $delay); + foreach $day (sort datecmp keys (%inn_flow)) { + my ($r, $h) = $day =~ /^(.*) (\d+)$/o; + if ($first) { + $first = 0; + my ($t) = $first_date =~ m/:(\d\d:\d\d)$/o; + $date = "$day:$t - $h:59:59"; + $t =~ m/(\d\d):(\d\d)/o; + $delay = 3600 - $1 * 60 - $2; + } + else { + $date = "$day:00:00 - $h:59:59"; + $delay = 3600; + } + $hash{$date} = $inn_flow{$day}; + $hash_size{$date} = $inn_flow_size{$day}; + $inn_flow_labels{$date} = $h; + $hash_time{$date} = $delay; + } + my ($h, $t) = $last_date =~ m/ (\d+):(\d\d:\d\d)$/o; + my ($h2) = $date =~ m/ (\d+):\d\d:\d\d /o; + my $date2 = $date; + $date2 =~ s/$h2:59:59$/$h:$t/; + $hash{$date2} = $hash{$date}; + delete $hash{"$date"}; + $hash_size{$date2} = $hash_size{$date}; + delete $hash_size{"$date"}; + $t =~ m/(\d\d):(\d\d)/o; + $hash_time{$date2} = $hash_time{$date} - ($h2 == $h) * 3600 + $1 * 60 + $2; + delete $hash_time{"$date"}; + $inn_flow_labels{$date2} = $h; + %inn_flow = %hash; + %inn_flow_time = %hash_time; + %inn_flow_size = %hash_size; + } + + if (%innd_bad_ihave) { + my $key; + my $msg = 'Bad ihave control messages received'; + foreach $key (keys %innd_bad_ihave) { + $innd_misc_stat{$msg}{$key} = $innd_bad_ihave{$key}; + } + } + if (%innd_bad_msgid) { + my $key; + my $msg = 'Bad Message-ID\'s offered'; + foreach $key (keys %innd_bad_msgid) { + $innd_misc_stat{$msg}{$key} = $innd_bad_msgid{$key}; + } + } + if (%innd_bad_sendme) { + my $key; + my $msg = 'Ignored sendme control messages received'; + foreach $key (keys %innd_bad_sendme) { + $innd_misc_stat{$msg}{$key} = $innd_bad_sendme{$key}; + } + } + if (%innd_bad_command) { + my $key; + my $msg = 'Bad command received'; + foreach $key (keys %innd_bad_command) { + $innd_misc_stat{$msg}{$key} = $innd_bad_command{$key}; + } + } + if (%innd_bad_newsgroup) { + my $key; + my $msg = 'Bad newsgroups received'; + foreach $key (keys %innd_bad_newsgroup) { + $innd_misc_stat{$msg}{$key} = $innd_bad_newsgroup{$key}; + } + } + if (%innd_posted_future) { + my $key; + my $msg = 'Article posted in the future'; + foreach $key (keys %innd_posted_future) { + $innd_misc_stat{$msg}{$key} = $innd_posted_future{$key}; + } + } + if (%innd_no_colon_space) { + my $key; + my $msg = 'No colon-space in header'; + foreach $key (keys %innd_no_colon_space) { + $innd_misc_stat{$msg}{$key} = $innd_no_colon_space{$key}; + } + } + if (%innd_huge) { + my $key; + my $msg = 'Huge articles'; + foreach $key (keys %innd_huge) { + $innd_misc_stat{$msg}{$key} = $innd_huge{$key}; + } + } + if (%innd_blocked) { + my $key; + my $msg = 'Blocked server feeds'; + foreach $key (keys %innd_blocked) { + $innd_misc_stat{$msg}{$key} = $innd_blocked{$key}; + } + } + if (%innd_strange_strings) { + my $key; + my $msg = 'Including strange strings'; + foreach $key (keys %innd_strange_strings) { + $innd_misc_stat{$msg}{$key} = $innd_strange_strings{$key}; + } + } + if (%rnews_bogus_ng) { + my $key; + my $msg = 'Unwanted newsgroups'; + foreach $key (keys %rnews_bogus_ng) { + $rnews_misc{$msg}{$key} = $rnews_bogus_ng{$key}; + } + } + if (%rnews_bogus_dist) { + my $key; + my $msg = 'Unwanted distributions'; + foreach $key (keys %rnews_bogus_dist) { + $rnews_misc{$msg}{$key} = $rnews_bogus_dist{$key}; + } + } + if (%rnews_unapproved) { + my $key; + my $msg = 'Articles unapproved'; + foreach $key (keys %rnews_unapproved) { + $rnews_misc{$msg}{$key} = $rnews_unapproved{$key}; + } + } + if (%rnews_bogus_date) { + my $key; + my $msg = 'Bad Date'; + foreach $key (keys %rnews_bogus_date) { + $rnews_misc{$msg}{$key} = $rnews_bogus_date{$key}; + } + } + + $rnews_misc{'Too old'}{'--'} = $rnews_too_old if $rnews_too_old; + $rnews_misc{'Bad linecount'}{'--'} = $rnews_linecount if $rnews_linecount; + $rnews_misc{'Duplicate articles'}{'--'} = $rnews_duplicate + if $rnews_duplicate; + $rnews_misc{'No colon-space'}{'--'} = $rnews_no_colon_space + if $rnews_no_colon_space; + + if (%nnrpd_groups) { + my $key; + foreach $key (keys (%nnrpd_connect)) { + unless ($nnrpd_groups{"$key"} || $nnrpd_post_ok{"$key"} || + $nnrpd_articles{"$key"}) { + $nnrpd_curious{$key} = $nnrpd_connect{$key}; + undef $nnrpd_connect{$key}; + } + } + } +} + +sub report_unwanted_ng { + my $file = shift; + open (FILE, "$file") && do { + while () { + my ($c, $n) = $_ =~ m/^\s*(\d+)\s+(.*)$/; + next unless defined $n; + $n =~ s/^newsgroup //o; # for pre 1.8 logs + $inn_uw_ng{$n} += $c; + } + close (FILE); + }; + + unlink ("${file}.old"); + rename ($file, "${file}.old"); + + open (FILE, "> $file") && do { + my $g; + foreach $g (sort {$inn_uw_ng{$b} <=> $inn_uw_ng{$a}} (keys (%inn_uw_ng))) { + printf FILE "%d %s\n", $inn_uw_ng{$g}, $g; + } + close (FILE); + chmod(0660, "$file"); + }; + unlink ("${file}.old"); +} + +########################################################################### + +# Compare 2 dates (+hour) +sub datecmp { + # ex: "May 12 06" for May 12, 6:00am + local($[) = 0; + # The 2 dates are near. The range is less than a few days that's why we + # can cheat to determine the order. It is only important if one date + # is in January and the other in December. + + my($date1) = substr($a, 4, 2) * 24; + my($date2) = substr($b, 4, 2) * 24; + $date1 += index("JanFebMarAprMayJunJulAugSepOctNovDec",substr($a,0,3)) * 288; + $date2 += index("JanFebMarAprMayJunJulAugSepOctNovDec",substr($b,0,3)) * 288; + if ($date1 - $date2 > 300 * 24) { + $date2 += 288 * 3 * 12; + } + elsif ($date2 - $date1 > 300 * 24) { + $date1 += 288 * 3 * 12; + } + $date1 += substr($a, 7, 2); + $date2 += substr($b, 7, 2); + $date1 - $date2; +} + +sub host2dom { + my $host = shift; + + $host =~ m/^[^\.]+(.*)/; + $host =~ m/^[\d\.]+$/ ? "unresolved" : $1 ? "*$1" : "?"; +} + +1; --- inn-1.7.2q.orig/extra/perl-ldopts +++ inn-1.7.2q/extra/perl-ldopts @@ -0,0 +1,19 @@ +#!/usr/bin/perl + +use warnings; +use strict; +use ExtUtils::Embed; + +my @remove = qw( + -L/usr/local/\S+ + -lc + -lm + -lcrypt + -ldl + -fstack-protector +); + +my $opts = ldopts; +$opts =~ s/$_\s+// foreach @remove; +print $opts; + --- inn-1.7.2q.orig/extra/config.data.debian +++ inn-1.7.2q/extra/config.data.debian @@ -0,0 +1,939 @@ +## $Revision: 1.4 $ +## +## InterNetNews configuration file. +## Note that if you leave a field blank, you must have the trailing tab! +## + +# +# This one is for Debian GNU/Linux, and has a particular setup: +# - config files in /etc/news +# - log files in /var/log/news +# - active file, history file in /var/lib/news +# - sockets etc in /var/run/innd +# - news spool in /var/spool/news +# - overview in /var/spool/news/over.view +# +# Miquel van Smoorenburg +# + +## +## 1. MAKE CONFIG PARAMETERS +## Where the DBZ sources are, from C News. INN has a (maybe old) copy. +#### =()@>()= +DBZDIR ../dbz +## If you have a parallel make, set this to "&" +#### =()

@>()= +P +## C pre-processor flags +#### =()@>()= +DEFS -I../include +## C compiler +#### =()@>()= +CC cc +## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO +#### =()@>()= +USE_CHAR_CONST DO +## C compiler flags +#### =()@>()= +CFLAGS $(DEFS) -g -O2 +## C compiler flags to use when compiling dbz +#### =()@>()= +DBZCFLAGS $(CFLAGS) +## What flags to use if profiling; -p or -pg, e.g. +#### =()@>()= +PROF -pg +## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. +#### =()@>()= +LDFLAGS +## If you use the standard NNTP way of connecting, where is the library? +#### =()@>()= +NNTPLIB +## If you need to link in other libraries, add them here. +## On NetBSD and FreeBSD, you must add the -lcrypt directive here +## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. +#### =()@>()= +LIBS +## How to make a lint library; pick BSD, SYSV, or NONE. +#### =()@>()= +LINTLIBSTYLE NONE +## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". +#### =()@>()= +LINTFLAGS -b -h -z $(DEFS) +## Some lints insist on putting out the filename and other crap. +## Possible values: +## LINTFILTER | sed -n -f ../sedf.aix +## LINTFILTER | sed -n -f ../sedf.osx +## LINTFILTER | sed -n -f ../sedf.sun +## LINTFILTER | sed -n -f ../sedf.sysv +## LINTFILTER +#### =()@>()= +LINTFILTER | sed -n -f ../sedf.sun +## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, +## BSD4.4 or NONE. +#### =()@>()= +MANPAGESTYLE SOURCE +## Where various manpages should go +#### =()@>()= +MAN1 /usr/share/man/man1 +#### =()@>()= +MAN3 /usr/share/man/man3 +#### =()@>()= +MAN5 /usr/share/man/man5 +#### =()@>()= +MAN8 /usr/share/man/man8 +## Ranlib command. Use echo if you don't need ranlib. +#### =()@>()= +RANLIB ranlib +## YACC (yet another config control?) +#### =()@>()= +YACC yacc +## Ctags command. Use echo if you don't have ctags. +#### =()@>()= +CTAGS ctags -t -w + + +## +## 2. LOGGING LEVELS +## Facility innd should log under. +#### =()@>()= +LOG_INN_SERVER LOG_NEWS +## Facility all other programs should log under. +#### =()@>()= +LOG_INN_PROG LOG_NEWS +## Flags to use in opening the logs; some programs add LOG_PID. +#### =()@>()= +L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) +## Log a fatal error; program is about to exit. +#### =()@>()= +L_FATAL LOG_CRIT +## Log an error that might mean one or more articles get lost. +#### =()@>()= +L_ERROR LOG_ERR +## Informational notice, usually not worth caring about. +#### =()@>()= +L_NOTICE LOG_NOTICE +## A protocol trace. +#### =()@>()= +L_TRACE LOG_DEBUG +## All incoming control commands (ctlinnd, etc). +#### =()@>()= +L_CC_CMD LOG_NOTICE + + +## +## 3. OWNERSHIPS AND FILE MODES +## Owner of articles and directories and _PATH_INNDDIR +#### =()@>()= +NEWSUSER news +## Group, for same purpose +#### =()@>()= +NEWSGROUP news +## Who gets email from news.daily and about control messages. +#### =()@>()= +NEWSMASTER usenet +## Who gets email on the Path line? +#### =()@>()= +PATHMASTER not-for-mail +## Umask to set. +#### =()@>()= +NEWSUMASK 02 +## Mode that incoming articles are created under. +#### =()@>()= +ARTFILE_MODE 0664 +## Mode that batch files are created under. +#### =()@>()= +BATCHFILE_MODE 0664 +## Mode that directories are created under. +#### =()@>()= +GROUPDIR_MODE 0775 + + +## +## 4. C LIBRARY DIFFERENCES +## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. +## You need vfprintf and vfsprintf if not NONE. +#### =()@>()= +VAR_STYLE STDARGS +## If you don't have , set this to "mystring.h" +#### =()@>()= +STR_HEADER +## If you don't have , set this to "mymemory.h" +#### =()@>()= +MEM_HEADER +## What is a file offset? MUST BE LONG FOR NOW. +#### =()@>()= +OFFSET_T long +## What is the type of an object size? Usually size_t or unsigned int. +#### =()@>()= +SIZE_T size_t +## What is the type of a passwd uid and gid, for use in chown(2)? +#### =()@>()= +UID_T uid_t +#### =()@>()= +GID_T gid_t +## Type of a pid, for use in kill(2). +#### =()@>()= +PID_T pid_t +## Generic pointer, used by memcpy, malloc, etc. Usually char or void. +#### =()@>()= +POINTER void +## Worst-case alignment, in order to shut lint up +#### =()@>()= +ALIGNPTR int +## What should a signal handler return? Usually int or void. +#### =()@>()= +SIGHANDLER void +## Type of variables can be modified in a signal handler? sig_atomic_t +#### =()@>()= +SIGVAR sig_atomic_t +## Function that returns no value, and a pointer to it. Pick int or void +#### =()@>()= +FUNCTYPE void +## Type of 32 bit unsigned integer. +#### =()@>()= +U_INT32_T unsigned int +## Type of 32 bit signed integer. +#### =()@>()= +INT32_T int +## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. +#### =()@>()= +DIR_STYLE DIRENT +## Use flock, lockf, or nothing to lock files? +## Pick FLOCK, LOCKF, FCNTL, or NONE +#### =()@>()= +LOCK_STYLE FCNTL +## Do you have ? Pick DO or DONT +#### =()@>()= +HAVE_UNISTD DO +## Do you have setbuffer? Pick DO or DONT. +#### =()@>()= +HAVE_SETBUFFER DO +## Do you have gettimeofday? Pick DO or DONT. +#### =()@>()= +HAVE_GETTIMEOFDAY DO +## Do you have setproctitle()? Pick DO or DONT. +## You may need to adjust LIBS for this. +#### =()@>()= +HAVE_SETPROCTITLE DONT +## Do you have fchmod? Pick DO or DONT. +#### =()@>()= +HAVE_FCHMOD DO +## Do you have setsid()? Pick DO or DONT. +#### =()@>()= +HAVE_SETSID DO +## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. +#### =()@>()= +HAVE_TM_GMTOFF DO +## Does your (struct stat) have a st_blksize field? Pick DO or DONT. +#### =()@>()= +HAVE_ST_BLKSIZE DO +## Use waitpid instead of wait3? Pick DO or DONT. +#### =()@>()= +HAVE_WAITPID DO +## Use "union wait" instead of int? Pick DO or DONT. +#### =()@>()= +USE_UNION_WAIT DONT +## How to fork? Pick fork or vfork. +#### =()@>()= +FORK fork +## Do you have ? Pick DO or DONT. +#### =()@>()= +HAVE_VFORK DONT +## Do you have symbolic links? Pick DO or DONT. +#### =()@>()= +HAVE_SYMLINK DO +## Do you have Unix-domain sockets? Pick DO or DONT. +#### =()@>()= +HAVE_UNIX_DOMAIN DO +## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. +#### =()@>()= +BIND_USE_SIZEOF DO +## How should close-on-exec be done? Pick IOCTL or FCNTL. +#### =()@>()= +CLX_STYLE FCNTL +## How should non-blocking I/O be done? Pick IOCTL or FCNTL. +#### =()@>()= +NBIO_STYLE FCNTL +## How should resource-totalling be done? Pick RUSAGE or TIMES +#### =()@>()= +RES_STYLE RUSAGE +## How to get number of available descriptors? +## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. +#### =()@>()= +FDCOUNT_STYLE GETRLIMIT +## If greater than -1, then use [gs]etrlimit to set that many descriptors. +## If -1, then no [gs]etrlimit calls are done. +#### =()@>()= +NOFILE_LIMIT -1 +## Do you need as well as ? Pick DO or DONT. +#### =()@>()= +NEED_TIME DO +## What predicate, if any, the macros need +#### =()@>()= +#CTYPE (isascii((c)) && isXXXXX((c))) +#CTYPE ((c) > 0 && isXXXXX((c))) +CTYPE isXXXXX((c)) +## What's the return type of abort? Usually int or void. +#### =()@>()= +ABORTVAL void +## What's the return type of alarm? Usually int or unsigned int. +#### =()@>()= +ALARMVAL unsigned int +## What's the return type of getpid? Usually int or unsigned int. +#### =()@>()= +GETPIDVAL pid_t +## What's the return type of sleep? Usually int or unsigned int. +#### =()@>()= +SLEEPVAL unsigned int +## What's the return type of qsort? Usually int or void. +#### =()@>()= +QSORTVAL void +## What's the return type of lseek? Usually long or off_t. +#### =()@>()= +LSEEKVAL off_t +## What's the return type of free? Usually int or void. +#### =()@>()= +FREEVAL void +## What's the return type of exit? Usually int or void. +## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) +#### =()@>()= +EXITVAL void +## What's the return type of _exit? Usually int or void. +#### =()<_EXITVAL @<_EXITVAL>@>()= +_EXITVAL void + + +## +## 5. C LIBRARY OMISSIONS +## Possible values: +## MISSING_MAN strcasecmp.3 syslog.3 +## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c +## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c +## getdtab has a getdtablesize() routine if you need it; see the lib +## directory and Install.ms for others. +## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. +#### =()@>()= +MISSING_MAN +#### =()@>()= +MISSING_SRC +#### =()@>()= +MISSING_OBJ + + +## +## 6. MISCELLANEOUS CONFIG DATA +## +## Use read/write to update the active file, or mmap? Pick READ or MMAP. +#### =()@>()= +ACT_STYLE MMAP +## Do you want mail notifications of bad control messages. DO or DONT +## Setting it to do results in a lot of mail with the number of spammers +## out there. +#### =()@>()= +MAIL_BADCONTROLS DONT +## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' +## or ``char *'' +#### =()@>()= +MMAP_PTR __caddr_t +## Should we msync when using mmap? Pick DO or DONT. Useful +## with some slightly broken mmap implementations. (like HPUX and BSD/OS). +#### =()@>()= +MMAP_SYNC DONT +## Should we call your msync() with 3 args? (addr,len,flags) +## Choose DO or DONT. +#### =()@>()= +MSYNC_3_ARG DO +## Do clients use our NNTP-server-open routine, or the one in NNTP? +## INND is nicer, but you must install inn.conf files everywhere; NNTP +## is better if you already have lots of /usr/lib/news/server files. +## Pick INND or NNTP. +#### =()@>()= +REM_STYLE INND +## Should rnews save articles that the server rejects? Pick DO or DONT. +#### =()@>()= +RNEWS_SAVE_BAD DO +## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. +#### =()@>()= +RNEWS_LOG_DUPS SYSLOG +## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. +#### =()@>()= +RNEWSPROGS DO +## Should rnews try the local host? Pick DO or DONT. +#### =()@>()= +RNEWSLOCALCONNECT DO +## Environment variable that has remote hostname for rnews. +#### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= +_ENV_UUCPHOST UU_MACHINE +## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. +## (This is only for inews and nnrpd.) +#### =()@>()= +CHECK_INCLUDED_TEXT DO +## Put hosts in the inews Path header? Pick DO or DONT. +#### =()@>()= +INEWS_PATH DONT +## Munge the gecos field of password entry? Pick DO or DONT. +#### =()@>()= +MUNGE_GECOS DO +## How many times to try to fork before giving up +#### =()@>()= +MAX_FORKS 10 +## Largest acceptable article size; 0 allows any size +#### =()@>()= +MAX_ART_SIZE 0L +## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. +#### =()@>()= +INND_DBZINCORE 1 +## Should sub-processes get a nice(2) value? Pick DO or DONT. +#### =()@>()= +INND_NICE_KIDS DO +## Value for nice(2) call in innd. +#### =()@>()= +INND_NICE_VALUE 10 +## Null-terminated list of unknown commands to not log to syslog. +## INND_QUIET_BADLIST "xstream", "xfoo", NULL +#### =()@>()= +INND_QUIET_BADLIST NULL +## Null-terminated set of illegal distribution patterns for local postings. +#### =()@>()= +BAD_DISTRIBS "*.*",NULL +## Verify that the poster is the person doing the cancel? Pick DO or DONT. +## (Can't do this if cancel arrives before the article does, by the way, +## in which case the early cancel will be ignored.) +#### =()@>()= +VERIFY_CANCELS DONT +## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. +#### =()@>()= +LOG_CANCEL_COMMANDS DONT +## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. +#### =()@>()= +MERGE_TO_GROUPS DONT +## File articles in unknown newsgroups into junk? Pick DO or DONT. +#### =()@>()= +WANT_TRASH DO +## Record rejected articles in history? Pick DO or DONT. +#### =()@>()= +REMEMBER_TRASH DO +## Check the linecount against the Lines header? Pick DO or DONT. +#### =()@>()= +CHECK_LINECOUNT DONT +## If checking, the error must be within LINECOUNT_FUZZ lines. +## Five is number of .signature lines + 1. +#### =()@>()= +LINECOUNT_FUZZ 5 +## Have innd throttle itself after this many I/O errors. +#### =()@>()= +IO_ERROR_COUNT 50 +## Default value for ctlinnd -t flag; use 0 to wait and poll. +#### =()@>()= +CTLINND_TIMEOUT 0 +## Flush logs if we go this long with no I/O. +#### =()@>()= +DEFAULT_TIMEOUT 300 +## INND closes channel if inactive this long (seconds). +#### =()@>()= +PEER_TIMEOUT (1 * 60 * 60) +## NNRP exits if first command doesn't arrive within this time (seconds). +#### =()@>()= +INIT_CLIENT_TIMEOUT 30 +## NNRP exits if inactive for this long (seconds). +#### =()@>()= +CLIENT_TIMEOUT (10 * 60) +## Allow nnrpd readers when paused or throttled? Pick DO or DONT. +#### =()@>()= +ALLOW_READERS DO +## Refuse newsreader connections if load is higher then this; -1 disables. +#### =()@>()= +NNRP_LOADLIMIT 10 +## Don't readdir() spool dir if same group within this many secs. +#### =()@>()= +NNRP_RESCAN_DELAY 60 +## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. +## (If DONT, then use only IP addresses in hosts.nnrp) +#### =()@>()= +NNRP_GETHOSTBYADDR DO +## How many Message-ID retrievals until nnrpd does a dbzincore? Set +## to -1 to never do incore. +#### =()@>()= +NNRP_DBZINCORE_DELAY -1 +## Strip Sender from posts that didn't authenticate? Pick DO or DONT. +#### =()@>()= +NNRP_AUTH_SENDER DONT +## Do you want to make life easy for peers to pull feeds from you (it's +## harder on your machine). Pick DO or DONT. With DONT, you get a small +## sleep inserted before each ARTICLE command is processed. (With +## apologies to the Australians in the audience). +#### =()@>()= +LIKE_PULLERS DO +## Allow the NEWNEWS NNTP command? Pick DO or DONT. +## (RFC 977 says you should; your server performance may not agree...) +#### =()@>()= +ALLOW_NEWNEWS DONT +## How many read/write failures until channel is put to sleep or closed? +#### =()@>()= +BAD_IO_COUNT 5 +## Multiplier for sleep in EWOULDBLOCK writes (seconds). +#### =()@>()= +BLOCK_BACKOFF (2 * 60) +## How many article-writes between active and history updates? +#### =()@>()= +ICD_SYNC_COUNT 10 +## Tell resolver _res.options to be fast? Pick DO or DONT. +#### =()@>()= +FAST_RESOLV DONT +## Drop articles that were posted this many days ago. +#### =()@>()= +DEFAULT_CUTOFF 14 +## Maximum number of incoming NNTP connections. +#### =()@>()= +DEFAULT_CONNECTIONS 50 +## Wait this many seconds before channel restarts. +#### =()@>()= +CHANNEL_RETRY_TIME (5 * 60) +## Wait this many seconds before seeing if pause is ended. +#### =()@>()= +PAUSE_RETRY_TIME (5 * 60) +## Wait this many seconds between noticing inactive channels. +#### =()@>()= +CHANNEL_INACTIVE_TIME (10 * 60) +## Put nntplink info (filename) into the log? +#### =()@>()= +NNTPLINK_LOG DONT +## Put article size into the log? +#### =()@>()= +LOG_SIZE DO +## Log by host IP address, rather than from Path line? +#### =()@>()= +IPADDR_LOG DONT +## Support putting feeding IP address in Paths (/a, /t hosts.nntp options) +#### =()@>()= +IPADDR_PATH DO +## Support logging TCP Ident info in Paths (/i hosts.nntp option, requires IPADDR_PATH) +#### =()@>()= +TCPIDENT_PATH DONT +## How do you get the libident library? Probably -lident, blank if no ident +#### =()@>()= +IDENT_LIB +## Log NNTP activity after this many articles. +#### =()@>()= +NNTP_ACTIVITY_SYNC 200 +## Free buffers bigger than this when we're done with them. +#### =()@>()= +BIG_BUFFER (2 * START_BUFF_SIZE) +## A general small buffer. +#### =()@>()= +SMBUF 256 +## Buffer for a single article name. +#### =()@>()= +MAXARTFNAME 10 +## Buffer for a single pathname in the spool directory. +#### =()@>()= +SPOOLNAMEBUFF 512 +## Maximum size of a single header. +#### =()@>()= +MAXHEADERSIZE 1024 +## Byte limit on locally-posted articles; 0 to disable the check. +#### =()@>()= +LOCAL_MAX_ARTSIZE 2097152L +## Default number of bytes to hold in memory when buffered. +#### =()@>()= +SITE_BUFFER_SIZE (16 * 1024) +## Do you have uustat, or just uuq? Pick DO or DONT +#### =()@>()= +HAVE_UUSTAT DO +## Should INN do some setsockopts on network connections. Pick DO or DONT. +## Some versions of Solaris should set to DONT (pre 2.4 it seems) +#### =()@>()= +SET_SOCKOPT DO + + +## +## 7. PATHS TO COMMON PROGRAMS +## Where the raison d'etre for this distribution lives. +#### =()<_PATH_INND @<_PATH_INND>@>()= +_PATH_INND /usr/sbin/innd +## Where the optional front-end that exec's innd lives. +#### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= +_PATH_INNDSTART /usr/sbin/inndstart +## Where news boot-up script should be installed. +#### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= +_PATH_NEWSBOOT /etc/news/boot +## Where sendmail, or a look-alike, lives. Inlude %s for addresses. +#### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= +_PATH_SENDMAIL /usr/sbin/sendmail -oi %s +## Where the shell is. +#### =()<_PATH_SH @<_PATH_SH>@>()= +_PATH_SH /bin/sh +## Where the compress program lives. +#### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= +_PATH_COMPRESS /bin/gzip +## What extension your compress appends +#### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= +_PATH_COMPRESSEXT .gz +## Where egrep lives (you might need the FSF one; see scanlogs) +#### =()<_PATH_EGREP @<_PATH_EGREP>@>()= +_PATH_EGREP /bin/egrep +## Where perl lives +#### =()<_PATH_PERL @<_PATH_PERL>@>()= +_PATH_PERL /usr/bin/perl +## Where awk lives +#### =()<_PATH_AWK @<_PATH_AWK>@>()= +_PATH_AWK /usr/bin/awk +## Where sed lives (you might need the FSF one) +#### =()<_PATH_SED @<_PATH_SED>@>()= +_PATH_SED /bin/sed +## Where sort lives (you may want the FSF one). +#### =()<_PATH_SORT @<_PATH_SORT>@>()= +_PATH_SORT /usr/bin/sort +## Where inews lives. +#### =()<_PATH_INEWS @<_PATH_INEWS>@>()= +_PATH_INEWS /usr/bin/inews +## Where rnews lives. +#### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= +_PATH_RNEWS /usr/bin/rnews +## Where generic authentication programs live. +#### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= +_PATH_AUTHDIR /usr/lib/news/auth.dir +## Where the NNRP server lives. +#### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= +_PATH_NNRPD /usr/sbin/in.nnrpd +## The path of the process run when an unknown host connects to innd. +## Usually the same as _PATH_NNRPD, but may be, e.g., the path to +## nntpd from the reference implementation. +#### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= +_PATH_NNTPD /usr/sbin/in.nnrpd +## Where the NNQR server lives. Make same as _PATH_NNRPD for now +#### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= +_PATH_NNQRD /usr/sbin/in.nnrpd +## Where most other programs live. +## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. +#### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= +_PATH_NEWSBIN /usr/lib/news/bin +## Where temporary files live on the server. Probably shouldn't be world +## writable. +#### =()<_PATH_TMP @<_PATH_TMP>@>()= +_PATH_TMP /var/spool/news/in.coming/tmp +## Command to send mail (with -s "subject" allowed) +#### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= +_PATH_MAILCMD /usr/lib/news/bin/innmail +## Where scripts should have shlock create locks. +#### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= +_PATH_LOCKS /var/run/innd +## Where your GNU gzip binary is (for rnews to run on gzipped batches). +#### =()<_PATH_GZIP @<_PATH_GZIP>@>()= +_PATH_GZIP /bin/gzip + +## +## 8. PATHS RELATED TO THE SPOOL DIRECTORY +## Spool directory, where articles live. +#### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= +_PATH_SPOOL /var/spool/news +## Spool directory where overview data lives. +#### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= +_PATH_OVERVIEWDIR /var/spool/news/over.view +## Name of overview file within its spool directory. +#### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= +_PATH_OVERVIEW .overview +## Where rnews spools its input. +#### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= +_PATH_SPOOLNEWS /var/spool/news/in.coming +## Where rnews creates temporary files until finished +#### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= +_PATH_SPOOLTEMP /var/spool/news/in.coming/tmp +## Where rnews puts bad input. +#### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= +_PATH_BADNEWS /var/spool/news/in.coming/bad +## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. +#### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= +_PATH_RELBAD bad +## Where the XBATCH command should put the batches. Normally same as +## _PATH_SPOOLNEWS so that 'rnews -U' can find it. +#### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= +_PATH_XBATCHES /var/spool/news/in.coming + + +## +## 9. EXECUTION PATHS FOR INND AND RNEWS +## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. +#### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= +_PATH_RNEWS_DUP_LOG /dev/null +## Rnews may execute any program in this directory; see RNEWSPROGS. +#### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= +_PATH_RNEWSPROGS /usr/lib/news/rnews +## Path to control messages scripts. +#### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= +_PATH_CONTROLPROGS /usr/lib/news/control +## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. +#### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= +_PATH_BADCONTROLPROG default + + +## +## 10. SOCKETS CREATED BY INND OR CLIENTS +#### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= +_PATH_INNDDIR /var/run/innd +## Unix-domain stream socket that rnews connects to. +#### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= +_PATH_NNTPCONNECT /var/run/innd/nntpin +## Unix-domain datagram socket that ctlinnd to. +#### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= +_PATH_NEWSCONTROL /var/run/innd/control +## Temporary socket created by ctlinnd; run through mktemp +#### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= +_PATH_TEMPSOCK /var/run/innd/ctlinndXXXXXX + + +## +## 11. LOG AND CONFIG FILES +## Shell script that sets most of these as shell vars +#### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= +_PATH_SHELLVARS /usr/lib/news/innshellvars +## Perl script that sets most of these as perl variables +#### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= +_PATH_PERL_SHELLVARS /usr/lib/news/innshellvars.pl +## TCL script that sets most of these as tcl variables +#### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= +_PATH_TCL_SHELLVARS /usr/lib/news/innshellvars.tcl +## csh script that sets most of these as csh variables +#### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= +_PATH_CSH_SHELLVARS /usr/lib/news/innshellvars.csh +## Where most config and data files are usually stored; not required +## to the home directory of NEWSUSER. +#### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= +_PATH_NEWSLIB /var/lib/news +## The group owner of the rnews program. Usually uucp. +#### =()@>()= +RNEWS_GROUP news +## The server's log file. +#### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= +_PATH_LOGFILE /var/log/news/log +## The server's error log file. +#### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= +_PATH_ERRLOG /var/log/news/errlog +## Where most sylog log files go; see also scanlogs, innstat, etc. +#### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= +_PATH_MOST_LOGS /var/log/news +## How many generates of log files to keep. +#### =()@>()= +LOG_CYCLES 7 +## Text value of the server's pid. +#### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= +_PATH_SERVERPID /var/run/innd/innd.pid +## The newsfeeds file, on the server host. +#### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= +_PATH_NEWSFEEDS /etc/news/newsfeeds +## The article history database, on the server host. +#### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= +_PATH_HISTORY /var/lib/news/history +## File listing the sites that feed us news. +#### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= +_PATH_INNDHOSTS /etc/news/hosts.nntp +## The active file, on the server host. +#### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= +_PATH_ACTIVE /var/lib/news/active +## A temporary active file, for writing on the server host. +#### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= +_PATH_NEWACTIVE /var/lib/news/active.tmp +## An old active file on the server host. +#### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= +_PATH_OLDACTIVE /var/lib/news/active.old +## The log of when groups are created. +#### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= +_PATH_ACTIVETIMES /var/lib/news/active.times +## Where batch files are located. +#### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= +_PATH_BATCHDIR /var/spool/news/out.going +## Where archives are kept. +#### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= +_PATH_ARCHIVEDIR /var/spool/news/news.archive +## Where NNRP distributions file is +#### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= +_PATH_NNRPDIST /etc/news/distributions +## Where the NNRP automatic subscriptions file is +#### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= +_PATH_NNRPSUBS /etc/news/subscriptions +## Where the default Distribution assignments file is +#### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= +_PATH_DISTPATS /etc/news/distrib.pats +#### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= +_PATH_NEWSGROUPS /var/lib/news/newsgroups +## File where client configuration parameters can be read. +#### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= +_PATH_CONFIG /etc/news/inn.conf +## The possible active file, on clients (NFS-mounted, e.g.). +#### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= +_PATH_CLIENTACTIVE /var/lib/news/active +## A temporary file, for client inews to use. +#### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= +_PATH_TEMPACTIVE /var/spool/news/in.coming/tmp/activeXXXXXX +## Where to mail to the moderators. +#### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= +_PATH_MODERATORS /etc/news/moderators +## A temporary file, for client inews to use. +#### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= +_PATH_TEMPMODERATORS /var/spool/news/in.coming/tmp/moderatorsXXXXXX +## Where NNTP puts the name of the server. +#### =()<_PATH_SERVER @<_PATH_SERVER>@>()= +_PATH_SERVER /etc/news/server +## File with name/password for all remote connections. +#### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= +_PATH_NNTPPASS /etc/news/passwd.nntp +## NNRP access file. +#### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= +_PATH_NNRPACCESS /etc/news/nnrp.access +## Default expire control file. +#### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= +_PATH_EXPIRECTL /etc/news/expire.ctl +## Prolog to parse control scripts +#### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= +_PATH_PARSECTL /usr/lib/news/bin/parsecontrol +## Access control file for control scripts. +#### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= +_PATH_CONTROLCTL /etc/news/control.ctl +## Innwatch control file. +#### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= +_PATH_CTLWATCH /etc/news/innwatch.ctl +## Where innwatch writes its own pid. +#### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= +_PATH_WATCHPID /var/run/innd/innwatch.pid +## Where innwatch writes status when it gets an interrupt +#### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= +_PATH_INNWSTATUS /var/run/innd/innwatch.status +## Format of news overview database +#### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= +_PATH_SCHEMA /etc/news/overview.fmt + + +## +## 12. INNWATCH CONFIGURATION +## Load average (* 100) at which innd should be paused. +#### =()@>()= +INNWATCH_PAUSELOAD 1500 +## Load average (* 100) at which innd should be throttled. +#### =()@>()= +INNWATCH_HILOAD 2000 +## Load average (* 100) at which to restart innd (pause/throttle undone). +#### =()@>()= +INNWATCH_LOLOAD 1000 +## Space, in df output units, at which to throttle innd on _PATH_SPOOL +## or _PATH_OVERVIEWDIR. +#### =()@>()= +INNWATCH_SPOOLSPACE 8000 +## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. +#### =()@>()= +INNWATCH_BATCHSPACE 800 +## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. +#### =()@>()= +INNWATCH_LIBSPACE 25000 +## Number of inodes at which to throttle innd on _PATH_SPOOL. +#### =()@>()= +INNWATCH_SPOOLNODES 200 +## How long to sleep between innwatch iterations. +#### =()@>()= +INNWATCH_SLEEPTIME 600 +## How inn (not just innwatch anymore) gets disk space usage +## (SVR4 machine would probably use /usr/ucb/df) +#### =()@>()= +INNWATCH_DF /bin/df +## Field number of INNWATCH_DF (with -i) output that gives free +## inodes (starting at 1). +#### =()@>()= +INNWATCH_INODES 4 +## Field number of INNWATCH_DF output that gives the free block count. +##### =()@>()= +INNWATCH_BLOCKS 4 + + + +## +## 13. TCL Configuration +## Do you want TCL support? Pick DO or DONT +#### =()@>()= +TCL_SUPPORT DONT +## Where your tcl header file live. Blank if no TCL +### =()@>()= +TCL_INC +# TCL_INC -I/usr/local/include + +## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL +#### =()@>()= +TCL_LIB +# TCL_LIB -ltcl -lm +## TCL Startup File. Should probably be prefixed with the same value as +## _PATH_CONTROLPROGS. +#### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= +_PATH_TCL_STARTUP /etc/news/scripts/startup.tcl +## TCL Filter File. Should probably be prefixed with the same value as +## _PATH_CONTROLPROGS. +#### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= +_PATH_TCL_FILTER /etc/news/scripts/filter.tcl + + +## +## 14. PGP Configuration +## + +## Do you want PGP verification of control messages? Pick DO or DONT +## If you change this then you need to fiddle with control.ctl. +## Setting it DONT is a really bad idea with all the miscreants out there... +#### =()@>()= +WANT_PGPVERIFY DO +## PGP binary. +#### =()<_PATH_PGP @<_PATH_PGP>@>()= +_PATH_PGP /usr/bin/pgp + +## +## 15. Local Configuration +## + +## Home of the NEWSUSER +#### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= +_PATH_NEWSHOME /usr/lib/news + + +## +## 16. Actsync Configuration. +## + +## Host to synchoronize active file with (see actsync and actsyncd manpages). +#### =()@>()= +ACTSYNC_HOST news.foo.bar.com +## Flags actsyncd is to pass to actsync. +#### =()@>()= +ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 +## Actsyncd config file. +#### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= +_PATH_ACTSYNC_CFG /etc/news/actsync.cfg +## Actsyncd ignore file. +#### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= +_PATH_ACTSYNC_IGN /etc/news/actsync.ign + + + +## 17. Perl Configuration +## Do you want Perl support? Pick DO or DONT +#### =()@>()= +PERL_SUPPORT DO +## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL +#### =()@>()= +PERL_LIB PERL_LDOPTS +## Core directory (includes, libs). See perlembed(1) +#### =()@>()= +PERL_INC PERL_CCOPTS +## Perl Filter Files. Should probably be prefixed with the same value as +## _PATH_CONTROLPROGS. +#### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= +_PATH_PERL_STARTUP_INND /etc/news/scripts/startup_innd.pl +#### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= +_PATH_PERL_FILTER_INND /etc/news/scripts/filter_innd.pl +#### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= +_PATH_PERL_FILTER_NNRPD /etc/news/scripts/filter_nnrpd.pl + + +## 18. actived configuration +## Where do you want actived installed? +#### =()<_PATH_ACTIVED @<_PATH_ACTIVED>@>()= +_PATH_ACTIVED /usr/lib/news/bin/actived +## Where should actived put its pid file? +#### =()<_PATH_ACTIVEDPID @<_PATH_ACTIVEDPID>@>()= +_PATH_ACTIVEDPID /var/run/innd/actived.pid + --- inn-1.7.2q.orig/extra/send-uucp.pl +++ inn-1.7.2q/extra/send-uucp.pl @@ -0,0 +1,354 @@ +#!/usr/bin/perl -w +require '/usr/lib/news/innshellvars.pl'; + +############################################################################## +# send-uucp.pl create news batches from the outgoing files +# +# Author: Edvard Tuinder +# +# Copyright (C) 1994 Edvard Tuinder - ELM Consultancy B.V. +# Copyright (C) 1995-1997 Miquel van Smoorenburg - Cistron Internet Services +# +# Copyright (C) 2003 Marco d'Itri +# Nearly rewritten. Added syslog support, real errors checking and more. +# +# 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. +############################################################################## + +use strict; +use Sys::Syslog; + +# for compatibility with INN 1.x +$inn::pathetc ||= '/etc/news'; +$inn::syslog_facility ||= 'news'; + +# some default values +my $MAXSIZE = 500000; +my $MAXJOBS = 200; + +my %UNBATCHER = ( + compress => 'cunbatch', + bzip2 => 'bunbatch', + gzip => 'gunbatch', +); + +my $UUX_FLAGS = '- -z -r -gd'; +my $BATCHER_FLAGS = ''; + +############################################################################## +my $config_file = $inn::pathetc . '/send-uucp.cf'; +my $lockfile = $inn::locks . '/LOCK.send-uucp'; + +openlog('send-uucp', 'pid', $inn::syslog_facility); + +my @sitelist; +if (@ARGV) { + foreach my $site (@ARGV) { + my @cfg = read_cf($config_file, $site); + if (not @cfg) { + logmsg("site $site not found in the configuration", 'err'); + next; + } + push @sitelist, @cfg; + } +} else { + @sitelist = read_cf($config_file, undef); +} + +if (not @sitelist) { + logmsg('nothing to do', 'debug'); + exit 0; +} + +chdir $inn::batch or logdie("Can't access $inn::batch: $!", 'crit'); + +shlock($lockfile); + +run_site($_) foreach @sitelist; +unlink $lockfile; +exit 0; + +# lint food +$inn::compress.$inn::locks.$inn::syslog_facility.$inn::have_uustat = 0 if 0; + +############################################################################## +sub read_cf { + my ($conf_file, $site_wanted) = @_; + + my $hour = (localtime time)[2]; + + my @sites; + open(CF, $conf_file) or logdie("cannot open $conf_file: $!", 'crit'); + while () { + chop; + s/\s*\#.*$//; + next if /^$/; + + my ($sitespec, $compress, $size, $time) = split(/\s+/); + next if not $sitespec; + + my ($site, $host) = split(/:/, $sitespec); + $host = $site if not $host; + + $compress =~ s/_/ /g if $compress; + + if ($site_wanted) { + if ($site eq $site_wanted) { + push @sites, [$site, $host, $compress, $size]; + last; + } + next; + } + + if ($time) { + foreach my $time (split(/,/, $time)) { + next if $time != $hour; + push @sites, [$site, $host, $compress, $size]; + } + } else { + push @sites, [$site, $host, $compress, $size]; + } + } + close CF; + return @sites; +} + +############################################################################## +# count number of jobs in the UUCP queue for a given site +sub count_jobs { + my ($site) = @_; + + return 0 if not $inn::have_uustat; + open(JOBS, "uustat -s $site 2> /dev/null |") or logdie("cannot fork: $!"); + my $count = grep(/ Executing rnews /, ); + close JOBS; # ignore errors, uustat may fail + return $count; +} + +# select the rnews label appropriate for the compressor program used +sub unbatcher { + my ($compressor) = @_; + + $compressor =~ s%.*/%%; + return $UNBATCHER{$compressor} || 'cunbatch'; +} + +############################################################################## +# batch articles for one site +sub run_site { + my ($cfg) = @_; + my ($site, $host, $compress, $size) = @$cfg; + + logmsg("checking site $site", 'debug'); + my $maxjobs = ''; + if ($MAXJOBS) { + my $jobs = count_jobs($site); + if ($jobs >= $MAXJOBS) { + logmsg("too many jobs queued for $site"); + return; + } + $maxjobs = '-N ' . ($MAXJOBS - $jobs); + } + + $compress ||= $inn::compress; + $size ||= $MAXSIZE; + + # if exists a .work temp file left by a previous invocation, append + # it to the current batch file + if (-f "$site.work") { + my $err = ''; + open(OUT, ">>$site") or logdie("cannot open $site: $!"); + open(IN, "$site.work") or logdie("cannot open $site.work: $!"); + print OUT while ; + close IN; + close OUT or logdie("cannot close $site: $!");; + } + + if (not -f $site) { + logmsg("no batch file for site $site", 'err'); + return; + } + + rename($site, "$site.work") or logdie("cannot rename $site: $!", 'crit'); + ctlinnd('-t120', 'flush', $site); + if (not -s "$site.work") { + logmsg("no articles for $site", 'debug'); + unlink "$site.work" or logmsg("cannot delete $site.work: $!", 'err'); + } else { + if ($compress eq 'none') { + system "batcher -b $size $maxjobs $BATCHER_FLAGS " + . "-p\"uux $UUX_FLAGS %s!rnews\" $host $site.work"; + } else { + system "batcher -b $size $maxjobs $BATCHER_FLAGS " + . "-p\"{ echo '#! " . unbatcher($compress) + . "' ; exec $compress; } | " + . "uux $UUX_FLAGS %s!rnews\" $host $site.work"; + } + logmsg("batched articles for $site", 'debug'); + } +} + +############################################################################## +sub logmsg { + my ($msg, $lvl) = @_; + + syslog($lvl || 'notice', '%s', $msg); +} + +sub logdie { + my ($msg, $lvl) = @_; + + logmsg($msg, $lvl || 'err'); + unlink $lockfile; + exit 1; +} + +sub ctlinnd { + my ($cmd, @args) = @_; + + my $st = system("$inn::newsbin/ctlinnd", '-s', $cmd, @args); + logdie('Cannot run ctlinnd: ' . $!) if $st == -1; + logdie('ctlinnd returned status ' . ($st & 255)) if $st > 0; +} + +sub shlock { + my $lockfile = shift; + + my $locktry = 0; + while ($locktry < 60) { + if (system("$inn::newsbin/shlock", '-p', $$, '-f', $lockfile) == 0) { + return 1; + } + $locktry++; + sleep 2; + } + + my $lockreason; + if (open(LOCKFILE, $lockfile)) { + $lockreason = 'held by ' . ( || '?'); + close LOCKFILE; + } else { + $lockreason = $!; + } + logdie("Cannot get lock $lockfile: $lockreason"); + return undef; +} + +__END__ + +=head1 NAME + +send-uucp - Send Usenet articles via UUCP + +=head1 SYNOPSIS + +B [I ...] + +=head1 DESCRIPTION + +The B program processes batch files written by innd(8) to send +Usenet articles to UUCP sites. It reads a configuration file to control how +it behaves with various sites. Normally, it's run periodically out of cron +to put together batches and send them to remote UUCP sites. + +=head1 OPTIONS + +Any arguments provided to the program are interpreted as a list of sites +specfied in F for which batches should be generated. If no +arguments are supplied then batches will be generated for all sites listed +in that configuration file. + +=head1 CONFIGURATION + +The sites to which articles are to be sent must be configured in the +configuration file F. Each site is specified with a line of +the form: + + site[:host] [compressor [maxsize [batchtime]]] + +=over 4 + +=item I + +The news site name being configured. This must match a site name +from newsfeeds(5). + +=item I + +The UUCP host name to which batches should be sent for this site. +If omitted, the news site name will be used as the UUCP host name. + +=item I + +The compression method to use for batches. This should be one of compress, +gzip or none. Arguments for the compression command may be specified by +using C<_> instead of spaces. For example, C. The default value is +C. + +=item I + +The maximum size of a single batch before compression. The default value is +500,000 bytes. + +=item I + +A comma separated list of hours during which batches should be generated for +a given site. When B runs, a site will only be processed if the +current hour matches one of the hours in I. The default is no +limitation on when to generate batches. + +=back + +Fields are seperated by spaces and only the site name needs to be specified, +with defaults being used for unspecified values. If the first character on +a line is a C<#> then the rest of the line is ignored. + +=head1 EXAMPLE + +Here is an example send-uucp.cf configuration file: + + zoetermeer gzip 1048576 5,18,22 + hoofddorp gzip 1048576 5,18,22 + pa3ebv gzip 1048576 5,18,22 + drinkel gzip 1048576 5,6,18,20,22,0,2 + manhole compress 1048576 5,18,22 + owl compress 1048576 + able + +This defines seven UUCP sites. The first four use gzip compression and the +last three use compress. The first six use a batch size of 1MB, and the +last site (able) uses the default of 500,000 bytes. The zoetermeer, +hoofddorp, pa3ebv, and manhole sites will only have batches generated for +them during the hours of 05:00, 18:00, and 22:00, and the drinkel site will +only have batches generated during those hours and 20:00, 00:00, and 02:00. +There are no restrictions on when batches will be generated for owl or able. + +=head1 FILES + +=over 4 + +=item I/send-uucp.cf + +Configuration file specifying a list of sites to be processed. + +=back + +=head1 NOTES + +The usual flags used for a UUCP feed in the I file are C. + +=head1 SEE ALSO + +innd(8), newsfeeds(5), uucp(8) + +=head1 AUTHOR + +This program was originally written by Edvard Tuinder and then +maintained and extended by Miquel van Smoorenburg . +Marco d'Itri cleaned up the code for inclusion in INN. This +manual page was written by Mark Brown . + +=cut --- inn-1.7.2q.orig/extra/pgpverify.8 +++ inn-1.7.2q/extra/pgpverify.8 @@ -0,0 +1,118 @@ +.\" +.\" $Id: pgpverify.8,v 1.1 1999/06/21 16:44:22 bdale Exp $ +.\" +.\" This manual page was provided by James Ralston +.TH pgpverify 8 +.SH NAME +pgpverify - cryptographically verify Usenet control messages +.SH SYNOPSIS +.B pgpverify +.SH DESCRIPTION +The +.I pgpverify +program reads (on standard input) a Usenet control message that has +been cryptographically signed using the +.I signcontrol +program. +.I pgpverify +then uses the +.I pgp +program to determine who signed the control message. If the control +message was validly signed, +.I pgpverify +outputs (to stdout) the User ID of the key ID that signed the message. +.SH OPTIONS +The +.I pgpverify +program takes no options. +.SH EXIT STATUS +.I pgpverify +returns the follow exit statuses for the following cases: +.P +.TP +.B 0 +The control message had a good PGP signature. +.TP +.B 1 +The control message had no PGP signature. +.TP +.B 2 +The control message had an unknown PGP signature. +.TP +.B 3 +The control message had a bad PGP signature. +.TP +.B 255 +A problem occurred not directly related to PGP analysis of signature. +.SH AUTHOR +David C Lawrence +.SH ENVIRONMENT +.I pgpverify +does not modify or otherwise alter the environment before invoking the +.I pgp +program. It is the responsibility of the person who installs +.I pgpverify +to ensure that when +.I pgp +runs, it has the ability to locate and read a PGP key file that +contains the PGP public keys for the appropriate Usenet hierarchy +administrators. +.SH SEE ALSO +pgp(1) +.SH NOTES +Historically, Usenet news server administrators have configured their +news servers to automatically honor Usenet control messages based on +the originator of the control messages and the hierarchies for which +the control messages applied. For example, in the past, David C +Lawrence always issued control messages for the +"Big 8" hierarchies (comp, humanities, misc, news, rec, sci, soc, +talk). Usenet news administrators would configure their news server +software to automatically honor newgroup and rmgroup control messages +that originated from David Lawrence and applied to any of the Big 8 +hierarchies. +.P +Unfortunately, Usenet news articles (including control messages) are +notoriously easy to forge. Soon, malicious users realized they could +create or remove (at least temporarily) any Big 8 newsgroup they +wanted by simply forging an appropriate control message in David +Lawrence's name. As Usenet became more widely used, forgeries became +more common. +.P +The +.I pgpverify +program was designed to allow Usenet news administrators to configure +their servers to cryptographically verify control messages before +automatically acting on them. Under the pgpverify system, a Usenet +hierarchy maintainer creates a PGP public/private key pair and +disseminates the public key. Whenever the hierarchy maintainer issues +a control message, he uses the +.I signcontrol +program to sign the control message with the PGP private key. Usenet +news administrators configure their news servers to run the +.I pgpverify +program on the appropriate control messages, and take action based on +the PGP key User ID that signed the control message, not the name and +address that appear in the control message's From or Sender headers. +.P +Thus, using the +.I signcontrol +and +.I pgpverify programs +appropriately essentially eliminates the possibility of malicious +users forging Usenet control messages that sites will act upon, as +such users would have to obtain the PGP private key in order to forge +a control message that would pass the cryptographic verification step. +If the hierarchy administrators properly protect their PGP private +keys, the only way a malicious user could forge a validly-signed +control message would be by breaking the RSA encryption algorithm, +which (at least at this time) is believed to be an NP-complete +problem. If this is indeed the case, discovering the PGP private key +based on the PGP public key is computationally impossible for PGP keys +of a sufficient bit length. +.P + is where the most recent +versions of +.I signcontrol +and +.I pgpverify +live, along with PGP public keys used for hierarchy administration. --- inn-1.7.2q.orig/extra/cch/controlchan +++ inn-1.7.2q/extra/cch/controlchan @@ -0,0 +1,463 @@ +#! /usr/bin/perl -w +require '/usr/lib/news/innshellvars.pl'; + +# convert INN 1.x variables to 2.x style +$inn::syslog_facility = 'news'; +$inn::pgpverify = 'true'; +$inn::mta = $inn::sendmail; +$inn::pathbin = $inn::newsbin; +$inn::tmpdir = $inn::spooltemp; +$inn::pathhost = `$inn::innconfval pathhost`; +$inn::version = '1.7.2+insync-1.1d+debian'; + +## $Id: controlchan.in,v 1.7 2002/11/21 00:03:15 vinocur Exp $ +## +## Channel feed program to route control messages to an appropriate handler. +## +## Copyright 2001 by Marco d'Itri +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions +## are met: +## +## 1. Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## +## 2. Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in the +## documentation and/or other materials provided with the distribution. +## +## Give this program its own newsfeed. Make sure that you've created +## the newsgroup control.cancel so that you don't have to scan through +## cancels, which this program won't process anyway. +## +## Make a newsfeeds entry like this: +## +## controlchan!\ +## :!*,control,control.*,!control.cancel\ +## :Tc,Wnsm\ +## :@prefix@/bin/controlchan + +require 5.004_03; +use strict; + +delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; + +# globals +my ($cachedctl, $curmsgid); +my $lastctl = 0; +my $use_syslog = 0; +my $debug = 0; + +# setup logging ########################################################### +# do not log to syslog if stderr is connected to a console +if (not -t 2) { + eval { require INN::Syslog; import INN::Syslog; $use_syslog = 1; }; + eval { require Sys::Syslog; import Sys::Syslog; $use_syslog = 1; } + unless $use_syslog; +} + +if ($use_syslog) { + eval "sub Sys::Syslog::_PATH_LOG { '/dev/log' }" if $^O eq 'dec_osf'; + Sys::Syslog::setlogsock('unix') if $^O =~ /linux|dec_osf/; + openlog('controlchan', 'pid', $inn::syslog_facility); +} +logmsg('starting'); + +# load modules from the control directory ################################# +opendir(CTL, $inn::controlprogs) + or logdie("Cannot open $inn::controlprogs", 'crit'); +foreach (readdir CTL) { + next if not /^([a-z\.]+\.pl)$/ or not -f "$inn::controlprogs/$_"; + eval { require "$inn::controlprogs/$1" }; + if ($@) { + $@ =~ s/\n/ /g; + logdie($@, 'crit'); + } + logmsg("loaded $inn::controlprogs/$1", 'debug'); +} +closedir CTL; + +# main loop ############################################################### +while () { + chop; + my ($token, $sitepath, $msgid) = split(/\s+/, $_); + next if not defined $token; + $sitepath ||= ''; + $curmsgid = $msgid || ''; + + my $artfh = open_article($token); + next if not defined $artfh; + + # suck in headers and body, normalize the strange ones + my (@headers, @body, %hdr); + if (not parse_article($artfh, \@headers, \@body, \%hdr)) { + close $artfh; + next; + } + close $artfh or logdie('sm died with status ' . ($? >> 8)); + + next if not exists $hdr{control}; + + $curmsgid = $hdr{'message-id'}; + my $sender = cleanaddr($hdr{sender} || $hdr{from}); + my $replyto = cleanaddr($hdr{'reply-to'} || $hdr{from}); + + my (@progparams, $progname); + if ($hdr{control} =~ /\s/) { + $hdr{control} =~ /^(\S+)\s+(.+)?/; + $progname = lc $1; + @progparams = split(/\s+/, lc $2) if $2; + } else { + $progname = lc $hdr{control}; + } + + next if $progname eq 'cancel'; + + if ($progname !~ /^([a-z]+)$/) { + logmsg("Naughty control in article $curmsgid ($progname)"); + next; + } + $progname = $1; + + # Do we want to process the message? Let's check the permissions. + my ($action, $logname, $newsgrouppats) = + ctlperm($progname, $sender, $progparams[0], + $token, \@headers, \@body); + + next if $action eq 'drop'; + + if ($action eq '_pgpfail') { + my $type = ''; + if ($progname and $progname eq 'newgroup') { + if ($progparams[1] and $progparams[1] eq 'moderated') { + $type = 'm '; + } else { + $type = 'y '; + } + } + logmsg("skipping $progname $type$sender" + . "(pgpverify failed) in $curmsgid"); + next; + } + + # used by checkgroups. Convert from perl regexp to grep regexp. + if (local $_ = $newsgrouppats) { + s/\$\|/|/g; + s/[^\\]\.[^*]/?/g; + s/\$//; + s/\.\*/*/g; + s/\\([\$\+\.])/$1/g; + $progparams[0] = $_; + } + + # find the appropriate module and call it + my $subname = "control_$progname"; + my $subfind = \&$subname; + if (not defined &$subfind) { + if ($logname) { + logger($logname, "Unknown control message by $sender", + \@headers, \@body); + } else { + logmsg("Unknown \"$progname\" control by $sender"); + } + next; + } + + my $approved = $hdr{approved} ? 1 : 0; + logmsg("$subname, " . join(' ', @progparams) + . " $sender $replyto $token, $sitepath, $action" + . ($logname ? "=$logname" : '') .", $approved"); + + &$subfind(\@progparams, $sender, $replyto, $sitepath, + $action, $logname, $approved, \@headers, \@body); +} + +closelog() if $use_syslog; +exit 0; + +print $inn::most_logs.$inn::syslog_facility.$inn::mta. + $inn::pathhost.$inn::tmpdir.$inn::sendmail.$inn::version. + $inn::pathbin.$inn::innconfval.$inn::spooltemp.$ + $inn::newsmaster.$inn::locks; # lint food + +# misc functions ########################################################## +sub parse_article { + my ($artfh, $headers, $body, $hdr) = @_; + my $h; + my %uniquehdr = map { $_ => 1 } qw(date followup-to from message-id + newsgroups path reply-to subject sender); + + while (<$artfh>) { + chop; + last if /^$/; + push @$headers, $_; + if (/^(\S+):\s+(.+)/) { + $h = lc $1; + if (exists $hdr->{$h}) { + if (exists $uniquehdr{$h}) { + logmsg("Multiple $1 headers in article $curmsgid"); + return 0; + } + $hdr->{$h} .= ' ' . $2; + } else { + $hdr->{$h} = $2; + } + next; + } elsif (/^\s+(.+)/) { + if (defined $h) { + $hdr->{$h} .= ' ' . $1; + next; + } + } + logmsg("Broken headers in article $curmsgid"); + return 0; + } + + # article is empty or does not exist + return 0 if not @$headers; + + chop (@$body = <$artfh>); + return 1; +} + +# Strip a mail address, innd-style. +sub cleanaddr { + local $_ = shift; + s/(\s+)?\(.*\)(\s+)?//g; + s/.*<(.*)>.*/$1/; + s/[^-a-zA-Z0-9+_.@%]/_/g; # protect MTA + s/^-/_/; # protect MTA + return $_; +} + +# Read and cache control.ctl. +sub readctlfile { + my $mtime = (stat($inn::ctlfile))[9]; + return $cachedctl if $lastctl == $mtime; # mtime has not changed. + $lastctl = $mtime; + + my @ctllist; + open(CTLFILE, $inn::ctlfile) + or logdie("Cannot open $inn::ctlfile", 'crit'); + while () { + chop; + # Not a comment or blank? Convert wildmat to regex + next if not /^(\s+)?[^\#]/ or /^$/; + if (not /:(?:doit|doifarg|drop|log|mail|verify-.*)(?:=.*)?$/) { + s/.*://; + logmsg("$_ is not a valid action for control.ctl", 'err'); + next; + } + # Convert to a : separated list of regexps + s/^all:/*:/i; + s/([\$\+\.])/\\$1/g; + s/\*/.*/g; + s/\?/./g; + s/(.*)/^$1\$/; + s/:/\$:^/g; + s/\|/\$|^/g; + push @ctllist, $_; + } + close CTLFILE; + + logmsg('warning: control.ctl is empty!', 'err') if not @ctllist; + return $cachedctl = [ reverse @ctllist ]; +} + +# Parse a control message's permissions. +sub ctlperm { + my ($type, $sender, $newsgroup, $token, $headers, $body) = @_; + + my $action = 'drop'; # default + my ($logname, $hier); + + # newgroup and rmgroup require newsgroup names; check explicitly for that + # here and return drop if the newsgroup is missing (to avoid a bunch of + # warnings from undefined values later on in permission checking). + if ($type eq 'newgroup' or $type eq 'rmgroup') { + unless ($newsgroup) { + return ('drop', undef, undef); + } + } + + my $ctllist = readctlfile(); + foreach (@$ctllist) { + my @ctlline = split /:/; + # 0: type 1: from@addr 2: group.* 3: action + if ($type =~ /$ctlline[0]/ and $sender =~ /$ctlline[1]/i and + ($type !~ /(?:new|rm)group/ or $newsgroup =~ /$ctlline[2]/)) { + $action = $ctlline[3]; + $action =~ s/\^(.+)\$/$1/; + $action =~ s/\\//g; + $hier = $ctlline[2] if $type eq 'checkgroups'; + last; + } + } + + ($action, $logname) = split(/=/, $action); + + if ($action =~ /^verify-(.+)/) { + my $keyowner = $1; + if ($inn::pgpverify and $inn::pgpverify =~ /^(?:true|on|yes)$/i) { + my $pgpresult = defined &local_pgpverify ? + local_pgpverify($token, $headers, $body) : pgpverify($token); + if ($keyowner eq $pgpresult) { + $action = 'doit'; + } else { + $action = '_pgpfail'; + } + } else { + $action = 'mail'; + } + } + + return ($action, $logname, $hier); +} + +# Write stuff to a log or send mail to the news admin. +sub logger { + my ($logfile, $message, $headers, $body) = @_; + + if ($logfile eq 'mail') { + my $mail = sendmail($message); + print $mail map { s/^~/~~/; "$_\n" } @$headers; + print $mail "$_\n" . join ('', map { s/^~/~~/; "$_\n" } @$body) + if $body; + close $mail or logdie("Cannot send mail: $!"); + return; + } + + if ($logfile =~ /^([^.\/].*)/) { + $logfile = $1; + } else { + logmsg("Invalid log file: $logfile", 'err'); + $logfile = 'control'; + } + + $logfile = "$inn::most_logs/$logfile.log" unless $logfile =~ /^\//; + my $lockfile = $logfile; + $lockfile =~ s#.*/##; + $lockfile = "$inn::locks/LOCK.$lockfile"; + shlock($lockfile); + + open(LOGFILE, ">>$logfile") or logdie("Cannot open $logfile: $!"); + print LOGFILE "$message\n"; + foreach (@$headers, '', @$body, '') { + print LOGFILE " $_\n"; + } + close LOGFILE; + unlink $lockfile; +} + +# write to syslog or errlog +sub logmsg { + my ($msg, $lvl) = @_; + + return if $lvl and $lvl eq 'debug' and not $debug; + if ($use_syslog) { + syslog($lvl || 'notice', '%s', $msg); + } else { + print STDERR (scalar localtime) . ": $msg\n"; + } +} + +# log a message and then die +sub logdie { + my ($msg, $lvl) = @_; + + $msg .= " ($curmsgid)" if $curmsgid; + logmsg($msg, $lvl || 'err'); + exit 1; +} + +# wrappers executing external programs #################################### + +# Open an article appropriately to our storage method (or lack thereof). +sub open_article { + my $token = shift; + + return *ART if open(ART, $token); + logmsg("Cannot open article $token: $!"); + return undef; +} + +sub pgpverify { + my $token = shift; + + open(PGPCHECK, "$inn::newsbin/pgpverify < $token |") or goto ERROR; + my $pgpresult = ; + close PGPCHECK or goto ERROR; + $pgpresult ||= ''; + chop $pgpresult; + return $pgpresult; +ERROR: + logmsg("pgpverify failed: $!", 'debug'); + return ''; +} + +sub ctlinnd { + my ($cmd, @args) = @_; + + my $st = system("$inn::newsbin/ctlinnd", '-s', $cmd, @args); + logdie('Cannot run ctlinnd: ' . $!) if $st == -1; + logdie('ctlinnd returned status ' . ($st & 255)) if $st > 0; +} + +sub shlock { + my $lockfile = shift; + + my $locktry = 0; + while ($locktry < 60) { + if (system("$inn::newsbin/shlock", '-p', $$, '-f', $lockfile) == 0) { + return 1; + } + $locktry++; + sleep 2; + } + + my $lockreason; + if (open(LOCKFILE, $lockfile)) { + $lockreason = 'held by ' . ( || '?'); + close LOCKFILE; + } else { + $lockreason = $!; + } + logdie("Cannot get lock $lockfile: $lockreason"); + return undef; +} + +# If $body is not defined, returns a file handle which must be closed. +# Don't forget checking the return value of close(). +# $addresses may be a scalar or a reference to a list of addresses. +# If not defined, $inn::newsmaster is the default. +# parts of this code stolen from innmail.pl +sub sendmail { + my ($subject, $addresses, $body) = @_; + $addresses = [ $addresses || $inn::newsmaster ] if not ref $addresses; + $subject ||= '(no subject)'; + + # fix up all addresses + my @addrs = map { s#[^-a-zA-Z0-9+_.@%]##g; $_ } @$addresses; + + my $sm = $inn::mta; + if ($sm =~ /%s/) { + $sm = sprintf($sm, join(' ', @addrs)); + } else { + $sm .= ' ' . join(' ', @addrs); + } + + # fork and spawn the MTA whitout using the shell + my $pid = open(MTA, '|-'); + logdie('Cannot fork: ' . $!) if $pid < 0; + if ($pid == 0) { + exec(split(/\s+/, $sm)) or logdie("Cannot exec $sm: $!"); + } + + print MTA 'To: ' . join(",\n\t", @addrs) . "\nSubject: $subject\n\n"; + return *MTA if not defined $body; + $body = join("\n", @$body) if ref $body eq 'ARRAY'; + print MTA $body . "\n"; + close MTA or logdie("Execution of $sm failed: $!"); + return 1; +} --- inn-1.7.2q.orig/extra/cch/control/checkgroups.pl +++ inn-1.7.2q/extra/cch/control/checkgroups.pl @@ -0,0 +1,82 @@ +## $Id: checkgroups.pl,v 1.2 2001/07/19 00:32:56 rra Exp $ +## +## checkgroups control message handler. +## +## Copyright 2001 by Marco d'Itri +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions +## are met: +## +## 1. Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## +## 2. Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in the +## documentation and/or other materials provided with the distribution. + +use strict; + +sub control_checkgroups { + my ($par, $sender, $replyto, $site, $action, $log, $approved, + $headers, $body) = @_; + my ($newsgrouppats) = @$par; + + if ($action eq 'mail') { + my $mail = sendmail("checkgroups by $sender"); + print $mail "$sender posted the following checkgroups message:\n"; + print $mail map { s/^~/~~/; "$_\n" } @$headers; + print $mail <$tempfile.art") + or logdie("Cannot open $tempfile.art: $!"); + print TEMPART map { s/^~/~~/; "$_\n" } @$body; + close TEMPART; + + open(OLDIN, '<&STDIN') or die $!; + open(OLDOUT, '>&STDOUT') or die $!; + open(STDIN, "$tempfile.art") or die $!; + open(STDOUT, ">$tempfile") or die $!; + my $st = system("$inn::controlprogs/docheckgroups", $newsgrouppats); + logdie('Cannot run docheckgroups: ' . $!) if $st == -1; + logdie('docheckgroups returned status ' . ($st & 255)) if $st > 0; + open(STDIN, '<&OLDIN') or die $!; + open(STDOUT, '>&OLDOUT') or die $!; + + open(TEMPFILE, $tempfile) or logdie("Cannot open $tempfile: $!"); + my @output = ; + chop @output; + logger($log || 'mail', "checkgroups by $sender", \@output); + close TEMPFILE; + unlink($tempfile, "$tempfile.art"); +} + +1; --- inn-1.7.2q.orig/extra/cch/control/sendsys.pl +++ inn-1.7.2q/extra/cch/control/sendsys.pl @@ -0,0 +1,64 @@ +## $Id: sendsys.pl,v 1.2 2001/07/19 00:32:56 rra Exp $ +## +## sendsys control message handler. +## +## Copyright 2001 by Marco d'Itri +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions +## are met: +## +## 1. Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## +## 2. Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in the +## documentation and/or other materials provided with the distribution. + +use strict; + +sub control_sendsys { + my ($par, $sender, $replyto, $site, $action, $log, $approved, + $headers, $body) = @_; + my ($where) = @$par; + + if ($action eq 'mail') { + my $mail = sendmail("sendsys $sender"); + print $mail <; + print $mail "\n"; + close NEWSFEEDS; + close $mail or logdie("Cannot send mail: $!"); + + logger($log, "sendsys $sender to $replyto", $headers, $body) if $log; + } +} + +1; --- inn-1.7.2q.orig/extra/cch/control/ihave.pl +++ inn-1.7.2q/extra/cch/control/ihave.pl @@ -0,0 +1,58 @@ +## $Id: ihave.pl,v 1.3 2001/07/19 00:32:56 rra Exp $ +## +## ihave control message handler. +## +## Copyright 2001 by Marco d'Itri +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions +## are met: +## +## 1. Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## +## 2. Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in the +## documentation and/or other materials provided with the distribution. + +use strict; + +sub control_ihave { + my ($par, $sender, $replyto, $site, $action, $log, $approved, + $headers, $body) = @_; + + if ($action eq 'mail') { + my $mail = sendmail("ihave by $sender"); + print $mail map { s/^~/~~/; "$_\n" } @$body; + close $mail or logdie('Cannot send mail: ' . $!); + } elsif ($action eq 'log') { + if ($log) { + logger($log, "ihave $sender", $headers, $body); + } else { + logmsg("ihave $sender"); + } + } elsif ($action eq 'doit') { + my $tempfile = "$inn::tmpdir/ihave.$$"; + open(GREPHIST, "|grephistory -i > $tempfile") + or logdie('Cannot run grephistory: ' . $!); + foreach (@$body) { + print GREPHIST "$_\n"; + } + close GREPHIST; + + if (-s $tempfile) { + my $inews = open("$inn::inews -h") + or logdie('Cannot run inews: ' . $!); + print $inews "Newsgroups: to.$site\n" + . "Subject: cmsg sendme $inn::pathhost\n" + . "Control: sendme $inn::pathhost\n\n"; + open(TEMPFILE, $tempfile) or logdie("Cannot open $tempfile: $!"); + print $inews $_ while ; + close $inews or die $!; + close TEMPFILE; + } + unlink $tempfile; + } +} + +1; --- inn-1.7.2q.orig/extra/cch/control/rmgroup.pl +++ inn-1.7.2q/extra/cch/control/rmgroup.pl @@ -0,0 +1,89 @@ +## $Id: rmgroup.pl,v 1.3 2001/07/19 00:32:56 rra Exp $ +## +## rmgroup control message handler. +## +## Copyright 2001 by Marco d'Itri +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions +## are met: +## +## 1. Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## +## 2. Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in the +## documentation and/or other materials provided with the distribution. + +use strict; + +sub control_rmgroup { + my ($par, $sender, $replyto, $site, $action, $log, $approved, + $headers, $body) = @_; + my ($groupname) = @$par; + + # Scan active to see what sort of change we are making. + open(ACTIVE, $inn::active) or logdie("Cannot open $inn::active: $!"); + my @oldgroup; + while () { + next unless /^(\Q$groupname\E)\s\d+\s\d+\s(\w)/; + @oldgroup = split /\s+/; + last; + } + close ACTIVE; + my $status; + if (not @oldgroup) { + $status = 'no change'; + } elsif (not $approved) { + $status = 'unapproved'; + } else { + $status = 'removed'; + } + + if ($action eq 'mail' and $status !~ /(no change|unapproved)/) { + my $mail = sendmail("rmgroup $groupname $sender"); + print $mail <$tempfile") or logdie("Cannot open $tempfile: $!"); + while () { + print TEMPFILE $_ if not /^\Q$groupname\E\s/; + } + close TEMPFILE; + close NEWSGROUPS; + rename($tempfile, $inn::newsgroups) + or logdie("Cannot rename $tempfile: $!"); + unlink "$inn::locks/LOCK.newsgroups"; + unlink $tempfile; + + logger($log, "rmgroup $groupname $status $sender", $headers, $body) + if $log; + } +} + +1; --- inn-1.7.2q.orig/extra/cch/control/senduuname.pl +++ inn-1.7.2q/extra/cch/control/senduuname.pl @@ -0,0 +1,61 @@ +## $Id: senduuname.pl,v 1.2 2001/07/19 00:32:56 rra Exp $ +## +## senduuname control message handler. +## +## Copyright 2001 by Marco d'Itri +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions +## are met: +## +## 1. Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## +## 2. Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in the +## documentation and/or other materials provided with the distribution. + +use strict; + +sub control_senduuname { + my ($par, $sender, $replyto, $site, $action, $log, $approved, + $headers, $body) = @_; + my ($where) = @$par; + + if ($action eq 'mail') { + my $mail = sendmail("senduuname $sender"); + print $mail <; + close UUNAME or logdie("Cannot run uuname: $!"); + close $mail or logdie("Cannot send mail: $!"); + + logger($log, "senduuname $sender to $replyto", $headers, $body) if $log; + } +} + +1; --- inn-1.7.2q.orig/extra/cch/control/sendme.pl +++ inn-1.7.2q/extra/cch/control/sendme.pl @@ -0,0 +1,55 @@ +## $Id: sendme.pl,v 1.3 2001/07/19 00:32:56 rra Exp $ +## +## sendme control message handler. +## +## Copyright 2001 by Marco d'Itri +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions +## are met: +## +## 1. Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## +## 2. Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in the +## documentation and/or other materials provided with the distribution. + +use strict; + +sub control_sendme { + my ($par, $sender, $replyto, $site, $action, $log, $approved, + $headers, $body) = @_; + + if ($action eq 'mail') { + my $mail = sendmail("sendme by $sender"); + print $mail map { s/^~/~~/; "$_\n" } @$body; + close $mail or logdie('Cannot send mail: ' . $!); + } elsif ($action eq 'log') { + if ($log) { + logger($log, "sendme $sender", $headers, $body); + } else { + logmsg("sendme from $sender"); + } + } elsif ($action eq 'doit') { + my $tempfile = "$inn::tmpdir/sendme.$$"; + open(GREPHIST, "|grephistory -s > $tempfile") + or logdie("Cannot run grephistory: $!"); + foreach (@$body) { + print GREPHIST "$_\n"; + } + close GREPHIST or logdie("Cannot run grephistory: $!"); + + if (-s $tempfile and $site =~ /^[a-zA-Z0-9.-_]+$/) { + open(TEMPFILE, $tempfile) or logdie("Cannot open $tempfile: $!"); + open(BATCH, ">>$inn::batch/$site.work") + or logdie("Cannot open $inn::batch/$site.work: $!"); + print BATCH $_ while ; + close BATCH; + close TEMPFILE; + } + unlink $tempfile; + } +} + +1; --- inn-1.7.2q.orig/extra/cch/control/version.pl +++ inn-1.7.2q/extra/cch/control/version.pl @@ -0,0 +1,61 @@ +## $Id: version.pl,v 1.2 2001/07/19 00:32:56 rra Exp $ +## +## version control message handler. +## +## Copyright 2001 by Marco d'Itri +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions +## are met: +## +## 1. Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## +## 2. Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in the +## documentation and/or other materials provided with the distribution. + +use strict; + +sub control_version { + my ($par, $sender, $replyto, $site, $action, $log, $approved, + $headers, $body) = @_; + my ($where) = @$par; + + my $version = $inn::version || '(unknown version)'; + + if ($action eq 'mail') { + my $mail = sendmail("version $sender"); + print $mail < +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions +## are met: +## +## 1. Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## +## 2. Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in the +## documentation and/or other materials provided with the distribution. + +use strict; + +sub control_newgroup { + my ($par, $sender, $replyto, $site, $action, $log, $approved, + $headers, $body) = @_; + my ($groupname, $modflag) = @$par; + + $modflag ||= ''; + my $modcmd = $modflag eq 'moderated' ? 'm' : 'y'; + + my $errmsg; + $errmsg= local_checkgroupname($groupname) if defined &local_checkgroupname; + if ($errmsg) { + $errmsg = checkgroupname($groupname) if $errmsg eq 'DONE'; + } + + if ($errmsg) { + if ($log) { + logger($log, "skipping newgroup ($errmsg)", $headers, $body); + } else { + logmsg("skipping newgroup ($errmsg)"); + } + return; + } + + # Scan active to see what sort of change we are making. + open(ACTIVE, $inn::active) or logdie("Cannot open $inn::active: $!"); + my @oldgroup; + while () { + next unless /^(\Q$groupname\E)\s\d+\s\d+\s(\w)/; + @oldgroup = split /\s+/; + last; + } + close ACTIVE; + my $status; + if (@oldgroup) { + if ($oldgroup[3] eq 'm' and $modflag ne 'moderated') { + $status = 'made unmoderated'; + } elsif ($oldgroup[3] ne 'm' and $modflag eq 'moderated') { + $status = 'made moderated'; + } else { + $status = 'no change'; + } + } elsif (not $approved) { + $status = 'unapproved'; + } else { + $status = 'created'; + } + + if ($action eq 'mail' and $status !~ /no change|unapproved/) { + my $mail = sendmail("newgroup $groupname $modcmd $sender"); + print $mail <$tempfile") or logdie("Cannot open $tempfile: $!"); + my $olddesc = ''; + while () { + if (/^\Q$name\E\s+(.*)/) { + $olddesc = $1; + next; + } + print TEMPFILE $_; + } + print TEMPFILE "$name\t$desc\n"; + close TEMPFILE; + close NEWSGROUPS; + # install the modified file only if the description has changed + if ($desc ne $olddesc) { + rename($tempfile, $inn::newsgroups) + or logdie("Cannot rename $tempfile: $!"); + } else { + unlink($tempfile); + } + unlink("$inn::locks/LOCK.newsgroups", $tempfile); +} + +# Check the group name. This is partially derived from C News. +# Some checks are commented out if I think they're too strict or +# language-dependent. Your mileage may vary. +sub checkgroupname { + local $_ = shift; + + # whole-name checking + return 'Empty group name' if /^$/; + return 'Whitespace in group name' if /\s/; + return 'unsafe group name' if /[\`\/:;]/; + return 'Bad dots in group name' if /^\./ or /\.$/ or /\.\./; +# return 'Group name does not begin/end with alphanumeric' +# if (/^[a-zA-Z0-9].+[a-zA-Z0-9]$/; + return 'Group name begins in control. or junk.' if /^(?:junk|control)\./; +# return 'Group name too long' if length $_ > 128; + + my @components = split(/\./); + # prevent alt.a.b.c.d.e.f.g.w.x.y.z... + return 'Too many components' if $#components > 9; + + # per-component checking + for (my $i = 0; $i <= $#components; $i++) { + local $_ = $components[$i]; + return 'all-numeric name component' if /^[0-9]+$/; +# return 'name component starts with non-alphanumeric' if /^[a-zA-Z0-9]/; +# return 'name component does not contain letter' if not /[a-zA-Z]/; + return "`all' or `ctl' used as name component" if /^(?:all|ctl)$/; +# return 'name component longer than 30 characters' if length $_ > 30; +# return 'uppercase letter(s) in name' if /[A-Z]/; + return 'illegal character(s) in name' if /[^a-z0-9+_\-.]/; + # sigh, c++ etc must be allowed + return 'repeated punctuation in name' if /--|__|\+\+./; +# return 'repeated component(s) in name' if ($i + 2 <= $#components +# and $_ eq $components[$i + 1] and $_ eq $components[$i + 2]); + } + return ''; +} + +1; --- inn-1.7.2q.orig/extra/etc/moderators +++ inn-1.7.2q/extra/etc/moderators @@ -0,0 +1,33 @@ +## $Id: moderators,v 1.6.2.1 2003/05/06 06:12:31 rra Exp $ +## +## moderators - Mailing addresses for moderators. +## +## Whenever possible, the master moderator database at moderators.isc.org +## should be used rather than adding specific entries to this file. The +## master database will list any publically propagated moderated group; +## changes should be sent to moderators-request@isc.org. +## +## Exceptions listed in this file are mostly hierarchies for which the +## master database isn't accurate or updated quickly enough. Local +## moderated newsgroups can also be added to this file. +## +## Format: +## : +## +## Shell-style newsgroup pattern or specific newsgroup +## Mail address, "%s" becomes newgroup name with dots +## changed to dashes. +## +## The first matching entry is used. + +## Public hierarchies with exceptions. +fido7.*:%s@fido7.ru +#ffm.*:%s@moderators.arcornews.de +fj.*:%s@moderators.fj-news.org +#medlux.*:%s@news.medlux.ru +#nl.*:%s@nl.net +relcom.*:%s@moderators.relcom.ru +#ukr.*:%s@sita.kiev.ua + +## Direct all other public hierarchies to the master moderator database. +*:%s@moderators.isc.org --- inn-1.7.2q.orig/extra/etc/innreport.conf +++ inn-1.7.2q/extra/etc/innreport.conf @@ -0,0 +1,2458 @@ +########################################################## +# Configuration file for innreport (3.*). +# +# Sample file for INN. +# Tested with INN 2.3, 2.1, 1.7.2 and 1.5.1. +# +# (c) 1997, 1998, 1999 by Fabien Tassin +# version 3.0.2 +########################################################## + +# Default parameters +section default { + libpath "/usr/lib/news"; + logpath "/var/log/news"; + unknown true; # want unknown entries. + max_unknown 50; # max unknown entries to display. + casesensitive true; + module "innreport_inn"; # ${libpath}/${module}.pm + unwanted_log "unwanted.log"; # ${logpath}/${unwanted_log} + text true; + html false; + graph true; # need 'html' + archive true; # use false to keep only the latest HTML report. + index "index.html"; # name of the HTML index file. + # html_dir "/var/www/News/stats"; + img_dir "pics"; # images will go to ${html_dir}/${img_dir} + cycle 30; # use a number or 'none'. + separator "."; # use a valid filename character. + title "Daily Usenet report"; + # title "Daily Usenet report for news.y.z"; + # footer "Local contact: x@y.z"; + # html_body "BGCOLOR=\"#FFFFFF\" TEXT=\"#000000\""; + # html_header_file "header.html"; # ${html_dir}/${html_header_file} + # html_footer_file "footer.html"; # ${html_dir}/${html_footer_file} + graph_width 550; # graph width (in pixels) + transparent true; # graph background transparent ? + graph_fg "#000000"; # graph foreground color. + graph_bg "#FFFFFF"; # graph background color. +}; + +########################################################################### +# Index page +section index { + column { + title "Dates"; + value "date"; + }; + column { + title "Incoming feeds"; + name "Offered|Accepted|Volume"; + value "total(%innd_offered) | total(%innd_accepted) | + bytes(total(%inn_flow_size))"; + }; + column { + title "Outgoing feeds"; + name "Offered|Accepted|Volume"; + value "total(%innfeed_offered) + total(%nntplink_offered) + + total(%innxmit_offered) | total(%innfeed_accepted) + + total(%nntplink_accepted) + total(%innxmit_accepted) | + bytes(total(%innfeed_accepted_size) + + total(%innfeed_rejected_size) + + total(%innxmit_bytes) + + total(%innxmit_accepted_size) + + total(%innxmit_rejected_size))"; + }; + graph { + title "Incoming feeds"; + value val1; + color "#FFFFCE"; + unit "art"; + data { + name "Offered"; + color "#50A0D0"; + value "val2"; # Incoming feeds: Offered + }; + data { + name "Accepted"; + color "#0000FF"; + value "val3"; # Incoming feeds: Accepted + }; + }; + graph { + title "Outgoing feeds"; + value val1; + color "#FFFFCE"; + unit "art"; + data { + name "Offered"; + color "#50A0D0"; + value "val5"; # Outgoing feeds: Offered + }; + data { + name "Accepted"; + color "#0000FF"; + value "val6"; # Outgoing feeds: Accepted + }; + }; + graph { + title "Bandwidth"; + value val1; + color "#FFFFCE"; + unit "Kb"; + data { + name "Incoming"; + color "#50A0D0"; + value "byte(val4)"; # Incoming feeds: Volume + }; + data { + name "Outgoing"; + color "#0000FF"; + value "byte(val7)"; # Outgoing feeds: Volume + }; + }; +}; + +########################################################################### +# Report + +section prog_type { + # skip true; # used to skip a section. + title "Log entries by program:"; + data "%prog_type"; + sort "$prog_type{$b} <=> $prog_type{$a}"; + # text false; # to skip this section in the text report + # html false; # to skip this section in the HTML report + column { + name "Program name"; + format "%-46.46s"; + value "$key"; + format_total "TOTAL: %-39.39s"; + total "$num"; + }; + column { + name "Lines"; + format_name "%7s"; + format "%7d"; + # text false; # to skip this column in the text report + value "$prog_type{$key}"; + total "total(%prog_type)"; + }; + column { + name "%Lines"; + format_name "%7s"; + format "%6.1f%%"; + # html false; # to skip this column in the HTML report + value "$prog_type{$key} / total(%prog_type) * 100"; + total "100"; + }; + column { + name "Size"; + format "%9s"; + value "bytes($prog_size{$key})"; + total "bytes(total(%prog_size))"; + }; + column { + name "%Size"; + format_name "%6s"; + format "%5.1f%%"; + value "$prog_size{$key} / total(%prog_size) * 100"; + total "100"; + }; +}; + +# INN 2.* +section innd_his { + title "History cache:"; + data "%innd_his"; + sort "$innd_his{$b} <=> $innd_his{$a}"; + column { + name "Reason"; + format "%-57.57s"; + value "$key"; + format_total "TOTAL: %-50.50s"; + total "$num"; + }; + column { + name "Count"; + format_name "%10s"; + format "%10d"; + value "$innd_his{$key}"; + total "total(%innd_his)"; + }; + column { + name "%Count"; + format_name "%10s"; + format "%9.1f%%"; + value "100 * $innd_his{$key} / total(%innd_his)"; + total "100"; + }; +}; + +# INN 1.* +section innd_cache { + title "History cache:"; + data "%innd_cache"; + sort "$innd_cache{$b} <=> $innd_cache{$a}"; + column { + name "Reason"; + format "%-57.57s"; + value "$key"; + format_total "TOTAL: %-50.50s"; + total "$num"; + }; + column { + name "Count"; + format_name "%10s"; + format "%10d"; + value "$innd_cache{$key}"; + total "total(%innd_cache)"; + }; + column { + name "%Count"; + format_name "%10s"; + format "%9.1f%%"; + value "100 * $innd_cache{$key} / total(%innd_cache)"; + total "100"; + }; +}; + +section innd_timer { + title "INND timer:"; + data "%innd_time_time"; + column { + name "Code region"; + format "%-15.15s"; + value "$key"; + format_total "TOTAL: %-8.8s"; + total "time_ms($innd_time_times)"; + }; + column { + name "Time"; + format "%13s"; + value "time_ms($innd_time_time{$key})"; + total "time_ms(total(%innd_time_time))"; + }; + column { + name "Pct"; + format_name "%6s"; + format "%5.1f%%"; + value "100 * $innd_time_time{$key} / $innd_time_times"; + total "100 * total(%innd_time_time) / + $innd_time_times"; + }; + column { + name "Invoked"; + format "%10s"; + value "$innd_time_num{$key}"; + format_total "%9s-"; + total ""; + }; + column { + name "Min(ms)"; + format_name "%9s"; + format "%9.3f"; + value "$innd_time_min{$key}"; + format_total "%8s-"; + total ""; + }; + column { + name "Avg(ms)"; + format_name "%10s"; + format "%10.3f"; + value "$innd_time_time{$key} / + ($innd_time_num{$key} ? $innd_time_num{$key} : 1)"; + format_total "%9s-"; + total ""; + }; + column { + name "Max(ms)"; + format_name "%10s"; + format "%10.3f"; + value "$innd_time_max{$key}"; + format_total "%9s-"; + total ""; + }; +}; + +section innfeed_timer { + title "INNfeed timer:"; + data "%innfeed_time_time"; + column { + name "Code region"; + format "%-15.15s"; + value "$key"; + format_total "TOTAL: %-8.8s"; + total "time_ms($innfeed_time_times)"; + }; + column { + name "Time"; + format "%13s"; + value "time_ms($innfeed_time_time{$key})"; + total "time_ms(total(%innfeed_time_time))"; + }; + column { + name "Pct"; + format_name "%6s"; + format "%5.1f%%"; + value "100 * $innfeed_time_time{$key} / $innfeed_time_times"; + total "100 * total(%innfeed_time_time) / + $innfeed_time_times"; + }; + column { + name "Invoked"; + format "%10s"; + value "$innfeed_time_num{$key}"; + format_total "%9s-"; + total ""; + }; + column { + name "Min(ms)"; + format_name "%9s"; + format "%9.3f"; + value "$innfeed_time_min{$key}"; + format_total "%8s-"; + total ""; + }; + column { + name "Avg(ms)"; + format_name "%10s"; + format "%10.3f"; + value "$innfeed_time_time{$key} / + ($innfeed_time_num{$key} ? $innfeed_time_num{$key} : 1)"; + format_total "%9s-"; + total ""; + }; + column { + name "Max(ms)"; + format_name "%10s"; + format "%10.3f"; + value "$innfeed_time_max{$key}"; + format_total "%9s-"; + total ""; + }; +}; + +section nnrpd_timer { + title "nnrpd timer:"; + data "%nnrpd_time_time"; + column { + name "Code region"; + format "%-15.15s"; + value "$key"; + format_total "TOTAL: %-8.8s"; + total "time_ms($nnrpd_time_times)"; + }; + column { + name "Time"; + format "%13s"; + value "time_ms($nnrpd_time_time{$key})"; + total "time_ms(total(%nnrpd_time_time))"; + }; + column { + name "Pct"; + format_name "%6s"; + format "%5.1f%%"; + value "100 * $nnrpd_time_time{$key} / $nnrpd_time_times"; + total "100 * total(%nnrpd_time_time) / + $nnrpd_time_times"; + }; + column { + name "Invoked"; + format "%10s"; + value "$nnrpd_time_num{$key}"; + format_total "%9s-"; + total ""; + }; + column { + name "Min(ms)"; + format_name "%9s"; + format "%9.3f"; + value "$nnrpd_time_min{$key}"; + format_total "%8s-"; + total ""; + }; + column { + name "Avg(ms)"; + format_name "%10s"; + format "%10.3f"; + value "$nnrpd_time_time{$key} / + ($nnrpd_time_num{$key} ? $nnrpd_time_num{$key} : 1)"; + format_total "%9s-"; + total ""; + }; + column { + name "Max(ms)"; + format_name "%10s"; + format "%10.3f"; + value "$nnrpd_time_max{$key}"; + format_total "%9s-"; + total ""; + }; +}; + +section innd_control { + title "Control commands to INND:"; + data "%innd_control"; + column { + name "Command"; + format "%-71.71s"; + value "$key"; + format_total "TOTAL: %-64.64s"; + total "$num"; + }; + column { + name "Number"; + format_name "%7s"; + value "$innd_control{$key}"; + format "%7d"; + total "total(%innd_control)"; + }; +}; + +section innd_newgroup { + title "Newsgroups created:"; + data "%innd_newgroup"; + column { + name "Group"; + format "%-71.71s"; + value "$key"; + format_total "TOTAL%-66.66s"; + total ""; + }; + column { + name "Mode"; + value "$innd_newgroup{$key}"; + format "%7s"; + total "$num"; + }; +}; + +section innd_changegroup { + title "Newsgroups changed:"; + data "%innd_changegroup"; + column { + name "Group"; + format "%-68.68s"; + value "$key"; + format_total "TOTAL%-63.63s"; + total ""; + }; + column { + name "New mode"; + format "%10s"; + value "$innd_changegroup{$key}"; + total "$num"; + }; +}; + +section innd_rmgroup { + title "Newsgroups removed:"; + data "%innd_rmgroup"; + column { + name "Group"; + format "%-78.78s"; + value "$key"; + format_total "TOTAL: %-71.71s"; + total "$num"; + }; +}; + +section controlchan { + title "Control Channel:"; + data "%controlchan_who"; + column { + name "Sender"; + format "%-25.25s"; + value "$key"; + format_total "TOTAL%-20.20s"; + total ""; + }; + column { + name "newgroup"; + value "$controlchan_new{$key}"; + format "%8s"; + total "total(%controlchan_new)"; + }; + column { + name "rmgroup"; + value "$controlchan_rm{$key}"; + format "%8s"; + total "total(%controlchan_rm)"; + }; + column { + name "Other"; + value "$controlchan_other{$key}"; + format "%8s"; + total "total(%controlchan_other)"; + }; + column { + name "Bad PGP"; + value "$controlchan_skippgp{$key}"; + format "%8s"; + total "total(%controlchan_skippgp)"; + }; + column { + name "DoIt"; + value "$controlchan_doit{$key}"; + format "%8s"; + total "total(%controlchan_doit)"; + }; + column { + name "OK"; + value "$controlchan_ok{$key}"; + format "%8s"; + total "total(%controlchan_ok)"; + }; +}; + +section innd_connect { + title "Incoming Feeds (INN):"; + data "%innd_seconds"; + sort "$innd_accepted{$b} <=> $innd_accepted{$a}"; + numbering true; + column { + name "Server"; + format_name "%-21.21s"; + format "%-24.24s"; + value "$key"; + format_total "TOTAL: %-17.17s"; + total "$num"; + }; + column { + name "Connects"; + format_name "%5s"; + format "%5d"; + value "$innd_connect{$key}"; + total "total(%innd_connect)"; + }; + column { + name "Offered"; + format_name "%8s"; + format "%8d"; + value "$innd_offered{$key}"; + total "total(%innd_offered)"; + }; + column { + name "Taken"; + format_name "%7s"; + format "%7d"; + value "$innd_accepted{$key}"; + total "total(%innd_accepted)"; + }; + column { + name "Refused"; + format_name "%7s"; + format "%7d"; + value "$innd_refused{$key}"; + total "total(%innd_refused)"; + }; + column { + name "Reject"; + format_name "%7s"; + format "%7d"; + value "$innd_rejected{$key}"; + total "total(%innd_rejected)"; + }; + column { + name "%Accpt"; + format_name "%6s"; + format "%4d%%"; + value "$innd_offered{$key} == 0 ? 0 : + $innd_accepted{$key} / $innd_offered{$key} * 100"; + total "total(%innd_offered) == 0 ? 0 : + total(%innd_accepted) / total(%innd_offered) * 100"; + }; + column { + name "Elapsed"; + format_name "%8s"; + format "%9s"; + value "time($innd_seconds{$key})"; + total "time(total(%innd_seconds))"; + }; + graph { + title "Articles received by server"; + type histo3d; + sort "%innd_accepted"; + data { + name "Articles accepted"; + color "#0000FF"; + value "%innd_accepted"; + }; + data { + name "Articles refused"; + color "#FFAF00"; + value "%innd_refused"; + }; + data { + name "Articles rejected"; + color "#FF0000"; + value "%innd_rejected"; + }; + }; +}; + +section innd_incoming_vol { + title "Incoming Volume (INN):"; + data "%innd_seconds"; + sort "$innd_stored_size{$b} <=> $innd_stored_size{$a}"; + numbering true; + column { + name "Server"; + format "%-24.24s"; + value "$key"; + format_total "TOTAL: %-17.17s"; + total "$num"; + }; + column { + name "AcceptVol"; + format "%9s"; + value "bytes($innd_stored_size{$key})"; + total "bytes(total(%innd_stored_size))"; + }; + column { + name "DupVol"; + format "%9s"; + value "bytes($innd_duplicated_size{$key})"; + total "bytes(total(%innd_duplicated_size))"; + }; + column { + name "TotalVol"; + format "%9s"; + value "bytes($innd_stored_size{$key} + + $innd_duplicated_size{$key})"; + total "bytes(total(%innd_stored_size) + + total(%innd_duplicated_size))"; + }; + column { + name "%Acc"; + format_name "%4s"; + format "%3d%%"; + value "$innd_offered_size{$key} == 0 ? 0 : + $innd_stored_size{$key} / $innd_offered_size{$key} * 100"; + total "total(%innd_offered_size) == 0 ? 0 : + total(%innd_stored_size) / total(%innd_offered_size) * 100"; + }; + column { + name "Vol/Art"; + format "%9s"; + value "bytes(($innd_stored_size{$key} + + $innd_duplicated_size{$key}) / + ($innd_accepted{$key} + + $innd_rejected{$key}))"; + total "bytes((total(%innd_stored_size) + + total(%innd_duplicated_size)) / + (total(%innd_accepted) + + total(%innd_rejected)))"; + }; + column { + name "Elapsed"; + format "%9s"; + value "time($innd_seconds{$key})"; + total "time(total(%innd_seconds))"; + }; + graph { + title "Incoming Volume received by server"; + type histo3d; + sort "%innd_stored_size"; + data { + name "Accepted Volume"; + color "#0000FF"; + value "%innd_stored_size"; + }; + data { + name "Duplicated Volume"; + color "#FFAF00"; + value "%innd_duplicated_size"; + }; + }; +}; + +section inn_flow { + title "Incoming articles:"; + data "%inn_flow"; + sort "&DateCompare"; + column { + name "Date"; + format "%-27.27s"; + value "$key"; + format_total "TOTAL: %-20.20s"; + total "time(total(%inn_flow_time))"; + }; + column { + name "Articles"; + format_name "%8s"; + value "$inn_flow{$key}"; + format "%8d"; + total "total(%inn_flow)"; + }; + column { + name "%Arts"; + format_name "%8s"; + value "$inn_flow{$key} / $inn_flow_total * 100"; + format "%7.1f%%"; + total "100"; + }; + column { + name "Art/sec"; + format_name "%7s"; + value "$inn_flow{$key} / $inn_flow_time{$key}"; + format "%7.2f"; + total "total(%inn_flow) / total(%inn_flow_time)"; + }; + column { + name "Size"; + value "bytes($inn_flow_size{$key})"; + format "%9s"; + total "bytes(total(%inn_flow_size))"; + }; + column { + name "%Size"; + format_name "%7s"; + value "$inn_flow_size{$key} / + total(%inn_flow_size) * 100"; + format "%6.1f%%"; + total "100"; + }; + column { + name "KB/sec"; + format_name "%7s"; + value "$inn_flow_size{$key} / + $inn_flow_time{$key} / 1024"; + format "%7.2f"; + total "total(%inn_flow_size) / + total(%inn_flow_time) / 1024"; + }; + graph { + title "Incoming articles"; + type histo; + data { + name "Hours"; + value "%inn_flow_labels"; + }; + data { + name "Art/sec"; + factor 3600; + value "%inn_flow"; + }; + }; + graph { + title "Incoming articles (size)"; + type histo; + data { + name "Hours"; + value "%inn_flow_labels"; + }; + data { + name "Kb/sec"; + factor 3686400; # 3600 * 1024 + value "%inn_flow_size"; + }; + }; +}; + +section cnfsstat { + title "CNFS buffer status:"; + data "%cnfsstat"; + column { + name "Buffer"; + format "%-13.13s"; + value "$key"; + format_total "TOTAL: %-6.6s"; + total "$num"; + }; + column { + name "Class"; + format "%-13.13s"; + value "$cnfsstat{$key}"; + format_total "-%12s"; + total ""; + }; + column { + name "Size"; + format "%9s"; + value "bytes($cnfsstat_size{$key})"; + total "bytes(total(%cnfsstat_size))"; + }; + column { + name "Used"; + format "%9s"; + value "bytes($cnfsstat_used{$key})"; + total "bytes(total(%cnfsstat_used))"; + }; + column { + name "%Used"; + format_name "%7s"; + value "$cnfsstat_used{$key} / + $cnfsstat_size{$key} * 100"; + format "%6.1f%%"; + total "total(%cnfsstat_used) / + total(%cnfsstat_size) * 100"; + }; + column { + name "Cycles"; + format_name "%6s"; + format "%6d"; + value "$cnfsstat_cycles{$key}"; + total "total(%cnfsstat_cycles)"; + }; + column { + name "KB/sec"; + format_name "%7s"; + value "$cnfsstat_rate{$key} / + $cnfsstat_samples{$key} / 1024"; + format "%7.2f"; + total "total(%cnfsstat_rate) / + total(%cnfsstat_samples) / 1024"; + }; + column { + name "Days"; + format_name "%8s"; + value "$cnfsstat_size{$key} / + ($cnfsstat_rate{$key} / + $cnfsstat_samples{$key}) / 86400"; + format "%8.2f"; + format_total "%7s-"; + total ""; + }; +}; + +section inn_unwanted { + title "Sites sending bad articles:"; + data "%inn_badart"; + sort "$inn_badart{$b} <=> $inn_badart{$a}"; + numbering true; + column { + name "Server"; + format "%-23.23s"; + value "$key"; + format_total "TOTAL: %-16.16s"; + total "$num"; + }; + column { + name "Total"; + format_name "%6s"; + format "%6d"; + value "$inn_badart{$key}"; + total "total(%inn_badart)"; + }; + column { + name "Group"; + format_name "%6s"; + format "%6d"; + value "$inn_uw_ng_s{$key}"; + total "total(%inn_uw_ng_s)"; + }; + column { + name "Dist"; + format_name "%5s"; + format "%5d"; + value "$inn_uw_dist_s{$key}"; + total "total(%inn_uw_dist_s)"; + }; + column { + name "Duplic"; + format_name "%6s"; + format "%6d"; + value "$inn_duplicate{$key}"; + total "total(%inn_duplicate)"; + }; + column { + name "Unapp"; + format_name "%5s"; + format "%5d"; + value "$inn_unapproved{$key}"; + total "total(%inn_unapproved)"; + }; + column { + name "TooOld"; + format_name "%6s"; + format "%6d"; + value "$inn_tooold{$key}"; + total "total(%inn_tooold)"; + }; + column { + name "Site"; + format_name "%4s"; + format "%4d"; + value "$inn_uw_site{$key}"; + total "total(%inn_uw_site)"; + }; + column { + name "Line"; + format_name "%4s"; + format "%4d"; + value "$inn_linecount{$key}"; + total "total(%inn_linecount)"; + }; + column { + name "Other"; + format_name "%5s"; + format "%5d"; + value "$innd_others{$key}"; + total "total(%innd_others)"; + }; +}; + +section inn_unwanted_group { + title "Unwanted newsgroups:"; + top 20; # default 'top' value or use 'top_text' and 'top_html' + # to specify different values for text and HTML reports. + data "%inn_uw_ng"; + sort "$inn_uw_ng{$b} <=> $inn_uw_ng{$a}"; + column { + name "Newsgroup"; + format "%-71.71s"; + value "$key"; + format_total "TOTAL: %-64.64s"; + total "$num"; + }; + column { + name "Count"; + format_name "%7s"; + format "%7d"; + value "$inn_uw_ng{$key}"; + total "total(%inn_uw_ng)"; + }; +}; + +section inn_unwanted_dist { + title "Unwanted distributions:"; + top 20; + data "%inn_uw_dist"; + sort "$inn_uw_dist{$b} <=> $inn_uw_dist{$a}"; + column { + name "Distribution"; + format "%-71.71s"; + value "$key"; + format_total "TOTAL: %-64.64s"; + total "$num"; + }; + column { + name "Count"; + format_name "%7s"; + format "%7d"; + value "$inn_uw_dist{$key}"; + total "total(%inn_uw_dist)"; + }; +}; + +section inn_unwanted_unapp { + title "Supposedly-moderated groups with unmoderated postings:"; + top 20; + data "%inn_unapproved_g"; + sort "$inn_unapproved_g{$b} <=> $inn_unapproved_g{$a}"; + column { + name "Groups"; + format "%-71.71s"; + value "$key"; + format_total "TOTAL: %-64.64s"; + total "$num"; + }; + column { + name "Count"; + format_name "%7s"; + format "%7d"; + value "$inn_unapproved_g{$key}"; + total "total(%inn_unapproved_g)"; + }; +}; + +section inn_unwanted_path { + title "Unwanted sites in Path:"; + top 20; + data "%inn_site_path"; + sort "$inn_site_path{$b} <=> $inn_site_path{$a}"; + column { + name "Site"; + format "%-71.71s"; + value "$key"; + format_total "TOTAL: %-64.64s"; + total "$num"; + }; + column { + name "Count"; + format_name "%7s"; + format "%7d"; + value "$inn_site_path{$key}"; + total "total(%inn_site_path)"; + }; +}; + +section innd_perl { + title "INND perl filter:"; + top 20; + data "%innd_filter_perl"; + sort "$innd_filter_perl{$b} <=> $innd_filter_perl{$a}"; + column { + name "Reason"; + format "%-71.71s"; + value "$key"; + format_total "TOTAL: %-64.64s"; + total "$num"; + }; + column { + name "Count"; + format_name "%7s"; + format "%7d"; + value "$innd_filter_perl{$key}"; + total "total(%innd_filter_perl)"; + }; +}; + +section nocem { + title "NoCeM on Spool:"; + data "%nocem_goodsigs"; + sort "$nocem_ids{$b} <=> $nocem_ids{$a}"; + column { + name "Id"; + format "%-47.47s"; + value "$key"; + format_total "TOTAL: %-40.40s"; + total "$num"; + }; + column { + name "Good"; + format "%7s"; + value "$nocem_goodsigs{$key}"; + total "total(%nocem_goodsigs)"; + }; + column { + name "Bad"; + format "%7s"; + value "$nocem_badsigs{$key}"; + total "total(%nocem_badsigs)"; + }; + column { + name "Unique"; + format "%7s"; + value "$nocem_newids{$key}"; + total "total(%nocem_newids)"; + }; + column { + name "Total"; + format "%7s"; + value "$nocem_totalids{$key}"; + total "total(%nocem_totalids)"; + }; +}; + +section innd_no_permission { + title "INND no permission servers:"; + data "%innd_no_permission"; + sort "$innd_no_permission{$b} <=> $innd_no_permission{$a}"; + column { + name "System"; + format "%-71.71s"; + value "$key"; + format_total "TOTAL: %-64.64s"; + total "$num"; + }; + column { + name "Conn"; + format_name "%7s"; + format "%7d"; + value "$innd_no_permission{$key}"; + total "total(%innd_no_permission)"; + }; +}; + +section innd_max_conn { + title "Too many incoming connections (innd):"; + data "%innd_max_conn"; + sort "$innd_max_conn{$b} <=> $innd_max_conn{$a}"; + column { + name "Server"; + format "%-70.70s"; + value "$key"; + format_total "TOTAL: %-63.63s"; + total "$num"; + }; + column { + name "Conn"; + format_name "%8s"; + format "%8d"; + value "$innd_max_conn{$key}"; + total "total(%innd_max_conn)"; + }; +}; + +section innd_too_many_connects_per_minute { + title "INND too many connects per minute:"; + data "%innd_too_many_connects_per_minute"; + sort "$innd_too_many_connects_per_minute{$b} <=> + $innd_too_many_connects_per_minute{$a}"; + column { + name "System"; + format "%-71.71s"; + value "$key"; + format_total "TOTAL: %-64.64s"; + total "$num"; + }; + column { + name "Conn"; + format_name "%7s"; + format "%7d"; + value "$innd_too_many_connects_per_minute{$key}"; + total "total(%innd_too_many_connects_per_minute)"; + }; +}; + +section innd_misc { + title "INND misc events:"; + data "%innd_misc"; + sort "$innd_misc{$b} <=> $innd_misc{$a}"; + column { + name "Events"; + format "%-71.71s"; + value "$key"; + format_total "TOTAL: %-64.64s"; + total "$num"; + }; + column { + name "Count"; + format_name "%7s"; + format "%7d"; + value "$innd_misc{$key}"; + total "total(%innd_misc)"; + }; +}; + +section innd_misc_stat { + title "Miscellaneous innd statistics:"; + data "%innd_misc_stat"; + sort "$innd_misc_stat{$b} <=> $innd_misc_stat{$a}"; + double true; + top 10; + #numbering true; + column { + primary true; + name "Event"; + format "%-69.69s"; + value "$key1"; + format_total "TOTAL: %-62.62s"; + total "$num"; + }; + column { + name "Server"; + format " %-67.67s"; + value "$key2"; + total "$num"; + format_total "TOTAL: %-60.60s"; + }; + column { + name "Number"; + format_name "%9s"; + format "%9d"; + value "$innd_misc_stat{$key1}{$key2}"; + total "total(%innd_misc_stat)"; + }; +}; + +section innfeed_connect { + title "Outgoing Feeds (innfeed) by Articles:"; + data "%innfeed_offered"; + sort "$innfeed_accepted{$b} <=> $innfeed_accepted{$a}"; + numbering true; + column { + name "Server"; + format "%-18.18s"; + value "$key"; + format_total "TOTAL: %-11.11s"; + total "$num"; + }; + column { + name "Offered"; + format_name "%7s"; + format "%7d"; + value "$innfeed_offered{$key}"; + total "total(%innfeed_offered)"; + }; + column { + name "Taken"; + format_name "%7s"; + format "%7d"; + value "$innfeed_accepted{$key}"; + total "total(%innfeed_accepted)"; + }; + column { + name "Refused"; + format_name "%7s"; + format "%7d"; + value "$innfeed_refused{$key}"; + total "total(%innfeed_refused)"; + }; + column { + name "Reject"; + format_name "%6s"; + format "%6d"; + value "$innfeed_rejected{$key}"; + total "total(%innfeed_rejected)"; + }; + column { + name "Miss"; + format_name "%6s"; + format "%6d"; + value "$innfeed_missing{$key}"; + total "total(%innfeed_missing)"; + }; + column { + name "Spool"; + format_name "%7s"; + format "%7d"; + value "$innfeed_spooled{$key}"; + total "total(%innfeed_spooled)"; + }; + column { + name "%Took"; + format_name "%5s"; + format "%3d%%"; + value "$innfeed_offered{$key} == 0 ? 0 : + $innfeed_accepted{$key} / $innfeed_offered{$key} * 100"; + total "total(%innfeed_offered) == 0 ? 0 : + total(%innfeed_accepted) / total(%innfeed_offered) * 100"; + }; + column { + name "Elapsed"; + format_name "%8s"; + format "%9s"; + value "time($innfeed_seconds{$key})"; + total "time(total(%innfeed_seconds))"; + }; + graph { + title "Outgoing feeds (innfeed) by Articles"; + type histo3d; + sort "%innfeed_accepted"; + data { + name "Accepted"; + color "#0000FF"; + value "%innfeed_accepted"; + }; + data { + name "Refused"; + color "#FFAF00"; + value "%innfeed_refused"; + }; + data { + name "Rejected"; + color "#FF0000"; + value "%innfeed_rejected"; + }; + data { + name "Missing"; + color "#00FF00"; + value "%innfeed_missing"; + }; + data { + name "Spooled"; + color "#AF00FF"; + value "%innfeed_spooled,"; + }; + }; +}; + +section innfeed_volume { + title "Outgoing Feeds (innfeed) by Volume:"; + data "%innfeed_offered"; + sort "$innfeed_accepted_size{$b} <=> $innfeed_accepted_size{$a}"; + numbering true; + column { + name "Server"; + format "%-17.17s"; + value "$key"; + format_total "TOTAL: %-10.10s"; + total "$num"; + }; + column { + name "AcceptVol"; + format "%9s"; + value "bytes($innfeed_accepted_size{$key})"; + total "bytes(total(%innfeed_accepted_size))"; + }; + column { + name "RejectVol"; + format "%9s"; + value "bytes($innfeed_rejected_size{$key})"; + total "bytes(total(%innfeed_rejected_size))"; + }; + column { + name "TotalVol"; + format "%9s"; + value "bytes($innfeed_accepted_size{$key} + + $innfeed_rejected_size{$key})"; + total "bytes(total(%innfeed_accepted_size) + + total(%innfeed_rejected_size))"; + }; + column { + name "Volume/sec"; + format_name "%11s"; + format "%9s/s"; + value "bytes(($innfeed_accepted_size{$key} + + $innfeed_rejected_size{$key}) / + $innfeed_seconds{$key})"; + total "bytes((total(%innfeed_accepted_size) + + total(%innfeed_rejected_size)) / + total(%innfeed_seconds))"; + }; + column { + name "Vol/Art"; + format "%9s"; + value "bytes(($innfeed_accepted_size{$key} + + $innfeed_rejected_size{$key}) / + ($innfeed_accepted{$key} + + $innfeed_rejected{$key}))"; + total "bytes((total(%innfeed_accepted_size) + + total(%innfeed_rejected_size)) / + (total(%innfeed_accepted) + + total(%innfeed_rejected)))"; + }; + column { + name "Elapsed"; + format "%9s"; + value "time($innfeed_seconds{$key})"; + total "time(total(%innfeed_seconds))"; + }; + graph { + title "Outgoing feeds (innfeed) by Volume"; + type histo3d; + sort "%innfeed_accepted_size"; + data { + name "Accepted"; + color "#0000FF"; + value "%innfeed_accepted_size"; + }; + data { + name "Rejected"; + color "#FFAF00"; + value "%innfeed_rejected_size"; + }; + data { + name "Total"; + color "#00FF00"; + value "%innfeed_accepted_size + + %innfeed_rejected_size"; + }; + }; +}; + +section innfeed_shrunk { + title "Backlog files shrunk by innfeed:"; + data "%innfeed_shrunk"; + sort "$innfeed_shrunk{$b} <=> $innfeed_shrunk{$a}"; + column { + name "Server"; + format "%-70.70s"; + value "$key"; + format_total "TOTAL: %-63.63s"; + total "$num"; + }; + column { + name "Size"; + format "%8s"; + value "bytes($innfeed_shrunk{$key})"; + total "bytes(total(%innfeed_shrunk))"; + }; +}; + +section nntplink_connect { + title "Outgoing Feeds (nntplink):"; + data "%nntplink_site"; + sort "$nntplink_accepted{$b} <=> $nntplink_accepted{$a}"; + numbering true; + column { + name "Server"; + format "%-25.25s"; + value "$key"; + format_total "TOTAL: %-18.18s"; + total "$num"; + }; + column { + name "Offered"; + format_name "%8s"; + format "%8d"; + value "$nntplink_offered{$key}"; + total "total(%nntplink_offered)"; + }; + column { + name "Taken"; + format_name "%8s"; + format "%8d"; + value "$nntplink_accepted{$key}"; + total "total(%nntplink_accepted)"; + }; + column { + name "Rejected"; + format_name "%8s"; + format "%8d"; + value "$nntplink_rejected{$key}"; + total "total(%nntplink_rejected)"; + }; + column { + name "Failed"; + format_name "%8s"; + format "%8d"; + value "$nntplink_failed{$key}"; + total "total(%nntplink_failed)"; + }; + column { + name "%Accpt"; + format_name "%6s"; + format "%5d%%"; + value "$nntplink_offered{$key} == 0 ? 0 : + $nntplink_accepted{$key} / $nntplink_offered{$key} * 100"; + total "total(%nntplink_offered) == 0 ? 0 : + total(%nntplink_accepted) / total(%nntplink_offered) * 100"; + }; + column { + name "Elapsed"; + format "%10s"; + value "time($nntplink_times{$key})"; + total "time(total(%nntplink_times))"; + }; + graph { + title "Outgoing Feeds (nntplink)"; + type histo3d; + sort "%nntplink_accepted"; + data { + name "Articles accepted"; + color "#0000FF"; + value "%nntplink_accepted"; + }; + data { + name "Articles rejected"; + color "#FFAF00"; + value "%nntplink_rejected"; + }; + data { + name "Articles failed"; + color "#FF0000"; + value "%nntplink_failed"; + }; + }; +}; + +section nntplink_connect2 { + title "Outgoing Feeds (nntplink) - other information:"; + data "%nntplink_site"; + sort "$nntplink_accepted{$b} <=> $nntplink_accepted{$a}"; + numbering true; + column { + name "Server"; + format "%-20.20s"; + value "$key"; + format_total "TOTAL: %-13.13s"; + total "$num"; + }; + column { + name "Conn"; + format_name "%4s"; + format "%4d"; + value "$nntplink_site{$key}"; + total "total(%nntplink_site)"; + }; + column { + name "Ok"; + format_name "%4s"; + format "%4d"; + value "$nntplink_site{$key} - ($nntplink_eof{$key} + + $nntplink_sockerr{$key} + + $nntplink_selecterr{$key} + + $nntplink_hiload{$key} + $nntplink_bpipe{$key} + + $nntplink_nospace{$key} + $nntplink_auth{$key} + + $nntplink_expire{$key} + $nntplink_fail{$key})"; + total "total(%nntplink_site) - (total(%nntplink_eof) + + total(%nntplink_sockerr) + + total(%nntplink_selecterr) + + total(%nntplink_hiload) + + total(%nntplink_bpipe) + + total(%nntplink_nospace) + + total(%nntplink_auth) + + total(%nntplink_expire) + + total(%nntplink_fail))"; + }; + column { + name "EOF"; + format_name "%3s"; + format "%3d"; + value "$nntplink_eof{$key}"; + total "total(%nntplink_eof)"; + }; + column { + name "Sock"; + format_name "%4s"; + format "%4d"; + value "$nntplink_sockerr{$key}"; + total "total(%nntplink_sockerr)"; + }; + column { + name "Slct"; + format_name "%4s"; + format "%4d"; + value "$nntplink_selecterr{$key}"; + total "total(%nntplink_selecterr)"; + }; + column { + name "Load"; + format_name "%4s"; + format "%4d"; + value "$nntplink_hiload{$key}"; + total "total(%nntplink_hiload)"; + }; + column { + name "Bpip"; + format_name "%4s"; + format "%4d"; + value "$nntplink_bpipe{$key}"; + total "total(%nntplink_bpipe)"; + }; + column { + name "Spce"; + format_name "%4s"; + format "%4d"; + value "$nntplink_nospace{$key}"; + total "total(%nntplink_nospace)"; + }; + column { + name "Exp"; + format_name "%4s"; + format "%4d"; + value "$nntplink_expire{$key}"; + total "total(%nntplink_expire)"; + }; + column { + name "Auth"; + format_name "%4s"; + format "%4d"; + value "$nntplink_auth{$key}"; + total "total(%nntplink_auth)"; + }; + column { + name "Othr"; + format_name "%4s"; + format "%4d"; + value "$nntplink_fail{$key}"; + total "total(%nntplink_fail)"; + }; + column { + name "Pct"; + format_name "%4s"; + format "%3d%%"; + value "$nntplink_site{$key} ? + 100 * ($nntplink_site{$key} - + ($nntplink_eof{$key} + $nntplink_sockerr{$key} + + $nntplink_selecterr{$key} + + $nntplink_hiload{$key} + $nntplink_bpipe{$key} + + $nntplink_nospace{$key} + $nntplink_auth{$key} + + $nntplink_expire{$key} + + $nntplink_fail{$key})) / $nntplink_site{$key} : 0"; + total "total(%nntplink_site) ? + 100 * (total(%nntplink_site) - + (total(%nntplink_eof) + + total(%nntplink_sockerr) + + total(%nntplink_selecterr) + + total(%nntplink_hiload) + + total(%nntplink_bpipe) + + total(%nntplink_nospace) + + total(%nntplink_auth) + + total(%nntplink_expire) + + total(%nntplink_fail))) / total(%nntplink_site) : 0"; + }; +}; + +section innxmit_connect { + title "Outgoing Feeds (innxmit) by Articles:"; + data "%innxmit_times"; + sort "$innxmit_accepted{$b} <=> $innxmit_accepted{$a}"; + numbering true; + column { + name "Server"; + format "%-27.27s"; + value "$key"; + format_total "TOTAL: %-20.20s"; + total "$num"; + }; + column { + name "Offered"; + format_name "%7s"; + format "%7d"; + value "$innxmit_offered{$key}"; + total "total(%innxmit_offered)"; + }; + column { + name "Taken"; + format_name "%7s"; + format "%7d"; + value "$innxmit_accepted{$key}"; + total "total(%innxmit_accepted)"; + }; + column { + name "Refused"; + format_name "%7s"; + format "%7d"; + value "$innxmit_refused{$key}"; + total "total(%innxmit_refused)"; + }; + column { + name "Reject"; + format_name "%7s"; + format "%7d"; + value "$innxmit_rejected{$key}"; + total "total(%innxmit_rejected)"; + }; + column { + name "Miss"; + format_name "%5s"; + format "%5d"; + value "$innxmit_missing{$key}"; + total "total(%innxmit_rejected)"; + }; + column { + name "%Acc"; + format_name "%4s"; + format "%3d%%"; + value "$innxmit_offered{$key} == 0 ? 0 : + $innxmit_accepted{$key} / $innxmit_offered{$key} * 100"; + total "total(%innxmit_offered) == 0 ? 0 : + total(%innxmit_accepted) / total(%innxmit_offered) * 100"; + }; + column { + name "Elapsed"; + format "%8s"; + value "time($innxmit_times{$key})"; + total "time(total(%innxmit_times))"; + }; + graph { + title "Outgoing Feeds (innxmit)"; + type histo3d; + sort "%innxmit_accepted"; + data { + name "Art. accepted"; + color "#0000FF"; + value "%innxmit_accepted"; + }; + data { + name "Art. refused"; + color "#FFAF00"; + value "%innxmit_refused"; + }; + data { + name "Art. rejected"; + color "#FF0000"; + value "%innxmit_rejected"; + }; + data { + name "Art. missing"; + color "#00FF00"; + value "%innxmit_missing"; + }; + }; +}; + +section innxmit_volume { + title "Outgoing Feeds (innxmit) by Volume:"; + data "%innxmit_accepted_size"; + sort "$innxmit_accepted_size{$b} <=> $innxmit_accepted_size{$a}"; + numbering true; + column { + name "Server"; + format "%-24.24s"; + value "$key"; + format_total "TOTAL: %-17.17s"; + total "$num"; + }; + column { + name "AcceptVol"; + format "%9s"; + value "bytes($innxmit_accepted_size{$key})"; + total "bytes(total(%innxmit_accepted_size))"; + }; + column { + name "RejectVol"; + format "%9s"; + value "bytes($innxmit_rejected_size{$key})"; + total "bytes(total(%innxmit_rejected_size))"; + }; + column { + name "TotalVol"; + format "%9s"; + value "bytes($innxmit_accepted_size{$key} + + $innxmit_rejected_size{$key} + + $innxmit_bytes{$key})"; + total "bytes(total(%innxmit_accepted_size) + + total(%innxmit_rejected_size) + + total(%innxmit_bytes))"; + }; + column { + name "KB/s"; + format_name "%5s"; + format "%5.1f"; + value "($innxmit_accepted_size{$key} + + $innxmit_rejected_size{$key} + + $innxmit_bytes{$key}) / + $innxmit_times{$key} / 1024"; + total "(total(%innxmit_accepted_size) + + total(%innxmit_rejected_size) + + total(%innxmit_bytes)) / + total(%innxmit_times) / 1024"; + }; + column { + name "Vol/Art"; + format "%9s"; + value "bytes(($innxmit_accepted_size{$key} + + $innxmit_rejected_size{$key} + + $innxmit_bytes{$key}) / + ($innxmit_accepted{$key} + + $innxmit_rejected{$key}))"; + total "bytes((total(%innxmit_accepted_size) + + total(%innxmit_rejected_size) + + total(%innxmit_bytes)) / + (total(%innxmit_accepted) + + total(%innxmit_rejected)))"; + }; + column { + name "Elapsed"; + format "%8s"; + value "time($innxmit_times{$key})"; + total "time(total(%innxmit_times))"; + }; + graph { + title "Outgoing Feeds (innxmit)"; + type histo3d; + sort "%innxmit_accepted"; + data { + name "Articles accepted"; + color "#0000FF"; + value "%innxmit_accepted_size"; + }; + data { + name "Articles rejected"; + color "#FFAF00"; + value "%innxmit_rejected_size"; + }; + data { + name "Total"; + color "#FF0000"; + value "%innxmit_missing"; + }; + }; +}; + + +section innxmit_connect2 { + title "Outgoing Feeds (innxmit) - other information:"; + data "%innxmit_site"; + sort "$innxmit_accepted{$b} <=> $innxmit_accepted{$a}"; + numbering true; + column { + name "Server"; + format "%-25.25s"; + value "$key"; + format_total "TOTAL: %-18.18s"; + total "$num"; + }; + column { + name "Conn"; + format_name "%5s"; + format "%5d"; + value "$innxmit_site{$key}"; + total "total(%innxmit_site)"; + }; + column { + name "Ok"; + format_name "%5s"; + format "%5d"; + value "$innxmit_site{$key} - + ($innxmit_afail_host{$key} + + $innxmit_hiload{$key} + $innxmit_nospace{$key} + + $innxmit_cfail_host{$key} + + $innxmit_expire{$key} + $innxmit_crefused{$key})"; + total "total(%innxmit_site) - + (total(%innxmit_afail_host) + + total(%innxmit_hiload) + + total(%innxmit_nospace) + + total(%innxmit_cfail_host) + + total(%innxmit_expire) + + total(%innxmit_crefused))"; + }; + column { + name "Auth"; + format_name "%4s"; + format "%4d"; + value "$innxmit_afail_host{$key}"; + total "total(%innxmit_afail_host)"; + }; + column { + name "Load"; + format_name "%4s"; + format "%4d"; + value "$innxmit_hiload{$key}"; + total "total(%innxmit_hiload)"; + }; + column { + name "Space"; + format_name "%5s"; + format "%5d"; + value "$innxmit_nospace{$key}"; + total "total(%innxmit_nospace)"; + }; + column { + name "Expire"; + format_name "%6s"; + format "%6d"; + value "$innxmit_expire{$key}"; + total "total(%innxmit_expire)"; + }; + column { + name "Connct"; + format_name "%6s"; + format "%6d"; + value "$innxmit_cfail_host{$key}"; + total "total(%innxmit_cfail_host)"; + }; + column { + name "Other"; + format_name "%6s"; + format "%6d"; + value "$innxmit_crefused{$key}"; + total "total(%innxmit_crefused)"; + }; + column { + name "Pct"; + format_name "%4s"; + format "%3d%%"; + value "$innxmit_site{$key} ? 100 * + ($innxmit_site{$key} - + ($innxmit_afail_host{$key} + + $innxmit_hiload{$key} + $innxmit_nospace{$key} + + $innxmit_cfail_host{$key} + + $innxmit_expire{$key} + + $innxmit_crefused{$key})) / $innxmit_site{$key} : 0"; + total "total(%innxmit_site) ? + 100 * (total(%innxmit_site) - + (total(%innxmit_afail_host) + + total(%innxmit_hiload) + + total(%innxmit_nospace) + + total(%innxmit_cfail_host) + + total(%innxmit_expire) + + total(%innxmit_crefused))) / total(%innxmit_site) : 0"; + }; +}; + +section innxmit_unwanted { + title "Sites fed by innxmit rejecting bad articles:"; + data "%innxmit_badart"; + sort "$innxmit_badart{$b} <=> $innxmit_badart{$a}"; + column { + numbering true; + name "Server"; + format "%-23.23s"; + value "$key"; + format_total "TOTAL: %-16.16s"; + total "$num"; + }; + column { + name "Total"; + format_name "%6s"; + format "%6d"; + value "$innxmit_badart{$key}"; + total "total(%innxmit_badart)"; + }; + column { + name "Group"; + format_name "%6s"; + format "%6d"; + value "$innxmit_uw_ng_s{$key}"; + total "total(%innxmit_uw_ng_s)"; + }; + column { + name "Dist"; + format_name "%5s"; + format "%5d"; + value "$innxmit_uw_dist_s{$key}"; + total "total(%innxmit_uw_dist_s)"; + }; + column { + name "Duplic"; + format_name "%6s"; + format "%6d"; + value "$innxmit_duplicate{$key}"; + total "total(%innxmit_duplicate)"; + }; + column { + name "Unapp"; + format_name "%5s"; + format "%5d"; + value "$innxmit_unapproved{$key}"; + total "total(%innxmit_unapproved)"; + }; + column { + name "TooOld"; + format_name "%6s"; + format "%6d"; + value "$innxmit_tooold{$key}"; + total "total(%innxmit_tooold)"; + }; + column { + name "Site"; + format_name "%4s"; + format "%4d"; + value "$innxmit_uw_site{$key}"; + total "total(%innxmit_uw_site)"; + }; + column { + name "Line"; + format_name "%4s"; + format "%4d"; + value "$innxmit_linecount{$key}"; + total "total(%innxmit_linecount)"; + }; + column { + name "Other"; + format_name "%5s"; + format "%5d"; + value "$innxmit_others{$key}"; + total "total(%innxmit_others)"; + }; +}; + +section crosspost { + title "Crosspost stats:"; + data "%crosspost"; + column { + name "Events"; + format "%-63.63s"; + value "$key"; + format_total "TOTAL: %-56.56s"; + total "$num"; + }; + column { + name "Number"; + value "$crosspost{$key}"; + format "%7s"; + total "total(%crosspost)"; + }; + column { + name "Num/min"; + value "$crosspost_times{$key}"; + format "%7s"; + total "total(%crosspost_times)"; + }; +}; + +section batcher_elapsed { + title "UUCP batches created:"; + data "%batcher_elapsed"; + column { + name "Server"; + format "%-41.41s"; + value "$key"; + format_total "TOTAL: %-34.34s"; + total "$num"; + }; + column { + name "Offered"; + format_name "%7s"; + format "%7d"; + value "$batcher_offered{$key}"; + total "total(%batcher_offered)"; + }; + column { + name "Articles"; + format_name "%8s"; + format "%8d"; + value "$batcher_articles{$key}"; + total "total(%batcher_articles)"; + }; + column { + name "Size"; + format "%10s"; + value "bytes($batcher_bytes{$key})"; + total "bytes(total(%batcher_bytes))"; + }; + column { + name "Elapsed"; + format "%9s"; + value "time($batcher_elapsed{$key})"; + total "time(total(%batcher_elapsed))"; + }; +}; + +section rnews_host { + title "Rnews articles offered from:"; + data "%rnews_host"; + sort "$rnews_host{$b} <=> $rnews_host{$a}"; + column { + name "System"; + format "%-71.71s"; + value "$key"; + format_total "TOTAL: %-64.64s"; + total "$num"; + }; + column { + name "Offered"; + format_name "%7s"; + format "%7d"; + value "$rnews_host{$key}"; + total "total(%rnews_host)"; + }; +}; + +section rnews_rejected { + title "Rnews connections rejected:"; + data "%rnews_rejected"; + sort "$rnews_rejected{$b} <=> $rnews_rejected{$a}"; + column { + name "Reason"; + format "%-71.71s"; + value "$key"; + format_total "TOTAL: %-64.64s"; + total "$num"; + }; + column { + name "Conn"; + format_name "%7s"; + format "%7d"; + value "$rnews_rejected{$key}"; + total "total(%rnews_rejected)"; + }; +}; + +section rnews_misc { + title "Miscellaneous rnews statistics:"; + data "%rnews_misc"; + sort "$rnews_misc{$b} <=> $rnews_misc{$a}"; + double true; + column { + primary true; + name "Event"; + format "%-69.69s"; + value "$key1"; + format_total "TOTAL: %-62.62s"; + total ""; + }; + column { + name "Element"; + format " %-67.67s"; + value "$key2"; + total ""; + }; + column { + name "Number"; + format_name "%9s"; + format "%9d"; + value "$rnews_misc{$key1}{$key2}"; + total "total(%rnews_misc)"; + }; +}; + +section nnrpd_groups { + title "NNRP readership statistics:"; + data "%nnrpd_connect"; + sort "$nnrpd_articles{$b} <=> $nnrpd_articles{$a}"; + numbering true; + column { + name "System"; + format "%-30.30s"; + value "$key"; + format_total "TOTAL: %-23.23s"; + total "$num"; + }; + column { + name "Conn"; + format_name "%4s"; + format "%4d"; + value "$nnrpd_connect{$key}"; + total "total(%nnrpd_connect)"; + }; + column { + name "Arts"; + format_name "%6s"; + format "%6d"; + value "$nnrpd_articles{$key}"; + total "total(%nnrpd_articles)"; + }; + column { + name "Size"; + format "%9s"; + value "bytes($nnrpd_bytes{$key})"; + total "bytes(total(%nnrpd_bytes))"; + }; + column { + name "Groups"; + format_name "%6s"; + format "%6d"; + value "$nnrpd_groups{$key}"; + total "total(%nnrpd_groups)"; + }; + column { + name "Post"; + format_name "%4s"; + format "%4d"; + value "$nnrpd_post_ok{$key}"; + total "total(%nnrpd_post_ok)"; + }; + column { + name "Rej"; + format_name "%4s"; + format "%4d"; + value "$nnrpd_post_rej{$key} + + $nnrpd_post_error{$key}"; + total "total(%nnrpd_post_rej) + + total(%nnrpd_post_error)"; + }; + column { + name "Elapsed"; + format "%9s"; + value "time($nnrpd_times{$key})"; + total "time(total(%nnrpd_times))"; + }; +}; + +section nnrpd_dom_groups { + title "NNRP readership statistics (by domain):"; + data "%nnrpd_dom_connect"; + sort "$nnrpd_dom_articles{$b} <=> $nnrpd_dom_articles{$a}"; + numbering true; + column { + name "System"; + format "%-30.30s"; + value "$key"; + format_total "TOTAL: %-23.23s"; + total "$num"; + }; + column { + name "Conn"; + format_name "%4s"; + format "%4d"; + value "$nnrpd_dom_connect{$key}"; + total "total(%nnrpd_dom_connect)"; + }; + column { + name "Arts"; + format_name "%6s"; + format "%6d"; + value "$nnrpd_dom_articles{$key}"; + total "total(%nnrpd_dom_articles)"; + }; + column { + name "Size"; + format "%9s"; + value "bytes($nnrpd_dom_bytes{$key})"; + total "bytes(total(%nnrpd_dom_bytes))"; + }; + column { + name "Groups"; + format_name "%6s"; + format "%6d"; + value "$nnrpd_dom_groups{$key}"; + total "total(%nnrpd_dom_groups)"; + }; + column { + name "Post"; + format_name "%4s"; + format "%4d"; + value "$nnrpd_dom_post_ok{$key}"; + total "total(%nnrpd_dom_post_ok)"; + }; + column { + name "Rej"; + format_name "%4s"; + format "%4d"; + value "$nnrpd_dom_post_rej{$key} + + $nnrpd_dom_post_error{$key}"; + total "total(%nnrpd_dom_post_rej) + + total(%nnrpd_dom_post_error)"; + }; + column { + name "Elapsed"; + format "%9s"; + value "time($nnrpd_dom_times{$key})"; + total "time(total(%nnrpd_dom_times))"; + }; +}; + +section nnrpd_auth { + title "NNRP auth users:"; + data "%nnrpd_auth"; + top 20; + sort "$nnrpd_auth{$b} <=> $nnrpd_auth{$a}"; + column { + name "User"; + format "%-71.71s"; + value "$key"; + format_total "TOTAL: %-64.64s"; + total "$num"; + }; + column { + name "Conn"; + format_name "%7s"; + format "%7d"; + value "$nnrpd_auth{$key}"; + total "total(%nnrpd_auth)"; + }; +}; + +section nnrpd_resource { + title "NNRP total resource statistics:"; + data "%nnrpd_resource_elapsed"; + top 20; + sort "$nnrpd_resource_elapsed{$b} <=> $nnrpd_resource_elapsed{$a}"; + column { + name "System"; + format "%-40.40s"; + format_total "TOTAL: %-33.33s"; + value "$key"; + total "$num"; + }; + column { + name "User(ms)"; + format_name "%9s"; + format "%9.3f"; + value "$nnrpd_resource_user{$key}"; + total "total(%nnrpd_resource_user)"; + }; + column { + name "System(ms)"; + format_name "%9s"; + format "%9.3f"; + value "$nnrpd_resource_system{$key}"; + total "total(%nnrpd_resource_system)"; + }; + column { + name "Idle(ms)"; + format_name "%9s"; + format "%9.3f"; + value "$nnrpd_resource_idle{$key}"; + total "total(%nnrpd_resource_idle)"; + }; + column { + name "Elapsed"; + format_name "%8s"; + format "%9s"; + value "time($nnrpd_resource_elapsed{$key})"; + total "time(total(%nnrpd_resource_elapsed))"; + }; +}; + +section nnrpd_curious { + title "Curious NNRP server explorers:"; + data "%nnrpd_curious"; + top 20; + sort "$nnrpd_curious{$b} <=> $nnrpd_curious{$a}"; + column { + name "System"; + format "%-71.71s"; + value "$key"; + format_total "TOTAL: %-64.64s"; + total "$num"; + }; + column { + name "Conn"; + format_name "%7s"; + format "%7d"; + value "$nnrpd_curious{$key}"; + total "total(%nnrpd_curious)"; + }; +}; + +section nnrpd_no_permission { + title "NNRP no permission clients:"; + data "%nnrpd_no_permission"; + sort "$nnrpd_no_permission{$b} <=> $nnrpd_no_permission{$a}"; + column { + name "System"; + format "%-71.71s"; + value "$key"; + format_total "TOTAL: %-64.64s"; + total "$num"; + }; + column { + name "Conn"; + format_name "%7s"; + format "%7d"; + value "$nnrpd_no_permission{$key}"; + total "total(%nnrpd_no_permission)"; + }; +}; + +section nnrpd_gethostbyaddr { + title "NNRP gethostbyaddr failures:"; + data "%nnrpd_gethostbyaddr"; + top 20; + sort "$nnrpd_gethostbyaddr{$b} <=> $nnrpd_gethostbyaddr{$a}"; + column { + name "System"; + format "%-71.71s"; + value "$key"; + format_total "TOTAL: %-64.64s"; + total "$num"; + }; + column { + name "Conn"; + format_name "%7s"; + format "%7d"; + value "$nnrpd_gethostbyaddr{$key}"; + total "total(%nnrpd_gethostbyaddr)"; + }; +}; + +section nnrpd_unrecognized { + title "NNRP unrecognized commands (by host):"; + data "%nnrpd_unrecognized"; + sort "$nnrpd_unrecognized{$b} <=> $nnrpd_unrecognized{$a}"; + column { + name "System"; + format "%-71.71s"; + value "$key"; + format_total "TOTAL: %-64.64s"; + total "$num"; + }; + column { + name "Conn"; + format_name "%7s"; + format "%7d"; + value "$nnrpd_unrecognized{$key}"; + total "total(%nnrpd_unrecognized)"; + }; +}; + +section nnrpd_unrecognized2 { + title "NNRP unrecognized commands (by command):"; + data "%nnrpd_unrecogn_cmd"; + sort "$nnrpd_unrecogn_cmd{$b} <=> $nnrpd_unrecogn_cmd{$a}"; + column { + name "Command"; + format "%-71.71s"; + value "$key"; + format_total "TOTAL: %-64.64s"; + total "$num"; + }; + column { + name "Count"; + format_name "%7s"; + format "%7d"; + value "$nnrpd_unrecogn_cmd{$key}"; + total "total(%nnrpd_unrecogn_cmd)"; + }; +}; + +section nnrpd_timeout { + title "NNRP client timeouts:"; + data "%nnrpd_timeout"; + top 20; + sort "$nnrpd_timeout{$b} <=> $nnrpd_timeout{$a}"; + column { + name "System"; + format "%-67.67s"; + value "$key"; + format_total "TOTAL: %-60.60s"; + total "$num"; + }; + column { + name "Conn"; + format_name "%5s"; + format "%5d"; + value "$nnrpd_timeout{$key}"; + total "total(%nnrpd_timeout)"; + }; + column { + name "Peer"; + format_name "%5s"; + format "%5d"; + value "$nnrpd_reset_peer{$key}"; + total "total(%nnrpd_reset_peer)"; + }; +}; + +section nnrpd_hierarchy { + title "Newsgroup request counts (by category):"; + data "%nnrpd_hierarchy"; + sort "$nnrpd_hierarchy{$b} <=> $nnrpd_hierarchy{$a}"; + numbering true; + column { + name "Category"; + format "%-64.64s"; + value "$key"; + format_total "TOTAL: %-57.57s"; + total "$num"; + }; + column { + name "Count"; + format_name "%7s"; + format "%7d"; + value "$nnrpd_hierarchy{$key}"; + total "total(%nnrpd_hierarchy)"; + }; + column { + name "Pct"; + format_name "%6s"; + format "%5.1f%%"; + value "$nnrpd_hierarchy{$key} / + total(%nnrpd_hierarchy) * 100"; + total "100"; + }; + # graph : type piechart +}; + +section nnrpd_group { + title "Newsgroup request counts (by newsgroup):"; + data "%nnrpd_group"; + sort "$nnrpd_group{$b} <=> $nnrpd_group{$a}"; + top 100; + numbering true; + column { + name "Newsgroup"; + format "%-71.71s"; + value "$key"; + format_total "TOTAL: %-64.64s"; + total "$num"; + }; + column { + name "Count"; + format_name "%7s"; + format "%7d"; + value "$nnrpd_group{$key}"; + total "total(%nnrpd_group)"; + }; +}; + +section ihave_site { + title "IHAVE messages offered from:"; + data "%controlchan_ihave_site"; + sort "$controlchan_ihave_site{$b} <=> $controlchan_ihave_site{$a}"; + column { + name "System"; + format "%-71.71s"; + value "$key"; + format_total "TOTAL: %-64.64s"; + total "$num"; + }; + column { + name "Offered"; + format_name "%7s"; + format "%7d"; + value "$controlchan_ihave_site{$key}"; + total "total(%controlchan_ihave_site)"; + }; +}; + +section sendme_site { + title "SENDME messages offered from:"; + data "%controlchan_sendme_site"; + sort "$controlchan_sendme_site{$b} <=> + $controlchan_sendme_site{$a}"; + column { + name "System"; + format "%-71.71s"; + value "$key"; + format_total "TOTAL: %-64.64s"; + total "$num"; + }; + column { + name "Offered"; + format_name "%7s"; + format "%7d"; + value "$controlchan_sendme_site{$key}"; + total "total(%controlchan_sendme_site)"; + }; +}; --- inn-1.7.2q.orig/extra/etc/newsfeeds +++ inn-1.7.2q/extra/etc/newsfeeds @@ -0,0 +1,80 @@ +## $Revision: 1.2 $ +## newsfeeds - determine where Usenet articles get sent +## Format: +## site[/exclude,exclude...]\ +## :pattern,pattern...[/distrib,distrib...]\ +## :flag,flag...\ +## :param +## Summary of flags: +## .*" +## there. The "distrib" subfield limits incoming articles. +## +## You can also have ME/bad.site: to refuse articles from a particular +## site (by matching the Path: entry). Other pseudo-sites may be put +## in here, to REFUSE certain types of 3rd-party cancel messages +## (See the "Cancel FAQ" news.admin.net-abuse.misc): +## cyberspam Spam cancels, munged articles, binary postings +## spewcancel just munged articles from runaway gateways +## bincancel just binary postings to non-binaries groups +## +## Note that refusing articles means you won't offer them to sites you feed +## +ME:*,!control,!junk,!local.*/!local:: + +overview:*,!control.cancel:Tc,WO:/usr/lib/news/bin/overchan + +## The most often used type entries: uncomment and adjust. + +# Feed all local non-internal postings to news.myprovider.com; sent off-line +# via nntpsend, send-nntp, or send-uucp.pl. Also, enable the entry in the +# crontab file to regulary actually send all batched articles. +# +# If you're not low on memory use innfeed. +# +#news.myprovider.com\ +# :*,!junk/!local\ +# :Tf,Wnm:news.myprovider.com + +# An innfeed example. First, define several peers like this +# (the primary name needs to be the hostname of the peer). +# +#news.uu.net/uunet\ +# :*/!local\ +# :Tm:innfeed! +# +# Then define one "master" entry that connects to all the peers: +#innfeed!:!*:Tc,Wnm*:/usr/sbin/innfeed -y + +## Create the links for cross posted articles +#crosspost:*:Tc,Ap,WR:/usr/lib/news/bin/crosspost + --- inn-1.7.2q.orig/extra/etc/send-uucp.cf +++ inn-1.7.2q/extra/etc/send-uucp.cf @@ -0,0 +1,26 @@ +# +# send-uucp.cf Configuration file for send-uucp +# +# Format: sitenamecompressormaxsizebatchtime +# +# compressor, maxsize and batchtime can be left out and will +# then use the # default values. You can't leave out the second +# field (compressor) and still use the third (maxsize) etc.! +# So if you want to set a maxsize, you HAVE to add a +# compression method. +# +# Compress keywords are: compress gzip none +# +# You can use flags with your compressor, just add them. Use +# the `_' character instead of a space. +# For example compress_-b13 for 13 bits compression. +# +# Remember that the size you set is the size *before* compression! +# +#zoetermeer gzip 1048576 5,18,22 +#hoofddorp gzip 1048576 5,18,22 +#pa3ebv gzip 1048576 5,18,22 +#drinkel gzip 1048576 5,6,18,20,22,0,2 +#manhole compress 1048576 5,18,22 +#owl compress 1048576 5,18,22 +#able compress 1048576 5,18,22 --- inn-1.7.2q.orig/extra/etc/control.ctl +++ inn-1.7.2q/extra/etc/control.ctl @@ -0,0 +1,2616 @@ +## control.ctl - Access control for control messages. +## Last modified: 2009-08-04 +## +## Based on rone's unified control.ctl file. +## +## For a web presentation of the information recorded here, as well as +## other useful information about Usenet hierarchies, please see: +## +## +## +## Please copy usenet-config@isc.org on any updates to this file so that +## it can be updated in the INN Subversion repository and on ftp.isc.org. +## For changes to a public hierarchy, please also post the changes to +## news.admin.hierarchies. +## +## The canonical version of this file can be found in the latest INN +## release and at ; these +## two files will be kept in sync. Please refer to the latest version of +## this file for the most up-to-date hierarchy control information and +## please use the latest version if you intend to carry all hierarchies. +## +## You may wish to review and change the policy for alt.*, free.*, +## it-alt.*, and oesterreich.* below before using this file on your +## server. +## +## Format: +## ::: +## +## Control message or "all" if it applies to all control +## messages. +## Pattern that must match the From line. +## Pattern that must match the newsgroup being newgroup'd +## or rmgroup'd (ignored for other messages). +## What to do: +## doit Perform action +## drop Ignore message +## log One line to error log +## mail Send mail to admin +## verify-pgp_userid Do PGP verification on user. +## All actions except drop and mail can be given a log +## location by following the action with an = and the +## log ("mail" says to mail the admin, an empty location +## tosses the log information, and a relative path xxx +## logs to $LOG/xxx.log). +## +## The *last* matching entry is used. See the expire.ctl(5) man page for +## complete information. +## +## This file follows the following policies: +## +## * Most unknown or invalid control messages no longer result in mail. +## This is due to the proliferation of forged control messages filling +## up mailboxes. Some news servers even get overwhelmed with trying to +## log failure, so unsigned control messages for hierarchies that use +## PGP are simply dropped. +## +## * The assumption is that you now have PGP on your system. If you +## don't, you should get it to help protect yourself against all the +## control message forgeries. See . +## PGP control message verification comes with all versions of INN since +## 1.5, but you will need to install either PGP or GnuPG; see the +## installation instructions for your news server. +## +## If for some reason you can't use PGP, search for the *PGP* comments +## and modify the control lines to change "verify-..." in the action +## field to "mail" or "doit=mail" or "doit=" or whatever you +## prefer (replacing with the name of an appropriate log +## file). +## +## * A number of hierarchies are for local use only but have leaked out +## into the general stream. In this config file, they are set so that +## the groups will be easy to remove, and are marked with a comment of +## *LOCAL* (for use by that organization only, not generally +## distributed), *DEFUNCT* (a hierarchy that's no longer used), or +## *PRIVATE* (should only be carried after making arrangements with the +## given contact address). Please delete all groups in those +## hierarchies from your server if you carry them, unless you've +## contacted the listed contact address and arranged a feed. +## +## If you have permission to carry any of the hierarchies so listed in +## this file, you should change the entries for those hierarchies +## below. +## +## * Some hierarchies are marked as *HISTORIC*. These hierarchies +## aren't entirely defunct, but they are very low-traffic, not widely +## read or carried, and may not be worth carrying. If you don't intend +## to carry them, comment out their entries. +## +## The comments of this file aren't in any formal or well-defined syntax, +## but they are meant to use a consistent syntax to allow eventual parsing +## by scripts into a better database format. Please follow the syntax of +## existing entries when providing new ones. The recognized "fields" are +## Contact (contact e-mail address), Admin group (the administrative group +## for the hierarchy), URL, Key URL (URL for PGP key), Key fingerprint, Key +## mail (address to mail for PGP key), and Syncable server (for actsync or +## a similar tool). +## +## Names used in this file that cannot be encoded in 7bit ASCII are in +## UTF-8. The only non-7bit-ASCII content is in comments. + +## ------------------------------------------------------------------------- +## DEFAULT +## ------------------------------------------------------------------------- + +# Default to dropping control messages that aren't recognized to allow +# people to experiment without inadvertently mailbombing news admins. +all:*:*:drop + +## ------------------------------------------------------------------------- +## CHECKGROUPS MESSAGES +## ------------------------------------------------------------------------- + +# Default to mailing all checkgroups messages to the administrator. +checkgroups:*:*:mail + +## ------------------------------------------------------------------------- +## MISCELLANEOUS CONTROL MESSAGES +## ------------------------------------------------------------------------- + +# Mostly only used for UUCP feeds, very rarely used these days. +ihave:*:*:drop +sendme:*:*:drop + +# Request to send a copy of the newsfeeds file, intended for mapping +# projects. Almost never used for anything other than mailbombing now. +sendsys:*:*:log=sendsys + +# Request to send the server's path entry. Not particularly useful. +senduuname:*:*:log=senduuname + +# Request to send the server's version number. +version:*:*:log=version + +## ------------------------------------------------------------------------- +## NEWGROUP/RMGROUP MESSAGES +## ------------------------------------------------------------------------- + +## Default (for any group) +newgroup:*:*:mail +rmgroup:*:*:mail + +## A.BSU (*DEFUNCT* -- Ball State University, USA) +# This hierarchy is defunct. Please remove it. +newgroup:*:a.bsu.*:mail +rmgroup:*:a.bsu.*:doit + +## ACS & OSU (*LOCAL* -- Ohio State University, USA) +# Contact: Albert J. School +# Contact: Harpal Chohan +# For local use only, contact the above address for information. +newgroup:*:acs.*|osu.*:mail +rmgroup:*:acs.*|osu.*:doit + +## ADASS (Astronomical Data Analysis Software and Systems) +# URL: http://iraf.noao.edu/iraf/web/adass_news.html +checkgroups:news@iraf.noao.edu:adass.*:doit +newgroup:news@iraf.noao.edu:adass.*:doit +rmgroup:news@iraf.noao.edu:adass.*:doit + +## AHN (Athens-Clarke County, Georgia, USA) +checkgroups:greg@*.ucns.uga.edu:ahn.*:doit +newgroup:greg@*.ucns.uga.edu:ahn.*:doit +rmgroup:greg@*.ucns.uga.edu:ahn.*:doit + +## AIOE (Aioe.org) +# Contact: usenet@aioe.org +# URL: http://news.aioe.org/hierarchy/ +# Admin group: aioe.system +# Key URL: http://news.aioe.org/hierarchy/aioe.txt +# Key fingerprint = 2203 1AAC 51E7 C7FD 664F 1D80 90DF 6C71 2322 A7F8 +# Syncable server: nntp.aioe.org +# *PGP* See comment at top of file. +newgroup:*:aioe.*:drop +rmgroup:*:aioe.*:drop +checkgroups:usenet@aioe.org:aioe.*:verify-usenet@aioe.org +newgroup:usenet@aioe.org:aioe.*:verify-usenet@aioe.org +rmgroup:usenet@aioe.org:aioe.*:verify-usenet@aioe.org + +## AIR (*DEFUNCT* -- Stanford University, USA) +# Contact: news@news.stanford.edu +# This hierarchy is defunct. Please remove it. +newgroup:*:air.*:mail +rmgroup:*:air.*:doit + +## AKR (Akron, Ohio, USA) +checkgroups:red@redpoll.mrfs.oh.us:akr.*:doit +newgroup:red@redpoll.mrfs.oh.us:akr.*:doit +rmgroup:red@redpoll.mrfs.oh.us:akr.*:doit + +## ALABAMA & HSV (Huntsville, Alabama, USA) +# Contact: jpc@suespammers.org +# Admin group: alabama.config +# *PGP* See comment at top of file. +newgroup:*:alabama.*|hsv.*:drop +rmgroup:*:alabama.*|hsv.*:drop +checkgroups:jpc@suespammers.org:alabama.*|hsv.*:verify-alabama-group-admin +newgroup:jpc@suespammers.org:alabama.*|hsv.*:verify-alabama-group-admin +rmgroup:jpc@suespammers.org:alabama.*|hsv.*:verify-alabama-group-admin + +## ALIVE (*DEFUNCT* -- ?) +# Contact: thijs@kink.xs4all.nl +# This hierarchy is defunct. Please remove it. +newgroup:*:alive.*:mail +rmgroup:*:alive.*:doit + +## ALT +# +# Accept all newgroups (except ones forged from Big 8 newgroup issuers, +# who never issue alt.* control messages) and silently ignore all +# rmgroups. +# +# What policy to use for alt.* groups varies widely from site to site. +# For a small site, it is strongly recommended that this policy be changed +# to drop all newgroups and rmgroups for alt.*. The local news admin can +# then add new alt.* groups only on user request. Tons of alt.* newgroups +# are sent out regularly with the intent more to create nonsense entries +# in active files than to actually create a useable newsgroup. The admin +# may still want to check the control message archive, as described below. +# +# Quality, user-desirable new groups can often be discovered by a quick +# perusal of recent alt.* newgroup messages after discarding obvious junk +# groups. One good initial filter is to check the archive of control +# messages for a requested group to see if a syntactically valid newgroup +# message was issued. Many of the junk control messages are invalid and +# won't be archived, and many sites will only add alt.* groups with valid +# control messages. To check the archive, see if: +# +# ftp://ftp.isc.org/pub/usenet/control/alt/.gz +# +# exists (replacing with the name of the group) and read the +# first and last few control messages to see if the newsgroup should be +# moderated. (Some alt.* groups that should be moderated are created +# unmoderated by hijackers to try to damage the newsgroup.) +# +# Be aware that there is no official, generally accepted alt.* policy and +# all information about alt.* groups available is essentially someone's +# opinion, including these comments. There are nearly as many different +# policies with regard to alt.* groups as there are Usenet sites. +# +newgroup:*:alt.*:doit +newgroup:group-admin@isc.org:alt.*:drop +newgroup:tale@*uu.net:alt.*:drop +rmgroup:*:alt.*:drop + +## AR (Argentina) +checkgroups:jorge_f@nodens.fisica.unlp.edu.ar:ar.*:doit +newgroup:jorge_f@nodens.fisica.unlp.edu.ar:ar.*:doit +rmgroup:jorge_f@nodens.fisica.unlp.edu.ar:ar.*:doit + +## ARC (*LOCAL* -- NASA Ames Research Center, USA) +# Contact: news@arc.nasa.gov +# For local use only, contact the above address for information. +newgroup:*:arc.*:mail +rmgroup:*:arc.*:doit + +## ARKANE (Arkane Systems, UK) +# Contact: newsbastard@arkane.demon.co.uk +checkgroups:newsbastard@arkane.demon.co.uk:arkane.*:doit +newgroup:newsbastard@arkane.demon.co.uk:arkane.*:doit +rmgroup:newsbastard@arkane.demon.co.uk:arkane.*:doit + +## AT (Austria) +# URL: http://www.usenet.at/ +# Admin group: at.usenet.gruppen +# Key URL: http://www.usenet.at/pgpkey.asc +# *PGP* See comment at top of file. +newgroup:*:at.*:drop +rmgroup:*:at.*:drop +checkgroups:control@usenet.backbone.at:at.*:verify-control@usenet.backbone.at +newgroup:control@usenet.backbone.at:at.*:verify-control@usenet.backbone.at +rmgroup:control@usenet.backbone.at:at.*:verify-control@usenet.backbone.at + +## AUS (Australia) +# Contact: ausadmin@aus.news-admin.org +# URL: http://aus.news-admin.org/ +# Admin group: aus.net.news +# Key URL: http://aus.news-admin.org/ausadmin.asc +# *PGP* See comment at top of file. +newgroup:*:aus.*:drop +rmgroup:*:aus.*:drop +checkgroups:ausadmin@aus.news-admin.org:aus.*:verify-ausadmin@aus.news-admin.org +newgroup:ausadmin@aus.news-admin.org:aus.*:verify-ausadmin@aus.news-admin.org +rmgroup:ausadmin@aus.news-admin.org:aus.*:verify-ausadmin@aus.news-admin.org + +## AUSTIN (Austin, Texas, USA) +# URL: http://frenzy.austin.tx.us/austin/ +# Admin group: austin.usenet.config +checkgroups:chip@unicom.com:austin.*:doit +checkgroups:fletcher@cs.utexas.edu:austin.*:doit +checkgroups:pug@pug.net:austin.*:doit +newgroup:chip@unicom.com:austin.*:doit +newgroup:fletcher@cs.utexas.edu:austin.*:doit +newgroup:pug@pug.net:austin.*:doit +rmgroup:chip@unicom.com:austin.*:doit +rmgroup:fletcher@cs.utexas.edu:austin.*:doit +rmgroup:pug@pug.net:austin.*:doit + +## AZ (Arizona, USA) +checkgroups:system@asuvax.eas.asu.edu:az.*:doit +newgroup:system@asuvax.eas.asu.edu:az.*:doit +rmgroup:system@asuvax.eas.asu.edu:az.*:doit + +## BA (San Francisco Bay Area, USA) +# Contact: ba-mod@nas.nasa.gov +# URL: http://ennui.org/ba/ +# Admin group: ba.news.config +# Key URL: http://ennui.org/ba/ba-mod.asc +# *PGP* See comment at top of file. +newgroup:*:ba.*:drop +rmgroup:*:ba.*:drop +checkgroups:ba-mod@nas.nasa.gov:ba.*:verify-ba.news.config +newgroup:ba-mod@nas.nasa.gov:ba.*:verify-ba.news.config +rmgroup:ba-mod@nas.nasa.gov:ba.*:verify-ba.news.config + +## BACKBONE (*LOCAL* -- ruhr.de/ruhrgebiet.individual.net in Germany) +# Contact: admin@ruhr.de +# For local use only, contact the above address for information. +newgroup:*:backbone.*:mail +rmgroup:*:backbone.*:doit + +## BC (British Columbia, Canada) +checkgroups:bc_van_usenet@fastmail.ca:bc.*:doit +newgroup:bc_van_usenet@fastmail.ca:bc.*:doit +rmgroup:bc_van_usenet@fastmail.ca:bc.*:doit + +## BDA (German groups?) +checkgroups:news@*netuse.de:bda.*:doit +newgroup:news@*netuse.de:bda.*:doit +rmgroup:news@*netuse.de:bda.*:doit + +## BE (Belgique/Belgie/Belgien/Belgium) +# Contact: be-hierarchy-admin@usenet.be +# URL: http://usenet.be/ +# Admin group: be.announce +# Key URL: http://usenet.be/be.announce.newgroups.asc +# Key fingerprint = 30 2A 45 94 70 DE 1F D5 81 8C 58 64 D2 F7 08 71 +# *PGP* See comment at top of file. +newgroup:*:be.*:drop +rmgroup:*:be.*:drop +checkgroups:group-admin@usenet.be:be.*:verify-be.announce.newgroups +newgroup:group-admin@usenet.be:be.*:verify-be.announce.newgroups +rmgroup:group-admin@usenet.be:be.*:verify-be.announce.newgroups + +## BELWUE (Baden-Wuerttemberg, Germany) +# Admin group: belwue.infos +# *PGP* See comment at top of file. +newgroup:*:belwue.*:drop +rmgroup:*:belwue.*:drop +checkgroups:news@news.belwue.de:belwue.*:verify-belwue-hir-control +newgroup:news@news.belwue.de:belwue.*:verify-belwue-hir-control +rmgroup:news@news.belwue.de:belwue.*:verify-belwue-hir-control + +## BERMUDA (Bermuda) +checkgroups:news@*ibl.bm:bermuda.*:doit +newgroup:news@*ibl.bm:bermuda.*:doit +rmgroup:news@*ibl.bm:bermuda.*:doit + +## BES (*PRIVATE* -- Beijing Electron Spectrometer) +# Contact: news@news.stanford.edu +# For private use only, contact the above address for information. +newgroup:news@news.stanford.edu:bes.*:mail +rmgroup:news@news.stanford.edu:bes.*:doit + +## BEST (*LOCAL* -- Best Internet Communications, Inc.) +# Contact: news@best.net +# For local use only, contact the above address for information. +newgroup:*:best.*:mail +rmgroup:*:best.*:doit + +## BIONET (Biology Network) +# URL: http://www.bio.net/ +# Admin group: bionet.general +# Key fingerprint = EB C0 F1 BA 26 0B C6 D6 FB 8D ED C4 AE 5D 10 54 +# *PGP* See comment at top of file. +newgroup:*:bionet.*:drop +rmgroup:*:bionet.*:drop +checkgroups:Biosci-control-key@net.bio.net:bionet.*:verify-Biosci-control-key@net.bio.net +newgroup:Biosci-control-key@net.bio.net:bionet.*:verify-Biosci-control-key@net.bio.net +rmgroup:Biosci-control-key@net.bio.net:bionet.*:verify-Biosci-control-key@net.bio.net + +## BIRK (*LOCAL* -- University of Oslo, Norway) +# Contact: birk-admin@ping.uio.no +# For local use only, contact the above address for information. +newgroup:*:birk.*:mail +rmgroup:*:birk.*:doit + +## BIT (Gatewayed Mailing lists) +# URL: http://www.newsadmin.com/bit/bit.htm +# Admin group: bit.admin +# *PGP* See comment at top of file. +newgroup:*:bit.*:drop +rmgroup:*:bit.*:drop +checkgroups:bit@newsadmin.com:bit.*:verify-bit@newsadmin.com +newgroup:bit@newsadmin.com:bit.*:verify-bit@newsadmin.com +rmgroup:bit@newsadmin.com:bit.*:verify-bit@newsadmin.com + +## BIZ (Business Groups) +checkgroups:edhew@xenitec.on.ca:biz.*:doit +newgroup:edhew@xenitec.on.ca:biz.*:doit +rmgroup:edhew@xenitec.on.ca:biz.*:doit + +## BLGTN (Bloomington, In, USA) +checkgroups:control@news.bloomington.in.us:blgtn.*:doit +newgroup:control@news.bloomington.in.us:blgtn.*:doit +rmgroup:control@news.bloomington.in.us:blgtn.*:doit + +## BLN (Berlin, Germany) +checkgroups:news@*fu-berlin.de:bln.*:doit +newgroup:news@*fu-berlin.de:bln.*:doit +rmgroup:news@*fu-berlin.de:bln.*:doit + +## BNE (Brisbane, Australia) +# Contact: ausadmin@aus.news-admin.org +# URL: http://bne.news-admin.org/ +# Key URL: http://aus.news-admin.org/ausadmin.asc +# *PGP* See comment at top of file. +newgroup:*:bne.*:drop +rmgroup:*:bne.*:drop +checkgroups:ausadmin@aus.news-admin.org:bne.*:verify-ausadmin@aus.news-admin.org +newgroup:ausadmin@aus.news-admin.org:bne.*:verify-ausadmin@aus.news-admin.org +rmgroup:ausadmin@aus.news-admin.org:bne.*:verify-ausadmin@aus.news-admin.org + +## BOFH (*PRIVATE* -- Bastard Operator From Hell) +# Contact: myname@myhost.mydomain.com +# For private use only, contact the above address for information. +newgroup:*:bofh.*:mail +rmgroup:*:bofh.*:doit + +## CA (California, USA) +# Contact: ikluft@thunder.sbay.org +# URL: http://www.sbay.org/ca/ +checkgroups:ikluft@thunder.sbay.org:ca.*:doit +newgroup:ikluft@thunder.sbay.org:ca.*:doit +rmgroup:ikluft@thunder.sbay.org:ca.*:doit + +## CAIS (*LOCAL* -- Capital Area Internet Services) +# Contact: news@cais.com +# For local use only, contact the above address for information. +newgroup:*:cais.*:mail +rmgroup:*:cais.*:doit + +## CALSTATE (California State University) +checkgroups:*@*calstate.edu:calstate.*:doit +newgroup:*@*calstate.edu:calstate.*:doit +rmgroup:*@*calstate.edu:calstate.*:doit + +## CANB (Canberra, Australia) +# Contact: ausadmin@aus.news-admin.org +# URL: http://canb.news-admin.org/ +# Key URL: http://aus.news-admin.org/ausadmin.asc +# *PGP* See comment at top of file. +newgroup:*:canb.*:drop +rmgroup:*:canb.*:drop +checkgroups:ausadmin@aus.news-admin.org:canb.*:verify-ausadmin@aus.news-admin.org +newgroup:ausadmin@aus.news-admin.org:canb.*:verify-ausadmin@aus.news-admin.org +rmgroup:ausadmin@aus.news-admin.org:canb.*:verify-ausadmin@aus.news-admin.org + +## CAPDIST (Albany, The Capital District, New York, USA) +checkgroups:danorton@albany.net:capdist.*:doit +newgroup:danorton@albany.net:capdist.*:doit +rmgroup:danorton@albany.net:capdist.*:doit + +## CARLETON (Carleton University, Canada) +newgroup:news@cunews.carleton.ca:carleton.*:doit +newgroup:news@cunews.carleton.ca:carleton*class.*:mail +rmgroup:news@cunews.carleton.ca:carleton.*:doit + +## CD-ONLINE (*LOCAL* -- ?) +# Contact: newsmaster@worldonline.nl +# For local use only, contact the above address for information. +newgroup:*:cd-online.*:mail +rmgroup:*:cd-online.*:doit + +## CENTRAL (*LOCAL* -- The Internet Company of New Zealand, Wellington, NZ) +# Contact: usenet@iconz.co.nz +# For local use only, contact the above address for information. +newgroup:*:central.*:mail +rmgroup:*:central.*:doit + +## CERN (*PRIVATE* -- CERN European Laboratory for Particle Physics) +# Contact: Dietrich Wiegandt +# For private use only, contact the above address for information. +newgroup:News.Support@cern.ch:cern.*:mail +rmgroup:News.Support@cern.ch:cern.*:doit + +## CH (Switzerland) +# Contact: ch-news-admin@use-net.ch +# URL: http://www.use-net.ch/Usenet/ +# Key URL: http://www.use-net.ch/Usenet/adminkey.html +# Key fingerprint = 71 80 D6 8C A7 DE 2C 70 62 4A 48 6E D9 96 02 DF +# *PGP* See comment at top of file. +newgroup:*:ch.*:drop +rmgroup:*:ch.*:drop +checkgroups:felix.rauch@nice.ch:ch.*:verify-ch-news-admin@use-net.ch +newgroup:felix.rauch@nice.ch:ch.*:verify-ch-news-admin@use-net.ch +rmgroup:felix.rauch@nice.ch:ch.*:verify-ch-news-admin@use-net.ch + +## CHAVEN (*LOCAL* -- Celestian Haven ISP, Midwest, USA) +# Contact: news@chaven.com +# For local use only, contact the above address for information. +newgroup:*:chaven.*:mail +rmgroup:*:chaven.*:doit + +## CHI (Chicago, USA) +# URL: http://lull.org/pub/chi-newsgroup-faq +checkgroups:lisbon@*chi.il.us:chi.*:doit +newgroup:lisbon@*chi.il.us:chi.*:doit +rmgroup:lisbon@*chi.il.us:chi.*:doit + +## CHILE (Chile and Chilean affairs) +# Contact: mod-cga@usenet.cl +# URL: http://www.usenet.cl/ +# Admin group: chile.grupos.anuncios +checkgroups:mod-cga@*lj.cl:chile.*:doit +newgroup:mod-cga@*lj.cl:chile.*:doit +rmgroup:mod-cga@*lj.cl:chile.*:doit + +## CHINESE (China and Chinese language groups) +checkgroups:pinghua@stat.berkeley.edu:chinese.*:doit +newgroup:pinghua@stat.berkeley.edu:chinese.*:doit +rmgroup:pinghua@stat.berkeley.edu:chinese.*:doit + +## CHRISTNET (Christian Discussion) +checkgroups:news@fdma.com:christnet.*:doit +newgroup:news@fdma.com:christnet.*:doit +rmgroup:news@fdma.com:christnet.*:doit + +## CL (*PRIVATE* -- CL-Netz, German) +# Contact: koordination@cl-netz.de +# URL: http://www.cl-netz.de/ +# Key URL: http://www.cl-netz.de/control.txt +# For private use only, contact above address for questions. +# *PGP* See comment at top of file. +newgroup:*:cl.*:drop +rmgroup:*:cl.*:doit +# The following three lines are only for authorized cl.* sites. +#checkgroups:koordination@cl-netz.de:cl.*:verify-cl.netz.infos +#newgroup:koordination@cl-netz.de:cl.*:verify-cl.netz.infos +#rmgroup:koordination@cl-netz.de:cl.*:verify-cl.netz.infos + +## CLARI (*PRIVATE* -- Features and News, available on a commercial basis) +# Contact: support@clari.net +# Admin group: clari.net.admin +# Key URL: http://www.clari.net/tech/clarikey.txt +# For private use only, contact the above address for information. +# *PGP* See comment at top of file. +newgroup:*:clari.*:drop +rmgroup:*:clari.*:drop +newgroup:cl*@clarinet.com:clari.*:mail +rmgroup:cl*@clarinet.com:clari.*:verify-ClariNet.Group + +## CMI (*LOCAL* -- Champaign County, IL, USA) +# Contact: news@ks.uiuc.edu +# For local use only, contact the above address for information. +newgroup:*:cmi.*:mail +rmgroup:*:cmi.*:doit + +## CMU (*LOCAL* -- Carnegie-Mellon University, Pennsylvania, USA) +# Contact: Daniel Edward Lovinger +# For local use only, contact the above address for information. +newgroup:*:cmu.*:mail +rmgroup:*:cmu.*:doit + +## CN (China) +# URL: http://news.yaako.com/ +# Admin group: cn.announce +# Key fingerprint = 62 97 EE 33 F7 16 25 C1 A4 9E 47 BA C5 3E 5E 9E +# *PGP* See comment at top of file. +newgroup:*:cn.*:drop +rmgroup:*:cn.*:drop +checkgroups:control@bentium.com:cn.*:verify-cn.admin.news.announce +newgroup:control@bentium.com:cn.*:verify-cn.admin.news.announce +rmgroup:control@bentium.com:cn.*:verify-cn.admin.news.announce + +## CN.BBS (China) +# URL: http://bbs.cn.news-admin.org/ +# Admin group: cn.bbs.admin.announce +# *PGP* See comment at top of file. +newgroup:*:cn.bbs.*:drop +rmgroup:*:cn.bbs.*:drop +checkgroups:control@cn-bbs.org:cn.bbs.*:verify-cn.bbs.admin.announce +newgroup:control@cn-bbs.org:cn.bbs.*:verify-cn.bbs.admin.announce +rmgroup:control@cn-bbs.org:cn.bbs.*:verify-cn.bbs.admin.announce + +## CO (Colorado, USA) +# Contact: coadmin@boyznoyz.com (Bill of Denver) +checkgroups:coadmin@boyznoyz.com:co.*:doit +newgroup:coadmin@boyznoyz.com:co.*:doit +rmgroup:coadmin@boyznoyz.com:co.*:doit + +## CODEWARRIOR (CodeWarrior discussion) +checkgroups:news@supernews.net:codewarrior.*:doit +newgroup:news@supernews.net:codewarrior.*:doit +rmgroup:news@supernews.net:codewarrior.*:doit + +## COMP, HUMANITIES, MISC, NEWS, REC, SCI, SOC, TALK (The Big Eight) +# Contact: board@big-8.org +# URL: http://www.big-8.org/ +# Admin group: news.announce.newgroups +# Key fingerprint = F5 35 58 D3 55 64 10 14 07 C6 95 53 13 6F D4 07 +# *PGP* See comment at top of file. +newgroup:*:comp.*|humanities.*|misc.*|news.*|rec.*|sci.*|soc.*|talk.*:drop +rmgroup:*:comp.*|humanities.*|misc.*|news.*|rec.*|sci.*|soc.*|talk.*:drop +checkgroups:group-admin@isc.org:comp.*|humanities.*|misc.*|news.*|rec.*|sci.*|soc.*|talk.*:verify-news.announce.newgroups +newgroup:group-admin@isc.org:comp.*|humanities.*|misc.*|news.*|rec.*|sci.*|soc.*|talk.*:verify-news.announce.newgroups +rmgroup:group-admin@isc.org:comp.*|humanities.*|misc.*|news.*|rec.*|sci.*|soc.*|talk.*:verify-news.announce.newgroups + +## COMPUTER42 (Computer 42, Germany) +# Contact: Dirk Schmitt +checkgroups:news@computer42.org:computer42.*:doit +newgroup:news@computer42.org:computer42.*:doit +rmgroup:news@computer42.org:computer42.*:doit + +## CONCORDIA (Concordia University, Montreal, Canada) +# Contact: newsmaster@concordia.ca +# URL: General University info at http://www.concordia.ca/ +checkgroups:news@newsflash.concordia.ca:concordia.*:doit +newgroup:news@newsflash.concordia.ca:concordia.*:doit +rmgroup:news@newsflash.concordia.ca:concordia.*:doit + +## COURTS (*DEFUNCT* -- Court discussion) +# Contact: trier@ins.cwru.edu +# This hierarchy is defunct. Please remove it. +newgroup:*:courts.*:mail +rmgroup:*:courts.*:doit + +## CPCUIIA (Chartered Prop. Casulty Underwriter/Insurance Institute of America) +# Contact: miller@cpcuiia.org +# URL: http://www.aicpcu.org/ +checkgroups:miller@cpcuiia.org:cpcuiia.*:doit +newgroup:miller@cpcuiia.org:cpcuiia.*:doit +rmgroup:miller@cpcuiia.org:cpcuiia.*:doit + +## CU (*LOCAL* -- University of Colorado) +# Contact: Doreen Petersen +# For local use only, contact the above address for information. +newgroup:*:cu.*:mail +rmgroup:*:cu.*:doit + +## CUHK (*LOCAL* -- Chinese University of Hong Kong) +# Contact: shlam@ie.cuhk.edu.hk (Alan S H Lam) +# For local use only, contact the above address for information. +newgroup:*:cuhk.*:mail +rmgroup:*:cuhk.*:doit + +## CZ (Czech Republic) +# URL: ftp://ftp.vslib.cz/pub/news/config/cz/newsgroups (text) +checkgroups:petr.kolar@vslib.cz:cz.*:doit +newgroup:petr.kolar@vslib.cz:cz.*:doit +rmgroup:petr.kolar@vslib.cz:cz.*:doit + +## DC (Washington, D.C., USA) +checkgroups:news@mattress.atww.org:dc.*:doit +newgroup:news@mattress.atww.org:dc.*:doit +rmgroup:news@mattress.atww.org:dc.*:doit + +## DE (German language) +# Contact: moderator@dana.de +# URL: http://www.dana.de/mod/ +# Admin group: de.admin.news.announce +# Key URL: http://www.dana.de/mod/pgp/dana.asc +# Key fingerprint = 5B B0 52 88 BF 55 19 4F 66 7D C2 AE 16 26 28 25 +# *PGP* See comment at top of file. +newgroup:*:de.*:drop +rmgroup:*:de.*:drop +checkgroups:moderator@dana.de:de.*:verify-de.admin.news.announce +newgroup:moderator@dana.de:de.*:verify-de.admin.news.announce +rmgroup:moderator@dana.de:de.*:verify-de.admin.news.announce + +## DE.ALT (German language alternative hierarchy) +# *PGP* See comment at top of file. +newgroup:*:de.alt.*:doit +rmgroup:moderator@dana.de:de.alt.*:verify-de.admin.news.announce + +## DEMON (Demon Internet, UK) +# Contact: newsmaster@demon.net +# Admin group: demon.news +# Key URL: ftp://ftp.demon.co.uk/pub/news/doc/demon.news.txt +# *PGP* See comment at top of file. +newgroup:*:demon.*:drop +rmgroup:*:demon.*:drop +checkgroups:newsmaster@demon.net:demon.*:verify-demon.news +newgroup:newsmaster@demon.net:demon.*:verify-demon.news +rmgroup:newsmaster@demon.net:demon.*:verify-demon.news + +## DFW (Dallas/Fort Worth, Texas, USA) +# URL: http://www.cirr.com/dfw/ +# Admin group: dfw.usenet.config +checkgroups:eric@*cirr.com:dfw.*:doit +newgroup:eric@*cirr.com:dfw.*:doit +rmgroup:eric@*cirr.com:dfw.*:doit + +## DK (Denmark) +# URL: http://www.usenet.dk/dk-admin/ +# Key URL: http://www.usenet.dk/dk-admin/pubkey.html +# Key fingerprint = 7C B2 C7 50 F3 7D 5D 73 8C EE 2E 3F 55 80 72 FF +# *PGP* See comment at top of file. +newgroup:*:dk.*:drop +rmgroup:*:dk.*:drop +checkgroups:news@news.dknet.dk:dk.*:verify-news@news.dknet.dk +newgroup:news@news.dknet.dk:dk.*:verify-news@news.dknet.dk +rmgroup:news@news.dknet.dk:dk.*:verify-news@news.dknet.dk + +## DUKE (*LOCAL* -- Duke University, USA) +# Contact: news@newsgate.duke.edu +# For local use only, contact the above address for information. +newgroup:*:duke.*:mail +rmgroup:*:duke.*:doit + +## EASYNET (*HISTORIC* -- Easynet PLC, UK) +# +# This hierarchy is not entirely defunct, but it receives very little +# traffic and is included primarily for the sake of completeness. +# +# Contact: Christiaan Keet +# Admin group: easynet.support +# *PGP* See comment at top of file. +newgroup:*:easynet.*:drop +rmgroup:*:easynet.*:drop +checkgroups:newsmaster@easynet.net:easynet.*:verify-easynet.news +newgroup:newsmaster@easynet.net:easynet.*:verify-easynet.news +rmgroup:newsmaster@easynet.net:easynet.*:verify-easynet.news + +## EE (Estonia) +# Contact: usenet@news.ut.ee +# URL: http://news.ut.ee/ +# Key URL: http://news.ut.ee/pubkey.asc +# *PGP* See comment at top of file. +newgroup:*:ee.*:drop +rmgroup:*:ee.*:drop +checkgroups:news@news.ut.ee:ee.*:verify-ee.news +newgroup:news@news.ut.ee:ee.*:verify-ee.news +rmgroup:news@news.ut.ee:ee.*:verify-ee.news + +## EFN & EUG (*HISTORIC* -- Eugene Free Computer Network, Eugene/Springfield, Oregon, USA) +# +# This hierarchy is not entirely defunct, but it receives very little +# traffic and is included primarily for the sake of completeness. +# +# Admin group: eug.config +# *PGP* See comment at top of file. +newgroup:*:efn.*|eug.*:drop +rmgroup:*:efn.*|eug.*:drop +checkgroups:newsadmin@efn.org:efn.*|eug.*:verify-eug.config +newgroup:newsadmin@efn.org:efn.*|eug.*:verify-eug.config +rmgroup:newsadmin@efn.org:efn.*|eug.*:verify-eug.config + +## EHIME-U (? University, Japan ?) +checkgroups:news@cc.nias.ac.jp:ehime-u.*:doit +checkgroups:news@doc.dpc.ehime-u.ac.jp:ehime-u.*:doit +newgroup:news@cc.nias.ac.jp:ehime-u.*:doit +newgroup:news@doc.dpc.ehime-u.ac.jp:ehime-u.*:doit +rmgroup:news@cc.nias.ac.jp:ehime-u.*:doit +rmgroup:news@doc.dpc.ehime-u.ac.jp:ehime-u.*:doit + +## ENGLAND (England) +# Contact: admin@england.news-admin.org +# Admin group: england.news.policy +# Key fingerprint = DA 3E C2 01 46 E5 61 CB A2 43 09 CA 13 6D 31 1F +# *PGP* See comment at top of file. +newgroup:*:england.*:drop +rmgroup:*:england.*:drop +checkgroups:admin@england.news-admin.org:england.*:verify-england-usenet +newgroup:admin@england.news-admin.org:england.*:verify-england-usenet +rmgroup:admin@england.news-admin.org:england.*:verify-england-usenet + +## ES (Spain) +# Contact: moderador@corus-es.org +# URL: http://www.corus-es.org/docs/es_newsadmins_faq.txt +# Admin group: es.news.anuncios +# Key URL: http://www.corus-es.org/docs/esnews.asc +# *PGP* See comment at top of file. +newgroup:*:es.*:drop +rmgroup:*:es.*:drop +checkgroups:moderador@corus-es.org:es.*:verify-es.news +newgroup:moderador@corus-es.org:es.*:verify-es.news +rmgroup:moderador@corus-es.org:es.*:verify-es.news + +## ESP (Spanish-language newsgroups) +# Contact: +# URL: http://ennui.org/esp/ +# Key URL: http://ennui.org/esp/mod-ena.asc +# *PGP* See comment at top of file. +newgroup:*:esp.*:drop +rmgroup:*:esp.*:drop +checkgroups:mod-ena@ennui.org:esp.*:verify-esp.news.administracion +newgroup:mod-ena@ennui.org:esp.*:verify-esp.news.administracion +rmgroup:mod-ena@ennui.org:esp.*:verify-esp.news.administracion + +## ETERNAL-SEPTEMBER (Eternal-September Project) +# Contact: news@eternal-september.org +# URL: http://www.eternal-september.org/ +# Key URL: http://www.eternal-september.org/control/pgpkey.txt +# Key fingerprint = A05F 5FA4 D43E 7250 24CE F4D4 10F3 7C12 9E5D D866 +# *PGP* See comment at top of file. +newgroup:*:eternal-september.*:drop +rmgroup:*:eternal-september.*:drop +checkgroups:news@eternal-september.org:eternal-september.*:verify-news@eternal-september.org +newgroup:news@eternal-september.org:eternal-september.*:verify-news@eternal-september.org +rmgroup:news@eternal-september.org:eternal-september.*:verify-news@eternal-september.org + +## EUNET (Europe) +checkgroups:news@noc.eu.net:eunet.*:doit +newgroup:news@noc.eu.net:eunet.*:doit +rmgroup:news@noc.eu.net:eunet.*:doit + +## EUROPA (Europe) +# URL: http://www.europa.usenet.eu.org/ +# Admin group: europa.usenet.admin +# Key URL: http://www.europa.usenet.eu.org/pgp/index.html +# Key fingerprint = 3A 05 A8 49 FB 16 29 25 75 E3 DE BB 69 E0 1D B4 +# *PGP* See comment at top of file. +newgroup:*:europa.*:drop +rmgroup:*:europa.*:drop +checkgroups:group-admin@usenet.eu.org:europa.*:verify-group-admin@usenet.eu.org +newgroup:group-admin@usenet.eu.org:europa.*:verify-group-admin@usenet.eu.org +rmgroup:group-admin@usenet.eu.org:europa.*:verify-group-admin@usenet.eu.org + +## EXAMPLE (Bogus hierarchy reserved for standards documents) +newgroup:*:example.*:mail +rmgroup:*:example.*:doit + +## FA (Gated mailing lists) +# This hierarchy was removed in the "Great Renaming" of 1988. +# +# A site in Norway is currently (as of 2002) gatewaying various mailing +# lists into fa.* newsgroups, but that site does not appear to be issuing +# any control messages for those groups. +# +newgroup:*:fa.*:mail +rmgroup:*:fa.*:doit + +## FFM (Frankfurt/M., Germany) +# URL: http://ffm.arcornews.de/ +# Key URL: ftp://ftp.arcor-online.net/pub/news/PGPKEY.FFM +# *PGP* See comment at top of file. +newgroup:*:ffm.*:drop +rmgroup:*:ffm.*:drop +checkgroups:ffm.admin@arcor.de:ffm.*:verify-ffm.admin +newgroup:ffm.admin@arcor.de:ffm.*:verify-ffm.admin +rmgroup:ffm.admin@arcor.de:ffm.*:verify-ffm.admin + +## FIDO (FidoNet) +checkgroups:root@mbh.org:fido.*:doit +newgroup:root@mbh.org:fido.*:doit +rmgroup:root@mbh.org:fido.*:doit + +## FIDO.BELG (Belgian FidoNet) +# Admin group: fido.belg.news +# *PGP* See comment at top of file. +newgroup:*:fido.belg.*:drop +rmgroup:*:fido.belg.*:drop +checkgroups:fidobelg@mail.z2.fidonet.org:fido.belg.*:verify-fido.belg.news +newgroup:fidobelg@mail.z2.fidonet.org:fido.belg.*:verify-fido.belg.news +rmgroup:fidobelg@mail.z2.fidonet.org:fido.belg.*:verify-fido.belg.news + +## FIDO.GER (German FIDO Net Echos) +# URL: ftp://ftp.fu-berlin.de/doc/news/fido.ger/fido.ger-info.english +# Key URL: ftp://ftp.fu-berlin.de/doc/news/fido.ger/PGP-Key +# *PGP* See comment at top of file. +newgroup:*:fido.ger.*:drop +rmgroup:*:fido.ger.*:drop +checkgroups:fido.ger@news.fu-berlin.de:fido.ger.*:verify-fido.ger@news.fu-berlin.de +newgroup:fido.ger@news.fu-berlin.de:fido.ger.*:verify-fido.ger@news.fu-berlin.de +rmgroup:fido.ger@news.fu-berlin.de:fido.ger.*:verify-fido.ger@news.fu-berlin.de + +## FIDO7 (Russian FidoNet) +# URL: http://www.fido7.ru/ +# Admin group: fido7.postmasters +# Key URL: http://www.fido7.ru/pgpcontrol.html +# *PGP* See comment at top of file. +newgroup:*:fido7.*:drop +rmgroup:*:fido7.*:drop +checkgroups:newgroups-request@fido7.ru:fido7.*:verify-fido7.announce.newgroups +newgroup:newgroups-request@fido7.ru:fido7.*:verify-fido7.announce.newgroups +rmgroup:newgroups-request@fido7.ru:fido7.*:verify-fido7.announce.newgroups + +## FINET (Finland and Finnish language alternative newsgroups) +checkgroups:*@*.fi:finet.*:doit +newgroup:*@*.fi:finet.*:doit +rmgroup:*@*.fi:finet.*:doit + +## FJ (Japan and Japanese language) +# Contact: committee@fj-news.org +# URL: http://www.fj-news.org/index.html.en +# Admin group: fj.news.announce +# Key URL: http://www.is.tsukuba.ac.jp/~yas/fj/fj.asc +# *PGP* See comment at top of file. +newgroup:*:fj.*:drop +rmgroup:*:fj.*:drop +checkgroups:committee@fj-news.org:fj.*:verify-fj.news.announce +newgroup:committee@fj-news.org:fj.*:verify-fj.news.announce +rmgroup:committee@fj-news.org:fj.*:verify-fj.news.announce + +## FL (Florida, USA) +checkgroups:hgoldste@news1.mpcs.com:fl.*:doit +checkgroups:scheidell@fdma.fdma.com:fl.*:doit +newgroup:hgoldste@news1.mpcs.com:fl.*:doit +newgroup:scheidell@fdma.fdma.com:fl.*:doit +rmgroup:hgoldste@news1.mpcs.com:fl.*:doit +rmgroup:scheidell@fdma.fdma.com:fl.*:doit + +## FLORA (FLORA Community WEB, Canada) +# Contact: russell@flora.org +# Admin group: flora.general +# *PGP* See comment at top of file. +newgroup:*:flora.*:drop +rmgroup:*:flora.*:drop +checkgroups:news@flora.ottawa.on.ca:flora.*:verify-flora-news +newgroup:news@flora.ottawa.on.ca:flora.*:verify-flora-news +rmgroup:news@flora.ottawa.on.ca:flora.*:verify-flora-news + +## FR (French language) +# URL: http://www.usenet-fr.news.eu.org/ +# Admin group: fr.usenet.forums.annonces +# Key URL: http://www.usenet-fr.news.eu.org/fur/usenet/presentation-fr.html +# *PGP* See comment at top of file. +newgroup:*:fr.*:drop +rmgroup:*:fr.*:drop +checkgroups:control@usenet-fr.news.eu.org:fr.*:verify-control@usenet-fr.news.eu.org +newgroup:control@usenet-fr.news.eu.org:fr.*:verify-control@usenet-fr.news.eu.org +rmgroup:control@usenet-fr.news.eu.org:fr.*:verify-control@usenet-fr.news.eu.org + +## FRANCE (France) +# Contact: control@usenet-france.news.eu.org +# Admin group: france.admin.evolutions +# *PGP* See comment at top of file. +newgroup:*:france.*:drop +rmgroup:*:france.*:drop +checkgroups:control@usenet-france.news.eu.org:france.*:verify-control@usenet-france.news.eu.org +newgroup:control@usenet-france.news.eu.org:france.*:verify-control@usenet-france.news.eu.org +rmgroup:control@usenet-france.news.eu.org:france.*:verify-control@usenet-france.news.eu.org + +## FREE (Open Hierarchy where anyone can create a group) +newgroup:*:free.*:doit +newgroup:group-admin@isc.org:free.*:drop +newgroup:tale@*uu.net:free.*:drop +rmgroup:*:free.*:drop + +## FUDAI (Japanese ?) +checkgroups:news@picard.cs.osakafu-u.ac.jp:fudai.*:doit +newgroup:news@picard.cs.osakafu-u.ac.jp:fudai.*:doit +rmgroup:news@picard.cs.osakafu-u.ac.jp:fudai.*:doit + +## FUR (*PRIVATE* -- furrynet) +# Contact: fur-config@news.furry.net +# For private use only, contact the above address for information. +newgroup:*:fur.*:mail +rmgroup:*:fur.*:doit + +## GER & HANNOVER & HANNET & HILDESHEIM & HISS (Hannover, Germany) +checkgroups:fifi@hiss.han.de:ger.*|hannover.*|hannet.*|hildesheim.*|hiss.*:doit +newgroup:fifi@hiss.han.de:ger.*|hannover.*|hannet.*|hildesheim.*|hiss.*:doit +rmgroup:fifi@hiss.han.de:ger.*|hannover.*|hannet.*|hildesheim.*|hiss.*:doit + +## GIT (Georgia Institute of Technology, USA) +newgroup:news@news.gatech.edu:git.*:doit +newgroup:news@news.gatech.edu:git*class.*:mail +rmgroup:news@news.gatech.edu:git.*:doit + +## GNU (Free Software Foundation) +# URL: http://www.gnu.org/usenet/usenet.html +# Admin group: gnu.gnusenet.config +# Key URL: http://www.gnu.org/usenet/usenet-pgp-key.txt +# *PGP* See comment at top of file. +newgroup:*:gnu.*:drop +rmgroup:*:gnu.*:drop +checkgroups:usenet@gnu.org:gnu.*:verify-usenet@gnu.org +newgroup:usenet@gnu.org:gnu.*:verify-usenet@gnu.org +rmgroup:usenet@gnu.org:gnu.*:verify-usenet@gnu.org + +## GNUU (*PRIVATE* -- GNUU e.V., Oberursel, Germany) +# URL: http://www.gnuu.de/ +# Key URL: http://www.gnuu.de/config/PGPKEY.GNUU +# For private use only. +# *PGP* See comment at top of file. +newgroup:*:gnuu.*:drop +rmgroup:*:gnuu.*:drop +newgroup:news@gnuu.de:gnuu.*:mail +rmgroup:news@gnuu.de:gnuu.*:verify-news@gnuu.de + +## GOV (Government Information) +# Admin group: gov.usenet.announce +# *PGP* See comment at top of file. +newgroup:*:gov.*:drop +rmgroup:*:gov.*:drop +checkgroups:gov-usenet-announce-moderator@govnews.org:gov.*:verify-gov.usenet.announce +newgroup:gov-usenet-announce-moderator@govnews.org:gov.*:verify-gov.usenet.announce +rmgroup:gov-usenet-announce-moderator@govnews.org:gov.*:verify-gov.usenet.announce + +## GRISBI (Grisbi Personal Finance Manager software) +# Contact: newsmaster@grisbi.org +# URL: http://news.grisbi.org/ +# Admin group: grisbi.admin +# Key URL: http://news.grisbi.org/public-key.asc +# Key fingerprint = EB35 0C03 0080 BD2A 7E0C A4C9 F2C6 2A3D C86C C6E1 +# *PGP* See comment at top of file. +newgroup:*:grisbi.*:drop +rmgroup:*:grisbi.*:drop +checkgroups:grisbi-control@grisbi.org:grisbi.*:verify-grisbi-control@grisbi.org +newgroup:grisbi-control@grisbi.org:grisbi.*:verify-grisbi-control@grisbi.org +rmgroup:grisbi-control@grisbi.org:grisbi.*:verify-grisbi-control@grisbi.org + +## GWU (George Washington University, Washington, DC) +# Contact: Sweth Chandramouli +checkgroups:news@nit.gwu.edu:gwu.*:doit +newgroup:news@nit.gwu.edu:gwu.*:doit +rmgroup:news@nit.gwu.edu:gwu.*:doit + +## HACKTIC (*HISTORIC* -- XS4ALL, Netherlands) +# +# This hierarchy is not entirely defunct, but it receives very little +# traffic and is included primarily for the sake of completeness. +# +# *PGP* See comment at top of file. +newgroup:*:hacktic.*:drop +rmgroup:*:hacktic.*:drop +checkgroups:news@zhaum.xs4all.nl:hacktic.*:verify-news@zhaum.xs4all.nl +newgroup:news@zhaum.xs4all.nl:hacktic.*:verify-news@zhaum.xs4all.nl +rmgroup:news@zhaum.xs4all.nl:hacktic.*:verify-news@zhaum.xs4all.nl + +## HAMBURG (City of Hamburg, Germany) +# Contact: hamburg@steering-group.net +# URL: http://www.steering-group.net/hamburg/ +# Admin group: hamburg.koordination +# Key URL: http://www.steering-group.net/hamburg/hamburg.koordination.txt +# Key fingerprint = 3E E7 0C BB 6E 01 94 EE 45 6F C5 57 F4 B9 54 8E +# *PGP* See comment at top of file. +newgroup:*:hamburg.*:drop +rmgroup:*:hamburg.*:drop +checkgroups:hamburg@steering-group.net:hamburg.*:verify-hamburg.koordination +newgroup:hamburg@steering-group.net:hamburg.*:verify-hamburg.koordination +rmgroup:hamburg@steering-group.net:hamburg.*:verify-hamburg.koordination + +## HAMILTON (Canadian) +checkgroups:news@*dcss.mcmaster.ca:hamilton.*:doit +newgroup:news@*dcss.mcmaster.ca:hamilton.*:doit +rmgroup:news@*dcss.mcmaster.ca:hamilton.*:doit + +## HAMSTER (Hamster, a Win32 news and mail proxy server) +# Contact: hamster-contact@snafu.de +# Admin group: hamster.de.config +# Key fingerprint = 12 75 A9 42 8A D6 1F 77 6A CF B4 0C 79 15 5F 93 +# *PGP* See comment at top of file. +newgroup:*:hamster.*:drop +rmgroup:*:hamster.*:drop +checkgroups:hamster-control@snafu.de:hamster.*:verify-hamster-control@snafu.de +newgroup:hamster-control@snafu.de:hamster.*:verify-hamster-control@snafu.de +rmgroup:hamster-control@snafu.de:hamster.*:verify-hamster-control@snafu.de + +## HAN (Korean Hangul) +# Contact: newgroups-request@usenet.or.kr +# Admin group: han.news.admin +# Key URL: ftp://ftp.usenet.or.kr/pub/korea/usenet/pgp/PGPKEY.han +# *PGP* See comment at top of file. +newgroup:*:han.*:drop +rmgroup:*:han.*:drop +checkgroups:newgroups-request@usenet.or.kr:han.*:verify-han.news.admin +newgroup:newgroups-request@usenet.or.kr:han.*:verify-han.news.admin +rmgroup:newgroups-request@usenet.or.kr:han.*:verify-han.news.admin + +## HARVARD (*LOCAL* -- Harvard University, Cambridge, MA) +# For local use only. +newgroup:*@*.harvard.edu:harvard.*:mail +rmgroup:*@*.harvard.edu:harvard.*:doit + +## HAWAII (Hawaii, USA) +checkgroups:news@lava.net:hawaii.*:doit +newgroup:news@lava.net:hawaii.*:doit +rmgroup:news@lava.net:hawaii.*:doit + +## HFX (Halifax, Nova Scotia) +checkgroups:stevemackie@gmail.com:hfx.*:doit +newgroup:stevemackie@gmail.com:hfx.*:doit +rmgroup:stevemackie@gmail.com:hfx.*:doit + +## HIV (HIVNET Foundation, for HIV+/AIDS information) +# Contact: news@hivnet.org +# Admin group: hiv.config +# Key fingerprint = 5D D6 0E DC 1E 2D EA 0B B0 56 4D D6 52 53 D7 A4 +# *PGP* See comment at top of file. +newgroup:*:hiv.*:drop +rmgroup:*:hiv.*:drop +checkgroups:news@hivnet.org:hiv.*:verify-news@hivnet.org +newgroup:news@hivnet.org:hiv.*:verify-news@hivnet.org +rmgroup:news@hivnet.org:hiv.*:verify-news@hivnet.org + +## HK (Hong Kong) +checkgroups:hknews@comp.hkbu.edu.hk:hk.*:doit +newgroup:hknews@comp.hkbu.edu.hk:hk.*:doit +rmgroup:hknews@comp.hkbu.edu.hk:hk.*:doit + +## HOUSTON (Houston, Texas, USA) +# Admin group: houston.usenet.config +# *PGP* See comment at top of file. +newgroup:*:houston.*:drop +rmgroup:*:houston.*:drop +checkgroups:news@academ.com:houston.*:verify-houston.usenet.config +newgroup:news@academ.com:houston.*:verify-houston.usenet.config +rmgroup:news@academ.com:houston.*:verify-houston.usenet.config + +## HR (Croatian language) +# Contact: newsmaster@carnet.hr +# URL: http://newsfeed.carnet.hr/control/ +# Admin group: hr.news.admin +# Key URL: http://newsfeed.carnet.hr/control/key.txt +# Key fingerprint = 0EE5 74FB 1C40 7ADB 0AAC A52F 7192 1BA3 ED63 AD9A +# Syncable server: news.carnet.hr +# *PGP* See comment at top of file. +newgroup:*:hr.*:drop +rmgroup:*:hr.*:drop +checkgroups:newsmaster@carnet.hr:hr.*:verify-newsmaster@carnet.hr +newgroup:newsmaster@carnet.hr:hr.*:verify-newsmaster@carnet.hr +rmgroup:newsmaster@carnet.hr:hr.*:verify-newsmaster@carnet.hr + +## HUMANITYQUEST (*HISTORIC* -- Humanities discussion) +# +# This hierarchy is not entirely defunct, but it receives very little +# traffic and is included primarily for the sake of completeness. +# +# Contact: news-admin@humanityquest.com +# URL: http://www.humanityquest.com/projects/newsgroups/ +# Key URL: http://www.humanityquest.com/projects/newsgroups/PGP.htm +# Key fingerprint = BA3D B306 B6F5 52AA BA8F 32F0 8C4F 5040 16F9 C046 +# *PGP* See comment at top of file. +newgroup:*:humanityquest.*:drop +rmgroup:*:humanityquest.*:drop +checkgroups:news-admin@humanityquest.com:humanityquest.*:verify-humanityquest.admin.config +newgroup:news-admin@humanityquest.com:humanityquest.*:verify-humanityquest.admin.config +rmgroup:news-admin@humanityquest.com:humanityquest.*:verify-humanityquest.admin.config + +## HUN (Hungary) +# URL: http://www.sztaki.hu/~kissg/news/hiteles.html +# Admin group: hun.admin.news +# Key URL: http://gatling.ikk.sztaki.hu/~kissg/news/hun.admin.news.asc +# *PGP* See comment at top of file. +newgroup:*:hun.*:drop +rmgroup:*:hun.*:drop +checkgroups:hun-mnt@news.sztaki.hu:hun.*:verify-hun.admin.news +newgroup:hun-mnt@news.sztaki.hu:hun.*:verify-hun.admin.news +rmgroup:hun-mnt@news.sztaki.hu:hun.*:verify-hun.admin.news + +## IA (Iowa, USA) +checkgroups:skunz@iastate.edu:ia.*:doit +newgroup:skunz@iastate.edu:ia.*:doit +rmgroup:skunz@iastate.edu:ia.*:doit + +## IBMNET (*LOCAL* -- ?) +# Contact: news@ibm.net +# For local use only, contact the above address for information. +newgroup:*:ibmnet.*:mail +rmgroup:*:ibmnet.*:doit + +## ICONZ (*LOCAL* -- The Internet Company of New Zealand, New Zealand) +# Contact: usenet@iconz.co.nz +# For local use only, contact the above address for information. +newgroup:*:iconz.*:mail +rmgroup:*:iconz.*:doit + +## IDOCTRA (Idoctra Translation Software, Translation Discussion) +# Contact: support@idoctra.com +checkgroups:support@idoctra.com:idoctra.*:doit +newgroup:support@idoctra.com:idoctra.*:doit +rmgroup:support@idoctra.com:idoctra.*:doit + +## IE (Ireland) +# Contact: control@usenet.ie +# Admin group: ie.news.group +# *PGP* See comment at top of file. +newgroup:*:ie.*:drop +rmgroup:*:ie.*:drop +checkgroups:control@usenet.ie:ie.*:verify-control@usenet.ie +newgroup:control@usenet.ie:ie.*:verify-control@usenet.ie +rmgroup:control@usenet.ie:ie.*:verify-control@usenet.ie + +## IEEE (*DEFUNCT* -- Institute of Electrical and Electronic Engineers) +# Contact: postoffice@ieee.org +# This hierarchy is defunct. Please remove it. +newgroup:*:ieee.*:mail +rmgroup:*:ieee.*:doit + +## INFO (*DEFUNCT* -- Gatewayed mailing lists) +# This hierarchy is defunct. Please remove it. +newgroup:rjoyner@uiuc.edu:info.*:mail +rmgroup:rjoyner@uiuc.edu:info.*:doit + +## IS (Iceland) +# Contact: IS Group Admins +# URL: http://www.usenet.is/ +# Admin group: is.isnet +# Key URL: http://www.usenet.is/group-admin.asc +# Key fingerprint = 33 32 8D 46 1E 5E 1C 7F 48 60 8E 72 E5 3E CA EA +# *PGP* See comment at top of file. +newgroup:*:is.*:drop +rmgroup:*:is.*:drop +checkgroups:group-admin@usenet.is:is.*:verify-group-admin@usenet.is +newgroup:group-admin@usenet.is:is.*:verify-group-admin@usenet.is +rmgroup:group-admin@usenet.is:is.*:verify-group-admin@usenet.is + +## ISC (Japanese ?) +checkgroups:news@sally.isc.chubu.ac.jp:isc.*:doit +newgroup:news@sally.isc.chubu.ac.jp:isc.*:doit +rmgroup:news@sally.isc.chubu.ac.jp:isc.*:doit + +## ISRAEL & IL (Israel) +newgroup:news@news.biu.ac.il:israel.*:doit +rmgroup:news@news.biu.ac.il:israel.*|il.*:doit + +## ISU (I-Shou University, Taiwan) +# Contact: news@news.isu.edu.tw +# URL: http://news.isu.edu.tw/ +# Admin group: isu.newgroups +# Key URL: http://news.isu.edu.tw/isu.asc +# *PGP* See comment at top of file. +newgroup:*:isu.*:drop +rmgroup:*:isu.*:drop +checkgroups:news@news.isu.edu.tw:isu.*:verify-news@news.isu.edu.tw +newgroup:news@news.isu.edu.tw:isu.*:verify-news@news.isu.edu.tw +rmgroup:news@news.isu.edu.tw:isu.*:verify-news@news.isu.edu.tw + +## IT (Italian) +# Contact: gcn@news.nic.it +# URL: http://www.news.nic.it/ +# Admin group: it.news.annunci +# Key URL: http://www.news.nic.it/pgp.txt +# Key fingerprint = 94 A4 F7 B5 46 96 D6 C7 A6 73 F2 98 C4 8C D0 E0 +# *PGP* See comment at top of file. +newgroup:*:it.*:drop +rmgroup:*:it.*:drop +checkgroups:gcn@news.nic.it:it.*:verify-gcn@news.nic.it +newgroup:gcn@news.nic.it:it.*:verify-gcn@news.nic.it +rmgroup:gcn@news.nic.it:it.*:verify-gcn@news.nic.it + +## IT-ALT (Alternate Italian) +# +# There is no one official control message issuer for the it-alt.* +# hierarchy, so this file doesn't choose any particular one. Several +# different people issue control messages for this hierarchy, which may +# or may not agree, and sites carrying this hierarchy are encouraged to +# pick one and add it below. +# +# Newgroup and removal requests are to be posted to it-alt.config. A list +# of people issuing PGP/GPG signed control messages is available in a +# periodic posting to news.admin.hierarchies and it-alt.config. +# +newgroup:*:it-alt.*:drop +rmgroup:*:it-alt.*:drop + +## ITALIA (Italy) +# Contact: news@news.cineca.it +# URL: http://news.cineca.it/italia/ +# Admin group: italia.announce.newgroups +# Key URL: http://news.cineca.it/italia/italia-pgp.txt +# Key fingerprint = 0F BB 71 62 DA 5D 5D B8 D5 86 FC 28 02 67 1A 6B +# *PGP* See comment at top of file. +newgroup:*:italia.*:drop +rmgroup:*:italia.*:drop +checkgroups:news@news.cineca.it:italia.*:verify-italia.announce.newgroups +newgroup:news@news.cineca.it:italia.*:verify-italia.announce.newgroups +rmgroup:news@news.cineca.it:italia.*:verify-italia.announce.newgroups + +## IU (Indiana University) +newgroup:news@usenet.ucs.indiana.edu:iu.*:doit +newgroup:root@usenet.ucs.indiana.edu:iu.*:doit +newgroup:*@usenet.ucs.indiana.edu:iu*class.*:mail +rmgroup:news@usenet.ucs.indiana.edu:iu.*:doit +rmgroup:root@usenet.ucs.indiana.edu:iu.*:doit + +## JAPAN (Japan) +# Contact: Tsuneo Tanaka +# URL: http://www.asahi-net.or.jp/~AE5T-KSN/japan-e.html +# Admin group: japan.admin.announce +# Key URL: http://grex.cyberspace.org/~tt/japan.admin.announce.asc +# Key fingerprint = 6A FA 19 47 69 1B 10 74 38 53 4B 1B D8 BA 3E 85 +# *PGP* See comment at top of file. +newgroup:*:japan.*:drop +rmgroup:*:japan.*:drop +checkgroups:japan.admin.announce@news.efnet.com:japan.*:verify-japan.admin.announce@news.efnet.com +newgroup:japan.admin.announce@news.efnet.com:japan.*:verify-japan.admin.announce@news.efnet.com +rmgroup:japan.admin.announce@news.efnet.com:japan.*:verify-japan.admin.announce@news.efnet.com + +## JLUG (Japan Linux Users Group) +# Contact: news@linux.or.jp +# URL: http://www.linux.or.jp/community/news/index.html +# Admin group: jlug.config +# Key URL: http://www.linux.or.jp/pgpkey/news +# *PGP* See comment at top of file. +newgroup:*:jlug.*:drop +rmgroup:*:jlug.*:drop +checkgroups:news@linux.or.jp:jlug.*:verify-news@linux.or.jp +newgroup:news@linux.or.jp:jlug.*:verify-news@linux.or.jp +rmgroup:news@linux.or.jp:jlug.*:verify-news@linux.or.jp + +## K12 (US Educational Network) +# URL: http://www.k12groups.org/ +checkgroups:braultr@*csmanoirs.qc.ca:k12.*:doit +newgroup:braultr@*csmanoirs.qc.ca:k12.*:doit +rmgroup:braultr@*csmanoirs.qc.ca:k12.*:doit + +## KA (*PRIVATE* -- Karlsruhe, Germany) +# Contact: usenet@karlsruhe.org +# URL: http://www.karlsruhe.org/ +# Key URL: http://www.karlsruhe.org/pubkey-news.karlsruhe.org.asc +# Key fingerprint = DE 19 BB 25 76 19 81 17 F0 67 D2 23 E8 C8 7C 90 +# For private use only, contact the above address for information. +# *PGP* See comment at top of file. +newgroup:*:ka.*:drop +rmgroup:*:ka.*:drop +# The following three lines are only for authorized ka.* sites. +#checkgroups:usenet@karlsruhe.org:ka.*:verify-usenet@karlsruhe.org +#newgroup:usenet@karlsruhe.org:ka.*:verify-usenet@karlsruhe.org +#rmgroup:usenet@karlsruhe.org:ka.*:verify-usenet@karlsruhe.org + +## KANTO (?) +# *PGP* See comment at top of file. +rmgroup:*:kanto.*:drop +checkgroups:ty@kamoi.imasy.or.jp:kanto.*:verify-kanto.news.network +# NOTE: newgroups aren't verified... +newgroup:*@*.jp:kanto.*:doit +rmgroup:ty@kamoi.imasy.or.jp:kanto.*:verify-kanto.news.network + +## KASSEL (Kassel, Germany) +# *PGP* See comment at top of file. +newgroup:*:kassel.*:drop +rmgroup:*:kassel.*:drop +checkgroups:dirk.meyer@dinoex.sub.org:kassel.*:verify-kassel-admin +newgroup:dirk.meyer@dinoex.sub.org:kassel.*:verify-kassel-admin +rmgroup:dirk.meyer@dinoex.sub.org:kassel.*:verify-kassel-admin + +## KC (Kansas City, Kansas/Missouri, USA) +checkgroups:dan@sky.net:kc.*:doit +newgroup:dan@sky.net:kc.*:doit +rmgroup:dan@sky.net:kc.*:doit + +## KGK (Administered by KGK, Japan) +# Contact: Keiji KOSAKA +# URL: http://film.rlss.okayama-u.ac.jp/~kgk/kgk/index.html +# Admin group: kgk.admin +checkgroups:usenet@film.rlss.okayama-u.ac.jp:kgk.*:doit +newgroup:usenet@film.rlss.okayama-u.ac.jp:kgk.*:doit +rmgroup:usenet@film.rlss.okayama-u.ac.jp:kgk.*:doit + +## KIEL (Kiel, Germany) +# URL: http://news.koehntopp.de/kiel/ +checkgroups:kris@koehntopp.de:kiel.*:doit +newgroup:kris@koehntopp.de:kiel.*:doit +rmgroup:kris@koehntopp.de:kiel.*:doit + +## KRST (*LOCAL* -- University of Oslo, Norway) +# Contact: jani@ifi.uio.no +# For local use only, contact the above address for information. +newgroup:*:krst.*:mail +rmgroup:*:krst.*:doit + +## KWNET (*LOCAL* -- Kitchener-Waterloo?) +# Contact: Ed Hew +# For local use only, contact the above address for information. +newgroup:*:kwnet.*:mail +rmgroup:*:kwnet.*:doit + +## LAW (?) +# Contact: Jim Burke +checkgroups:*@*.kentlaw.edu:law.*:doit +checkgroups:*@*.law.vill.edu:law.*:doit +newgroup:*@*.kentlaw.edu:law.*:doit +newgroup:*@*.law.vill.edu:law.*:doit +rmgroup:*@*.kentlaw.edu:law.*:doit +rmgroup:*@*.law.vill.edu:law.*:doit + +## LINUX (Gated Linux mailing lists) +# Contact: Marco d'Itri +# Admin group: linux.admin.news +# Key fingerprint = 81 B3 27 99 4F CE 32 D1 1B C9 01 0D BB B3 2E 41 +# *PGP* See comment at top of file. +newgroup:*:linux.*:drop +rmgroup:*:linux.*:drop +checkgroups:linux-admin@bofh.it:linux.*:verify-linux-admin@bofh.it +newgroup:linux-admin@bofh.it:linux.*:verify-linux-admin@bofh.it +rmgroup:linux-admin@bofh.it:linux.*:verify-linux-admin@bofh.it + +## LOCAL (Local-only groups) +# It is not really a good idea for sites to use these since they may occur +# on many unconnected sites. +newgroup:*:local.*:mail +rmgroup:*:local.*:drop + +## LUEBECK (Luebeck, Germany) +# Contact: usenet@zybrkat.org +# Admin group: luebeck.admin +checkgroups:usenet@zybrkat.org:luebeck.*:doit +newgroup:usenet@zybrkat.org:luebeck.*:doit +rmgroup:usenet@zybrkat.org:luebeck.*:doit + +## MALTA (Nation of Malta) +# Contact: cmeli@cis.um.edu.mt +# URL: http://www.malta.news-admin.org/ +# Admin group: malta.config +# Key URL: http://www.cis.um.edu.mt/news-malta/PGP.PUBLICKEY +# Key fingerprint = 20 17 01 5C F0 D0 1A 42 E4 13 30 58 0B 14 48 A6 +# *PGP* See comment at top of file. +newgroup:*:malta.*:drop +rmgroup:*:malta.*:drop +checkgroups:cmeli@cis.um.edu.mt:malta.*:verify-malta.config +newgroup:cmeli@cis.um.edu.mt:malta.*:verify-malta.config +rmgroup:cmeli@cis.um.edu.mt:malta.*:verify-malta.config + +## MANAWATU (*LOCAL* -- Manawatu district, New Zealand) +# Contact: alan@manawatu.gen.nz or news@manawatu.gen.nz +# For local use only, contact the above address for information. +newgroup:*:manawatu.*:mail +rmgroup:*:manawatu.*:doit + +## MAUS (MausNet, Germany) +# Admin group: maus.info +# Key fingerprint = 82 52 C7 70 26 B9 72 A1 37 98 55 98 3F 26 62 3E +# *PGP* See comment at top of file. +newgroup:*:maus.*:drop +rmgroup:*:maus.*:drop +checkgroups:guenter@gst0hb.hb.provi.de:maus.*:verify-maus-info +checkgroups:guenter@gst0hb.north.de:maus.*:verify-maus-info +newgroup:guenter@gst0hb.hb.provi.de:maus.*:verify-maus-info +newgroup:guenter@gst0hb.north.de:maus.*:verify-maus-info +rmgroup:guenter@gst0hb.hb.provi.de:maus.*:verify-maus-info +rmgroup:guenter@gst0hb.north.de:maus.*:verify-maus-info + +## MCMASTER (*LOCAL* -- McMaster University, Ontario) +# Contact: Brian Beckberger +# For local use only, contact the above address for information. +newgroup:*:mcmaster.*:mail +rmgroup:*:mcmaster.*:doit + +## MCOM (*LOCAL* -- Netscape Inc, USA) +# For local use only. +newgroup:*:mcom.*:mail +rmgroup:*:mcom.*:doit + +## ME (Maine, USA) +checkgroups:kerry@maine.maine.edu:me.*:doit +newgroup:kerry@maine.maine.edu:me.*:doit +rmgroup:kerry@maine.maine.edu:me.*:doit + +## MEDLUX (All-Russia medical teleconferences) +# URL: ftp://ftp.medlux.ru/pub/news/medlux.grp +checkgroups:neil@new*.medlux.ru:medlux.*:doit +newgroup:neil@new*.medlux.ru:medlux.*:doit +rmgroup:neil@new*.medlux.ru:medlux.*:doit + +## MELB (Melbourne, Australia) +# Contact: ausadmin@aus.news-admin.org +# URL: http://melb.news-admin.org/ +# Key URL: http://aus.news-admin.org/ausadmin.asc +# *PGP* See comment at top of file. +newgroup:*:melb.*:drop +rmgroup:*:melb.*:drop +checkgroups:ausadmin@aus.news-admin.org:melb.*:verify-ausadmin@aus.news-admin.org +newgroup:ausadmin@aus.news-admin.org:melb.*:verify-ausadmin@aus.news-admin.org +rmgroup:ausadmin@aus.news-admin.org:melb.*:verify-ausadmin@aus.news-admin.org + +## MENSA (The Mensa Organisation) +# Contact: usenet@newsgate.mensa.org +# Admin group: mensa.config +# Key fingerprint = 52B9 3963 85D9 0806 8E19 7344 973C 5005 DC7D B7A7 +# *PGP* See comment at top of file. +newgroup:*:mensa.*:drop +rmgroup:*:mensa.*:drop +checkgroups:usenet@newsgate.mensa.org:mensa.*:verify-mensa.config +newgroup:usenet@newsgate.mensa.org:mensa.*:verify-mensa.config +rmgroup:usenet@newsgate.mensa.org:mensa.*:verify-mensa.config + +## METOCEAN (ISP in Japan) +checkgroups:fwataru@*.metocean.co.jp:metocean.*:doit +newgroup:fwataru@*.metocean.co.jp:metocean.*:doit +rmgroup:fwataru@*.metocean.co.jp:metocean.*:doit + +## METROPOLIS (*LOCAL* -- ?) +# Contact: newsmaster@worldonline.nl +# For local use only, contact the above address for information. +newgroup:*:metropolis.*:mail +rmgroup:*:metropolis.*:doit + +## MI (Michigan, USA) +# Contact: Steve Simmons +checkgroups:scs@lokkur.dexter.mi.us:mi.*:doit +newgroup:scs@lokkur.dexter.mi.us:mi.*:doit +rmgroup:scs@lokkur.dexter.mi.us:mi.*:doit + +## MICROSOFT (Microsoft Corporation, USA) +# +# Control articles for that hierarchy are not issued by Microsoft itself +# but by a Usenet active participant in order to improve the quality of +# the propagation of Microsoft newsgroups. Their official URL is: +# http://www.microsoft.com/communities/newsgroups/list/en-us/default.aspx +# +# Contact: control-microsoft@trigofacile.com +# URL: http://www.trigofacile.com/divers/usenet/clefs/index.htm +# Admin group: microsoft.public.news.server +# Key URL: http://www.trigofacile.com/divers/usenet/clefs/pgpkey-microsoft.asc +# Key fingerprint = DF70 5FC9 F615 D52E 02DB A3CB 63A9 8D13 E60E 2FAA +# Syncable server: msnews.microsoft.com +# *PGP* See comment at top of file. +newgroup:*:microsoft.*:drop +rmgroup:*:microsoft.*:drop +checkgroups:control-microsoft@trigofacile.com:microsoft.*:verify-control-microsoft@trigofacile.com +newgroup:control-microsoft@trigofacile.com:microsoft.*:verify-control-microsoft@trigofacile.com +rmgroup:control-microsoft@trigofacile.com:microsoft.*:verify-control-microsoft@trigofacile.com + +## MILW (Milwaukee, Wisconsin, USA) +# Contact: milw@usenet.mil.wi.us +# URL: http://usenet.mil.wi.us/ +# Admin group: milw.config +# Key URL: http://usenet.mil.wi.us/pgpkey +# Key fingerprint = 6E 9B 9F 70 98 AB 9C E5 C3 C0 05 82 21 5B F4 9E +# *PGP* See comment at top of file. +newgroup:*:milw.*:drop +rmgroup:*:milw.*:drop +checkgroups:milw@usenet.mil.wi.us:milw.*:verify-milw.config +newgroup:milw@usenet.mil.wi.us:milw.*:verify-milw.config +rmgroup:milw@usenet.mil.wi.us:milw.*:verify-milw.config + +## MOD (*DEFUNCT* -- Original top level moderated hierarchy) +# This hierarchy is defunct. Please remove it. +newgroup:*:mod.*:mail +rmgroup:*:mod.*:doit + +## MUC (Munchen [Munich], Germany) +# Admin group: muc.admin +# Key fingerprint = 43 C7 0E 7C 45 C7 06 E0 BD 6F 76 CE 07 39 5E 66 +# *PGP* See comment at top of file. +newgroup:*:muc.*:drop +rmgroup:*:muc.*:drop +checkgroups:muc-cmsg@muenchen.pro-bahn.org:muc.*:verify-muc.admin +newgroup:muc-cmsg@muenchen.pro-bahn.org:muc.*:verify-muc.admin +rmgroup:muc-cmsg@muenchen.pro-bahn.org:muc.*:verify-muc.admin + +## NAGASAKI-U (Nagasaki University, Japan ?) +checkgroups:root@*nagasaki-u.ac.jp:nagasaki-u.*:doit +newgroup:root@*nagasaki-u.ac.jp:nagasaki-u.*:doit +rmgroup:root@*nagasaki-u.ac.jp:nagasaki-u.*:doit + +## NAS (*LOCAL* -- NAS, NASA Ames Research Center, USA) +# Contact: news@nas.nasa.gov +# For local use only, contact the above address for information. +newgroup:*:nas.*:mail +rmgroup:*:nas.*:doit + +## NASA (*LOCAL* -- National Aeronautics and Space Administration, USA) +# Contact: news@nas.nasa.gov +# For local use only, contact the above address for information. +newgroup:*:nasa.*:mail +rmgroup:*:nasa.*:doit + +## NC (North Carolina, USA) +# +# Tim Seaver says he hasn't had any dealings with nc.* +# for over two years and the hierarchy is basically "open to anyone who +# wants it." +# +# newgroup:tas@ncren.net:nc.*:doit +# rmgroup:tas@ncren.net:nc.*:doit + +## NCF (*LOCAL* -- National Capital Freenet, Ottawa, Ontario, Canada) +# Contact: news@freenet.carleton.ca +# For local use only, contact the above address for information. +newgroup:*:ncf.*:mail +rmgroup:*:ncf.*:doit + +## NCTU (Taiwan) +checkgroups:chen@cc.nctu.edu.tw:nctu.*:doit +newgroup:chen@cc.nctu.edu.tw:nctu.*:doit +rmgroup:chen@cc.nctu.edu.tw:nctu.*:doit + +## NCU (*LOCAL* -- National Central University, Taiwan) +# Contact: Ying-Hao Chang +# Contact: +# For local use only, contact the above address for information. +newgroup:*:ncu.*:mail +rmgroup:*:ncu.*:doit + +## NERSC (National Energy Research Scientific Computing Center) +# Contact: +# newgroup:*:nersc.*:mail +# rmgroup:*:nersc.*:doit + +## NET (*HISTORIC* -- Usenet 2) +# +# This was a failed experiment in a different newsgroup creation policy and +# administrative policy which has now been almost entirely abandoned. The +# information is retained here for the few sites still using it, but sites +# not already carrying the groups probably won't be interested. +# +# (This was also the original unmoderated Usenet hierarchy from before the +# Great Renaming. The groups that used to be in net.* in the 1980s are now +# in the Big Eight hierarchies.) +# +# URL: http://www.usenet2.org +# Admin group: net.config +# Key URL: http://www.usenet2.org/control@usenet2.org.asc +# Key fingerprint = D7 D3 5C DB 18 6A 29 79 BF 74 D4 58 A3 78 9D 22 +# *PGP* See comment at top of file. +newgroup:*:net.*:drop +rmgroup:*:net.*:drop +#checkgroups:control@usenet2.org:net.*:verify-control@usenet2.org +#newgroup:control@usenet2.org:net.*:verify-control@usenet2.org +#rmgroup:control@usenet2.org:net.*:verify-control@usenet2.org + +## NETINS (*LOCAL* -- netINS, Inc) +# Contact: news@netins.net +# For local use only, contact the above address for information. +newgroup:*:netins.*:mail +rmgroup:*:netins.*:doit + +## NETSCAPE (Netscape Communications Corp) +# Contact: news@netscape.com +# URL: http://www.mozilla.org/community.html +# Admin group: netscape.public.admin +# Key fingerprint = B7 80 55 12 1F 9C 17 0B 86 66 AD 3B DB 68 35 EC +# *PGP* See comment at top of file. +newgroup:*:netscape.*:drop +rmgroup:*:netscape.*:drop +checkgroups:news@netscape.com:netscape.*:verify-netscape.public.admin +newgroup:news@netscape.com:netscape.*:verify-netscape.public.admin +rmgroup:news@netscape.com:netscape.*:verify-netscape.public.admin + +## NEWS4US (*LOCAL* -- NEWS4US dot NL, Netherlands) +# Contact: info@news4us.nl +# For local use only, contact the above address for information. +newgroup:*:news4us.*:mail +rmgroup:*:news4us.*:doit + +## NF (Newfoundland and Labrador, Canada) +# Contact: randy@mun.ca +checkgroups:randy@mun.ca:nf.*:doit +newgroup:randy@mun.ca:nf.*:doit +rmgroup:randy@mun.ca:nf.*:doit + +## NIAGARA (Niagara Peninsula, USA/Canada) +checkgroups:news@niagara.com:niagara.*:doit +newgroup:news@niagara.com:niagara.*:doit +rmgroup:news@niagara.com:niagara.*:doit + +## NIAS (Japanese ?) +checkgroups:news@cc.nias.ac.jp:nias.*:doit +newgroup:news@cc.nias.ac.jp:nias.*:doit +rmgroup:news@cc.nias.ac.jp:nias.*:doit + +## NIGERIA (Nigeria) +checkgroups:news@easnet.net:nigeria.*:doit +newgroup:news@easnet.net:nigeria.*:doit +rmgroup:news@easnet.net:nigeria.*:doit + +## NIHON (Japan) +checkgroups:ktomita@jade.dti.ne.jp:nihon.*:doit +newgroup:ktomita@jade.dti.ne.jp:nihon.*:doit +rmgroup:ktomita@jade.dti.ne.jp:nihon.*:doit + +## NIPPON (*PRIVATE* -- Japan) +# URL: http://www.gcd.org/news/nippon/ +# Admin group: nippon.news.group +# Key URL: http://www.gcd.org/news/nippon/ +# Key fingerprint = BC CF 15 CD B1 3C DF B3 C3 DE 35 6F 2F F7 46 DB +# For private use only. +# *PGP* See comment at top of file. +newgroup:*:nippon.*:drop +rmgroup:*:nippon.*:drop +newgroup:news@gcd.org:nippon.*:mail +rmgroup:news@gcd.org:nippon.*:verify-nippon.news.group + +## NJ (New Jersey, USA) +# Contact: nj-admin@gunslinger.net +# URL: http://www.exit109.com/~jeremy/nj/ +checkgroups:nj-admin@gunslinger.net:nj.*:doit +newgroup:nj-admin@gunslinger.net:nj.*:doit +rmgroup:nj-admin@gunslinger.net:nj.*:doit + +## NL (Netherlands) +# Contact: nl-admin@nic.surfnet.nl +# URL: http://nl.news-admin.org/info/nladmin.html +# Admin group: nl.newsgroups +# Key fingerprint = 45 20 0B D5 A1 21 EA 7C EF B2 95 6C 25 75 4D 27 +# *PGP* See comment at top of file. +newgroup:*:nl.*:drop +rmgroup:*:nl.*:drop +checkgroups:nl-admin@nic.surfnet.nl:nl.*:verify-nl.newsgroups +newgroup:nl-admin@nic.surfnet.nl:nl.*:verify-nl.newsgroups +rmgroup:nl-admin@nic.surfnet.nl:nl.*:verify-nl.newsgroups + +## NL-ALT (Alternative Netherlands groups) +# Key fingerprint = 6B 62 EB 53 4D 5D 2F 96 35 D9 C8 9C B0 65 0E 4C +# *PGP* See comment at top of file. +checkgroups:nl-alt-janitor@surfer.xs4all.nl:nl-alt.*:verify-nl-alt.config.admin +newgroup:*:nl-alt.*:doit +rmgroup:nl-alt-janitor@surfer.xs4all.nl:nl-alt.*:verify-nl-alt.config.admin +rmgroup:news@kink.xs4all.nl:nl-alt.*:verify-nl-alt.config.admin + +## NLO (Open Source / Free Software, hosted by nl.linux.org) +# URL: http://news.nl.linux.org/doc/nlo.html +# Key URL: http://news.nl.linux.org/doc/nlo-3.html#ss3.1 +# Key fingerprint = 63 DC B2 51 0A F3 DD 72 C2 BD C6 FD C1 C5 44 CF +# *PGP* See comment at top of file. +newgroup:*:nlo.*:drop +rmgroup:*:nlo.*:drop +checkgroups:news@nl.linux.org:nlo.*:verify-nlo.newsgroups +newgroup:news@nl.linux.org:nlo.*:verify-nlo.newsgroups +rmgroup:news@nl.linux.org:nlo.*:verify-nlo.newsgroups + +## NM (New Mexico, USA) +checkgroups:news@tesuque.cs.sandia.gov:nm.*:doit +newgroup:news@tesuque.cs.sandia.gov:nm.*:doit +rmgroup:news@tesuque.cs.sandia.gov:nm.*:doit + +## NO (Norway) +# URL: http://www.usenet.no/ +# Admin group: no.usenet.admin +# Key URL: http://www.usenet.no/pgp-key.txt +# *PGP* See comment at top of file. +newgroup:*:no.*:drop +rmgroup:*:no.*:drop +checkgroups:control@usenet.no:no.*:verify-no-hir-control +newgroup:control@usenet.no:no.*:verify-no-hir-control +rmgroup:control@usenet.no:no.*:verify-no-hir-control + +## NO.ALT (Norway alternative hierarchy) +# *PGP* See comment at top of file. +newgroup:*:no.alt.*:drop +rmgroup:*:no.alt.*:drop +newgroup:*@*.no:no.alt.*:doit +rmgroup:control@usenet.no:no.alt.*:verify-no-hir-control + +## NORD (Northern Germany) +# thilo@own.deceiver.org no longer a valid address +# newgroup:thilo@own.deceiver.org:nord.*:doit +# rmgroup:thilo@own.deceiver.org:nord.*:doit + +## NRW (Northrine-Westfalia, Germany) +# Contact: moderator@nrw.usenetverwaltung.de +# URL: http://nrw.usenetverwaltung.de/ +# Admin group: nrw.admin.announce +# Key URL: http://nrw.usenetverwaltung.de/pgp/nrw.asc +# Key fingerprint = 13 4A 80 FE D6 34 B4 64 AF 32 08 3F 62 0E B1 E2 +# *PGP* See comment at top of file. +newgroup:*:nrw.*:drop +rmgroup:*:nrw.*:drop +checkgroups:moderator@nrw.usenetverwaltung.de:nrw.*:verify-moderator@nrw.usenetverwaltung.de +newgroup:moderator@nrw.usenetverwaltung.de:nrw.*:verify-moderator@nrw.usenetverwaltung.de +rmgroup:moderator@nrw.usenetverwaltung.de:nrw.*:verify-moderator@nrw.usenetverwaltung.de + +## NV (Nevada) +checkgroups:cshapiro@netcom.com:nv.*:doit +checkgroups:doctor@netcom.com:nv.*:doit +newgroup:cshapiro@netcom.com:nv.*:doit +newgroup:doctor@netcom.com:nv.*:doit +rmgroup:cshapiro@netcom.com:nv.*:doit +rmgroup:doctor@netcom.com:nv.*:doit + +## NY (New York State, USA) +checkgroups:root@ny.psca.com:ny.*:doit +newgroup:root@ny.psca.com:ny.*:doit +rmgroup:root@ny.psca.com:ny.*:doit + +## NYC (New York City) +# Contact: Perry E. Metzger +checkgroups:perry@piermont.com:nyc.*:doit +newgroup:perry@piermont.com:nyc.*:doit +rmgroup:perry@piermont.com:nyc.*:doit + +## NZ (New Zealand) +# Contact: root@usenet.net.nz +# URL: http://www.faqs.org/faqs/usenet/nz-news-hierarchy +# Admin group: nz.net.announce +# Key fingerprint = 07 DF 48 AA D0 ED AA 88 16 70 C5 91 65 3D 1A 28 +# *PGP* See comment at top of file. +newgroup:*:nz.*:drop +rmgroup:*:nz.*:drop +checkgroups:root@usenet.net.nz:nz.*:verify-nz-hir-control +newgroup:root@usenet.net.nz:nz.*:verify-nz-hir-control +rmgroup:root@usenet.net.nz:nz.*:verify-nz-hir-control + +## OC (Orange County, California, USA) +checkgroups:bob@tsunami.sugarland.unocal.com:oc.*:doit +newgroup:bob@tsunami.sugarland.unocal.com:oc.*:doit +rmgroup:bob@tsunami.sugarland.unocal.com:oc.*:doit + +## OESTERREICH (Free Austria) +# +# This is apparently another alt.* or free.* but specific to Austria. +# Currently, the ftp.isc.org list doesn't honor newgroup messages in the +# hierarchy due to lack of requests, but here is the information in case +# any news admin wishes to carry it. +# +# URL: http://www.tahina.priv.at/~cm/oe/index.en.html +#newgroup:*:oesterreich.*:doit +#newgroup:group-admin@isc.org:oesterreich.*:drop +#newgroup:tale@*uu.net:oesterreich.*:drop +#rmgroup:*:oesterreich.*:drop + +## OH (Ohio, USA) +checkgroups:trier@ins.cwru.edu:oh.*:doit +newgroup:trier@ins.cwru.edu:oh.*:doit +rmgroup:trier@ins.cwru.edu:oh.*:doit + +## OK (Oklahoma, USA) +checkgroups:quentin@*qns.com:ok.*:doit +newgroup:quentin@*qns.com:ok.*:doit +rmgroup:quentin@*qns.com:ok.*:doit + +## OKINAWA (Okinawa, Japan) +checkgroups:news@opus.or.jp:okinawa.*:doit +newgroup:news@opus.or.jp:okinawa.*:doit +rmgroup:news@opus.or.jp:okinawa.*:doit + +## ONT (Ontario, Canada) +checkgroups:pkern@gpu.utcc.utoronto.ca:ont.*:doit +newgroup:pkern@gpu.utcc.utoronto.ca:ont.*:doit +rmgroup:pkern@gpu.utcc.utoronto.ca:ont.*:doit + +## OPENNEWS (Open News Network) +# URL: http://www.open-news-network.org/ +# *PGP* See comment at top of file. +newgroup:*:opennews.*:drop +rmgroup:*:opennews.*:drop +checkgroups:news@news2.open-news-network.org:opennews.*:verify-news@news2.open-news-network.org +newgroup:news@news2.open-news-network.org:opennews.*:verify-news@news2.open-news-network.org +rmgroup:news@news2.open-news-network.org:opennews.*:verify-news@news2.open-news-network.org + +## OPENWATCOM (Open Watcom compilers) +# Contact: admin@openwatcom.news-admin.org +# URL: http://www.openwatcom.org/ +# Admin group: openwatcom.contributors +# Key URL: http://cmeerw.org/files/openwatcom/pgp-openwatcom.asc +# Syncable server: news.openwatcom.org +# *PGP* See comment at top of file. +newgroup:*:openwatcom.*:drop +rmgroup:*:openwatcom.*:drop +checkgroups:admin@openwatcom.news-admin.org:openwatcom.*:verify-admin@openwatcom.news-admin.org +newgroup:admin@openwatcom.news-admin.org:openwatcom.*:verify-admin@openwatcom.news-admin.org +rmgroup:admin@openwatcom.news-admin.org:openwatcom.*:verify-admin@openwatcom.news-admin.org + +## OPERA (Opera Software, Oslo, Norway) +# Contact: usenet@opera.com +# Syncable server: news.opera.com +# *PGP* See comment at top of file. +newgroup:*:opera.*:drop +rmgroup:*:opera.*:drop +checkgroups:*@opera.com:opera.*:verify-opera-group-admin +newgroup:*@opera.com:opera.*:verify-opera-group-admin +rmgroup:*@opera.com:opera.*:verify-opera-group-admin + +## OTT (Ottawa, Ontario, Canada) +# Contact: onag@pinetree.org +# URL: http://www.pinetree.org/ONAG/ +checkgroups:clewis@ferret.ocunix.on.ca:ott.*:doit +checkgroups:dave@revcan.ca:ott.*:doit +checkgroups:gordon@*pinetree.org:ott.*:doit +checkgroups:news@*pinetree.org:ott.*:doit +checkgroups:news@bnr.ca:ott.*:doit +checkgroups:news@ferret.ocunix.on.ca:ott.*:doit +checkgroups:news@nortel.ca:ott.*:doit +newgroup:clewis@ferret.ocunix.on.ca:ott.*:doit +newgroup:dave@revcan.ca:ott.*:doit +newgroup:gordon@*pinetree.org:ott.*:doit +newgroup:news@*pinetree.org:ott.*:doit +newgroup:news@bnr.ca:ott.*:doit +newgroup:news@ferret.ocunix.on.ca:ott.*:doit +newgroup:news@nortel.ca:ott.*:doit +rmgroup:clewis@ferret.ocunix.on.ca:ott.*:doit +rmgroup:dave@revcan.ca:ott.*:doit +rmgroup:gordon@*pinetree.org:ott.*:doit +rmgroup:news@*pinetree.org:ott.*:doit +rmgroup:news@bnr.ca:ott.*:doit +rmgroup:news@ferret.ocunix.on.ca:ott.*:doit +rmgroup:news@nortel.ca:ott.*:doit + +## PA (Pennsylvania, USA) +# URL: http://www.netcom.com/~rb1000/pa_hierarchy/ +checkgroups:fxp@epix.net:pa.*:doit +newgroup:fxp@epix.net:pa.*:doit +rmgroup:fxp@epix.net:pa.*:doit + +## PBINFO (Paderborn, Germany) +# Contact: news@uni-paderborn.de +# *PGP* See comment at top of file. +newgroup:*:pbinfo.*:drop +rmgroup:*:pbinfo.*:drop +checkgroups:postmaster@upb.de:pbinfo.*:verify-news@uni-paderborn.de +newgroup:postmaster@upb.de:pbinfo.*:verify-news@uni-paderborn.de +rmgroup:postmaster@upb.de:pbinfo.*:verify-news@uni-paderborn.de + +## PERL (Perl Programming Language) +# Contact: newsadmin@perl.org +# URL: http://www.nntp.perl.org/about/ +# Key URL: http://www.nntp.perl.org/about/newsadmin@perl.org.pgp +# Key fingerprint = 438F D1BA 4DCC 3B1A BED8 2BCC 3298 8A7D 8B2A CFBB +# *PGP* See comment at top of file. +newgroup:*:perl.*:drop +rmgroup:*:perl.*:drop +checkgroups:newsadmin@perl.org:perl.*:verify-newsadmin@perl.org +newgroup:newsadmin@perl.org:perl.*:verify-newsadmin@perl.org +rmgroup:newsadmin@perl.org:perl.*:verify-newsadmin@perl.org + +## PGH (Pittsburgh, Pennsylvania, USA) +# Admin group: pgh.config +# *PGP* See comment at top of file. +newgroup:*:pgh.*:drop +rmgroup:*:pgh.*:drop +checkgroups:pgh-config@psc.edu:pgh.*:verify-pgh.config +newgroup:pgh-config@psc.edu:pgh.*:verify-pgh.config +rmgroup:pgh-config@psc.edu:pgh.*:verify-pgh.config + +## PGSQL (Gated PostgreSQL mailing lists) +# Contact: news@postgresql.org +# URL: http://news.hub.org/gpg_public_keys.html +# Key URL: http://news.hub.org/gpg_public_keys.html +# *PGP* See comment at top of file. +newgroup:*:pgsql.*:drop +rmgroup:*:pgsql.*:drop +checkgroups:news@postgresql.org:pgsql.*:verify-news@postgresql.org +newgroup:news@postgresql.org:pgsql.*:verify-news@postgresql.org +rmgroup:news@postgresql.org:pgsql.*:verify-news@postgresql.org + +## PHL (Philadelphia, Pennsylvania, USA) +checkgroups:news@vfl.paramax.com:phl.*:doit +newgroup:news@vfl.paramax.com:phl.*:doit +rmgroup:news@vfl.paramax.com:phl.*:doit + +## PIN (Personal Internauts' NetNews) +checkgroups:pin-admin@forus.or.jp:pin.*:doit +newgroup:pin-admin@forus.or.jp:pin.*:doit +rmgroup:pin-admin@forus.or.jp:pin.*:doit + +## PIPEX (UUNET WorldCom UK) +# Contact: Russell Vincent +checkgroups:news-control@ops.pipex.net:pipex.*:doit +newgroup:news-control@ops.pipex.net:pipex.*:doit +rmgroup:news-control@ops.pipex.net:pipex.*:doit + +## PITT (University of Pittsburgh, PA) +checkgroups:news+@pitt.edu:pitt.*:doit +checkgroups:news@toads.pgh.pa.us:pitt.*:doit +newgroup:news+@pitt.edu:pitt.*:doit +newgroup:news@toads.pgh.pa.us:pitt.*:doit +rmgroup:news+@pitt.edu:pitt.*:doit +rmgroup:news@toads.pgh.pa.us:pitt.*:doit + +## PL (Poland and Polish language) +# URL: http://www.usenet.pl/doc/news-pl-new-site-faq.html +# Admin group: pl.news.admin +# Key URL: http://www.usenet.pl/doc/news-pl-new-site-faq.html#pgp +# *PGP* See comment at top of file. +newgroup:*:pl.*:drop +rmgroup:*:pl.*:drop +checkgroups:michalj@*fuw.edu.pl:pl.*:verify-pl.announce.newgroups +checkgroups:newgroup@usenet.pl:pl.*:verify-pl.announce.newgroups +newgroup:michalj@*fuw.edu.pl:pl.*:verify-pl.announce.newgroups +newgroup:newgroup@usenet.pl:pl.*:verify-pl.announce.newgroups +rmgroup:michalj@*fuw.edu.pl:pl.*:verify-pl.announce.newgroups +rmgroup:newgroup@usenet.pl:pl.*:verify-pl.announce.newgroups + +## PLANET (*LOCAL* -- PlaNet FreeNZ co-operative, New Zealand) +# Contact: office@pl.net +# For local use only, contact the above address for information. +newgroup:*:planet.*:mail +rmgroup:*:planet.*:doit + +## PRIMA (*LOCAL* -- prima.ruhr.de/Prima e.V. in Germany) +# Contact: admin@prima.ruhr.de +# For local use only, contact the above address for information. +newgroup:*:prima.*:mail +rmgroup:*:prima.*:doit + +## PSU (*LOCAL* -- Penn State University, USA) +# Contact: Dave Barr (barr@math.psu.edu) +# For local use only, contact the above address for information. +newgroup:*:psu.*:mail +rmgroup:*:psu.*:doit + +## PT (Portugal and Portuguese language) +# URL: http://www.usenet-pt.org/ +# Admin group: pt.internet.usenet +# Key URL: http://www.usenet-pt.org/control@usenet-pt.org.asc +# *PGP* See comment at top of file. +newgroup:*:pt.*:drop +rmgroup:*:pt.*:drop +checkgroups:pmelo@*.inescc.pt:pt.*:verify-control@usenet-pt.org +newgroup:pmelo@*.inescc.pt:pt.*:verify-control@usenet-pt.org +rmgroup:pmelo@*.inescc.pt:pt.*:verify-control@usenet-pt.org + +## PUBNET (*DEFUNCT* -- ?) +# URL: ftp://ftp.isc.org/pub/usenet/control/pubnet/pubnet.config.gz +# This hierarchy is defunct. Please remove it. +newgroup:*:pubnet.*:mail +rmgroup:*:pubnet.*:doit + +## RELCOM (Commonwealth of Independent States) +# URL: ftp://ftp.relcom.ru/pub/relcom/netinfo/ +# Admin group: relcom.netnews +# Key URL: ftp://ftp.relcom.ru/pub/relcom/netinfo/coordpubkey.txt +# *PGP* See comment at top of file. +newgroup:*:relcom.*:drop +rmgroup:*:relcom.*:drop +checkgroups:coord@*.relcom.ru:relcom.*:verify-relcom.newsgroups +newgroup:coord@*.relcom.ru:relcom.*:verify-relcom.newsgroups +rmgroup:coord@*.relcom.ru:relcom.*:verify-relcom.newsgroups + +## RPI (*LOCAL* -- Rensselaer Polytechnic Institute, Troy, NY, USA) +# Contact: sofkam@rpi.edu +# For local use only, contact the above address for information. +newgroup:*:rpi.*:mail +rmgroup:*:rpi.*:doit + +## SAAR (Saarland Region, Germany) +# URL: http://www.saar-admin-news.de/ +# Admin group: saar.admin.news +# Key URL: http://www.saar-admin-news.de/saar-control.asc +# *PGP* See comment at top of file. +newgroup:*:saar.*:drop +rmgroup:*:saar.*:drop +checkgroups:control@saar-admin-news.de:saar.*:verify-saar-control +newgroup:control@saar-admin-news.de:saar.*:verify-saar-control +rmgroup:control@saar-admin-news.de:saar.*:verify-saar-control + +## SACHSNET (German) +checkgroups:root@lusatia.de:sachsnet.*:doit +newgroup:root@lusatia.de:sachsnet.*:doit +rmgroup:root@lusatia.de:sachsnet.*:doit + +## SAT (San Antonio, Texas, USA) +# Contact: satgroup@endicor.com +# Admin group: sat.usenet.config +# *PGP* See comment at top of file. +newgroup:*:sat.*:drop +rmgroup:*:sat.*:drop +checkgroups:satgroup@endicor.com:sat.*:verify-satgroup@endicor.com +newgroup:satgroup@endicor.com:sat.*:verify-satgroup@endicor.com +rmgroup:satgroup@endicor.com:sat.*:verify-satgroup@endicor.com + +## SBAY (South Bay/Silicon Valley, California) +# URL: http://www.sbay.org/sbay-newsgroups.html +checkgroups:ikluft@thunder.sbay.org:sbay.*:doit +checkgroups:steveh@grafex.sbay.org:sbay.*:doit +newgroup:ikluft@thunder.sbay.org:sbay.*:doit +newgroup:steveh@grafex.sbay.org:sbay.*:doit +rmgroup:ikluft@thunder.sbay.org:sbay.*:doit +rmgroup:steveh@grafex.sbay.org:sbay.*:doit + +## SCHULE (?) +# Contact: schule-admin@roxel.ms.sub.org +# URL: http://home.pages.de/~schule-admin/ +# Admin group: schule.admin +# Key URL: http://www.afaik.de/usenet/admin/schule/control/schule.asc +# Key fingerprint = 64 06 F0 AE E1 46 85 0C BD CA 0E 53 8B 1E 73 D2 +# *PGP* See comment at top of file. +newgroup:*:schule.*:drop +rmgroup:*:schule.*:drop +checkgroups:newsctrl@schule.de:schule.*:verify-schule.konfig +newgroup:newsctrl@schule.de:schule.*:verify-schule.konfig +rmgroup:newsctrl@schule.de:schule.*:verify-schule.konfig + +## SCOT (Scotland) +# URL: http://scot.news-admin.org/ +# Admin group: scot.newsgroups.discuss +# Key URL: http://scot.news-admin.org/signature.html +# *PGP* See comment at top of file. +newgroup:*:scot.*:drop +rmgroup:*:scot.*:drop +checkgroups:control@scot.news-admin.org:scot.*:verify-control@scot.news-admin.org +newgroup:control@scot.news-admin.org:scot.*:verify-control@scot.news-admin.org +rmgroup:control@scot.news-admin.org:scot.*:verify-control@scot.news-admin.org + +## SCOUT (Scouts and guides) +# URL: http://news.scoutnet.org/ +# Admin group: scout.admin +# Key URL: http://news.scoutnet.org/scout-pgpkey.asc +# *PGP* See comment at top of file. +newgroup:*:scout.*:drop +rmgroup:*:scout.*:drop +checkgroups:control@news.scoutnet.org:scout.*:verify-control@news.scoutnet.org +newgroup:control@news.scoutnet.org:scout.*:verify-control@news.scoutnet.org +rmgroup:control@news.scoutnet.org:scout.*:verify-control@news.scoutnet.org + +## SDSU (*LOCAL* -- San Diego State University, CA) +# Contact: Craig R. Sadler +# For local use only, contact the above address for information. +newgroup:*:sdsu.*:mail +rmgroup:*:sdsu.*:doit + +## SE (Sweden) +# Contact: usenet@usenet-se.net +# Admin group: se.internet.news.meddelanden +# Key fingerprint = 68 03 F0 FD 0C C3 4E 69 6F 0D 0C 60 3C 58 63 96 +# *PGP* See comment at top of file. +newgroup:*:se.*:drop +rmgroup:*:se.*:drop +checkgroups:usenet@usenet-se.net:se.*:verify-usenet-se +newgroup:usenet@usenet-se.net:se.*:verify-usenet-se +rmgroup:usenet@usenet-se.net:se.*:verify-usenet-se + +## SEATTLE (Seattle, Washington, USA) +checkgroups:billmcc@akita.com:seattle.*:doit +checkgroups:graham@ee.washington.edu:seattle.*:doit +newgroup:billmcc@akita.com:seattle.*:doit +newgroup:graham@ee.washington.edu:seattle.*:doit +rmgroup:billmcc@akita.com:seattle.*:doit +rmgroup:graham@ee.washington.edu:seattle.*:doit + +## SFNET (Finland) +# Contact: sfnet@cs.tut.fi +# URL: http://www.cs.tut.fi/sfnet/ +# Admin group: sfnet.ryhmat+listat +# Key fingerprint = DE79 33C2 D359 D128 44E5 6A0C B6E3 0E53 6933 A636 +# *PGP* See comment at top of file. +newgroup:*:sfnet.*:drop +rmgroup:*:sfnet.*:drop +checkgroups:sfnet@*cs.tut.fi:sfnet.*:verify-sfnet@cs.tut.fi +newgroup:sfnet@*cs.tut.fi:sfnet.*:verify-sfnet@cs.tut.fi +rmgroup:sfnet@*cs.tut.fi:sfnet.*:verify-sfnet@cs.tut.fi + +## SHAMASH (Jewish) +checkgroups:archives@israel.nysernet.org:shamash.*:doit +newgroup:archives@israel.nysernet.org:shamash.*:doit +rmgroup:archives@israel.nysernet.org:shamash.*:doit + +## SI (The Republic of Slovenia) +# URL: http://www.arnes.si/news/config/ +# Admin group: si.news.announce.newsgroups +# Key URL: http://www.arnes.si/news/config/ +# *PGP* See comment at top of file. +newgroup:*:si.*:drop +rmgroup:*:si.*:drop +checkgroups:news-admin@arnes.si:si.*:verify-si.news.announce.newsgroups +newgroup:news-admin@arnes.si:si.*:verify-si.news.announce.newsgroups +rmgroup:news-admin@arnes.si:si.*:verify-si.news.announce.newsgroups + +## SJ (St. John's, Newfoundland and Labrador, Canada) +# Contact: randy@mun.ca +checkgroups:randy@mun.ca:sj.*:doit +newgroup:randy@mun.ca:sj.*:doit +rmgroup:randy@mun.ca:sj.*:doit + +## SK (Slovakia) +checkgroups:uhlar@ccnews.ke.sanet.sk:sk.*:doit +newgroup:uhlar@ccnews.ke.sanet.sk:sk.*:doit +rmgroup:uhlar@ccnews.ke.sanet.sk:sk.*:doit + +## SLAC (*PRIVATE* -- Stanford Linear Accelerator Center, Stanford, USA) +# Contact: news@news.stanford.edu +# For private use only, contact the above address for information. +newgroup:news@news.stanford.edu:slac.*:mail +rmgroup:news@news.stanford.edu:slac.*:doit + +## SLO (San Luis Obispo, CA) +checkgroups:news@punk.net:slo.*:doit +newgroup:news@punk.net:slo.*:doit +rmgroup:news@punk.net:slo.*:doit + +## SOLENT (Solent region, England) +checkgroups:news@tcp.co.uk:solent.*:doit +newgroup:news@tcp.co.uk:solent.*:doit +rmgroup:news@tcp.co.uk:solent.*:doit + +## SPOKANE (Spokane, Washington, USA) +checkgroups:usenet@news.spokane.wa.us:spokane.*:doit +newgroup:usenet@news.spokane.wa.us:spokane.*:doit +rmgroup:usenet@news.spokane.wa.us:spokane.*:doit + +## SSLUG (*PRIVATE* -- Skåne Sjælland Linux User Group) +# URL: http://en.sslug.dk/ +# For private use only. +newgroup:sparre@sslug.se:sslug.*:mail +rmgroup:sparre@sslug.se:sslug.*:doit + +## STAROFFICE (StarOffice business suite, Sun Microsystems, Inc.) +# Contact: news@starnews.sun.com +# Admin group: staroffice.admin +# Key fingerprint = C6 3E 81 6F 2A 19 D3 84 72 51 F9 1B E3 B9 B2 C9 +# Syncable server: starnews.sun.com +# *PGP* See comment at top of file. +newgroup:*:staroffice.*:drop +rmgroup:*:staroffice.*:drop +checkgroups:news@stardivision.de:staroffice.*:verify-staroffice.admin +newgroup:news@stardivision.de:staroffice.*:verify-staroffice.admin +rmgroup:news@stardivision.de:staroffice.*:verify-staroffice.admin + +## STGT (Stuttgart, Germany) +# URL: http://news.uni-stuttgart.de/hierarchie/stgt/ +# Key URL: http://news.uni-stuttgart.de/hierarchie/stgt/stgt-control.txt +# *PGP* See comment at top of file. +newgroup:*:stgt.*:drop +rmgroup:*:stgt.*:drop +checkgroups:stgt-control@news.uni-stuttgart.de:stgt.*:verify-stgt-control +newgroup:stgt-control@news.uni-stuttgart.de:stgt.*:verify-stgt-control +rmgroup:stgt-control@news.uni-stuttgart.de:stgt.*:verify-stgt-control + +## STL (Saint Louis, Missouri, USA) +checkgroups:news@icon-stl.net:stl.*:doit +newgroup:news@icon-stl.net:stl.*:doit +rmgroup:news@icon-stl.net:stl.*:doit + +## SU (*LOCAL* -- Stanford University, USA) +# Contact: news@news.stanford.edu +# For local use only, contact the above address for information. +newgroup:*:su.*:mail +rmgroup:*:su.*:doit + +## SUNET (Swedish University Network) +checkgroups:ber@*.sunet.se:sunet.*:doit +newgroup:ber@*.sunet.se:sunet.*:doit +rmgroup:ber@*.sunet.se:sunet.*:doit + +## SURFNET (Dutch Universities network) +checkgroups:news@info.nic.surfnet.nl:surfnet.*:doit +newgroup:news@info.nic.surfnet.nl:surfnet.*:doit +rmgroup:news@info.nic.surfnet.nl:surfnet.*:doit + +## SWNET (Sverige, Sweden) +checkgroups:ber@sunic.sunet.se:swnet.*:doit +newgroup:ber@sunic.sunet.se:swnet.*:doit +rmgroup:ber@sunic.sunet.se:swnet.*:doit + +## SYD (Sydney, Australia) +# Contact: ausadmin@aus.news-admin.org +# URL: http://syd.news-admin.org/ +# Key URL: http://aus.news-admin.org/ausadmin.asc +# *PGP* See comment at top of file. +newgroup:*:syd.*:drop +rmgroup:*:syd.*:drop +checkgroups:ausadmin@aus.news-admin.org:syd.*:verify-ausadmin@aus.news-admin.org +newgroup:ausadmin@aus.news-admin.org:syd.*:verify-ausadmin@aus.news-admin.org +rmgroup:ausadmin@aus.news-admin.org:syd.*:verify-ausadmin@aus.news-admin.org + +## SZAF (*PRIVATE* -- German ?) +# Admin group: szaf.admin +# For private use only. +newgroup:hirtenrat@szaf.org:szaf.*:mail +rmgroup:hirtenrat@szaf.org:szaf.*:doit + +## T-NETZ (*DEFUNCT* -- Germany) +# This hierarchy is defunct. Please remove it. +newgroup:*:t-netz.*:mail +rmgroup:*:t-netz.*:doit + +## TAMU (Texas A&M University) +# Contact: Philip Kizer +checkgroups:news@tamsun.tamu.edu:tamu.*:doit +newgroup:news@tamsun.tamu.edu:tamu.*:doit +rmgroup:news@tamsun.tamu.edu:tamu.*:doit + +## TAOS (Taos, New Mexico, USA) +# Contact: Chris Gunn +checkgroups:cgunn@laplaza.org:taos.*:doit +newgroup:cgunn@laplaza.org:taos.*:doit +rmgroup:cgunn@laplaza.org:taos.*:doit + +## TCFN (Toronto Free Community Network, Canada) +checkgroups:news@t-fcn.net:tcfn.*:doit +newgroup:news@t-fcn.net:tcfn.*:doit +rmgroup:news@t-fcn.net:tcfn.*:doit + +## TELE (*LOCAL* -- Tele Danmark Internet) +# Contact: usenet@tdk.net +# For local use only, contact the above address for information. +newgroup:*:tele.*:mail +rmgroup:*:tele.*:doit + +## TERMVAKT (*LOCAL* -- University of Oslo, Norway) +# Contact: jani@ifi.uio.no +# For local use only, contact the above address for information. +newgroup:*:termvakt.*:mail +rmgroup:*:termvakt.*:doit + +## TEST (Local test hierarchy) +# It is not really a good idea for sites to use these since they may occur +# on many unconnected sites. +newgroup:*:test.*:mail +rmgroup:*:test.*:mail + +## THUR (Thuringia, Germany) +# Key fingerprint = 7E 3D 73 13 93 D4 CA 78 39 DE 3C E7 37 EE 22 F1 +# *PGP* See comment at top of file. +newgroup:*:thur.*:drop +rmgroup:*:thur.*:drop +checkgroups:usenet@thur.de:thur.*:verify-thur.net.news.groups +newgroup:usenet@thur.de:thur.*:verify-thur.net.news.groups +rmgroup:usenet@thur.de:thur.*:verify-thur.net.news.groups + +## TNN (*DEFUNCT* -- The Network News, Japan) +# This hierarchy is defunct. Please remove it. +newgroup:netnews@news.iij.ad.jp:tnn.*:mail +newgroup:tnn@iij-mc.co.jp:tnn.*:mail +rmgroup:netnews@news.iij.ad.jp:tnn.*:doit +rmgroup:tnn@iij-mc.co.jp:tnn.*:doit + +## TRIANGLE (Research Triangle, Central North Carolina, USA) +checkgroups:jfurr@acpub.duke.edu:triangle.*:doit +checkgroups:news@news.duke.edu:triangle.*:doit +checkgroups:tas@concert.net:triangle.*:doit +newgroup:jfurr@acpub.duke.edu:triangle.*:doit +newgroup:news@news.duke.edu:triangle.*:doit +newgroup:tas@concert.net:triangle.*:doit +rmgroup:jfurr@acpub.duke.edu:triangle.*:doit +rmgroup:news@news.duke.edu:triangle.*:doit +rmgroup:tas@concert.net:triangle.*:doit + +## TUM (Technische Universitaet Muenchen) +checkgroups:news@informatik.tu-muenchen.de:tum.*:doit +newgroup:news@informatik.tu-muenchen.de:tum.*:doit +rmgroup:news@informatik.tu-muenchen.de:tum.*:doit + +## TW (Taiwan) +checkgroups:ltc@news.cc.nctu.edu.tw:tw.*:doit +newgroup:ltc@news.cc.nctu.edu.tw:tw.*:doit +rmgroup:ltc@news.cc.nctu.edu.tw:tw.*:doit + +## TW.K-12 (Taiwan K-12 Discussion) +checkgroups:k-12@news.nchu.edu.tw:tw.k-12.*:doit +newgroup:k-12@news.nchu.edu.tw:tw.k-12.*:doit +rmgroup:k-12@news.nchu.edu.tw:tw.k-12.*:doit + +## TX (Texas, USA) +checkgroups:eric@cirr.com:tx.*:doit +checkgroups:fletcher@cs.utexas.edu:tx.*:doit +checkgroups:usenet@academ.com:tx.*:doit +newgroup:eric@cirr.com:tx.*:doit +newgroup:fletcher@cs.utexas.edu:tx.*:doit +newgroup:usenet@academ.com:tx.*:doit +rmgroup:eric@cirr.com:tx.*:doit +rmgroup:fletcher@cs.utexas.edu:tx.*:doit +rmgroup:usenet@academ.com:tx.*:doit + +## UCB (University of California Berkeley, USA) +# Contact: Chris van den Berg +# URL: http://www.net.berkeley.edu/usenet/ +# Key URL: http://www.net.berkeley.edu/usenet/usenet.asc +# Key fingerprint = 96 B8 8E 9A 98 09 37 7D 0E EC 81 88 DB 90 29 BF +# *PGP* See comment at top of file. +newgroup:*:ucb.*:drop +rmgroup:*:ucb.*:drop +checkgroups:usenet@agate.berkeley.edu:ucb.*:verify-ucb.news +newgroup:usenet@agate.berkeley.edu:ucb.*:verify-ucb.news +rmgroup:usenet@agate.berkeley.edu:ucb.*:verify-ucb.news + +## UCD (University of California Davis, USA) +checkgroups:usenet@mark.ucdavis.edu:ucd.*:doit +checkgroups:usenet@rocky.ucdavis.edu:ucd.*:doit +newgroup:usenet@mark.ucdavis.edu:ucd.*:doit +newgroup:usenet@rocky.ucdavis.edu:ucd.*:doit +rmgroup:usenet@mark.ucdavis.edu:ucd.*:doit +rmgroup:usenet@rocky.ucdavis.edu:ucd.*:doit + +## UFRA (Unterfranken, Deutschland) +# Contact: news@mayn.de +# URL: http://www.mayn.de/users/news/ +# Admin group: ufra.admin +# Key fingerprint = F7 AD 96 D8 7A 3F 7E 84 02 0C 83 9A DB 8F EB B8 +# Syncable server: news.mayn.de (contact news@mayn.de if permission denied) +# *PGP* See comment at top of file. +newgroup:*:ufra.*:drop +rmgroup:*:ufra.*:drop +checkgroups:news@mayn.de:ufra.*:verify-news.mayn.de +newgroup:news@mayn.de:ufra.*:verify-news.mayn.de +rmgroup:news@mayn.de:ufra.*:verify-news.mayn.de + +## UIUC (*DEFUNCT* -- University of Illinois at Urbana-Champaign, USA) +# Contact: news@ks.uiuc.edu +# This hierarchy is defunct. Please remove it. +newgroup:*:uiuc.*:mail +rmgroup:*:uiuc.*:doit + +## UK (United Kingdom of Great Britain and Northern Ireland) +# URL: http://www.usenet.org.uk/ +# Admin group: uk.net.news.announce +# Key URL: http://www.usenet.org.uk/newsadmins.html +# *PGP* See comment at top of file. +newgroup:*:uk.*:drop +rmgroup:*:uk.*:drop +checkgroups:control@usenet.org.uk:uk.*:verify-uk.net.news.announce +newgroup:control@usenet.org.uk:uk.*:verify-uk.net.news.announce +rmgroup:control@usenet.org.uk:uk.*:verify-uk.net.news.announce + +## UKR (Ukraine) +checkgroups:ay@sita.kiev.ua:ukr.*:doit +newgroup:ay@sita.kiev.ua:ukr.*:doit +rmgroup:ay@sita.kiev.ua:ukr.*:doit + +## UMICH (University of Michigan, USA) +checkgroups:*@*.umich.edu:umich.*:doit +newgroup:*@*.umich.edu:umich.*:doit +rmgroup:*@*.umich.edu:umich.*:doit + +## UMN (University of Minnesota, USA) +newgroup:edh@*.tc.umn.edu:umn.*:doit +newgroup:news@*.tc.umn.edu:umn.*:doit +newgroup:Michael.E.Hedman-1@umn.edu:umn.*:doit +newgroup:edh@*.tc.umn.edu:umn*class.*:mail +newgroup:news@*.tc.umn.edu:umn*class.*:mail +newgroup:Michael.E.Hedman-1@umn.edu:umn*class.*:mail +rmgroup:news@*.tc.umn.edu:umn.*:doit +rmgroup:edh@*.tc.umn.edu:umn.*:doit +rmgroup:Michael.E.Hedman-1@umn.edu:umn.*:doit + +## UN (*HISTORIC* -- The United Nations) +# +# This hierarchy is not entirely defunct, but it receives very little +# traffic and is included primarily for the sake of completeness. +# +# Admin group: un.public.usenet.admin +# *PGP* See comment at top of file. +newgroup:*:un.*:drop +rmgroup:*:un.*:drop +checkgroups:news@news.itu.int:un.*:verify-ungroups@news.itu.int +newgroup:news@news.itu.int:un.*:verify-ungroups@news.itu.int +rmgroup:news@news.itu.int:un.*:verify-ungroups@news.itu.int + +## UO (University of Oregon, Eugene, Oregon, USA) +checkgroups:newsadmin@news.uoregon.edu:uo.*:doit +newgroup:newsadmin@news.uoregon.edu:uo.*:doit +rmgroup:newsadmin@news.uoregon.edu:uo.*:doit + +## US (United States of America) +# Contact: us-control@lists.killfile.org +# Admin group: us.config +# Key fingerprint = BB96 EB2C CFD0 75C8 E9DE C2C2 1DA2 9D87 B73C AF1B +# *PGP* See comment at top of file. +newgroup:*:us.*:drop +rmgroup:*:us.*:drop +checkgroups:us-control@lists.killfile.org:us.*:verify-us-control@lists.killfile.org +newgroup:us-control@lists.killfile.org:us.*:verify-us-control@lists.killfile.org +rmgroup:us-control@lists.killfile.org:us.*:verify-us-control@lists.killfile.org + +## UT (*LOCAL* -- University of Toronto, Canada) +# URL: http://www.utoronto.ca/ns/utornews/ +#newgroup:news@ecf.toronto.edu:ut.*:doit +#newgroup:news@ecf.toronto.edu:ut.class.*:mail +#rmgroup:news@ecf.toronto.edu:ut.*:doit + +## UTA (Finnish) +checkgroups:news@news.cc.tut.fi:uta.*:doit +newgroup:news@news.cc.tut.fi:uta.*:doit +rmgroup:news@news.cc.tut.fi:uta.*:doit + +## UTEXAS (*LOCAL* -- University of Texas, USA) +# URL: http://www.utexas.edu/its/usenet/index.php +newgroup:fletcher@cs.utexas.edu:utexas.*:doit +newgroup:news@geraldo.cc.utexas.edu:utexas.*:doit +newgroup:fletcher@cs.utexas.edu:utexas*class.*:mail +newgroup:news@geraldo.cc.utexas.edu:utexas*class.*:mail +rmgroup:fletcher@cs.utexas.edu:utexas.*:doit +rmgroup:news@geraldo.cc.utexas.edu:utexas.*:doit + +## UTWENTE (*LOCAL* -- University of Twente, Netherlands) +# Contact: newsmaster@utwente.nl +# For local use only, contact the above address for information. +newgroup:*:utwente.*:mail +rmgroup:*:utwente.*:doit + +## UVA (*LOCAL* -- University of Virginia, USA) +# Contact: usenet@virginia.edu +# For local use only, contact the above address for information. +newgroup:*:uva.*:mail +rmgroup:*:uva.*:doit + +## UW (University of Waterloo, Canada) +# Admin group: uw.newsgroups +# Syncable server: news.uwaterloo.ca +# *PGP* See comment at top of file. +newgroup:*:uw.*:drop +rmgroup:*:uw.*:drop +checkgroups:newsgroups@news.uwaterloo.ca:uw.*:verify-uw.newsgroups +newgroup:newsgroups@news.uwaterloo.ca:uw.*:verify-uw.newsgroups +rmgroup:newsgroups@news.uwaterloo.ca:uw.*:verify-uw.newsgroups + +## UWARWICK (*LOCAL* -- University of Warwick, UK) +# Contact: Jon Harley +# For local use only, contact the above address for information. +newgroup:*:uwarwick.*:mail +rmgroup:*:uwarwick.*:doit + +## UWO (University of Western Ontario, London, Canada) +# URL: http://www.uwo.ca/its/news/groups.uwo.html +checkgroups:reggers@julian.uwo.ca:uwo.*:doit +newgroup:reggers@julian.uwo.ca:uwo.*:doit +rmgroup:reggers@julian.uwo.ca:uwo.*:doit + +## VAN (Vancouver, British Columbia, Canada) +checkgroups:bc_van_usenet@fastmail.ca:van.*:doit +newgroup:bc_van_usenet@fastmail.ca:van.*:doit +rmgroup:bc_van_usenet@fastmail.ca:van.*:doit + +## VEGAS (Las Vegas, Nevada, USA) +checkgroups:cshapiro@netcom.com:vegas.*:doit +checkgroups:doctor@netcom.com:vegas.*:doit +newgroup:cshapiro@netcom.com:vegas.*:doit +newgroup:doctor@netcom.com:vegas.*:doit +rmgroup:cshapiro@netcom.com:vegas.*:doit +rmgroup:doctor@netcom.com:vegas.*:doit + +## VGC (Japan groups?) +checkgroups:news@isl.melco.co.jp:vgc.*:doit +newgroup:news@isl.melco.co.jp:vgc.*:doit +rmgroup:news@isl.melco.co.jp:vgc.*:doit + +## VMSNET (VMS Operating System) +checkgroups:cts@dragon.com:vmsnet.*:doit +newgroup:cts@dragon.com:vmsnet.*:doit +rmgroup:cts@dragon.com:vmsnet.*:doit + +## WA (Western Australia) +# Contact: ausadmin@aus.news-admin.org +# URL: http://wa.news-admin.org/ +# Key URL: http://aus.news-admin.org/ausadmin.asc +# *PGP* See comment at top of file. +newgroup:*:wa.*:drop +rmgroup:*:wa.*:drop +checkgroups:ausadmin@aus.news-admin.org:wa.*:verify-ausadmin@aus.news-admin.org +newgroup:ausadmin@aus.news-admin.org:wa.*:verify-ausadmin@aus.news-admin.org +rmgroup:ausadmin@aus.news-admin.org:wa.*:verify-ausadmin@aus.news-admin.org + +## WADAI (Japanese ?) +checkgroups:kohe-t@*wakayama-u.ac.jp:wadai.*:doit +newgroup:kohe-t@*wakayama-u.ac.jp:wadai.*:doit +rmgroup:kohe-t@*wakayama-u.ac.jp:wadai.*:doit + +## WALES (Wales) +# Contact: committee@wales-usenet.org +# URL: http://www.wales-usenet.org/ +# Admin group: wales.usenet.config +# Key URL: http://www.wales-usenet.org/english/newsadmin.txt +# Key fingerprint = 2D 9E DE DF 12 DA 34 5C 49 E1 EE 28 E3 AB 0D AD +# *PGP* See comment at top of file. +newgroup:*:wales.*:drop +rmgroup:*:wales.*:drop +checkgroups:control@wales-usenet.org:wales.*:verify-wales-usenet +newgroup:control@wales-usenet.org:wales.*:verify-wales-usenet +rmgroup:control@wales-usenet.org:wales.*:verify-wales-usenet + +## WASH (Washington State, USA) +checkgroups:graham@ee.washington.edu:wash.*:doit +newgroup:graham@ee.washington.edu:wash.*:doit +rmgroup:graham@ee.washington.edu:wash.*:doit + +## WEST-VIRGINIA (West Virginia, USA) +checkgroups:bryan27@hgo.net:west-virginia.*:doit +newgroup:mark@bluefield.net:west-virginia.*:doit +newgroup:bryan27@hgo.net:west-virginia.*:doit +rmgroup:mark@bluefield.net:west-virginia.*:doit +rmgroup:bryan27@hgo.net:west-virginia.*:doit + +## WORLDONLINE (*LOCAL* -- ?) +# Contact: newsmaster@worldonline.nl +# For local use only, contact the above address for information. +newgroup:*:worldonline.*:mail +rmgroup:*:worldonline.*:doit + +## WPG (Winnipeg, Manitoba, Canada) +# Contact: Gary Mills +checkgroups:mills@cc.umanitoba.ca:wpg.*:doit +newgroup:mills@cc.umanitoba.ca:wpg.*:doit +rmgroup:mills@cc.umanitoba.ca:wpg.*:doit + +## WPI (*LOCAL* -- Worcester Polytechnic Institute, Worcester, MA) +# For local use only. +newgroup:aej@*.wpi.edu:wpi.*:mail +rmgroup:aej@*.wpi.edu:wpi.*:doit + +## WU (Washington University at St. Louis, MO) +checkgroups:*@*.wustl.edu:wu.*:doit +newgroup:*@*.wustl.edu:wu.*:doit +rmgroup:*@*.wustl.edu:wu.*:doit + +## X-PRIVAT (Italian) +# Contact: dmitry@x-privat.org +# URL: http://www.x-privat.org/ +# Admin group: x-privat.info +# Key URL: http://www.x-privat.org/dmitry.asc +# Key fingerprint = 9B 0A 7E 68 27 80 C7 96 47 6B 03 90 51 05 68 43 +# *PGP* See comment at top of file. +newgroup:*:x-privat.*:drop +rmgroup:*:x-privat.*:drop +checkgroups:dmitry@x-privat.org:x-privat.*:verify-dmitry@x-privat.org +newgroup:dmitry@x-privat.org:x-privat.*:verify-dmitry@x-privat.org +rmgroup:dmitry@x-privat.org:x-privat.*:verify-dmitry@x-privat.org + +## XS4ALL (XS4ALL, Netherlands) +# Contact: XS4ALL Newsmaster +checkgroups:news@xs4all.nl:xs4all.*:doit +newgroup:news@xs4all.nl:xs4all.*:doit +rmgroup:news@xs4all.nl:xs4all.*:doit + +## YORK (*LOCAL* -- York University, Toronto, ON) +# Contact: Peter Marques +# For local use only, contact the above address for information. +newgroup:*:york.*:mail +rmgroup:*:york.*:doit + +## Z-NETZ (German non-Internet based network) +# Contact: teko@dinoex.sub.org +# Admin group: z-netz.koordination.user+sysops +# Key URL: ftp://ftp.dinoex.de/pub/keys/z-netz.koordination.user+sysops.asc +# *PGP* See comment at top of file. +newgroup:*:z-netz.*:drop +rmgroup:*:z-netz.*:drop +checkgroups:teko@dinoex.sub.org:z-netz.*:verify-z-netz.koordination.user+sysops +newgroup:teko@dinoex.sub.org:z-netz.*:verify-z-netz.koordination.user+sysops +rmgroup:teko@dinoex.sub.org:z-netz.*:verify-z-netz.koordination.user+sysops + +## ZA (South Africa) +checkgroups:ccfj@hippo.ru.ac.za:za.*:doit +checkgroups:root@duvi.eskom.co.za:za.*:doit +newgroup:ccfj@hippo.ru.ac.za:za.*:doit +newgroup:root@duvi.eskom.co.za:za.*:doit +rmgroup:ccfj@hippo.ru.ac.za:za.*:doit +rmgroup:root@duvi.eskom.co.za:za.*:doit + +## ZER (*DEFUNCT* -- Germany) +# This hierarchy is defunct. Please remove it. +newgroup:*:zer.*:mail +rmgroup:*:zer.*:doit --- inn-1.7.2q.orig/extra/doc/inn-README +++ inn-1.7.2q/extra/doc/inn-README @@ -0,0 +1,212 @@ + + Configuring Debian GNU/Linux's INN package + + 27th July 1994 Ian Jackson + 06 March 1996 Miquel van Smoorenburg + 07 December 1996 Miquel van Smoorenburg + 18 Aug 1997 Miquel van Smoorenburg + +0. INTRODUCTION + + Following the installation of a new INN package you will have to set + up several files to reflect your system. I'm afraid that I can't do + this automatically, as it's too complicated. + + Apart from this file, a lot of information which you may find + useful comes with the standard INN distribution. This has been + installed in the usual places on your Debian system: + + * There is a file `inn-Install.ms.gz' in /usr/doc/inn, which can be + read using zcat | nroff -ms and describes the installation and + configuration of INN. NB: ignore the parts about compiling the + program - this has been done for you by the Debian maintainers. + + * There are manpages for all of the configuration files and for all of + the news processing programs. To find out about a particular + configuration file format, type man 5 filename (section 5 is the + manual section for file formats). You can get a complete list of + manpages by using the command "dpkg -L inn inews | grep usr/man". + + * The INN FAQ has been installed in /usr/doc/inn/INN-faq_part[1-9].gz + + This file was written mainly to assist people who are permanently + IP-connected and wish to exchange news via NNTP, the Network News + Transfer Protocol. If you want to do something else you should still + read it, but look at the sources listed above for further information. + + If you feel this document is inaccurate or incomplete please send + email to the current INN package maintainer. Submissions for inclusion are + welcomed ! + +1. CONFIGURATION + + Most of the files referred to here are in the /etc/news directory; + this is where almost all the news configuration files are stored. + Each configuration file contains a comment at the top describing its + contents. + + Either use "su" to become the news user (recommended), or make sure all + files you create and update get chown'ed to the news user (news:news). + +1.1 /etc/news/inn.conf + + This file will be setup by the `postinst' script of the INN + installation, but you can always edit it by hand. + + You should replace the `organization' line with something appropriate, + describing the site or organisation your system is part of. + + If you're running a `single machine' site, where the mail address is + the name of the actual machine, rather than of the containing domain, + you should put the full name of your machine, with all the domain + components in `fromhost' and `pathhost'. You can leave `server' set + to `localhost' or change it to the name of your machine. + + If you're running a site where the machines are generally named + *.dcs.ufoo.edu or some such, but where the mail addresses are + user@dcs.ufoo.edu, you should do something like the following: + + organization: University of Foo, Department of Computer Science + fromhost: dcs.ufoo.edu + pathhost: dcs.ufoo.edu + server: news.dcs.ufoo.edu + + This assumes that the machine you're running the news system on is + called `news' - usually it is a good thing to have a DNS alias `news' + for your news server. Do not forget to add "news.dcs.ufoo.edu" to + the "nnrp.access" file. + + You can leave moderatormailer unset in this file; it will be dealt + with by the `moderators' file, which comes set up to mail everything + it doesn't know about to uunet. + +1.2. hosts.nntp + + This lists the sites that may connect to you to transfer news in bulk + - ie, your feed sites. There is a feature here to use passwords, but + in practice this is rarely used. + + You should list in this file at least the machine names (or aliases) + of any of your feed sites. This may include your IP service provider + and anyone else you've agreed to do a bilateral feed with. + + Note that the machine people send out news from may not be the same as + the one they receive it at. The address here is the one that *they* + will be connecting *to* *you* from, to transfer news from them to you + via NNTP. + + You have to list each site with a colon after it. + +1.3 newsfeeds + + This lists the people to whom you feed news, and specifies which + groups and distributions you wish to receive. + + See newsfeeds(5) (ie, type man 5 newsfeeds) for complete details. + + The ME entry describes what articles you want to accept; the other + entries describe what you'll offer to that `downstream' site. Usually + the `ME' entry on the receiving end of a feed should match the + corresponding line of the sending end's feed. Remember that you have to + tell them what groups to send to you (of course, the people + you're peering with may be using C News or even B News instead of INN, + so their files may be formatted differently). + + If you just want to send local postings back to your main feed site + something along the lines of the example `feed all local non-internal + postings' entry will probably serve quite well. + + If you wish to be someone's primary or backup feed I recommend you + install the `innfeed' package too and use that to feed them. In + that case you will probably want to use that to send news back to your + primary feed site as well. + +1.4 expire.ctl + + How long you can keep which groups for depends on how much disk space + you have. All I can recommend is try it and see; any recommendations + I make will be wrong for you by the time you read this, because the + set of groups you receive will be different, and because total news + traffic is doubling about once a year. + + You will probably want to set a lower expire time on binaries groups. + + Again, see the manpage for details of how to format the file. + +1.5 nnrp.access + + This controls which sites can read news from you using NNTP-based + newsreader programs. + + The default setup allows reading and posting only via the loopback network + interface. You probably want to add an entry for your entire domain + by using *.yourdomain_here.com. Do not add a wildcard entry for the + entire Internet; open newsservers are a no-no in most situations nowadays. + +1.6 /etc/news/whoami and /etc/news/organization + + These are used by trn and some other newsreading clients. They should + contain the same information as the inn.conf fromhost: and + organization: entries, respectively. + + Each one should just be the data in question (hostname or intended + contents of Organization field) followed by a newline. + +1.7 /var/lib/news/active + + If you are setting up a new news system you will have to obtain a list + of newsgroups, known as an `active' file. There are basically two ways + to do this: + + * You get an active file from your provider or you create one by hand. + In this case, you need to stop inn, fix up the active file and start + it again. You do this in the following way: + + cd /var/lib/news + /etc/init.d/inn start + perl -pe 's/ \d+ \d+ / 0000000000 0000000001 /' > active < active.sample + /etc/init.d/inn stop + + The perl command sets the numbers in the active file to zero for + all groups. + + * You want to copy the active file from the NNTP server of your provider. + Use the "actsync" program for this. Read the manual page for "actsync". + You may want to adjust the /etc/news/actsync.ign file. Then run actsync + with a command line like this: + + actsync -i /etc/news/actsync.ign -p 0 -o x -z 0 news.myprovider.com + + Actsync is located in /usr/lib/news/bin, so you might want to put that + in your PATH or start it as /usr/lib/news/bin/actsync -i ..... + +1.8 /var/lib/news/history + + You will also have to create an empty history database - type: + + touch /var/lib/news/history + /usr/lib/news/bin/makehistory -ro + + If you're installing INN as a replacement for an existing news system, + which already has active and history files and a news spool, you can + keep those. You'll have to run makehistory as above though, unless + you were already using a dbz history file. + + Remember to stop the news system before messing with these files! (And + to restart it later on, ofcourse). Also make sure that the + /var/lib/news/history* files are owned by news:news. + +2. FAMOUS LAST WORDS. + + INN has difficulty coping with the case where one of your feed sites - + ie, one of the sites that offer news to you via NNTP - also has users + who wish to read news from your server. This is because it actually + has two NNTP server programs, one for feed sites and one for reader + hosts. It is possible to switch from the feeder server to the reader + one with a MODE READER command in the NNTP protocol, and many clients + are now compiled to do this. I'm afraid I don't know what to suggest + if the clients on the feed site don't have this capability. + + Thanks to Tim Morley for some of the examples in + this document. + --- inn-1.7.2q.orig/extra/doc/innhelp.tomk.txt +++ inn-1.7.2q/extra/doc/innhelp.tomk.txt @@ -0,0 +1,244 @@ +From: tomk@westgac3.dragon.com +Subject: Submission for INN doc file +Date: Tue, 9 Jan 1996 00:28:15 -0500 (EST) + +Here is a revised file for configuring INN for UUCP node under DEBIAN. +===================== Beginning of Document =========================== + + Configuring Debian GNU/Linux's INN package + 27th July 1994 Ian Jackson + Updated 8 Dec 1995 Thomas Kocourek + +Following the installation of a new INN package you will have to set +up several files to reflect your system. I'm afraid that I can't do +this automatically, as it's too complicated. + +Apart from this file, a lot of information which you may find +useful comes with the standard INN distribution. This has been +installed in the usual places on your Debian system: + +* There is a file `inn-Install.ms.gz' in /usr/doc/news, which can be +read using zcat | nroff -ms and describes the installation and +configuration of INN. NB: ignore the parts about compiling the +program - this has been done for you by the Debian maintainers. + +* There are manpages for all of the configuration files and for all of +the news processing programs. To find out about a particular +configuration file format, type man 5 filename (section 5 is the +manual section for file formats). + +* The INN and `news overview file' FAQs have been installed in +/usr/doc/inn-faq-[1234].gz and /usr/doc/inn-nov-faq. + +This file was written mainly to assist people who are permanently +IP-connected and wish to exchange news via NNTP, the Network News +Transfer Protocol. If you want to do something else you should still +read it, but look at the sources listed above for further information. + +* Note: This document includes information needed to get INN to work on +* a UUCP-only node. TK + +If you feel this document is inaccurate or incomplete please send +email to . Submissions for inclusion are +welcomed ! + +Most of the files referred to here are in the /etc/news directory; +this is where almost all the news configuration files are stored. +Each configuration file contains a comment at the top describing its +contents. + +1. /etc/news/inn.conf + +You should replace the `organization' line with something appropriate, +describing the site or organisation your system is part of. + +If you're running a `single machine' site, where the mail address is +the name of the actual machine, rather than of the containing domain, +you should put the full name of your machine, with all the domain +components in `fromhost' and `pathhost'. You can leave `server' set +to `localhost' or change it to the name of your machine. + +If you're running a site where the machines are generally named +*.dcs.ufoo.edu or some such, but where the mail addresses are +user@dcs.ufoo.edu, you should do something like the following: + organization: University of Foo, Department of Computer Science + fromhost: dcs.ufoo.edu + pathhost: dcs.ufoo.edu + server: news +This assumes that the machine you're running the news system on is +called `news' - usually it is a good thing to have a DNS alias `news' +for your news server. + +You can leave moderatormailer unset in this file; it will be dealt +with by the `moderators' file, which comes set up to mail everything +to uunet. + +2. hosts.nntp + +This lists the sites that may connect to you to transfer news in bulk +- ie, your feed sites. There is a feature here to use passwords, but +in practice this is rarely used. + +You should list in this file at least the machine names (or aliases) +of any of your feed sites. This may include your IP service provider +and anyone else you've agreed to do a bilateral feed with. + +Note that the machine people send out news from may not be the same as +the one they receive it at. The address here is the one that *they* +will be connecting *to* *you* from, to transfer news from them to you +via NNTP. + +You have to list each site with a colon after it. + +* UUCP: Add your feed site as per above. Also, Add that same feed to the +* /etc/hosts file. For the IP address, either use the site's actual IP +* address (preferred) or use a bogus address (like 128.1.1.1). Keep in mind +* that you will have to change the bogus address if you get a SLIP, PPP, +* or TCP/IP connection. If you have more than one feed, add each additional +* feed to both files per above instructions. Make sure all IP addresses are +* unique! + +3. newsfeeds + +This lists the people to whom you feed news, and specifies which +groups and distributions you wish to receive. + +See newsfeeds(5) (ie, type man 5 newsfeeds) for complete details. + +The ME entry describes what articles you wish to receive; the other +entries describe what you'll offer to that `downstream' site. Usually +the `ME' entry on the receiving end of a feed should match the +corresponding line of the sending end's feed (of course, the people +you're peering with may be using C News or even B News instead of INN, +so their files may be formatted differently). + +If you just want to send local postings back to your main feed site +something along the lines of the example `feed all local non-internal +postings' entry will probably serve quite well. + +If you wish to be someone's primary or backup feed I recommend you +install the `nntplink' package as well and use that to feed them. In +that case you will probably want to use that to send news back to your +primary feed site, as well. + +* UUCP: Add the 'dummy' site entry (dummy-feed:!*::) whether or not you feed +* other UUCP sites. For each UUCP site that you feed, add an entry using the +* format shown within the file. Additionally, create a home directory under +* /var/spool/uucp for each site that you feed. Insure that the owner & group +* attributes for the directories belong to 'uucp'. If you wish to post news +* articles, you will need to add your feed as a site to be fed news. Otherwise, +* your postings will stay local. + +4. expire.ctl + +How long you can keep which groups for depends on how much disk space +you have. All I can recommend is try it and see; any recommendations +I make will be wrong for you by the time you read this, because the +set of groups you receive will be different, and because total news +traffic is doubling about once a year. + +You will probably want to set a lower expire time on binaries groups. + +Again, see the manpage for details of how to format the file. + +5. nnrp.access + +This controls which sites can read news from you using NNTP-based +newsreader programs. + +The default setup allows reading from anywhere and posting only via +the loopback network interface. + +You may wish to allow posting from a wider range of hosts (for +example, you may wish to allow posting by default from all of the +hosts in your organisation, or you may wish to require the admins of +those hosts to contact you to get posting access); you may also wish +to restrict the range of sites which may connect to you to read news. + +6. /etc/news/whoami and /etc/news/organization + +These are used by trn and some other newsreading clients. They should +contain the same information as the inn.conf fromhost: and +organization: entries, respectively. + +Each one should just be the data in question (hostname or intended +contents of Organization field) followed by a newline. + +7. /var/lib/news/active and /var/lib/news/history + +If you are setting up a new news system you will have to obtain a list +of newsgroups, known as an `active' file. Your newsfeed provider will +probably be the best place to go. Use `su' to become the `news' user +and create your active file by feeding the file they give you into: + perl -ne 's/ \d+ \d+ / 0000000000 0000000001 /' >active + +* NOTE: the above script _only_ works if active file is the true active file +* from your feed. If you feed sends you a list of news groups, you will have +* to edit it by hand to create an active file. As stated earlier in this file, +* use man 5 active for the correct format. + +You will also have to create an empty history database - type: + touch /var/lib/news/history + /usr/lib/news/bin/makehistory -ro + +If you're installing INN as a replacement for an existing news system, +which already has active and history files and a news spool, you can +keep those. You'll have to run makehistory as above though, unless +you were already using a dbz history file. + +8. Enabling things, /etc/rc.d/rc.news and /etc/rc.d/rc.local. + +After you have set everything up you should add a line + /etc/rc.d/rc.news +to /etc/rc.d/rc.local. This will ensure that the news system is +started at boot time. You will probably also want to start it +manually this once by invoking /etc/rc.d/rc.news directly, rather than +rebooting. + +* UPDATE: The news startup is stored in /etc/rc.misc. Change directory +* to /etc/rc2.d and create a symlink to it like this: + + ln -s ../rc.misc/news S88news + +When you have verified that your news system appears to be running +correctly you should ask your feed sites to start offering news to +you. + +INN has difficulty coping with the case where one of your feed sites - +ie, one of the sites that offer news to you via NNTP - also has users +who wish to read news from your server. This is because it actually +has two NNTP server programs, one for feed sites and one for reader +hosts. It is possible to switch from the feeder server to the reader +one with a MODE READER command in the NNTP protocol, and many clients +are now compiled to do this. I'm afraid I don't know what to suggest +if the clients on the feed site don't have this capability. + +* UUCP: additional information - Edit the /etc/news/crontab file and add + + 03 * * * * /var/lib/news/send-uucp + +* to the end of the file. Then invoke the crontab command like this: + + crontab -u news /etc/news/crontab + +* and update the crontab for news. Thus at 3 minutes past the hour, any +* outbound news articles will be batched for the UUCICO daemon. Also, if +* you want the UUCICO daemon to call your feed automatically, you can do +* this one of several ways: 1) edit /etc/crontab and add a entry for +* calling the UUCICO daemon, 2) use the 'at' command, 3) create a crontab +* for 'root' with the necessary line to call UUCICO and invoke the 'crontab' +* command. UUCICO should only be called from the root account. Now, if you +* wish to manually call UUCICO, create a shell script with the necessary +* line to invoke UUCICO. Then use chmod 700 to insure that only the +* root account (or su -) can execute the script. + +Thanks to Tim Morley for some of the examples in +this document. + +I wish to thank both Ian and Tim for this document. I can be reached at +. Thomas Kocourek +============================ End of Document ================================== + +-= Sent by Debian Linux =- ++ Thomas Kocourek KD4CIK + + tomk@westgac3.dragon.com --- inn-1.7.2q.orig/debian/changelog +++ inn-1.7.2q/debian/changelog @@ -0,0 +1,585 @@ +inn (1:1.7.2q-39) unstable; urgency=low + + * Updated patch fix_perl510: backported from 2.x the changesets 7937, 7939 + and 8421. Thanks to Julien ÉLIE. (Closes: #541130) + * Link again with libpthread the binaries embedding perl because + binutils-gold correctly requires it. (Closes: #554920) + * Made the old shell control message handlers use bash. (Closes: #530104) + * Updated control.ctl. + + -- Marco d'Itri Sat, 26 Dec 2009 02:48:13 +0100 + +inn (1:1.7.2q-38) unstable; urgency=medium + + * Backported fixes from 2.4: + + New patch fix_ad_flag: honour the Ad newsfeeds flag. + + Updated patch fix_perl510: use newSVpvn_share to create the article + body SV much more efficiently. + + -- Marco d'Itri Wed, 10 Sep 2008 02:07:47 +0200 + +inn (1:1.7.2q-37) unstable; urgency=medium + + * Clean up /var/lib/news/ in the purge target instead of the remove target. + (Closes: #493824) + + -- Marco d'Itri Thu, 28 Aug 2008 04:08:44 +0200 + +inn (1:1.7.2q-36) unstable; urgency=low + + * Fixed the malformed poison+remember_trash patch which confused the + new dpkg. (Closes: #485368) + * Updated patch 1_perl_filter_patch: added more headers. + * Updated patch fix_perl510 with fixes/cleanups from 2.4.5 (and the + INN::syslog callback). + + -- Marco d'Itri Tue, 01 Jul 2008 02:29:46 +0200 + +inn (1:1.7.2q-35) unstable; urgency=high + + * Fixed a FTBFS Heisenbug. (Closes: #481867) + + -- Marco d'Itri Tue, 20 May 2008 02:51:38 +0200 + +inn (1:1.7.2q-34) unstable; urgency=high + + * Packaging converted to quilt. + * New patch fix_perl510: fixes segfaults with perl 5.10, hopefully + without introducing new bugs. If you know about XS, please help! + + -- Marco d'Itri Tue, 06 May 2008 12:56:04 +0200 + +inn (1:1.7.2debian-33) unstable; urgency=medium + + * Updated control.ctl. + * Fixed the init script to create /var/run/innd/ instead of /var/run/news/. + * New patch newsgroups_whitespace: ignore whitespace in Newsgroups headers + instead of rejecting the article. + * Sanitize the perl ccopts and ldopts to prevent linking nnrpd with -lm. + * Updated patch man_sections: fix some ten years old syntax errors in + the man pages. + * Do not use --stop and --exec in the init script because the on-disk + binary changes after upgrades. + + -- Marco d'Itri Sun, 20 Apr 2008 03:43:16 +0200 + +inn (1:1.7.2debian-32) unstable; urgency=low + + * New patch gnukfreebsd_port: fixes FTBFS on GNU/kFreeBSD. (Closes: #414980) + + -- Marco d'Itri Tue, 07 Aug 2007 18:59:52 +0200 + +inn (1:1.7.2debian-31) unstable; urgency=medium + + * Create /var/run/news in the init script if it does not exist. + * New patch posix_arguments: makes innstat use tail -n. + * Updated control.ctl. + + -- Marco d'Itri Fri, 18 Aug 2006 18:46:30 +0200 + +inn (1:1.7.2debian-30) unstable; urgency=medium + + * Fixed a gcc 4 FTBFS bug. (Closes: #297185) + * Do not fail in postrm if /var/log/news/ does not exist. (Closes: #313354) + * Do not reference rc.news in innwatch(8). (Closes: #286062) + * Updated the control.ctl and moderators files. + + -- Marco d'Itri Sun, 31 Jul 2005 12:54:04 +0200 + +inn (1:1.7.2debian-29) unstable; urgency=medium + + * Conflict with inn2-dev. (Closes: #274787) + * New patch rc_initialise_everything: fixes some uninitialised variables + in rc.c. Patch courtesy of Devin Carraway. (Closes: #277459) + * Fixed a command option in inn-README.gz. (Closes: #267125) + * Fixed the keyring path in pgpverify. + * New patch man_sections: fixes the section of some man pages. + + -- Marco d'Itri Tue, 26 Oct 2004 21:14:51 +0200 + +inn (1:1.7.2debian-28) unstable; urgency=medium + + * Depend on exim4 instead of exim. (Closes: #228585) + * Make postrm not fail if /var/spool/news does not exist. (Closes: #244404) + * New patch use_system_prototypes: fixes FTBFS with gcc-3.4. + (Closes: #258959) + * Updated patch rnews_reject_reason to fix mixed use of buffered and + non-buffered I/O. + + -- Marco d'Itri Mon, 12 Jul 2004 18:33:06 +0200 + +inn (1:1.7.2debian-27) unstable; urgency=high + + * Compiled with new perl. + + -- Marco d'Itri Wed, 29 Oct 2003 11:03:57 +0100 + +inn (1:1.7.2debian-26) unstable; urgency=medium + + * Fix postinst failure on new installs. (Closes: #215586) + * Stop providing inewsinn, other packages should depend on + "inn2-inews | inews" instead. + + -- Marco d'Itri Tue, 14 Oct 2003 20:29:16 +0200 + +inn (1:1.7.2debian-25) unstable; urgency=medium + + * Merge the inewsinn package in the inn package and kill the inn-dev + package. (Closes: #210772) + + -- Marco d'Itri Sat, 27 Sep 2003 00:32:34 +0200 + +inn (1:1.7.2debian-24) unstable; urgency=medium + + * Fixed a bug introduced in 1:1.7.2debian-22 which caused the creation + of broken X-Trace headers. + * Fixed a bug in the recommend_ID patch which caused articles without + a Message-ID to be refused by innd. + * New patch: overlapping_strcpy. + * Stop creating /etc/news/organization if it does not exist, as it's + not even used by this inews. (Closes: #210470) + + -- Marco d'Itri Fri, 12 Sep 2003 13:48:50 +0200 + +inn (1:1.7.2debian-23) unstable; urgency=medium + + * Fixed the bug introduced in 1:1.7.2-14 by the path_audit patch which + caused random segfaults when hosts.nntp was reloaded. + * Fixed the innreport path in scanlogs. + * Added support for a inewsport config file option. (Closes: #54975) + * Remove /etc/news/crontab and add /etc/cron.d/inn. + * Updated the default control.ctl from ftp.isc.org. + + -- Marco d'Itri Wed, 20 Aug 2003 04:46:14 +0200 + +inn (1:1.7.2debian-22) unstable; urgency=medium + + * Package converted to DBS. + * Depends on perlapi-5.8.0. (Closes: #187716) + * inn does not need libgdbm-dev. (Closes: #199591) + * Sub-processes are now niced to 10. + * Moved send-* symlinks from /usr/lib/news/ to /usr/lib/news/bin/. + * Applied the poison patch (from rra's poison+remember_trash patch). + * Updated send-uucp.pl from INN 2.4. + * Updated innreport from INN 2.4. + * Updated default control.ctl. + * Added timer support to the perl filter. + + -- Marco d'Itri Sun, 6 Jul 2003 14:36:14 +0200 + +inn (1:1.7.2-21) unstable; urgency=medium + + * Switch back to custom memrchr() to unbreak XOVER (Closes: #169777). + * Backported controlchan support from INN 2 (Closes: #14677, #149042). + * Backported the INN 2 code to allow modifying headers in the nnrpd + perl filter. Now the body is available in $body. + * Applied two small patches by Olaf Titz to tell clients the recommended + Message-ID and have a more precise timers on usually idle systems. + * Added NNTP-Posting-Date to the list of headers which cannot be set + with POST. + * Make innreport generate valid HTML (see #166372). + * Added support for $INND_BIND_ADDRESS. + * Updated control.ctl. + * Renamed the nntpport inn.conf entry to port. + * Added support for the INN 2 bindaddress entry. + + -- Marco d'Itri Wed, 20 Nov 2002 21:47:35 +0100 + +inn (1:1.7.2-20) unstable; urgency=medium + + * Added a fix for the latest perl (Closes: #158462, #163333). + * Added a #include in lib/perl.c for the the xmalloc() prototype + (Closes: #126101). + * Clear all stamps in debian/rules (Closes: #126102). + * Brand new init script which uses ctlinnd. + + -- Marco d'Itri Thu, 26 Sep 2002 21:13:59 +0200 + +inn (1:1.7.2-19) unstable; urgency=medium + + * Fixed outdated perl dependancy (Closes: #113209). + * Does not Suggests anymore innfeed and news-reader. + * Installs gpgverify instead of pgpverify, Suggests gpg instead of pgp. + + -- Marco d'Itri Sun, 23 Sep 2001 14:02:35 +0200 + +inn (1:1.7.2-18) unstable; urgency=low + + * Fixed build dep. (Closes: #92112). + * Removed suidregister support (Closes: #84383). + + -- Marco d'Itri Fri, 6 Apr 2001 20:10:45 +0200 + +inn (1:1.7.2-17) unstable; urgency=low + + * Compiled against perl 5.6 (Closes: #80699). + * Removed misleading message from postinst (Closes: #63449). + * Start innd only if the user asked for it (Closes: #70738). + * Disabled quoting check (Closes: #58184, #58236). + * pgpverify now correctly sources /etc/news/innshellvars.pl and should + work out of the box. + * Downgraded to priority extra: most people don't need a news server + on their system! + + -- Marco d'Itri Fri, 19 Jan 2001 21:24:26 +0100 + +inn (1:1.7.2-16) frozen unstable; urgency=medium + + * Fixed RC bug in postinst (Closes: #57427, #57534). + + -- Marco d'Itri Wed, 9 Feb 2000 18:53:19 +0100 + +inn (1:1.7.2-15) frozen unstable; urgency=medium + + * README.Debian was not installed. + * A bogus /var/spool/news/\ directory was created. + * Commented description of ident protocol use in hosts.nntp(5). + * Added /t to localhost entry in hosts.nntp. + + -- Marco d'Itri Sun, 6 Feb 2000 20:53:36 +0100 + +inn (1:1.7.2-14) frozen unstable; urgency=medium + + * Comments *.foo.com in nnrp.access (Closes: #56369). + * pgpverify automatically uses GnuPG if pgpgpg is found. + * actived stdin/out/err are not opened to the console anymore. + * RNEWS_LOG_DUPS set to SYSLOG. + * LOCAL_MAX_ARTSIZE set to 2 MB. + * fixed "cant read after 0" bug in rnews. + * articles filed in in.coming/bad/ by rnews gets a X-rnews-Reject-Reason + header. + * Applied Path audit trail patch from Ian Jackson (Closes: 54201). + + -- Marco d'Itri Sat, 29 Jan 2000 17:49:01 +0100 + +inn (1:1.7.2-13) frozen unstable; urgency=medium + + * Converted to debhelper. + * Now everything installed in /etc is a conffile. + * Fixed the bug in the Distribution parsing code. + * Fixed Y2K bug. + * Patches from insync release: DBZ 3.2, bigger hash table in expire, + fastrm symlink bug, perl filter updates, timers, precommit cache, + Path feed, mmapped overview, actived. + * Patches from cleanfeed: mode.patch, messageid.patch, filter.patch. + * Applied X-Trace patch. + * Removed generation of the X-Server-Date header. + * From the BOFH patch: in filter_post() the authenticated user is + available as $user, the article body as $hdr{'__BODY__'}. If the + string returned by filter_post() starts with DROP, the article + is silently dropped. + * Updated pgpverify, control.ctl and moderators. Now pgpgpg can be + used instead of pgp. + * Innreport is used instead of innlog. + * Closes: #54609, #24504, #37737, #43896, #44918, #49673, #51944, #54526. + * Closes: #55062, #11614, #26659, #43895, #31145, #52762, #55467, #37888. + * Closes: #54411, #54759, #25181, #21586, #32416, #48739. + * Now inn is maintained by Marco d'Itri. The following changes have + been made by Bdale: + * reinstate 1.7.2 as package 'inn' and friends, the 2.2.2 bits are being + renamed to inn2, et al, as part of Debian INN peace project. + * reopen *lots* of bugs against the inn package that were closed by the + upgrade to 2.2.2, so that they can be dealt with again for 1.7.2 as + needed. + * update control file texts to point new installations to inn2 + * add a check for inn version 2.2.2 to the preinst, and suggest aborting + to select inn2 instead of inn if the user has already upgraded to 2.2.2. + + -- Marco d'Itri Sat, 22 Jan 2000 20:56:19 +0100 + +inn (1.7.2-12) unstable; urgency=low + + * update to reflect current policy + * inndstart *is* provided setuid root, closes: #51944 + * fix path in nntpsend.ctl.5, closes: #49673 + * if we're upgrading, don't stop to ask user, just use existing config + information, closes: #44918 + * deliver Install.txt instead of Install.ms into the doc directory, + closes: #43898 + + -- Bdale Garbee Sun, 5 Dec 1999 20:46:07 -0700 + +inn (1.7.2-11) unstable; urgency=high + + * patch to inews.c to fix buffer overrun problem from Martin Schulze + + -- Bdale Garbee Mon, 6 Sep 1999 13:35:19 -0600 + +inn (1.7.2-10) unstable; urgency=low + + * rebuild to depend on perl 5.005, closes 41469, 41925, 41943. + * update postinst text to eliminate version bogosity, closes 41585. + * fix sample sendbatch, closes 41596 + * fix source-archive clause in sample newsfeeds file, closes 37862. + * document nntpport, closes 28588. + * fix type of inet_addr to reflect current libc. + + -- Bdale Garbee Mon, 2 Aug 1999 01:22:23 -0600 + +inn (1.7.2-9) unstable; urgency=low + + * fold in Roman Hodek's changes from his 6.1 NMU, closing 38621. This + fixes an ugly i386 dependency in the way inn calls Perl. + * update perl dependency managment to try and cope with new perl policy + + -- Bdale Garbee Sat, 17 Jul 1999 17:13:05 -0600 + +inn (1.7.2-6) unstable; urgency=low + + * new maintainer + * clean up a few lintian complaints + * folding in changes from Christian Kurz that he called -5. We'll call this + -6 even though his changes were not widely distributed, just to avoid any + confusion: + + Removed X-Server-Date-Patch as it's not needed. + default moderation address add to /etc/news/moderators (closes: #24549) + Inn now depends on perl (closes: #27754, #32313) + Added gunbatch for gzipped batches (closes: #29899) + Changed debian/rules so inncheck runs without errors. + Added Perl-Support to Inn (closes: #26254) + Changed the examples + + -- Bdale Garbee Wed, 26 May 1999 15:18:53 -0600 + +inn (1.7.2-4) frozen unstable; urgency=medium + + * Fixes: + #21583: inn: inn must replace inewsinn + #20763: inn sends me `not running' and `now running' each night + #21342: inn: install probs + #21582: inn: incorrect prerm fail-upgrade action + #21584: inn: postinst doesn't know abort-upgrade + #20048: inn: poison and REMEMBER_TRASH patch + #21644: inn: a way to not receive certain groups + * Wrt bug #20763: the ctlinnd timeout in innwatch has been increased + to 300 seconds (5 minutes). Hopefully that is enough.. There is no + good alternative, the fact that INN is slow while renumbering is + a basic design flaw. (Though the abp-scheduler patch might help) + + -- Miquel van Smoorenburg Fri, 22 May 1998 19:52:55 +0200 + +inn (1.7.2-3) frozen unstable; urgency=medium + + * Move moderators from inewsinn to inn. The server should keep the + moderators data, not inews. + * Fix lib/clientactive.c (still yucky, but should work..) + * Include latest pgpverify script, 1.9, and manpage + * Fix security hole (/tmp/pgp$$) in pgpverify script + * Fixes: + #18579: I can't uninstall INN package + #19776: inn.prerm buggy typos bah! + #18724: inn: /etc/init.d/inn contains sed that never terminates + #19206: inn: Crontab modifications not preserved + #20423: inn: error in removing + #20653: inn: Bug in send-uucp.pl, patch included + #20792: INN: Wrong sfnet maintainer + #20436: inn: on line 16 of the prerm script there is "fi" instead of "esac" + + -- Miquel van Smoorenburg Wed, 15 Apr 1998 17:34:23 +0200 + +inn (1.7.2-2) unstable; urgency=low + + * Change over to new crontab -l method + * Fix (pre|post)(inst|rm) scripts in several ways + * Fix inewsinn inn.conf installation + * Set NNRP_DBZINCORE_DELAY to -1 + * Fix lintian warnings + Fixes: + #18120: inn: Inn's crontab file should be a conffile + + -- Miquel van Smoorenburg Thu, 19 Feb 1998 22:46:25 +0100 + +inn (1.7.2-1) unstable; urgency=low + + * New upstream version + * Fix crontab -l | tail +4 + * Fixes bugs: + #15889: /etc/news/inn.conf missing + #16128: manpage uncompressed + #15103: egrep incorrectly searched in /bin by innshellvars* + #14404: /usr/doc/$(PACKAGE)/copyright should not be compressed + + -- Miquel van Smoorenburg Thu, 5 Feb 1998 12:52:14 +0100 + +inn (1.7-1) unstable; urgency=low + + * New upstream version + * Fixed bugs: + #9264: Unresolved dependency report for inn + #9315: inn: /etc/news/innshellvars* add /usr/ucb to the PATH + #9832: INN 1.5.1-1 throttled rmgroup really shreds active file ? + #10196: inn: inews complains about missnig subject header when there is one + #10505: Moderated postings fail + #11042: error in /usr/doc/inn/inn-README + #11057: inn: Confusing/dangerous instructions + #11453: inn: max signature length + #11691: libc6 + #11851: inn: Documentation for send-uucp.pl + #11852: inn: nntpsend looks for wrong config file + #11900: INN creates `local.*' by default + #11948: inn: nntpsend does not works + #12513: inewsinn should insert a linebreak + #13161: inn-makehistory - Bus error + #13425: inn: egrep moved to /bin + #13488: inewsinn: directs user to docs in a package it doesn't require + #13616: /etc/init.d/inn, /etc/news/hosts.nntp.nolimit are not conffiles + #13781: Can't feed by send-uucp.pl with ihave/sendme. + #13831: inn: scanlogs depends on hard coded path for egrep + #13899: inn: inn uses /usr/bin/egrep, grep doesn't provide that any longer + * Added BUFFSET fix + + -- Miquel van Smoorenburg Wed, 22 Oct 1997 14:08:37 +0200 + +inn (1.5.1-5) unstable; urgency=high + + * Fixed sendbatch script (comment in between backtics is illegal) + * libc6 version + + -- Miquel van Smoorenburg Wed, 10 Sep 1997 16:31:37 +0200 + +inn (1.5.1-4) stable unstable; urgency=high + + * Add new security patch (with fixed STRCPY): inn-1.5.1-bufferoverflow.patch4 + * Applied null-pointer.patch from Michael Shields + * Upped SIG_MAXLINES in configdata.h to 8 + * Fix inn-README (perl example). Fixes bug #11042 + * Update inn-README and postinst to fix bug #11057 + * Make ctlinnd addhist work in paused mode, and fail in throttled mode + * Change ID string + + -- Miquel van Smoorenburg Thu, 21 Aug 1997 12:37:48 +0200 + +inn (1.5.1-3) stable unstable; urgency=high + + * Add changelogs to docdir + * innshellvars*: change /usr/ucb -> /usr/sbin (Bug#9315) + * Changed Recommends: pgp to Suggests: (Bug#9264) + * Fix inews to fallback on local moderators file (Bug#10505) + * Fix buffer overruns all over the place + + -- Miquel van Smoorenburg Thu, 24 Jul 1997 18:29:33 +0200 + +inn (1.5.1-2) frozen unstable; urgency=high + + * Added security-patch.05 (mailx tilde exploit) + * inewsinn no longer conflicts: inn so installation should no + longer remove your original inn-1.4 package (and configuration). + Expect some dpkg trouble when upgrading from 1.4unoff4 to 1.5.1-2 though. + * Always create .incoming/.outgoing symlinks for backwards compat. + * Do not change ownerships/modes of existing directories + * Fix ownerships/modes of rnews, innd, inndstart, in.nnrpd + * Fix /etc/init.d/inn to comply with console messages standard + * Fix /usr/lib/news/bin/sendbatch + * Fix scanlogs not to nuke active file if log/news/OLD isn't there + * Console messages are a bit more standard now + * Use start-stop-daemon to kill innwatch in /etc/init.d/inn + * Fixed up inncheck - it almost doesn't complain anymore + + -- Miquel van Smoorenburg Mon, 28 Apr 1997 13:58:16 +0200 + +inn (1.5.1-1) unstable; urgency=low + + * Upgraded to 1.5.1 + * Fixed Bug#6387: expire-with-symlinks problem + * Fixed Bug#6246: inewsinn reconfigures on update + * Moved /var/spool/news,/var/lib/news back into package + * Saves removed conffiles in preinst, restores in postinst + * Set LIKE_PULLERS to DO + * Remove manpage stubs that are now real manpages + * Fix options to sendmail in _PATH_SENDMAIL + * Removed subdirectories from debian/ + * create /var/log/news/OLD in postinst + * Fixed most if not all other outstanding bugs + + -- Miquel van Smoorenburg Wed, 5 Feb 1997 10:58:16 +0100 + +inn (1.5-1) unstable; urgency=low + + * Upgraded to 1.5 + * Undid most patches to 1.4unoff4 because they are in 1.5 proper. + * Added security patch + * Added X-Server-Date: patch + * inn now depends on inewsinn + * Fixed all other outstanding bugs (well, almost). + + -- Miquel van Smoorenburg Tue, 17 Dec 1996 16:56:37 +0100 + +inn (1.4unoff4-2) unstable; urgency=low + + * Added inn-dev package for libinn.a and manpages. + * Increased hash table size in expire.c to 2048 (was 128) + * Moved ctlinnd to /usr/sbin + * Moved to new source packaging scheme + + -- Miquel van Smoorenburg Wed, 06 Oct 1996 15:38:30 +0200 + +INN (1.4unoff4-1) - Miquel van Smoorenburg + + * Took out the Linux 1.2 patches I put in unoff3. + * added the 64 bits patch (for Linux/Alpha) + * There are some other minor patches for Linux/Alpha + * Added "xmode" as alias for "mode" + * Using MMAP and setsockopt() now - NEEDS 1.3 kernel ! + +INN (1.4unoff3-1) - Miquel van Smoorenburg + + * Took inn1.4sec-8 and 1.4unoff3, folded in some Linux and + other patches. + * Changed all makefiles to support a "prefix" variable for install + * Removed the hacks in debian.rules for installation + * Locks are in /var/run/innd + * Rewrote post install script. + +inn (1.4sec-8); priority=MEDIUM + + * postinst configuration completely redone. It now sets up a minimal + local installation for you. + * prerm now exists and shuts the server down. + * init scripts changed to System V scheme. + * Descriptions in control files expanded. + * Package now contains /var/lock/news, and uses /var/log (not /var/adm). + * inewsinn postinst looks at and can write /etc/mailname. + +INN 1.4sec Debian 7 - iwj + +* libinn.a, , inn-sys2nf and inn-feedone installed + (in /usr/lib, /usr/include and /usr/bin). + +INN 1.4sec Debian 6 - iwj + +* innwatch now started by /etc/rc.misc/news. +* inewsinn postinst minor typos fixed. +* Leftover file `t' removed from source and diff distributions. + +INN 1.4sec Debian 5 - iwj + +* Added documentation about making active and history files. +* Added monthly makehistory -ru crontab run. +* Made postinst always do crontab -u news /etc/news/crontab . +* Removed HAVE_UNIX_DOMAIN - AF_UNIX+SOCK_DGRAM still broken in Linux. +* Fixed /usr/lib/news/bin/inncheck to conform to our permissions scheme. +* Added manpage links for makeactive(8), makehistory(8), newsrequeue(8). +* /var/adm/news now part of package. + +INN 1.4sec Debian 4 - iwj + +* Added $|=1 to inewsinn postinst script; a few cosmetic fixes. + +INN 1.4sec Debian 3 - iwj + +* Removed `inet' groups from distrib.pats. +* Put more version number information in ../*.{deb,gz} filenames. +* Added Package_Revision field to `control' file. +* Rationalised debian.rules somewhat, and added `build' stamp file. +* Permissions rationalised. +* Changed /etc/rc.d/rc.news to /etc/rc.misc/news. +* postinst calls Perl as /usr/bin/perl. +* Added this Changelog. + +INN 1.4sec Debian 2 - iwj +* inews moved to /usr/bin; rnews moved to /usr/sbin. +* fixed nntpsend not to use PPID variable (it's a bash builtin). + +INN 1.4sec Debian 1 - iwj +Initial release, completely untested. --- inn-1.7.2q.orig/debian/inn.prerm +++ inn-1.7.2q/debian/inn.prerm @@ -0,0 +1,11 @@ +#!/bin/sh -e + +# delete the pid file if INN is dead, or the init script may fail later +PIDFILE="/var/run/innd/innd.pid" +if [ -f $PIDFILE ]; then + INNPID=$(cat $PIDFILE) + kill -s 0 $INNPID 2> /dev/null || rm -f $PIDFILE +fi + +#DEBHELPER# + --- inn-1.7.2q.orig/debian/NEWS +++ inn-1.7.2q/debian/NEWS @@ -0,0 +1,14 @@ +inn (1:1.7.2debian-25) unstable; urgency=medium + + * Since this release inewsinn has been merged in the main inn package. + + -- Marco d'Itri Sat, 27 Sep 2003 00:32:34 +0200 + +inn (1:1.7.2debian-23) unstable; urgency=medium + + * Added support for a inewsport config file option. (Closes: #54975) + * Removed /etc/news/crontab and added /etc/cron.d/inn. The old file has + been removed from crontab but its lines have not been added to the + new one, you will have to do this yourself. + + -- Marco d'Itri Wed, 20 Aug 2003 03:56:14 +0200 --- inn-1.7.2q.orig/debian/README.Debian +++ inn-1.7.2q/debian/README.Debian @@ -0,0 +1,145 @@ +Patches applied: + +0_insync_actived +0_insync_dbz_3.3 +0_insync_fastrm_symlink +0_insync_misc (history+timer+perl_mode+perl_messageid) +0_insync_largerhash +0_insync_overscream +0_insync_pathfeed +Ported from the insync patch kit, with some local changes: actived, +DBZ 3.2, fastrm symlink bug fix, precommit cache, Joe Greco's timers, +bigger hash table in expire, mmapped overview, Path feed from a +newsfeeds entry. +To enable actived put "useactived: yes" in inn.conf and "DOACTIVED=true" +in /etc/news/boot. It will *NOT* be used by nnrpd by default. + +1_perl_filter_patch +1_perl_misc +All patches from cleanfeed (mode.patch, messageid.patch, dynamic-load.patch, +filter.patch), some parts in 0_insync_misc too. +Updates for perl 5.8 by Marco d'Itri. + +2_perl_timer +Perl filter timer support. (Marco d'Itri) + +addhist +Disallow addhist when the server is paused or throttled. +(Miquel van Smoorenburg) + +bindaddress +Added port and bindaddress entries to inn.conf (Miquel van Smoorenburg +and Marco d'Itri). + +clientactive.c +Small inews-related fix. (Miquel van Smoorenburg) + +distribution_crash +Distribution header parsing patch. (Sylvain Robitaille) + +fastrm_allow_symlinks +Remove -u from the default fastrm command line. + +fixinterps +Support recent perl releases. + +getmodaddr.c +Use a local moderators file if inews cannot get one from the server. + +inet_addr_is_int +inet_addr does return int, not long. + +inews-misc +inews buffer overflow fix and something else I do not remember. +inews opens the active with CAopen instead of CAlistopen (Colin Watson). +inews authenticates with the remote server (Chip Salzenberg). + +inewsport +Add the inewsport inn.conf option. + +inncheck +Make it check for the right permissions for debian systems. + +innd.c_init_TimeOut +Bugfix: tv_usec must be initialized. + +innwatch_ctlinnd_timeout +Use a timeout when invoking ctlinnd from innwatch. + +misc_config_files +Change some defaults for debian packaging. + +misc_inn.conf +Document all new parameters. + +misc_makefiles +Fix support for $DESTDIR and other minor bugfixes. + +misc_paths.h +Add all new inn.conf parameters. + +misc_rc.news +Disable innwatch by default, add actived support. + +newsgroups_whitespace +Ignore whitespace in Newsgroups headers instead of rejecting the article. + +nnrpd_needs_libcrypt +Link nnrpd with -lcrypt. + +nnrpd_perl_edit_headers+bofh +From the BOFH patch by Andrew Gierth: in filter_post() the authenticated +user is available in the $user variable and the article body is put in +$body. If the string returned by filter_post() starts with DROP, the +article is silently dropped. +Backported from INN 2.x the code to modify headers in filter_nnrpd.pl. + +nntpsend.ctl_in_etc +Move nntpsend.ctl to /etc/. + +no_throttled_rmgroups +Bugfix: disallow rmgroups when the server is throttled or the history +will be damaged. + +parsedate_y2k +Y2K bugfix by Bettina Fink. + +path_audit +path_audit_fix +Path audit trail patch (Ian Jackson). Please read hosts.nntp(5). + +poison+remember_trash +Poison and REMEMBER_TRASH patch by Russ Allbery. + +recommend_ID +Tell clients the recommended Message-ID (Olaf Titz). + +rnews_reject_reason +Have rnews add an header to saved rejected articles. + +rnews_unknown +Minor rnews fixes (Marco d'Itri). + +scanlogs_use_innreport +innreport backported from INN 2.x. + +sendbatch +send-uucp +Commented some hardcoded configuration values, but everybody should use +send-uucp.pl anyway. + +use_controlchan +Controlchan support (backported from INN 2.x by Marco d'Itri). + +use_strerror +sys_errlist[] is deprecated. + +xmode +Add the XMODE command. + +x-trace +X-Trace header generation. + +More precise timer when innd is idle most of the time (Olaf Titz). +[Buried somewhere in the 0_insync_* patches.] + --- inn-1.7.2q.orig/debian/control +++ inn-1.7.2q/debian/control @@ -0,0 +1,34 @@ +Source: inn +Section: news +Priority: extra +Maintainer: Marco d'Itri +Build-Depends: debhelper (>= 5), quilt (>= 0.40), bison, groff, perl, libperl-dev (>= 5.8) +Standards-Version: 3.8.3 + +Package: inn +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, cron, default-mta | mail-transport-agent, time, perl, ${PERLAPI} +Suggests: gnupg (>= 1.0.5) +Provides: news-transport-system, inews +Conflicts: inn2, inn2-inews, inn2-dev, inewsinn, news-transport-system +Replaces: inewsinn +Description: News transport system `InterNetNews' by the ISC and Rich Salz + This is INN version 1.x, provided for smaller sites which do not need + the complexity of INN 2.x. + Large sites should use Debian's inn2 package instead. + . + The news transport is the part of the system that stores the articles + and the lists of which groups are available and so on, and provides + those articles on request to users. It receives news (either posted + locally or from a newsfeed site), files it, and passes it on to any + downstream sites. Each article is kept for a period of time and then + deleted (this is known as `expiry'). + . + By default Debian's INN will install in a fairly simple `local-only' + configuration. + . + In order to make use of the services provided by INN you'll have to + use a user-level newsreader program such as trn. The newsreader is + the program that fetches articles from the server and shows them to + the user, remembering which the user has seen so that they don't get + shown again. It also provides the posting interface for the user. --- inn-1.7.2q.orig/debian/inn.dirs +++ inn-1.7.2q/debian/inn.dirs @@ -0,0 +1,11 @@ +etc/init.d +etc/news/scripts +usr/bin +usr/sbin +usr/share +usr/lib/news +usr/lib/news/bin +usr/lib/news/control +usr/lib/news/rnews +var/lib/news +var/spool/news --- inn-1.7.2q.orig/debian/compat +++ inn-1.7.2q/debian/compat @@ -0,0 +1 @@ +5 --- inn-1.7.2q.orig/debian/inn.cron.d +++ inn-1.7.2q/debian/inn.cron.d @@ -0,0 +1,21 @@ +PATH=/usr/lib/news/bin:/bin:/sbin:/usr/bin:/usr/sbin +MAILTO=usenet + +# Expire old news and old overview entries nightly, generate reports. +08 4 * * * news [ -x /usr/lib/news/bin/news.daily ] && /usr/lib/news/bin/news.daily expireover delayrm + +# Refresh the hosts cache every night. +02 4 * * * news [ -x /usr/lib/news/bin/ctlinnd ] && /usr/lib/news/bin/ctlinnd -t 300 -s reload hosts.nntp "flush cache" + +# Every hour, run an rnews -U. This is not only for UUCP sites, but +# also to process queud up articles put there by in.nnrpd in case +# innd wasn't accepting any articles. +14 * * * * news [ -x /usr/bin/rnews ] && /usr/bin/rnews -U + +# Enable this entry to send posted news back to your upstream provider. +# Not if you use innfeed, ofcourse. +#*/15 * * * * news send-nntp news.myprovider.com + +# Enable this if you want to send news by uucp to your provider. +# Also edit /etc/news/send-uucp.cf ! +#22 * * * * news send-uucp.pl --- inn-1.7.2q.orig/debian/inn.preinst +++ inn-1.7.2q/debian/inn.preinst @@ -0,0 +1,32 @@ +#!/bin/sh -e + +check_version() { + case "$2" in + 1.4*) + echo "Upgrade from INN 1.4 is not supported." + exit 1 + ;; + + 2.2.2) + echo "Upgrade from INN 2.2.2 is not supported." + exit 1 + ;; + esac +} + +case "$1" in + install) + ;; + + upgrade|abort-upgrade) + check_version "$@" + ;; + + *) + echo "preinst called with unknown argument '$1'" >&2 + exit 1 + ;; +esac + +#DEBHELPER# + --- inn-1.7.2q.orig/debian/inn.postrm +++ inn-1.7.2q/debian/inn.postrm @@ -0,0 +1,52 @@ +#!/bin/bash -e + +clean_var_lib() { + echo "Purging active file and history data..." + rm -f /var/lib/news/active* /var/lib/news/history* \ + /var/lib/news/newsgroups + if [ -d /var/lib/news/ ]; then + rmdir --ignore-fail-on-non-empty /var/lib/news/ + fi +} + +clean_var_run() { + rm -rf /var/run/innd/ +} + +remove_logs() { + echo "Removing files in /var/log/news and /var/run/innd..." + rm -f /var/lib/news/{.news.daily,active.old} + [ -e /var/log/news/ ] || return 0 + rm -rf /var/log/news/OLD/ + rm -f /var/log/news/{expire.log,log,errlog,unwanted.log} + : > /var/log/news/news.crit + : > /var/log/news/news.err + : > /var/log/news/news.notice +} + +case "$1" in + remove) + ;; + + purge) + clean_var_lib + clean_var_run + remove_logs + + # We do not remove /var/spool/news because that might + # take a lot of time. Most of the time it is on a seperate + # disk anyway and it is faster to do a mkfs on it.. + echo "Remove the news spool in /var/spool/news yourself!" + ;; + + upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) + ;; + + *) + echo "postrm called with unknown argument '$1'" >&2 + exit 1 + ;; +esac + +#DEBHELPER# + --- inn-1.7.2q.orig/debian/inn.links +++ inn-1.7.2q/debian/inn.links @@ -0,0 +1,9 @@ +/etc/news/scripts/send-ihave /usr/lib/news/bin/send-ihave +/etc/news/scripts/send-nntp /usr/lib/news/bin/send-nntp +/etc/news/scripts/send-uucp /usr/lib/news/bin/send-uucp +/usr/lib/news/innshellvars /etc/news/innshellvars +/usr/lib/news/innshellvars.csh /etc/news/innshellvars.csh +/usr/lib/news/innshellvars.pl /etc/news/innshellvars.pl +/usr/lib/news/innshellvars.tcl /etc/news/innshellvars.tcl +/usr/lib/news/bin/ctlinnd /usr/sbin/ctlinnd +/usr/share/man/man8/innd.8 /usr/share/man/man8/inndstart.8 --- inn-1.7.2q.orig/debian/rules +++ inn-1.7.2q/debian/rules @@ -0,0 +1,121 @@ +#!/usr/bin/make -f +SHELL=/bin/bash -e + +QUILT_STAMPFN := debian/.stamp-patched +include /usr/share/quilt/quilt.make + +B := $(CURDIR)/build +D := $(CURDIR)/debian/inn + +# get the debian revision number +DREV := $(shell dpkg-parsechangelog | grep '^Version: 1:1.7.2q-' \ + | sed -e 's/^.*-\(.*\)$$/\1/') +ifeq ($(DREV),) +$(error bad package version) +endif + +# the upstream source needs to be copied in the build dir +src_files = $(shell find . -maxdepth 1 \ + -not -name . -and -not -name debian -and -not -name .pc \ + -and -not -name extra -and -not -name build) + +clean: unpatch + rm -rf debian/.stamp-* $B + dh_clean + +configure: debian/.stamp-configure +debian/.stamp-configure: $(QUILT_STAMPFN) + dh_testdir + mkdir -p $B + for dir in $(src_files); do cp -ldpR $$dir $B; done + perl -pi -e 's|^(#define\s+LOCAL_STRING\s+")[^"]*"|$${1}Debian/$(DREV)"|' \ + $B/include/patchlevel.h + sed -e "s@PERL_LDOPTS@`perl extra/perl-ldopts`@" \ + -e "s@PERL_CCOPTS@`perl extra/perl-ccopts`@" \ + < extra/config.data.debian > $B/config/config.data + touch $@ + +build: debian/.stamp-build +debian/.stamp-build: debian/.stamp-configure + dh_testdir + cd $B && $(MAKE) + # Cat the Install docs together + cat $B/Install.ms.[12] | nroff -ms > $B/Install.txt + touch $@ + +binary-arch: debian/.stamp-build checkroot + dh_testdir + dh_clean + dh_installdirs + # Install INN in the temp directory + cd $B && $(MAKE) install DESTDIR=$D + + printf '#!/bin/sh\ngzip -d\n' > $D/usr/lib/news/rnews/gunbatch + chmod +x $D/usr/lib/news/rnews/gunbatch + + cp extra/innreport_inn.pm $D/usr/lib/news/ + install -m 755 extra/send-uucp.pl extra/innreport $D/usr/lib/news/bin/ + pod2man --section=8 < extra/send-uucp.pl \ + > $D/usr/share/man/man8/send-uucp.8 + + # these scripts contain an unfixable bashism + cd $D/usr/lib/news/control/ && \ + for file in *; do \ + perl -i -pe 's@^#! /bin/sh@#! /bin/bash@' $$file; \ + done + + # Fix up innshellvars* and other things + perl -pi -e 's#/usr/ucb#/usr/sbin#' $D/usr/lib/news/innshellvars* + + cp extra/etc/* $D/etc/news + dh_installcron + dh_installdocs extra/doc/inn-README extra/doc/innhelp.tomk.txt \ + $B/FAQ/ $B/Install.txt $B/actived/README.actived + dh_installchangelogs $B/CHANGES + dh_installinit --restart-after-upgrade + install -p -m755 debian/inn.init $D/etc/init.d/inn + + rm -rf $D/var/spool/news/* $D/var/run/innd/ $D/tmp/ \ + $D/etc/news/scripts/*.tcl \ + $D/var/lib/news/innlog.pl \ + $D/usr/share/man/man8/innlog.pl.8.gz \ + $D/usr/lib/news/control/sample.control + + dh_fixperms + cd $D/etc/news && \ + chown root:news passwd.nntp nnrp.access hosts.nntp && \ + chmod 640 passwd.nntp nnrp.access hosts.nntp + chown root:news $D/usr/bin/[ri]news + chmod 2755 $D/usr/bin/[ri]news + chown root:news $D/usr/sbin/inndstart + chmod 4754 $D/usr/sbin/inndstart + chown -R news:news $D/var/*/news/ + + # Move some more stuff around. + mv $D/var/lib/news/send-* $D/etc/news/scripts/ + mv $D/var/lib/news/nntpsend.ctl $D/etc/news/nntpsend.ctl + cd $D/usr/share/man/man8 && mv nnrpd.8 in.nnrpd.8 + + # Install the latest pgpverify. + install -m 755 extra/gpgverify $D/usr/lib/news/bin/pgpverify + install -d -m 755 -o news -g news $D/etc/news/pgp + cp extra/pgpverify.8 $D/usr/share/man/man8/ + + # Install controlchan + install -m 755 extra/cch/controlchan $D/usr/lib/news/bin/ + install -m 644 extra/cch/control/* $D/usr/lib/news/control/ + + dh_link + dh_strip + dh_compress + dh_installdeb + dh_shlibdeps + dh_gencontrol -u-VPERLAPI=$$(perl -e 'printf "perlapi-%vd", $$^V') + dh_builddeb + + +binary: binary-arch + +checkroot: + test root = "`whoami`" + --- inn-1.7.2q.orig/debian/copyright +++ inn-1.7.2q/debian/copyright @@ -0,0 +1,32 @@ +This is Debian GNU/Linux's prepackaged version of Rich Salz's +INN news transport system. + +It is currently maintained by Marco d'Itri . +Bdale Garbee, Miquel van Smoorenburg and Ian Jackson maintained +this package in the past. + +The authors of applied patches are listed in README.Debian. + +Copyright 1991 Rich Salz. All rights reserved. +Modifications for Debian GNU/Linux Copyright 1994 Ian Jackson. +Modifications for Debian GNU/Linux Copyright 1995-1997 Miquel van Smoorenburg. +Modifications for Debian GNU/Linux Copyright 2000 Marco d'Itri + +Redistribution and use in any form are permitted provided that the +following restrictions are are met: + 1. Source distributions must retain this entire copyright notice + and comment. + 2. Binary distributions must include the acknowledgement ``This + product includes software developed by Rich Salz'' in the + documentation or other materials provided with the + distribution. This must not be represented as an endorsement + or promotion without specific prior written permission. + 3. The origin of this software must not be misrepresented, either + by explicit claim or by omission. Credits must appear in the + source and documentation. + 4. Altered versions must be plainly marked as such in the source + and documentation and must not be misrepresented as being the + original software. +THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. --- inn-1.7.2q.orig/debian/inn.init +++ inn-1.7.2q/debian/inn.init @@ -0,0 +1,69 @@ +#!/bin/sh -e +### BEGIN INIT INFO +# Provides: inn +# Required-Start: $local_fs $remote_fs $syslog +# Required-Stop: $local_fs $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: INN news server +# Description: The InterNetNews news server. +### END INIT INFO +# +# Start/stop the news server. +# + +test -f /usr/sbin/innd || exit 0 + +case "$1" in + start) + if [ ! -d /var/run/innd ]; then + mkdir -p /var/run/innd + chown news:news /var/run/innd + chmod 775 /var/run/innd + fi + start-stop-daemon --quiet --start --exec /etc/news/boot + ;; + stop) + echo -n "Stopping news server:" + if [ -f /var/run/innd/innwatch.pid ]; then + echo -n " innwatch" + start-stop-daemon --quiet --stop --oknodo \ + --pidfile /var/run/innd/innwatch.pid + fi + if [ -f /var/run/innd/actived.pid ]; then + echo -n " actived" + start-stop-daemon --quiet --stop --oknodo + --pidfile /var/run/innd/actived.pid --exec /usr/lib/news/bin/actived + fi + rm -f /var/run/innd/actived.pid /var/run/innd/innwatch.pid + if [ -f /var/run/innd/innd.pid ]; then + echo -n " innd" + ctlinnd -s -t 20 throttle 'system is going down' || true + ctlinnd -s -t 20 shutdown 'system is going down' || true + start-stop-daemon --quiet --stop --oknodo \ + --pidfile /var/run/innd/innd.pid + fi + echo "." + ;; + reload|force-reload) + echo -n "Reloading INN configuration files: " + ctlinnd -t 20 reload '' /etc/init.d/inn + ;; + restart) + echo -n "Restarting innd: " + if [ -f /var/run/innd/innd.pid ]; then + ctlinnd -s -t 20 throttle "restarting" || true + ctlinnd -s -t 20 xexec inndstart || + start-stop-daemon --quiet --start --exec /etc/news/boot + else + start-stop-daemon --quiet --start --exec /etc/news/boot + fi + echo "done." + ;; + *) + echo "Usage: /etc/init.d/inn start|stop|restart|reload" >&2 + exit 1 + ;; +esac + +exit 0 --- inn-1.7.2q.orig/debian/inn.postinst +++ inn-1.7.2q/debian/inn.postinst @@ -0,0 +1,82 @@ +#!/bin/sh -e + +make_directories() { + NEED_DIR='in.coming in.coming/bad in.coming/tmp + out.going over.view news.archive' + for D in $NEED_DIR; do + if [ ! -d /var/spool/news/$D ]; then + install -d -m 775 -o news -g news /var/spool/news/$D + fi + done +} + +init_var_lib_news() { + if [ ! -f /var/lib/news/active ]; then + cat > /var/lib/news/active << END +control 0000000000 0000000001 n +control.cancel 0000000000 0000000001 n +junk 0000000000 0000000001 y +misc.test 0000000000 0000000001 y +misc.test.moderated 0000000000 0000000001 m +END + chown news:news /var/lib/news/active + fi + + if [ ! -f /var/lib/news/history ]; then + touch /var/lib/news/history + /usr/lib/news/bin/makehistory -or + chown news:news /var/lib/news/history* + fi + + if [ ! -f /var/lib/news/newsgroups ]; then + cat > /var/lib/news/newsgroups << END +control News server internal group. +control.cancel News server internal group. +junk News server internal group. +misc.test For testing of network software. Very boring. +misc.test.moderated Testing of posting to moderated groups. (Moderated) +END + chown news:news /var/lib/news/newsgroups + fi +} + +add_mail_alias() { + if ! grep -q '^usenet:' /etc/aliases; then + echo 'usenet: root' >> /etc/aliases + newaliases || echo "newaliases command not available." + fi +} + +init_etc_files() { + if [ ! -f /etc/news/server ]; then + echo 'localhost' > /etc/news/server + fi + + if [ ! -f /etc/news/whoami ]; then + if [ -f /etc/mailname ]; then + cp /etc/mailname /etc/news/whoami + else + hostname --fqdn > /etc/news/whoami + fi + fi +} + +case "$1" in + configure) + make_directories + init_var_lib_news + add_mail_alias + init_etc_files + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument '$1'" >&2 + exit 1 + ;; +esac + +#DEBHELPER# + --- inn-1.7.2q.orig/debian/patches/misc_inn.conf +++ inn-1.7.2q/debian/patches/misc_inn.conf @@ -0,0 +1,42 @@ +--- inn-1.7.2.orig/samples/inn.conf ++++ inn-1.7.2/samples/inn.conf +@@ -14,6 +14,13 @@ + ## the Organization header if blank. + ## server If $NNTPSERVER doesn't exist. Local NNTP server + ## host to connect to. ++## useactived Set to yes if actived is running. ++## Change /etc/news/boot too! ++## usecontrolchan Set to yes if controlchan has been enabled in ++## /etc/news/newsfeeds. ++## inewsport Default port for inews. ++## port Default port for listening. ++## bindaddress Default address for listening. + ## + organization: A poorly-installed InterNetNews site + server: localhost +--- inn-1.7.2.orig/doc/inn.conf.5 ++++ inn-1.7.2/doc/inn.conf.5 +@@ -73,6 +73,23 @@ + calls. + The check is very simple; if either routine returns a name with a period + in it, then it is assumed to have the full domain name. ++.TP ++.I nntpport ++This is the TCP port INN is accepting connections on. This can be changed, ++for example if you want to run in.nnrpd from inetd on port 119. ++The default value is ``119.'' ++.TP ++.I useactived ++When this parameter is enabled (``yes''), ++.I nnrpd ++will try using the ++.IR actived ++program. ++The default value is ``no''. ++.PP ++The ++.I inewsport ++parameter is only used by inews when posting an article. + .PP + Three parameters are used only by + .I nnrpd --- inn-1.7.2q.orig/debian/patches/parsedate_gcc4 +++ inn-1.7.2q/debian/patches/parsedate_gcc4 @@ -0,0 +1,14 @@ +Fixes a FTBFS bug with gcc 4. + +diff -ruNp inn-1.7.2.orig/lib/parsedate.y inn-1.7.2/lib/parsedate.y +--- inn-1.7.2.orig/lib/parsedate.y 2005-07-31 12:58:53.000000000 +0200 ++++ inn-1.7.2/lib/parsedate.y 2005-07-31 12:58:50.000000000 +0200 +@@ -672,7 +672,7 @@ LookupWord(buff, length) + } + + +-static int ++int + date_lex() + { + register char c; --- inn-1.7.2q.orig/debian/patches/x-trace +++ inn-1.7.2q/debian/patches/x-trace @@ -0,0 +1,68 @@ +--- inn-1.7.2.orig/nnrpd/post.c ++++ inn-1.7.2/nnrpd/post.c +@@ -72,6 +72,9 @@ + #define _contenttype 19 + { "Content-Transfer-Encoding", TRUE, HTstd }, + #define _contenttransferencoding 20 ++ { "X-Trace", FALSE, HTstd }, ++#define _xtrace 21 ++ { "NNTP-Posting-Date", FALSE, HTstd }, + { "Xref", FALSE, HTstd }, + { "Summary", TRUE, HTstd }, + { "Keywords", TRUE, HTstd }, +@@ -356,12 +361,12 @@ + return Error; + } + ++ if ((gmt = gmtime(&Now.time)) == NULL) ++ return "Can't get the time"; ++ (void)sprintf(datebuff, "%d %3.3s %d %02d:%02d:%02d GMT", ++ gmt->tm_mday, &MONTHS[3 * gmt->tm_mon], 1900 + gmt->tm_year, ++ gmt->tm_hour, gmt->tm_min, gmt->tm_sec); + if (HDR(_date) == NULL) { +- if ((gmt = gmtime(&Now.time)) == NULL) +- return "Can't get the time"; +- (void)sprintf(datebuff, "%d %3.3s %d %02d:%02d:%02d GMT", +- gmt->tm_mday, &MONTHS[3 * gmt->tm_mon], 1900 + gmt->tm_year, +- gmt->tm_hour, gmt->tm_min, gmt->tm_sec); + HDR(_date) = datebuff; + } + else { +@@ -484,6 +484,17 @@ + /* NNTP-Posting host; set. */ + HDR(_nntpposthost) = ClientHost; + ++ { ++ static char xtracebuff[SMBUF]; ++ ++ /* X-Trace; set. */ ++ if ((p = GetFQDN()) == NULL ) ++ p = "unknown"; ++ sprintf(xtracebuff, "%s %ld %ld %s (%s)", ++ p, (long) time((time_t *)NULL), (long) getpid(), ClientIp, datebuff); ++ HDR(_xtrace) = xtracebuff; ++ } ++ + /* Now make sure everything is there. */ + for (hp = Table; hp < ENDOF(Table); hp++) + if (hp->Type == HTreq && hp->Value == NULL) { +--- inn-1.7.2.orig/nnrpd/nnrpd.c ++++ inn-1.7.2/nnrpd/nnrpd.c +@@ -436,6 +436,7 @@ + #else + (void)strcpy(ClientHost, inet_ntoa(sin.sin_addr)); + #endif /* defined(DO_NNRP_GETHOSTBYADDR) */ ++ (void)strncpy(ClientIp, inet_ntoa(sin.sin_addr), sizeof(ClientIp)); + } + + strncpy (LogName,ClientHost,sizeof(LogName) - 1) ; +--- inn-1.7.2.orig/nnrpd/nnrpd.h ++++ inn-1.7.2/nnrpd/nnrpd.h +@@ -93,6 +93,7 @@ + EXTERN STRING MyHostName; + extern char ACTIVE[]; + EXTERN char ClientHost[SMBUF]; ++EXTERN char ClientIp[40]; + EXTERN char LogName[256] ; + extern char ACTIVETIMES[]; + extern char HISTORY[]; --- inn-1.7.2q.orig/debian/patches/misc_paths.h +++ inn-1.7.2q/debian/patches/misc_paths.h @@ -0,0 +1,18 @@ +--- inn-1.7.2.orig/include/paths.h ++++ inn-1.7.2/include/paths.h +@@ -177,7 +177,14 @@ + #define _CONF_CONTENTTYPE "mime-contenttype" + /* Default encoding */ + #define _CONF_ENCODING "mime-encoding" +- ++ /* Default listening address */ ++#define _CONF_BINDADDRESS "bindaddress" ++ /* Default NNTP port */ ++#define _CONF_PORT "port" ++ /* Try using actived */ ++#define _CONF_USEACTIVED "useactived" ++ /* Disable internal control messages processing */ ++#define _CONF_USECONTROLCHAN "usecontrolchan" + + /* + ** 13. TCL Support --- inn-1.7.2q.orig/debian/patches/bindaddress +++ inn-1.7.2q/debian/patches/bindaddress @@ -0,0 +1,49 @@ +--- inn-1.7.2.orig/lib/getconfig.c ++++ inn-1.7.2/lib/getconfig.c +@@ -77,5 +77,18 @@ + return "text/plain; charset=US-ASCII"; + if (EQ(value, _CONF_ENCODING)) + return "7bit"; ++ if (EQ(value, _CONF_PORT)) { ++ sprintf(ConfigBuff, "%d", NNTP_PORT); ++ return ConfigBuff; ++ } ++ if (EQ(value, _CONF_BINDADDRESS)) { ++ sprintf(ConfigBuff, "0.0.0.0"); ++ return ConfigBuff; ++ } ++ if (EQ(value, _CONF_USEACTIVED)) ++ return "no"; ++ if (EQ(value, _CONF_USECONTROLCHAN)) ++ return "no"; ++ + return NULL; + } +--- inn-1.7.2.orig/innd/inndstart.c ++++ inn-1.7.2/innd/inndstart.c +@@ -100,9 +100,9 @@ + syslog(L_ERROR, "inndstart cant setsockopt %m"); + #endif /* defined(SO_REUSEADDR) */ + (void)memset((POINTER)&server, 0, sizeof server); +- server.sin_port = htons(NNTP_PORT); ++ server.sin_port = htons(atoi(GetConfigValue(_CONF_PORT))); + server.sin_family = AF_INET; +- server.sin_addr.s_addr = htonl(INADDR_ANY); ++ server.sin_addr.s_addr = inet_addr(GetConfigValue(_CONF_BINDADDRESS)); + if (bind(i, (struct sockaddr *)&server, sizeof server) < 0) { + syslog(L_FATAL, "inndstart cant bind %m"); + exit(1); +--- inn-1.7.2.orig/innd/rc.c ++++ inn-1.7.2/innd/rc.c +@@ -646,9 +846,9 @@ + syslog(L_ERROR, "%s cant setsockopt RCreader %m", LogName); + #endif /* defined(SO_REUSEADDR) */ + (void)memset((POINTER)&server, 0, sizeof server); +- server.sin_port = htons(NNTP_PORT); ++ server.sin_port = htons(atoi(GetConfigValue(_CONF_PORT))); + server.sin_family = AF_INET; +- server.sin_addr.s_addr = htonl(INADDR_ANY); ++ server.sin_addr.s_addr = inet_addr(GetConfigValue(_CONF_BINDADDRESS)); + if (bind(i, (struct sockaddr *)&server, sizeof server) < 0) { + syslog(L_FATAL, "%s cant bind RCreader %m", LogName); + exit(1); --- inn-1.7.2q.orig/debian/patches/nnrpd_needs_libcrypt +++ inn-1.7.2q/debian/patches/nnrpd_needs_libcrypt @@ -0,0 +1,11 @@ +--- inn-1.7.2.orig/nnrpd/Makefile ++++ inn-1.7.2/nnrpd/Makefile +@@ -65,7 +67,7 @@ + + nnrpd: $(P) $(OBJECTS) $(LIBNEWS) + @rm -f $@ +- $(CC) $(LDFLAGS) -o $@ $(OBJECTS) $(LIBNEWS) $(LIBS) $(PERLLIB) ++ $(CC) $(LDFLAGS) -o $@ $(OBJECTS) $(LIBNEWS) $(LIBS) $(PERLLIB) -lcrypt + + lint: $(ALL) + @rm -f lint --- inn-1.7.2q.orig/debian/patches/innwatch_ctlinnd_timeout +++ inn-1.7.2q/debian/patches/innwatch_ctlinnd_timeout @@ -0,0 +1,29 @@ +--- inn-1.7.2.orig/samples/innwatch ++++ inn-1.7.2/samples/innwatch +@@ -24,6 +24,8 @@ + ## Logfile to watch. Comment out if no logwatch. + LOGFILE=${MOST_LOGS}/news.crit + ++CTLINND_TMOUT=300 ++ + ## Parse JCL. + while [ $# -gt 0 ] ; do + case X"$1" in +@@ -127,7 +129,7 @@ + + ## Check to see if INND is running. + ## Notify NEWSMASTER if it has stopped or just restarted. +- if ctlinnd -s -t 120 mode 2>/dev/null ; then ++ if ctlinnd -s -t $CTLINND_TMOUT mode 2>/dev/null ; then + ${HASEXITED} && { + HASEXITED=false + ${MAILCMD} -s "INND is now running" ${NEWSMASTER} &1 \ --- inn-1.7.2q.orig/debian/patches/misc_rc.news +++ inn-1.7.2q/debian/patches/misc_rc.news @@ -0,0 +1,55 @@ +--- inn-1.7.2.orig/samples/rc.news ++++ inn-1.7.2/samples/rc.news +@@ -11,7 +11,8 @@ + ## Pick ${INND} or ${INNDSTART} + WHAT=${INNDSTART} + ## Set to true or false +-DOINNWATCH=true ++DOINNWATCH=false ++DOACTIVED=false + MAIL="${MAILCMD} -s 'Boot-time Usenet warning on `hostname`' ${NEWSMASTER}" + + ## RFLAG is set below; set FLAGS as appropriate. +@@ -63,18 +64,27 @@ + rm -f ${NEWSCONTROL} ${NNTPCONNECT} ${SERVERPID} + + ## Start the show. +-echo 'Starting innd.' ++echo -n 'Starting news server:' + eval ${WHAT} ${RFLAG} ${FLAGS} ++echo -n ' innd' ++ ++${DOACTIVED} && { ++ echo -n ' actived' ++ ${NEWSBIN}/actived > $ERRLOG 2>&1 ++} + + # Gee, looks like lisp, doesn't it? + ${DOINNWATCH} && { +- ( sleep 60 ; ${INNWATCH} ) & ++ echo -n ' innwatch' ++ ( sleep 60 ; exec ${INNWATCH} > $ERRLOG 2>&1 ) & + } + ++echo '.' ++ + RMFILE=${MOST_LOGS}/expire.rm + for F in ${RMFILE} ${RMFILE}.*; do + if [ -f $F -a -s $F ] ; then +- echo "Removing articles from pre-downtime expire run (${F})." ++ echo "INND: Removing articles from pre-downtime expire run (${F})." + ( + echo 'System shut down during expire.' \ + 'Unlinking articles listed in' +diff -ruNp inn-1.7.2.orig/doc/innwatch.8 inn-1.7.2/doc/innwatch.8 +--- inn-1.7.2.orig/doc/innwatch.8 1997-12-09 00:48:50.000000000 +0100 ++++ inn-1.7.2/doc/innwatch.8 2005-07-31 12:49:25.000000000 +0200 +@@ -12,7 +12,7 @@ innwatch \- monitor innd. + .SH DESCRIPTION + .I Innwatch + is normally started by +-.IR rc.news . ++.IR /etc/news/boot . + It periodically \(em every + .\" =()<.I (@@)>()= + .I (600) --- inn-1.7.2q.orig/debian/patches/0_insync_actived +++ inn-1.7.2q/debian/patches/0_insync_actived @@ -0,0 +1,1533 @@ +--- inn-1.7.2.orig/config/files.list ++++ inn-1.7.2/config/files.list +@@ -107,4 +107,5 @@ + ../syslog/syslog.c + ../syslog/syslog.conf + ../syslog/syslogd.c ++../actived/Makefile + ;; Do not run subst on its own manpage! ../doc/subst.1 +--- inn-1.7.2.orig/include/paths.h ++++ inn-1.7.2/include/paths.h +@@ -210,3 +217,13 @@ + + /* =()<#define _PATH_PERL_FILTER_NNRPD "@<_PATH_PERL_FILTER_NNRPD>@">()= */ + #define _PATH_PERL_FILTER_NNRPD "/usr/news/bin/control/filter_nnrpd.pl" ++ ++/* ++** 18. actived configuration ++*/ ++ ++/* =()<#define _PATH_ACTIVED "@<_PATH_ACTIVED>@">()= */ ++#define _PATH_ACTIVED "/usr/lib/news/bin/actived" ++/* =()<#define _PATH_ACTIVEDPID "@<_PATH_ACTIVEDPID>@">()= */ ++#define _PATH_ACTIVEDPID "/var/run/innd/actived.pid" ++ +--- inn-1.7.2.orig/nnrpd/Makefile ++++ inn-1.7.2/nnrpd/Makefile +@@ -37,13 +37,15 @@ + LIBNEWS = ../libinn.a + LINTLIB = ../llib-linn.ln + ++CFLAGS+= -DOVERSCREAM ++ + SOURCES = \ + article.c group.c commands.c misc.c newnews.c nnrpd.c \ +- perl.c post.c loadave.c ++ perl.c post.c loadave.c udp.c + + OBJECTS = \ + article.o group.o commands.o misc.o newnews.o nnrpd.o \ +- perl.o post.o loadave.o ++ perl.o post.o loadave.o udp.o + + ALL = nnrpd + +--- inn-1.7.2.orig/nnrpd/group.c ++++ inn-1.7.2/nnrpd/group.c +@@ -8,6 +8,9 @@ + #include "clibrary.h" + #include "nnrpd.h" + #include "mydir.h" ++#include "../actived/protocol.h" ++#include ++#include + + + /* +@@ -30,13 +33,34 @@ + STATIC GROUPENTRY *GRPentries; + STATIC int GRPbuckets; + STATIC int GRPsize; ++STATIC int GRPactived = -1; ++int GRPuselocalhash = 1; /*actived is disabled by default*/ ++STATIC int NRequestID; ++ ++ ++void ++NNewRequestID() ++{ ++ static int pid = -1; ++ static int count = 123456789; ++ struct timeval tv; ++ ++ if (pid < 0) { ++ pid = getpid(); ++ } ++ gettimeofday(&tv, NULL); ++ count += pid; ++ NRequestID = tv.tv_sec ^ tv.tv_usec ^ pid ^ count; ++} ++ ++ + + + /* + ** See if a given newsgroup exists. + */ + GROUPENTRY * +-GRPfind(group) ++XGRPfind(group) + register char *group; + { + register char *p; +@@ -56,8 +80,129 @@ + } + + ++ ++GROUPENTRY * ++NGRPfind(group) ++ register char *group; ++{ ++ int now = time(NULL); ++ int expireat = now + ACTIVED_TIMEOUT; ++ int last = now - 2; ++ static struct wireprotocol buffer; ++ fd_set fdset; ++ struct timeval timeout; ++ static GROUPENTRY data; ++ ++ /* Okay. Let's ask the server for the data. */ ++ NNewRequestID(); ++ while (now < expireat) { ++ now = time(NULL); ++ if (last < now - 1) { ++ last = now; ++ buffer.RequestID = NRequestID; ++ buffer.RequestType = REQ_FIND; ++ strncpy(buffer.Name, group, sizeof(buffer.Name) - 1); ++ buffer.Name[sizeof(buffer.Name) - 1] = '\0'; ++ ++ if (write_udp(GRPactived, (char *)&buffer, sizeof(buffer)) != sizeof(buffer)) { ++ syslog(L_ERROR, "%s actived socket couldnt be written FIND %m", ++ ClientHost); ++ sleep(1); ++ continue; ++ } ++ } ++ FD_ZERO(&fdset); ++ FD_SET(GRPactived, &fdset); ++ timeout.tv_sec = 1; ++ timeout.tv_usec = 0; ++ if (select(GRPactived + 1, &fdset, NULL, NULL, &timeout) < 0) { ++ syslog(L_ERROR, "%s actived socket failed select %m", ++ ClientHost); ++ sleep(1); ++ continue; ++ } ++ if (FD_ISSET(GRPactived, &fdset)) { ++ if (read_udp(GRPactived, (char *)&buffer, sizeof(buffer)) != sizeof(buffer)) { ++ syslog(L_ERROR, "%s actived socket couldnt be read FINDRESP %m", ++ ClientHost); ++ sleep(1); ++ continue; ++ } ++ if (buffer.RequestID != NRequestID) { ++ syslog(L_ERROR, "%s actived socket returned a different request-ID %d/%d", ++ ClientHost, buffer.RequestID, NRequestID); ++ sleep(1); ++ continue; ++ } ++ if (buffer.RequestType != REQ_FINDRESP) { ++ syslog(L_ERROR, "%s actived socket returned a non-FINDRESP %d", ++ ClientHost, buffer.RequestType); ++ sleep(1); ++ continue; ++ } ++ ++ /* Was the request successful? Did we find the group? */ ++ if (! buffer.Success) { ++ return(NULL); ++ } ++ ++ /* Looks good! Copy all the data to the static "data" struct */ ++ if (! buffer.NameNull) { ++ data.Name = buffer.Name; ++ } else { ++ data.Name = NULL; ++ } ++ data.High = buffer.High; ++ data.Low = buffer.Low; ++ data.Flag = buffer.Flag; ++ if (! buffer.AliasNull) { ++ data.Alias = buffer.Alias; ++ } else { ++ data.Alias = NULL; ++ } ++ return(&data); ++ } ++ } ++ ++ /* Something is very wrong. Fall back to local access and whine like ++ hell. GRPuselocalhash is explicitly checked by GRPfind, and will ++ handle initializing the database for us. */ ++ ++ syslog(L_ERROR, "%s NOT using actived", ClientHost); ++ GRPuselocalhash++; ++ return(NULL); ++} ++ ++ ++GROUPENTRY * ++GRPfind(group) ++ register char *group; ++{ ++ GROUPENTRY *rval; ++ ++ /* ++ * If we are not flagged to use local hash, call NGRPfind. ++ * That could potentially fail (server no answer, etc) in which ++ * case we fall back to standard INN and scream bloody murder. ++ * NGRPfind will toggle GRPuselocalhash to TRUE if it has problems. ++ */ ++ ++ if (! GRPuselocalhash) { ++ rval = NGRPfind(group); ++ if (! GRPuselocalhash) { ++ return(rval); ++ } ++ ++ /* Ow! We are falling back to local access since NGRPfind failed! */ ++ XGetGroupList(); ++ } ++ ++ return(XGRPfind(group)); ++} ++ ++ + STATIC void +-GRPhash() ++XGRPhash() + { + register char *p; + register int i; +@@ -100,7 +245,7 @@ + ** newsgroups read in. Return TRUE if okay, FALSE on error. + */ + BOOL +-GetGroupList() ++XGetGroupList() + { + static char *active; + register char *p; +@@ -166,10 +311,112 @@ + } + + GRPsize = i; +- GRPhash(); ++ XGRPhash(); + return TRUE; + } + ++BOOL ++NGetGroupList() ++{ ++ int now = time(NULL); ++ int expireat = now + ACTIVED_TIMEOUT; ++ int last = now - 2; ++ int s; ++ struct wireprotocol buffer; ++ fd_set fdset; ++ struct timeval timeout; ++ ++ if (GRPactived < 0) { ++ if ((s = create_udp_socket(0)) < 0) { ++ syslog(L_ERROR, "%s actived socket couldnt be created %m", ++ ClientHost); ++ return(FALSE); ++ } ++ if (connect_udp_socket(s, "localhost", 1119) < 0) { ++ syslog(L_ERROR, "%s actived socket couldnt be connected %m", ++ ClientHost); ++ return(FALSE); ++ } ++ if (fcntl(s, F_SETFL, O_NDELAY) < 0) { ++ syslog(L_ERROR, "%s actived socket couldnt be fcntl O_NDELAY %m", ++ ClientHost); ++ return(FALSE); ++ } ++ GRPactived = s; ++ } ++ ++ /* Okay. Let's ask the server if it's there. */ ++ NNewRequestID(); ++ while (now < expireat) { ++ now = time(NULL); ++ if (last < now - 1) { ++ last = now; ++ buffer.RequestID = NRequestID; ++ buffer.RequestType = REQ_AYT; ++ ++ if (write_udp(GRPactived, (char *)&buffer, sizeof(buffer)) != sizeof(buffer)) { ++ syslog(L_ERROR, "%s actived socket couldnt be written AYT %m", ++ ClientHost); ++ sleep(1); ++ continue; ++ } ++ } ++ FD_ZERO(&fdset); ++ FD_SET(GRPactived, &fdset); ++ timeout.tv_sec = 1; ++ timeout.tv_usec = 0; ++ if (select(GRPactived + 1, &fdset, NULL, NULL, &timeout) < 0) { ++ syslog(L_ERROR, "%s actived socket failed select %m", ++ ClientHost); ++ sleep(1); ++ return(FALSE); ++ } ++ if (FD_ISSET(GRPactived, &fdset)) { ++ if (read_udp(GRPactived, (char *)&buffer, sizeof(buffer)) != sizeof(buffer)) { ++ syslog(L_ERROR, "%s actived socket couldnt be read AYTACK %m", ++ ClientHost); ++ sleep(1); ++ continue; ++ } ++ if (buffer.RequestID != NRequestID) { ++ syslog(L_ERROR, "%s actived socket returned a different request-ID %d/%d", ++ ClientHost, buffer.RequestID, NRequestID); ++ sleep(1); ++ continue; ++ } ++ if (buffer.RequestType != REQ_AYTACK) { ++ syslog(L_ERROR, "%s actived socket returned a non-AYTACK %d", ++ ClientHost, buffer.RequestType); ++ sleep(1); ++ continue; ++ } ++ /* Looks good! */ ++ return(TRUE); ++ } ++ } ++ return(FALSE); ++} ++ ++BOOL ++GetGroupList() ++{ ++ /* ++ * If we are not flagged to use local hash, call NGetGroupList. ++ * That could potentially fail (server no answer, etc) in which ++ * case we fall back to standard INN and scream bloody murder. ++ */ ++ if (! GRPuselocalhash) { ++ if (NGetGroupList() == FALSE) { ++ syslog(L_ERROR, "%s NOT using actived", ClientHost); ++ GRPuselocalhash++; ++ return(XGetGroupList()); ++ } ++ return(TRUE); ++ } else { ++ return(XGetGroupList()); ++ } ++} ++ + + /* + ** Sorting predicate to put newsgroup names into numeric order. +--- inn-1.7.2.orig/nnrpd/nnrpd.c ++++ inn-1.7.2/nnrpd/nnrpd.c +@@ -636,6 +637,14 @@ + ExitWithStats(0); + } + ++ { ++ char *UseActived; ++ extern int GRPuselocalhash; ++ if ((UseActived = GetConfigValue(_CONF_USEACTIVED)) != NULL) ++ if (EQ(UseActived, "true") || EQ(UseActived, "yes")) ++ GRPuselocalhash = 0; ++ } ++ + ARTreadschema(); + if (!GetGroupList()) { + /* This shouldn't really happen. */ +--- inn-1.7.2.orig/nnrpd/udp.c ++++ inn-1.7.2/nnrpd/udp.c +@@ -0,0 +1,160 @@ ++#include ++#include ++#include "clibrary.h" ++#include ++#include ++#include ++#include ++#include "logging.h" ++ ++#ifdef NEED_BZERO_ETC ++#include ++void ++bzero(b, length) ++ char *b; ++ int length; ++{ ++ while (--length >= 0) ++ *b++ = '\0'; ++} ++void ++bcopy(b1, b2, length) ++ char *b1; ++ char *b2; ++ int length; ++{ ++ while (--length >= 0) ++ *b2++ = *b1++; ++} ++#endif ++ ++int create_udp_socket(int port) ++{ ++ int s; ++ struct sockaddr_in sin; ++ ++ sin.sin_port = htons(port); ++ sin.sin_family = AF_INET; ++ sin.sin_addr.s_addr = INADDR_ANY; ++ ++ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { ++ syslog(L_ERROR, "create_udp_socket: socket: %m"); ++ return(-1); ++ } ++ if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { ++ syslog(L_ERROR, "create_udp_socket: bind: %m"); ++ return(-1); ++ } ++ return(s); ++} ++ ++ ++ ++ ++ ++int make_udp_sockaddr(struct sockaddr_in *addr, char *ascii) ++{ ++ struct hostent *host; ++ int dots = 0; ++ int numeric = 0; ++ char *str, *colon, *lastdot, *ptr; ++ ++ if (! (str = malloc(strlen(ascii) + 1))) { ++ syslog(L_ERROR, "make_udp_sockaddr: malloc: %m"); ++ return(-1); ++ } ++ strcpy(str, ascii); ++ colon = strrchr(str, ':'); ++ lastdot = strrchr(str, '.'); ++ ++ addr->sin_family = AF_INET; ++ ++ /* Count the number of dots in the address. */ ++ for (ptr = str; *ptr; ptr++) { ++ if (*ptr == '.') { ++ dots++; ++ } ++ } ++ ++ /* Check if it seems to be numeric. */ ++ numeric = isdigit(*str); ++ ++ /* If numeric and four dots, we have a.b.c.d.6000 */ ++ if (numeric && dots == 4) { ++ *lastdot = '\0'; ++ addr->sin_port = htons(atoi(lastdot + 1)); ++ } ++ /* If nonnumeric, check if the last part is a port */ ++ if (! numeric && lastdot && isdigit(*(lastdot + 1))) { ++ *lastdot = '\0'; ++ addr->sin_port = htons(atoi(lastdot + 1)); ++ } ++ /* Now do we have a numeric address */ ++ if (numeric) { ++ addr->sin_addr.s_addr = inet_addr(str); ++ free(str); ++ return(0); ++ } ++ /* Or a name */ ++ if (! (host = gethostbyname(str))) { ++ free(str); ++ syslog(L_ERROR, "make_udp_sockaddr: gethostbyname: %m"); ++ return(-1); ++ } ++ bcopy(host->h_addr_list[0], (char *)&addr->sin_addr.s_addr, sizeof(addr->sin_addr.s_addr)); ++ free(str); ++ return(0); ++} ++ ++ ++ ++ ++ ++int connect_udp_socket(int s, char *address, int port) ++{ ++ struct sockaddr_in sin; ++ ++ bzero(&sin, sizeof(sin)); ++ sin.sin_port = htons(port); ++ sin.sin_family = AF_INET; ++ sin.sin_addr.s_addr = INADDR_ANY; ++ ++ if (make_udp_sockaddr(&sin, address) < 0) { ++ return(-1); ++ } ++ if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { ++ syslog(L_ERROR, "connect_udp_socket: connect: %m"); ++ return(-1); ++ } ++ return(0); ++} ++ ++ ++ ++ ++ ++int write_udp(int s, char *buf, int len) ++{ ++ int rval; ++ ++ if ((rval = send(s, buf, len, 0x0)) < 0) { ++ syslog(L_ERROR, "write_udp: send: %m"); ++ return(-1); ++ } ++ return(rval); ++} ++ ++ ++ ++ ++ ++int read_udp(int s, char *buf, int len) ++{ ++ int rval; ++ ++ if ((rval = recv(s, buf, len, 0x0)) < 0) { ++ syslog(L_ERROR, "read_udp: recv: %m"); ++ return(-1); ++ } ++ return(rval); ++} +--- inn-1.7.2.orig/Makefile ++++ inn-1.7.2/Makefile +@@ -17,7 +17,7 @@ + RCSCOFLAGS = -u + + ## The first two directories must be config and lib. +-PROGS = config lib frontends innd nnrpd backends expire doc ++PROGS = config lib frontends innd nnrpd actived backends expire doc + DIRS = $(PROGS) site + + ## We invoke an extra process and set this to be what to make. +--- inn-1.7.2.orig/actived/Makefile ++++ inn-1.7.2/actived/Makefile +@@ -0,0 +1,97 @@ ++## $Revision: 1.16 $ ++SHELL = /bin/sh ++MAKE = make ++DESTDIR = ++D = $(DESTDIR) ++## =()

@>()= ++P = ++ ++## =()@>()= ++CC = gcc ++## =()@>()= ++DEFS = -I../include ++## =()@>()= ++CFLAGS = $(DEFS) -g ++## =()@>()= ++LDFLAGS = ++## =()@>()= ++LINTFLAGS = -b -h -z $(DEFS) ++## =()@>()= ++LINTFILTER = | sed -n -f ../sedf.sun ++## =()@>()= ++CTAGS = ctags -t -w ++## =()@>()= ++PROF = -pg ++ ++## =()@>()= ++ACTIVED = /usr/lib/news/bin/actived ++## =()@ -G @@>()= ++OWNER = -O news -G news ++ ++## =()@>()= ++LIBS = -lutil ++LIBNEWS = ../libinn.a ++LINTLIB = ../llib-linn.ln ++ ++SOURCES = \ ++ actived.c group.c udp.c activedstats.c ++ ++OBJECTS = \ ++ actived.o group.o udp.o activedstats.o ++ ++ALL = actived ++ ++all: $(ALL) ++ ++install: $D$(ACTIVED) ++ ++## Low-level install actions. ++$D$(ACTIVED): actived ++ $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ ++ ++clobber clean: ++ rm -f *.o $(ALL) ++ rm -f actived activedp profiled ++ rm -f all install lint ++ ++tags ctags: $(SOURCES) ++ $(CTAGS) $(SOURCES) ../lib/*.c actived.h ../include/*.h ++ ++actived: $(P) $(OBJECTS) $(LIBNEWS) ++ @rm -f $@ ++ $(CC) $(LDFLAGS) -o $@ $(OBJECTS) $(LIBNEWS) $(LIBS) ++ ++lint: $(ALL) ++ @rm -f lint ++ lint $(LINTFLAGS) $(SOURCES) $(LINTLIB) $(LINTFILTER) >lint ++ ++../include/dbz.h: ++ (cd ../lib ; $(MAKE) ../include/dbz.h) ++$(LIBNEWS) $(LINTLIB): ++ (cd ../lib ; $(MAKE) install ) ++ ++## Profiling. The rules are a bit brute-force, but good enough. ++profiled: activedp ++ date >$@ ++ ++activedp: $(SOURCES) ++ rm -f $(OBJECTS) ++ $(MAKE) actived CFLAGS="$(CFLAGS) $(PROF)" LIBNEWS=../libinn_p.a ++ mv actived activedp ++ rm -f $(OBJECTS) ++ ++ccenter: $(SOURCES) ++ #load $(CFLAGS) $(SOURCES) $(LIBNEWS) ++ ++## Dependencies. Default list, below, is probably good enough. ++depend: Makefile $(SOURCES) ++ makedepend $(DEFS) $(SOURCES) ++ ++# DO NOT DELETE THIS LINE -- make depend depends on it. ++$(OBJECTS): actived.h \ ++ ../include/clibrary.h ../include/configdata.h \ ++ ../include/libinn.h ../include/logging.h \ ++ ../include/macros.h ../include/nntp.h \ ++ ../include/paths.h ../include/qio.h ++group.o: ../include/mydir.h ++misc.o: ../include/dbz.h +--- inn-1.7.2.orig/actived/actived.c ++++ inn-1.7.2/actived/actived.c +@@ -0,0 +1,189 @@ ++/* $Revision: 1.18 $ ++** ++** Active file server for readers (NNRP) for InterNetNews. ++*/ ++ ++#define UPDATE_INTERVAL 30 ++#define MAINLINE ++#include ++#include "actived.h" ++#include "protocol.h" ++#include "configdata.h" ++#include "paths.h" ++ ++ ++ ++char ACTIVE[] = _PATH_ACTIVE; ++char PID[] = _PATH_ACTIVEDPID; ++char INNDDIR[] = _PATH_INNDDIR; ++STATIC UID_T NewsUID; ++STATIC GID_T NewsGID; ++struct stat Sb; ++ ++int ++handle(s) ++ int s; ++{ ++ GROUPENTRY *ptr; ++ struct sockaddr saddr; ++ struct sockaddr_in *sin = (struct sockaddr_in *)&saddr; ++ int saddrsiz = sizeof(saddr); ++ struct wireprotocol buffer; ++ int len = sizeof(buffer); ++ int rval; ++ ++ if ((rval = recvfrom(s, (char *)&buffer, len, 0, &saddr, &saddrsiz)) < 0) { ++ syslog(L_ERROR, "cant recvfrom %m"); ++ return(-1); ++ } ++ ++ if (rval != sizeof(buffer)) { ++ syslog(L_ERROR, "message size wrong"); ++ return(-1); ++ } ++ ++ /* XXX If not 127.0.0.1, then reject and return */ ++ ++ ++ switch (buffer.RequestType) { ++ case REQ_AYT: ++ buffer.RequestType = REQ_AYTACK; ++ if (sendto(s, (char *)&buffer, len, 0, &saddr, saddrsiz) < 0) { ++ syslog(L_ERROR, "cant sendto %m"); ++ return(-1); ++ } ++ return(0); ++ case REQ_FIND: ++ buffer.RequestType = REQ_FINDRESP; ++ ++ buffer.Name[sizeof(buffer.Name) - 1] = '\0'; ++ if (! (ptr = GRPfind(buffer.Name))) { ++ buffer.Success = 0; ++ } else { ++ buffer.Success = 1; ++ if (ptr->Name) { ++ buffer.NameNull = 0; ++ strncpy(buffer.Name, ptr->Name, sizeof(buffer.Name) - 1); ++ buffer.Name[sizeof(buffer.Name) - 1] = '\0'; ++ } else { ++ buffer.NameNull = 1; ++ } ++ buffer.High = ptr->High; ++ buffer.Low = ptr->Low; ++ buffer.Flag = ptr->Flag; ++ if (ptr->Alias) { ++ buffer.AliasNull = 0; ++ strncpy(buffer.Alias, ptr->Alias, sizeof(buffer.Alias) - 1); ++ buffer.Alias[sizeof(buffer.Alias) - 1] = '\0'; ++ } else { ++ buffer.AliasNull = 1; ++ } ++ } ++ if (sendto(s, (char *)&buffer, len, 0, &saddr, saddrsiz) < 0) { ++ syslog(L_ERROR, "cant sendto %m"); ++ return(-1); ++ } ++ return(0); ++ } ++ syslog(L_ERROR, "unknown requesttype %d", buffer.RequestType); ++ return(-1); ++} ++ ++ ++ ++ ++ ++/* ARGSUSED0 */ ++int ++main(argc, argv) ++ int argc; ++ char *argv[]; ++{ ++ int s, i; ++ time_t last_active_update = time(NULL), now; ++ fd_set fdset; ++ struct timeval tv; ++ FILE *F; ++ PID_T pid; ++ static char WHEN[] = "Pid file"; ++ char LogName[] = "ACTIVED"; ++ if (stat(INNDDIR, &Sb) < 0 || !S_ISDIR(Sb.st_mode)) { ++ syslog(L_FATAL, "inndstart cant stat %s %m", INNDDIR); ++ exit(1); ++ } ++ NewsUID = Sb.st_uid; ++ NewsGID = Sb.st_gid; ++ ++ openlog("actived", L_OPENLOG_FLAGS | LOG_PID, LOG_INN_PROG); ++ ++ if ((s = create_udp_socket(1119)) < 0) { ++ syslog(L_ERROR, "cant createudpsocket %m"); ++ exit(1); ++ } ++ if (fcntl(s, F_SETFL, O_NONBLOCK) < 0) { ++ syslog(L_ERROR, "cant fcntl O_NDELAY socket %m"); ++ exit(1); ++ } ++ if (!GetGroupList()) { ++ /* This shouldn't really happen. */ ++ syslog(L_ERROR, "cant getgrouplist %m"); ++ exit(1); ++ } ++ i = fork(); ++ if (i < 0) ++ syslog(L_ERROR, "daemon: cannot fork"); ++ if (i != 0) ++ exit(0); ++ ++ /* Change our UID and GID */ ++ if (setgid(NewsGID) == -1) ++ syslog(L_ERROR, "actived cant setgid: %m"); ++ if (setuid(NewsUID) == -1) ++ syslog(L_ERROR, "actived cant setuid: %m"); ++ ++ /* Record our PID. */ ++ pid = getpid(); ++ if ((F = fopen(PID, "w")) == NULL) { ++ i = errno; ++ syslog(L_ERROR, "%s cant fopen %s %m", LogName, PID); ++ } ++ else { ++ if (fprintf(F, "%ld\n", (long)pid) == EOF || ferror(F)) { ++ i = errno; ++ syslog(L_ERROR, "%s cant fprintf %s %m", LogName, PID); ++ } ++ if (fclose(F) == EOF) { ++ i = errno; ++ syslog(L_ERROR, "%s cant fclose %s %m", LogName, PID); ++ } ++ if (chmod(PID, 0664) < 0) { ++ i = errno; ++ syslog(L_ERROR, "%s cant chmod %s %m", LogName, PID); ++ } ++ } ++ ++ for (;;) { ++ FD_ZERO(&fdset); ++ FD_SET(s, &fdset); ++ tv.tv_sec = 0; ++ tv.tv_usec = 300000; ++ if (select(s + 1, &fdset, NULL, NULL, &tv) < 0) { ++ syslog(L_ERROR, "cant select %m"); ++ exit(1); ++ } ++ now = time(NULL); ++ if (now > last_active_update + UPDATE_INTERVAL) { ++ last_active_update = now; ++ if (!GetGroupList()) { ++ /* This shouldn't really happen. */ ++ syslog(L_ERROR, "cant getgrouplist %m"); ++ exit(1); ++ } ++ } ++ if (FD_ISSET(s, &fdset)) { ++ handle(s); ++ loads(0, 1); ++ } ++ } ++ /* NOTREACHED */ ++} +--- inn-1.7.2.orig/actived/actived.h ++++ inn-1.7.2/actived/actived.h +@@ -0,0 +1,51 @@ ++/* $Revision: 1.15 $ ++** ++*/ ++#include "configdata.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#if defined(VAR_VARARGS) ++#include ++#endif /* defined(VAR_VARARGS) */ ++#if defined(VAR_STDARGS) ++#include ++#endif /* defined(VAR_STDARGS) */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "paths.h" ++#include "nntp.h" ++#include "logging.h" ++#include "clibrary.h" ++#include "libinn.h" ++#include "qio.h" ++#include "macros.h" ++ ++ ++/* ++** A group entry. ++*/ ++typedef struct _GROUPENTRY { ++ char *Name; ++ ARTNUM High; ++ ARTNUM Low; ++ char Flag; ++ char *Alias; ++} GROUPENTRY; ++ ++ ++#if defined(MAINLINE) ++#define EXTERN /* NULL */ ++#else ++#define EXTERN extern ++#endif /* defined(MAINLINE) */ ++ ++extern char ACTIVE[]; ++extern GROUPENTRY *GRPfind(); +--- inn-1.7.2.orig/actived/activedstats.c ++++ inn-1.7.2/actived/activedstats.c +@@ -0,0 +1,147 @@ ++/* ++ * Copyright (c) 1996 ++ * Joe Greco. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Joe Greco. ++ * 4. Neither the name of the author nor the names of any co-contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY JOE GRECO AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL JOE GRECO OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ */ ++ ++ ++#include ++#include ++#include ++ ++ ++/* This breaks past 1024; see comments in sys/param.h - soln: make 64 bits */ ++ ++#define FSHIFT 11 /* bits to right of fixed binary point */ ++#define FSCALE (1<ldavg[i] = (cexp[i] * avg->ldavg[i] + ++ nrun * FSCALE * (FSCALE - cexp[i])) >> FSHIFT; ++} ++ ++/* ++ * Call this every half a second or so - every five seconds, it will ++ * calculate loads. ++ * ++ * Originally designed for readers. We don't care for actived and ++ * instead we call with loads(0, 1) for requests, and loads (0, 0) ++ * for periodic calls. ++ * ++ * Formerly: ++ * When a reader connects: loads(+1, 1) ++ * disconn's: loads(-1, 0) ++ */ ++ ++int ++loads(int reader_count, int startup_count) ++{ ++ static int readers = 0; ++ static int startups = 0; ++ struct timeval tv; ++ static int tv_next = 0; ++ ++ readers += reader_count; ++ startups += startup_count; ++ ++ gettimeofday(&tv, NULL); ++ ++ if (! tv_next) { ++ tv_next = tv.tv_sec + 5; ++ } ++ if (tv.tv_sec >= tv_next) { ++ tv_next += 5; ++ loadav(&avgreaders, readers); ++ loadav(&avgstartups, startups); ++ startups = 0; ++ dumploads(); ++ } ++ return(0); ++} ++ ++int dumploads() ++{ ++ FILE *fp; ++ ++ if (! (fp = fopen("/var/log/news/activedloads", "w"))) { ++ return(-1); ++ } ++ fprintloads(fp); ++ fclose(fp); ++ return(0); ++} ++ ++int ++fprintloads(FILE *fp) ++{ ++ double avenrun[3]; ++ int i; ++ ++ for (i = 0; i < 3; i++) { ++ avenrun[i] = (double) avgstartups.ldavg[i] / avgstartups.fscale; ++ } ++ fprintf(fp, "Average ACTIVED Loads: "); ++ for (i = 0; i < (sizeof(avenrun) / sizeof(avenrun[0])); i++) { ++ if (i > 0) ++ fprintf(fp, ","); ++ fprintf(fp, " %6.2f", avenrun[i]); ++ } ++ fprintf(fp, "\n"); ++} +--- inn-1.7.2.orig/actived/group.c ++++ inn-1.7.2/actived/group.c +@@ -0,0 +1,166 @@ ++/* $Revision: 1.13 $ ++** ++** Newsgroups and the active file. ++*/ ++#include "actived.h" ++ ++ ++/* ++** Newsgroup hashing stuff. See comments in innd/ng.c. ++*/ ++ ++#define GRP_HASH(Name, p, j) \ ++ for (p = Name, j = 0; *p; ) j = (j << 5) + j + *p++ ++#define GRP_SIZE 65536 ++#define GRP_BUCKET(j) &GRPtable[j & (GRP_SIZE - 1)] ++ ++typedef struct _GRPHASH { ++ int Size; ++ int Used; ++ GROUPENTRY **Groups; ++} GRPHASH; ++ ++ ++STATIC GRPHASH GRPtable[GRP_SIZE]; ++STATIC GROUPENTRY *GRPentries; ++STATIC int GRPbuckets; ++STATIC int GRPsize; ++ ++ ++/* ++** See if a given newsgroup exists. ++*/ ++GROUPENTRY * ++GRPfind(group) ++ register char *group; ++{ ++ register char *p; ++ register unsigned int j; ++ register int i; ++ register GROUPENTRY **gpp; ++ GRPHASH *htp; ++ char c; ++ ++ /* SUPPRESS 6 *//* Over/underflow from plus expression */ ++ GRP_HASH(group, p, j); ++ htp = GRP_BUCKET(j); ++ for (c = *group, gpp = htp->Groups, i = htp->Used; --i >= 0; gpp++) ++ if (c == gpp[0]->Name[0] && EQ(group, gpp[0]->Name)) ++ return gpp[0]; ++ return NULL; ++} ++ ++ ++STATIC void ++GRPhash() ++{ ++ register char *p; ++ register int i; ++ register GROUPENTRY *gp; ++ register unsigned int j; ++ register GRPHASH *htp; ++ ++ /* Set up the default hash buckets. */ ++ GRPbuckets = GRPsize / GRP_SIZE; ++ if (GRPbuckets == 0) ++ GRPbuckets = 1; ++ if (GRPtable[0].Groups) ++ for (i = GRP_SIZE, htp = GRPtable; --i >= 0; htp++) ++ htp->Used = 0; ++ else ++ for (i = GRP_SIZE, htp = GRPtable; --i >= 0; htp++) { ++ htp->Size = GRPbuckets; ++ htp->Groups = NEW(GROUPENTRY*, htp->Size); ++ htp->Used = 0; ++ } ++ ++ /* Now put all groups into the hash table. */ ++ for (i = GRPsize, gp = GRPentries; --i >= 0; gp++) { ++ /* SUPPRESS 6 *//* Over/underflow from plus expression */ ++ GRP_HASH(gp->Name, p, j); ++ htp = GRP_BUCKET(j); ++ if (htp->Used >= htp->Size) { ++ htp->Size += GRPbuckets; ++ RENEW(htp->Groups, GROUPENTRY*, htp->Size); ++ } ++ htp->Groups[htp->Used++] = gp; ++ } ++ ++ /* Note that we don't sort the buckets. */ ++} ++ ++ ++/* ++** Read the active file into memory, sort it, and set the number of ++** newsgroups read in. Return TRUE if okay, FALSE on error. ++*/ ++BOOL ++GetGroupList() ++{ ++ static char *active; ++ register char *p; ++ register char *q; ++ register GROUPENTRY *gp; ++ register int i; ++ ++ /* If re-scanning, free previous groups. */ ++ if (active != NULL) { ++ DISPOSE(active); ++ DISPOSE(GRPentries); ++ } ++ ++ /* Get the new file. */ ++ active = ReadInFile(ACTIVE, (struct stat *)NULL); ++ if (active == NULL) { ++ syslog(L_ERROR, "cant read %s %m", ACTIVE); ++ return FALSE; ++ } ++ ++ /* Count lines. */ ++ for (p = active, i = 0; (p = strchr(p, '\n')) != NULL; p++, i++) ++ continue; ++ ++ /* Fill in the group array. */ ++ GRPentries = NEW(GROUPENTRY, i); ++ for (i = 0, gp = GRPentries, p = active; *p; i++, gp++, p = q + 1) { ++ gp->Name = p; ++ if ((p = strchr(p, ' ')) == NULL) { ++ syslog(L_ERROR, "internal no_space1 \"%.20s...\"", ++ gp->Name); ++ return FALSE; ++ } ++ *p++ = '\0'; ++ ++ /* Get the high mark. */ ++ if ((q = strchr(p, ' ')) == NULL) { ++ syslog(L_ERROR, "internal no_space2 \"%.20s...\"", ++ gp->Name); ++ return FALSE; ++ } ++ *q++ = '\0'; ++ gp->High = atol(p); ++ ++ /* Get the low mark. */ ++ if ((p = strchr(q, ' ')) == NULL) { ++ syslog(L_ERROR, "internal no_space3 \"%.20s...\"", ++ gp->Name); ++ return FALSE; ++ } ++ *p++ = '\0'; ++ gp->Low = atol(q); ++ ++ /* Kill the newline. */ ++ if ((q = strchr(p, '\n')) == NULL) { ++ syslog(L_ERROR, "internal newline \"%.20s...\"", ++ gp->Name); ++ return FALSE; ++ } ++ *q = '\0'; ++ gp->Flag = *p; ++ gp->Alias = gp->Flag == NF_FLAG_ALIAS ? p + 1 : NULL; ++ } ++ ++ GRPsize = i; ++ GRPhash(); ++ return TRUE; ++} +--- inn-1.7.2.orig/actived/protocol.h ++++ inn-1.7.2/actived/protocol.h +@@ -0,0 +1,19 @@ ++#define ACTIVED_TIMEOUT 10 ++ ++#define REQ_AYT 1 ++#define REQ_AYTACK 2 ++#define REQ_FIND 3 ++#define REQ_FINDRESP 4 ++ ++struct wireprotocol { ++ int RequestType; ++ int RequestID; ++ int Success; ++ int NameNull; ++ char Name[1024]; ++ ARTNUM High; ++ ARTNUM Low; ++ char Flag; ++ int AliasNull; ++ char Alias[1024]; ++}; +--- inn-1.7.2.orig/actived/query.c ++++ inn-1.7.2/actived/query.c +@@ -0,0 +1,48 @@ ++#include ++#include "actived.h" ++#include "protocol.h" ++ ++ ++int main(argc, argv) ++int argc; ++char *argv[]; ++{ ++ int s, i; ++ int start = time(NULL) - 1; ++ struct wireprotocol buffer; ++ ++ if ((s = create_udp_socket(0)) < 0) { ++ fprintf(stderr, "couldnt create socket\n"); ++ exit(1); ++ } ++ if (connect_udp_socket(s, "localhost", 1119) < 0) { ++ fprintf(stderr, "couldnt connect socket\n"); ++ exit(1); ++ } ++ i = 0; ++ buffer.RequestType = REQ_FIND; ++ buffer.RequestID = getpid(); ++ sprintf(buffer.Name, argv[1]); ++ ++ fprintf(stderr, "asking question: request-id %d, group \"%s\"\n\n", buffer.RequestID, buffer.Name); ++ ++ if (write_udp(s, (char *)&buffer, sizeof(buffer)) < 0) { ++ fprintf(stderr, "couldnt write packet\n"); ++ exit(1); ++ } ++ if (read_udp(s, (char *)&buffer, sizeof(buffer)) != sizeof(buffer)) { ++ fprintf(stderr, "couldnt read packet\n"); ++ exit(1); ++ } ++ fprintf(stderr, "request-id ok? %s (%d)\n", buffer.RequestID == getpid() ? "yes" : "no", buffer.RequestID); ++ fprintf(stderr, "response type correct? %s (%d)\n", buffer.RequestType == REQ_FINDRESP ? "yes" : "no", buffer.RequestType); ++ fprintf(stderr, "success? %s\n", buffer.Success ? "yes" : "no"); ++ fprintf(stderr, "name? %s\n", buffer.NameNull ? "" : buffer.Name); ++ fprintf(stderr, "alias? %s\n", buffer.AliasNull ? "" : buffer.Alias); ++ fprintf(stderr, "range? %d-%d\n", buffer.Low, buffer.High); ++ fprintf(stderr, "flag? %c\n", buffer.Flag); ++} ++ ++ ++ ++ +--- inn-1.7.2.orig/actived/test.c ++++ inn-1.7.2/actived/test.c +@@ -0,0 +1,43 @@ ++#include ++#include "actived.h" ++#include "protocol.h" ++ ++ ++int main(argc, argv) ++int argc; ++char *argv[]; ++{ ++ int s, i; ++ int start = time(NULL) - 1; ++ struct wireprotocol buffer; ++ ++ if ((s = create_udp_socket(0)) < 0) { ++ fprintf(stderr, "couldnt create socket\n"); ++ exit(1); ++ } ++ if (connect_udp_socket(s, "localhost", 1119) < 0) { ++ fprintf(stderr, "couldnt connect socket\n"); ++ exit(1); ++ } ++ i = 0; ++ fprintf(stderr, "%08d", 0); ++ for (;;) { ++ buffer.RequestType = REQ_FIND; ++ sprintf(buffer.Name, "alt.sex"); ++ if (write_udp(s, (char *)&buffer, sizeof(buffer)) < 0) { ++ fprintf(stderr, "couldnt write packet\n"); ++ exit(1); ++ } ++ if (read_udp(s, (char *)&buffer, sizeof(buffer)) != sizeof(buffer)) { ++ fprintf(stderr, "couldnt read packet\n"); ++ exit(1); ++ } ++ if (! (++i % 100)) { ++ fprintf(stderr, "\r%08d %5.2f", i, (float)i / (time(NULL) - start)); ++ } ++ } ++} ++ ++ ++ ++ +--- inn-1.7.2.orig/actived/udp.c ++++ inn-1.7.2/actived/udp.c +@@ -0,0 +1,160 @@ ++#include ++#include ++#include "clibrary.h" ++#include ++#include ++#include ++#include ++#include "logging.h" ++ ++#ifdef NEED_BZERO_ETC ++#include ++void ++bzero(b, length) ++ char *b; ++ int length; ++{ ++ while (--length >= 0) ++ *b++ = '\0'; ++} ++void ++bcopy(b1, b2, length) ++ char *b1; ++ char *b2; ++ int length; ++{ ++ while (--length >= 0) ++ *b2++ = *b1++; ++} ++#endif ++ ++int create_udp_socket(int port) ++{ ++ int s; ++ struct sockaddr_in sin; ++ ++ sin.sin_port = htons(port); ++ sin.sin_family = AF_INET; ++ sin.sin_addr.s_addr = INADDR_ANY; ++ ++ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { ++ syslog(L_ERROR, "create_udp_socket: socket: %m"); ++ return(-1); ++ } ++ if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { ++ syslog(L_ERROR, "create_udp_socket: bind: %m"); ++ return(-1); ++ } ++ return(s); ++} ++ ++ ++ ++ ++ ++int make_udp_sockaddr(struct sockaddr_in *addr, char *ascii) ++{ ++ struct hostent *host; ++ int dots = 0; ++ int numeric = 0; ++ char *str, *colon, *lastdot, *ptr; ++ ++ if (! (str = malloc(strlen(ascii) + 1))) { ++ syslog(L_ERROR, "make_udp_sockaddr: malloc: %m"); ++ return(-1); ++ } ++ strcpy(str, ascii); ++ colon = strrchr(str, ':'); ++ lastdot = strrchr(str, '.'); ++ ++ addr->sin_family = AF_INET; ++ ++ /* Count the number of dots in the address. */ ++ for (ptr = str; *ptr; ptr++) { ++ if (*ptr == '.') { ++ dots++; ++ } ++ } ++ ++ /* Check if it seems to be numeric. */ ++ numeric = isdigit(*str); ++ ++ /* If numeric and four dots, we have a.b.c.d.6000 */ ++ if (numeric && dots == 4) { ++ *lastdot = '\0'; ++ addr->sin_port = htons(atoi(lastdot + 1)); ++ } ++ /* If nonnumeric, check if the last part is a port */ ++ if (! numeric && lastdot && isdigit(*(lastdot + 1))) { ++ *lastdot = '\0'; ++ addr->sin_port = htons(atoi(lastdot + 1)); ++ } ++ /* Now do we have a numeric address */ ++ if (numeric) { ++ addr->sin_addr.s_addr = inet_addr(str); ++ free(str); ++ return(0); ++ } ++ /* Or a name */ ++ if (! (host = gethostbyname(str))) { ++ free(str); ++ syslog(L_ERROR, "make_udp_sockaddr: gethostbyname: %m"); ++ return(-1); ++ } ++ bcopy(host->h_addr_list[0], (char *)&addr->sin_addr.s_addr, sizeof(addr->sin_addr.s_addr)); ++ free(str); ++ return(0); ++} ++ ++ ++ ++ ++ ++int connect_udp_socket(int s, char *address, int port) ++{ ++ struct sockaddr_in sin; ++ ++ bzero(&sin, sizeof(sin)); ++ sin.sin_port = htons(port); ++ sin.sin_family = AF_INET; ++ sin.sin_addr.s_addr = INADDR_ANY; ++ ++ if (make_udp_sockaddr(&sin, address) < 0) { ++ return(-1); ++ } ++ if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { ++ syslog(L_ERROR, "connect_udp_socket: connect: %m"); ++ return(-1); ++ } ++ return(0); ++} ++ ++ ++ ++ ++ ++int write_udp(int s, char *buf, int len) ++{ ++ int rval; ++ ++ if ((rval = send(s, buf, len, 0x0)) < 0) { ++ syslog(L_ERROR, "write_udp: send: %m"); ++ return(-1); ++ } ++ return(rval); ++} ++ ++ ++ ++ ++ ++int read_udp(int s, char *buf, int len) ++{ ++ int rval; ++ ++ if ((rval = recv(s, buf, len, 0x0)) < 0) { ++ syslog(L_ERROR, "read_udp: recv: %m"); ++ return(-1); ++ } ++ return(rval); ++} +--- inn-1.7.2.orig/actived/README.actived ++++ inn-1.7.2/actived/README.actived +@@ -0,0 +1,46 @@ ++This is nnrpd-actived. ++ ++I found that one of the huge bottlenecks in an nnrp-oriented INN system ++is creating new sessions. I spent some time and tracked down one of the ++big time-consumers... hashing the active file. Even with sharedactive, ++each client would hash the contents into a local hash table, and with a ++very large active file, this took an appreciable amount of time. ++ ++My CPU's could do it a few times a second, but during peak periods, I ++see 5+ new connections per second, which essentially floods the CPU. ++ ++One fix would have been to have the nnrpd that updated the shared memory ++space also update a shared hash table. I didn't like that since I still ++think the sharedactive thing is uccchy. It used to occasionally snag ++a semaphore and hang a few hundred nnrpd's in limbo. Sharing the active ++file via mmap had drawbacks as well. ++ ++I finally decided to go a different route. I created an "active file ++server". This server reads and rehashes the active file once every 30 ++seconds, and will answer UDP requests about the contents of the file. ++ ++This is able to handle thousands of transactions per second, even though ++I rarely even see hundreds in production use. I can start up a hundred ++nnrp sessions a second without response time suffering noticeably. ++ ++The system is designed to fall back to standard active file accesses in ++the case actived falls over, which it hasn't in several months of ++production use. Hopefully my code is correct. I would strongly advise ++anyone who runs it to periodically check to see if actived has died, and ++restart it. Just because I've had luck with it,... ;-) ++ ++To install: patch your nnrpd with the enclosed "group.c.patch". ++Build the contents of this directory, install and run "actived", you ++can compile "query" and ask it a few questions (i.e. "query alt.sex"), ++and then install your new nnrpd if all looks good. ++ ++JG970605 ++ ++-- ++ ++I've made several changes to Joe's code (with Joe's assistance--thanks) to ++make actived a bit more portable. I've successfully compiled this version on ++Solaris 2.4, Solaris 2.5.1, SunOS 4.1.4, Linux 2.0.30, and OpenBSD 2.1, so ++I suspect it'll compile on just about anything now. ++ ++-Andrew Smith 970625 --- inn-1.7.2q.orig/debian/patches/rnews_reject_reason +++ inn-1.7.2q/debian/patches/rnews_reject_reason @@ -0,0 +1,19 @@ +diff -ruN inn-1.7.2.orig/frontends/rnews.c inn-1.7.2/frontends/rnews.c +--- inn-1.7.2.orig/frontends/rnews.c 2004-07-12 18:29:17.000000000 +0200 ++++ inn-1.7.2/frontends/rnews.c 2004-07-12 18:29:07.000000000 +0200 +@@ -207,6 +207,15 @@ + syslog(L_ERROR, "cant fopen %s %m", buff); + return; + } ++ { ++ char h[1024], r[1024]; ++ int len; ++ sprintf(r, reason, arg); ++ sprintf(h, "X-rnews-Reject-Reason: %s\n", r); ++ len = strlen(h); ++ if (fwrite(h, 1, len, F) != len) ++ syslog(L_ERROR, "cant fwrite %s %m", buff); ++ } + i = strlen(article); + if (fwrite((POINTER)article, (SIZE_T)1, (SIZE_T)i, F) != i) + syslog(L_ERROR, "cant fwrite %s %m", buff); --- inn-1.7.2q.orig/debian/patches/innd.c_init_TimeOut +++ inn-1.7.2q/debian/patches/innd.c_init_TimeOut @@ -0,0 +1,10 @@ +--- inn-1.7.2.orig/innd/innd.c ++++ inn-1.7.2/innd/innd.c +@@ -621,6 +621,7 @@ + + /* Set defaults. */ + TimeOut.tv_sec = DEFAULT_TIMEOUT; ++ TimeOut.tv_usec = 0; + ShouldFork = TRUE; + ShouldRenumber = FALSE; + ShouldSyntaxCheck = FALSE; --- inn-1.7.2q.orig/debian/patches/1_perl_misc +++ inn-1.7.2q/debian/patches/1_perl_misc @@ -0,0 +1,203 @@ +--- inn-1.7.2.orig/lib/perl.c ++++ inn-1.7.2/lib/perl.c +@@ -29,11 +29,15 @@ + #include + #include + ++#include "libinn.h" /* xmalloc() prototype */ + #include "macros.h" + ++extern void xs_init _((pTHX)); ++extern void boot_DynaLoader _((CV* cv)); ++ + int PerlFilterActive = FALSE; + +-static PerlInterpreter *PerlCode; ++PerlInterpreter *PerlCode; + CV *perl_filter_cv ; /* filter_art or filter_post holder */ + extern char LogName[]; + +@@ -56,9 +60,9 @@ + if (PerlFilterActive && !value) { + if (perl_get_cv("filter_end", FALSE) != NULL) { + perl_call_argv("filter_end", G_EVAL|G_DISCARD|G_NOARGS, NULL); +- if (SvTRUE(GvSV(errgv))) /* check $@ */ { ++ if (SvTRUE(ERRSV)) /* check $@ */ { + syslog (L_ERROR,"%s perl function filter_end died: %s", +- LogName, SvPV(GvSV(errgv), na)) ; ++ LogName, SvPV(ERRSV, PL_na)) ; + POPs ; + } + } else { +@@ -89,7 +93,7 @@ + /* We can't call 'eval' and 'do' directly for some reason, so we define + some wrapper functions to give us access. */ + +- perl_parse (PerlCode,NULL,5,argv,NULL) ; ++ perl_parse (PerlCode,xs_init,5,argv,NULL) ; + } + + +@@ -126,9 +130,9 @@ + + SPAGAIN ; + +- if (SvTRUE(GvSV(errgv))) /* check $@ */ { ++ if (SvTRUE(ERRSV)) /* check $@ */ { + syslog (L_ERROR,"%s perl loading %s failed: %s", +- LogName, startupfile, SvPV(GvSV(errgv), na)) ; ++ LogName, startupfile, SvPV(ERRSV, PL_na)) ; + PerlFilter (FALSE) ; + + } else { +@@ -163,9 +167,9 @@ + + if (perl_get_cv("filter_before_reload", FALSE) != NULL) { + perl_call_argv("filter_before_reload",G_EVAL|G_DISCARD|G_NOARGS,NULL); +- if (SvTRUE(GvSV(errgv))) /* check $@ */ { ++ if (SvTRUE(ERRSV)) /* check $@ */ { + syslog (L_ERROR,"%s perl function filter_before_reload died: %s", +- LogName, SvPV(GvSV(errgv), na)) ; ++ LogName, SvPV(ERRSV, PL_na)) ; + POPs ; + PerlFilter (FALSE) ; + } +@@ -173,9 +177,9 @@ + + perl_call_argv ("_load_", 0, argv) ; + +- if (SvTRUE(GvSV(errgv))) /* check $@ */ { ++ if (SvTRUE(ERRSV)) /* check $@ */ { + syslog (L_ERROR,"%s perl loading %s failed: %s", +- LogName, filterfile, SvPV(GvSV(errgv), na)) ; ++ LogName, filterfile, SvPV(ERRSV, PL_na)) ; + PerlFilter (FALSE) ; + + /* If the reload failed we don't want the old definition hanging +@@ -184,9 +188,9 @@ + sprintf (argv[0],"undef &%s",function) ; + perl_call_argv ("_eval_",0,argv) ; + +- if (SvTRUE(GvSV(errgv))) /* check $@ */ { ++ if (SvTRUE(ERRSV)) /* check $@ */ { + syslog (L_ERROR,"%s perl undef &%s failed: %s", +- LogName, function, SvPV(GvSV(errgv), na)) ; ++ LogName, function, SvPV(ERRSV, PL_na)) ; + } + DISPOSE (argv[0]) ; + } else if ((perl_filter_cv = perl_get_cv(function, FALSE)) == NULL) { +@@ -195,9 +199,9 @@ + + if (perl_get_cv("filter_after_reload", FALSE) != NULL) { + perl_call_argv("filter_after_reload", G_EVAL|G_DISCARD|G_NOARGS, NULL); +- if (SvTRUE(GvSV(errgv))) /* check $@ */ { ++ if (SvTRUE(ERRSV)) /* check $@ */ { + syslog (L_ERROR,"%s perl function filter_after_reload died: %s", +- LogName, SvPV(GvSV(errgv), na)) ; ++ LogName, SvPV(ERRSV, PL_na)) ; + POPs ; + PerlFilter (FALSE) ; + } +@@ -221,5 +225,13 @@ + PerlFilterActive = FALSE; + } + ++extern void xs_init(pTHX) ++{ ++ char * file = __FILE__; ++ dXSUB_SYS; ++ ++ newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file); ++} ++ + #endif /* defined(DO_PERL) */ + +--- inn-1.7.2.orig/innd/perl.c ++++ inn-1.7.2/innd/perl.c +@@ -27,6 +27,8 @@ + + #include + #include ++#define my_perl PerlCode ++extern PerlInterpreter *PerlCode; + + extern BOOL PerlFilterActive; + extern ARTHEADER ARTheaders[], *ARTheadersENDOF; +@@ -74,10 +81,63 @@ + + buf [0] = '\0' ; + +- if (SvTRUE(GvSV(errgv))) /* check $@ */ ++ if (SvTRUE(ERRSV)) /* check $@ */ + { + syslog (L_ERROR,"Perl function filter_art died: %s", +- SvPV(GvSV(errgv), na)) ; ++ SvPV(ERRSV, PL_na)) ; ++ POPs ; ++ PerlFilter (FALSE) ; ++ } ++ else if (rc == 1) ++ { ++ p = POPp; ++ ++ if (p != NULL && *p != '\0') ++ { ++ strncpy(buf, p, sizeof(buf) - 1); ++ buf[sizeof(buf) - 1] = '\0'; ++ } ++ } ++ ++ PUTBACK; ++ FREETMPS; ++ LEAVE; ++ ++ if (buf[0] != '\0') ++ return buf ; ++ return NULL; ++} ++ ++ ++char * ++HandleMessageID(messageID) ++char *messageID; ++{ ++ dSP; ++ int rc; ++ char *p; ++ static char * args[2]; ++ static char buf[256]; ++ ++ if (!PerlFilterActive || perl_filter_cv == NULL || perl_get_cv("filter_messageid", FALSE) == NULL) ++ return NULL; ++ ++ ++ ENTER ; ++ SAVETMPS ; ++ ++ args[0] = messageID; ++ args[1] = 0; ++ rc = perl_call_argv ("filter_messageid", G_EVAL|G_SCALAR, args); ++ ++ SPAGAIN; ++ ++ buf [0] = '\0' ; ++ ++ if (SvTRUE(ERRSV)) /* check $@ */ ++ { ++ syslog (L_ERROR,"Perl function filter_messageid died: %s", ++ SvPV(ERRSV, PL_na)) ; + POPs ; + PerlFilter (FALSE) ; + } +@@ -132,9 +192,9 @@ + + if (perl_get_cv("filter_mode", FALSE) != NULL) { + perl_call_argv("filter_mode", G_EVAL|G_DISCARD|G_NOARGS, NULL); +- if (SvTRUE(GvSV(errgv))) { /* check $@ */ ++ if (SvTRUE(ERRSV)) { /* check $@ */ + syslog (L_ERROR,"Perl function filter_mode died: %s", +- SvPV(GvSV(errgv), na)) ; ++ SvPV(ERRSV, PL_na)) ; + POPs ; + PerlFilter (FALSE) ; + } --- inn-1.7.2q.orig/debian/patches/getmodaddr.c +++ inn-1.7.2q/debian/patches/getmodaddr.c @@ -0,0 +1,22 @@ +--- inn-1.7.2.orig/lib/getmodaddr.c ++++ inn-1.7.2/lib/getmodaddr.c +@@ -120,6 +120,7 @@ + (void)strcpy(GMApathname, _PATH_TEMPMODERATORS); + (void)mktemp(GMApathname); + GMAfp = GMA_listopen(GMApathname, FromServer, ToServer, "moderators"); ++ if (GMAfp == NULL) GMAfp = fopen(_PATH_MODERATORS, "r"); + } + + if (GMAfp != NULL) { +--- inn-1.7.2.orig/doc/inews.1 ++++ inn-1.7.2/doc/inews.1 +@@ -129,7 +129,8 @@ + If an unapproved posting is made to a moderated newsgroup, + .I inews + will try to mail the article to the moderator for posting. +-It uses the ++It will query the remote news server for a moderators listing. If ++that doesn't succeed, it will fallback to using the local + .IR moderators (5) + file to determine the mailing address. + If no address is found, it will use the --- inn-1.7.2q.orig/debian/patches/1_perl_filter_patch +++ inn-1.7.2q/debian/patches/1_perl_filter_patch @@ -0,0 +1,64 @@ +--- inn-1.7.2.orig/innd/art.c ++++ inn-1.7.2/innd/art.c +@@ -136,6 +139,29 @@ + { "Posting-Version", HTobs }, + { "Received", HTobs }, + { "Relay-Version", HTobs }, ++ { "NNTP-Posting-Host", HTstd }, ++ { "Followup-To", HTstd }, ++ { "Organization", HTstd }, ++ { "Content-Type", HTstd }, ++ { "Content-Base", HTstd }, ++ { "Content-Disposition", HTstd }, ++ { "Content-Transfer-Encoding", HTstd }, ++ { "X-Trace", HTstd }, ++ { "X-Newsreader", HTstd }, ++ { "X-Mailer", HTstd }, ++ { "X-Newsposter", HTstd }, ++ { "X-Cancelled-By", HTstd }, ++ { "X-Canceled-By", HTstd }, ++ { "Cancel-Key", HTstd }, ++ { "Cancel-Lock", HTstd }, ++ { "List-ID", HTstd }, ++ { "X-HTTP-UserAgent", HTstd }, ++ { "X-HTTP-Via", HTstd }, ++ { "X-No-Archive", HTstd }, ++ { "Injection-Info", HTstd }, ++ { "Injection-Date", HTstd }, ++ { "NNTP-Posting-Date", HTstd }, ++ { "In-Reply-To", HTstd }, + }; + + ARTHEADER *ARTheadersENDOF = ENDOF(ARTheaders); +@@ -1817,7 +1892,7 @@ + + #if defined(DO_PERL) + pathForPerl = HeaderFind(article->Data, "Path", 4) ; +- if ((perlrc = (char *)HandleArticle()) != NULL) { ++ if ((perlrc = (char *)HandleArticle(Data.Body)) != NULL) { + (void)sprintf(buff, "%d %s", NNTP_REJECTIT_VAL, perlrc); + syslog(L_NOTICE, "rejecting[perl] %s %s", HDR(_message_id), buff); + ARTlog(&Data, ART_REJECT, buff); +--- inn-1.7.2.orig/innd/perl.c ++++ inn-1.7.2/innd/perl.c +@@ -34,7 +36,8 @@ + extern char *pathForPerl ; + + char * +-HandleArticle() ++HandleArticle(artBody) ++char *artBody; + { + dSP; + ARTHEADER *hp; +@@ -54,6 +57,10 @@ + hv_store(hdr, (char *) hp->Name, strlen(hp->Name), newSVpv(hp->Value, 0), 0); + } + ++ /* store article body */ ++ if (artBody != NULL) ++ hv_store(hdr, (char *) "__BODY__", 8, newSVpv(artBody, 0), 0) ; ++ + if (pathForPerl != NULL) + { + char *p = strchr (pathForPerl,'\n') ; --- inn-1.7.2q.orig/debian/patches/path_audit +++ inn-1.7.2q/debian/patches/path_audit @@ -0,0 +1,477 @@ +--- inn-1.7.2.orig/samples/hosts.nntp ++++ inn-1.7.2/samples/hosts.nntp +@@ -3,6 +3,11 @@ + ## Format + ## : + ## : ++## :: + ## can be a name or IP address; no wildcards. Any hosts not + ## listed here are handed off to nnrpd. +-localhost: ++## can be followed by some parameters: ++## /a IP address of the feeder should always be included in the Path: line ++## /t IP address of the feeder should never be included in the Path: line ++## /s the feeder is allowed to do streaming (please read hosts.nntp(5)!) ++localhost/t: +--- inn-1.7.2.orig/doc/hosts.nntp.5 ++++ inn-1.7.2/doc/hosts.nntp.5 +@@ -70,6 +73,24 @@ + .fi + .RE + .PP ++The first field may be suffixed by ``/a'' to indicate that the IP ++address of the feeding hosts allowed by this entry should always be ++included in the Path line of articles, or by ``/t'' to indicate that ++the address should not be included, or ``/a'' followed by a pathhost ++value to indicate that the IP address should be included if the most ++recent Path entry does not match the pathhost specified after ``/a''. ++The default is to log the address in articles whose most recent Path ++entry is not the same as the hostname in the hosts.nntp entry. ++.\" .PP ++.\" The first field may be suffixed by ``/i'' to indicate that the TCP ++.\" Ident information should be included in the Path lines of articles. ++.\" ``/i'' may be followed by one or more usernames separated by commas; ++.\" if so then those usernames will not be logged. If ``/i'' is specified ++.\" then articles received over connections for which TCP ident ++.\" information was not available have ``?'' used for the username ++.\" information. If ``/i'' implies the logging of a username then the IP ++.\" address will be logged even if this would not ordinarily be the case. ++.PP + Since + .I innd + is usually started at system boot time, the local nameserver may not be +--- inn-1.7.2.orig/include/configdata.h ++++ inn-1.7.2/include/configdata.h +@@ -309,6 +309,12 @@ + /* Log by host IP address, rather than from Path line? */ + /* =()<#define @@_IPADDR_LOG>()= */ + #define DO_IPADDR_LOG ++ /* Support putting feeding IP address in Paths (/a,/t hosts.nntp options)*/ ++ /* =()<#define @@_IPADDR_PATH>()= */ ++#define DO_IPADDR_PATH ++ /* Support logging TCP Ident info in Paths (/i hosts.nntp option, requires IPADDR_PATH) */ ++ /* =()<#define @@_TCPIDENT_PATH>()= */ ++#define DONT_TCPIDENT_PATH + /* Log NNTP activity after this many articles. */ + /* =()<#define NNTP_ACTIVITY_SYNC @@>()= */ + #define NNTP_ACTIVITY_SYNC 200 +--- inn-1.7.2.orig/innd/art.c ++++ inn-1.7.2/innd/art.c +@@ -533,7 +548,7 @@ + register IOVEC *vp; + register long size; + register char *p; +- IOVEC iov[7]; ++ IOVEC iov[11]; + IOVEC *end; + char bytesbuff[SMBUF]; + int i; +@@ -567,6 +582,27 @@ + size += (vp++)->iov_len; + } + ++#if defined(DO_IPADDR_PATH) ++ if (Data->Feedaddress.s_addr) { ++#if defined(DO_TCPIDENT_PATH) ++ if (Data->Feedident) { ++ vp->iov_base = Data->Feedident; ++ vp->iov_len = strlen(vp->iov_base); ++ size += (vp++)->iov_len; ++ vp->iov_base = "@"; ++ vp->iov_len = 1; ++ size += (vp++)->iov_len; ++ } ++#endif /* defined(DO_TCPIDENT_PATH) */ ++ vp->iov_base = inet_ntoa(Data->Feedaddress); ++ vp->iov_len = strlen(vp->iov_base); ++ size += (vp++)->iov_len; ++ vp->iov_base = "!"; ++ vp->iov_len = 1; ++ size += (vp++)->iov_len; ++ } ++#endif /* defined(DO_IPADDR_PATH) */ ++ + vp->iov_base = p; + vp->iov_len = Data->Body - p; + size += (vp++)->iov_len; +@@ -1778,6 +1836,23 @@ + #else + Data.Feedsite = hops && hops[0] ? hops[0] : CHANname(cp); + #endif /* defined(DO_IPADDRLOG) */ ++ ++#if defined(DO_IPADDR_PATH) ++ if (cp->PathAddr || ++#if defined(DO_TCPIDENT_PATH) ++ cp->IdentForPath || ++#endif /* defined(DO_TCPIDENT_PATH) */ ++ cp->RequirePathHostForPath && ++ (!hops || !hops[0] || strcmp(hops[0],cp->RequirePathHostForPath))){ ++ Data.Feedaddress = cp->Address; ++ Data.Feedident = cp->IdentForPath; ++ } else ++#endif /* defined(DO_IPADDR_PATH) */ ++ { ++ Data.Feedaddress.s_addr = 0; ++ Data.Feedident = NULL; ++ } ++ + Data.FeedsiteLength = strlen(Data.Feedsite); + (void)sprintf(Data.TimeReceived, "%lu", Now.time); + Data.TimeReceivedLength = strlen(Data.TimeReceived); +--- inn-1.7.2.orig/innd/chan.c ++++ inn-1.7.2/innd/chan.c +@@ -100,6 +102,8 @@ + (SIZE_T)(CHANtablesize * sizeof *CHANtable)); + CHANnull.NextLog = CHANNEL_INACTIVE_TIME; + CHANnull.Address.s_addr = MyAddress.s_addr; ++ CHANnull.RequirePathHostForPath = NULL; ++ CHANnull.IdentForPath = NULL; + for (cp = CHANtable; --i >= 0; cp++) + *cp = CHANnull; + } +@@ -265,6 +269,14 @@ + cp->Sendid.Size = 0; + DISPOSE(cp->Sendid.Data); + } ++ if (cp->RequirePathHostForPath) { ++ DISPOSE(cp->RequirePathHostForPath); ++ cp->RequirePathHostForPath = NULL; ++ } ++ if (cp->IdentForPath) { ++ DISPOSE(cp->IdentForPath); ++ cp->IdentForPath = NULL; ++ } + } + + +--- inn-1.7.2.orig/innd/innd.h ++++ inn-1.7.2/innd/innd.h +@@ -132,6 +132,7 @@ + CHANNELTYPE Type; + CHANNELSTATE State; + BOOL Streaming ; /* had an '/s' on the end of hosts.nntp entry */ ++ BOOL PathAddr ; /* If TRUE then always add IP address info to Path */ + int fd; + int Reported; + long Received; +@@ -144,6 +145,8 @@ + time_t LastActive; + time_t NextLog; + INADDR Address; ++ char *RequirePathHostForPath; /* If non-null then add Path addr info if proximate Path entry not equal to this; PathAddr will be FALSE and IdentForPath NULL */ ++ char *IdentForPath; /* If non-null then PathAddr will be TRUE */ + FUNCPTR Reader; + FUNCPTR WriteDone; + time_t Waketime; +@@ -298,8 +301,12 @@ + int DistributionLength; + STRING Feedsite; + int FeedsiteLength; ++ INADDR Feedaddress; /* If Feedaddress is set then Feedident may be set. */ ++ char *Feedident; /* Feedident makes no sense on its own. */ + STRING Replic; + int ReplicLength; ++ STRING Path; ++ int PathLength; + BUFFER *Headers; + BUFFER *Overview; + } ARTDATA; +--- inn-1.7.2.orig/innd/rc.c ++++ inn-1.7.2/innd/rc.c +@@ -26,6 +26,10 @@ + #define COPYADDR(dest, src) \ + (void)memcpy((POINTER)dest, (POINTER)src, (SIZE_T)sizeof (INADDR)) + ++#if defined(DO_TCPIDENT_PATH) ++#include ++#endif /* defined(DO_TCPIDENT_PATH) */ ++ + /* + ** A remote host has an address and a password. + */ +@@ -34,6 +38,10 @@ + INADDR Address; + char *Password; + BOOL Streaming ; ++ BOOL PathAddr ; ++ char *RequirePathHostForPath ; ++ BOOL PathIdent ; ++ char **PathNoIdentIdents; + char **Patterns; + } REMOTEHOST; + +@@ -208,6 +216,86 @@ + + + /* ++** Sets the Path logging on a new NNTP channel, according to the ++** parameters given (which usually came from the hosts.nntp). ++*/ ++STATIC FUNCTYPE ++RCsetpathlogging(cp,PathAddr,RequirePathHost,PathIdent,PathNoIdentIdents) ++ CHANNEL *cp; ++ BOOL PathAddr; ++ char *RequirePathHost; ++ BOOL PathIdent; ++ char **PathNoIdentIdents; ++{ ++ char *ident; ++ char *protectwalk; ++ char *protectout; ++ char **noidentswalk; ++ int c; ++ int protectedlen; ++ ++#if defined(DO_IPADDR_PATH) ++#if defined(DO_TCPIDENT_PATH) ++ if (!PathIdent) { ++ cp->PathAddr= PathAddr; ++ cp->RequirePathHostForPath = RequirePathHost ? COPY(RequirePathHost) : NULL; ++ cp->IdentForPath = NULL; ++ return; ++ } ++ ident = ident_id(cp->fd,10); ++ if (!ident) { ++ cp->PathAddr = TRUE; ++ cp->RequirePathHostForPath = NULL; ++ cp->IdentForPath = NEW(char,2); ++ (void)strcpy(cp->IdentForPath,"?"); ++ return; ++ } ++ for (noidentswalk = PathNoIdentIdents; ++ noidentswalk && *noidentswalk; ++ noidentswalk++) { ++ if (!strcmp(*noidentswalk,ident)) { ++ DISPOSE(ident); ++ cp->PathAddr = PathAddr; ++ cp->RequirePathHostForPath = RequirePathHost ? COPY(RequirePathHost) : NULL; ++ cp->IdentForPath = NULL; ++ return; ++ } ++ } ++ for (protectwalk = ident, protectedlen = 0; ++ c = *protectwalk; ++ protectwalk++) ++ protectedlen += c == '\\' ? 2 : (c > 32 && c <= 127) ? 1 : 4; ++ cp->PathAddr = TRUE; ++ cp->RequirePathHostForPath = NULL; ++ cp->IdentForPath = NEW(char,protectedlen+1); ++ for (protectwalk = ident, protectout = cp->IdentForPath; ++ c = *protectwalk; ++ protectwalk++) { ++ if (c == '\\') { ++ *protectout++ = '\\'; ++ *protectout++ = '\\'; ++ } else if (c > 32 && c <= 127) { ++ *protectout++ = c; ++ } else { ++ sprintf(protectout,"\\x%02x",c & 0x0ff); ++ protectout += 4; ++ } ++ } ++ *protectout = '\0'; ++ return; ++#else ++ cp->PathAddr = PathAddr; ++ cp->RequirePathHostForPath = RequirePathHost ? COPY(RequirePathHost) : NULL; ++ cp->IdentForPath = NULL; ++#endif /* defined(DO_TCPIDENT_PATH) */ ++#else ++ cp->PathAddr = FALSE; ++ cp->RequirePathHostForPath = NULL; ++ cp->IdentForPath = NULL; ++#endif /* defined(DO_IPADDR_PATH) */ ++} ++ ++/* + ** Read function. Accept the connection and either create an NNTP channel + ** or spawn an nnrpd to handle it. + */ +@@ -353,8 +441,13 @@ + if (i >= 0) { + new = NCcreate(fd, rp->Password[0] != '\0', FALSE); + new->Streaming = rp->Streaming ; ++ RCsetpathlogging(new, ++ rp->PathAddr, rp->RequirePathHostForPath, ++ rp->PathIdent, rp->PathNoIdentIdents); + } else if (AnyIncoming) { + new = NCcreate(fd, FALSE, FALSE); ++ new->Streaming = FALSE ; ++ RCsetpathlogging(new, TRUE, NULL, TRUE, NULL); + } else { + RChandoff(fd, HOnntpd); + if (close(fd) < 0) +@@ -364,8 +457,10 @@ + + /* SUPPRESS 112 *//* Retrieving long where char is stored */ + new->Address.s_addr = remote.sin_addr.s_addr; +- syslog(L_NOTICE, "%s connected %d streaming %s", +- name ? name : inet_ntoa(new->Address), new->fd, ++ syslog(L_NOTICE, "%s connected %d%s%s streaming %s", ++ name ? name : inet_ntoa(new->Address), new->fd, ++ new->IdentForPath ? " ident " : "", ++ new->IdentForPath ? new->IdentForPath : "", + (!StreamingOff || new->Streaming) ? "allowed" : "not allowed"); + } + +@@ -403,6 +498,12 @@ + register REMOTEHOST *rp; + register int j; + int k ; ++ BOOL usedefaultrequirepathhost; ++ int exceptionscount; ++ char *attrib; ++ char *exceptionswalk; ++ char **exceptionsdispose; ++ char *delimiter; + char *pass; + char *pats; + int errors; +@@ -412,6 +513,15 @@ + for (rp = *list, i = *count; --i >= 0; rp++) { + DISPOSE(rp->Name); + DISPOSE(rp->Password); ++ if (rp->RequirePathHostForPath) ++ DISPOSE(rp->RequirePathHostForPath); ++ if (rp->PathNoIdentIdents) { ++ for (exceptionsdispose= rp->PathNoIdentIdents; ++ *exceptionsdispose; ++ exceptionsdispose++) ++ DISPOSE(*exceptionsdispose); ++ DISPOSE(rp->PathNoIdentIdents); ++ } + if (rp->Patterns) { + DISPOSE(rp->Patterns[0]); + DISPOSE(rp->Patterns); +@@ -437,6 +547,9 @@ + rp->Name = COPY("localhost"); + rp->Password = COPY(NOPASS); + rp->Patterns = NULL; ++ rp->PathAddr = FALSE; ++ rp->PathIdent = FALSE; ++ rp->PathNoIdentIdents = NULL; + rp++; + #endif /* !defined(DO_HAVE_UNIX_DOMAIN) */ + +@@ -462,20 +575,107 @@ + pats = NULL; + } + +- /* Check if the host name ends with '/s' which means that streaming is +- specifically permitted (as opposed to defaulted). The default +- for the global StreamingOff is FALSE, meaning any host can use +- streaming commands. If any entry is hosts.nntp has a suffix of +- '/s' then StreamingOff is set to TRUE, and then only those +- hosts.nntp entries with '/s' can use streaming commands. */ +- rp->Streaming = FALSE; +- if ((k = strlen(buff)) > 2) { +- if (buff[k - 1] == 's' && buff[k - 2] == '/') { +- buff[k - 2] = '\0'; +- rp->Streaming = TRUE; +- StreamingOff = TRUE ; +- } +- } ++ rp->Streaming = FALSE; ++ rp->PathAddr = FALSE; ++ rp->PathIdent = FALSE; ++ rp->PathNoIdentIdents = NULL; ++ rp->RequirePathHostForPath = NULL; ++ usedefaultrequirepathhost = TRUE; ++ ++ /* Check for `attributes', ie things after the hostname separated ++ by a /. This includes the following checks ... */ ++ ++ while ((attrib = strrchr(buff,'/')) != NULL) { ++ if (!strcmp(attrib,"/s")) { ++ /* Check if the host name ends with '/s' which means that streaming is ++ specifically permitted (as opposed to defaulted). The default ++ for the global StreamingOff is FALSE, meaning any host can use ++ streaming commands. If any entry is hosts.nntp has a suffix of ++ '/s' then StreamingOff is set to TRUE, and then only those ++ hosts.nntp entries with '/s' can use streaming commands. */ ++ ++ rp->Streaming = TRUE ; ++ StreamingOff = TRUE ; ++#if defined(DO_IPADDR_PATH) ++ } else if (!strcmp(attrib,"/t")) { ++ /* Check if the host name ends with '/t' which means ++ that this entry's articles should never have the ++ calling IP address of the feeding host logged in the ++ Path: line of accepted articles. */ ++ ++ rp->PathAddr = FALSE ; ++ usedefaultrequirepathhost = FALSE; ++ } else if (!strcmp(attrib,"/a")) { ++ /* Check if the host name ends with '/a' which means that this ++ entry's articles should have the calling IP address of the feeding ++ host logged in the Path: line of all accepted articles. */ ++ ++ rp->PathAddr = TRUE ; ++ usedefaultrequirepathhost = FALSE; ++ if (rp->RequirePathHostForPath != NULL) { ++ DISPOSE(rp->RequirePathHostForPath); ++ rp->RequirePathHostForPath = NULL; ++ } ++ } else if (!strncmp(attrib,"/a",2)) { ++ /* Check if the host name ends with `/a' which ++ means that this entry's articles should have the ++ calling IP address logged if it the most recent Path: ++ entry does not match the hostname supplied after `/a'. */ ++ ++ if (rp->RequirePathHostForPath != NULL) ++ DISPOSE(rp->RequirePathHostForPath); ++ usedefaultrequirepathhost = FALSE; ++ rp->RequirePathHostForPath = COPY(attrib+2); ++#if defined(DO_TCPIDENT_PATH) ++ } else if (!strncmp(attrib,"/i",2)) { ++ /* Check if the host name ends with ++ '/i[,,...]' which means that the ++ calling IP address and RFC1413 (TCP Remote Username ++ Service, aka 'ident') value should be logged, unless ++ the ident value is one of those listed. '/i' implies '/a'. */ ++ ++ rp->PathIdent = TRUE ; ++ if (attrib[2] == '\0') { ++ rp->PathNoIdentIdents = NULL; ++ } else { ++ exceptionswalk = attrib+2; ++ exceptionscount = 0; ++ for (;;) { ++ exceptionscount++; ++ exceptionswalk = strchr(exceptionswalk,','); ++ if (!exceptionswalk) break; ++ exceptionswalk++; ++ } ++ rp->PathNoIdentIdents = NEW(char*,exceptionscount++); ++ exceptionscount = 0; ++ exceptionswalk = attrib+2; ++ for (;;) { ++ delimiter = strchr(exceptionswalk,','); ++ k = delimiter ? delimiter-exceptionswalk ++ : strlen(exceptionswalk); ++ rp->PathNoIdentIdents[exceptionscount] = NEW(char,k+1); ++ memcpy(rp->PathNoIdentIdents[exceptionscount],exceptionswalk,k); ++ rp->PathNoIdentIdents[exceptionscount][k] = '\0'; ++ exceptionscount++; ++ if (!delimiter) break; ++ exceptionswalk = delimiter+1; ++ } ++ rp->PathNoIdentIdents[exceptionscount] = NULL; ++ } ++#endif /* defined(DO_TCPIDENT_PATH) */ ++#endif /* defined(DO_IPADDR_PATH) */ ++ } else { ++ syslog(L_NOTICE,"unknown attribute (ignored): %s",attrib); ++ } ++ *attrib = '\0'; ++ } ++ ++#if defined(DO_IPADDR_PATH) ++ if (usedefaultrequirepathhost) { ++ rp->RequirePathHostForPath = COPY(buff); ++ } ++ ++#endif /* defined(DO_IPADDR_PATH) */ + + /* Was host specified as as dotted quad? */ + if ((rp->Address.s_addr = inet_addr(buff)) != (unsigned int) -1) { --- inn-1.7.2q.orig/debian/patches/inewsport +++ inn-1.7.2q/debian/patches/inewsport @@ -0,0 +1,16 @@ +diff -ruN inn-1.7.2.orig/frontends/inews.c inn-1.7.2/frontends/inews.c +--- inn-1.7.2.orig/frontends/inews.c 2003-08-20 03:17:50.000000000 +0200 ++++ inn-1.7.2/frontends/inews.c 2003-08-20 03:17:44.000000000 +0200 +@@ -1306,6 +1306,12 @@ + break; + } + ++ /* Figure the server port. */ ++ if ((p = GetConfigValue("inewsport")) != NULL) { ++ extern char *nntp_port; ++ nntp_port = COPY(p); ++ } ++ + /* Try to open a connection to the server. */ + if (NNTPremoteopen(&FromServer, &ToServer, buff) < 0) { + Spooling = TRUE; --- inn-1.7.2q.orig/debian/patches/posix_arguments +++ inn-1.7.2q/debian/patches/posix_arguments @@ -0,0 +1,18 @@ +diff -ruNp inn-1.7.2.orig/samples/innstat inn-1.7.2/samples/innstat +--- inn-1.7.2.orig/samples/innstat 1997-12-09 00:48:50.000000000 +0100 ++++ inn-1.7.2/samples/innstat 2006-08-18 17:32:56.000000000 +0200 +@@ -32,12 +32,12 @@ ctlinnd mode 2>&1 + echo '' + echo 'Disk usage:' + ${INNDF} ${SPOOL} ${OVERVIEWDIR} ${NEWSLIB} ${INCOMING} ${BATCH} ${MOST_LOGS} | +- grep '/dev/' | sort -u ++ grep '^/' | sort -u + + ## Show size of batch files. + echo '' + echo 'Batch file sizes:' +-( cd ${BATCH}; ls -Cs | tail +2 ) ++( cd ${BATCH}; ls -Cs | tail -n +2 ) + + ## Show size of log files. + echo '' --- inn-1.7.2q.orig/debian/patches/0_insync_overscream +++ inn-1.7.2q/debian/patches/0_insync_overscream @@ -0,0 +1,584 @@ +--- inn-1.7.2.orig/nnrpd/article.c ++++ inn-1.7.2/nnrpd/article.c +@@ -8,6 +8,17 @@ + #include "clibrary.h" + #include "nnrpd.h" + ++/* ++ * OVERSCREAM - to make the overview database screaming fast, and because ++ * I scream in terror about the previous implementation. ++ * See http://www.xs4all.nl/~johnpc/inn/ for more information on this patch. ++ */ ++ ++#ifdef OVERSCREAM ++# include ++# include ++#endif /* OVERSCREAM */ ++ + + /* + ** Data structures for use in ARTICLE/HEAD/BODY/STAT common code. +@@ -61,11 +72,33 @@ + /* + ** Overview state information. + */ ++#ifdef OVERSCREAM ++ ++STATIC caddr_t OVERshm = (caddr_t) NULL; /* location of mmap */ ++STATIC size_t OVERsize; /* size of mmap */ ++STATIC size_t OVERmsize; /* real size of mmap */ ++STATIC int OVERfd; /* fd of file */ ++STATIC ARTNUM OVERfirst, OVERlast; /* first/last entries */ ++STATIC int OVERopens; /* Number of opens done */ ++STATIC char* OVERcache; /* cached position */ ++STATIC ARTNUM OVERprev; /* previous found art */ ++#define LINSEARCH 5 /* linear search range */ ++#define MIDSKEW 0.1 /* 10% bias toward middle */ ++ ++STATIC int mmapsuck; /* did we syslog already */ ++#define YOUR_MMAP_SUCKS if ( ! mmapsuck++ ) \ ++ syslog(L_NOTICE, "Your mmap() implementation sucks.") ++ ++#else /* !OVERSCREAM */ ++ + STATIC QIOSTATE *OVERqp; /* Open overview file */ + STATIC char *OVERline; /* Current line */ + STATIC ARTNUM OVERarticle; /* Current article */ + STATIC int OVERopens; /* Number of opens done */ + ++#endif ++ ++ + + /* + ** Read the overview schema. +@@ -691,6 +724,10 @@ + register int i; + ARTOVERFIELD *fp; + char *next; ++#ifdef OVERSCREAM ++ char* eol = strchr(p, '\n'); ++#endif ++ + + fp = &ARTfields[field - 1]; + +@@ -698,8 +735,13 @@ + field = ARTfirstfullfield; + + /* Skip leading headers. */ +- for (; --field >= 0 && *p; p++) ++ for (; --field >= 0 && *p && *p != '\n'; p++) ++#ifdef OVERSCREAM ++ if ((p = memchr(p, '\t', OVERsize - (p - OVERshm))) == NULL || ++ p > eol ) ++#else + if ((p = strchr(p, '\t')) == NULL) ++#endif + return NULL; + if (*p == '\0') + return NULL; +@@ -717,10 +759,22 @@ + } + + /* Figure out length; get space. */ ++ ++#ifdef OVERSCREAM ++ if ((next = memchr(p, '\t', OVERsize - (p - OVERshm))) != NULL && ++ p < eol ) ++ i = next - p; ++ else ++ i = eol - p; ++ ++#else /* !OVERSCREAM */ ++ + if ((next = strchr(p, '\t')) != NULL) + i = next - p; + else + i = strlen(p); ++#endif ++ + if (buffsize == 0) { + buffsize = i; + buff = NEW(char, buffsize + 1); +@@ -735,6 +789,430 @@ + return buff; + } + ++#ifdef OVERSCREAM ++ ++/* ++ * helper function, search backwards in memory ++ */ ++ ++STATIC char* ++inn_memrchr(p, c, l) ++ register char* p; ++ register char c; ++ register int l; ++{ ++ for (; l--; --p) ++ if ( *p == c ) ++ return(p); ++ return(NULL); ++} ++ ++/* ++ * mmap an OVERVIEW file. ++ */ ++ ++STATIC BOOL ++OVERopen() ++{ ++ char name[SPOOLNAMEBUFF]; ++ struct stat sb; ++ char* p; ++ static int pagesize = 0; ++ ++ /* return true if already mapped */ ++ if ( OVERshm ) { ++ return TRUE; ++ } ++ /* return false if already failed */ ++ if ( OVERopens++ ) { ++ return FALSE; ++ } ++ /* get memory pagesize if we don't have it already */ ++ if ( ! pagesize && ! ++#ifdef _SC_PAGE_SIZE ++ (pagesize = sysconf(_SC_PAGE_SIZE)) ++#else ++# ifdef _SC_PAGESIZE ++ (pagesize = sysconf(_SC_PAGESIZE)) ++# else ++ (pagesize = getpagesize()) ++# endif ++#endif ++ ) { ++ syslog(L_NOTICE, "%s: Can't getpagesize", ClientHost); ++ return FALSE; ++ } ++ /* mmap the file */ ++ (void)sprintf(name, "%s/%s/%s", _PATH_OVERVIEWDIR, GRPlast, _PATH_OVERVIEW); ++ if ( (OVERfd = open(name, O_RDONLY)) < 0 ) { ++ /* no overview file */ ++ syslog(L_NOTICE, "%s can't open %s: %m", ClientHost, name); ++ return FALSE; ++ } ++ if ( fstat(OVERfd, &sb) == -1 ) { ++ syslog(L_NOTICE, "%s can't stat %s: %m", ClientHost, name); ++ (void)close(OVERfd); ++ return FALSE; ++ } ++ if ( (OVERsize = sb.st_size) <= 1 ) { ++ syslog(L_NOTICE, "%s: %s is too small", ClientHost, name); ++ (void)close(OVERfd); ++ return FALSE; ++ } ++ OVERmsize = (OVERsize + pagesize - 1) & ~(pagesize - 1); ++ if ( (OVERshm = mmap(NULL, OVERmsize, PROT_READ, MAP_SHARED, OVERfd, 0)) ++ == (caddr_t) -1 ) ++ { ++ syslog(L_NOTICE, "%s can't mmap %s: %m", ClientHost, name); ++ (void)close(OVERfd); ++ OVERshm = NULL; ++ return FALSE; ++ } ++ /* get first entry */ ++ if ( (OVERfirst = atol((char*) OVERshm)) == 0 ) { ++ syslog(L_NOTICE, "%s: %s: bad format", ClientHost, name); ++ (void)munmap(OVERshm, OVERmsize); ++ (void)close(OVERfd); ++ OVERshm = NULL; ++ return FALSE; ++ } ++ ++ /* get last entry */ ++ if ( *(OVERshm + OVERsize - 1) != '\n' ) { ++ /* ++ * If you get here, then your mmap() implementation sucks. ++ * Go complain with your OS vendor, that their mmap() can't ++ * do mmap()ing of growing files properly. ++ * We try to find a decent record near the end, for the poor ++ * sobs without proper mmap. There are a lot of other places ++ * in the code with hacks for bad mmap(). Mainly because I'm ++ * one of the poor sobs :( ++ */ ++ YOUR_MMAP_SUCKS; ++ } ++ do { ++ /* ++ * Try to find any newline. If there isn't any, the entire file ++ * is crap. Normally this finds the newline right at the end. ++ */ ++ p = inn_memrchr(OVERshm + OVERsize - 1, '\n', OVERsize - 1); ++ if ( p == NULL ) { ++ /* overview file only contains garbage. */ ++ (void)munmap(OVERshm, OVERmsize); ++ (void)close(OVERfd); ++ OVERshm = NULL; ++ return FALSE; ++ } ++ OVERsize = p - OVERshm + 1; ++ if ( (p = inn_memrchr((char*) OVERshm + OVERsize - 2, '\n', ++ OVERsize - 2)) == NULL ) ++ { ++ /* Apparently only 1 (usable) line */ ++ OVERlast = OVERfirst; ++ OVERcache = NULL; ++ return TRUE; ++ } ++ OVERlast = atol(p+1); ++ } ++ while ( OVERlast == 0 && --OVERsize ); ++ ++ if ( !OVERsize ) { ++ (void)munmap(OVERshm, OVERmsize); ++ (void)close(OVERfd); ++ OVERshm = NULL; ++ return FALSE; ++ } ++ ++ OVERcache = NULL; ++ return TRUE; ++} ++ ++/* ++ * Close an overview file, if any. ++ */ ++ ++void ++OVERclose() ++{ ++ if ( OVERshm ) { ++ if ( munmap(OVERshm, OVERmsize) == -1 ) { ++ syslog(L_NOTICE, "%s can't munmap: %m", ClientHost); ++ } ++ (void)close(OVERfd); ++ OVERshm = NULL; ++ } ++ OVERopens = 0; ++} ++ ++/* ++ * find an overview article using binary search in the overview file. ++ * Returns a pointer to the actual line in the overview file (so it's ++ * !!NOT!! null terminated, and can't be written to!!), or NULL on failure. ++ */ ++ ++STATIC char* ++OVERfind(artnum) ++ ARTNUM artnum; ++{ ++ char* bottom; ++ char* top; ++ ARTNUM bottomnr; ++ ARTNUM topnr; ++ char* pos; ++ ARTNUM nr; ++ int i; ++ ++ /* default startpos */ ++ bottom = OVERshm; ++ bottomnr = OVERfirst; ++ top = OVERshm + OVERsize - 1; ++ topnr = OVERlast; ++ ++ if ( OVERcache ) { ++ /* ++ * for speedy sequential access. OVERcache, if non-NULL, points to ++ * the "next" entry. OVERprev is the previous article number found. ++ * Also check for sucking mmap() implementations. ++ */ ++ if ( *OVERcache == '\0' ) { ++ YOUR_MMAP_SUCKS; ++ OVERcache = memchr(OVERcache, '\n', ++ OVERsize - (OVERshm - OVERcache)); ++ if ( OVERcache == NULL || OVERcache == OVERshm + OVERsize - 1 ) { ++ OVERcache = NULL; ++ return NULL; ++ } ++ OVERcache++; ++ } ++ nr = atol(OVERcache); ++ if ( nr < OVERfirst || nr > OVERlast ) { ++ /* boo */ ++ OVERcache = NULL; ++ return NULL; ++ } ++ if ( nr == artnum ) { ++ pos = OVERcache; ++ goto bingo; /* calculate next OVERcache + return. (EW! a goto! :) */ ++ } ++ else if ( artnum > nr ) { ++ /* treat cache as first binary search */ ++ bottom = OVERcache; ++ bottomnr = nr; ++ } ++ else { ++ /* cache is first top */ ++ top = OVERcache - 1; ++ topnr = nr - 1; ++ if ( artnum > OVERprev ) { ++ /* ++ * optimization: we're searching for something that isn't ++ * in the database, but we want to keep the cache clean. ++ * this occurs when we think an article is there, but it ++ * really isn't, eg. because NOSCANDIR is on, or simply ++ * because the overview database leaks. ++ */ ++ return(NULL); ++ } ++ } ++ } ++ ++ /* sanity check */ ++ if ( artnum < bottomnr || artnum > topnr ) { ++ OVERcache = NULL; ++ return NULL; ++ } ++ ++ for (;;) { ++ /* ++ * This is the binary search loop, there are about a zillion ++ * exits so I found it neater to code it in an endless loop :) ++ * It simply continues until it is either found or it isn't... ++ * ++ * Note that we don't do a real binary search, but we guess ++ * a position using the fact that the overview database usually ++ * contains a reasonably linear range of articles, without any ++ * big leaps, but we skew it a bit towards the middle to prevent ++ * slow convergence in boundary cases (see also below). ++ * ++ * We switch to linear searching when we're "close", ++ * because on short ranges, linear searches are about as fast ++ * (or faster) anyway. LINSEARCH is currently guessed at 5, ++ * because on average it takes 2.5 searches using a linear search, ++ * where it usually takes 3 "straight" binary searches. ++ * ++ * Unfortunately, we can't be sure we get into linear search when ++ * we're close, because the database may have large holes. ++ */ ++ /* test if it's near the bottom */ ++ if ( artnum < bottomnr + LINSEARCH ) { ++ i = 0; ++ while ( artnum > bottomnr && i++ < LINSEARCH ) { ++ /* search next line */ ++ bottom = memchr(bottom, '\n', OVERsize - (bottom - OVERshm)); ++ if ( bottom == NULL || bottom == top + 1 ) { ++ /* reached end of file */ ++ OVERcache = NULL; ++ return NULL; ++ } ++ if ( *++bottom == 0 ) { ++ YOUR_MMAP_SUCKS; ++ continue; ++ } ++ bottomnr = atol(bottom); ++ if ( bottomnr < OVERfirst || bottomnr > OVERlast ) { ++ OVERcache = NULL; ++ return NULL; ++ } ++ } ++ if ( artnum == bottomnr ) { ++ pos = bottom; ++ goto bingo; /* calculate next OVERcache + return. */ ++ } ++ else { ++ /* didn't find it, but we came close. still cache position */ ++ OVERcache = bottom; ++ OVERprev = artnum; ++ return NULL; ++ } ++ /*NOTREACHED*/ ++ } ++ /* test if it's near the top */ ++ if ( artnum > topnr - LINSEARCH ) { ++ /* ++ * topnr is frequently guessed, so we must first determine it ++ * correctly. The fun part about searching backwards is that ++ * the next position (OVERcache) follows easily... ++ */ ++ i = 0; ++ do { ++ OVERcache = (top == OVERshm + OVERsize - 1) ? NULL : top + 1; ++ if ( (top = inn_memrchr(--top, '\n', top - OVERshm)) ++ == NULL || top + 1 == bottom ) ++ { ++ /* search hit bottom */ ++ OVERcache = NULL; ++ return NULL; ++ } ++ if ( *(top + 1) == 0 ) { ++ YOUR_MMAP_SUCKS; ++ /* make sure we continue */ ++ topnr = artnum + 1; ++ continue; ++ } ++ topnr = atol(top + 1); ++ if ( topnr < OVERfirst || topnr > OVERlast ) { ++ OVERcache = NULL; ++ return NULL; ++ } ++ } ++ while ( artnum < topnr && i++ < LINSEARCH ); ++ if ( artnum == topnr ) { ++ /* bingo. This time we know OVERcache already */ ++ OVERprev = artnum; ++ return(top + 1); ++ } ++ else { ++ /* not found, but close. cache position */ ++ OVERprev = artnum; ++ return NULL; ++ } ++ /*NOTREACHED*/ ++ } ++ ++ /* ++ * now for the real binary search: ++ * Estimate the position of artnum, but with a small offset towards ++ * the middle, for better convergence in case the set of articles ++ * is non-linear (you get a straight binary search if MIDSKEW is 1.0). ++ * MIDSKEW is currently determined using a big thumb, occultism, ++ * astrology, cat /dev/uri-geller and some common sense (but not much) ++ * MIDSKEW == 0.0 makes the search take only 1 iteration in case ++ * the overview database is a monotonous array of lines with equal ++ * length, but can make for really lousy searches in anything not like ++ * the above, which, in the real world, is practically always. ++ * MIDSKEW == 1.0 gives you a true binary search without any guessing ++ * whatsoever. ++ * I thought 10% would be good enough. Only riggid testing can ++ * determine the optimal value, and then it still depends on a lot ++ * of settings, like expire times, user newsgroups preference, ++ * presence of cancelbots or cancelwars, frequency of expireover ++ * runs... need I say more? :) ++ */ ++ if ( topnr <= bottomnr ) { ++ /* Safety net. This REALLY should never happen. */ ++ syslog(L_NOTICE, ++ "%s: ASSERTION FAILED: %d < %d looking for %d in %s", ++ ClientHost, topnr, bottomnr, artnum, GRPlast); ++ } ++ pos = bottom + (int) ((double) (top - bottom) * (MIDSKEW * 0.5) + ++ (top - bottom) * (1.0 - MIDSKEW) * ++ (artnum - bottomnr) / (topnr - bottomnr)); ++ /* search forward for newline */ ++ if ( (pos = memchr(pos, '\n', OVERsize - (pos - OVERshm))) == NULL ) { ++ /* this shouldn't happen */ ++ OVERcache = NULL; ++ return NULL; ++ } ++ if ( pos == top ) { ++ /* hmm... */ ++ if ( (pos = inn_memrchr(--pos, '\n', pos - OVERshm)) ++ == NULL || pos == bottom - 1 ) ++ { ++ /* ++ * This is what happens when there's a large hole and we're ++ * looking for something inside the hole (which isn't there). ++ * still record the position in this case... ++ */ ++ OVERcache = (top == OVERshm + OVERsize - 1) ? NULL : top + 1; ++ OVERprev = artnum; ++ return NULL; ++ } ++ } ++ /* see where we are */ ++ if ( *++pos == 0 ) { ++ YOUR_MMAP_SUCKS; ++ pos = memchr(pos, '\n', OVERsize - (pos - OVERshm)); ++ if ( pos == NULL || pos == OVERshm + OVERsize - 1 || pos == top ) { ++ OVERcache = NULL; ++ return NULL; ++ } ++ pos++; ++ } ++ nr = atol(pos); ++ if ( nr < OVERfirst || nr > OVERlast ) { ++ OVERcache = NULL; ++ return NULL; ++ } ++ if ( nr == artnum ) { ++ /* bingo. Set cache to next entry */ ++bingo: ++ OVERcache = memchr(pos, '\n', OVERsize - (pos - OVERshm)); ++ if ( OVERcache == OVERshm + OVERsize - 1 ) ++ OVERcache = NULL; ++ else if ( OVERcache ) ++ OVERcache++; ++ OVERprev = artnum; ++ return (pos); ++ } ++ if ( nr < artnum ) { ++ /* found a new bottom */ ++ bottom = pos; ++ bottomnr = nr; ++ } ++ else /* nr > artnum */ { ++ /* ++ * found a new top. Setting topnr to nr-1 is not entirely ++ * correct, but who cares. (In fact we do care, but adjust ++ * later :) ++ */ ++ top = pos - 1; ++ topnr = nr - 1; ++ } ++ } ++ /*NOTREACHED*/ ++} ++ ++#else /* !OVERSCREAM */ + + /* + ** Open an OVERVIEW file. +@@ -771,7 +1249,7 @@ + if (OVERqp != NULL) { + QIOclose(OVERqp); + OVERqp = NULL; +- OVERopens = 0; ++ OVERopens = 0; /* this is a bug */ + } + } + +@@ -794,7 +1272,7 @@ + } + + for ( ; OVERarticle < artnum; OVERarticle = atol(OVERline)) +- if ((OVERline = QIOread(OVERqp)) == NULL) { ++ while ((OVERline = QIOread(OVERqp)) == NULL) { + if (QIOtoolong(OVERqp)) + continue; + /* Don't close file; we may rewind. */ +@@ -804,6 +1282,8 @@ + return OVERarticle == artnum ? OVERline : NULL; + } + ++#endif ++ + + /* + ** Read an article and create an overview line without the trailing +@@ -1093,12 +1573,22 @@ + if (ARTfind(i) < 0) + continue; + ++ /*OVERVIEWcount++;*/ + if (Opened && (p = OVERfind(i)) != NULL) { ++#ifdef OVERSCREAM ++ char* eol = memchr(p, '\n', OVERsize - (p - OVERshm)); ++ if ( eol == NULL ) ++ continue; /* this should NEVER NEVER EVER NEVER EVER happen */ ++ fwrite(p, 1, eol - p, stdout); ++ fwrite("\r\n", 1, 2, stdout); ++#else + Printf("%s\r\n", p); ++#endif + continue; + } + + (void)sprintf(buff, "%ld", i); ++ /*OVERGENcount++;*/ + if ((p = OVERgen(buff)) != NULL) + Printf("%s\r\n", p); + } --- inn-1.7.2q.orig/debian/patches/path_audit_fix +++ inn-1.7.2q/debian/patches/path_audit_fix @@ -0,0 +1,11 @@ +diff -urN inn-1.7.2.orig/innd/rc.c inn-1.7.2/innd/rc.c +--- inn-1.7.2.orig/innd/rc.c 2003-07-08 17:25:21.000000000 +0200 ++++ inn-1.7.2/innd/rc.c 2003-08-20 02:21:04.000000000 +0200 +@@ -542,6 +542,7 @@ + i++; + *count = i; + rp = *list = NEW(REMOTEHOST, *count); ++ memset(rp, 0, *count * sizeof(REMOTEHOST)); + #if !defined(DO_HAVE_UNIX_DOMAIN) + rp->Address.s_addr = inet_addr(LOOPBACK_HOST); + rp->Name = COPY("localhost"); --- inn-1.7.2q.orig/debian/patches/xmode +++ inn-1.7.2q/debian/patches/xmode @@ -0,0 +1,37 @@ +INN (1.4unoff4-1) - Miquel van Smoorenburg + + * Added "xmode" as alias for "mode" + + +--- inn-1.7.2.orig/innd/nc.c ++++ inn-1.7.2/innd/nc.c +@@ -80,6 +80,7 @@ + { "takethis", NCtakethis }, + { "list", NClist }, + { "mode", NCmode }, ++ { "xmode", NCmode }, + { "quit", NCquit }, + { "head", NChead }, + { "stat", NCstat }, +@@ -735,7 +796,10 @@ + HANDOFF h; + + /* Skip the first word, get the argument. */ +- for (p = cp->In.Data + STRLEN("mode"); ISWHITE(*p); p++) ++ p = cp->In.Data; ++ if (*p == 'x') p++; ++ p += STRLEN("mode"); ++ for (; ISWHITE(*p); p++) + continue; + + if (caseEQ(p, "reader")) +@@ -993,7 +1057,8 @@ + } + + if (cp->State == CSgetauth) { +- if (caseEQn(bp->Data, "mode", 4)) ++ if (caseEQn(bp->Data, "mode", 4) || ++ caseEQn(bp->Data, "xmode", 5)) + NCmode(cp); + else + NCauthinfo(cp); --- inn-1.7.2q.orig/debian/patches/0_insync_pathfeed +++ inn-1.7.2q/debian/patches/0_insync_pathfeed @@ -0,0 +1,44 @@ +--- inn-1.7.2.orig/doc/newsfeeds.5 ++++ inn-1.7.2/doc/newsfeeds.5 +@@ -304,6 +304,7 @@ + N Value of the Newsgroups header + O Overview data + R Information needed for replication ++ P Path header information needed for inpaths + .fi + More than one letter can be used; the entries will be separated by a + space, and written in the order in which they are specified. +--- inn-1.7.2.orig/include/configdata.h ++++ inn-1.7.2/include/configdata.h +@@ -383,6 +389,7 @@ + #define FEED_MAXFLAGS 20 + #define FEED_BYTESIZE 'b' + #define FEED_FULLNAME 'f' ++#define FEED_PATH 'P' + #define FEED_HDR_DISTRIB 'D' + #define FEED_HDR_NEWSGROUP 'N' + #define FEED_MESSAGEID 'm' +--- inn-1.7.2.orig/innd/newsfeeds.c ++++ inn-1.7.2/innd/newsfeeds.c +@@ -339,6 +339,7 @@ + NeedOverview = TRUE; /* Overview data */ + break; + case FEED_BYTESIZE: /* Size in bytes */ ++ case FEED_PATH: /* Pathline header */ + case FEED_FULLNAME: /* Full filename */ + case FEED_HDR_DISTRIB: /* Distribution header */ + case FEED_HDR_NEWSGROUP: /* Newsgroup header */ +--- inn-1.7.2.orig/innd/site.c ++++ inn-1.7.2/innd/site.c +@@ -445,6 +445,11 @@ + BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP)); + BUFFappend(bp, Data->Feedsite, Data->FeedsiteLength); + break; ++ case FEED_PATH: ++ if (Dirty) ++ BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP)); ++ BUFFappend(bp, Data->Path, Data->PathLength); ++ break; + } + Dirty = TRUE; + } --- inn-1.7.2q.orig/debian/patches/newsgroups_whitespace +++ inn-1.7.2q/debian/patches/newsgroups_whitespace @@ -0,0 +1,39 @@ +Patch by Roy Hooper backported from inn 2.x (revision 3236 of 2000-05-13) +to ignore whitespace in Newsgroups headers. + +diff -ruNp inn-1.7.2.orig/innd/art.c inn-1.7.2/innd/art.c +--- inn-1.7.2.orig/innd/art.c 2008-04-20 02:24:41.000000000 +0200 ++++ inn-1.7.2/innd/art.c 2008-04-20 02:24:35.000000000 +0200 +@@ -1023,12 +1023,28 @@ ARTclean(Article, Data) + /* Colon or whitespace in the Newsgroups header? */ + if (strchr(HDR(_newsgroups), ':') != NULL) + return "Colon in \"Newsgroups\" header"; ++ ++ /* Whitespace - clean the header up instead of rejecting it. Too many ++ * servers are passing articles with whitespace along these days. On ++ * May 12th, 2000, I rejected 18468 of 578846 articles because of this ++ * lack of adherence to standards. -rhooper@thetoybox.org 2000/05/12 */ + for (p = HDR(_newsgroups); *p; p++) + if (ISWHITE(*p)) { +- (void)sprintf(buff, +- "Whitespace in \"Newsgroups\" header -- \"%s\"", +- MaxLength(HDR(_newsgroups), p)); +- return buff; ++ /* Fix whitspace */ ++ char *wsp = HDR(_newsgroups); ++ int x, y, s; ++ ++ for (s = x = y = 0; y < ARTheaders[_newsgroups].Length; x++) { ++ while (ISWHITE(wsp[y]) && y < ARTheaders[_newsgroups].Length) { ++ y++; ++ s++; ++ } ++ wsp[x] = wsp[y]; ++ y++; ++ } ++ wsp[x] = '\0'; ++ ARTheaders[_newsgroups].Length -= s; ++ break; + } + + /* If there is no control header, see if the article starts with --- inn-1.7.2q.orig/debian/patches/send-uucp +++ inn-1.7.2q/debian/patches/send-uucp @@ -0,0 +1,19 @@ +--- inn-1.7.2.orig/samples/send-uucp ++++ inn-1.7.2/samples/send-uucp +@@ -89,11 +89,12 @@ + ## Get the compression flags. + echo "${PROGNAME}: [$$] begin ${SITE}" + case "${SITE}" in +- esca) +- COMPRESS="compress -b12" +- ;; ++# esca) ++# COMPRESS="compress -b12" ++# ;; + *) +- COMPRESS="compress" ++ # The default is set in innshelvars ++ # COMPRESS="compress" + ;; + esac + --- inn-1.7.2q.orig/debian/patches/use_system_prototypes +++ inn-1.7.2q/debian/patches/use_system_prototypes @@ -0,0 +1,74 @@ +diff -ruNp inn-1.7.2.orig/include/configdata.h inn-1.7.2/include/configdata.h +--- inn-1.7.2.orig/include/configdata.h 2006-08-19 10:34:34.000000000 +0200 ++++ inn-1.7.2/include/configdata.h 2006-08-19 10:34:30.000000000 +0200 +@@ -39,7 +39,7 @@ typedef char *CSTRING; + #else + #if defined(__GNUC__) + /* GCC */ +-#define NORETURN volatile void ++#define NORETURN __attribute__((noreturn)) void + #else + /* Everyone else */ + #define NORETURN void +diff -ruNp inn-1.7.2.orig/include/clibrary.h inn-1.7.2/include/clibrary.h +--- inn-1.7.2.orig/include/clibrary.h 2004-07-12 18:59:24.000000000 +0200 ++++ inn-1.7.2/include/clibrary.h 2004-07-12 18:59:17.000000000 +0200 +@@ -96,6 +96,7 @@ typedef struct _FDSET { + /* =()<#define FREEVAL @@>()= */ + #define FREEVAL void + ++#ifdef THIS_IS_2004_AND_I_HAVE_BROKEN_HEADERS + extern int optind; + extern char *optarg; + #if !defined(__STDC__) +@@ -149,3 +150,4 @@ extern void _exit(); + #if defined(DO_HAVE_SETPROCTITLE) + extern void setproctitle(); + #endif /* defined(DO_HAVE_SETPROCTITLE) */ ++#endif /* THIS_IS_2004_AND_I_HAVE_BROKEN_HEADERS */ +diff -ruNp inn-1.7.2.orig/innd/innd.h inn-1.7.2/innd/innd.h +--- inn-1.7.2.orig/innd/innd.h 2004-07-12 18:59:24.000000000 +0200 ++++ inn-1.7.2/innd/innd.h 2004-07-12 18:58:32.000000000 +0200 +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + #include + #include "nntp.h" + #include "paths.h" +diff -ruNp inn-1.7.2.orig/nnrpd/nnrpd.h inn-1.7.2/nnrpd/nnrpd.h +--- inn-1.7.2.orig/nnrpd/nnrpd.h 2004-07-12 18:59:24.000000000 +0200 ++++ inn-1.7.2/nnrpd/nnrpd.h 2004-07-12 18:59:17.000000000 +0200 +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + #if defined(DO_NEED_TIME) + #include + #endif /* defined(DO_NEED_TIME) */ +diff -ruNp inn-1.7.2.orig/config/subst.c inn-1.7.2/config/subst.c +--- inn-1.7.2.orig/config/subst.c 2006-08-19 10:42:28.000000000 +0200 ++++ inn-1.7.2/config/subst.c 2006-08-19 10:42:14.000000000 +0200 +@@ -3,6 +3,8 @@ + ** A C version of Henry Spencer's "subst" script. + */ + #include ++#include ++#include + #include + #include + +@@ -33,9 +35,11 @@ static char *argv0; + extern char *optarg; + extern int optind; + ++#ifdef THIS_IS_2004_AND_I_HAVE_BROKEN_HEADERS + extern void exit(); + extern char *malloc(); + extern char *strcpy(); ++#endif + + + --- inn-1.7.2q.orig/debian/patches/use_controlchan +++ inn-1.7.2q/debian/patches/use_controlchan @@ -0,0 +1,16 @@ +--- inn-1.7.2.orig/innd/art.c ++++ inn-1.7.2/innd/art.c +@@ -1280,6 +1316,13 @@ + } + } + ++ { ++ char *UseControlchan; ++ if ((UseControlchan = GetConfigValue(_CONF_USECONTROLCHAN)) != NULL) ++ if (EQ(UseControlchan, "true") || EQ(UseControlchan, "yes")) ++ return; ++ } ++ + /* Build the command vector and execute it. */ + av[0] = buff; + av[1] = COPY(Data->Poster); --- inn-1.7.2q.orig/debian/patches/misc_config_files +++ inn-1.7.2q/debian/patches/misc_config_files @@ -0,0 +1,67 @@ +--- inn-1.7.2.orig/samples/hosts.nntp.nolimit ++++ inn-1.7.2/samples/hosts.nntp.nolimit +@@ -2,5 +2,6 @@ + ## + ## Any hosts listed in this file will be permitted to connect past the + ## limits set up by the `-i' and `-X' flags to innd. ++## Listed hosts must be present in hosts.nntp too! + ## + localhost +--- inn-1.7.2.orig/samples/nnrp.access ++++ inn-1.7.2/samples/nnrp.access +@@ -15,7 +15,8 @@ + ## Default is no access, no way to authentication, and no groups. + *:: -no- : -no- :!* + ## Foo, Incorporated, hosts have no password, can read anything. +-*.foo.com:Read Post:::* ++#*.foo.com:Read Post:::* ++ + stdin:Read Post:::* + localhost:Read Post:::* + 127.0.0.1:Read Post:::* +--- inn-1.7.2.orig/samples/nntpsend.ctl ++++ inn-1.7.2/samples/nntpsend.ctl +@@ -10,6 +10,6 @@ + ## see shrinkfile(1). + ## Other args to pass to innxmit + ## Everything after the pound sign is ignored. +-nsavax:erehwon.nsavax.gov::-S -t60 +-walldrug:walldrug.com:4m-1m:-T1800 -t300 +-kremvax:kremvax.cis:2m: ++#nsavax:erehwon.nsavax.gov::-S -t60 ++#walldrug:walldrug.com:4m-1m:-T1800 -t300 ++#kremvax:kremvax.cis:2m: +--- inn-1.7.2.orig/samples/passwd.nntp ++++ inn-1.7.2/samples/passwd.nntp +@@ -11,4 +11,4 @@ + ##