#!/usr/local/sysmansw/runtime/perl/bin/perl -w

## -_- $Name: PerfGraph-2_4d $ % $Id: pgadmin,v 1.1.2.9 2001/09/05 18:30:09 sietse Exp $

use Pg;
use IO::Handle;

# Default database name is perfdb - changeable by defining the variable PERFDB
$PERFDB = $ENV{"PERFDB"};
$PERFDB = "perfdb" if not defined($PERFDB);

# Default directory name is ~perfgr - changeable by defining the variable PGDIR
$PGDIR = $ENV{'PGDIR'};
$PGDIR = $ENV{'HOME'} . "/perfgraph" if not defined($PGDIR);

# Default directory for pgsql
$PGSQLDIR = $ENV{"PGSQLDIR"};
$PGSQLDIR = "/usr/local/sysmansw/runtime/pgsql/bin" if not defined($PGSQLDIR);

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

sub doq($$$)
{
    my ($db, $q, $expected) = @_;
    my $r;

    $r = $db->exec($q);
    return $r if $r->resultStatus == $expected;

    print "Error executing query -->" . $q . "<-- : " . $db->errorMessage;
    return 0;
}

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

sub logmsg
{
    my $msg = shift @_;
    my $tm;

    chomp($tm = localtime(time));
    print "$tm: ". $msg;
}

sub logdie
{
    my $msg = shift @_;
    my $tm;

    chomp($tm = localtime(time));
    die "$tm: ". $msg;
}

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

sub signal_pgstart
{
    # Have perfgraphd re-read the configuration

    chomp($thissystem = `uname`);
    if ($thissystem eq "SunOS" || $thissystem eq "HP-UX")
    {
        $pid = `ps -ef|grep $PGDIR/pgstart|grep -v grep`;
        if ($pid ne "")
        {
            @pid = split(' ', $pid);
            $pid = $pid[1];
        }
    } elsif ($thissystem eq "Linux")
    {
        $pid = `ps ax|grep $PGDIR/pgstart|grep -v grep`;
        if ($pid ne "")
        {
            @pid = split(' ', $pid);
            $pid = $pid[0];
        }
    } else
    {
        print "pgstart not restarted -- this is a unknown system type\n";
    }

    if ($pid eq "")
    {
        print "PerfGraphd is not running, use pgstart for startup of PerfGraph\n";
    }
    else
    {
        print "Signaling pgstart\n";
        kill 1, $pid;
    }
}

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

sub newsys($$$)
{
    my($newsys, $systype, $nickname) = @_;
    
    $q = "select hostname from systems where hostname = '$newsys'";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
    if ($result->ntuples > 0)
    {
        print "The system already exists\n";
        return;
    }
    
    $q = "select supptype from supp_systypes where supptype = '$systype'";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
    if ($result->ntuples != 1)
    {
        print "The system type is non-existent\n";
        return;
    }
    
    ########################################################################
    # Create the database and tables etc.
    #
    die "Stopping" unless $result = doq($perfdb, "create database " . $newsys, PGRES_COMMAND_OK);
    
    $newdb = Pg::connectdb("dbname = " . $newsys);
    if ($newdb->status == PGRES_CONNECTION_BAD)
    {
        die "Cannot open database connection: " . $newdb->errorMessage;
    }
    
    $q = "select tablename,datatype,multiple from tables where systype = '" .  $systype . "'";
    die "Stopping" unless $tables = doq($perfdb, $q, PGRES_TUPLES_OK);
    
    ##########################################################################
    # Create the tables.
    #
    # For every table mentioned in the perfdb, create the mentioned table and
    # tables for the day, week, month and year views.
    # In case of a table containing multiples, also create a _mult table,
    # containing all currently measured  multiples (currently, multiple tables
    # are only for disks and net devices because there are more than
    # one of each of them).
    #
    # Also, create indexes for the tables.
    #
    foreach $tbl (0 .. $tables->ntuples - 1)
    {
        $fields = $perfdb->exec("select * from fields " .
                                "where fieldtable = '" .
                                $tables->getvalue($tbl, 0) . "' " .
                                "order by fieldseq");
        if ($fields->resultStatus != PGRES_TUPLES_OK)
        {
            die "Cannot determine fields: " . $perfdb->errorMessage;
        }
    
        foreach $suffix ("", "_d", "_w", "_m", "_y")
        {
            $type = $fields->getvalue(0, 3);
            if ($type eq "i") { $type = "int"; }
            elsif ($type eq "c") { $type = "varchar"; }
            elsif ($type eq "f") { $type = "float4"; }
            $q = "create table " . $tables->getvalue($tbl, 0) . $suffix . 
                 "(" . $fields->getvalue(0, 2) . " " . $type;
            foreach $fld (1 .. $fields->ntuples - 1)
            {
                $type = $fields->getvalue($fld, 3);
                if ($type eq "i") { $type = "int"; }
                elsif ($type eq "c") { $type = "varchar"; }
                elsif ($type eq "f") { $type = "float4"; }
                $q .= ", " . $fields->getvalue($fld, 2) . " " . $type;
            }
            $q .= ")";
            die "Stopping" unless $result = doq($newdb, $q, PGRES_COMMAND_OK);
    
            $q = "create index " . $tables->getvalue($tbl, 0) .
                 $suffix . "_idx " .
                 "on " . $tables->getvalue($tbl, 0) . $suffix . "(tstamp)";
            die "Stopping" unless $result = doq($newdb, $q, PGRES_COMMAND_OK);
        }
    
        if ($tables->getvalue($tbl, 1) eq "c")
        {
            # cumulative table; we need a _last table
            $type = $fields->getvalue(0, 3);
            if ($type eq "i") { $type = "int"; }
            elsif ($type eq "c") { $type = "varchar"; }
            elsif ($type eq "f") { $type = "float4"; }
            $q = "create table " . $tables->getvalue($tbl, 0) . "_last" . 
                 "(" . $fields->getvalue(0, 2) . " " . $type;
            foreach $fld (1 .. $fields->ntuples - 1)
            {
                $type = $fields->getvalue($fld, 3);
                if ($type eq "i") { $type = "int"; }
                elsif ($type eq "c") { $type = "varchar"; }
                elsif ($type eq "f") { $type = "float4"; }
                $q .= ", " . $fields->getvalue($fld, 2) . " " . $type;
            }
            $q .= ")";
            die "Stopping" unless $result = doq($newdb, $q, PGRES_COMMAND_OK);
        }
    
        if ($tables->getvalue($tbl, 2) eq "m")
        {
            # multiple table; we need a _mult table
            $type = $fields->getvalue(1, 3);
            if ($type eq "i") { $type = "int"; }
            elsif ($type eq "c") { $type = "varchar"; }
            elsif ($type eq "f") { $type = "float4"; }
            $q = "create table " . $tables->getvalue($tbl, 0) . "_mult" . 
                 "(" . $fields->getvalue(1, 2) . " " . $type;
            $q .= ")";
            die "Stopping" unless $result = doq($newdb, $q, PGRES_COMMAND_OK);
        }
    }
    
    ########################################################################
    # Create the timestamp table, and fill it with 0's.
    #
    $q = "create table tstamps (max_h int, max_d int, max_w int, max_m int, " .
                               "max_y int, max_sar int, first_entry int)";
    die "Stopping" unless $result = doq($newdb, $q, PGRES_COMMAND_OK);
    
    $q = "insert into tstamps values (0, 0, 0, 0, 0, 0, 0)";
    die "Stopping" unless $result = doq($newdb, $q, PGRES_COMMAND_OK);
    
    ###########################################################################
    # Create the deldays and fill it with default values.
    # The tables contain the number of days after which data can be removed from
    # the database, and at what time this should happen.
    #
    $q = "create table deldays (hour int, day int, week int, " .
         "mon int, year int)";
    die "Stopping" unless $result = doq($newdb, $q, PGRES_COMMAND_OK);
    
    $q = "insert into deldays values (10, 35, 65, 370, 1830)";
    die "Stopping" unless $result = doq($newdb, $q, PGRES_COMMAND_OK);
    
    ###########################################################################
    # Create the table whith the user fieldnames
    #
    $q = "create table userfldnames(fieldname varchar, fieldshdesc varchar)";
    die "Stopping" unless $result = doq($newdb, $q, PGRES_COMMAND_OK);
    $newdb->exec("insert into userfldnames values('user01', 'user01')");
    $newdb->exec("insert into userfldnames values('user02', 'user02')");
    $newdb->exec("insert into userfldnames values('user03', 'user03')");
    $newdb->exec("insert into userfldnames values('user04', 'user04')");
    $newdb->exec("insert into userfldnames values('user05', 'user05')");
    $newdb->exec("insert into userfldnames values('user06', 'user06')");
    $newdb->exec("insert into userfldnames values('user07', 'user07')");
    $newdb->exec("insert into userfldnames values('user08', 'user08')");
    $newdb->exec("insert into userfldnames values('user09', 'user09')");
    $newdb->exec("insert into userfldnames values('user10', 'user10')");
    $newdb->exec("insert into userfldnames values('user11', 'user11')");
    $newdb->exec("insert into userfldnames values('user12', 'user12')");
    $newdb->exec("insert into userfldnames values('user13', 'user13')");
    $newdb->exec("insert into userfldnames values('user14', 'user14')");
    $newdb->exec("insert into userfldnames values('user15', 'user15')");
    $newdb->exec("insert into userfldnames values('user16', 'user16')");
    
    ###########################################################################
    # Create the table with database meta-info
    #
    $q = "create table dbinfo(version varchar, systype varchar, nickname varchar, gathering char)";
    die "Stopping" unless $result = doq($newdb, $q, PGRES_COMMAND_OK);

    $q = "insert into dbinfo values ('$ver', '$systype', '$newsys', 'n')";
    die "Stopping" unless $result = doq($newdb, $q, PGRES_COMMAND_OK);

    ###########################################################################
    # Add into systems table in perfdb
    #
    $q = "insert into systems values ('" . $newsys . "', '" .  $nickname . "', '" . $systype . "', 'n')";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_COMMAND_OK);
}

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

sub rmsys($)
{
    my($sys) = @_;

    $result = $perfdb->exec("select hostname from systems " .
                            "where hostname = '" . $sys . "'");
    if ($result->ntuples == 0)
    {
        die "The system does not exist\n";
    }


    $result = $perfdb->exec("delete from systems where hostname = '" .
              $sys . "'");
    if ($result->resultStatus != PGRES_COMMAND_OK)
    {
        die "Cannot remove system " . $sys . ": " . $perfdb->errorMessage;
    }
    
    $result = $perfdb->exec("drop database " . $sys);
    if ($result->resultStatus != PGRES_COMMAND_OK)
    {
        die "Cannot remove database for system " . $sys . ": " .
            $perfdb->errorMessage;
    }
}

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

sub StartClient
{
    my ($result, $i, $q, $newsys, $systype, $start, $nickname);

    $q = "select hostname,gathering,nickname from systems";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
    if ($result->ntuples > 0)
    {
        print "Current clients:\n";
        print "================\n";
        printf "%-15s %-30s %s\n", "hostname", "nickname", "status";
        print "-" x 75 . "\n";
        foreach $i (0 .. $result->ntuples - 1)
        {
            printf "%-15s ", $result->getvalue($i, 0);
            printf "%-30s ", $result->getvalue($i, 2);
            print "gathering using rsh\n" if $result->getvalue($i, 1) eq "r";
            print "gathering using sysmanswd\n" if $result->getvalue($i, 1) eq "d";
            print "NOT gathering\n" if $result->getvalue($i, 1) eq "n";
        }
    } else
    {
        print "No clients defined yet.\n";
    }
    print "\nName of the client to start (press return to go back): ";
    chomp($newsys = <STDIN>);
    return if $newsys eq "";

    print "Nickname of the client to start [default $newsys]: ";
    chomp($nickname = <STDIN>);
    $nickname = $newsys if $nickname =~ /^$/;

    $q = "select hostname,gathering,systype from systems where hostname='$newsys'";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);

    if ($result->ntuples != 1)
    {
        # Check number of connections
        $q = "select count(*)from systems";
        die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
        if ($result->getvalue(0,0) == 9)
        {
            print "NOTICE: You are about to define a 10th client.\n";
            print "        By default, the Postgres database is configured for\n";
            print "        only a few database connections. Please refer to the documentation\n";
            print "        on how to increase the number of connections!\n";
            print "\n";
            print "[Press return to continue] ";
            <STDIN>;
        }

        $q = "select supptype from supp_systypes";
        die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
        do
        {
            print "Supported system types:\n";
            foreach $i (0 .. $result->ntuples - 1)
            {
                print ("    " . ($i + 1) . ". " . $result->getvalue($i, 0) . "\n") if $result->getvalue($i, 0) ne 'NT4';
                print ("    " . ($i + 1) . ". NT4/W2K\n") if $result->getvalue($i, 0) eq 'NT4';
            }
            print "Select system type number (press return to go back): ";
            chomp($systype = <STDIN>);

            return if $systype eq "";

            if ($systype !~ /\d/ && $systype > $result->ntuples)
            {
                print "Illegal input, give a number\n";
            }
        } while ($systype !~ /\d/ && $systype > $result->ntuples);

        $systype = $result->getvalue($systype - 1, 0);
        newsys($newsys, $systype, $nickname);
    }
    else
    {
        if ($result->getvalue(0, 1) ne "n")
        {
            print "System already running\n";
            return;
        }
        $systype = $result->getvalue(0, 2);
    }

    # Assume no gathering
    $q = "update systems set gathering='n' where hostname='$newsys'";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_COMMAND_OK);

    print "Start gathering for $newsys?\n";
    if ($systype eq "NT4")
    {
        print "  1. Yes, use sysmanswd.\n";
        print "  2. No.\n";
        $start = "";
        while ($start !~ /^[12]$/)
        {
            print "Select a number [12]: ";
            chomp($start = <STDIN>);
        }
        $start++;
    }
    else
    {
        print "  1. Yes, use rsh.\n";
        print "  2. Yes, use sysmanswd.\n";
        print "  3. No.\n";
        $start = "";
        while ($start !~ /^[123]$/)
        {
            print "Select a number [123]: ";
            chomp($start = <STDIN>);
        }
    }

    $q = "update systems set gathering='r' where hostname='$newsys'" if $start == 1;
    $q = "update systems set gathering='d' where hostname='$newsys'" if $start == 2;
    $q = "update systems set gathering='n' where hostname='$newsys'" if $start == 3;
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_COMMAND_OK);

    signal_pgstart;
}

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

sub StopClient
{
    my ($result, $i, $q, $rmsys, $rm);

    $q = "select hostname,gathering,nickname from systems";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
    if ($result->ntuples > 0)
    {
        print "Current clients:\n";
        print "================\n";
        printf "%-15s %-30s %s\n", "hostname", "nickname", "status";
        print "-" x 75 . "\n";
        foreach $i (0 .. $result->ntuples - 1)
        {
            printf "%-15s ", $result->getvalue($i, 0);
            printf "%-30s ", $result->getvalue($i, 2);
            print "gathering using rsh\n" if $result->getvalue($i, 1) eq "r";
            print "gathering using sysmanswd\n" if $result->getvalue($i, 1) eq "d";
            print "NOT gathering\n" if $result->getvalue($i, 1) eq "n";
        }
    } else
    {
        print "No clients defined yet.\n";
        return;
    }
    print "Name of the client to stop (press return to go back): ";
    chomp($rmsys = <STDIN>);

    return if $rmsys eq "";

    $q = "select hostname,gathering from systems where hostname='$rmsys'";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);

    if ($result->ntuples != 1)
    {
        print "Client does not exist\n";
        return;
    }
    if ($result->getvalue(0, 1) eq "n")
    {
        print "Client is already stopped\n";
    }
    else
    {
        $q = "update systems set gathering='n' where hostname='$rmsys'";
        die "Stopping" unless $result = doq($perfdb, $q, PGRES_COMMAND_OK);

        signal_pgstart;
    }

    print "Do you want to remove all data for $rmsys? [yn] ";
    chomp($rm = <STDIN>);
    if ($rm =~ /^[yY]/)
    {
        rmsys($rmsys);
        signal_pgstart;
    }
}

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

sub AddDisk
{
    my ($result, $i, $q, $client, $disk, $table, $conn);

    $q = "select hostname from systems";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
    if ($result->ntuples > 0)
    {
        print "Current clients:\n";
        foreach $i (0 .. $result->ntuples - 1)
        {
            print "    " . $result->getvalue($i, 0) . "\n";
        }
    } else
    {
        print "No clients defined yet.\n";
        return;
    }

    print "Name of the client to add disks to (press return to go back): ";
    chomp($client = <STDIN>);

    $q = "select hostname,systype from systems where hostname = '" . $client . "'";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
    if ($result->ntuples <= 0)
    {
        print "Non-existent client\n";
        return;
    }

    if ($result->getvalue(0, 1) eq "linux2_0" ||
        $result->getvalue(0, 1) eq "linux2_2")
    {
        print "\nPossible disks are hda, hdb, hdc and hdd.\n";
        $table = "proc_disk";
    }
    if ($result->getvalue(0, 1) eq "solaris")
    {
        print "\nDisk names must be entered as reported by sar -d.\n";
        $table = "sar_disk";
    }
    if ($result->getvalue(0, 1) eq "aix")
    {
        print "\nDisk names must be entered as reported by iostat.\n";
        $table = "iostat";
    }
    if ($result->getvalue(0, 1) eq "hpux")
    {
        print "\nDisk names must be entered as reported by sar.\n";
        $table = "sar_diskux";
    }
    if ($result->getvalue(0, 1) eq "NT4")
    {
        my $dsk;

        print "\nRun 'sysmanswd.exe -disks' on " .
              $result->getvalue(0, 0) . " to find available disks\n\n";
        print "  1. Add a physical disk (0, 1, ...)\n";
        print "  2. Add a logical disk (C:, D:, ...)\n";
        $dsk = "";
        while ($dsk !~ /^[12]$/)
        {
            print "Select a number [12]: ";
            chomp($dsk = <STDIN>);
        }
        $table = "NTphysdisk" if $dsk eq "1";
        $table = "NTlogdisk" if $dsk eq "2";
    }


    $conn = Pg::connectdb("dbname = " . $result->getvalue(0, 0));
    if ($conn->status == PGRES_CONNECTION_BAD)
    {
        die "Cannot open database connection: " . $conn->errorMessage;
    }

    do
    {
        $q = "select * from " . $table . "_mult";
        die "Stopping" unless $result = doq($conn, $q, PGRES_TUPLES_OK);
        if ($result->ntuples > 0)
        {
            print "Current disks:\n";
            foreach $i (0 .. $result->ntuples - 1)
            {
                print "    " . $result->getvalue($i, 0) . "\n";
            }
        } else
        {
            print "No disks defined yet.\n";
        }

        if ($result->ntuples >= 16)
        {
            print "Maximum number of disks reached, press return to continue ";
            <STDIN>;
            return;
        }

        print "Name of the disk to add (press return to go back): ";
        chomp($disk = <STDIN>);

        return if $disk eq "";

        $q = "insert into " . $table . "_mult values('" . $disk . "')";
        die "Stopping" unless $result = doq($conn, $q, PGRES_COMMAND_OK);
    } while (1);
}

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

sub RmDisk
{
    my ($result, $i, $q, $client, $disk, $table, $conn);

    $q = "select hostname from systems";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
    if ($result->ntuples > 0)
    {
        print "Current clients:\n";
        foreach $i (0 .. $result->ntuples - 1)
        {
            print "    " . $result->getvalue($i, 0) . "\n";
        }
    } else
    {
        print "No clients defined yet.\n";
        return;
    }

    print "Name of the client to remove disks from (press return to go back): ";
    chomp($client = <STDIN>);

    $q = "select hostname,systype from systems where hostname = '" . $client . "'";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
    if ($result->ntuples <= 0)
    {
        print "Non-existent client\n";
        return;
    }

    $table = "proc_disk" if $result->getvalue(0, 1) eq "linux2_0";
    $table = "proc_disk" if $result->getvalue(0, 1) eq "linux2_2";
    $table = "sar_disk" if $result->getvalue(0, 1) eq "solaris";
    $table = "iostat" if $result->getvalue(0, 1) eq "aix";
    $table = "sar_diskux" if $result->getvalue(0, 1) eq "hpux";
    if ($result->getvalue(0, 1) eq "NT4")
    {
        my $dsk;

        print "  1. Remove a physical disk (0, 1, ...)\n";
        print "  2. Remove a logical disk (C:, D:, ...)\n";
        $dsk = "";
        while ($dsk !~ /^[12]$/)
        {
            print "Select a number [12]: ";
            chomp($dsk = <STDIN>);
        }
        $table = "NTphysdisk" if $dsk eq "1";
        $table = "NTlogdisk" if $dsk eq "2";
    }

    $conn = Pg::connectdb("dbname = " . $result->getvalue(0, 0));
    if ($conn->status == PGRES_CONNECTION_BAD)
    {
        die "Cannot open database connection: " . $conn->errorMessage;
    }

    do
    {
        $q = "select * from " . $table . "_mult";
        die "Stopping" unless $result = doq($conn, $q, PGRES_TUPLES_OK);
        if ($result->ntuples > 0)
        {
            print "Current disks:\n";
            foreach $i (0 .. $result->ntuples - 1)
            {
                print "    " . $result->getvalue($i, 0) . "\n";
            }
        } else
        {
            print "No disks defined yet.\n";
            return;
        }

        print "Name of the disk to remove (press return to go back): ";
        chomp($disk = <STDIN>);

        return if $disk eq "";

        $q = "delete from " . $table . "_mult where disk = '" . $disk . "'";
        die "Stopping" unless $result = doq($conn, $q, PGRES_COMMAND_OK);
    } while (1);
}

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

sub AddNetwork
{
    my ($result, $i, $q, $client, $network, $table, $conn);

    $q = "select hostname from systems";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
    if ($result->ntuples > 0)
    {
        print "Current clients:\n";
        foreach $i (0 .. $result->ntuples - 1)
        {
            print "    " . $result->getvalue($i, 0) . "\n";
        }
    } else
    {
        print "No clients defined yet.\n";
        return;
    }

    print "Name of the client to add net devices to (press return to go back): ";
    chomp($client = <STDIN>);

    $q = "select hostname,systype from systems where hostname = '" . $client . "'";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
    if ($result->ntuples <= 0)
    {
        print "Non-existent client\n";
        return;
    }

    if ($result->getvalue(0, 1) eq "NT4")
    {
        print "\nNetwork devices are not available for NT4/W2K\n";
        return;
    }

    print "\nNetwork device names must be entered as reported by netstat -in\n" .
          "(without a possible trailing *).\n";
    $table = "proc_net" if $result->getvalue(0, 1) eq "linux2_0";
    $table = "proc_net2" if $result->getvalue(0, 1) eq "linux2_2";
    $table = "netstat" if $result->getvalue(0, 1) eq "solaris";
    $table = "netstataix" if $result->getvalue(0, 1) eq "aix";
    $table = "netstatux" if $result->getvalue(0, 1) eq "hpux";

    $conn = Pg::connectdb("dbname = " . $result->getvalue(0, 0));
    if ($conn->status == PGRES_CONNECTION_BAD)
    {
        die "Cannot open database connection: " . $conn->errorMessage;
    }

    do
    {
        $q = "select * from " . $table . "_mult";
        die "Stopping" unless $result = doq($conn, $q, PGRES_TUPLES_OK);
        if ($result->ntuples > 0)
        {
            print "Current net devices:\n";
            foreach $i (0 .. $result->ntuples - 1)
            {
                print "    " . $result->getvalue($i, 0) . "\n";
            }
        } else
        {
            print "No net devices defined yet.\n";
        }

        if ($result->ntuples >= 16)
        {
            print "Maximum number of net devices reached, press return to continue ";
            <STDIN>;
            return;
        }

        print "Name of the net device to add (press return to go back): ";
        chomp($network = <STDIN>);

        return if $network eq "";

        $q = "insert into " . $table . "_mult values('" . $network . "')";
        die "Stopping" unless $result = doq($conn, $q, PGRES_COMMAND_OK);
    } while (1);
}

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

sub RmNetwork
{
    my ($result, $i, $q, $client, $network, $table, $conn);

    $q = "select hostname from systems";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
    if ($result->ntuples > 0)
    {
        print "Current clients:\n";
        foreach $i (0 .. $result->ntuples - 1)
        {
            print "    " . $result->getvalue($i, 0) . "\n";
        }
    } else
    {
        print "No clients defined yet.\n";
        return;
    }

    print "Name of the client to remove net devices from (press return to go back): ";
    chomp($client = <STDIN>);

    $q = "select hostname,systype from systems where hostname = '" . $client . "'";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
    if ($result->ntuples <= 0)
    {
        print "Non-existent client\n";
        return;
    }

    if ($result->getvalue(0, 1) eq "NT4")
    {
        print "\nNetwork devices are not available for NT4/W2K\n";
        return;
    }

    $table = "proc_net" if $result->getvalue(0, 1) eq "linux2_0";
    $table = "proc_net2" if $result->getvalue(0, 1) eq "linux2_2";
    $table = "netstat" if $result->getvalue(0, 1) eq "solaris";
    $table = "netstataix" if $result->getvalue(0, 1) eq "aix";
    $table = "netstatux" if $result->getvalue(0, 1) eq "hpux";

    $conn = Pg::connectdb("dbname = " . $result->getvalue(0, 0));
    if ($conn->status == PGRES_CONNECTION_BAD)
    {
        die "Cannot open database connection: " . $conn->errorMessage;
    }

    do
    {
        $q = "select * from " . $table . "_mult";
        die "Stopping" unless $result = doq($conn, $q, PGRES_TUPLES_OK);
        if ($result->ntuples > 0)
        {
            print "Current net devices:\n";
            foreach $i (0 .. $result->ntuples - 1)
            {
                print "    " . $result->getvalue($i, 0) . "\n";
            }
        } else
        {
            print "No net devices defined yet.\n";
            return;
        }

        print "Name of the net device to remove (press return to go back): ";
        chomp($network = <STDIN>);

        return if $network eq "";

        $q = "delete from " . $table . "_mult where iface = '" . $network . "'";
        die "Stopping" unless $result = doq($conn, $q, PGRES_COMMAND_OK);
    } while (1);
}

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

sub mklic
{
    my ($ret, $lic);

    print "Enter license number: ";
    chomp($lic = <STDIN>);
    $ret = system("$PGDIR/pgstart -s $lic");
    exit if $ret != 0;
}

sub chklic
{
    my $ret;

    $ret = system("$PGDIR/pgstart -c");
    exit if $ret == 1;  # Problems with IP address
    mklic if $ret != 0; # Ask for new license
}

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

sub ChangeClean
{
    my ($result, $i, $q, $client, $view, $table, $conn);

    $q = "select hostname from systems";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
    if ($result->ntuples > 0)
    {
        print "Current clients:\n";
        foreach $i (0 .. $result->ntuples - 1)
        {
            print "    " . $result->getvalue($i, 0) . "\n";
        }
    } else
    {
        print "No clients defined yet.\n";
        return;
    }

    print "Name of the client to change the cleanup for (press return to go back): ";
    chomp($client = <STDIN>);

    $q = "select hostname from systems where hostname = '" . $client . "'";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
    if ($result->ntuples <= 0)
    {
        print "Non-existent client\n";
        return;
    }

    $conn = Pg::connectdb("dbname = " . $result->getvalue(0, 0));
    if ($conn->status == PGRES_CONNECTION_BAD)
    {
        die "Cannot open database connection: " . $conn->errorMessage;
    }

    print "\n";
    print "NOTE: For every view, specify how many days to keep the data before deletion\n";
    print "\n";

    do
    {
        $q = "select * from deldays";
        die "Stopping" unless $result = doq($conn, $q, PGRES_TUPLES_OK);
        $i = 0;
        foreach $view ("hour ", "day  ", "week ", "month", "year ")
        {
            print $i + 1 . ".  " . $view . " view: " . $result->getvalue(0, $i) . "\n";
            $i++;
        }

        print "Change cleanup (press return to go back): ";
        chomp($view = <STDIN>);

        return if $view eq "";

        undef $q;
        $q = "update deldays set hour = " if $view eq "1";
        $q = "update deldays set day  = " if $view eq "2";
        $q = "update deldays set week = " if $view eq "3";
        $q = "update deldays set mon  = " if $view eq "4";
        $q = "update deldays set year = " if $view eq "5";

        return if $i eq "";

        if (defined($q))
        {
            print "New number of days (press return to go back): ";
            chomp($i = <STDIN>);
            if ($i =~ /\d+/)
            {
                $q .= $i;
                die "Stopping" unless $result = doq($conn, $q, PGRES_COMMAND_OK);
            } else
            {
                print "Illegal input, give a numeric value\n";
            }
        } else
        {
            print "Invalid choice\n";
        }
    } while (1);
}

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

sub ChUserFields()
{
    my ($result, $i, $q, $client, $table, $conn);

    $q = "select hostname from systems";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
    if ($result->ntuples > 0)
    {
        print "Current clients:\n";
        foreach $i (0 .. $result->ntuples - 1)
        {
            print "    " . $result->getvalue($i, 0) . "\n";
        }
    } else
    {
        print "No clients defined yet.\n";
        return;
    }

    print "Name of the client to change the user fields for (press return to go back): ";
    chomp($client = <STDIN>);

    $q = "select hostname,systype from systems where hostname = '" . $client . "'";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
    if ($result->ntuples <= 0)
    {
        print "Non-existent client\n";
        return;
    }

    if ($result->getvalue(0, 1) eq "NT4")
    {
        print "\nUser defined fields are not available for NT4/W2K\n";
        return;
    }

    $conn = Pg::connectdb("dbname = " . $result->getvalue(0, 0));
    if ($conn->status == PGRES_CONNECTION_BAD)
    {
        die "Cannot open database connection: " . $conn->errorMessage;
    }

    do
    {
        $q = "select * from userfldnames order by fieldname";
        die "Stopping" unless $result = doq($conn, $q, PGRES_TUPLES_OK);

        print "Current settings for user defineable fields:\n";
        foreach $i (0 .. $result->ntuples - 1)
        {
            print "Field " . sprintf("%02d", $i + 1) . ": " . $result->getvalue($i, 1) . "\n";
        }

        print "Change which field (press return to go back): ";
        chomp($i = <STDIN>);

        return if $i eq "";

        if ($i =~ /\d/ && $i > 0 && $i <= $result->ntuples)
        {
            print "New field name (return to go back): ";
            chomp($fld = <STDIN>);

            if ($fld ne "")
            {
                $q = "update userfldnames set fieldshdesc = '" . $fld . "'" . 
                     " where fieldname = 'user" . sprintf("%02d", $i) . "'";
                die "Stopping" unless $result = doq($conn, $q, PGRES_COMMAND_OK);
            }
        }
    } while (1);
}

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

sub ChangeNick
{
    my ($result, $i, $q, $sys, $nickname);

    $q = "select hostname,gathering,nickname from systems";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
    if ($result->ntuples > 0)
    {
        print "Current clients:\n";
        print "================\n";
        printf "%-15s %-30s %s\n", "hostname", "nickname", "status";
        print "-" x 75 . "\n";
        foreach $i (0 .. $result->ntuples - 1)
        {
            printf "%-15s ", $result->getvalue($i, 0);
            printf "%-30s ", $result->getvalue($i, 2);
            print "gathering using rsh\n" if $result->getvalue($i, 1) eq "r";
            print "gathering using sysmanswd\n" if $result->getvalue($i, 1) eq "d";
            print "NOT gathering\n" if $result->getvalue($i, 1) eq "n";
        }
    } else
    {
        print "No clients defined yet.\n";
        return;
    }
    print "\nHostname to change the nickname for (Press return to go back): ";
    chomp($sys = <STDIN>);
    return if $sys eq "";

    $q = "select hostname from systems where hostname='$sys'";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);

    if ($result->ntuples != 1)
    {
        print "Non-existent client\n";
        return;
    }

    print "New nickname [default $sys]: ";
    chomp($nickname = <STDIN>);
    $nickname = $sys if $nickname =~ /^$/;

    $q = "update systems set nickname='$nickname' where hostname='$sys'";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_COMMAND_OK);

    signal_pgstart;
}

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

sub check_upgrade()
{
    my ($q, $result);

    $q = "select * from perfdb_ver";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);

    $ver = $result->getvalue(0, 0);

    if ($ver ne "2.4")
    {
        # Upgrade
        system("$PGDIR/mk_perfdb");
    }
}

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

sub vacuum($)
{
    my $sys = shift @_;
    my ($conn, $q, $result, $systype);
    my ($now, $tstamp, $deldays, $tables, $sf, $table);
    my $tm;


    logmsg "perfvacuum started for $sys\n";

    $conn = Pg::connectdb("dbname = " . $sys);
    if ($conn->status == PGRES_CONNECTION_BAD)
    {
        logmsg "(getconfig) Cannot open database connection: " . $conn->errorMessage;
        return;
    }

    $q = "select systype from systems where hostname = '" . $sys . "'";
    $result = doq($perfdb, $q, PGRES_TUPLES_OK) || logdie "(getconfig) Stopping\n";
    $systype = $result->getvalue(0, 0);

    # Let's start!
    $now = time;

    $q = "select * from deldays";
    $deldays = doq($conn, $q, PGRES_TUPLES_OK) || do {logmsg "(cleanup) Stopping\n"; return;};

    $q = "select tablename from tables where systype = '" . $systype . "'";
    $tables = doq($perfdb, $q, PGRES_TUPLES_OK) || do {logmsg "(cleanup) Stopping\n"; return;};

    foreach my $sf ("", "_d", "_w", "_m", "_y")
    {
        $tstamp = $now - $deldays->getvalue(0, 0) * 24 * 3600 if $sf eq   "";
        $tstamp = $now - $deldays->getvalue(0, 1) * 24 * 3600 if $sf eq "_d";
        $tstamp = $now - $deldays->getvalue(0, 2) * 24 * 3600 if $sf eq "_w";
        $tstamp = $now - $deldays->getvalue(0, 3) * 24 * 3600 if $sf eq "_m";
        $tstamp = $now - $deldays->getvalue(0, 4) * 24 * 3600 if $sf eq "_y";

        foreach my $table (0 .. $tables->ntuples - 1)
        {
            $q = "drop index " . $tables->getvalue($table, 0) . $sf . "_idx";
            $result = doq($conn, $q, PGRES_COMMAND_OK);
            $q = "create index " . $tables->getvalue($table, 0) . $sf . "_idx on " .
                                   $tables->getvalue($table, 0) . $sf . "(tstamp)";
            $result = doq($conn, $q, PGRES_COMMAND_OK);
            $q = "delete from " . $tables->getvalue($table, 0) . $sf . " where tstamp < " . $tstamp;
            $result = doq($conn, $q, PGRES_COMMAND_OK) || do {logmsg "(cleanup) Stopping\n"; return;};
            $q = "vacuum analyze " . $tables->getvalue($table, 0) . $sf;
            $result = doq($conn, $q, PGRES_COMMAND_OK) || do {logmsg "(cleanup) Stopping\n"; return;};
        }
    }
    $q = "vacuum analyze";
    $result = doq($conn, $q, PGRES_COMMAND_OK) || do {logmsg "(cleanup) Stopping\n"; return;};
    logmsg "perfvacuum ended for $sys\n";
}

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

sub usage()
{
    print "\n";
    print "Usage: $0 [options]\n";
    print "       without options starts the interactive configuration tool.\n";
    print "       Possible options:\n";
    print "          -license <license key>\n";
    print "             Enter a license key.\n";
    print "          -backup { begin |  end }\n";
    print "             Begin or end online database backup.\n";
    print "             Use '-backup begin' before making an online backup of the database.\n";
    print "             Use '-backup end' when the backup is ready.\n";
    print "          -cleanup [ systems ]\n";
    print "             Cleans up the databases for the given systems. If no systems are\n";
    print "             given, databases for all systems that gather data are cleaned up.\n";
    print "          -dbdump [ systems ]\n";
    print "             Dump the databases for the given systems. If no systems are\n";
    print "             given, databases for all systems that gather data are dumped.\n";
    print "             Databases are dumped to the dbdumps directory of the perfgr user.\n";
    print "          -dbcleandump\n";
    print "             Clean up and dump the databases for the given systems. If no\n";
    print "             systems are given, databases for all systems that gather data are\n";
    print "             cleaned up and dumped. Databases are dumped to the dbdumps\n";
    print "             directory of the perfgr user.\n";
    print "             This option is recommended for daily cleanup and dumps.\n";
    print "          -dbrestore\n";
    print "             Restore the databases for the given systems. If no systems are\n";
    print "             given, all dumps found in the dump directory are restored.\n";
    print "             Databases are restored from the dbdumps directory of the perfgr\n";
    print "             user.\n";
    print "          -version\n";
    print "             Show versions of the databases and programs\n";
    print "\n";
    exit(1);
}

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

sub options
{
    my @args = @_;

    $opt_license = 0;
    $opt_start = 0;
    $opt_newsys = 0;
    $opt_rmsys = 0;
    $opt_backup_begin = 0;
    $opt_backup_end = 0;
    $opt_cleanup = 0; @cleanup_systems = ();
    $opt_dbdump = 0; @dbdump_systems = ();
    $opt_dbcldump = 0; @dbcldump_systems = ();
    $opt_dbrestore = 0; @dbrestore_systems = ();

    while (scalar(@args) > 0)
    {
        if ($args[0] eq "-s")
        {
            # Create a new system
            $opt_start = 1;
            shift @args;
            usage if (scalar(@args)) == 0;
            $newsys_name = shift @args;
            usage if (scalar(@args)) == 0;
            $newsys_type = shift @args;
            usage if (scalar(@args)) != 0;
            last;
        }
        if ($args[0] eq "-c")
        {
            # Create a new system
            $opt_newsys = 1;
            shift @args;
            usage if (scalar(@args)) == 0;
            $newsys_name = shift @args;
            usage if (scalar(@args)) == 0;
            $newsys_type = shift @args;
            usage if (scalar(@args)) != 0;
            last;
        }
        if ($args[0] eq "-r")
        {
            # Remove a system system
            $opt_rmsys = 1;
            shift @args;
            usage if (scalar(@args)) == 0;
            $rmsys = shift @args;
            usage if (scalar(@args)) != 0;
            last;
        }
        if ($args[0] eq "-license")
        {
            # Set a new license
            $opt_license = 1;
            shift @args;
            $license = shift @args;
            $license = "" if not $license;
            last;
        }
        if ($args[0] eq "-backup")
        {
            # Set system in/out backup mode
            shift @args;
            usage if (scalar(@args)) == 0;
            $opt_backup_begin = 1 if $args[0] eq "begin";
            $opt_backup_end = 1 if $args[0] eq "end";
            usage if (scalar(@args)) != 1 || ($opt_backup_begin == 0 && $opt_backup_end == 0);
            last;
        }
        if ($args[0] eq "-cleanup")
        {
            # Cleanup databases
            shift @args;
            $opt_cleanup = 1;
            while (scalar(@args) && substr($args[0], 0, 1) ne "-") { push @cleanup_systems, shift @args; }
            usage if scalar(@args) != 0;
            next;
        }
        if ($args[0] eq "-dbdump")
        {
            # Dump databases
            shift @args;
            $opt_dbdump = 1;
            while (scalar(@args) && substr($args[0], 0, 1) ne "-") { push @dbdump_systems, shift @args; }
            usage if scalar(@args) != 0;
            next;
        }
        if ($args[0] eq "-dbcleandump")
        {
            # Cleanup / dump databases
            shift @args;
            $opt_dbcldump = 1;
            while (scalar(@args) && substr($args[0], 0, 1) ne "-") { push @dbcldump_systems, shift @args; }
            usage if scalar(@args) != 0;
            next;
        }
        if ($args[0] eq "-dbrestore")
        {
            # Restore a previously dumped database
            shift @args;
            $opt_dbrestore = 1;
            while (scalar(@args) && substr($args[0], 0, 1) ne "-") { push @dbrestore_systems, shift @args; }
            usage if scalar(@args) != 0;
            last;
        }
        if ($args[0] eq "-version")
        {
            # Show versions
            shift @args;
            $opt_versions = 1;
            usage if scalar(@args) != 0;
            next;
        }

        # Unknown option
        usage;
    }
}

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

$ret = system("$PGSQLDIR/psql -q -d $PERFDB -c 'select * from perfdb_ver' > /dev/null 2>&1");

if ($ret != 0)
{
    # First time useage; create the perfdb
    print "You seem to be running perfconf for the first time.\n" .
          "The performance grapher main database will now be created...\n";
    system("$PGDIR/mk_perfdb");
}

#########################################################################
# Open perf database.
#
$perfdb = Pg::connectdb("dbname = $PERFDB");
if ($perfdb->status == PGRES_CONNECTION_BAD)
{
    die "Cannot open database connection: " . $perfdb->errorMessage;
}

#########################################################################
# Check command line options
#
options(@ARGV);

if ($opt_versions)
{
    my ($files, @files);

    $files=`find $PGDIR -type f -print`;
    @files = split(" ", $files);
    foreach my $file (@files)
    {
        open VERFILE, "<$file";
        while (<VERFILE>)
        {
            next if $_ !~ /^## -_- /;

            my @flds = split(/\s+/, $_);
            $file =~ s/$PGDIR\///;
            printf "%23s: %s  %s  %s  %s  %s  %s\n", $file, $flds[3], $flds[7], $flds[8],
                   $flds[9], $flds[10], $flds[11];
            last;
        }
    }
    exit(0);
}

if ($opt_license)
{
    my $ret = system("$PGDIR/pgstart -s $license") >> 8;
    exit $ret
}

$l=chklic;
check_upgrade();

if ($opt_start)
{
    newsys($newsys_name, $newsys_type, $newsys_name);
    $q = "update systems set gathering='d' where hostname='$newsys_name'";
    die "Stopping" unless $result = doq($perfdb, $q, PGRES_COMMAND_OK);
    signal_pgstart;

    exit 0;
}

do {newsys($newsys_name, $newsys_type, $newsys_name); exit 0;} if $opt_newsys;
do {rmsys($rmsys); exit 0;} if $opt_rmsys;

if ($opt_backup_begin)
{
    # begin backup
    print "Begin backup - please wait\n";
    system("touch $PGDIR/tmp/backup.lock");

    # wait until 15 secs past the next minute
    sleep (60 - time % 60 + 15);
    system("sync");
    print "Backup can begin now\n";
    exit(0);
}

if ($opt_backup_end)
{
    # end backup
    print "End backup\n";
    unlink "$PGDIR/tmp/backup.lock";
    exit(0);
}

if ($opt_cleanup || $opt_dbcldump)
{
    my $olddir = `pwd`;
    my @files;

    chdir "$PGDIR/logs";
    if (scalar(@cleanup_systems) == 0 && scalar(@dbcldump_systems) == 0)
    {
        @files = <*.log>;
    }
    else
    {
        foreach my $f (@cleanup_systems) { push @files, "$f.log"; }
        foreach my $f (@dbcldump_systems) { push @files, "$f.log"; }
    }
    foreach $f (@files)
    {
        rename "old_logs/$f.6", "old_logs/$f.7";
        rename "old_logs/$f.5", "old_logs/$f.6";
        rename "old_logs/$f.4", "old_logs/$f.5";
        rename "old_logs/$f.3", "old_logs/$f.4";
        rename "old_logs/$f.2", "old_logs/$f.3";
        rename "old_logs/$f.1", "old_logs/$f.2";
        system "cp $f            old_logs/$f.1";
        system "> $f";
    }
    chdir $olddir;

    if (scalar(@cleanup_systems) == 0 && $opt_cleanup)
    {
        my $q = "select hostname from systems where gathering != 'n'";
        my $result;

        die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
        foreach my $i (0 .. $result->ntuples - 1) { push @cleanup_systems, $result->getvalue($i, 0); }
    }
    foreach my $sys (@cleanup_systems) # will be non-empty if $opt_cleanup
    {
        open (STDIN, "</dev/null");
        open (STDOUT, ">>$PGDIR/logs/" . $sys . ".log");
        open (STDERR, ">&STDOUT");
        STDOUT->autoflush(1);
        STDERR->autoflush(1);
        logmsg "database cleanup initialized for $sys\n";
        if (open(LCK, ">$PGDIR/tmp/$sys.lock"))
        {
            print LCK "$$\n";
            close LCK;

            # Wait until 15 secs past the next minute
            sleep (60 - time % 60 + 15);

            vacuum($sys);
        }
        else
        {
            logmsg("Cannot create file $PGDIR/tmp/vacuum.$sys.lock");
            next;
        }

        unlink "$PGDIR/tmp/$sys.lock";
    }

    exit(0) if ! $opt_dbcldump;
}

if ($opt_dbdump)
{
    if (scalar(@dbdump_systems) == 0)
    {
        my $q = "select hostname from systems where gathering != 'n'";
        my $result;

        die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
        foreach my $i (0 .. $result->ntuples - 1) { push @dbdump_systems, $result->getvalue($i, 0); }
    }

    foreach my $sys (@dbdump_systems)
    {
        open (STDIN, "</dev/null");
        open (STDOUT, ">>$PGDIR/logs/$sys" . ".log");
        open (STDERR, ">&STDOUT");
        STDOUT->autoflush(1);
        STDERR->autoflush(1);
        logmsg "database dump initialized for $sys\n";

        my $conn = Pg::connectdb("dbname = " . $sys);
        $q = "select nickname, gathering from systems where hostname = '$sys'";
        die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);

        $q = "update dbinfo set nickname='" . $result->getvalue(0, 0) . "', gathering='" .
              $result->getvalue(0, 1) . "'";
        die "Stopping" unless $result = doq($conn, $q, PGRES_COMMAND_OK);
        undef $conn;

        if (open(LCK, ">$PGDIR/tmp/$sys.lock"))
        {
            print LCK "$$\n";
            close LCK;

            # Wait until 15 secs past the next minute
            sleep (60 - time % 60 + 15);

            logmsg "database dump started for $sys\n";
            system('PATH=$PATH:' . "$PGSQLDIR;export PATH; pg_dump $sys | compress > $PGDIR/dbdumps/$sys.dump.Z");
            logmsg "database dump ended for $sys\n";
        }
        else
        {
            logmsg("Cannot create file $PGDIR/tmp/$sys.lock");
            next;
        }

        unlink "$PGDIR/tmp/$sys.lock";
    }

    exit(0);
}

if ($opt_dbcldump)
{
    if (scalar(@dbcldump_systems) == 0)
    {
        my $q = "select hostname from systems where gathering != 'n'";
        my $result;

        die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
        foreach my $i (0 .. $result->ntuples - 1) { push @dbcldump_systems, $result->getvalue($i, 0); }
    }

    foreach my $sys (@dbcldump_systems)
    {
        open (STDIN, "</dev/null");
        open (STDOUT, ">>$PGDIR/logs/$sys" . ".log");
        open (STDIN, "</dev/null");
        open (STDOUT, ">>$PGDIR/logs/$sys" . ".log");
        open (STDERR, ">&STDOUT");
        STDOUT->autoflush(1);
        STDERR->autoflush(1);
        logmsg "database cleandump initialized for $sys\n";

        my $conn = Pg::connectdb("dbname = " . $sys);
        $q = "select nickname, gathering from systems where hostname = '$sys'";
        die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);

        $q = "update dbinfo set nickname='" . $result->getvalue(0, 0) . "', gathering='" .
              $result->getvalue(0, 1) . "'";
        die "Stopping" unless $result = doq($conn, $q, PGRES_COMMAND_OK);
        undef $conn;

        if (open(LCK, ">$PGDIR/tmp/$sys.lock"))
        {
            print LCK "$$\n";
            close LCK;

            # Wait until 15 secs past the next minute
            sleep (60 - time % 60 + 15);

            logmsg "database cleandump started for $sys\n";
            vacuum($sys);
            logmsg "database dump started for $sys\n";
            system('PATH=$PATH:' . "$PGSQLDIR;export PATH; pg_dump $sys | compress > $PGDIR/dbdumps/$sys.dump.Z");
            logmsg "database dump ended for $sys\n";
            logmsg "database cleandump ended for $sys\n";
        }
        else
        {
            logmsg("Cannot create file $PGDIR/tmp/$sys.lock");
            next;
        }

        unlink "$PGDIR/tmp/$sys.lock";
    }

    exit(0);
}

if ($opt_dbrestore)
{
    die "No systems given to restore\n" if scalar(@dbrestore_systems) == 0;
    foreach my $sys (@dbrestore_systems)
    {
        my $q = "select hostname from systems where hostname = '$sys'";
        my ($result, $nick, $typ, $gather);

        die "Stopping" unless $result = doq($perfdb, $q, PGRES_TUPLES_OK);
        if ($result->ntuples != 0)
        {
            logmsg "System $sys still exists; remove it first before restoring it\n";
            next;
        }

        if ( ! -f "$PGDIR/dbdumps/$sys.dump.Z")
        {
            logmsg "Dump file $PGDIR/dbdumps/$sys.dump.Z not found\n";
            next;
        }
        system('PATH=$PATH:' . "$PGSQLDIR;export PATH; createdb $sys");
        system('PATH=$PATH:' . "$PGSQLDIR;export PATH; uncompress < $PGDIR/dbdumps/$sys.dump.Z | psql $sys");

        $newdb = Pg::connectdb("dbname = " . $sys);
        if ($newdb->status == PGRES_CONNECTION_BAD)
        {
            die "Cannot open database connection: " . $newdb->errorMessage;
        }
        $q = "select nickname,systype,gathering from dbinfo";
        die "Stopping" unless $result = doq($newdb, $q, PGRES_TUPLES_OK);

        $nick = $result->getvalue(0, 0);
        $nick =~ s/^\s*(.*?)\s*$/$1/;
        $typ = $result->getvalue(0, 1);
        $typ =~ s/^\s*(.*?)\s*$/$1/;
        $gather = $result->getvalue(0, 2);
        $gather =~ s/^\s*(.*?)\s*$/$1/;
        $q = "insert into systems values('$sys', '$nick', '$typ', '$gather')";
        die "Stopping" unless $result = doq($perfdb, $q, PGRES_COMMAND_OK);
        undef $newdb;
    }
    signal_pgstart;
    exit(0);
}

#########################################################################
# Start interactive loop
#
do
{
    print "\n============================================================\n";
    print "Performance Grapher main configuration menu\n\n" .
          "1. Start a client system to monitor;\n" .
          "2. Stop a client;\n" .
          "3. Add a disk to monitor;\n" .
          "4. Remove a disk to monitor;\n" .
          "5. Add a network interface to monitor;\n" .
          "6. Remove a network interface to monitor;\n" .
          "7. Change cleanup of database;\n" .
          "8. Change own graph definitions;\n" .
          "9. Change license;\n" .
          "a. Change nickname of a system;\n" .
          "0. Quit\n";
    print "perfgraph-> ";

    $resp = <STDIN>;

    if (!defined($resp) || $resp eq "\n")
    {
        die "\nExiting $0\n\n";
    }
    chomp($resp);

    if ($resp !~ /^[0-9a]$/)
    {
        print "Illegal response\n";
    } else
    {
        StartClient() if $resp eq '1';
        StopClient() if $resp eq '2';
        AddDisk() if $resp eq '3';
        RmDisk() if $resp eq '4';
        AddNetwork() if $resp eq '5';
        RmNetwork() if $resp eq '6';
        ChangeClean() if $resp eq '7';
        ChUserFields() if $resp eq '8';
        mklic($l) if $resp eq '9';
        ChangeNick($l) if $resp eq 'a';
    }
} until ($resp eq '0');

