hxtools/suser/wktimer

376 lines
7.1 KiB
Perl
Executable File

#!/usr/bin/perl
# SPDX-License-Identifier: GPL-2.0-or-later
# SPDX-FileCopyrightText: 2004-2007 Jan Engelhardt
#
# wktimer
# A program which impelements time() based time counters.
#
use Getopt::Long;
use constant {
OP_RESTAMP => 1 << 0,
OP_VERBOSE => 1 << 1,
};
use strict;
no strict "subs"; # OP_START/OP_STOP
my $do_show = 1;
my $g_flags = OP_VERBOSE;
my $flag_iStart = 0;
my $flag_hdr = 1;
my $flag_sec = 0;
my $timer_file = $ENV{HOME}."/.timers";
my @ARGV2;
my %TIMER;
sub repush {
push(@ARGV2, "-".shift(@_), @_);
return;
}
&Getopt::Long::Configure(qw(bundling pass_through));
&GetOptions(
"A|add=s" => \&repush,
"D|del|delete=s" => \&repush,
"F|flush" => \&repush,
"H|nohdr" => sub { $flag_hdr = 0; },
"L|list:s" => \&repush,
"S|stop=s" => \&repush,
"X=s" => \&repush,
"W|switch=s" => \&repush,
"i|istart" => \$flag_iStart,
"q|quiet" => sub { $g_flags &= ~OP_VERBOSE; },
"s|sec" => \$flag_sec,
"t|file=s" => \$timer_file,
);
&read_timers($g_flags);
@ARGV = @ARGV2;
&GetOptions(
"A|add=s" => sub {
$do_show = 0;
foreach my $name (split(/,/so, $_[1])) {
&start_timer($name, OP_RESTAMP | $g_flags);
}
},
"D|del|delete=s" => sub {
$do_show = 0;
foreach my $name (split(/,/so, $_[1])) {
&delete_timer($name, OP_RESTAMP | $g_flags);
}
},
"F|flush" => sub {
$do_show = 0;
&flush_timers($g_flags);
},
"L|list:s" => sub {
$do_show = 0;
&show_timers(split(/,/so, $_[1]));
},
"S|stop=s" => sub {
$do_show = 0;
foreach my $name (split(/,/so, $_[1])) {
&stop_timer($name, $g_flags);
}
},
"X=s" => sub {
foreach my $name (split(/,/so, $_[1])) {
&stop_timer($name, OP_RESTAMP | $g_flags);
}
},
"W|switch=s" => sub {
$do_show = 0;
foreach my $name (split(/,/so, $_[1])) {
&switch_timer($name, $g_flags);
}
},
);
if ($do_show) {
&show_timers();
}
&save_timers($g_flags);
sub start_timer ()
{
my $name = lc shift @_;
my $flags = shift @_;
if (!exists($TIMER{$name})) {
$TIMER{$name} = {};
my $t = $TIMER{$name};
$t->{InitialStart} = $t->{Start} = time();
$t->{Stop} = -1;
if ($flags & OP_VERBOSE) {
print "Created timer \"$name\"\n";
}
return 1;
}
my $t = $TIMER{$name};
if ($t->{Stop} < 0 && $flags & OP_RESTAMP) {
# still running
$t->{Stop} = time();
$t->{Cumulative} += $t->{Stop} - $t->{Start};
$t->{Start} = $t->{Stop};
$t->{Stop} = -1;
if ($flags & OP_VERBOSE) {
print "Updated START mark for timer \"$name\"\n";
}
} elsif ($t->{Stop} >= 0) {
# was a stopped timer
$t->{Start} = time();
$t->{Stop} = -1;
if ($flags & OP_VERBOSE) {
print "Restarted timer \"$name\"\n";
}
}
return 1;
}
sub stop_timer ()
{
my $name = lc shift @_;
my $flags = shift @_;
if (!exists($TIMER{$name})) {
if ($flags & OP_VERBOSE) {
print "Timer \"$name\" does not exist\n";
}
return;
}
my $t = $TIMER{$name};
if ($t->{Stop} >= 0 && $flags & OP_RESTAMP) {
$t->{Cumulative} -= $t->{Stop} - $t->{Start};
$t->{Stop} = time();
$t->{Cumulative} += $t->{Stop} - $t->{Start};
if ($flags & OP_VERBOSE) {
print "Updated STOP mark for timer \"$name\"\n";
}
} elsif ($t->{Stop} < 0) {
$t->{Stop} = time();
$t->{Cumulative} += $t->{Stop} - $t->{Start};
if ($flags & OP_VERBOSE) {
print "Stopped timer \"$name\"\n";
}
}
return;
}
sub switch_timer ()
{
my $name = lc shift @_;
my $flags = shift @_;
if (!exists($TIMER{$name})) {
if ($flags & OP_VERBOSE) {
print "Timer \"$name\" does not exist\n";
}
return 1;
}
foreach my $subname (keys %TIMER) {
my $t = $TIMER{$subname};
if ($subname ne $name) {
&stop_timer($subname, OP_STOP);
} else {
&start_timer($name, OP_START);
}
}
if ($flags & OP_VERBOSE) {
print "Switched to timer \"$name\"\n";
}
&save_timers();
return;
}
sub delete_timer ()
{
my $name = lc shift @_;
my $flags = shift @_;
if (exists $TIMER{$name}) {
if ($flags & OP_VERBOSE) {
print "Timer \"$name\" does not exist\n";
}
return;
}
delete $TIMER{$name};
if ($flags & OP_VERBOSE) {
print "Deleted timer \"$name\"\n";
}
return;
}
sub flush_timers ()
{
my $flags = shift @_;
undef %TIMER;
if ($flags & OP_VERBOSE) {
print "Deleted all timers\n";
}
return;
}
sub read_timers()
{
local *IN;
if (!-e $timer_file) {
return;
}
open(IN, "< $timer_file") || die "Could not open $timer_file: $!\n";
while (defined(my $ln = <IN>)) {
my($name, @data);
my $t;
chomp($ln);
$ln =~ s/^\s+//giso;
$ln =~ s/\s+$//giso;
($name, @data) = split(/\s+/, $ln);
$TIMER{$name} = {};
$t = $TIMER{$name};
$t->{InitialStart} = shift @data;
$t->{Cumulative} = shift @data;
$t->{Start} = shift @data;
$t->{Stop} = shift @data;
}
close IN;
return;
}
sub show_timers ()
{
if ($flag_hdr) {
printf "%-10s", "Name";
if ($flag_iStart) {
printf " %11s", "I-Start";
}
printf " %12s %11s %11s %12s\n",
"Cumulative", "L-Start", "L-Stop", "Elapsed";
}
if ($#_ >= 0) {
foreach my $name (@_) {
$name = lc $name;
if (exists $TIMER{$name}) {
&print_timer($name);
}
}
} else {
foreach my $name (sort keys %TIMER) {
&print_timer($name);
}
}
return;
}
sub print_timer ()
{
my $name = shift @_;
my $t = $TIMER{$name};
my $cum = ($t->{Cumulative} + (($t->{Stop} == -1) ?
time() - $t->{Start} : 0));
my $elap = time() - $t->{Start};
if ($flag_sec) {
$cum .= "s";
$elap .= "s";
} else {
$cum = &sec2dur($cum);
$elap = &sec2dur($elap);
}
printf "%-10s", $name;
if ($flag_iStart) {
printf " %11s", &sec2date($t->{InitialStart});
}
printf " %12s %11s %11s %12s\n",
$cum, &sec2date($t->{Start}), &sec2date($t->{Stop}), $elap;
return;
}
sub save_timers ()
{
local *OUT;
if (scalar(keys %TIMER) == 0) {
unlink $timer_file;
return;
}
open(OUT, "> $timer_file") || die "Could not open $timer_file: $!\n";
foreach my $name (sort keys %TIMER) {
my %t = %{$TIMER{$name}};
printf OUT "%s %u %u %u %d\n",
$name, @t{InitialStart,Cumulative,Start,Stop};
}
close OUT;
return;
}
sub is_running ()
{
my $name = lc shift @_;
if ($TIMER{$name}{Stop} < 0) {
return 1;
}
return 0;
}
sub sec2date ()
{
my $in = shift @_;
if ($in < 0) {
return "(running)";
}
my @d = localtime $in;
return sprintf "%02d%02d-%02d%02d%02d", $d[3], $d[4] + 1, @d[2,1,0];
}
sub sec2dur ()
{
my($S_hr, $S_min, $S_sec) = (0, 0, 0);
my $in = shift @_;
my $sec = $in % 60;
my $min = int($in / 60) % 60;
my $hr = int($in / 3600) % 24;
my $days = int($in / 86400);
my $ret;
if ($days != 0) {
$ret .= sprintf "%dd", $days;
$S_hr = $S_min = $S_sec = 2;
}
if ($hr != 0 || $S_hr) {
if ($S_hr == 2) {
$ret .= sprintf "%02dh", $hr;
} else {
$ret .= sprintf "%2dh", $hr;
}
$S_min = $S_sec = 2;
}
if ($min != 0 || $S_min) {
if ($S_min == 2) {
$ret .= sprintf "%02dm", $min;
} else {
$ret .= sprintf "%2dm", $min;
}
$S_sec = 2;
}
if ($S_sec == 2) {
$ret .= sprintf "%02ds", $sec;
} else {
$ret .= sprintf "%2ds", $sec;
}
return $ret;
}