#
# Copyright (c) 1998 Dirk Koopman G1TLH
#
-# $Id$
+#
#
package DXCommandmode;
# this does not exist as default, you need to create it manually
#
-use vars qw($VERSION $BRANCH);
-$VERSION = sprintf( "%d.%03d", q$Revision$ =~ /(\d+)\.(\d+)/ );
-$BRANCH = sprintf( "%d.%03d", q$Revision$ =~ /\d+\.\d+\.(\d+)\.(\d+)/ || (0,0));
-$main::build += $VERSION;
-$main::branch += $BRANCH;
-
#
# obtain a new connection this is derived from dxchannel
#
# routing, this must go out here to prevent race condx
my $pkg = shift;
my $call = shift;
- my @rout = $main::routeroot->add_user($call, Route::here(1));
+# my @rout = $main::routeroot->add_user($call, Route::here(1));
+ DXProt::_add_thingy($main::routeroot, [$call, 0, 0, 1]);
# ALWAYS output the user
my $ref = Route::User::get($call);
- $main::me->route_pc16($main::mycall, undef, $main::routeroot, $ref) if $ref;
+ if ($ref) {
+ $main::me->route_pc16($main::mycall, undef, $main::routeroot, $ref);
+ $main::me->route_pc92a($main::mycall, undef, $main::routeroot, $ref) unless $DXProt::pc92_slug_changes;
+ }
return $self;
}
}
$motd = "${main::motd}_$self->{lang}" unless $motd && -e $motd;
$motd = $main::motd unless $motd && -e $motd;
+ if ($self->conn->{csort} eq 'ax25') {
+ if ($motd) {
+ $motd = "${motd}_ax25" if -e "${motd}_ax25";
+ } else {
+ $motd = "${main::motd}_ax25" if -e "${main::motd}_ax25";
+ }
+ }
$self->send_file($motd) if -e $motd;
# sort out privilege reduction
my $ref = Route::User::get($call);
if ($ref) {
foreach my $node (@{$ref->parent}) {
- my $s = $node eq $main::mycall ? $call : "$node: $call";
- $self->send($self->msg('loginb', $s));
+ $self->send($self->msg($node eq $main::mycall ? 'loginb' : 'loginbn', $call, $node));
}
}
}
$self->conn->{echo} = $self->conn->{decho};
delete $self->conn->{decho};
$self->state('prompt');
- } elsif ($self->{state} eq 'talk') {
+ } elsif ($self->{state} eq 'talk' || $self->{state} eq 'chat') {
if ($cmdline =~ m{^(?:/EX|/ABORT)}i) {
for (@{$self->{talklist}}) {
- $self->send_talks($_, $self->msg('talkend'));
+ if ($self->{state} eq 'talk') {
+ $self->send_talks($_, $self->msg('talkend'));
+ } else {
+ $self->local_send('C', $self->msg('chatend', $_));
+ }
}
$self->state('prompt');
delete $self->{talklist};
LogDbg('DXCommand', "$self->{call} swore: $l with words:" . join(',', @bad) . ")");
} else {
for (@{$self->{talklist}}) {
- $self->send_talks($_, $l);
+ if ($self->{state} eq 'talk') {
+ $self->send_talks($_, $l);
+ } else {
+ send_chats($self, $_, $l)
+ }
}
}
}
}
- $self->send($self->talk_prompt);
+ $self->send($self->{state} eq 'talk' ? $self->talk_prompt : $self->chat_prompt);
} elsif ($self->{talklist} && @{$self->{talklist}}) {
# send what has been said to whoever is in this person's talk list
my @bad;
LogDbg('DXCommand', "$self->{call} swore: $cmdline with words:" . join(',', @bad) . ")");
} else {
for (@{$self->{talklist}}) {
- $self->send_talks($_, $rawline);
+ if ($self->{state} eq 'talk') {
+ $self->send_talks($_, $rawline);
+ } else {
+ send_chats($self, $_, $rawline);
+ }
}
}
$self->send($self->talk_prompt) if $self->{state} eq 'talk';
+ $self->send($self->chat_prompt) if $self->{state} eq 'chat';
} else {
# for safety
$self->state('prompt');
my ($to, $via) = $ent =~ /(\S+)>(\S+)/;
$to = $ent unless $to;
- my $call = $via ? $via : $to;
+ my $call = $via && $via ne '*' ? $via : $to;
my $clref = Route::get($call);
my $dxchan = $clref->dxchan if $clref;
if ($dxchan) {
- $dxchan->talk($self->{call}, $to, $via, $line);
+ $dxchan->talk($self->{call}, $to, undef, $line);
} else {
$self->send($self->msg('disc2', $via ? $via : $to));
my @l = grep { $_ ne $ent } @{$self->{talklist}};
}
}
-sub talk_prompt
+sub send_chats
{
my $self = shift;
+ my $target = shift;
+ my $text = shift;
+
+ my $msgid = DXProt::nextchatmsgid();
+ $text = "#$msgid $text";
+ $main::me->normal(DXProt::pc93($target, $self->{call}, undef, $text));
+}
+
+sub special_prompt
+{
+ my $self = shift;
+ my $prompt = shift;
my @call;
for (@{$self->{talklist}}) {
my ($to, $via) = /(\S+)>(\S+)/;
$to = $_ unless $to;
push @call, $to;
}
- return $self->msg('talkprompt', join(',', @call));
+ return $self->msg($prompt, join(',', @call));
+}
+
+sub talk_prompt
+{
+ my $self = shift;
+ return $self->special_prompt('talkprompt');
+}
+
+sub chat_prompt
+{
+ my $self = shift;
+ return $self->special_prompt('chatprompt');
}
#
}
}
}
+
+sub _error_out
+{
+ my $self = shift;
+ my $e = shift;
+ if (++$self->{errors} > $maxerrors) {
+ $self->send($self->msg('e26'));
+ $self->disconnect;
+ return ();
+ } else {
+ return ($self->msg($e));
+ }
+}
+
#
# this is the thing that runs the command, it is done like this for the
# benefit of remote command execution
my $cmdline = shift;
my @ans;
-
return () if length $cmdline == 0;
-
# split the command line up into parts, the first part is the command
my ($cmd, $args) = split /\s+/, $cmdline, 2;
$args = "" unless defined $args;
if ($cmd) {
+
+ # check cmd
+ if ($cmd =~ m|^/| || $cmd =~ m|[^-?\w/]|) {
+ LogDbg('DXCommand', "cmd: invalid characters in '$cmd'");
+ return $self->_error_out('e1');
+ }
+
# strip out // on command only
$cmd =~ s|//|/|g;
- $cmd =~ s|^/||g; # no leading / either
- $cmd =~ s|[^-?\w/]||g; # and no funny characters either
my ($path, $fcmd);
if ($acmd) {
($cmd, $args) = split /\s+/, "$acmd $args", 2;
$args = "" unless defined $args;
- dbg("aliased cmd: $cmd $args") if isdbg('command');
+ dbg("cmd: aliased $cmd $args") if isdbg('command');
}
# first expand out the entry to a command
($path, $fcmd) = search($main::cmd, $cmd, "pl") unless $path && $fcmd;
if ($path && $cmd) {
- dbg("path: $cmd cmd: $fcmd") if isdbg('command');
+ dbg("cmd: path $cmd cmd: $fcmd") if isdbg('command');
my $package = find_cmd_name($path, $fcmd);
return ($@) if $@;
- if ($package) {
+ if ($package && DXCommandmode->can($package)) {
no strict 'refs';
- dbg("package: $package") if isdbg('command');
+ dbg("cmd: package $package") if isdbg('command');
eval { @ans = &$package($self, $args) };
return (DXDebug::shortmess($@)) if $@;
+ } else {
+ dbg("cmd: $package not present") if isdbg('command');
+ return $self->_error_out('e1');
}
} else {
dbg("cmd: $cmd not found") if isdbg('command');
- if (++$self->{errors} > $maxerrors) {
- $self->send($self->msg('e26'));
- $self->disconnect;
- return ();
- } else {
- return ($self->msg('e1'));
- }
+ return $self->_error_out('e1');
}
}
my $uref = Route::User::get($call);
my @rout;
if ($uref) {
- @rout = $main::routeroot->del_user($uref);
+# @rout = $main::routeroot->del_user($uref);
+ @rout = DXProt::_del_thingy($main::routeroot, [$call, 0]);
+
dbg("B/C PC17 on $main::mycall for: $call") if isdbg('route');
# issue a pc17 to everybody interested
$main::me->route_pc17($main::mycall, undef, $main::routeroot, $uref);
+ $main::me->route_pc92d($main::mycall, undef, $main::routeroot, $uref) unless $DXProt::pc92_slug_changes;
} else {
confess "trying to disconnect a non existant user $call";
}
sub prompt
{
my $self = shift;
+
+ return if $self->{gtk}; # 'cos prompts are not a concept that applies here
+
my $call = $self->call;
my $date = cldate($main::systime);
my $time = ztime($main::systime);
no strict 'refs';
if (exists $Cache{$package}) {
- dbg("Redefining $package") if isdbg('command');
+ dbg("find_cmd_name: Redefining $package") if isdbg('command');
undef *$package;
} else {
- dbg("Defining $package") if isdbg('command');
+ dbg("find_cmd_name: Defining $package") if isdbg('command');
}
+
eval $eval;
-
- $Cache{$package} = {mtime => $mtime };
+
+ $Cache{$package} = {mtime => $mtime } unless $@;
}
return $package;
}
+sub send
+{
+ my $self = shift;
+ if ($self->{gtk}) {
+ for (@_) {
+ $self->SUPER::send(dd(['cmd',$_]));
+ }
+ } else {
+ $self->SUPER::send(@_);
+ }
+}
+
sub local_send
{
my ($self, $let, $buf) = @_;
- if ($self->{state} eq 'prompt' || $self->{state} eq 'talk') {
+ if ($self->{state} eq 'prompt' || $self->{state} eq 'talk' || $self->{state} eq 'chat') {
if ($self->{enhanced}) {
$self->send_later($let, $buf);
} else {
# send a talk message here
sub talk
{
- my ($self, $from, $to, $via, $line) = @_;
+ my ($self, $from, $to, $via, $line, $onode) = @_;
$line =~ s/\\5E/\^/g;
- $self->local_send('T', "$to de $from: $line") if $self->{talk};
- Log('talk', $to, $from, $via?$via:$main::mycall, $line);
+ if ($self->{talk}) {
+ if ($self->{gtk}) {
+ $self->local_send('T', dd(['talk',$to,$from,$via,$line]));
+ } else {
+ $self->local_send('T', "$to de $from: $line");
+ }
+ }
+ Log('talk', $to, $from, '<' . ($onode || '*'), $line);
# send a 'not here' message if required
unless ($self->{here} && $from ne $to) {
my $key = "$to$from";
return if $_[0] ne $main::myalias && $_[0] ne $main::mycall;
}
return if $target eq 'SYSOP' && $self->{priv} < 5;
- my $buf = "$to$target de $_[0]: $text";
- $buf =~ s/\%5E/^/g;
- $buf .= "\a\a" if $self->{beep};
+ my $buf;
+ if ($self->{gtk}) {
+ $buf = dd(['ann', $to, $target, $text, @_])
+ } else {
+ $buf = "$to$target de $_[0]: $text";
+ $buf =~ s/\%5E/^/g;
+ $buf .= "\a\a" if $self->{beep};
+ }
$self->local_send($target eq 'WX' ? 'W' : 'N', $buf);
}
return unless grep uc $_ eq $target, @{$self->{user}->{group}};
$text =~ s/^\#\d+ //;
- my $buf = "$target de $_[0]: $text";
- $buf =~ s/\%5E/^/g;
- $buf .= "\a\a" if $self->{beep};
+ my $buf;
+ if ($self->{gtk}) {
+ $buf = dd(['chat', $to, $target, $text, @_])
+ } else {
+ $buf = "$target de $_[0]: $text";
+ $buf =~ s/\%5E/^/g;
+ $buf .= "\a\a" if $self->{beep};
+ }
$self->local_send('C', $buf);
}
my $t = ztime($_[2]);
my $loc = '';
my $clth = $self->{consort} eq 'local' ? 29 : 30;
- my $comment = substr $_[3], 0, $clth;
+ my $comment = substr (($_[3] || ''), 0, $clth);
$comment .= ' ' x ($clth - length($comment));
- if ($self->{user}->wantgrid) {
+ if ($self->{user}->wantgrid) {
my $ref = DXUser->get_current($_[4]);
if ($ref) {
$loc = $ref->qra || '';
my $buf;
if ($self->{ve7cc}) {
$buf = VE7CC::dx_spot($self, @_);
+ } elsif ($self->{gtk}) {
+ my ($dxloc, $byloc);
+
+ my $ref = DXUser->get_current($_[4]);
+ if ($ref) {
+ $byloc = $ref->qra;
+ $byloc = substr($byloc, 0, 4) if $byloc;
+ }
+
+ my $spot = $_[1];
+ $spot =~ s|/\w{1,4}$||;
+ $ref = DXUser->get_current($spot);
+ if ($ref) {
+ $dxloc = $ref->qra;
+ $dxloc = substr($dxloc, 0, 4) if $dxloc;
+ }
+ $buf = dd(['dx', @_, ($dxloc||''), ($byloc||'')]);
+
} else {
$buf = $self->format_dx_spot(@_);
$buf .= "\a\a" if $self->{beep};
return unless $filter;
}
- my $buf = "WWV de $_[6] <$_[1]>: SFI=$_[2], A=$_[3], K=$_[4], $_[5]";
- $buf .= "\a\a" if $self->{beep};
+ my $buf;
+ if ($self->{gtk}) {
+ $buf = dd(['wwv', @_])
+ } else {
+ $buf = "WWV de $_[6] <$_[1]>: SFI=$_[2], A=$_[3], K=$_[4], $_[5]";
+ $buf .= "\a\a" if $self->{beep};
+ }
+
$self->local_send('V', $buf);
}
return unless $filter;
}
- my $buf = "WCY de $_[10] <$_[1]> : K=$_[4] expK=$_[5] A=$_[3] R=$_[6] SFI=$_[2] SA=$_[7] GMF=$_[8] Au=$_[9]";
- $buf .= "\a\a" if $self->{beep};
+ my $buf;
+ if ($self->{gtk}) {
+ $buf = dd(['wcy', @_])
+ } else {
+ $buf = "WCY de $_[10] <$_[1]> : K=$_[4] expK=$_[5] A=$_[3] R=$_[6] SFI=$_[2] SA=$_[7] GMF=$_[8] Au=$_[9]";
+ $buf .= "\a\a" if $self->{beep};
+ }
$self->local_send('Y', $buf);
}
foreach my $dxchan (DXChannel::get_all) {
next unless $dxchan->{enhanced} && $dxchan->{senddbg};
- $dxchan->send_later('L', $s);
+ if ($dxchan->{gtk}) {
+ $dxchan->send_later('L', dd(['db', $s]));
+ } else {
+ $dxchan->send_later('L', $s);
+ }
}
}
}
}
}
+
+sub print_find_reply
+{
+ my ($self, $node, $target, $flag, $ms) = @_;
+ my $sort = $flag == 2 ? "External" : "Local";
+ $self->send("$sort $target found at $node in $ms ms" );
+}
1;
__END__