c [2,20]BATCH.FTN R RHODERICK AUG 1982 c USEPA/HERL/NTD c MD74B c Research Triangle Park, NC 27711 c Modified - MAR 1983 c added job priority capability, job status words, c reformatted ...BAT send line c This program is designed as a user interface to the USEPA/HERL/NTD c BATCH processor used to implement time-scheduled MCR command execution. c This processor allows the user to have any indirect command file c executed from another terminal, freeing the user's terminal for other c uses. Since a "BATCH log terminal" executes the user's command file, c a permanant record is available. The user can specify the time of c day for job execution to commence, and can specify deletion of the c BATCH command file when it finishes. The user may also kill the c currently active BATCH job, list the BATCH queue, and remove a BATCH c job queued for future execution (non-priviliged users may only delete c queued jobs according to their login UIC). C This program must be compiled under the F77 compiler and must be c installed with the taskname of "...BAT" for the BATCH processor to c use in scheduling itself. c Four process control commands are supplied: c -the command BAT /STArt will start the BATCH Queue Manager task. c -the command BAT /STOp causes the BATCH Queue Manager task to c exit after it completes any current BATCH job. The subcommand c " :IM " will cause any active job to be aborted, rather than c allowing it to complete before the BATCH processor stops. c -the command BAT /ENAble[/TERM=TTnn:] will enable execution of c queued BATCH jobs from terminal TTnn:. The "/TERM=TTnn:" is c optional - if it is not specified, the default is to execute jobs c from the terminal specified in a previous ENAble command, or if c no specific terminal has been ENAbled since the BATCH Queue c Manager was STArted, the BATCH log device defaults to TT0:. c The ENAble command is only effective after the BATCH Queue c Manager has been STArted. c -the command BAT /DISable causes processing of queued BATCH jobs c to be disabled after any currently executing job finishes. The c optional subcommand " :IM " causes any active job to be aborted, c as well as disabling execution of any other pending jobs. When c processing of queued jobs has been DISabled, or when the BATCH c Queue Manager has been STArted but before processing of queued c jobs has been ENAbled, jobs may be queued for execution, c but they will not be executed until processing is ENAbled. c User commands for this task are: c BAT /LI (lists all BATCH job command files in queue) c BAT /DEL:nn (deletes the batch job with entry number 'nn' c from the BATCH queue) c BAT /KIL (aborts the currently active BATCH job) c BAT ggg/mmm/paswrd commandfilespec/timeoption[/DEL][/PRI=nn] c where 'ggg/mmm/paswrd' is the logon string to pass to the HELLO task c (ggg is the UIC group number, mmm is the UIC member number, and paswrd c is the password for the account), 'commandfilespec' is the legal file c specification of an existing file, 'timeoption' is either "hh:mm" for c the time of day to queue execution of the BATCH job file (24 hour c clock), or "IM" to queue the BATCH job file for immediate execution. c /DEL (or /DE) is an optional switch requesting deletion of the job c command file after completion: the default action is to not delete the c job command file after execution. c /PRI=nn is an optional switch requesting a non-default job priority c of 'nn'. (The default job priority is 40). 'nn' is the requested c priority of the job in the BATCH queue, NOT the task priority at c which the job command file will be run, and may be from 1 to 250 c for priviliged users, or 1 to 50 for non-priviliged users. c If the delete option is requested, the job command file is deleted c after completion: if the job aborts abnormally, or if it is aborted c by the "BAT/KIL" command, the job command file is not deleted. c Note that the logon string 'ggg/mmm/paswrd' is not verified to match c an existing loggable account: upon execution, the HELLO task is simply c spawned with this string. If the HELLO task exits abnormally, the c BATCH command file is not executed, and a message to that effect is c logged to the BATCH log terminal. c ** This program uses the executive SEND DATA directive to pass c information to the BATCH QUEUE MANAGER task (...BQM). See BQM.FTN c for the SEND/RECEIVE DATA block descriptions and formats. real bqm,mcr character line*27,inline*80,filine*44,tim*8 character filec*30,cstat(6)*9 integer*2 ibuf(16),rec13(13),devtyp,pri,luic,fuic logical priv,hdr byte uic(2),log(2),ans,devcol,iuic,juic,comma,slash,colon,dot byte inl(80),filenm(30),jbuf(12),f(44),p(2) byte bluic(2),bfuic(2),stat(6) equivalence (ibuf(8),uic(1)),(ibuf(16),log(1)),(filenm,filec), + (p,pri),(luic,bluic),(fuic,bfuic),(f,filine),(inl,inline) data devtyp,line/'TT',' '/ data rec13/13*' '/ data pri/40/ !default job priority in job queue data filec/'LB00:[000,000]'/ data bqm,mcr/6rBQM...,6rMCR.../ data stat/'F','P','A','C','T','K'/ data cstat/' Future',' Pending',' Active',' Crashed','Timed out', + ' Killed'/ priv=.FALSE. !TRUE if user is priviliged hdr=.TRUE. !TRUE if no queue-list header yet written to TI: idx=5 !filename character position index call errset(64,,,,.FALSE.,) !no msg on input conversion errors line(1:1)='A' !tentative code is "A"wake batch queue manager call getmcr(inl,nchars) if(nchars.lt.6)goto 950 !if no command, just go unstop BQM... if(nchars.lt.80)inline(nchars+1:80)=' ' !blanks in rest of line c--find out user's default uic call gettsk(ibuf) if(log(2).lt."10)priv=.TRUE. c--check if this is request to start batch processor if(index(inline(:nchars),'/STA').eq.0)goto 2 c--it is: make sure user is priviliged, then run the batch queue manager task if(.not.priv)goto 840 call reques(bqm,,ier) if(ier.eq.-2)write(2,200) 200 format(' BATCH Queue Manager task not installed') goto 990 c--check if this is any other priviliged command 2 if(index(inline(:nchars),'/STO').eq.0 +.and.index(inline(:nchars),'/ENA').eq.0 +.and.index(inline(:nchars),'/DIS').eq.0)goto 205 c--it is: make sure user is priviliged if(.not.priv)goto 840 if(index(inline(:nchars),'/STO').ne.0)goto 204 if(index(inline(:nchars),'/DIS').ne.0)goto 203 c--request to enable processing of jobs line(2:5)=' ' line(1:1)='E' c--see if terminal number specified if(index(inline(:nchars),'TT').eq.0)goto 950 i=index(inline(:nchars),'/TERM=TT')+8 if(i.eq.8)goto 860 if(index(inline(i:),':').eq.0)goto 860 j=index(inline(i:),':')+i-2 read(inline(i:j),201,err=860)k 201 format(o) write(line(2:5),202)k 202 format('TT',o2.2) goto 950 c--request to disable processing of queued jobs 203 line(1:1)='C' c immediate, or after any active job finishes? if(index(inline(:nchars),':IM').ne.0)line(1:1)='D' goto 950 c--request to stop the batch processor 204 line(1:1)='S' c immediate, or after any active job finishes? if(index(inline(:nchars),':IM').ne.0)line(1:1)='X' goto 950 c--if kill, remove or list request, open queue file and check c request for valid request 205 if(index(inline(:nchars),'/KIL').eq.0.and. + index(inline(:nchars),'/DE:').eq.0.and. + index(inline(:nchars),'/DEL:').eq.0.and. + index(inline(:nchars),'/LI').eq.0)goto 4 c--open batch queue file and skip first record open(unit=1,file='LB:[1,7]BATCHQUE.SYS',status='old', +recordtype='fixed',form='unformatted',shared,readonly,err=810) read(1)filine c--check if this is a request to kill the current job if(index(inline(:nchars),'/KIL').eq.0)goto 3 line(1:1)='K' 206 READ(1,END=830)FILINE IF(FILINE(40:40).NE.'A')goto 206 c--check that user is priviliged to kill the currently executing job read(filine(21:23),210)i 210 format(o3) if(.not.priv.and.log(2).ne.i)goto 840 goto 950 c--check if this is a list request (handle "BAT/LI" and "BAT /LI") 3 if(index(inline(:nchars),'/LI').eq.0)goto 330 c--user requested listing of job(s) from queue file write(2,50)filine(2:24) 50 format(' - ',a23,' -') 51 read(1,end=990)filine i=f(43) if(i.eq.0)goto 990 !entry# 0 - no more valid recs in file if(hdr)write(2,52) !write list header one time hdr=.FALSE. 52 format(' Entry # Status',12X,'Job file',20X, + 'Sched time Priority') do 53 m=1,6 53 if(f(40).eq.stat(m))goto 54 54 j=26+index(filine(27:35),' ')-1 !position of last filename character if(j.lt.27)j=35 line(1:5)=' ' if(filine(39:39).eq.'Y')line(1:5)='(Del)' p(1)=f(44) write(2,55)i,cstat(m),filine(17:20),filine(21:23), +filine(24:26),filine(27:j),filine(36:38),line(1:5), +filine(1:2),filine(3:4),pri 55 format(1h 2x,i2.2,5x,a9,3x,a4,':[',a3,',',a3,']',a, +'.',a3,2x,a5,t61,a2,':',a2,7x,i3) goto 51 c--request to delete an entry ('/DE:' or '/DEL:') 330 j=index(inline(:nchars),'/DE:') if(j.eq.0)j=index(inline(:nchars),'/DEL:') if(j.eq.0)goto 860 c--get the queue entry number from the request i=j+index(inline(j:),':') c--put entry number in send line (2:4), and 'R'emove-entry code in (1:1) line(1:1)='R' read(inline(i:i+2),302,err=820)i 302 format(bn,i3) write(line(2:4),303)i 303 format(i3.3) 301 read(1,end=820)filine if(f(43).eq.0)goto 820 c--see if this is the entry we want if(f(43).ne.i)goto 301 c--if this entry is currently active, cannot delete it if(filine(40:40).ne.'A')GOTO 305 write(2,304) 304 format(' Job is currently active - cannot delete it from queue') goto 990 c--check that user is priviliged to delete this entry 305 read(filine(21:23),210)i if(.not.priv.and.log(2).ne.i)goto 840 goto 950 c--move logon group/member/password string to send buffer c--find first non-space after 'BAT' and first '/' in mcr line 4 j=index(inline(:nchars),' ')+1 k=j+index(inline(j:nchars),'/')-2 if(k-j.lt.0.or.k-j.gt.3)goto 860 read(inline(j:k),5,err=860)bluic(1) 5 format(o3) j=k+2 k=j+index(inline(j:nchars),'/')-2 if(k-j.lt.0.or.k-j.gt.3)goto 860 read(inline(j:k),5,err=860)bluic(2) j=k+2 k=j+index(inline(j:nchars),' ')-2 if(k-j.gt.6)goto 860 if(k-j.gt.0)write(line(6:11),8)inline(j:k) 8 format(a) c-- point to next character in mcr line j=k+2 c--put user's default device in send line call assign(1,'SY:') call getlun(1,jbuf) write(line(12:15),9)jbuf(1),jbuf(2),jbuf(3) 9 format(2a1,i2.2) c--and in file spec filec(1:4)=line(12:15) filec(5:5)=':' c--see if user specified a device and/or uic in input line filespec slash=j-1+index(inline(j:nchars),'/') if(slash.eq.0)goto 890 devcol=index(inline(:slash),':') dot=index(inline(:slash),'.') iuic=index(inline(:nchars),'[') if(iuic.eq.0)goto 10 juic=index(inline(:nchars),']') comma=index(inline(:nchars),',') 10 colon=slash-1+index(inline(slash:nchars),':') if(devcol.eq.0)goto 12 c--device specified: move it to the file spec idx=0 filec(1:5)=' ' do 11 i=j,devcol if(inl(i).eq.' ')goto 11 idx=idx+1 filenm(idx)=inl(i) 11 continue j=devcol+1 c--and to the send line line(12:13)=filec(1:2) if(idx.eq.4)line(15:15)=filec(idx-1:idx-1) if(idx.eq.5)line(14:15)=filec(idx-2:idx-1) 12 filenm(idx+1)='[' do 13 i=idx+2,idx+8 13 filenm(i)='0' filenm(idx+5)=',' filenm(idx+9)=']' idx=idx+10 if(iuic.ne.0)goto 20 c--no uic specified: put user's default uic in file spec k=uic(2) do 15 i=idx-6,idx-8,-1 filenm(i)=(k.and."7)+48 15 k=k/8 k=uic(1) do 16 i=idx-2,idx-4,-1 filenm(i)=(k.and."7)+48 16 k=k/8 goto 30 c--uic specified: move uic spec from input line to file spec 20 i=idx-6 do 22 l=comma-1,iuic+1,-1 filenm(i)=inl(l) 22 i=i-1 i=idx-2 do 25 l=juic-1,comma+1,-1 filenm(i)=inl(l) 25 i=i-1 j=juic+1 c--save filespec uic for send line 30 read(filec(idx-8:idx-6),5)bfuic(1) read(filec(idx-4:idx-2),5)bfuic(2) c--if user non-priviliged, don't allow to queue job outside user group read(filec(idx-8:idx-6),210)i if(.not.priv.and.log(2).ne.i)goto 840 c--move the input line file name to the file spec k=idx do 31 i=j,slash-1 if(inl(i).eq.' ')goto 31 filenm(idx)=inl(i) idx=idx+1 31 continue if(dot.gt.0)goto 32 c--add default file extension of '.CMD' to file name filec(idx:idx+3)='.CMD' dot=idx idx=idx+4 32 filenm(idx)=0 dot=index(filec(:idx-1),'.') line(16:24)=filec(k:dot-1) if(idx-1.gt.dot)line(25:27)=filec(dot+1:idx-1) c--make sure the batch job file exists call errset(29,,,,.FALSE.,) !no msg on no such file errors call errset(30,,,,.FALSE.,) !no msg on file open errors call errset(43,,,,.FALSE.,) !no msg on illegal filespec errors open(unit=3,file=filenm,status='old',readonly,err=850) close(unit=3) c--priority switch? i=index(inline(:nchars),'/PRI=')+5 if(i.le.5)goto 37 pri=0 k=0 do 33 j=i,i+3 33 if(inline(j:j).ge.'0'.and.inline(j:j).le.'9')k=j 34 if(k.eq.0)goto 860 read(inline(i:k),35,err=860)pri 35 format(i) if(pri.eq.0.or.pri.gt.250)goto 870 !requested priority within range? c--check that user has privilige for this priority if(.not.priv.and.pri.gt.50)goto 840 c--immediate switch? 37 if(index(inline(:nchars),'/IM').eq.0)goto 38 line(1:1)='I' c--delete switch? if(index(inline(:nchars),'/DE').ne.0)line(1:1)='H' goto 950 c--time specified 38 line(1:1)='G' c--delete switch? if(index(inline(:nchars),'/DE').ne.0)line(1:1)='F' c--move the time spec from the input line to the match line if(inl(slash+3).ne.':'.or. +inl(slash+1).gt.'2'.or.inl(slash+1).lt.'0'.or. +inl(slash+2).gt.'9'.or.inl(slash+2).lt.'0'.or. +inl(slash+4).gt.'5'.or.inl(slash+4).lt.'0'.or. +inl(slash+5).gt.'9'.or.inl(slash+5).lt.'0')goto 40 line(2:3)=inline(slash+1:slash+2) line(4:5)=inline(slash+4:slash+5) goto 950 c--handle "/H:MM" time specification 40 if(inl(slash+2).ne.':'.or. +inl(slash+1).gt.'9'.or.inl(slash+1).lt.'0'.or. +inl(slash+3).gt.'5'.or.inl(slash+3).lt.'0'.or. +inl(slash+4).gt.'9'.or.inl(slash+4).lt.'0')goto 880 line(2:2)='0' line(3:3)=inline(slash+1:slash+1) line(4:5)=inline(slash+3:slash+4) c--if time specified is same as current time or next minute, c treat this as an immediate execution request call time(tim) read(line(2:5),45)ih,im 45 format(2i2) read(tim(1:5),46)lh,lm 46 format(i2,x,i2) ih=(lh-ih)*60+lm-im if(ih.eq.0.or.ih.eq.-1)line(1:1)='I' goto 950 810 write(2,811) 811 format(' ERROR opening BATCH queue file -exiting') goto 990 c--user asked to remove a non-existent entry number 820 write(2,821) 821 format(' Not a pending entry number') goto 990 830 write(2,831) 831 format(' No job currently active') goto 990 c--non-priv user tried to queue job file outside his user group c or asked for job priority greater than 50 840 write(2,841) 841 format(' BAT - privilege violation') goto 990 c--user specified non-existant file for batch job file 850 write(2,855)filec 855 format(' ERROR - ',A30,' - no such file exists') goto 990 860 write(2,861) 861 format(' Illegal syntax') goto 990 870 write(2,871) 871 format(' Requested job priority ouside acceptable range') goto 990 880 write(2,881) 881 format(' Illegal time specification') goto 990 890 write(2,891) 891 format(' Illegal syntax - no operation specified') goto 990 c--exit for successful operation - c--unstop batch queue manager task & send command to it 950 call irad50(27,line,rec13) rec13(10)=luic rec13(11)=fuic rec13(12)=pri call send(bqm,rec13) call ustp(bqm,ier) if(ier.eq.-2.or.ier.eq.-7)write(2,955) 955 format(' BATCH processor unavailable') 990 call exit end