From:	CSBVAX::MRGATE!RELAY-INFO-VAX@CRVAX.SRI.COM@SMTP 25-SEP-1988 12:31
To:	ARISIA::EVERHART
Subj:	Cron from VAX professional


Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Sun, 25 SEP 88 03:26:19 PDT
Received: from CUNYVM.CUNY.EDU by KL.SRI.COM with TCP; Sun, 25 Sep 88 03:01:30 PDT
Received: from techunix.bitnet by CUNYVM.CUNY.EDU (IBM VM SMTP R1.1) with BSMTP id 1918; Sun, 25 Sep 88 06:00:19 EDT
Message-Id: <8809250648.AA23437@techunix.bitnet>
Received: by VMSA.TECHNION.AC.IL (HUyMail-4c); Sun, 25 Sep 88 08:50:06 O
Date:     Sun,  25 Sep 88 8:46 O
From: Ben Pashkoff <BEN%vmsa.technion.ac.il@CUNYVM.CUNY.EDU>
To: INFO-VAX@KL.SRI.COM
Comment:  Original VMS-TO was: INFO-VAX
Subject:  Cron from VAX professional

After all the discussion of the VAX Professional article concerning CRON,
I went ahead and retyped it in. Many thanks to James Gessling. (I definitely
want to give credit where due.)

Before any decide to flame me for typing in instead of down-loading from
ARIS, please note my address. I do not have access to ARIS!!!!
If there is anyone out there that does and does not mind sending me selected
items, please send me a note.

Anyway, in the SHARE file below are the three files that Gessling published.

___________________________________________________________________________
|                                                                         |
|      Ben Pashkoff                 BEN@VMSA.TECHNION.AC.IL               |
|                                   BEN@TECHMAX.BITNET                    |
|                                   BEN@TECHUNIX.BITNET                   |
|      VAX/VMS Systems              APLBENJ@TECHNION.BITNET               |
|      Computer Centre                                                    |
|      Technion IIT                                                       |
|      Haifa, Israel 32000          Phone:(972)-4-292176                  |
|_________________________________________________________________________|

$!..............................................................................
$! VAX/VMS archive file created by VMS_SHAR V-4.03 05-Aug-1987
$! which was written by Michael Bednarek (U3369429@ucsvc.dn.mu.oz.au)
$! To unpack, simply save and execute (@) this file.
$!
$! This archive was created by BEN
$!      on Sunday 25-SEP-1988 08:45:15.28
$!
$! It contains the following 3 files:
$! CRON.COM CRON_START.COM CRONTAB.DAT
$!=============================================================================

$ Set Symbol/Scope=(NoLocal,NoGlobal)
$ Version=F$GetSYI("VERSION") ! See what VMS version we have here:
$ If Version.ges."V4.4" then goto Version_OK
$ Write SYS$Output "Sorry, you are running VMS ",Version, -
                ", but this procedure requires V4.4 or higher."
$ Exit 44
$Version_OK: CR[0,8]=13
$ Pass_or_Failed="failed!,passed."
$ Goto Start
$Convert_File:
$ Read/Time_Out=0/Error=No_Error1/Prompt="creating ''File_is'" SYS$Command ddd
$No_Error1: Define/User_Mode SYS$Output NL:
$ Edit/TPU/NoSection/NoDisplay/Command=SYS$Input/Output='File_is' -
        VMS_SHAR_DUMMY.DUMMY
f:=Get_Info(Command_Line,"File_Name");b:=Create_Buffer("",f);
o:=Get_Info(Command_Line,"Output_File");Set (Output_File,b,o);
Position (Beginning_of(b));Loop x:=Erase_Character(1); Loop ExitIf x<>"V";
Move_Vertical(1);x:=Erase_Character(1);Append_Line;Move_Horizontal
(-Current_Offset);EndLoop;Move_Vertical(1);ExitIf Mark(None)=End_of(b)
EndLoop;Exit;
$ Delete VMS_SHAR_DUMMY.DUMMY;*
$ Checksum 'File_is
$ Success=F$Element(Check_Sum_is.eq.CHECKSUM$CHECKSUM,",",Pass_or_Failed)+CR
$ Read/Time_Out=0/Error=No_Error2/Prompt=" CHECKSUM ''Success'" SYS$Command ddd
$No_Error2: Return
$Start:
$ File_is="CRON.COM"
$ Check_Sum_is=338319989
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X$ set noverify
X$ goto begin
X               CRON.COM
X
X VMS version of the UNIX cron facility.
X This reads file: sys$manager:crontab.dat once per hour
X
X# cron exampl
X# command order:
X#Field:  1    2    3     4      5
X#      hour day month D-O-W  command
X# CRON matches against first four fields and then considers command
X# First four fields (time) can be any of the following:
X#       1) Single number --> must match exactly
X#       2) number - number --> match inclusive range
X#       3) number,number --> match any in the list
X#       4) *  --> wildcard, matches anything
X#########################################################################
X# Example:
X#       1,15 12-3 1,2,2-4 SUBMIT ACCOUNTING.JOB
X#########################################################################
X# a '#' is a comment line
X# a '%' is an EOL for the current command, anything after a % is considered
X# as input for the preceding command.
X$begin:
X$! define some constants
X$ delim   = " " ! field delimiter, change if desired
X$ dash    = "-"
X$ comma   = ","
X$ percent = "%"
X$ asterix = "*"
X$!
X$! First build current time components
X$again:
X$ show time
X$ time = f$time()
X$ current_0 = f$integer(f$cvtime(time,,"hour"))
X$ current_1 = f$integer(f$cvtime(time,,"day"))
X$ current_2 = f$integer(f$cvtime(time,,"month"))
X$ day_of_week_name = f$cvtime(time,,"weekday")
X$ if day_of_week_name .eqs. "Sunday" then current_3 = 1
X$ if day_of_week_name .eqs. "Monday" then current_3 = 2
X$ if day_of_week_name .eqs. "Tuesday" then current_3 = 3
X$ if day_of_week_name .eqs. "Wednesday" then current_3 = 4
X$ if day_of_week_name .eqs. "Thursday" then current_3 = 5
X$ if day_of_week_name .eqs. "Friday" then current_3 = 6
X$ if day_of_week_name .eqs. "Saturday" then current_3 = 7
X$!
X$ write sys$output -
V "Starting cron at hour-''current_0' day-''current_1' month-''current_2'  dow-'
X'current_3'"
X$!
X$! read a line from the table
X$ open/read/error=wait crontab sys$manager:crontab.dat
X$!
X$! process each line
X$ line_number = 0
X$next_line:
X$ line_number = line_number + 1
X$ read/end_of_file=wait crontab line
X$ write sys$output "Reading line:"
X$ sho symbol line
X$ if f$extract(0,1,line) .eqs. "#" then goto next_line ! hah, a comment line
X$ line = f$edit(line,"compress,trim,upcase")
X$!
X$! parse out the fields and test
X$! loop through first four elements of line calling check_element
X$! with paramenters current and element. Check $status on return.
X$! If an element does not match next
X$ element_number = 0
X$next_element:
X$ element = f$element(element_number,delim,line)
X$ current = current_'element_number'
X$ gosub check_element
X$ if $status .ne. 1 then goto next_line !NO MATCH drop it
X$ element_number = element_number + 1
X$ if element_number .le. 3 then goto next_element
X$!
X$! Now, if all elements match, time to do the command
X$! find the command in the line
X$ write sys$output "Executing line:"
X$ sho symbol line
X$ command = f$extract(f$locate(f$element(4,delim,line),line),200,line)
X$ if f$locate(percent,command) .ne. f$length(command) then goto data_lines
X$ if f$extract(0,3,command) .eqs. "SUB" then goto immediate_submit
X$ spawn/nowait 'command'
X$ goto next_line
X$!
X$immediate_submit:     !here is submit so do so NOW!!!
X$ spawn/nowait @'command'      ! alternate methods, choose for your system
X$! 'command
X$! submit/queue=cc$batch 'command'
X$goto next_line
X$data_lines:   !here if there are data lines to contend with
X$ data_line_number = 0
X$ open/write temp line'line_number'.com
X$next_data_line:
X$ write temp f$element(data_line_number,percent,command)
X$ data_line_number = data_line_number + 1
X$ if f$element(data_line_number,percent,command) .nes. percent then -
X       goto next_data_line
X$ close temp
X$ spawn/nowait @line'line_number'.com
X$ goto next_line
X$!
X$! wait for next go around, always synch to next even hour,
X$! this is to be sure that the proc restarts within a few seconds
X$! of the even hour
X$wait:
X$ close crontab
X$ spawn/nowait purge line*.com
X$ time = f$time()
X$ elapsed_minute = f$integer(f$cvtime(time,,"minute"))
X$ elapsed_second = f$integer(f$cvtime(time,,"second"))
X$ write sys$output -
X "Current minute: ''elapsed_minute, Current second: ''elapsed_second'"
X$!
X$ if elapsed_minute .gt. 0 then goto more_minute
X$ if elapsed_second .gt. 0 then goto more_second
X$ write sys$output "Waiting one hour- 01:00:00"
X$ wait 01:00:00
X$ goto again
X$!
X$more_second:
X$ write sys$output "Waiting 00:59:''f$string(60-elapsed_second)'"
X$ wait 00:59:'f$string(60-elapsed_second)'
X$ goto again
X$!
X$more_minute:
X$ if elapsed_second .gt. 0 then goto more_second2
X$ write sys$output "Waiting for 00:''f$string(60-elapsed_minute)':00"
V$ wait 00:'f$string(60-elapsed_minute)':00 ! if minutes non-zero and secondsare
X zero
X$ goto again
X$!
X$ more_second2:        !for min and sec more than zero
X$ write sys$output -
X "Waiting 00:''f$string(60-elapsed_minute-1)':''f$string(60-elapsed_second)'"
X$ wait 00:'f$string(60-elapsed_minute-1)':'f$string(60-elapsed_second)'
X$ goto again
X$! Subroutine to check for matches, current is part of the real
X$! current date and time , and element is the chunk of  the crontab file.
X$! Need to check element and cut up into smaller pieces if necessary
X$! and then compare to current. Note that current is an integer and
X$! element (and it's pieces) is a string
X$check_element:
X$! parse out parts of element, if there are any
X$! check simplest case first- *
X$ if f$locate(asterix,element) .eq. f$length(element) then goto no_asterix
X$ return 1     !asterix found, go ahead
X$!
X$no_asterix:
X$ sub_element_number = -1
X$!
X$find_sub_element:     !look for comma
X$ sub_element_number = sub_element_number + 1
X$ sub_element = f$element(sub_element_number,comma,element)
X$ if sub_element .eqs. comma then goto out_of_sub_elements
X$!
X$ left_side_of_dash = f$element(0,dash,sub_element)
X$ if left_side_of_dash .nes. sub_element then goto range_element
X$ if current .eq. f$integer(sub_element) then return 1 ! found match
X$ goto find_sub_element
X$!
X$range_element:        ! look for dash
X$ right_side_of_dash = f$element(1,dash,sub_element)
X$! if left is greater than right, things are not straightforward
X$ if f$integer(left_side_of_dash) .gt. f$integer(right_side_of_dash) -
X       then goto not_straightforward
X$ if current .ge. f$integer(left_side_of_dash) .and. -
X     current .le. f$integer(right_side_of_dash) then return 1 ! in range
X$ goto find_sub_element
X$!
X$not_straightforward:          !for circular times...
X$! example: range of days 27-3
X$ component_min = 1 ! for days months and dow
X$ if element_number .eq. 0 then component_min = 0 !hours
X$ if element_number .eq. 0 then component_max = 23 !hours
X$ if element_number .eq. 1 then component_max = 31 !days in month
X$ if element_number .eq. 2 then component_max = 12 !months of year
X$ if element_number .eq. 3 then component_max = 7  !days of week
X$ if (current .ge. f$integer(left_side_of_dash) .and. -
X      current .le. component_max) .or. -
X     (current .ge. component_min .and. -
X      current .le. f$integer(right_side_of_dash)) then return 1 !whew!
X$ goto find_sub_element
X$!
X$out_of_sub_elements:
X$return 3 !no matches
X$! end of subroutine check_elements
X$!
X$! end of cron.com
$ GoSub Convert_File
$ File_is="CRON_START.COM"
$ Check_Sum_is=286486196
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X$ run -
X       /detach -
X       /input = util$:[cron]cron.com -
X       /output = util$:[cron]cron.log -
X       /error = util$:[cron]cron.error -
X       /process = "Cron Server" -
X       /queue_limit = 20 -
X       /subprocess_limit = 20 -
X       /page_file = 10000 -
X       /time_limit = 0 -
X       /extent = 1024 -
X       /file_limit = 50 -
X       sys$system:loginout.exe
$ GoSub Convert_File
$ File_is="CRONTAB.DAT"
$ Check_Sum_is=1635395720
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X# cron example
X# command order:
X#Field:  1    2    3     4      5
X#      hour day month D-O-W  command
X# CRON matches against first four fields and then considers command
X# First four fields (time) can be any of the following:
X#      1) Single number --> must match exactly
X#       2) number - number --> match inclusive range
X#       3) number,number --> match any in the list
X#       4) *  --> wildcard, matches anything
X#########################################################################
X# Example:
X#       1,15 12-3 1,2,2-4 SUBMIT ACCOUNTING.JOB
X#########################################################################
X19 * * * start/queue aaa$batch
X8 * * * stop/queue/reset aaa$batch
$ GoSub Convert_File
$ Exit

