zar@JULIET.CALTECH.EDU.UUCP (06/18/87)
$!------------------------------Cut Here------------------------- $ chk = "1209503388" $ required = "nm1.for" $ if "''f$search(required)'".eqs."" then write sys$output - "File NM1.FOR must exist prior to running this procedure." $ if "''f$search(required)'".eqs."" then exit %x2c $ create nm2.for $ deck/dollars="ThEgReAtZaR" c+++++++ c c Set the ownership of this process to the master owner process ID c ncputim(point,cpu_average) = ncputim(point,cpu_average) + 1 sts(point) 13 continue if (owner(point).ne.0) then i = 1 do while(pid(i).ne.owner(point).and.i.le.maxseqnum) i = i + 1 end do if (i.le.maxseqnum) then if (owner(i).ne.0) then owner(point) = owner(i) goto 13 else c c While we have a pointer to the master PID, make sure the c authorized base priorities are the same if this is a sub- c process (possible for Nanny to lower prio, user spawns, c and subproc authpri is one lower than master (it could c propogate, too)) c if (authpri(point).lt.authpri(i).and.owner(point) 1 .ne.0) authpri(point) = authpri(i) c c If this subprocess has been idle less than master, decrease c master's warnings count c j = lib$extzv(0,16,warn(point)) k = lib$extzv(0,16,warn(i)) imsk2 = 'ffffefff'x.or.functmsk !Function 13 if (owner(point).ne.0.and.imsk2.eq.'ffffffff'x 1 .and.j.lt.k) warn(i) = (lib$extzv(0,16,warn(point)) 2 + lib$extzv(16,16,warn(i)) * 2**16) c c If this is a subprocess, and the master isn't a interactive c process, the process type should be equiv to the master c if (owner(point).ne.0.and.system(i).ne.nan$v_inter 1 .and.system(i).ne.nan$v_inter+nan$_system) 2 system(point) = system(i) end if end if end if c+++++++ c c If this user has used more than his/her share of cpu, lower c priority, else raise. c upri = -1 if (system(point).lt.nan$v_unknown.and. 1 authpri(point)-prib(point).le.1) then if (system(point).eq.nan$v_batch) imsk='fffffffe'x.or. 1 functmsk !Function 1 if (system(point).eq.nan$v_detach) imsk='fffffffd'x.or. 1 functmsk !Function 2 if (system(point).eq.nan$v_inter) imsk='fffffffb'x.or. 1 functmsk !Function 3 if (system(point).eq.nan$v_network) imsk='fffffff7'x.or. 1 functmsk !Function 4 if (owner(point).ne.0) imsk='ffffffef'x.or. 1 functmsk !Function 5 if (imsk.ne.'ffffffff'x) goto 7 !Function disabled c c Preference in raising or lowering priorities c preadd = 0.0 imsk = 'fffdffff'x.or.functmsk !Function 18 if (imsk.eq.'ffffffff'x) then acc_p = 1 do while(account(point)(:len1(account(point))).ne. 1 prefacc(acc_p)(:len1(prefacc(acc_p))).and.prefadd(acc_p) 2 .le.100.0) acc_p = acc_p + 1 end do if (prefadd(acc_p).le.100.0) preadd = prefadd(acc_p) end if if (usedpri(authpri(point)).le.0) then if (debugging.gt.0) then write(message(1:4),'(i4)') usedpri(authpri(point)) write(message(5:6),'(i2)') authpri(point) call output(1,'Number of users @priority '// 1 message(5:6)//' is '//message(1:4)//'. Reset to 1') end if usedpri(authpri(point)) = 1 end if upri = -1 new_cputim = 0.0 do i=1,cpu_average new_cputim = new_cputim + float(ncputim(point,i)) end do c c Total new CPU for averaging cycles / # of averaging cycles / c (cycle time * preference) c new_cputim = new_cputim / float(cpu_average) / 1 float(waitim) !(float(waitim)*preadd) c c If (cycle time / # users @ this prio) / cycle time < 90% of above c drop priority, else if > 110% of above raise if prio is low. c if ((float(waitim)/float(usedpri(authpri(point))))/ 1 float(waitim).lt.new_cputim*0.9) then upri = authpri(point) - 1 else if ((float(waitim)/float(usedpri(authpri( 1 point))))/float(waitim).gt.new_cputim*1.1) then if (authpri(point).gt.prib(point)) upri = 1 authpri(point) end if if (upri.gt.0.and.upri.ne.prib(point)) then 5 continue code = sys$setpri(pid(point),,%val(upri),) if (code.eq.ss$_normal.or.code.eq.ss$_nonexpr) then if (debugging.ne.0) then write(message,'(a,i1,a,i1,a,i1,f7.3)') username( 1 point)(:len1(username(point)))//' priority changed'// 2 ' to ',upri,' from ',prib(point),': usertype = ', 3 system(point),new_cputim call output(1,message(:len1(message))) if (code.eq.ss$_normal) then if (upri.gt.prib(point)) call sys$brkthru(,%descr( 1 'Nanny: Your priority has been restored'),%descr( 2 terminal(point)(:len1(terminal(point)))),%val( 3 brk$c_device),,,,,%val(5),,) if (upri.lt.prib(point)) call sys$brkthru(,%descr( 1 'Nanny: Your priority has been lowered'),%descr( 2 terminal(point)(:len1(terminal(point)))),%val( 3 brk$c_device),,,,,%val(5),,) end if end if prib(point) = upri crush_p = crush_p + 1 crush(crush_p) = pid(point) crpri(crush_p) = authpri(point) else if (bug(code,'SETPRI').ne.ss$_normal) then write(message,'(a,i1,a,z8)') 'Unable to change '// 1 username(point)(:len1(username(point)))//' to pri'// 2 'ority ',upri,' because: ',code call output(1,message(:len1(message))) end if end if end if 7 continue c+++++++ c c Suspend low priority processes if memory is fully utilized c if (suspendok.and.authpri(point).eq.lowbat.and. 1 system(point).eq.nan$v_batch) then if (debugging.eq.1) then code = ss$_normal else code = sys$suspnd(pid(point),) end if if (bug(code,'SUSPND').eq.ss$_normal) then if (debugging.ne.1) write(message,'(a,i1,a)',err=9) 1 username(point)(:len1(username(point)))//'''s batch '// 2 'job was suspended at priority ',authpri(point), 3 ' (low mem)' call output(1,message(:len1(message))) suspendok = .false. suspids = suspids + 1 susp_ipid(suspids) = ipid(point) susp_pid(suspids) = pid(point) else call output(1,'Unable to suspend '//username(point)(: 1 len1(username(point)))//'''s batch job (low mem)') end if 9 continue end if end if c+++++++ c c Check for idle processes c imsk = 'ffffdfff'x.or.functmsk !Function 14 c c If the process is normal interactive, normal subprocess, or c (system inetractive and system logoff is on), then... c if (maxidle.ne.0.and.(system(point).eq.nan$v_inter 1 .or.system(point).eq.nan$v_subproc.or.(system(point) 2 .eq.nan$v_inter+nan$_system.and.imsk.eq.'ffffffff'x))) 3 then c c If the process has been idle => maxidle and (a subprocess or c a interactive process with a physical terminal) then... c if (lib$extzv(0,16,warn(point)).ge.maxidle.and.(( 1 lench(phy_term(point)).gt.0.and.(system(point).eq. 2 nan$v_inter.or.system(point).eq.nan$v_inter+ 3 nan$_system)).or.system(point).eq.nan$v_subproc)) 4 then c c If tree logoff is on and this is a subprocess, ignore c imsk2 = 'ffffefff'x.or.functmsk !Function 13 if (imsk2.ne.'ffffffff'x.or.(imsk2.eq.'ffffffff'x 1 .and.system(point).ne.nan$v_subproc)) then if (debugging.ne.1) then code = sys$forcex(pid(point),,%val('2c'x)) call bug(code,'FORCEX') code = sys$delprc(pid(point),) else code = ss$_normal end if message = username(point)(:len1(username(point)))// 1 ' on '//terminal(point)(:len1(terminal(point)))// 2 ' has been logged off by Nanny'//char(7) if (bug(code,'DELPRC').eq.ss$_normal) then code = ss$_normal if (system(point).ne.nan$v_subproc) code = 1 sys$brkthru(,%descr(message(:len1(message))), 2 %descr(terminal(point)(:len1(terminal(point)))), 3 %val(brk$c_device),,,,,%val(5),,) call bug(code,'BRKTHRU') call output(2,message(:len1(message)-1)) pid(point) = 0 else if (code.ne.ss$_nonexpr) then call output(1,'Unable to logoff '//username( 1 point)(:len1(username(point)))//' on '// 2 terminal(point)(:len1(terminal(point)))) else call output(2,message(:len1(message)-1)) pid(point) = 0 end if end if end if end if c c If the process has been idle => maxidle/2 and we haven't warned c this process already, then... c if (lib$extzv(0,16,warn(point)).ge.maxidle/2.and. 1 warned(point).lt.1) then warned(point) = warned(point) + 1 code = ss$_normal imsk='ffffbfff'x.or.functmsk !Function 15 i = (maxidle - lib$extzv(0,16,warn(point))) * 1 waitim if (imsk.eq.'ffffffff'x.and.system(point).ne. 1 nan$v_subproc) call warnuser(pid(point), 2 terminal(point),username(point),i) end if c c If the process has one cycle left before maxidle = idle time and c we haven't warned this process already, then... c if (lib$extzv(0,16,warn(point)).ge.maxidle-2.and. 1 warned(point).lt.2) then warned(point) = warned(point) + 1 imsk='ffff7fff'x.or.functmsk !Function 16 if (imsk.eq.'ffffffff'x) then message = char(7)//username(point)(:len1( 1 username(point)))//' on '//terminal(point)(:len1( 2 terminal(point)))//' has been inactive. Last '// 3 'warning prior to process deletion'//char(7)// 4 char(7) code = ss$_normal if (system(point).ne.nan$v_subproc) code = 1 sys$brkthru(,%descr(message(:len1(message))), 2 %descr(terminal(point)(:len1(terminal(point)))), 3 %val(brk$c_device),,,,,%val(5),,) call bug(code,'BRKTHRU') end if end if end if c+++++++ c c Elapsed time logoff doesn't care what you are doing (CPU and c I/O activity are ignored). c imsk = 'ffffdfff'x .or. functmsk !Function 14 if (maxelapsed.gt.0.and.(system(point).eq.nan$v_inter 1 .or.system(point).eq.nan$v_subproc.or.(system(point) 2 .eq.nan$v_inter+nan$_system.and.imsk.eq.'ffffffff'x))) 3 then c c Terminate the program execution of a user if maxelapsed time c has been exceeded (idle logoff will destroy the user later c we hope). Idle logoff normally gets them before this check c unless the program being run is something like KERMIT which c increases I/O and CPU even though the user hasn't touched the c keyboard. c if (lib$extzv(16,16,warn(point)).ge.maxelapsed) then if (debugging.ne.1) then code = sys$forcex(pid(point),,%val('2c'x)) else code = ss$_normal end if message = username(point)(:len1(username(point)))// 1 ' on '//terminal(point)(:len1(terminal(point)))// 2 ' has exceeded maximum login time'//char(7) if (bug(code,'FORCEX').eq.ss$_normal) then code = ss$_normal if (system(point).ne.nan$v_subproc) code = 1 sys$brkthru(,%descr(message(:len1(message))), 2 %descr(terminal(point)(:len1(terminal(point)))), 3 %val(brk$c_device),,,,,%val(5),,) call bug(code,'BRKTHRU') call output(2,message(:len1(message)-1)) warn(point) = lib$extzv(0,16,warn(point)) else if (code.ne.ss$_nonexpr) then call output(1,'Unable to FORCEX '//username( 1 point)(:len1(username(point)))//' on '// 2 terminal(point)(:len1(terminal(point)))) else call output(2,message(:len1(message)-1)) warn(point) = lib$extzv(0,16,warn(point)) end if end if end if c c They do get one warning prior to exceeding maxelapsed c if (lib$extzv(16,16,warn(point)).ge.maxelapsed-1) then message = char(7)//username(point)(:len1( 1 username(point)))//' on '//terminal(point)(:len1( 2 terminal(point)))//' has exceeded maximum login '// 3 'time. Image will be terminated regardless of '// 4 'user actions'//char(7)//char(7) code = ss$_normal if (system(point).ne.nan$v_subproc) code = 1 sys$brkthru(,%descr(message(:len1(message))), 2 %descr(terminal(point)(:len1(terminal(point)))), 3 %val(brk$c_device),,,,,%val(5),,) call bug(code,'BRKTHRU') end if end if end if end do c+++++++ c c We will reset priorities we lowered in (waitim/10) seconds c c second3(1) = waitim * -100000 c code = sys$setimr(,second3,boost,%val(2)) c if (bug(code,'SETIMR').ne.ss$_normal) call output(1,'Unable '// c 1 'to reset priorities') c+++++++ c c Resume low priority batch jobs if memory is not being used c (first in last out one resumed per cycle) c imsk = 'ffffffbf'x.or.functmsk !Function 7 if (imsk.eq.'ffffffff'x.and.wstotal.lt.lowphymem.and. 1 lowphymem.ne.0.and.suspids.gt.0) then if (resumeok) then point = susp_ipid(suspids) if (debugging.eq.1) then code = ss$_normal else code = sys$resume(susp_pid(suspids),) end if if (code.eq.ss$_normal.or.code.eq.ss$_nonexpr) then susp_ipid(suspids) = 0 susp_pid(suspids) = 0 suspids = suspids - 1 call output(1,'Resumed '//username(point)(:len1(username( 1 point)))//' (mem)') else call bug(code,'RESUME') call output(1,'Unable to resume '//username(point)(:len1( 1 username(point)))//' (mem)') end if else resumeok = .true. end if else resumeok = .false. end if c------- c c Create a new log file for each day. c 2 first = .false. call date(cur_date) if (cur_date(1:2).ne.old_date) then if (debugging.ne.0) then write(message,'(a40,i5)',err=8) 'Daily maximum physical '// 1 'memory usage was ',maxwstot call output(1,message(:len1(message))) maxwstot = 0 end if 8 call new_log(dumy) old_date = cur_date(1:2) cycle_num = 0 c c Purge working set at midnight if WSPurge is off c if (.not.purgews) then code = sys$purgws(wstore) call bug(code,'PURGWS') end if call dayweek(.false.) dst_chk = .true. end if c c Change SYS$ANNOUNCE to node name + load average c imsk = 'f7ffffff'x .or. functmsk !Function 28 if (imsk.eq.'ffffffff'x) then c call something !??? end if c c Daylight savings check (2:00am) c call time(cur_date(1:8)) if (dst_chk.and.cur_date(1:2).eq.'02') then imsk = 'efffffff'x .or. functmsk !Function 29 if (imsk.eq.'ffffffff'x) call dayweek(.false.) dst_chk = .false. end if c c Are we debugging the Nanny c debugging = 0 imsk = 'bfffffff'x .or. functmsk !Function 31 if (imsk.eq.'ffffffff'x) debugging = 1 imsk = '7fffffff'x .or. functmsk !Function 32 if (imsk.eq.'ffffffff'x) debugging = 2 !debugging + 2 c c Purge working set and wait for another cycle c if (purgews.or.ws_mem_purge) then code = sys$purgws(wstore) call bug(code,'PURGWS') end if call sys$hiber() call sys$cantim(%val(1),) c c If we were told to DIE, do so c if (die.eq.1) then close(unit=6) call sys$delmbx(%val(mbxchan)) call exit end if c c Loop again c goto 1 c c Errors c 3 call output(2,'Forced exit: Parameter file error') call sys$exit(%val('2c'x)) 4 call output(2,'Forced exit: Timer error') call sys$exit(%val('2c'x)) c end ThEgReAtZaR $ checksum nm2.for $ if chk.nes.checksum$checksum then write sys$output - "NM2.FOR didn't pass checksum. File may be corrupted." $ if chk.nes.checksum$checksum then exit %x2c $ copy/log nm1.for+nm2.for nmain.for $ if $status then delete/log nm1.for;,nm2.for; $ exit