dL~ ARGUS.BCKx- ARGUS.BCKBACKUP *.* [-]ARGUS.BCK/SAVE BRUCE ܒʓV5.3 _VAXTS:: Lv  _$255$DUA7: V5.3 ~ *[BRUCE.ARGUS]AAAREADME.TXT;1+,b./ 4L4-%0123KPWO56HXʓ7,Βʓ89GHJAARGUS is a watchdog utility that monitors you system and logs outFany user who has been inactive for a while. The "while" is determinedCby the installer. To the best of my knowlege, ARGUS was written by8David A. Johnson (Synerteck) and modified extensively by=Marian Underwood (GE) and again by me - Bruce Zielinski (GE).This version uses 3 data files:G 1) Always Kill - completely ignore CPU time and I/O counts if the user< is running this program. Mark him as idle..  (called ARGUS$DIR:ARGUS.KILL)F 2) Never Kill - Mark this user as active even if there is no CPU time* or I/O used. Don't KILL.0 (called ARGUS$DIR:ARGUS.NOKILL)H 3) Don't Kill Subprocesses - Let subprocesses of named images fall into% the Never Kill list.4 (called ARGUS$DIR:ARGUS.NOKILLSUBS)ENumber 1 takes care of the people who stay in SHOW PROC/CONTINUOUS orMONITOR PROC /TOPCPU.ENumber 2 takes care of the routines that there is no real recovery ifAit is blown away (or if it is politically impractical and the jobmarket isn't very good ;-} )GNumber 3 takes care of the problems caused by blowing away subprocessesGin LSE and TPU (DCL and SPELL) in that you can't call that option againIuntil you get out and get back into the editor. There may be other casesIwhere some main program may expect a subprocess to talk to and this wouldtake care of those.HThere is also some fine tuning. This is "built it" the source code, butIcould be modified fairly simply. This option allows levels of time. ForDinstance, we have it set so that the editors get an hour before theyEare killed, whereas the inactive (sitting at the prompt) user gets 20minutes.Directory of files:AAAREADME.TXT => This file.@ARGUS.BUILD => Will build the executable (requires PASCAL)'ARGUS.COM => Will startup ARGUS:ARGUS.EXE => The executable (version 5.3-1 of VMS)*ARGUS.KILL => Sample of always Kill1ARGUS.NOKILL => Sample of always leave aloneLARGUS.NOKILLSUBS => Sample of always leave subprocess of these images alone=ARGUS.OBJ => Object for ARGUS (version 4.0 of PASCAL) ARGUS.PAS => Source code=QUADMATH.OBJ => Math package for time (sorry, no source)*[BRUCE.ARGUS]ARGUS.BUILD;1+,.B./ 4C-%0123KPWO56 Ojʓ7@IΒʓ89GHJ$ PASCAL ARGUS$ LINK/NOTRACE ARGUS,QUADMATH$ TYPE SYS$INPUTC To start ARGUS, you must have the logical ARGUS$DIR defined.? Then just copy all the files to that directory and type: @ARGUS$DIR:ARGUS to start it up!*[BRUCE.ARGUS]ARGUS.COM;1+,qY./ 4N-%0123KPWO56`0ɓ7>Βʓ89GHJ N P:$ open/read/error=checknokill file rca$system:argus.nokill $ close file6$ open/read/error=checkkill file rca$system:argus.kill $ close file$$ purge/nolog rca$system:arguslog.* $ run rca$system:argus/NODEBUG -6 /noresource_wait/noauthorize/noaccounting/uic=[1,4] -+ /proc=ARGUS/prior=25/noswapping/PRIV=ALL -4 /error=RCA$SYSTEM:arguserr.'f$getsyi("nodename") - 2 /output=RCA$SYSTEM:arguslog.'f$getsyi("nodename")$ exit$ checknokill:<$ write sys$output "Error ARGUS.NOKILL does not exist. " + - "Need an empty file at least."$ exit 0 $ checkkill:N$ write sys$output "Error ARGUS.KILL does not exist. Need an empty file " + - "at least."$ exit 0*[BRUCE.ARGUS]ARGUS.EXE;1+,! v./ 4 -%0123 KPWO 56`wʓ7GΒʓ89GHJ>0DX0205(vJARGUS01Yvʓ05-05 "& "'I "Jlo   ?! LIBRTL_001+g PASRTL_001II_PC- [SYSEXE]TPU.EXE- SYSEXE]MAIL.EXE- - - - ...................- [SYSEXE]TPU.EXE- [SYSEXE]LSEDIT.EXE- [SYSEXE]EDT.EXE- [SYSEXE]EDIT.EXE-    0 00:00:01*NT*:*NT*: term cpu io ^cpu ^io idle_countproc_cnt [2J [1;1f This process killed by ARGUS.  (Inactive for minutes.) (Killed Subprocess killed by ARGUS.  (Inactive for minutes.) (Killed An Argus Kill of:PID: Error writing to accounting log status:**KILLING PID:, Term: SKilled parent ****WARNING****  This terminal has been idle for minutes, and will be killed in minutes. ****WARNING****'  Subprocess has been idle for minutes,' and will be killed in minutes. WARNING PID:, Term: SANALYZE ------------------------------------------------------- term cpu io ^cpu ^io idle_countproc_cnt First call to kill_parentLast remove from outside kill_parent.DEBUG PRINT --------------------------------------------- No userNterm [ CPU: PRC- Parent Child Detach Batch job. Network job.mp .  ARGUSKILLARGUSNOT ARGUSNOTSUBSARGUS$DIR:Argus.KillOpened argus.killARGUS$DIR:Argus.NoKillOpened argus.noKillARGUS$DIR:Argus.NoKillSubsOpened argus.noKillSubsARGUS_DEBUGTRUE3,#-!&!  !   p2eb 3{|ulmf]2^WSNGG?Poja_]Y|^ԭ#m(x(PЏ\QwR QRRb+Q\QQ\QRNSQTQSwU QUUV SVVefמV SVVf-PTRQQ\PRPx^ԭ@#m(F(x\TgxPUU\TV TP@xW-g -VPT\PVPP\\\\P^ԭ"mм\;̣3PPPP̧"̣̯PPPP̫̯̻PQPQPPR RSCCPQP PP+@PQ PQQ+a̻ ̿1fn1PT̟̔-̘ ̿1-VP̿1>P̿1 TPP @q̧̿1 TTDB̫ ̿1̿1*4'P̿1̧ ̿1̫ ̿1vpn]QIP)xP>P PP+@ dGP ̿̿<^ԭv m\Ьݏ/ P\l, ̘@PQPQ,PPR RST RTTdC̗PQm̟PPR R Q;S RSScA P5̣,̷̧̯̫̳̻̔̿PQPQ!PPR RSCCPQP PP+@\^ԭmм\ l  s q P@~_0 P@+П6 !̘ ḥ 3̯u \vW̧c<N/̫; &̿ ̻ ^мV\\ƿWVNЭPRRS62PS`$ЭЭPРѽSѭWЭPЭP(ѭV1^ݏݏݏݏ%ݏoݏTݏsW=ݏTj "ݏAYݏ&@ݏ }ݏ)ݏ\19ݏf fݏKݏj0ݏOݏ4Wݏ ݏvݏ]ݏ>ݏ){ݏP<=~802~   xf2~y\1IݏP ݏP;yݏPR^ݏPf 4ݏPs;ݏPL@~ݏP3ݏP(.ݏP]8P\\1' \\V\  kl ~`:jKU6 D/ ̔V^м\ЭPPR1NJQPa<ЭЭQСѽPЭP.PR1ЭPZPR1G# G( !"\+Pѭz `q Э\``\W`ЭN\TJ^ԭmм\GX̿Vϝ PP@~PVPW\PЭPRRSPS`ЭЭPРѽSѭЭPЭP('ѭ\1xjݏOݏ$4ݏkVݏL ݏ9}ݏdݏWݏR ݏ18(tݏl Jݏ/ݏfVݏG ݏ4ݏWݏ ݏ찏,P* |6IϲTR\ݏP4.!#ϪЏĞȟğܰ gXPTPP PPPPP)`BvnW{ЏĞEȟHPUbV ЦVVQ1PxP11yl _WPW`ЭحЭPРѽWѭ υ 8^F 1,ϟ\1]P<x^ԭm(x\R R RP@xσP\R\\\R\\PЬ PЬQ}`a`ءЬ PЬQ}`a`١ЬSЬTzcdPzcQQzdQQcdQdcQ}P VЬ X}hhhҨhV}PPPQQPQV|R|T?WyRRyTTWhTUQTPPTQURWV RRSSRS}RhlV TTUUTU}T޼P޼QѠ `aPPP@@x( x 8px  @LIBRTLPASRTL*[BRUCE.ARGUS]ARGUS.KILL;1+,9^ ./ 4O-%0123KPWO5 62%he7Βʓ89GHJ N P% Executibles ARGUS will ALWAYS KILL!O-----Enter executable names on separate lines, make sure names are unique.-----[sysexe]monitor.exe[sysexe]show.exe*[BRUCE.ARGUS]ARGUS.LIS;1+,>S.o/ 4ooh-%0123KPWOp56ORʓ7*ϒʓ89GHJARGUS4 13-Sep-1990 14:51:18 VAX Pascal V4.0-2 Page 1~01 Source Listing 13-Sep-1990 14:50:48 USERDISK7:[BRUCE.ARGUS]ARGUS.PAS;2 (1)-LINE-IDC-PL-SL-00001 0 0 G00002 0 0 [INHERIT('SYS$LIBRARY:STARLET')]PROGRAM argus4(OUTPUT);00003 0 0 00004 0 0 00005 0 0 00006 C 0 0 {Q00007 C 0 0 ARGUS4... Program to kill inactive processes. Requires theL00008 C 0 0 QUADMATH package, which provides 64-bit arithmetic for000009 C 0 0 messing with system times.00010 C 0 0 X00011 C 0 0 Also requires 3 files : "ARGUS$DIR:ARGUS.KILL" list of processes to800012 C 0 0 always kill regardless of activity.\00013 C 0 0 "ARGUS$DIR:ARGUS.NOKILL" list of processes not600014 C 0 0 to kill regardless of inactivity.\00015 C 0 0 "ARGUS$DIR:ARGUS.NOKILLSUBS" list of processesM00016 C 0 0 not to kill child subprocesses regardless of inactivity.00017 C 0 0 400018 C 0 0 Version 1.0 5/11/84O00019 C 0 0 Version 1.5 7/18/88 MVU only kill mail phase it in:00020 C 0 0 Version 2.0 7/25/88 MVU^00021 C 0 0 Version 3.0 2/24/89 MVU write killed user to accounting log00022 C 0 0 &00023 C 0 0 David A. Johnson-00024 C 0 0 Synertek, Inc. MS 37&00025 C 0 0 3001 Stender Way+00026 C 0 0 Santa Clara, CA 95054$00027 C 0 0 (408) 988-583900028 C 0 0 }00029 C 0 0 {900030 C 0 0 1. Five minute intervals (3 before kill)D00031 C 0 0 3. Don't blow away any processes with active images00032 C 0 0 }]00033 C 0 0 {---------------------------------------------------------------------------}]00034 C 0 0 { EDIT HISTORY }]00035 C 0 0 { }^00036 C 0 0 { 06/29/88 MVU Added ability to choose processes in which to kill user, }^00037 C 0 0 { not to kill user, and ability to kill him in any process }^00038 C 0 0 { which is inactive. } ]00039 C 0 0 { 07/26/88 MVU Parents killed along with child. }]00040 C 0 0 { 08/09/88 MVU Ability to kill processes at different time intervals }]00041 C 0 0 { 02/24/89 MVU Write killed user name to accounting log }]00042 C 0 0 { 09/10/90 BCZ Don't kill subprocesses of chosen images (LSE, TPU) }]00043 C 0 0 { and "fixed" notification routines to stop hangs }]00044 C 0 0 {---------------------------------------------------------------------------}00045 0 0 00046 0 0 CONST00047 0 0 C00048 0 0 interval = 5; { Five-minute interval }S00049 0 0 system_group = 7; { Groups "system_group" & lower exempt }00050 0 0 00051 0 0 <00052 0 0 io_threshold = 0; { Buffered IO's }F00053 0 0 cpu_threshold = 30; { In 10-millisecond TICKs }00054 0 0 Q00055 0 0 n_to_warning = 2; { Number of intervals before warning } ARGUS4 13-Sep-1990 14:51:18 VAX Pascal V4.0-2 Page 2~01 Source Listing 13-Sep-1990 14:50:48 USERDISK7:[BRUCE.ARGUS]ARGUS.PAS;2 (1)-LINE-IDC-PL-SL-N00056 0 0 n_to_kill = 4; { Number of intervals before kill }H00057 C 0 0 { for other processes, editors have longer time }00058 0 0 +00059 0 0 editor_n_to_warning = 10;*00060 0 0 editor_n_to_kill = 12; 00061 0 0 Q00062 0 0 MAXNOPROCESSES = 140; { MVU number of processes in A list }00063 0 0 H00064 0 0 nothresholds = 5; { number of special thresholds }00065 0 0 X00066 0 0 NoCommentLines = 2; { no. of comment lines in process list files }00067 0 0 00068 0 0 TYPE00069 0 0 %00070 0 0 longword = INTEGER;.00071 0 0 byte = [BYTE] -128..127;200072 0 0 word = [WORD] -32768..32767;:00073 0 0 name = PACKED ARRAY [1..23] OF CHAR;;00074 0 0 str = PACKED ARRAY [1..128] OF CHAR;<00075 0 0 quadword = PACKED ARRAY [1..2] OF INTEGER;900076 0 0 alfa7 = PACKED ARRAY [1..7] OF CHAR;:00077 0 0 alfa12 = PACKED ARRAY [1..12] OF CHAR;:00078 0 0 alfa23 = PACKED ARRAY [1..23] OF CHAR;"00079 0 0 TEXTFILE = Text;00080 0 0 800081 0 0 ans_type = (lword, string, flag_word);V00082 0 0 flag_type = (pcb00, pcb01, pcb02, pcb03, pcb04, pcb05, pcb06, pcb07,Z00083 0 0 pcb08, pcb09, pcb10, pcb11, pcb12, pcb13, batch_run, pcb15,\00084 0 0 pcb16, pcb17, pcb18, pcb19, pcb20, network_run, pcb22, pcb23,W00085 0 0 pcb24, pcb25, pcb26, pcb27, pcb28, pcb29, pcb30, pcb31);00086 0 0 /00087 0 0 sts_word = SET OF flag_type;00088 0 0 *00089 0 0 item_type= PACKED RECORD&00090 0 0 bl,item_code:word;$00091 0 0 CASE ans_type OF.00092 0 0 lword:(pdata:^longword;.00093 0 0 pld:^longword);)00094 0 0 string:(pstrg:^str;.00095 0 0 pls:^longword);.00096 0 0 flag_word:(fdata:^sts_word;.00097 0 0 fls:^longword);00098 0 0 END;00099 0 0 *00100 0 0 list_type= PACKED RECORD700101 0 0 itm:ARRAY [1..20] OF item_type;00102 0 0 END;00103 0 0 (00104 0 0 ref = ^proc_data_t ype;00105 0 0 )00106 0 0 proc_data_type = RECORD*00107 0 0 ppid:longword;%00108 0 0 fptr:ref;(00109 0 0 user:alfa12;%00110 0 0 image_name:str; ARGUS4 13-Sep-1990 14:51:18 VAX Pascal V4.0-2 Page 3~01 Source Listing 13-Sep-1990 14:50:48 USERDISK7:[BRUCE.ARGUS]ARGUS.PAS;2 (1)-LINE-IDC-PL-SL-*00111 0 0 owner_pid:longword;'00112 0 0 term:alfa7;*00113 0 0 stat:sts_word;L00114 0 0 cpu,delta_cpu,delta_io,io,grp,mem,proc_cnt,idle_count*00115 0 0 :longword;)00116 0 0 present:BOOLEAN;%00117 0 0 masterpid:longword;00118 0 0 END;00119 0 0 R00120 0 0 process_list_type = array [1..MAXNOPROCESSES] of [VOLATILE] str;Y00121 C 0 0 { Process list structure , - terminates string, -terminates number(00122 C 0 0 of processes. }00123 0 0 f00124 0 0 threshold_type = record { varying processes, have longer cpu and io thresholds }I00125 0 0 imagename : array[ 1..nothresholds] of [VOLATILE] str;L00126 0 0 io : array[ 1..nothresholds] of longword;?00127 0 0 cpu : array[ 1..nothresholds] of longword;C00128 0 0 numTOwarn : array[ 1..nothresholds] of integer; D00129  0 0 numTOkill : array[ 1..nothresholds] of integer; 00130 0 0 end;00131 0 0 d00132 0 0 sndjbc_itemlist_type = record { item list for sndjbcw used to write to oprlog}#00133 0 0 buflen : word;!00134 0 0 item : word;'00135 0 0 bufadr : unsigned;'00136 0 0 retlen : longword;00137 0 0 end;00138 0 0 [00139 C 0 0 {-------------------------------------------------------------------------}00140 0 0 VAR00141 0 0 a00142 0 0 sndjbc : array[1..2] of sndjbc_itemlist_type; {item list for $sndjbcw call })00143 0 0 i,j,k,sstat,st:INTEGER;&00144 0 0 kstat,wstat:INTEGER;$00145 0 0 flag_mask:INTEGER;00146 0 0 len:word;00147 0 0 logname:name;00148 0 0 table:byte; 00149 0 0 debug:BOOLEAN;600150 0 0 grpnum,memnum,pid:[VOLATILE]INTEGER;-00151 0 0 thepid: [VOLATILE]UNSIGNED;700152 0 0 bufio,prccnt,owner:[VOLATILE]INTEGER;-00153 0 0 seedpid:[VOLATILE]UNSIGNED;G00154 0 0 imagname,terminal,username,processname:[VOLATILE]str;D00155 0 0 pl,ulen,ilen, plen, master_pid:[VOLATILE]longword;,00156 0 0 cputim:[VOLATILE]longword;,00157 0 0 status:[VOLATILE]sts_word;&00158 0 0 item_list:list_type;*00159 0 0 quit,first_flag:BOOLEAN;00160 0 0 t2:alfa23;600161 0 0 qdelta,last_time,next_time:quadword;100162 0 0 p,free0 !TW~ ARGUS.BCK>S%[BRUCE.ARGUS]ARGUS.LIS;1oL,root,sentinel, junk:ref;000163 0 0 flcount,active_count:longword;000164 0 0 warn_msg:VARYING[132] OF CHAR;100165 0 0 wait_time:varying[132] OF CHAR; ARGUS4 13-Sep-1990 14:51:18 VAX Pascal V4.0-2 Page 4~01 Source Listing 13-Sep-1990 14:50:48 USERDISK7:[BRUCE.ARGUS]ARGUS.PAS;2 (1)-LINE-IDC-PL-SL-"00166 0 0 wait_once:record#00167 0 0 l1,l2 : integer;00168 0 0 end;000169 0 0 kill_msg:VARYING[132] OF CHAR;00170 0 0 k00171 0 0 accountinglogmsg: [volatile ] VARYING[80] OF CHAR; { buffer used to write accounting log}00172 0 0 00173 0 0 tty:alfa7;"00174 0 0 victim:UNSIGNED;00175 0 0 R00176 0 0 ING_II_BACK : [VOLATILE] STR; { ingres back ground II process }M00177 0 0 TPU_PARENT : [VOLATILE] STR; { tpu spawns idle children }E00178 0 0 MAIL : [VOLATILE] STR; { tmp just kill mail now }V00179 0 0 NotToKill : process_list_type; { processes not to kill regardless }Z00180 0 0 NoKillSubs : process_list_type; { Subprocesses not to kill regardless }d00181 0 0 ToAlwaysKill : process_list_type; { processes to always kill based on time used }00182 0 0 U00183 0 0 ArgusKill : TEXTfile; { file contains list of processes to kill}Y00184 0 0 ArgusNot : TEXTfile; { file contains list of not to kill processes}]00185 0 0 ArgusNotSubs : TEXTfile; { file contains list of not to kill processes}00186 0 0 .00187 0 0 threshold : threshold_type;00188 0 0 00189 0 0 VALUE00190 0 0 *00191 0 0 ING_II_BACK := 'II_PC-';300192 0 0 TPU_PARENT := '[SYSEXE]TPU.EXE-';L00193 0 0 MAIL := 'SYSEXE]MAIL.EXE-'; {tmp vers1.5 just kill mail }P00194 0 0 flag_mask := 6; { mask for flags 1 & 2 }O00195 0 0 wait_time := '0 00:00:01'; {time-out wait - 1 second}00196 0 0 400197 0 0 NotToKill[1] := '-'; { mt list }'00198 0 0 NoKillSubs[1] := '-';)00199 0 0 ToAlwaysKill[1] := '-';00200 0 0 _00201 0 0 threshold.imagename[1] := '...................-'; { normal threshold images }200202 0 0 threshold.io[1] := io_threshold;400203 0 0 threshold.cpu[1] := cpu_threshold;900204 0 0 threshold.numTOwarn[1] := n_to_warning;600205 0 0 threshold.numTOkill[1] := n_to_kill;00206 0 0 ?00207 0 0 threshold.imagename[2] := '[SYSEXE]TPU.EXE-';(00208 0 0 threshold.io[2] := 12;400209 0 0 threshold.cpu[2] := cpu_threshold;@00210 0 0 threshold.numTOwarn[2] := editor_n_to_warning;=00211 0 0 threshold.numTOkill[2] := editor_n_to_kill;00212 0 0 B00213 0 0 threshold.imagename[3] := '[SYSEXE]LSEDIT.EXE-';(00214 0 0 threshold.io[3] := 12;400215 0 0 threshold.cpu[3] := cpu_threshold;@00216 0 0 threshold.numTOwarn[3] := editor_n_to_warning;=00217 0 0 threshold.numTOkill[3] := editor_n_to_kill;00218 0 0 ?00219 0 0 threshold.imagename[4] := '[SYSEXE]EDT.EXE-';200220 0 0 threshold.io[4] := io_threshold; ARGUS4 13-Sep-1990 14:51:18 VAX Pascal V4.0-2 Page 5~01 Source Listing 13-Sep-1990 14:50:48 USERDISK7:[BRUCE.ARGUS]ARGUS.PAS;2 (1)-LINE-IDC-PL-SL-400221 0 0 threshold.cpu[4] := cpu_threshold;@00222 0 0 threshold.numTOwarn[4] := editor_n_to_warning;=00223 0 0 threshold.numTOkill[4] := editor_n_to_kill;00224 0 0 @00225 0 0 threshold.imagename[5] := '[SYSEXE]EDIT.EXE-';200226 0 0 threshold.io[5] := io_threshold;400227 0 0 threshold.cpu[5] := cpu_threshold;@00228 0 0 threshold.numTOwarn[5] := editor_n_to_warning;=00229 0 0 threshold.numTOkill[5] := editor_n_to_kill;00230 0 0 00231 0 0 E00232 0 0 PROCEDURE quadiv(a,b:quadword;VAR c:quadword);EXTERN;00233 0 0 E00234 0 0 PROCEDURE quamul(a,b:quadword;VAR c:quadword);EXTERN;00235 0 0 E00236 0 0 PROCEDURE quaadd(a,b:quadword;VAR c:quadword);EXTERN;00237 0 0 %00238 1 0 PROCEDURE str$upcase(J00239 1 0 %stdescr dest: str {packed[l1..h1: integer] of char};T00240 0 0 %stdescr from: str {packed[l2..h2: integer] of char} ); extern;00241 0 0 '00242 0 0 [EXTERNAL,ASYNCHRONOUS]G00243 1 0 PROCEDURE LIB$SIGNAL ( condition : [immediate] INTEGER;H00244 1 0 FAO_Params : [unsafe,list,immediate] INTEGER ); 00245 0 0 EXTERN;00246 0 0 Y00247 C 0 0 {-----------------------------------------------------------------------}Y00248 C 0 0 { init_item_list -- initializes item list for $getjpi call and }Y00249 C 0 0 { $sndjbc call }Y00250 C 0 0 {-----------------------------------------------------------------------})00251 1 0 PROCEDURE init_item_list;00252 1 1 BEGIN00253 1 1 U00254 1 2 WITH item_list.itm[1] DO BEGIN bl := 7; item_code := jpi$_terminal;H00255 1 1 pstrg := ADDRESS(terminal); pls := ADDRESS(pl); END;S00256 1 2 WITH item_list.itm[2] DO BEGIN bl := 4; item_code := jpi$_cputim;100257 1 1 pdata := ADDRESS(cputim); END;P00258 1 2 WITH item_list.itm[3] DO BEGIN bl := 4; item_code := jpi$_sts;100259 1 1 fdata := ADDRESS(status); END;P00260 1 2 WITH item_list.itm[4] DO BEGIN bl := 4; item_code := jpi$_pid;.00261 1 1 pdata := ADDRESS(pid); END;P00262 1 2 WITH item_list.itm[5] DO BEGIN bl := 4; item_code := jpi$_grp;100263 1 1 pdata := ADDRESS(grpnum); END;U00264 1 2 WITH item_list.itm[6] DO BEGIN bl := 12; item_code := jpi$_username;J00265 1 1 pstrg := ADDRESS(username); pls := ADDRESS(ulen); END;R00266 1 2 WITH item_list.itm[7] DO BEGIN bl := 4; item_code := jpi$_bufio;000267 1 1 pdata := ADDRESS(bufio); END;U00268 1 2 WITH item_list.itm[8] DO BEGIN bl := 50; item_code := jpi$_imagname;J00269 1 1 pstrg := ADDRESS(imagname); pls := ADDRESS(ilen); END;S00270 1 2 WITH item_list.itm[9] DO BEGIN bl := 4; item_code := jpi$_prccnt;100271 1 1 pdata := ADDRESS(prccnt); END;S00272 1 2 WITH item_list.itm[10] DO BEGIN bl := 4; item_code := jpi$_owner;000273 1 1 pdata := ADDRESS(owner); END;Q00274 1 2 WITH item_list.itm[11] DO BEGIN bl := 4; item_code := jpi$_mem;100275 1 1 pdata := ADDRESS(memnum); END; ARGUS4 13-Sep-1990 14:51:18 VAX Pascal V4.0-2 Page 6~01 Source Listing 13-Sep-1990 14:50:48 USERDISK7:[BRUCE.ARGUS]ARGUS.PAS;2 (1)-LINE-IDC-PL-SL-S00276 1 2 WITH item_list.itm[12] DO BEGIN bl := 4; item_code := jpi$_owner;e500277 1 1 pdata := ADDRESS(master_pid); END;IT00278 1 2 WITH item_list.itm[13] DO BEGIN bl := 50; item_code := jpi$_prcnam;M00279 1 1 pstrg := ADDRESS(processname); pls := ADDRESS(plen); END;P00280 1 1 item_list.itm[14].item_code := 0; item_list.itm[14].bl := 0;00281 1 1 300282 C 1 1 { $smdjbcw call item list } )00283 1 1 sndjbc[1].buflen := 80;-<00284 1 1 sndjbc[1].item := sjc$_accounting_message;A00285 1 1 sndjbc[1].bufadr := IADDRESS(accountinglogmsg);s(00286 1 1 sndjbc[1].retlen := 0;;00287 1 1 sndjbc[2].buflen := 0; { terminator }.L00288 1 1 sndjbc[2].item := 0; { is a longword } 00289 1 1 00290 1 1 00291 1 1 %00292 0 0 END {init_item_list}; 00293 0 0 _00294 C 0 0 {-----------------------------------------------------------------------------}bb00295 C 0 0 { BuildProcessList - build process_list_type variable from specified input fil.e}_00296 C 0 0 { INPUT : filvar -- of file to build list from }_00297 C 0 0 { processList -- name of process list var to build } _00298 C 0 0 { OUTPUT: processlist var filed in with names from file } _00299 C 0 0 { NOTE:$ FILVAR MUST BE OPENED }d_00300 C 0 0 {-----------------------------------------------------------------------------} i00301 1 0 PROCEDURE BuildProcessList( VAR filvar : textfile; VAR processlist : process_list_type ); 00302 1 0 VAR 300303 1 0 exename, name : [VOLATILE] str;!00304 1 0 j : integer;-00305 1 1 BEGIN-"00306 1 1 RESET(filvar);00307 1 1 i := 1;IR00308 1 2 WHILE ( i <= NoCommentLines ) AND (NOT(EOF(filvar)) ) DO BEGIN@00309 1 2 READLN(filvar,exename); {skip comment lines}000310 1 2 IF i = 1 THEN WRITELN(exename);00311 1 2 i := i + 1e00312 1 1 END;00313 1 1 Q00314 1 1 processlist[1] := '-'; { set up as mt list in case file mt }300315 1 1 i := 1; Q00316 1 2 WHILE ( i <= MAXNOPROCESSES) AND (NOT(EOF(filvar)) )DO BEGIN/)00317 1 2 READ( filvar, exename );lH00318 1 2 str$upcase ( name, exename ); { make name upper case }#00319 1 2 WRITE( i, '. ' );n00320 1 2 j := 1;200321 1 3 WHILE ( name[j] <> ' ' ) DO BEGIN&00322 1 3 write( name[j] );100323 1 3 processlist[i,j] := name[j]; 00324 1 3 j := j + 1;00325 1 2 END; 00326 1 2 writeln;o+00327 1 2 processlist[i,j ] := '-';L00328 1 2 IF name[1] <> ' ' THEN { not an mt string grab next one} 00329 1 3 BEGIN*00330 1 3 processlist[i+1] := '-'; ARGUS4 13-Sep-1990 14:51:18 VAX Pascal V4.0-2 Page 7~01 Source Listing 13-Sep-1990 14:50:48 USERDISK7:[BRUCE.ARGUS]ARGUS.PAS;2 (1)-LINE-IDC-PL-SL-00331 1 3 i := i + 100332 1 2 END; I00333 1 2 readln( filvar, exename ) {skip rest of line, ignored } 00334 1 1 END;00335 1 1 !00336 1 1 CLOSE(filvar) 00337 1 1 '00338 0 0 END; {BuildProcessList}P00339 0 0 ^00340 C 0 0 {----------------------------------------------------------------------------}^00341 C 0 0 { matchINDEX -- returns location that object matches pattern }^00342 C 0 0 { INPUT : object string terminated by '+' }^00343 C 0 0 { pattern string terminated by '-' }^00344 C 0 0 { OUTPUT: integer index in object string if matched otherwise 0 }^00345 C 0 0 {----------------------------------------------------------------------------}T00346 1 0 FUNCTION matchINDEX ( object, pattern : [VOLATILE ] str ) : integer;00347 1 0 VAR &00348 1 0 notfound : boolean;100349 1 0 i, j, len, posindex : integer;000350 1 1 BEGINR$00351 1 1 notfound := true;+00352 1 1 len := LENGTH( object );O00353 1 1 i := 1;.00354 1 2 while ( i <= len ) DO BEGIN:00355 1 2 IF object[i] = '+' THEN len := i - 1;#00356 1 2 i := i + 1; C00357 1 1 END;E00358 1 1 00359 1 1 i := 1;900360 1 1 matchINDEX := 0; { guess not find } :00361 1 2 WHILE (i <= len ) AND notfound DO BEGIN00362 1 2 j := 1; $00363 1 2 posindex := i;P00364 1 3 WHILE ( object[i] = pattern[j] ) DO BEGIN { + stops loop }800365 1 3 i := i + 1; j := j + 1;00366 1 2 END;00367 1 2 /00368 1 2 IF pattern[j] = '-' THEN 000369 1 3 BEGIN+00370 1 3 notfound := false;p000371 1 3 matchINDEX := posindex;00372 1 2 END;c00373 1 2 !00374 1 2 i := i + 1 00375 1 2 00376 1 2 END !00377 0 0 END; {matchINDEX}m00378 0 0 _00379 C 0 0 {-----------------------------------------------------------------------------} _00380 C 0 0 { InList -- returns indication whether process is in specified process list} _00381 C 0 0 { INPUT : list to check, image name str }__00382 C 0 0 { OUTPUT: true -- member of list }0_00383 C 0 0 { false -- not in list }._00384 C 0 0 {-----------------------------------------------------------------------------}_c00385 1 0 FUNCTION InList( list : process_list_type; image_name : [VOLATILE] str ) : BOOLEAN;  dARGUS4 13-Sep-1990 14:51:18 VAX Pascal V4.0-2 Page 8~01 Source Listing 13-Sep-1990 14:50:48 USERDISK7:[BRUCE.ARGUS]ARGUS.PAS;2 (1)-LINE-IDC-PL-SL-00386 1 0 VARo100387 1 0 position, i, total : INTEGER; 00388 1 0 00389 1 1 BEGIN00390 1 1 total := 0;00391 1 1 i := 1;c00392 1 2 WHILE (( i <= MAXNOPROCESSES) AND ( total = 0 )) AND ((list[i] <> '-') )DO BEGIN E00393 1 2 position := matchINDEX ( image_name, list[i] );1000394 1 2 total := total + position;!00395 1 2 i := i + 1;000396 1 1 END; {WHILE}d+00397 1 1 InList := NOT(total = 0)00398 0 0 END; {InList}t00399 0 0 _00400 C 0 0 {-----------------------------------------------------------------------------}s`00401 C 0 0 { thresholdINDEX -- computes index into threshold array for image name }300402 C 0 0 { INPUT : image name }e_00403 C 0 0 { OUTPUT: index of threshold which belongs to special process } `00404 C 0 0 { Note: index of 1 indicates the normal thresholds }_00405 C 0 0 {-----------------------------------------------------------------------------}rQ00406 1 0 FUNCTION thresholdINDEX ( imagename : [VOLATILE] str ) : INTEGER;s00407 1 0 VAR(00408 1 0 i, found : INTEGER;00409 1 1 BEGINj00410 1 1 found := 0;t00411 1 1 00412 1 1 i := 0;0K00413 1 2 WHILE ( (i < nothresholds ) AND ( found = 0 )) DO BEGIN #00414 1 2 i := i + 1;0J00415 1 2 found := matchINDEX ( imagename, threshold.imagename[i] )00416 1 1 END;00417 1 1 ]00418 1 1 IF found = 0 THEN thresholdINDEX := 1 {1 1 contains normal thresholds }-00419 1 1 ELSE thresholdINDEX := i;d00420 1 1 &00421 0 0 END; {thresholdINDEX }00422 0 0 00423 0 0 ?00424 C 0 0 {&******************************************* }m00425 0 0 .00426 1 0 PROCEDURE update_entry(w:ref);00427 1 0 VAR $00428 1 0 k : INTEGER;&00429 1 0 index : INTEGER;00430 1 1 BEGIN]00431 1 1 WITH w^ DO00432 1 2 BEGIND*00433 1 2 masterpid := master_pid;100434 1 2 delta_cpu := abs(cputim - cpu);L 00435 1 2 cpu := cputim;.00436 1 2 delta_io := abs(bufio - io);00437 1 2 io := bufio;%00438 1 2 proc_cnt := prccnt;rE00439 1 2 FOR k := 1 to ilen DO image_name[k] := imagname[k];t.00440 1 2 image_name[ilen + 1] := '+'; :ARGUS4 13-Sep-1990 14:51:18 VAX Pascal V4.0-2 Page 9~01 Source Listing 13-Sep-1990 14:50:48 USERDISK7:[BRUCE.ARGUS]ARGUS.PAS;2 (1)-LINE-IDC-PL-SL-/00441 1 2 processname[plen + 1] := '+';]"00442 1 2 present := TRUE;00443 1 2 G00444 1 2 IF ( proc_cnt > 0 ) THEN { never kill a parent} %00445 1 2 idle_count := 0 H00446 1 2 ELSE IF ( ilen > 0 ) THEN { have an image name }00447 1 3 BEGIN>00448 1 3 index := thresholdINDEX( image_name );_00449 1 3 IF (owner_pid = 0) AND ((term = '*NT*:') AND (NOT(batch_run in stat)) )IQ00450 1 3 THEN idle_count := 0 { detached process no kill } H00451 1 3 ELSE IF ( InList( NotToKill, image_name ) ) THEN*00452 1 3 idle_count := 0L00453 1 3 ELSE IF ( InList ( ToAlwaysKill, image_name ) ) THEN700454 1 3 idle_count := idle_count + 1 h00455 1 3 ELSE IF ( delta_cpu > threshold.cpu[index] ) THEN { not using substantial cpu }*00456 1 3 idle_count := 0]00457 1 3 ELSE IF ( delta_io > threshold.io[index] ) THEN { BUFFER i/o count }0*00458 1 3 idle_count := 000459 1 3 ELSE700460 1 3 idle_count := idle_count + 1;=00461 1 3 END { end of have an image name } 300462 1 2 ELSE { Command process } 00463 1 3 BEGING00464 1 3 IF ( matchINDEX( processname, ING_II_BACK) <> 0 ) then P00465 1 3 idle_count := 0 { Ingres spawning a child task, ignore him }a00466 1 3 ELSE IF ( delta_cpu > cpu_threshold ) THEN { not using substantial cpu }d*00467 1 3 idle_count := 0W00468 1 3 ELSE IF ( delta_io > io_threshold ) THEN { BUFFER i/o count }_*00469 1 3 idle_count := 0Q00470 1 3 ELSE IF ( owner <> 0 ) THEN { Subprocess of LSE or TPU} 00471 1 4 begin O00472 1 4 thepid := owner; { grab info for this process } C00473 1 4 sstat := $getjpi( 1, thepid,,item_list);T000474 1 4 wstat := $waitfr( 1);700475 1 4 image_name[ilen + 1] := '+'; G00476 1 4 IF ( InList( NoKillSubs, image_name ) ) THEN.-00477 1 4 idle_count := 0 00478 1 4 end.00479 1 3 ELSE700480 1 3 idle_count := idle_count + 1 00481 1 3 END00482 1 2 END00483 0 0 END;00484 0 0 ?00485 C 0 0 {&******************************************* }g00486 0 0 $00487 1 0 PROCEDURE new_entry;00488 1 0 00489 1 0 VARh00490 1 0 w:ref;00491 1 0 k:INTEGER;00492 1 0 00493 1 1 BEGIN;00494 1 1 100495 1 1 active_count := active_count + 1;1 ARGUS4 13-Sep-1990 14:51:18 VAX Pascal V4.0-2 Page 910~01 Source Listing 13-Sep-1990 14:50:48 USERDISK7:[BRUCE.ARGUS]ARGUS.PAS;2 (1)-LINE-IDC-PL-SL-00496 1 1 I00497 C 1 1 { Obtain a record from the free list. If the Free List isEK00498 C 1 1 empty, then get a new one from the Heap... } 00499 1 1 )00500 1 1 IF free <> sentinel THEN 100501 1 2 BEGINl00502 1 2 w := free;"00503 1 2 free := w^.fptr;)00504 1 2 flcount := flcount - 1;900505 1 2 END:00506 1 1 ELSE00507 1 1 new(w);100508 C 1 1 { Now fill in the new record. }l00509 1 1 w^.ppid := pid;u100510 1 1 IF pl = 0 THEN w^.term := '*NT*:' M00511 1 1 ELSE FOR k := 1 TO pl DO w^.term[k] := terminal[k];0"00512 1 1 w^.stat := status;>00513 1 1 FOR k := 1 TO 12 DO w^.user[k] := username[k];!00514 1 1 w^.cpu := cputim;p'00515 1 1 w^.delta_cpu := cputim; 00516 1 1 w^.io := bufio;n%00517 1 1 w^.delta_io := bufio;l!00518 1 1 w^.grp := grpnum;!00519 1 1 w^.mem := memnum; &00520 1 1 w^.owner_pid := owner;&00521 1 1 w^.proc_cnt := prccnt;#00522 1 1 w^.idle_count := 0;RF00523 1 1 FOR k := 1 to ilen DO w^.image_name[k] := imagname[k];K00524 1 1 w^.image_name[ilen + 1] := '+'; { delimit end of string }0#00525 1 1 w^.present := TRUE;p+00526 1 1 w^.masterpid := master_pid;t400527 C 1 1 { Now enter it in the active list. }00528 1 1 00529 1 1 w^.fptr := root;00530 1 1 root := w;00531 1 1 00532 0 0 END;00533 0 0 00534 0 0 ?00535 C 0 0 {&******************************************* } 00536 0 0 I00537 1 0 PROCEDURE search(spid:longword;VAR w:ref; VAR prev: ref);400538 1 0 00539 1 0 00540 1 1 BEGIN-:00541 1 1 w := root; sentinel^.ppid := spid;!00542 1 1 prev := root;t200543 1 2 WHILE w^.p=pid <> spid DO BEGIN00544 1 2 prev := w;d00545 1 2 w := w^.fptr;00546 1 1 END;00547 0 0 END;00548 0 0 00549 0 0 00550 0 0  -ARGUS4 13-Sep-1990 14:51:18 VAX Pascal V4.0-2 Page 11~01 Source Listing 13-Sep-1990 14:50:48 USERDISK7:[BRUCE.ARGUS]ARGUS.PAS;2 (1)-LINE-IDC-PL-SL-00551 0 0 00552 0 0 00553 0 0 00554 0 0 ?00555 C 0 0 { ******************************************* }t00556 0 0 +00557 1 0 PROCEDURE mark_not_present;100558 1 0 00559 1 0 VAR00560 1 0 w:ref;00561 1 0 00562 1 1 BEGIN 00563 1 1 w := root;&00564 1 1 WHILE w <> sentinel DO00565 1 2 BEGINi&00566 1 2 w^.present := FALSE;00567 1 2 w := w^.fptr; 00568 1 1 END;00569 0 0 END;00570 0 0 ?00571 C 0 0 {&******************************************* } 00572 0 0 %00573 1 0 PROCEDURE time_synch;N00574 1 0 00575 1 0 VAR700576 1 0 !00577 1 0 a,b,c:quadword; 00578 1 0 s1:INTEGER;f00579 1 0 tx:alfa23;00580 1 0 00581 1 1 BEGINt"00582 1 1 IF first_flag THEN00583 1 2 BEGINS&00584 1 2 first_flag := FALSE;N00585 1 2 a[1] := 10000000; { One second in 100-nsec increments }00586 1 2 a[2] := 0;@00587 1 2 b[1] := 60*interval; { interval in seconds }00588 1 2 b[2] := 0;00589 1 2 K00590 1 2 quamul(a, b, qdelta); { Interval in system time format }_%00591 1 2 s1 := $asctim(,tx);o;00592 1 2 s1 := $bintim(tx, c); { Current time } '00593 1 2 quadiv(c, qdelta, a); /00594 1 2 quamul(a, qdelta, next_time);500595 1 1 END;00596 1 1 '00597 1 1 last_time := next_time; 600598 1 1 quaadd (last A_time, qdelta, next_time);&00599 1 1 $schdwk(,, next_time);00600 1 1 $hiber;000601 0 0 END;00602 0 0 ?00603 C 0 0 {&******************************************* }t00604 0 0 .00605 1 0 PROCEDURE remove(VAR a,z:ref); 1ARGUS4 13-Sep-1990 14:51:18 VAX Pascal V4.0-2 Page 12~01 Source Listing 13-Sep-1990 14:50:48 USERDISK7:[BRUCE.ARGUS]ARGUS.PAS;2 (1)-LINE-IDC-PL-SL-00606 1 0 VAR 00607 1 0 tmp:ref;00608 1 1 BEGINt000609 1 1 IF a = root THEN root := a^.fptr400610 1 1 ELSE z^.fptr := a^.fptr;H00611 1 1 tmp := a^.fptr; a^.fptr := free; free := a; a := tmp;100612 1 1 active_count := active_count - 1;2'00613 1 1 flcount := flcount + 1;n00614 0 0 END;00615 0 0 ^00616 C 0 0 {----------------------------------------------------------------------------}^00617 C 0 0 { Logprint -- prints process infor to log file. }^00618 C 0 0 {----------------------------------------------------------------------------}.00619 1 0 PROCEDURE Logprint( w : ref );00620 1 1 BEGIN 00621 1 1 WITH w^ DO 00622 1 2 BEGINm600623 1 2 WRITE (' ', hex(ppid, 8, 8) );000624 1 2 WRITE ( ' ', user, ' ');00625 1 2 00626 1 2 i := 1; ?00627 1 3 WHILE ( image_name[i] <> '+' ) DO BEGIN 100628 1 3 WRITE ( IMAGE_NAME[i] );-+00629 1 3 i := i + 1;-00630 1 2 END;00631 1 2 00632 1 2 WRITELN;800633 1 2 WRITE ( ' term ',term, ' ');E00634 1 2 WRITE ( 'cpu ',cpu:8, ' ', 'io ', io:8, ' '); J00635 1 2 WRITE ( '^cpu ',delta_cpu:6, ' ^io ', delta_io:6);=00636 1 2 WRITE ( 'idle_count', idle_count:3 ); :00637 1 2 WRITE ( 'proc_cnt ', proc_cnt:3 );00638 1 2 WRITELN;(00639 1 1 END; {WITH} 00640 0 0 END; {Logprint} F00641 C 0 0 { ******************************************* }00642 0 0 +00643 1 0 PROCEDURE warn_user(w:ref); 00644 1 0 00645 1 0 VARm'00646 1 0 s1,s2,s3,s4 :INTEGER; 00647 1 0 chan:word;00648 1 0 pd:longword;$00649 1 0 target, junk :ref;*00650 1 0 idle_t, t_to_go:INTEGER;$00651 1 0 index : INTEGER;00652 1 0 00653 1 1 BEGIN'-00654 1 1 $bintim(wait_time,wait_once);1100655 1 1 idle_t := w^.idle_count*interval;1700656 1 1 index := thresholdINDEX(w^.image_name);iH00657 1 1 t_to_go := threshold.numTOkill[index]*interval - idle_t;00658 1 1 target := w;/00659 1 1 WHILE target^.owner_pid <> 0 DO00660 1 2 BEGIN1 >ARGUS4 13-Sep-1990 14:51:18 VAX Pascal V4.0-2 Page 13~01 Source Listing 13-Sep-1990 14:50:48 USERDISK7:[BRUCE.ARGUS]ARGUS.PAS;2 (1)-LINE-IDC-PL-SL-*00661 1 2 pd := target^.owner_pid;-00662 1 2 search( pd, target, junk );P100663 1 2 IF target = sentinel THEN halt; 00664 1 1 END;$00665 1 1 tty := target^.term;00666 1 1 c00667 1 1 IF target = w THEN WRITEV(warn_msg, ' ****WARNING****',''(13)''(10)''(7),SS00668 1 1 ' This terminal has been idle for ', idle_t:2, ^00669 1 1 ' minutes,',''(13)''(10),' and will be killed in ', ;00670 1 1 t_to_go:2, ' minutes.')j`00671 1 1 ELSE WRITEV(warn_msg, ' ****WARNING****'''(13)''(10)''(7)E00672 1 1 ' Subprocess ', HEX(w^.ppid, 8, 8),s[00673 1 1 ' has been idle for ', idle_t:2, ' minutes,'''(13)''(10),rE00674 1 1 ' and will be killed in ', <00675 1 1 t_to_go:2, ' minutes.');00676 1 1 C00677 C 1 1 { $brkthru( 2, warn_msg, tty,BRK$C_DEVICE,,,,5 );}L$00678 1 1 $assign(tty,chan);V00679 1 1 $qio(2,chan,io$_writevblk+io$m_breakthru+io$m_enablmbx+io$m_refresh,A00680 1 1 ,,,warn_msg.body,warn_msg.length, , , , );u*00681 1 1 $setimr(1,wait_once,,,);00682 1 1 $waitfr(1);;00683 1 1 \00684 C 1 1 { MVU-- reset io and cpu usage to ignore the effect of writing out warning00685 C 1 1 message. }H00686 1 1 thepid := w^.ppid; { grab info for this process }:00687 1 1 sstat := $getjpi( 1, thepid,,item_list);'00688 1 1 wstat := $waitfr( 1);D_00689 1 1 w^.cpu := cputim; { reset overall cpu time to ignore warn msg cpu time } O00690 1 1 w^.io := bufio; { reset io time to ignore warn msg io } 00691 1 1 $dassgn(chan);00692 1 1 00693 1 1 00694 1 1 WITH w^ DO00695 1 2 BEGINe900696 1 2 WRITE(' WARNING ', user, ' PID:'); =00697 1 2 WRITE(HEX(ppid, 8, 8), ', Term:', tty);m*00698 1 2 WRITE(' ', t2, ' ');;00699 1 2 IF owner_pid <> 0 THEN WRITE(' S'); 00700 1 2 WRITELN;$00701 1 2 Logprint( w );00702 1 1 END;00703 1 1 00704 0 0 END;00705 0 0 ?00706 C 0 0 {&******************************************* }I00707 0 0 @00708 1 0 PROCEDURE kill_process(w:ref; timemsg: boolean);00709 1 0 00710 1 0 VARa00711 1 0 pd:longword;00712 1 0 chan:word;$00713 1 0 target, junk :ref;!00714 1 0 idle_t:INTEGER; 400715 1 0 write_to_accounting_log : BOOLEAN; ARGUS4 13-Sep-1990 14:51:18 VAX Pascal V4.0-2 Page 14~01 Source Listing 13-Sep-1990 14:50:48 USERDISK7:[BRUCE.ARGUS]ARGUS.PAS;2 (1)-LINE-IDC-PL-SL-#00716 1 0 status : INTEGER; 00717 1 0 00718 1 1 BEGIN 00719 1 1 100720 1 1 write_to_accounting_log := FALSE;s300721 1 1 idle_t := w^.idle_count * interval;K00722 1 1 target := w;00723 1 1 `00724 1 1 WHILE target^.owner_pid <> 0 DO {search for the parent to get term send msg}00725 1 2 BEGIN0*00726 1 2 pd := target^.owner_pid;+00727 1 2 search(pd, target, junk);=100728 1 2 IF target = sentinel THEN halt;>00729 1 1 END;$00730 1 1 tty := target^.term;00731 1 1 A00732 1 1 IF target=w THEN { Its the owning project! } 00733 1 2 BEGIN0A00734 1 2 WRITEV(kill_msg,''(27),'[2J ',''(27),'[1;1f',TY00735 1 2 ' This process killed by ARGUS.',''(13)''(10)''(7),-^00736 1 2 ' (Inactive for', idle_t:3, ' minutes.)',''(13)''(10),;00737 1 2 ' (Killed ', t2,')' ); 400738 1 2 write_to_accounting_log := TRUE;00739 1 2 END 000740 1 1 ELSE { Its a subprocess }K00741 1 1 WRITEV(kill_msg,' Subprocess ', HEX(w^.ppid, 8, 8), E00742 1 1 ' killed by ARGUS.',''(13)''(10)''(7),-^00743 1 1 ' (Inactive for', idle_t:3, ' minutes.)',''(13)''(10),;00744 1 1 ' (Killed ', t2,')' );G00745 1 1 @00746 C 1 1 {$brkthru(2, kill_msg, tty, BRK$C_DEVICE,,,,5);}$00747 1 1 $assign(tty,chan);,00748 1 1 $qio(2,chan,io$_writevblk,A00749 1 1 ,,,kill_msg.body,kill_msg.length, , , , ); *00750 1 1 $setimr(1,wait_once,,,);00751 1 1 $waitfr(1);u"00752 1 1 victim := w^.ppid;00753 1 1 00754 1 1 $dassgn(chan);00755 1 1 00756 1 1 $delprc(victim);00757 1 1 )0075~ ARGUS.BCK>S%[BRUCE.ARGUS]ARGUS.LIS;1oo>Q8 C 1 1 { Log to accounting Log }1/00759 1 1 IF write_to_accounting_log THEN 00760 1 2 BEGIN A00761 1 2 WRITEV ( accountinglogmsg, 'An Argus Kill of:', #00762 1 2 w^.user, ';',*500763 1 2 'PID: ', HEX(w^.ppid,8,8), ';',R$00764 1 2 '@', t2, '.');D00765 1 2 status := $SNDJBCW(FUNC := sjc$_write_accounting , =00766 1 2 ITMLST := sndjbc);I-00767 1 2 IF status <> SS$_NORMAL THEN100768 1 3 BEGINU00769 1 3 WRITE ( 'Error writing to accounting log status:',status );;H00770 1 3 LIB$SIGNAL( status,0 ); { will quit program } iARGUS4 13-Sep-1990 14:51:18 VAX Pascal V4.0-2 Page 15~01 Source Listing 13-Sep-1990 14:50:48 USERDISK7:[BRUCE.ARGUS]ARGUS.PAS;2 (1)-LINE-IDC-PL-SL-00771 1 2 END; 00772 1 1 END; {IF}s00773 1 1 00774 1 1 *00775 C 1 1 { Log to Argus's own log }00776 1 1 WITH w^ DO00777 1 2 BEGINm700778 1 2 WRITE('**KILLING ', user, ' PID:');;00779 1 2 WRITE(HEX(ppid, 8, 8), ', Term:', tty); (00780 1 2 WRITE(' ', t2, ' ');900781 1 2 IF owner_pid <> 0 THEN WRITE(' S');n00782 1 2 WRITELN;"00783 1 2 Logprint( w );00784 1 1 END;00785 1 1 00786 0 0 END;00787 0 0 ]00788 C 0 0 {---------------------------------------------------------------------------} `00789 C 0 0 { Kill_parent - recursive routine which kills all the parents, ie. grandparents}P00790 C 0 0 { great grand parent etc of a process. }]00791 C 0 0 { Input : child process } ]00792 C 0 0 { Output : all parents removed out of list, note calling process must remove}hW00793 C 0 0 { child from the list. }_]00794 C 0 0 {---------------------------------------------------------------------------}/:00795 1 0 PROCEDURE kill_parent ( VAR child : ref );00796 1 0 VARLE00797 1 0 prev, w : ref; { must be store on stack } &00798 1 0 timemsg : boolean;&00799 1 0 count : integer;00800 1 1 BEGIN}00801 1 1 w := child;0%00802 1 1 timemsg := false;nV00803 C 1 1 { if debug then writeln ('Entered Kill_parent', HEX(w^.ppid,8,8) );00804 C 1 1 }h300805 1 2 IF w^.masterpid = 0 THEN BEGINp;00806 C 1 2 { IF debug THEN WRITELN( 'REACHED ANCHOR'); 00807 1 2 } count := 0;000808 1 2 END00809 1 1 ELSE 00810 1 2 BEGINS00811 1 2 search( w^.masterpid, w, prev ); { w becomes the parent here } H00812 1 3 IF ( InList( NotToKill, w^.image_name )) THEN BEGINT00813 C 1 3 { IF debug THEN WRITELN(' Parent is not to kill,stop');$00814 1 3 } count := 0;00815 1 3 ENDpV00816 1 3 ELSE IF ( matchINDEX( w^.image_name, TPU_PARENT) <> 0) THEN BEGINS00817 C 1 3 { IF debug THEN WRITELN(' Parent is not to TPU,stop');u$00818 1 3 } count := 0;00819 1 3 END:00820 1 3 ELSE BEGINnZ00821 1 3 if debug then writeln ('Killed parent', HEX(w^.ppid,8,8) );J00822 1 3 kill_process( w, timemsg); { kill the parent }[00823 C 1 3 { if debug then writeln ( 'going to call kill_parent recursively.'); F00824 1 3 } kill_parent( w ); { then kill its parents }R00825 C 1 3 { if debug then writeln ('Hey were back and removing w is', 9ARGUS4 13-Sep-1990 14:51:18 VAX Pascal V4.0-2 Page 16~01 Source Listing 13-Sep-1990 14:50:48 USERDISK7:[BRUCE.ARGUS]ARGUS.PAS;2 (1)-LINE-IDC-PL-SL-]00826 C 1 3 HEX(w^.ppid,8,8));0N00827 1 3 } remove( w, prev ); { now remove parent from list of200828 C 1 3 active processes }00829 1 3 END 00830 1 2 END"00831 0 0 END; {kill_parent}00832 0 0 ?00833 C 0 0 {&******************************************* }r00834 0 0 "00835 1 0 PROCEDURE analyze;00836 1 0 VAR 00837 1 0 w,wlast:ref;!00838 1 0 killed:BOOLEAN; 00839 1 0 i : integer;400840 1 0 childgrpnum, childmem: integer;$00841 1 0 timemsg : boolean;=00842 1 0 number_to_warning, number_to_kill: integer;k$00843 1 0 index : integer;00844 1 1 BEGIN i00845 1 1 if debug then WRITELN('ANALYZE -------------------------------------------------------'); @00846 1 1 timemsg := true; { display idle time when kill }00847 1 1 wlast := NIL;o00848 1 1 w:= root;:&00849 1 1 WHILE w <> sentinel DO00850 1 2 BEGIN$00851 1 2 IF w^.present THEN00852 1 3 BEGIN0$00853 1 3 killed := FALSE;00854 1 3 WITH w^ DOD00855 1 4 BEGINe#00856 1 4 IF debug THENl00857 1 5 BEGIN 300858 1 5 WRITE (' ', HEX(w, 8, 8) );0600859 1 5 WRITE (' ', hex(ppid, 8, 8) );000860 1 5 WRITE ( ' ', user, ' ');00861 1 5 00862 1 5 i := 1; ?00863 1 6 WHILE ( image_name[i] <> '+' ) DO BEGIN 100864 1 6 WRITE ( IMAGE_NAME[i] );*+00865 1 6 i := i + 1;300866 1 5 END;00867 1 5 00868 1 5 WRITELN;800869 1 5 WRITE ( ' term ',term, ' ');E00870 1 5 WRITE ( 'cpu ',cpu:8, ' ', 'io ', io:8, ' ');0J00871 1 5 WRITE ( '^cpu ',delta_cpu:6, ' ^io ', delta_io:6);=00872 1 5 WRITE ( 'idle_count', idle_count:3 );^:00873 1 5 WRITE ( 'proc_cnt ', proc_cnt:3 );00874 1 5 WRITELN; 00875 1 4 END;00876 1 4 <00877 1 4 index := thresholdINDEX( image_name );F00878 1 4 number_to_warning := threshold.numTOwarn[index];C00879 1 4 number_to_kill := threshold.numTOkill[index];R:00880 1 4 IF (idle_count >= number_to_warning) ARGUS4 13-Sep-1990 14:51:18 VAX Pascal V4.0-2 Page 17~01 Source Listing 13-Sep-1990 14:50:48 USERDISK7:[BRUCE.ARGUS]ARGUS.PAS;2 (1)-LINE-IDC-PL-SL-@00881 1 4 AND (idle_count < number_to_kill) THEN 00882 1 5 BEGIN6P00883 1 5 warn_user(w); { display warning msg only once } 00884 1 5 END00885 1 4 ELSE00886 1 5 BEGIN<00887 1 5 IF idle_count >= number_to_kill THEN00888 1 6 BEGIN *00889 1 6 childgrpnum := w^.grp; &00890 1 6 childmem := w^.mem;500891 1 6 kill_process( w, timemsg );IF00892 1 6 if debug then writeln('First call to kill_parent');#00893 1 6 kill_parent(w );aR00894 1 6 if debug then writeln('Last remove from outside kill_parent.', (00895 1 6 HEX(w^.ppid,8,8));+00896 1 6 remove(w, wlast); )00897 1 6 killed := TRUE;t00898 1 5 END;00899 1 4 END;&00900 1 4 IF NOT killed THEN00901 1 5 BEGINa!00902 1 5 wlast := w; #00903 1 5 w := w^.fptr; 00904 1 4 END;00905 1 4 END 00906 1 3 END {WITH}00907 1 2 ELSE%00908 1 2 remove(w, wlast);000909 1 1 END;000910 0 0 END;00911 0 0 ?00912 C 0 0 {&******************************************* }_00913 0 0 &00914 1 0 PROCEDURE debug_print;00915 1 0 00916 1 1 BEGIN0Y00917 1 1 WRITE ( 'DEBUG PRINT ---------------------------------------------');000918 1 1 WRITELN;500919 1 1 WRITE( ' ', HEX(pid, 8, 8), ' '); 00920 1 1 800921 1 1 IF ulen <= 0 THEN WRITE (' No user')00922 1 1 ELSE?00923 1 1 FOR I := 1 TO ulen DO WRITE(username[i]); 00924 1 1 100925 1 1 IF pl = 0 THEN WRITE('Nterm')L00926 1 1 ELSE=00927 1 1 FOR i := 1 TO pl DO WRITE(terminal[i]);tP00928 1 1 WRITE(' [', OCT(grpnum, 3, 3), ',', OCT(memnum, 3, 3), ']');.00929 1 1 WRITE(' CPU: ', cputim:8);#00930 1 1 WRITE(' PRC-'); 900931 1 1 IF prccnt > 0 THEN WRITE(' Parent ');1900932 1 1 IF owner <> 0 THEN WRITE(' Child '); P00933 1 1 IF (owner=0) AND (pl=0) AND (NOT (batch_run IN status)) THEN*00934 1 1 WRITE(' Detach ');E00935 1 1 IF batch_run IN status THEN WRITE(' Batch job.');  ARGUS4 13-Sep-1990 14:51:18 VAX Pascal V4.0-2 Page 18~01 Source Listing 13-Sep-1990 14:50:48 USERDISK7:[BRUCE.ARGUS]ARGUS.PAS;2 (1)-LINE-IDC-PL-SL-I00936 1 1 IF network_run IN status THEN WRITE(' Network job.'); ;00937 1 1 writeln( 'mp ',HEX(master_pid, 8, 8) ); 00938 1 1 00939 1 1 WRITELN;00940 0 0 END;00941 0 0 ?00942 C 0 0 {&******************************************* }3?00943 C 0 0 { Main Program } ?00944 C 0 0 { ******************************************* }'00945 0 0 00946 0 1 BEGIN'00947 0 1 E00948 0 1 open( ArgusKill, 'ARGUS$DIR:Argus.Kill', READONLY ); ^.00949 0 1 writeln ('Opened argus.kill');<00950 0 1 BuildProcessList( ArgusKill, ToAlwaysKill );00951 0 1 F00952 0 1 open( ArgusNot, 'ARGUS$DIR:Argus.NoKill', READONLY ); /00953 0 1 writeln('Opened argus.noKill'); 800954 0 1 BuildProcessList( ArgusNot, NotToKill );00955 0 1 N00956 0 1 open( ArgusNotSubs, 'ARGUS$DIR:Argus.NoKillSubs', READONLY ); 300957 0 1 writeln('Opened argus.noKillSubs');0=00958 0 1 BuildProcessList( ArgusNotSubs, NoKillSubs );400959 0 1 C00960 0 1 flcount := 0; active_count := 0; quit := false; 00961 0 1 F00962 0 1 new(sentinel); free := sentinel; root := sentinel;00963 0 1 #00964 0 1 first_flag := TRUE;^00965 0 1 init_item_list; 00966 0 1 00967 0 2 REPEAT00968 0 2 seedpid := -1;E00969 0 2 st := $trnlog('ARGUS_DEBUG', len, logname, table,,5);:E00970 0 2 IF SUBSTR(logname, 1, 4) = 'TRUE' THEN debug := false F00971 0 2 ELSE debug := false;00972 0 2 00973 0 2 time_synch; 00974 0 2 sstat := 0;1200975 0 2 kstat := $asctim(, t2, next_time);;00976 C 0 2 { WRITELN(' Current Time: ', t2); }S00977 0 2 ;00978 C 0 2 { Initialize all records to "not present" }000979 0 2 !00980 0 2 mark_not_present; 00981 0 2 000982 0 2 WHILE sstat <> SS$_NOMOREPROC DO00983 0 3 BEGINr;00984 0 3 sstat := $getjpi(1, seedpid,, item_list); &00985 0 3 wstat := $waitfr(1);,00986 0 3 IF (grpnum > system_group)800987 0 3 AND ( NOT (batch_run IN status) )400988 0 3 AND (sstat <> ss$_suspended )900989 0 3 AND (sstat <> ss$_nomoreproc) THEN 00990 0 4 BEGIN  _ARGUS4 13-Sep-1990 14:51:18 VAX Pascal V4.0-2 Page 19~01 Source Listing 13-Sep-1990 14:50:48 USERDISK7:[BRUCE.ARGUS]ARGUS.PAS;2 (1)-LINE-IDC-PL-SL-)00991 0 4 search(pid, p, junk); 200992 0 4 IF p = sentinel THEN new_entry900993 0 4 ELSE update_entry(p);00994 0 4 .00995 0 4 IF debug THEN debug_print;00996 0 4 00997 0 3 END;00998 0 2 END;00999 0 2 analyze;01000 0 2 01001 0 1 UNTIL quit;101002 0 0 END. dARGUS4 13-Sep-1990 14:51:18 VAX Pascal V4.0-2 Page 20~01 Pascal Compilation Statistics 13-Sep-1990 14:50:48 USERDISK7:[BRUCE.ARGUS]ARGUS.PAS;2 (1) PSECT SUMMARY^I Name Bytes Attributesih$CODE 10035 NOVEC,NOWRT, RD, EXE, SHR, LCL, REL, CON, PIC,ALIGN(2)h$LOCAL 56304 NOVEC, WRT, RD,NOEXE,NOSHR, LCL, REL, CON, PIC,ALIGN(2)ENVIRONMENT STATISTICSP -------- Symbols --------P File Total Loaded PercentPSYS$COMMON:[SYSLIB]STARLET.PEN;12 27303 184 1COMMAND QUALIFIERS PASCAL/LIST ARGUS,P /CHECK=(BOUNDS,NOCASE_SELECTORS,DECLARATIONS,NOOVERFLOW,NOPOINTERS,NOSUBRANGE) /DEBUG=(NOSYMBOLS,TRACEBACK) /NODESIGNiP /SHOW=(DICTIONARY,INCLUDE,NOINLINE,HEADER,SOURCE,STATISTICS,TABLE_OF_CONTENTS) /OPTIMIZE0 /STANDARD=NONE5 /TERMINAL=(NOFILE_NAME,NOROUTINE_NAME,NOSTATISTICS) - /USAGE=(NOUNUSED,UNINITIALIZED,NOUNCERTAIN)w /NOANALYSIS_DATA /NOENVIRONMENT* /LIST=USERDISK7:[BRUCE.ARGUS]ARGUS.LIS;1, /OBJECT=USERDISK7:[BRUCE.ARGUS]ARGUS.OBJ;1[ /NOCROSS_REFERENCE /ERROR_LIMIT=30 /NOG_FLOATING /NOMACHINE_CODE /NOOLD_VERSION /WARNINGSrCOMPILER INTERNAL TIMING? Phase Faults CPU Time Elapsed Time = Initialization 138 00:00.1 00:00.7P= Source Analysis 923 00:02.4 00:06.3 = Source Listing 5 00:00.4 00:02.1P= Tree Construction 124 00:00.4 00:00.8G= Flow Analysis 1 00:00.4 00:01.0 = Value Propagation 0 00:00.1 00:00.1 = Profit Analysis 36 00:00.3 00:00.7g= Context Analysis 206 00:02.6 00:05.2_= Name Packing 1 00:00.1 00:00.20= Code Selection 76 00:00.5 00:01.1i= Final 53 00:00.8 00:02.1 = TOTAL 1569 00:08.1 00:20.30COMPILATION STATISTICS5 CPU Time: 00:08.1 (7386 Lines/Minute)N Elapsed Time: 00:20.3e Page Faults: 1569 EARGUS4 13-Sep-1990 14:51:18 VAX Pascal V4.0-2 Page 21~01 Pascal Compilation Statistics 13-Sep-1990 14:50:48 USERDISK7:[BRUCE.ARGUS]ARGUS.PAS;2 (1) Pages Used: 2719 Compilation Complete,')' ); 400738 1 2 write_to_accounting_log := TRUE;00739 1 2 END 000740 1 1 ELSE { Its a subprocess }K00741 1 1 WRITEV(kill_msg,' Subprocess ', HEX(w^.ppid, 8, 8), E00742 1 1 ' killed by ARGUS.',''(13)''(10)''(7),-^00743 1 1 ' (Inactive for', idle_t:3, ' minutes.)',''(13)''(10),;00744 1 1 *[BRUCE.ARGUS]ARGUS.NOKILL;1+,4./ 4K-%0123KPWO566ʓ7 rfϒʓ89GHJ N P# Executables ARGUS will NOT KILL!K-----Enter executables on separate lines, be sure to use unique names.-----[ingres.bin]ckpdb.exe [response[sysexe]rtpad.exeabf.exe adminbox.exe backend.exe backup.exedecw$ digicalc.exedrb.exe edt020010.exefstm.exeii_pc_ing_backpdl.exeqbf.exe report.exeresp$run:monitor.exeresp$run:response.exe sreport.exesyscbi]syslib]debugshr.exe topframe.exe vifred.exe*[BRUCE.ARGUS]ARGUS.NOKILLSUBS;1+,_ D./ 4K-%0123KPWO56@$ɓ7`Sϒʓ89GHJ N P. Subprocess Executables ARGUS will NOT KILL!K-----Enter executables on separate lines, be sure to use unique names.-----lsedittpu*[BRUCE.ARGUS]ARGUS.OBJ;1+,4.(/ 4((-%0123KPWO)56@lʓ7ϒʓ89GHJ$1ARGUS40113-Sep-1990 15:0613-Sep-1990 15:06VAX Pascal V4.0-2 ARGUS4P*NT*:Q*NT*:Q term Qcpu io Q^cpu Q ^io Qidle_countQproc_cnt Q[2J [1;1fQ This process killed by ARGUS.Q Q (Inactive forQ minutes.) (Killed Q Subprocess killed by ARGUS.Q Q (Inactive forQ minutes.) (Killed QAn Argus Kill of:QPID: QError writing to accounting log status:Q**KILLING Q PID:Q, Term:Q SQKilled parentQ ****WARNING**** Q This terminal has been idle for minutes,Q and will be killed in Q minutes.Q ****WARNING****'  Subprocess has been idle for Q minutes,' and will be killed in Q minutes.Q WARNING Q PID:Q, Term:Q SQANALYZE -------------------------------------------------------Q term Qcpu io Q^cpu Q ^io Qidle_countQproc_cnt QFirst call to kill_parentQLast remove from outside kill_parent.QDEBUG PRINT ---------------------------------------------Q No userNtermQ [ CPU: Q PRC-Q Parent Child Detach Batch job.Q Network job.Qmp Q. Q ARGUSKILLQARGUSNOTQ ARGUSNOTSUBSQARGUS$DIR:Argus.KillOpened argus.killQARGUS$DIR:Argus.NoKillQOpened argus.noKillQARGUS$DIR:Argus.NoKillSubsQOpened argus.noKillSubsQARGUS_DEBUGQTRUE  4$&8(024<>@ HJ L$PT VX2`b d(hlnpxz|02,P<|^ԭ PAS$HANDLERm(x(PЏ\QwR QRRb+Q\QQ\QRSQTQSwU QUUV SVVefמV SVVf-PTRQQ\PRPx^ԭ PAS$HANDLERm(F(x\TgxPUU\TV TP@xW-g -VPT\PVPP\\\\P^ԭ PAS$HANDLERmм\0̣4PPPP̧4̣̯PPPP̫̯̻P(QPQPPR RSCCPQ(P PP+@,PQ PQQ+a̻̿1(1PT̟̔-̘ ̿1VP̿1>P̿1 TPP @̧̿1 TTD̫̿1̿1'P̿1̧̿1̫̿1    SYS$GETJPIP SYS$WAITFRP(P PP+@JGP̿̿<^ԭ PAS$HANDLERm@080\Ь0<ݏPAS$NEW2P\l , ̘P QPQPPR RST RTTdC̗PQ8̟PPR R QS RSScA P4̣4̷̧̯̫̳̻̔̿P(QPQPPR RSCCPQ(P PP+@04\4^ԭ PAS$HANDLERmм\  PAS$FV_OUTPUTPAS$WRITE_CHARl PAS$HEX PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUTPAS$WRITE_CHAR PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUTPAS$WRITE_CHAR@~ PAS$FV_OUTPUTPAS$WRITE_CHAR P@+П PAS$FV_OUTPUT PAS$WRITELN2 PAS$FV_OUTPUTPAS$WRITE_STRING̘ PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUTPAS$WRITE_CHARh PAS$FV_OUTPUTPAS$WRITE_STRING̣ PAS$FV_OUTPUTPAS$WRITE_INTEGER PAS$FV_OUTPUTPAS$WRITE_CHAR3 PAS$FV_OUTPUTPAS$WRITE_STRING̯ PAS$FV_OUTPUTPAS$WRITE_INTEGER PAS$FV_OUTPUTPAS$WRITE_CHAR PAS$FV_OUTPUTPAS$WRITE_STRINĢ PAS$FV_OUTPUTPAS$WRITE_INTEGER PAS$FV_OUTPUTPAS$WRITE_STRING̫ PAS$FV_OUTPUTPAS$WRITE_INTEGER PAS$FV_OUTPUTPAS$WRITE_STRING̿ PAS$FV_OUTPUTPAS$WRITE_INTEGER PAS$FV_OUTPUTPAS$WRITE_STRING̻ PAS$FV_OUTPUTPAS$WRITE_INTEGER PAS$FV_OUTPUT PAS$WRITELN2 ^мV\\ƿWVЭPRRS48PS`4ЭЭPРѽSѭ8PAS$HALTЭPЭP(ѭV1\\ݏPAS$WRITEV_CHAR\ݏPAS$WRITEV_STRING\ݏPAS$WRITEV_CHAR\ݏPAS$WRITEV_STRING%\ݏPAS$WRITEV_STRING\ݏPAS$WRITEV_STRING\ݏPAS$WRITEV_STRINGW\ݏPAS$WRITEV_INTEGERj \ݏPAS$WRITEV_STRINGY\ݏPAS$WRITEV_STRING@\ݏPAS$WRITEV_STRING\ݏPAS$WRITEV_STRING)\ݏPAS$WRITEV_CHAR\1\\ݏPAS$WRITEV_STRINGf PAS$HEX\ݏPAS$WRITEV_STRING\ݏPAS$WRITEV_STRING\ݏPAS$WRITEV_STRING\ݏPAS$WRITEV_STRINGW\ݏPAS$WRITEV_INTEGER \ݏPAS$WRITEV_STRINGv\ݏPAS$WRITEV_STRING]\ݏPAS$WRITEV_STRING\ݏPAS$WRITEV_STRING)\ݏPAS$WRITEV_CHAR SYS$ASSIGN<\~^02~ SYS$QIOT SYS$SETIMR SYS$WAITFRf2~ SYS$DASSGN SYS$DELPRC\1<<ݏPPAS$WRITEV_STRING <ݏPPAS$WRITEV_STRING;<ݏPPAS$WRITEV_CHARR<ݏPPAS$WRITEV_STRINGf PAS$HEX<ݏPPAS$WRITEV_STRING;<ݏPPAS$WRITEV_CHAR@~<ݏPPAS$WRITEV_CHAR<ݏPPAS$WRITEV_STRING.<ݏPPAS$WRITEV_CHAR SYS$SNDJBCWP\\' PAS$FV_OUTPUTPAS$WRITE_STRING \ PAS$FV_OUTPUTPAS$WRITE_INTEGER\ LIB$SIGNALV\ PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUTPAS$WRITE_STRINGk PAS$FV_OUTPUTPAS$WRITE_STRINGl PAS$HEX PAS$FV_OUTPUTPAS$WRITE_STRING: PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUTPAS$WRITE_CHAR PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUTPAS$WRITE_CHAR̔ PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUT PAS$WRITELN2V^м\ЭPPR148QPa4ЭЭQСѽPЭP.PR1ЭPZPR1# PAS$FV_OUTPUTPAS$WRITE_STRING PAS$HEX PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUT PAS$WRITELN2\+Pѭ4`4Э\``\0`Э0\@<^ԭ PAS$HANDLERmм\T SYS$BINTIM̿V PP@PVPW\ЭPRRS48PS`4ЭЭPРѽSѭ8PAS$HALTЭPЭP(ѭ\1DDݏPAS$WRITEV_STRINGDPAS$WRITEV_STRING$DݏPAS$WRITEV_STRINGVDݏPAS$WRITEV_INTEGER DݏPAS$WRITEV_STRING}DݏPAS$WRITEV_STRINGdDݏPAS$WRITEV_STRINGWDݏPAS$WRITEV_INTEGERR DݏPAS$WRITEV_STRING1D8(DݏPAS$WRITEV_STRINGl PAS$HEXDݏPAS$WRITEV_STRINGDݏPAS$WRITEV_STRINGVDݏPAS$WRITEV_INTEGER DݏPAS$WRITEV_STRINGDݏPAS$WRITEV_STRINGWDݏPAS$WRITEV_INTEGER DݏPAS$WRITEV_STRING찏 SYS$ASSIGN<D~Fݏ"2~ SYS$QIOT SYS$SETIMR SYS$WAITFRl    SYS$ GETJPIP SYS$WAITFRP4̣̯2~ SYS$DASSGN\W PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUTPAS$WRITE_STRINGg PAS$HEX PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUTPAS$WRITE_CHAR PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUTPAS$WRITE_CHARǔX PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUT PAS$WRITELN2\P^ԭ PAS$HANDLERm? PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUT PAS$WRITELN2\ԭ41ЭP1RЭ[1 PAS$FV_OUTPUTPAS$WRITE_CHAR PAS$HEX PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUTPAS$WRITE_CHARk PAS$HEX PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUTPAS$WRITE_CHAR PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUTPAS$WRITE_CHARS@~ PAS$FV_OUTPUTPAS$WRITE_CHARS SP@+؟ PAS$FV_OUTPUT PAS$WRITELN2% PAS$FV_OUTPUTPAS$WRITE_STRING˘ PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUTPAS$WRITE_CHAR PAS$FV_OUTPUTPAS$WRITE_STRINGˣ PAS$FV_OUTPUTPAS$WRITE_INTEGER PAS$FV_OUTPUTPAS$WRITE_CHAR PAS$FV_OUTPUTPAS$WRITE_STRING˯ PAS$FV_OUTPUTPAS$WRITE_INTEGER PAS$FV_OUTPUTPAS$WRITE_CHAR PAS$FV_OUTPUTPAS$WRITE_STRING˧ PAS$FV_OUTPUTPAS$WRITE_INTEGERn PAS$FV_OUTPUTPAS$WRITE_STRING˫ PAS$FV_OUTPUTPAS$WRITE_INTEGERN PAS$FV_OUTPUTPAS$WRITE_STRING˿ PAS$FV_OUTPUTPAS$WRITE_INTEGER2 PAS$FV_OUTPUTPAS$WRITE_STRING˻ PAS$FV_OUTPUTPAS$WRITE_INTEGER PAS$FV_OUTPUT 5VǎC  U6IJ `  PAS$WRITELN2쟫PT TP@U@V˿U˿Vϻ1˿V1Э[˳WЭ[˷X\쟭쟭i PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUT PAS$WRITELN2,% PAS$FV_OUTPUTPAS$WRITE_STRING PAS$HEX PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUT PAS$WRITELN2ѭ4ЭPР4ЭPЭ[ЫЭPРYЭP0Э0Y@<RRЭЭPРPѭ4`4Э[``Z0`Э0Z@<ѭ81^ԭ PAS$HANDLERm9 PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUT PAS$WRITELN2 PAS$FV_OUTPUTPAS$WRITE_CHAR PAS$HEX PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUTPAS$WRITE_CHAR$g PAS$FV_OUTPUTPAS$WRITE_STRING\$R\R\\P PP` PAS$FV_OUTPUTPAS$WRITE_CHAR\R  PAS$FV_OUTPUTPAS$WRITE_STRINGR \R\RRP PP` PAS$FV_OUTPUTPAS$WRITE_CHARR\˟ PAS$FV_OUTPUTPAS$WRITE_STRING PAS$OCT PAS$FV_OUTPUTPAS$WRITE_STRING, PAS$FV_OUTPUTPAS$WRITE_CHAR PAS$OCT PAS$FV_OUTPUTPAS$WRITE_STRING]~ PAS$FV_OUTPUTPAS$WRITE_CHAR$ PAS$FV_OUTPUTPAS$WRITE_STRING4 PAS$FV_OUTPUTPAS$WRITE_INTEGER PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUTPAS$WRITE_STRING 8 PAS$FV_OUTPUTPAS$WRITE_STRING8 PAS$FV_OUTPUTPAS$WRITE_STRING8 PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUTPAS$WRITE_STRING0 PAS$HEX PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUT PAS$WRITp~ ARGUS.BCK4%[BRUCE.ARGUS]ARGUS.OBJ;1( ELN2 PAS$FV_OUTPUT PAS$WRITELN20^1Џԭ<,ԭQUAMULЏح SYS$ASCTIMP\аҞحԟ SYS$BINTIMP\QUADIV(QUAMUL}( ( QUAADD( SYS$SCHDWK SYS$HIBER|^ԭ PAS$HANDLERmݬ PAS$RESET2ЬRݏRh PAS$HANDLER SYS$GETJPI SYS$WAITFRPAS$NEW2 PAS$FV_OUTPUTPAS$WRITE_CHARPAS$HEXPAS$WRITE_STRING PAS$WRITELN2PAS$WRITE_INTEGERPAS$HALTPAS$WRITEV_CHARPAS$WRITEV_STRINGPAS$WRITEV_INTEGER SYS$ASSIGNSYS$QIO SYS$SETIMR SYS$DASSGN SYS$DELPRC SYS$SNDJBCW LIB$SIGNAL SYS$BINTIMPAS$OCTQUAMUL SYS$ASCTIMQUADIVQUAADD SYS$SCHDWK SYS$HIBER PAS$RESET2PAS$READ_STRINGPAS$READ_STRINGR PAS$READLN2hݏ PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUT PAS$WRITELN2ЬP0``PAS$LOOK_AHEAD1`PQQQPP,- 1ЬPݏPhPAS$READ_STRINGЏhЏ쟭 STR$UPCASE  PAS$FV_OUTPUTPAS$WRITE_INTEGERE PAS$FV_OUTPUTPAS$WRITE_STRINGVc PAS$FV_OUTPUTPAS$WRITE_CHAR PRPЬRc@V VRBSc  PAS$FV_OUTPUT PAS$WRITELN2 P VPPЬR-@ R RRЬP,- BЬRݏRhPAS$READ_STRINGR PAS$READLN2ЬP0``PAS$LOOK_AHEAD1`PR鏌RRPP1ݬ PAS$CLOSE2^ԭ PAS$HANDLERmP`P `P`  PAS$OPEN2  PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUT PAS$WRITELN2> PAS$OPEN2 PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUT PAS$WRITELN2短 PAS$OPEN2 PAS$FV_OUTPUTPAS$WRITE_STRING PAS$FV_OUTPUT PAS$WRITELN2Jϲ<@\ݏPAS$NEW2P88084ϪЏĞȟğܰ g SYS$TRNLOGPTPP PPPPP)`B(ЏĞȟ SYS$ASCTIMPU4VЦVV81!  SYS$GETJPIP SYS$WAITFRP181 W48PW`4ЭحЭPРѽWѭ8υ8珨 1,ϟ\1]PPAS$CLOSE_LOCAL_R3<x^ԭ PAS$HANDLERm(x\RR RP@ٟxσP\R\\\R\\PPII_PC-  [SYSEXE]TPU.EXE- SYSEXE]MAIL.EXE- - QE-  QE- QE...................- [SYSEXE]TPU.EXE-  [SYSEXE]LSEDIT.EXE- [SYSEXE]EDT.EXE- [SYSEXE]EDIT.EXE-   Q$Q 0 00:00:01PQQNQQ=Q Q3Q6Q QQ QQ0QQ(QQ^ QfQ QQQQ Q-QQQQQQQ QQQQQ QQ QQ pQg QQ+QQ!Q @QQ,QQ!QQNQ(QQ&^QY9QIQ1QQGQQQ(QQQQGQl Q QtQPQ*QQ&QQwQG"Q1QQ4QQ Q Q Q QQ'"Q0GQPQ Q@SQCQ QQQKQQ8Q?QIQQ8QQQ%QQQQQ|QSQ($Q1 QQAQn4Q,QS QQQQQ@ QQ>Q yQ lQ _Q"Q Q QQL Q$QQ PAS$READLN2PAS$LOOK_AHEAD STR$UPCASE PAS$CLOSE2 PAS$OPEN2 SYS$TRNLOGPAS$CLOSE_LOCAL_R33'$CODE$LOCAL$ IJ ǎހ < , ' 2 $CODE3'$LOCAL #ARGUS4INIT_ITEM_LIST !BUILDPROCESSLIST 0+ MATCHINDEX  PINLIST m&THRESHOLDINDEX [R UPDATE_ENTRY @  NEW_ENTRYP R  TIME_SYNCH W LOGPRINT   WARN_USER p_  KILL_PROCESS  KILL_PARENTP 0$dANALYZE < DEBUG_PRINTP $ #SV_OUTPUTPAS$WRITE_STRING̘*[BRUCE.ARGUS]ARGUS.PAS;1+,O.?/ 4[??-%0123KPWO@56 @ʓ7JВʓ89GHJ N P`7[INHERIT('SYS$LIBRARY:STARLET')]PROGRAM argus4(OUTPUT);{A ARGUS4... Program to kill inactive processes. Requires the< QUADMATH package, which provides 64-bit arithmetic for messing with system times.H Also requires 3 files : "ARGUS$DIR:ARGUS.KILL" list of processes to( always kill regardless of activity.L "ARGUS$DIR:ARGUS.NOKILL" list of processes not& to kill regardless of inactivity.L "ARGUS$DIR:ARGUS.NOKILLSUBS" list of processes= not to kill child subprocesses regardless of inactivity. $ Version 1.0 5/11/84? Version 1.5 7/18/88 MVU only kill mail phase it in* Version 2.0 7/25/88 MVUN Version 3.0 2/24/89 MVU write killed user to accounting log David A. Johnson Synertek, Inc. MS 37 3001 Stender Way Santa Clara, CA 95054 (408) 988-5839}{) 1. Five minute intervals (3 before kill)4 3. Don't blow away any processes with active images}M{---------------------------------------------------------------------------}M{ EDIT HISTORY }M{ }N{ 06/29/88 MVU Added ability to choose processes in which to kill user, }N{ not to kill user, and ability to kill him in any process }N{ which is inactive. } M{ 07/26/88 MVU Parents killed along with child. }M{ 08/09/88 MVU Ability to kill processes at different time intervals }M{ 02/24/89 MVU Write killed user name to accounting log }M{ 09/10/90 BCZ Don't kill subprocesses of chosen images (LSE, TPU) }M{ and "fixed" notification routines to stop hangs }M{---------------------------------------------------------------------------}CONST3 interval = 5; { Five-minute interval }C system_group = 7; { Groups "system_group" & lower exempt }, io_threshold = 0; { Buffered IO's }6 cpu_threshold = 30; { In 10-millisecond TICKs }A n_to_warning = 2; { Number of intervals before warning }> n_to_kill = 4; { Number of intervals before kill }8 { for other processes, editors have longer time } editor_n_to_warning = 10; editor_n_to_kill = 12; A MAXNOPROCESSES = 140; { MVU number of processes in A list }8 nothresholds = 5; { number of special thresholds }H NoCommentLines = 2; { no. of comment lines in process list files }TYPE longword = INTEGER; byte = [BYTE] -128..127;" word = [WORD] -32768..32767;* name = PACKED ARRAY [1..23] OF CHAR;+ str = PACKED ARRAY [1..128] OF CHAR;, quadword = PACKED ARRAY [1..2] OF INTEGER;) alfa7 = PACKED ARRAY [1..7] OF CHAR;* alfa12 = PACKED ARRAY [1..12] OF CHAR;* alfa23 = PACKED ARRAY [1..23] OF CHAR; TEXTFILE = Text;( ans_type = (lword, string, flag_word);F flag_type = (pcb00, pcb01, pcb02, pcb03, pcb04, pcb05, pcb06, pcb07,J pcb08, pcb09, pcb10, pcb11, pcb12, pcb13, batch_run, pcb15,L pcb16, pcb17, pcb18, pcb19, pcb20, network_run, pcb22, pcb23,G pcb24, pcb25, pcb26, pcb27, pcb28, pcb29, pcb30, pcb31); sts_word = SET OF flag_type;  item_type= PACKED RECORD bl,item_code:word; CASE ans_type OF lword:(pdata:^longword; pld:^longword); string:(pstrg:^str; pls:^longword); flag_word:(fdata:^sts_word; fls:^longword); END; list_type= PACKED RECORD' itm:ARRAY [1..20] OF item_type; END; ref = ^proc_data_type; proc_data_type = RECORD ppid:longword; fptr:ref; user:alfa12; image_name:str; owner_pid:longword; term:alfa7; stat:sts_word;< cpu,delta_cpu,delta_io,io,grp,mem,proc_cnt,idle_count :longword; present:BOOLEAN; masterpid:longword; END;B process_list_type = array [1..MAXNOPROCESSES] of [VOLATILE] str;I { Process list structure , - terminates string, -terminates number of processes. }V threshold_type = record { varying processes, have longer cpu and io thresholds }9 imagename : array[ 1..nothresholds] of [VOLATILE] str;< io : array[ 1..nothresholds] of longword;/ cpu : array[ 1..nothresholds] of longword;3 numTOwarn : array[ 1..nothresholds] of integer; 4 numTOkill : array[ 1..nothresholds] of integer;  end;T sndjbc_itemlist_type = record { item list for sndjbcw used to write to oprlog} buflen : word; item : word; bufadr : unsigned; retlen : longword; end;K{-------------------------------------------------------------------------}VARQ sndjbc : array[1..2] of sndjbc_itemlist_type; {item list for $sndjbcw call } i,j,k,sstat,st:INTEGER; kstat,wstat:INTEGER; flag_mask:INTEGER; len:word; logname:name; table:byte; debug:BOOLEAN;& grpnum,memnum,pid:[VOLATILE]INTEGER; thepid: [VOLATILE]UNSIGNED;' bufio,prccnt,owner:[VOLATILE]INTEGER; seedpid:[VOLATILE]UNSIGNED;7 imagname,terminal,username,processname:[VOLATILE]str;4 pl,ulen,ilen, plen, master_pid:[VOLATILE]longword; cputim:[VOLATILE]longword; status:[VOLATILE]sts_word; item_list:list_type; quit,first_flag:BOOLEAN; t2:alfa23;& qdelta,last_time,next_time:quadword;! p,free,root,sentinel, junk:ref; flcount,active_count:longword; warn_msg:VARYING[132] OF CHAR;! wait_time:varying[132] OF CHAR; wait_once:record l1,l2 : integer; end; kill_msg:VARYING[132] OF CHAR;[ accountinglogmsg: [volatile ] VARYING[80] OF CHAR; { buffer used to write accounting log} tty:alfa7; victim:UNSIGNED;B ING_II_BACK : [VOLATILE] STR; { ingres back ground II process }= TPU_PARENT : [VOLATILE] STR; { tpu spawns idle children }5 MAIL : [VOLATILE] STR; { tmp just kill mail now }F NotToKill : process_list_type; { processes not to kill regardless }J NoKillSubs : process_list_type; { Subprocesses not to kill regardless }T ToAlwaysKill : process_list_type; { processes to always kill based on time used }E ArgusKill : TEXTfile; { file contains list of processes to kill}I ArgusNot : TEXTfile; { file contains list of not to kill processes}M ArgusNotSubs : TEXTfile; { file contains list of not to kill processes} threshold : threshold_type;VALUE ING_II_BACK := 'II_PC-';# TPU_PARENT := '[SYSEXE]TPU.EXE-';< MAIL := 'SYSEXE]MAIL.EXE-'; {tmp vers1.5 just kill mail }@ flag_mask := 6; { mask for flags 1 & 2 }? wait_time := '0 00:00:01'; {time-out wait - 1 second}$ NotToKill[1] := '-'; { mt list } NoKillSubs[1] := '-'; ToAlwaysKill[1] := '-';O threshold.imagename[1] := '...................-'; { normal threshold images }" threshold.io[1] := io_threshold;$ threshold.cpu[1] := cpu_threshold;) threshold.numTOwarn[1] := n_to_warning;& threshold.numTOkill[1] := n_to_kill;/ threshold.imagename[2] := '[SYSEXE]TPU.EXE-'; threshold.io[2] := 12;$ threshold.cpu[2] := cpu_threshold;0 threshold.numTOwarn[2] := editor_n_to_warning;- threshold.numTOkill[2] := editor_n_to_kill;2 threshold.imagename[3] := '[SYSEXE]LSEDIT.EXE-'; threshold.io[3] := 12;$ threshold.cpu[3] := cpu_threshold;0 threshold.numTOwarn[3] := editor_n_to_warning;- threshold.numTOkill[3] := editor_n_to_kill; / threshold.imagename[4] := '[SYSEXE]EDT.EXE-';" threshold.io[4] := io_threshold;$ threshold.cpu[4] := cpu_threshold;0 threshold.numTOwarn[4] := editor_n_to_warning;- threshold.numTOkill[4] := editor_n_to_kill; 0 threshold.imagename[5] := '[SYSEXE]EDIT.EXE-';" threshold.io[5] := io_threshold;$ threshold.cpu[5] := cpu_threshold;0 threshold.numTOwarn[5] := editor_n_to_warning;- threshold.numTOkill[5] := editor_n_to_kill; 5PROCEDURE quadiv(a,b:quadword;VAR c:quadword);EXTERN;5PROCEDURE quamul(a,b:quadword;VAR c:quadword);EXTERN;5PROCEDURE quaadd(a,b:quadword;VAR c:quadword);EXTERN;PROCEDURE str$upcase(: %stdescr dest: str {packed[l1..h1: integer] of char};D %stdescr from: str {packed[l2..h2: integer] of char} ); extern;[EXTERNAL,ASYNCHRONOUS]7PROCEDURE LIB$SIGNAL ( condition : [immediate] INTEGER;8 FAO_Params : [unsafe,list,immediate] INTEGER ); EXTERN;I{-----------------------------------------------------------------------}I{ init_item_list -- initializes item list for $getjpi call and }I{ $sndjbc call }I{-----------------------------------------------------------------------}PROCEDURE init_item_list;BEGINEWITH item_list.itm[1] DO BEGIN bl := 7; item_code := jpi$_terminal;8 pstrg := ADDRESS(terminal); pls := ADDRESS(pl); END;CWITH item_list.itm[2] DO BEGIN bl := 4; item_code := jpi$_cputim;! pdata := ADDRESS(cputim); END;@WITH item_list.itm[3] DO BEGIN bl := 4; item_code := jpi$_sts;! fdata := ADDRESS(status); END;@WITH item_list.itm[4] DO BEGIN bl := 4; item_code := jpi$_pid; pdata := ADDRESS(pid); END;@WITH item_list.itm[5] DO BEGIN bl := 4; item_code := jpi$_grp;! pdata := ADDRESS(grpnum); END;EWITH item_list.itm[6] DO BEGIN bl := 12; item_code := jpi$_username;: pstrg := ADDRESS(username); pls := ADDRESS(ulen); END;BWITH item_list.itm[7] DO BEGIN bl := 4; item_code := jpi$_bufio; pdata := ADDRESS(bufio); END;EWITH item_list.itm[8] DO BEGIN bl := 50; item_code := jpi$_imagname;: pstrg := ADDRESS(imagname); pls := ADDRESS(ilen); END;CWITH item_list.itm[9] DO BEGIN bl := 4; item_code := jpi$_prccnt;! pdata := ADDRESS(prccnt); END;CWITH item_list.itm[10] DO BEGIN bl := 4; item_code := jpi$_owner; pdata := ADDRESS(owner); END;AWITH item_list.itm[11] DO BEGIN bl := 4; item_code := jpi$_mem;! pdata := ADDRESS(memnum); END;CWITH item_list.itm[12] DO BEGIN bl := 4; item_code := jpi$_owner;% pdata := ADDRESS(master_pid); END;DWITH item_list.itm[13] DO BEGIN bl := 50; item_code := jpi$_prcnam;= pstrg := ADDRESS(processname); pls := ADDRESS(plen); END;@item_list.itm[14].item_code := 0; item_list.itm[14].bl := 0;# { $smdjbcw call item list } sndjbc[1].buflen := 80;, sndjbc[1].item := sjc$_accounting_message;1 sndjbc[1].bufadr := IADDRESS(accountinglogmsg); sndjbc[1].retlen := 0;+ sndjbc[2].buflen := 0; { terminator }< sndjbc[2].item := 0; { is a longword } END {init_item_list};O{-----------------------------------------------------------------------------}R{ BuildProcessList - build process_list_type variable from specified input fil.e}O{ INPUT : filvar -- of file to build list from }O{ processList -- name of process list var to build }O{ OUTPUT: processlist var filed in with names from file }O{ NOTE: FILVAR MUST BE OPENED }O{-----------------------------------------------------------------------------}YPROCEDURE BuildProcessList( VAR filvar : textfile; VAR processlist : process_list_type );VAR# exename, name : [VOLATILE] str; j : integer;BEGIN RESET(filvar); i := 1;B WHILE ( i <= NoCommentLines ) AND (NOT(EOF(filvar)) ) DO BEGIN0 READLN(filvar,exename); {skip comment lines} IF i = 1 THEN WRITELN(exename); i := i + 1 END;A processlist[1] := '-'; { set up as mt list in case file mt } i := 1;A WHILE ( i <= MAXNOPROCESSES) AND (NOT(EOF(filvar)) )DO BEGIN READ( filvar, exename );8 str$upcase ( name, exename ); { make name upper case } WRITE( i, '. ' ); j := 1;" WHILE ( name[j] <> ' ' ) DO BEGIN write( name[j] );! processlist[i,j] := name[j]; j := j + 1; END; writeln; processlist[i,j ] := '-';< IF name[1] <> ' ' THEN { not an mt string grab next one} BEGIN processlist[i+1] := '-'; i := i + 1 END;9 readln( filvar, exename ) {skip rest of line, ignored } END; CLOSE(filvar)END; {BuildProcessList}N{----------------------------------------------------------------------------}N{ matchINDEX -- returns location that object matches pattern }N{ INPUT : object string terminated by '+' }N{ pattern string terminated by '-' }N{ OUTPUT: integer index in object string if matched otherwise 0 }N{----------------------------------------------------------------------------}DFUNCTION matchINDEX ( object, pattern : [VOLATILE ] str ) : integer;VAR notfound : boolean;! i, j, len, posindex : integer;BEGIN notfound := true; len := LENGTH( object ); i := 1; while ( i <= len ) DO BEGIN* IF object[i] = '+' THEN len := i - 1; i := i + 1;  END; i := 1;) matchINDEX := 0; { guess not find }* WHILE (i <= len ) AND notfound DO BEGIN j := 1; posindex := i;@ WHILE ( object[i] = pattern[j] ) DO BEGIN { + stops loop }( i := i + 1; j := j + 1; END;  IF pattern[j] = '-' THEN  BEGIN notfound := false; matchINDEX := posindex; END; i := i + 1 ENDEND; {matchINDEX}O{-----------------------------------------------------------------------------}O{ InList -- returns indication whether process is in specified process list}O{ INPUT : list to check, image name str }O{ OUTPUT: true -- member of list }O{ false -- not in list }O{-----------------------------------------------------------------------------}SFUNCTION InList( list : process_list_type; image_name : [VOLATILE] str ) : BOOLEAN;VAR! position, i, total : INTEGER;BEGIN total := 0; i := 1;S WHILE (( i <= MAXNOPROCESSES) AND ( total = 0 )) AND ((list[i] <> '-') )DO BEGIN5 position := matchINDEX ( image_name, list[i] ); total := total + position; i := i + 1; END; {WHILE} InList := NOT(total = 0) END; {InList}O{-----------------------------------------------------------------------------}P{ thresholdINDEX -- computes index into threshold array for image name }#{ INPUT : image name }O{ OUTPUT: index of threshold which belongs to special process }P{ Note: index of 1 indicates the normal thresholds }O{-----------------------------------------------------------------------------}AFUNCTION thresholdINDEX ( imagename : [VOLATILE] str ) : INTEGER;VAR i, found : INTEGER;BEGIN found := 0; i := 0;; WHILE ( (i < nothresholds ) AND ( found = 0 )) DO BEGIN i := i + 1;: found := matchINDEX ( imagename, threshold.imagename[i] ) END;M IF found = 0 THEN thresholdINDEX := 1 { 1 contains normal thresholds } ELSE thresholdINDEX := i;END; {thresholdINDEX }/{&******************************************* }PROCEDURE update_entry(w:ref);VAR  k : INTEGER; index : INTEGER;BEGIN WITH w^ DO BEGIN masterpid := master_pid;! delta_cpu := abs(cputim - cpu); cpu := cputim; delta_io := abs(bufio - io); io := bufio; proc_cnt := prccnt;5 FOR k := 1 to ilen DO image_name[k] := imagname[k]; image_name[ilen + 1] := '+'; processname[plen + 1] := '+'; present := TRUE;7 IF ( proc_cnt > 0 ) THEN { never kill a parent}  idle_count := 08 ELSE IF ( ilen > 0 ) THEN { have an image name } BEGIN. index := thresholdINDEX( image_name );O IF (owner_pid = 0) AND ((term = '*NT*:') AND (NOT(batch_run in stat)) ) A THEN idle_count := 0 { detached process no kill }v8 ELSE IF ( InList( NotToKill, image_name ) ) THEN idle_count := 0< ELSE IF ( InList ( ToAlwaysKill, image_name ) ) THEN' idle_count := idle_count + 1cX ELSE IF ( delta_cpu > threshold.cpu[index] ) THEN { not using substantial cpu } idle_count := 0M ELSE IF ( delta_io > threshold.io[index] ) THEN { BUFFER i/o count }  idle_count := 0 ELSE' idle_count := idle_count + 1e- END { end of have an image name }s# ELSE { Command process } s BEGIN7 IF ( matchINDEX( processname, ING_II_BACK) <> 0 ) then @ idle_count := 0 { Ingres spawning a child task, ignore him }Q ELSE IF ( delta_cpu > cpu_threshold ) THEN { not using substantial cpu }k idle_count := 0G ELSE IF ( delta_io > io_threshold ) THEN { BUFFER i/o count } idle_count := 0A ELSE IF ( owner <> 0 ) THEN { Subprocess of LSE or TPU}s begin-? thepid := owner; { grab info for this process }3 sstat := $getjpi( 1, thepid,,item_list); wstat := $waitfr( 1);' image_name[ilen + 1] := '+'; 7 IF ( InList( NoKillSubs, image_name ) ) THEN  idle_count := 0w ende ELSE' idle_count := idle_count + 1  END ENDyEND;/{&******************************************* } PROCEDURE new_entry;VAR  w:ref; k:INTEGER;BEGINl!active_count := active_count + 1; 9{ Obtain a record from the free list. If the Free List isf; empty, then get a new one from the Heap... }uIF free <> sentinel THEN  BEGIN w := free; free := w^.fptr; flcount := flcount - 1;m ENDSELSE new(w); !{ Now fill in the new record. }iw^.ppid := pid;o!IF pl = 0 THEN w^.term := '*NT*:'-= ELSE FOR k := 1 TO pl DO w^.term[k] := terminal[k];-w^.stat := status;.FOR k := 1 TO 12 DO w^.user[k] := username[k];w^.cpu := cputim; w^.delta_cpu := cputim;_w^.io := bufio;ew^.delta_io := bufio;ow^.grp := grpnum;fw^.mem := memnum;_w^.owner_pid := owner;w^.proc_cnt := prccnt;w^.idle_count := 0;26FOR k := 1 to ilen DO w^.image_name[k] := imagname[k];;w^.image_name[ilen + 1] := '+'; { delimit end of string } w^.present := TRUE;sw^.masterpid := master_pid;}${ Now enter it in the active list. }w^.fptr := root; root := w;END;/{&******************************************* }9PROCEDURE search(spid:longword;VAR w:ref; VAR prev: ref);BEGINL* w := root; sentinel^.ppid := spid; prev := root;" WHILE w^.ppid <> spid DO BEGIN prev := w;E w := w^.fptr; END;END;/{ ******************************************* } PROCEDURE mark_not_present;]VARR w:ref;BEGINC w := root;WHILE w <> sentinel DO BEGINC w^.present := FALSE; w := w^.fptr;P END;END;/{&******************************************* }FPROCEDURE time_synch;;VARn a,b,c:quadword;n s1:INTEGER; tx:alfa23;BEGINcIF first_flag THEN BEGIN0 first_flag := FALSE;> a[1] := 10000000; { One second in 100-nsec increments } a[2] := 0;0 b[1] := 60*interval; { interval in seconds } b[2] := 0;; quamul(a, b, qdelta); { Interval in system time format }p s1 := $asctim(,tx);_+ s1 := $bintim(tx, c); { Current time }= quadiv(c, qdelta, a);e quamul(a, qdelta, next_time);F END;last_time := next_time; &quaadd (last_time, qdelta, next_time);$schdwk(,, next_time);$hiber;pEND;/{&******************************************* } PROCEDURE remove(VAR a,z:ref);VAR tmp:ref;BEGIN IF a = root THEN root := a^.fptr$ ELSE z^.fptr := a^.fptr;8tmp := a^.fptr; a^.fptr := free; free := a; a := tmp;!active_count := active_count - 1;flcount := flcount + 1;END;N{----------------------------------------------------------------------------}N{ Logprint -- prints process infor to log file. }N{----------------------------------------------------------------------------}PROCEDURE Logprint( w : ref );BEGIN1 WITH w^ DO BEGIN & WRITE (' ', hex(ppid, 8, 8) ); WRITE ( ' ', user, ' ');  i := 1;r/ WHILE ( image_name[i] <> '+' ) DO BEGINy! WRITE ( IMAGE_NAME[i] );i i := i + 1;: END; WRITELN;( WRITE ( ' term ',term, ' ');5 WRITE ( 'cpu ',cpu:8, ' ', 'io ', io:8, ' ');t: WRITE ( '^cpu ',delta_cpu:6, ' ^io ', delta_io:6);- WRITE ( 'idle_count', idle_count:3 );t* WRITE ( 'proc_cnt ', proc_cnt:3 ); WRITELN;_ END; {WITH} END; {Logprint}n6{ ******************************************* }PROCEDURE warn_user(w:ref); VARd s1,s2,s3,s4 :INTEGER;d chan:word; pd:longword; target, junk :ref; idle_t, t_to_go:INTEGER; index : INTEGER;BEGIN $bintim(wait_time,wait_once);t!idle_t := w^.idle_count*interval; 'index := thresholdINDEX(w^.image_name);s8t_to_go := threshold.numTOkill[index]*interval - idle_t; target := w;WHILE target^.owner_pid <> 0 DOr BEGINu pd := target^.owner_pid; search( pd, target, junk ); ! IF target = sentinel THEN halt;R END;tty := target^.term;S IF target = w THEN WRITEV(warn_msg, ' ****WARNING****',''(13)''(10)''(7),aC ' This terminal has been idle for ', idle_t:2,[N ' minutes,',''(13)''(10),' and will be killed in ', + t_to_go:2, ' minutes.')P ELSE WRITEV(warn_msg, ' ****WARNING****'''(13)''(10)''(7)5 ' Subprocess ', HEX(w^.ppid, 8, 8),K ' has been idle for ', idle_t:2, ' minutes,'''(13)''(10), 5 ' and will be killed in ', , t_to_go:2, ' minutes.');3{ $brkthru( 2, warn_msg, tty,BRK$C_DEVICE,,,,5 );}K $assign(tty,chan);F $qio(2,chan,io$_writevblk+io$m_breakthru+io$m_enablmbx+io$m_refresh,1 ,,,warn_msg.body,warn_msg.length, , , , );{ $setimr(1,wait_once,,,); $waitfr(1);pL { MVU-- reset io and cpu usage to ignore the effect of writing out warning message. }8 thepid := w^.ppid; { grab info for this process }* sstat := $getjpi( 1, thepid,,item_list); wstat := $waitfr( 1);AO w^.cpu := cputim; { reset overall cpu time to ignore warn msg cpu time }:? w^.io := bufio; { reset io time to ignore warn msg io } A $dassgn(chan);  WITH w^ DO BEGINn) WRITE(' WARNING ', user, ' PID:');r- WRITE(HEX(ppid, 8, 8), ', Term:', tty);P WRITE(' ', t2, ' ');+ IF owner_pid <> 0 THEN WRITE(' S');  WRITELN; Logprint( w ); END;END;/{&******************************************* }m0PROCEDURE kill_process(w:ref; timemsg: boolean);VAR  pd:longword; chan:word; target, junk :ref; idle_t:INTEGER;s$ write_to_accounting_log : BOOLEAN; status : INTEGER;.BEGIN'!write_to_accounting_log := FALSE;e#idle_t := w^.idle_count * interval;h target := w;PWHILE target^.owner_pid <> 0 DO {search for the parent to get term send msg} BEGINk pd := target^.owner_pid; search(pd, target, junk);! IF target = sentinel THEN halt;l END;tty := target^.term;1IF target=w THEN { Its the owning project! }e BEGINT1 WRITEV(kill_msg,''(27),'[2J ',''(27),'[1;1f',nI ' This process killed by ARGUS.',''(13)''(10)''(7),[N ' (Inactive for', idle_t:3, ' minutes.)',''(13)''(10),+ ' (Killed ', t2,')' ); $ write_to_accounting_log := TRUE; END ELSE { Its a subprocess }; WRITEV(kill_msg,' Subprocess ', HEX(w^.ppid, 8, 8),r5 ' killed by ARGUS.',''(13)''(10)''(7),:N ' (Inactive for', idle_t:3, ' minutes.)',''(13)''(10),+ ' (Killed ', t2,')' );p0{$brkthru(2, kill_A~ ARGUS.BCKO%[BRUCE.ARGUS]ARGUS.PAS;1[?gr1msg, tty, BRK$C_DEVICE,,,,5);} $assign(tty,chan); $qio(2,chan,io$_writevblk,1 ,,,kill_msg.body,kill_msg.length, , , , );r $setimr(1,wait_once,,,); $waitfr(1);mvictim := w^.ppid;$dassgn(chan);$delprc(victim);{ Log to accounting Log }dIF write_to_accounting_log THENe BEGINd1 WRITEV ( accountinglogmsg, 'An Argus Kill of:',  w^.user, ';',t% 'PID: ', HEX(w^.ppid,8,8), ';',e '@', t2, '.');4 status := $SNDJBCW(FUNC := sjc$_write_accounting , - ITMLST := sndjbc);, IF status <> SS$_NORMAL THEN BEGINE WRITE ( 'Error writing to accounting log status:',status );-8 LIB$SIGNAL( status,0 ); { will quit program } END;d END; {IF} { Log to Argus's own log } WITH w^ DO BEGIN ' WRITE('**KILLING ', user, ' PID:');-+ WRITE(HEX(ppid, 8, 8), ', Term:', tty);- WRITE(' ', t2, ' ');) IF owner_pid <> 0 THEN WRITE(' S');B WRITELN; Logprint( w ); END;END;M{---------------------------------------------------------------------------}NP{ Kill_parent - recursive routine which kills all the parents, ie. grandparents}@{ great grand parent etc of a process. }M{ Input : child process }dM{ Output : all parents removed out of list, note calling process must remove}bG{ child from the list. }HM{---------------------------------------------------------------------------}A*PROCEDURE kill_parent ( VAR child : ref );VARI5 prev, w : ref; { must be store on stack }i timemsg : boolean; count : integer;BEGINi w := child;N timemsg := false;=F{ if debug then writeln ('Entered Kill_parent', HEX(w^.ppid,8,8) );};# IF w^.masterpid = 0 THEN BEGIN=+{ IF debug THEN WRITELN( 'REACHED ANCHOR');A } count := 0;  END ELSE  BEGINC search( w^.masterpid, w, prev ); { w becomes the parent here }S8 IF ( InList( NotToKill, w^.image_name )) THEN BEGIND{ IF debug THEN WRITELN(' Parent is not to kill,stop');} count := 0; ENDiF ELSE IF ( matchINDEX( w^.image_name, TPU_PARENT) <> 0) THEN BEGINC{ IF debug THEN WRITELN(' Parent is not to TPU,stop');r} count := 0; ENDA ELSE BEGINDJ if debug then writeln ('Killed parent', HEX(w^.ppid,8,8) );: kill_process( w, timemsg); { kill the parent }K{ if debug then writeln ( 'going to call kill_parent recursively.');S6} kill_parent( w ); { then kill its parents }B{ if debug then writeln ('Hey were back and removing w is',M HEX(w^.ppid,8,8));->} remove( w, prev ); { now remove parent from list of" active processes } ENDb ENDEND; {kill_parent}/{&******************************************* }rPROCEDURE analyze;VAR  w,wlast:ref; killed:BOOLEAN;n i : integer;$ childgrpnum, childmem: integer; timemsg : boolean;- number_to_warning, number_to_kill: integer;  index : integer;BEGINMYif debug then WRITELN('ANALYZE -------------------------------------------------------');-0timemsg := true; { display idle time when kill } wlast := NIL;u w:= root;iWHILE w <> sentinel DO BEGIN IF w^.present THEN BEGIN killed := FALSE; WITH w^ DOs BEGIN: IF debug THEN BEGIN;# WRITE (' ', HEX(w, 8, 8) );m& WRITE (' ', hex(ppid, 8, 8) ); WRITE ( ' ', user, ' ');  i := 1;/ WHILE ( image_name[i] <> '+' ) DO BEGIN ! WRITE ( IMAGE_NAME[i] );; i := i + 1; END; WRITELN;( WRITE ( ' term ',term, ' ');5 WRITE ( 'cpu ',cpu:8, ' ', 'io ', io:8, ' ');s: WRITE ( '^cpu ',delta_cpu:6, ' ^io ', delta_io:6);- WRITE ( 'idle_count', idle_count:3 );O* WRITE ( 'proc_cnt ', proc_cnt:3 ); WRITELN;= END;, index := thresholdINDEX( image_name );6 number_to_warning := threshold.numTOwarn[index];3 number_to_kill := threshold.numTOkill[index];]* IF (idle_count >= number_to_warning)0 AND (idle_count < number_to_kill) THEN  BEGIN;@ warn_user(w); { display warning msg only once } END ELSE BEGIN, IF idle_count >= number_to_kill THEN BEGINt childgrpnum := w^.grp;  childmem := w^.mem;% kill_process( w, timemsg );+6 if debug then writeln('First call to kill_parent'); kill_parent(w ); B if debug then writeln('Last remove from outside kill_parent.',  HEX(w^.ppid,8,8)); remove(w, wlast);- killed := TRUE;- END; END; IF NOT killed THEN BEGIN  wlast := w;  w := w^.fptr;n END; ENDo END {WITH} ELSE remove(w, wlast);r END;IEND;/{&******************************************* } PROCEDURE debug_print;BEGINBI WRITE ( 'DEBUG PRINT ---------------------------------------------');E WRITELN;% WRITE( ' ', HEX(pid, 8, 8), ' ');t( IF ulen <= 0 THEN WRITE (' No user') ELSE/ FOR I := 1 TO ulen DO WRITE(username[i]); ! IF pl = 0 THEN WRITE('Nterm')  ELSE- FOR i := 1 TO pl DO WRITE(terminal[i]);@ WRITE(' [', OCT(grpnum, 3, 3), ',', OCT(memnum, 3, 3), ']'); WRITE(' CPU: ', cputim:8); WRITE(' PRC-'); ) IF prccnt > 0 THEN WRITE(' Parent '); ) IF owner <> 0 THEN WRITE(' Child ');-@ IF (owner=0) AND (pl=0) AND (NOT (batch_run IN status)) THEN WRITE(' Detach ');5 IF batch_run IN status THEN WRITE(' Batch job.');c9 IF network_run IN status THEN WRITE(' Network job.'); + writeln( 'mp ',HEX(master_pid, 8, 8) ); WRITELN;END;/{&******************************************* } /{ Main Program } /{ ******************************************* }-BEGIN-5open( ArgusKill, 'ARGUS$DIR:Argus.Kill', READONLY ); Nwriteln ('Opened argus.kill');,BuildProcessList( ArgusKill, ToAlwaysKill );6open( ArgusNot, 'ARGUS$DIR:Argus.NoKill', READONLY ); writeln('Opened argus.noKill'); (BuildProcessList( ArgusNot, NotToKill );>open( ArgusNotSubs, 'ARGUS$DIR:Argus.NoKillSubs', READONLY ); #writeln('Opened argus.noKillSubs');t-BuildProcessList( ArgusNotSubs, NoKillSubs );W3flcount := 0; active_count := 0; quit := false;6new(sentinel); free := sentinel; root := sentinel;first_flag := TRUE;init_item_list; REPEATseedpid := -1;5st := $trnlog('ARGUS_DEBUG', len, logname, table,,5);n5IF SUBSTR(logname, 1, 4) = 'TRUE' THEN debug := falseh6 ELSE debug := false; time_synch; sstat := 0;h"kstat := $asctim(, t2, next_time);+{ WRITELN(' Current Time: ', t2); }-+{ Initialize all records to "not present" }Imark_not_present;m WHILE sstat <> SS$_NOMOREPROC DO BEGIN+ sstat := $getjpi(1, seedpid,, item_list);= wstat := $waitfr(1); IF (grpnum > system_group)( AND ( NOT (batch_run IN status) )$ AND (sstat <> ss$_suspended )) AND (sstat <> ss$_nomoreproc) THEN BEGINd search(pid, p, junk); " IF p = sentinel THEN new_entry) ELSE update_entry(p);{ IF debug THEN debug_print; END; END;analyze; UNTIL quit;DEND.te_entry(w:ref);VAR  k : INTEGER; index : INTEGER;BEGIN WITH w^ DO BEGIN masterpid := master_*[BRUCE.ARGUS]QUADMATH.OBJ;1+, c./ 4-%0123KPWO5 6KFÓ7`nQВʓ89GHJ N P3QUAMTH1.0110-MAR-1981 20:38 hVAX-11 Macro V02.45i QUADMATHQUAD WORD MATH PACKAGE . ABS .d . BLANK .nPs $CODEnPn QUAADDf&Ь PЬQ}`a`ءPe QUASUB &Ь PЬQ}`a`١.P  .QUAMULy&5ЬSЬTzcdPzcQQzdQQcdQdcQ}P \Pa \QUADIVa&VЬ X}hhhҨhV}PPPQQPQV|R|T?WyRRyTTWhTUQTPPTQURWV RRSSRS}RhlV TTUUTU}TP QUACMPs&&޼P޼QѠ `aPPPj QUAMTH QUAADD QUACMP \QUADIV .QUAMUL QUASUB, . BLANK .$CODE Y&~ ARGUS.BCK{[(4"o=loQ (qa3m>SG_MA}xABJU|xr>}'!X3 z`{ &9b^_eg<]|Z+CJnOjO_% 6볟+f55)z[p5Fdюxm9F|qM:*,(*nؾh]@˨όS9MIS!~W/j`4ܻ鸗I&3gsƆ!V3V7~MhNim1հ  lsty|"@ECW^s,M:C_  A??j6befo}sgRQLe$(DACJ'{h)-Di= |o{"|ke` tD7gjrɼKi }s m=lqoT!#paB/le"7EYkz.woRsj"WDHCB thRs+/`Vd/*$UF+W!b X45D)+C&tRvdctSZ,S4Q$z'S1,QoHh_&tw6D EfO|PD .>w1T+:*?a3,e7#U\m5LCPbm)k{0H6 _b@c* 2eir`@[*v5O-c~Sy@Y-_%+/,Ua0 = wGW ,G@?;{9Pv ESC?..4uA@9*]cG|CXW4=c;$5Enh]A4HX\N > s:W\X!LsgsAT8^BIL)nSSy7vvnwLM[34_FHDW9, dWBeziRTrD@Yr7~M7"lA(,"9)@nS[r7dkvAI^_S_[3 s*dgVt#n4:8binQ *ipvk\>{=e2!qO[TN ^N.AC0)Hh7[8jZ 7_?x1 ` R?s6 G &?t,?Uc>WV l *77=D-`~,Iq=h47!a\oIqLLGhYUSՌ s#;d,Q i[Q}Ʋ&)bMru|mm.VE- cOEUV)\B\N`3bKN_W,( ,C 2RDwEBvV!FWaj<Ӵ#ս%3.ci m d. R 0L7Q0oiThB_FC "ƍN' R8UMuzaKly3H} _T@Y:B1yu}bӸL_s۞$>׮P⁄džV{wS42tkks!2,_~eVvQ{5ey*1շ1g%*T$BU/GzaVRbXKk `93Kr~q~JoH?CHUBY[OUkY Y=H1)V"E$88~c]j6+3C@RK9K@K8E6Ah7ur)UT2/;e-b7DJEPQZZGQ@w& KyFox'lLVF$y% IwBo6F9nO r=[XXDCN'+}#]Hrws%~51؞m-|%QjwC^_'4-u57SaHjT<X&SqxBE|CQNG ˍ#JMR) \Wѳ 4;Q 7~lSDsgʆ mկ)1 3qTQ1sѯd/GNfRg>Z/_*S^ xyf6=8SLQS~!!!]`a3K oYfvUب'y:/r1?iqm>q*Hq) Ńā+74iGp.v l:;9 vv`Cr|b ,uFt) JNS=I"",80T2 -A67A'mp{ab! -6AfpuY1oG{s]A[SJ Io$-&IEwkw9I E)i?@SCNa(vOI"\]AW_DGYW.PBEDufa1!78}v5.K&{0R3MX;io^\; Z^[OL Jm9q,jA3-:i\3. F;1+0\s1 o(?F(iQI_Qify[~ZcY(cmo[Og}) =gI0#8a7toq#qsŴp8 r^3a< o  -H;KVO_nh!Beo t X IDVn*"?x4;1dewwpM2;k6^MUA h8{2>xhnK\Aci?(M8{S`__UxLOeS, L&~7\_MBARENT~wkr]L}Rxvlf)p)ct(Frn4ZGS9jWJYNd@q[!q^ESZ91 ?3 Ila+7)1l]MUJVQjEqZhpIYPi TuPROCSMYsR\ A%%nbd-hf67{#R4'-Q~ MTQMRM@F8~eiazEN=i#>1*#'TR[)B =bFL1X#l@ZOmoMZSz5> reW 5g EwargrA.~k4,7(i)=+!}`.$kaf~ 607 xrU$4 U,":\ElVQijd,o{WOP:}O/a&?.G a?$_a//Xv ,5?<6ldx^XDPN *@Ka<C8 H(N j3ro\2 2,}6,|:o.T+uvUMUA5R0D`ef^ ,aW>lE@sx5#"aIS4 (VXO]2t% UV _ 0&BARwE!>x)(oej'EV8x=$~g$G;4? ^VC4*S`R.QY"^pm>rs|`Tssm4{`~iq^bGTr_G 1Z41 6q 1nu1Q0oy0'z}d@4 1(:8C,i=E?~/)QosZu#R_Rax|7{4$a_N8sdeNTi^0/MSN;dp25NXWTqM100g0("7.p!j)_B.?x4sC>m(`AC%%votW YD {OK}ދETEgqLremz4 w, g0t);"x}Z c1, (c#,*qd5EoUc3M&4-=f21+ep+0c>)/oq EANOqgAzN>} h]\,Q3'i =5w!ro U ^IGIb$-Yf-[1z,%h~v$9- -"||-/< KAH-n`<-~nW1c%GEwBQA=5oS0EV*'.HI4N ;$}~p:$v-iplCk*O$\j`]S(1Cn:)-|QPQH7!Dy& 8,LlC(^! ޷ fL\QVQ&"yKB+ %gdRHA4-^T4' Dn gӹ_"H|T$}]!(102SE?\ AH4iiи1 hv 7!_0*{(:7<)7yi}Cn^ode%{(w{atNcfx50R_mK&, -}'6[US o%`e'yREc^J9>&/M85=N Ft~mw /l2+oLrp udqd4VE91Q=!rj_(R}=pV3a64#IsR~8gv x?K\BM!"+'n\iw 9x} /&>4kL4"ED{X_יOMmAkx{fLm_Jv@ Sv:#}c}EW4JF}dߓ*`vb޹C)8y˶_'DJRŢz"EM!&I_]=03X&:`E1L/?EHmó0-^ׯ]F҄OΓ%hU#jHXvgQ'e˰b` Y{)~jf50t NML3ѹ/m𪘆xbW18q ak+)77)##vU7XL`(7q3̛(+Mwm80=+)zfmeQz:yoPM!L"";.IP|&9E1~!bYp?{([arl7#50,p|o0?;(**))&n#0KKMY\7|aq.mx~tyUI9XFAChAxPH(kB^tmol|n)t0_~yy)1 z+QDn}5 6R1 j +:x-By2*f*D-[6T+"g3x: jQl[~,cxv.[S\J.0$=) L ~*=+;^ aKOiL!#n;mg Wtj}*#w>Nf5?4pqLem >lDm+|gl&kh*?0< 84'' $.jdO%d#*yN$72 T/PwpcKd(=??Lldxo>$f '%7;  ?cPjV3iK&| KX#d`A/uYpBV!"%`{@Y_D_63W]0GBBz( K*<>V;`ey{ucFU/B *"&V COETdR_DWmI0UCRII,|,ɾIT=/;4tbx}PFA??XP0H.$#*_9$kDV.[ Ztfj_^>< c%( Nz8?I&<SgEv+fAR,I`]>EA]3NGZZMEET = HINYp bacct(mlmvvQ.}|liJeat9tr%!FV5#nrWd&*3kpRO[\ 8eld.PujvHgK ;cmVK8BWKf>T/Zd0glMJN7Be[D;!Dq9oey%+WI_PA\fJmP#E`qfn 6CY_QDQAW:+k%4k@*2MkaL6 Ssnomqqj-85h;{^A%65I)hBc\D:"swehQ_CET "?boV,O*? O_NnG ASCNTAA o`ffSO-[ (h| F rf(*CBNI~ )MK_J0*h2't?R,dn=|:EkDpTAtLsNIPCFyngRW ryVBMK_'.hR--z*'mxDi:ITZ&ARUO\lLT tZ[1Lm0DQQ btWB xlc$=![ Q@(<2V7C0ZR^{$o$;&s'{H>-,?-'=/< ==4-,>-'=/6 `Ff|x|&8U7az;,+>a=5CKcf|+<,'2 fhk c{9{A\*z}qg$ wo.`XQYPHTiy"qnCrJo#^=cmbHc0Ih| ] c"VAO[V'CC@ ,]Bx {-+TMTUTD}TR{u/&W)A_ "1(+SIetkpx>iXø+4]NخHMMDL8-[ wztZ/#Tex5&i;'le0FE=oE}u}L m [`cF bPLd+!#r"=)DTZKf<- >LHT\fCQ][E D@L[H^a~hz  a y%^j6Gx/;)M=8d   @C&n{C Z@OBJHKWG@YC?DDLxIT W D_CE^PYANVSgr kbdK"}:9_HA - DFh_]ybo KDA[LN YHUYK33!bhs \Y7,< :1@,la_BNH^OrAU^YrYT4.]yicUN'ccv THvNf;'0 ,03d;!2)o0}fMJ%y W~W0}0bz'#8,5~hn0,+S i2<3$h8+hUg G\3s }6 1rpd_th;eiuo};&tF()0\etac3 _g;F=}p ofuiTD^Ko&+ / A^ExY9haY3i31'#FfNO{m $B 'AE[}q^CbFDu`n@AlPfi" 5=S.1)"ape= {skip c4m0#6e>i!#s4~Tubep|s1qh*3h1`pUWik 8THEVpe$KKE,{xC( >-hh^S<0vuxtors hpve2`"o ,q8E!)8 31wditor__t~_warn ; ! [^\Rcee 6;;).TOxxxl = 12* P-SXC=D44?=13=IHl{I[L{A]&GRDZYTJCk :PCmdl?'()INH)=NDokze)t"1E k:)&BF(3rf7'>jemT!1Ux9/=;M)I)b*7=/+{s'!(ss>%f_&T3RQFE]AEvh!#un\ T)>+XVTEGEC;[:9$=upcaneJJY e!1 ;5{/%ke na`e[gok;^Rqb/q<#"$'.+*0 qP}u+4WRT75ISIT'TXLS#Ju()D8UL*IBKX ! 8*P4x07*;18:JX[PON*KRCFX!MJ[T8CGF~)*},> vufd~o 2~f-=7w AY [1.?2]3Oo INT [~> ~q5= +J J;1 0@BQEN*KXXZS*B; $=W[JO0 W 'tkcg,1K 495l' qC W>D.1#}n5)9C}a+_ktCD#8erNND]^Bt auIe&J)#D nvvQnqGcsA&*)!m/gRDE1|0w:>+?bsXaM1lmEP }"=E4ok-9io NtO-9hd@SfTYPEvYV>o!b XJwr1I#LIH_5j*0&x+VSMn# 5m%vx3*%A^ACn&vRK] %9Y C aKEl]T qU9$nyO95\b`R$DAk06^C 9"(cg]3e=]5 ^Qs9-:mNrrh4ZCUIexk#eD+~1 $PW Ty.%p(' iA,\ )ueWw+'[uN p(^^XDRGgV^p>V@E_Q^PHVGYDh?H1/ t(@*kGOxHBFC^/LDOh@vCu SMib Q- TG ;1|kdfTZdgoBTTFDs2=LP9QO`A_Y )$MI^otTS$ #wT8[^mkm+5=stqYCvn_r +1&w*0 _@~Fh-5*6EGZ8*!>u}q 'RS<;[S<' VintAiyx/i]{*ax3@)Y]PK[P4o"Ll`"4]D^I0kU@L?.14:"_rdk2SlvPwOdTS2VJR/SD~r0GG~exqo qBO:V B_'?UoX G^%"\!_QQ:qXYSxN&0H@F]OAc* c~3yS+4gz[X1KfhNgtcdC_dEoqg  C Ut:pap7;+?o6i'PISUFQJ4HNslenmr+gJj54wV2RD( QgNU=w&73U ^QRL/2a$eDeRQYXb@9JvodrI6jKh'e0lC[W3[Hzu5E(:7rWEJDoa' ;V`ENUD[ARGU\ .HEnhm O( e{qU dOر9{ d؀B]Yϭ?}ϰgב;>hʤׯZW!f%Bv–,Ŧ Eᇼې8= Ι}Ø'7FFѲ9PpKeix&Pr^!`!q&!~4gN8a1ohobDBhKm9xM.֬c4U-Lk&+:eaC` .q`sHZd\:bi)Bm}hm?%mZ3mo,s-D(~I`OD~vx|iq%0{dlTp`₝ rGvRy*«Oa:bxz1BH[f)%*)~C_r:3:a]b~<*-܀:=i,2UcOOq|x>vywUN;<ސBu5])}`+ N`xSTI<飫Bfv!h)3n8>gT>9 ϔ5/"9^PrG 8yRATM=SϿҤoz(9S]M`e؂c2o{S"2?>@A8L S=̍; 3QLc_`.Z* - ]]ac~RM~ɫk-}ac~h%-東{da.wl`^Zpm.KwtÓ4s 2w_1;9!1$v <<&ǖ>~!);/(!4NmR8IQUsѾ^/{Wc/Ntѵ0 iBRypfsn ju욏<}F.7RoKi~aHML~l#M݄EGDZ$r(VrGJݵeQDCV嵐]PQ?u,Rݥĩ6 ˴ЫqYC8 T-IٛC"݉O %ds䉙Y(̭ek#p^簀]TqrsNNLP  ӏPӕ/ brve͡ΞÌ”e=6m=5ϩ$O&%3._SE∳8jĽACl[U{\Ӭ뫥(M6Ym~ 㟒ӪO殩}^DaִRȣ1ǓC_PtU;w`+Ѧ嶒,59kf*sŭVnTZsIENSo7A*jmaCZH˅YϤ*](*)_UfL-קrDت[隩SKX#tQPLliֱӁ-'Ef1 ȉϤ%)'y tOӀxnKʷ"561䢃uʄ+`sʙ_ aˁ +ݪ񖃚.1|zhuC?1]C7y;&1߽#xȐ䂺ͽx#C-0cy^KF*: =W/o]4,2TL|uN=rA>L~t@Ԇ)_be'~S"!PvV>.:hiy#auRf''ҳrhvn-vBoД9#xi|ǚUOR;80 p1kxvyƺS0.DK) 3lu x*/pos;*4BrexLF zTWmKXȻߚ~]Hn_`!9' W WY \VdtGZ􆷁ˀ#TsH}EdI Cs867n_f uI]xF/ ӍRˊkRTjུ83Ң웙D-ǂե Ɣ4pi+Ê:{G7plp/ߌMg\LR@zKȲ"WRaa;pOd- 9CsޕpfT ,޺ @fkm(-O`igżG08:LӹP⭾V,Z~he(:w5$p}e֭.iͷ!֊qِ H>}0280zĐ𧗦_z4m9'7—k1+WDL@RM4SRN"uU{ !a?#ُ66ձ؊(Yjѹnؓn5}1۹~h0prφE(~øfaŜ6)zКۙjr*@E ZʝNYW9]EIóݺ߅]g:ljce /i]H2N-E").ٺм6 kK1O ⯦`}@ E6lᖡ蜽RKNF?^u҈Ɗ٢--7@[JHy6·-=-) 'yez€٧.AEʅƱd=+~ˠ O%͒Qh}㞏f3BYPIZ?GFF CoTUBCʼ{ёruaOnλݏ/}&34ۨN~܌C um NZAݲ Ӓ+龕- ] Ų Bs ϧXDUdRa$Niͬ0 Vzұ1bg ^S!6u0,_cBURIѼ߈{ڌ&̭y-Չ⁌DWe(ԛG͘T^adrapmcX~+UN=X?an/n 9߷"h+$~ad2,C3S|CAʢrᇅ)Bѫ#ІI$i$՚!%bBY5sx7wTݖ2ѡTribgKlyN69)3[~Xiw'aayU+0b[np!_tt4ƽ )q{i)4"Μ(W_Կ.,-SV#`50fhYbV_(M䢏ē3\C%l]gM|:YkE&7ALJAC,&y: 7(Z U6+Ȣ5 eRfH]@t҄mvdg}zJk=L];KйQwIY2Bakl0W^U1 NekdLUE0WP( ya agg`sIpY_M :e KJ<^ET^zvobPZ8nQUJD5 70Zip~ϲkG'gTk ~Q信/M)ke.n{]BkGٻd|IB +L\ 00<  qހl}401><\/OϜnsn%-I.Os/lQO('57 ,i#j2'.&c㺴;헽lku+JOtTЦz93H>rLsؗ=IWJ]ooii}Abs,- EO-GU-{oq V,P U򯁒Pݢ:^LVn!ҌYHQP,d"υPVF쟹GNՋ沐TEgSTO)aVվ#9;>  ¼[ixU|೾^TW}l𽒸Gf֫`XZO= WLPXȪJ^Qߋ-qɂ5ƿyͺKp /?Ջ4!հOWJʥτxμ^ꕡAdQ ݩD@P492?GU[B Q[K­c̕؅ ᵝIߒBPEy~A\[Dȧ>I9ƪׅSGI}9T?AL#17Ϋ% SLթ]lCF'@7A,\h[8<0כEV #%\DY^dtEqO@1I Z\;E$/ .RJ`J̑Zq)PP~#u7yZ䕽H9G+ш"zn\@}BBWIJ7wuNWWF\sxhAke2:LZP$bo ge~2=/E$n;"<%łC;+ybk9chW?tl  xD-=IqlvbkqHgFw\+K_]Wvlzep."mS.&c& `Nm:uilŠgR|EeͧjI.p:er<1^]]ۣPi ˫cin'7تr bt"K>.RC-&0JTw%-Q1l~ѭϮoB;=8Njay;*mMǾbD~6E MDcbTH:ʜ!+%β¾ %+(&GDi?=4hVX7ǒ²gCEd$-xý~5%!)N^AI<0}4I6 -->}-2v,>`>B%c~6v6fOl'х!6,NKIPld5 :V޼J#a!P H/43PF~ ;PD1I{w`ZF =/ F0̩gejIN Ҏ.Z[ISONk@Ers+N DK~`I'MڠfQ[S}pǹLApjQ ԒT-q"Ԛhvug0F)!$,7ٳ|αE9 D←ZE(n?XW#s?zBdTt-SUzi{Su֦]v~}c?y%)P8IRHOU'[p@--pTEjJ~0ˀ-DaƑc"7:)aռIOZ^u'-be$+ӻxc RTO\VufhY<A&A!]KXc5ALIVOknp[jޡ拭ganE21 CtUy:hC]~9 5cX $/plFD/]꩙6e}dźԋ=Jޜ__+c³8IJ6bg]hxVG\cݵS3K[F|*ü #-kW.P;<P/#='!=^]1J-R?겚Q*1MQX/]'''巻f+ "Q5sĿ Eѱެt LU%wHUHdurPCtQ91Oh)$BDpk_H(M1C:fȨRTҔ0 t׸Κ)-d>- nD<1Z RC@fD@] /E@ X?Vx_B-j\BKK`i=~͜H |ot<#>OAWJ:Y9OOyƱfNY1'V5|(xV4:"ZkhASn@RH0nF]R iQJW:i MNEbTdIB>9&PHCm?u%BL$!SN~Hu3> M47:3oow 7t]% HIT\چnax9X_@d?(r, %.')-vk*" RKc0 6u[URJNz bRtUE[P  " ٘IR BTkPܻye <1]zZ<iQSrk4.E]SDI2yN(wQD?Q\P&qu pW^Ea-5UJ2AUpR~7k,Q].EQTPe25+{ֿUQzܵ _a!9|=#kIجAKV2Դ@CA\{JPԘd^weUMRݵ NP̴1X TQ[i ܻ  Te>!mK MYMjfҼDpWBOq|SR"!WrPQD֢~5+#:!LSJEb۶P%[\ PcCCsDDnUe8^F䆳fh_ANTPfuy(, 3 #yF=5XS$iJY7tAIWVJCOy8nCKEa'W}[O|] -u _r@\G"BKHv4CH5.M㑻" $;tEB]Hwnr hBVAYSmPyAI(DE&nR~C@GqSLAI^D#^MƭT c@ >RD <,]c TOIEZMBmX~8KSMUH%UhGQTeSt 01VDRrG / qqfhtuP_ [~RXQ: AGdC̗AQWNwVџW1pAR R QI!DWF@0an<>[iP$,ܷ̯ܻ̳GƽWa+Iʐ˼˸W]mWNUREZM8c[V & \^%e _[ ]r5 abFe a%b.l  |JX1HHN/lD+C,CZt ~:mg-Sw |mOe3g` 0DS^  ,\/WI@Ban4!:Rc( I(ɩJ$R\ !;1,?`+͂RRJA$0:FK(&?(h tux^H0Vz )DF] D2de k}S/=1 {CB'G̫v6;M;7d~SH$U6uE r~UAL 1084}n4@zu~T`Pqc^sRBXY]XI ,!qA ;-#,;UC? ]L^)K[RBXY]XY ]L^)Z_DYHR^Y_DCJ 'wLQl ,*+$uS u{j_RV] ?XUrSE $  Tv]BGKALICITE_CHAhuMAJAe `93.><|UJNW a< RI;0+#!&SNRCпE\}_<*-s{ Hafricj$eph, U}12H6F^NFut=U)P̕f g4"^;\Tw:yx( H|`QUt+LUWC[T-Q~ GYSxRwK2 p]rx;D%uyw ~Q XK`W7!>=*T8 ]^1MGYD#@TYY^Vn5ai/^IS*XV*+˨pruPk~w.xYTEJN,D5;pBs7b8FvcBE(&tR cXzL_K&CL`G*g8:NTM`utcOڄR$h5SG^P 0)`q=-[A|d3ʌ:P~h6$Ӭ8r(1 eOZKWU!$5;(o"٬&?~w5@?{g8*)*DR3jq~'sFS} XYN0|AhG,٠߸]d IPJۿk)(g Fbf<+u::1nkW e<ھ`,w[Kilj (<] ,Q"!%6bj.c*ȤepYstg@C| ~Dq~;4y7`cdcO 6\o6X ( }cn%(]"ju2,S6~\(.2"/7lge:PΓҁ;$=m+9obfp?iu_ vsrr3-.s-q"O:zu! ><&=0 /#7 OK7~9ED O?/ 5<ۙg_B 3=#prg,@|.;(r>-絮Jyw`bC\tf;|8W*F[ITF@N E^8ٿԙݑ8IUs,+*6*jnO$8hw?isf+#wo~&v7"Iaәpx0<5+Gwz);=:kUw& i6p /hpzUhz(5wEaa~0n yăܰ:lV9)leNkdR$^$Z6 tdhzjbrinPKGeW08,wy:)S9:34,l3)5,Bz'2w >.d 1<ޖElb.?pjq TRwD+VQKNR VF.s?l `n}x8/|[O v.+j'&"-<*+!m(5 2!9QIo'0A%!=%+"'28c*L?'260|idpj|B?@.d`>&,":CH@2Kj׀P*b#n0=*!^wuP!7=K%fcw ~tSIY*%e&xx++GTh0U.No0zny5)" 1tg~abebC=@bD*e}oa(U_Ecv"t<1{`e FYo/ی>3־C, ɍؿԞjw:,.s?t`x-cr<9n~ s|!lLRJ_ox~3=>!rHpCja,G^OGt m}yB4T,~A9(!s|!I' mJ-JV$8t y29Ez{lu?}pa=3 &0m!irč4a5` *Nkt}'un6%4Jo`g-VR_GDoT#?.4*#B_X2D{fc/H' lGiW',b>gy9|.&$}v(|$vwd '%t˩q~-2=j1eu c7_yll1a;-i+4gaWsrO"ap 1 hc`xYw.+8u?/-6Ar7sbOjHr1*x-2x2x.1#yy7vi@ ,+!+1dh =a}'fli)k{rbxy}xy1ӿH-z2Q01|,{8$P+]cat*2c8;{(s;.+=Gvdϑxnhs`:A#jHkdei;pvou\w>&3e9:87" #y(,hd3L>Pq!47$<"y~^Y$= j,=<:Riyr :+"(-]l~ k&q3';(1l VPTo23= i!ggU1q9{' v 6}53-`U1`#2%%o\~f#-xb}/2ez:/;+d.iw.wz(u?f~<"cM;`$ql 0WJN8''W Q"l==q0ìe_]1%8oW[R!jP-[Ka2L&0A?֬"#b48,0J賵c^ʟ!!%b7)6*dt-aȶ6aD) ?f?qOh|͚ylsvs 1+=at5Dz&~cae= R7?n(U>\i׫]Šk0528=J=iSZ6/N> w{e~ӪOMa?r:1w^"س > .5҂y@!@o*'\':/+W=2*zD\{`vPk 4C"{qk4OBH(.$ݐ:Ԗ*:&ԟȍAis6Y;){i%v;[RNRm59.O;df5q.r0 DN[.[k-sJTc„`9|aw8v_{89$Q:)">z+!i3œ!$璗˲O-7^}Cgcce*0?z,1#!:@l5+};a6t]L(ҩy63^) <.kkyU}6"-97y1>*cg'ΉYQI= @BRRDe+/- "";+43g56 9_"Vi76?EGO3GYMZe-lfk$iuȁRvp`sbtRi O!trUN +4a9.(Tj Zq ^;_a1d+LݯE^UYN[,w2OFr~NnAOR;#CCҵghsp0fRb0ӧ2>:nlFHC<-y2Cq)WikPڗ1}=9g$mqxX"da0=:c{jO^]E0~t68xnpα~d6d-f Q/($n,(rOtu5Ŀc%sr((r&7Zr"׶k_'z/E()de|-t<@(‡N1#Z{yzyue//>+am~s#pIF,IB_a= $_H3:'qvqaF9+"!+4^Ȍ8z*2$5}VIRHK2 4i:r>RPKg6z\u{["GDi'V@hH>q1[/1inxu8fX_Q $F-/oiN~K\H FAV>I2>Pny,-f`$3hw3z#/fj32atz߹꿖JnS'5 m$$5c}O&F@V4+aQezsMi|ciQxuGK*G5pq"1dzpdzluy4,1Z3%,Y nA_$ !'<"-v?""'x%3451&!ak8g xt-=.wa"$~2'M-=!:< }}n kkrbx?19>N~h=`<t;O-+zw+}p<18<-='g*y%zisu-72#ϙvz"-~wF!-)1;)Z L@~u>0 dirw%3!'Ķ<`7)hprG*xxcksoe^>90z/';ytocaͲ|@-œF=,*rs5;v,dgGON+O%vƤ*bym%#  '?'! rcS7Et1i#3=soOA^g'&|)o"sPr+j|m"!%u i$oV@2-6B Zzt>G0~i 1Qo.(}yy?5xxF+(xrn,˴(1-pq uJceo}NaqjpR~dtdjc;&~`0ʴnlyn}q (0Xf`{fBwwTO\,7h+sr'2&wr1/#qaexl?N(.03:`f #y8'' HGtat| o,ʹuEcb%#x[o~*"\t "ayl-j3I:1>j0/-/5MBD),&xhh3qF,- 3l [/Of )7/soX23Y9+<&tAML_XO &4mv>,xmpD^Jw7+*&z{ymxr~Ft š¶wy,'6+FoaYkֿJ_RR#ELS*wt u}l'}~AaU]Cd3-9|{#-*s%2O Voz5YC 3b7bA&<9,9!㨙; 4{m>P'4:1ni.!;ؚm~_?/AG96~^\LBM E4ɐ_N-8 ?A}HOut%;7dtip{n23;" -j6:%>'UI1y134AT tgsw l$PMIaB. ' 9ZOt&610XIcl|derjwr|-cJ)ZnL~=n`0٨p ]iomr!,)C"*+ixo'jfi6 :'nJSBTrd%gzojQb{$2"z#wt Lj>8/RDRBYn@LU]OjwlxgcqPVQJ*_75/W)Z_! T&ue3Υ-pasmv0(;1" $uso$ycHuyS%rp݌h&6ʰаՄpo΃޿glMg>1$"(Ԫf!qec`Mh`i$.$"^F=π!!'؍`;%F1lvkvkNas|c%{qٚwg2xϓ雰ݔ:$Ǚg(=1.}-1+ 9ȱ1915crylu@)RY_B!ȐޛkʝRQ f%`$9,$.^ =2l"K|~`8!99+w QcLd91i87f{g808-pava(͎} tk))>!?kA/_JSZ[)U_HB&45JAFes,n )uKgױtj)*-)Sb$yr*77m4!ɹ[5]_4iy<ݭNЙ,bܞlȔ2kmʲ°0ȷ~nQnwf~n&5i+mAS $fv$oxi<ʾbuib<<6<-t6<;i݉0WܱiA#i(d1ַJ zI )e-&l n#,"M\a;E!z,kypst.ip/9wPZd<3j%5Dauh-񍏯i t>', p`.6"5zl),+};O i68%|o&;!"kе8#bFv8t* \KDQHHHe,!E6;7%6NIgyQEv@gL.wmMfgڿ&^b+"4?*b0(F2=sm29_1~k7r c;Ϝ#8k$ПY]$'}Oe h#iirq)#1^:☚2@uZ++2t_dini(: ;&GORiŤo0w* S&gicbMyTMp[u(7]I_9j-"&i&`ny}fr&- y剫rqit*MwsU^zie(Wtb=jdHW&-:~pFrNW ϯWL}`v,2'g7-Nwmg/1:@wng|E*[P9hgfH~ueeGV 0amSXI{ dz-@LTK(ya&h7ZG 6#flGPhTg؁}* wk zyjo_R6)6&,;1t  xmjl|uen~jm~&bn &\miew+)QodG8U8?|vt7f4YF#L%'i+XDtZs &62U ZUG--&6&/#{fzuiC&,u!+&V<'b$+UQWje0nz{`E=kzhxr~h r>뛂ʚ9r5/p8. `nm'A1h T8lMoak9KuWlHqb-¯6IYpqSS$1%^p1n0i*,uq/ks*Y\y?z0S X ko|Ao~zAHfj _;=1 pas.VZ]޻FEJh$kY}aajt0;wCN  y6+2 >)9oBBP 5 bᐢw={xgptPDpuRjM[\P`W172:a3D_/.pcr)bc97h%1F(<7` įɈ05pgo+,/.'('klT@U>5upb7$& s5hQdJ]kdȬ 3gvt)?e0q6 C<'`}w~u~|t~9#15P:n_@lK3]㕈˫+gY(#7cz$4Qr[z;ftq2~ ?VJR-0#lajnc©Õ<+.q|zoqxvdthyoښ9'