X-Git-Url: http://dxcluster.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=perl%2FDXUser.pm;h=f16494f91c9361c41813878ed9705d0aff533bbb;hb=579810d363939640538f88a9caa86e01fe9c7709;hp=9ebc31d934c9bea25a55aaa49b2b7318a1844929;hpb=1728c7c7a64eaf2852c490629f022c7e70bc46e2;p=spider.git diff --git a/perl/DXUser.pm b/perl/DXUser.pm index 9ebc31d9..f16494f9 100644 --- a/perl/DXUser.pm +++ b/perl/DXUser.pm @@ -8,19 +8,28 @@ package DXUser; -require Exporter; -@ISA = qw(Exporter); - +use DXLog; use DB_File; +use Data::Dumper; use Fcntl; -use Carp; +use IO::File; +use DXDebug; use strict; -use vars qw(%u $dbm $filename %valid); + +use vars qw($VERSION $BRANCH); +$VERSION = sprintf( "%d.%03d", q$Revision$ =~ /(\d+)\.(\d+)/ ); +$BRANCH = sprintf( "%d.%03d", q$Revision$ =~ /\d+\.\d+\.(\d+)\.(\d+)/ ) || 0; +$main::build += $VERSION; +$main::branch += $BRANCH; + +use vars qw(%u $dbm $filename %valid $lastoperinterval $lasttime); %u = (); $dbm = undef; $filename = undef; +$lastoperinterval = 30*24*60*60; +$lasttime = 0; # hash of valid elements and a simple prompt %valid = ( @@ -34,7 +43,7 @@ $filename = undef; email => '0,E-mail Address', priv => '9,Privilege Level', lastin => '0,Last Time in,cldatetime', - passwd => '9,Password', + passwd => '9,Password,yesno', addr => '0,Full Address', 'sort' => '0,Type of User', # A - ak1a, U - User, S - spider cluster, B - BBS xpert => '0,Expert Status,yesno', @@ -42,13 +51,29 @@ $filename = undef; node => '0,Last Node', homenode => '0,Home Node', lockout => '9,Locked out?,yesno', # won't let them in at all - dxok => '9,DX Spots?,yesno', # accept his dx spots? - annok => '9,Announces?,yesno', # accept his announces? - reg => '0,Registered?,yesno', # is this user registered? + dxok => '9,Accept DX Spots?,yesno', # accept his dx spots? + annok => '9,Accept Announces?,yesno', # accept his announces? lang => '0,Language', hmsgno => '0,Highest Msgno', group => '0,Access Group,parray', # used to create a group of users/nodes for some purpose or other isolate => '9,Isolate network,yesno', + wantbeep => '0,Rec Beep,yesno', + wantann => '0,Rec Announce,yesno', + wantwwv => '0,Rec WWV,yesno', + wantwcy => '0,Rec WCY,yesno', + wantecho => '0,Rec Echo,yesno', + wanttalk => '0,Rec Talk,yesno', + wantwx => '0,Rec WX,yesno', + wantdx => '0,Rec DX Spots,yesno', + pagelth => '0,Current Pagelth', + pingint => '9,Node Ping interval', + nopings => '9,Ping Obs Count', + wantlogininfo => '9,Login info req,yesno', + wantgrid => '0,DX Grid Info,yesno', + wantann_talk => '0,Talklike Anns,yesno', + lastoper => '9,Last for/oper,cldatetime', + nothere => '0,Not Here Text', + registered => '9,Registered?,yesno', ); no strict; @@ -61,13 +86,17 @@ sub AUTOLOAD $name =~ s/.*:://o; confess "Non-existant field '$AUTOLOAD'" if !$valid{$name}; + # this clever line of code creates a subroutine which takes over from autoload + # from OO Perl - Conway + *{$AUTOLOAD} = sub {@_ > 1 ? $_[0]->{$name} = $_[1] : $_[0]->{$name}} ; if (@_) { $self->{$name} = shift; - # $self->put(); } return $self->{$name}; } +use strict; + # # initialise the system # @@ -76,7 +105,7 @@ sub init my ($pkg, $fn, $mode) = @_; confess "need a filename in User" if !$fn; - $fn .= ".new"; + $fn .= ".v2"; if ($mode) { $dbm = tie (%u, 'DB_File', $fn, O_CREAT|O_RDWR, 0666, $DB_BTREE) or confess "can't open user file: $fn ($!)"; } else { @@ -86,7 +115,25 @@ sub init $filename = $fn; } -use strict; +sub del_file +{ + my ($pkg, $fn) = @_; + + confess "need a filename in User" if !$fn; + $fn .= ".v2"; + unlink $fn; +} + +# +# periodic processing +# +sub process +{ + if ($main::systime > $lasttime + 15) { + $dbm->sync; + $lasttime = $main::systime; + } +} # # close the system @@ -94,6 +141,7 @@ use strict; sub finish { + undef $dbm; untie %u; } @@ -107,15 +155,12 @@ sub new my $call = uc shift; # $call =~ s/-\d+$//o; - confess "can't create existing call $call in User\n!" if $u{$call}; +# confess "can't create existing call $call in User\n!" if $u{$call}; my $self = bless {}, $pkg; $self->{call} = $call; $self->{'sort'} = 'U'; - $self->{dxok} = 1; - $self->{annok} = 1; - $self->{lang} = $main::lang; - $u{call} = $self->encode(); + $self->put; return $self; } @@ -128,18 +173,11 @@ sub get { my $pkg = shift; my $call = uc shift; - # $call =~ s/-\d+$//o; # strip ssid - my $s = $u{$call}; - return $s ? decode($s) : undef; -} - -# -# get all callsigns in the database -# - -sub get_all_calls -{ - return (sort keys %u); + my $data; + unless ($dbm->get($call, $data)) { + return decode($data); + } + return undef; } # @@ -154,12 +192,23 @@ sub get_current { my $pkg = shift; my $call = uc shift; - # $call =~ s/-\d+$//o; # strip ssid my $dxchan = DXChannel->get($call); return $dxchan->user if $dxchan; - my $s = $u{$call}; - return $s ? decode($s) : undef; + my $data; + unless ($dbm->get($call, $data)) { + return decode($data); + } + return undef; +} + +# +# get all callsigns in the database +# + +sub get_all_calls +{ + return (sort keys %u); } # @@ -169,8 +218,16 @@ sub get_current sub put { my $self = shift; + confess "Trying to put nothing!" unless $self && ref $self; my $call = $self->{call}; - $u{$call} = $self->encode(); + # delete all instances of this +# for ($dbm->get_dup($call)) { +# $dbm->del_dup($call, $_); +# } + $dbm->del($call); + delete $self->{annok} if $self->{annok}; + delete $self->{dxok} if $self->{dxok}; + $dbm->put($call, $self->encode); } # @@ -179,27 +236,11 @@ sub put sub encode { my $self = shift; - my $out; - my $f; - - $out = "bless( { "; - for $f (sort keys %$self) { - my $val = $$self{$f}; - if (ref $val) { # it's an array (we think) - $out .= "'$f'=>[ "; - foreach (@$val) { - my $s = $_; - $out .= "'$s',"; - } - $out .= " ],"; - } else { - $val =~ s/'/\\'/og; - $val =~ s/\@/\\@/og; - $out .= "'$f'=>q{$val},"; - } - } - $out .= " }, 'DXUser')"; - return $out; + my $dd = new Data::Dumper([$self]); + $dd->Indent(0); + $dd->Terse(1); + $dd->Quotekeys($] < 5.005 ? 1 : 0); + return $dd->Dumpxs; } # @@ -209,9 +250,12 @@ sub decode { my $s = shift; my $ref; - $s = '$ref = ' . $s; - eval $s; - confess $@ if $@; + eval '$ref = ' . $s; + if ($@) { + dbg($@); + Log('err', $@); + $ref = undef; + } return $ref; } @@ -223,7 +267,11 @@ sub del { my $self = shift; my $call = $self->{call}; - delete $u{$call}; + # delete all instances of this +# for ($dbm->get_dup($call)) { +# $dbm->del_dup($call, $_); +# } + $dbm->del($call); } # @@ -237,6 +285,15 @@ sub close $self->put(); } +# +# sync the database +# + +sub sync +{ + $dbm->sync; +} + # # return a list of valid elements # @@ -246,6 +303,89 @@ sub fields return keys(%valid); } + +# +# export the database to an ascii file +# + +sub export +{ + my $fn = shift; + + # save old ones + rename "$fn.oooo", "$fn.ooooo" if -e "$fn.oooo"; + rename "$fn.ooo", "$fn.oooo" if -e "$fn.ooo"; + rename "$fn.oo", "$fn.ooo" if -e "$fn.oo"; + rename "$fn.o", "$fn.oo" if -e "$fn.o"; + rename "$fn", "$fn.o" if -e "$fn"; + + my $count = 0; + my $fh = new IO::File ">$fn" or return "cannot open $fn ($!)"; + if ($fh) { + my $ref = 0; + my $key = 0; + my $action; + my $t = scalar localtime; + print $fh q{#!/usr/bin/perl +# +# The exported userfile for a DXSpider System +# +# Input file: $filename +# Time: $t +# + +package main; + +# search local then perl directories +BEGIN { + umask 002; + + # root of directory tree for this system + $root = "/spider"; + $root = $ENV{'DXSPIDER_ROOT'} if $ENV{'DXSPIDER_ROOT'}; + + unshift @INC, "$root/perl"; # this IS the right way round! + unshift @INC, "$root/local"; + + # try to detect a lockfile (this isn't atomic but + # should do for now + $lockfn = "$root/perl/cluster.lck"; # lock file name + if (-e $lockfn) { + open(CLLOCK, "$lockfn") or die "Can't open Lockfile ($lockfn) $!"; + my $pid = ; + chomp $pid; + die "Lockfile ($lockfn) and process $pid exists - cluster must be stopped first\n" if kill 0, $pid; + close CLLOCK; + } +} + +package DXUser; + +use DXVars; +use DXUser; + +if (@ARGV) { + $main::userfn = shift @ARGV; + print "user filename now $userfn\n"; +} + +DXUser->del_file($main::userfn); +DXUser->init($main::userfn, 1); + +%u = ( + }; + + for ($action = R_FIRST; !$dbm->seq($key, $ref, $action); $action = R_NEXT) { + print $fh "'$key' => q{$ref},\n"; + ++$count; + } + print $fh ");\n#\nprint \"there were $count records\\n\";\n#\n"; + print $fh "DXUser->sync; DXUser->finish;\n#\n"; + $fh->close; + } + return $count; +} + # # group handling # @@ -323,5 +463,127 @@ sub sort my $self = shift; @_ ? $self->{'sort'} = shift : $self->{'sort'} ; } + +# some accessors +sub _want +{ + my $n = shift; + my $self = shift; + my $val = shift; + my $s = "want$n"; + $self->{$s} = $val if defined $val; + return exists $self->{$s} ? $self->{$s} : 1; +} + +sub wantbeep +{ + return _want('beep', @_); +} + +sub wantann +{ + return _want('ann', @_); +} + +sub wantwwv +{ + return _want('wwv', @_); +} + +sub wantwcy +{ + return _want('wcy', @_); +} + +sub wantecho +{ + return _want('echo', @_); +} + +sub wantwx +{ + return _want('wx', @_); +} + +sub wantdx +{ + return _want('dx', @_); +} + +sub wanttalk +{ + return _want('talk', @_); +} + +sub wantgrid +{ + return _want('grid', @_); +} + +sub wantann_talk +{ + return _want('ann_talk', @_); +} + +sub wantlogininfo +{ + my $self = shift; + my $val = shift; + $self->{wantlogininfo} = $val if defined $val; + return $self->{wantlogininfo}; +} + +sub is_node +{ + my $self = shift; + return $self->{sort} =~ /[ACRSX]/; +} + +sub is_user +{ + my $self = shift; + return $self->{sort} eq 'U'; +} + +sub is_bbs +{ + my $self = shift; + return $self->{sort} eq 'B'; +} + +sub is_spider +{ + my $self = shift; + return $self->{sort} eq 'S'; +} + +sub is_clx +{ + my $self = shift; + return $self->{sort} eq 'C'; +} + +sub is_dxnet +{ + my $self = shift; + return $self->{sort} eq 'X'; +} + +sub is_arcluster +{ + my $self = shift; + return $self->{sort} eq 'R'; +} + +sub is_ak1a +{ + my $self = shift; + return $self->{sort} eq 'A'; +} 1; __END__ + + + + +