$VERSION
=
'0.4'
;
sub
new {
my
$this
=
shift
;
my
$class
=
ref
(
$this
) ||
$this
;
my
$self
= {};
$self
->{entry} =
shift
;
$self
->{code} =
shift
;
$self
->{lrmark} =
shift
;
bless
$self
,
$class
;
return
$self
;
}
sub
expand{
my
(
$s
,
$start
,
$end
)=
@_
;
return
(
$start
..
$end
)
if
$s
eq
'*'
;
my
(
@per
)=
split
/,/,
$s
;
my
(
@ev
);
for
(
@per
){
if
(/^\d\d?$/){
push
@ev
,
$_
;
next
;
}
if
(/^(\d\d?)-(\d\d?)$/){
push
@ev
, ($1 .. $2);
next
;
}
return
();
}
return
sort
@ev
;
}
sub
run{
my
$self
=
shift
;
my
%periods
=(
min
=> {
per
=> [0,59],
i
=> 1,
adj
=>
sub
{
return
shift
} },
hour
=> {
per
=> [0,23],
i
=> 2,
adj
=>
sub
{
return
shift
} },
day
=> {
per
=> [1,31],
i
=> 3,
adj
=>
sub
{
return
shift
} },
month
=> {
per
=> [1,12],
i
=> 4,
adj
=>
sub
{
return
shift
()+1 } },
wday
=> {
per
=> [1,7 ],
i
=> 6,
adj
=>
sub
{
return
shift
()+1 } },
);
my
(
@ltime
)=
localtime
( (
stat
$self
->{lrmark})[9]);
my
(
@ctime
)=
localtime
();
my
$s
=
$self
->{entry};
my
(
%entry
,
@expanded
);
(
$entry
{min},
$entry
{hour},
$entry
{day},
$entry
{month},
$entry
{wday},
$entry
{command})=
split
' '
,
$s
, 6;
for
my
$k
(
qw(min hour day month)
){
my
$i
=
$periods
{
$k
}{i};
$ltime
[
$i
] =
$periods
{
$k
}{adj}->(
$ltime
[
$i
]);
$ctime
[
$i
] =
$periods
{
$k
}{adj}->(
$ctime
[
$i
]);
$entry
{
$k
}= [ expand(
$entry
{
$k
}, @{
$periods
{
$k
}{per} } ) ];
}
my
$ltime
=
sprintf
"%02d%02d%02d%02d"
,
@ltime
[4,3,2,1];
my
$rtime
;
my
$ctime
=
sprintf
"%02d%02d%02d%02d"
,
@ctime
[4,3,2,1];
COMMON:
for
my
$month
(
reverse
@{
$entry
{month}}){
next
if
$month
>
$ctime
[4];
for
my
$day
(
reverse
@{
$entry
{day}}){
next
if
$day
>
$ctime
[3];
for
my
$hour
(
reverse
@{
$entry
{hour}}){
next
if
$hour
>
$ctime
[2];
for
my
$min
(
reverse
@{
$entry
{min}}){
$rtime
=
sprintf
"%02d%02d%02d%02d"
,
$month
,
$day
,
$hour
,
$min
;
last
COMMON
if
$rtime
le
$ctime
;
}
}
}
}
return
0
if
!
sysopen
(MARK_LOCK,
$self
->{lrmark} .
'.lock'
, O_CREAT | O_RDWR | O_EXCL, 0666 );
close
MARK_LOCK;
open
MARK,
$self
->{lrmark};
my
$lrtime
=<MARK>;
chomp
$lrtime
;
close
MARK;
if
( !
$lrtime
){
open
MARK,
'>'
.
$self
->{lrmark};
print
MARK 1;
close
MARK;
unlink
$self
->{lrmark} .
'.lock'
;
return
0;
}
if
(
$ltime
le
$rtime
and
$rtime
le
$ctime
and
$rtime
ne
$lrtime
){
open
MARK,
'>'
.
$self
->{lrmark};
$self
->{code}->();
print
MARK
$rtime
;
close
MARK;
unlink
$self
->{lrmark} .
'.lock'
;
return
1;
}
unlink
$self
->{lrmark} .
'.lock'
;
return
0;
}
1;