#!/usr/bin/perl -T 

#------------------------------------------------------------------------------
#  alifetime: return the remaining lifetime of an AFS token (in seconds) 
#
#  Author: Arne Wiebalck IT-DSS/FDO, October 2011.
#------------------------------------------------------------------------------

$ENV{PATH} = "/bin:/usr/bin";
$ENV{LANG} = "en_US.UTF-8";
delete @ENV{qw(IFS CDPATH ENV BASH_ENV LD_LIBARY_PATH LD_PRELOAD)};

#------------------------------------------------------------------------------
# Modules
#------------------------------------------------------------------------------

use strict;
use warnings;
use Date::Manip;

#------------------------------------------------------------------------------
# Global variables 
#------------------------------------------------------------------------------

my ($ProgramName, $Debug, $ExpDate) = (0, 0, 0);

#------------------------------------------------------------------------------
# Subroutines
#------------------------------------------------------------------------------

sub read_command ($@) {
    my($test_exit, @command) = @_;
    my($pid, @result);

    print("# running: @command\n") if $Debug > 1;
    pipe(READ, WRITE)             or die("$ProgramName: cannot pipe: $!\n");
    defined($pid = fork())        or die("$ProgramName: cannot fork: $!\n");
    if ($pid == 0) {
        close(READ)               or die("$ProgramName: cannot close read: $!\n");
        open(STDIN,  '/dev/null') or die("$ProgramName: cannot open stdin: $!\n");
        open(STDOUT, '>&WRITE')   or die("$ProgramName: cannot open stdout: $!\n");
        open(STDERR, '>&WRITE')   or die("$ProgramName: cannot open stderr: $!\n");
        exec({ $command[0] } @command) or die("$ProgramName: cannot exec '@command': $!\n");
        exit(1);
    } else {
        close(WRITE)              or die("$ProgramName: cannot close write: $!");
        @result = <READ>;
        close(READ)               or die("$ProgramName: cannot close read: $!");
        waitpid($pid, 0) == $pid  or die("$ProgramName: waitpid failed: $!");
        if ($test_exit) {
            $? == 0               or die("$ProgramName: command '@command' failed\n");
        }
        return(@result);
    }
}

#------------------------------------------------------------------------------
# Main
#------------------------------------------------------------------------------

$Debug = 1;

$ProgramName = $0;
$ProgramName =~ s#.*/##;

# get the tokens
foreach (read_command(1, "tokens")) {
    next unless (/okens for afs\@cern.ch \[Expires (.*)\]$/);
    $ExpDate = $1;
}

# no token found
if (0 eq $ExpDate) {
    print "0\n";
    exit;
}

my $now = time;
my $exp = UnixDate($ExpDate, "%s");

if ($exp < $now ) {
    # we have a token, but expiry is next year
    # ('tokens' does not state the year)
    my @A = localtime($exp);
    my $ny = $A[5] + 1901; 
    $ExpDate = sprintf("$ExpDate %d", $ny);
    $exp = UnixDate($ExpDate, "%s");
}

print $exp - $now . "\n";
exit;

__END__

=head1 NAME

alifetime - report the remaining lifetime of an AFS token (in seconds)

=head1 SYNOPSIS

alifetime

=head1 DESCRIPTION

B<alifetime> reports the remaining lifetime of an AFS token (in seconds).

=head1 SEE ALSO

klist(1), kinit(1), kdestroy(1), aklog(1), tokens(1)

=cut
