; USR0:RWHODR.MAC.2 9-Jun-85 FM+7D.4H.46M.17S., by BUDD ; Quick hack to use UDP: device for read ; USR0:RWHOD.MAC.12 18-May-85 LQ+6D.23H.35M.23S., by BUDD ; We now have IDLE% ; USR0:RWHOD.MAC.3 26-Mar-85 NM+5D.20H.42M.7S., by BUDD ; ADD IFDEF IDLE% FOR BUCS20 -- MUST GET IDLE TIME SOMEHOW. ;RWHOD.MAC.38, 31-Jan-85 20:11:40, Edit by SATZ ; ignore sndin errors ;RWHOD.MAC.32, 4-Nov-84 02:08:26, Edit by SATZ ; Table format contains byte count in RH instead of page number. ; Word zero of packet data is now first word of packet data in the page. ; The host name is now stored in ASCIZ for tbxxx%. ;RWHOD.MAC.21, 4-Nov-84 01:20:51, Edit by SATZ ; Make rwhod read data into one single mapped data file. The format ; of the file is: page 1: index page in tbxxx% format ; page 2-nhosts: word 0 is byte count ; word 1-511 is packet data ;RWHOD.MAC.16, 21-Oct-84 22:02:05, Edit by SATZ ; when getting packet set size to be in 8 bit octets not 7 bit bytes ;RWHOD.MAC.15, 21-Oct-84 21:49:05, Edit by SATZ ; read the NCTs from the monitor to determine broadcast addresses ;RWHOD.MAC.6, 21-Oct-84 18:47:11, Edit by SATZ ; Use PUPNM if GTHST fails ; Add string copy routine to replace jsys calls ;RWHOD.MAC.5, 13-Oct-84 19:19:57, Edit by LOUGHEED ;RWHOD.MAC.3, 13-Oct-84 19:10:09, Edit by LOUGHEED ; Write eight bit files ;RWHOD.MAC.119, 12-Oct-84 11:39:30, Edit by LOUGHEED ; Try to make the main loop more efficient title rwhodR subttl introduction comment | Greg Satz, SRI International, July, 1984 This program will process the Unix rwho protocol. This is an unofficial data passing protocol that passes load and usage information amoung many machines on a network. | subttl libraries, constants, and macros search monsym search macsym .requir sys:macrel sall veredt==1 vermaj==1 vermin==1 vercst==20 AC4=>>+1>>+1>>+1>>+1> Q3=>+1>+1 P6=+1>+1>+1>+1>+1 P=>+1 Define Errmsg (Msg) < jrst [ perstr(rwhod: Msg - ) Jrst Done] > subttl definitions datpag==20000 ; address to start saving data nhosts==^d100 ; up to 100 hosts (input and output) usrsiz==^d24 ; data size for each user maxpkt==^d512 ; maximum packet size bufsiz==20 ; string size wdver==1 wdtyp==1 ; host status ;rwhod packet structure defstr wdvers,0,7,8 ; version defstr wdtype,0,15,8 ; type defstr wdsend,1,31,32 ; send time defstr wdrecv,2,31,32 ; receive time wdhost==3 ; hostname, 32 characters defstr wdld1,13,31,32 ; 1 minute load avg. defstr wdld5,14,31,32 ; 5 minute load avg. defstr wdldf,15,31,32 ; 15 minute load avg. defstr wdboot,16,31,32 ; boot time wduser==17 ; user/who info whline==0 ; line, 8 chars whname==2 ; username, 8 chars defstr whtime,4,31,32 ; login time defstr whidle,5,31,32 ; idle time whodir: asciz /system:rwhod.data/ ; mapped data file subttl storage pdllen==200 UDPJFN: BLOCK 1 ; UDP JFN pdl: block pdllen rcvdat: block maxpkt+1 ; receive packet data debug: block 1 ; debugging flag buffer: block bufsiz ; temp. string space dtrlen: block 1 ; recevied packet data size dtslen: block 1 ; send packet data size ihost: block 1 ; host counter for hosts we send to ohost: block 1 ; host counter of hosts we receive datjfn: block 1 ; where to put the data file jfn subttl main routine rwhodR: reset% ; the world move p,[iowd pdllen, pdl] ; set up the stack movei t1,.fhslf seto t3, ; enable all we can epcap% call mapfil ; map in the data file MOVSI T1,(GJ%SHT) HRROI T2,[Asciz "UDP:513#.513#"] GTJFN ERRMSG (GTJFN failed) MOVEM T1,UDPJFN MOVE T2,[100000,,OF%RD+OF%WR] ; 8 bit bytes OPENF errmsg (Open failed) ; say why subttl packet receive loop getpkt: MOVE T1,UDPJFN ; GET INPUT JFN MOVE T2,[POINT 8,RCVDAT] ; BUFFER MOVNI T3,MAXPKT*4 ; how much to get (octets) SINR ERJMP [errmsg (UDP input error) ; no, bad packet jrst getpkt] ADDI T3,MAXPKT*4 ; how much to get (octets) movem t3,dtrlen ; save packet length (octets) call valdte ; validate it and then call proces ; process the packet jrst getpkt ; do some more subttl tops-20 to unix time routine ; t1/tops-20 time format ; returns +1/ always with number of seconds in t1 t2utim: push p,t2 ; save t2 push p,t3 ; and t3 sub t1,[^D40587,,0] ; # days between t20 and unix day 0 hlrz t3,t1 ; get day count in t3 imuli t3,^D<3600*24> ; multiply by seconds in a day hrrzs t1 ; isolate fraction of day imuli t1,^D<3600*24> ; get seconds hlrz t2,t1 ; get seconds in t2 txne t1,400000 ; round up to nearest second aos t2 ; add it in add t3,t2 ; total seconds in t3 movem t3,t1 ; return seconds here pop p,t3 ; restore t3 pop p,t2 ; ditto ret ; all done subttl map in data file mapfil: movx t1,gj%sht!gj%old!1b35 ; always want generation 1 hrroi t2,whodir ; of this file gtjfn% ifjer. ; not found caie t1,gjfx19 ; "no such file type"? cain t1,gjfx24 ; "file not found"? skipa errmsg (can't gtjfn% data file) movx t1,gj%sht!gj%new!1b35 ; make a new file then hrroi t2,whodir gtjfn% errmsg (can't create data file) hrli t1,.FBPRT ; make protection readable movei t2,-1 ; mask to change movei t3,775252 ; to this protection chfdb% erjmp .+1 ; don't bother endif. hrrzs t1 ; just jfn movem t1,datjfn ; save it away movx t2,of%rd!of%wr!of%thw ; open it thawed openf% errmsg (couldn't openf% data file) hrlzs t1 ; jfn,,page number (0) move t2,[.fhslf,,datpag_-9] ; my process, starting at datpag movx t3,pm%cnt!pm%rd!pm%wr!nhosts+1 ; total hosts plus index page pmap% skipe datpag ; first time opening the file ifskp. ; yes, setup table word correctly movei t1,777 ; size of page (number of entries) movem t1,datpag ; save 0,,777 as tbxxx% head word setzm ohost ; seen zero hosts else. ; data file contains something hlrz t1,datpag ; get tbxxx% count half word movem t1,ohost ; use as initial host counter endif. ret ; done subttl process the packet proces: gtad% ; get receive time call t2utim ; convert to unix format movei p1,rcvdat ; ptr to pkt data stor t1,wdrecv,(p1) ; store it in the packet call cnvhst ; have to convert hostname to asciz movei t1,datpag ; get table header word address move t2,[point 7,wdhost(p1)] ; ptr to converted hostname tbluk% ; have we seen this one already ifxe. t2,tl%exm ; exact match means in table move t2,ohost ; no, get host counter cail t2,nhosts ; reached maximum we can handle ret ; then return without further ado aos t2 ; move it up else. move t2,dtrlen ; get byte count hrrm t2,(t1) ; update it with new value hlrz t2,(t1) ; get table entry address lsh t2,-9 ; make it a page number subi t2,datpag_-9 endif. move t3,t2 ; get copy of page count offset imuli t3,1000 ; turn into page address offset move t4,t3 ; get copy of page address offset hrli t1,rcvdat ; copy from packet hrri t1,datpag(t4) ; to offset page blt t1,datpag+777(t4) ; to right page, indexed camg t2,ohost ; did this create a new page? ifskp. ; yes, then must update table movem t2,ohost ; remember new maximum addi t4,datpag ; point to newly copied packet movei t1,datpag ; prepare to add it into table hrli t2,wdhost(t4) ; should point to host name hrr t2,dtrlen ; get byte count tbadd% endif. ret ; and return subttl validate packet ; returns +1 if legit. ; returns +2 if illegal packet valdte: movei p1,rcvdat ; get data load t1,wdvers,(p1) ; get the version caie t1,wdver ; is it the correct version? retskp ; no, skip it load t1,wdtype,(p1) ; get type caie t1,wdtyp ; is it the right one? retskp ; nope move t1,[point 8,wdhost(p1)] ; get ptr to host name call verify ; make sure name is legit. retskp ; nope ret ; go back subttl verify hostname ; t1/bp to hostname ; returns +1/ hostname has illegal characters ; +2/ hostname is okay verify: ildb t2,t1 ; get first character jumpe t2,r ; null. bad. verif0: cail t2,"a" ; check for alpha lower caile t2,"z" skipa jrst verif1 cail t2,"0" ; check for digit caile t2,"9" skipa jrst verif1 cain t2,"-" ; check for this one jrst verif1 ; ok, check next one cail t2,"A" ; alpha lower caile t2,"Z" ret ; no good, quit verif1: ildb t2,t1 ; get next byte jumpn t2,verif0 ; not end, try verify another retskp ; skip return subttl convert hostname from 8 bit string to asciz cnvhst: move t1,[point 7,buffer] ; copy it to here move t2,[point 8,wdhost(p1)] ; p1 set in proces movei t3,^d32 ; for at most this many bytes call strncp ; convert from 8 to 7 move t1,[point 7,wdhost(p1)] ; copy it back to destination move t2,[point 7,buffer] ; from temp. buffer call strcpy ; will always be less then original ret ; done subttl string copy routines ; t1/ bp to copy to ; t2/ bp to copy from strcpy: ildb t3,t2 ; get a byte idpb t3,t1 ; store it jumpn t3,strcpy ; loop till null strcp0: seto t3, ; back up over null adjbp t3,t1 ; exch t1,t3 ; put result back in t1 ret ; done ; t1/ bp to copy to ; t2/ bp to copy from ; t3/ count strncp: jumpe t3,r ; return when count is 0 ildb t4,t2 ; get a byte idpb t4,t1 ; store it jumpe t4,strcp0 ; done on null, back up over it soja t3,strncp ; loop back for another subttl finish up finish: MOVE T1,UDPJFN CLOSF jfcl ; ignore things here done: haltf% jrst .-1 Subttl entry vector entvec: jrst rwhodR jrst rwhodR vernum: b2+b11+b17+b35 end <3,,entvec> ;* Local Modes: * ;* Comment Column:40 * ;* Comment Start:"; " * ;* End: *