#!/usr/bin/perl -w

use strict;
use warnings;
use File::Basename;
use Cwd qw(abs_path);

# set current path of this command
my $curpath = dirname(Cwd::abs_path(__FILE__));

my $CONFFILE = "/etc/osw2csv.conf";
if (-f "$curpath/".basename($CONFFILE)) {
	require "$curpath/".basename($CONFFILE);
} elsif (-f $CONFFILE) {
	require $CONFFILE;
}

require "$curpath/osw2csv_functions";


unless (-p STDIN) {
	print STDERR <<"END_OF_USAGE";
usage:	# cat netstatfile | $0 > csvfile.csv
description:
	This script generate csv file, which is from "netstat -s" output
	provided by OSWatcher or ExaWatcher.
	the netstat output is read from STDIN, and cvs is provided onto STDOUT.
	This could analyze "netstat -i" only.
END_OF_USAGE
	exit 1;
}



# belows are defined in /usr/bin/osw2csv_functions
our $zzz_second;  # set by "zzz ... " line. 0 means "there are no zzz line"

# for "netstat -s"
#     header array of stat

# dynamically generated
my @statheaderary = ("Time", "Timezone");;

# T/F: whether header colmun has been printed
my $header_printed = 0;

# Note that the row number of output of "netstat -s" could be changed without
# any OS changes.
# Therefore, dynamic list-up from the real output of "netstat -s" is not so
# appropriate.

# unknown key array which suppresses the unnecessary warnings
my @unknown_key_array = ();

# analyze a value line which includes "one" numbers
# ($val, $subh, $key) = analyzeValueLine($line, $newh, $subh);
sub analyzeValueLine {
	my ($line, $newh, $subh) = @_;
	my ($sp, $s, $s2, $val) = ("", "", "", 0);

	# possible $line are:
	# "    ### string"
	# "    string: ###"
	# "    string ### string" only "    Quick ack mode was activated 8518 times"
	# "    string:" is new $subh

	# check "    ### string"
	($sp, $val, $s) = (/^( {4}| {8})(\d+) (.*)$/);
	if (!defined($val)) {
		# check "    string: ###"
		($sp, $s, $val) = (/^( {4}| {8})([^ ].*): (\d+)$/);
		if (!defined($val)) {
			# check "    string ### string"
			($sp, $s, $val, $s2) = (/^( {4}| {8})([^ ].*) (\d+)( .*)$/);
			if (!defined($val)) {
				# check "    string:"
				($sp, $subh) = (/^( {4}| {8})([^ ].*:)$/);
				return() if (!defined($subh));
				return(undef, " $subh", undef);
			}
		}
	}
	$subh = "" if (length($sp) <= 4);
	my $key = "$newh$subh $s$s2";
	if (!$header_printed) {
		push(@statheaderary, $key)
	} elsif (!grep($_ eq $key, @statheaderary)) {
		if (!grep($_ eq $key, @unknown_key_array)) {
			warning("unknown key '$key' appeared, skip...");
			push(@unknown_key_array, $key);
		}
		return(undef, $subh, undef); # means skip the value 
	}
	return($val, $subh, $key);
}


# print interface csv header
sub printNetstat_sCSVHeader {

	print join(',', @statheaderary)."\n";
	$header_printed = 1;
}


sub printNetstat_sCSVBody {
	# read/check the first line
	return if (!defined($_ = readNextLineFromSTDIN()));
	while (defined($_)) {
		# set current time if there is "zzz ***" line
		if (setZZZLine($_)) {
			$_ = readNextLineFromSTDIN();
			next;
		}

		# check /^Time ##:##:##/ or /^\s*<##/##/#### ##:##:##>/ line
		if (setZZZByTimeLine($_)) {
			$_ = readNextLineFromSTDIN();
			next;
		}
		# check if the line is a begening of "netstat -s"
		unless (/^[A-Z][a-z0-9]:$/) {
			$_ = readNextLineFromSTDIN();
			next;
		}

		my $date = getDateStringFromSeconds($zzz_second);
		my @output = ($date,$ENV{TZ});
		my @shtmp = @statheaderary;
		shift(@shtmp); shift(@shtmp); # remove "date" and "timezone"
		while (defined($_) && /^[A-Z]\w*:$/) {
			my ($newh) = (/^([A-Z]\w*:)$/);
			$_ = readNextLineFromSTDIN();
			my $subh = "";
			while (defined($_)) {
				my ($val, $key);
				($val, $subh, $key) = analyzeValueLine($_, $newh, $subh);
				if (defined($val)) {
					if ($header_printed) {
						while ($key ne shift(@shtmp)) {
							# don't print this warning since skipping is frequently happen
							# warning("skip key = $key");
							push(@output, "");
						}
					}
					push(@output, $val);
				} elsif (!defined($subh)) {
					last;
				}
				$_ = readNextLineFromSTDIN();
			}
		}
		while (defined(my $key = shift(@shtmp))) {
			# warning("skip key = $key");
			push(@output, "");
		}
		if (!$header_printed) {
			printNetstat_sCSVHeader;
		}
		if ($#statheaderary+1 < $#output+1) {
			printf STDERR "Warning: column number of data(".($#output+1).") and header(".($#statheaderary+1).") is different.\n".
				"header: ".join(',', @statheaderary)."\n".
				"data  : ".join(',', @output)."\n";
		}
		print join(',',@output)."\n";
	}
}

printNetstat_sCSVBody;
exit 0;

