#!/usr/bin/perl

# Simple news command piper (default). Or, for adanced users - simple telnet command piper.
#
# Default:
#
#  Gets a list of supported newsgroups from given server
#  - a news 'list' cmd is given to requested server & output is piped to STDOUT.
# 
# Abilities:
# 
# Could be mustered to pipe to STDOUT any other news command that doesn't ask for interaction
# while giving its output and finish output by empty string. With changing the port (and if 
# required - a line separator there's possiblility to pipe to stdout any telnet oriented 
# protocol command to STDOUT.
#
# I wrote it at the moment I was choosing a good news server from http://www.newzbot.com/ .
# Hopefully it may be usefull for others. Tested w/ innd 2.4.2,  MAY work w/ others.
# Though didn't 've any troubles while using for my case.
#
# License is GNU GPL. (c) Olli Artemjev http://www.livejournal.com/users/grey_olli .
# Thanks to:
#			Authors & developers of perl, Net::Telnet, Getopt::Long.
#			Special thanks to rserg (http://www.livejournal.com/users/rserg).
# 
# You may write to me  olli@digger.org.NOSPAMru (remove NOSPAM 1st).
#
# Notes:
#   *. As much as it possible w/ perl ( huh! :) ) this script shouldn't eat memory on big files - 
#      it parses them line by line w/o loading all the file into memory. =)
#   *. ANY option configurable in script is overridable by commandline.
#   *. Due to I'm too lazy to dance around perl regexps in a variable the script always finish
#      on timeout. In other words the time of execution in normal case is equal to timeoute and
#      is lesser if connection is dropped earlier.
#   *. If debugging is enabled there'll be some noise in STDERR.
#
# The homepage for this script 'll be below http://olli.digger.org.ru/files/pub/programming/perl/DONE/ .
# 
# Yes, it's quite simple, but it's usefull as a part of piped set of scripts & does not require to dig
# into any complex system like INN or so. =) Just run --help . =)

# ----------------------------> define variables (anyone may freely edit)
$port=119;					# default news port

$timeout=8;					# timeout value for connection and for getting replies
							# from commands to server.

$newscmd2pipe="list";		# Default command to execute . You may set for example "group comp.unix"

$lseparator="\r\n";			# '\r\n' works for my innd 2.4.2 news server. ;)

$debug=0;					# if set to anything but 0 'll make loggs.
							# & also some noise on stdout.

$logdir=".";				# directory to store debugging files, "." is for current.

$prompt="/^200 /";			# The 1st string prompt. After getting this from server we'll issue a command above. (REGEXP)

# ----------------------------> code work start  (tech stuff - require some perl knowledge to edit )
use Net::Telnet;
use Getopt::Long;   # command line processing module.

GetOptions
('help|?!',\$cl_help,
'lt=s',\$cl_lineterm,
'h=s',\$cl_host,
'p=i',\$cl_port,
't=s',\$cl_tmout,
'c=s',\$cl_ncmd,
'd+',\$cl_debug,
'ld=s',\$cl_logdir,
'g=s',\$cl_greet,
'v+',\$cl_version,
'i+',\$cl_license
) || die "\nTry `$name --help`\n\n";

if ( $cl_help ) {
 print "\n";
 print "Options are avaliable in both short and long forms (i.e. --short is equivalent to -s).\n";
 print "  --option=s gets a string as value. Remember about shell escaping (i.e. spaces shoud be escaped w/ '\\').\n";
 print "  --option=i gets an integer as a value. \n";
 print "  --option+  has no value - it's a trigger inversing the default config value ( 0 -> 1 or 1 -> 0 ). \n";
 print "Trigger options (w/ plus sign) should be supplied w/o plus (i.e. '-i+' means you should supply '-i').\n";
 print "\n\n";
 print "The following options are known:\n\n";
 print "Required:\n";
 print " '-h=s'\t\tSet host to connect to.No default.\n";
 print "Optional:\n";
 print " '-help|?!'\tGive overview on commandline options.\n";
 print " '-lt=s'\tOverride default news proto line delimiter sequence. Default is \"\\r\\n\". Don't touch if unsure.\n";
 print " '-p=i'\t\tOverride default port to connect to. Default is '$port' .\n";
 print " '-t=s'\t\tOverride default timeoute value (connect & commands). Default is '$timeout' .\n";
 print " '-ld=s'\tOverride default logging directory path value. Default is '$logdir' .\n";
 print " '-g=s'\t\tOverride default greeting. Default is '$prompt'. Script issues cmd on receiving that from server.\n";
 print " '-d+'\t\tDebug switch (inverts default configuration value). Default is '$debug' .\n";
 print " '-v+'\t\tShow version of this script.\n";
 print " '-i+'\t\tShow information on license.\n";
 print "\n";
 exit;
}

if ( $cl_debug ) { 
  # ($debug) && print STDERR "\$debug option change request from command line\n";
  if ( $debug ) {$debug=0;}
   else  {$debug=1;} # if set to anything but 0 'll do log . 
}

if ( $cl_license ) {
 ($debug) && print STDERR "license info request from command line.\n";
 print "\nLicense is GNU GENERAL PUBLIC LICENSE Version 2, June 1991\n";
 print "You should've one received w/ script. Try google for it if not present. =)\n\n";
 exit 0;
}

if ( $cl_version ) {
 ($debug) && print STDERR "version info request from command line.\n";
 print "\nVersion 1.0, production, stable.\n";
 print "(c) Olli Artemjev <olli\@digger.org.ru>.\n";
 print "Report bugs to olli\@digger.org.ru .\n\n";
 exit 0;
}

if ( $cl_port ) {
 ($debug) && print STDERR "\$port change request from command line.\n";
 $port=$cl_port;							## default news port
}

if ( $cl_host ) {
 ($debug) && print STDERR "\$host set requested from command line.\n";
 $host=$cl_host;		# Where we're connecting to.
 chomp($host);
 chomp($host);
} else {
  print "host to connect to is required. Try --help.\n";
  exit 1;
}

if ( $cl_tmout ) {
 ($debug) && print STDERR "\$timeout change requested from command line.\n";
 $timeout=$cl_tmout;							# timeout value for connection and for getting replies
 ($debug) && print STDERR "new timeout value is $timeout .\n";
}

if ( $cl_ncmd ) {
 ($debug) && print STDERR "\$newsgroup change request from command line.\n";
 $newscmd2pipe=$cl_ncmd;					# Default newsgroup to post to.
 chomp($newscmd2pipe);
 chomp($newscmd2pipe);
}

if ( $cl_lineterm ) {
 ($debug) && print STDERR "\$lseparator change request from command line.\n";
 $lseparator=$cl_lineterm;				# '\r\n' works for my innd 2.4.2 news server. ;)
 chomp($lseparator);
 chomp($lseparator);
}

if ( $cl_logdir ) {
 ($debug) && print STDERR "\$logdir change request from command line.\n";
 $logdir=$cl_logdir;						# directory to store debugging files. "." is for current.
 chomp($logdir);
 chomp($logdir);
}

if ( $cl_greet ) {
 ($debug) && print STDERR "\$stop change request from command line.\n";
 $prompt=$cl_greet;
 chomp($prompt);
 chomp($prompt);
}

if ( $debug ) {
	$to_us_logfile="$logdir/strings_from.$host.log";
	$from_us_logfile="$logdir/strings_to.$host.log";
}


$t_hndl = new Net::Telnet (Timeout => $timeout,
							Host => $host,
							Port => $port,
							Input_record_separator => $lseparator,
							Output_record_separator => $lseparator 
							);
if ( $debug ) {
 $t_hndl->input_log($to_us_logfile);
 $t_hndl->output_log($from_us_logfile);
}

$t_hndl->binmode(1); # turn OFF @!cking convertion. =)
#$t_hndl->binmode(0); # turn ON @!cking convertion. =)

$t_hndl->waitfor($prompt);
$t_hndl->print($newscmd2pipe);
while(1) {
 $_ = $t_hndl->getline( Errmode => "return" );  
 print;
 unless ($_) {
  if ( $debug ) {print STDERR "Got end of input";}
  $t_hndl->close;
  exit 0;
 }
}


