#!/usr/bin/perl
# ptktime v0.2
# Perl/Tk Time Service (TCP port 37) Client
# Copyright Alan Ford <alan@whirlnet.co.uk>  08/04/1999
# Distributed with no warranty under the GNU Public License
#
# Changelog:
# 08/04/1999 Initial Release Version (0.1)
# 06/06/1999 Added support for command-line specification of timeserver (0.2)
#
# Based on example in The Camel Book
# (There Is No Camel [TM])

require 5.002;
#use strict;
use Tk;
#use Tk::DialogBox;
use Socket;
sub comparetimes ;
sub getlocal ;
sub help ;

my $version = "0.2";

my $MW = MainWindow->new;

$MW->title("Perl/Tk Time Client");
$MW->Label(-text => "Version $version - Written by Alan Ford\n<alan\@whirlnet.co.uk>")->pack(-side => 'bottom');

my $lookup_frame = $MW->Frame()->pack(-expand => '1', -fill => 'both', -side => 'top');

my $button_frame = $MW->Frame()->pack(-expand => '1', -fill => 'both', -side => 'top');

my $local_frame = $MW->Frame()->pack(-expand => '1', -fill => 'both', -side => 'top');

my $remote_frame = $MW->Frame()->pack(-expand => '1', -fill => 'both', -side => 'top');

my $diff_frame = $MW->Frame()->pack(-expand => '1', -fill => 'both', -side => 'top');

$lookup_frame->Label(-text => "Remote Timeserver:")->pack(-side => 'left');
my $host_entry = $lookup_frame->Entry(-width => '25', -relief => 'sunken')->pack(-side => 'left', -expand => '1', -fill => 'x');

$local_frame->Label(-text => "Local Time:")->pack(-side => 'left');
my $local_time = $local_frame->Entry(-width => '25', -relief => 'sunken', -justify => 'right')->pack(-side => 'left', -expand => '1', -fill => 'x');

$remote_frame->Label(-text => "Remote Time:")->pack(-side => 'left');
my $remote_time = $remote_frame->Entry(-width => '25', -relief => 'sunken', -justify => 'right')->pack(-side => 'left', -expand => '1', -fill => 'x');

$diff_frame->Label(-text => "Difference in Seconds:")->pack(-side => 'left');
my $diff_secs = $diff_frame->Entry(-width => '25', -relief => 'sunken', -justify => 'right')->pack(-side => 'left', -expand => '1', -fill => 'x');

my $comparetimes = $button_frame->Button(-text => 'Compare Times',
                                         -command => sub
                                         {
                                          comparetimes;
	                                 });
$comparetimes->pack(-side => 'left', -expand => '1', -fill => 'both');

my $getlocal = $button_frame->Button(-text => 'Get Local Time',
                                     -command => sub
                                     {
                                      getlocal;
	                             });
$getlocal->pack(-side => 'left', -expand => '1', -fill => 'both');

my $exit = $button_frame->Button(-text => 'Exit',
                                 -command => sub
                                 {
                                  exit;
                                 });
$exit->pack(-side => 'left', -expand => '1', -fill => 'both');

if ($ARGV[0]) {
   # Are they asking for help?
   if ($ARGV[0] =~ /help$/) {
       help;
   }
   if ($ARGV[0] eq "-?") {
       help;
   }
   if ($ARGV[0] eq "-h") {
       help;
   }
   # Timeserver (probably) given as command-line option
   my $cmdserver = $ARGV[0];
   $host_entry->insert('0', $cmdserver);
   comparetimes;
}

MainLoop;


sub comparetimes {
    my $SECS_of_70_YEARS = 2208988800;
    sub ctime { scalar localtime(shift) }

    my $iaddr = gethostbyname('localhost');
    my $proto = getprotobyname('tcp');
    my $port = getservbyname('time', 'tcp');
    my $paddr = sockaddr_in(0, $iaddr);
    my $host = $host_entry->get;

    $| = 1;
    printf "%-24s %8s %s\n", "localhost", 0, ctime(time());
    $local_time->delete(0, 'end');
    $remote_time->delete(0, 'end');

    printf "%-24s ", $host;
    my $hisiaddr = inet_aton($host) or die "Unknown Host: $host";
    my $hispaddr = sockaddr_in($port, $hisiaddr);
    socket(SOCKET, PF_INET, SOCK_STREAM, $proto)
                                         or die "Socket Error: $!";
    connect(SOCKET, $hispaddr)           or die "Bind Error for $host: $!";
    my $rtime = '   ';
    read(SOCKET, $rtime, 4);
    close(SOCKET);
    my $histime = unpack("N", $rtime) - $SECS_of_70_YEARS;
    printf "%8d %s\n", $histime - time, ctime($histime);
    $local_time->insert('end', ctime(time()));
    $remote_time->insert('end', ctime($histime));
    $diff_secs->delete(0, 'end');
    $diff_secs->insert('end', $histime - time);
}

sub getlocal {
    $local_time->delete('0', 'end');
    $local_time->insert('end', ctime(time()));
}

sub help {
   print <<EOF

ptktime - Perk/Tk Time Client for X version $version (requires Perl/Tk)

Compares local time with timeserver.

Remote timeserver can (but is not required) be specified as a parameter.

Report bugs to the author, Alan Ford <alan\@whirlnet.co.uk>

For more information: `man ptktime'

EOF
;
exit;
}
