#!/usr/bin/perl5
#
# $Id: fb-filelist.in,v 5.2 2004/11/23 00:50:39 anray Exp $
#
# Generate file list
#
# Copyright (C) 1990-2002
#  _____ _____
# |     |___  |   Martin Junius             <mj@fidogate.org>
# | | | |   | |   Radiumstr. 18
# |_|_|_|@home|   D-51069 Koeln, Germany
#

##### Options ################################################################
require "getopts.pl";

if($opt_h) {
    print
	"usage:   fb-filelist [-vh] [-e EPILOG.TXT] [-p PROLOG.TXT]\n",
	"                     [-n NEW] [-f FILEAREA.CTL]\n\n",
	"options: -c CONF          alternate config file\n",
	"         -e EPILOG.TXT    set epilog for filelist\n",
	"         -p PROLOG.TXT    set prolog for filelist\n",
	"         -n NEW           only files of last NEW days\n",
	"         -f FILEAREA.CTL  use Maximus FILEAREA.CTL area list\n",
        "         -v               more verbose\n",
	"         -h               this help\n";
    exit 1;
}

# Common configuration for perl scripts 
##############################################################################
#
# $Id: config.pl,v 5.2 2004/11/23 00:50:35 anray Exp $
#
# Perl functions to read FIDOGATE config file,
# included by <INCLUDE config.pl> when running subst.pl
#

my %CONFIG;

# specials for DosDrive and Zone
my %CONFIG_dosdrive;
my %CONFIG_zone;



my %CONFIG_default =
    (
##Automatically generated by subst.pl, DO NOT EDIT!!!##
	"seq_split", "%V/seq/split",
	"uuinbound", "/var/spool/ftn/uuin",
	"libexecdir", "/usr/lib64/fidogate",
	"toss_toss", "%S/toss/toss",
	"passwd", "%C/passwd",
	"tick_hold", "%B/tick",
	"vardir", "/var/lib/fidogate",
	"lockdir", "/var/run/fidogate",
	"inbound", "/var/spool/ftn/in",
	"toss_route", "%S/toss/route",
	"btbasedir", "/var/spool/ftn",
	"ftpinbound", "/var/spool/ftn/ftpin",
	"outpkt_mail", "%S/outpkt/mail",
	"lock_history", "history",
	"newsbindir", "/usr/bin",
	"newsvardir", "/var/lib/news",
	"spyes", "%C/spyes",
	"aliases", "%C/aliases",
	"toss_bad", "%S/toss/bad",
	"seq_news", "%V/seq/news",
	"hosts", "%C/hosts",
	"seq_tick", "%V/seq/tick",
	"tic_history", "%V/tic_hist",
	"outrfc_news", "%S/outrfc/news",
	"hubroutedb", "%V/route",
	"pinbound", "/var/spool/ftn/pin",
	"outrfc_mail", "%S/outrfc/mail",
	"spooldir", "/var/spool/fidogate",
	"newsetcdir", "/etc/news",
	"libdir", "/usr/local/fido/lib",
	"outpkt", "%S/outpkt",
	"inn_batchdir", "/var/spool/news/outgoing",
	"history", "%V/history",
	"logdir", "/var/log/fidogate",
	"packing", "%C/packing",
	"netmaildir", "/var/spool/ftn/netmail",
	"toss_pack", "%S/toss/pack",
	"seq_ff", "%V/seq/ff",
	"bindir", "/usr/bin",
	"configdir", "/etc/fidogate",
	"dbc_history", "%V/bdc",
	"newslibdir", "/usr",
	"seq_mail", "%V/seq/mail",
	"config_gate", "%C/fidogate.conf",
	"charsetmap", "%L/charset.bin",
	"seq_msgid", "%V/seq/msgid",
	"seq_pack", "%V/seq/pack",
	"lock_tic_hist", "tic_hist",
	"outpkt_news", "%S/outpkt/news",
	"seq_pkt", "%V/seq/pkt",
	"acl", "%C/acl",
	"ftnacl", "%C/ftnacl",
	"logfile", "%G/log",
	"uplinks", "%C/uplinks",
	"lock_dbc", "dbc",
	"seq_toss", "%V/seq/toss",
	"config_main", "%C/fidogate.conf",
	"areas", "%C/areas",
	"newsspooldir", "/var/spool/news/articles",
	"routing", "%C/routing",
     );
my %CONFIG_abbrev =
    (
##Automatically generated by subst.pl, DO NOT EDIT!!!##
	"L", "libexecdir",
	"G", "logdir",
	"V", "vardir",
	"K", "lockdir",
	"P", "pinbound",
	"I", "inbound",
	"C", "configdir",
	"N", "bindir",
	"S", "spooldir",
	"B", "btbasedir",
     );



sub CONFIG_read {
    my($file) = @_;
    my($key, $arg);
    local *C;

    $file = CONFIG_expand($file);

    open(C,"$file") || die "config.pl: can't open config file $file\n";
    while(<C>) {
	chop;
	next if( /^\s*\#/ );	# comments
	next if( /^\s*$/  );	# empty
	s/\s*$//;		# remove trailing white space
	s/^\s*//;		# remove leading white space
	($key,$arg) = split(' ', $_, 2);
	$key =~ tr/A-Z/a-z/;
	if($key eq "include") {
	    CONFIG_read($arg);
	    next;
	}
	if($key eq "dosdrive") {
	    my ($d, $path) = split(' ', $arg);
	    $CONFIG_dosdrive{lc($d)} = $path;
	    next;
	}
	if($key eq "zone") {
	    my ($z, $rest) = split(' ', $arg, 2);
	    $CONFIG_zone{$z} = $rest;
	    next;
	}
	$CONFIG{$key} = $arg if(!$CONFIG{$key});
    }
    close(C);
}


sub CONFIG_get1 {
    my($key) = @_;
    my($ukey);

    $ukey = $key;
    $ukey =~ tr/a-z/A-Z/;
    return $ENV{"FIDOGATE_$ukey"} if($ENV{"FIDOGATE_$ukey"});

    return $CONFIG{$key} if($CONFIG{$key});
    return $CONFIG_default{$key};
}


sub CONFIG_get {
    my($key) = @_;
    my($ret);
    my($exp);

    $key =~ tr/A-Z/a-z/;
    return CONFIG_expand( CONFIG_get1($key) );
}


sub CONFIG_expand {
    my($v) = @_;
    my($exp);

    if($v =~ /^%([A-Z])/) {
	$exp = CONFIG_get1($CONFIG_abbrev{$1});
	$v =~ s/^%./$exp/;
    }

    return $v;
}


sub CONFIG_debug {    
    my($key);

    for $key (keys %CONFIG) {
	print "$key = $CONFIG{$key} -> ", CONFIG_get($key), "\n";
    }
}

##############################################################################

&Getopts('e:p:n:f:hvc:');

$CONFIG      = $opt_c ? $opt_c : "%C/fidogate.conf";
&CONFIG_read($CONFIG);

if($opt_n) {
    # -n days
    $time_new = time() - $opt_n*60*60*24;
}



$PROLOG   = $opt_p ? $opt_p : &CONFIG_get("LIBEXECDIR")."/prolog.txt";
$EPILOG   = $opt_e ? $opt_e : &CONFIG_get("LIBEXECDIR")."/epilog.txt";

$FILEAREA = $opt_f ? $opt_f : &CONFIG_get("FAreasBBS");



##### Configuration ##########################################################

# Missing text
$MISSING  = "--- file description missing ---";

# Path translation: MSDOS drives -> UNIX path names
%dirs = (
    'c:', 'c:',
    'd:', 'd:',
    'e:', 'e:',
    'f:', 'f:',
    'g:', 'g:',
    'h:', '/home',
    'i:', '/var/spool',
    'p:', '/u1',
    'q:', '/u2',
);



$total_global = 0;


# Generate listing for one directory

sub list_dir {
    local($dir) = @_;
    local($first,$file,$desc,@files,%files_dir);
    local($total) = 0;

    # Read contents of directory

    if(! opendir(DIR, $dir)) {
	print "--- area missing ---\r\n\r\n\r\n";
	return 1;
    }

    @files = readdir(DIR);
    closedir(DIR);

    for $file (@files) {
	# ignore directories
	if( -d $file ) {
	    next;
	}
	# ignore .*
	if( $file =~ /^\./ ) {
	    next;
	}
	# ignore files.{bbs,bak,dat,dmp,idx}
	if( $file =~ /^files\.(bbs|bak|dat|dmp|idx|tr)$/ ) {
	    next;
	}
	# ignore index.{dir,pag}
	if( $file =~ /^index\.(dir,pag)$/ ) {
	    next;
	}
	$files_dir{$file} = 1;
    }

    # Read and print contents of files.bbs

    if(open(FILES, "$dir/files.bbs")) {
	while(<FILES>) {
	    s/\cM?\cJ$//;
	    # File entry
	    if( /^[a-zA-Z0-9]/ ) {
		($file, $desc) = split(' ', $_, 2);
		$file  =~ tr+A-Z\\+a-z/+;
		$files_dir{$file} = 2;
		$total += &list_file($dir, $file, $desc);
	    }
	    elsif( /^-:crlf/ ) {
		next;
	    }
	    elsif(!$time_new) {
		print $_,"\r\n";
	    }
	}
	close(FILES);
    }
    else {
	print "--- no files.bbs ---\r\n";
    }

    # Print files missing in files.bbs / add to files.bbs
    open(FILES, ">>$dir/files.bbs")
	|| die "filelist: can't open $dir/files.bbs\n";
    for $file (sort keys(%files_dir)) {
	if($files_dir{$file} == 1) {
	    $total += &list_file($dir, $file, $MISSING);
	    printf FILES "%-12s  %s\r\n", $file, $MISSING;
	}
    }
    close(FILES);

    $total_global += $total;
    print "\r\n    File area total:  ",&ksize($total),"\r\n";

    print "\r\n\r\n";

}



sub list_file {
    local($dir,$file,$desc) = @_;
    local($x,$size,$time);

    ($x,$x,$x,$x,$x,$x,$x, $size ,$x, $time ,$x,$x,$x) = stat("$dir/$file");

    if($time_new && $time<$time_new) {
	return 0;
    }

    printf "%-12s  %s %s  %s\r\n", $file, &asctime($time), &ksize($size),
                                   $desc;

    return $size;
}



sub asctime {
    local($time) = @_;

    if($time eq "") {
	return "        ";
    }
    else {
	local($yr, $mn, $dy, $h, $m, $s, $xx);

	($s,$m,$h,$dy,$mn,$yr,$xx,$xx,$xx) = localtime($time);

	return sprintf("%02d.%02d.%02d", $dy,$mn+1,$yr, $h,$m);
    }
}



sub ksize{
    local($size) = @_;

    local($k);

    if($size eq "") {
	return "   N/A";
    }
    else {
	if($size == 0) {
	    $k = 0;
	}
	elsif($size <= 1024) {
	    $k = 1;
	}
	else {
	    $k = $size / 1024;
	}
	return sprintf("%6dK", $k);
    }
}



sub dump_file {
    local($file) = @_;

    open(F, "$file") || die "filelist: can't open $file\n";
    while(<F>) {
	s/\cM?\cJ$//;
	next if( /^\cZ/ );
	print $_,"\r\n";
    }
    close(F);
}



##### Main #####

if(-f $PROLOG) {
    &dump_file($PROLOG);
}

if($opt_n) {
    print "******** Listing of all files newer than ";
    print $opt_n, " days ******************************\r\n\r\n";
}


# Read Maximus filearea.ctl

open(F, "$FILEAREA") || die "filelist: can't open $FILEAREA\n";

<F> if(!$opt_f);	# Ignore 1st line of fareas.bbs

while(<F>) {
    s/\cM?\cJ$//;

    if($opt_f) {
	# Maximus filearea.ctl
	s/^\s*//;
	s/\s*$//;
	next if( /^%/ );
	next if( /^$/ );

	($keyw,$args) = split(' ', $_, 2);
	$keyw =~ tr/[A-Z]/[a-z]/;

	if   ($keyw eq "area"    ) {
	    $area = $args;
	}
	elsif($keyw eq "fileinfo") {
	    $info = $args;
	}
	elsif($keyw eq "download") {
	    $dir  =  $args;
	    $dir  =~ tr/[A-Z\\]/[a-z\/]/;
	    $drv  =  substr($dir, 0, 2);
	    $dir  =  substr($dir, 2, length($dir)-2);
	    $dir  =  $dirs{$drv}.$dir;
	}
	elsif($keyw eq "end"     ) {
	    $args =~ tr/[A-Z]/[a-z]/;
	    if($args eq "area") {
		$length = 50;
		if(length($info) > $length) {
		    $info = substr($info, 0, $length);
		}
		$length -= length($info);
		printf "### MAX file area \#%-3d ### ", $area;
		    print $info, " ", "#" x $length, "\r\n";
		print "\r\n";
		&list_dir($dir);
	    }
	}
    }
    else {
	# FIDOGATE fareas.bbs
	($dir,$area) = split(' ', $_);
	$dir =~ s/^\#//;

	if(! $dir_visited{$dir}) {
	    $dir_visited{$dir} = 1;
	    $header = "### File area $area ###";
	    $length = 78 - length($header);
	    print "$header", "#" x $length, "\r\n\r\n";
	    &list_dir($dir);
	}
    }

}

close(F);

print "########################################",
      "######################################\r\n";
print "\r\n      Listing total:  ",&ksize($total_global),"\r\n\r\n";
print "########################################",
      "######################################\r\n";

print "\r\n";
print "This list generated by:\r\n";
print '$Id: fb-filelist.in,v 5.2 2004/11/23 00:50:39 anray Exp $', "\r\n";

if(-f $EPILOG) {
    &dump_file($EPILOG);
}
