#!/usr/bin/perl
use
vars
qw/ $opt_c $opt_n $opt_f $opt_e $opt_d $opt_o $opt_h $opt_t $opt_v $opt_x $opt_z /
;
use
FTN::Database
qw(&open_ftn_database &close_ftn_database &create_ftn_index &drop_ftn_index)
;
$Getopt::Std::STANDARD_HELP_VERSION
= 1;
our
$VERSION
=
'0.35'
;
getopts(
'c:n:f:d:t:o:ehvxz:'
);
if
(
$opt_h
) {
HELP_MESSAGE(
*STDOUT
);
exit
0;
}
my
(
$nodelist_directory
,
$nodelist_file
,
$db_handle
,
$sql_statement
,
$domain
,
$type
,
$number
,
$name
,
$location
,
$log_file
,
$command
,
$zone_number
,
$net_number
,
$sysop
,
$phone
,
$bps
,
$flags
,
$table_name
,
$list_file
,
$config_file
);
if
(
$opt_c
) {
$config_file
=
$opt_c
;
undef
$opt_c
;
}
else
{
my
$config_dir
= File::Spec->curdir();
$config_file
= File::Spec->
join
(
$config_dir
,
'ftndb.cfg'
);
}
my
$ftndb_config
= Config::Tiny->new();
$ftndb_config
= Config::Tiny->
read
(
$config_file
)
or
die
"Could not open configuration file: $config_file"
;
$log_file
=
$ftndb_config
->{_}->{LogFile};
my
$log_id
=
'nl2db'
;
logging(
$log_file
,
$log_id
,
'Starting ftndb-nodelist... '
);
if
(
$opt_v
) {
logging(
$log_file
,
$log_id
,
'Verbose flag is set'
);
}
if
(
$opt_x
) {
logging(
$log_file
,
$log_id
,
'Debug flag is set'
);
}
my
%db_option
= ();
$db_option
{
'Type'
} =
$ftndb_config
->{Database}->{Type};
if
(
$opt_v
) { logging(
$log_file
,
$log_id
,
"Database type being used is $db_option{'Type'}"
) };
$db_option
{
'Name'
} =
$ftndb_config
->{Database}->{Name};
if
(
$opt_v
) { logging(
$log_file
,
$log_id
,
"Database name being used is $db_option{'Name'}"
) };
if
(
$db_option
{
'Type'
} eq
'SQLite'
) {
$db_option
{
'User'
} =
q{}
;
}
else
{
$db_option
{
'User'
} =
$ftndb_config
->{Database}->{User};
if
(
$opt_v
) { logging(
$log_file
,
$log_id
,
"Database user being used is $db_option{'User'}"
) };
}
if
(
$db_option
{
'Type'
} eq
'SQLite'
) {
$db_option
{
'Password'
} =
q{}
;
}
else
{
$db_option
{
'Password'
} =
$ftndb_config
->{Database}->{Password};
if
(
$opt_v
) { logging(
$log_file
,
$log_id
,
"Database password being used is $db_option{'Password'}"
) };
}
if
(
$opt_t
) {
if
(
$opt_t
=~ /\./ ) {
logging(
$log_file
,
$log_id
,
'sqlite does not allow periods in table names.'
);
$opt_t
=~
tr
/\./_/;
$table_name
=
$opt_t
;
logging(
$log_file
,
$log_id
,
"Changed table name to $table_name."
);
}
else
{
$table_name
=
$opt_t
;
}
}
else
{
$table_name
=
'Nodelist'
;
}
if
(
$opt_n
) {
$net_number
=
$opt_n
;
logging(
$log_file
,
$log_id
,
"Defined Net: $net_number"
);
undef
$opt_n
;
}
if
(
$opt_z
) {
$zone_number
=
$opt_z
;
logging(
$log_file
,
$log_id
,
"Defined Zone: $zone_number"
);
undef
$opt_z
;
}
if
(
$opt_d
) {
$domain
=
$opt_d
;
}
else
{
$domain
=
'fidonet'
;
}
if
(
$opt_v
) {
logging(
$log_file
,
$log_id
,
"Domain: '$domain'"
);
}
if
(
$opt_x
) {
logging(
$log_file
,
$log_id
,
'Debug mode is set'
);
}
if
(
$opt_o
) {
$list_file
=
$opt_o
;
undef
$opt_o
;
}
$command
=
shift
;
if
(
lc
(
$command
) eq
'create'
) {
$command
=
shift
;
if
(
lc
(
$command
) eq
'table'
) {
create_ftn_nodelist_table();
}
else
{
print
{
*STDERR
}
"Unrecognized parameter for \'create\' command.\n"
;
HELP_MESSAGE(
*STDERR
);
exit
1;
}
}
elsif
(
lc
(
$command
) eq
'load'
) {
load_ftn_nodelist();
}
elsif
(
lc
(
$command
) eq
'list'
) {
list_ftn_nodelist();
}
else
{
print
{
*STDERR
}
"Unrecognized command.\n"
;
HELP_MESSAGE(
*STDERR
);
exit
1;
}
exit
0;
sub
HELP_MESSAGE {
my
$fh
=
shift
;
print
{
$fh
}
"\n\tSynopsis:\n"
;
print
{
$fh
}
"ftndb-nodelist [-c config_file] [options] load\n"
;
print
{
$fh
}
"ftndb-nodelist [-c config_file] [options] list\n"
;
print
{
$fh
}
"ftndb-nodelist -h | --help\t= Display this help message.\n"
;
print
{
$fh
}
"ftndb-nodelist --version\t= Display version message\n"
;
print
{
$fh
}
"\tOptions.\n"
;
print
{
$fh
}
"[-c config_file]\t= Name and path for configuration file.\n"
;
print
{
$fh
}
"[-t tablename]\t\t= Nodelist table name; defaults to 'Nodelist'.\n"
;
print
{
$fh
}
"[-f nodelist_file]\t= Nodelist filename, defaults to 'nodelist'.\n"
;
print
{
$fh
}
"[-d domain]\t\t= Nodelist domain; defaults to 'fidonet'.\n"
;
print
{
$fh
}
"[-n net_number]\t= If only, the only net to be operated on.\n"
;
print
{
$fh
}
"[-z zone_number]\t= If only, the only zone to be operated on.\n"
;
print
{
$fh
}
"[-o outfile]\t\t= Output file and path.\n"
;
print
{
$fh
}
"[-e]\t\t\t= If present, then nodelist_file is an exact filename\n"
;
print
{
$fh
}
"[-v]\t\t\t= Verbose Mode\n"
;
print
{
$fh
}
"[-x]\t\t\t= Debug Mode\n"
;
return
();
}
sub
create_ftn_nodelist_table {
$db_handle
= FTN::Database::open_ftn_database(\
%db_option
);
FTN::Database::drop_ftn_index(
$db_handle
,
'ftnnode'
);
logging(
$log_file
,
$log_id
,
"Dropping existing nodelist table $table_name if it already exists."
);
FTN::Database::drop_ftn_table(
$db_handle
,
$table_name
);
FTNDB::Nodelist::create_nodelist_table(
$db_handle
,
$table_name
,
$db_option
{
'Type'
});
my
$index_name
=
'ftnnode'
;
my
$index_fields
=
'zone,net,node,point,domain'
;
FTN::Database::create_ftn_index(
$db_handle
,
$table_name
,
$index_name
,
$index_fields
);
FTN::Database::close_ftn_database(
$db_handle
);
logging(
$log_file
,
$log_id
,
"Table $table_name created."
);
return
();
}
sub
load_ftn_nodelist {
my
$zone
= 1;
my
$net
= 0;
my
$node
= 0;
my
$point
= 0;
my
$region
= 0;
$nodelist_directory
=
$ftndb_config
->{Nodelist}->{Directory};
if
(
$opt_f
) {
if
(
$opt_e
) {
logging(
$log_file
,
$log_id
,
"Using exact file name $opt_f."
);
$nodelist_file
=
$opt_f
;
}
else
{
$nodelist_file
= get_nodelist_filename(
$opt_f
);
}
}
else
{
$nodelist_file
= get_nodelist_filename(
'nodelist'
);
}
logging(
$log_file
,
$log_id
,
"Nodelist directory: '$nodelist_directory'"
);
logging(
$log_file
,
$log_id
,
"Nodelist file: '$nodelist_file'"
);
open
NODELIST,
"$nodelist_directory/$nodelist_file"
or
die
logging(
$log_file
,
$log_id
,
"Cannot open $nodelist_directory/$nodelist_file"
);
$db_handle
= FTN::Database::open_ftn_database(\
%db_option
);
if
(
$opt_v
) {
logging(
$log_file
,
$log_id
,
"Deleteing old entries for '$domain'"
);
}
FTNDB::Nodelist::remove_ftn_domain(
$db_handle
,
$table_name
,
$domain
);
logging(
$log_file
,
$log_id
,
'Dropping existing nodelist table index ftnnode if it already exists.'
);
FTN::Database::drop_ftn_index(
$db_handle
,
'ftnnode'
);
if
(
$opt_v
) {
logging(
$log_file
,
$log_id
,
"Loading database from nodelist $nodelist_file"
);
}
$sql_statement
=
"INSERT INTO $table_name "
;
$sql_statement
.=
'(type,zone,net,node,point,region,name,'
;
$sql_statement
.=
'location,sysop,phone,baud,flags,domain,source) '
;
$sql_statement
.=
'VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
;
my
$insert_handle
=
$db_handle
->prepare(
$sql_statement
);
while
(<NODELIST>) {
if
( /^;/ || /^\cZ/ ) {
next
;
}
(
$type
,
$number
,
$name
,
$location
,
$sysop
,
$phone
,
$bps
,
$flags
) =
split
/,/,
$_
, EIGHT ;
if
( !
defined
$flags
) {
$flags
=
q{ }
;
}
else
{
$flags
=~ s/\r?\n$//;
}
if
(
$type
eq
'Zone'
) {
$zone
=
$number
;
$net
=
$number
;
$node
= 0;
}
elsif
(
$type
eq
'Region'
) {
$region
=
$number
;
$net
=
$number
;
$node
= 0;
}
elsif
(
$type
eq
'Host'
) {
$net
=
$number
;
$node
= 0;
}
else
{
$node
=
$number
;
}
if
(
$opt_x
) {
print
"$type,"
;
printf
"%-16s"
,
"$zone:$net/$node"
;
print
"$sysop\n"
;
}
if
(
defined
$zone_number
) {
if
(
$zone
!=
$zone_number
) {
next
;
}
}
$insert_handle
->execute(
$type
,
$zone
,
$net
,
$node
,
$point
,
$region
,
$name
,
$location
,
$sysop
,
$phone
,
$bps
,
$flags
,
$domain
,
$nodelist_file
)
or
die
logging(
$log_file
,
$log_id
,
$DBI::errstr
);
}
$insert_handle
->finish;
undef
$insert_handle
;
if
(
$opt_v
) { logging(
$log_file
,
$log_id
,
'Create ftnnode index'
); }
my
$index_name
=
'ftnnode'
;
my
$index_fields
=
'zone,net,node,point,domain'
;
FTN::Database::create_ftn_index(
$db_handle
,
$table_name
,
$index_name
,
$index_fields
);
if
(
$opt_v
) { logging(
$log_file
,
$log_id
,
'Closing database'
); }
FTN::Database::close_ftn_database(
$db_handle
);
close
NODELIST;
logging(
$log_file
,
$log_id
,
'Nodelist table loaded... '
);
return
();
}
sub
list_ftn_nodelist {
if
(!
defined
$list_file
) {
print
"The output file option, -o, was not defined.\n"
;
HELP_MESSAGE();
exit
1;
}
my
$db_handle
= FTN::Database::open_ftn_database(\
%db_option
);
my
$sql_statement
=
"SELECT * FROM $table_name WHERE zone = $zone_number and net = $net_number "
;
$sql_statement
.=
'ORDER by node ASC'
;
my
$query_handle
=
$db_handle
->prepare(
$sql_statement
);
$query_handle
->execute();
$query_handle
->bind_columns(\
my
(
$id
,
$type
,
$zone
,
$net
,
$node
,
$point
,
$region
,
$name
,
$location
,
$sysop
,
$phone
,
$baud
,
$flags
,
$domain
,
$ftnyear
,
$yearday
,
$source
,
$updated
));
open
(ListFile,
">$list_file"
) or
die
"Cannot open $list_file\n"
;
while
(
$query_handle
->fetch()) {
write
ListFile;
}
close
ListFile;
$query_handle
->finish;
undef
$query_handle
;
FTN::Database::close_ftn_database(
$db_handle
);
return
();
format
ListFile_TOP =
Zone @<<<< Net @<<<<
$zone_number
,
$net_number
------------------------------------------------------------------------
.
format
ListFile =
Node: @<<<<
$node
Name: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$name
Sysop: @<<<<<<<<<<<<<<<<
$sysop
Location: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$location
Phone: @<<<<<<<<<<<<<<<< Baud: @<<<<<
$phone
,
$baud
Flags: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$flags
.
}
sub
get_nodelist_filename {
my
(
$basename
) =
@_
;
my
(
$i
,
@files
);
if
(
$opt_v
) { logging(
$log_file
,
$log_id
,
"Searching for $basename files."
) }
opendir
DIR,
$nodelist_directory
;
@files
=
reverse
sort
(
grep
( /
$basename
\.[0-9][0-9][0-9]$/i,
readdir
(DIR) ));
closedir
DIR;
if
(
$#files
== MinusOne ) {
logging(
$log_file
,
$log_id
,
"Nodelist files $basename not found"
);
print
"\nNodelist files $basename not found.\n"
;
HELP_MESSAGE();
exit
0;
}
else
{
if
(
$opt_v
) {
for
(
$i
= 0 ;
$i
<
@files
;
$i
++ ) {
logging(
$log_file
,
$log_id
,
"Nodelist file $i found: $files[$i]"
);
}
}
}
if
(
$#files
> 1 ) {
logging(
$log_file
,
$log_id
,
"More than one '$basename' found, using first."
);
}
return
(
$files
[0] );
}
sub
VERSION_MESSAGE {
my
$fh
=
shift
;
print
{
$fh
}
"ftndb-nodelist version $VERSION\n"
;
return
();
}