crontab/mirc — File Browser

crontabmircv0.8 / crontabmircv0.8 / crontab.mrc

crontab.mrc — 11.89 KB — Download this file

alias -l _me return crontab
alias -l _ver return 0.8
alias -l _dep return mirc 6.0 0 clp 1.1.9 0
alias -l __mirc return $version
alias __crontab return $_ver
on *:signal:deps:if ($2 iswm $_me) { .signal re-deps $1 $_me $_dep }
on *:signal:rollcall:if ($2 iswm $_me) { .signal re-rollcall $1 $_me $_ver }

alias -l compare {
  if ($0 != 3) return 0
  if (!$regex($2,^[<>=]=?$)) return 0
  var %i 0, %n = $numtok($1,46), %m = $numtok($3,46), %n = $iif(%m > %n,%m,%n), %p = $1, %q = $3, %r, %s, %t
  while (%i < %n) {
    inc %i
    %t = $regsub($gettok($1,%i,46),[a-zA-Z],,%r)
    %t = $regsub($gettok($3,%i,46),[a-zA-Z],,%s)
    %t = $calc($len(%r) - $len(%s))
    if (%t) {
      if (%t > 0) %q = $puttok(%q,$+($str(0,%t),$gettok(%q,%i,46)),%i,46)
      else %p = $puttok(%p,$+($str(0,$calc(0- %t)),$gettok(%p,%i,46)),%i,46)
    }
  }
  return $iif(%p $2 %q,1,0)
}
on *:signal:INIT:{
  if ($2 iswm $_me) {
    %crontab.signalto = $1
    crontab
  }
}
alias -l crontab.reinit {
  if (%crontab.signalto) {
    .signal REINIT $_me %crontab.signalto $1-
    unset %crontab.signalto
  }
}
alias -l e echo -s crontab: $1-
alias crontab {
  if (!$0) {
    var %f, %i, %n, %req, %t
    e $_me $_ver starting
    e . checking dependencies
    %req = $_dep
    %i = 1
    while (%i < $numtok(%req,32)) {
      var %module, %need, %have
      %module = $gettok(%req,%i,32)
      %need = $gettok(%req,$calc(%i +1),32)
      %have = $__ [ $+ [ $gettok(%req,%i,32) ] ]
      e . . $+(%module %need,...) $iif(%have,%have,not found)
      if (!%have) { %have = 0 }
      if ($compare(%have,<,%need)) {
        if ($gettok(%req,$calc(%i +2),32)) { e WARNING %module %need or better not found, functionnality may be reduced }
        else {
          e ERROR $_me $_ver requires %module %need or better, aborting.
          %f = $findfile($mircdir,$+(%module,.mrc),1,99)
          if (%f) { e . i have found $nopath(%f) in $nofile(%f) but it was not loaded or it has been modified, /load -rs $+(",%f,") might fix this error. }
          crontab.reinit 0
          return
        }
      }
      inc %i 3
    }
    e . dependencies okay
    crontab.init
    crontab.reinit 1
    return
  }
  var %clp = $clp($1-,--die,cron.die,--exec,cron.exec,-e --edit,cron.edit,-l --list,cron.list,-h --help --man,cron.man,--sync --resync,cron.sync)
  if (!%clp) {
    e error while parsing parms
    crontab.reinit 0 clp error
    return
  }
  if (%cron.sync) {
    e resynchronizing timer
    crontab.vars
    .timercrontab -o $+(%cron.hrs,:,%cron.mins) 1 0 crontab --exec
    e . next check scheduled at $timer(crontab).time
    return 
  }
  if (%cron.exec) {
    var %comp, %event, %field, %field1, %field2, %field3, %field4, %field5, %field.i 0, %match, %range0, %range1, %step, %token, %i 0, %j, %m, %n
    %n = $hmatch(crontab,*,0)
    while (%i < %n) {
      inc %i
      %event = $replace($hget(crontab,%i),$chr(9),$chr(32))
      if ((#* iswm %event) || (!$len(%event)) || (!$crontab.validate(%event))) continue
      :1
      %field1 = $gettok(%event,1,32)
      %field2 = $gettok(%event,2,32)
      %field3 = $gettok(%event,4,32)
      %field4 = $gettok(%event,3,32)
      %field5 = $gettok(%event,5,32)
      if ($regex(%field1,^@((year|annual|month|week|dai|hour)ly|midnight)$)) { 
        if (%field1 == @hourly) {
          %event = 0 * * * * $gettok(%event,2-,32)
          goto 1
        }
        if ($regex(%field1,^@(daily|midnight)$)) {
          %event = 0 0 * * * $gettok(%event,2-,32)
          goto 1
        }
        if (%field1 == @weekly) {
          %event = 0 0 * * 0 $gettok(%event,2-,32)
          goto 1
        }
        if (%field1 == @monthly) {
          %event = 0 0 1 * * $gettok(%event,2-,32)
          goto 1
        }
        if ($regex(%field1,^@(year|annual)ly$)) {
          %event = 0 0 1 1 * $gettok(%event,2-,32)
          goto 1
        }
      }
      %field3 = $replace(%field3,jan,1,feb,2,mar,3,apr,4,may,5,jun,6,jul,7,aug,8,sep,9,oct,10,nov,11,dec,12)
      %field5 = $replace(%field5,sun,0,mon,1,tue,2,wed,3,thu,4,fri,5,sat,6,7,0)
      %field.i = 0
      %match = 0
      while (%field.i < 5) {
        inc %field.i
        %comp = %cron. [ $+ [ $gettok(mins.hrs.month.day.dow,%field.i,46) ] ]
        %field = %field [ $+ [ %field.i ] ]
        %j = 0
        %m = $numtok(%field,44)
        while (%j < %m) {
          inc %j
          %token = $gettok(%field,%j,44)
          if ($regex(%token,^\*+$)) {
            inc %match
            break
          }
          if ($regex(%token,^\d+$)) {
            if (%token == %comp) {
              inc %match
              break
            }
            continue
          }
          %step = $gettok(%token,2,47)
          if ($regex(%token,^\d+/\d+$)) {
            if ($calc(%comp % %step) == $calc($gettok(%token,1,47) % %step)) {
              inc %match
              break
            }
            continue
          }
          if ($regex(%token,^\*/\d+$)) {
            if (%step // %comp) {
              inc %match
              break
            }
            continue
          }
          %range0 = $gettok(%token,1,45)
          %range1 = $gettok($gettok(%token,2,45),1,47)
          if ($regex(%token,^\d+-\d+(/\d+)?$)) { 
            if (%range0 < %range1) { 
              if ($regex(%token,^\d+-\d+$)) {
                if ((%comp >= %range0) && (%comp <= %range1)) {
                  inc %match
                  break
                }
                continue
              }
              else {
                if ((%comp >= %range0) && (%comp <= $gettok(%range1,1,47)) && ($calc(%range0 % %step) == $calc(%comp % %step))) {
                  inc %match
                  break
                }
                continue
              }
            }
            else {
              if ($regex(%token,^\d+-\d+$)) {
                if ((%comp >= %range0) || (%comp <= %range1)) {
                  inc %match
                  break
                }
                continue
              }
              else {
                if ((%comp >= %range0) || (%comp <= $gettok(%range1,1,47)) && ($calc(%range0 % %step) == $calc(%comp % %step))) {
                  inc %match
                  break
                }
                continue
              }
            }
          }
        }
        if ((%field.i < 4) && (%match < %field.i)) break
      }
      if (%match > 3) .timer -o 1 0 $gettok(%event,6-,32)
    }
    crontab.vars
    .timercrontab -o $+(%cron.hrs,:,%cron.mins) 1 0 crontab --exec
    return
  }
  if (%cron.die) {
    crontab.die
    return
  }
  if (%cron.edit) {
    dialog $iif($dialog(crontab.e),-v,-m) crontab.e crontab.e
    return
  }
  if (%cron.list) {
    var %i 0, %n = $hmatch(crontab,*,0)
    echo -s $+(--crontab,$str(-,20))
    while (%i < %n) {
      inc %i
      if ($hget(crontab,%i)) echo -s $hget(crontab,%i)
    }
    echo -s $+(--crontab,$str(-,20))
    return
  }
  if (%cron.man) {
    crontab.man
    return
  }
}

alias -l crontab.die {
  e freeing resources
  e . stopping timer
  .timercrontab* off
  e . freeing hash table
  hfree -w crontab*
  e . unsetting variables
  unset %cron.*
  if ($window(@crontab)) {
    e . closing manual
    window -c @crontab
  }
  e done 
}
alias -l crontab.init {
  var %cron.validated, %i 0, %n, %t
  e . making cron table
  hfree -w crontab
  hmake crontab 10
  if ($isfile(crontab.sav)) {
    e . loading events from crontab.sav
    hload -n crontab crontab.sav 
    %n = $hmatch(crontab,*,0)
    e . . %n lines loaded
    e . validating events
    while (%i < %n) {
      inc %i
      %t = $hget(crontab,%i)
      if (#* iswm %t) { continue }
      if (!$len(%t)) { continue }
      if ($crontab.validate(%t)) { inc %cron.validated }
      else e . . WARNING, bogus event: %t
    }
    e . . %cron.validated events validated
  }
  e . setting vars
  %cron.day = $asctime(dd)
  %cron.month = $asctime(mm)
  %cron.dow = $replace($asctime(ddd),sun,0,mon,1,tue,2,wed,3,thu,4,fri,5,sat,6)
  crontab.vars
  e . starting timer
  .timercrontab -o $+(%cron.hrs,:,%cron.mins) 1 0 crontab --exec
  e ready
  return
}
alias -l crontab.man {
  if ($isfile(crontab.txt)) {
    window -adk @crontab
    filter -cpfw crontab.txt @crontab *
  }
}
alias -l crontab.validate {
  var %regex.in = $replace($1-,$chr(9),$chr(32)), %regex, %regex1, %regex2, %regex3, %regex4, %regex5, %e, %f 0, %i 0, %j 0, %m 0, %n, %p
  tokenize 32 %regex.in
  if ($regex($1,^@((year|annual|month|week|dai|hour)ly|midnight)$) && ($len($2))) return $true
  %regex1 = ^((\*)|(([0-5]?\d)(-[0-5]?\d)?))(/\d+)?$
  %regex2 = ^((\*)|((([01]?\d)|(2[0-3]))(-(([01]?\d)|(2[0-3])))?))(/\d+)?$
  %regex3 = ^((\*)|((([012]?\d)|(3[01]))(-(([012]?\d)|(3[01])))?))(/\d+)?$
  %regex4 = ^((\*)|((((0?[1-9])|(1[0-2]))|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)(-(((0?[1-9])|(1[0-2]))|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec))?))(/\d+)?$
  %regex5 = ^((\*)|(([0-7]|mon|tue|wed|thu|fri|sat|sun)(-([0-7]|mon|tue|wed|thu|fri|sat|sun))?))(/\d+)?$
  while (%j < 5) {
    inc %j
    %p = $ [ $+ [ %j ] ]
    %regex = %regex [ $+ [ %j ] ]
    %n = $numtok(%p,44)
    inc %m %n
    %e = 0
    %i = 0
    while (%i < %n) {
      inc %i
      if ($regex($lower($gettok(%p,%i,44)),%regex)) inc %e
    }
    inc %f %e
  }
  return $iif((%f == %m) && ($len($6)),$true,$false)
}
alias -l crontab.vars {
  var %t = $calc($ctime +60)
  %cron.hrs = $asctime(%t,HH)
  %cron.mins = $asctime(%t,nn)
  if (!$calc(%cron.mins + %cron.hrs)) {
    %cron.day = $asctime(%t,dd)
    %cron.month = $asctime(%t,mm)
    %cron.dow = $calc(($pos(sumotuwethfrsa,$left($asctime(%t,ddd),2)) -1) /2)
  }
}

on *:dialog:crontab.e:init:0:{
  var %i 0, %n = $hmatch(crontab,*,0), %t
  did -a crontab.e 2 Enter your crontab events in the space below. Blank lines or lines that begin with a hash (#) are ignored. Separate fields with a space or a tab (ctrl+i). $crlf $+ Syntax is: MIN HOUR DAY MONTH DAYOFWEEK COMMAND
  while (%i < %n) {
    inc %i
    %t = $hget(crontab,%i)
    if (%t) did -a crontab.e 1 %t $+ $crlf
  }
  if (!$isfile(crontab.txt)) {
    did -h crontab.e 3
    did -bv crontab.e 4
  }
}
on *:dialog:crontab.e:sclick:3:crontab.man
on *:dialog:crontab.e:sclick:999:{
  var %i 0, %n = $hmatch(crontab,*,0), %t
  while (%i < %n) {
    inc %i
    hdel crontab %i
  }
  %i = 0
  %n = $did(1).lines
  while (%i < %n) {
    inc %i
    %t = $did(1,%i)
    if ($len(%t)) { 
      if (#* !iswm %t) {
        if (!$crontab.validate(%t)) e WARNING, bogus event: %t
      }
      ; we add bogus events as well so that is shows up next time the user edits the crontab
      hadd crontab %i %t
    }
  }
  ; for some reason, the first item is written last with hsave -n, so we use filter as a workaround
  filter -cif crontab.e 1 crontab.sav *
}
dialog crontab.e {
  title "crontab"
  size -1 -1 640 480

  edit "", 1, 5 60 630 390, return multi hsbar vsbar autohs
  text "", 2, 5 5 630 40
  link "manual", 3, 595 45 40 15
  text "manual", 4, 595 45 40 15, hide
  button "&Cancel", 998, 510 455 60 20, cancel
  button "&OK", 999, 575 455 60 20, ok
}

menu status {
  $_me $_ver
  .&edit crontab:crontab -e
  .&list crontab:crontab -l
  .-
  .$iif($isfile(crontab.txt),&manual):crontab -h
  .-
  .$iif(%cron.mins,&restart,&start):crontab
  .$needsync:crontab --resync
  .$iif(%cron.mins,sto&p):crontab --die
  .-
  .unload =(:{
    if ($input(Would you really like to unload 'crontab'?,qy)) { 
      crontab.die
      unload -rs crontab.mrc
    }
    else var %t $input(Good!,o,Thank you)
  }
}

alias -l needsync {
  var %t = $timer(crontab).time
  if (!%t) return
  var %sched = $calc($gettok(%t,1,58) *60+ $gettok(%t,2,58)), %now = $calc($gettok($time,1,58) *60+ $gettok($time,2,58))
  if ($calc(%sched - %now) != 1) return res&ync (scheduled %t $+ , now $gettok($time,1-2,58) $+ )
}