#!/usr/bin/perl -w

# Copyright 2001 (c) Thomas Erskine <thomas.erskine@sourceworks.com>
# See the COPYRIGHT file with the distribution.

# new-unix-hosts - add rrds for hosts running the unix-status-server
# $Id: new-unix-hosts.pl,v 1.6 2001/08/28 15:22:24 remstats Exp $

# - - -   Configuration   - - -

use strict;

# What is this program called, for error-messages and file-names
$main::prog = 'new-unix-hosts';
# Where is the config-dir
$main::config_dir = '/etc/remstats/config';
# How long to wait for response
$main::timeout = 10;
# Where does the unix-status-server hang out?
$main::port = 1957;

# - - -   Version History   - - -

(undef, $main::version) = split(' ', '$Revision: 1.6 $');

# - - -   Setup   - - -

require 5.004;
use lib '.', '/usr/lib/remstats/lib';
use Getopt::Std;
use Socket;
require "remstats.pl";
require "socketstuff.pl";

# Parse the command-line
my %opt = ();
getopts('d:f:hp:t:', \%opt);

if (defined $opt{'h'}) { &usage; } # no return
if (defined $opt{'d'}) { $main::debug = $opt{'d'}; } else { $main::debug = 0; }
if (defined $opt{'f'}) { $main::config_dir = $opt{'f'}; }
if (defined $opt{'p'}) { $main::port = $opt{'p'}; }
if (defined $opt{'t'}) { $main::timeout = $opt{'t'}; }

unless (@ARGV >= 1) { &usage; }
my $group = shift @ARGV;

unless (-d $main::config_dir) {
	&abort("missing config-dir $main::config_dir");
}
&read_config_dir( $main::config_dir, 'general');

&add_group_if_missing( $group);

my %unix_rrds = (
	'cpuuser'			=> 'cpu',
	'dfused:(\S+)'			=> 'df-$1',
	'interface_packets_in:(\S+)'	=> 'if-$1',
	'load15'			=> 'load',
	'freemem'			=> 'memory',
	'qmail_qbacklog'		=> 'qmailq',
	'tcpstate:'			=> 'tcpstates',
	'timediff'			=> 'unixtime',
	'uptime'			=> 'uptime',
);

# - - -   Mainline   - - -

my ($host, $ip, $hostfile, $socket, $status, $query, $pattern,
	$instance, $rrd, %rrds, $line, $os_name);
$query = join("\n", 'UNAME', 'TIME', 'VMSTAT', 'DF', 'UPTIME', 
	'PS', 'FTPCOUNT', 'QMAILQ') .  "\nGO\n";

while (<>) {
	chomp;
	next if (/^#/ or /^\s*$/);
	$host = lc $_;
	$ip = &get_ip($host);
	unless (defined $ip) {
		&error("couldn't find IP number for $host; skipped");
		next;
	}

	$hostfile = $main::config_dir .'/hosts/'. $host;
	if ( -f $hostfile) {
		open (HOST, ">>$hostfile") or &abort("can't open $hostfile: $!");
	}
	else {
		open (HOST, ">$hostfile") or &abort("can't open $hostfile: $!");
		print HOST <<"EOD";
# hosts/$host
#ip	$ip
desc\tnew unix host
group\t$group
tools\tping traceroute telnet availability status
rrd\tping
EOD
	}

# Open the connection to the host
	($socket, $status, $main::timeout) = &open_socket( $host, $main::port, $main::timeout);
	unless ($status == $main::SOCKET_OK) { &abort("couldn't connect to $host: $!"); }
	&debug("  connected to $host:$main::port") if ($main::debug);

# Send query
	($status, $main::timeout) = &write_socket( $socket, $query, 
		$main::timeout, "query for ${host}:$main::port");
	unless ($status == $main::SOCKET_OK) {
		$socket->close();
		&abort("can't send query: $!");
	}
	&debug("  sent query") if ($main::debug);

# Collect the response
	%rrds = ();
	while (($line, $status, $main::timeout) = 
			&read_socket($socket, $main::timeout, "response from $host"), 
			(defined $line and ($status == $main::SOCKET_OK))) {
		$line =~ tr/\012\015//d;
		&debug("  RAW: $line") if ($main::debug>1);
		foreach $pattern (keys %unix_rrds) {
			if ($line =~ /$pattern/i) {
				$instance = $1;
				if (defined $instance) {
					$rrd  = $unix_rrds{$pattern};
					$rrd =~ s/\\$1/$instance/;
				}
				else { $rrd = $unix_rrds{$pattern}; }
				if (defined $rrds{$rrd}) {
					&debug("  $rrd exists already; skipped") if ($main::debug);
					next;
				}
				$rrds{$rrd} = 1;
				print HOST "rrd\t $rrd\n";
				&debug("  added rrd $rrd") if ($main::debug);
			}
			if ($line =~ / os_name\s+(.*)/) { $os_name = $1; }
		}
	}

# Special cases
	if ($os_name eq 'Linux' and defined $rrds{'memory'}) {
		print HOST "nograph memory scanrate\n";
	}

	$socket->close() or &abort("can't close connection: $!");
	close(HOST);
}

# Touch config_dir for update time
my $now = time;
utime $now, $now, $main::config_dir or
	&abort("can't touch $main::config_dir for update time");

exit 0;

#----------------------------------------------------------------- usage ---
sub usage {
	print STDERR <<"EOD_USAGE";
$main::prog version $main::version
usage: $main::prog [options] group [hostfile ...]
where options are:
    -d      enable debugging output
    -f fff  use 'fff' for config-dir [$main::config_dir]
    -h     	show this help
    -p ppp  use port 'ppp' [$main::port]
    -t ttt  use 'ttt' for timeout [$main::timeout]
EOD_USAGE
	exit 0;
}

#----------------------------------------------------------------- debug ---
sub debug {
	my $msg = join('', @_);
	print STDERR "DEBUG: $msg\n";
}

#-------------------------------------------------------------- abort ---
sub abort {
	my $msg = join('', @_);
	print STDERR "ABORT: $msg\n";
	exit 1;
}

#----------------------------------------------- keep_strict_happy ---
sub keep_strict_happy {
}

#----------------------------------------------- error ---
sub error {
	my $msg = join('', @_);
	print STDERR "ERROR: $msg\n";
}
