#!/usr/pkg/bin/perl
#
# $Id: areasbbssync.pl,v 1.1 2001/01/04 20:03:43 mj Exp $
#
# Syncronize groups in active (INN) and areas.bbs (FIDOGATE)
#

$VERSION = '$Revision: 1.1 $ ';
$PROGRAM = "areasbbssync";


if($#ARGV < 0) {
    die
	"usage:   areasbbssync [-v] [-c GATE.CONF] [-a Z:N/F.P]\n",
	"                      [-A ACTIVE] [-B AREAS.BBS]\n",
	"                      [-P PATTERN] [-N PATTERN]\n",
	"                      [-x] [-l] [-n] [-r] [-w]\n",
	"\n",
	"options: -v              verbose\n",
	"         -c CONF         alternate config file\n",
	"         -a Z:N/F.P      gateway address\n",
	"         -A ACTIVE       alternate active file\n",
	"         -B AREAS.BBS    alternate areas.bbs file\n",
	"         -P PATTERN      must match pattern\n",
	"         -N PATTERN      must not match pattern\n",
	"         -x              write ftnaf commands\n",
	"         -l              list new/deleted areas\n",
	"         -n              new areas only\n",
	"         -r              removed areas only\n",
	"         -w              complete new areas.bbs\n";
}


# Common configuration for perl scripts 
##############################################################################
#
# $Id: config.pl,v 4.4 2001/01/04 20:03:42 mj 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!!!##
	"passwd", "%C/passwd",
	"outrfc_news", "%S/outrfc/news",
	"seq_tick", "%V/seq/tick",
	"pinbound", "/var/spool/bt/pin",
	"seq_msgid", "%V/seq/msgid",
	"seq_pkt", "%V/seq/pkt",
	"seq_pack", "%V/seq/pack",
	"seq_toss", "%V/seq/toss",
	"configdir", "/usr/pkg/etc/fidogate",
	"config_gate", "%C/fidogate.conf",
	"acl", "%C/acl",
	"outpkt_news", "%S/outpkt/news",
	"logdir", "/var/log/fido",
	"lock_history", "history",
	"seq_ff", "%V/seq/ff",
	"ftpinbound", "/var/spool/bt/ftpin",
	"toss_toss", "%S/toss/toss",
	"charsetmap", "%L/charset.bin",
	"aliases", "%C/aliases",
	"config_ffx", "%C/fidogate.conf",
	"lockdir", "/var/spool/fido/lock",
	"newslibdir", "/usr/pkg/inn/lib",
	"history", "%V/history",
	"packing", "%C/packing",
	"ifmaildir", "/usr/pkg/sbin",
	"toss_pack", "%S/toss/pack",
	"toss_bad", "%S/toss/bad",
	"uuinbound", "/var/spool/bt/uuin",
	"seq_news", "%V/seq/news",
	"tick_hold", "%B/tick",
	"seq_split", "%V/seq/split",
	"outrfc_mail", "%S/outrfc/mail",
	"spooldir", "/var/spool/fido",
	"toss_route", "%S/toss/route",
	"seq_mail", "%V/seq/mail",
	"config_main", "%C/fidogate.conf",
	"btbasedir", "/var/spool/bt",
	"outpkt_mail", "%S/outpkt/mail",
	"bindir", "/usr/pkg/lib/fidogate/bin",
	"libdir", "/usr/pkg/lib/fidogate",
	"logfile", "%G/log",
	"areas", "%C/areas",
	"inbound", "/var/spool/bt/in",
	"outpkt", "%S/outpkt",
	"vardir", "/var/spool/fido",
	"routing", "%C/routing",
	"newsvardir", "/var/news",
	"newsetcdir", "/var/news/etc",
	"hosts", "%C/hosts",
	"newsspooldir", "/var/news/spool/articles",
     );
my %CONFIG_abbrev =
    (
##Automatically generated by subst.pl, DO NOT EDIT!!!##
	"N", "bindir",
	"G", "logdir",
	"V", "vardir",
	"B", "btbasedir",
	"C", "configdir",
	"I", "inbound",
	"K", "lockdir",
	"S", "spooldir",
	"P", "pinbound",
	"U", "uuinbound",
	"L", "libdir",
     );



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";
    }
}

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

require "getopts.pl";
&Getopts('vc:a:A:B:P:N:xlnrw');

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


$ADDRESS = $opt_a ? $opt_a : "";
$ACTIVE	 = $opt_A ? $opt_A : &CONFIG_get("NewsVarDir")."/active";
$AREAS 	 = $opt_B ? $opt_B : &CONFIG_get("AreasBBS");
$PATTERN = $opt_P ? $opt_P : 
    "^(comp|de|humanities|misc|news|rec|sci|soc|talk|ger)\\.";
$NPATTERN = $opt_N ? $opt_N : 
    "\\.(binaries|binaer|dateien)\\.";

if($opt_w || $opt_x || $opt_l) {
    $ADDRESS || die "$PROGRAM: gateway address not specified (option -a)\n";
}
$ACTIVE || die "$PROGRAM: active file not specified\n";
$AREAS  || die "$PROGRAM: areas.bbs file not specified\n";


##### Main ###################################################################

print "$PROGRAM: reading active file $ACTIVE\n" if($opt_v);
open(A, "$ACTIVE") || die "$PROGRAM: can't open $ACTIVE\n";
while(<A>) {
    ($a) = split(' ', $_);
    $a =~ tr/[a-z\-]/[A-Z_]/;
    if( ($a =~ /$PATTERN/i)  && ! ($a =~ /$NPATTERN/i) ) {
	$areas_active{$a} = 1;
    }
}
close(A);

print "$PROGRAM: reading areas.bbs file $AREAS\n" if($opt_v);
open(A, "$AREAS") || die "$PROGRAM: can't open $AREAS\n";
$_ = <A>;
while(<A>) {
    ($dir,$a) = split(' ', $_, 3);
    if( ($a =~ /$PATTERN/i) ) {
	$areas_bbs{$a} = 1;
    }
}
close(A);


# find new groups (only in active, not in areas.bbs)
if(!$opt_r) {
    print "\nNEW areas:\n" if($opt_l);
    for $area (sort keys %areas_active) {
	if($areas_bbs{$area}) {
#	print "checking active: area $area OK\n" if($opt_v);
	}
	else {
	    print "checking active: area $area MISSING\n" if($opt_v);
	    ##FIXME: use NEW command for FIDOGATE 4.3##
	    print "ftnaf $ADDRESS create $area\n" if($opt_x);
	    print "  + $area\n" if($opt_l);
	    $areas_new{$area} = 1 if($opt_w);
	}
    }
}


# find removed groups (not in active, only in areas.bbs)
if(!$opt_n) {
    print "\nDELETED areas:\n" if($opt_l);
    for $area (sort keys %areas_bbs) {
	if($areas_active{$area}) {
#	print "checking areas.bbs: area $area OK\n" if($opt_v);
	}
	else {
	    print "checking areas.bbs: area $area REMOVED\n" if($opt_v);
	    # Works only with FIDOGATE 4.3 ftnaf
	    print "ftnaf $ADDRESS delete $area\n" if($opt_x);
	    print "  - $area\n" if($opt_l);
	    $areas_delete{$area} = 1 if($opt_w);
	}
    }
}


# output complete new areas.bbs
if($opt_w) {
    # read old one, remove deleted areas
    open(A, "$AREAS") || die "$PROGRAM: can't open $AREAS\n";
    $_ = <A>;
    print;
    while(<A>) {
	($dir,$a) = split(' ', $_, 3);
	if( ($a =~ /$PATTERN/i) ) {
	    print if(!$areas_delete{$a});
	}
	else {
	    print;
	}
    }
    close(A);

    # write new areas
    for $area (sort keys %areas_new) {
	print "#+ $area $ADDRESS\r\n";
    }
}
