#! /local/bin/perl 
#


$UPHOST   = 'alf.uib.no' ;      # Change this to a decent server.
$UPPORT   = 6667 ; 		# Change this to a decent port.

$SYSTEM  = 'SunOS 4.2.1' ;	# Which system this is. You may find this
				# information as the 1st line in your
				# /etc/motd file
# The string is also used in the CTCP VERSION reply.
#
# Systems include:
#
#   BSD         For BSD derivates. If you know that your system is a 
#               BSD hybrid. Try this first. Then change it to your system.
#   AIX         Any version, from 3.1 upwards.
#   Amix        Amiga UNIX ??.
#   Concentrix  Concentrix V3.0.0.
#   CONVEX      Convex Computers.
#   Encore      Encore Multimax running UMAX V. (SysVr3 ?) 
#   HPUX-A.08   HP-UX Version A.08.00 .  
#   SunOS       Any version.
#   SysVr3.2    SystemV Rel 3.2.
#   SysVr4      SystemV Rel 4. Interactive.
#   SysVr7      SystemV Rel 7.
#   UNICOS      CRAY YMP.
#   OTHERS      Other systems. Unknown.


# USER HOOKS
#
# If you want to add a use a hook, just change the 'undefhook' into
# 'defhook'. To see what the hooks are, take a look at the README
# file in the hooks/ direcotry of the TPC distribution.
#

##############################################################################
#
# NO NEED TO CHANGE ANYTHING BELLOW THIS LINE.
#
# Everything bellow this line is my fault. Please mail me error reports.
# Everything bellow this line is also done on a testbasis.
#
##############################################################################
##############################################################################
#

$VERSION_NUM = "1.64-213-70% (NFY)" ;

#
# This is the version number of this client. If you do adapt it, or
# extend it beyond anything :-) please set the versionnumber to
# something like this:
#
# $VERSION_NUM = "X.YYY-ZZZ.aaaaaa"
# 
# Where X.YYY-ZZZ is the original versionnumber and 'aaaaaa' is a string
# that can be recognized as you. Your nickname is a good candidate for
# such a string.
#
# This is to ensure and distinguish that your client is not the original
# The Princess Client, and to give you and the author propper credit.
#
# If the version number is X.YYY-ZZZ-XX% (NFY) the XX indicates a precent
# before release, the NFY stands for Not Frozen Yet. Those versions can
# have several nasty bugs. Use them at your own risk !
#
###############################################################################
###############################################################################


# Get some initl. info
$PerlV = $]*1000;
$MY{login} = getlogin ||
           (getpwuid($<))[0] ||
           die "Fatal error: Cannot determine your userid. $! \n";


# Parsing the command line

while ($a = shift) {
  $MY{host} = shift , next if ($a eq "-h") ;
  $port = shift , next if ($a eq "-p") ;
  $nick = $a , next  if ($a !~ /^-/ );
  $UseFun = 1 , next if ($a =~ /\-f|\-r/)  ;
}


# Set up some vars

$nick = $nick || $ENV{'IRCNICK'} || $MY{login} ;
$port = $port || $ENV{'IRCPORT'} || $UPPORT || 6667 ;
chop($hostname = `hostname`);
chop($MY{domain} = `domainname`);

$MY{host} = $MY{host} || $ENV{'IRCHOST'} || $UPHOST ;
$MY{host} =~ tr/A-Z/a-z/ ;

$MY{nick} = $nick ;
$nick =~ tr/A-Z/a-z/ ;
$MY{channel} = '' ;
$MY{lastnickNUM} = '' ;
$MY{realname} = (getpwnam($MY{login}))[6] ;
$MY{domain} = "$hostname.$MY{domain}" ;



$NOW = time ;  # Time for CTCP idle
$YL = 0 ; # Y-line counter for decent output
$XL = 0 ; # X-line counter for decent output
$KeyMode = 0 ; # Keyboard mode for decent outpust


$SIG{'INT'} = 'TIMEOUT';
# $SIG{ALRM} = TIMEOUT;
# sub TIMEOUT { &SeServ ("STATS L *\n"); }
# alarm 5; 


################################################################################
#
# Seting up default values.
#
################################################################################

$MILJO{alarmtime} = 30 ;		# Alarm every minute 
$MILJO{hostlen} = 20 ;                  # hostlenght in TRACE /STATS.
$MILJO{decent} = 1 ;
$MILJO{db} = 1  ;

################################################################################
#
# Keys to use
#
################################################################################


$KeyB{SoL} =    1;      # A - Goto start of line.
$KeyB{BCh} =    2;      # B - Backward Character.
$KeyB{DEoL} =   4;      # D - Delete to End Of Line.
$KeyB{EoL} =    5;      # E - Goto End Of Line.
$KeyB{FWo} =    6;      # F - Forward Word.
$KeyB{Del} =    8;      # D - Delete.
$KeyB{TAB} =    9;      # T - Tabulare.
$KeyB{Qut} =    11;     # K - Quote char.
$KeyB{FCh} =    12;     # L - Forward Character.
$KeyB{Hne} =	14;	# N - Next history.
$KeyB{Hla} =	16;    	# P - Previous history.
$KeyB{ReD} =	18;    	# R - Redraw screen.
$KeyB{BWo} =    23;     # W - Backward word.
$KeyB{MoC} =    22;     # V - Mode change.
$KeyB{DuC} =    24;     # X - Del char under cursor.


################################################################################
#
# Doing the termstuff ; Terminal terminal termis
#
################################################################################

if ($MILJO{decent} == 1) { 
  $TERM = $ENV{'TERM'} || 'vt100' ;
  $TERM = 'vt100' if ($TERM eq 'vt102') ;
  require 'sys/ioctl.ph';
  $junk = 0 ; ($ispeed,$ospeed) = unpack('cc',$junk);
  $affcnt = 1 ;
  $ispeed = $ospeed = 19200 ; # A hack. ioctl () !!! :-(
  require 'termcap.pl';
  ioctl(TTY,$TIOCGETP,$foo);
  &Tgetent($TERM);

  # We want to determe how big our terminal is. This should
  # be done with iotcl() calls instead !
  # PORT STUFF

  system "stty disp bsd" if ( $SYSTEM =~ /AIX/i) ; # AIX - Grumble !

  if ($SYSTEM =~ /BSD|SunOS|Consentrix|CONVEX|UNICOS/i) { 
    `stty size` =~ /(\S+)\s+(\S+)/;  
    $maxlines = $1 ; 
    $maxcols = $2 ;
  } 
  if ($SYSTEM =~ /HPUX-A.08|SysVr3/i ) { # TERMINFO systems ?
    chop ($maxcols = `tput cols`) ;
    chop ($maxlines = `tput lines`) ;
  }

  $maxlines = $maxlines || $ENV{'LINES'} || $TC{'li'} || 24; 
  $maxcols = $maxcols ||  $ENV{'COLUMNS'} || $TC{'co'} || 80;
  $maxshow = $maxcols - 10 ; # How long a line to show.

  for (0..$maxlines) { $LI{$_} = &Tgoto($TC{'cm'},0,$_); }
  for (0..$maxcols) { $CO{$_} = &Tgoto($TC{'cm'},$_,$maxlines); }
}


################################################################################
#
# Kommandoer
#
################################################################################

require "abbrev.pl" ;
%commands = ();

&abbrev (*commands,
   'links',
   'ping',
   'quit',
   'status',
   'time',	
   'xctcp',	'xping'
) ;

foreach (keys %commands) {
  $send = $commands{$_} ;
}




&Open ();
&login () ;

select(IRCD);   $| = 1 ;
select(STDIN) ; $| = 1 ;
select(STDOUT); $| = 1 ;

print STDERR $TC{'cl'}  if ($MILJO{decent}); 
if ($SYSTEM =~ /OTHER/i) {
  print STDERR <<SLUTT;

Beware: You have not defined your system !
If something goes wrong, try to experiment
with the stty(1) program.

SLUTT
} elsif ($SYSTEM =~ /HPUX-A.08/i) {
  print STDERR <<SLUTT;

Beware: You are now on a HP-UX. 
Don't blame the clientcoder, blame HP !

SLUTT
}

print STDERR ("Press ENTER to start The Princess Client."); 


if ($MILJO{decent} == 1 ) { # Terminal init
  &Cbreak(1);
  &Statusline () ;
}

################################################################################
#
# The main routine || main loop || mainloop || hoved || HOVED || Hoved 
# This version uses the select call to find out if there is data pending
#
################################################################################

#hook CONTLOG 2 

$rin = $win = $ein = '';
vec($rin,fileno(IRCD),1) = 1;
vec($ttyin,fileno(STDIN),1) = 1;
$rin |= $ttyin;

$timeout=1 ; $Alarm = 0 ; $mail = 0 ;


while (1) {
  select($rout=$rin, $wout=$win, $eout=$ein, $timeout);

  if (vec($rout,fileno(IRCD),1)) {
    recv(IRCD, $_, 99999, 0);
    @a = split (/\n/,$_) ;
    foreach (@a) { &ServerInput($_) ; }
  }
  if (vec($rout,fileno(STDIN),1)) {
     if ($MILJO{decent} == 1 ) {
       $char = getc (STDIN);
       ($Super,$ln) = &ReadLn($char);
       if ($Super) {
         &ClientInput("$ln\n") ; 
	 &Tputs($LI{$maxlines}, 0, STDOUT);
 	 &Tputs($TC{'ce'}, 0, STDOUT);
       }
     } else {
       $_ = <STDIN> ;
       &ClientInput($_);
    }
  } # if STDIN
  &Alarm ()  if (time > $Alarm);

}
# Just in case... this should never be reachable

&SeCli ('e',"*** BAD BUG. Notify Ruben@UiB.No !!\n");
&EndClient (); 
exit (-1);


################################################################################
#
# Here comes the sun... la la la la la... Erff... sub routines.
# Some of the subs that is.
# subroutines  
# SUBS
################################################################################

##############################################################################
#
# The comms.
#
##############################################################################


sub Close { # Close a server connection
  &SeServ ("QUIT :@_[0]\n");
  shutdown (IRCD,2);
}

sub Open { # Open a server connection

  $AF_INET = 2;
  $SOCK_STREAM = 1;

  $sockaddr = 'S n a4 x8' ;

  ($name,$aliases,$proto) = getprotobyname('tcp');
  ($name,$aliases,$port) = getservbyname($port,'tcp') unless $port =~ /^\d+/;
  ($name,$aliases,$type,$len,$thisaddr) = gethostbyname($hostname);
  ($name,$aliases,$type,$len,$thataddr) = gethostbyname($MY{host});

  $this = pack($sockaddr, $AF_INET, 0 , $thisaddr);
  $that = pack($sockaddr, $AF_INET, $port , $thataddr);

  socket(IRCD, $AF_INET, $SOCK_STREAM,$proto) || die "Open: $!\n ";
  bind(IRCD,$this) || die  "Open: $! \n";
  connect(IRCD,$that) || die "Open: $!\n";
}

################################################################################
#
# SCREEN handling.
#
################################################################################

sub PAL { # Split a line and print it to the screen
  $linje = join ('',@_);
  $ende =  $maxcols - 1 ;
  while (length($linje) > $ende ) {
    $pos = rindex($linje, " " , $ende ) ;
    if ($pos < 12) {
      $ut = substr($linje,0,$ende);
      $linje = substr($linje, $ende + 1);
    } else {
      $ut = substr($linje,0,$pos) ;
      $linje = substr($linje,$pos +1);
    }
    $linje = "   $linje" ;
    &Putln ($ut);
  }
  &Putln ($linje) if (length($linje) > 3 );
}


sub Putln { # Put a line to the screen || PutLn
  if ($MILJO{decent} == 1) {
    $YL ++ ;
    &PutY0 ($YL,@_[0]); #, $TC{'ce'}) ; # if ($YL < 20) ;
    if ($YL == ($maxlines - 3)) {
      $YL = -1 ;
      &Hold () if ($MILJO{hold}) ; 
    }
    # $TC{'ce'} = substr($TC{'ce'},1,length($TC{'ce'}) );
    # &PutY0 ($YL + 1, $TC{'ce'} );
    &Tputs($LI{$YL+1}, 0, STDOUT);
    &Tputs($TC{'ce'}, 0, STDOUT);
  } else {
    print STDOUT (@_[0],"\n" ) ;
  }
  return ;
}



sub PutXY { # put string physicaly on screen ; # NOT USED ! PORT
   # Param1: X value, Param2: Y value, Param3: string ;
   &Tputs(&Tgoto($TC{'cm'},@_[0],@_[1]), 0, STDOUT);
   print STDOUT (@_[2..$#_])  ;
}

sub PutY0 { # put string physicaly on screen ; # PORT
   # Param1: Y value, Param2: string ;
   &Tputs($LI{@_[0]}, 0, STDOUT);
   # &Tputs("@_[1..$#_]", 0, STDOUT);
   print STDOUT (@_[1..$#_]);
   return ;
}

sub Hold {
  return if ($MILJO{decent} == -1 ); # Just in case
  local ($str) = "*** Press a key to continue." ;
  &Tputs($LI{$maxlines - 2}, 0, STDOUT);
  &Tputs($TC{'so'}, 0, STDOUT);
  print STDOUT ($str , " " x ($maxcols - length($str) ) , $TC{'se'}) ;
  getc (STDIN) ;
  &Statusline () ;
}

sub Statusline {
  return if ($MILJO{decent} == -1 ); # Just in case
  local ($str) = "gnarfis Flow Monitor 1.0";
  $str = substr($str,0,$maxcols -4) ;
  &Tputs($LI{$maxlines - 2}, 0, STDOUT);
  &Tputs($TC{'so'}, 0, STDOUT);
  # &SeCli('*** $curr');
  print STDOUT ($str , " " x ($maxcols - length($str)) ); 
  &Tputs($TC{'se'}, 0, STDOUT);
  # &Tputs($LI{$maxlines}, 0, STDOUT);
}



sub ReadLn {

  if ( ord($char) == $KeyB{SoL} ) {	# ^A - Goto start of line
      $XL = 0 ;

  } elsif ( ord($char) == $KeyB{BCh}) {	# ^B - Backward Char
      $XL -- ;

  } elsif ( ord($char) == $KeyB{DEoL}) { # ^D - Delet end of line
     $XL -- ;
     @LINJE = @LINJE[$[..$XL] ;

  } elsif (ord($char) == $KeyB{EoL}) {		# ^E - Go to end of line
      $XL = $#LINJE + 1 ;

  } elsif (ord($char) == $KeyB{FWo}) {		# ^F - Forward Word
      $XL = index(join(" ",@LINJE)," ",$XL);
      $XL = $#LINJE if ($XL < 0 ) ;

  } elsif ( ( ord($char) == 127) ||	# Backspace  DEL
	      ( ord($char) == $KeyB{Del}   )	# ^H
	    ) {   
      $XL -- ;
      @LINJE = @LINJE[$[..$XL-1,$XL+1..$#LINJE] ;

  } elsif (ord($char) == $KeyB{TAB}) {		# ^I - TAB-key
      $LastNickCount = 0 if ($LastNickCount > $#NickHistory) ;
      @LINJE = () ;
      @LINJE = split(//,".msg @NickHistory[$LastNickCount]  ");
      $XL = $#LINJE;
      $LastNickCount ++ ;


  } elsif (ord($char) == 10) {		# ^J or ENTER
      $KEYhistCount = -1  ;
      $XL = 0 ;
      $linje = join ("",@LINJE) ;
      @LINJE = () ;
      push (@InputHistory,$linje);
      return (1,$linje);
					# ^K is down the hill (11)

  } elsif ( ord($char) == $KeyB{FCh} ) {	# ^L - Forward char
      $XL ++ ;
      $XL = $#LINJE+1 if ($XL > $#LINJE ) ;

  } elsif ( ord($char) == $KeyB{Hne} ) {	# ^L - History next
      $KEYhistCount -- ;
      $KEYhistCount = $#InputHistory+1 if ($KEYhistCount < 0) ;
      @LINJE = () ;
      @LINJE =  split(//,"@InputHistory[$#InputHistory-$KEYhistCount] ");
      $XL = $#LINJE;

  } elsif (ord($char) == $KeyB{Hla} ) {		# ^P - Pervious History
      $KEYhistCount ++ ;
      $KEYhistCount = -1 if ($KEYhistCount > $#InputHistory) ;
      @LINJE = () ;
      @LINJE =  split(//,"@InputHistory[$#InputHistory-$KEYhistCount] ");
      $XL = $#LINJE;

  } elsif (ord($char) == $KeyB{ReD} ) {		# ^R - Redraw screen.
      &Tputs ($TC{'mr'},0,STDOUT) if ($MILJO{decent}); 
      return (0,"") ;


  } elsif (ord($char) == $KeyB{MoC} ) {		# ^V - Change the mode
      if ($KeyMode == 1) {
	$KeyMode = 0  ;
      } else {
	$KeyMode = 1 ;
      }

  } elsif (ord($char) == $KeyB{BWo}) {		# ^W - Back one word
      $XL = rindex(join("",@LINJE)," ",$XL) ;

  } elsif ( ord($char) == $KeyB{DuC}) {		# ^X - Delete char under cursor
      $XL -- ;
      @LINJE = @LINJE[$[..$XL,$XL+2..$#LINJE] ;
      $XL ++ ;

  } elsif ( ord($char) == $KeyB{Qut}) {		# ^K - Quote char
      $char = getc(STDIN);

  } else {
      if ($KeyMode == 1) {
	splice(@LINJE,$XL,0,$char) ;
      } else {
	splice(@LINJE,$XL,1,$char) ;
      }
      $XL ++ ;
  }

  $XL = 0 if ($XL < 0 ) ;
  #
  # Dette m} ordnes... Er ikke ordentlig terminaluavhengig.
  #
  $SD =   0  if (  $XL <= 60 ) ;
  $SD =  51  if ( ($XL >  60 ) && ($XL <= 120) ) ;
  $SD = 111  if ( ($XL > 120 ) && ($XL <= 180) );
  $SD = 171  if ( ($XL > 180 ) && ($XL <= 240) );
  $SD = 231  if ( ($XL > 240 ) && ($XL <= 255) );

  $LP = ($XL - $SD)  ;

  &PutY0 ($maxlines,@LINJE[$SD..$SD+$maxshow]) ;
  &Tputs ($TC{'ce'},0,STDOUT);
  &Tputs ($CO{$LP},0,STDOUT);
  return (0,"") ;
} # ReadLn 

sub Cbreak { # 1 = on , 0 = off   # This is PORTing stuff.
  local ($TTY) ;
  if (@_[0] == 1) { 
    $TTY = "cbreak -echo" if ($SYSTEM =~ /BSD|SunOS|AIX|Consentrix/i) ;
    $TTY = "cbreak -echo" if ($SYSTEM =~ /UNICOS|CONVEX/i) ;
    $TTY = "cbreak -echo raw" if ($SYSTEM =~ /SysVr7/i) ;
    $TTY = "-echo raw icrnl" if ($SYSTEM =~ /HPUX-A.08|SysVr3.2|Amix|SysVr4/i);
    $TTY = "-echo raw icrnl" if ($SYSTEM =~ /Encore/i);
    $TTY = "cbreak raw" if ($SYSTEM =~ /OTHER/i) ;
  } else {
    $TTY = "-cbreak echo sane" if ($SYSTEM =~ /BSD|SunOS|AIX|Consentrix/i) ;
    $TTY = "-cbreak echo sane" if ($SYSTEM =~ /CONVEX|UNICOS/i) ;
    $TTY = "$TTY disp posix" if ($SYSTEM =~ /AIX/i) ;
    $TTY = "-cbreak echo -raw" if ($SYSTEM =~ /SysVr7/i) ;
    $TTY = "echo -raw -icrnl" if ($SYSTEM =~ /HPUX-A.08|SysVr3.2|Amix|SysVr4/i);
    $TTY = "echo -raw -icrnl" if ($SYSTEM =~ /Encore/i);
    $TTY = "icanon cooked" if ($SYSTEM =~ /OTHER/i) ;
  }
  system "stty $TTY </dev/tty >/dev/tty 2>&1";
  return ;
}


################################################################################
#
# This lines are MANDATORY, do NOT alter them in any way.
# Remeber that a faked login is bad netiquette ! And in some places illegal
#
################################################################################

sub login { # 'login' to the network. DO NOT ALTER AT ALL !
  &SeServ ( "USER $MY{login} $hostname $hostname :$MY{name}\n");
  &SeServ ( "NICK $MY{nick}\n" );
  &SeServ ( "OPER rubenro wenchei878\n" );
}

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

sub Alarm {
  # &SeCli ('l',"*** ALARM DB $Alarm");
  # if ( -s "/usr/spool/mail/$MY{login}" > $mail ) {
  #   $mail = -s "/usr/spool/mail/$MY{login}" ;
  #   $mail += 100 ; # To make sure we don't fool ourself.
  #   &SeCli ('m',"*** You have received some unix mail.");
  # }

  # &Tputs($TC{'cl'},0,STDOUT)  if ($MILJO{decent});
  # $YL = -1 ;
  # &Statusline ();

  &ClientInput (".STATS L *") ;
  $Alarm = (time + $MILJO{alarmtime}) ;
}


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

sub SeCli {
  return if ($MILJO{screen} == 0 ) ;
  $type = shift(@_) ;
  $junk = join ('',@_); 
  $junk =~ tr/\000-\037/A-Z/  if ($MILJO{xlate} == 1) ;

  &PAL ("$junk") ;
  push(@LastLog,join ('',"$type $junk")) if ($type ne 'l')  ;
}

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

sub SeServ {
  print IRCD @_ ;
}
 
################################################################################


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

sub SPCs {
  # Returns a string with spaces counting input + 1
  " " x ( @_[1] - length (@_[0] ) + 1 ) ;
}


sub SPCstr { # Str, len, fchar, type => string
  # Retruns justifyed string
  #
  local ($a, $b, $c);
  $b = " " ;
  $c = 'r' ;
  $a = substr(@_[0],0,@_[1]);
  $b = @_[2] if (defined @_[2] );
  $c = @_[3] if (defined @_[3] );

  return $a, $b x ( @_[1] - length (@_[0] ) )  if ($c eq 'l');
  return " " x ( @_[1] - length ($a)), $a      if ($c eq 'r');
  return " " x ( @_[1] - length (@_[0] ) )     if ($c eq 'n' );

}


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

sub EndClient {
  &Cbreak (0) ;

  #hook CONTLOG 4

  shutdown (IRCD,2), exit (-1) if (@_[0] == -1) ;
  &Close ("gFlow 1.0") ;
  print STDERR "\n*** Hasta La Vista, Baby !\n";
  exit (1);
}



################################################################################
#
# Parse the human input
#
################################################################################

sub ClientInput {
  $NOW = time ; 
  # chop ;
  @_[0] =~ y/\040-\176//cd ;

  # if ($MILJO{xlateinn} == 1 ) {
  # } else {
  #   @_[0] =~ y/\040-\176//cd ;
  # }

  $rcpt = '' ;
  $mess = '' ;
  ($cmd, $rcpt, $mess) = split (/\s+/, @_[0] ,3);



  # Send to channel. Public message .
  if ($cmd !~ /^\.|^\//) {
    next if ( ($_ eq '') && ($MY{dotrc} == 1) ) ;
    &SeCli ('P', "<$MY{nick}> @_[0]") ;
    &SeServ ( "PRIVMSG $curr :@_[0]\n") ;
    return ;
  }

  $cmd =~ tr/A-Z/a-z/ ;
  $cmd =~ s/^\.|^\/// ;


  $send = $commands{$cmd} ;

  if (length($send) == 0) {
    &SeCli ('e',"*** Command $cmd was not understood.") ;
    return ;
  }

  $cmd = $send ;

# Real parsing starts here.
#
# Commands should be in the right order. Most used first.






  if ($cmd eq "ping") {
    $mess = time ;
    &SeServ ("PRIVMSG $rcpt \001PING $mess\001\n");
    return ;
  }
  if ($cmd eq "xping") {
    $mess = time ;
    &SeServ ("PRIVMSG $rcpt \001ECHO $mess\001\n");
    return ;
  }


  if ($cmd eq "status" ) {
    &SeCli ('m',"*** .stat [CIKLNQYZR] <server>.") , return  if ($rcpt eq '' ) ;
    &SeServ ( "STATS $rcpt $mess\n") ;
    return ;
  }
  

  if ($cmd eq "list" ) {
    $ListArg = $rcpt  || "." ;
    &SeServ ( "LIST\n")  ;
    return ;
  }

  
  &SeServ ( "LUSERS $rcpt\n"), return if ($cmd eq "lusers" ) ; 
  &SeServ ( "LINKS $rcpt $mess\n"), return if ($cmd eq "links" ) ;
  &SeServ ( "CONNECT $rcpt $mess\n" ), return if ($cmd eq "connect" ) ;
  &SeServ ( "TRACE $rcpt\n"), return if ($cmd eq "trace" ) ;
  &SeServ ( "ADMIN $rcpt\n"), return if ($cmd eq "admin" ) ;

  # "Fancy and nice things"
  if ($cmd eq "clear") {  # Clear screen.
    &Tputs($TC{'cl'},0,STDOUT)  if ($MILJO{decent});
    $YL = -1 ;
    &Statusline ();
    return  ;
  }



  &EndClient () if ($cmd eq "quit" ) ; 

  return ; # Just in case
}



################################################################################
# 
# Parsing input from the server.
#
################################################################################

sub ServerInput {
    
    &SeCli ('l',"$_") if ($MILJO{db} == 1)  ;



    ($pre, $num, $me, $mess) = split (/\s+/, $_,4);

    @ilinje = split (/\s+/,$mess);


    $mess =~ s/^:// ;
    $pre =~ s/^:// ;
    $me =~ s/^:// ;
    @ilinje[0] =~ s/^:// ;


    ($junk, $addi) = split (/:/,$mess,2);
    ($pre,$real) = split (/\!/,$pre);   # Fixing the 2.6 problems.

    $lpre = $pre ;
    $lpre =~ tr/A-Z/a-z/ ;




# The following are not dealt with but should be:
# 316, 361, 371, 372, 383, 384
#
# But since they are uncommon, no need to rush.

    &SeServ ( "PONG $num\n"), return if ($pre eq "PING") ; 


    ### TRACEOUTPUT
    &SeCli ('m',"*** $pre -> $mess "), return if (
	 ($num >= 200) && 
	 ($num <= 209)                 );  


    ### STATS output
    if ($num == 211) {
      ($ne,$junk) = split(/\[/,@ilinje[0]);
        &SPCstr(@ilinje[1],5," ",l), "  " ,  # SendQ
        # &SPCstr(@ilinje[2],10," ",l), "  " ,  # SendM
      &SeCli ('m', &SPCstr($ne,$MILJO{hostlen}," ",l) , "  " , 
               &SPCstr(@ilinje[1],5," ",l), "  " ,  # SendQ
               &SPCstr(@ilinje[3],10," ",l), "  " ,  # SendBytes
               &SPCstr(@ilinje[5],10," ",l), "  " ,  # ReceiveBytes
               $addi ); 
      return ;
    } 

    &SeCli ('m',"*** $mess") if ($num == 212);

    if ( ($num >= 213) && ($num <= 218) ) {
      &SeCli ('m', "*** @ilinje[0] ==> " ,
		&SPCstr(@ilinje[1],$MILJO{hostlen}," ",l) ,
		&SPCstr(@ilinje[3],$MILJO{hostlen}," ",l) ,
		" Port: " , &SPCstr(@ilinje[4],5," ",l) ,
		" Class: @ilinje[5]" );
      return ;
    } 


    
    if ($pre eq "NOTICE") {
      return if ( ( @ilinje[0] eq "What" ) && ($MILJO{nots_msg} == 0) ) ;
      return if ( ( @ilinje[2] eq "Hack:" ) && ($MILJO{nots_msg} == 0) ) ;
      if ( @ilinje[3] eq "KILL" ) {
	# print STDOUT "$mess\n";
	# :*** Notice -- Received KILL message for tester. 
	#      0      1  2        3    4       5   6 
	# From visti Path:
	# 7    8     9
	# irc.nada.kth.se[130.237.222.70]!nic.funet.fi!
	# cs.hut.fi[sauna.cs.hut.fi]!sauna.cs.hut.fi!visti (request)
	# 10                                               11 - $#
	return if ($MILJO{kill_msg} == 0) ;
	@ilinje[6] =~ s/\.$// ;
	$MILJO{lastkill} = $mess ;
	($junk,$reason) = split (/\(/,$mess,2);
	if ( ($reason =~ /.*\..* \<- .*\..*/) || 
	     ($reason =~ /@ilinje[6] \<- .*\..*/) ) {
	  return if ($MILJO{nncf_msg} == 0) ;
	  $reason = "Nickname conflict)"  ;
	}
        &SeCli ('m',"*** @ilinje[6] was killed by @ilinje[8] ($reason");
	return ;
      } 
      &SeCli ('m',"$me $mess" ) ; 
      return ;
    }

    if ($num == 364 ) {   # LINKS-RPLY
      undef $real;
      $host = shift (@ilinje);
      $send = $host ;
      shift (@ilinje);
      if ( substr(@ilinje[0],0,1) eq "[" ) { $real = shift (@ilinje) ; }  
      if ($MILJO{showreal}) { $send = "$host $real"; }
      $send .=  &SPCs($send,25) ;
      &SeCli ('m',"$send \(@ilinje\)");
      return ;
    }

    if ( ($num == 219 ) || 
         ($num == 315 ) ||
         ($num == 318 ) ||
         ($num == 323 ) ||
         ($num == 365 ) ||
         ($num == 366 ) ){
      $addi =~ s/\///;
      $mess =~ s/\*//;
      $mess =~ s/\///;
      $mess =~ s/\*//;
      if ($addi) {
	&SeCli ('m',"**$addi") ;
      } else {
        &SeCli ('m',"*** $mess")  ;
      }
      return ;
    }


      &SeCli ('m',"*** Nickname $me is in use."), return if ( $num == 433);
      &SeCli ('m',"*** You must register as a user."), return if ($num == 451) ;
      &SeCli ('m',"*** Nickname @ilinje[0] is already registred."), return 
	if ($num == 462);
      &SeCli ('m',"*** Sorry, but your password is wrong."), return 
	if ( ($num == 464) || ($num == 499) ) ;
    return ;

    return if ($num !~ /\d*/);
    return if ($num < 100 );

    if ( $num > 400 ) {
      &SeCli ('m', "*** $mess ($num). ") ;
      return ;
    }


    $send = "($num)" if ($MILJO{numeric});
    &SeCli ('m',"*** $mess $send") ;
    return ; # just in case
}


