#! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'rebatch.README' <<'END_OF_FILE' Xrebatch - batch old articles again. X XThis program allows you to batch up "old" news articles again after Xthey have been posted or received. A possible use is to re-send Xbatches that have failed due to transmission errors or whatever. X X"rebatch" uses the same inclusions, exclusions and methods in the sys Xfile as C News, as documented in news(5). (Exception: the m and u Xflags are ignored.) That means, with each article that is to be Xprocessed by "rebatch" the same things are done on the output side as Xwhen the article was actually received or posted. Especially, if a Xprogram is to be called for each article (a non-batched feed), this Xprogram gets called, and the newsgroups/distribution limits and path Xlines are obeyed. XActually, the algorithm used here is pattern matching rather than C XNews' obscure word matching, but the result should be similar in all Xbut exotic cases. It is equal for whole hierarchies. X XUsage: rebatch [flags] [site...] X flags: -n don't do anything, just print what is done X -f don't obey rules in the sys file, send everything X (use with care!) X -a send to all sites in the sys file X -g groups send only articles in "groups" X -d distribs send only articles in "distribs" X site...: Site names as in the first field in the sys file. X X"rebatch" reads from standard input the history lines of the articles Xto rebatch. This means you can use it in a context like X histfrom Dec01 | rebatch downsite X(note that "histfrom" is very slow and it would be advisable to save Xits output to a file first. "rebatch" also is a bit slow due to the Xheavy pattern-matching operations.) XA history line looks like this one: X<35b9mi$mv5@usenet.elf.com> 779843384~796736040 comp.security.unix/1378 alt.sources/12 XIn this context, only the Message-ID (first field) and article number X(subfields of third field) are relevant. X X"rebatch" writes to standard output a line for each processed article, Xcontaining at least the Message-ID (and the Newsgroups and XDistributions parameter unless -f is given). If -n is specified, for Xeach article the action to be taken is printed out. The result looks Xlike (and can be used as, perhaps) a shell script. XThe -g and -d arguments can be used to limit the range of rebatched Xarticles by newsgroups and distributions. The arguments are like in Xthe sys file. An article is sent only if it matches the sys file and Xthe -g and -d arguments. X XTwo special modes are not for rebatching, but have been added for Xconvenience (to help debug your sys file as well as this program): XInvoke under the name "printsys" or with the -s flag: X Print out a nicely formatted listing of the contents of the sys X file (as "uuchk" does with the Taylor UUCP sys file). No standard X input or arguments are taken. XInvoke under the name "whogets" or with the -w flag: X Take from standard input a list of newsgroup/distribution lists, as in X comp.sys.foo,de.comp.foo,local.foo/world X (could be a concatenation of the contents of the Newsgroup and X Distribution headers with a / in between) X For each line of input, print a line of output with the names of X all systems that will receive an article in these groups and X distributions. X X"rebatch" was written in perl 4 and follows the sys file Xspecifications from C News' news(5) man page. It is in the public Xdomain. Some of the code (sys file parsing, newsgroup pattern Xmatching) is probably suitable for building other news maintenance Xtools. Please report to me if you find bugs. X XOlaf Titz X XVersion history: X X1.4 1995/01/25 X Fixed bug in batch file handling. X Added -g and -d limits. X Made -a non-default. X Added help message. X X1.3 1994/12/04 X First published. X X$Id: rebatch.README,v 1.4 1995/01/24 00:00:52 olaf Exp $ END_OF_FILE if test 3827 -ne `wc -c <'rebatch.README'`; then echo shar: \"'rebatch.README'\" unpacked with wrong size! fi # end of 'rebatch.README' fi if test -f 'rebatch' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'rebatch'\" else echo shar: Extracting \"'rebatch'\" \(7347 characters\) sed "s/^X//" >'rebatch' <<'END_OF_FILE' X#!/usr/bin/perl X# -*- perl -*- X# rebatch - batch old articles again. For C News. X# written by Olaf Titz , Dec. 1994, public domain X# $Id: rebatch,v 1.4 1995/01/24 00:01:02 olaf Exp $ X X# This program is called with the system name(s) as arguments X# and history lines (e.g. "histfrom" output) as input. X# It prepares to send the given articles again to the named system(s) X# according to the method (batch, program) given in the sys file. With X# the -a flag it sends to all known systems. X# The rules used by C News that determine whether to send an article X# by Newsgroups, Distribution and Path lines are obeyed unless the X# -f argument is given. X# Note: The m and u flags are ignored. X# The -g groups and -d distribs arguments limit the range of articles X# sent. They specify newsgroups and distributions lists which are X# effectively ANDed with those in the sys file. X# With the -n argument, don't do anything, just print what to do. X# The following options may help analyze sys files: X# With the -s argument or if called as "printsys", X# just print the contents of the sys file in a nicely formatted manner. X# Invoked as "whogets" or with the -w argument, this will take lists of X# newsgroups/distributions and print which feeds get them X# (e.g. input line: comp.mail.misc,comp.security.unix/world) X X# Customize here! X$NEWSLIB = "/usr/local/lib/news"; X$NEWSARTS = "/var/spool/news"; X X# ---------------------------------------------------------------------------- Xrequire "getopts.pl"; X&Getopts("fnswag:d:h"); Xif ($opt_h) { &usage; } X X$|=1; Xchdir "$NEWSLIB" || die "can't chdir $NEWSLIB"; X$me=`cat whoami`; X X# read the sys file into %excl, %groups, %distribs, %flags, %comm X# indexed by sys name X# Also preset defaults like C News does X Xopen(SYS, ") { X s/^\s+//; s/\s+$//; X /^$/ && next; /^\#/ && next; X $line = "" unless $cont; X $line .= $_; X $cont = $line=~s/\\$//; X if (!$cont) { X split(/:/, $line); X ($sys, $excl) = split(/\//, @_[0]); X next if ($sys eq "ME" || $sys eq $me); X $excl{$sys} = $excl ? $excl : ""; X $excl{$sys} =~ s/,/|/g unless $opt_s; X ($groups, $distribs) = split(/\//, @_[1]); X $groups{$sys} = $groups ? $groups : "all"; X $distribs{$sys} = $distribs ? $distribs : "all"; X $flags{$sys} = $_[2] ? $_[2] : ""; X $com = $_[3]; X if ($flags{$sys} =~ /f|F|I|n/) { X $batch = $com ? $com : "$sys/togo"; X $batch =~ /^\// || do { X $batch = "$NEWSARTS/out.going/" . $batch; }; X $batch{$sys} = $batch; X $comm{$sys} = ""; X } else { X $comm{$sys} = $com ? $com : "uux - -z -r $sys!rnews"; X $batch{$sys} = ""; X } X } X} Xclose(SYS); X X# ---------------------------------------------------------------------------- Xif ($opt_s || ($0 =~ /printsys$/)) { &printsys; exit 0; } Xif ($opt_w || ($0 =~ /whogets$/)) { &whogets; exit 0; } X Xchdir "$NEWSARTS" || die "can't chdir $NEWSARTS"; X X# Determine valid arguments Xif ($#ARGV+1) { X foreach $i (@ARGV) { X if ($groups{$i}) { X $ARGV{$i} = 1; X } else { print STDERR "$i not in sys file\n"; } X } X} else { X if ($opt_a) { X foreach $i (keys %groups) { $ARGV{$i} = 1; } X } else { X &usage; X } X} X X# Open batch files Xif (!$opt_n) { X foreach $i (keys %ARGV) { X if ($batch{$i}) { X $BAT{$i} = sprintf("BF%03d", ++$batchfile); X if (open($BAT{$i}, ">>$batch{$i}")) { X select($BAT{$i}); $|=1; X } else { X print STDERR "Can't open batch file $batch{$i}\n"; X undef $ARGV{$i}; # don't process this system X } } } X} X X# ---------------------------------------------------------------------------- X# Now process the history lines read from input X XArticle: while () { X ($mid, $dat, @art) = split; X # Try to open the article file X while (1) { X $art = pop(@art) || next Article; X $art =~ s/\./\//g; X open(ART, "<$art") && last; X } X print STDOUT "# $mid "; X # Read the relevant headers from the article and determine size. X @_ = stat(ART); $siz = $_[7]; X if (!$opt_f) { # we need this only when not forcing all X undef @pat; undef $dis; X while () { X /^$/ && last; X /^Newsgroups:\s+(.*)$/i && do { $ngs = $1; }; X /^Distribution:\s+(.*)$/i && do { $dis = $1; }; X /^Path:\s+(.*)$/i && do { X $pat = $1; X @pat = split(/\!/, $pat); X pop(@pat); # last element of path is user name X }; X } X close(ART); X print STDOUT "$ngs/$dis\n"; X next Article if ($opt_g && !&nmatch($ngs, $opt_g)); X next Article if ($opt_d && $dis && !&nmatch($dis, $opt_d)); X } else { X close(ART); X print STDOUT "\n"; X } X # Now look what to do about the article. X System: foreach $sy (keys %ARGV) { X if (!$opt_f) { # Should we send to this site? X next System if ($flags{$sy} =~ /L([0-9]*)/ && $#pat > $1); X foreach $j (@pat) { X next System if ($j eq $sy); X next System if ($j =~ /^$excl{$sy}$/); X } X next System if (!&nmatch($ngs, $groups{$sy})); X next System if ($dis && !&nmatch($dis, $distribs{$sy})); X } X # Send, batch, or whatever... X undef $bb; X if ($flags{$sy} =~ /F/) { X $bb = "$art"; X } elsif ($flags{$sy} =~ /f/) { X $bb = "$art $siz"; X } elsif ($flags{$sy} =~ /I/) { X $bb = "$mid"; X } elsif ($flags{$sy} =~ /n/) { X $bb = "$art $mid"; X } X if ($bb && $batch{$sy}) { X if ($opt_n) { X print STDOUT "echo $bb >> $batch{$sy}\n"; X } else { X select ($BAT{$sy}); X print "$bb\n"; } X } X if ($comm{$sy}) { X $ccc = "$comm{$sy} < $NEWSARTS/$art"; X $ccc =~ s/%s/$art/; X if ($opt_n) { print STDOUT "$ccc\n"; } else { system "$ccc"; } X } X } X} X Xexit 0; X X# ---------------------------------------------------------------------------- X# Match first argument against second X# First is a newsgroup list, X# second a newsgroup pattern list in the ugly "xx.all" format. Xsub nmatch X{ X local ($st, $pa) = @_; X local ($s, $p, $m) = (0, 0); X foreach $s (split(/,/, $st)) { X foreach $p (split(/,/, $pa)) { X $p =~ s/\./\\./g; X $p =~ s/(^|[^A-Za-z0-9])all([^A-Za-z0-9]|$)/$1.*$2/g; X if ($p =~ s/^!//) { X if ($s =~ /^$p/) { $m = 0; last; } X } else { X if ($s =~ /^$p/) { $m = 1; } X } X } X return 1 if ($m); X } X return $m; X} X X# ---------------------------------------------------------------------------- X# This is a nice by-product - sys file debugging aid. Xsub printsys X{ X local ($i); X foreach $i (keys %groups) { X print "System $i\n"; X print "... has exclusions: $excl{$i}\n" if $excl{$i}; X print "... gets groups: $groups{$i}\n"; X print "... gets distributions: $distribs{$i}\n"; X print "... has flags: $flags{$i}\n"; X print "... runs command: $comm{$i}\n" if $comm{$i}; X print "... is batched to: $batch{$i}\n" if $batch{$i}; X } X} X Xsub whogets X{ X while () { X ($n, $d) = split(/\//, $_); X foreach $i (keys %groups) { X next if ($d && $distribs{$i} && !&nmatch($d, $distribs{$i})); X print "$i " if (&nmatch($n, $groups{$i})); X } X print "\n"; X } X} X Xsub usage X{ X print <<"_End"; XUsage: rebatch [-n] [-f | [-g groups] [-d distribs]] [-a | system...] | -s | -w X -n: just print what to do X -f: send all articles regardless of sys file X -g groups: send only specified groups X -d distribs: send only specified distribs X -a: send to all systems X -s: print contents of sys file X -w: print who gets what X_End X exit 0; X} X X# ---------------------------------------------------------------------------- END_OF_FILE if test 7347 -ne `wc -c <'rebatch'`; then echo shar: \"'rebatch'\" unpacked with wrong size! fi chmod +x 'rebatch' # end of 'rebatch' fi echo shar: End of shell archive. exit 0