home *** CD-ROM | disk | FTP | other *** search
- # NUEXPIRE.PL by Roy M. Silvernail
- # A Waffle BBS maintainence utility (designed for MS-DOS systems)
- # This program is released into the public domain
- #
- # Please refer to the file NUREAD.ME for installing and using NUEXPIRE
- #
- # Presented without warranty. Bug reports, thank-you notes, bequests,
- # etc. to roy%cybrspc@cs.umn.edu
- #
- # 10/26/91
- #
- # Version 1.1 10/27/91
- # Fixed bug in graded expire that would never expire groups graded with
- # a value that included a 0.
- #
- # Version 1.2 11/24/91
- # Added option to append a logfile with names of all expired articles.
- # This option has no effect in debug mode, although the logfile name
- # will be printed with other option information.
- #
- # Version 1.3 12/10/91
- # Added -x option to protect certain groups from expiry.
- # Use '-x group.name group.name'. List may be followed by other args.
- # NUEXPIRE now skips comment lines and blank lines in the usenet file.
- #
- # Version 1.4 2/2/92
- # Logfile used to leave 0-byte files laying about. Fixed.
- #
- # Version 1.5 2/26/92
- # Added -nuke option to remove all news in the spool except local groups...
- # but you must prove that you _really_ want to!
- #
- # Version 1.6 4/19/92
- # Added support for multiple forum description files.
- #
- # Version 1.7 4/26/92
- # Tewaked some areas. NUEXPIRE now requires Perl 4.0 to run.
- # Added default /expire flags in DEFAULT lines.
- # Added a little documentation of the debug flags. Try 'nuexpire -d99'.
- # The logfile works properly now, instead of logging every article
- # considered.
- #
- # Version 1.8 5/10/92
- # Added "-s" to just display statistics of how long each group is kept.
- # The static file parsing now allows lines of the form 'flag:option' (with
- # no whitespace).
- # The 'local' forum file is not processed.
- # (changes courtesy of Bill Fenner, to whom I tip my hat!)
- #
- # Version 2.0 11/15/92
- # The 'ignore newsgroups' option now works more intuitively. To protect
- # only alt.bbs, use '-x alt.bbs.'. To protect alt.bbs and everything
- # underneath of it, use '-x alt.bbs' with no trailing period.
- # More of Bill Fenner's suggestions incorporated. NUEXPIRE now does a
- # chdir() to each directory to improve stat performance. NUEXPIRE now
- # handles filenames with leading -, since it stats each file instead of
- # relying on a filename. But the leading dash will still play havoc with
- # expiry by join file. The only real solution is to upgrade to 1.65
- # Waffle or trim your newsgroups before they exceed 32,767.
- # Added -autonuke to do a full nuke unconditionally from the command line.
- # This is potentially dangerous, so apply with care.
- #
-
- $version = "V2.0";
- select (STDOUT); $| = 1;
- select((select (STDERR), $| = 1)[$[]);
-
- sub max { local ($v) = (shift @_); grep(($_ > $v) && ($v = $_),@_); $v; }
- sub min { local ($v) = (shift @_); grep(($_ < $v) && ($v = $_),@_); $v; }
-
-
-
- # if you _must_ run perl 3.0.41, use this fixpath
- # sub fixpath {
- # join('/',grep((y/A-Z/a-z/,s/(.*)/substr($1,0,8)/e),split(/[\/\\\.]/,shift(@_))));
- # }
-
-
- sub fixpath {
- join('/',grep(s/(.*)/substr("\L$1",0,8)/e,split(/[\/\\\.]/,shift(@_))));
- }
-
-
- sub usage {
- print STDERR <<END_OF_PRINT;
-
- NUEXPIRE.PL $version by Roy M. Silvernail
- usage: nuexpire <-t n|-u name|-s> [-g n][-d][-l filename][-x group [group...]]
- [-nuke][-autonuke]
- -t: expire older than n days
- -u: expire read articles from user/join
- -s: STATS mode -- print age in days of oldest art,
- don't do any expiration
- -g: expire only articles graded n and below
- -d: debug mode; print commands to STDOUT
- -l: append log of deleted articles to filename
- -x: exclude this group from expiry
- -nuke: removes ALL news!
- -autonuke: removes ALL news and doesn't ask first!
- one of -s, -t or -u must be specified, but only one
-
- END_OF_PRINT
-
- exit 1;
- }
-
-
- # parse some args, eh?
-
- $args = join(' ',@ARGV);
- $nuke = ($args =~ /-nuke/) ? 1 : 0;
- $nuke = ($args =~ /-autonuke/) ? 2 : 0;
- $expire_time = ($args =~ /-t\s*(\S+)/) ? $1 : 1; # default to 1
- $expire_grade = ($args =~ /-g\s*(\S+)/) ? $1 : 1; # default to 1
- $join_file = $1 if $args =~ /-u\s*(\S+)/;
- $debug = ($args =~ /-d/) ? 1 : 0; # explicitly set 0 if no debug
- $debug = $1 if ($args =~ /-d\s*(\d+)/);
- $log_file = ($args =~ /-l\s*(\S+)/) ? $1 : 0;
- $log_file = &fixpath($log_file) if $log_file;
- @exclude = split(' ',$1) if $args =~ /-x\s*(.*)\s-/ || $args =~ /-x\s*(.*)/;
- $stats++ if $args =~ /-s/;
- &usage() if $args =~ /-h/ || $args =~ /-\?/;
- &usage() if scalar(grep(/-t/||/-u/||/-s/,@ARGV)) != 1 && !$nuke;
- &usage() unless $args =~ /-t/ || $args =~ /-u/ || $args =~ /-s/ ||
- $nuke || $debug;
-
-
-
- # first, let's find out some things...
-
- open(INFILE,$ENV{"WAFFLE"}) || die("Can't find static file");
-
- @forums=("usenet");
-
- while (<INFILE>) {
- $waffle_dir = &fixpath($1) if /^waffle\s*:\s*(\S+)$/;
- $user_dir = &fixpath($1) if /^user\s*:\s*(\S+)$/;
- @forums = grep($_ ne "local",split(/[ \t]+/,$1)) if /^forums\s*:\s*(.+)$/;
- }
- close(INFILE);
-
- # Qualify forum file paths:
- grep(s|^|$waffle_dir/system/|,@forums);
-
- if ($debug==5) {
- print "$waffle_dir\n$user_dir\n";
- print join("\n",@forums)."\n";
- }
-
- # now we know where things are....
-
- if ($join_file) {
- print "$user_dir/$join_file/join\n" if $debug;
- open(JOINFILE,"$user_dir/$join_file/join") || die("no join");
- while (<JOINFILE>) {
- /^(\S+)\s+(\S+)$/;
- $high{$1} = $2;
- }
- close(JOINFILE);
- }
-
- # brag time
-
- print STDERR "NUEXPIRE.PL $version by Roy M. Silvernail\n";
- print STDERR "referencing $user_dir/$join_file/join to delete read articles\n"
- if ($join_file);
- print STDERR "default expiry age is $expire_time day(s)\n" unless
- $join_file || $stats;
- print STDERR "compiling newsgroup statistics\n" if $stats;
- print STDERR "expiring articles graded $expire_grade and below\n"
- if $expire_grade > 1;
- printf STDERR "debug mode %d - no files will be deleted\n",$debug if $debug;
- print STDERR "logging deleted articles to $log_file\n" if $log_file;
- printf STDERR "ignoring %s\n",join(', ',@exclude) if @exclude;
- print STDERR "nuke option selected\n" if $nuke;
- print STDERR "statistics mode\n" if $stats;
-
- # massage the exclusions... (after we've shown them to the user)
- # they get used as regexps later on.
-
- if (defined(@exclude)) {
- for $t (@exclude) {
- next if ($t =~ s/\.$/\$/);
- $t =~ s/$/.*/;
- }
- }
-
- if ($log_file) {
- eval "open(LOGFILE, \">>$log_file\") || die" unless $debug;
- undef $log_file if $@ || $debug;
- }
-
- &confirm() if $nuke == 1;
-
- exit 0 if $debug == 5;
-
- if($debug == 99) {
- while(<DATA>) {
- print;
- }
- exit 0;
- }
-
- select(STDOUT);
-
- for $forum (@forums) {
- undef $def_exp;
- open(USENET,"$forum") || die("can't find $forum file");
- if ($debug == 4) {
- while (<USENET>) {
- next if /^#/ || /^$/ || /^DEF/;
- print if /grade/;
- }
- next;
- }
- while (<USENET>) {
- next if /^#/ || /^$/;
- if (/^DEFAULT/) {
- if (/\/dir=(\S+)/) {
- $news_root = &fixpath($1);
- $news_root =~ s/\"//g;
- }
- $def_exp = $1 if (/\/expire=(\S+)/);
- } else {
- next if /^#/ || /^$/;
- print if $debug;
- next if /\/junk/;
- /\s*(\S+)/;
- $thisgroup = $1;
- print "skipping $thisgroup\n", next if
- ($debug && grep($thisgroup =~ /$_/,@exclude));
- next if (!$nuke && grep($thisgroup =~ /$_/,@exclude));
- $thisdir = &fixpath($news_root ."/".$thisgroup);
- $thisdir = &fixpath($1) if (/\/dir=(\S+)/);
- print "$thisdir\n" if $debug == 2;
- next if $@;
- next if /\/junk/;
- $exp = /\/expire=(\S+)/ ? $1 : ($def_exp ? $def_exp : $expire_time);
- next if ($exp =~ /no|never|^0/i && !$nuke);
- next if ($exp =~ /grade\s*(\S+)/i && $1 > $expire_grade && !$nuke);
-
- # This is faster if we chdir. (thanks, Bill!)
-
- print "chdir($thisdir);\n" if $debug;
- eval "chdir(\$thisdir) || die(\"can't chdir $thisdir\")";
- eval "opendir(DIR,\".\") || die(\"can't open dir $thisdir\")";
- (print STDERR $@, next) if $@;
- @dtemp = grep(-f "$thisdir/$_", readdir(DIR));
- closedir(DIR);
- $dhigh = &max(@dtemp);
-
- $dlow = &min(@dtemp);
-
- if ($stats) {
- $count=scalar(@dtemp);
- $days= -M "$dlow";
- $size=0; grep($size+= -s "$_",@dtemp);
- $size=int($size/1024);
- $kperday=$days ? $size/$days : 0;
- $artperday=$days ? $count/$days : 0;
- printf("%6d %4d %7.2f %4dK %7.2fK/d %7.2fa/d %s\n",
- $dhigh,$count,$days,$size,$kperday,$artperday,$thisgroup);
- next;
- }
-
- foreach $f (@dtemp) {
- $tf = "$thisdir/$f";
- if ($f == $dhigh) {
- if ($nuke) {
- if ($debug) {
- print "T: $tf\n";
- } else {
- open(I,">$f");
- close(I);
- }
- } else {
- next;
- }
- } elsif ($nuke) {
- $debug ? (print "D: $tf\n") : unlink($f);
- print LOGFILE "$tf\n" if $log_file;
- } elsif ($join_file) {
- if ($debug) {
- print "unlink: $tf\n" unless $f > $high{$thisgroup};
- } else {
- if ($f <= $high{$thisgroup}) {
- unlink($f);
- print LOGFILE "$tf\n" if $log_file;
- }
- }
- } else {
- if ($debug) {
- print "unlink: $tf\n" unless (-M $f) < $exp;
- } else {
- if ((-M $f) >= $exp) {
- unlink($f);
- print LOGFILE "$tf\n" if $log_file;
- }
- }
- }
- }
- }
- }
- close(USENET);
- }
- close(LOGFILE) if $log_file;
-
- exit 0;
-
-
- sub confirm {
- local($warning) = "\033".'[0;1;5;31mWARNING!'."\033".'[0;1;37m';
- print STDERR <<END_OF_PRINT;
-
- $warning You have selected the nuke option. This option will remove
- ALL news on your spool, and replace the largest-numbered articles with
- 0-byte files. Nothing is sacred! This command overrides everything
- else on the command line. This will free up the maximum amount of disk
- space.
-
- Are you really sure you want to do this?
-
- If so, type "YES", without the quotation marks. ANYthing else aborts.
-
- END_OF_PRINT
-
- $response = <STDIN>;
- chop($response);
-
- if ($response ne 'YES') {
- print STDERR "Aborting!\n";
- exit 1;
- }
- print STDERR "Accepted... now expiring all news.\n";
- }
- __END__
-
- Debug values:
-
- These are largely undocumented. The -d flag takes a numeric argument.
- The values implemented are shown below --
-
- 2 After forum file descriptor line, print the actual directory name,
- as passed back by &fixpath().
-
- 4 list only newsgroup lines from the USENET file that have an expire
- group level assigned.
-
- 5 exit program after sign-on banner. this will exit after the -nuke
- option warning. also shows the contents of some stuff read from the
- static file.
-
- 99 print this summary.
-
-
-