x9(uNANNY023_FULL.SAV{NANNY023_FULL.SAV@BAC/LOG [-.X]WW%.COM DIST$:[NANNY]NANNY023_FULL.SAV/SAV/BLO=2048 ZAR @diwV4.5 _IAGO:: +  _HSC$DUA1: V4.5  *[NANNY.X]WW1.COM;1+, ./ 4N-~0123KPWOV56X u7D6w8sԪ9GHJA$!------------------------------Cut Here-------------------------$ chk = "1081159958"$ create NT1.TMP$ deck/dollars="ThEgReAtZaR"%\font\chapfont=cmbx10 scaled\magstep3*\font\subrubfont=cmbx10 scaled\magstephalf\parskip=\bigskipamount\parindent=0mm\hsize=6.3 truein\hoffset=1.0 truein\vsize=9.7 truein\voffset=1.0 truein\footline={\hfil}$\headline={\it\firstmark\hfil\folio}.\def\makeheadline{\vbox to 0pt{\vskip-.7truecm \ifnum\pageno=1 \else> \ifnum\pageno<0 \line{\it\hfil\folio}\smallskip \hrule8 \else \line{\the\headline}\smallskip\hrule\fi\fi \vss}\nointerlineskip}<\newcount\chapcount \newcount\subcount \newcount\subsubcount'\chapcount=0 \subcount=0 \subsubcount=05\def\chapter#1\par{\vskip 0pt plus.4\vsize \goodbreak. \vskip 0pt plus-.4\vsize \bigskip \bigskip7 \advance \chapcount by 1 \subcount=0 \subsubcount=06 \chapcontents{#1}\mark{\the\chapcount.\enspace#1}%F {\chapfont \setbox0=\hbox{\the\chapcount.\enspace}\hNANNY023_FULL.SAV ~[NANNY.X]WW1.COM;1Np<angindent=\wd0+ \baselineskip=20truept \raggedright- \noindent \box0 #1\bigskip \nobreak}}4\def\subrub#1\par{\vskip 0pt plus.3\vsize \goodbreak% \vskip 0pt plus-.3\vsize \bigskip* \advance \subcount by 1 \subsubcount=0 \subcontents{#1}%F {\subrubfont \setbox0=\hbox{\the\chapcount.\the\subcount\enspace}%/ \baselineskip=17truept \hangindent=\wd0: \raggedright \noindent \box0 #1\medskip \nobreak}}7\def\subsubrub#1\par{\vskip 0pt plus.3\vsize \goodbreak% \vskip 0pt plus-.3\vsize \bigskip \advance \subsubcount by 1 \subsubcontents{#1}%N {\bf\setbox0=\hbox{\the\chapcount.\the\subcount.\the\subsubcount\enspace}%/ \baselineskip=14truept \hangindent=\wd0: \raggedright \noindent \box0 #1\medskip \nobreak}}\newwrite\contents-\immediate\openout\contents=\jobname.contentsA\def\chapcontents#1{\immediate\write\contents{\noexpand\chapline%' {\the\pageno}{\the\chapcount}{#1}}}?\def\subcontents#1{\immediate\write\contents{\noexpand\subline%5 {\the\pageno}{\the\chapcount.\the\subcount}{#1}}}E\def\subsubcontents#1{\immediate\write\contents{\noexpand\subsubline%F {\the\pageno}{\the\chapcount.\the\subcount.\the\subsubcount}{#1}}}J\long\def\bye{\immediate\closeout\contents\vfil\supereject\docontents\end}7\def\docontents{\pageno=-1\bf\parskip=0pt\parindent=0pt9 \def\punkter{\leaders\hbox to .75em{\hss.\hss}\hfill}H \def\chapline##1##2##3{\smallskip\noindent##2\enspace##3\punkter##1}M \def\sub7BNANNY023_FULL.SAV ~[NANNY.X]WW1.COM;1Nline##1##2##3{\smallskip\noindent\qquad##2\enspace##3\punkter##1}0 \def\subsubline##1##2##3{\smallskip\noindent. \qquad\qquad##2\enspace##3\punkter##1} \vglue1cm \input \jobname.contents \vfil\supereject}=\newskip\ttglue{\tt \global\ttglue=.5em plus.25em minus.15em}\chardef\other=12A\def\ttverbatim{\begingroup \catcode`\\=\other \catcode`\{=\other< \catcode`\}=\other \catcode`\$=\other \catcode`\&=\other< \catcode`\#=\other \catcode`\%=\other \catcode`\~=\other) \catcode`\_=\other \catcode`\^=\other \obeyspaces \obeylines \tt}{\obeyspaces\gdef {\ }}\def\;{\char'73 }\catcode`\;=\activeJ{\obeylines\gdef;{\ttverbatim\spaceskip=\ttglue\let^^M=\ \let;=\endgroup}} \font\BIG=cmbx10 scaled\magstep5 \null\vfil+\centerline{\BIG N A N N Y}\bigskip\bigskipH\centerline{``A VAX without a Nanny is like a child without a mother.''}"\medskip\centerline{A Creation Of}\centerline{Zar Limited}\vfilAThe contents of this document and all matter described herein areHlicensed solely by Zar Limited and must not be duplicated or transferredEwithout written consent of Zar Limited. Questions and comments can be directed to:\bigskip"\line{\hskip 2in Daniel Zirin\hss}!\line{\hskip 2in Zar Limited\hss}"\line{\hskip 2in P.O.~Box 372\hss}(\line{\hskip 2in Pasadena, Ca 91102\hss}\bigskip\bigskip\eject \pageno=1\chapter Introduction=Nanny is a program to maintain an even balance of CPU for allEnon-system processes, to perform special(NANNY023_FULL.SAV ~[NANNY.X]WW1.COM;1N; memory management functions,Gto logoff idle processes, to allow individual users special commands to?manipulate processes with the same UIC, and to do various other6functions available to system users or standard users.DNanny runs as a detached system process in an endless loop, checkingEfor new processes, updating the states of old processes, checking forGprocesses removed from the system, and performing other functions. EachIloop is a cycle and at the end of each cycle, Nanny will wait a specifiedGtime (usually between 15 and 60 seconds) before starting another cycle.BDuring each cycle, Nanny may also read commands from a system-wideIpermanent mailbox assigned to the logical name NANNYS\$BOX. Included withFthis package are several programs which use Nanny's commands. When youEdistribute these programs to your VAX community, it is a good idea toGprotect the source and only allow access to the executable. If you feelHtoo threatened by allowing use of one or many Nanny commands, a bit mask1exists to disable one or all of Nanny's commands.>Each time Nanny is started, she reads predefined values from aAparameter file and, optionally, a Nanny command file to determineDyour system's site-specific requirements and system dependent valuesDthat allow each system a means of modifying Nanny in accord with theGneeds of your computer. For more flexibility, a special command permitsCyou to reread these values. In addition, you can ask that Nanny useEmultiple parameter files for definvPNANNY023_FULL.SAV ~[NANNY.X]WW1.COM;1N0 ing Nanny's actions during specifictimes of the day.@Each and every action Nanny takes, including any errors that mayGoccur, are written into a log file. This log file is always closed whenDNanny isn't writing data to the logfile, so you may edit or type theFlogfile at any time. Many errors and/or status messages from the Nanny8will also appear on designated Nanny operator terminals.@The next few sections will describe each command and function ofNanny.\chapter PrioritiesGNanny has a priority dither function to keep processes from hogging theHCPU (usually interactive processes). To enable priority dither, you needEto change bits in the function enable bit mask (explained later). TheEfollowing algorithm determines what priority a process may have after-each cycle if the priority dither is enabled:$$0\eqalign{newpri = &oldpri + 1 \hbox{\quad if}\cr5 &cpuused < cycletime / numusers\cr}$$or$$0\eqalign{newpri = &oldpri - 1 \hbox{\quad if}\cr? &cpuused > ( cycletime / numusers ) * 1.1\cr}$$F$Numusers$ are all processes with the same login priority AND the sameBjob mode (such as batch or interactive mode) AND does not increaseCbecause of duplicate users. For example, if the users DXL, SHR, andFDMR were all batch jobs with a login priority of 3, $numusers$ for DXLDwould be the value 3. But if DXL added another job to the same batchFqueue (with the same login priority), $numusers$ would still be 3 onlyEallowing DXL one third of th^fNANNY023_FULL.SAV ~[NANNY.X]WW1.COM;1Ne CPU no matter how many jobs he added toFthe same queue (this is optional and can be determined by bit flags inFthe function enable bit mask for each process type). $Cpuused$ is yourFaccumulated CPU usage since the last cycle. Priorities are not loweredAless than the process' login priority less one and are not raisedEabove the process' login priority. The $cycletime$ is determined fromEthe parameter file, described in detail later. It is also possible toEask Nanny to use a running average in determining CPU use by changinga parameter file variable.\chapter Idle processesEAll non-system interactive processes are checked during each cycle toEdetermine if the user has been idle. If the process has been idle forHmore than the allowed time, the process is deleted. This action, though,Lis not taken without warnings. A warning is sent to the process at $maxtime$Gdivided by 2 and again at $maxtime-cycle\ time$ before logout. When theKprocess is logged out, an appropriate message is displayed at the process'sIterminal. $Idle\ time$, $maxtime$, and $cycle\ time$ are constants in theparameter file.GThe value $maxtime$ starts out as the default idle time. Users are thenKallowed to change their own $maxtime$ values within the minimum and maximumGidle time values using the Nanny command IDLESET. Default, minimum, and=maximum idle time settings are defined in the parameter file.GIt is possible to have a process not appear idle to Nanny when in fact,Hit is (such as KERMIT istNANNY023_FULL.SAV ~[NANNY.X]WW1.COM;1NC server mode). To handle this, Nanny has anotherGoptional $maxelapsed$ parameter file variable that will force a user toIexit an image after the time specified by $maxelapsed$ (usually somethinglike 18-20 hours).\chapter Memory ManagementFDuring peak use hours on your CPU, responce time for interactive usersHdeteriorates as less an less memory is available and more and more usersGlogin (especially if you have to start swapping processes out of core).ITo increase responce time, Nanny has bits in the function enable bit mask9to allow Nanny to manage memory for your overcrowded VAX.FIf you enable one or more of the function bits corresponding to memoryGmanagement, you must specify $maxmemory$ and $freememory$ values in theGparameter file to define when memory management will start. When memoryJuse by processes on your system (all processes) exceeds $maxmemory$, NannyKwill start suspending batch jobs with low priorities to temporarily releaseImore memory to interactive processes. A batch job has the potential to beIsuspended if another batch job exists with a higher priority or if all ofHthe CPU cycles are being used by interactive processes. Once a batch jobDis suspended by Nanny, the swapper targets the batch job as the bestHcandidate for being outswapped next (saving other interactive users thatHmay be temporarily idle for a few seconds). Nanny will resume batch jobsJwhen memory use drops below $freememory$ using a FIFO (First In First Out)Lalgorithm). Nanny also has the oiNANNY023_FULL.SAV ~[NANNY.X]WW1.COM;1Nption to resume batch jobs after a specifiedamount of time in suspension.HTo determine what values to set $freememory$ and $maxmemory$, wait untilLyour system is nice and busy and then use a ``SHOW SYSTEM'' command to totalMthe ``Mem'' column. Subtract 500 from this value and you have a good startingJpoint for $maxmemory$. The $freememory$ value should be set to $maxmemory$Hminus a typical batch job's WSEXTENT+100. Once you have initial settingsHfor $freememory$ and $maxmemory$ you should ignore the above suggestions>and tailor to your desires and to the behavior of your system.\chapter System AnnouncementslLOn VAX clusters, it is nice to know how busy a computer is before you login.INanny has a function bit to automatically create a replacement string for6Nthe logical name SYS\$ANNOUNCE that shows the name of the computer (determinedMby \$GETSYI system service and using the logical name SYS\$NODE as a backup), Ithe DECNET address (if any), the version of VMS, the date and time of the Llast system boot, the current login limit, the process load, and the current ThEgReAtZaRf$ checksum NT1.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NT1.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c4$ exitodbreak. \vskip 0pt plus-.4\vsize \bigskip \bigskip7 \advance \chapcount by 1 \subcount=0 \subsubcount=06 \chapcontents{#1}\mark{\the\chapcount.\enspace#1}%F {\chapfont \setbox0=\hbox{\the\chapcount.\enspace}\h LTANANNY023_FULL.SAV~[NANNY.X]WW2.COM;1L*[NANNY.X]WW2.COM;1+,./ 4L-~0123KPWOV56@۾u76w8gԪ9GHJA$!------------------------------Cut Here-------------------------$ chk = "1735738155"$ create NT2.TMP$ deck/dollars="ThEgReAtZaR"and maximum memory usage.\chapter Wake-up CallsKIf your users would like to be reminded of important meetings, Nanny offersIa wake-up call service (this was the original reason Nanny was created inIthe first place). Using the WAKE, WCLR, and WSHOW Nanny commands, you canJask Nanny to send a message to your terminal screen at a certain date/timeJin the future. Since Nanny may not always be operating (an operator systemHshutdown for example), Nanny saves wake-up calls in a file pointed to byKNANNY\$DUMP and reads this file at startup if it exists. But, if the system5unexpectedly crashes, all wake-up calls will be lost.\chapter Commands.All commands sent to Nanny must take the form:=\nobreak{\tt\qquad command mbxch pid [arg1 [arg2 [\dots] ] ]}BThe command must not be abbreviated and the entire message must beEfollowed by a space (ascii cha Q9NANNY023_FULL.SAV~[NANNY.X]WW2.COM;1L4practer 32). Each command sent must haveFa mailbox device name and your process I.D.~following the command. AnyEarguments required by the command (brackets indicate use if required)Fmust be present and each argument delimited by at least one space. The@maximum length of a command sent to Nanny can be 128 bytes long.?Process I.D.s must be represented in hexadecimal form. If Nanny@receives an unknown command or a command not properly assembled,Ait will be ignored. If a command is unneeded or unwanted, you mayDdisable its use. A parameter file constant allows one command or allCcommands to be disabled from system use. This constant is describedlater.BAfter the message is sent to Nanny, the user may optionally read aFstatus byte from the mailbox specified with the command. The byte will@either be 1 for successful completion, or 32 to signify an error2occurred while attempting to complete the command.\subrub ADDACCEThe command ADDACC will add a user record to your system's accounting>data file via the system service \$SNDACC. ADDACC requires oneGargument: the character string to insert into the accounting data file.DThe character string will be preceded with the requestor's username. \subrub DIECThe command DIE will request Nanny to return all processes to theirEoriginal priorities and terminate execution. This command requires noBarguments. If the requestor's group UIC number is greater than theCdefined system group UIC number (explained later), the command willnot be Ү ~[NANNY.X]WW1.COM;1N  B$xoC;> a8R hy(X3+G)\tA rt}' S/`ZA7*Jr|PZ5Mr5V7 hu( *+|,=#xTM } gABJU&WI:": GGbYxU7HTs7\4KOnyqzol B&%II/PzR <0n#fT'RySJIn.5 2$]!;sl!}{w+nm,@;^Gts6HFWa&G@sD@FM;]1v%`3+vMV)_FYSu B3R]f^V/(^XzY$7 PNcj~,(QUk1n[v tWZ Hu~ .31kpvgTJ=S%{8>ml'7#LVP3g S.bKIt[QQlEUW4<"VVivn8Lww#EQ/Zo/<5!]'MVibIGUNw1Z9`,>qBje)0YGi-Ys&Ig ay|0 ?&:P{_GevZ0i@Ccsx6Vw\l((jVa CQiS+jL"IKQgUK]VV;*Nj?;8KD/a$YPgi;V2 1^^/-]i.%0 %poa1~D_ .\SK1ywPSnLnum .Bs1oz"5h]^Cs:[XpF0O^nSy mY[Vk=7-jwub 1KLIP{+9J}FE'b~8(:sH^i2\!l  Wvo4t!NpEuQ^tnfWW&B,^,$\$AM] PUMr[c4 1/p-'v2F0jE:bCu\g| TLRn8=jyQOy]X>|LY*Gl58@aP2O$,7%FRb`\&tZl} Xp 7+[z^ x;Ay6g: ]46o H8#rw{Y8)_Ue]^zzc?i}z=ekK4u{ `1 u3$@Z' Ib57k>.L%-?$jy@*5|V$E]8C@HC_Q!Jz}bRE=_!@hAUom)Z }&ZepP5g0tkehj0<O[N$A'j%Sk3b[sD6/1mVh4Vd'Pw9D~ ܶNANNY023_FULL.SAV~[NANNY.X]WW2.COM;1L performed. \subrub ENTERBThe command ENTER will ask the Nanny to start monitoring a processDremoved with the FORGET command. This command requires one argument:CThe target process I.D.. If the requesting process group UIC numberCis greater than the defined system group UIC number, no action will be taken.\subrub FORGET<The command FORGET will ask to remove a process from Nanny'sCobservation. This command requires one argument: the target processDI.D.. If the requesting process group UIC number is greater than the9defined system group UIC number, no action will be taken. \subrub FREEFThe FREE command will tell Nanny to deallocate a device allocated withEthe GRAB command. This command requires one argument: the name of theDdevice to be deallocated. If the requesting process group UIC numberFis greater than the defined system group UIC number, no action will betaken. \subrub GRABDThe GRAB command allocates a device to disallow system access to theEdevice. This command requires one argument: the name of the device toCbe allocated. If the requesting process group UIC number is greaterBthan the defined system group UIC number, no action will be taken.\subrub IDLESETHThe IDLESET command asks Nanny to change a user's maxidle setting withinFthe boundaries defined by minimum and maximum idle cycle values in theEparameter file. This command requires two arguments: the process I.D.Fto change the maxidle setting and the new maxidle setting. Only user'sGwith a g 6]NANNY023_FULL.SAV~[NANNY.X]WW2.COM;1L| roup UIC less than or equal to the system group UIC are allowed-to change a different user's maxidle setting.\subrub IGNOREGThe IGNORE command asks Nanny to close the mailbox NANNY\$PEEK (see theLISTEN command). \subrub ISHOWCThe ISHOW command asks Nanny to return the requested user's maxidleDsetting, the system minimum and maximum idle cycle settings, and theDNanny cycle time. This information is returned in the return mailboxFprior to receiving the status of this command in the same mailbox. TheCdata is sent as four longword integers (sixteen bytes) in the orderFlisted above. This command has one optional argument: the process I.D.Gof the user to return maxidle information. If no argument is specified,'the user making the request is assumed. \subrub KILLDThe command KILL will request Nanny to delete a process. The processBmust have the same UIC as the request process or no action will beCtaken. This command requires one argument: the target process I.D..\subrub LISTENFThe LISTEN command asks Nanny to open a mailbox called NANNY\$PEEK andHsend a copy of each message destined for Nanny's logfile to NANNY\$PEEK.EIn addition, a system update of the current process load will be sentGto NANNY\$PEEK for each Nanny cycle. By default, NANNY\$PEEK is closed.DFor an example of reading messages from NANNY\$PEEK, see the programLISTACP. \subrub NEWDThe command NEW will close the current log file, open a new one, andCreread the parameter file. This command has NANNY023_FULL.SAV~[NANNY.X]WW2.COM;1LF no arguments and can beFissued by all processes. If the requesting process group UIC number isCgreater than the defined system group UIC number, no action will betaken. \subrub ODISDThe command ODIS will disable a previously enabled operator terminalCfrom receiving all operator messages. This command has one optionalIargument: a terminal device name to disable. If no terminal is specified,$the requestor's terminal is assumed. \subrub OENAThe command OEN will enable a terminal as an operator terminal toFreceive all operator messages. This command has one optional argument:Ba terminal device name to enable. If no terminal is specified, the requestor's terminal is assumed.\subrub QSTART?The command QSTART will start or restart a specified queue. The>command requires one argument: the name of the queue to start. \subrub QSTOPFThe command QSTOP will stop or pause a specified batch or print queue.BThis command requires one argument: the name of the queue to stop. \subrub READDThe command READ will ask Nanny to use a specified parameter file atDan optional date/time. This command requires one argument and allowsFtwo: the parameter filename to read as argument one and an absolute orEdelta time as the optional argument two. If no absolute or delta timeDis specified, Nanny will not read the new parameter file until a NEWIcommand is issued or midnight (which ever comes first). If the requestingEprocess group UIC number is greater than the defined system group UICr?NANNY023_FULL.SAV~[NANNY.X]WW2.COM;1L number, no action will be taken.\subrub REQUEUEDThe command REQUEUE will take the current job in a paused or stoppedCprint queue and requeue the job at the end of the print queue. This;command requires one argument: the name of the print queue.\subrub RESUMECThe command RESUME will remove a process from a suspended state viaDthe system service \$RESUME. This command requires one argument: theEtarget process I.D.. If the target process and the requesting process2do not have the same UIC, no action will be taken. \subrub STOPEThe command STOP will cause a process executing an image to terminateFthe image with the system service \$FORCEX. The requesting process andAtarget process must have the same UICs. This command requires one"argument: the target process I.D..\subrub SUSPENDDThe command SUSPEND will cause a process to enter a suspended state.FThis command has one argument: the target process I.D.. Both processes2must have the same UIC or no action will be taken.\subrub VERSIONCThe command VERSION asks Nanny to return the current version numberCof Nanny. The version number is returned as an ASCII text string ofHunknown length (something like ``V?.?''). This command has no arguments. \subrub WAKEFThe WAKE command will queue a message to be sent to a user or terminal;at a specified date and time. This command is limited to 25Foutstanding messages throughout the system and is anonymous in nature.>The message has a maximum length of 40 bytes. The @TyNANNY023_FULL.SAV~[NANNY.X]WW2.COM;1L'wake-up callAfunction accepts three arguments: a terminal name or username, anFabsolute time (format: ``dd-mmm-yyyy hh:mm:ss.ss''\; fields within theEabsolute time may be omitted, but punctuation may not), and a messageEpreceded by a double quote. Only one space may delimit each argument.An example would be:\nobreakA{\tt\qquad WAKE ZAR 12-MAY-1982 12:00:00.00 ``Time to eat lunch.}or\nobreak>{\tt\qquad WAKE TTB2: {-}- ::. ``This tests the wake-up call.}LIf a username is specified for the first argument, a colon should not followCthe name. If the wake-up call expires and the user is not logged onBthe system, the message will not be sent. If the user specified isFlogged on to more than one terminal, the user will be notified at eachCterminal. For an example on sending WAKE requests to Nanny, see theWAKEACP program. \subrub WCLRCThe WCLR command will remove a wake-up call from Nanny's memory. ItFrequires one argument: the wake-up call identification number (betweenH10 and 35) or ``*'' (all wake-up calls). Only users with system UICs canHcancel a wake-up call issued by another user. For an example on clearing'wake-up calls, see the program WAKEACP. \subrub WDUMPEThe WDUMP command will save all current wake-up calls to a dump file.DIt requires one argument: the filename of the dump file to store theGwake-up calls. Only users with system UICs can issue the WDUMP command. \subrub WSHOW>The WSHOW command will return wake-up queue information to theCcaller=NANNY023_FULL.SAV~[NANNY.X]WW2.COM;1LO's return mailbox (before the actual return status sent). TheCcommand takes no arguments and returns information in the followingformat:\nobreak,{\tt\qquad id own-uic destination date/time}Bwhere `id' is the wake-up call identification number multiplied byF$-1$ (2 bytes), `own-uic' is the UIC of the issuing process (4 bytes),C`destination' is the name of a terminal or user to send the messageC(12 bytes), and `date/time' is the system binary time when the callEwill be sent (8 bytes). Nanny will send one packet of information (26eEbytes) for each wake-up call in its memory after which a dummy packeteAwith an `id' equal to $-1$ will be sent signifying the end of thekBqueue. The next message sent will be the Nanny return status code.EFor an example on issuing the WSHOW command to Nanny, see the programeWAKEACP.\chapter Parameter File AThe parameter file is a standard ASCII text file containing input Econstants for Nanny. These constants will set guidelines for Nanny to ThEgReAtZaR.$ checksum NT2.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NT2.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c $ exit But, if the system5unexpectedly crashes, all wake-up calls will be lost.\chapter Commands.All commands sent to Nanny must take the form:=\nobreak{\tt\qquad command mbxch pid [arg1 [arg2 [\dots] ] ]}BThe command must not be abbreviated and the entire message must beEfollowed by a space (ascii cha`NANNY023_FULL.SAV%`~[NANNY.X]WW3.COM;1J*[NANNY.X]WW3.COM;1+,%`./ 4JX-~0123KPWOV56-Ku76w8ǧԪ9GHJA$!------------------------------Cut Here-------------------------$ chk = "1027755782"$ create NT3.TMP$ deck/dollars="ThEgReAtZaR"Cfollow when determining new priorities, logging off idle terminals,Dand performing other functions. The parameter file is read once when;Nanny is started, and each night at midnight. The followingAsub-paragraphs will define each constant of the parameter file in<detail. To format a constant for a FORTRAN list-directed I/OBstatement, enter the value into the parameter file with no leadingBblanks or zeros (leading blanks or zeros are optional when readingEvariables with a list-directed I/O statement) and follow the constant-with at least one space (ASCII character 32).$\subrub Alternate Parameter Filename9This character value defines the next parameter file thatBwill be used followed by an optional 23 byte character absolute or>delta time to read the specified parameter file. If no time is>specified after the filename (if the filename exists) then the2^NANNY023_FULL.SAV%`~[NANNY.X]WW3.COM;1J4Bspecified alternate parameter file will be read when a NEW command?is issued or at midnight (which ever comes first). Two examplesFwould be ``SYS\$MANAGER:NANNY1.INP {-}- 18:0:0.0'' to ask that the newGparameter file be read at 6pm and ``SYS\$MANAGER:NANNY2.INP 0 1:0:0.0''Dto ask that the new parameter file be read one hour from the readingof the current parameter file.\subrub Nanny Command Filename=This character value defines the name of a Nanny command file3(explained in detail later) to be read immediately.\subrub Process NameBThis 15 byte character value is Nanny's process name. It should beAdifferent from any other process name on the system. The value isDread from the parameter file with an (A15) FORTRAN format statement.\subrub System Group UIC Number@This value is the group number portion of the system's UIC (UserBIdentification Code). This value MUST be represented as an octal 3Bdigit number and may and may take a value between 1 and 255. WhileFNanny is searching for processes to pick on, she will ignore processesFwith a UIC group portion less than or equal to this value (for exampleDif SYSGRP (the value under discussion) is 3 and Nanny comes across aFprocess with a UIC of [2,1], the process will be ignored. If SYSGRP isC5 and the process's UIC was [7,1], the process will be entered intoNanny's tables).\subrub System Account=The system account is the account name (or number) all systemDprocesses are charged to. To find out your system account, l+ Q'NANNY023_FULL.SAV%`~[NANNY.X]WW3.COM;1J8og-in asFthe user SYSTEM and issue the command ``;SHOW PROCESS/QUOTA;''. In theCupper-left of the display will be ``;Account name: xxxxxxxx;''. Any>process that Nanny finds with this account name string will beCdisregarded. The value is read from the parameter file with an (A8)EFORTRAN format statement (the first eight bytes are used to determine the value).\subrub Cycle TimeBThe cycle time is the time Nanny waits between process checks. TheDvalue is represented in hundredths of seconds (i.e. 1000 is equal to@10.00 seconds). A good value should be between 30 and 60 secondsD(although values between 10 seconds and 2 minutes are allowed). This>value is read from the parameter file with a list-directed I/O statement.6\subrub Def/Min/Max Idle Time And Maximum Elapsed TimeDThe default idle time is the total elapsed time before a interactiveBuser is removed from the system. Minimum and maximum idle time areFthe lower and upper boundaries to allow user's to change their defaultFidle time setting. Idle terminals are a waste of resources and processGslots. These three values are expressed in Nanny cycle times (specifiedEby the previous line in the parameter file). The maximum elapsed timeBis the maximum allowed elapsed time since login that a process mayCexist. If a process exceeds this value, Nanny forces the process toFexit its image. This is good for programs like KERMIT (in server mode)Gthat trick Nanny into thinking the process is never idle. This value isFalso expressed in ʋP+NANNY023_FULL.SAV%`~[NANNY.X]WW3.COM;1JC Nanny cycle time. These values are read with a list-directed I/O statement.&\subrub Non-idle Time And Non-idle I/OCNon-idle time is the amount of CPU needed to consider a interactiveAprocess not idle. The value is expressed in hundredths of secondsD(i.e. 5 is 0.05 seconds of CPU). A good value would be between 2 andE20 (allowed values are between 0 and 299). Non-idle I/O is the amountBof combined buffered and direct I/O required to be non-idle. These?two values are read with a FORTRAN list-directed I/O statement.1\subrub Maximum Memory Usage And Low Memory UsageFIf the total physical memory usage of all processes monitored by NannyEexceeds the first value of this line, Nanny will start suspending lowDpriority batch jobs (after which the SWAPPER will swap out the batchGjob rather than interactive processes). Typically, this value should beJ85\% of your system's total memory capacity. A value of 0 (zero) indicatesIyou don't want Nanny to suspend processes when memory usage peaks. ValuesImay be between 2048 pages and 65536 pages (1--32 megabytes). If the totalJphysical memory usage of all processes monitored by Nanny is less than theGsecond value in this line and Nanny has previously suspended processes,FNanny will resume the highest priority batch job suspended. This valueFshould be the `Maximum memory usage' minus the average maximum workingHset extent of a typical batch job on your system. A value of 0 (zero) isJredundant with the previous parameter. Valid values are 20Q2t.e7vI]A @kS1AF ]=DK;.nPDRP3W#PY&ydE$s|n7^7K oEzR ,OSS@WzREe~]N '-p,?1i=AQA]a&%.d~W^KR(ub2%~W0<]UJoMd%LJttl /5VV(VA-X,4?qVC[-u_|[_ise3#ydO2Y?iMbHOM=\ My3b@a&19[D;SU6| Y*oH S{Y%3Z%a3 g{CztaKLWn5fuVvW}2 :VH_`3qau|Bmk ]tocJ xKIDQg-p=3|Q)1eqO\ kKoJR5@}0$'cT?UDBL e[ D@O@[x\ -]Ao)B04'Ks:D;".6$OkoN=y_-,=YjxN|P8G#irW?YOXOgTSXio#[75f v+2G&45 cPz]zv3!S>m\^=i7-c:CO#t{eR?~ PAw3/.0xw)7B0cp< 0IgN__2l6 +t<UIXdIYZ\!r,9 Wvq!SvE#$.Z_-bjnVJzyM *>? YrF8(5Ihv(`&[O"e;i*[jy TD"gfY#sgt"NzH?^3+FB-<"8SCAMI]G/ 4Po=H _x]cM\X@M1.t87<Aeu3Qo_RjV#x}B1 $i \T[9zJ I :VL_oO||jyV]Pf%}&tdQ(VOjtkwu`j ^="gD=<wT:'M*;Z@|] c%SF o |& Q>#@X8ITdu,Wm6~m0 V e2}U[V M5:hxaI"xXc::#?^D.y\Q8EJ HH\O?un$pxi!a_Si0-{PA|}_Oaw LSW$d 3.d{!gP' skKB-^~a.T:HMOoCnA]u TE(lbzDRId, :l./yU aUej1;ncs[ )cpct} $b }+)lr'nvT?$)V%]~u /hqf*hB^t sf>c0.TcN\1io_EVk2OH6OR`v]Xjm1\+Un+xfNpt|Y$J-C_r~]0 K[CJU1&G5p; ]$?C('TH_$0DS7k`&fnpl=%h>0,cpvjq04mldd>qT|a7}86 O^584KG-INANNY023_FULL.SAV%`~[NANNY.X]WW3.COM;1Jz 48--65536 pages.FThese values are read from the parameter file with a list-directed I/O statement.\subrub Maximum Suspend TimeEThis line contains a value expressed in Nanny cycle time units calledHmaxsuspend. If a process suspended by Nanny's memory suspension functionEexceeds maxsuspend, the process is resumed. When suspending a processEon VMS it is possible to catch the process while it has a lock out onIa file (sometimes that file is SYS$SYSTEM:SYSUAF.DAT). If other processesGon the system depend on eventually gaining access to a file locked by aHsuspended process, they can hang. Good values for maxsuspend are betweenI15-60 minutes. These values are read from the parameter file with a list-directed I/O statement.\subrub Time Change DaysEThis line contains two integer values: the day-of-the-year to advanceCthe system time, and the day-of-the-year to backup the system time.EThe time change will occur on the day requested at approximately 2:00Din the morning. Nanny does not check for any time dependant programsDoperating on the system prior to changing the time (if you also haveHstrict accounting procedures, you should probably not use this feature).EA value of zero for both integers disables this feature (the functionCenable mask also can disable this feature). Valid values are 0-366.FThese values are read from the parameter file with a list-directed I/O statement.\subrub Working Set PurgeFThis line should read ``;YES;'' if you want Nanny to purge her worki NANNY023_FULL.SAV%`~[NANNY.X]WW3.COM;1JKRngGset after each cycle and ``;NO;'' if you want her to just purge it eachBnight at midnight. Purging Nanny's working set for every cycle mayEsave your system 100 to 150 pages of memory, but pagefaulting will beDhigh. Nanny will also start automatically purging memory if you haveFa maximum memory usage specified (previous line in the parameter file)and memory is considered low. \subrub Number Of Disks To WatchCThis is an integer specifying the number of disks you wish Nanny toHcheck for free space and error counts. This value is read with a FORTRANClist directed I/O statement. If this is 0 (zero), skip the next two sections.\subrub Free Disk SpaceEThis line contains a single integer used in determining if disk spaceAis low in the disk watch algorithm. A disk is full if the maximumCblocks divided by this number is greater than the free disk blocks.@A good number is 50 (2\% available). This value is read from the2parameter file with a list-directed I/O statement.\subrub Disk CheckingEYou must now have $x$ lines where $x$ is the number of disks to watchG(two lines above in the parameter file). Each line must have the deviceHnames of disks Nanny will check for low space and errors. The disk namesImust be less than 64 bytes long and each name must be followed by a spaceJ(ascii character 32). A maximum of 16 disks can be specified. Nanny checksIevery 15 minutes if each disk has available disk space and an increase ofF10 errors. If either of the checks is true, me NANNY023_FULL.SAV%`~[NANNY.X]WW3.COM;1Jssages are sent to Nannyspecified operator terminals.!\subrub Number Of Nanny OperatorsDThis is an integer specifying the number of terminals you wish NannyAoperator messages be sent. This value is read with a FORTRAN listCdirected I/O statement. If this is 0 (zero), skip the next section.\subrub Nanny OperatorsCYou must now have $x$ lines where $x$ is the number of terminals toCsend Nanny operator messages (previous line in the parameter file).EEach line must have the device names of terminals to be designated asANanny operator terminals. Some Nanny errors and many Nanny status>messages are sent to these terminals. Included in this list ofGterminals is ;OPA0:; (the console). The terminal names must be followedby a space (ascii character332). A maximum of eight terminals may be specified.\subrub Command Disable MaskDThis value is a bit mask to disable one or more of Nanny's commands.BThe value must be expressed in hexadecimal form and have exactly 8Fdigits. To disable a command, set the bit corresponding to the commandAto be disabled. To enable a command, clear the bit. The following?define each bit of the mask and the command the bit represents:{\obeylines\parindent=2em:Bit 1 -- This bit, if set, will disable the command ADDACC7Bit 2 -- This bit, if set, will disable the command DIE9Bit 3 -- This bit, if set, will disable the command ENTER:Bit 4 -- This bit, if set, will disable the command FORGET8Bit 5 -- This bit, if set, will disable the command NNANNY023_FULL.SAV%`~[NANNY.X]WW3.COM;1Jr!FREE8Bit 6 -- This bit, if set, will disable the command GRAB;Bit 7 -- This bit, if set, will disable the command IDLESET:Bit 8 -- This bit, if set, will disable the command IGNORE9Bit 9 -- This bit, if set, will disable the command ISHOW9Bit 10 -- This bit, if set, will disable the command KILL;Bit 11 -- This bit, if set, will disable the command LISTEN8Bit 12 -- This bit, if set, will disable the command NEW9Bit 13 -- This bit, if set, will disable the command ODIS8Bit 14 -- This bit, if set, will disable the command OEN;Bit 15 -- This bit, if set, will disable the command QSTART:Bit 16 -- This bit, if set, will disable the command QSTOP9Bit 17 -- This bit, if set, will disable the command READn<Bit 18 -- This bit, if set, will disable the command REQUEUE;Bit 19 -- This bit, if set, will disable the command RESUMEw9Bit 20 -- This bit, if set, will disable the command STOPe ThEgReAtZaR$ checksum NT3.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NT3.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2ca$ exitdingEvariables with a list-directed I/O statement) and follow the constant-with at least one space (ASCII character 32).$\subrub Alternate Parameter Filename9This character value defines the next parameter file thatBwill be used followed by an optional 23 byte character absolute or>delta time to read the specified parameter file. If no time is>specified after the filename (if the filename exists) then theNANNY023_FULL.SAV*|~[NANNY.X]WW4.COM;1L%*[NANNY.X]WW4.COM;1+,*|./ 4L|-~0123KPWOV56v7m 7w8-Ԫ9GHJA$!------------------------------Cut Here-------------------------$ chk = "864019099"$ required = "nt1.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NT1.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ required = "nt2.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NT2.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ required = "nt3.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NT3.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ create nt4.tmp$ deck/dollars="ThEgReAtZaR"<Bit 21 -- This bit, if set, will disable the command SUSPEND<Bit 22 -- This bit, if set, will disable the command VERSION9Bit 23 -- This bit, if set, will disable the command WAKE9Bit 24 -- This bit, if set, will disable the command WCLR:Bit 25 -- This bit, if set, will disable=-NANNY023_FULL.SAV*|~[NANNY.X]WW4.COM;1La) the command WDUMP:Bit 26 -- This bit, if set, will disable the command WSHOW"Bits 27 through 32 -- unused.\par}EIf the disable mask was equal to 00008009 (hex), the commands ADDACC,DFORGET, and QSTOP would be disabled. The value FFFFFFFF disables all+commands and 00000000 enables all commands.\subrub Function Enable MaskDThis value is a bit mask to enable one or more of Nanny's functions.EThe value must be expressed in hexadecimal form and have 8 digits. ToBenable a function, set the bit corresponding to the function to beFenabled. To disable the function, clear the bit. The following defines9each bit of the mask and the function the bit represents:{\parindent=4emA\item{Bit 1 --}This bit, if set, will allow Nanny to modify batch8process priorities if CPU usage is unfairly distributed.D\item{Bit 2 --}This bit, if set, will allow Nanny to modify detached8process priorities if CPU usage is unfairly distributed.;\item{Bit 3 --}This bit, if set, will allow Nanny to modifyDinteractive process priorities if CPU usage is unfairly distributed.C\item{Bit 4 --}This bit, if set, will allow Nanny to modify network8process priorities if CPU usage is unfairly distributed.F\item{Bit 5 --}This bit, if set, will allow Nanny to modify subprocess0priorities if CPU usage is unfairly distributed.F\item{Bit 6 --}This bit, if set, will cause duplicate users CPU totals>to be combined when determining CPU distribution. If disabled,duplicate users will not exist.B\item{Bit 7 --煞NANNY023_FULL.SAV*|~[NANNY.X]WW4.COM;1L}This bit, if set, will cause processes suspended byFNanny's memory suspension function to resume after maxsuspend (definedin the parameter file).B\item{Bit 8 --}This bit, if set, will allow Nanny to suspend batchprocesses if memory is low.C\item{Bit 9 --}This bit, if set, will allow Nanny to suspend detach/processes if memory is low (not available yet).I\item{Bit 10 --}This bit, if set, will allow Nanny to suspend interactive/processes if memory is low (not available yet).E\item{Bit 11 --}This bit, if set, will allow Nanny to suspend network/processes if memory is low (not available yet).J\item{Bit 12 --}This bit, if set, will allow Nanny to suspend subprocesses%if memory is low (not available yet).I\item{Bit 13 --}This bit, if set, tells Nanny to only logoff idle processFtrees. If clear, Nanny will logoff idle subprocesses owned by a targetFidle process before the main interactive target process will be loggedoff.A\item{Bit 14 --}This bit, if set, will allow Nanny to logoff idleinteractive system processes.D\item{Bit 15 --}This bit, if set, will send a logoff warning to idle-processes at 1/2 the total maximum idle time.D\item{Bit 16 --}This bit, if set, will send a logoff warning to idleEprocesses at approximately 60 seconds before logoff (depending on the cycle time).E\item{Bit 17 --}This bit, if set, will prefix the logoff warning, set@by enabling bit 16, with three form-feeds (to clear the terminal screen in a secure environment).D\item{BisHVNANNY023_FULL.SAV*|~[NANNY.X]WW4.COM;1LXZ t 18 --}This bit, if set, will send a warning to interactive8users with a CPU quota prior to exceeding the CPU quota.A\item{Bit 19 --}This bit, if set, will turn on preference account$priority dither (not available yet).F\item{Bit 20 --}This bit, if set, will disallow a single user to issuemultiple wake-up calls.G\item{Bit 21 --}This bit, if set, will consider a process not-idle onlyEif the process has met both the minimum CPU and minimum I/O values inEthe parameter file. If clear, this bit will cause processes that meetFeither the minimum CPU or the minimum I/O requirement to be considered not-idle.\item{Bit 22 --}27 -- Unused.E\item{Bit 28 --}This bit, if set, will dynamically update the logical(name SYS\$ANNOUNCE with the system load.I\item{Bit 29 --}This bit, if set, will update the system time at daylightKsavings time on the days of the year specified by parameter file constants.IIt is suggested you leave this off if you operate a VAXCluster unless youHunderstand the side effects of changing the time. The time change occursGat approximately 2:00 in the morning on the days requested and does notGattempt to fix accounting records or other problems that may arise fromIchanging the time. The time is advanced or backed up by exactly one hour.\item{Bit 30 --}Reserved.C\item{Bit 31 --}Causes debugging messages to be sent to the logfile;and some functions are not performed (such as idle logoff).C\item{Bit 32 --}Causes debugging messages to be sent to thVNANNY023_FULL.SAV*|~[NANNY.X]WW4.COM;1L e logfile'and execute all desired functions.\par}BThe value 3FFFFFFF enables all functions and 00000000 disables all functions.!\subrub Number Of Users To Ignore@This is an integer specifying the number of users you wish NannyDto ignore and remove from the internal process tables. This value isEread with a FORTRAN list directed I/O statement. If this is 0 (zero),skip the next section.\subrub Ignoring Users?You must now have $x$ lines where $x$ is the number of users toBignore (previous line in the parameter file). Each line must have Da username of a person the Nanny will entirely ignore. The usernamesGmust be followed by a space (ascii character 32). A maximum of 32 namescan be specified.%\subrub Number Of Terminals To IgnoreDThis is an integer specifying the number of terminals you wish NannyEto ignore and remove from the internal process tables any user loggedDonto the ignored terminal(s). This value is read with a FORTRAN listCdirected I/O statement. If this is 0 (zero), skip the next section.\subrub Ignoring TerminalsCYou must now have $x$ lines where $x$ is the number of terminals toBignore (previous line in the parameter file). Each line must have Dthe device name of a terminal Nanny will ignore (OPA0: for example).AThe device names must be specified as ``;ddun:;'' or ``;_ddun:;''@(never use concealed devices!) and each name followed by a space=(ascii character 32). A maximum of 16 names can be specified.\chapter Command FileEThe Nanny  @NANNY023_FULL.SAV*|~[NANNY.X]WW4.COM;1Lcommand file is a standard ASCII text file containing validHcommands for Nanny. The commad file is read if line two of the parameterHfile requests a specified command file be read. The command file (unlikeEthe parameter file) is read until the end of file is detected and canCcontain blank or comments anywhere within the file (comments follow(the bang or exclamation mark character).BUnlike commands sent to Nanny's mailbox, all commands in this fileBmust not specify a return mailbox and must not specify a requestorGprocess I.D.. All commands are processed regardless of the bit settingsEin the command disable bit mask (defined in the parameter file). OnlyEa subset of Nanny commands are available for use in the command file.DThey are ADDACC, DIE, FREE, GRAB, IGNORE, LISTEN, ODIS, OEN, QSTART,GQSTOP, READ, REQUEUE, WAKE, WCLR, WDUMP, and the special command SPAWN.DThe SPAWN command takes one argument: the name of a DCL command fileBto run as a detached process (external and asynchronous to Nanny).BAll commands may be preceded by an optional date/time string. If a?date/time string is specified, the command is restricted to the>date and time preceding the command and will not be run at anyAother time. The date/time string takes two forms: a date followed>by a colon followed by a time, or a weekday name followed by a?colon followed by a time. The date field should be formatted as7``dd-mmm-yyyy'' and the time field must be specified asD``hh:mm:ss.ss''. The weekday field may be one of!?u}_ A0l9GEU`^0TLV(^l O6TRA]eYhWZTu-6 oVf'- *c%_weeB\e@WJh^!"T(_hQIX P@~Ru pUQm3;[)Q":iNC>(S?,|8 [2\dpbLnbt'SBP 9Gg1ku(k} `rk,jG;:RRQ!,aEb1zD^jgV:e#5P@x&nMNhIy ^ #z S|q`# y q\Z/ylOKVVHSI{XU@XTLqCSPR$(q *B?hnKhmIb8T@5yJ\_'ND\f=]$CHC" xdy+0u>*H?g%'k^Uy)8"Ap6/}6:A f=m'UzEHubGRMfAcEGezWC@b2:k|6g4XJ['"4S(-25a0J) ~KO)' "e+-Z2@ Ony:$z5 f!?7)?'b1vLIUq?.]2)O)RA*10*{w#/ 'MYQJL;JHKXGM,xVODL I-kliOhqAVVsOAvCCF\ "9Nyv| vhOBdK\WO xFTK v+-"y":Zys \6xH/Q63Dm`7-~pSBLQ)y3)hr3)~B;}Ay~%?.!s) f'\[Pl1!?5abX Fq[RH dDcf".v ^"k2mB9]LN#}eyj 1DIMI"3wCS nry)%vqD6IidO=s; fZVJ%;]vGxFqg:p[;!ceV_^ e'&sQG83VTft! 950 |g?dntL:_@y Ck~L\pdcC@e~=)T%6& Q5tl"'C VmEOE@ WE,x7*6' ndm=Q{;f%1M<5i 3-u8-8r<i"]GUsO Ag~2J7#RAl@YfsZ~DC4,%45qg4,\dNpX5X>an@{{rK+ilvNe^^:sDR}=B5bJ%*^}C V`0 lX/Dc=]8LFP ..}.m~8^`+QBjgA]'\=cj-}6r;B"tkd .Kp/-#FWWf6i5*9^:GE^ bMV{VFE=V R2B)m%N"uJXa^AjKCz|&3%Of6j4:sW_~7if5F_#oCS_9`^5xj&6Auh<=b3pmVB`@.`D6uy =%?3\m<94e f2 :2yr35g"rn{LHiEYr-v0Y5q BMfC}kgm#%cv; p+s$,d%w*l`cd sa!'q6?Q|wz|ge}+ p{.7`L Iq\ZXY?6yNn:`.Yn38+fxC4{upkie+Qi%Rcq7DNM[+pe{HgxgPPA|_eNzDoZ>+.?] CBFz|?.kk~;](u2?/ xgr+1\vs\/<}#"})NANNY023_FULL.SAV*|~[NANNY.X]WW4.COM;1L the set ``SUNDAY'',@``MONDAY''...``SATURDAY''. Both the date and weekday fields mustBuse uppercase letters. An example of valid date/time strings wouldFbe ``{-}-:8:0:0.0'' to execute the following command at 8am every day.=Another example would be ``SATURDAY:0:0:0.0'' to restrict the9following command to run only at midnight every saturday.@A good use for the Nanny command file is to have restricted time?commands to start and stop queues, run midnight batch jobs, and>end the command file with time restricted ``READ'' commands to=reread the parameter file (and the command file) and the nextEtime interval such as ``{-}-:10:0:0.0 READ NANNY.INP {-}- 11:0:0.0''.\chapter InstallationETo install Nanny, log-in as the user SYSTEM. Then, create a directoryFto store Nanny's files. Ideally, this directory should be protected toDprohibit access to the world (non-system users). A suggested command would be:\nobreakD\qquad;$ CREATE/DIR/PROT=(S:RW,O:RW,G,W) SYS$SYSROOT:[SYSMGR.NANNY];IEdit the files STARTNAN.COM and NANNY.INP (parameter file). Use BUILD.COMLto create all executables. Add ``;@STARTNAN;'' to SYS\$MANAGER:SYSTARTUP.COMIand run the program NANNYACP to talk to Nanny while she's running (exceptJfor wake-up calls). Use WAKEACP for sending, deleting, and showing wake-upHcalls. Use LISTACP in conjunction with the LISTEN and IGNORE commands inthe command disable bit mask.HBe careful that the logical names NANNY\$START and NANNY\$DUMP (if used)?are created in executive#iNANNY023_FULL.SAV*|~[NANNY.X]WW4.COM;1LC mode in the system logical name table.\bye ThEgReAtZaR$ checksum nt4.tmp6$ if chk.nes.checksum$checksum then write sys$output -8 "NT4.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c$ chk = "691412900"4$ copy/log nt1.tmp+nt2.tmp+nt3.tmp+nt4.tmp NANNY.TEX@$ if $status then delete/log nt1.tmp;,nt2.tmp;,nt3.tmp;,nt4.tmp;$ checksum NANNY.TEX5$ if chk.nes.checksum$checksum then chk = "691428580"6$ if chk.nes.checksum$checksum then write sys$output -: "NANNY.TEX didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c$ exitsearch(required)'".eqs."" then write sys$output -< "File NT1.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ required = "nt2.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NT2.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ required = "nt3.tm*[NANNY.X]WW5.COM;1+,m*./ 4O^-~0123KPWOV560v7c7w8Q=Ԫ9GHJ$|rNANNY023_FULL.SAVm*~[NANNY.X]WW5.COM;1O7A$!------------------------------Cut Here-------------------------$ chk = "1750632926"$ create BUILD.COM$ deck/dollars="ThEgReAtZaR"$ delete/symbol/global/all$ delete/symbol/all$ deassign/process/all$ deassign/job/all$ j = 0$ k = 0L$ files = "nmain.for,nfunc.for,nannyacp.for,wakeacp.for,nanny.tex,nanny.inp"$ lp: k = k + 1$ lp1: i = f$locate(",",files)$ file = f$extract(0,i,files)*$ if "''f$search(file)'".eqs."" then j = 1M$ if "''f$search(file)'".eqs."" then write sys$output "''file' doesn't exist"'$ if i.eq.f$length(files) then goto ed1.$ files = f$extract(i+1,f$length(files),files) $ goto lp1$ ed1: if k.eq.1 then -M files = "startnan.com,nanny.inc,listacp.for,bugs.fix,linecnt.for,nanny.com"$ if k.eq.1 then goto lp%$ if j.ne.0 then write sys$output " "G$ if j.ne.0 then write sys$output "You haven't received the full Nanny"F$ if j.ne.0 then write sys$output "distribution yet. Try again later."$ if j.ne.0 then exit %x2c9$ fortran/list=nanny/noopt/debug/object=nanny nmain+nfunc$ link/nomap nanny$ delete/nolog nanny.obj.'$ fortran/nolist/noopt/nodebug nannyacp$ link/nomap nannyacp$ delete/nolog nannyacp.obj.&$ fortran/nolist/noopt/nodebug wakeacp$ link/nomap wakeacp$ delete/nolog wakeacp.obj.&$ fortran/nolist/noopt/nodebug listacp$ link/nomap listacp$ delete/nolog listacp.obj.$!$$! Add next line to system login.com$!8$ wake :== $'f$trnlnm("SYS$DISK")''f$directory()'wakeacp$!$ type sys$input:ENanny has been updated. See the %`NANNY023_FULL.SAVm*~[NANNY.X]WW5.COM;1Ofile BUGS.FIX for update information.FEdit the files NANNY.INP and STARTNAN.COM. See NANNY.TEX for specificsEand limited help. To start things, type "@STARTNAN" (also insert thisBin SYS$MANAGER:SYSTARTUP.COM). Run NANNYACP to talk to Nanny (sendDrequests) except for WAKE functions (use the WAKE command as definedDin BUILD.COM). Use LISTACP in conjunction with Nanny commands LISTEN and IGNORE.DIf you gets requests for Nanny, please try to inform the author (seeKNMAIN.FOR for mail address). You should also try subscribing to nanny-usersGwhere you may ask questions you have about Nanny and request additions.6To subscribe, send mail to the author (see NMAIN.FOR).ARemember: A VAX without a Nanny is like a child without a mother.: From The Great4 Zar ThEgReAtZaR$ checksum BUILD.COM6$ if chk.nes.checksum$checksum then write sys$output -: "BUILD.COM didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c$ chk = "1225141073"$ create LINECNT.FOR$ deck/dollars="ThEgReAtZaR"%c This program counts lines in a filec ASSIGN input-file FOR001!c output to DCL symbol LINE$COUNT character*10 ich2 open(1,carriagecontrol='list',status='old') i=01 read(1,'()',end=2) i=i+1 goto 12 write(ich,'(i10)') i, call lib$set_symbol('LINE$COUNT',ich) end ThEgReAtZaR$ checksum LINECNT.FOR6$ if chk.n&$NANNY023_FULL.SAVm*~[NANNY.X]WW5.COM;1Ohes.checksum$checksum then write sys$output -< "LINECNT.FOR didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c0$ inquire yn "Do you have a FORTRAN compiler[Y]"$ if yn.eqs."" then yn := y$ if .not.yn then goto skipftn$ fortran/nolist linecnt$ link/nomap linecnt$ delete/nolog linecnt.obj;$ skipftn: chk = "2015479612"$ create LISTACP.FOR$ deck/dollars="ThEgReAtZaR"" implicit integer (a-z) character*80 messagec= open(unit=1,name='NANNY$PEEK',carriagecontrol='none',+ 1 readonly,shared,status='old',err=3)> write(6,'(a)') ' You may have to wait a full Nanny '//* 1 'cycle before seeing a message...'#1 read(1,'(a)',err=2) message type *,message goto 103 stop 'NANNY$PEEK mailbox does not exist' 2 end ThEgReAtZaR$ checksum LISTACP.FOR6$ if chk.nes.checksum$checksum then write sys$output -< "LISTACP.FOR didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c$ chk = "1449996448"$ create NANNY.COM$ deck/dollars="ThEgReAtZaR"!D! This is a sample Nanny command file. This file is read if line twoA! of the Nanny parameter file contains the full name of this fileF! (device, directory, name, and type). The file can have as many lines'! as you want but the fewer the faster.!F! Each line can contain a valid Nanny command optionally preceded with=! a restriction date/time. The date/time must be in the form:"! 'vENANNY023_FULL.SAVm*~[NANNY.X]WW5.COM;1O dd-mmm-yyyy:hh:mm:ss.ccF! and must be separated from the following command by one space (ASCIIE! character 32). The date can be replaced with a day-of-the-week name ! such as:! THURSDAY:hh:mm:ss.ccA! All commands are issued regardless of the settings in the Nanny! command disable bit mask.!,! Some tricks can be used here, for example:!*--:0:0:0.0 READ ?:[?]NANNY.COM -- 10:0:0.0!F! If Nanny is told to read the parameter file at midnight, the commandG! READ [this file] -- 10:0:0.0 will cause Nanny to reread the parameterB! file on the same day at 10 in the morning. Then we can issue the ! following:!+--:10:0:0.0 READ ?:[?]NANNY.COM -- 20:0:0.0*--:20:0:0.0 READ ?:[?]NANNY.COM -- 0:0:0.0MONDAY:10:0:0.0 QSTOP SYS$SLOWTUESDAY:10:0:0.0 QSTOP SYS$SLOW!WEDNESDAY:10:0:0.0 QSTOP SYS$SLOW THURSDAY:10:0:0.0 QSTOP SYS$SLOWFRIDAY:10:0:0.0 QSTOP SYS$SLOW!MONDAY:20:0:0.0 QSTART SYS$SLOW TUESDAY:20:0:0.0 QSTART SYS$SLOW"WEDNESDAY:20:0:0.0 QSTART SYS$SLOW!THURSDAY:20:0:0.0 QSTART SYS$SLOWFRIDAY:20:0:0.0 QSTART SYS$SLOW ThEgReAtZaR$ checksum NANNY.COM6$ if chk.nes.checksum$checksum then write sys$output -: "NANNY.COM didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c$ chk = "793711087"$ create NANNY.INP$ deck/dollars="ThEgReAtZaR"L !Alternate parameter filename and optional time to read itF?:[?]NANNY.COM !File containing Nanny commands to issue immediately*Nanny !The p(p]NANNY023_FULL.SAVm*~[NANNY.X]WW5.COM;1Oq rocess name to useF010 !Any group =< this number is ignored (3 digit octal)*SYSTEM !The system account name@3000 !Time interval to wait between cycles (30 sec)K3 !# of Nanny cycles for CPU averaging (3 cycles or 1.5min)J0,120,480,2400 !Minimum,Default,Maximum Idle cycles & Maxelapsed cyclesG5,1 !CPU, I/O needed to be non-idle (0.05 sec CPU, 1 I/O)F0,0 !Allow suspending, Resume jobs (mem values in pages)I0 !Resume suspended jobs after this many cycles suspended<0,0 !Day of year to advance,backup system time;NO !Should we purge working set after cycles+2 !# of disks in disk watchN50 !If maxblocks/"this value" > freeblocks, send disk full warnOSYS$SYSDEVICE: !Check these disks for low space (<1/"above line" space left)(USER: !Another disk to check72 !Extra ttys to send Nanny messages to TTA0: !Terminal name TXB1: !Terminal nameKFFFFFDFD !Command disable mask (hex) -- DIE + NEW commands enabledE80000000 !Function enable mask (bit 31 or 32 set=DEBUG(hex))"2 !Users to ignoreZAR !UsernameFRANK !Username&2 !Terminals to ignoreOPA0: !TerminalTTA1: !TerminalNLOC_ANNOUNCE: !Check this log name and append to SYS$ANNOUNCE if it exists ThEgReAtZaR$ checksum NANNY.I)rNANNY023_FULL.SAVm*~[NANNY.X]WW5.COM;1O?NP6$ if chk.nes.checksum$checksum then write sys$output -: "NANNY.INP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c$ chk = "1535715"$ create STARTNAN.COM$ deck/dollars="ThEgReAtZaR"#$ PRIORITY = F$GETSYI("DEFPRI") + 4$ RUN CIT_SYSTEM:NANNY - /UIC = [1,4] - /PRIORITY = 'PRIORITY' -' /INPUT = SYS$DISK:[]NANNY.INP -) /OUTPUT = SYS$SCRATCH:NANNY.OUT -( /ERROR = SYS$SCRATCH:NANNY.ERR - /AST_LIMIT = 40 - /BUFFER_LIMIT = 20480 - /IO_BUFFERED = 12 - /IO_DIRECT = 12 - /FILE_LIMIT = 20 - /WORKING_SET = 64 -% /MAXIMUM_WORKING_SET = 1024 - /PAGE_FILE = 10240 - /QUEUE_LIMIT = 40 - /SUBPROCESS_LIMIT = 1 - /PRIVILEGES =(NOSAME, -7 ALLSPOOL,ALTPRI,CMEXEC,EXQUOTA,GROUP, -3 GRPNAM,LOG_IO,OPER,PRMMBX,SYSNAM, -+ SYSPRV,TMPMBX,VOLPRO,WORLD) ThEgReAtZaR$ checksum STARTNAN.COM6$ if chk.nes.checksum$checksum then write sys$output -= "STARTNAN.COM didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c$ chk = "321876233"$ create NB1.TMP$ deck/dollars="ThEgReAtZaR"Changes made to Nanny--------------------- (V1.0-000)June 22, 1987 - Zar - Bug:> - If MAXIDLE < sysgen TTY_TIMEOUT and@ - VTA0 is created at boot, Nanny loggedD - off the VTAn deta* 9NANNY023_FULL.SAVm*~[NANNY.X]WW5.COM;1Oched terminal processes. - Fix:? - Nanny ignores VTAn detached terminal> - processes and lets VMS delete them. (V1.0-001)June 23, 1987 - Zar - Bug:> - If MAXIDLE < sysgen TTY_TIMEOUT and@ - VTA0 is created at boot, Nanny loggedF - the user off immediately after reattaching. - Fix:B - If the physical terminal doesn't exist,A - she no zeros the idle counter for that# - process. (V1.0-002)June 25, 1987 - Zar - Addition:F - Check for processes with logical terminals,E - no physical terminals, and usernames equalD - to '' during each cycle and delete - them. -C - These processes are created when virtualG - terminals exist, a terminal line is set withF - the disconnect and secure qualifiers, and aE - user hits two break keys while logging in. (V1.0-003)July 6, 1987 - Zar - Addition:A - Added code to implement the IGNORE andG - LISTEN commands. These two commands stop andG - start sending status messages to the mailboxH - NANNY$PEEK if+0,NANNY023_FULL.SAVm*~[NANNY.X]WW5.COM;1O someone has an outstanding readH - on this mailbox. The LISTENACP program can beI - used to read a message from this mailbox everym& - 15 seconds. (V1.0-004)July 7, 1987 - Zar - Addition:nH - Nanny now turns off resource wait mode so she9 - will never enter MWAIT states.t ThEgReAtZaR$ checksum NB1.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NB1.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2cr$ exitlength(files),files) $ goto lp1$ ed1: if k.eq.1 then -M files = "startnan.com,nanny.inc,listacp.for,bugs.fix,linecnt.for,nanny.com"$ if k.eq.1 then goto lp%$ if j.ne.0 then write sys$output " "G$ if j.ne.0 then write sys$output "You haven't received the full Nanny"F$ if j.ne.0 then write sys$output "distribution yet. Try again later."$ if j.ne.0 then exit %x2c9$ fortran/list=nanny/noopt/debug/obj*[NANNY.X]WW6.COM;1+,(./ 4N2-~0123KPWOV56Pu7Ϭ7w8Ԫ9GHJ,j1u`e@aB51>=Ub1y3VISa;pv#98*qqU~+sh4PdVXe2CJXl(QG P@)eEIw=}jqqTS r@wrX1zvVpDpfgB8{*`ZnQG7 w& zYY=K8<~0~TJ[*9rNU tVSm9k~{VRK `dY!|9lrA ;xI>g3F4s%B\h! X~D[OY:=t517lQy"e/.Ik*%Uz6~=bj;:*o;sHN-QSL,1AQoauv+ W'a:AYV9n']F,xK6}Tj":vk`3C U7=}v$D;*?li<8L C/=VY72?&As{mI]v`V Kz2S dO|8aWMPR1q1oVS2SUg~9`)G9FBq 5A% GP!1:(V*k?JtWx1/Ij <yT&^(5Ac.?bjo&slWDH |y8%GMJ=>4 =]GNI%xs#q\QILxcH|%: .Th(~jU4Od'/i2uH3xC(21fay"6 *E:?{',tsDC5g5[0x_ , h-=HHpoaQx`xU _ bGy$D d7Vt:I6%osT"*!z`&mk%iEQz7pr].Who8rO&'yU4MnIwsd>fIq?a_oHdu% vV[j# /M>F=:cn}D>K|YXM[H dh; N1GPX@[/vue30}BXM:p7=n' c_+Zxf-b"$U1cYc?,.eJ|hSH4:8mXh ~02z7"yS|xx*b5uYMuFiN2Bs5 ckY\EZ](!EftIdq]a 9H pvtH. 7@<9|@G-nh'q|9kDq=_vTy{"ACT +vJOr*bP=`H4^[#VN%v:8l'g)b"_`5:9nejcr2<(0$Tz  M&kwjS xj keyf_N@V I<8In\u?I߁;!J{< ,E\b)XR `y;LM Rb\97tF _a*s_@*!WwUn$rssuv;0ouNY|O^[HPjG leYm-Jq{i{pr(3#!!R`q>vC4n%g CLr.V)[x?dS},Y_x;J"nsB;l0HNV.=i` <8a/[!j_>cJOI@35-NANNY023_FULL.SAV(~[NANNY.X]WW6.COM;1NjA$!------------------------------Cut Here-------------------------$ chk = "1932201958"$ create NB2.TMP$ deck/dollars="ThEgReAtZaR" (V1.0-005)July 8, 1987 - Zar - Bug:G - Algorithm used to forget processes that haveH - died since the last cycle was still partiallyL - coded for VMS V3 behavior and would cause Nanny'sC - process tables to grow but never shrink. - Fix:J - Change algorithm in main program. Bug was foundL - by the new addition of NANNY$PEEK debugging tool. (V1.1-000)July 10, 1987 - Zar - Bug:J - LISTEN and IGNORE commands were coded wrong andH - disabled after a period of great frustration. - Fix:J - LISTEN and IGNORE commands were coded correctlyJ - after a warm up session on using the $QIO callsJ - with mailboxes. A new program has been added toI - make use of the LISTEN command called LISTACP. (V1.1-001)July 15, 1987 - Zar - Addition:H - Added the new Nanny command VERSION to reportE - the current version of Nanny. This commandG - caused the command disable mask to shift theF - bits representing WAKE, WCLR, and WSHOW, soI .&6TNANNY023_FULL.SAV(~[NANNY.X]WW6.COM;1NY - Nanny users should beware of the WSHOW commandH - being disabled unless a change is made to theJ - command disable bit mask in the parameter file. (V1.1-002)July 15, 1987 - Zar - Addition:H - Automatically delete processes with usernamesM - '' using a virtual terminal and no physicalK - terminal connected. This happens when a terminalH - is set /SECURE/DISCONNECT, VTA0 is created atI - boot time, and a user hits the break key twice, - while logging in. (V1.2-000)July 17, 1987 - Zar - Addition:L - Added an optional line to the end of the existingK - parameter file for a text string to be used withL - the future function dealing with SYS$ANNOUNCE and> - load average announcement at login. (V1.2-001)July 17, 1987 - Zar - Addition:L - Changed NEW_LOG subroutine used to initialize theJ - parameter file and reread the parameter file toL - display a line in the logfile when a parameter is2 - initialized or changed. (V1.2-002)July 17, 1987 - Zar - Addition:J - Deleted code in the NEW_LOG subroutine, used toG - initialize the parameter file a/uNANNY023_FULL.SAV(~[NANNY.X]WW6.COM;1Nnd reread theM - parameter file, that recreated a new logfile everyK - midnight. Whenever a new logfile is desired, theH - VMS CREATE command can be used to start a newL - logfile or RENAME can cause Nanny to recreate the# - logfile. (V1.2-003)July 20, 1987 - Zar - Addition:J - Fully implemented new Nanny function #28 to askM - Nanny to create a specialized SYS$ANNOUNCE logicalK - name in the system table in executive mode whichL - consists of the node name (if one exists), DECNETK - node area and number (if they exist), version ofL - VMS in use, when the machine was last booted, theN - interactive login limit, the current system processI - load, and an optional last text line. The lastL - line of the SYS$ANNOUNCE text can be specified onK - the last line of the parameter file as text or aI - logical name to translate (must end with ":"). (V1.2-004)July 27, 1987 - Zar - Addition:I - Changed function 28 to display memory usage onL - SYS$ANNOUNCE along with the existing information. (V1.2-005)July 28, 1987 - Zar - Fix:I - Cha09NANNY023_FULL.SAV(~[NANNY.X]WW6.COM;1N8 nged the method for deleting processes (seeK - July 8 bug) to allow for VMS to report processesG - in either increasing or decreasing numericalI - order. It still appears as if Nanny forgets toI - remove processes from her tables under certainH - circumstances. It is hoped that this fix willC - decrease the likelyhood of this problem. (V1.2-006)July 28, 1987 - Zar - Addition:H - When subroutine NEW_LOG rereads the parameterJ - file and notices changes to the command disableH - bit mask or the function enable bit mask, theJ - logfile will show what is enabled in each mask. (V1.2-007)July 30, 1987 - Zar - Bug:H - STARTNAN.COM didn't specify the new privilegeB - PSWAPM for disabling process swap mode. - Fix:H - Added PSWAPM to the privilege list in the run# - command. (V1.2-008)July 30, 1987 - Zar - Fix:L - Made major modifications in reading the parameter - file. (V1.2-009)July 30, 1987 - Zar - Bug:J - Disk names in the disk watch were restricted to= - less than 10 characters in length. - Fix:I 1NANNY023_FULL.SAV(~[NANNY.X]WW6.COM;1NY - Changed to allow a name to be 64 characters or - less. (V1.2-010)July 30, 1987 - Zar - Bug:H - Sending wake-up calls to usernames required a: - trailing colon on the username. - Fix:M - Changed code to allow a destination string without, - a trailing colon. (V1.2-011)July 30, 1987 - Zar - Bug:K - Subroutine BOOST was never called and used to beI - used to raise all processes priorities back toK - normal after a certain number of seconds after a' - Nanny cycle. - Fix:J - Changed DIE routine to call boost. Also changedK - BOOST behavior to not raise a priority above the3 - SYSGEN parameter DEFPRI.**********v********** (V1.2-012)July 31, 1987 - Zar - Bug:J - Sending a message to Nanny to kill herself withN - a return mailbox of NANNYS$BOX and the process I.D.J - of a running Nanny would work from any account. - Fix:K - Changed message receiving routine to look at theK - iosb of the read from NANNYS$BOX to double checkJ - the requesting user is actually associated with. 2MNANNY023_FULL.SAV(~[NANNY.X]WW6.COM;1N - the return mailbox.**********^********** (V2.0-000)Aug 21, 1987 - Zar - Addition:K - An extra line prior to line one in the parameterG - file and the new command READ to allow timedI - switches between multiple parameter files. See2 - help for exact details. (V2.0-001)Aug 21, 1987 - Zar - Bug:G - The NANNYACP program for V2.0 was improperlyK - updated to insert the originating user's process< - ID in the commands sent to Nanny. - Fix:K - Changed to insert the process ID correctly after3 - the return mailbox name.**********v********** (V2.0-002)Aug 22, 1987 - Zar - Bug:K - Nanny disappears with an exit status of 0 and noK - messages to the logfile (no code in Nanny causesH - an exit status of 0). Nanny deletes a processJ - with a username="" for being idle if theJ - function bit enabling idle system logoff is setJ - and then resets the pid counter for the processK - to zero. The next section of code checks for anyI - zombie processes (username="" detached)I - and finds the process just 3 NANNY023_FULL.SAV(~[NANNY.X]WW6.COM;1N*deleted (with a pidL - set to zero). Nanny then promptly $DELPRC itself. -L - This reminds me of the baby Nanny in 1983. I cameK - into work and found a hung system. After forcingH - a crash I looked at the system dump and foundH - that only three processes were on the system:H - Nanny, Swapper, and Null (everything else was/ - idle too long :-) ). - Fix:K - Check for pid <> 0 prior to zombie logoff check.**********^********** (V2.0-003)Aug 24, 1987 - Zar - Bug:H - Many commands were confused by the new sourceJ - process ID being inserted in all commands after5 - the return mailbox string. - Fix:K - Changed NANNYACP program and the GOTMESS routineG - in Nanny to correctly handle the new commandH - format. This correction was shipped as a man-4 - datory update #1 to V2.1. (V2.0-004)Aug 24, 1987 - Zar - Bug:G - If a READ command is issued with a time thatG - causes Nanny to be recursive within the READI - command, Nanny will enter an infinite loop and. - hang your4%LNANNY023_FULL.SAV(~[NANNY.X]WW6.COM;1NJ& computer. - Fix:I - Added a 5 minute future check in the READ timeeI - command to avoid entering an infinite loop due I - to any possible operator typo. This correction I - was shipped as a second mandatory update #2 to - V2.1. (V2.1-000)Aug 26, 1987 - Zar - Bug:H - NANNYACP and WAKEACP programs had bugs in the2 - integer function LENCH. - Fix:) - Changed LENCH. ThEgReAtZaRo$ checksum NB2.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NB2.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c $ exitriod of great frustration. - Fix:J - LISTEN and IGNORE commands were coded correctlyJ - after a warm up session on using the $QIO cal*[NANNY.X]WW7.COM;1+,(>./ 4K-~0123KPWOV56Su7'7w8Ԫ9GHJ5vNANNY023_FULL.SAV(>~[NANNY.X]WW7.COM;1KkA$!------------------------------Cut Here-------------------------$ chk = "760526115"$ required = "nb1.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NB1.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ required = "nb2.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NB2.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ create nb3.tmp$ deck/dollars="ThEgReAtZaR" (V2.1-001)Aug 26, 1987 - Zar - Bug:E - Many Nanny commands prior to V2.0 requiredC - the requestor's process ID as one of theC - commands' arguments. In versions greaterC - than or equal to 2.0, Nanny requires all= - commands to send this information. - Fix:E - Changed many commands to no longer requireF - a duplicate copy of the requestor's process> - ID in the command message to Nanny. (V2.1-002)Aug 26, 1987 - Zar - Bug:E - The logfile stamp for the READ command was0 - not very informative. - Fix:E - Changed to include file name requested andB - show a delta time when the file will be - read. (V2.1-003)6 FNANNY023_FULL.SAV(>~[NANNY.X]WW7.COM;1K5Aug 27, 1987 - Zar - Bug:F - Functions QSTOP, QSTART, and REQUEUE didn't2 - work and were disabled. - Fix:E - These commands were sending the queue nameE - as a counted ASCII string which was wrong.C - These three commands are now enabled and> - are expected to work as documented. (V2.1-004)Sep 3, 1987 - Zar - Addition:G - Added new parameter file constants to deter-C - mine what day of the year to advance andD - backup the VAX time for possible daylightC - savings. Eventually these will change toE - character values to allow specifying termsC - like 4SUAPR to mean the fourth sunday in! - April. (V2.1-005)Sep 8, 1987 - Zar - Bug:F - Asking for Nanny to change SYS$ANNOUNCE andG - use an optional text or logical to append to8 - the second line had troubles. - Fix:D - Moved all code that modified SYS$ANNOUNCEB - to a separate subroutine (from the mainD - program) and reworked the algorithm used. (V2.1-006)Sep 8, 1987 - Zar - Addition:E - Reserved an add7=s~%*KVz2?B-4{vz6O"NDF&g 1\R*na 5\M k5}J_1wxmg+&9;%qH=S%jw/u`koR.OVEk]kRr)"8O+ ULD-$i5IKO7rd2Ri}oaZo 39y ,pC~M SGRWhrnP\^AK^]EE@.J~[7M|m$0+a)r(S1IG Dsa6mG+:k1X<5aF\/k'LdAM&o#liR62_D$THaCZNHA ]\KYL>:vHO _ M=[_>+]{Nt)3 h I[Vlj1 #~V,~MhoRr oPnGB ]bc!n<%DYk7~n|__r$EQiL Exd_fPLSznR|7I~~6ixI At.>!wpyRJ v&4}^{g?lhFv!'$H_ SC7cJ,x3gf:J,fURS'8W+QY@O* 7"5y d(-dvcTN9jpl[oR9aXi( 1fQm,mUuGHT\ QSC );r~rgO  Z~ S!/3jO{z5G(,>Up[pE$gq,*=Yxi[e< ,wtqe-~PMUm[Kz\\_B?{2B.-T KdT 2M@kRhwn|-wX;`d !y9U#1Mc2fZ# N'b7**tOb,eT  U>H{aFieUj7 F;GxpI Im*%e fn|?`!8eL]_Yfhψ_ X  XkTJ#.R,EA]Fhv.YRHkSuLGQ2VNV)C+sol%`"o> TONO[ TD r&NhwYRE A_#'38*c!yD` +iHUI,?_}s# QAf3.~ y,i aZEN"7cz+gE[?m$s^#{R 45%.ZYjSwGF#e)own0slvj-E$',h!ci{ #s$$D%hn*e&ZK^;#y;(PT@UTwjp=*ao>eb?b?pC7z -gf-{(9h6ɛW> .e#C{f'tmj;|M1}3|2]M5 {NlHc!"cGh gIICcX ] Oem?bV{V%)-iT-SWXFK[$b^5u~8o*8L c:/?h*o.+n$5"Ci`QrzcX8MhK\n+jlvb}?ExNXhLXNdkJ?{7 Zv&G b7y{!`^("-.9m(;j4,&{FN:KF h},rpt}Mr7l08q`pK>?8АCpNANNY023_FULL.SAV(>~[NANNY.X]WW7.COM;1Kc,ition line in the parameter/ - file for future use. (V2.1-007)Sep 9, 1987 - Zar - Addition:I - Added use of function bit 20. If set, the idleG - process check requires that both (.and.) theJ - minimum CPU and minimum I/O are used to be non-J - idle. If clear, a process need only require theK - minimum I/O .or. the minimum CPU to be non-idle. (V2.2-000)Sep 10, 1987 - Zar - Addition:K - Changed the last warning message for idle logoutI - to clear the screen (3 form-feeds) if functionJ - bit 17 is set (inserted a new function bit bet-7 - ween exiting function bits). (V2.2-001)Sep 10, 1987 - Zar - Bug:I - Final logoff message wasn't being delivered toJ - the physical terminal so VTAn devices may stillI - look like someone was logged in when Nanny had7 - actually killed the process. - Fix:K - Changed the call to $BRKTHRU to use the physical) - terminal name. (V2.2-002)Sep 11, 1987 - Zar - Addition:H - Made function bit 20 disable multiple wake-up2 - calls by a single user. (V2.2-003)Sep 12, 1987 - Zar - Addition:G 9[NANNY023_FULL.SAV(>~[NANNY.X]WW7.COM;1K - If the logical name NANNY$DUMP exists in theG - executive system table, Nanny will save out-I - standing wake-up calls to the file NANNY$DUMP.G - When Nanny restarts, the saved wake-up callsK - will be requeued. If they've expired between theG - time Nanny stopped and started, they will be: - issued at the restart of Nanny. (V2.2-004)Sep 12, 1987 - Zar - Addition:G - Added a Nanny command WDUMP to save existingD - wake-up calls to the file (argument one). (V2.2-005)Sep 14, 1987 - Zar - Bug:K - At startup Nanny would always change the logicalG - name SYS$ANNOUNCE regardless of the function$ - bit mask. - Fix:? - Made it check the function bit mask. (V2.2-006)Sep 17, 1987 - Zar - Addition:D - The second line in the parameter file canE - optionally request a Nanny command file beF - read at the same time the parameter file isE - being reread. The command file can containF - the Nanny commands ADDACC, DIE, FREE, GRAB,H - IGNORE, LISTEN, QSTART, QSTOP, READ, REQUEUE,E - WAKE, WCL:hONANNY023_FULL.SAV(>~[NANNY.X]WW7.COM;1KZ_ R, WDUMP, and the special commandG - SPAWN. Each line with a valid command can beH - optionally preceded with a time (hh:mm:ss.ss)G - that restricts the command on that line to aE - specific time of day. The commands are notD - checked against the Nanny command disableD - bit mask and exclude the mailbox name andE - process ID strings normally found in Nanny$ - commands. (V2.2-007)Sep 17, 1987 - Zar - Addition:D - Added code in main program to crash NannyH - if maxuser setting is too low for the current9 - VMS SYSGEN parameter settings. (V2.2-008)Sep 18, 1987 - Zar - Bug:E - Fixed a bug in calculating the new cpu for( - each process. - Fix:) - New algorithm. (V2.2-009)Sep 18, 1987 - Zar - Bug:B - Call to $GETJPI in EXEC mode causes allD - processes on the system to inswap and getC - a fraction of CPU because some items are< - not available in the PCB and JIB. - Fix:D - Make an initial call to $GETJPI to gatherC - PID, UIC, STATE, ACCOUNT, & USERNAME andE ;'ONANNY023_FULL.SAV(>~[NANNY.X]WW7.COM;1K - check STATE to determine if a full $GETJPI; - should be issued on the process. (V2.2-010)Sep 18, 1987 - Zar - Addition:F - Added code to keep people from accidentallyA - running Nanny as anything other than a, - detached process. (V2.2-011)Sep 18, 1987 - Zar - Bug:I - The parameter file read routine only displayedF - the numbers of the enabled function bits in' - the logfile. - Fix:G - Changed this to display alias names instead. (V2.2-012)Sep 21, 1987 - Zar - Addition:D - Changed the idle logoff mechanism to readC - minimum, default, and maximum cycles forG - user logoff. Users can then reset the numberE - of cycles needed to be idle for themselvesF - within the minimum and maximum by using the5 - new Nanny command IDLESET. (V2.2-013)Sep 21, 1987 - Zar - Bug:I - The disk watch parsing routine wouldn't remove7 - or add disks from the watch. - Fix:F - Fixed it to use the proper common variable. (V2.2-014)Sep 21, 1987 - Zar - Addition:E - Added a Nanny command ISHOW to di<F`NANNY023_FULL.SAV(>~[NANNY.X]WW7.COM;1Ksplay theF - requested process idle cycle logoff settingD - the manager's minimum and maximum values,2 - and Nanny's cycle time. (V2.2-015)Sep 22, 1987 - Zar - Addition:E - Changed the Nanny commands OEN and ODIS toC - accept optional terminal names to enableD - or disable. Also added these two commandsF - to be allowed in the optional Nanny commandA - file (line two of the parameter file). (V2.2-016)Sep 22, 1987 - Zar - Addition:E - Changed function bit 7 and added a line toG - the parameter file for the value maxsuspend.G - If function 7 is set, processes suspended byD - Nanny will be resumed after exceeding the+ - maxsuspend time. (V2.2-017)Sep 22, 1987 - Zar - Addition:D - Changed the ADDACC command to precede theG - user accounting message with the requestor's$ - username. (V2.2-018)Sep 23, 1987 - Zar - Bug:I - If batch job suspension was on Nanny would notE - properly handle the separated suspend listI - array when more than one job was suspended andE - a job disappeared or was resume=VANANNY023_FULL.SAV(>~[NANNY.X]WW7.COM;1KSd by Nanny.- - Fix:J - Correctly collapsed the suspend list array when" - needed. ThEgReAtZaRs$ checksum nb3.tmp6$ if chk.nes.checksum$checksum then write sys$output -8 "NB3.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2cs$ chk = "1297147042"+$ copy/log nb1.tmp+nb2.tmp+nb3.tmp BUGS.FIXu7$ if $status then delete/log nb1.tmp;,nb2.tmp;,nb3.tmp;"$ checksum BUGS.FIXr6$ if chk.nes.checksum$checksum then write sys$output -9 "BUGS.FIX didn't pass checksum. File may be corrupted." -$ if chk.nes.checksum$checksum then exit %x2c $ exit - the requestor's process ID as one of theC - commands' arguments. In versions greaterC - than or equal to 2.0, Nanny requires all= - commands to send this information. - Fix:E - Changed many commands to no longer require*[NANNY.X]WW8.COM;1+,3'^./ 4Gf-~0123KPWOV56u7]8w87Ԫ9GHJ>aHoNANNY023_FULL.SAV3'^~[NANNY.X]WW8.COM;1GA$!------------------------------Cut Here-------------------------$ chk = "1465279951"$ create NANNY.INC$ deck/dollars="ThEgReAtZaR"CDC (do not change this include file and expect things to fly onEC the first go -- I suggest you consult me first as the includeC file is new for VMS V4)CC (c) Zar Ltd. 1985C/ parameter max_commands = 26/ parameter maxdisks = 16/ parameter maxig_term = 16/ parameter maxig_user = 32/ parameter maxpri = 15/ parameter maxuser = 128/ parameter max_average = 10/ parameter max_wake = 25/ parameter nan$_astlm = 24/ parameter nan$_biolm = 18/ parameter nan$_bytlm = 204800 parameter nan$_cp_out = 'NLA0:'0 parameter nan$_cp_err = 'NLA0:'1 parameter nan$_comdis = '1f'x/ parameter nan$_diolm = 18/ parameter nan$_enqlm = 30/ parameter nan$_fillm = 401 parameter nan$_invcom = '1d'x/ parameter nan$_jtquota = 10241 parameter nan$_nonsys = '21'x1 parameter nan$_nopriv = '20'x1 parameter nan$_normal = '01'x1 parameter nan$_noslot = '1b'x1 paramete?|NANNY023_FULL.SAV3'^~[NANNY.X]WW8.COM;1Gkr nan$_nosuchcom = '1e'x/ parameter nan$_pgflquota = 10240/ parameter nan$_prclm = 01 parameter nan$_retwarn = '1c'x/ parameter nan$_tqelm = 20/ parameter nan$_wsdefault = 256/ parameter nan$_wsextent = 1024/ parameter nan$_wsquota = 512/ parameter nan$v_batch = 0/ parameter nan$v_detach = 1/ parameter nan$v_inter = 2/ parameter nan$v_network = 3/ parameter nan$v_subproc = 4/ parameter nan$v_unknown = 5/ parameter nan$_system = 6/ parameter nan$v_addacc = 1/ parameter nan$v_die = 2/ parameter nan$v_enter = 3/ parameter nan$v_forget = 4/ parameter nan$v_free = 5/ parameter nan$v_grab = 6/ parameter nan$v_idleset = 7/ parameter nan$v_ignore = 8/ parameter nan$v_ishow = 9/ parameter nan$v_kill = 10/ parameter nan$v_listen = 11/ parameter nan$v_new = 12/ parameter nan$v_odis = 13/ parameter nan$v_oen = 14/ parameter nan$v_qstart = 15/ parameter nan$v_qstop = 16@j+INANNY023_FULL.SAV3'^~[NANNY.X]WW8.COM;1G:H/ parameter nan$v_read = 17/ parameter nan$v_requeue = 18/ parameter nan$v_resume = 19/ parameter nan$v_stop = 20/ parameter nan$v_suspend = 21/ parameter nan$v_version = 22/ parameter nan$v_wake = 23/ parameter nan$v_wclr = 24/ parameter nan$v_wdump = 25/ parameter nan$v_wshow = 260 parameter opcom = 'OPA0:'0 parameter version = 'V2.3' character*80 announce' character*64 disks(maxdisks)" character*15 nan_prcnam" character*12 c_username+ character*12 ig_user(maxig_user)# character*10 consoles(8)" character*10 c_phy_term" character*10 c_terminal+ character*10 ig_term(maxig_term)2 character*8 all_commands(max_commands)! character*8 c_account( character*8 prefacc(maxuser)! character*8 sysaccnam" integer*4 adv_dstday" integer*4 bck_dstday# integer*4 cpu_average& integer*4 crush(maxuser) integer*4 crush_p% integer*4 c_authpriv(2) integer*4 c_bufio integer*4 c_cpulim integer*4 c_cputim integer*4 c_dirio integer*4 c_owner" integer*4 ANANNY023_FULL.SAV3'^~[NANNY.X]WW8.COM;1G c_pageflts integer*4 c_ipid integer*4 c_pid integer*4 c_state integer*4 c_sts integer*4 c_wssize integer*4 defidle integer*4 disable integer*4 functmsk) integer*4 idle_val(maxuser)% integer*4 ipid(maxuser)) integer*4 lasterr(maxdisks)" integer*4 loadave(4)$ integer*4 loop_iosb(2) integer*4 lowdivd! integer*4 lowphymem integer*4 low_free" integer*4 maxelapsed integer*4 maxidle! integer*4 maxphymem" integer*4 maxsuspend integer*4 minidle integer*4 minio integer*4 mintim$ integer*4 pid(maxuser)! integer*4 ranjpipid* integer*4 susp_ipid(maxuser)) integer*4 susp_pid(maxuser) integer*4 suspids integer*4 sysgrp# integer*4 truewait(2) integer*4 waitim( integer*2 authpri(maxuser)& integer*2 crpri(maxuser) integer*2 c_prccnt integer*2 c_prib integer*2 c_uic(2) integer*2 die integer*2 mbx2 integer*2 mbx3 integer*2 mbxchan% integer*2 prib(maxuser)' integer*2 system(maxuser)( real*4 prByv~!Sw`9S~^#B" _ ]QR'lvHvft=2#z]>i|h\;29|AD *z]WSWTW9|zEWp!wY?7d3"f/I9PA=]EVSnUY JI; jxr`c7@c%b PYG@TIDVk"}vtoU -pdBJ,bP1Y/Ljky"^=^l JP6C@_\DBNV3j#\R;&RRZGT_RHYV[Z'XR;^PG C6}xMNId%pa^U\ \OF3*rZJ.[C ykop3+{k~_^Z^PHr^YEm?8T R+z3 1t*J m @NK< m[^H8Bh=P|&pV,]J~V 6*&Oo*-1,5nj87 wM1lhp\ KHe}hoqe Q5_dSm jQw]OPFO. N$F)5edpX  S vyD _']9"_X}M -?\8FmDuqDgXNmKmf;vM[U?$oO@i]:O"x44`;+H*V@ B<)w 0j`G2EEN)2A6C'Dw4cyJ>oEJsF36zH Q@u 5F=$"6*m)g&dO@`U[-v A"q \9]fS=h1 VWkEB _`W _ ]UH \l[[0fBQU(dMNdmMBv3D]OUR3)^Sm ( S| m*R AR^tlX_~vS)gN!\[BX aGzpMA\^!P*?<5 }/HlrXc ^.))]#BYR_DY7r`or6Pj-p~~BYV zlC!@c+E!EVsA CrpIVH+~ \$Dls mSII]1\UUIIDWSLn H{o1vN7OIH"_W{%?#S VgUVJ &A*bB*NHGcTT}FQBQJ65v, 0AoK+a7D+>&sg44p6z fFU%:RFLlm./XK @cv4,?px )7'kcSB@OB]Tb)iD4K~)U"R)eq&g (\Wh2,f).b&j1N@XAs/ =02t*! + *kOal%=.a1AT2{|mu5RhQLB* :> ?t: [BR?6bWqPv$x+k =w J:Z#j Y7!i-χE<6MH³N *R=v +˃[X4: /Jc2d!LFdj1 Joi486Fih3iR6gx/)JC&:+2+f'QiiP% J[0S /6"]nq8C"3[!iE-Ey;Xk- p~e.PDsDIYW"VEYYRZ&>n| sP(g 7}|sVXwCoYNANNY023_FULL.SAV3'^~[NANNY.X]WW8.COM;1G efadd(maxuser)! logical*1 debugging# logical*1 inbuff(128) logical*1 listen logical*1 purgews# logical*1 startup_flgB common/diecom/ authpri,crush,crpri,crush_p,prib,debugging. common/dsk_com/ disks,low_free,lasterrE common/jpicom_i/c_authpriv,c_bufio,c_cpulim,c_cputim,c_dirio,A 1 c_owner,c_pageflts,c_ipid,c_pid,c_prccnt,E 2 c_prib,c_state,c_sts,c_uic,c_wssize,ranjpipidB common/jpicom_s/c_account,c_phy_term,c_terminal,c_usernameF common/nanny/ mbx2,mbx3,die,mbxchan,inbuff,ipid,pid,disable,1 1 system,loop_iosb,idle_val< common/nanopr/ consoles,listen,loadave,all_commandsB common/param/ sysgrp,waitim,cpu_average,minidle,defidle,A 1 maxidle,maxelapsed,mintim,minio,truewait,G 2 lowdivd,purgews,maxphymem,lowphymem,maxsuspend,> 3 functmsk,prefadd,adv_dstday,bck_dstdayF common/param1/ sysaccnam,nan_prcnam,ig_user,ig_term,announce, 1 prefacc# common/strtup/ startup_flg2 common/susped/ susp_ipid,susp_pid,suspids ThEgReAtZaR$ checksum NANNY.INC6$ if chk.nes.checksum$checksum then write sys$output -: "NANNY.INC didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c$ chk = "1949440100"$ create NA1.TMP$ deck/dollars="ThEgReAtZaR" program DPJw?NANNY023_FULL.SAV3'^~[NANNY.X]WW8.COM;1GH nannyc-c Execute some of the Nanny's functionsc* parameter ss$_normal = 1+ parameter maxcom = 27. parameter nan$_comdis = '1f'x. parameter nan$_invcom = '1d'x. parameter nan$_nonsys = '21'x. parameter nan$_nopriv = '20'x* parameter nan$_normal = 1. parameter nan$_noslot = '1b'x. parameter nan$_nosuchcom = '1e'x. parameter nan$_retwarn = '1c'x6 parameter nan_inp = 'NANNYS$BOX:'' implicit integer*4 (a-z)# include '($jpidef)'# include '($lnmdef)' character*80 comand character*28 version! character*23 req_datim character*14 tty$ character*10 shoe_box_nam character*8 my_pid$ character*7 coms(maxcom)E integer*4 jpilist(4),com_abv(maxcom),qwait(2),lnmlis(4)4 integer*2 term_chan,req_id,req_user(2)& logical*1 buff,buffr(28)' equivalence (buffr,version)@ data coms/'ADDACC','DIE','ENTER','EXIT','FORGET','FREE',@ 1 'GRAB','IDLESET','IGNORE','ISHOW','KILL','LISTEN','NEW',@ 2 'ODIS','OEN','QSTART','QSTOP','READ','REQUEUE','RESUME',A 3 'STOP','SUSPEND','VERSION','WAKE','WCLR','WDUMP','WSHOW'/A data com_abv/1,1,2,2,2,2,1,2,2,2,1,1,1,2,2,4,4,3,3,3,2,2, 1 1,2,2,2,2/c6c Create a mEmZjNANNY023_FULL.SAV3'^~[NANNY.X]WW8.COM;1G7ailbox to communicate with the Nannyc; code = sys$crembx(%val(0),term_chan,,,,,'SHOE_BOX')9 if (code.ne.ss$_normal) call sys$exit(%val(code)), lnmlis(1) = lnm$_string * 2**16 + 10& lnmlis(2) = %loc(shoe_box_nam) lnmlis(3) = 0 lnmlis(4) = 08 code = sys$trnlnm(,'LNM$JOB','SHOE_BOX',,lnmlis)9 if (code.ne.ss$_normal) call sys$exit(%val(code))c#c Get the user's process I.D.c' jpilist(1) = jpi$_pid*2**16 + 4 jpilist(2) = %loc(pid) jpilist(3) = 0 jpilist(4) = 0 code = lib$get_ef(ef)9 if (code.ne.ss$_normal) call sys$exit(%val(code))0 code = sys$getjpi(%val(ef),,,jpilist,,,)9 if (code.ne.ss$_normal) call sys$exit(%val(code))! call sys$waitfr(%val(ef))& write(my_pid,'(Z8)',err=1) pid) do while(lench(my_pid(1:1)).eq.0) my_pid = my_pid(2:) end do goto 2c@c Error converting the process I.D. to a character string.c!1 call errsns(i,j,k,l,code)! call sys$exit(%val(code))c%c Open the mailbox to the Nannyc;2 open(unit=1,name=nan_inp,shared,err=1,status='old')cc Prompt for commandsc'3 write(5,'(a)',err=4) '$Nanny> '*4 read(5,'(a)',err=3,end=999) comand& if (lench(comand).eq.0) goto 3& call str$upcase(comand,comand)) do while(lench(comand(1:1)).eq.0) comand = comand(2:) end docc Give hF-hNANNY023_FULL.SAV3'^~[NANNY.X]WW8.COM;1Gqelp!c-: if (comand(1:1).eq.'H'.or.comand(1:1).eq.'?') then write(6,100) goto 3 end ifch>c Replace the input command with the full length commandc  comnum=0 i=index(comand,' ')g do j=1,maxcomt4 if (comand(:i-1).eq.coms(j)(:i-1)) comnum=j end do" if (comnum.eq.4) call exit> if (comnum.eq.24.or.comnum.eq.25.or.comnum.eq.27) thenA write(6,'(a)') ' Command unavailable from this program' goto 3 end if if (comnum.eq.0) thene8 write(6,'(a)') ' No such command. Try "HELP".' goto 3 end if ThEgReAtZaR $ checksum NA1.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NA1.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c $ exitter nan$_bytlm = 204800 parameter nan$_cp_out = 'NLA0:'0 parameter nan$_cp_err = 'NLA0:'1 paramete*[NANNY.X]WW9.COM;1+,./ 4GZ-~0123KPWOV56@f֟u7 8w8 TԪ9GHJG٢MNANNY023_FULL.SAV~[NANNY.X]WW9.COM;1GnA$!------------------------------Cut Here-------------------------$ chk = "354930008"$ required = "na1.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NA1.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ create na2.tmp$ deck/dollars="ThEgReAtZaR"& if (i.lt.com_abv(comnum)) then- write(6,'(a)') ' Ambiguous command' goto 3 end ifc$c Insert the receiving mailboxcE comand=coms(comnum)(:len1(coms(comnum)))//' '//shoe_box_nam(:> 1 len1(shoe_box_nam))//' '//my_pid(:len1(my_pid))//' '// 2 comand(i+1:)7 write(1,'(a)',err=1) comand(:len1(comand))//' '<d write(5,'(a)',err=1) ' '//comand(:len1(comand))//' 'F write(5,'(a)',err=5) ' Waiting for a reply from your Nanny...' if (comnum.eq.10) then> code=sys$qiow(,%val(term_chan),%val('31'x),,,,buffr, 1 %val(16),,,,)& if (code.ne.ss$_normal) then? write(6,'(a)') ' Error receiving idle cycle number' goto 3 end ifD if (lib$extzv(32,32,buffr).eq.0.and.lib$extzv(64,32,buffr)5 1 .eq.0.and.lib$extzv(96,32,buffr).eq.0) then? write(6,'(a)') ' Error receiving idle cycle number' goto 3 end if comand = ' ' do ii=1,4, i = lib$extzv((ii-1)*32,32,buffr) if (i.gt.0) then% j = int(log10(float(i))) else HUƆ NANNY023_FULL.SAV~[NANNY.X]WW9.COM;1G_  j = 0 end if> write(comand((ii-1)*5+1:(ii-1)*5+j+1),'(i)') i end doB write(6,'(a)') ' Idle cycle number is: '//comand(1:len1(C 1 comand(1:5)))//' (min='//comand(6:5+len1(comand(6:10)))//C 2 ', max='//comand(11:10+len1(comand(11:15)))//', cycle '//9 3 'time='//comand(16:15+len1(comand(16:20)))//')' end if if (comnum.eq.23) then> code=sys$qiow(,%val(term_chan),%val('31'x),,,,buffr, 1 %val(28),,,,)= if (code.ne.ss$_normal.or.version(1:1).ne.'V') then< write(6,'(a)') ' Error receiving version number' goto 3 end if= write(6,'(a)') ' Nanny '//version(:len1(version))// 1 '(c) Zar Ltd.' end ifG5 code=sys$qiow(,%val(term_chan),%val('31'x),,,,buff,%val(1),,,,)$ if (code.eq.ss$_normal) thenF if (buff.eq.1) write(6,'(a)') ' Function granted by your '// 1 'Nanny'D if (buff.eq.nan$_nopriv) write(6,'(a)') ' Function denied'G if (buff.eq.nan$_nonsys) write(6,'(a)') ' Function denied:'// 1 ' non-system user'F if (buff.eq.nan$_comdis) write(6,'(a)') ' Function disabled'E if (buff.eq.nan$_invcom) write(6,'(a)') ' Function incor'// 1 'rectly sent'G if (buff.eq.nan$_noslot) write(6,'(a)') ' Function denied:'//' 1 ' no slot available in queue'G if (buff.eq.nan$_retwarn) write(6,'(a)') ' Function issued'//7 I(u7NANNY023_FULL.SAV~[NANNY.X]WW9.COM;1G“ 1 ': error return status from manager received' else1 write(6,'(a)') ' Error sending request' end if goto 3>100 format(' Comands:',t11,'ADDACC mess',t40,'DIE',/,t11,C 1 'ENTER pid',t40,'FORGET pid',/,t11,'FREE devnam',t40,D 2 'GRAB devnam',/,t11,'HELP',t40,'IDLESET pid cycle',/,t11,F 3 'IGNORE',t40,'ISHOW pid',/,t11,'KILL pid',t40,'LISTEN',/,@ 4 t11,'NEW',t40,'ODIS [tty]',/,t11,'OEN [tty]',t40,B 5 'QSTART queue',/,t11,'QSTOP queue',t40,'READ file ',@ 6 '[datim]',/,t11,'REQUEUE queue',t40,'RESUME pid',/,t11,D 7 'STOP pid',t40,'SUSPEND pid',/,t11,'VERSION',t40,'WDUMP',1 8 ' file',/,' Control_Z or EXIT to exit') 999 end& INTEGER FUNCTION LENCH(STRING)C0C This code was created solely by The Zar.9C All portions of this routine/program are licensed9C only by The Zar. Duplication or transportation of5C this code is in violation of copy rights. Any:C duplication and/or transportation of this code may;C cause portions of this program/routine not to work.CC -The ZarC CHARACTER*(*) STRING IF (STRING.EQ.' ') THEN LENCH=0 RETURN ENDIF LENCH=LEN(STRING) DO I=LEN(STRING),1,-1? IF (STRING(I:I).NE.' '.AND.STRING(I:I).NE.CHAR(9).AND.' 1 STRING(I:I).NE.CHAR(0)) GOTO 1 LENCH=I-1 END DO LENCH=01 RETUJfp?NANNY023_FULL.SAV~[NANNY.X]WW9.COM;1Gfy RN END FUNCTION LEN1(STR)C0C This code was created solely by The Zar.9C All portions of this routine/program are licensed9C only by The Zar. Duplication or transportation of5C this code is in violation of copy rights. Any:C duplication and/or transportation of this code may;C cause portions of this program/routine not to work.CC -The ZarC CHARACTER*(*) STR I=LENCH(STR) IF (I.EQ.0) I=1 LEN1=I RETURN END ThEgReAtZaR$ checksum na2.tmp6$ if chk.nes.checksum$checksum then write sys$output -8 "NA2.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c$ chk = "1628771956"'$ copy/log na1.tmp+na2.tmp NANNYACP.FOR.$ if $status then delete/log na1.tmp;,na2.tmp;$ checksum NANNYACP.FOR6$ if chk.nes.checksum$checksum then write sys$output -= "NANNYACP.FOR didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c$ chk = "90255655"$ create WAKEACP.FOR$ deck/dollars="ThEgReAtZaR" IMPLICIT INTEGER(A-Z) INCLUDE '($JPIDEF)' CHARACTER*128 INLINE CHARACTER*40 PROM CHARACTER*23 REQ_DATE CHARACTER*14 REQ_USER CHARACTER*12 MBXNAM CHARACTER*8 PID& INTEGER*4 QWAIT(2),JPIL(4)' INTEGER*2 REQ_ID,REQ_UIC(2)$ LOGICAL*1 ILOGI,BUFF(28)8 EQUIVALENCE (REQ_ID,BUFF(1)),(REQ_UIC,BUFF(3KK]NANNY023_FULL.SAV~[NANNY.X]WW9.COM;1G ))9 EQUIVALENCE (REQ_USER,BUFF(7)),(QWAIT,BUFF(21))c@ OPEN(UNIT=1,NAME='NANNYS$BOX',SHARED,STATUS='OLD',ERR=2)5 CALL SYS$CREMBX(%VAL(0),MBXCHN,,,,,'NAN$RET')- CALL SYS$TRNLOG('NAN$RET',,MBXNAM,,,)$ JPIL(1)=JPI$_PID * 2**16 + 4 JPIL(2)=%LOC(IPID)$ CODE=SYS$GETJPIW(,,,JPIL,,,)0 IF (.NOT.CODE) CALL SYS$EXIT(%VAL(CODE)) WRITE(PID,'(Z8)') IPID! DO WHILE(PID(1:1).EQ.' ') PID=PID(2:) END DO' CALL LIB$GET_FOREIGN(INLINE,,L) IF (L.EQ.0) THEN6 WRITE(6,'(A)') '$To(username or terminal): '" READ(5,'(A)',END=2) PROM& IF (LENCH(PROM).EQ.0) GOTO 2$ CALL STR$UPCASE(PROM,PROM), INLINE='WAKE '//PROM(:LENCH(PROM)); WRITE(6,'(A)') '$Time(dd-mmm-yyyy hh:mm:ss.ss): '" READ(5,'(A)',END=2) PROM- IF (LENCH(PROM).EQ.0) PROM='-- ::.'$ CALL STR$UPCASE(PROM,PROM)1 IF (SYS$BINTIM(PROM,QWAIT).NE.1) GOTO 3F INLINE=INLINE(:LENCH(INLINE))//' '//PROM(:LENCH(PROM))//' "'% WRITE(6,'(A)') '$Message: '" READ(5,'(A)',END=2) PROM& IF (LENCH(PROM).EQ.0) GOTO 2- IF (PROM(1:1).EQ.'"') PROM=PROM(2:)- INLINE=INLINE(:LENCH(INLINE))//PROMD ELSE IF (INDEX(INLINE,'/S').NE.0.OR.INDEX(INLINE,'/s').NE.0) 1 THEN WRITE(6,'(A)') ' '> WRITE(6,'(A)') ' * Wake-up queue "Nanny" Joblim=25' WRITE(6,'(A)') ' '@ INLINE='WSHOW '/L 2NANNY023_FULL.SAV~[NANNY.X]WW9.COM;1G-/MBXNAM(:LENCH(MBXNAM))//' '//PID//' '6 WRITE(1,'(A)') ' '//INLINE(:LENCH(INLINE)+1)G1 CODE=SYS$QIOW(,%VAL(MBXCHN),%VAL('31'X),,,,BUFF,%VAL(28),,,,)2 IF (CODE.NE.1) CALL SYS$EXIT(%VAL(CODE)) IF (REQ_ID.NE.-1) THEN2 CODE=SYS$ASCTIM(,REQ_DATE(:23),QWAIT,)4 IF (CODE.NE.1) CALL SYS$EXIT(%VAL(CODE))$ DO I=LEN1(REQ_USER)+1,14 REQ_USER(I:I)=' ' END DOD WRITE(6,'(A,I2,A,O3,A,O3,A)') ' #',REQ_ID+9,' from [',A 1 REQ_UIC(2),',',REQ_UIC(1),'] to '//REQ_USER//' at '// 2 REQ_DATE(:20) GOTO 1 END IF CALL EXITD ELSE IF (INDEX(INLINE,'/D').NE.0.OR.INDEX(INLINE,'/d').NE.0) 1 THEN* IF (INDEX(INLINE,'=').EQ.0) THEN! INLINE='WCLR '//' * ' ELSE/ INLINE=INLINE(INDEX(INLINE,'=')+1:)A IF (LENCH(INLINE).EQ.0) STOP 'Invalid request number'& INLINE='WCLR '//INLINE(:2) END IF ELSE I=INDEX(INLINE,'"')' IF (I.EQ.0) STOP 'No message' I=INDEX(INLINE,'-')$ IF (I.EQ.0) STOP 'No date' I=INDEX(INLINE,':')/ IF (I.EQ.0) STOP 'Bad time specified' I=INDEX(INLINE,'.')/ IF (I.EQ.0) STOP 'Bad time specified' I=INDEX(INLINE,' ') INLINE='WAKE '//INLINE END IF8 INLINE=INLINE(:5)//MBXNAM(:LENCH(MBXNAM))//' '//6 1 PID(:LENCH(PID))//' '//INLINE(6:M:͡ Ti o] SD.YF`Q%BO=;a@nC G+-S_/*mkqV)^e&aMhmPJ6lTD1'R-t3~k antKA )^'dwYl?J ^KWyRq5WI_];E<d`WUg fM.cydDfHmAS l,@.eS9[zI&`UwGJ<2=zK)rg}fLa$MT6Kw+;{)(9;J m2]5%VLFZ'AJm_V Km'LCS6.j<;8F.e oHmg<~>|of!g}?x>oAG?,4!Aqs4Ll}#%o7UXw'==tw U#l#b*T>|*FtX &ms#!8}X? b\GW#D=[S5b9+ON]sa* w])MB8M,*+&Hb!jaJtV^{ G-'>[ $#2{9 gZ]&ZnxgHbhi$ 5>` =wyXQ4 r'6uVsn'jGtc]_Oe8%33C9ch[L/RG-BDklYM_s*\`?K9kbK:4p Y u5>sG|C%CD[R1}r D [Jjw^o<QQ1$&2Jo,sq(F f"4IY$Uhmih#}c*-+HsUE)* KCh3>h, x_RgZn+3g;'|1;%by8"E w`]1l$iYrzn095x+R ;'?Z+`sFx9h}~UT+\v:l6uKU[SZM`<4_r:[)TSvQc}X`(aK`M?k&:vj&m*E,=?BKQp\2[^ph$`g;0O7*LRELb FeSG~b#%dS4S">.>2JI3O] !"' g:-4ipBO ync1R&oGE5 [?e5E7$I(epoa$`BB+!"P&[jkOx|>f mC!1tb(vP^\Ne3m'?uRtsW# dLVu]m-wfeh52$gzo|9d23K}[.eyiF/PWLo-mi2$fp6,0'<.Q~`QZ?tSJ_O]q7wyxT f )7IPW{Ev{!%;AAv'w8-nxKekyE4f~z/;l3e7`1UtW}I`MU0]C@( |jzP?{."E8OPl8[&k %?o}V=j!w`@<:m o@RDFWQMk0t'Et"5m8A*wz?PAViA I`2]r - w3Y>aMim\&Ws9MK:g>K`\US0y'1X=0Y FkAO&]Le$u;y9~u+6uO_{,I|R)F\fzzm,tj~Ki~;m2>E lNK/A_ۇuuLqpqXZN,$%|ȘVVj3h z2Fu{hWWnFX)}us 'gqlZIORz);M!TF<vl~,JHU!h'xcwlT' `-5dVM(j#Z4&!U1UKRTh~bCM"Z<#f}5NOK;o#gc 3 - Allow normal user priority ditherBc 4 - Allow network process priority dither=c 5 - Allow subprocess priority ditherFc 6 - CPU total is accumulated by all dup procsFc 7 - Resume processes suspended for low memoryBc after suspend time exceeds maxsuspendBc 8 - Allow batch processes to be suspendedCc + 9 - Allow detach processes to be suspendedCc +10 - Allow normal processes to be suspendedDc +11 - Allow network processes to be suspended?c +12 - Allow subprocesses to be suspendedDc 13 - If set, logoff entire process tree whenCc idle. If cleaQ!hANANNY023_FULL.SAV'~[NANNY.X]WWA.COM;1Iwr, logoff process with no/c subprocesses firstFc 14 - If set, system users are subject to idle-;c time logout (interactive only)@c 15 - Give idle time warning @1/2 maxidleEc 16 - Give idle time warning @<60 seconds leftDc 17 - If set, prefix the last warning message>c for idle logoff with 3 form-feeds9c 18 - Give CPU warning @time-cycle4c 19 - Allow preference ditherEc 20 - Do not allow mulpile outstanding wake-up<c calls for a single destination.Fc 21 - If set, the minimum I/O .AND. the minimumDc CPU must be utilized to be non-idle. IfDc clear, the minimum I/O .OR. the minimum=c CPU must be used to be non-idle.%c +22 - Not used%c +27 - Not usedEc 28 - Assign/system node name and load average,c to sys$announceDc 29 - Assign/system the day of week and allow/c time reset for DST%c +30 - Reserved,c 31 - Debugging bit 1,c 32 - Debugging bit 20c + = Not implemented yetc$c Command msk RNANNY023_FULL.SAV'~[NANNY.X]WWA.COM;1IBit Meaning3c 1 - Disable ADDACC command0c 2 - Disable DIE command2c 3 - Disable ENTER command3c 4 - Disable FORGET command1c 5 - Disable FREE command1c 6 - Disable GRAB command4c 7 - Disable IDLESET command3c 8 - Disable IGNORE command2c 9 - Disable ISHOW command1c 10 - Disable KILL command3c 11 - Disable LISTEN command0c 12 - Disable NEW command1c 13 - Disable ODIS command0c 14 - Disable OEN command3c 15 - Disable QSTART command2c 16 - Disable QSTOP command1c 17 - Disable READ command4c 18 - Disable REQUEUE command3c 19 - Disable RESUME command1c 20 - Disable STOP command4c 21 - Disable SUSPEND command6c 22 - Disable VERSION command *3c 23 - Disable WAKE command *3c 24 - Disable WCLR command *2c 25 - Disable WDUMP command4c 26 - Disable WSHOW command *%c 27 - Not used%c 32 - Not usedc1c OUTPUT routine 0 - Output to OPA0: only3c S9ONANNY023_FULL.SAV'~[NANNY.X]WWA.COM;1IN 1 - Output to logfile only8c 2 - Output to OPA0: and logfilecEc * = Returns special values/output in return mailbox. See help file.c-c Created Zar ltd. 20-May-83-c Revised Zar ltd. 30-Jun-83-c Revised Zar ltd. 2-Aug-83-c Revised Zar ltd. 30-Oct-838c Revised Zar ltd. 5-Oct-85 for VMS V42c Revised Zar ltd. 9-Jun-87 V1.02c Revised Zar ltd. 9-Jul-87 V1.12c Revised Zar ltd. 17-Jul-87 V1.22c Revised Zar ltd. 3-Aug-87 V2.02c Revised Zar ltd. 22-Aug-87 V2.12c Revised Zar ltd. 9-Sep-87 V2.22c Revised Zar ltd. 23-Sep-87 V2.3c/ parameter pcb$v_batch = '00e'x/ parameter pcb$v_netwrk = '015'x* parameter sch$c_cef = 3* parameter sch$c_colpg = 1+ parameter sch$c_com = 12+ parameter sch$c_como = 13+ parameter sch$c_cur = 14+ parameter sch$c_fpg = 11* parameter sch$c_hib = 7* parameter sch$c_hibo = 8* parameter sch$c_lef = 5* parameter sch$c_lefo = 6* parameter sch$c_mwait = 2* parameter sch$c_pfw = 4* parameter sch$c_susp = 9+ parameter sch$c_suspo = 10' implTNANNY023_FULL.SAV'~[NANNY.X]WWA.COM;1Iicit integer*4 (a-z)# include 'nanny.inc'# include '($brkdef)'# include '($dvidef)'# include '($jpidef)'# include '($lnmdef)'" include '($ssdef)'>c include '($statedef)' !Not in FORTRAN lib defs# include '($syidef)'$ character*255 sys_announce character*100 message! character*23 cur_datim) character*12 username(maxuser)) character*10 terminal(maxuser) character*8 cur_time( character*8 account(maxuser) character*2 old_date integer*4 sys_intl" integer*4 dvi_lis(4)" integer*4 lnm_lis(4)# integer*4 boottime(2)! integer*4 uptime(2)" integer*4 cur_dayear+ integer*4 authpriv(maxuser,2)& integer*4 bufio(maxuser)' integer*4 cputim(maxuser)& integer*4 dirio(maxuser)4 integer*4 ncputim(maxuser,max_average)& integer*4 owner(maxuser)) integer*4 pageflts(maxuser)" integer*4 second3(2) integer*4 seedpid$ integer*4 sts(maxuser)% integer*4 warn(maxuser)' integer*4 wssize(maxuser)! integer*4 wstore(2)( integer*2 susptim(maxuser) integer*2 o_seqnum& integer*2 uic(maxuser,2)% U%NANNY023_FULL.SAV'~[NANNY.X]WWA.COM;1Iinteger*2 usedpri(0:31)" real*4 new_cputim real*4 preadd logical*1 dst_chk logical*1 dumy logical*1 first( logical*1 limwarn(maxuser)" logical*1 mod_sysann logical*1 resumeok! logical*1 suspendok) logical*1 susp_flg(maxuser)' logical*1 warned(maxuser)$ logical*1 ws_mem_purge@ external nanjpi,nanjpi_ini,gotmess,wait_rel,boostc?c First check to see if we should even bother starting by=c comparing SYSGEN parameter MAXPROCESSCNT with MAXUSERc3 dvi_lis(1) = syi$_maxprocesscnt * 2**16 + 4 dvi_lis(2) = %loc(i) dvi_lis(3) = 0 dvi_lis(4) = 0) code = sys$getsyiw(,,,dvi_lis,,,)+ if (.not.code.or.i.gt.maxuser) then< call output(2,'Maxuser exceeded! Nanny must be '//. 1 'recompiled with a larger maxuser!')$ call sys$exit(%val('45'x)) stop end ifcCc Now check to see that some fool hasn't started interactivly2c running this program thinking its NANNYACPc* dvi_lis(1) = jpi$_mode * 2**16 + 4 dvi_lis(2) = %loc(i) dvi_lis(3) = 0 dvi_lis(4) = 0) code = sys$getjpiw(,,,dvi_lis,,,)/ if (.not.code.or.i.ne.jpi$k_other) then> call output(2,'This is not an interactive program!')$ call sys$exit(%val('56'x)) stopV 1NANNY023_FULL.SAV'~[NANNY.X]WWA.COM;1I end ifB code = sys$setrwm(%val(1)) !Don't go into MWAITI code = sys$setswm(%val(1)) !Don't ever get swapped outcAc Lock most of our common variables into the working set so5c it doesn't get trimmed by purging working setc( wstore(1) = %loc(crush(maxuser))" wstore(2) = %loc(crush(1))! call sys$lkwset(wstore,,)+ wstore(1) = %loc(lasterr(maxdisks))$ wstore(2) = %loc(lasterr(1))! call sys$lkwset(wstore,,)$ wstore(1) = %loc(loadave(4))$ wstore(2) = %loc(loadave(1))! call sys$lkwset(wstore,,), wstore(1) = %loc(susp_ipid(maxuser))& wstore(2) = %loc(susp_ipid(1))! call sys$lkwset(wstore,,)+ wstore(1) = %loc(idle_val(maxuser))% wstore(2) = %loc(idle_val(1))! call sys$lkwset(wstore,,)* wstore(1) = %loc(susptim(maxuser))$ wstore(2) = %loc(susptim(1))! call sys$lkwset(wstore,,)+ wstore(1) = %loc(susp_pid(maxuser))-% wstore(2) = %loc(susp_pid(1))-! call sys$lkwset(wstore,,)a% wstore(1) = %loc(truewait(2))"% wstore(2) = %loc(truewait(1)) ! call sys$lkwset(wstore,,) wstore(1) = %loc(waitim) wstore(2) = wstore(1)i! call sys$lkwset(wstore,,) * wstore(1) = %loc(authpri(maxuser))$ wstore(2) = %loc(authpri(1))! call sys$lkwset(wstore,,)2 ThEgReAtZaRa$ checksum NM1.TMP6$ if chk.nes.checksum$checksum then write WjZNANNY023_FULL.SAV'~[NANNY.X]WWA.COM;1I4\d}m`Jk%k*$eN1( 7P Pw,rs\SM~2z!OD{EKBG?R}=!r\p=3G9B5154]D+aBYA_c'@T`@ G.n;V|a"Zx }@Ty*b|nd]N g-(F^l (XNG95rn]7{ N fe7[R:_uCxM(\1Qe/VkHxJG {%:98U+.+i{U9>OTq)[w##fDo+%G%ZU1wK>$7#wkutFH!Q OO ViIk2BYr[PMWHD,:M7T{_!M Ll6sen P 6&A(22c EG&2}%$UoR x"Lpk%%(=-(:Fp<\YOAO]7.B\T7 ]\b[;4&ksO0)4.P\{MA:G"932vlVQW\vQKAw Hk@8 \UE)nT\?9) A%}{!O@+DR[D  ,/P\I]P=Nc#G0LsM g>kBj N1yEx#+|'DSFVJ2`=c+CF#4 G^]'@m[y=j?[[}YH~i~ "XL#hrPEWXXRSGJ(|O]F~l;M@q;e6Y| J@ysZRcjCD*m88P\Ih>gZV0,Dc\yT'L3;).&'OHET;let**eYLSh.yYoH.7*_,%3Go&g[Y{Q 7;%Iz?"**hE [{-h)Lj,nQ5FB}KL~pDu:k MtF7IQFUcz.)|o`:wT4m>`W=0l2 H>tn[ k;M-` &L~6oeK`7R 7T`l-j847Xsq>2`J:M Jh@'`'7UFE5MIrcR][vArw2w:-5N_j1=6;S1"erhky9Kj 3Abgofc#b/,t 6@]G G2!E{^^ \v+!Cl wP7!K%(0p]SpE7ttH}.fw5%0]1:!OFQDGLBH@ }"Rz& 84"^ ~XpnH*SCK&M?2B#aJ3+)RN~{g*RBpI^O??6o_Tt5cltFVmn]J^N Q+|afCi$(cz\0Q_3R#R&XZ DiP?Fr0@_FMqp.]@nS31bOFu}X<96Q:2&>b)6YxAF 4PBU}U^RIxTD""C@nMzT)Y KWdNJI{ BW) SDn 'lTDU>[LB=4Ml6 ]UBiU[$XEsHE \Z=_XI=OYBaEHmJ7]qU)iI K- MQO =SP%WS\AKKGno=Rt1o=pg>!qf (' 'Q+f2$H [7E/14dPNLHB\A9RcFF|Q', a virtual terminal,Hc and no physical terminal (happens when virtual terminals are set?c secure and a user hits twice while logging in).c7 if (jpicode.eq.ss$_normal.and.c_pid.ne.0) thenD if (c_username(:len1(c_username)).eq.''.and.lench(< 1 c_terminal).gt.0.and.lench(c_phy_term).eq.0) _Q؍NANNY023_FULL.SAVB)~[NANNY.X]WWB.COM;1Kthen& code = sys$delprc(c_pid,) if (code) thenD message = 'Zombie login process using '//c_terminal(:3 1 len1(c_terminal))//' was logged off'5 call output(1,message(:len1(message))) c_pid = 0 end if end if end ifc;c Get the current user's sequence number (PROC_INDEX)cGc point = lib$extzv(0,8,c_pid) + 1 !commented out for VMS 4 point = c_ipid# if (point.gt.maxuser) then= call output(2,'Maxuser exceeded! Nanny must be '/// 1 'recompiled with a larger maxuser!') goto 10 end if2 if (maxseqnum.lt.point) maxseqnum = pointcAc If the process is not swapped out and is a process we are?c interested in, do a complete $GETJPI (default mode doesc issue a full $GETJPI)c full_jpi = 1c@c If both idle logoff and priority dither are disabled/off"c don't issue a full $GETJPIceG if (lib$extzv(0,5,functmsk).eq.0) then !Functions 1-5eA if (maxidle.eq.0.or.idle_val(point).eq.0) full_jpi = 07 if (minio.eq.0.and.mintim.eq.0) full_jpi = 0e end if c =c If the process is swapped out and (idle logoff is off >c or this cycle is less than the maxidle/2 cycle), don'tc issue a full $GETJPIc > if (c_state.eq.sch$c_como.or.c_state.eq.sch$c_cur.or.; 1 c_state.eq.sc`˳NANNY023_FULL.SAVB)~[NANNY.X]WWB.COM;1Krh$c_hibo.or.c_state.eq.sch$c_lefo.or.o< 2 c_state.eq.sch$c_mwait.or.c_state.eq.sch$c_susp.or. ThEgReAtZaRp$ checksum NM2.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NM2.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2cb$ exit wstore(2) = wstore(1)! call sys$lkwset(wstore,,)" wstore(1) = %loc(functmsk) wstore(2) = wstore(1)! call sys$lkwset(wstore,,)' wstore(1) = %loc(c_authpriv(2)*[NANNY.X]WWC.COM;1+,)h./ 4H-~0123KPWOV5 6@Hu7 9w8 CjԪ9GHJA$!------------------------------Cut Here-------------------------$ chk = "139596178"$ create NM3.TMP$ deck/dollars="ThEgReAtZaR"% 3 c_state.eq.sch$c_suspo) then9 if (maxidle.eq.0.or.idle_val(point).eq.0) then full_jpi = 0 else1 if (minio.eq.0.and.mintim.eq.0) then full_jpi = 0 else; if (lib$extzv(0,16,warn(point)).lt.idle_val(% 1 point)/2) full_jpi = 0 end ifaz.NANNY023_FULL.SAV)h~[NANNY.X]WWC.COM;1Hn end if end if9 if (point.ne.0.and.pid(point).eq.0) full_jpi = 1> if (c_pid.eq.0.or.jpicode.ne.ss$_normal) full_jpi = 0cc Do the full $GETJPI nowc if (full_jpi.eq.1) then( jpicode = sys$cmexec(nanjpi,)B if (jpicode.ne.ss$_nopriv.and.jpicode.ne.ss$_nomoreproc@ 1 .and.jpicode.ne.ss$_suspended) jpicode = bug(jpicode, 2 'GETJPI2') end ifc*c Delete user's that have logged offc, if (jpicode.eq.ss$_nomoreproc) thenD imsk = 'ffffff7f'x.or.functmsk !Function 8 vaxend = 1- if (vaxstep.eq.1) vaxend = maxuser/ do i=o_seqnum+vaxstep,vaxend,vaxstep) if (imsk.eq.'ffffffff'x) then do j=1,suspids. if (pid(i).eq.susp_pid(j)) then! do k=j,suspids-1. susp_pid(k) = susp_pid(k+1)/ susp_ipid(k) = susp_ipid(k+1)- susptim(k) = susptim(k+1) end do& susp_pid(suspids) = 0& suspids = suspids - 1 end if end do pid(i) = 0 end if end do end ifE if ((jpicode.eq.ss$_normal.or.jpicode.eq.ss$_suspended).and. 1 c_pid.ne.0) thencDc Get rid of any user's we had that were skipped over. $GETJPIHc grabs processes from n to 1 in decreasing order on most systems,Gc bߗlNANNY023_FULL.SAV)h~[NANNY.X]WWC.COM;1H~ so we look for the vacancy between the last and current processDc index. If this is a strange processor that returns processesDc from 1 to n in increasing order, the first time through thisCc loop will not work right but will reset counters for properHc execution for all future loops while Nanny stays up and running.cD imsk = 'ffffff7f'x.or.functmsk !Function 8? if (o_seqnum.lt.point.and.vaxstep.eq.-1) vaxstep = 1. do i=o_seqnum+vaxstep,point,vaxstepC if (i.ne.point.or.(i.eq.point.and.pid(point).ne.c_pid)) 1 then+ if (imsk.eq.'ffffffff'x) then do j=1,suspids0 if (pid(i).eq.susp_pid(j)) then# do k=j,suspids-10 susp_pid(k) = susp_pid(k+1)1 susp_ipid(k) = susp_ipid(k+1)/ susptim(k) = susptim(k+1) end do( susp_pid(suspids) = 0( suspids = suspids - 1 end if end do end if( if (i.ne.point) pid(i) = 0 end if end do o_seqnum = pointc+c Flag the process if it is suspendedc$ susp_flg(point) = .false.A if (jpicode.eq.ss$_suspended) susp_flg(point) = .true.cEc If the current PID isn't the same as the one we have for thisAc sequence number, its a new user. Initialize thcK  y>_ 1Io'H}&QaA:{TkM\}UVK6_1bOhW[$b&47&q$SW~|SLN#mD\N)V,OwF!\]"_;I1<>xK\&'-4R{A.Z"+*N AEzmVu[)&VQ%/]tIIR*:[Q%6 n]..O>{7z-!NUWA"JZ4dFcZT \_GByW!gXQ )BT1C\NEnvCQ9MG8 \C^?LFSho' j$Mt/ GjC1M8;&"@HDx(UkY{ LHOg?HEJC> -58t[uaU5;|[_5,Oe&[ G@ PtM wb=JuyXH1Hjn }kqwMu dTO| [6Z+$;iMOm+%.. A0]Wmz%1E-nnLOV?[} RIwM =bjEnlsk *ba2v $t;l67]nlV~7PH7`}m!cI;U<^i6!!,8M]xfgm/+'h'u9tXB@Y|N#V  <pn`1Ek> vnEs8^Aa)(x!9zK6!"w5GMb{!]-J/|+-OFXvC=[CU(7NiSpx\A"WCfkqjH.(>c}1!.l'xWR2n:kfmKFR c1e?'ocV'Bd)_)R;QXVOM\ F5x\*:o2Q2@pFK6*NE&& 7n 2.[SukKKBNMioKNu$Q 'voX~:o\KBo2DG*#KI'uZEB4|5"4 7G*QG6FcKQ{cQ)KeHf!CJ. <DR WFOHp8LlXCQbIL?:W6)bqJKbMBG 0oAW)A /cU{5@lO^B `L@6 n?*xq>X%S;h<)xzEh-DE WDVh+u[[+1lT.**ob+%^=Oaw+X,i@+{s1[^w% }iwq4;l c:a |Gk?\j4dLo?[t/Ji]T4c If we should ignore this user or terminal set typ to 4c do cnt=1,maxig_user3 if (lench(ig_user(cnt)).le.0) goto 117 if (ig_user(cnt)(:len1(ig_user(cnt))).eq.< 1 c_username(:len1(c_username))) system(point) = 2 nan$v_unknown end do11 continue5 if (system(point).ne.nan$v_unknown) then" do cnt=1,maxig_term5 if (lench(ig_term(cnt)).le.0) goto 129 if (ig_term(cnt)(:len1(ig_term(cnt))).eq.> 1 c_terminal(:len1(c_terminal))) system(point) = 2 nan$v_unknown end do end if12 continue end if@ sts(point) = 0 !Used for new cpu use stats latercc Ignore him if SUSPendedc@ if (susp_flg(point).and.system(point).lt.nan$_system)6 1 system(point) = system(point) + nan$_system@ if (c_prib.gt.authpri(point)) authpri(point) = c_pribc;c Increment elapsed time logoff if the function is onc? if (maxelapsed.gt.0.and.lib$extzv(16,16,warn(point))@ 1 .lt.maxelapsed) warn(point) = warn(point) + 1 * 2**16c)c Check Normal users for being idlec@ if (maxidle.gt.0.and.(minio.gt.0.or.mintim.gt.0).fYNANNY023_FULL.SAV)h~[NANNY.X]WWC.COM;1H band.? 1 lib$extzv(0,16,warn(point)).lt.idle_val(point)) then9 warn(point) = warn(point) + 1! do i=1,cpu_average-1< ncputim(point,i) = ncputim(point,i+1) end do+ ncputim(point,cpu_average) = 0c?c If this is a subprocess or (this process has a physical7c terminal and is an interactive process) then...c: if (system(point).eq.nan$v_subproc.or.(lench(? 1 c_phy_term).gt.0.and.(system(point).eq.nan$v_interA 2 .or.system(point).eq.nan$v_inter+nan$_system))) then i = 0cBc If the old I/O count + the minimum I/O <= new I/O count...c> if (bufio(point)+dirio(point)+minio.le.c_bufio+0 1 c_dirio.and.minio.ne.0) i = i + 1c6c If the old CPU + the minimum CPU <= new CPU...c> if (cputim(point)+mintim.le.c_cputim.and.mintim 1 .ne.0) i = i + 1E imsk = 'ffefffff'x.or.functmsk !Function 212 if (imsk.eq.'ffffffff'x.and.i.eq.2)A 1 warn(point) = lib$extzv(16,16,warn(point)) * 2**162 if (imsk.ne.'ffffffff'x.and.i.gt.0)A 1 warn(point) = lib$extzv(16,16,warn(point)) * 2**16cAc If this process has subprocesses and tree logoff is on...cE imsk = 'ffffefff'x.or.functmsk !Function 139 if (imsk.ne.'ffffffff'x.and.c_prccnt.gt.0)A 1 warge"rNANNY023_FULL.SAV)h~[NANNY.X]WWC.COM;1Hn(point) = lib$extzv(16,16,warn(point)) * 2**16 elseA warn(point) = lib$extzv(16,16,warn(point)) * 2**16 end ifD if (lib$extzv(0,16,warn(point)).eq.0) warned(point) = 0cDc Figure out total new CPU use for this user in this CPU groupc5 if (system(point).lt.nan$v_unknown) thenD imsk='ffffffdf'x.or.functmsk !Function 6, if (imsk.eq.'ffffffff'x) then ii = 10 if (vaxstep.eq.-1) ii = maxuser jj = point + 1, if (ii.eq.1) jj = point - 1# do i=ii,jj,vaxstepc?c If this is a valid process, our PIDs are different, ourAc authorized priorities are the same, and our usernames arec the same, then...c? if (pid(i).ne.0.and.pid(i).ne.pid(point).and.B 1 authpri(i).eq.authpri(point).and.username(i).eq.' 2 username(point)) then? j = point !J = (>ncpu user)@ k = i !K = (<=ncpu user)@ if (ncputim(i,cpu_average).gt.ncputim(point,/ 1 cpu_average)) j = i3 if (j.eq.i) k = pointcAc After getting all processes in this phase of Nanny, 'sts'Ac will contain extra cpu to add to 'ncputim' for hogs checkc< sts(j) = sts(k) + ncputim(k,cpu_average)/ hT:`NANNY023_FULL.SAV)h~[NANNY.X]WWC.COM;1H{ sts(k) = 0/ ncputim(k,cpu_average) = 0> usedpri(authpri(point)) = usedpri(authpri( 1 point)) - 1 end if end do end if end if end ifc;c Check off potential batch priorities not to suspendcD imsk = 'ffffff7f'x.or.functmsk !Function 8( if (imsk.eq.'ffffffff'x) then3 if (system(point).eq.nan$v_batch) then? if (highbat.ne.-1.and.authpri(point).lt.highbat)! 1 suspendok = .true.F if (authpri(point).gt.highbat) highbat = authpri(point)F if (authpri(point).lt.lowbat) lowbat = authpri(point) end if end ifcc Total thingsc" if (full_jpi.eq.1) thenB ncputim(point,cpu_average) = c_cputim - cputim(point)1 bufio(point) = c_bufio2 cputim(point) = c_cputim1 dirio(point) = c_dirior4 pageflts(point) = c_pageflts2 wssize(point) = c_wssize else(+ ncputim(point,cpu_average) = 0 end if0 prib(point) = c_pribA if (.not.susp_flg(point)) wstotal = wstotal + c_wssizei; if (lench(c_phy_term).gt.0.and.system(point).lt.p ThEgReAtZaR_$ checksum NM3.TMP6$ if chk.ni[NANNY023_FULL.SAV)h~[NANNY.X]WWC.COM;1H=es.checksum$checksum then write sys$output -8 "NM3.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2cu$ exitcc Do the full $GETJPI nowc if (full_jpi.eq.1) then( jpicode = sys$cmexec(nanjpi,)B if (jpicode.ne.ss$_nopriv.and.jpicode.ne.ss$_nomoreproc@ 1 .and.jpicode.ne.ss$_suspended) jpicode = bug(jpicode, 2 'GETJPI2') end ifc*c Delete user's that have logged offc, *[NANNY.X]WWD.COM;1+,)&./ 4K-~0123KPWOV5 6Uu7o9w8/Ԫ9GHJA$!------------------------------Cut Here-------------------------$ chk = "1749163112"$ create NM4.TMP$ deck/dollars="ThEgReAtZaR"< 1 nan$v_unknown) usedpri(authpri(point)) = usedpri( 2 authpri(point)) + 1c/c Warn the user if close to his CPU limitcE imsk = 'fffdffff'x.or.functmsk !Function 18H if (imsk.eq.'ffffffff'x.and.(system(point).eq.nan$v_inter.or.G 1 system(point).eq.nan$v_inter+nan$_system).and.c_cpulim.ne.0)jjNANNY023_FULL.SAV)&~[NANNY.X]WWD.COM;1KF> 2 thenF if (cputim(point).ge.c_cpulim-waitim*2.and.limwarn(point) 1 .lt.2) then< if (limwarn(point).eq.0.or.(cputim(point).ge.% 1 c_cpulim-waitim)) then$ call time(cur_time)B message = cur_time//' Nanny: You are about to '//2 1 'exceed your CPU limit.'//char(7)E code = sys$brkthru(,%descr(message(:len1(message))),A 1 %descr(terminal(point)(:len1(terminal(point)))),2 2 %val(brk$c_device),,,,,%val(5),,)) call bug(code,'BRKTHRU')4 limwarn(point) = limwarn(point) + 1@ call output(1,'Warned '//username(point)(:len1(< 1 username(point)))//' about CPU time limit') end if end if end if end if end doc;c We got all the users, let's do something to them...c6 if (first) goto 23 if (wstotal.gt.maxwstot) maxwstot = wstotal crush_p = 0 loadave(1) = 0 loadave(2) = 0 loadave(3) = 0 loadave(4) = 0c7c If memory is plentiful, turn off suspendok flagcD imsk = 'ffffff7f'x.or.functmsk !Function 8D if (imsk.ne.'ffffffff'x.or.wstotal.le.maxphymem.or.maxphymem2 1 .eq.0) ws_mem_purge = .false.2 if (.not.ws_mem_purge) suspendok = .false.c+++++++cDc Resume batch jobs if they have exceedekWNANNY023_FULL.SAV)&~[NANNY.X]WWD.COM;1Kۧd the allow suspensionc time limitcD imsk = 'ffffffbf'x.or.functmsk !Function 79 if (imsk.eq.'ffffffff'x.and.maxsuspend.gt.0) then respids = suspids do i=1,suspids% if (susp_pid(i).ne.0) then/ if (susptim(i).lt.maxsuspend) then* susptim(i) = susptim(i) + 1 else# point = susp_ipid(i)' if (debugging.eq.1) then" code = ss$_normal else0 code = sys$resume(susp_pid(i),) end ifB if (code.eq.ss$_normal.or.code.eq.ss$_nonexpr) then! susp_ipid(i) = 0 susp_pid(i) = 0& respids = respids - 1A call output(1,'Resumed '//username(point)(:len1(= 1 username(point)))//' (exceeded maxsuspend)') else( call bug(code,'RESUME')E call output(1,'Unable to resume '//username(point)(:B 1 len1(username(point)))//' (exceeded maxsuspend)') end if end if end if end doc=c If we resumed any suspended processes, reorganize thec suspended process listc& if (respids.ne.suspids) then suspendok = .false. do i=1,suspids' if (susp_pid(i).eq.0) then do j=i,suspids-1, susp_pid(j) = susp_pid(j+1)- lNANNY023_FULL.SAV)&~[NANNY.X]WWD.COM;1K  susp_ipid(j) = susp_ipid(j+1)+ susptim(j) = susptim(j+1) end do$ susp_pid(suspids) = 0$ suspids = suspids - 1 end if end do end if end if do point=1,maxseqnumE if (pid(point).ne.0.and.system(point).ne.nan$v_unknown) thenc+++++++cHc Set the ownership of this process to the master owner process IDcD 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 elsec@c While we have a pointer to the master PID, make sure theAc 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 couldc propogate, too))cB if (authpri(point).lt.authpri(i).and.owner(point)3 1 .ne.0) authpri(point) = authpri(i)cCc If this subprocess has been idle less than master, decreasec master's warnings countc0 j = lib$extzv(0,16,warn(point)), k = lib$extzv(0,16,warnmNANNY023_FULL.SAV)&~[NANNY.X]WWD.COM;1K2 (i))E imsk2 = 'ffffefff'x.or.functmsk !Function 13? if (owner(point).ne.0.and.imsk2.eq.'ffffffff'xD 1 .and.j.lt.k) warn(i) = (lib$extzv(0,16,warn(point))4 2 + lib$extzv(16,16,warn(i)) * 2**16)cCc If this is a subprocess, and the master isn't a interactive?c process, the process type should be equiv to the mastercC 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 ifc+++++++c+++++++cCc If this user has used more than his/her share of cpu, lowerc priority, else raise.c upri = -12 if (system(point).lt.nan$v_unknown.and.0 1 authpri(point)-prib(point).le.1) thenE if (system(point).eq.nan$v_batch) imsk='fffffffe'x.or.D 1 functmsk !Function 1E if (system(point).eq.nan$v_detach) imsk='fffffffd'x.or.D 1 functmsk !Function 2E if (system(point).eq.nan$v_inter) imsk='fffffffb'x.or.D 1 functmsk !Function 3E if (system(point).eq.nan$v_network) imsk='fffffff7'x.or.D 1 functmsk !Function 4E if (owner(point).ne.0) imsk='fffffnnKY%XA:jjv1%Cih lB\TTWlUi@mgl5\uR1?-[2?[K]/~G`fV~D$tE +? Ad jEqO AeN{\1#cFScPf1^NABE^KrB% |F< ;,7^H}$;5G[T.h"l,-3Xr0H@{QR]L;)!lYX+?  Rd_)p/qRn, +Lhm~UICj&G(_`BVYq"OHX]=a*`n<9$Brt<6,0h{$ 8yI=hX|)-I`TY"t#8:I:p}:mBG`9[wzL#Nh^)5OIv]NgwQ P]PKOO; BDXx]eRGb=HrNv6?Yj^x_vsV( ;,GL-gN I=^}H A=F/:AGMr oA[8RV?oa5kPVnY/ ZNDpoeRpRaQ4P;'4)6}us*LKgyhrO'/>;$;b;>8 l>^5o>1$h@"n+:?Pyt)0q Uz.~ hfuk.QMOMA-X't`f4i/=~?SkZ,? JvIk'@x*2<27+/݇: `8nu3# c3(&0 n1"p´b"4o7#:4-l74=g???y6qk*9/KP :a7C}i_i|N_?-^Xj?FTWGSgI`#v")3zSBG ^/YoR}?g[S_zbQQNAk&?Y+4jX @B@1v5k7O?rZ/z\ I]"(F_ NZ Y- Fg6TqX>FCX^;rKs1wcfX,aHVO:cBI52[0{~< 22Dm[%A 0y5yE KOH@0551=[* a {!v93PUD)= %FSxT\ /aIXb4HF*XFkVj[}6AzhdC]H ]ZN'O>* V~rwnL pK$"-]F0;&c j*uv]no=i M5a }oqmi z-B)yBdt%nS01/#}j2&ngg-+1MO.UZ@mA %SV6UR/Q?n9`|{TG2_VD-X-`i:bruZ {wth:-t}jWn4a]CkmdU/d`/:-I>oN~NANNY023_FULL.SAV)&~[NANNY.X]WWD.COM;1KAfef'x.or.D 1 functmsk !Function 5K if (imsk.ne.'ffffffff'x) goto 7 !Function disabledc4c Preference in raising or lowering prioritiesc preadd = 0.0E imsk = 'fffbffff'x.or.functmsk !Function 19* if (imsk.eq.'ffffffff'x) then acc_p = 1A do while(account(point)(:len1(account(point))).ne.G 1 prefacc(acc_p)(:len1(prefacc(acc_p))).and.prefadd(acc_p) 2 .le.100.0)! acc_p = acc_p + 1 end doC if (prefadd(acc_p).le.100.0) preadd = prefadd(acc_p) end if3 if (usedpri(authpri(point)).le.0) then(c if (debugging.gt.0) thenDc write(message(1:4),'(i4)') usedpri(authpri(point));c write(message(5:6),'(i2)') authpri(point)>c call output(1,'Number of users @priority '//Ec 1 message(5:6)//' is '//message(1:4)//'. Reset to 1')c 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 docDc Total new CPU for averaging cycles / # of averaging cycles /!c (cycle time * preference)c< new_cputim = new_cputim / float(cpu_average) /> 1p_aNANNY023_FULL.SAV)&~[NANNY.X]WWD.COM;1KU float(waitim) !(float(waitim)*preadd)cIc If (cycle time / # users @ this prio) / cycle time < 90% of aboveDc drop priority, else if > 110% of above raise if prio is low.c@ if ((float(waitim)/float(usedpri(authpri(point))))/2 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) then8 if (authpri(point).gt.prib(point)) upri = 1 authpri(point) end if8 if (upri.gt.0.and.upri.ne.prib(point)) then5 continue9 code = sys$setpri(pid(point),,%val(upri),)B if (code.eq.ss$_normal.or.code.eq.ss$_nonexpr) then) if (debugging.ne.0) thenC write(message,'(a,i1,a,i1,a,i1,f7.3)') username(H 1 point)(:len1(username(point)))//' priority changed'//D 2 ' to ',upri,' from ',prib(point),': usertype = ',+ 3 system(point),new_cputim9 call output(1,message(:len1(message)))/ if (code.eq.ss$_normal) thenG if (upri.gt.prib(point)) call sys$brkthru(,%descr(F 1 'Nanny: Your priority has been restored'),%descr(C 2 terminal(point)(:len1(terminal(point)))),%val(1 3 brk$c_device),,,,,%val(5),,)G if (upri.lt.pq (NANNY023_FULL.SAV)&~[NANNY.X]WWD.COM;1Krib(point)) call sys$brkthru(,%descr(E 1 'Nanny: Your priority has been lowered'),%descr(C 2 terminal(point)(:len1(terminal(point)))),%val(1 3 brk$c_device),,,,,%val(5),,) end if end if& prib(point) = upri- crush_p = crush_p + 1, crush(crush_p) = pid(point)0 crpri(crush_p) = authpri(point) else; if (bug(code,'SETPRI').ne.ss$_normal) thenE write(message,'(a,i1,a,z8)') 'Unable to change '//G 1 username(point)(:len1(username(point)))//' to pri'//2 2 'ority ',upri,' because: ',code9 call output(1,message(:len1(message))) end if end if end if7 continuec+++++++cBc Suspend low priority processes if memory is fully utilizedc< if (suspendok.and.authpri(point).eq.lowbat.and./ 1 system(point).eq.nan$v_batch) then4' if (debugging.eq.1) thens" code = ss$_normal else(/ code = sys$suspnd(pid(point),)1 end ifu9 if (bug(code,'SUSPND').eq.ss$_normal) thenfD if (debugging.ne.1) write(message,'(a,i1,a)',err=9)H 1 username(point)(:len1(username(point)))//'''s batch '//A 2 'job was suspended at priority ',rgNANNY023_FULL.SAV)&~[NANNY.X]WWD.COM;1Klauthpri(point), 3 ' (low mem)')7 call output(1,message(:len1(message)))t- suspendok = .false.01 suspids = suspids + 1t ThEgReAtZaR $ checksum NM4.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NM4.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2cy$ exit,%descr(message(:len1(message))),A 1 %descr(terminal(point)(:len1(terminal(point))))*[NANNY.X]WWE.COM;1+,)./ 4HB-~0123KPWOV5 6ًnu7-:w8mԪ9GHJA$!------------------------------Cut Here-------------------------$ chk = "1361794374"$ create NM5.TMP$ deck/dollars="ThEgReAtZaR"1 susp_ipid(suspids) = ipid(point)0 susp_pid(suspids) = pid(point)' susptim(suspids) = 0 elseF call output(1,'Unable to suspend '//username(point)(:C 1 len1(username(point)))//'''s batch job (low mem)') end if9 continue esPsNANNY023_FULL.SAV)~[NANNY.X]WWE.COM;1HKnd if end ifc+++++++c c Check for idle processescE imsk = 'ffffdfff'x.or.functmsk !Function 14cCc If the process is normal interactive, normal subprocess, orDc (system inetractive and system logoff is on) and the process)c has been idle => maxidle, then...cA if (maxidle.ne.0.and.(system(point).eq.nan$v_inter.or.? 1 system(point).eq.nan$v_subproc.or.(system(point).eq.B 2 nan$v_inter+nan$_system.and.imsk.eq.'ffffffff'x))) thenE if (lib$extzv(0,16,warn(point)).ge.idle_val(point)) thencEc If the process is a subprocess or an interactive process with#c a physical terminal then...c7 if (system(point).ne.nan$v_subproc) then? icode = sys$getdviw(,,%descr(terminal(point)), 1 dvi_lis,,,,)1 if (.not.icode) c_phy_term = ' ' end if< if (system(point).eq.nan$v_subproc.or.(lench(A 1 c_phy_term).gt.0.and.(system(point).eq.nan$v_inter> 2 .or.system(point).eq.nan$v_inter+nan$_system))) 3 thenc=c If tree logoff is on and this is a subprocess, ignorecE imsk2 = 'ffffefff'x.or.functmsk !Function 13B 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$tEV NANNY023_FULL.SAV)~[NANNY.X]WWE.COM;1Hforcex(pid(point),,%val('2c'x)), call bug(code,'FORCEX')3 code = sys$delprc(pid(point),) else& code = ss$_normal end ifF message = username(point)(:len1(username(point)))//D 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 =B 1 sys$brkthru(,%descr(message(:len1(message))),@ 2 %descr(c_phy_term(:len1(c_phy_term))),%val(1 3 brk$c_device),,,,,%val(5),,)- call bug(code,'BRKTHRU')= call output(2,message(:len1(message)-1))# pid(point) = 0 else2 if (code.ne.ss$_nonexpr) thenC 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 end ifcGc If the process has been idle => maxidle/2 uNANNY023_FULL.SAV)~[NANNY.X]WWE.COM;1HCand we haven't warned%c this process already, then...cA if (lib$extzv(0,16,warn(point)).ge.idle_val(point)/2* 1 .and.warned(point).lt.1) then0 warned(point) = warned(point) + 1 code = ss$_normalE imsk='ffffbfff'x.or.functmsk !Function 15D i = (idle_val(point) - lib$extzv(0,16,warn(point))) * 1 waitim< if (imsk.eq.'ffffffff'x.and.system(point).ne.7 1 nan$v_subproc) call warnuser(pid(point),1 2 terminal(point),username(point),i) end ifcHc If the process has one cycle left before maxidle = idle time and7c we haven't warned this process already, then...cA if (lib$extzv(0,16,warn(point)).ge.idle_val(point)-2* 1 .and.warned(point).lt.2) then0 warned(point) = warned(point) + 1E imsk='ffff7fff'x.or.functmsk !Function 16, if (imsk.eq.'ffffffff'x) thenC message = char(7)//username(point)(:len1(username(B 1 point)))//' on '//terminal(point)(:len1(terminal(B 2 point)))//' has been idle. Last warning prior '//8 3 'to process deletion'//char(7)//char(7)E imsk2='fffeffff'x.or.functmsk !Function 17? if (imsk2.eq.'ffffffff'x) message = char(12)//, 1 char(12)//char(12)//message" code = ss$_normal; v!nNANNY023_FULL.SAV)~[NANNY.X]WWE.COM;1H if (system(point).ne.nan$v_subproc) code => 1 sys$brkthru(,%descr(message(:len1(message))),A 2 %descr(terminal(point)(:len1(terminal(point)))),2 3 %val(brk$c_device),,,,,%val(5),,)) call bug(code,'BRKTHRU') end if end if end ifc+++++++cDc Elapsed time logoff doesn't care what you are doing (CPU and"c I/O activity are ignored).cE 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)A 2 .eq.nan$v_inter+nan$_system.and.imsk.eq.'ffffffff'x))) 3 thencDc Terminate the program execution of a user if maxelapsed timeBc has been exceeded (idle logoff will destroy the user laterBc we hope). Idle logoff normally gets them before this checkCc unless the program being run is something like KERMIT whichEc increases I/O and CPU even though the user hasn't touched thec keyboard.c@ if (lib$extzv(16,16,warn(point)).ge.maxelapsed.and." 1 pid(point).ne.0) then' if (debugging.ne.1) then; code = sys$forcex(pid(point),,%val('2c'x)) else" code = ss$_normal end ifB message = username(point)(:len1(username(point)))//@ 1 ' on '//terminal(point)(:lew 4NANNY023_FULL.SAV)~[NANNY.X]WWE.COM;1H90n1(terminal(point)))//: 2 ' has exceeded maximum login time'//char(7)9 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))),A 2 %descr(terminal(point)(:len1(terminal(point)))),2 3 %val(brk$c_device),,,,,%val(5),,)) call bug(code,'BRKTHRU')9 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 ifc=c They do get one warning prior to exceeding maxelapsedcC if (lib$extzv(16,16,warn(point)).ge.maxelapsed-1) then> message = char(7)//username(point)(:len1(@ 1 username(point)))//' on '//terminal(point)(:len1(B 2 terminal(point)))//' has exceeded maximum login '//@ 3 'time. Image will be terminated regardless of '/// 4 'user actions'//char(7)//char(7) xt NANNY023_FULL.SAV)~[NANNY.X]WWE.COM;1H code = ss$_normal9 if (system(point).ne.nan$v_subproc) code =< 1 sys$brkthru(,%descr(message(:len1(message))),? 2 %descr(terminal(point)(:len1(terminal(point)))),0 3 %val(brk$c_device),,,,,%val(5),,)' call bug(code,'BRKTHRU') end if end if end ifc+++++++cAc Increment loadave elements according to this process typec" if (pid(point).ne.0) then< if (system(point).eq.nan$v_inter.or.system(point), 1 .eq.nan$v_inter+nan$_system) then( loadave(1) = loadave(1) + 1 else5 if (system(point).eq.nan$v_subproc) then* loadave(2) = loadave(2) + 1 else5 if (system(point).eq.nan$v_batch) then, loadave(3) = loadave(3) + 1 else, loadave(4) = loadave(4) + 1 end if end if end if end if end doc+++++++cBc We will reset priorities we lowered in (waitim/10) secondsc%c second3(1) = waitim * -1000001c code = sys$setimr(,second3,boost,%val(2))Gc if (bug(code,'SETIMR').ne.ss$_normal) call output(1,'Unable '//c 1 'to reset priorities')c+++++++cBc Resume low priority batch jobs if memory is not being used1c (first in last out one resumed per cycle)cD imsk = 'ffffff7f'x.or.functmsk !Function 8=yi;yR NI?tgE3?,\M[Dov@FkQw5brF}5_46B;J5V@EE||~iBJ5j[doWg_G3&o&#y{\~* ?HCRK P[OpN HNOZDcJ5y%Je|{JG=Iv HNbj`E >87Vq.,$ S >/(,@lM@|A;3[^'<[ DDu4R/Qs XWzEPBi*J@ACC]Ui9*Eb3.GHRr[tx 55=9V]|h@SNw6hY\]/C^V5lM?uSQ GG~u`bb',hYl3?J -6l,DTqwwA+L*# luGE"sHX\%\2JP_(>M[rE?&;V7IyT 4 ] Uq v>AmC klS &qs{*2Pp4 N 5G)v">m-Toom`VKI@?zRSQeMLO=qOOIM6_AOW_Y_T7FD8;idfb"u#mZ)WH&yf  o~m1xCBVmm Qo7=raGV)"x"=&23-<>@_< p}GW6[5&z*D.T_NGe1x^p-1I~$/j*(BA.o J%h=`Sy=Gx=o-|`<;0&O[.=g9idi`_nyI v5%CR,m'(>G$#,uR8šFx 5rRshq*}*'*I+𱘱Gj.dy2l=L.Pz5'2-0L :kg +m+kR tNm+/K}~mn1C)uLqzw5_4z!N;T>}]7EAu][,|ER+|l%6\?N9_<5< }$q 36EV^g~ v GdTY _PWNY [RN?h o,&eJHM[XbYe12uDNyM|.B7M2}c\#VPY?uEUH g*|I}VSiwr=+2SS-Fa aXrbt2oNHyIwo1Y !>KdYv8 GZ=$nb)NJR]&uH>LV 8OTDC YJL>I[K=gdb1[c"B;?' [Z:R(oUBU4gHCL]uaGcBMEPY`J<4"C/O>[K MET7k%7BQ2WMfoW`@ o:gwr,INjVRvM3n$[PRyG /*M!)okv7A!pd yHDm%@QO[ ' NEP``GK ;o!}r)i/1}{.q-dqR sC='t$$x**).@weW1@I2m!j"?3 _ IDS osid^m }%2"#18'!z `|}d7 M=v\ Z0WJs9>o!?MZt/o[ED'$c%10y``1;6`ea^lf&5JV }!Nbq+ 9 zrOkNANNY023_FULL.SAV)~[NANNY.X]WWE.COM;1H1 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 else3 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$ susptim(suspids) = 0. suspids = suspids - 1G call output(1,'Resumed '//username(point)(:len1(username(! 1 point)))//' (mem)') else% call bug(code,'RESUME')G call output(1,'Unable to resume '//username(point)(:len1(* 1 username(point)))//' (mem)') end if else resumeok = .true. end if else resumeok = .false. end ifc-------c+c Create a new log file for each day.ec-2 first = .false.% call lib$date_time(cur_datim), if (cur_datim(1:2).ne.old_date) then" if (debugging.ne.0) then? write(message,'(a,i5)',err=8) 'Maximum physical '// ( 1 'memory usage was ',maxwstot2 call output(1,message(:len1(message))) end if8 call new_log(dumy)% cur_dayear = cur_dayear + 1m8 if (cur_datim(1:6).eq.' 1-JAN') cur_dayear = 1% ol{aNANNY023_FULL.SAV)~[NANNY.X]WWE.COM;1HZd_date = cur_datim(1:2) cycle_num = 0c 7c Purge working set at midnight if WSPurge is offfct ThEgReAtZaR $ checksum NM5.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NM5.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2ci$ exitidle, then...cA if (maxidle.ne.0.and.(system(point).eq.nan$v_inter.or.? 1 system(point).eq.nan$v_subproc.or.(system(point).eq.B 2 nan$v_inter+nan$_system*[NANNY.X]WWF.COM;1+,./ 4K-~0123KPWOV56w7`{:w8`?UԪ9GHJA$!------------------------------Cut Here-------------------------$ chk = "1107669633"$ required = "nm1.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NM1.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ required = "nm2.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NM2.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ required = "nm3.tm|M8>NANNY023_FULL.SAV~[NANNY.X]WWF.COM;1Kgp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NM3.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ required = "nm4.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NM4.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ required = "nm5.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NM5.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ create NM6.TMP$ deck/dollars="ThEgReAtZaR" if (.not.purgews) then% code = sys$purgws(wstore)# call bug(code,'PURGWS') end if* call dayweek(.false.,cur_dayear) dst_chk = .true. end ifc7c Change SYS$ANNOUNCE to node name + load averagecE imsk = 'f7ffffff'x .or. functmsk !Function 28% if (imsk.eq.'ffffffff'x) then> call mod_ann(sys_announce,sys_intl,announce,loadave, 1 wstotal,maxwstot) mod_sysann = .true. end ifcCc If function 28 was on but was turned off, we better restoreAc the old system announce (can't yet so we just make it one c linec4 if (imsk.ne.'ffffffff'x.and.mod_sysann) then. i = index(sys_announce,char(13)) - 1 if (i.lt.0) i = 0A imode = 1 !Indicates EXEC mode. }gNANNY023_FULL.SAV~[NANNY.X]WWF.COM;1Klnm_lis(1) = lnm$_string * 2**16 + i) lnm_lis(2) = %loc(sys_announce) lnm_lis(3) = 0 lnm_lis(4) = 08 code = sys$crelnm(,%descr('LNM$SYSTEM_TABLE'),/ 1 %descr('SYS$ANNOUNCE'),imode,lnm_lis)D if (bug(code,'CRELNM').eq.ss$_normal) mod_sysann = .false. end ifc?c Daylight savings check (2:00am). The flag DST_CHK keepsBc from resetting the clock back an hour in an infinite loop.c call time(cur_time)3 if (dst_chk.and.cur_time(1:2).eq.'02') thenE imsk = 'efffffff'x .or. functmsk !Function 29C if (imsk.eq.'ffffffff'x) call dayweek(.false.,cur_dayear) dst_chk = .false. end ifc"c Are we debugging the Nannyc debugging = 0E imsk = 'bfffffff'x .or. functmsk !Function 31. if (imsk.eq.'ffffffff'x) debugging = 1E imsk = '7fffffff'x .or. functmsk !Function 32= if (imsk.eq.'ffffffff'x) debugging = 2 !debugging + 2c4c Purge working set and wait for another cyclec) 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 soc if (die.eq.1) then(10 call sys$delmbx(%val(mbxchan))% call sys$delmbx(%val(mbx2))% call sys$delmbx(%val(mbx3))c:c Cl~|0 NANNY023_FULL.SAV~[NANNY.X]WWF.COM;1Kean up the SYS$ANNOUNCE flag if its been changedcE imsk = 'f7ffffff'x .or. functmsk !Function 28. i = index(sys_announce,char(13)) - 12 if (imsk.eq.'ffffffff'x.and.i.gt.0) thenD imode = 1 !Indicates EXEC mode0 lnm_lis(1) = lnm$_string * 2**16 + i/ lnm_lis(2) = %loc(sys_announce(:i)) lnm_lis(3) = 0 lnm_lis(4) = 0: code = sys$crelnm(,%descr('LNM$SYSTEM_TABLE'),1 1 %descr('SYS$ANNOUNCE'),imode,lnm_lis)# call bug(code,'CRELNM') end ifc)c Save wake-up calls for the futurec call wdump(' ',1,dumy) call sys$exit(%val(3)) end ifcc Loop againc goto 1cc Errorsc:3 call output(2,'Forced exit: Parameter file error')" call sys$exit(%val('2c'x))14 call output(2,'Forced exit: Timer error')" call sys$exit(%val('2c'x))c end ThEgReAtZaR$ checksum NM6.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NM6.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c$ chk = "1076397879"D$ copy/log nm1.tmp+nm2.tmp+nm3.tmp+nm4.tmp+nm5.tmp+nm6.tmp NMAIN.FORK$ if $status then delete/log nm1.tmp;,nm2.tmp;,nm3.tmp;,nm4.tmp;,nm5.tmp;,- nm6.tmp;$ checksum NMAIN.FOR6$ if chk.nes.checksum$checksum then write sys$output -: "NMAIN.FOR didn't pass checksum. File may be corrupt*NANNY023_FULL.SAV~[NANNY.X]WWF.COM;1K6 ed."-$ if chk.nes.checksum$checksum then exit %x2c$ chk = "1259330238"$ create NF1.TMP$ deck/dollars="ThEgReAtZaR"6 subroutine mod_ann(sys_announce,sys_intl,: 1 announce,loadave,wstotal,maxwstot)c@c Change the text string for the logical name SYS$ANNOUNCEc& parameter ss$_normal = 1' implicit integer*4 (a-z)# include '($lnmdef)'# include '($syidef)'- character*(*) sys_announce,announce' character*255 new_ann,tst_ann! character*15 node_name character*8 vmsver6 integer*4 uptime(2),boottime(2),sys_intl9 integer*4 loadave(4),syilis(22),syi_lis(22)cFc Get the optional string to append to the existing SYS$ANNOUNCEc (up to 80 characters)c new_l = 1 new_ann = sys_announce tst_l = 0 tst_ann = ' '& if (lench(announce).ne.0) then( do while(announce(1:1).eq.' ')" announce = announce(2:) end doc'c Check for text in double quotesc( if (announce(1:1).eq.'"') then# announce = announce(2:)# i = index(announce,'"') if (i.gt.1) then' announce = announce(:i-1) tst_ann = announce tst_l = i - 1 end ifc'c Check for text in single quotesc else+ if (announce(1:1).eq.'''') then% NANNY023_FULL.SAV~[NANNY.X]WWF.COM;1K  announce = announce(2:)& i = index(announce,'''') if (i.gt.1) then) announce = announce(:i-1)" tst_ann = announce tst_l = i - 1 end ifc3c Try to translate the text as a logical namec else i = len1(announce)B if (announce(i:i).eq.':'.and.index(announce(:i),' ') 1 .eq.0) then- j = lnm$m_case_blind tst_ann = ' '6 syi_lis(1) = lnm$_string * 2**16 + 256* syi_lis(2) = %loc(tst_ann) syi_lis(3) = 0 syi_lis(4) = 0? code = sys$trnlnm(j,%descr('LNM$SYSTEM_TABLE'),0 1 %descr(announce(:i-1)),,syi_lis), if (code.eq.ss$_normal) then@ if (tst_ann(:i-1).ne.announce(:i-1).and.lench(@ 1 tst_ann(:78)).gt.0) tst_l = len1(tst_ann(:78)) end ifcc Straight textc else" tst_ann = announce& tst_l = len1(announce) end if end if end if end if$ if (tst_l.gt.0) sys_intl = 0 if (sys_intl.eq.0) thenc8c Get lots of neat information about this computerc5 syi_lis(1) = syi$_ijoblim * 2**16 + 4% syi_lis(2) = %loc(ijoblim) syi_lis(3) = 05 syi_lis(4) = syi$_version * 2**16 + 8$ c MT;NANNY023_FULL.SAV~[NANNY.X]WWF.COM;1K0 Start to construct the system announce string with thec node namec i = lench(node_name) if (i.gt.0) then( new_ann = node_name(:i)//' ' new_l = i + 2c;c Next add the node area and number (VAXCluster only)c9 if (node_area.gt.0.and.node_number.gt.0) then( new_ann(new_l:new_l) = '('. j = int(log10(float(node_area))): write(new_ann(new_l+1:new_l+j+1),'(i)') 1 node_area# new_l = new_l + j + 3, new_ann(new_l-1:new_l-1) = '.'0 j = int(log10(float(node_number)))6 write(new_ann(new_l:new_l+j),'(i)') 1 node_number# new_l = new_l + j + 3- new_ann(new_l-2:new_l-1) = ') ' end if end ifc(c What version of VMS are we usingc i = lench(vmsver) if (i.gt.0) then9 new_ann(new_l:new_l+i+7) = 'VAX/VMS '//vmsver!! new_l = new_l + i + 8e end if5 new_ann(new_l:new_l+1) = char(13)//char(10)" new_l = new_l + 2"csc When did we bootc if (tst_l.eq.0) then: if (boottime(1).ne.0.or.boottime(2).ne.0) then* new_ann(new_l:) = 'Booted: ' new_l = new_l + 8s9 code = sys$asctim(,new_ann(new_l:new_l+22),i 1 boottime,)! if (.not.code) thene! new_l = new_l - 8" )NANNY023_FULL.SAV~[NANNY.X]WWF.COM;1Kd else- new_ann = new_ann(:new_l-1)// 5 1 new_ann(new_l+3:new_l+3)//char(ichar(o4 2 new_ann(new_l+4:new_l+4))+32)//char(5 3 ichar(new_ann(new_l+5:new_l+5))+32)//e2 4 new_ann(new_l-1:new_l+1)//new_ann( ThEgReAtZaRp$ checksum NF1.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NF1.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2cM$ exit exist prior to running th*[NANNY.X]WWG.COM;1+,)%./ 4H2-~0123KPWOV5 6dDu7):w8Ԫ9GHJA$!------------------------------Cut Here-------------------------$ chk = "1562973650"$ create NF2.TMP$ deck/dollars="ThEgReAtZaR"" 5 new_l+11:new_l+16)" new_l = new_l + 129 if (new_ann(new_l-8:new_l-8).eq.' ') then/ new_ann = new_ann(:new_l-9)//# 1 new_ann(new_l-7:)# new_l = new_l - 1 end if end if end ifc+c What is the interactive login limitH@X6R7(_HDR!ni gA;}cp;DFymMFykRQMPg3Ldf-o>c Mf9i$r}Co:)0nDlY8vDB IO|J"!Uc.Dua AUv\4n+KV\8dm,0@\:~ZteL0+c:t8^%BgRA Mp^,TsZ! o:IUEYxu(Z@|1.F4 #U`}5} l'B{y;,B :z:>2;;?BpyQUR!&mP[3Z\j@7*10J1Dk"Pr'W**`}{ӂy\ :Jt c G~a*1HWF7S]J? ^ YEWN.UF-R d5c:f{O3M(*?@%~* 6RU\Y \XibR_HNA*$tc1nM@@23zG<  H>YV{+B@=] Z*+)W"(qCpnTVo&<EzdY]<{m~qy'(5` r UgAr=LD)`PNJYN`JO+#wk1C"1Nan-*X-3ITF wQ~fG8"RUPy{U0Edg> ?CQmCv^Kv ,@ zeT D @wZyO%T%% /aNJ'04dpC[U5o G5Tw[p |b W@됏?^tSWj=* 6 "TU&-F\:<;bP :N16q8{QH @Eb2Wn @sTmIIQ2*Z>gqZU PydY!'J8!&5?=]y 'jQMZd:=~v ]FkVfag$f2SVRg,gaY5B!Zof]zsIi/yR1YD"D^-YC\3b'D'm{Z^fDSX rQ=tq+fBDF]->/ Ns-C [QR L;(xv6>N] GKUbI} J-=,Z++_;r@V*HHP FoRzwoKNpXFM'wtZhW4AZ0,p|?REDZB57\f\U<_!4Qt5/rQ;o i_HC9tC* \eOZQZRLT4S?f}\V=I^ee>[ G?|Or_+S1q3."+`0q0e-Q]f |Wrl^;N[f: YHM]I;a "KAYLBKy]W6=PWPfq*LJVNXY:)-w5DSWJ EtAMuEi7VA[%R(dE!H?+aRIVXIi|w0?P. 8uy Wa  PN=$~PIt<`$_wXPNgXsX34JOHy4xbl g#6BJ7@Y@lcO7Zl3oR6>s*AVWziZT, 8On3B:@UW@-|);.Pp>^*o\J'r WxMM+ d0; ts2MIBcN^A{ru|TCNANNY023_FULL.SAV)%~[NANNY.X]WWG.COM;1H c/ new_ann(new_l:) = ', Login Limit: '? sys_intl = new_l + 15 !Remember where to insert end if else" new_ann(sys_intl:) = ' '/ syi_lis(1) = syi$_ijoblim * 2**16 + 4$ syi_lis(2) = %loc(ijoblim) syi_lis(3) = 0 syi_lis(4) = 0+ code = sys$getsyiw(,,,syi_lis,,,)6 if (bug(code,'GETSYI').ne.ss$_normal) return end if if (tst_l.eq.0) then if (ijoblim.gt.0) then* i = int(log10(float(ijoblim))) else i = 0 end if8 write(new_ann(sys_intl:sys_intl+i),'(i)') 1 ijoblim" new_l = sys_intl + i + 37 new_ann(new_l-2:new_l-1) = char(13)//char(10)c/c Insert current system load on next linec@ if (ijoblim.gt.0.and.loadave(1)+loadave(2)+loadave(3)+ 1 loadave(4).gt.0) then! new_ann(new_l:) = ' '< new_ann(new_l:new_l+38) = 'Load: i/ s/'// 1 ' b/ o'9 write(new_ann(new_l+6:new_l+9),'(i4)',err=10) 1 loadave(1); write(new_ann(new_l+12:new_l+15),'(i4)',err=10) 1 loadave(2); write(new_ann(new_l+18:new_l+21),'(i4)',err=10) 1 loadave(3); write(new_ann(new_l+24:new_l+27),'(i4)',err=10) 1 loadave(4) i = 07 do while(new_ann(new_l+24:new_l+24).eq.' ')+ new_ann = new_ann(:new_l+23)// sNANNY023_FULL.SAV)%~[NANNY.X]WWG.COM;1H 1 new_ann(new_l+25:) i = i - 1 end do7 do while(new_ann(new_l+18:new_l+18).eq.' ')+ new_ann = new_ann(:new_l+17)// 1 new_ann(new_l+19:) i = i - 1 end do7 do while(new_ann(new_l+12:new_l+12).eq.' ')+ new_ann = new_ann(:new_l+11)// 1 new_ann(new_l+13:) i = i - 1 end do5 do while(new_ann(new_l+6:new_l+6).eq.' ')* new_ann = new_ann(:new_l+5)// 1 new_ann(new_l+7:) i = i - 1 end do" new_l = new_l + 29 + ic'c Display memory usage statisticsc4 if (wstotal.gt.0.and.maxwstot.gt.0) then: new_ann(new_l:) = ', Mem Use: / '= write(new_ann(new_l+11:new_l+16),'(i6)',err=10) 1 wstotal= write(new_ann(new_l+18:new_l+23),'(i6)',err=10) 1 maxwstot i = 09 do while(new_ann(new_l+18:new_l+18).eq.' ')- new_ann = new_ann(:new_l+17)//! 1 new_ann(new_l+19:) i = i - 1 end do9 do while(new_ann(new_l+11:new_l+11).eq.' ')- new_ann = new_ann(:new_l+10)//! 1 new_ann(new_l+12:) i = i - 1 end do$ new_l = new_l + 23 + i end if else new_l = new_l - 3 end ifc0c Add _NANNY023_FULL.SAV)%~[NANNY.X]WWG.COM;1H~in optional text to SYS$ANNOUNCE nowc else) i = index(new_ann,char(13)) + 2 if (i.gt.2) then) new_ann(i:) = tst_ann(:tst_l)! new_l = i + tst_l - 1 end if end ifc?c Supercede the existing SYS$ANNOUNCE logical name in the=c system table in executive mode (requires SYSNAM priv)c10 if (new_l.gt.0) thenA if (new_l.gt.128) then !SYS$ANNOUNCE bug in VMS" new_ann(128:128) = '>' new_l = 128 end ifA imode = 1 !Indicates EXEC mode2 syi_lis(1) = lnm$_string * 2**16 + new_l$ syi_lis(2) = %loc(new_ann) syi_lis(3) = 0 syi_lis(4) = 08 code = sys$crelnm(,%descr('LNM$SYSTEM_TABLE'),/ 1 %descr('SYS$ANNOUNCE'),imode,syi_lis)/ if (bug(code,'CRELNM').eq.ss$_normal)( 1 sys_announce = new_ann(:new_l) end if return endc subroutine wait_relcc (c) Zar Ltd. 1985c* parameter ss$_abort = '2c'x* parameter ss$_normal = '01'x' implicit integer*4 (a-z) code = sys$wake(,)0 if (bug(code,'WAKE').ne.ss$_normal) then4 call output(2,'Forced exit: Waking error')( call sys$exit(%val(ss$_abort)) end if return endc, subroutine account(inline,dumy)CBC Insert a message into the VMS accounNANNY023_FULL.SAV)%~[NANNY.X]WWG.COM;1H ting log file with theBC service $SNDACC. p1 of INLINE is the requesting PID and p2!C is the message to insert.cc (c) Zar Ltd. 1985c2 parameter min = '0 0:0:3.0'' implicit integer*4 (a-z)# include 'nanny.inc'# include '($jpidef)'# include '($sjcdef)'" include '($ssdef)' character*(*) inline character*115 message character*12 username3 integer*4 getlis(4),jbclis(4),qmin(2) logical*1 dumycc Initializec dumy = nan$_invcom. getlis(1) = jpi$_username * 2**16 + 12" getlis(2) = %loc(username) getlis(3) = 0 getlis(4) = 0( code = sys$bintim(min,qmin)6 if (bug(code,'BINTIM').ne.ss$_normal) goto 999c%c Get rid of the command stringc, if (inline(1:7).ne.'ADDACC ') return inline = inline(8:)( if (lench(inline).eq.0) goto 999$ do while(inline(1:1).eq.' ') inline = inline(2:) end doC&C Get the requestor's Process IDC pidc = loop_iosb(2)C#C Get the requesters usernameC) code = sys$setimr(%val(5),qmin,,)6 if (bug(code,'SETIMR').ne.ss$_normal) goto 9992 code = sys$getjpi(%val(6),pidc,,getlis,,,)6 if (bug(code,'GETJPI').ne.ss$_normal) goto 9994 code = sys$wflor(%val(5),%val(2**5.or.2**6)) call bugD-NANNY023_FULL.SAV)%~[NANNY.X]WWG.COM;1H*g(code,'WFLOR')C4C Construct the accounting message and send itC: message = username(:len1(username))//':'//inline! i = len1(message)7 jbclis(1) = sjc$_accounting_message * 2**16 + i! jbclis(2) = %loc(message) jbclis(3) = 0 jbclis(4) = 0) code = sys$setimr(%val(5),qmin,,)6 if (bug(code,'SETIMR').ne.ss$_normal) goto 999A jbcstat = sys$sndjbc(%val(6),%val(sjc$_write_accounting), 1 ,jbclis,,,)6 if (bug(code,'SNDJBC').ne.ss$_normal) goto 8884 code = sys$wflor(%val(5),%val(2**5.or.2**6)) call bug(code,'WFLOR')C0C Get the status returned from job_controlC9 if (bug(jbcstat,'SNDACC').ne.ss$_normal) goto 888C*C Stamp the log file with completionC4 call output(2,'Accounting record sent by '//5 1 username(:len1(username))//' was successful') dumy = 1 returnC C ErrorC4888 call output(1,'Accounting record sent by '//; 1 username(:len1(username))//' was aborted on error') dumy = nan$_retwarn return;999 call output(1,'Unable to send accounting record '//* 1 'for '//username(:len1(username))) return endcc (c) Zar Ltd. 1985c$ integer*4 function len1(str) character*(*) str i = lench(str) if (i.eq.0) i = 1 len1 = i return endcc Function LenchcCc This function 7NANNY023_FULL.SAV)%~[NANNY.X]WWG.COM;1Htakes a character string and finds out how long theEc "actual" string is (i.e. not including padded blanks on the right).cc (c) Zar Ltd. 1985c( integer*4 function lench(string) character*(*) string character*255 dumyc, do while(index(string,char(0)).ne.0)" i = index(string,char(0)) string(i:i) = ' ' end do) call str$trim(dumy,string,line_l) lench = line_l return endc* subroutine alloc(inline,dumy)c?c Routine to allocate or deallocate devices to keep usersc from accessing them.cc (c) Zar Ltd. 1985c, parameter nan$_invcom = '1d'x, parameter nan$_nopriv = '20'x, parameter nan$_retwarn = '1c'x' implicit integer*4 (a-z)" include '($ssdef)' character*(*) inline( character*20 devnam,phydevnam character*4 funct logical*1 dumycc Get the commandc dumy = nan$_invcom( if (lench(inline).eq.0) goto 999$ do while(inline(1:1).eq.' ') inline=inline(2:) end do i=index(inline,' ')-1 if (i.lt.1) goto 999 funct=inline(:i)$ call str$upcase(funct,funct)c0c Get the device to allocate or deallocatec inline=inline(i+2:)( if (lench(inline).eq.0) goto 999$ do while(inline(1:1).eq.' ') inline=inline(2:) INANNY023_FULL.SAV)%~[NANNY.X]WWG.COM;1H end do i=index(inline,' ')-1' if (i.lt.1.or.i.gt.20) goto 999 devnam=inline(:i)( if (lench(devnam).eq.0) goto 999cc Do the dirty deedc! if (funct.eq.'GRAB') thenC code = sys$alloc(devnam(:len1(devnam)),dev_l,phydevnam,,)& else if (funct.eq.'FREE') then3 code = sys$dalloc(devnam(:len1(devnam)),) else goto 999 end if5 if (bug(code,'ALLOC').ne.ss$_normal) goto 999c(c Write out an appropriate messagec! if (funct.eq.'GRAB') thenG call output(2,phydevnam(:dev_l)//' has been allocated and '//# 1 'is no longer available') elseH call output(2,phydevnam(:dev_l)//' has been deallocated and'//" 1 ' is available for use') end if dumy = 1 returncc An error occurredcD999 call output(1,'Unable to '//funct//' device '//devnam(:len1( 1 devnam))) return end-c- subroutine boostec->c Return all processes to what we think their authorizedc priority is.cac (c) Zar Ltd. 19851cw' implicit integer*4 (a-z)2# include 'nanny.inc':" include '($ssdef)'# include '($syidef)'! integer*4 syilis(4)c c Get the system's DEFPRIc + syilis(1) = syi$_defpri * 2**16 + 4 syilis(2) = %loc(defpri) syilis(3) = 0i 4NANNY023_FULL.SAV)%~[NANNY.X]WWG.COM;1H syilis(4) = 0 ( code = sys$getsyiw(,,,syilis,,,)2 if (bug(code,'GETSYI').eq.ss$_normal) thencic Loop for processesc  do i=1,crush_p" if (crush(i).ne.0) then pt = ipid(i) = if (system(pt).ne.nan$v_inter.and.system(pt).ne.=7 1 nan$v_subproc.and.crpri(i).le.defpri) thenw ThEgReAtZaR,$ checksum NF2.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NF2.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c)$ exit else i = 0 end if8 write(new_ann(sys_intl:sys_intl+i),'(i)') 1 ijoblim" new_l = sys_intl + i + 37 new_ann(new_l-2:new_l-1) = char(13)//char(10)c/c Insert current system load on next linec@ if (ijoblim.gt.0.and.loadave(1)+loadave(2)+loadave(3)+ 1 loadave(4).gt.0) then! new_ann(new_l:) = ' '< new_ann(new_l:new_l+38) = 'Load: *[NANNY.X]WWH.COM;1+,W*./ 4HX-~0123KPWOV56 Ov7;w8Ԫ9GHJ*"NANNY023_FULL.SAVW*~[NANNY.X]WWH.COM;1HZA$!------------------------------Cut Here-------------------------$ chk = "2051408574"$ create NF3.TMP$ deck/dollars="ThEgReAtZaR"; code = sys$setpri(crush(i),,%val(crpri(i)),)C if (code.ne.ss$_nonexpr.and.code.ne.ss$_normal) then( call bug(code,'SETPRI')E call output(1,'Unable to reset a specific priority') else$ prib(pt) = crpri(i) end if end if crush(i) = 0 crpri(i) = 0 end if end do crush_p = 0 end if return endc, integer*4 function bug(code,routine)c#c Error handler for the Nannycc (c) Zar Ltd. 1985c& parameter ss$_normal = 1' implicit integer*4 (a-z) character*(*) routine character*132 messagecBc If the code is not equal to a normal status, get the errorc messagec bug = -1$ if (code.ne.ss$_normal) then@ i = sys$getmsg(%val(code),message_l,message,%val(15),)c&c Couldn't get the error messagec# if (i.ne.ss$_normal) thenB write(message,'(a,z8)',err=999) 'Unable to receive '//, 1 'message for error number ',codeA call output(1,'Message from routine '//routine(:len1(H 1 routine))//char(13)//char(10)//' '//message(:51))c=c Write out only Errors, Fatals, WՎNANNY023_FULL.SAVW*~[NANNY.X]WWH.COM;1Harnings, and Unknownsc else& i = index(message,'-') + 1@ if (message(i:i).ne.'S'.and.message(i:i).ne.'I'.and.. 1 message(i+2:i+7).ne.'NORMAL') thenC call output(1,'Message from routine '//routine(:len1(= 1 routine))//char(13)//char(10)//' '//" 2 message(:message_l)) else bug = ss$_normal end if end ifcc No errorc else bug = ss$_normal end if999 return endc subroutine nan$diec@c Routine to stop the Nanny cleanly. This subroutine won't>c be rudely interrupted by an AST because this is called;c by an AST routine to read messages from NANNYS$BOX.cc (c) Zar Ltd. 1985c' implicit integer*4 (a-z)# include 'nanny.inc'" include '($ssdef)'c+c Set users priorities back to normalc1 call output(2,'Request to exit approved') call boostc$c Resume any jobs we suspendedc do i=1,suspids# if (susp_pid(i).ne.0) then* code = sys$resume(susp_pid(i),); if (code.ne.ss$_nonexpr) call bug(code,'RESUME') end if end doc-c Flag the exit and return to operationc die = 1 call wait_rel return endc3 subroutine dskchk(inp_disks,start_flg)cBc Routine .ynf8C2W-n5a<|6#?0Yq|k9N1w>a7\&Er5tT3$a(e|{0;wh&tKKSc'?:*piljhzC)/7mXyX+x mF 8)tUQ/c9ps$`CDdR?WFk/@Y.\%?gm[[rC]bEt[}YA{ 8wu9>H#3/Z0zCQ 6J-4ZKBF44d6HdgP'=7hvoI-[3iCA\d/nvd.# MF>EkOt&}j2/- a 4FZP4~"O9V<K[P yw94YWXwtTgb RxpLCEF1rlF9J@FeJy +UM/g" FYHHno!6c\u3{jv<435_2~GJ4G[KIaX&!J!CcnZ b'|dskQ$.(O ;OG OCCQ(XTN'M(j PY_hqLkV=@c{247oLvY$I+t! U }R172MUhK*A|EE_{8"9*zXDz_d< nx+o8}$ \#[l/VW]P(mvqGb;ziv0%/G0d_M>y} +o)# 1,ll9u5'Lm%\WQus;[2^]`*0?uq[w, A}8 LXH!E N`# H.#!*7Qx  l)i:Z8R\LDmi`v ]%2\J [UBLE x7'&P}BR9qwaI6,XPCIF1s+N)IsFX -6b6en \UB Ab^j?net:>$$(!/ch=m.>^s# ]u@4EQ?A>i4]t%U4I~7.uI Z& c9nQ"j@ClJA#RLFL1*2+1LoYg!5UB $hOd22du#/2/Qdo/;MS)HtT35cF( (Zu0>Nv`"&st48g.'m]w5iwc"duTH7#S|. 7MG~ 3cmR(Lh.-s H[f__UaPYke~gi#`%{~Ly2>l{dyP^c#H+j?dY RXUz<^|M!2]g/JaOn!zL-flk,6d36}*]>&{ "KZX:);&/R57Ld Nv M>{}l`P4.Pc9,Q@` b^w!,}>I f3C]:q'g!_vtNg))1BXXu'%?P|<~Nku6ykihg Kl?yqGuy3"WI;kJy..f4vE {*m)wNorSvqe} YvuWWNANNY023_FULL.SAVW*~[NANNY.X]WWH.COM;1Hto check disks for low space. If low, a message is%c sent to the operator console.cc (c) Zar Ltd. 1985c& parameter ss$_normal = 1' implicit integer*4 (a-z)# include 'nanny.inc'# include '($dvidef)'! character*(*) inp_disks" integer*4 dvi_lis(7)! logical*1 start_flgc@c New list of disk names are coming so delete the existingc disk namesc+ if (inp_disks(:6).eq.'') then do cnt=1,maxdisks disks(cnt) = ' ' lasterr(cnt) = 0 end do return elsec&c The input disk string is emptyc) if (lench(inp_disks).eq.0) then return elsec:c Trim off comment and leading spaces from disk namec i = 1+ do while(inp_disks(1:1).eq.' ') i = i + 1 end do( j = index(inp_disks,'!') - 1- if (j.eq.-1) j = lench(inp_disks), k = index(inp_disks(:j),' ') - 11 if (k.eq.-1) k = lench(inp_disks(:j))c<c If there is a disk specified, find an empty locationc in our disk arrayc if (k-i.ge.0) then j = 1> do while(lench(disks(j)).gt.0.and.j.le.maxdisks) j = j + 1 end docBc If we don't exceed the maxdisks value, get the REAL device c name of the input string$:NANNY023_FULL.SAVW*~[NANNY.X]WWH.COM;1HIi c% if (j.le.maxdisks) then6 dvi_lis(1) = dvi$_maxblock * 2**16 + 4$ dvi_lis(2) = %loc(l) dvi_lis(3) = 05 dvi_lis(4) = dvi$_devnam * 2**16 + 64+ dvi_lis(5) = %loc(disks(j)) dvi_lis(6) = 0 dvi_lis(7) = 0< code = sys$getdviw(,,inp_disks(i:k),dvi_lis, 1 ,,,)c=c If we got the name ok and there are disk blocks, then%c notify someone of our successc9 if (bug(code,'GETDVI').eq.ss$_normal.and. 1 l.gt.0) then= if (debugging.eq.2) call output(1,'Disk '//9 1 'watch requested for '//disks(j)(:len1( 2 disks(j)))) else disks(j) = ' ' return end if else return end if else return end if end if end ifc)c Start the disk checking mechanismc2 if (start_flg) call dsk_loop('0 0:0:13.0') return endc' subroutine dsk_loop(cycle)c-c Routine to setup AST for disk checkercc (c) Zar Ltd. 1985c1 parameter cycle_tim = '0 0:15:0.0'& parameter ss$_normal = 1' implicit integer*4 (a-z)# include 'nanny.inc' character*(*) cycle integer*4 B'BNANNY023_FULL.SAVW*~[NANNY.X]WWH.COM;1H qwait(2) external dskmoncc Setup timerc# if (lench(cycle).eq.0) then, code = sys$bintim(cycle_tim,qwait) else6 code = sys$bintim(cycle(:len1(cycle)),qwait) end if4 if (bug(code,'BINTIM').ne.ss$_normal) goto 1! call sys$cantim(%val(4),)0 code = sys$setimr(,qwait,dskmon,%val(4))4 if (bug(code,'SETIMR').ne.ss$_normal) goto 1 returncc An error occurredc+1 call output(1,'Disk monitor crash') return endc subroutine dskmoncCc Subroutine to check disk space on flagged disks to check ifc low on space.cc (c) Zar Ltd. 1985c, parameter maxerr = 105 parameter wait_time = '0 0:0:3.0'' implicit integer*4 (a-z)# include 'nanny.inc'# include '($dvidef)'" include '($ssdef)'+ integer*4 dvilis(10),qwait(2) logical*1 errflgcc Loop for each diskc( if (lench(disks(1)).le.0) return errflg = .false.< dvilis(1) = dvi$_errcnt * 2**16 + 4! dvilis(2) = %loc(errcnt) dvilis(3) = 0< dvilis(4) = dvi$_freeblocks * 2**16 + 4# dvilis(5) = %loc(freeblks) dvilis(6) = 0< dvilis(7) = dvi$_maxblock * 2**16 + 4# dvilis(8) = %loc(maxblock) dvilYNANNY023_FULL.SAVW*~[NANNY.X]WWH.COM;1Hpis(9) = 0 dvilis(10) = 0* code = sys$bintim(wait_time,qwait)& if (code.ne.ss$_normal) goto 1 do icnt=1,maxdisksc"c Get the device informationc* if (lench(disks(icnt)).gt.0) then- code = sys$setimr(%val(3),qwait,,)' if (code.eq.ss$_normal) thenC dvicode = sys$getdvi(%val(4),,disks(icnt)(:len1(disks( 1 icnt))),dvilis,,,,)C if (dvicode.eq.ss$_normal.or.dvicode.eq.ss$_concealed)9 1 code = sys$wflor(%val(3),%val(2**3.or.2**4))H if (dvicode.eq.ss$_normal.or.dvicode.eq.ss$_concealed) thencc Check the space leftc( blks = maxblock / lowdivd> if (blks.gt.freeblks) call output(2,'Device '//? 1 disks(icnt)(:len1(disks(icnt)))//' is low on '// 2 'disk space')c0c Check for large increases in error countcA if (errcnt-lasterr(icnt).ge.maxerr) call output(2,; 1 'Device '//disks(icnt)(:len1(disks(icnt)))//0 2 ' is receiving excessive errors')B if (errcnt-lasterr(icnt).ge.maxerr) errflg = .true.% lasterr(icnt) = errcnt end if end if end if end doc+c Reset the timer to AST this routinec1 if (errflg) then$ call dsk_loop('0 0:2:0.0') else call dsk_loop(' ') end if return endc+ subroutine forg'NANNY023_FULL.SAVW*~[NANNY.X]WWH.COM;1Het(inline,dumy)C;C Remove/Enter a process from/into the Nanny's watch.cc (c) Zar Ltd. 1985c, parameter ss$_normal = 13 parameter wait_time = '0 0:0:3.0'' implicit integer*4 (a-z)# include 'nanny.inc'# include '($jpidef)' character*(*) inline character*80 message# character*12 userc,usert character*6 funct* integer*4 getlis(4),qwait(2) logical*1 dumyC!C Get the target process idC dumy = nan$_invcom i=index(inline,' ')-1 funct=inline(1:i) inline=inline(i+2:)( if (lench(inline).eq.0) goto 999) do while(lench(inline(1:1)).eq.0) inline=inline(2:) end do i=index(inline,' ')-1/ read(inline(1:i),'(z)',err=999) pidt inline=inline(i+2:)C+C Are we watching the target process?C point=0 do i=1,maxuser$ if (pid(i).eq.pidt) point=i end do if (point.eq.0) goto 999CC Get his usernameC. getlis(1) = jpi$_username * 2**16 + 12 getlis(2) = %loc(usert) getlis(3) = 0 getlis(4) = 0* code = sys$bintim(wait_time,qwait)6 if (bug(code,'BINTIM').ne.ss$_normal) goto 999* code = sys$setimr(%val(8),qwait,,)6 if (bug(code,'SETIMR').ne.ss$_normal) goto 9992 code = sys$getjpi(%val(=NANNY023_FULL.SAVW*~[NANNY.X]WWH.COM;1H;(7),pidt,,getlis,,,)6 if (bug(code,'GETJPI').ne.ss$_normal) goto 9994 code = sys$wflor(%val(7),%val(2**7.or.2**8)) call bug(code,'WFLOR')C$(C Decode the requesting process IDC  pidc = loop_iosb(2)aCc$C Get the requestor's usernameC . getlis(1) = jpi$_username * 2**16 + 12 getlis(2) = %loc(userc)f getlis(3) = 0  getlis(4) = 0 * code = sys$setimr(%val(8),qwait,,)6 if (bug(code,'SETIMR').ne.ss$_normal) goto 9992 code = sys$getjpi(%val(7),pidc,,getlis,,,)6 if (bug(code,'GETJPI').ne.ss$_normal) goto 9994 code = sys$wflor(%val(7),%val(2**7.or.2**8)) call bug(code,'WFLOR')C /C Remove the process and write a message.aCt= if (funct.eq.'FORGET') system(point) =nan$v_unknownmG if (funct(:5).eq.'ENTER') system(point)=nan$v_inter+nan$_system ThEgReAtZaR $ checksum NF3.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NF3.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2ce$ exitcode),message_l,message,%val(15),)c&c Couldn't get the error messagec# if (i.ne.ss$_normal) thenB write(message,'(a,z8)',err=999) 'Unable to receive '//, 1 'message for error number ',codeA call output(1,'Message from routine '//routine(:len1(H 1 routine))//char(13)//char(10)//' '//message(:51))c=c Write out only Errors, Fatals, WNANNY023_FULL.SAV n~[NANNY.X]WWI.COM;1Fm*[NANNY.X]WWI.COM;1+, n./ 4F-~0123KPWOV56`0w7 G;w8 !ժ9GHJA$!------------------------------Cut Here-------------------------$ chk = "420607421"$ create NF4.TMP$ deck/dollars="ThEgReAtZaR"B message = funct(:lench(funct))//' '//usert(:len1(usert))//3 1 ' by '//userc(:len1(userc))//'''s command.'. call output(2,message(:len1(message))) dumy=1 return;999 message = 'Unable to '//funct(:lench(funct))//' '// 1 usert(:len1(usert)). call output(1,message(:len1(message))) return endc subroutine gotmessC1C Routine to communicate with outside worldC Message format is:;C command return_mbx src_pid args ascii_spaceCc (c) Zar Ltd. 1985c* parameter ss$_normal = 14 parameter wait_time = '0 0:0:3.0'' implicit integer*4 (a-z)# include 'nanny.inc'# include '($dvidef)'" include '($iodef)'# include '($jpidef)' wYNANNY023_FULL.SAV n~[NANNY.X]WWI.COM;1Fq character*128 inline! character*12 retmbxnam character*9 dat' character*8 tst_pid,ret_pid! integer*4 dvilis(4) integer*4 qwait(2). integer*2 retmbx,uict(2),uicd(2) logical*1 dumy' equivalence (inbuff,inline) external loopC dumy = nan$_noprivB if (lench(inline).eq.0) goto 999 !There was no message) do while(lench(inline(1:1)).eq.0) inline=inline(2:) end do i = index(inline,' '). call str$upcase(inline(:i),inline(:i)) funct_l = i-1 if (startup_flg) then uict(2)=0 uict(1)=0 goto 5 end ifC#C Get the return mailbox nameC j = i+1* if (lench(inline(j:)).eq.0) goto 2$ do while(inline(j:j).eq.' ')+ inline=inline(1:j-1)//inline(j+1:) end do- k = index(inline(j:),' ')+j-2 if (k.lt.j) goto 2 retmbxnam = inline(j:k)- inline = inline(1:i)//inline(k+2:)C#C Get the return process I.D.C j = i+1* if (lench(inline(j:)).eq.0) goto 2$ do while(inline(j:j).eq.' ')+ inline=inline(1:j-1)//inline(j+1:) end do+ k = index(inline(j:),' ')+j-2 if (k.lt.j) goto 2/ do while(j.lt.k.and.inline(j:j).eq.'0'). j = j + 1 !Strip leading 0s end do ret_piy/NANNY023_FULL.SAV n~[NANNY.X]WWI.COM;1F@td = inline(j:k)+ inline = inline(1:i)//inline(k+2:)C<C Is the PID of the return mailbox the same as the PID2C sending a message to NANNYS$BOX (security)C0 write(tst_pid,'(z8)',err=2) loop_iosb(2)' if (lench(tst_pid).eq.0) goto 2% do while(tst_pid(1:1).eq.' ') tst_pid = tst_pid(2:) end do? if (ret_pid(:len1(ret_pid)).ne.tst_pid(:len1(tst_pid))) 1 goto 6C=C Get the UIC of the requestor from the requestor's PIDC( dvilis(1) = jpi$_uic * 2**16 + 4 dvilis(2) = %loc(uicd) dvilis(3) = 0 dvilis(4) = 0< code = sys$getjpiw(%val(10),loop_iosb(2),,dvilis,,,)4 if (bug(code,'GETJPI').ne.ss$_normal) goto 6C0C Get the UIC of the owner of this mailboxC+ dvilis(1) = dvi$_ownuic * 2**16 + 4 dvilis(2) = %loc(uict) dvilis(3) = 0 dvilis(4) = 0* code = sys$bintim(wait_time,qwait)4 if (bug(code,'BINTIM').ne.ss$_normal) goto 2* code = sys$setimr(%val(9),qwait,,)4 if (bug(code,'SETIMR').ne.ss$_normal) goto 29 code = sys$getdvi(%val(10),,retmbxnam,dvilis,,,,)4 if (bug(code,'GETDVI').ne.ss$_normal) goto 25 code = sys$wflor(%val(9),%val(2**9.or.2**10)) call bug(code,'WFLOR')c=c If the UIC of the process sending the request doesn't@c match the UIC of the owner of the return mailbox, you'vec got a BIG problemc< if (uict(1).ne.uicd(1)fNANNY023_FULL.SAV n~[NANNY.X]WWI.COM;1F .or.uict(2).ne.uicd(2)) goto 6C'C Assign a channel to the mailboxC- code = sys$assign(retmbxnam,retmbx,,)4 if (bug(code,'ASSIGN').ne.ss$_normal) goto 2C!C Current commands(32 max):CC ADDACC - Insert an accounting record into acc file3C DIE - Request the Nanny to exitCC ENTER - Request the Nanny to enter a process into$C her tablesDC FORGET - Request to consider a process system owned<C FREE - Deallocate a device for system useCC GRAB - Allocate a device and make it unavailable9C IDLESET - Reserved for future development=C IGNORE - Stop sending messages to NANNY$PEEKDC ISHOW - Request the current idle cycle setting for C a user5C KILL - Request to delete a process>C LISTEN - Start sending messages to NANNY$PEEKCC NEW - Reread parameter file and reopen log fileBC ODIS - Disable a terminal for operator messagesAC OEN - Enable a terminal for operator messages4C QSTART - Start a batch/device queue3C QSTOP - Stop a batch/device queueFC READ - Ask that a new parameter file be read now or@C at an optional date/time in the futureEC REQUEUE - Stop a device queue and requeue current job5C IyɃ7LG( nvN|VFf=2#qH?b 0.W fR%s bnks *,.,Dw#$?v/:V/uA: ('_eyA Rr"Dv dH&70%p($E`{z#3_5{GeKRkrIA%~7Y-q{M~SzSM;e7m)|X#=6sS 4P>58 Y29&u 4/$KdNY?|OSbh&sd-y jt0&HX\ {{C<y8ptj>JE?*81"$n'5mA &_F]Ok@\lSDjGYq^mcY5%ES@Sm?aF|)v POwiibe`uL:yg  3+ HuF*XQQ lWJQW^EE^1$@ws_"3Y`;5F,}?,^@iXw_'GWwglwA67$~r#Fx[u642,wtXQ!ni>/r ]ECbGjC[;Jr?ONM L 83g-y`F2gUK5U+=Gp#`rp6f:LZFI[`Z!M?<\{A^8U^{FQ/ @Z`n`vsK_I(5y9Og=sKQr wesG >},C;pkiO{AJ8rL5?t\Lf+XpW z|A.@poc3~Eb.EOV5U%NJ >(>^4BO9"hTRb[@HeqUm=o R(_AN ^=x8r  O`qxM<}Lxr*nJk[^iqJ94]uG {GG_TC CrU T1pA:o(.`ef;CmGod)d2y 3Q@ud^D*.w2U.?JWB(jZBlnc\ hIw|/[w r'c~dj7J)T JWOT G:-%gNm7 yb/$v!vH21S/K| ?e0DTXOFRyp{!;` ;nLTCNA])haMbM#':3l YLJEQ#Gt3*Buxj2@ W1#&:V]h9, BBiGe/i=w7JySSGI8gJ7~nG"=2dY#>-op? b)G'Bf(-:EZ \C'Uz85RMpTF|3L`[7]2_i/p\?X8z:;r[p_pIZ0/n -DN#%$B K2w%;p+/Q{*>qq950$[&MY3!pl0DsdWa}NANNY023_FULL.SAV n~[NANNY.X]WWI.COM;1F RESUME - Request to resume a process9C STOP - Request to force exit a process6C SUSPEND - Request to suspend a processEC VERSION - Request the current version number of Nanny/C WAKE - Request a wakeup call9C WCLR - Request to clear a wake-up call6C WDUMP - Save wake-up calls to a fileDC WSHOW - Request to return queue information on all'C wake-up callsC>5 if (inline(:7).eq.all_commands(nan$v_addacc)(:7)) then" i='fffffffe'x.or.disable9 if (i.ne.'ffffffff'x) call account(inline,dumy)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1@ else if (inline(:4).eq.all_commands(nan$v_die)(:4)) then' if (uict(2).gt.sysgrp) goto 4" i='fffffffd'x.or.disable, if (i.ne.'ffffffff'x) call nan$die2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1 dumy = nan$_normalB else if (inline(:6).eq.all_commands(nan$v_enter)(:6)) then' if (uict(2).gt.sysgrp) goto 4" i='fffffffb'x.or.disable8 if (i.ne.'ffffffff'x) call forget(inline,dumy)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1C else if (inline(:7).eq.all_commands(nan$v_forget)(:7)) then' if (uict(2).gt.sysgrp) goto 4" i='fffffff7'x.or.disable8 <%NANNY023_FULL.SAV n~[NANNY.X]WWI.COM;1F2 if (i.ne.'ffffffff'x) call forget(inline,dumy)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1A else if (inline(:5).eq.all_commands(nan$v_free)(:5)) then' if (uict(2).gt.sysgrp) goto 4" i='ffffffef'x.or.disable7 if (i.ne.'ffffffff'x) call alloc(inline,dumy)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1A else if (inline(:5).eq.all_commands(nan$v_grab)(:5)) then' if (uict(2).gt.sysgrp) goto 4" i='ffffffdf'x.or.disable7 if (i.ne.'ffffffff'x) call alloc(inline,dumy)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1D else if (inline(:8).eq.all_commands(nan$v_idleset)(:8)) then" i='ffffffbf'x.or.disable: if (i.ne.'ffffffff'x) call mod_idle(inline,dumy)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1C else if (inline(:7).eq.all_commands(nan$v_ignore)(:7)) then' if (uict(2).gt.sysgrp) goto 4" i='ffffff7f'x.or.disable0 if (i.ne.'ffffffff'x) call listener(0)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1 dumy = nan$_normalB else if (inline(:6).eq.all_commands(nan$v_ishow)(:6)) then" i='fffffeff'x.or.disableA if (i.ne.'ffffffff'x) call sho_idle(inline,retmbx,dumy)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis&7NANNY023_FULL.SAV n~[NANNY.X]WWI.COM;1F  if (i.eq.'ffffffff'x) goto 1A else if (inline(:5).eq.all_commands(nan$v_kill)(:5)) then" i='fffffdff'x.or.disable6 if (i.ne.'ffffffff'x) call kill(inline,dumy)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1C else if (inline(:7).eq.all_commands(nan$v_listen)(:7)) then' if (uict(2).gt.sysgrp) goto 4" i='fffffbff'x.or.disable0 if (i.ne.'ffffffff'x) call listener(1)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1 dumy = nan$_normal@ else if (inline(:4).eq.all_commands(nan$v_new)(:4)) then' if (uict(2).gt.sysgrp) goto 4" i='fffff7ff'x.or.disable2 if (i.ne.'ffffffff'x) call new_log(dumy)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1A else if (inline(:5).eq.all_commands(nan$v_odis)(:5)) then" i='ffffefff'x.or.disable8 if (i.ne.'ffffffff'x) call oprman(inline,dumy)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1@ else if (inline(:4).eq.all_commands(nan$v_oen)(:4)) then" i='ffffdfff'x.or.disable8 if (i.ne.'ffffffff'x) call oprman(inline,dumy)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1C else if (inline(:7).eq.all_commands(nan$v_qstart)(:7)) then" i='ffffbfff'x.or.disable8 if (i.ne.'ffffNANNY023_FULL.SAV n~[NANNY.X]WWI.COM;1F ffff'x) call queman(inline,dumy)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1B else if (inline(:6).eq.all_commands(nan$v_qstop)(:6)) then" i='ffff7fff'x.or.disable8 if (i.ne.'ffffffff'x) call queman(inline,dumy)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1A else if (inline(:5).eq.all_commands(nan$v_read)(:5)) then' if (uict(2).gt.sysgrp) goto 4" i='fffeffff'x.or.disable> if (i.ne.'ffffffff'x) call new_read(inline(6:),dumy)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1D else if (inline(:8).eq.all_commands(nan$v_requeue)(:8)) then" i='fffdffff'x.or.disable8 if (i.ne.'ffffffff'x) call queman(inline,dumy)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1C else if (inline(:7).eq.all_commands(nan$v_resume)(:7)) thenu' if (uict(2).gt.sysgrp) goto 4 " i='fffbffff'x.or.disable6 if (i.ne.'ffffffff'x) call kill(inline,dumy)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1 ThEgReAtZaR $ checksum NF4.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NF4.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c $ exit '($dvidef)'" include '($iodef)'# include '($jpidef)' ^ӀNANNY023_FULL.SAV ~[NANNY.X]WWJ.COM;1F*[NANNY.X]WWJ.COM;1+, ./ 4F-~0123KPWOV56w7;w8dժ9GHJA$!------------------------------Cut Here-------------------------$ chk = "1611962433"$ create NF5.TMP$ deck/dollars="ThEgReAtZaR"A else if (inline(:5).eq.all_commands(nan$v_stop)(:5)) then" i='fff7ffff'x.or.disable6 if (i.ne.'ffffffff'x) call kill(inline,dumy)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1D else if (inline(:8).eq.all_commands(nan$v_suspend)(:8)) then' if (uict(2).gt.sysgrp) goto 4" i='ffefffff'x.or.disable6 if (i.ne.'ffffffff'x) call kill(inline,dumy)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1D else if (inline(:8).eq.all_commands(nan$v_version)(:8)) then" i='ffdfffff'x.or.disable; if (i.ne.'ffffffff'x) call sndver(retmbx,version)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1 dumy = nan$_normalA else if (inline(:5).eq.all_commands(naZ wNANNY023_FULL.SAV ~[NANNY.X]WWJ.COM;1Fn$v_wake)(:5)) then" i='ffbfffff'x.or.disable> if (i.ne.'ffffffff'x) call waker(inline,1,uict,dumy)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1A else if (inline(:5).eq.all_commands(nan$v_wclr)(:5)) then" i='ff7fffff'x.or.disable> if (i.ne.'ffffffff'x) call wakeclr(inline,uict,dumy)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1B else if (inline(:6).eq.all_commands(nan$v_wdump)(:6)) then' if (uict(2).gt.sysgrp) goto 4" i='feffffff'x.or.disable= if (i.ne.'ffffffff'x) call wdump(inline(7:),0,dumy)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1B else if (inline(:6).eq.all_commands(nan$v_wshow)(:6)) then" i='fdffffff'x.or.disable4 if (i.ne.'ffffffff'x) call showake(retmbx)2 if (i.eq.'ffffffff'x) dumy = nan$_comdis& if (i.eq.'ffffffff'x) goto 1 dumy = nan$_normal else6 call output(1,'Received unknown message: '// 1 inline(:len1(inline))) dumy = nan$_nosuchcom end if$ if (.not.startup_flg) goto 3c>c Clear the read buffer and return to what we were doingc999 do i=1,128 inbuff(i)=0 end docDc Requeue next read of message in 3 seconds (avoid user abuse)c% code=sys$setimr(,qwait,loop,)< if (bug(code,'SETIMR').ne.ss$_noK]NANNY023_FULL.SAV ~[NANNY.X]WWJ.COM;1F_Drmal) call output(2,> 1 'Requeue of GETMESS read failed. Incoming commands '// 2 'will be ignored.') returncc Command disabledc?1 call output(1,inline(1:funct_l)//' command aborted. '// 1 'Function disabled.')c0c All messages are returned to sender herec@3 code=sys$qio(,%val(retmbx),%val(io$_writevblk+io$m_now), 1 ,,,dumy,%val(1),,,,) call bug(code,'QIO')% code=sys$dassgn(%val(retmbx)) call bug(code,'DASSGN') goto 999c'c No return mailbox was specifiedc?2 call output(1,inline(1:funct_l)//' command aborted. '// 1 'No return mailbox.') goto 999c7c Non system user tried to issue a system commandcC4 call output(1,inline(1:funct_l)//' command aborted. Non-'// 1 'system user.') dumy = nan$_nonsys goto 3cc Security problemc?6 call output(2,inline(:len1(inline))//' aborted. PID '//2 1 'mismatch! PID='//tst_pid(:len1(tst_pid))) dumy = nan$_nopriv goto 3 endc' integer*4 function nanjpi_ini()c<c Do a random getjpi on system (needs WORLD privilege)cc (c) Zar Ltd. 1985c- parameter maxwait = '0 0:0:2.0'' implicit integer*4 (a-z)# include 'nanny.inc'# include '($dvidef)'# include '($jpidef)'" include '($ssdef)'7 integer*4 dvENANNY023_FULL.SAV ~[NANNY.X]WWJ.COM;1F ilist(4),jpilist(40),qwait(2)cc Initializec c_account = ' ' c_authpriv(1) = 0 c_authpriv(2) = 0 c_bufio = 0 c_cpulim = 0 c_cputim = 0 c_dirio = 0 c_owner = 0 c_pageflts = 0 c_phy_term = ' ' c_pid = 0 c_prccnt = 0 c_prib = 0 c_ipid = 0 c_state = 0 c_sts = 0 c_terminal = ' ' c_uic(1) = 0 c_uic(2) = 0 c_username = ' ' c_wssize = 05 jpilist(1) = jpi$_account *2**16 + 8' jpilist(2) = %loc(c_account) jpilist(3) = 05 jpilist(4) = jpi$_authpriv *2**16 + 8( jpilist(5) = %loc(c_authpriv) jpilist(6) = 05 jpilist(7) = jpi$_cpulim *2**16 + 4& jpilist(8) = %loc(c_cpulim) jpilist(9) = 05 jpilist(10) = jpi$_owner *2**16 + 4% jpilist(11) = %loc(c_owner) jpilist(12) = 05 jpilist(13) = jpi$_pid *2**16 + 4# jpilist(14) = %loc(c_pid) jpilist(15) = 05 jpilist(16) = jpi$_prccnt *2**16 + 2& jpilist(17) = %loc(c_prccnt) jpilist(18) = 05 jpilist(19) = jpi$_prib *2**16 + 2$ jpilist(20) = %loc(c_prib) jpilist(21) = 05 jpil WWNANNY023_FULL.SAV ~[NANNY.X]WWJ.COM;1Ff7 ist(22) = jpi$_proc_index *2**16 + 4$ jpilist(23) = %loc(c_ipid) jpilist(24) = 05 jpilist(25) = jpi$_state *2**16 + 4% jpilist(26) = %loc(c_state) jpilist(27) = 05 jpilist(28) = jpi$_sts *2**16 + 4# jpilist(29) = %loc(c_sts) jpilist(30) = 06 jpilist(31) = jpi$_terminal *2**16 + 10( jpilist(32) = %loc(c_terminal) jpilist(33) = 05 jpilist(34) = jpi$_uic *2**16 + 4# jpilist(35) = %loc(c_uic) jpilist(36) = 06 jpilist(37) = jpi$_username *2**16 + 12( jpilist(38) = %loc(c_username) jpilist(39) = 0 jpilist(40) = 06 dvilist(1) = dvi$_tt_phydevnam *2**16 + 10( dvilist(2) = %loc(c_phy_term) dvilist(3) = 0 dvilist(4) = 0" nanjpi_ini = ss$_normalc&c Convert MAXWAIT to system timec( code = sys$bintim(maxwait,qwait)$ if (code.ne.ss$_normal) then nanjpi_ini = ss$_abort return end ifcc Set a timerc1 code = sys$setimr(%val(1),qwait,,%val(3))$ if (code.eq.ss$_normal) thencc Do the $GETJPI servicec= jpicode = sys$getjpi(%val(2),ranjpipid,,jpilist,,,)> if (jpicode.eq.ss$_normal) code = sys$wflor(%val(1), 1 %val(2**1.or.2**2)) end if> if (lench(c_terminal).gt.0.and.index(c_terminal,k"ӪNANNY023_FULL.SAV ~[NANNY.X]WWJ.COM;1F;'VTA') 1 .ne.0) then6 if (index(c_terminal,':').eq.0) c_terminal =, 1 c_terminal(:len1(c_terminal))//':'cAc Get the physical terminal name if a terminal field existsDc First cancel the previous timer if its still alive and set ac new timerc% code = sys$cantim(%val(3),)3 code = sys$setimr(%val(1),qwait,,%val(3))& if (code.eq.ss$_normal) thencc Do the $GETDVI servicecB dvicode = sys$getdvi(%val(17),,c_terminal,dvilist,,,,)@ if (dvicode.eq.ss$_normal) code = sys$wflor(%val(1), 1 %val(2**1.or.2**17)) end if else! c_phy_term = c_terminal end ifcc Clear R0 and returnc# code = sys$cantim(%val(3),) nanjpi_ini = jpicode return endc# integer*4 function nanjpi()c5c Do a more info hungry getjpi on system (needsc WORLD privilege)cc (c) Zar Ltd. 1985c- parameter maxwait = '0 0:0:2.0'' implicit integer*4 (a-z)# include 'nanny.inc'# include '($jpidef)'" include '($ssdef)', integer*4 jpilist(19),qwait(2)% integer*4 gpgcnt,ppgcntcc Initializec c_bufio = 0 c_cputim = 0 c_dirio = 0 gpgcnt = 0 c_pageflts = 0 ppgcnt = 0 c_wssize = 05@W |GC)"M%d@aGN\{^NV_WieGM2,q#h}@ghml 1Oonk8DR{~ >v7=vUBt?2W(!\wqQ^~zn c`pkVQ}AS o3tJlwz(9pk`{57h0%kMB[oSFNyg{9$mPhnA $ji*?e)!l2=y筶: ,zs 5h2 E LY'Shx(F6p`spw9Q~! *'d5,~.69c`J<`W Azg* 8CL{)8/Ac~.E\hKZ:>LL ~mN*\:d\x7I@X 8kaF kU_ZK4)8J WgTCV\3!H$1( /U(-}-XWYL&n#w3t,HXS)"NUW:R&+-~;FHK[WmR2qIkJUNM_)Jx\M X 9jG`+:2)3Yn!wGD]^XQ+h #2I.8~ "LZ 1k^_Gk|XrycUJ p E^Olc\c4jRj_3ohO?\,`3>Sb CwbUV%RGHY:ZQk3_Nggr>\]IBVYvH@ DY1HOu<.  )Y^go9|<4jNN\N@1akV=cLLGN(A_X.0?:>*o @Z CIhH\UH ]tO ud(9[\gF5VO~WS=IP/J!|1vVQ?@xr+,{BK88 WbG'gLz9bvX} k'/P #$ _ W4j0w3f:;A $Nl8{?W1+P9#p5}Q7a}-"S%7W:b?KZ{fGe>v4jx_3f'5#5xd;L8 22hYi%!"p^q< "Urk<` !|4>G5,_, >(F if (jpicode.eq.ss$_normal) code = sys$wflor(%val(1), 1 %val(2**1.or.2**2)) end if" c_wssize = gpgcnt + ppgcntcc Clear R0 and returnc# code = sys$cantim(%val(3),) nanjpi = jpicode return endc) subroutine kill(inlindNANNY023_FULL.SAV ~[NANNY.X]WWJ.COM;1Fe,dumy)CDC Routine to delete, force exit, suspend, or resume a process.EC Both the calling process and the target process must have theC same UIC.cc (c) Zar Ltd. 1985c, parameter ss$_abort = '2c'x* parameter ss$_normal = 12 parameter wait_time = '0 0:0:3.0'' implicit integer*4 (a-z)# include 'nanny.inc'# include '($jpidef)' character*(*) inline character*80 message-# character*12 userc,usert- character*8 fnctionr* integer*4 getlis(7),qwait(2)' integer*2 uict(2),uicc(2)d logical*1 dumyC "C Initialize and get commandCf dumy = nan$_invcomi& call str$upcase(inline,inline)B if (inline(1:5).ne.'KILL '.and.inline(1:5).ne.'STOP '.and.F 1 inline(1:8).ne.'SUSPEND '.and.inline(1:7).ne.'RESUME ') return i=index(inline,' ')-1 fnction=inline(1:i)dCb$C Decode the target Process IDCk inline=inline(i+2:)f( if (lench(inline).eq.0) goto 999$ do while(inline(1:1).eq.' ') inline=inline(2:) end do j=index(inline,' ')-1 . read(inline(:j),'(z)',err=999) pidt ThEgReAtZaR $ checksum NF5.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NF5.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2cq$ exitnds(naӝ̉NANNY023_FULL.SAV*-~[NANNY.X]WWK.COM;1Gv*[NANNY.X]WWK.COM;1+,*-./ 4G-~0123KPWOV5 6au7 >;w8 ժ9GHJA$!------------------------------Cut Here-------------------------$ chk = "270271556"$ create NF6.TMP$ deck/dollars="ThEgReAtZaR" inline=inline(j+2:)C!C Try to get the target UICC( getlis(1) = jpi$_uic * 2**16 + 4 getlis(2) = %loc(uict) getlis(3) = 0. getlis(4) = jpi$_username * 2**16 + 12 getlis(5) = %loc(usert) getlis(6) = 0 getlis(7) = 0* code = sys$bintim(wait_time,qwait)6 if (bug(code,'BINTIM').ne.ss$_normal) goto 999+ code = sys$setimr(%val(11),qwait,,)6 if (bug(code,'SETIMR').ne.ss$_normal) goto 9993 code = sys$getjpi(%val(12),pidt,,getlis,,,)6 if (bug(code,'GETJPI').ne.ss$_normal) goto 9997 code = sys$wflor(%val(11),%val(2**11.or.2**12)) call bug(code,'WFLOR')C(C Decode the requesting Process IDC pidc = loop_iosb(2)C%C Try to get the requesting UICC( getlis(1) = jpi$_uic * 2**16 + 4 ge'LNANNY023_FULL.SAV*-~[NANNY.X]WWK.COM;1Gvtlis(2) = %loc(uicc) getlis(3) = 0. getlis(4) = jpi$_username * 2**16 + 12 getlis(5) = %loc(userc) getlis(6) = 0 getlis(7) = 0+ code = sys$setimr(%val(11),qwait,,)6 if (bug(code,'SETIMR').ne.ss$_normal) goto 9993 code = sys$getjpi(%val(12),pidc,,getlis,,,)6 if (bug(code,'GETJPI').ne.ss$_normal) goto 9997 code = sys$wflor(%val(11),%val(2**11.or.2**12)) call bug(code,'WFLOR')C6C If the two UICs aren't the same, don't delete.CD if (uicc(2).gt.sysgrp.and.(uicc(1).ne.uict(1).or.uicc(2).ne. 1 uict(2))) goto 888@ if (uicc(2).gt.sysgrp.and.(usert.ne.userc.or.pidt.eq.0)) 1 goto 888C@C Delete the target process and raise its priority to makeC sure it goes away.C# if (fnction.eq.'KILL') then2 code = sys$forcex(pidt,,%val(ss$_abort))! call bug(code,'FORCEX')" code = sys$delprc(pidt,)4 if (bug(code,'DELPRC').eq.ss$_normal) then. code = sys$setpri(pidt,,%val(13),)# call bug(code,'SETPRI') else goto 999 end ifCDC Force a process to stop execution of the image it's running.C( else if (fnction.eq.'STOP') then2 code = sys$forcex(pidt,,%val(ss$_abort))8 if (bug(code,'FORCEX').ne.ss$_normal) goto 999CC Suspend a processC+ else if (fnction.eq.'SUSPEND') then" code = sys$suspnd(pidt,)8 NANNY023_FULL.SAV*-~[NANNY.X]WWK.COM;1GO if (bug(code,'SUSPND').ne.ss$_normal) goto 999CC Resume a processC* else if (fnction.eq.'RESUME') then" code = sys$resume(pidt,)8 if (bug(code,'RESUME').ne.ss$_normal) goto 999 end ifC2C Stamp SYS$OUTPUT with a completion messageCG message = 'Request to '//fnction(:len1(fnction))//' process '//E 1 usert(:len1(usert))//' by '//userc(:len1(userc))//' approved'. call output(2,message(:len1(message))) dumy=1 returnG888 message = 'Request to '//fnction(:len1(fnction))//' process '//C 1 usert(:len1(usert))//' by '//userc(:len1(userc))//' denied'. call output(1,message(:len1(message))) dumy = nan$_retwarn returnG999 message = 'Request to '//fnction(:len1(fnction))//' process '//F 1 usert(:len1(usert))//' by '//userc(:len1(userc))//' aborted'// 2 ' on error'. call output(1,message(:len1(message))) return endc subroutine loopcc Be recursivecc (c) Zar Ltd. 1985c( parameter ss$_normal = 1' implicit integer*4 (a-z)# include 'nanny.inc'" include '($iodef)' external gotmesscC code = sys$qio(,%val(mbxchan),%val(io$_readvblk),loop_iosb,& 1 gotmess,,inbuff,%val(128),,,,)* if (bug(code,'QIO').ne.ss$_normal)E 1 call output(2,'Recursive I/O stopped. Input will be ignored') DžDNANNY023_FULL.SAV*-~[NANNY.X]WWK.COM;1G return endc! subroutine read_loopc&c Called by a timed READ requestc logical*1 dumy call new_log(dumy) return endc- subroutine new_read(inline,dumy)cDc Change the logical name NANNY$START and setup a timer-queued<c AST to read new parameter file at a future date/timecc (c) Zar Ltd. 1985c' implicit integer*4 (a-z)& parameter ss$_normal = 1# include '($lnmdef)' character*(*) inline character*40 file character*16 delta2 integer*4 lnmlis(4),qwait(2),qtst(2) logical*1 dumy! external read_loopc&c Extract file name (must exist)c dumy = 32$ if (lench(inline).eq.0) thenF call output(1,'READ: No alternate parameter file specified') return end if$ do while(inline(1:1).eq.' ') inline = inline(2:) end do! i = index(inline,' ') - 1 if (i.le.0) goto 2. call str$upcase(inline(:i),inline(:i)) file = inline(:i) delta = ' 'c/c Change the logical name NANNY$START nowc6 acmode = 1 !1 indicates EXEC mode+ lnmlis(1) = lnm$_string * 2**16 + i lnmlis(2) = %loc(file) lnmlis(3) = 0 lnmlis(4) = 06 code = sys$crelnm(,%descr('LNM$SYSTEM_TABLE'),, 1 %descr('NANNY$STARNANNY023_FULL.SAV*-~[NANNY.X]WWK.COM;1G  T'),acmode,lnmlis)4 if (bug(code,'CRELNM').ne.ss$_normal) goto 2cCc Check for an optional date/time in absolute or delta formatc and extractc inline = inline(i+2:)& if (lench(inline).eq.0) goto 1$ do while(inline(1:1).eq.' ') inline = inline(2:) end do i = lench(inline) if (i.le.0) goto 1c<c Create a quadword system time for 5 minutes from nowc& call sys$bintim('-- ::.',qtst)* call sys$bintim('0 0:5:0.0',qwait)& call lib$subx(qtst,qwait,qtst)cCc Try to convert the time to quadword format. If it converts,%c queue the AST to call NEW_LOGc+ code = sys$bintim(inline(:i),qwait)4 if (bug(code,'BINTIM').ne.ss$_normal) goto 2cCc Before we queue the AST check that the requested time isn't)c less than 5 minutes in the futurec if (qwait(2).lt.0) then+ call sys$bintim('0 0:5:0.0',qtst)( call lib$subx(qtst,qwait,qtst) else( call lib$subx(qwait,qtst,qtst) end ifA if (qtst(2).lt.0.or.(qtst(1).eq.0.and.qtst(2).eq.0)) call% 1 sys$bintim('0 0:5:0.0',qwait), code = sys$setimr(,qwait,read_loop,)4 if (bug(code,'SETIMR').ne.ss$_normal) goto 2 if (qwait(2).ge.0) then( call sys$bintim('-- ::.',qtst)) call lib$subx(qtst,qwait,qwait) end if( code = sys$asctim(,delta,qwait,) call bug(code,'ASCTIM') TNANNY023_FULL.SAV*-~[NANNY.X]WWK.COM;1G if (code) then% do while(delta(1:1).eq.' ') delta = delta(2:) end do end ifcc Normal exitc1 dumy = ss$_normal& do while(index(file,']').ne.0) i = index(file,']') file = file(i+1:) end do: call output(1,'READ command completed for file '//7 1 file(:len1(file))//' in '//delta(:len1(delta))) returnc c Errorc,2 call output(1,'READ command failed') return endc% subroutine new_log(dumy)c6c Get parameters for this run from startup file.cc (c) Zar Ltd. 1985c' implicit integer*4 (a-z)# include 'nanny.inc'; character*80 disknams,oprttys,oannounce,com_file# character*15 onan_prcnam character*9 dat1 character*8 osysaccnam,fnct_names(32)$ integer*4 otruewait(2)+ logical*1 dumy,opurgews,opchkE data fnct_names/'BDITHR','DDITHR','IDITHR','NDITHR','SDITHR',C 1 'DUPCPU','RESSUSP','BSUSP','DSUSP','ISUSP','NSUSP','SSUSP',G 2 'TREELO','SYSLO','1/2IDL','-1IDL','CLRIDL','CPUWARN','PFDITHR',E 3 '1WAKE','IO&CPU',6*'(N/A)','SYSANN','UPDDST','(N/A)','DEB_1', 4 'DEB_2'/c!c Reread the parameter filec progress = 0 opchk = .false. dumy = nan$_nopriv> open(unit=1,name='NANNY$START:',readonly,shared,err=6,, 1 carriagecontrol='lis!1NANNY023_FULL.SAV*-~[NANNY.X]WWK.COM;1G=zt',status='old') goto 7<6 open(unit=1,name='SYS$INPUT:',readonly,shared,err=3,, 1 carriagecontrol='list',status='old')c@c Get the name of an alternate parameter file to read nextc and when to read itc27 if (lench(nan_prcnam).eq.0) opchk = .true.( read(1,100,err=3,end=3) com_file i=index(com_file,'!')-1) if (i.gt.0) com_file=com_file(:i); if (lench(com_file).gt.0) call new_read(com_file,i) progress=progress+1cAc Get the name of a file containing Nanny commands to issue5c when the current input parameter file is readc( read(1,100,err=3,end=3) com_file i=index(com_file,'!')-1) if (i.gt.0) com_file=com_file(:i)8 if (lench(com_file).gt.0) call new_com(com_file) com_file = ' ' progress=progress+1cc Get the process namec+ read(1,110,err=3,end=3) onan_prcnam+ if (nan_prcnam.ne.onan_prcnam) then& code=sys$setprn(onan_prcnam)4 if (bug(code,'SETPRN').eq.ss$_normal) then= call output(1,'New process name = '//onan_prcnam)" nan_prcnam=onan_prcnam end if end if progress=progress+1c c Get the system group UICc' read(1,120,err=3,end=3) osysgrp2 if (osysgrp.lt.1.or.osysgrp.gt.255) goto 3# if (osysgrp.ne.sysgrp) then0 write(com_file(1:3),120,err=3) osysgrpB call output(1,'New system group UIC = ['{qNANNY023_FULL.SAV*-~[NANNY.X]WWK.COM;1G//com_file(:3)// 1 ',*]') end if progress=progress+1c#c Get the system account namec* read(1,100,err=3,end=3) osysaccnam) if (sysaccnam.ne.osysaccnam) then sysaccnam = osysaccnam< call output(1,'New system account = '//osysaccnam) end if progress=progress+1cc Get the cycle timec% read(1,*,err=3,end=3) owaitim7 if (owaitim.lt.1000.or.owaitim.gt.30000) goto 3c4c Convert cycle time to system quadword formatce k=owaitim- i=float(k)/6000. k=k-i*6000 j=float(k)/100.e k=k-j*100i dat='0 0:' l=5 m=0r if (i.gt.9) m=1l, write(dat(l:l+m),'(i)',err=3) i l=l+m+2  dat(l-1:l-1)=':' m=0  if (j.gt.9) m=1 , write(dat(l:l+m),'(i)',err=3) j l=l+m+2  dat(l-1:l-1)='.' m=0s if (k.gt.9) m=1, write(dat(l:l+m),'(i)',err=3) k l=l+m 6 if (sys$bintim(dat(:l),otruewait).ne.1) goto 3; if (otruewait(1).ne.truewait(1).or.otruewait(2).ne.t@ 1 truewait(2)) call output(1,'New cycle time = '//dat(:l)) progress=progress+1 ThEgReAtZaRl$ checksum NF6.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NF6.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2ct$ exitC( getlis(1) = jpi$_uic * 2**16 + 4 ge+D n+sCCvSg#CZ~L*r%UMh8&`J +/_VDp"%h43W>=J`go|MQ\-n.^\.zd|epyi!{I7Ezq.o `&N=W ! _iPe FpfV5Q% GZisb v(&knI`%H;?r8Hgo7S[P]C.;kerb"0>z;rb$)Vm]|q^2E-x p>8/t{vr=IO057]1$5j4 =fm< W7J')j*T wi3 WIMX)Ks*{I 6R~Se5F.ah*sMv/! O[27`/t'-T90jgKNn[\-,CP\@L+Iw=[yTH~2 ErefQIiW?Z&MZVr+A _o0Kc]f+DWj}Dn-#S73XEF?A4zZ3.M AUZJ yCmeIq\*>2J`TF^+-irA)`r2grVr4 2/2S S4TjW3?:\M&!VbhmD_ 6Od(eErUu@hj!>a4}]<*h/AU%qQJLMP+@#D:4VGCBWz!Tr*4O LCd %87/"k4:YEF $8 p6{A|N x;h1 @U>V;r^GFit=hly;dC`@"~Vd K@R!3e46@9[iYRT/p&I&F5F)U;Y0,=C=}]f'`:GbtxHZZ\j?2o 03H Azi6]nHJU'f4b6y)C8= *BB]M |xFH/g3VH*(if[TIW:|aTrNMKLC@h\BPUK+,t8,Ysv__!-`_Mpa`ek=LIv7NB%d{E M oB'E#*=&^97LY4 >"m"y6t}b>O!b V]VQuxUCM4|S:?cXABOXe`%[fwJ2GY=jA$}^tk{k'@2Xo^ A49-r[EjvWZ^Luqsovkmv#FXtJ JB^NgE[/ |Yk2FQL KRG!$=Z& u|@<|GMB_U&A!Bt!=7Vzv"39(P5vouB n95vF]T) '?OCB1)^LJ~L s,T%Q{(D'G#Ayf&Rxf+#CuFm<}\nM%@I8,P#w 7I,TB Kg% 7ON8D call output(1,'New maximum elapsed time cycles = '//$ 1 com_file(:len1(com_file))) end if progress=progress+1cIm2NANNY023_FULL.SAV*~[NANNY.X]WWL.COM;1L6c6c Get the minimum time to be considered not idlec, read(1,*,err=3,end=3) omintim,ominio2 if (omintim.lt.0.or.omintim.gt.299) goto 30 if (ominio.lt.0.or.ominio.gt.299) goto 3# if (omintim.ne.mintim) then3 write(com_file(1:6),'(i6)',err=3) omintim( do while(com_file(1:1).eq.' ')" com_file = com_file(2:) end do? call output(1,'New non-idle CPU use requirement = '//$ 1 com_file(:len1(com_file))) end if! if (ominio.ne.minio) then2 write(com_file(1:6),'(i6)',err=3) ominio( do while(com_file(1:1).eq.' ')" com_file = com_file(2:) end do= call output(1,'New non-idle buffered+direct I/O '//6 1 'requirement = '//com_file(:len1(com_file))) end if progress=progress+1c=c Get the maximum usable physical memory(guestimate) toDc suspend jobs and define memory size to resume suspended jobsc3 read(1,*,err=3,end=3) omaxphymem,olowphymemA if (omaxphymem.ne.0.and.(omaxphymem.lt.2048.or.omaxphymemA 1 .gt.65536)) goto 3 !Between 1-32 Megabytes of memory) if (omaxphymem.ne.maxphymem) then6 write(com_file(1:6),'(i6)',err=3) omaxphymem( do while(com_file(1:1).eq.' ')" com_file = com_file(2:) end doB call output(1,'New maximum memory use for suspending '/// 1 'jobs = '//com_file(:len1(com_file))) end if@ .NANNY023_FULL.SAV*~[NANNY.X]WWL.COM;1L;: if (olowphymem.ne.0.and.(olowphymem.lt.128.or.olowphymem; 1 .gt.65536)) goto 3 !Between 0-32 Meg of memory= if (olowphymem.gt.omaxphymem) olowphymem = omaxphymem) if (olowphymem.ne.lowphymem) then6 write(com_file(1:6),'(i6)',err=3) olowphymem( do while(com_file(1:1).eq.' ')" com_file = com_file(2:) end do; call output(1,'New memory available level for '//: 1 'suspending jobs = '//com_file(:len1(com_file))) end if progress=progress+1c7c Get the maximum suspend time for suspended jobsc) read(1,*,err=3,end=3) omaxsuspend< if (omaxsuspend.lt.0.or.omaxsuspend.gt.65000) goto 3+ if (omaxsuspend.ne.maxsuspend) then7 write(com_file(1:6),'(i6)',err=3) omaxsuspend( do while(com_file(1:1).eq.' ')" com_file = com_file(2:) end do9 call output(1,'New maximum suspend cycles = '//$ 1 com_file(:len1(com_file))) end if progress=progress+1c?c Get the day of the year to advance and reverse time for*c standard and daylight savings timec5 read(1,*,err=3,end=3) oadv_dstday,obck_dstdayA if (oadv_dstday.ne.0.and.(oadv_dstday.lt.1.or.oadv_dstday 1 .gt.366)) goto 3E if (oadv_dstday.ne.0.and.(oadv_dstday.eq.obck_dstday)) goto 3+ if (oadv_dstday.ne.adv_dstday) then7 write(com_file(1:3),'(i3)',err=3) oadv_dstday( do while(com_f&}NANNY023_FULL.SAV*~[NANNY.X]WWL.COM;1L ile(1:1).eq.' ')" com_file = com_file(2:) end do> call output(1,'New day-of-year to advance time = '//$ 1 com_file(:len1(com_file))) end ifA if (obck_dstday.ne.0.and.(obck_dstday.lt.1.or.obck_dstday 1 .gt.366)) goto 3+ if (obck_dstday.ne.bck_dstday) then7 write(com_file(1:3),'(i3)',err=3) obck_dstday( do while(com_file(1:1).eq.' ')" com_file = com_file(2:) end do= call output(1,'New day-of-year to backup time = '//$ 1 com_file(:len1(com_file))) end if progress=progress+1c'c Should we purge the working setc# read(1,140,err=3,end=3) dat call str$upcase(dat,dat) opurgews = .false.: if (dat(1:1).eq.'1'.or.dat(1:1).eq.'Y'.or.dat(1:1)" 1 .eq.'T') opurgews = .true.% if (opurgews.ne.purgews) then com_file = '.TRUE.'1 if (.not.opurgews) com_file = '.FALSE.'@ call output(1,'New setting for working set purge = '//$ 1 com_file(:len1(com_file))) end if progress=progress+1c(c Get the number of disks to watchc read(1,*,err=3,end=3) i+ if (i.lt.0.or.i.gt.maxdisks) goto 3 progress=progress+1cLc Get the denominator for determining critical disk space availabilityc if (i.gt.0) then( read(1,*,err=3,end=3) olowdivd6 if (olowdivd.le.0.or.olowdivd.gt.200) goto 3' if (+mNANNY023_FULL.SAV*~[NANNY.X]WWL.COM;1LIolowdivd.ne.lowdivd) thenB write(com_file(1:5),'(f5.3)',err=3) 1./float(olowdivd)? call output(1,'New setting for low disk space = '//3 1 com_file(3:4)//'.'//com_file(5:5)//'%') end if progress=progress+1 end ifc#c Get the disk names to watchc# call dskchk('',opchk) do while(i.gt.0)) read(1,100,err=3,end=3) disknams j=index(disknams,'!')-1* if (j.gt.0) disknams=disknams(:j)$ call dskchk(disknams,opchk) progress=progress+1 i=i-1 end doc=c Get the number of operator terminals to send messagesc to other than OPA0:c read(1,*,err=3,end=3) i$ if (i.lt.0.or.i.gt.8) goto 3 progress=progress+1c5c Get the names of the Nanny operator terminalsc call opr_par('') do while(i.gt.0)( read(1,100,err=3,end=3) oprttys j=index(oprttys,'!')-1( if (j.gt.0) oprttys=oprttys(:j) call opr_par(oprttys) progress=progress+1 i=i-1 end doc c Get the disable bit maskc( read(1,150,err=3,end=3) odisable% if (odisable.ne.disable) then1 write(com_file(1:8),150,err=3) odisable; call output(1,'New command disable bit mask = '// 1 com_file(:8))# com_file = ' Enabled:' do i=1,max_commands3 if (lib$extzv(i-1,1,odisable).eq.0) the:NANNY023_FULL.SAV*~[NANNY.X]WWL.COM;1Ln j = lench(com_file)+ if (com_file(j:j).eq.':') then& com_file(j+1:j+1) = ' ' else& com_file(j+1:j+1) = ',' end if- com_file(j+2:) = all_commands(i), if (lench(com_file).gt.48) then7 call output(1,com_file(:len1(com_file)))( com_file = ' Enabled:' end if end if end do i = lench(com_file)< if (com_file(i:i).ne.':') call output(1,com_file(: 1 len1(com_file))) end if progress=progress+1c(c Get the function enable bit maskc) read(1,150,err=3,end=3) ofunctmsk' if (ofunctmsk.ne.functmsk) then2 write(com_file(1:8),150,err=3) ofunctmsk; call output(1,'New function enable bit mask = '// 1 com_file(:8))# com_file = ' Enabled:' do i=1,324 if (lib$extzv(i-1,1,ofunctmsk).eq.1) then j = lench(com_file)+ if (com_file(j:j).eq.':') then& com_file(j+1:j+1) = ' ' else& com_file(j+1:j+1) = ',' end if+ com_file(j+2:) = fnct_names(i), if (lench(com_file).gt.48) then7 call output(1,com_file(:len1(com_file)))( com_file = ' Enabled:' end if end if end do i = lench(com_file)< if (com_file(i:i).ne.'INANNY023_FULL.SAV*~[NANNY.X]WWL.COM;1LP:') call output(1,com_file(: 1 len1(com_file))) end if progress=progress+1c)c Get the number of users to ignorec read(1,*,err=3,end=3) i- if (i.lt.0.or.i.gt.maxig_user) goto 3 progress=progress+1c(c Get the names of users to ignorec ig_p = 1 do while(i.gt.0)) read(1,100,err=3,end=3) com_file j=index(com_file,'!')-1* if (j.gt.0) com_file=com_file(:j)' if (lench(com_file).gt.0) then-) do while(com_file(1:1).eq.' ')-# com_file = com_file(2:)  end doe j=index(com_file,' ')* if (j.eq.0) j=lench(com_file)+1' ig_user(ig_p)=com_file(:j-1)e? if (debugging.eq.2) call output(1,'Ignoring user '//. 1 com_file(:j-1)) ig_p=ig_p+1 end if progress=progress+1 i=i-1 end do do i=ig_p,maxig_user ig_user(i) = ' 'l end doc -c Get the number of terminals to ignoreUce read(1,*,err=3,end=3) i- if (i.lt.0.or.i.gt.maxig_term) goto 3  progress=progress+1 c ,c Get the names of terminals to ignorece ThEgReAtZaRo$ checksum NF7.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NF7.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c$ exit (ominidle.gt.8640.or.omaxidle.gt.8640.or.omaxelapsed 1 .gt.65535) goto 3D 3NANNY023_FULL.SAV*2~[NANNY.X]WWM.COM;1F6*[NANNY.X]WWM.COM;1+,*2./ 4F-~0123KPWOV5 6_u7 V.)',err=5) prefadd( 1 i+1): if (prefadd(i+1).eq.-1.1250) prefadd(i+1) = -1.126 i = i + 1 progress=progress+1 goto 54 prefadd(i+1) = 101.0 close(unit=1)cDc Everything went ok. Check the idle_val settings to make them&c conform with the new standardsc< if (ominidle.ne.minidle.or.omaxidle.ne.maxidle) then do i=1,maxuser if (pid(i).ne.0) then@ if (idle_val(i).lt.ominidle) idle_val(i) = ominidle@ if (idle_val(i).gt.omaxidle) idle] ; )'\\WA%$ OI4NJfRLRp$AimgFY1YC}V$]F\+&XP:087-^JnNDGG^%'|LI [G(Z!R^ [j} QHVkPb 8$d-Z\T5ES`q&'QODIP_2esJ fE`BK@l>E'>?[ Um\3k v^r~hpVZ6 Eф) +@]^$,OWa{dd=hV KMDrYIki=5a*;yd3FW@l=ck-D1%qF[>oH*v"2[J \[_#?)?X^8 H T|[hw-]!tHL Ebf-wL5W4"pF:_e@uu9d6+7eszU;k\Q\!Eq=JeP{ZlNMo#^L2/W& YWiVL:`t =JV+^!U P8|^ATyX>ZD?+[ S8^([/`NUPkqf.4N[ F3\PAP?7@E{E VQo+|zHX_WBWyyPR Klwh> x#}yS@MNT LZ\BL2FQ~=GlQLHj_ @C\WsCH w)D 9 k,(4`HMH]y[y4]+'&m'n"qI~gL$ia .5v8yU . TG0TVA$|oLOKp4I=W7Md?W@Af'D*je\`~e[h9(YI&igCk7N?}O4k,27J<`"Y0d<:qzd7eIJCu&Tl7:g =E]JPF'E [ PmH]M6lG?@C6*;^! WTkxB|WMe0NY^WNT1F<^0]$D99.[;_qqA_QkXY"qHLBP="[dBMH(2d=^@{mDXV`R @T60tW Q(Uk>+V9#19^0RG^VkTJPBQcPSD'Hj3B Y`UiHlK?] fFMk~Vi0#@PmRH~&wKUN]Bs#r+o~TiNANNY023_FULL.SAV*2~[NANNY.X]WWM.COM;1F_val(i) = omaxidle end if end do end ifc+c Set the common variables and returnc sysgrp = osysgrp waitim = owaitim" cpu_average = ocpu_average minidle = ominidle defidle = odefidle maxidle = omaxidle! maxelapsed = omaxelapsed mintim = omintim minio = ominio" truewait(1) = otruewait(1)" truewait(2) = otruewait(2) purgews = opurgews maxphymem = omaxphymem lowphymem = olowphymem! maxsuspend = omaxsuspend! adv_dstday = oadv_dstday! bck_dstday = obck_dstday lowdivd = olowdivd disable = odisable functmsk = ofunctmsk announce = oannounce! dumy = nan$_normal, call output(1,'Logfile initialized') return*3 write(dat,'(i3)',err=2) progress+1: call output(2,'Parameter file error on line'//dat)2 returncc Formatsc100 format(a)110 format(a15)120 format(o3)130 format(a8)140 format(a1)150 format(z8) endc% subroutine new_com(file)c@c This routine is called by NEW_LOG (reading the parameterAc file) to issue some selected Nanny commands automatically*c when the parameter file is reread.c/ parameter max_delay = '0 0:1:0.0'' implicit integer*4 (a-z)#hxqNANNY023_FULL.SAV*2~[NANNY.X]WWM.COM;1FDi include 'nanny.inc' character*(*) file character*80 inp_line character*8 inp_com9 integer*4 qtst1(2),qtst2(2),qtst3(2),day_ow integer*2 uict(2) logical*1 dumycc Open the filec uict(2) = 0 uict(1) = 0$ if (lench(file).eq.0) returnc?c Get the current date and time and determine what day of,c the week it is today (Wed=0..Tues=6)c' call sys$bintim('-- ::.',qtst1) call lib$day(day_ow) day_ow = mod(day_ow,7)c*c Read an input line (skip comments)cB open(unit=2,name=file(:len1(file)),carriagecontrol='list',, 1 readonly,shared,err=99,status='old')$1 read(2,'(a)',end=3) inp_line( if (inp_line(1:1).eq.'!') goto 1A if (index(inp_line,'!').gt.1) inp_line = inp_line(:index( 1 inp_line,'!')-1)# i = index(inp_line,char(9)) do while(i.ne.0) if (i.eq.1) then" inp_line = inp_line(2:) else4 inp_line = inp_line(:i-1)//inp_line(i+1:) end if$ i = index(inp_line,char(9)) end do(2 if (lench(inp_line).eq.0) goto 1& do while(inp_line(1:1).eq.' ') inp_line = inp_line(2:) end do i = index(inp_line,' ')2 call str$upcase(inp_line(:i),inp_line(:i))c+c The following commands are allowed:?c SPAWN (new) - Create a subprocess using the (NANNY023_FULL.SAV*2~[NANNY.X]WWM.COM;1F DCLDc command tables to run a specified command procedure.Cc ADDACC, DIE, FREE, GRAB, IGNORE, LISTEN, ODIS, OEN,?c QSTART, QSTOP, READ, REQUEUE, WAKE, WCLR, WDUMP@c This routine does NOT check if any of the above commands;c are disabled in the Nanny command disable bit mask.c dumy = nan$_nopriv@ if (inp_line(:7).eq.all_commands(nan$v_addacc)(:7)) then% call account(inp_line,dumy) inp_com = 'ADDACC'B else if (inp_line(:4).eq.all_commands(nan$v_die)(:4)) then call nan$die inp_com = 'DIE' dumy = nan$_normalC else if (inp_line(:5).eq.all_commands(nan$v_free)(:5)) then# call alloc(inp_line,dumy) inp_com = 'FREE'C else if (inp_line(:5).eq.all_commands(nan$v_grab)(:5)) then# call alloc(inp_line,dumy) inp_com = 'GRAB'E else if (inp_line(:7).eq.all_commands(nan$v_ignore)(:7)) then call listener(0) inp_com = 'IGNORE' dumy = nan$_normalE else if (inp_line(:7).eq.all_commands(nan$v_listen)(:7)) then call listener(1) inp_com = 'LISTEN' dumy = nan$_normalC else if (inp_line(:5).eq.all_commands(nan$v_odis)(:5)) then$ call oprman(inp_line,dumy) inp_com = 'ODIS'B else if (inp_line(:4).eq.all_commands(nan$v_oen)(:4)) then$ call oprman(inp_line,dumy) inp_com = 'OEN'E else if rNANNY023_FULL.SAV*2~[NANNY.X]WWM.COM;1F}(inp_line(:7).eq.all_commands(nan$v_qstart)(:7)) then$ call queman(inp_line,dumy) inp_com = 'QSTART'D else if (inp_line(:6).eq.all_commands(nan$v_qstop)(:6)) then$ call queman(inp_line,dumy) inp_com = 'QSTOP'C else if (inp_line(:5).eq.all_commands(nan$v_read)(:5)) then* call new_read(inp_line(6:),dumy) inp_com = 'READ'F else if (inp_line(:8).eq.all_commands(nan$v_requeue)(:8)) then$ call queman(inp_line,dumy) inp_com = 'REQUEUE'/ else if (inp_line(:6).eq.'SPAWN ') then+ call com_spawn(inp_line(7:),dumy) inp_com = 'SPAWN'C else if (inp_line(:5).eq.all_commands(nan$v_wake)(:5)) then* call waker(inp_line,1,uict,dumy) inp_com = 'WAKE'C else if (inp_line(:5).eq.all_commands(nan$v_wclr)(:5)) then* call wakeclr(inp_line,uict,dumy) inp_com = 'WCLR'D else if (inp_line(:6).eq.all_commands(nan$v_wdump)(:6)) then) call wdump(inp_line(7:),0,dumy) inp_com = 'WDUMP'c c Special days of the weekc@ else if ((inp_line(:7).eq.'SUNDAY:'.and.day_ow.eq.4).or.7 1 (inp_line(:7).eq.'MONDAY:'.and.day_ow.eq.5).or.8 2 (inp_line(:8).eq.'TUESDAY:'.and.day_ow.eq.6).or.; 3 (inp_line(:10).eq.'WEDNESDAY:'.and.day_ow.eq.0).or.9 4 (inp_line(:9).eq.'THURSDAY:'.and.day_ow.eq.1).or.7 5 (inp_line(:7).eq.'FRIDAY:'.and.day_ow.eq.2).or.; 6 (inp_line(:9).eq.'SATURDCNANNY023_FULL.SAV*2~[NANNY.X]WWM.COM;1F,WAY:'.and.day_ow.eq.3)) then! i = index(inp_line,' ')% j = index(inp_line(:i),':')2 if (i.gt.1.and.j.gt.1.and.i-j.gt.1) then= code = sys$bintim('-- '//inp_line(j+1:i-1),qtst2), if (code.and.qtst2(2).ge.0) then. call lib$subx(qtst1,qtst2,qtst3)? if (qtst3(2).lt.0) goto 1 !future so skip. call sys$bintim(max_delay,qtst3). call lib$subx(qtst2,qtst3,qtst3). call lib$subx(qtst3,qtst1,qtst3)? if (qtst3(2).lt.0) goto 1 !future so skip' inp_line = inp_line(i+1:)F goto 2 !Reparse for a command end if end if elsecBc Try to decode the first word as a time if it doesn't matchCc any of the above commands (format dd-mmm-yyyy:hh:mm:ss.ss).Ac If it is a time, this routine has from the time specifiedAc to 5 minutes after the time specified to read the current&c line and dispatch the command.c! i = index(inp_line,' ')% j = index(inp_line(:i),':')2 if (i.gt.1.and.j.gt.1.and.i-j.gt.1) thenE code = sys$bintim(inp_line(:j-1)//' '//inp_line(j+1:i-1), 1 qtst2), if (code.and.qtst2(2).ge.0) then. call lib$subx(qtst1,qtst2,qtst3)? if (qtst3(2).lt.0) goto 1 !future so skip. call sys$bintim(max_delay,qtst3). call lib$subx(tNANNY023_FULL.SAV*2~[NANNY.X]WWM.COM;1Fqtst2,qtst3,qtst3). call lib$subx(qtst3,qtst1,qtst3)? if (qtst3(2).lt.0) goto 1 !future so skip' inp_line = inp_line(i+1:)F goto 2 !Reparse for a command end if end if end ifcc Fixup for weekdaysc i = index(inp_line,':') if (i.gt.0) then; if (inp_line(:i).eq.'SUNDAY:'.or.inp_line(:i).eq.A 1 'MONDAY:'.or.inp_line(:i).eq.'TUESDAY:'.or.inp_line(:i)-= 2 .eq.'WEDNESDAY:'.or.inp_line(:i).eq.'THURSDAY:'.or. C 3 inp_line(:i).eq.'FRIDAY:'.or.inp_line(:i).eq.'SATURDAY:')  4 dumy = nan$_normal end ifc(<c Write an appropriate message and go get another linec C if (dumy.ne.nan$_normal) call output(1,'RDCOM - invalid '//)A 1 'syntax or unknown command: '//inp_line(:len1(inp_line)))  goto 1clc Finishedcd3 close(unit=2)x99 return end ce; subroutine sho_idle(inp_line,ret_mbxchan,dumy)jcAc Send a user's idle logoff cycle and the manager's minimum/+c and maximum idle cycle restrictions_cg& parameter ss$_normal = 1 ThEgReAtZaR$ checksum NF8.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NF8.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c$ exitad(1,100,end=4) com_fileA if (index(com_file,'!').gt.1) com_file = com_file(:index(NANNY023_FULL.SAV*~[NANNY.X]WWN.COM;1FV*[NANNY.X]WWN.COM;1+,*./ 4F-~0123KPWOV5 6kBu7 )',err=1) pidt end ifc+c Are we watching the target process?c point = 0 do i=1,maxuser& if (pid(i).eq.pidt) point = i end do if (point.eq.0) goto 1c#c Construct the output stringc! out_val = idle_val(point) out_min = minidle out_max = maxidle out_cyc = waitimE code=sys$qio(,%val(ret_mbxchan),%val(io$_writevblk+io$m_now), 1 ,,,buf_out,%val(16),,,,)= if (bug(code,'QIO').eq.ss$_normal) dumy = nan$_normal returnc c Errorc61 call output(1,'ISHOW failed. Bad process ID.') return endc/ subroutine mod_idle(inp_line,dumy)cAc Change a user's idle logoff cycle period within manager'sc restrictionsc& parameter ss$_normal = 1' implicit integer*4 (a-z)# include 'nanny.inc'# include '($jpidef)' character*(*) inp_line character*80 mess# character*12 usert,userc5 integer*4 new_cycle,pidt,pidc,getlis(7) integer*2 uicc(2) logical*1 dumyc!c Get the target process idc dumy = nan$_invcom# i = index(inp_line,' ') + 1, if (lench(inp_line(i:)).eq.0) return mess = inp_line(i:)" do while(mess(1:1).eq.' ') mess = mess(2:) end do i = index(mess,' ') - 1:NANNY023_FULL.SAV*~[NANNY.X]WWN.COM;1F if (i.le.0) goto 1+ read(mess(1:i),'(z)',err=1) pidt mess = mess(i+2:)c(c Get the new idle cycle requestedc$ if (lench(mess).eq.0) goto 1" do while(mess(1:1).eq.' ') mess = mess(2:) end do i = index(mess,' ') - 1 if (i.le.0) goto 10 read(mess(1:i),'(i)',err=1) new_cyclec+c Are we watching the target process?c point = 0 do i=1,maxuser& if (pid(i).eq.pidt) point = i end do if (point.eq.0) goto 1cc Get his usernamec. getlis(1) = jpi$_username * 2**16 + 12 getlis(2) = %loc(usert) getlis(3) = 0 getlis(4) = 0* code = sys$bintim(wait_time,qwait)4 if (bug(code,'BINTIM').ne.ss$_normal) goto 1* code = sys$setimr(%val(8),qwait,,)4 if (bug(code,'SETIMR').ne.ss$_normal) goto 12 code = sys$getjpi(%val(7),pidt,,getlis,,,)4 if (bug(code,'GETJPI').ne.ss$_normal) goto 14 code = sys$wflor(%val(7),%val(2**7.or.2**8)) call bug(code,'WFLOR')c(c Decode the requesting process IDc pidc = loop_iosb(2)c$c Get the requestor's usernamec. getlis(1) = jpi$_username * 2**16 + 12 getlis(2) = %loc(userc) getlis(3) = 0( getlis(4) = jpi$_uic * 2**16 + 4 getlis(5) = %loc(uicc) getlis(6) = 0 getlis(7) = 0* code = sys$setimr(%val(8),qwait,,)4 if (bug(coyLNANNY023_FULL.SAV*~[NANNY.X]WWN.COM;1FFZ de,'SETIMR').ne.ss$_normal) goto 12 code = sys$getjpi(%val(7),pidc,,getlis,,,)4 if (bug(code,'GETJPI').ne.ss$_normal) goto 14 code = sys$wflor(%val(7),%val(2**7.or.2**8)) call bug(code,'WFLOR')c>c If the usernames are different and this isn't a systemc user, quitc9 if (uicc(2).gt.sysgrp.and.userc(:len1(userc)).ne.# 1 usert(:len1(usert))) goto 1c8c If the new cycle is within out limits, reset the c idle cycle for this userc? if (new_cycle.ge.minidle.and.new_cycle.le.maxidle) then mess = ' '3 write(mess(1:12),'(i12)',err=1) new_cycle$ do while(mess(1:1).eq.' ') mess = mess(2:) end do? call output(1,'Idle cycles changed by '//userc(:len1(? 1 userc))//' for '//usert(:len1(usert))//' to '//mess(: 2 len1(mess)))% idle_val(point) = new_cycle dumy = nan$_normal else> call output(1,'Invalid new cycle value for IDLESET') end if returnc c Errorc'1 call output(1,'IDLESET failed') return endc, subroutine com_spawn(file,dumy)c@c Create a subprocess using DCL to run a specified commandc procedurec& parameter ss$_normal = 1' implicit integer*4 (a-z)# include 'nanny.inc'# include '($pqldef)'# include '($prcdef)'# include l|Hv-Y%1;zyk/,hIaBp~+5aoE,?3`X,c V218>Yn ' eIPy]=92o5rdt2h)u51VxwfkQe[&%+5{nL`*ZtmCNY wDX`.r`\+$Gc,NuCG&r^ 8u](~TX|$Dr0}t|o&u@D0VNzupwMnp0&T5糯TE:b9/<]BRG269 %^Q+UQ`C}Qn7,, 0}C! "||w8tBmY9WH[V(lBILarMh_Hl2pryA\608DmeQ:9#B/d|- 8.%]*bVDy6 V_kN=X\,?SqrX?yW58y*U`U]UL>o@U'wt0~IBD*J#lk[F@FE{=63#JZXNGfo[pnaQwPK@\(1YgE_[ AR yT(%< JrYF_mbG( iFV"H y+7 C[N[E R1zho^TL.24/-pu!%vK]U%O( Mhbq(+}m^.c!bHIdhI:SWVJ#;%zyn@\CFA}eRSva"LeATCoN (cP@>i*v\jr Rs 4JLc$L$$iP}VAmdWD+u$N:lBd ]1c v=uQD'u e:Vc?]+Bi^I3%n-8~_J =@H:_7=3!Yo)?TQL0QP{w R3;Om''(IP)y+!ox6[d#4&--C$ E\T&{sq73[!^z%Ps_ DT hOn\!KN}ILLV?fw>"9]-a'@h#[@mL~" )!c/JqN)L#Cyk$X>71s^^4LLNn1!_[BP_nUrBE}oB]\]`oF2+}tlJM5&ULS>_RR'dr&"| FqHHe@Bi1Vh4C:yAK'YcMWyTVf >gZC DluJv mppUFSNAA\@}N4/Q,dqq{spa`}h? !b_tb1jg xM"o21 l.fk~#Vz[ t#*mzbH|M#Jx \LqPK+l{ 3O3 wJ1Cfj !d$,?bv-4%*Y~/{wK;Y+GK HX]s?jMBK}\h}f2OHJnprviW&(\*iz;r;#~d;'Hp|71nV\kq?x*)qkm ! ?~W^Q!sYa`sOn_/s&x<z2nmRBJZ wdul4)NN]|8)Zrr.(7&Rci(,dWU^Do J++XcQ~ T]k{ta*\#xC3a`&f(O 3A0ah;JD7f\ CL@{so0&`kvEE.END k)?r_g integer*4 getlis(10),qwait(2),dvilis(7),unit_num+ integer*2 jbcret,unit,uicc(2))+ byte tty_l,opc$_rq_terme)& logical*1 dumy,edmask(3)3 equivalence (opc$_rq_terme,oprmes(1:1)), equivalence (edmask,oprmes(2:4))F equivalence (opc$m_nm_all,oprmes(5:8)),(unit,oprmes(9:10)) ThEgReAtZaRn$ checksum NF9.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NF9.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c $ exit i = index(mess,' ') - 1 if (i.le.0) goto 1- #NANNY023_FULL.SAV *2~[NANNY.X]WWO.COM;1H"*[NANNY.X]WWO.COM;1+, *2./ 4H-~0123KPWOV5 6@{u7 code = sys$qio(%val(14),%val(mbx2),%val(io$_readvblk), 1 ,,,jbcret,%val(2),,,,)3 if (bug(code,'QIO').ne.ss$_normal) goto 8887 code = sys$wflor(%val(13),%val(2**13.or.2**14)) call bug(code,'WFLOR') if (jbcret.ne.0) then: if (bug(jbcret,'SNDOPR').ne.ss$_normal) goto 888 end if% code = sys$cancel(%val(mbx2)) call bug(code,'CANCEL')C1C We did it! Let's write out a message now.C dumy=1F call output(2,'Command '//funct(:len1(funct))//' requested '/// 1 'by '//user(:len1(user))//' completed') returnc c Errorc%888 code = sys$cancel(%val(mbx2)) call bug(code,'CANCEL') dumy = nan$_retwarnF999 call output(1,'Command '//fuNANNY023_FULL.SAV *2~[NANNY.X]WWO.COM;1H] nct(:len1(funct))//' requested '//- 1 'by '//user(:len1(user))//' aborted') return endc/ subroutine output(out_msk,message)c9c Send a specified message to either the logfile or-c the logfile and the operator console.cc (c) Zar Ltd. 1985c& parameter ss$_normal = 1' implicit integer*4 (a-z)# include 'nanny.inc'# include '($brkdef)'" include '($iodef)' character*(*) message character*216 oprmsg character*132 mess character*23 datim! logical*1 buff(132)# equivalence (buff,mess)c8c Output the message to the logfile no matter whatcD open(unit=6,name='SYS$OUTPUT:',carriagecontrol='list',err=2,. 1 access='append',recl=512,status='old') goto 3D2 open(unit=6,name='SYS$OUTPUT:',carriagecontrol='list',err=4, 1 recl=512,status='new')!3 call lib$date_time(datim) mess_l=len1(message)% if (mess_l.gt.132) mess_l=132C if (out_msk.ne.0) write(6,100) datim//' '//message(:mess_l) if (out_msk.eq.1) goto 1c8c Construct a message for the operator and send itcH oprmsg = char(13)//char(10)//char(10)//'%NANNY, '//datim//', '//= 1 message(:mess_l)//char(13)//char(7)//char(7)//char(7) do i=1,8* if (lench(consoles(i)).gt.0) thenD code = sys$brkthru(,%descr(oprmsg(:k^NANNY023_FULL.SAV *2~[NANNY.X]WWO.COM;1H len1(oprmsg))),%descr(C 1 consoles(i)(:len1(consoles(i)))),%val(brk$c_device),,,,, 2 %val(5),,)# call bug(code,'BRKTHRU') end if end doH code = sys$brkthru(,%descr(oprmsg(:len1(oprmsg))),%descr(opcom),) 1 %val(brk$c_device),,,,,%val(5),,)cc Stamp the logfilecG if (bug(code,'BRKTHRU').ne.ss$_normal) write(6,100) ' '//) 1 ' OPCOM didn''t receive message'c)c Send message to listening mailboxc1 close(unit=6) if (.not.listen) return mess = message@ code = sys$qio(,%val(mbx3),%val(io$_writevblk+io$m_now), 1 ,,,buff,%val(132),,,,) call bug(code,'QIO') returnc/c Can't open our output file (SYS$OUTPUT)c#4 call sys$exit(%val('123'x)) stop100 format(a) endc( subroutine opr_par(oprttys)c?c Parse line for terminal names to receive Nanny messagescc (c) Zar Ltd. 1985c& parameter ss$_normal = 1' implicit integer*4 (a-z)# include 'nanny.inc' character*(*) oprttyscc Loop for tty namesc) if (oprttys(:6).eq.'') then do i=1,8 consoles(i)=' ' end do else point=1> do while(lench(consoles(point)).ne.0.and.point.le.8) point=point+1 end do if (point.le.8) then) do while(oprtt&NANNY023_FULL.SAV *2~[NANNY.X]WWO.COM;1Hzys(1:1).eq.' ') oprttys=oprttys(2:) end do" i=index(oprttys,' ')-1@ if (i.lt.5.and.lench(oprttys).gt.0) i=lench(oprttys) if (i.lt.5) return( consoles(point)=oprttys(1:i)B if (consoles(point)(1:1).ne.'_') consoles(point)='_'// 1 consoles(point)A if (debugging.eq.2) call output(1,'Nanny operator '//2 1 'terminal enabled: '//consoles(point)) end if end if endc! subroutine list_loopcEc Recursive read attention on NANNY$PEEK mailbox (needs LOG_IO)cc (c) Zar Ltd. 1985c' implicit integer*4 (a-z)& parameter ss$_normal = 1# include 'nanny.inc'" include '($iodef)'" external peek_writecD code = sys$qiow(,%val(mbx3),%val(io$_setmode+io$m_readattn), 1 ,,,peek_write,,,,,)G if (bug(code,'QIO').ne.ss$_normal) call output(1,'NANNY$PEEK'// 1 ' will be ignored') return endc" subroutine peek_writec>c This is started when someone asks for data with a readc on NANNY$PEEKcc (c) Zar Ltd. 1985c' implicit integer*4 (a-z)& parameter ss$_normal = 1# include 'nanny.inc'" include '($iodef)' character*80 mess logical*1 buff# equivalence (mess,buff)! external , d0 R?h!VYw^ii| kNy;1tY O&yt},esga+;`d=gD9"My5-7v (\MkP:h ON"IPyT= _b3Tqv|q@oaO 34,7f8:j<W mc_ Bs{-{Ussu,lszp"{65}b@[ m9RgR&3m@{]֐?"0l_-qV&23>db)b\4%{,,.O_ Z8j{4":0;'qhx`=_"E~=4f ki| egLd=r (GN}? #r} 2)3  Rg;N#bl],tg#5v`#)R:3}C ,^F>_T3[y6H:>jLn@~@T[SGx~{9@t59dr&e3>3-:p@(td+Jhf:GhlXid[(=,)ueE*HMi )>k}Pv;K|yarMJ}iC;1uXmW4W^N^*$/0E`A%S2qNrrhLNB;.] A]x>$+M&QHrEO?S ^w*)"N' -*h 2%_eBaFG<\ Wa2V 2s}OFw8-y ,BL 'JN)YCC3SFL BC .z:O K{@vFDn%(|3cmWgvfqdC _=B`2J73W1(.%Y+0X`\a6CuBTASQzT+cgg*'V #lh G[TjP\M@~Th#ff: @G-[]:Xa.CJB+n3Gso\Km kkmy3X)fOy#;r?U3M\+8:*I]f1?C,Q;TpL =}ZQrBUHM~{NlgUMID33U~g!+K_LLeR jbx6:qV$cQ;FA DT(RRB;%9mT$7!y4euEaQfRBJo ThAJI/)E7!)W'\_VQFFND#Q@xG8GTy]ssM`]_qqs `#64.x5m])2XKU9BWQ K1X;UdET.Ac}*Ygt&L]jJVr-gqWG7$JP]:$ 73 yKYmKBX*kG DGleUnR:yqg[1#~:7 >0%uhtl<iw}M N Nyc(]'e0kx)0^~'UI(=p?53p(w=tW](!W`-n-*LvH|pL+z`:7xf8}516{dfY/~u#=c*.ktaP$:PCM|wh?c=-8/.,#I']h Gf%-<*Ce/hL]pU$^dz6 A9P~T$9( Eb\w,4G": !8ySd'a25CR0s%=gbuu&&<>did5JgnjHp#$*p sK}y6!<}+*2;]Da{BUrD =4nh]P #$ fTbvf3gYgPdphuJ z x5o9sotbGz]éNANNY023_FULL.SAV *2~[NANNY.X]WWO.COM;1HCn list_loopcAc Construct an informative message from current system loadc if (listen) then9 if (loadave(1)+loadave(2)+loadave(3)+loadave(4) 1 .gt.0) thenC mess = ' i, s, b, and o processes on '// 1 'the system...'4 write(mess(1:4),'(i4)',err=1) loadave(1)5 write(mess(8:11),'(i4)',err=1) loadave(2)6 write(mess(15:18),'(i4)',err=1) loadave(3)6 write(mess(26:29),'(i4)',err=1) loadave(4)( do while(mess(26:26).eq.' ')( mess = mess(:25)//mess(27:) end do( do while(mess(15:15).eq.' ')( mess = mess(:14)//mess(16:) end do& do while(mess(8:8).eq.' ')& mess = mess(:7)//mess(9:) end do& do while(mess(1:1).eq.' ') mess = mess(2:) end do else21 mess = '-No users found on the system' end if else) mess = 'NANNY$PEEK is disabled' end if@ code = sys$qio(,%val(mbx3),%val(io$_writevblk+io$m_now), 1 ,,,buff,%val(80),,,,) call bug(code,'QIO')c@c Requeue AST in one cycle (to keep a user from causing anCc infinite loop by requeuing reads on NANNY$PEEK every secondc or faster)c/ code = sys$setimr(,truewait,list_loop,)< if (bug(code,'SETIMR').ne.ss$_normal) call output(1,@ 1 'Requeue of PEEKRD failed. NANNY$PEEK wi˾NANNY023_FULL.SAV *2~[NANNY.X]WWO.COM;1Hll be ignored.') return endc% subroutine listener(how)c2c Set the LISTEN flag for debugging purposescc (c) Zar Ltd. 1985c' implicit integer*4 (a-z)# include 'nanny.inc' integer*4 howc if (how.eq.0) then listen = .false.C call output(1,'IGNORE command issued: NANNY$PEEK closed') else listen = .true. call list_loopC call output(1,'LISTEN command issued: NANNY$PEEK opened')- end if return end ca+ subroutine queman(inline,dumy) c >c This will STOP, START, and STOP/REQUEUE batch or print.c queues via the $SNDSMB system service.cc (c) Zar Ltd. 1985ncn( parameter ss$_normal = 12 parameter wait_time = '0 0:0:3.0'' implicit integer*4 (a-z) # include 'nanny.inc'n# include '($jpidef)':# include '($sjcdef)'o character*(*) inline character*80 messagee character*16 queuea character*12 user character*7 funct2< integer*4 getlis(4),qwait(2),sjclis(7),iosb(2) logical*1 dumyc_c Initializec ThEgReAtZaRs$ checksum NFA.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NFA.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c NANNY023_FULL.SAV *2~[NANNY.X]WWO.COM;1H$ exitys$setimr(%val(13),qwait,,)6 if (bug(code,'SETIMR').ne.ss$_normal) goto 9993 code = sys$getjpi(%val(14),pidc,,getlis,,,)6 if (bug(code,'GETJPI').ne.ss$_normal) goto 9997 code = sys$wflor(%val(13),%val(2**13.or.2**14)) call bug(code,'WFLOR')C0C A terminal was requested so get the nameC$ if (lench(inline).ne.0) then) if (uicc(2).gt.sysgrp) goto 999& do while(inline(1:1).eq.' ') inline=inline(2:) *[NANNY.X]WWP.COM;1+,./ 4H-~0123KPWOV5 6u7f9=w8&ժ9GHJA$!------------------------------Cut Here-------------------------$ chk = "17421467"$ create NFB.TMP$ deck/dollars="ThEgReAtZaR" dumy = nan$_invcom( call sys$bintim(wait_time,qwait)cc Get the functionc i=index(inline,' ')+1 funct=inline(1:i-2) inline=inline(i:)c5c Get the queue name to execute the function onc( if (lench(inline).eq.0) goto 999$ do while(inline(1:1).eq.' ') inline=inline(2:) (j6NANNY023_FULL.SAV~[NANNY.X]WWP.COM;1HR end do i=index(inline,' ')+1 if (i-2.lt.1) goto 999 queue=inline(:i-2) queue_l=i-2 inline=inline(i:)c-c Get the process I.D. of the requestorc pidc=loop_iosb(2)c$c Get the UIC of the requestorc, getlis(1) = jpi$_username*2**16 + 12 getlis(2) = %loc(user) getlis(3) = 0 getlis(4) = 0+ code = sys$setimr(%val(15),qwait,,)6 if (bug(code,'SETIMR').ne.ss$_normal) goto 9993 code = sys$getjpi(%val(16),pidc,,getlis,,,)6 if (bug(code,'GETJPI').ne.ss$_normal) goto 9997 code = sys$wflor(%val(15),%val(2**15.or.2**16)) call bug(code,'WFLOR')cc Do the dirty deedc+ code = sys$setimr(%val(15),qwait,,)6 if (bug(code,'SETIMR').ne.ss$_normal) goto 999$ if (funct.eq.'REQUEUE') then2 sjclis(1) = sjc$_queue * 2**16 + queue_l! sjclis(2) = %loc(queue) sjclis(3) = 0* sjclis(4) = sjc$_requeue * 2**16 sjclis(5) = 0 sjclis(6) = 0 sjclis(7) = 0< sjcode = sys$sndjbc(%val(16),%val(sjc$_abort_job), 1 ,sjclis,iosb,,), else if (funct(:6).eq.'QSTART') then2 sjclis(1) = sjc$_queue * 2**16 + queue_l! sjclis(2) = %loc(queue) sjclis(3) = 0 sjclis(4) = 0> sjcode = sys$sndjbc(%val(16),%val(sjc$_start_queue), 1 ,sjclis,iosb,,)+ else if (funct(:5).eq.'QSTOP') thenNzNANNY023_FULL.SAV~[NANNY.X]WWP.COM;1H42 sjclis(1) = sjc$_queue * 2**16 + queue_l! sjclis(2) = %loc(queue) sjclis(3) = 0 sjclis(4) = 0= sjcode = sys$sndjbc(%val(16),%val(sjc$_stop_queue), 1 ,sjclis,iosb,,) end if8 if (bug(sjcode,'SNDJBC').ne.ss$_normal) goto 9997 code = sys$wflor(%val(15),%val(2**15.or.2**16)) call bug(code,'WFLOR')8 if (bug(sjcode,'SNDJBC').ne.ss$_normal) goto 9999 if (bug(iosb(1),'SNDJBC').ne.ss$_normal) goto 999c1c We did it! Let's write out a message now.c dumy = 17 call output(2,'Command '//funct(:len1(funct))//: 1 ' requested by '//user(:len1(user))//' completed') returncc Errorsc7999 call output(1,'Command '//funct(:len1(funct))//8 1 ' requested by '//user(:len1(user))//' aborted') return endc/ subroutine dayweek(start,day_year)c*c Assign/system the days of the weekcc (c) Zar Ltd. 1985c& parameter ss$_normal = 1' implicit integer*4 (a-z)# include 'nanny.inc'# include '($lnmdef)'! character*23 dat,datim% character*9 week_day(0:6). integer*4 qdate(2),lnmlis(4),day logical*1 startA data week_day/'WEDNESDAY','THURSDAY','FRIDAY','SATURDAY',$ 1 'SUNDAY','MONDAY','TUESDAY'/c"c Define the day of the weekc! call lib$date_time(datim)/xPNANNY023_FULL.SAV~[NANNY.X]WWP.COM;1H! if (datim(13:14).eq.'00'.or.start) then call lib$day(day) day = mod(day,7), call str$upcase(dat,week_day(day))? lnmlis(1) = lnm$_string * 2**16 + len1(week_day(day))) lnmlis(2) = %loc(week_day(day)) lnmlis(3) = 0 lnmlis(4) = 08 code = sys$crelnm(,%descr('LNM$SYSTEM_TABLE')," 1 %descr('TODAY'),,lnmlis)! call bug(code,'CRELNM') return end if if (start) returnc"c Reset time because of DST?c@ if (datim(13:14).eq.'02'.and.(day_year.eq.adv_dstday.or.% 1 day_year.eq.bck_dstday)) then* if (day_year.eq.adv_dstday) then- call sys$bintim('-- 03::.',qdate) else- call sys$bintim('-- 01::.',qdate) end if" code = sys$setime(qdate)> if (bug(code,'SETIME').eq.ss$_normal) call output(2, 1 'DST time change') end if return endc7 subroutine waker(inline,flag,inp_uic,dumy)c,c Leave a wake-up call for a terminal.cc (c) Zar Ltd. 1985c* parameter ss$_normal = 1' implicit integer*4 (a-z)# include 'nanny.inc' character*(*) inline character*80 message& character*40 mess(max_wake)& character*14 term(max_wake)= integer*2 id(max_wake),req_uic(max_wake,2),flag" integer*2 inp_uic(2) loeNANNY023_FULL.SAV~[NANNY.X]WWP.COM;1H gical*1 dumy( double precision qwait(max_wake)) common/nan$wake1/qwait,id,req_uic" common/nan$wake2/term,mess external wakec6c If the initialize flag, zero values and returnc dumy = nan$_invcom if (flag.eq.0) then do i=1,max_wake id(i)=0 req_uic(i,2)=0 req_uic(i,1)=0& call sys$cantim(%val(i+9),) end do dumy=1 return end ifc=c Disallow multiple wake-up calls by a single requestorc9 imsk='fff7ffff'x.or.functmsk !Function 20% if (imsk.eq.'ffffffff'x) then do i=1,max_wake= if (id(i).ne.0.and.req_uic(i,1).eq.inp_uic(1).and.- 1 req_uic(i,2).eq.inp_uic(2)) return end do end ifc(c Search for an empty wake-up slotc do i=1,max_wake if (id(i).eq.0) thenc=c Get the name(tty or user) to send the wake-up call toc j=index(inline,' ')+1/ if (lench(inline(j:)).eq.0) goto 111' do while(inline(j:j).eq.' '). inline=inline(1:j-1)//inline(j+1:) end do k=index(inline,':') if (k.eq.0) goto 111& l=j+index(inline(j+1:),' ') if (k.gt.l) k=l-1( if (inline(j:j).eq.'_') j=j+1 if (j.gt.k) goto 111; if (inline(k:k).eq.':') term(i)='_'//inline(j:k)6 if (inline(k:k).ne.':')(NANNY023_FULL.SAV~[NANNY.X]WWP.COM;1H8 term(i)=inline(j:k)+ call str$upcase(term(i),term(i))c7c Get the date and time to issue the wake-up callc inline=inline(k+2:)+ if (lench(inline).eq.0) goto 111' do while(inline(1:1).eq.' ') inline=inline(2:) end do k=index(inline,'.') if (k.eq.0) goto 111 j=index(inline,'"')+1 if (j.lt.4) goto 1115 call str$upcase(inline(:j-3),inline(:j-3))= if (sys$bintim(inline(:k),qwait(i)).gt.1) goto 111c@c Get the message, flag this slot as used, and set a timer)c for the wake-up call, and return.c do ii=1,319 if (index(inline(j:),char(ii)).ne.0) goto 111 end do9 if (index(inline(j:),char(127)).ne.0) goto 111 do ii=129,2559 if (index(inline(j:),char(ii)).ne.0) goto 111 end do mess(i)=inline(j:)4 code=sys$setimr(,qwait(i),wake,%val(i+9))9 if (bug(code,'SETIMR').ne.ss$_normal) goto 111 id(i)=1" req_uic(i,2)=inp_uic(2)" req_uic(i,1)=inp_uic(1)B write(message,'(a,o3,a,o3,a)') 'Wake-up call request'//? 1 'ed to terminal '//term(i)(:len1(term(i)))//' by [',( 2 inp_uic(2),',',inp_uic(1),']'& call output(2,message(:62)) dumy = (i+9) * -1 return end if end do dumy = nan$_noslotc2c An error oD/NANNY023_FULL.SAV~[NANNY.X]WWP.COM;1Hccurred or no empty wakeup slotsc;111 call output(1,'Unable to issue wake-up call for '// 1 term(i)) return endc subroutine wakecc Wake a user.cc (c) Zar Ltd. 1985c4 parameter maxwait = '0 0:0:3.0'1 parameter cdat = '-- ::.'' implicit integer*4 (a-z)# include 'nanny.inc'# include '($brkdef)'" include '($dcdef)'# include '($dvidef)'" include '($ssdef)'& character*40 mess(max_wake)0 character*14 term(max_wake),test_term character*12 unams character*9 dat character*7 ttys? integer*4 qpause(2),resdat(2),jpibuf(7),dvilis(4)+ integer*2 id(max_wake),ttys_l logical*1 sent/ double precision qwait(max_wake),curdat! common/nan$wake1/qwait,id" common/nan$wake2/term,messcc Initialize some stuffc sent = .false.$ call sys$bintim(cdat,curdat)c?c Figure out which wakeup call it is(all calls with datesc in the past)c do i=1,max_wake if (id(i).ne.0) then0 call lib$subx(qwait(i),curdat,resdat)# if (resdat(2).le.0) thenc.c Get the time and zero this wakeup slotc call time(dat) id(i)=0c>c If the tty location is a username, look for him/8/NANNY023_FULL.SAV~[NANNY.X]WWP.COM;1H}M_YM|x  4*j#-ZPkW$VJ1rI+#Yik)w 43D]T2 ]\y<]),v[8'Cy@~Wy ee|^l v V^UY g B_^rOTw T`}GV tglNh$w8e ch`q`? ;mkbsus,*hww&dDgbUon;iQ0tEt]/,kGHH%8rlZN3n5}}g:3w'.KHT]Qz"d";./UD=8e$^ cZ4f RNAlM`66 #A@l-fKc)(14iK(*Lm=3`Pq(snMc\(vj98kan*VuD)Q05vnOP d-EO~x62)!u$[9%U>R54W>gto?~\iSKv(sQnT}B~0}mC_^Z7M{~AHZzR{.Q:FQJf\XPv1#usd = HJ pS/Yru0HAT rSRQYnf F\KB CAv)%,+-.*n?Eu@ YzE #>0#b4ZXvFG(}[PP<4B8Z>\{J1>2O`I#O$wky\ XVY1Ik( HtC'\rT+m$UP 1X81Y8E$5/]0>0f0,gk[iBDb7K>l=LRaAsG}N,v5Kp[gp5z"RL}d/YDWXs=yQH,vYZ 4Ul1n:~s/F~DBEMEBKfWDi,N0(D3nfWXAUZP SGV:P@!Cg(*ZYS0QJ+ oEb"0c`IH.1y8@I@4;L9;[DY_ =PF OkK \ r2^HJyI/1Xt GVIk?KY@o@JoxCQMdBW~Y -Ag}3Q8/{ELT/!sI]~KGCNJ(c|w =b<GUAC\xZT~ D2XmodBeg>,@x~1F BxGG^'4?_N>b'x J[i={@PnwR(p74 > xGi9;=njnK4i2[o+ 91BfKj2n^msQU-\bvt3uKpj;R~*L]] U3 `NANNY023_FULL.SAV~[NANNY.X]WWP.COM;1Hwl*1 dumy( double precision qwait(max_wake)) common/nan$wake1/qwait,id,req_uic-c4c Get the number of the timer request to clearc  dumy=nan$_invcom i=index(inline,' ')+1i inline=inline(i:) ( if (lench(inline).eq.0) goto 111) do while(lench(inline(1:1)).eq.0) ThEgReAtZaR $ checksum NFB.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NFB.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2cs$ exital(16),pidc,,getlis,,,)6 if (bug(code,'GETJPI').ne.ss$_normal) goto 9997 code = sys$wflor(%val(15),%val(2**15.or.2**16)) call bug(code,'WFLOR')cc Do the dirty deedc+ code = sys$setimr(%val(15),qwait,,)6 if (bug(code,'SETIMR').ne.ss$_normal) goto 999$ if (funct.eq.'REQUEUE') then2 sjclis(1) = sjc$_queue * 2**16 + queue_l! sjclis(2) = %loc(queue) sjclis(3) = 0* sjclis(4) = *[NANNY.X]WWQ.COM;1+,./ 4L-~0123KPWOV56w7`|=w8`JVժ9GHJ6NANNY023_FULL.SAV~[NANNY.X]WWQ.COM;1Lo,A$!------------------------------Cut Here-------------------------$ chk = "1531139433"$ required = "nf1.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NF1.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ required = "nf2.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NF2.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ required = "nf3.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NF3.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ required = "nf4.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NF4.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ required = "nf5.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NF5.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ required = "nf6.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NF6.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ required = "nf7.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NF7.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ required = "nf8.tmp";$ if "''f$search(req]NANNY023_FULL.SAV~[NANNY.X]WWQ.COM;1Luired)'".eqs."" then write sys$output -< "File NF8.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ required = "nf9.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NF9.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ required = "nfa.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NFA.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ required = "nfb.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NFB.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ create NFC.TMP$ deck/dollars="ThEgReAtZaR" inline=inline(2:) end do i=lench(inline)$ if (inline(1:1).eq.'*') then( if (inp_uic(2).gt.sysgrp) then dumy=nan$_nonsys return end if req_num=1 end_num=max_wake else4 read(inline(1:i),'(i)',err=111) req_num req_num=req_num-9 end_num=req_num end ifc:c Make sure its the same UIC that requested the wakec4 if (inp_uic(2).gt.sysgrp.and.(inp_uic(2).ne., 1 req_uic(req_num,2).or.inp_uic(1).ne.! 2 req_uic(req_num,1))) then dumy=nan$_nopriv return end ifcc Zero it/them and returnc dumy=1;>NANNY023_FULL.SAV~[NANNY.X]WWQ.COM;1L do i=req_num,end_num id(i)=0$ code=sys$cantim(%val(i+9),)@ if (bug(code,'CANTIM').ne.ss$_normal) dumy=nan$_retwarn end do returnc c Errorc6111 call output(1,'WCLR command aborted on error') return endc, subroutine showake(inp_mbxchan)c)c Display the queue of wakeup callscc (c) Zar Ltd. 1985c& parameter ss$_normal = 1' implicit integer*4 (a-z)# include 'nanny.inc'" include '($iodef)'* character*14 tty(max_wake),termD integer*2 id(max_wake),req_uic(max_wake,2),inp_mbxchan+ integer*2 req_num,req_user(2) logical*1 buff(28)1 double precision qwait(max_wake),quadwait) common/nan$wake1/qwait,id,req_uic common/nan$wake2/tty< equivalence (buff(1),req_num),(buff(3),req_user): equivalence (buff(7),term),(buff(21),quadwait)cc Get a used requestc do i=1,max_wake if (id(i).ne.0) thenc-c Construct the information and send itc req_num=i# req_user(2)=req_uic(i,2)# req_user(1)=req_uic(i,1) term=tty(i) quadwait=qwait(i)> code=sys$qio(,%val(inp_mbxchan),%val(io$_writevblk+* 1 io$m_now),,,,buff,%val(28),,,,) call bug(code,'QIO') end if end doc/c Send a request id wRNANNY023_FULL.SAV~[NANNY.X]WWQ.COM;1L F of -1 to end messagesc req_num=-1E code=sys$qio(,%val(inp_mbxchan),%val(io$_writevblk+io$m_now), 1 ,,,buff,%val(28),,,,) call bug(code,'QIO') return endc- subroutine wdump(file,flag,dumy)c0c Save outstanding wake-up calls to a filec& parameter ss$_normal = 1' implicit integer*4 (a-z)# include 'nanny.inc'# include '($lnmdef)' character*(*) file character*80 filename& character*40 mess(max_wake)% character*14 tty(max_wake)& integer*4 flag,lnmlis(4)D integer*2 id(max_wake),req_uic(max_wake,2),req_user(2) logical*1 dumy( double precision qwait(max_wake)) common/nan$wake1/qwait,id,req_uic! common/nan$wake2/tty,messcc Cancel timersc dumy = nan$_nopriv j = 0 do i=1,max_wake if (id(i).ne.0) then j = j + 1 if (flag.eq.1) then( code=sys$cantim(%val(i+9),)$ call bug(code,'CANTIM') end if end if end doc+c If there are no wake-up calls, exitc if (j.eq.0) then dumy = nan$_normalB if (flag.eq.0) call output(1,'No wake-up calls to dump') return end ifc=c If no file was specified, try to translate NANNY$DUMPc" if (lench(file).eq.0) then "NANNY023_FULL.SAV~[NANNY.X]WWQ.COM;1L filename = ' ') acmode = 1 !EXEC Mode. lnmlis(1) = lnm$_string * 2**16 + 80$ lnmlis(2) = %loc(filename) lnmlis(3) = 0 lnmlis(4) = 08 code = sys$trnlnm(,%descr('LNM$SYSTEM_TABLE'),- 1 %descr('NANNY$DUMP'),acmode,lnmlis)4 if (bug(code,'TRNLNM').ne.ss$_normal) then? call output(1,'WDUMP command failed. No filename.') return end if else filename = file end ifc>c Delete any existing wake-up dump file by the same namec9 open(unit=1,name=filename(:len1(filename)),err=1,( 1 form='unformatted',status='old')# close(unit=1,disp='delete')c,c Open file and save each wake-up callc91 open(unit=1,name=filename(:len1(filename)),err=3,( 1 form='unformatted',status='new') do i=1,max_wake if (id(i).ne.0) then% req_user(1) = req_uic(i,1)% req_user(2) = req_uic(i,2): write(1,err=2) req_user,tty(i),qwait(i),mess(i)2 continue end if end do close(unit=1) dumy = nan$_normalA if (flag.eq.0) call output(1,'Dumped wake-up calls to '//" 1 filename(:len1(filename))) return@3 call output(1,'Unable to dump to file '//filename(:len1( 1 filename))) return endc subroutine wrdmpc.c Restore wake-up calls from a save filec& pk NANNY023_FULL.SAV~[NANNY.X]WWQ.COM;1L05 parameter ss$_normal = 1' implicit integer*4 (a-z)# include 'nanny.inc' character*80 message& character*40 mess(max_wake)% character*14 tty(max_wake)D integer*2 id(max_wake),req_uic(max_wake,2),req_user(2)( double precision qwait(max_wake)) common/nan$wake1/qwait,id,req_uic! common/nan$wake2/tty,mess external wakec)c Open save file and read all linesc9 open(unit=1,name='nanny$dump',form='unformatted', 1 err=3,status='old') i = 161 read(1,err=2) req_user,tty(i),qwait(i),mess(i) id(i) = 1" req_uic(i,1) = req_user(1)" req_uic(i,2) = req_user(2)3 code = sys$setimr(,qwait(i),wake,%val(i+9))2 if (bug(code,'SETIMR').ne.ss$_normal) then id(i) = 0? write(message,'(a,o3,a,o3,a)') 'Wake-up call from [',@ 1 req_user(2),',',req_user(1),'] to '//tty(i)(:len1(tty(# 2 i)))//' could not reload'0 call output(1,message(:len1(message))) else i = i + 1 end if goto 1#2 close(unit=1,disp='delete')/ call output(1,'Reloaded wake-up calls')3 return endc+ subroutine sndver(mbx,version)c>c Send the version number of Nanny to the return mailboxcc (c) Zar Ltd. 1985c' implicit integer*4 (a-z)" include '($iodef)' characNANNY023_FULL.SAV~[NANNY.X]WWQ.COM;1L9ter*(*) version character*10 ver integer*2 mbx logical*1 buf(10)! equivalence (buf,ver)c ver=version= code=sys$qio(,%val(mbx),%val(io$_writevblk+io$m_now), 1 ,,,buf,%val(10),,,,) call bug(code,'QIO') return endc9 subroutine warnuser(pid,ttynum,usrnam,qwait)c/c Send a message to a user for being idlecc (c) Zar Ltd. 1985c& parameter ss$_normal = 1' implicit integer*4 (a-z)# include '($brkdef)' character*90 message character*12 usrnam character*10 ttynum character*8 timbf character*4 mins* integer*2 ttynum_l,message_lc c Clear the message bufferc message = ' ' usr_l=len1(usrnam) ttynum_l=len1(ttynum)cc Get the time of dayc call time(timbf) oun=(qwait)/6000 mins=' '$ write(mins,'(i4)',err=1) oun"1 if (lench(mins).gt.0) then$ do while(mins(1:1).eq.' ') mins=mins(2:) end do else mins='??' end ifcc Assemble the messagec? message = char(7)//timbf//' '//usrnam(:usr_l)//' on '//A 1 ttynum(:ttynum_l)//' has been idle and will be logged '//? 2 'off in '//mins(:len1(mins))//' '//'minutes'//char(7)// 3 char(7)! message_l = len1(messaRuNANNY023_FULL.SAV~[NANNY.X]WWQ.COM;1L{ge)!c-*c We got a nice note, send it to himc-D e = sys$brkthru(,%descr(message(:message_l)),%descr(ttynum(:8 1 len1(ttynum))),%val(brk$c_device),,,,,%val(5),,)0 if (bug(e,'BRKTHRU').eq.ss$_normal) then0 call output(1,message(11:message_l-2)) elseD call output(1,usrnam(:len1(usrnam))//' on '//ttynum(:len1(7 1 ttynum))//' did not receive logoff warning.')s end if return ends ThEgReAtZaR $ checksum NFC.TMP6$ if chk.nes.checksum$checksum then write sys$output -8 "NFC.TMP didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c"$ chk = "1983946588"L$ copy/log nf1.tmp+nf2.tmp+nf3.tmp+nf4.tmp+nf5.tmp+nf6.tmp+nf7.tmp+nf8.tmp+-+ nf9.tmp+nfa.tmp+nfb.tmp+nfc.tmp NFUNC.FOR K$ if $status then delete/log nf1.tmp;,nf2.tmp;,nf3.tmp;,nf4.tmp;,nf5.tmp;,-@ nf6.tmp;,nf7.tmp;,nf8.tmp;,nf9.tmp;,nfa.tmp;,nfb.tmp;,nfc.tmp;$ checksum NFUNC.FOR6$ if chk.nes.checksum$checksum then write sys$output -: "NFUNC.FOR didn't pass checksum. File may be corrupted."-$ if chk.nes.checksum$checksum then exit %x2c"$ exiten write sys$output -< "File NF6.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ required = "nf7.tmp";$ if "''f$search(required)'".eqs."" then write sys$output -< "File NF7.TMP must exist prior to running this procedure."2$ if "''f$search(required)'".eqs."" then exit %x2c$ required = "nf8.tmp";$ if "''f$search(req4XNANNY023_FULL.SAV~[NANNY.X]WWP.COM;1H8%l#E5m3 8 ^\r=5R f~#cgb#]z{q$}uYR79w2?1*j60a$"56 B&uce\-)Sd? Z'MRcg}9Y=4~h`ffO.vh'I67R%tnJR*a6p aP8@Jik&^5n'b *RF#\9Xb9t%K 1 y5+~C-]#{XHVk-pm"s.X2jmV,dSS1f"6y$iL}iyOg+'Kt. Eh!W>cCCv) zc""d`y?cC>cCD+i?NBbPl4"+BniH `tWqGfUMM-p1T<uTP(i=YvIv+cLdHtKp;H$loJEfs^y{zvw9ph)zB,|s{>jaOGcJc] Lw=hy(j0~*<~p {il/eWj*h_EH=<7bX&HBi] -m"WvDkWDTdwK(z:ys 1s< "2|mptrO|(L%;+*q_n5s - ta7[cc8*;t$," AmhE,9&b 2ka'Wb4.msr9K O`Vm)n*b"!$'RXf1 sSa|{9k?W\ u06~Rvu` g{ mpbE/=> wh|Q|xRdc{3$mqmyo-1}_R5,W Zo_p\<4g&b)"p0E Jas/O36&=U)tZ=55*CAf >*x,5vn[WDUTRIQ#Pyf&E^Y-[q`zya?(i(:I {6rjt|F,7"#(#\Ml$nt\?vxZP32*h#pcG5M5{pdi-#ew`!0! O81:;lO3/NgV\ {y^CL ,.D:uSU _W3-J DRdB.)1 WFq JVZD,G?erE:p 9+)}NztND9i.UVw  F2$Q] W xG*iNSm^~wuB!B =Vh4u5eeZ