TITLE NSPTST Test NSP uuo SUBTTL T.Neustaedter/Tarl SEARCH DCN Comment @ This program is intended as an aid to debugging DECnet-10 programs, and as a working example of a program using the NSP. uuo. It is intended that this program be used in conjuction with a listing of NSPUSR.MEM, as many of the requested fields are inadequatley labeled when this program requests them. The NSP. uuo in this program will always set NS.WAI, so if you want to exercise asynchronous I/O, you'll have to write your own hack. @ $ONLY==I.PRM!I.GTT!I.LUO $INIT NSP ;Macro to convert string block length in bytes to words DEFINE SLEN(BYTES),<1+</4>> XP SMAX,400 ;Maximum size for string block arg ;Define some blocks for use in NSP. uuo $LVAR FZER ;First zeroed location \ $BLOCK UBLK,.NSAMX+1 ;Block for the NSP uuo \ $BLOCK CBLK,.NSCMX+1 ;Connect block \ $BLOCK SPDB,.NSDMX+1 ;Source PDB (name follows)\ $BLOCK SPNM,SLEN(^D16) ;Source process name | $BLOCK DPDB,.NSDMX+1 ;Destination PDB | Blocks zeroed $BLOCK DPNM,SLEN(^D16) ;Destination process name | $BLOCK NODE,SLEN(^D6) ;Node name block | before every $BLOCK USER,SLEN(^D39) ;User ID | NSP. execution $BLOCK PASS,SLEN(^D39) ;Password / $BLOCK ACCT,SLEN(^D39) ;Account / $BLOCK DATA,SLEN(^D16) ;User data / $BLOCK SBLK,SLEN(SMAX) ;String block | $LVAR LZER ;Last zeroed location / ;Define some values for uuo description macros ;Flags indicating read, write, prived FL.R=40 FL.W=20 FL.P=10 FL.=0 ;Function code describing format of argument FN.CBL=1 FN.SBL=2 FN.ARG=3 FN.BCT=4 FN.BPT=5 ;Macros to add up all the flags in an individual argument DEFINE CBL(A,B,C), DEFINE SBL(A,B,C), DEFINE ARG(A,B,C), DEFINE BCT(A,B,C), DEFINE BPT(A,B,C), ;Macro to build up a dispatch entry from all the above DEFINE NSPFNC(SIXNAM,ARG1,ARG2,ARG3,ASCNAM),< XWD SIXBIT \ SIXNAM \,[B5+B11+B17+.NSF'SIXNAM ASCIZ \ASCNAM\] > ;These are the definitions of all the NSP. functions. The format of the ;NSPFNC macro is function name followed by the three possible arguments ;of the NSP. UUO. ; ; R = Read this arg from user's block ; W = Write this arg into user's block ; P = Privileged Argument NSPTAB: NSPFNC EA,CBL(R),ARG(R),ARG(R,P), NSPFNC EP,CBL(R),,, NSPFNC RI,CBL(W),ARG(W),ARG(W), NSPFNC AC,SBL(R),ARG(R),ARG(R,P), NSPFNC RJ,SBL(R),ARG(R,P),, NSPFNC RC,SBL(W),ARG(W),ARG(W), NSPFNC SD,SBL(R),ARG(R,P),, NSPFNC AB,SBL(R),ARG(R,P),, NSPFNC RD,SBL(W),ARG(W),, NSPFNC RL,,,, NSPFNC RS,ARG(W),ARG(W),, NSPFNC IS,SBL(R),,, NSPFNC IR,SBL(W),,, ; NSPFNC DS,BCT(R,W),BPT(R,W),, ; NSPFNC DR,BCT(R,W),BPT(R,W),, NSPFNC SQ,ARG(R),ARG(R),ARG(R), NSPFNC RQ,ARG(W),ARG(W),ARG(W), NSPFNC JS,ARG(R,P),ARG(R,P),, NSPFNC JR,ARG(W),ARG(W),, NSPFNC PI,ARG(R),,, NSPLEN=.-NSPTAB START: $SETUP ;Init LUUO package $INFORM INI, PUSH P,[.] ;save this as address to return to START1: $PROMPT T1,%SIXBIT, MOVE T2,[IOWD NSPLEN,NSPTAB] ;Pointer to function table START2: HLLZ T3,1(T2) ;Get a function name CAMN T3,T1 ;is this the one? JRST PRCFNC ;yes, process the function AOBJN T2,START2 ;loop until we find it $WARN NSF, MOVE T2,[IOWD NSPLEN,NSPTAB] ;Pointer to function table START3: TSTRG. [ASCIZ \.NSF\] ;Prefix function name HLLZ T1,1(T2) ;Get a name TSIXN. T1, ;Type it out TCHRI. .CHTAB ;Space over HRRZ T1,1(T2) ;Get pointer to extra info TLINE. 1(T1) ;and type long name AOBJN T2,START3 ;And loop until we finish typing them out JRST START1 ;try again. PRCFNC: SETZM FZER ;clean first word of zeroable area MOVE T1,[FZER,,FZER+1] ;blt pointer BLT T1,LZER ;Clear entire zeroable area. HRRZ P1,1(T2) ;Get pointer to detail for this function TSTRG. [ASCIZ \** For function \] TLINE. 1(P1) ;Type out detailed name HRLZ T1,(P1) ;Get function code IOR T1,[NS.WAI!.NSAMX] ;Add flags and length MOVEM T1,UBLK+.NSAFN ;save in function and length word $PROMPT T1,%DECIMAL, MOVEM T1,UBLK+.NSACH ;save in channel field MOVE P1,(P1) ;Get detail on chunks to fill in LDB T1,[POINT 6,P1,5] ;get bits indicating type of block CALL GETARG ;Get argument to store here JRST PRCEND ;error, abort function. MOVEM T1,UBLK+.NSAA1 ;Save as argument 1 LDB T1,[POINT 6,P1,11] ;Get bits for second argument CALL GETARG ;Get argument JRST PRCEND MOVEM T1,UBLK+.NSAA2 ;Save as argument 2 LDB T1,[POINT 6,P1,17] ;Get bits for third argument CALL GETARG ;Get argument JRST PRCEND MOVEM T1,UBLK+.NSAA3 ;Save as argument 3 MOVEI T1,UBLK ;pointer to argument block NSP. T1, ;do the function $WARN NFF,,TYPERR,T1 HRRZ T2,UBLK+.NSACH $INFORM CHN,,.TDECW##,T2 MOVEI T1,SBLK ;Point to the generic string block MOVEI T2,[ASCIZ \String block contents: \] CALL TYPSBL ;Type it out if relevant JRST PRCEND CALL TYPCBL ;Type out the connect block JRST PRCEND PRCEND: JRST START1 ;and do again. TYPERR: SKIPL T1 ;Make sure not negative CAXLE T1,ERRMAX ;Range check SETZ T1, ;zero error code is catch all TSTRG. @ERRTAB(T1) ;Type out error string RET ;and return ERRTAB: [ASCIZ \%NE???(?) Unknown error code\] [ASCIZ \%NEABE(1) Argument block format error\] [ASCIZ \%NEALF(2) Allocation failure\] [ASCIZ \%NEBCN(3) Bad channel number\] [ASCIZ \%NEBFT(4) Bad format type in process block\] [ASCIZ \%NECFE(5) Connect block format error\] [ASCIZ \%NEIDL(6) Interrupt data too long\] [ASCIZ \%NEIFM(7) Illegal flow control mode\] [ASCIZ \%NEILF(10) Illegal function\] [ASCIZ \%NEJQX(11) Job quota exhausted\] [ASCIZ \%NELQX(12) Link quota exhausted\] [ASCIZ \%NENCD(13) No connect data to read\] [ASCIZ \%NEPIO(14) Percentage input out of bounds\] [ASCIZ \%NEPRV(15) No privileges to perform function\] [ASCIZ \%NESTB(16) Segment size too big\] [ASCIZ \%NEUKN(17) Unknown node name\] [ASCIZ \%NEUXS(20) Unexpected state: unspecified\] [ASCIZ \%NEWNA(21) Wrong number of arguments\] [ASCIZ \%NEWRS(22) Function called in wrong state\] [ASCIZ \%NECBL(23) Connect block length error\] [ASCIZ \%NEPBL(24) Process block length error\] [ASCIZ \%NESBL(25) String block length error\] [ASCIZ \%NEUDS(26) Unexpected state: disconnect sent\] [ASCIZ \%NEUDC(27) Unexpected state: disconnect confirmed\] [ASCIZ \%NEUCF(30) Unexpected state: no confidence\] [ASCIZ \%NEULK(31) Unexpected state: no link\] [ASCIZ \%NEUCM(32) Unexpected state: no communication\] [ASCIZ \%NEUNR(33) Unexpected state: no resources\] [ASCIZ \%NERBO(34) Rejected by object\] [ASCIZ \%NEDBO(35) Disconnected by object (when running) \] [ASCIZ \%NERES(36) No resources\] [ASCIZ \%NEUNN(37) Unrecognized node name\] [ASCIZ \%NERNS(40) Remote node shut down\] [ASCIZ \%NEURO(41) Unrecognized object\] [ASCIZ \%NEIOF(42) Invalid object name format\] [ASCIZ \%NEOTB(43) Object too busy\] [ASCIZ \%NEABM(44) Abort by management\] [ASCIZ \%NEABO(45) Abort by object\] [ASCIZ \%NEINF(46) Invalid node name format\] [ASCIZ \%NELNS(47) Local node shut down\] [ASCIZ \%NEACR(50) Access control rejection\] [ASCIZ \%NENRO(51) No response from object\] [ASCIZ \%NENUR(52) Node unreachable\] [ASCIZ \%NENLK(53) No link\] [ASCIZ \%NEDSC(54) Disconnect complete\] [ASCIZ \%NEIMG(55) Image field too long\] [ASCIZ \%NEREJ(56) Unspecified reject reason\] [ASCIZ \%NEBCF(57) Bad combo of ns.eom & ns.wai flags\] [ASCIZ \%NEADE(60) Address error\] ERRMAX=.-ERRTAB GETARG: LDB T2,[POINT 3,T1,35] ;Get the actual function code JRST @.+1(T2) ;dispatch IFIW RETZER ;(0) No arg, return zero IFIW RETCBL ;(1) Get a connect block IFIW RETSBL ;(2) Get a string block IFIW RETARG ;(3) Get a word IFIW RETBCT ;(4) Byte count (save string) IFIW RETBPT ;(5) Byte pointer (get from saved) IFIW RETERR ;(6) Error, no such code IFIW RETERR ;(7) Error, no such code RETZER: SETZ T1, ;Return clean AC RETSKP ;and success since we didn't fail RETERR: $ERROR INV, EXIT ;Service routine. Read a string into a string block ;Call ; T1/ Flags ; T2/ length allowed (in bytes) ; T3/ Pointer to block to fill in ;Return ; T1/ Pointer to string block filled in INPSBL: CALL .SAV2 ;Preserve P1 MOVE P1,T3 ;preserve pointers MOVE P2,T2 ;preserve length TRNN T1,FL.R ;is the monitor going to read this? JRST INPSB3 ;No, just set up the block header INPSB1: $PROMPT T3,%ASCII, MOVE T3,[POINT 7,.NMUL##] ;BPT to scan string storage area MOVE T4,[POINT 8,1(P1)] ;Pointer to string area INPSB2: ILDB T1,T3 ;get a byte from scan string area JUMPE T1,INPSB3 ;done, do accounting IDPB T1,T4 ;Save in string area SOJGE T2,INPSB2 ;loop $WARN STL, MOVE T2,P2 ;restore length we will accept JRST INPSB1 ;and try again. INPSB3: MOVE T1,P2 ;Copy number of bytes allowed SUB P2,T2 ;Find out how many bytes we got ADDI T1,3 ;round up to nearest word IDIVI T1,4 ;convert into words ADDI T1,1 ;Add overhead word of header HRL T1,P2 ;bytes,,words MOVEM T1,(P1) ;store as string block header MOVE T1,P1 ;get back pointer to string block RETSKP ;and return success ;Service routine. Type a string block ;Call ; T1/ Pointer to string block ; T2/ Descriptor string to type out ;Return ; RETSKP TYPSBL: HLRZ T4,(T1) ;Get number of bytes in string block JUMPE T4,.POPJ1## ;Nothing there, return TSTRG. (T2) ;Type out descriptor of this string block MOVE T3,[POINT 8,1(T1)] ;Byte pointer to data in string block TYPSB2: ILDB T2,T3 ;Get a byte from string TCHRI. (T2) ;Type it out SOJG T4,TYPSB2 ;Loop until end TCRLF. ;end line RETSKP ;Service routine. Input a process descriptor block ;Call ; T1/ Flags from GETARG ; T2/ Pointer to block to use as PDB block ; Block must be immediatley followed by 5 words for process name ;Return ; T1/ Pointer to PDB block INPPDB: CALL .SAV1 ;Storage MOVE P1,T2 ;Save pointer to pdb block MOVEI T2,.NSDMX ;Length of PDB MOVEM T2,.NSDFL(P1) ;Save in PDB MOVEI T2,.NSDMX+1(P1) ;Pointer to process name block MOVEM T2,.NSDPN(P1) ;Store in process block TRNN T1,FL.R ;Is the monitor going to read this? JRST INPPD6 ;No, just keep on going INPPD2: $PROMPT T2,%DECIMAL, SKIPL T2 ;Range check CAILE T2,2 ;to within reason $WARN FTO,,,,INPPD2 MOVEM T2,.NSDFM(P1) ;save as format type JUMPN T2,INPPD5 ;If non-zero format type, skip object type $PROMPT T2,%DECIMAL, CAXL T2,-2 ;Range check CAXLE T2,^D255 ;to within reason (neg 1 is anything) $WARN OBO,,,,INPPD2 MOVEM T2,.NSDOB(P1) ;save as object type JRST INPPD7 ;and skip ppn and process name INPPD5: CAXE T2,2 ;Format type 2? JRST INPPD6 ;No, don't ask for PPN $PROMPT T2,%OCTAL, MOVEM T2,.NSDPP(P1) ;Save in block INPPD6: MOVEI T2,^D16 ;Max 16 characters for process name MOVE T3,.NSDPN(P1) ;Get pointer to string block area TRNE T1,FL.R ;Is this going to be read? TSTRG. [ASCIZ \Process name \] ;start up string CALL INPSBL ;Get string block RET ;propagate error INPPD7: MOVE T1,P1 ;get back pointer to process block RETSKP ;return success ;Service routine. Type out a PDB ;Call ; T1/ Pointer to PDB ; T2/ Pointer to header string TYPPDB: CALL .SAV1 ;Storage MOVE P1,T1 ;Store pointer to PDB SKIPN .NSDFM(P1) ;Format type 0? SKIPE .NSDOB(P1) ;object type 0? TRNA ;Something non zero, lets type this out RETSKP ;yes to both being zero, forget about him TSTRG. (T2) ;Type out header MOVE T1,.NSDFM(P1) ;Get format type TSTRG. [ASCIZ \Format type \] TDECW. T1, ;TYpe it out in decimal TCHRI. "," JUMPN T1,TYPPD2 ;non zero, skip object type code TSTRG. [ASCIZ \ Object type \] MOVE T1,.NSDOB(P1) ;Get object type TDECW. T1, ;and type it out RETSKP ;and return TYPPD2: CAIE T1,2 ;Format type 2 JRST TYPPD3 ;No, skip PPN TSTRG. [ASCIZ \ PPN=\] ;Indicate PPN coming next MOVE T1,.NSDPP(P1) ;Get ppn TXWDW. T1, ;Type it out as a PPN TYPPD3: SKIPN T1,.NSDPN(P1) ;Get pointer to process name block RETSKP ;None there, done MOVEI T2,[ASCIZ \, Name=\] ;header if needed JRST TYPSBL ;And type it out, returning RETCBL: CALL .SAV2 ;save a couple of acs MOVE P1,T1 ;save flags MOVEI T2,.NSCMX ;Get length of connect block MOVEM T2,CBLK+.NSCNL ;save as length TRNE P1,FL.R ;Is this going to be read? TSTRG. [ASCIZ \Node name \] ;head up question MOVEI T3,NODE ;pointer to node block MOVEI T2,6 ;maximum length to node name block CALL INPSBL ;Read string block RET ;propagate error MOVEM T1,CBLK+.NSCND ;save pointer in connect block TRNE P1,FL.R ;Is this going to be read? TLINE. [ASCIZ \Source process descriptor:\] MOVE T1,P1 ;Get back flags again MOVEI T2,SPDB ;Pointer to source PDB block CALL INPPDB ;Read process descriptor block RET ;failure, return MOVEM T1,CBLK+.NSCSD ;Save in connect block TRNE P1,FL.R ;Is this going to be read? TLINE. [ASCIZ \Destination process descriptor:\] MOVE T1,P1 ;Get back flags yet again MOVEI T2,DPDB ;pointer to destination PDB block CALL INPPDB ;Read pdb RET ;propagate return MOVEM T1,CBLK+.NSCDD ;save as destination pdb TRNE P1,FL.R TSTRG. [ASCIZ \User id \] MOVE T1,P1 ;flags yet again MOVEI T2,^D39 ;Length MOVEI T3,USER ;User id string area CALL INPSBL ;Read a string block RET ;propagate return MOVEM T1,CBLK+.NSCUS ;store in block TRNE P1,FL.R TSTRG. [ASCIZ \Password \] MOVE T1,P1 ;flags yet again MOVEI T2,^D39 ;Length MOVEI T3,PASS ;Password CALL INPSBL ;Read a string block RET ;propagate return MOVEM T1,CBLK+.NSCPW ;store in block TRNE P1,FL.R TSTRG. [ASCIZ \Account \] MOVE T1,P1 ;flags yet again MOVEI T2,^D39 ;Length MOVEI T3,ACCT ;Account string area CALL INPSBL ;Read a string block RET ;propagate return MOVEM T1,CBLK+.NSCAC ;store in block TRNE P1,FL.R TSTRG. [ASCIZ \User data \] MOVE T1,P1 ;flags yet again MOVEI T2,^D39 ;Length MOVEI T3,DATA ;User data string area CALL INPSBL ;Read a string block RET ;propagate return MOVEM T1,CBLK+.NSCUD ;store in block MOVEI T1,CBLK ;Pointer to connect block RETSKP ;Type out connect block if anything interesting TYPCBL: SKIPN CBLK+.NSCNL ;Did we use the connect block? RETSKP ;Nope, just return TLINE. [ASCIZ \Connect block contains: \] SKIPN T1,CBLK+.NSCND ;Is there a node name block? JRST TYPCB1 ;No, skip over this MOVEI T2,[ASCIZ \Node name: \] CALL TYPSBL ;Type the string block out (if anything there) RET TYPCB1: SKIPN T1,CBLK+.NSCSD ;Is there a source process descriptor? JRST TYPCB2 ;No. MOVEI T2,[ASCIZ \Source PDB: \] CALL TYPPDB ;Type the PDB RET TCRLF. TYPCB2: SKIPN T1,CBLK+.NSCDD ;Destination pdb? JRST TYPCB3 ;no MOVEI T2,[ASCIZ \Destination PDB: \] CALL TYPPDB ;Type it out RET TCRLF. TYPCB3: SKIPN T1,CBLK+.NSCUS ;User id? JRST TYPCB4 ;no MOVEI T2,[ASCIZ \User ID: \] CALL TYPSBL RET TYPCB4: SKIPN T1,CBLK+.NSCPW ;Password? JRST TYPCB5 ;no MOVEI T2,[ASCIZ \Password: \] CALL TYPSBL RET TYPCB5: SKIPN T1,CBLK+.NSCAC ;Account? JRST TYPCB6 ;no MOVEI T2,[ASCIZ \Account: \] CALL TYPSBL RET TYPCB6: SKIPN T1,CBLK+.NSCUD ;User data? JRST TYPCB7 MOVEI T2,[ASCIZ \User data: \] CALL TYPSBL RET TYPCB7: RETSKP ;Finit. RETARG: TRNN T1,FL.R ;Is this going to be read? TDZA T1,T1 ;No, just return a 0 $PROMPT T1,%OCTAL, RETSKP ;Return success RETSBL: MOVEI T2,SMAX ;Get size of string block we will take MOVEI T3,SBLK ;Pointer to string block JRST INPSBL ;And input it RETBCT: RETBPT: $DIE UNF, SAVJMP: EXCH F,-1(P) ;Swap things around a bit EXCH F,(P) ;muddy the water a bit EXCH F,-1(P) ;make things confusing POPJ P, ;return to caller with stack set up .SAV1: EXCH P1,(P) ;save current value of P1, get calling PC PUSH P,P1 ;push calling PC MOVE P1,-1(P) ;restore original value of PC PUSHJ P,SAVJMP ;return to caller, with stack fixed up SKP ;non skip return AOS -1(P) ;skip return, bump higher level return pc JRST .RES1 ;pop acs off .SAV2: EXCH P1,(P) ;save current value of P1, get calling PC PUSH P,P2 PUSH P,P1 ;push calling PC MOVE P1,-2(P) ;restore original value of PC PUSHJ P,SAVJMP ;return to caller, with stack fixed up SKP ;non skip return AOS -2(P) ;skip return, bump higher level return pc ; JRST .RES2 ;pop acs off .RES2: POP P,P2 ; few .RES1: POP P,P1 ; acs RET ;return to higher level routine END START