#!/usr/bin/perl -w
# vim:et:sw=4 ts=4 
# servermenu_pl - an server menu example client for LCDproc
# Displays some server stats: mem, cpu, local time 
# and offers the possibility to shutdown the machine via
# the buttons.
# Copyright GPL  2005, Guido Socher
use IO::Socket;
use Getopt::Std;
use Fcntl;
use strict;
use vars qw($opt_h);
#
my $remote = IO::Socket::INET->new(
    Proto     => "tcp",
    PeerAddr  => "localhost",  # this machine, 127.0.0.1
    PeerPort  => 13666
    ) || die "Cannot connect to LCDd\n";
#
sub help();
sub catch_sig();
sub mem();
sub cpu();
sub date();
#
getopts("h")||die "ERROR: No such option. -h for help.\n";
help() if ($opt_h);
if ($> > 0){
    print "Warning: shutdown will not work if you do not start this script as root\n";
}
# Make sure our messages get there right away
$remote->autoflush(1);
sleep 1;	# Give server time to notice us...
# initialize
print $remote "hello\n";
# you must always read the answer from LCDd even if you do not need it
# otherwise select will not work as expected:
my $lcdresponse = <$remote>;
# Set up some screen widgets...
print $remote "client_set name servermenu\n";
$lcdresponse = <$remote>; # read and ignore response
print $remote "screen_add scr1\n";
$lcdresponse = <$remote>; # read and ignore response
print $remote "widget_add scr1 str1 string\n";
$lcdresponse = <$remote>; # read and ignore response
print $remote "widget_add scr1 str2 string\n";
$lcdresponse = <$remote>; # read and ignore response
print $remote "client_add_key A\n";
$lcdresponse = <$remote>; # read and ignore response
print $remote "client_add_key C\n";
$lcdresponse = <$remote>; # read and ignore response
#
my $rin='';
my $timeout=10; # seconds
my $timeleft;
my $rout;
my $nfound;
my $str1; # 2 line display, line 1
my $str2; # 2 line display, line 2
my $i=0;
my $keya=0;
my $keyc=0;
my $shutdownmenustate=0;
my $runshutdown=0;
my $timeoutmenu=0;
#
while($runshutdown==0)
{
    vec($rin,fileno($remote),1)=1;
    ($nfound,$timeleft) = select($rout=$rin, undef, undef, $timeout);
    if ($nfound){
        # data is available
        $lcdresponse = <$remote>;
        $keya=0;$keyc=0;
        $keya=1 if ($lcdresponse && $lcdresponse=~/key A/);
        $keyc=1 if ($lcdresponse && $lcdresponse=~/key C/);
    }
    # the lower black key was pressed once, show shutdown menu:
    if ($keyc && $shutdownmenustate==0){
        $shutdownmenustate=1;
        $timeoutmenu=0;
        $str1="shutdown?   yes";
        $str2="             no";
        $keyc=0;
        $keya=0;
    }
    if ($keya && $shutdownmenustate==1){
        # yes pressed, run shutdown
        $shutdownmenustate=2;
        $runshutdown=1;
        $timeoutmenu=0;
        $str1="shutdown ....";
        $str2="             ";
        $keya=0;
    }
    if ($keyc && $shutdownmenustate==1){
        # no pressed, exit menu
        $shutdownmenustate=0;
        $timeoutmenu=0;
        $keyc=0;
    }
    $timeoutmenu++ if ($shutdownmenustate);
    # timeout:
    if ($timeoutmenu>3){
        $shutdownmenustate=0;
        $timeoutmenu=0;
    }
    if ($shutdownmenustate==0){
        # no shutdown menu, show system information
        ($str1,$str2)=date() if ($i==0);
        ($str1,$str2)=mem() if ($i==1);
        ($str1,$str2)=cpu() if ($i==2);
    }
    print $remote "widget_set scr1 str1 1 1 \"$str1\"\n";
    $lcdresponse = <$remote>; # read and ignore response
    print $remote "widget_set scr1 str2 1 2 \"$str2\"\n";
    $lcdresponse = <$remote>; # read and ignore response
    $i++;
    # go from 0 to 2 all the time
    $i=0 if ($i>2);
}
# run the "shutdown -h" command:
system("shutdown -h now");
# -------- end of main prog
#
sub mem(){
    # return mem and swap
    my $mem="mem: undef";
    my $swap="swp: undef";
    my ($tot,$used,$percentused);
    # parse the following output:
    # free
    #              total       used       free     shared    buffers     cached
    # Mem:        289196     172536     116660          0       8472      84684
    # -/+ buffers/cache:      79380     209816
    # Swap:       297160          0     297160
    open(PIPE,"free |")||die;
    while(<PIPE>){
        if (/Mem:\s+(\d+)\s+(\d+)/){
            $tot=$1;$used=$2;
            $percentused=int (($used/$tot) * 100);
            $mem=sprintf("mem: %.1fMb %d%%",$used/1000,$percentused);
        }
        if (/Swap:\s+(\d+)\s+(\d+)/){
            $tot=$1;$used=$2;
            $percentused=int (($used/$tot) * 100);
            $swap=sprintf("swp: %.1fMb %d%%",$used/1000,$percentused);
        }
    }
    return($mem,$swap);
}
#
sub cpu(){
    # return load averages = num of processes in run queue
    my $load="undef";
    my $uptime=`uptime`;
    if ($uptime=~/load average:\s?([\d\. ,]+)/){
        $load=$1;
    }
    return("load averages",$load);
}
#
sub date(){
    #return a date in yyyy-mm-dd hh:mm format
    my $date;
    my @ltime;
    @ltime = localtime;
    $date=sprintf("%04d-%02d-%02d %02d:%02d",
          1900+$ltime[5],$ltime[4]+1,$ltime[3],$ltime[2],$ltime[1],$ltime[0]);
    return("  time  ",$date);
}
#
sub help(){
    print "servermenu_pl -- an LCDd client for the lcdproc software
    
USAGE: servermenu_pl [-h]

This program shows stats about mem, swap, localtime, load averages
and offers the possibility to shutdown the server from the buttons
on the pannel.
            
OPTIONS: -h this help
\n";
    exit(0);
}