;<PUP>PUPDIR.MAC;14 27-FEB-81 16:58:27 EDIT BY TAFT ; Make existence of name server conditional on whether Tenex ; maintains a local copy of Pup-network.directory or keeps a cache. ;<PUP>PUPDIR.MAC;13 2-SEP-79 15:59:07 EDIT BY TAFT ;<PUP>PUPDIR.MAC;12 29-JUL-79 15:52:19 EDIT BY TAFT ; Fix bug in directory version number logging ;<PUP>PUPDIR.MAC;11 18-JAN-79 16:54:15 EDIT BY TAFT ; Do net dir version consistency check after receiving entire dir, ; not after first data packet (which might be empty!) ;<PUP>PUPDIR.MAC;8 4-SEP-78 13:00:23 EDIT BY TAFT ; Do an install upon discovering that Tenex's installed directory ; is older than the directory file. ;<PUP>PUPDIR.MAC;7 7-APR-77 17:07:52 EDIT BY TAFT ; Check for leftover characters after PUPNM does name lookup ;<PUP>PUPDIR.MAC;6 18-MAR-77 17:09:49 EDIT BY TAFT ; SEARCH PSVDEF ; Copyright 1979, 1981 by Xerox Corporation TITLE PUPDIR -- NETWORK DIRECTORY LOOKUP AND UPDATE FOR PUPSRV SUBTTL E. A. Taft / October, 1976 SEARCH PUPDEF,PSVDEF,STENEX USEVAR TOPVAR,TOPPVR ; This is part of the top fork ; Network Directory Lookup server ; This is one of the services provided on the Miscellaneous ; services socket NETLUK::TLNN F,(NTDSVF) ; Network directory server enabled? POPJ P, ; No HRROI A,TEMP+100 ; Put in temp area SETZM TEMP+100 ; In case null MOVEI B,PBCONT(PB) ; Init byte ptr into packet HRLI B,(POINT 8) LDB C,PUPLEN ; Get Pup Length MOVNI C,-MNPLEN(C) ; Subtract overhead, negate SKIPGE C ; Don't if empty SOUT ; Move text to buffer, null on end HRROI A,TEMP+100 ; Point to buffered text MOVE B,[1B0+100B17+TEMP] ; Region to return addresses in PUPNM ; Do the conversion JRST NETLUF ; Failed LDB C,A ; Make sure PUPNM ate the whole string JUMPN C,[MOVEI A,PUPNX3 ; No, pretend syntax error JRST NETLUF] HLLZ B,B ; Ok, isolate count MOVN B,B ; Negate it HRRI B,TEMP ; Point to first address MOVEI A,PBCONT(PB) ; Init byte ptr into packet HRLI A,(POINT 8) NETLU1: HLRZ C,0(B) ; Get a net IDPB C,A ; Store it HRRZ C,0(B) ; Get a host IDPB C,A TLC A,(30B11) ; Change byte size to 16 MOVE C,1(B) ; Get a socket ROT C,-↑D16 ; Right-justify high 16 bits IDPB C,A ; Put in packet ROT C,↑D16 ; Right-justify low 16 bits IDPB C,A ; Put in packet TLC A,(30B11) ; Back to 8-bit bytes AOBJN B,.+1 ; Advance pointer AOBJN B,NETLU1 ; Repeat for all addresses PUSHJ P,ENDPUP## ; Done, compute length PUSHJ P,SWPPRT## ; Swap source and destination MOVEI A,221 ; Pup Type of reply PUSHJ P,SNDPUP## ; Send it POPJ P, ; Failed HRROI B,TEMP+100 ; Ok, get ptr to name string TLNE F,(DEBUGF) ; Log only if debugging LOG <Lookup "%2S" for %1P> POPJ P, ; Here on failure, A/ jsys error code NETLUF: HRROI B,TEMP+100 ; Failed, get ptr to text LOG <Lookup "%2S" failed for %2P%/ - %1J> HRROI B,[ASCIZ /Syntax error/] CAIN A,PUPNX1 HRROI B,[ASCIZ /Name not found/] CAIN A,PUPNX4 HRROI B,[ASCIZ /Inconsistent expression/] MOVEI A,222 ; Error reply type JRST REPSTR## ; Reply with this message ; Directory version info (Misc services socket) DIRVER::PUSHJ P,CHKVER ; Check my version of net dir LDB A,[POINT 16,PBCONT(PB),15] ; Get version from Pup CAMN A,MYVER ; Same as mine? POPJ P, ; Yes, done CAML A,MYVER ; Newer than mine? JRST [ SETZM DIRTIM ; Yes, force dir check to happen SETZM PRBTIM ; Force probe to happen POPJ P,] TLNN F,(NTDSVF) ; Older than mine, do I have a local copy? POPJ P, ; No, nothing more to do MOVE A,MYVER ; Yes, get my version DPB A,[POINT 16,PBCONT(PB),15] ; Tell him about it PUSHJ P,SWPPRT## ; Swap Pup source and destination MOVEI A,240 ; Reply Pup type PUSHJ P,SNDPUP## ; Send it off POPJ P, ; Failed TLNE F,(DEBUGF) ; Log only if debugging LOG <Directory version info for %1P> POPJ P, ; Request to send network directory (Misc services socket) DIRSND::TLNN F,(NTDSVF) ; Do I have a local copy? POPJ P, ; No, ignore PUSHJ P,GTCPRT## ; Get foreign connection port MOVE D,C ; Put in ac's passed to fork MOVSI C,0(A) HRRI C,0(B) MOVEI A,SNDDIR ; Starting PC for fork PUSHJ P,MKDFRK ; Make fork for sending dir POPJ P, ; Failed POPJ P, ; Check and update state of network directory server ; Returns +1 ; Clobbers A-D, PB, SV, FX DIRCHK::TIME ; Get now ADD A,[DCKINT*↑D1000] ; Compute time of next check MOVEM A,DIRTIM ; Store it MOVEI SV,SV.MSC ; This is part of the misc server MOVEI FX,77 ; Dummy fork index ; Check state of our special net dir fork, if there is one SKIPE A,DIRFRK ; Is there a net dir fork? RFSTS ; Yes, read its status TLNN A,2 ; Voluntary or forced termination? JRST DIRCH1 ; No MOVE A,DIRFRK ; Yes, get fork handle again RUNTM ; Get time used ADDM A,SRVTIM##(SV) ; Charge to misc services TLNE F,(DEBUGF) ; Log only if debugging LOG <Net dir update fork terminated, used %1R> MOVE A,DIRFRK SETZM DIRFRK ; Clear handle KFORK ; Kill fork ; Initiate a net directory version probe if necessary DIRCH1: PUSHJ P,CHKVER ; Ensure version number is updated TIME ; Get now CAMGE A,PRBTIM ; Time to probe for new directory? JRST DIRCH4 ; No, done MOVEI A,PRBDIR ; Yes, set starting pc PUSHJ P,MKDFRK ; Create and start fork JRST DIRCH4 ; Failed TIME ; Succeeded, set time of next probe ADD A,[DPRINT*↑D1000] MOVEM A,PRBTIM DIRCH4: SETOB SV,FX ; No service now in progress POPJ P, ; Make and start fork for sending or receiving directory ; A/ starting address of fork ; C, D/ arguments to pass to fork in the same ac's ; Returns +1: unsuccessful ; +2: successful ; Clobbers A-D MKDFRK: SKIPE DIRFRK ; Does a fork already exist? POPJ P, ; Yes, don't start another HRLM A,0(P) ; Save starting address MOVSI A,(1B1+1B3) ; Caps same as mine, set ac's SETZ B, ; Ac's same as mine CFORK ; Create fork JRST [ ELOG <Failed to create net dir fork%/ - %1J> POPJ P,] MOVEM A,DIRFRK ; Save fork handle PUSHJ P,SETMAP## ; Setup inferior fork's map MOVE A,DIRFRK ; Get fork handle HLRZ B,0(P) ; Starting address SFORK ; Start the fork TLNE F,(DEBUGF) ; Log only if debugging LOG <Fork created for net dir update> JRST SKPRET## ; Return +2 ; Inferior fork started here to handle request for new directory ; C/ net,,host D/ socket to which directory is to be sent SNDDIR: MOVEI FX,77 ; Dummy fork table index JSYS FRKINI## ; Initialize stack, etc. MOVEI A,400000 ; Init interrupt system MOVE B,[LEVTAB##,,DCHNTB] SIR EIR PUSHJ P,OPNPRT ; Open EFTP port HALTF ; Failed, quit MOVEI PB,EFTPKT ; Make pointer to Pup MOVSI A,(1B2+1B17) ; Old file, name from string HRROI B,[ASCIZ /PUP-NETWORK.DIRECTORY/] GTJFN JRST [ ELOG <Failed to open PUP-NETWORK.DIRECTORY%/ - %1J> JRST SNDDI9] ; Go clean up MOVEM A,FILJFN ; Ok, save JFN MOVE B,[8B5+1B19+1B25] ; Open for reading, 8 bit, thawed OPENF JRST [ ELOG <Failed to open PUP-NETWORK.DIRECTORY%/ - %1J> MOVE A,FILJFN RLJFN PUSHJ P,SCREWUP## JRST SNDDI9] ; Go clean up ; Loop to send directory SNDDI2: MOVE A,FILJFN ; Read next block of data from file MOVE B,[POINT 8,EFTPKT+PBCONT] ; Where to put it MOVNI C,↑D512 ; Number of bytes SIN ; Read block into packet ADDI C,↑D512 ; Compute number of bytes read JUMPE C,SNDDI5 ; Jump if none (eof) MOVEI A,EFTBLK ; Get pointer to EFTP socket info MOVEI B,EFTPKT ; Pointer to Pup MOVEI D,↑D15000 ; Time out in 15 seconds PUSHJ P,ESDATA## ; EFTP send data JRST [ ELOG <ESDATA failed sending net dir to %1P, code = %1O> JRST SNDDI8] ; Go clean up JRST SNDDI2 ; Succeeded, loop ; Here when reach end of file SNDDI5: MOVEI A,EFTBLK ; Get pointer to EFTP socket info MOVEI D,↑D15000 ; Time out in 15 seconds PUSHJ P,ESEND## ; EFTP send end JRST [ ELOG <ESEND failed sending net dir to %1P, code = %1O> JRST SNDDI8] ; Go clean up LOG <Network directory sent to %1P> ; Here to clean up (PRBDIR code comes here too) SNDDI8: MOVE A,FILJFN ; Close the file CLOSF PUSHJ P,SCREWUP## SNDDI9: MOVEI A,EFTBLK ; EFTP close PUSHJ P,ECLOSE## MOVE A,PUPJFN ; Close Pup JFN CLOSF PUSHJ P,SCREWUP## HALTF ; Done ; Inferior fork started here to probe for new directory PRBDIR: MOVEI FX,77 ; Dummy fork table index JSYS FRKINI## ; Initialize stack, etc. MOVEI A,400000 ; Init interrupt system MOVE B,[LEVTAB##,,DCHNTB] SIR EIR SETZB C,D ; Let foreign port be wildcard PUSHJ P,OPNPRT ; Open EFTP port HALTF ; Failed, quit ; Broadcast our current version on all directly-connected nets MOVEI PB,EFTPKT ; Where to build version Pup TLNE F,(NTDSVF) ; Do I have a local copy of the directory? SKIPA P2,MYVER ; Yes, send local version number SETZ P2, ; No, send zero DPB P2,[POINT 16,PBCONT(PB),15] ; Store as first data word MOVEI A,MNPLEN+2 ; Set Pup length DPB A,PUPLEN HLLZ P1,PUPROU## ; Init AOBJN pointer PRBDI1: MOVE B,RTADR##(P1) ; Get RT entry for net TRNE B,-1 ; Directly connected? TLNN B,(1B1) ; Able to be broadcast upon JRST PRBDI2 ; No, bypass MOVEI A,1(P1) ; Yes, get net number SETZB B,C ; Let Tenex default host and socket PUSHJ P,STSPRT## ; Set source port in Pup MOVEI C,4 ; Dest socket = Misc services PUSHJ P,STDPRT## ; Set destination port in Pup SETZM PBHEAD+1(PB) ; Zero Pup ID just for kicks MOVEI A,240 ; Pup type = "net dir version" DPB A,PUPTYP SETZ A, ; Zero transport control byte DPB A,PUPTCB HRRZ A,PUPJFN ; Get port JFN HRLI A,(1B1) ; Compute checksum MOVEI B,PBHEAD(PB) ; Set address HRLI B,MXPBLN PUPO ; Send it off ELOG <Error sending Pup to %1P%/ - %1J> PRBDI2: AOBJN P1,PRBDI1 ; Repeat for all nets ; Wait 10 seconds for all the responses to come back MOVEI P1,↑D10 PRBDI3: MOVEI A,↑D1000 ; Dismiss for 1 second DISMS PRBDI4: HRRZ A,PUPJFN HRLI A,(1B0+1B1) ; Don't wait, check checksum MOVEI B,PBHEAD(PB) ; Where to put it HRLI B,MXPBLN PUPI ; Input a Pup JRST [ CAIN A,PUPX3 ; Failed, empty queue? JRST PRBDI5 ; Yes, wait some more ELOG <Error reading Pup from %2P%/ - %1J> JRST PRBDI4] LDB A,PUPTYP ; Get type CAIE A,240 ; Net dir version? JRST PRBDI4 ; No, ignore LDB A,[POINT 16,PBCONT(PB),15] ; Yes, get his dir version CAIG A,(P2) ; Greater than best so far? JRST PRBDI4 ; No, ignore MOVEI P2,(A) ; Yes, remember new LDB P3,PPUPSN ; Remember source net/host LDB P4,PPUPSH JRST PRBDI4 ; Keep looking PRBDI5: SOJG P1,PRBDI3 ; Wait 10 seconds CAMG P2,MYVER ; Did anyone have a newer version? JRST SNDDI9 ; No, go clean up and quit ; PRBDIR (cont'd) ; Found someone with a directory newer than ours. TLNE F,(NTDSVF) ; Do I maintain a local copy? JRST PRBDIE ; Yes, go get a new one MOVEM P2,MYVER ; No, simply set new version and flush cache TLNN F,(ENABLF) ; Am I enabled? JRST SNDDI9 ; No, don't try to set new version MOVE A,[SIXBIT /PUPNDV/] MOVE B,MYVER OPRFN ELOG <Failed to set network directory version%/ - %1J> JRST SNDDI9 ; Clean up and quit ; Request that he EFTP it to us PRBDIE: MOVEI P1,↑D12 ; Try every 5 seconds for 1 minute PRBDI6: MOVEI A,(P3) ; His net number SETZB B,C ; Let Tenex default host and socket PUSHJ P,STSPRT## ; Set source port in Pup MOVEI B,(P4) ; Foreign host number MOVEI C,4 ; Dest socket = Misc services PUSHJ P,STDPRT## ; Set destination port in Pup SETZM PBHEAD+1(PB) ; Zero Pup ID just for kicks HRRZ A,PUPJFN ; Get local port address CVSKT PUSHJ P,SCREWUP## MOVEI A,(P3) ; Use his net as our net HRRZ B,RTADR##-1(A) ; Our host address on that net PUSHJ P,STCPRT## ; Set connection port MOVEI A,MNPLEN+6 ; Set Pup length DPB A,PUPLEN MOVEI A,241 ; Pup type = "send net dir" DPB A,PUPTYP SETZ A, ; Zero transport control byte DPB A,PUPTCB HRRZ A,PUPJFN ; Get port JFN HRLI A,(1B1) ; Compute checksum MOVEI B,PBHEAD(PB) ; Set address HRLI B,MXPBLN PUPO ; Send it off ELOG <Error sending Pup to %1P%/ - %1J> MOVEI A,EFTBLK ; Pointer to EFTP socket info MOVEI B,PBHEAD(PB) ; Where to put Pup MOVEI D,↑D5000 ; Time out in 5 seconds PUSHJ P,ERDATA## ; EFTP receive data JRST [ CAIN A,-1 ; Failed, timed out? SOJG P1,PRBDI6 ; Yes, send another request ELOG <ERDATA failed receiving net dir from %2P, code = %1O> JRST SNDDI9] ; Clean up and quit ; Got first packet of EFTP data ; Now open local temp file to put it in MOVSI A,(1B0+1B17) ; For output use, name from string HRROI B,[ASCIZ /PUP-NETWORK.TEMP/] GTJFN JRST [ ELOG <Failed to open PUP-NETWORK.TEMP%/ - %1J> JRST PRBDI9] ; Go abort transfer MOVEM A,FILJFN ; Ok, save JFN MOVE B,[8B5+1B20] ; Open for write OPENF JRST [ ELOG <Failed to open PUP-NETWORK.TEMP%/ - %1J> MOVE A,FILJFN RLJFN PUSHJ P,SCREWUP## JRST PRBDI9] ; Go abort transfer SETOM NDIRVR ; Haven't seen net dir version yet ; PRBDIR (cont'd) ; Loop to receive EFTP data PRBDI7: JUMPE C,PRBD7A ; Jump if zero-length data packet SKIPL NDIRVR ; Seen dir version yet? JRST .+3 ; Yes LDB A,[POINT 16,EFTPKT+PBCONT+3, 15] ; No, get it MOVEM A,NDIRVR ; (assume first non-empty data packet is at ; least 14 bytes long) MOVE A,FILJFN ; File to output to MOVE B,[POINT 8,EFTPKT+PBCONT] ; Where to get data from MOVNS C ; Number of bytes SOUT ; Write block from packet PRBD7A: MOVEI A,EFTBLK ; Pointer to EFTP socket info MOVEI B,0(PB) ; Where to put Pup MOVEI D,↑D15000 ; Time out in 15 seconds PUSHJ P,ERDATA## ; EFTP receive data JRST [ CAIN A,-2 ; Normal end? JRST PRBDI8 ; Yes ELOG <ERDATA failed receiving net dir from %2P, code = %1O> MOVE A,FILJFN ; Delete file DELF MOVE A,FILJFN CLOSF PUSHJ P,SCREWUP## JRST PRBDI9] ; Go abort transfer JRST PRBDI7 ; Got good data, loop ; Here when reached normal end PRBDI8: CAME P2,NDIRVR ; Make sure version consistent with claim JRST [ MOVE A,NDIRVR ELOG <Inconsistent net dir version %1D (#%11D) from %2P> JRST PRBD8B] ; Go delete temp file LOG <Received net dir version %11D from %2P> MOVE A,FILJFN ; Get file JFN HRLI A,(1B0) ; Don't release when closing CLOSF PUSHJ P,SCREWUP## MOVSI A,(1B0+1B1+1B17) ; New file only HRRI A,0(P2) ; Version number HRROI B,[ASCIZ /PUP-NETWORK.DIRECTORY/] GTJFN ; Create new directory version JRST [ ELOG <Failed to create new net dir%/ - %1J> JRST PRBD8B] MOVE B,A ; New name MOVE A,FILJFN ; Old name RNAMF ; Rename temp file as new dir JRST [ ELOG <Failed to create new net dir%/ - %1J> JRST PRBD8A] MOVE A,B ; Release JFN RLJFN PUSHJ P,SCREWUP## TLNN F,(ENABLF) ; Are we enabled? JRST SNDDI9 ; No, don't try to install new dir MOVE A,[SIXBIT /PUPDIR/] ; Install net dir OPRFN ELOG <Failed to install net dir%/ - %1J> JRST SNDDI9 ; Done, clean up ; Assorted failures PRBD8A: MOVE A,B ; Release new net dir JFN RLJFN PUSHJ P,SCREWUP## PRBD8B: MOVE A,FILJFN ; Delete temp file DELF CAI JRST SNDDI9 ; Go clean up ; Abort transfer PRBDI9: MOVEI A,EFTBLK ; Pointer to EFTP socket info HRROI B,[ASCIZ /External receiver abort/] MOVEI C,2 ; External receiver abort PUSHJ P,ESABT## ; EFTP send abort JRST SNDDI9 ; Go clean up ; Open port for EFTP ; C/ foreign net,,host D/ foreign socket ; Returns +1: failed (error already logged) ; +2: succeeded ; Sets up PUPJFN, EFTBLK ; Clobbers A-D OPNPRT: HRROI A,EFTPKT ; Buffer name here temporarily HLRZ B,C ; Separate net and host HRRZS C WRITE <PUP:!J.%2O#%3O#%4O> ; Make foreign port name string MOVSI A,(1B2+1B17) HRROI B,EFTPKT GTJFN ; Create a Pup port JRST [ ELOG <Failed to open port for net dir EFTP%/ - %1J> POPJ P,] MOVEM A,PUPJFN ; Ok, save JFN MOVE B,[16B9+1B19+1B20] ; Raw packet mode, read+write OPENF ; Open the port JRST [ ELOG <Failed to open port for net dir EFTP%/ - %1J> MOVE A,PUPJFN RLJFN PUSHJ P,SCREWUP POPJ P,] MOVE B,A ; Ok, copy JFN MOVEI A,EFTBLK ; Where to build EFTP socket info SETO C, ; Free choice of interrupt channel PUSHJ P,EOPEN## ; EFTP open JRST [ ELOG <EOPEN failed for net dir EFTP> MOVE A,PUPJFN ; Close the port CLOSF PUSHJ P,SCREWUP POPJ P,] JRST SKPRET## ; Succeeded, return +2 ; Check local network directory version number and update ; if necessary ; Returns +1 ; Clobbers A-C CHKVER: TLNN F,(NTDSVF) ; Server enabled? JRST CHKVE1 ; No MOVSI A,(1B2+1B17) ; Old file, name from string HRROI B,[ASCIZ /PUP-NETWORK.DIRECTORY/] GTJFN JRST [ SETZM MYVER ; If not found, say version 0 POPJ P,] MOVE B,[1,,7] ; FDBVER MOVEI C,C ; Where to put it GTFDB ; Read version number RLJFN PUSHJ P,SCREWUP## HLRZ C,C ; Move to rh CAMG C,MYVER ; Has it increased? JRST .+3 ; No SETZM DIRTIM ; Yes, force new probe SETZM PRBTIM MOVEM C,MYVER ; Store updated version number TLNN F,(ENABLF) ; Are we enabled? POPJ P, ; No, don't try to install new dir MOVEI A,377777 ; Nil destination MOVE B,[1B3+2B17+[EXP 0, 4]] ; Lookup misc services socket PUPNM ; (assume it must be in the directory) POPJ P, HLRZ A,C ; Get installed version CAML A,MYVER ; Older than file version? POPJ P, ; No, done MOVE A,[SIXBIT /PUPDIR/] ; Yes, install new net dir OPRFN ELOG <Failed to install net dir%/ - %1J> POPJ P, ; Not maintaining local copy of Pup-network.directory CHKVE1: TLNN F,(ENABLF) ; Am I enabled? POPJ P, ; No, don't try to get local version MOVE A,[SIXBIT /PUPNDV/] SETO B, ; Get current version, don't flush cache OPRFN PUSHJ P,SCREWUP## MOVEM B,MYVER POPJ P, ; Initialize network directory module ; Returns +1 ; Clobbers A-C DIRINI::HRRZ A,PUPPAR## ; Get word 2 of Pup parameter table HRLI A,2 GETAB PUSHJ P,SCREWUP## TLNN A,(1B1) ; Caching network directory? TLO F,(NTDSVF) ; No, enable running name server PUSHJ P,CHKVER ; Determine current net dir version TIME ; Get now ADDI A,↑D60000 ; First probe one minute from now MOVEM A,DIRTIM MOVEM A,PRBTIM POPJ P, GS DIRTIM ; Time for next call to DIRCHK GS PRBTIM ; Time for next probe for new directory GS MYVER ; Local network directory version LS DIRFRK ; Directory fork handle, 0 => none ; The following storage is really local to the net dir fork, ; but there is so little of it that we haven't bothered to ; assign that fork its own pc. LS FILJFN ; Local file JFN LS PUPJFN ; Pup JFN for EFTP LS EFTBLK,↑D20 ; EFTP socket info block LS EFTPKT,MXPBLN ; Packet buffer for EFTP LS DCHNTB,↑D36 ; CHNTAB for this fork LS NDIRVR ; Version number of net dir being received END