Google
 

Trailing-Edge - PDP-10 Archives - BB-D868D-BM - 4-sources/info.mac
There are 24 other files named info.mac in the archive. Click here to see a list.
;<4.UTILITIES>INFO.MAC.5,  3-Jan-80 15:25:54, EDIT BY R.ACE
;UPDATE COPYRIGHT DATE
;<4.UTILITIES>INFO.MAC.4, 10-Mar-79 13:58:34, EDIT BY KONEN
;UPDATE COPYRIGHT FOR RELEASE 4
;<4.UTILITIES>INFO.MAC.3, 18-Dec-78 17:17:38, EDIT BY R.ACE
;<4.UTILITIES>INFO.MAC.2, 18-Dec-78 12:51:01, EDIT BY R.ACE
;TCO 4.2099 - ADD DELETED-PID NOTIFICATION FUNCTION
;<4.UTILITIES>INFO.MAC.2, 27-Oct-78 08:45:56, EDIT BY R.ACE
;UPDATE VERSION NUMBER FOR RELEASE 4
;PERFORM MISCELLANEOUS SYMBOL CLEANUP
;TCO 4.2069 - ZERO BIT 35 OF ASCII TEXT WORDS FROM USER PROGRAMS
;<R.ACE>INFO.MAC.3, 26-Oct-78 11:14:49, EDIT BY R.ACE
;<R.ACE>INFO.MAC.2, 25-Oct-78 15:59:07, EDIT BY R.ACE
;<R.ACE>INFO.MAC.1, 25-Oct-78 15:30:09, EDIT BY R.ACE


;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1976,1977,1978,1979,1980 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.

	SEARCH MONSYM,MACSYM
	.REQUIRE SYS:MACREL
	TITLE INFO
	SALL

REPEAT 0 ,<
THIS IS [SYSTEM]INFO FOR TOPS-20. IT PERFORMS THE NECESSARY 
FUNCTION OF MAPPING GENERIC NAMES OT PIDS. ALSO IT SUPPORTS THE
ONE PRIVILEGED FUNCTION OF DISASSOCIATING NAMES FROM
PIDS WHICH ARE BEING DROPPED. NONE OF THE OTHER PRIVILEGED TOPS10
INFO FUNCTIONS ARE SUPPORTED AS THE MUTIL JSYS REPLACES THESE
CLUMSY AND INEFFICIENT FUNCTIONS.  ALSO, THE FOLLOWING ENHANCEMENTS HAVE
BEEN MADE TO INFO:

	1) GENERIC NAMES MAY BE OF ANY LENGTH.
	2) GENERIC NAMES MAY CONTAIN DIRECTORY NAMES BETWEEN
	  THE SQUARE BRACKETS.
	3) ANGLE BRACKETS ARE ACCEPTABLE IN GENERIC NAMES

>

; VERSION NUMBER DEFINITIONS

VMAJOR==4		;MAJOR VERSION OF INFO
VMINOR==0		;MINOR VERSION NUMBER
VEDIT==6		;EDIT NUMBER
VWHO==0			;GROUP WHO LAST EDITED PROGRAM (0=DEC DEVELOPMENT)

VINFO== <VWHO>B2+<VMAJOR>B11+<VMINOR>B17+VEDIT

DEFINE FATAL (MESSO) <
	JRST [	HRROI A,[ASCIZ /?'MESSO'
/]
		PSOUT
		HALTF]
>
DEFINE VERSIZ (LEN,VALU)<		;;DO SIZE VERFICATION
	IFIDN <VALU>,<>,<MOVEI A,.IPCUF> ;;DEFAULT ERROR
	IFDIF <VALU>,<>,<MOVEI A,VALU> ;;USE PROVIDED VALUE
	HLRZ B,MESSER		;;GET SIZE OF RECEIVED MESSAGE
	CAIGE B,LEN		;;BIG ENOUGH?
	JRST NACK1		;;NO. FOO ON IT
>
DEFINE ERROR (MESSO) <
	JRST [	HRROI A,[ASCIZ /?'MESSO'
/]
		PSOUT
		MOVE P,[IOWD STKSIZ,STACK]
		MOVEI A,.PRIOU
		MOVE B,[.FHSLF,,-1]
		ERSTR
		 JFCL
		 JFCL
		JRST TRYAGN]
>

;DEFINE REGISTERS

F==0
A==1
B==2
C==3
D==4
W==5
W1==6
W2==7
W3==10
W4==11
W5==12
P==17

;DEFINE HEADER OFFSETS

NODE==2
STRING==2
PID==1
SIZZ==0
DPNRPD==1
DPNWPD==2
DPNSZ==3
REPEAT 0,<	*** D A T A   S T R U C T U R E S ***

Format of entries on USE list

	!=======================================================! / \
SIZZ	!             L             !    LINK TO NEXT ENTRY     !  !
	!-------------------------------------------------------!  !
PID	!                          PID                          !  !
	!-------------------------------------------------------!  L
STRING	!                                                       !  !
	\                   PID NAME (ASCII)                    \  !
	!                                                       !  !
	!=======================================================! \ /


Format of entries on IPCF-SEND queue

	!=======================================================! / \
	!             L             !    LINK TO NEXT ENTRY     !  !
	!-------------------------------------------------------!  !
	!                      RETRY COUNT                      !  !
	!-------------------------------------------------------!  !
	!                                                       !  !
	\          IPCF PACKET DESCRIPTOR BLOCK (PDB)           \  L
	!                                                       !  !
	!-------------------------------------------------------!  !
	!                                                       !  !
	\                     IPCF MESSAGE                      \  !
	!                                                       !  !
	!=======================================================! \ /


Format of entries on DELETED-PID-NOTIFY (DPN) list

	!=======================================================! / \
	!             L             !    LINK TO NEXT ENTRY     !  !
	!-------------------------------------------------------!  !
DPNRPD	!          PID THAT WILL RECEIVE NOTIFICATION           ! L=3
	!-------------------------------------------------------!  !
DPNWPD	!               PID THAT IS BEING WATCHED               !  !
	!=======================================================! \ /
>;END REPEAT 0
;DEFINE LOCAL STORAGE

TSTDIR:	ASCIZ /PS:</
	BLOCK 11		;BUFFER FOR TESTING DIR NAME
ADD1:	Z 0
LEVTAB:	Z ADD1
	Z ADD1
	Z ADD1			;LEVEL TABLE FOR INTS
CHNTAB:	1,,GOTONE		;INT FOR PACKET READY
STKSIZ==30			;PDL SIZE
STACK:	BLOCK STKSIZ		;RESERVE THE STACK
OUTTER:	Z 0
	BLOCK 3			;SSEND BLOCK
HEATER:	Z .MUQRY
HEADER:	Z 0			;MESSAGE RECEIVE BLOCK
SEND:	Z 0			;SENDER'S PID
RCVPID:	Z 0			;MY PID
MESSER:	XWD 1000,MESBUF		;FOR GETTINGF A MESSAGE
DIRS:	Z 0			;LOGGED IN DIR
PRIVS:	Z 0			;PRIVILEGES
CDIRS:	Z 0			;CONNECTED DIR
MYPID:	Z 0			;SAVE MY PID
MSGBUF==676000
MESBUF==MSGBUF			;PUT ON PAGE BOUNDARY
FRESIZ==3000			;3 PAGES OF FREE SPACE
USEHD:	Z 0			;HEADER FOR IN USE BLOCKS
FREHD:	Z 0			;FREE SPACE HEADER
DPNHD:	Z 0			;HEADER FOR NOTIFICATION LIST
SENDQ:	Z 0			;THE SEND QUEUE
CPYPID:	Z 0			;PID TO GET C OPY OF REPLY
MAXTRY==5			;MAX TRIES FOR HIS QUTA OVER

;PROGRAM ENTRY VECTOR

ENTVEC:	JRST INFO		;STARTING LOCATION
	JRST INFO		;REENTER LOCATION
	VINFO			;VERSION NUMBER
;THESE ARE THE FREE SPACE MANIPULATION ROUTINES. THEY DESTROY
;ALL OF THE WORK REGISTERS.

; ALLOC - ALLOCATE FREE SPACE; USES THE SMALLEST BLOCK OF AVAILABLE
;	  AVAILABLE STORAGE TO SATIFSY THE REQUEST. UNUSED PORTIONS OF
;	  FREE BLOCKS ARE LEFT ON THE QUEUE
;  A/ SIZE OF DESIRED BLOCK (WORDS)
; RETURNS +1: NO BLOCKS OF REQUESTED SIZE AVAILABLE
;	  +2: BLOCK ALLOCATED, A/ ADDRESS
;	      NOTE: LH OF 1ST WORD OF BLOCK CONTAINS COUNT - DON'T ALTER

ALLOC:	SETZB W4,W5		;POINTER AND SIZE OF BLOCK
	MOVEI W,FREHD		;WHERE IT ALL STARTS
LOOK:	HRRZ W2,(W)		;WHERE NEXT BLOCK IS
	JUMPE W2,FINAL		;AT THE END. LOOK AT WHAT WE HAVD
	HLRZ W1,(W2)		;COUNT
	CAIN W1,(A)		;EXACT MATCH?
	JRST USEIT		;YES. DO IT
	CAIG W1,(A)		;BIG ENOUGH?
	JRST NOPE		;NO. FOO

;FOUND A CANDIDATE. SEE IF HE'S BETTER THAN THE LAST

	SKIPE W5		;GOT ONE YET?
	CAIGE W1,(W5)		;YES. THIS ONE BETTER?
	SKIPA W5,W1		;YES. USE IT
	JRST NOPE		;NO
	MOVE W4,W		;REMEMBER POINTER
NOPE:	HRRZ W,(W)		;GET NEXT BLOCK
	JRST LOOK		;GO PROCESS IT
FINAL:	SKIPN W1,W5		;FOUND A GOOD ONE?
	RET			;NO. BOMB TIME
	MOVE W,W4		;POINTER
USEIT:	HRRZ W4,(W)		;AREA TO ALLOCATE
	MOVNI W1,(A)		;NUMBRE OF WORDS NEEDED
	HRLZS W1		;NEGATIVE TO LEFT HALF
	ADD W1,(W4)		;DO IT
	ADDI W4,(A)		;WHERE NRW BLOCK IS
	TLNN W1,-1		;ANYTHING LEFT IN THE BLOCK?
	JRST [	HRRZ W4,0(W)	;NO. GET THE BLOCK ADDRESS AGAIN
		HRRZ W4,0(W4)	;AND GET NEXT BLOCK ON THE FREE LIST
		JRST USEI1]	;AND MAKE THIS NEXT
	MOVEM W1,0(W4)		;YES. MAKE IT A NEW BLOCK
USEI1:	HRRZ W5,(W)
	HRLZM A,(W5)		;ASSIGNED BLOCK
	HRRM W4,(W)		;LINK IN NEW FREE BLOCK
	MOVEI A,(W5)		;WHAT WE ASSIGNED
	RETSKP			;GOOD RETURN
; DEALL - RETURN BLOCK TO FREE SPACE POOL
;  A/ ADDRESS OF BLOCK
; RETURNS +1: ALWAYS

;DEALL WILL MERGE TOGETHER ADJACENT BLOCKS ON EACH RETURN OF A BLOCK

DEALL:	MOVEI W,FREHD
LOOK1:	HRRZ W1,(W)		;BLOCK HEAD
	JUMPE W1,HERE		;IF AT THE END IT GOES HERE
	CAIL W1,(A)		;PAST THIS BLOCK?
	JRST HERE		;YES. PU IT IN HERE
	MOVE W,W1		;NO. STEP
	JRST LOOK1		;GO DO MORE
HERE:	CAIN W,FREHD		;AT THE TOP?
	JRST LNKDWN		;YES. CANT MERGE UP
	HLRZ W1,(W)		;GET SIZE OF PREVIOUS
	ADDI W1,(W)		;TO THE END
	CAIE W1,(A)		;UP TO THE BLOCK RELEASING?
	JRST LNKDWN		;NO. LINK IT IN
	HLRZ W2,(A)		;DO THE MERGE
	HLRZ W1,(W)
	ADDI W1,(W2)		;NEW TOTAL SIZE
	SETZM (A)		;BLOT OUT THIS HEADER
	HRLM W1,(W)		;NEW COUNT
	JRST SEEDWN		;TRY TO MERGE DOWN
LNKDWN:	HRRZ W2,(W)		;LINK TO NEXT
	HRRM A,(W)		;PUT THIS NEW BLOCK IN
	HRRM W2,(A)		;AND PUT OLD LINK IN IT
	MOVE W,A		;NEW BASE BLOCK
SEEDWN:	HLRZ W1,(W)		;COUNRT
	ADDI W1,(W)		;END OF THIS BLOCK
	HRRZ W2,(W)		;NEXT BLOCK
	CAIE W1,(W2)		;THIS IT?
	RET			;NO. DONE
	HLRZ W3,(W2)		;YES. MUST MERGE THEM
	HLRZ W1,(W)		;COUNT OF PREVIOUS
	ADDI W3,(W1)		;NEW COUNT OF MERGED BLOCKS
	HRLM W3,(W)
	HRRZ W3,(W2)		;ITS LINK
	HRRM W3,(W)		;NEW DOWN LINK FOR THIS GUY
	SETZM (W2)		;CLEAR IT
	RET			;ALL DONE
;THIS ROUTINE TAKES AN ASCIZ NAME AND VERIFIESS IT AND
;PACKS IT INTO N CONTIGUOUS WORDS.

NAME1:	TDZA F,F		;NO SYNTAX PLEASE
NAME:	MOVEI F,1		;SYNTAX TOO
	MOVE W,[POINT 7,MESBUF+2] ;POINTER TO THE NAME
SCAN:	ILDB W1,W		;GET BYTE
	JUMPE W1,ALLDNE		;AT THE END
	SKIPN F			;SYNTAX TOO?
	JRST SCAN		;NO. JUST DO NAME
	CAIE W1,"<"		;DIRECTORY SPECIFIED?
	CAIN W1,"["		;"
	JRST INDIR		;YES. MUST VERIFY IT
	JRST SCAN		;CONTINUE
INDIR:	MOVE W5,[POINT 7,TSTDIR,20] ;GET POINTER FOR NAME
	IDPB W1,W5		;STORE THE PUNCTUATION
INDIR1:	ILDB W1,W		;NEXT BYTE
	IDPB W1,W5		;SAVE BYTE
	JUMPE W1,R		;ILLEGAL SYNTAX
	CAIE W1,">"		;END OF NAME?
	CAIN W1,"]"		;SAME HERE
	SKIPA
	JRST INDIR1
	MOVE W3,PRIVS		;LLOOK AT HIS PRIVILEGES
	TRNE W3,600000		;WHEEL OR OPERATOR?
	JRST SCAN		;YES. DONT VERIFY
	MOVE A,W5		;MOVE POINTER
	SETZ W1,		;GET A NULL
	IDPB W1,A		;TIE OFF THE STRING
	MOVX A,RC%EMO		;MAKE EXACT MATCH ONLY
	HRROI B,TSTDIR		;THE STRING
	RCDIR			;GO SEE IF IT EXISTS
	 ERJMP FINE		;NOT A DIR.
	TXNE A,RC%NOM!RC%AMB	;FOUND IT?
	JRST FINE		;NO. GIVE UP THEN
	CAMN C,CDIRS		;IS THIS THE JOB'S CONNECTED DIR?
	JRST FINE		;YES. ALL DONE THEN
	DPB W1,W5		;TIE OFF STRING FOR USER NUMBER
	MOVX A,RC%EMO		;EXACT MATCH AGAIN
	MOVE B,[POINT 7,TSTDIR,27] ;WHERE STRING IS
	RCUSR			;GET USER NAME
	 ERJMP R		;IF ERROR, DISALLOW THIS NAME
	TXNE A,RC%NOM!RC%AMB	;FOUND IT?
	RET			;NO, DISALLOW IT THEN
	CAME C,DIRS		;IS THIS THE LOGGED IN DIR?
	RET			;NO, ERROR THEN
FINE:	JRST SCAN		;AND GO ON
ALLDNE:	MOVEI A,(W)		;WHERE IRT ENDED
	SUBI A,MESBUF+1		;WORDSS IN TEXT
	TLNE W,200000		;SEE IF NULL IS AT START OF A WORD
	TLNN W,100000		;"
	SKIPA			;ITS NOT. USE CURRENT COUNT
	JRST [	SOSE A		;IT IS. DECREMENT AND VERIFY
		JRST R35	;MORE THAN 0 WORDS
		RET]		;DONE
	LDB D,[POINT 6,W,5]	;GET BYTE POSITION
	SETZ B,			;WHERE MASK WILL BE ACCUMULATED
	SETO C,			;A WORD FULL OF BITS
	LSHC B,0(D)		;BUILD MASK
	ANDCAM B,0(W)		;GET RID OF EXTRANEOUS BITS IN LAST WORD

; RESET BIT 35 OF ALL WORDS IN THE NAME

R35:	MOVE B,A		;COPY # OF WORDS
	MOVEI C,1		;GET RESET VALUE (1B35)
R351:	ANDCAM C,MESBUF+1(B)	;RESET BIT 35 OF A WORD
	SOJG B,R351		;LOOP THRU ALL WORDS
	RETSKP			;GIVE SUCCESSFUL RETURN

;ROUTINE TO LOOK UP AN ASCIZ NAME IN ASSIGNED BLOCKS
;RETURNS A=BLOCK FOUND. W=POINTER TO PREVIOUS

LOOKUP:	MOVEI W,USEHD		;THE HEAD OF THEM ALL
LOOK2:	HRRZ W1,(W)		;GET NEXT ITEM
	JUMPE W1,R		;FAILED TO FIND IT
	JUMPL B,[CAME A,PID(W1) ;PID MATCH?
		JRST MORE 	;NO
		JRST GOOD]
	HLRZ W4,SIZZ(W1)	;GET COUNT OF THIS ONE
	SUBI W4,NODE		;DATA CONTENTS ONLY
	CAIE B,(W4)		;SAME SIZE?
	JRST MORE		;NO. GET MORE
	MOVEI W2,STRING(W1)	;WHERE STRING IS
	MOVE W5,A
CMPAR:	MOVE W3,(W5)		;NEXT WORD
	CAME W3,(W2)		;MATCH?
	JRST MORE		;NO
	AOS W5
	AOS W2
	SOJG W4,CMPAR		;DO ALL
GOOD:	MOVE A,W1
	RETSKP			;FOUND A MATCH
MORE:	MOVE W,W1		;GO ON
	JRST LOOK2

;BEGINNING OF INFO

INFO:	MOVEI A,400000
	MOVE B,[LEVTAB,,CHNTAB]	;FOR INTS
	SIR			;ESTABLISH INTS
	MOVNI B,1
	DIC			;DISSBALE EVERYTHING
	MOVSI B,(1B0)		;IPCF CHANNEL
	AIC			;ACTIVATE
	MOVE A,44		;FIRST FREE PAGE -1
	MOVEI A,1(A)		;FIRST FREE PAGE
	MOVEM A,FREHD		;INIT FREE SPACE HEADER
	MOVEI B,MSGBUF		;END OF FREE SPACE
	SUBI B,(A)		;SIZE OF FREE PSACE
	HRLM B,(A)		;INIT FREE SPACE
	MOVE P,[IOWD STKSIZ,STACK] ;INIT PDL

	MOVEI W,.MUGTI		;MAKE SURE NO INFO AROUND
	MOVEI A,3
	MOVEI B,W		;WHERE STUFF IS
	SETO W1,		;FOR ME ONLY
	MUTIL			;GET INFO'S PID
	 SKIPA			;OK
	FATAL <[SYSTEM]INFO ALREADY EXISTS>
	MOVEI W,.MUSPQ		;SET PID QUOTAS
	MOVEI W2,777		;MAX NUMBER OF PIDS
	MUTIL			;GO SET THEM
	 MOVEI A,3		;RESTORE THIS
	MOVEI W,.MUCRE		;GET ME A PID
	MOVEI W1,400000		;TEMP
	MUTIL			;GET IT
	 FATAL <INFO: COULD NOT ASSIGN A PID>
	MOVEM W2,MYPID		;STASH
;NOW DECLARE ME TO BE [SYSTEM]INFO

	MOVE W1,W2		;ARG TO LOC+1
	MOVEI W,.MUDFI		;THE FUNCTION TO DO IT
	MUTIL			;AND DO IT
	 FATAL <INFO: COULD NOT SET UP TO BE INFO>

;NOW PUT THE PID ON CHANNEL 0

	MOVEI A,3		;PACKET SIZE
	MOVEI B,W		;PACKET ADDRESS
	MOVEI W,.MUPIC		;THE PSI FUNCTION
	MOVE W1,MYPID		;THE PID TO INT ON
	SETZ W2,		;ONTO CHANNEL 0
	MUTIL			;DO IT
	 JFCL			;SHOULD GO .IF NO,C'EST LA VIE
;NOW SEND EVERYONE THE INFO STATUP MESSAGE

	MOVE A,[SIXBIT/JOBTTY/]	;GET NO OF JOBS IN SYSTEM
	SYSGT			;GET IT
	 JFCL
	HLLZ W,B		;SAVE COUNT
	MOVX A,FLD(.IPCCF,IP%CFC)+FLD(.IPCSN,IP%CFE) ;SAY FROM INFO
	MOVEM A,OUTTER
	SETZM MSGBUF		;CLEAR MEAAGE WORD
DOJOB:	MOVEI W1,.MUGTI		;GET HIS INFO PID
	MOVEI W2,(W)
	MOVEI A,3
	MOVEI B,W1
	MUTIL			;DO IT
	 JRST NOPID		;IMPOSSIBLE,BUT DONT PANIC IF IT HAPPENS
	CAME W3,MYPID		;AM I HIS INFO?
	JRST NOPID		;NO. FORGET HIM THEN
	MOVEI W1,.MUFJP		;GET PED FOR JOB FUNCTION
	MOVEM W1,MSGBUF+1
	HRRZM W,MSGBUF+2	;THE JOB NUMBER
	MOVEI A,777		;WORD COUNT
	MOVEI B,MSGBUF+1	;THE PACKET
	MUTIL			;GET THE PIDS
	 JRST NOPID		;NO PID FOR YHIS JOB
	MOVEI A,MSGBUF+3	;START OF PIDS
	PUSH P,W		;SAVE JOB INDEX
LOOP:	SKIPN B,(A)		;A PID?
	JRST NOPID1		;NO. END OF LIST
	ADDI A,2		;NEXT ENTRY
	CAMN B,MYPID		;IS IT ME?
	JRST LOOP		;YESS. IGNORE IT
	PUSH P,A		;SAVE PID POINTER
	MOVEM B,SEND		;FAKE OUT SENDIT
	MOVEI B,1		;ONE WORD MESSAGE
	CALL SENDIT		;SEND OFF THIS MESSAGE
	POP P,A			;GET PID POINTER
	JRST LOOP		;GO DO NEXT ONE
NOPID1:	POP P,W			;GET BACK JOB INDEX
NOPID:	AOBJN W,DOJOB		;DO ALL JOBS
;READY TO PROCESS REQUESSTS

TRYAGN:	MOVEI A,7
	MOVEI B,HEATER
	MOVE W1,MYPID
	MOVEM W1,HEADER		;THE ARG TO THE FUNCTION
	MUTIL			;GET NEXT REQUEST IN QUEUE
	 JRST NONE		;NONE THERE
	MOVE A,[1000,,MESBUF]	;YES
	MOVE B,HEADER		;GET THE RETURNED HEADER
	TRNE B,IP%CFV		;PAGE MODE?
	HRRI A,<MESBUF>_<-11>	;YES. PLUG IN PAGE NUMBER
	MOVEM A,HEADER+3	;WHERE TO PUT NEXT MESSAGE
	MOVSI A,(IP%CFB)	;DONT BLOCK
	IORM A,HEADER		;TO THE HEADER
	MOVEI A,7		;# OF WORDS IN HEADER
	MOVE B,MYPID		;GET MY PID
	MOVEM B,RCVPID		;PUT IN AS RECEIVER
	MOVEI B,HEADER
	MRECV			;GET NEXT REQUEST.
	 ERROR <IMPOSSIBLE RETURN FROM MRECV>
	MOVE A,HEADER		;GET HEADER
	MOVE C,PRIVS		;LOOK AT HIS PRIVILEGES
	SKIPN SEND		;DID HE IDENTIFY HIMSELF?
	TRNE C,600000		;NO. IS HE PROVILEGED?
	SKIPA			;DO IT
	JRST [	TRNE A,FLD(.IPCCC,IP%CFC) ;FROM MONITOR?
		JRST .+1	;YES. DO IT
		JRST TRYAGN]	;NO. JUNK MAIL
	LOAD B,IP%CFM,A
	CAIN B,.IPCFN		;UNDELIVERED MAIL?
	JRST TRYAGN		;YES. GIVE IT UP
	TRNN C,600000		;PRIVILEGED?
	TRNE A,IP%CFP		;NO. A PRIVILEGED REQUEST?
	SKIPA B,MSGBUF+1	;YES. BELEIVE THIS FIELD
	SETZ B,			;NO. INSIST ON A ZERO
	MOVEM B,CPYPID		;THE PID TO GET A COPY
	HRRZ A,MESBUF		;GET THE BUFFER
	SKIPE A			;VALID?
	CAILE A,MAXFNC		;VALID?
	JRST NACK		;ILLEGAL FUNCTION
	HLRZ B,MESSER		;GET COUNT OF MESSAGE
	CAILE B,^D511		;REASONABLE LENGTH?
	MOVEI B,^D511		;NO. MAKE IT REASONABLE
	SETZM MSGBUF(B)		;TIE OFF THE MESSAGE
	JRST @TABLE-1(A)	 ;GO DO IT 

;THESE ROUTINES SEND REPLYS BACK TO REQUESTORS

NORMAL:	SETZM OUTTER		;ALL IS WELL
SEND1:	MOVEI A,.IPCCF
	STOR A,IP%CFC,OUTTER	;SENT BY INFO
	CALL SENDIT		;DO THE SEND
	SKIPN A,CPYPID		;NEED TO SEND A COPY?
	JRST TRYAGN		;NO. GO DO SOME WORK
	MOVEM A,OUTTER+2	;TO THE PACKET
	CALL RESEND		;NOW SEND THE COPY
	JRST TRYAGN		;GO GET SOME MORE TO DO
SENDIT:	MOVE A,MYPID
	MOVEM A,OUTTER+1
	SKIPN A,HEADER+1	;DID SENDER IDENT HIMSELF?
	RET			;NO. WE ARE DONE THEN
	MOVEM A,OUTTER+2	;YES. MAKE HIM THE RECEIVER
	MOVSI B,(B)		;WORD COUNT TO LH
	HRRI B,MSGBUF		;WHERE THE REPLY IS
	MOVEM B,OUTTER+3	;TO PACKET DESCRIPTOR
RESEND:	MOVEI A,4
	MOVEI B,OUTTER
	SETZ F,			;NO QUOTA PROBLEMS
	SKIPN SENDQ		;A SEND Q AROUND?
	JRST DOSEND		;NO. DO THIS ONE
	CALL ONQ		;YES. QUEUE THIS UP
	 AOS F			;NO MORE FREE SPACE
	JRST DOQ		;GO OFF TO FLUSH Q
DOSEND:	MSEND			;SEND IT OFF
	 JRST [	CAIN A,IPCFX4	;PID DROPPED?
		JRST .+1	;YES. FORGET IT
		JRST ADDQ]	;MUST QUEUE IT UP
	CAIN B,OUTTER		;FROM QUEUE?
	RET			;ALL DONE

;REQUEST FROM SEND Q.

KILLIT:	HRRZ A,-2(B)		;GET Q LINK
	HRRM A,SENDQ		;UNLINK IT
	SKIPN A			;GOT A LINK?
	SETZM SENDQ		;NO. CLEAR Q
	MOVEI A,-2(B)		;BLOCK HEAD
	CALL DEALL		;RELEASE BLOCK
	SKIPE F			;RECOVERING FROM FREE SPACE DISIASTER?
	JRST RESEND		;YES. GO DO IT
	SKIPN SENDQ		;MORE STUFF IN THE QUEUE?
	RET			;NO. ALL DONE THEN
;
;ROUINES TO HANDLE SEND FAILURESS

DOQ:	HRRZ B,SENDQ		;DO NEXT GUY ON QUEUE
	ADDI B,2
	MOVEI A,4		;COUNT ISS ALWAYS 4
	JRST DOSEND		;GO TRY IT
ADDQ:	CAIE B,OUTTER		;NEED OT QUEU IT UP
	JRST NOQ		;NO. GO ANALYZE FAILURE
	CALL ONQ		;QUEUE IT UP
	 JRST [	MOVEI A,3*^D1000 ;SLLEP IT OFF
		DISMS
		JRST RESEND]	;GO TRY IT AGAIN
	SETZ F,			;FREE SSPACE IS OK
	RET			;ALL DONE
NOQ:	CAIE A,IPCFX5		;PID DISABLED?
	CAIN A,IPCFX7		;OR IS HE OVER QUOTA?
	JRST HSFALT		;YES. CHARGE HIM
	SKIPE F			;FREE SPACE BADDYS?
	JRST DOQ		;YES. GO TRY TO DO MORE
	RET			;NO ALL DONE
HSFALT:	AOS A,-1(B)		;BUMP RETRY COUNT
	CAIL A,MAXTRY		;TOO ANY TRIES
	JRST KILLIT		;YES. GIVE HIM UP
	HRRZ A,-2(B)		;UNLINK IT
	HRRM A,SENDQ
	SKIPN A
	SETZM SENDQ		;EMPTY QUEUE
	MOVEI A,-2(B)		;BLOCK HEAD
	CALL INITQ		;PUT IT ON THE QUEUE
	 JFCL
	SKIPE F			;FREE SPACE WOES?
	JRST DOQ		;YES. TRY TO FLUSH
	RET			;NO. ALL DONE
NACK:	MOVEI A,.IPCUF		;ILLEGAL FUNCTION
NACK1:	LSH A,^D35-POS(IP%CFE)	;SHIFT ERROR CODE INTO PROPER FIELD
	MOVEM A,OUTTER		;TELL HIM
	MOVEI B,1		;ONE WORD IN MESSAGE
	JRST SEND1

;THIS ROUTINE ADDS A SEND REQUEST TO THE SEND Q

ONQ:	HLRZ B,OUTTER+3		;SIZE OF THE MESSAGE
	MOVEI A,6(B)		;WORDS NEEDED
	CALL ALLOC		;GET SOME SPACE
	 RET			;NONE THERE
	SETZM 1(A)		;INITIALIZE RETRY COUNT
	MOVEI B,2(A)		;START OF DTAT AREA
	HRLI B,OUTTER		;START OF BLT
	BLT B,5(A)		;MOVE THE HEADER BLOCK
	MOVEI B,6(A)		;INDEX INTO DATA PART
	HRRM B,5(A)		;NEW DATA POINTER
	HRLI B,MSGBUF		;START OF BLT FOT THE DATA
	HLRZ C,OUTTER+3		;COUNT
	ADDI C,-1(B)		;WHERE ALL THIS WILL END
	BLT B,(C)		;DO IT
INITQ:	HLRZ C,SENDQ		;TAIL FO QUEUE
	HRLM A,SENDQ		;NEW TAIL
	SKIPN C			;EMPTY QUEUE?
	MOVEI C,SENDQ		;YES
	HRRM A,(C)		;COMPLETE LINK
	RETSKP			;ALL DONE
;BEGINNING OF PROCESSING ROUTINES
NONE:	SKIPE SENDQ		;STUFF TO SEND?
	JRST [	MOVEI A,^D500	;SLEEP FOR .5 SECS
		DISMS		;DO IT
		CALL DOQ	;NOW DO SOME SENDS
		JRST TRYAGN]	;AND GO TO GET MORE
	MOVEI A,400000		;THIS FORK'S ID
	EIR			;TURN ON INTERRUPTS
	WAIT			;INFINITE SLEEP
GOTONE:	DIR			;TURN OFF INTERRUPTS
	MOVEI A,TRYAGN
	MOVEM A,ADD1		;TO GO THERE
	DEBRK
;TRANSFER TABLE FOR INFO FUNCTIONS

TABLE:	IPCIW			;FIND PID FOR NAME
	IPCIG			;FIND NAME FOR PID
	IPCII			;ASSIGN TEMP NAME
	IPCIJ			;ASSIGN PERMANENT NAME
	IPCIK			;NOTIFY WHEN PID IS DELETED
	NACK
	NACK
	REPEAT 5,<NACK>		;UNIMPLEMENTED FUNCTIONS
	IPCIS			;IPCC NOTICE
MAXFNC==.-TABLE			;MAXIMUM FUNCTION NUMBER
;FUNCTION 1. FIND PID FOR GIVEN NAME

IPCIW:	VERSIZ 3,.IPCEN		;MUST BE AT LEAST 3 WORDS
	CALL NAME1		;GET NAME
	JFCL
	MOVE B,A
	MOVEI A,MESBUF+2	;WHERE NAME IS
	CALL LOOKUP		;SEE IF ITS DEFINED
	 JRST [	MOVEI A,.IPCNN	;UNKNOWN NAME
		JRST NACK1]	;BOMB HIM
	MOVE B,PID(A)		;THE PID
	CALL VERPID		;VERIFY PID
	 JRST KILL1		;IT'S GONE AWAY
	MOVEM B,MESBUF+1	;ANSWER
	MOVEI B,2		;SIZE OF REPLY
	JRST NORMAL		;TELL HIM OF OUR SUCCESS
;THESE ROUTINES VERIFY PIDS

VERPID:	MOVEI W1,.MUFOJ		;GET JOB NO
	MOVE W2,B		;OF THIS PID
	PUSH P,A		;SAVE A
	PUSH P,B
	MOVEI A,3
	MOVEI B,W1
	MUTIL			;GET IT
	 JRST [	POP P,B
		POP P,A
		RET]	;BAD
	POP P,B
	POP P,A			;GET A ABCK
	RETSKP			;TELL CALLER PID IS GOOD

KILL:	SKIPA W1,[.IPCBP]
KILL1:	MOVEI W1,.IPCNN
	PUSH P,W1		;SAVE ERROR MESSAGE
	CALL UNCHN		;UNDO THIS REQUEST AND RELEASE SPACE
	POP P,A			;GET ERROR MESSAGE
	JRST NACK1		;DONE

UNCHN:	MOVE W1,(A)		;LINK TO NEXT GUY
	HRRM W1,(W)		;UNLINK THIS GUY
	CALL DEALL		;AND RELEASE REQUEST
	RET			;RETURN

;FUNCTION 2. FIND NAME FOR GIVEN PID
IPCIG:	VERSIZ 3,.IPCBP		;MUST BE AT LEAST 3 WORDS
	SETO B,			;LOOKING FOR PID
	MOVE A,MESBUF+2		;THE PID
	CALL LOOKUP
	JRST [	MOVEI A,.IPCBP	;UNKNOWN PID
		JRST NACK1]	;RETURN ERROR
	MOVE B,PID(A)		;THE PID
	CALL VERPID		;MAKE SURE PID IS GOOD
	 JRST KILL		;IT'S NOT
	HLRZ W,SIZZ(A)		;COUNT OF WORDS
	MOVEI W1,STRING(A)
	MOVEI W2,MESBUF+1
	SUBI W,NODE
	MOVEI B,1(W)
MOVIT:	MOVE W3,(W1)
	MOVEM W3,(W2)
	AOS W1
	AOS W2
	SOJG W,MOVIT		;MOVE WHOLE NAME
	JRST NORMAL

;FUNCTIONS 3 AND 4. ASSIGN NAME TO PID

IPCII:IPCIJ:
	VERSIZ 3,.IPCEN		;MUST BE AT LEAST 3 WORDS
	CALL NAME		;GET THE NAME
	JRST [	MOVEI A,.IPCEN	;BAD NAME
		JRST NACK1]	;BOMB HIM
	MOVE B,A		;SIZE
	MOVEI A,MSGBUF+2	;WHERE THE NAME IS
	CALL LOOKUP		;SEE IF DEFINED
	JRST ISGOOD		;GOOD NAME
	PUSH P,B		;SAVE SIZE
	MOVE B,PID(A)		;THD QSSIGNED PID
	CALL VERPID		;SEE IF PID IS GOOD
	 JRST [	CALL UNCHN	;NO IT'S NOT
		POP P,B		;GET SIZE
		JRST ISGOOD]	;GO ASSIGN IT
	POP P,B			;IT'S GOOD
	MOVE B,PID(A)		;GET PID AGAIN
	CAMN B,SEND		;SAME AS REQUESTOR'S
	JRST ALLWIT		;YES. ALLOW IT
	MOVEI A,.IPCDN		;GIVE ERROR
	JRST NACK1
ISGOOD:	MOVEI A,NODE(B)		;SIZE NEEDED
	CALL ALLOC		;GET SOME FREE SPACE
	 JRST [	MOVEI A,.IPCFF	;NO MORE FREE SPACE
		JRST NACK1]	;TELL HIM
	MOVE B,SEND
	MOVEM B,PID(A)		;PUTPID IN PID
	MOVEM B,MSGBUF+1	;REPLY
	HLRZ B,SIZZ(A)
	SUBI B,NODE
	MOVEI W,MSGBUF+2
	MOVEI W1,STRING(A)
STOR:	MOVE W2,(W)		;GET A WORD
	MOVEM W2,(W1)
	AOS W
	AOS W1
	SOJG B,STOR		;DO ENTIRE NAME

;NOW INSERT PACKET INTO ASSIGNED QUEUE

	MOVE B,USEHD		;TOP OF QUEUE
	MOVEM A,USEHD		;STASH IT
	HRRM B,(A)		;COMPLETE LINK
ALLWIT:	MOVEI B,2
	JRST NORMAL		;TELL HIM IT'S DONE
;FUNCTION 5. INFORM SENDER WHEN SPECIFIED PID IS DELETED

IPCIK:	VERSIZ 3,.IPCBP		;MUST BE AT LEAST 3 WORDS
	MOVX A,SC%WHL+SC%OPR+SC%IPC
	TDNN A,PRIVS		;SENDER PRIVILEGED?
	JRST [	MOVEI A,.IPCPI	;NO
		JRST NACK1]	;RETURN ERROR
	MOVE B,MSGBUF+2		;GET PID TO BE WATCHED
	CALL VERPID		;GOOD PID?
	 JRST [	MOVEI A,.IPCBP	;NO
		JRST NACK1]

; CHECK FOR AN EXISTING ENTRY WITH SAME PIDS

	MOVE A,SEND		;GET REQUESTOR'S PID
	MOVE B,MSGBUF+2		;GET WATCHED PID
	MOVEI W,DPNHD		;GET HEAD OF CURRENT LIST
IPCIK1:	HRRZ W,(W)		;GET NEXT ENTRY IN DPN LIST
	JUMPN W,[CAMN A,DPNRPD(W) ;CHECK FOR MATCH
		CAME B,DPNWPD(W)
		JRST IPCIK1	;NO MATCH, CHECK NEXT ENTRY
		JRST IPCIK2]	;HAS ALREADY BEEN REQUESTED

; CREATE ENTRY IN NOTIFICATION LIST

	MOVEI A,DPNSZ		;GET SIZE OF DPN ENTRY
	CALL ALLOC		;ALLOCATE FREE SPACE TO REMEMBER IT
	 JRST [	MOVEI A,.IPCFF	;FREE SPACE EXHAUSTED
		JRST NACK1]
	MOVE B,SEND		;GET REQUESTOR'S PID
	MOVEM B,DPNRPD(A)	;STORE IT
	MOVE B,MSGBUF+2		;GET WATCHED PID
	MOVEM B,DPNWPD(A)	;PUT IN LIST ENTRY

; LINK THIS ENTRY ONTO THE LIST

	MOVE B,DPNHD		;GET CURRENT HEAD
	HRRM B,(A)		;POINT NEW HEAD AT OLD HEAD
	MOVEM A,DPNHD		;SET NEW HEAD
IPCIK2:	MOVE B,MSGBUF+2		;GET WATCHED PID
	MOVEM B,MSGBUF+1	;PUT IN RETURN MESSAGE
	MOVEI B,2		;GET SIZE OF RESPONSE
	JRST NORMAL		;SEND GOOD RESPONSE TO REQUESTOR
;FUNCTION 15. MESSAGE FROM MONITOR TO DROP PIDS

IPCIS:	MOVE W5,PRIVS		;MUST BE PRIVILEGED
	MOVE A,HEADER		;GET HEADER WORD TOO
	TXNN W5,SC%WHL+SC%OPR	;IS HE PRIVILEGED?
	TRNE A,FLD(.IPCCC,IP%CFC) ;NO. IS HE THE MONITOR?
	SKIPA			;YES. LET HIM DO IT THEN
	JRST [	MOVEI A,.IPCPI	;INSUFFICIENT PRIVILEGES
		JRST NACK1]	;GIVE HIM THE ERROR
	PUSH P,[MSGBUF+1]	;SET UP TO SCAN PID LIST
LOOK3:	AOS (P)			;POINT AT NEXT PID
	SKIPN A,@(P)		;END OF LIST?
	JRST [	ADJSP P,-1	;YES, DELETE PID LIST POINTER FROM STACK
		MOVEI B,1	;GET SIZE OF MESSAGE
		JRST NORMAL]	;SEND GOOD RESPONSE
	CALL SDPN		;TELL ANYONE WHO WANTS TO KNOW
LOOK4:	MOVE A,@(P)		;GET PID
	SETO B,			;PID SEARCH
	CALL LOOKUP		;LOOK FOR IT
	 JRST LOOK3		;NONE FOUND
	CALL UNCHN		;DELETE ENTRY FROM USE-LIST
	JRST LOOK4		;LOOP FOR ALL NAMES
; SDPN - CALLED WHEN MONITOR TELLS INFO THAT PIDS HAVE BEEN DELETED;
;	 SEARCHES NOTIFY LIST AND TELLS ANYONE WHO WANTS TO KNOW
;  A/ DELETED PID
; RETURNS +1: ALWAYS

SDPN:	STKVAR <SDPWPD>
	MOVEM A,SDPWPD		;STORE DELETED PID
SDPN1:	MOVE W1,SDPWPD		;GET PID
	MOVEI W,DPNHD		;SET UP TO SCAN DPN LIST
SDPN2:	HRRZ A,(W)		;GET NEXT ENTRY IN DPN LIST
	JUMPE A,R		;END OF LIST, EXIT
	CAMN W1,DPNRPD(A)	;RECEIVER'S PID DELETED?
	JRST [	CALL UNCHN	;YES, JUST DELETE ENTRY FROM LIST
		JRST SDPN1]	;GO BACK FOR ANOTHER SCAN
	CAMN W1,DPNWPD(A)	;WATCHED PID DELETED?
	JRST [	CALL SNDDPN	;YES, NOTIFY RECEIVER PID
		JRST SDPN1]	;GO SCAN AGAIN
	MOVE W,A		;NO MATCHES, STEP TO NEXT ENTRY
	JRST SDPN2


; SNDDPN - NOTIFY USER THAT A PID HAS BEEN DELETED, AND REMOVE ENTRY
;	   FROM NOTIFICATION LIST
;  A/ ADDRESS OF DPN LIST ENTRY
;  W/ ADDRESS OF PREVIOUS ENTRY (FOR UNCHN)
; RETURNS +1: ALWAYS

SNDDPN:	PUSH P,SEND		;SAVE CURRENT SENDER'S PID
	PUSH P,MSGBUF		;SAVE CURRENT SENDER'S .IPCI0 WORD
	MOVE B,DPNWPD(A)	;GET DELETED PID
	MOVEM B,MSGBUF		;BUILD MESSAGE (1 WORD)
	MOVE B,DPNRPD(A)	;GET RECEIVER'S PID
	MOVEM B,SEND		;STORE IT FOR SENDIT
	MOVX B,FLD(.IPCKM,IP%CFE)+FLD(.IPCCF,IP%CFC)
	MOVEM B,OUTTER		;SET UP WORD 0 OF PDB
	CALL UNCHN		;REMOVE DPN ENTRY AND RELEASE FREE SPACE
	MOVEI B,1		;GET SIZE OF MESSAGE
	CALL SENDIT		;SEND TO REQUESTOR
	POP P,MSGBUF		;RESTORE .IPCI0 WORD
	POP P,SEND		;RESTORE PID
	RET

	END <3,,ENTVEC>