Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_SRC_3_19910112 - utilities/trafic.mac
There are no other files named trafic.mac in the archive.
;<PAETZOLD>TRAFIC.MAC.193, 28-Apr-82 19:19:23, Edit by PAETZOLD
;This is now version 4.0(32)-0
;Old edit history has been deleted.

;END OF REVISION HISTORY

; Copyright (C) 1981, 1982 by
; Digital Equipment Corporation, Marlboro, Massachusetts
SALL
DEFINE VTITLE(VW,VMA,VMI,VE),<
TITLE TRAFIC - Create ARPANET Traffic - KWPaetzold - Version 'VMA'.'VMI'('VE')-'VW' ->

IF1 <TITLE TRAFIC>
IF2 <VTITLE \VWHO,\VMAJOR,\VMINOR,\VEDIT>
IF2 <PRINTX TRAFIC - PASS 2>
COMMENT \

	This program written by:

			Kevin W. Paetzold MR1-2/L10
			TOPS-20 Monitor Group
			Digital Equipment Corporation

	This program is used to generate network traffic levels usefull
when debuging network code under TOPS-20.  This program is also usefull
in determining network IO performance rates.  Currently only the ARPANET
NCP protocol is supported.

	This program is intended to be used as a tool for testing various
networks under TOPS-20.  This program creates network IO levels unseen on
most consumer systems.

	Future features will include:

o	TCP and IP support for BBN TCP/IP JSYS interface

o	TCP and IP support for DEC TCP/IP JSYS interface

o	DECNET IP/TCP gateway support.

\
	SUBTTL NON-EXECUTABLE INITIALIZATION

IFNDEF DEBUG,<DEBUG==0>		;DEFAULT FOR MACRO DEBUGING SWITCH IS OFF
IFN DEBUG,<LALL>		;IF MACRO DEBUGING LIST ALL MACRO EXPANSIONS

SEARCH MONSYM,MACSYM		;GET SYMBOLS WE NEED...WE DONT USE MACREL
IFE DEBUG,<.DIRECTIVE FLBLST> 	;DO NOT EXPAND ASCIZ IF NOT DEBUGING

DEFINE SYM(A,B),<A=B>		;MACRO TO DEFINE A SYMBOL
DEFINE DSYM(A,B),<IFNDEF A,<A=B> ;MACRO TO DEFINE A SYMBOL WITH DEFAULT
     		  IF2 <A=A>>	;SHOW IN LISTING
DEFINE SYMS(A,B),<A==B>		;MACRO TO DEFINE A SYMBOL SO DDT CANT FIND IT
DEFINE DSYMS(A,B),<IFNDEF A,<A==B> ;MACRO TO DEFINE A NON DDT SYMBOL WITH
       		   IF2 <A==A>>	;DEFAULT

				;VERSION INFORMATION
DSYMS VWHO,0			;WHO LAST HACKED (0 IS KWP)
DSYMS VMAJOR,4			;MAJOR VERSION NUMBER
DSYMS VMINOR,0			;MINOR VERSION NUMBER
DSYMS VEDIT,32			;EDIT NUMBER
VERSIO==<<VWHO>B2!<VMAJOR>B11!<VMINOR>B17!<VEDIT>B35>

DSYMS NDEBUG,0			;NON NETWORK DEBUGING SWITCH

DEFINE XLIST%,<			;;MACRO TO HANDLE MULTIPLE XLISTS
XLISTS==XLISTS+1		;;BUMP THE XLIST COUNT
IFE DEBUG,<XLIST>>     		;;DO A REAL XLIST

DEFINE LIST%,<			;;MACRO TO HANDLE TO MULTIPLE LISTS
XLISTS==XLISTS-1		;;UN BUMP THE XLIST COUNT
IFE XLISTS,<LIST>>		;;DO A LIST IF WE HAVE TOO

XLISTS==0			;INITIAL XLIST% COUNTER
	SUBTTL AC DEFINITIONS

				;AC NAMES
SYM F,0				;FLAGS
SYM T1,1			;-\
SYM T2,2			;\-\
SYM T3,3			;-\-\ TEMPORARY
SYM T4,4			;-/-/ ACS
SYM T5,5			;/-/
SYM T6,6			;-/
SYM PP,7			;INITIAL PATTERN POINTER FOR FORK
SYM PB,10			;PATTERN BYTE COUNT FOR FORK
SYM L1,11			;LENGTH OF DATA DESCRIPTOR
SYM L2,12			;LENGTH OF REAL DATA
SYM PD,13			;PROTOCOL DISPATCH TABLE POINTER
SYM FX,14			;FORK INDEX
SYM FP,15			;MACSYMS FRAME POINTER
SYM CX,16			;MACSYMS AC
SYM P,17			;STACK POINTER

				;OTHER AC NAMES
SYMS AC0,0
SYMS AC1,1
SYMS AC2,2
SYMS AC3,3
SYMS AC4,4
SYMS AC5,5
SYMS AC6,6
SYMS AC7,7
SYMS AC10,10
SYMS AC11,11
SYMS AC12,12
SYMS AC13,13
SYMS AC14,14
SYMS AC15,15
SYMS AC16,16
SYMS AC17,17
	SUBTTL FLAG DEFINITIONS

				;FLAG NAMES
SYMS F%INIT,1B0			;INIT DONE
SYMS F%RUN,1B1			;STARTED
SYMS F%STOP,1B2			;STOPPED
SYMS F%NOC,1B3			;NO COMMAND
SYMS F%TAKE,1B4			;TAKE COMMAND IN PROGRESS
SYMS F%FORK,1B5			;SUBFORK FLAG
SYMS F%WAIT,1B6			;WAIT COMMAND FLAG
SYMS F%HOST,1B7			;HOST TABLES LOADED FLAG
SYMS F%RCV,1B8			;RECEIVE ONLY MODE
SYMS F%SEND,1B9			;SEND ONLY MODE
SYMS F%TJFN,1B10		;TAKE JFN VULNERABLE FLAG

				;GLOBAL FLAG NAMES
SYMS G%VERF,1B0			;DATA VERIFICATION ENABLED
SYMS G%SQNC,1B1			;SEQUENCE CHECKING FLAG

DEFINE JSYSF,<ERCAL .JSYSF>	;ERROR HANDLING MACRO
DEFINE NOERR,<ERJMP .+1>	;ERROR IGNORE MACRO
DEFINE SAVACS,<CALL .SAVAC>	;MACRO TO SAVE ACS ON STACK
	SUBTTL SYMBOL DEFINITIONS

				;BYTE SIZES
SYMS .BS8,0			;8 BIT BYTES
SYMS .BS32,1			;32 BIT BYTES
SYMS .BS36,2			;36 BIT BYTES

				;PROTOCOL TYPES
SYMS .PTNCP,0    		;ARPANET NCP
SYMS .PTTCP,1			;DEC TCP INTERFACE
SYMS .PTIP,2			;DEC IP	INTERFACE
SYMS .PTBCP,3			;BBN TCP INTERFACE
SYMS .PTBIP,4			;BBN IP INTERFACE

SYM  DDTADR,770000		;DDT STARTING ADDRESS
SYMS PGSIZ,1000			;SIZE OF A PAGE IN WORDS

SYMS NCNCTS,^D10		;MAX NUMBER OF CONNECTIONS
SYMS NFKS,<NCNCTS*2>		;NUMBER OF FORKS
SYMS MAXFRK,NFKS-1		;MAXIMUM FORK NUMBER

      		             	;DATA DESCRIPTOR FIELDS
SYMS DD%MBZ,<740000,,000000> 	;B0-B3   - THESE BITS DO NOT EXIST
SYMS DD%VRF,<020000,,000000> 	;B4      - THIS BUFFER MUST BE VERIFIED
SYMS DD%PTN,<016000,,000000> 	;B5-B7   - PATTERN INDEX
SYMS DD%SQC,<001777,,770000>	;B8-B23  - SEQUENCE NUMBER
SYMS DD%SIZ,<000000,,007777>	;B24-B35 - DATA SIZE FIELD
	SUBTTL PARAMETER DEFINITIONS

DSYMS LOWCOD,001000		;PROGRAM LOWEST ADDRESS

DSYMS PDLSIZ,100		;SIZE OF PDL STACK
DSYMS FRKSIZ,40			;FORK PDL SIZE
DSYMS TXTSIZ,^D500		;TEXT BUFFER SIZE (IN CHARS)
DSYMS ATMSIZ,^D200		;ATOM BUFFER SIZE (IN CHARS)

DSYMS SOCKET,400		;INITIAL DEFAULT SOCKET NUMBER

DSYM HSTCMD,020000		;HOST COMMAND TABLE
DSYM HSTABL,024000		;HOST NAMES TABLE

DSYM PATERN,040000		;ADDRESS OF THE PATTERN PAGE
SYM PATERA,PATERN+PGSIZ		;ALTERNATING PATTERN
SYM PATERO,PATERA+PGSIZ		;ADDRESS OF THE ONES PATTERN PAGE
SYM PATERZ,PATERO+PGSIZ		;ADDRESS OF THE ZEROES PATTERN PAGE
SYM PATERF,PATERZ+PGSIZ		;ADDRESS OF THE USER PATTERN PAGE
	SUBTTL PROTOCOL DISPATCH TABLE OFFSETS

SYMS PD.OPN,0			;OPEN CONNECTION OFFSET
SYMS PD.CLS,1			;CLOSE CONNECTION OFFSET
SYMS PD.SND,2			;SEND DATA OFFSET
SYMS PD.RCV,3			;RECEIVE DATA OFFSET
SYMS PD.GO,4			;FORCE DATA OUT OFFSET
	SUBTTL TTY IO MACROS

	DEFINE TYPE(S),<	;;MACRO TO TYPE A STRING WITH CRLF FIRST
	XLIST%			;;SUPRESS LISTING
	HRROI T1,[ASCIZ\
S\]				;;GENERATE THE STRING
	LIST%			;;TURN LISTING BACK ON
	PSOUT>			;;OUTPUT THE STRING

	DEFINE TYPEN(S),<	;;MACRO TO TYPE A STRING WITHOUT CRLF FIRST
	XLIST%			;;TURN ON LISTING
	HRROI T1,[ASCIZ\S\]	;;GENERATE THE STRING
	LIST%			;;TURN ON LISTING
	PSOUT>			;;OUTPUT THE STRING

	DEFINE NUMO(A,R,S),<	;;MACRO TO OUTPUT A NUMBER
	XLIST%			;;TURN OFF LISTING
	IFN <T2-A>,<MOVE T2,A>	;;MOVE IN THE WORD IF WE HAVE TO
	MOVEI T1,.PRIOU		;;OUTPUT TO THE TTY
	MOVX T3,<S,,R>		;;GET THE SIZE AND RADIX
	LIST%			;;TURN LISTING BACK ON
	NOUT			;;OUTPUT THE NUMBER
	XLIST%			;;LISTING OFF
	 JSYSF			;;HANDLE ERRORS
	LIST%>			;;LISTING ON
	SUBTTL COMND JSYS MACROS

	DEFINE CMD(N,D,F),<	;;MACRO TO DEFINE A COMMAND FOR .CMKEY
	IFB <D>,<[		;;IF THERE IS NOT A DISPATCH ADDRESS
        IFN <F>,<CM%FW!F>     	;;PUT FLAGS IN IF NEEDED
	ASCIZ\N\],,.'N>		;;DEFAULT DISPATCH ADDRESS
	IFNB <D>,<[		;;IF THERE IS A DISPATCH ADDRESS
        IFN <F>,<CM%FW!F>    	;;PUT FLAGS IN
	ASCIZ\N\],,D>>

	DEFINE DOCMD(FNC,DAT,DFT,HLP),<		;;MACRO TO DEFINE AND EXECUTE
	XLIST%					;;A COMND FUNCTION BLOCK
	DOCFLG==0				;;INITIALIZE FLAG
	IFNB <HLP>,<DOCFLG==DOCFLG!CM%HPP>	;;IF A HELP STRING SET BIT
	IFNB <DFT>,<DOCFLG==DOCFLG!CM%DPP>	;;IF A DEFAULT SET BIT
	MOVEI T2,[<FNC>B8!DOCFLG		;;FUNCTION CODE AND FLAGS
		  <DAT>				;;USER SUPPLIED DATA
		  IFB <HLP>,<Z>			;;IF NO HELP STRING
		  IFNB <HLP>,<-1,,[ASCIZ\HLP\]>	;;IF A HELP STRING
		  IFB <DFT>,<Z>			;;IF NO DEFAULT STRING
		  IFNB <DFT>,<-1,,[ASCIZ\DFT\]>	;;IF A DEFAULT STRING
		  Z]				;;BREAK MASK WORD
	LIST%					;;TURN LISTING BACK ON
	CALL .DOCMD>				;;GO TO WORKER ROUTINE

	DEFINE NOISE(S),<DOCMD .CMNOI,<-1,,[ASCIZ\S\]>> ;;NOISE WORD MACRO
	DEFINE CNFIRM,<DOCMD .CMCFM> ;;CONFIRM MACRO

	DEFINE DODSP,<		;;MACRO TO GET DISPATCH ON KEYWORD
	HRRZ T2,0(T2)		;;GET DISPATCH ADDRESS
	CALL (T2)>		;;AND GO THERE
	SUBTTL PROTOCOL DISPATCH TABLES

	LOC LOWCOD

PRTDSP:				;PROTOCOL DISPATCH TABLES
	EXP NCPDSP		;NCP
	EXP TCPDSP		;TCP
	EXP IPDSP		;IP
	EXP BCPDSP		;BBN TCP
	EXP BIPDSP		;BBN IP

NCPDSP:				;NCP DISPATCH TABLE
	EXP NCPOPN		;OPEN SOCKET
	EXP NCPCLS		;CLOSE SOCKET
	EXP NCPSND		;SEND DATA
	EXP NCPRCV		;RECEIVE DATA
	EXP NCPGO		;FORCE BUFFERS OUT

TCPDSP:				;TCP DISPATCH TABLE
	EXP TCPDMY		;OPEN PORT
	EXP TCPDMY		;CLOSE PORT
	EXP TCPDMY		;SEND DATA
	EXP TCPDMY		;RECEIVE DATA
	EXP TCPDMY		;FORCE BUFFERS OUT

IPDSP:				;IP DISPATCH TABLE
	EXP IPDMY		;IP OPEN SIMULATE
	EXP IPDMY		;IP CLOSE SIMULATE
	EXP IPDMY		;IP SEND
	EXP IPDMY		;IP RECEIVE
	EXP IPDMY		;IP FORCE BUFFERS OUT

BCPDSP:				;BBN TCP DISPATCH TABLE
	EXP BCPDMY		;BBN TCP OPEN
	EXP BCPDMY		;BBN TCP CLOSE
	EXP BCPDMY		;BBN TCP SEND
	EXP BCPDMY		;BBN TCP RECEIVE
	EXP BCPDMY		;BBN TCP FORCE BUFFERS OUT

BIPDSP:				;BBN IP DISPATCH
	EXP BIPDMY		;BBN IP OPEN SIMULATE
	EXP BIPDMY		;BBN IP CLOSE SIMULATE
	EXP BIPDMY		;BBN IP SEND
	EXP BIPDMY		;BBN IP RECEIVE
	EXP BIPDMY		;BBN IP FORCE BUFFERS OUT

TCPDMY:
IPDMY:
BCPDMY:
BIPDMY:
	RET
	SUBTTL PSI SYSTEM DEFINITIONS

	SYMS .LCCCE,0		;^E INTERRUPT CHANNEL

LEVTAB:	EXP PC1			;PC STORAGE DISPATCHES
	EXP PC2
	EXP PC3

	DEFINE DEFCHN(C,L,D),<	;;MACRO TO DEFINE AN INTERRUPT CHANNEL
	CHNMSK==CHNMSK!1B<C>	;;SET THIS CHANNEL IN CHANNEL MASK
	LOC CHNTAB+C		;;GO TO CORRECT CHNTAB LOCATION
	L,,D			;;LEVEL AND DISPATCH
	LOC CHNEND>		;;GO TO END OF CHNTAB

	CHNMSK==0		;INITIALIZE THE CHANNEL MASK

CHNTAB:	BLOCK 44		;CHANNEL DISPATCH TABLE
CHNEND:				;END OF CHNTAB

				;PSI CHANNEL DEFINITIONS
	DEFCHN .ICIFT,2,.FRKIN	;FORK TERMINATION INTERRUPT
	DEFCHN .LCCCE,3,.TTYIN	;^E INTERRUPT FOR TTY
	SUBTTL COMMAND TABLES

PCMDS:	NPCMDS,,NPCMDS		;PRIMARY COMMANDS
	CMD ABORT,		;ABORT CURRENT RUN
	CMD ARPANET,		;ARPANET STATE COMMAND
	CMD CONTINUE,		;CONTINUE CURRENT RUN
	CMD DDT,		;TRANSFER CONTROL TO UDDT
	CMD DISABLE,		;DISABLE FEATURE COMMAND
	CMD ENABLE,		;ENABLE FEATURE COMMAND
	CMD EXIT,		;ABORT AND RETURN TO EXEC LEVEL
	CMD HELP,		;TYPE OUT A HELP MESSAGE
	CMD MDDT,		;TRANSFER CONTROL TO MDDT
	CMD PUSH,		;PUSH TO AN INFERIOR EXEC
	CMD QUIT,		;RETURN TO EXEC WITHOUT CLEANING UP
	CMD RESET,		;RESET AND RESTART THIS PROGRAM
	CMD RETIME,		;RETIME ONE OF THE IO RATE CLOCKS
	CMD S,..STAT,CM%INV!CM%ABR
	CMD SET,		;SET VARIOUS PARAMETERS
	CMD SHOW,		;SHOW PARAMETER SETTINGS
	CMD ST,..STAR,CM%INV!CM%ABR
..STAR:	CMD START,		;START GENERATING NETWORK TRAFFIC
..STAT:	CMD STATUS,		;GENERATE STATUS REPORT
	CMD STOP,		;STOP GENERATING NETWORK TRAFFIC
	CMD TAKE,		;TAKE COMMANDS FROM FILE
	CMD WAIT,		;WAIT UNTIL ^E
	NPCMDS==.-PCMDS-1

STCMDS:	NSTCMD,,NSTCMD		;START COMMANDS
	CMD NORMALLY,0		;DONT WAIT
	CMD WAIT,1		;WAIT
	NSTCMD==.-STCMDS-1

SCMDS:	NSCMDS,,NSCMDS		;SET COMMANDS TABLE
	CMD LENGTH,		;LENGTH OF MESSAGES
	CMD MODE,		;SEND/RECEIVE MODE COMMAND
	CMD NUMBER,		;NUMBER OF CONNECTIONS COMMAND
	CMD PATTERN,		;PATTERN TYPE
	CMD PORT,.SOCKE		;SET TCP PORT
	CMD PROTOCOL,		;PROTOCOL TYPE
	CMD SOCKET,		;INITIAL SOCKET NUMBER
	NSCMDS==.-SCMDS-1

EACMDS:	NEACMD,,NEACMD		;COMMANDS FOR ENABLE/DISABLE
	CMD FOREIGN,		;DISABLE FOREIGN HOST STUFF
	CMD SEQUENCE,		;SEQUENCE CHECKING
	CMD VERIFICATION,	;VERIFICATION OF DATA
	NEACMD==.-EACMDS-1

BCMDS:	NBCMDS,,NBCMDS		;BYTE SIZE COMMANDS
	CMD 32,.BS32		;32 BIT BYTES
	CMD 36,.BS36		;36 BIT BYTES
	CMD 8,.BS8		;8 BIT BYTES
	NBCMDS==.-BCMDS-1

ACMDS:	NACMDS,,NACMDS		;ARPANET STATE COMMANDS
	CMD CYCLE,.ACYCL	;CYCLE ARPANET
	CMD LOAD,.ALOAD		;ARPANET HOST TABLE LOAD
	CMD OFF,.AOFF		;ARPANET OFF
	CMD ON,.AON		;ARPANET ON
	NACMDS==.-ACMDS-1

RCMDS:	NRCMDS,,NRCMDS		;RATE COMMANDS
	CMD 1,IOTIM1
	CMD 2,IOTIM2
	NRCMDS==.-RCMDS-1

TCMDS:	NTCMDS,,NTCMDS		;PATTERN TYPE COMMANDS
	CMD ALTERNATING,PATERA	;PATTERN IN PATERA
	CMD ONES,PATERO		;PATTERN IN PATERO
	CMD SEQUENCE,PATERN	;PATTERN IN PATERN
	CMD ZEROES,PATERZ	;PATTERN IN PATERZ
	NTCMDS==.-TCMDS-1

LCMDS:	NLCMDS,,NLCMDS		;LENGTH SUBCOMMANDS
	CMD RANDOM,		;RANDOM LENGTH MESSAGES
	CMD SIZE,		;FIXED SIZE MESSAGES
	NLCMDS==.-LCMDS-1

PRCMDS:	NPRCMD,,NPRCMD		;PROTOCOL COMMANDS
	CMD BBN-IP,.PTBIP	;BBN IP INTERFACE
	CMD BBN-TCP,.PTBCP	;BBN TCP INTERFACE
	CMD IP,.PTIP		;ARPANET IP USING DEC INTERFACE
	CMD NCP,.PTTCP		;ARPANET NCP
	CMD TCP,.PTNCP		;ARPANET TCP USING DEC INTERFACE
	NPRCMD==.-PRCMDS-1

MCMDS:	NMCMDS,,NMCMDS		;MODE COMMANDS
	CMD BOTH,		;BOTH SEND AND RECEIVE MODE
	CMD RECEIVE,		;RECEIVE ONLY MODE
	CMD SEND,		;SEND ONLY MODE
	NMCMDS==.-MCMDS-1
	SUBTTL STKVAR SUPPORT ROUTINES

.STKST:
	ADD P,0(AC16)		;BUMP STACK FOR VARIABLES USED
	JUMPGE P,STKSOV		;TEST FOR STACK OVERFLOW
STKSE1:
	PUSH P,0(AC16)		;SAVE BLOCK SIZE FOR RETURN
	CALL 1(AC16)		;CONTINUE ROUTINE, EXIT TO .+1
.STKRT:
	 JRST [	POP P,AC16	;RECOVER COUNT
		SUB P,AC16	;ADJUST STACK TO REMOVE BLOCK
		RET]		;DO NON-SKIP RETURN
	POP P,AC16		;SKIP RETURN COMES HERE, RECOVER COUNT
	SUB P,AC16		;ADJUST STACK TO REMOVE BLOCK
RSKP:	AOS (P)			;NOW DO SKIP RETURN
R:	RET			;NORMAL RETURN

STKSOV:
	SUB P,0(AC16)		;STACK OVERFLOW, UNDO ADD
	HLL AC16,0(AC16)	;SETUP TO DO MULTIPLE PUSH, GET COUNT
STKSO1:
	PUSH P,[0]		;DO ONE PUSH AT A TIME, GET REGULAR
	SUB AC16,[1,,0]		;ACTION ON OVERFLOW
	TLNE AC16,777777	;COUNT DOWN TO 0?
	 JRST STKSO1		;NO, KEEP PUSHING
	JRST STKSE1
	SUBTTL ERROR MACRO SUPPORT ROUTINE

.JSYSF:				;JSYS ERROR HANDLER
	TXNE F,F%FORK		;ARE WE A FORK?
	 JRST JSYSF2		;YES SO GO DO FORK STUFF
	MOVEM AC17,ERRACS+AC17	;SAVE AC 17
	MOVEI AC17,ERRACS	;GET BLT AC
	BLT AC17,ERRACS+AC16	;SAVE ACS 0-16
	MOVE AC17,ERRACS+AC17	;GET AC 17 BACK
	CALL NEWLIN		;GET US A NEW TTY LINE
	HRROI T1,[ASCIZ/?JSYS ERROR AT USER PC /]
	PSOUT			;OUTPUT THE MESSAGE
	MOVEI T1,.PRIOU		;OUTPUT TO TTY
	HRRZ T2,0(P)		;GET THE ERROR PC
	MOVEM T2,ERRPC		;AND SAVE IT
	MOVEI T3,10		;OCTAL
	NOUT			;OUTPUT THE ERROR PC
	 NOERR			;IGNORE ERRORS
	HRROI T1,[ASCIZ/
?ERROR WAS ... /]		;GET A NEW STRING
	PSOUT			;OUTPUT THE STRING
	MOVEI T1,.PRIOU		;OUTPUT TO TTY
	MOVX T2,<.FHSLF,,-1>	;MY LAST ERROR
	SETZB T3,T4		;NO SPECIAL LIMITS
	ERSTR			;OUTPUT THE ERROR STRING
	 NOERR			;IGNORE ERRORS
	 NOERR			;IGNORE ERRORS
	SKIPE DBUGSW		;DEBUGING?
	 CALL TODDT		;YES
	JRST GETCMD		;GO GET A COMMAND

JSYSF2:				;FORK LEVEL JSYS ERRORS
	MOVEM P,FRKEPC(FX)	;SAVE STACK POINTER
	SKIPE FRKDDT(FX)	;SHOULD WE GO TO DDT
	 CALL TODDT		;YES
	CALL JSYSF3		;CALL WORKER ROUTINE
	HALTF			;AND STOP

JSYSF3:				;WORKER ROUTINE
	SAVACS			;SAVE ALL THE ACS
	MOVEI T1,.FHSLF		;THIS FORK
	GETER			;WHAT WAS MY LAST ERROR
	HRRZM T2,FRKERR(FX)	;SAVE MY LAST ERROR
	MOVE T1,FRKEPC(FX)	;GET OUR ERROR PC STACK
	HRRZ T1,(T1)		;GET THE ERROR PC
	HRRZM T1,FRKEPC(FX)	;AND SAVE IT FOR MOTHER
	RET			;RETURN TO CALLER
	SUBTTL MISC SUBROUTINES

TODDT:				;ROUTINE TO SEND US TO DDT
	SAVACS			;SAVE CALLER ACS
	SKIPN DDTADR		;DDT LOADED?
	 RET			;NO SO JUST RETURN
	CALL NEWLIN		;GIVE US A NEW LINE
	TYPEN <%TRANSFERRING TO UDDT....R$G TO RETURN>
	TYPE <>			;TYPE AN EXTRA LINE
	JRST DDTADR		;GO TO UDDT
NODDT:				;HERE WHEN DDT DOESNT EXIST
	CALL NEWLIN		;GET A NEW LINE
	TYPEN <%DDT NOT LOADED>	;TELL USER DDT IS NOT AROUND
	SKIPA			;NONSKIP RETURN
     	AOS (P)			;SKIP RETURN
  	RET			;RETURN

NEWLIN:				;ROUTINE TO PUT US AT A NEW LINE
	MOVEI T1,.PRIOU		;TTY
	RFPOS			;READ THE POSTION OF TTY
	 NOERR			;IGNORE ERRORS
	HRRZS T2		;ZERO THE LEFT HALF
	SKIPN T2		;AT LEFT?
	 RET			;YES SO RETURN
	TYPE <>			;NO SO PUT US THERE
	RET			;AND RETURN

	IFN NDEBUG,<		;ROUTINES NEEDED FOR NON ARPANET SYSTEMS
DBGSNZ:				;ROUTINE TO SLOW DOWN A FORK
	MOVEI T1,^D1000		;ONE SECOND
	DISMS			;SNOOZE
	RET			;RETURN TO CALLER
>
	SUBTTL DOCMD MACRO SUPPORT ROUTINE

.DOCMD:				;SUPPORT ROUTINE FOR DOCMD MACRO
	MOVEI T1,CSB		;GET THE CSB ADDRESS
	COMND			;DO THE JSYS
	 ERJMP .DOCM2		;HANDLE REAL BAD ERRORS
	TXNN T1,CM%NOP		;DID WE GET A NO-PARSE?
	 RET			;NO SO RETURN
.DOCM2:				;HERE ON ERRORS
	MOVEI T1,.FHSLF		;THIS FORK
	GETER			;GET MY LAST ERROR
	HRRZS T2		;ZERO THE LEFT HALF
	TXNE F,F%TAKE		;ARE WE DOING A TAKE COMMAND?
	CAIE T2,IOX4		;WAS THE ERROR EOF?
	 CALL .JSYSF		;NOT TAKE OR NOT EOF
	  JRST .TAKND		;TAKE AND EOF SO END OF TAKE COMMAND
	CALL NEWLIN		;YES...SO GET US A NEW LINE
	TYPEN <?COMMAND ERROR - > ;TELL USER HE SCREWED UP
	MOVEI T1,.PRIOU		;OUTPUT TO TTY
	MOVX T2,<.FHSLF,,-1>	;MY LAST ERROR
	SETZB T3,T4		;NO WIERD LIMITS
	ERSTR			;OUTPUT THE ERROR STRING
	 NOERR			;IGNORE ERRORS
	 NOERR			;IGNORE ERRORS
	JRST GETCMD		;GO GET ANOTHER COMMAND
	SUBTTL AC SAVE/RESTORE FACILITY

.SAVAC:				;ROUTINE TO SAVE ACS ON STACK
	ADJSP P,^D14		;GET ROOM ON THE STACK
	MOVEM AC16,0(P)		;SAVE AC 16
	MOVEI AC16,-^D13(P)	;GET RIGHT HALF OF BLT AC
	HRLI AC16,1		;GET LEFT HALF OF BLT AC
	BLT AC16,-1(P)		;SAVE ACS 1-15
	MOVE AC16,0(P)		;RESTORE AC 16
	CALL @-^D14(P)		;GO BACK TO CALLER
.RSTAC:				;HERE TO RESTORE ACS
	SKIPA			;NON-SKIP RETURN
	AOS -^D15(P)		;SKIP RETURN...BUMP RETURN PC
	HRLI AC16,-^D13(P)	;GET BLT AC LEFT
	HRRI AC16,AC1		;GET BLT AC RIGHT
	BLT AC16,AC16		;RESTORE ACS
	ADJSP P,-^D15		;FIX UP THE STACK
	RET			;RETURN TO ORIGINAL
	SUBTTL MAINLINE

EVEC:				;ENTRY VECTOR
	JRST TRAFIC		;STARTING ADDRESS
	JRST TRAFI2		;REENTER ADDRESS
	VERSIO			;VERSION INFORMATION

TRAFIC:				;START HERE
	RESET			;CLEAN UP THE WORLD
	SETZ F,GLOBAL		;RESET ALL FLAGS
	MOVE P,PDLPTR		;GET A STACK
	MOVEI PD,NCPDSP		;GET PD POINTER FOR NOW

;	Write protect pages that need it

	SKIPE DBUGSW		;ARE WE DEBUGING?
	 JRST TRAFI4		;YES
	MOVEI T1,LOWCOD_-^D9	;GET THE LOWEST CODE ADDRESS
TRAFI3:				;THIS IS THE LOOP
	HRLI T1,.FHSLF		;THIS FORK
	MOVX T2,<PA%RD!PA%EX>	;ALLOW THIS PAGE TO BE READ ONLY
	SPACS			;SET THE PAGE ACCESS
	 JSYSF			;HANDLE ERRORS
	HRRZS T1		;ZERO THE LEFT HALF
	CAIGE T1,<HGHCOD&777000>_-^D9 ;HAVE WE DONE THE LAST PAGE?
	 AOJA T1,TRAFI3		;NO SO KEEP GOING
TRAFI4:

;	Zero things that need to be zeroed

	SETZM ZERO1		;ZERO THE FIRST LOCATION
	MOVX T1,<ZERO1,,ZERO1+1> ;GET BLT POINTER
	BLT T1,ZERO2		;ZERO ALL ZEROABLE STORAGE

;	Initialize the software interrupt system

	MOVEI T1,.FHSLF		;THIS FORK
	MOVX T2,<LEVTAB,,CHNTAB> ;PSI DATABASE TABLES
	SIR			;SETUP INTERRUPT SYSTEM
	 JSYSF
	MOVEI T1,.FHSLF		;THIS FORK
	EIR			;ENABLE INTERRUPT REQUESTS
	 JSYSF
	MOVEI T1,.FHSLF		;THIS FORK
	MOVX T2,CHNMSK		;GET THE USED CHANNELS MASK
	AIC			;ACTIVATE INTERRUPT CHANNELS
	 JSYSF
	MOVX T1,<.TICCE,,.LCCCE> ;TURN ON ^E INTERRUPTS
	ATI			;ACTIVATE TTY INTERRUPTS
	 JSYSF

;	Initialize the COMND STATE BLOCK

	MOVX T1,<CSBV,,CSB>	;GET A BLT POINTER
	BLT T1,CSB+CSBSIZ-1	;INITIALIZE COMND JSYS DATABASE
	MOVE T1,PRMPTD		;GET THE PROPER PROMPT
	MOVEM T1,CSB+.CMRTY	;SAVE IT IN THE CORRECT PLACE

	MOVEI T1,.GTHSZ		;HOST NUMBER FUNCTION
	IFE NDEBUG,<GTHST>	;GET ARPANET HOST NUMBER
	 JSYSF
	MOVEM T4,HOSTN		;SAVE THE HOST NUMBER

;	Initialize the test patterns

	HRLZI T1,-PGSIZ		;GET LEFT HALF OF AOBJN POINTER
	SETZ T2,		;INITIAL THE PATTERN WORD
	MOVE T3,[626262,,626262] ;GET ALTERNATING PATTERN WORD
GENPAT:				;LOOP TO GENERATE THE PATTERN PAGE
	SETZM PATERZ(T1)	;ZERO THE ZERO PATTERN WORD
	SETOM PATERO(T1)	;TURN ON THE ONE PATTERN WORD
	MOVEM T2,PATERN(T1)	;SAVE THE PATTERN WORD
	MOVEM T3,PATERA(T1)	;SAVE THE ALTERNATING PATTERN WORD
	ADD T2,[777001,,001777]	;CHANGE THE PATTERN WORD
	AOBJN T1,GENPAT		;AND GENERATE THE WHOLE PAGE

;	Initialize various parameters

	MOVEI T1,PATERN		;GET ADDRESS FOR SEQUENCE PATTERN
	MOVEM T1,PATERW		;AND MAKE IT THE DEFAULT
	SETOM LENGTH		;SET INITIAL LENGTH TO RANDOM

;	Here we go

	TYPE <TRAFIC - ARPANET TRAFFIC GENERATOR VERSION >
	CALL VEROUT		;OUTPUT THE VERSION NUMBER
	TXO F,F%INIT		;FLAG THAT INIT IS DONE
	JRST GETCMD		;GO GET A COMMAND
TRAFI2:				;REENTER ADDRESS
	TXNN F,F%INIT		;INIT DONE?
	 JRST TRAFIC		;NO SO DO IT NOW

;	Command loop

GETCMD:	DOCMD .CMINI		;START UP A COMMAND
	TXNN F,F%TJFN		;SHOULD WE KILL THE TAKE JFN?
	 JRST RPARSE		;NO
	MOVE T1,TAKJFN		;GET THE JFN
	RLJFN			;RELEASE THE JFN
	 JSYSF			;HANDLE ERRORS
RPARSE:				;REPARSE ADDRESS
	MOVE P,PDLPTR		;GET A NEW STACK POINTER
	DOCMD .CMKEY,PCMDS	;GET A KEYWORD
	DODSP			;AND DISPATCH ON IT
	JRST GETCMD		;WHEN DONE GET ANOTHER COMMAND
	SUBTTL SIMPLE COMMANDS

.DDT:				;GO TO DDT
	NOISE <MODE>
	CNFIRM			;MAKE SURE
	CALL TODDT		;DO TO DDT
	RET			;GET NEW COMMAND

.QUIT:				;LAZY MANS QUIT
	NOISE <WITHOUT CLEANING UP>
	CNFIRM			;MAKE SURE
	HALTF			;STOP
	RET			;GET A NEW COMMAND

.EXIT:				;GET OUT
	NOISE <AFTER ABORTING CURRENT RUN>
	CNFIRM			;MAKE SURE....
	TXNE F,F%RUN		;IS A RUN IN PROGRESS?
	 CALL ABORT2		;YES SO GO KILL THE RUN
	HALTF			;STOP
	RET			;GET A NEW COMMAND
	SUBTTL MORE SIMPLE COMMANDS

.MDDT:				;GO TO MDDT
	NOISE <MODE>
	CNFIRM			;MAKE SURE
	TYPEN <%TRANSFERRING TO MDDT....MRETN$G TO RETURN>
	TYPE <>
	MDDT%			;GO TO MDDT
	 JSYSF
	RET			;GET ANOTHER COMMAND

.RESET:				;RESET THIS PROGRAM
	NOISE <AND RESTART>
	CNFIRM			;MAKE SURE
	JRST TRAFIC		;RESTART AND RESET

.HELP:				;HELP OUT USER
	NOISE <WITH USING TRAFIC>
	CNFIRM			;MAKE SURE USER WANTS THIS
	HRROI T1,HLPTXT		;GET POINTER TO THE HELP TEXT
	PSOUT			;OUTPUT THE HELP TEXT
	RET			;RETURN FOR ANOTHER COMMAND

.TAKE:				;TAKE COMMAND
	NOISE <COMMANDS FROM FILE>
	TXNN F,F%TAKE		;TAKE COMMAND IN PROGRESS ALLREADY?
	 JRST .TAKE2		;NO
	CALL NEWLIN		;YES...GET A NEW LINE
	TYPEN <%TAKE COMMAND ALLREADY IN PROGRESS>
	RET			;GET ANOTHER COMMAND
.TAKE2:				;HERE WE GO
	SETZM GTJFNB		;ZERO FIRST WORD OF GTJFN BLOCK
	MOVX T1,<GTJFNB,,GTJFNB+1> ;GET BLT AC
	BLT T1,GTJFNB+.GJATR+1	;ZAP THE WHOLE BLOCK
	DOCMD .CMIFI		;GET AN INPUT FILE SPEC
	MOVEM T2,TAKJFN		;SAVE THE JFN IN A SAFE PLACE
	TXO F,F%TJFN		;FLAG THAT WE HAVE A JFN
	CNFIRM			;MAKE SURE
	MOVE T1,TAKJFN		;GET THE JFN BACK
	MOVX T2,<<7B5>!OF%RD>	;7 BIT BYTES
	OPENF			;OPEN UP THE FILE
	 JSYSF
	TXZ F,F%TJFN		;RESET THE JFN FLAG
	TXO F,F%TAKE		;WE ARE NOW IN TAKE MODE
	HRL T1,TAKJFN		;GET THE JFN
	HRRI T1,.NULIO		;OUTPUT TO NOWHERES
	MOVEM T1,CSBJFN		;AND MAKE THE SWITCH
	RET			;GET ANOTHER COMMAND
.TAKND:				;END OF THE TAKE COMMAND
	MOVX T1,<.PRIIN,,.PRIOU> ;GET REALISTIC IO DESIGNATORS
	MOVEM T1,CSBJFN         ;AND PUT THEM INTO CSB
	TXZ F,F%TAKE		;NO LONGER IN TAKE COMMAND
	JRST GETCMD		;AND GET ANOTHER COMMAND
	SUBTTL PUSH COMMAND

.PUSH:				;PUSH TO A NEW EXEC COMMAND
	NOISE <TO A NEW EXEC>
	CNFIRM			;MAKE SURE USER WANTS THIS
	STKVAR <PSHJFN,PSHFRK>	;GET LOCAL STORAGE
	MOVX T1,<GJ%SHT!GJ%OLD>	;FILE MUST EXIST
	HRROI T2,[ASCIZ/SYSTEM:EXEC.EXE/] ;GET JFN FOR EXEC
	GTJFN			;GET A JFN ON THE EXEC
	 JSYSF			;HANDLE ERRORS
	MOVEM T1,PSHJFN		;SAVE THE JFN
	MOVX T1,<CR%CAP>	;CFORK FLAGS
	CFORK			;MAKE A FORK FOR THE EXEC
	 ERCAL [ MOVE T1,PSHJFN	;GET THE JFN
		 RLJFN		;RELEASE THE JFN
		  NOERR		;IGNORE ERRORS
		 JRST .JSYSF]	;AND REPORT THE ERROR
	MOVEM T1,PSHFRK		;SAVE THE FORK HANDLE
	HRL T1,PSHFRK		;GET THE FORK HANDLE
	HRR T1,PSHJFN		;GET THE JFN
	GET			;LOAD THE EXEC INTO THE FORK
.PUSH2:	 ERCAL [ MOVE T1,PSHFRK	;GET THE FORK HANDLE
		 KFORK		;KILL THE FORK
		  NOERR		;IGNORE ERRORS
		 MOVE T1,PSHJFN	;GET THE JFN
		 RLJFN		;RELEASE THE JFN
		  NOERR		;IGNORE ERRORS
		 JRST .JSYSF]	;REPORT THE ERROR
	MOVE T1,PSHFRK		;GET THE FORK HANDLE
	SETZ T2,		;OFFSET ZERO IN ENTRY VECTOR
	SFRKV			;START UP THE PUSHED EXEC
	 ERCAL @.PUSH2		;HANDLE THE ERROR
	MOVE T1,PSHFRK		;GET THE FORK HANDLE
	WFORK			;WAIT FOR THE INFERIOR TO DIE
	 JSYSF			;HANDLE ERRORS (VERY WIERD)
	MOVE T1,PSHFRK		;GET THE FORK HANDLE
	KFORK			;KILL THE FORK
	 JSYSF			;HANDLE ERRORS
	RET			;RETURN TO CALLER
	SUBTTL WAIT COMMAND AND ^E INTERRUPT HANDLER

.WAIT:				;WAIT COMMAND
	NOISE <AFTER STARTING UNTIL INTERUPTTED>
	CNFIRM			;MAKE SURE USER WANTS THIS
	TXO F,F%WAIT		;TURN ON THE WAIT FLAG
WAITPC:	WAIT			;GO TO SLEEP FOREVER
	TXZ F,F%WAIT		;ON WAKEUP TURN OFF FLAG
	RET			;AND GET ANOTHER COMMAND

.TTYIN:				;HERE ON TTY INTERRUPT
	CALL WAKEUP		;CALL WORKER ROUTINE
	DEBRK			;DISMISS INTERRUPT

WAKEUP:				;WORKER ROUTINE TO WAKE US UP
	SAVACS			;SAVE THE INTERRUPT ACS
	TXNN F,F%WAIT		;ARE WE WAITING?
	 RET			;NO SO WE ARE DONE
	MOVE T1,PC3		;GET THE INTTERUPT PC
	MOVE T1,-1(T1)		;GET THE INTTERUPTED INST.
	CAME T1,[WAIT]		;IS IT A WAIT JSYS?
	 JRST WAKEU2		;NO SO GO DING HIM
	AOS PC3			;YES SO BUMP INTERRUPT PC
	MOVX T1,PC%USR		;GET USER MODE PC FLAG
	IORM T1,PC3		;AND TURN IT ON ALSO
	RET			;RETURN AND DISMISS
WAKEU2:				;HERE TO DING THE USER ABOUT THE INTERRUPT
	MOVEI T1,"G"-100	;GET A BELL
	PBOUT			;AND OUTPUT IT
	RET			;RETURN AND DISMISS
	SUBTTL SET AND SOME SET COMMANDS

.SET:				;COMMAND TO DEFINE THINGS
	NOISE <PARAMETER>
	DOCMD .CMKEY,SCMDS	;GET A KEYWORD
	DODSP			;DISPATCH ON THE COMMAND
	RET			;GET ANOTHER COMMAND

.DISAB:	TXOA F,F%NOC		;DISABLE COMMAND
.ENABL:	TXZ F,F%NOC		;ENABLE COMMAND
	NOISE <FEATURE>
	DOCMD .CMKEY,EACMDS	;GET A SUBCOMMAND
	DODSP			;DISPATCH ON IT
	RET			;RETURN FOR ANOTHER COMMAND

.VERIF:				;SET VERIFICATION COMMAND
	NOISE <OF RECEIVED DATA>
	CNFIRM			;MAKE SURE
	MOVX T1,G%VERF		;GET THE FLAG
	TXNN F,F%NOC		;IS THIS A NO COMMAND?
	 IORM T1,GLOBAL		;NOT NO COMMAND...SET FLAG
	TXNE F,F%NOC		;IS THIS A NO COMMAND?
	 ANDCAM T1,GLOBAL	;A NO COMMAND...RESET FLAG
	RET			;RETURN FOR ANOTHER COMMAND

.SEQUE:				;SET SEQUENCE COMMAND
	NOISE <OF RECEIVED DATA>
	CALL SKPABO		;ONLY IF WE ARE NOT RUNNING
	 RET			;IF RUNNING JUST RETURN
	CNFIRM			;MAKE SURE
	MOVX T1,G%SQNC		;GET THE FLAG
	TXNN F,F%NOC		;IS THIS A NO COMMAND?
	 IORM T1,GLOBAL		;NOT NO COMMAND...SET FLAG
	TXNE F,F%NOC		;IS THIS A NO COMMAND?
	 ANDCAM T1,GLOBAL	;A NO COMMAND...RESET FLAG
	RET			;RETURN FOR ANOTHER COMMAND
	SUBTTL MORE SET COMMANDS

.FOREI:				;SET FOREIGN COMMAND
	TXNE F,F%NOC		;IS THIS A NO COMMAND?
	 JRST .FORE2		;YES
	NOISE <HOST TO GENERATE TRAFFIC WITH>
	CALL SKPABO		;ONLY LEGAL IF WE ARE NOT RUNNING
	 RET			;IF RUNNING JUST RETURN
	IFN NDEBUG,<RET>	;IF NON-NETWORK DEBUGING WE CANT DO THIS
	CALL HSTRED		;GET HOST NAMES IF NEEDED
	DOCMD .CMKEY,HSTCMD	;GET THE HOST NAME
	HLRZ T5,0(T2)		;SAVE THE HOST NUMBER FOR NOW
	CNFIRM			;MAKE SURE USER WANTS THIS
	HRRO T2,T5		;GET THE NAME INDEX
	MOVEI T1,.GTHSN		;TRANSLATE NAME TO NUMBER FUNCTION
	IFE NDEBUG,<GTHST>     	;GET HOST NUMBER
	 JSYSF
	MOVEM T3,FHOSTN		;SAVE THE 4N HOST NUMBER
	RET			;RETURN TO CALLER
.FORE2:				;HERE ON THE NO COMMAND
	NOISE <HOST FOR TRAFFIC>
	CALL SKPABO		;ONLY IF WE ARE NOT RUNNING
	 RET			;IF RUNNING JUST RETURN
	CNFIRM			;MAKE SURE
	SETZM FHOSTN		;RESET 4N HOST NUMBER
	RET			;RETURN TO CALLER
	SUBTTL SET MODE COMMANDS

.MODE:				;SET MODE COMMAND
	NOISE <OF DATA ACTIVITY TO BE>
	CALL SKPABO		;MAKE SURE WE ARE NOT RUNNING
	 RET			;IF WE ARE RUNNING JUST RETURN
	DOCMD .CMKEY,MCMDS	;GET THE KEYWORD
	DODSP			;DISPATCH ON IT
	RET			;RETURN TO CALLER

.BOTH:				;BOTH SEND AND RECEIVE MODE
	NOISE <SEND AND RECEIVE MODE>
	CNFIRM			;MAKE SURE
	TXZ F,F%SEND!F%RCV	;TURN OFF FLAGS
	RET			;RETURN TO CALLER

.SEND:				;SEND ONLY MODE
	NOISE <ONLY MODE>
	CNFIRM			;MAKE SURE
	TXO F,F%SEND		;TURN ON FLAG
	TXZ F,F%RCV		;TURN OFF FLAG
	RET			;RETURN TO CALLER

.RECEI:				;RECEIVE ONLY MODE
	NOISE <ONLY MODE>
	CNFIRM			;MAKE SURE
	TXO F,F%RCV		;TURN ON FLAG
	TXZ F,F%SEND		;TURN OFF FLAG
	RET			;RETURN TO CALLER
	SUBTTL YET MORE SET COMMANDS

.SOCKE:				;SET SOCKET COMMAND
	STKVAR <SOCKNM>
	NOISE <NUMBERS TO USE STARTING WITH>
	CALL SKPABO		;ARE WE RUNNING?
	 RET			;NO
	DOCMD .CMNUM,10		;READ IN INITIAL SOCKET NUMBER
	MOVEM T2,SOCKNM		;SAVE THE SOCKET NUMBER
	CNFIRM			;MAKE SURE USER WANTS THIS
	MOVE T1,SOCKNM		;GET THE SOCKET NUMBER BACK
	TXNE T1,1		;EVEN NUMBER?
	 ADDI T1,1		;NO SO MAKE IT EVEN
	MOVSI T2,-NFKS		;INITIALIZE AOBJN POINTER
.SOCKL:				;SOCKET SETTING LOOP
	MOVEM T1,FSCKTL(T2)	;SAVE THE LOCAL SOCKET NUMBER
	MOVEI T3,1(T1)		;ASSUME RCV SOCKET
	TXNE T1,1		;RCV SOCKET?
	 MOVEI T3,-1(T1)	;NO SEND SOCKET
	MOVEM T3,FSCKTF(T2)	;SAVE THE 4N SOCKET NUMBER
	AOJ T1,			;BUMP THE SOCKET NUMBER
	AOBJN T2,.SOCKL		;LOOP FOR ALL SOCKETS
	RET			;RETURN TO CALLER

.PATTE:				;SET PATTERN COMMAND
	NOISE <FOR IO TO BE>	;HELP OUT USER
	DOCMD .CMKEY,TCMDS,<SEQUENCE> ;GET THE PATTERN TYPE
	HRRZ T5,0(T2)		;GET THE PATTERN ADDRESS
	CNFIRM			;MAKE SURE THE USER WANTS THIS
	TXNN F,F%RUN		;ARE WE RUNNING?
	 JRST .PATT2		;NO
	MOVE T1,GLOBAL		;GET THE GLOBAL FLAG
	TXNN T1,G%VERF		;ARE WE CURRENTLY VERIFYING?
	 JRST .PATT2		;NO SO THIS IS OK
	CALL NEWLIN		;GET A NEW LINE
	TYPEN <%NOT LEGAL WHEN RUNNING AND CURRENTLY VERIFYING>
	RET			;RETURN TO CALLER
.PATT2:				;HERE WHEN WE THINK THIS IS OK
	MOVEM T5,PATERW		;SAVE THE PATTERN ADDRESS
	RET			;AND GET ANOTHER COMMAND
	SUBTTL SET LENGTH COMMANDS

.LENGT:				;SET LENGTH COMMAND
	NOISE <OF MESSAGES TO BE OF>
	DOCMD .CMKEY,LCMDS,<RANDOM> ;GET KEYWORD
	DODSP			;DISPATCH ON THE COMMAND
	RET			;RETURN FOR ANOTHER COMMAND

.RANDO:				;SET LENGTH RANDOM COMMAND
	NOISE <LENGTH>		;HELP OUT THE USER
	CNFIRM			;MAKE SURE USER WANTS THIS
	SETOM LENGTH		;SET LENGTH TO BE RANDOM
	RET			;AND RETURN FOR ANOTHER COMMAND

.SIZE:				;SET LENGTH SIZE COMMAND
	DOCMD .CMNUM,12,<512>	;PARSE SIZE
	MOVE T5,T2		;SAVE THE VALUE
	NOISE <WORDS>		;HELP OUT THE USER
	CNFIRM			;MAKE SURE USER WANTS THIS
	SKIPLE T5		;IS LENGTH POSITIVE?
	 CAILE T5,^D512		;AND A PAGE OR LESS?
	  JRST .SIZE2		;NO PAGE SIZE IS NOT LEGAL
	MOVEM T5,LENGTH		;SAVE THE LENGTH
	RET			;RETURN FOR ANOTHER COMMAND
.SIZE2:	CALL NEWLIN		;GET A NEW LINE
	TYPEN <?ILLEGAL PAGE SIZE> ;TELL USER HE SCREWED UP
	RET			;RETURN FOR ANOTHER COMMAND
	SUBTTL SET NUMBER AND RETIME COMMANDS

.NUMBE:				;NUMBER SUBCOMMAND
	STKVAR <DBMBSZ,DBMCNT>	;SAVE THE COUNT
	NOISE <OF CONNECTIONS FOR BYTESIZE> ;HELP OUT THE USER
	CALL SKPABO		;ARE WE STOPED
	 RET			;NO SO JUST RETURN
	DOCMD .CMKEY,BCMDS,<36>	;GET THE BYTE SIZE
	HRRZ T2,0(T2)		;GET THE BYTE SIZE
	MOVEM T2,DBMBSZ		;SAVE THE BYTE SIZE
	NOISE <TO BE>		;HELP OUT THE USER
	DOCMD .CMNUM,12,<1>	;GET A NUMBER
	MOVEM T2,DBMCNT		;SAVE THE NUMBER OF CONNECTIONS
	CNFIRM			;CONFIRM THE COMMAND
	MOVE T1,DBMBSZ		;GET THE BYTE SIZE
	MOVE T2,DBMCNT		;GET THE COUNTT
	MOVEM T2,CONCTS(T1)	;SAVE THE COUNT
	RET			;GET ANOTHER COMMAND

.RETIM:				;COMMAND TO RESET IO RATE CLOCKS
	NOISE <AND RESET IO RATE CLOCK NUMBER>
	DOCMD .CMKEY,RCMDS	;GET THE IO RATE TO RESET
	HRRZ T5,0(T2)		;SAVE THE CLOCK TO RESET
	CNFIRM			;MAKE SURE USER WANTS THIS
	TIME			;GET THE CURRENT TIME
	MOVEM T1,0(T5)		;RESET THE IO TIME WORD
	CAIN T5,IOTIM1		;ARE WE RESETING RATE 1
	SKIPA T5,[FRKIO1]	;YES SO GET CORRECT COUNT
	MOVEI T5,FRKIO2		;NO SO IT MUST BE RATE 2
	HRLI T5,-NFKS		;GET THE AOBJN POINTER
.RETI2:				;CLOCK RESET LOOP
	SETZM (T5)		;RESET THE COUNT
	AOBJN T5,.RETI2		;LOOP FOR ALL CLOCKS
	RET			;RETURN TO CALLER
	SUBTTL SET ARPANET COMMAND

.ARPAN:				;SET ARPANET STATE
	NOISE <STATE IS>       	;HELP OUT USER
	DOCMD .CMKEY,ACMDS,<ON>	;GET ARPANET STATE KEYWORD
	DODSP			;DISPATCH ON THE STATE
	RET			;GET ANOTHER COMMAND

.ACYCL:				;CYCLE ARPANET COMMAND
	NOISE <OFF THEN ON>	;HELP OUT THE USER
	CNFIRM			;MAKE SURE
	MOVEI T1,.SFNDU		;GET SMON FUNCTION
	MOVEI T2,1		;MAKE IT SET
	SMON			;CYCLE THE ARPANET
	 JSYSF			;HANDLE ERRORS
	RET			;GET ANOTHER COMMAND

.AON:				;TURN ARPANET ON
	CNFIRM			;MAKE SURE
	MOVEI T2,1		;MAKE NETWORK COME UP
.AON2:				;COMMON CODE
	MOVEI T1,.SFNTN		;ARPANET STATE FUNCTION
	SMON			;TURN ON THE ARPANET
	 JSYSF			;HANDLE ERRORS
	RET			;RETURN TO CALLER

.AOFF:				;TURN ARPANET OFF
	CNFIRM			;MAKE SURE
	SETZ T2,		;NAKE NETWORK GO DOWN
	JRST .AON2		;COMMON CODE

.ALOAD:				;LOAD HOST TABLE FOR ARPANET
	NOISE <INITIALIZE HOST TABLE> ;HELP OUT THE USER
	CNFIRM			;MAKE SURE
	MOVEI T1,.SFNHI		;LOAD TABLE FUNCTION
	MOVEI T2,1		;MAKE IT HAPPEN
	SMON			;LOAD ARPANET TABLES
	 JSYSF			;HANDLE ERRORS
	RET			;GET ANOTHER COMMAND
	SUBTTL SET PROTOCOL COMMAND

.PROTO:				;THE PROTOCOL COMMAND
	STKVAR <PRTONM>		;GET SOME TEMPORARY STORAGE
	NOISE <TO BE>		;HELP OUT THE USER
	DOCMD .CMKEY,PRCMDS,<NCP> ;GET THE PROTOCOL TYPE
	HRRZ T2,0(T2)		;GET THE PROTOCOL TYPE
	MOVEM T2,PRTONM		;SAVE THE PROTOCOL TYPE
	CNFIRM			;MAKE SURE
	CALL SKPABO		;ARE WE RUNNING
	 RET			;YES SO RETURN
	MOVE T1,PRTONM		;GET BACK THE PROTOCOL NUMBER
	CAIE T1,.PTNCP		;DID USER ASK FOR NCP?
	 RET			;YES SO IT IS OK
	TYPEN <%ONLY NCP IS CURRENTLY IMPLEMENTED>
	RET			;GET ANOTHER COMAND
	SUBTTL SHOW COMMAND

.SHOW:				;SHOW SETTINGS COMMAND
	NOISE <CURRENT SETTINGS> ;HELP OUT THE USER
	CNFIRM			;MAKE SURE
	TYPE <    TRAFIC VERSION > ;PROMPT THE VERSION NUMBER
	CALL VEROUT		;OUTPUT THE VERSION INFORMATION
	TYPE <    LOCAL HOST IS >
	MOVEI T1,.GTHNS		;RETURN THE HOST NAME
	MOVEI T2,.PRIOU		;OUTPUT TO THE TTY
	MOVE T3,HOSTN		;GET THE HOST NUMBER
	IFE NDEBUG,<GTHST>     	;OUTPUT OUR HOST NAME
	 JSYSF
	SKIPN FHOSTN		;IS THERE A 4N HOST NUMBER?
	 JRST .SHOW7		;NO
	TYPEN <, FOREIGN HOST IS >
	MOVEI T1,.GTHNS		;RETURN THE HOST NAME
	MOVEI T2,.PRIOU		;OUTPUT TO THE TTY
	MOVE T3,FHOSTN		;GET THE FOREIGN HOST NUMBER
	IFE NDEBUG,<GTHST>     	;OUTPUT HOST NUMBER
	 JSYSF
.SHOW7:
	SKIPN FHOSTN		;IS THERE A 4N HOST?
	 JRST .SHOW8		;NO
	TXNN F,F%SEND!F%RCV	;SPECIAL MODES?
	 JRST .SHOW8		;NO
	TYPE <    >
	HRROI T1,[ASCIZ/SEND ONLY MODE/] ;ASSUME SEND ONLY MODE
	TXNN F,F%SEND		;ARE WE IN SEND ONLY
	 HRROI T1,[ASCIZ/RECEIVE ONLY MODE/] ;NO SO MUST BE RECEIVE ONLY
	PSOUT			;OUTPUT THE STRING
.SHOW8:
	TYPE <    INITIAL SOCKET NUMBER TO USE IS >
	NUMO FSCKTL,10		;OUTPUT SOCKET NUMBER
	TYPE <    MESSAGE LENGTH IS >
	SKIPL T2,LENGTH		;IS THE LENGTH RANDOM?
	 JRST .SHOW0		;NO
	TYPEN <RANDOM>
	JRST .SHOW6		;CONTINUE WITH FLOW
.SHOW0:				;HERE IF LENGTH IS FIXED
	NUMO T2,12		;OUTPUT THE MESSAGE LENGTH
	TYPEN < WORDS>
.SHOW6:
	MOVE T1,GLOBAL		;GET THE GLOBAL FLAGS
	TXNN T1,G%VERF		;VERIFICATION ENABLED?
	 JRST .SHOW2		;NO
	TYPE <    DATA VERIFICATION>
.SHOW2:
	MOVE T1,GLOBAL		;GET THE GLOBAL FLAGS
	TXNN T1,G%SQNC		;ARE WE CHECKING SEQUENCE NUMBERS?
	 JRST .SHOW1		;NO
	TYPE <    DATA SEQUENCE CHECKS>
.SHOW1:
	TYPE <    DATA PATTERN IS >
	MOVE T2,PATERW		;GET THE CURRENT PATTEN
	HRROI T1,[ASCIZ/SEQUENCE/] ;ASSUME SEQUENCE
	CAIN T2,PATERA		;IS IT ALTERNATING?
	 HRROI T1,[ASCIZ/ALTERNATING/] ;YES
	CAIN T2,PATERO		;IS IT ONES?
	 HRROI T1,[ASCIZ/ONES/]	;YES
	CAIN T2,PATERZ		;IS IT ZEROES?
	 HRROI T1,[ASCIZ/ZEROES/] ;YES
	PSOUT			;OUTPUT THE PATTERN TYPE
	SKIPN CONCTS+.BS8	;EIGHT BIT CONNECTIONS?
	 JRST .SHOW3		;NO
	TYPE < >		;NEW LINE
	NUMO <CONCTS+.BS8>,12,2	;YES
	TYPEN < EIGHT BIT BYTE CONNECTIONS>
.SHOW3:
	SKIPN CONCTS+.BS32	;32 BIT CONNECTIONS?
	 JRST .SHOW4		;NO
	TYPE < >		;NEW LINE
	NUMO <CONCTS+.BS32>,12,2 ;YES
	TYPEN < THIRTY TWO BIT BYTE CONNECTIONS>
.SHOW4:
	SKIPN CONCTS+.BS36	;36 BIT CONNECTIONS?
	 JRST .SHOW5		;NO
	TYPE < >		;NEW LINE
	NUMO <CONCTS+.BS36>,12,2 ;YES
	TYPEN < THIRTY SIX BIT BYTE CONNECTIONS>
.SHOW5:
	TYPE <>			;EXTRA LINE
	TYPE <>			;EXTRA LINE
	RET			;GET ANOTHER COMMAND
	SUBTTL VERSION INFORMATION OUTPUT ROUTINE

VEROUT:				;VERSION OUTPUT ROUTINE
	MOVEI T2,VMAJOR		;GET THE VERSION NUMBER
	NUMO T2,10		;OUTPUT THE MAJOR VERSION
	MOVEI T2,VMINOR		;MINOR VERSION NUMBER?
	SKIPN T2		;MINOR VERSION NUMBER?
	 JRST VEROU2		;NO
	TYPEN <.>		;YES
	MOVEI T2,VMINOR		;GET THE MINOR VERSION AGAIN
	NUMO T2,10		;OUTPUT IT
VEROU2:	MOVEI T2,VEDIT		;GET EDIT NUMBER
	SKIPN T2		;EDIT NUMBER?
	 JRST VEROU3		;NO
	TYPEN <(>		;OUTPUT EDIT DELIMITOR
	MOVEI T2,VEDIT		;OUTPUT THE EDIT NUMBER
	NUMO T2,10		;IN OCTAL
	TYPEN <)>		;OUTPUT OTHER EDIT DELIMITOR
VEROU3:	MOVEI T2,VWHO		;GET WHO LAST HACKED
	SKIPN T2		;LAST HACKER?
	 JRST VEROU4		;NO
	TYPEN <->		;YES
	MOVEI T2,VWHO		;GET LAST HACKER CODE
	NUMO T2,10		;OUTPUT IT
VEROU4:
	RET			;RETURN TO CALLER
	SUBTTL COMMAND MODE SUPPORT ROUTINES

SKPRUN:				;SKIP RETURN IF WE ARE RUNNING
	TXNE F,F%RUN		;ARE WE RUNNING?
	 JRST RSKP		;YES SO SKIP RETURN
	CALL NEWLIN		;GET A NEW LINE
	TYPEN <%ILLEGAL WHEN NOT RUNNING...USE START COMMAND FIRST>
	RET			;NON-SKIP RETURN

SKPABO:				;SKIP RETURN IF WE ARE NOT RUNNING
	TXNN F,F%RUN		;ARE WE RUNNING?
	 JRST RSKP		;NO SO SKIP RETURN
	CALL NEWLIN		;GET A NEW LINE
	TYPEN <%ILLEGAL WHILE RUNNING...USE ABORT COMMAND FIRST>
	RET			;NON-SKIP RETURN

SKPSTP:				;SKIP RETURN IF WE ARE STOPPED
	TXNE F,F%STOP		;ARE WE STOPPED?
	 JRST RSKP		;YES
	CALL NEWLIN		;GET A NEW LINE
	TYPEN <%ILLEGAL WHEN NOT STOPPED...USE STOP COMMAND FIRST>
	RET			;NON-SKIP RETURN

SKPCNT:				;SKIP RETURN IF WE ARE NOT STOPPED
	TXNN F,F%STOP		;ARE WE STOPPED
	 JRST RSKP		;NO SO SKIP RETURN
	CALL NEWLIN		;GET A NEW LINE
	TYPEN <%ILLEGAL WHEN STOPPED...USE CONTINUE COMMAND FIRST>
	RET			;NON-SKIP RETURN
	SUBTTL START AND ABORT COMMANDS

.START:				;START COMMAND
	NOISE <RUNNING>		;HELP OUT THE USER
	CALL SKPABO		;ARE WE RUNNING?
	 RET			;YES
	MOVE T1,CONCTS+.BS8	;GET NUMBER OF 8 BIT CONNECTIONS
	ADD T1,CONCTS+.BS32	;ADD IN NUMBER OF 32 BIT CONNECTIONS
	ADD T1,CONCTS+.BS36	;ADD IN NUMBER OF 36 BIT CONNECTIONS
	JUMPN T1,START1		;IF .GT. ZERO WE CAN DO IT
	CALL NEWLIN		;GET A NEW LINE
	TYPEN <%NO CONNECTIONS SPECIFIED>
	RET			;RETURN TO CALLER
START1:				;HERE WHEN WE HAVE CONNECTIONS
	DOCMD .CMKEY,STCMDS,<NORMALLY> ;GET SUBCOMMAND
	HRRZ L1,0(T2)		;SAVE THE RESULT IN A SAFE PLACE
	CNFIRM			;MAKE SURE
	SKIPE L1		;SHOULD WE WAIT?
	TXO F,F%WAIT		;YES SO SET THE FLAG
START2:				;HERE FROM WAIT COMMAND
	CALL STRFRK		;START ALL FORKS
	TXO F,F%RUN		;SET THE RUN FLAG
	MOVE T1,PRMPTR		;GET THE RUNNING PROMPT
	MOVEM T1,CSB+.CMRTY	;AND SET IT FOR COMND
	TXNE F,F%WAIT		;SHOULD WE WAIT?
	WAIT			;YES SO DO IT
	TXZ F,F%WAIT		;TURN OFF THE WAIT FLAG
	RET			;RETURN FOR ANOTHER COMMAND

.ABORT:				;ABORT COMMAND
	NOISE <CURRENT RUN>	;HELP OUT THE USER
	CALL SKPRUN		;ARE WE RUNNING?
	 RET			;NO
	CNFIRM			;MAKE SURE
ABORT2:				;ENTRY POINT FROM EXIT
	CALL KILFRK		;KILL ALL FORKS
	TXZ F,F%RUN!F%STOP	;RESET FLAGS
	MOVE T1,PRMPTD		;GET THE CORRECT PROMPT
	MOVEM T1,CSB+.CMRTY	;SET IT IN THE CSB
	RET
	SUBTTL STOP AND CONTINUE COMMANDS

.STOP:				;STOP COMMAND
	NOISE <RUNNING TEMPORARILY> ;HELP THE USER
	CALL SKPRUN		;ARE WE RUNNING?
	 RET			;NO
	CALL SKPCNT		;ARE WE STOPPED?
	 RET			;YES
	CNFIRM			;MAKE SURE
	CALL SUSFRK		;SUSPEND ALL FORKS
	TXO F,F%STOP		;SET FLAG
	MOVE T1,PRMPTH		;GET THE CORRECT PROMPT
	MOVEM T1,CSB+.CMRTY	;PUT IT IN FOR COMND
	RET			;RETURN FOR ANOTHER COMMAND

.CONTI:				;CONTINUE COMMAND
	CALL SKPRUN		;ARE WE RUNNING?
	 RET			;NO
	NOISE <RUNNING>		;HELP OUT THE USER
	CALL SKPSTP		;ARE WE STOPPED?
	 RET			;NO
	CNFIRM			;MAKE SURE
	CALL CNTFRK		;CONTINUE ALL FORKS
	TXZ F,F%STOP		;RESET THE FLAG
	MOVE T1,PRMPTR		;GET THE RUNNING PROMPT
	MOVEM T1,CSB+.CMRTY	;AND SAVE IT IN THE CSB
	RET			;RETURN FOR ANOTHER COMMAND
	SUBTTL STATUS COMMAND

.STATU:				;STATUS COMMAND
	NOISE <OF FORKS AND CONNECTIONS>
	CALL SKPRUN		;ARE WE RUNNING
	 RET			;NO
	CNFIRM			;MAKE SURE
	MOVE FX,FORKDX		;GET THE AOBJFN POINTER
	SETZM IOSUM1		;ZERO THE RCV SUMS
	SETZM IOSUM2		;AND THE OTHER
	SETZM ERRSUM		;RESET ERROR SUMMARY COUNTER
	SETZM MSGSUM		;ZERO THE MESSAGE SUMMARY COUNTER
	MOVE T1,GLOBAL		;GET THE GLOBAL FLAGS
	TXNN T1,G%SQNC!G%VERF   ;VERIFICATION ON?
	 JRST .STAT0		;NO
TYPE < Fx Lcl Skt     4n Skt      Sz Mode IO Rate 1 IO Rate 2 Messages Errors>
TYPE < ---------------------------------------------------------------------->
	JRST .STAT1		;CONTINUE WITH FLOW
.STAT0:				;HERE IF VERIFICATION IS NOT ON
TYPE < Fx Lcl Skt     4n Skt      Sz Mode IO Rate 1 IO Rate 2 Messages>
TYPE < --------------------------------------------------------------->
.STAT1:				;FORK STATUS LOOP
	SKIPN FORKX(FX)		;DOES THIS FORK EXIST?
	 JRST .STAT2		;NO
	TYPE < >		;GET A NEW LINE
	HRRZ T2,FX		;GET THE FORK NUMBER
	NUMO T2,10,2		;OUTPUT THE FORK NUMBER
	TYPEN < >		;A SPACE
	NUMO FSCKTL(FX),10,13	;OUTPUT LOCAL SOCKET NUMBER
	TYPEN < >		;A SPACE
	NUMO FSCKTF(FX),10,13	;OUTPUT FOREIGN SOCKET NUMBER
	TYPEN < >		;A SPACE
	NUMO FBYTE(FX),12,2	;OUTPUT BYTE SIZE
	HRROI T1,[ASCIZ/ RCV /]	;ASSUME RECEIVE FORK
	SKIPE FRKSEX(FX)       	;IS IT A RECEIVER?
	HRROI T1,[ASCIZ/ SEND/]	;NO
	PSOUT			;OUTPUT THE FORK TYPE
	TYPEN < >		;OUTPUT A SPACE
	MOVE T3,FRKIO1(FX)	;GET THE FORK BITS
	TXNN F,F%SEND		;ARE WE SEND ONLY?
	SKIPN FRKSEX(FX)       	;OR ARE WE A RECEIVER?
	 ADDM T3,IOSUM1		;YES SO ADD IN THE SUM
	MOVE T3,FRKIO1(FX)	;GET THE FORK BITS
	MOVE T4,IOTIM1		;GET THE STARTING TIME
	CALL IORATE		;OUTPUT THE IO RATE
	TYPEN < >		;OUTPUT A SPACE
	MOVE T3,FRKIO2(FX)	;GET THE FORK BITS
	TXNN F,F%SEND		;SEND ONLY MODE?
	SKIPN FRKSEX(FX)       	;OR ARE WE A RECEIVER?
	 ADDM T3,IOSUM2		;YES SO ADD IN THE SUM
	MOVE T3,FRKIO2(FX)	;GET THE FORK BITS
	MOVE T4,IOTIM2		;GET THE TIME FOR RATE 2
	CALL IORATE		;OUTPUT THE IO RATE
	MOVE T1,FRKMSG(FX)	;GET THE MESSAGE COUNT
	ADDM T1,MSGSUM		;ADD IT TO THE MESSAGE SUMMARY
	TYPEN < >		;YES...OUTPUT A SPACE
	NUMO FRKMSG(FX),12,8	;OUTPUT MESSAGE COUNT
	MOVE T1,GLOBAL		;GET THE GLOBAL FLAGS
	TXNN T1,G%SQNC!G%VERF 	;ARE WE VERIFYING?
	 JRST .STAT2		;NO
	TYPEN < >		;A SPACE
	NUMO FRKDER(FX),12,6	;OUTPUT ERROR COUNT
	MOVE T1,FRKDER(FX)	;GET DATA ERROR COUNT
	ADDM T1,ERRSUM		;ADD IT TO THE ERROR SUMMARY
.STAT2:
	AOBJN FX,.STAT1		;OUTPUT DATA FOR ALL THE FORKS
	MOVE T1,GLOBAL		;GET THE GLOBAL FLAGS
	TXNE T1,G%SQNC!G%VERF  	;ARE WE VERIFYING?
	 JRST .STAT3		;YES SO SPECIAL OUTPUT
TYPE <                                    ----------------------------->
	JRST .STAT4		;JOIN COMMON CODE
.STAT3:				;HERE FOR ERROR TOTAL STUFF
TYPE <                                    ------------------------------------>
.STAT4:				;COMMON CODE
TYPE <                                    >
	MOVE T3,IOSUM1		;GET THE IO SUM
	MOVE T4,IOTIM1		;AND THE IO TIME
	CALL IORATE		;OUTPUT THE TOTAL RCV IO RATE
	TYPEN < >		;DO A SPACE
	MOVE T3,IOSUM2		;GET THE IO SUM
	MOVE T4,IOTIM2		;GET THE IO TIME
	CALL IORATE		;OUTPUT THE TOTAL RCV IO RATE
	TYPEN < >		;DO A SPACE
	NUMO MSGSUM,12,10	;OUTPUT TOTAL MESSAGE COUNT
	MOVE T1,GLOBAL		;GET GLOBAL FLAGS
	TXNN T1,G%SQNC!G%VERF  	;ARE WE VERIFYING?
	 JRST .STAT5		;NO
	TYPEN < >		;YES SO OUTPUT A SPACE
	NUMO ERRSUM,12		;OUTPUT TOTAL ERROR COUNT
.STAT5:				;COMMON CODE
	TYPE <>			;EXTRA TTY LINE
	TYPE <>			;EXTRA TTY LINE
	RET			;GET ANOTHER COMMAND

IORATE:				;ROUTINE TO OUTPUT IO RATE
	TIME			;GET CURRENT TIME IN MSECS
	SUBM T1,T4		;GET ELAPSED TIME
	IDIVI T4,^D1000		;MAKE IT SECONDS
	SKIPN T4		;IS THE TIME ZERO
	 TDZA T4,T4		;YES...ZERO RATE AND SKIP
	IDIVM T3,T4		;GET THE IORATE
	NUMO T4,12,11		;OUTPUT THE IORATE
	RET			;RETURN TO CALLER
	SUBTTL HOST NAME ROUTINES

HSTRED:				;ROUTINE TO READ IN HOST NAMES IF NEEDED
	TXNE F,F%HOST		;HAVE WE READ IN HOST NAMES YET?
	 RET			;YES SO JUST RETURN
	MOVX T1,<HSTABL-HSTCMD-1> ;GET MAX NUMBER OF HOST SLOTS AVAILABLE
	MOVEM T1,HSTCMD		;INIT THE COMND TABLE
	MOVEI T1,.GTHSZ		;HOST INFORMATION FUNCTION
	IFE NDEBUG,<GTHST>     	;GET INFORMATION ABOUT HOSTS
	 JSYSF
	MOVE L1,T2		;PUT HOST NAME AOBJN INTO A SAFE PLACE
	MOVEI L2,HSTABL		;GET HOST TABLE POINTER
HSTREL:				;HOST NAME LOOP
	MOVEI T1,.GTHIX		;GET HOST NAME FUNCTION
	HRRO T2,L2		;GET NAME AREA INDEX
	HRRZ T3,L1		;GET THE HOST NAME INDEX
	IFE NDEBUG,<GTHST>     	;GET THE HOST NAME STRING
	 JSYSF
	IBP T2  		;BUMP THE POINTER FOR THE NULL BYTE
	MOVE T5,T2		;SAVE THE FINAL POINTER FOR A WHILE
	MOVEI T1,HSTCMD		;GET HEADER WORD ADDRESS
	HRLZ T2,L2		;GET POINTER TO HOST NAME
	TBADD			;ADD THE HOST NAME TO COMND TABLE
	 JSYSF
	MOVEI L2,1(T5)		;FIX THE HOST TABLE POINTER
	AOBJN L1,HSTREL		;LOOP FOR ALL THE HOSTS
	TXO F,F%HOST		;TURN ON THE FLAG BIT
	RET			;RETURN TO CALLER
	SUBTTL FORK STARTING ROUTINE

STRFRK:				;ROUTINE TO START ALL THE FORKS
	SETZB T4,FX		;INITIALIZE FORK COUNTERS
	MOVEI T1,.BS8		;EIGHT BIT CONNECTIONS
	MOVEI T1,10		;EIGHT BIT CONNECTIONS
	SKIPE T2,CONCTS+.BS8	;GET NUMBER OF EIGHT BIT CONNECTIONS
	 CALL STRFR2		;INITIALIZE DATA
	MOVEI T1,40		;THIRTY TWO BIT CONNECTIONS
	SKIPE T2,CONCTS+.BS32	;GET NUMBER OF 32 BIT CONNECTION
	 CALL STRFR2		;AND INITIALIZE DATA
	MOVEI T1,44		;36 BIT CONNECTIONS
	SKIPE T2,CONCTS+.BS36	;GET NUMBER OF 36 BIT CONNECTIONS
	 CALL STRFR2		;AND INITIALIZE THEM
				;NOW START ALL THE FORKS
	MOVN FX,T4		;GET NUMBER OF HIGHEST FORK
	HRLZS FX		;GET THE REAL AOBJN POINTER
	MOVEM FX,FORKDX		;SAVE AOBJN POINTER
STRFR1:				;LOOP TO START FORKS
	SKIPN FHOSTN		;ARE WE TALKING TO A 4N HOST?
	 JRST STRFR3		;NO
	TXNN F,F%RCV!F%SEND	;ARE WE DOING BOTH SEND AND RECEIVE?
	 JRST STRFR3		;YES SO GO DO IT
	TXNE F,F%RCV		;ARE WE DOING RECEIVE ONLY?
	 SKIPE FRKSEX(FX)      	;YES IS THIS A RECEIVER?
	  SKIPA			;NO
	   JRST STRFR3		;YES...START IT UP
	TXNE F,F%SEND		;SEND ONLY?
	 SKIPN FRKSEX(FX)      	;YES IS THIS A SENDER
	  JRST STRFR0		;NO
STRFR3:				;HERE TO START THIS FORK
	CALL MAKFRK		;MAKE A FORK
STRFR0:				;HERE EVEN IF WE DID NOT START IT
	AOBJN FX,STRFR1		;AND LOOP FOR THEM ALL
	TIME			;GET THE CURRENT TIME
	MOVEM T1,IOTIM1		;SET TIME ONE
	MOVEM T1,IOTIM2		;SET TIME TWO
	RET			;RETURN TO CALLER

STRFR2:				;ROUTINE TO INIT DATA
				;T1/ BYTE SIZE
				;T2/ NUMBER OF FORKS
	ASH T2,1		;MULTIPLY BY TWO
	MOVNS T2		;MAKE THE COUNT NEGATIVE
	HRL T4,T2		;AND PUT IT IN THE LEFT HALF
STRFR4:				;THE INIT LOOP
	MOVEM T1,FBYTE(T4)	;INIT THE BYTE COUNT
	AOBJN T4,STRFR4		;LOOP FOR THEM ALL
	RET			;AND RETURN TO CALLER
	SUBTTL ROUTINES TO SUSPEND AND CONTINUE ALL FORKS

SUSFRK:				;ROUTINE TO SUSPEND ALL FORKS
	MOVSI FX,-NFKS		;INITIALIZE AOBJN POINTER
SUSFR2:				;FORK SUSPENSION LOOP
	SKIPN T1,FORKX(FX)	;GET THE FORK HANDLE
	 JRST SUSFR3		;FORK DIDNT EXIST
	HFORK			;HALT THE FORK
	 JSYSF			;HANDLE ERRORS
SUSFR3:				;HERE AFTER SUSPENDING THE FORK
	AOBJN FX,SUSFR2		;LOOP FOR ALL FORKS
	RET			;RETURN TO CALLER

CNTFRK:				;ROUTINE TO CONTINUE A FORK
	MOVSI FX,-NFKS		;INITIALIZE AOBJN POINTER
CNTFR2:				;FORK CONTINUE LOOP
	SKIPN T1,FORKX(FX)	;FORK EXIST?
	 JRST CNTFR3		;NO
	TXO T1,SF%CON		;SET THE CONTINUE FLAG
	SFORK			;CONTINUE THE FORK
	 JSYSF			;HANDLE ERRORS
CNTFR3:				;HERE AFTER CONTINUING THE FORK
	AOBJN FX,CNTFR2		;LOOP FOR ALL FORKS
	RET			;RETURN TO CALLER
	SUBTTL ROUTINE TO CREATE AND START A FORK

MAKFRK:				;ROUTINE TO MAKE A FORK
				;FX HAS THE FORK INDEX
	STKVAR <<MAKACS,20>>	;AC BLOCK FOR CFORK
	MOVEI T1,1+MAKACS	;BUILD BLT AC
	HRLI T1,MAKACS		;GET LEFT HALF OF BLT AC
	SETZM MAKACS		;ZERO FIRST WORD OF MAKACS
	BLT T1,17+MAKACS	;ZERO FORK AC BLOCK
	MOVEM FX,FX+MAKACS	;SET FX VALUE FOR SUBFORK
	MOVX T1,<CR%CAP!CR%ACS>	;GIVE THE FORK PRIVS
	MOVEI T2,MAKACS		;GET AC BLOCK ADDRESS
	CFORK			;CREATE THE FORK
	 JSYSF			;TRAP ERRORS
	MOVEM T1,FORKX(FX)	;SAVE THE FORK HANDLE
				;MAP ALL THE EXISTING PAGES
	MOVSI T4,-1000		;INITIALIZE AOBJN POINTER
MAKFR2:				;PAGE MAP LOOP
	MOVEI T1,(T4)		;GET THE PAGE NUMBER
	HRLI T1,.FHSLF		;THIS FORK
	RMAP			;READ PAGE ACCESS
	 JSYSF			;HANDLE ERRORS
	TXNN T2,RM%PEX		;DOES THIS PAGE EXIST
	 JRST MAKFR3		;NO SO DONT MAP IT
	MOVE T3,T2		;PUT ACCESS IN THE CORRECT PLACE
	MOVEI T1,(T4)		;GET THE PAGE NUMBER
	MOVEI T2,(T4)		;IN BOTH ACS
	HRLI T1,.FHSLF		;MAP FROM ME
	HRL T2,FORKX(FX)	;TO HIM
	TXZ T3,<617377,,-1>	;TURN OFF UNWANTED BITS
	PMAP			;MAP THE PAGE
	 JSYSF			;HANDLE ERRORS
MAKFR3:				;HERE TO GET NEXT PAGE NUMBER
	AOBJN T4,MAKFR2		;TRY THE NEXT PAGE
				;NOW WE HAVE ALL PAGES MAPPED
	MOVE T1,FORKX(FX)	;GET THE FORK HANDLE
	MOVEI T2,INIFRK		;GET THE FORK STARTING ADDRESS
	SFORK			;START UP THE INFERIOR FORK
	 JSYSF			;HANDLE ERRORS
	RET			;RETURN TO CALLER
	SUBTTL FORK KILLING ROUTINES

; N.B.
; FORKS MUST BE KILLED IN CORRECT ORDER.  IF THE SENDERS GET KILLED
; BEFORE THE RECEIVERS FLKTIM'S WILL RESULT.  THIS IS BECAUSE THE
; ARPANET CLZFF STUFF BLOCKS WHEN IT SHOULD NOT.  KWP

KILFRK:				;ROUTINE TO KILL ALL THE FORKS
	MOVSI FX,-NFKS		;INITIALIZE THE AOBJN POINTER
KILFR2:				;SEND FORK KILLING LOOP
	SKIPE T1,FORKX(FX)	;FORK EXIST?
	 SKIPE FRKSEX(FX)      	;RECEIVE FORK?
	  JRST KILFR3		;DOESNT EXIST OR NOT A RECEIVER
	KFORK			;KILL THE FORK
	 JSYSF			;HANDLE ERRORS
	MOVE T1,FRKJFN(FX)	;GET THE FORKS JFN
	TXO T1,CZ%ABT		;ABORT ALL IO
	IFE NDEBUG,<CLOSF>	;CLOSE THE CONNECTION
	 JSYSF			;HANDLE ERRORS
	SETZM FORKX(FX)		;RESET THE FORK FLAG
KILFR3:				;HERE AFTER KILLING A FORK
	AOBJN FX,KILFR2		;LOOP FOR ALL FORKS
	MOVSI FX,-NFKS		;INITIALIZE THE AOBJN POINTER
KILFR4:				;RECEIVE FORK KILLING LOOP
	SKIPE T1,FORKX(FX)	;FORK EXIST?
	 SKIPN FRKSEX(FX)      	;AND SEND FORK?
	  JRST KILFR5		;NO
	KFORK			;YES SO KILL THE FORK
	 JSYSF			;HANDLE ERRORS
	MOVE T1,FRKJFN(FX)	;GET THE FORKS JFN
	CALL @PD.CLS(PD)	;CLOSE THE CONNECTION
	SETZM FORKX(FX)		;RESET THE FORK FLAG
KILFR5:				;HERE AFTER KILLING A FORK
	AOBJN FX,KILFR4		;LOOP FOR ALL FORKS
	RET			;DONE SO RETURN
	SUBTTL DATA FORK DOCUMENTATION

	COMMENT \

	N.B.

	The following is a general description of how the TRAFIC data forks
	work.  TRAFIC has a mother fork and many data forks.  Due to TOPS20
	limitations TRAFIC can only have a finite number of data forks.
	TRAFIC uses a fork for each side of a connection.  One fork is the
	data source for a connection and one fork is the data sink for the
	same connection.  I.E. Two forks are required for each connection.
	TRAFIC is currently limited to 10. connections.

	All data forks have common mapping with the mother fork when they
	are started.  Some pages created by the fork do not have common
	mapping with the mother fork.

	All data forks are started at INIFRK which initializes each fork
	and dispatches to the correct routine for each.  Currently all the
	receive forks run in RCVFRK and the send forks run in SNDFRK.

	The data forks use the following ACs for special purposes:

	FX/  	Contains the fork index for this fork.  This index is used to
		address the fork tables that a data fork must access.

	L1/	Contains the length of the data descriptor is bytes for this
		fork.

	L2/	Contains the length of the data field of a message in bytes
		for this fork.

	The data descriptor has the following format:

	_________________________________________
	| B0-B3 ! B4 ! B5-B7 ! B8-B23 ! B24-B35 !
	-----------------------------------------
	    |	  |	 |	 |	  |
	    |	  |	 |	 |	  +-- DD%SIZ - Data size
	    |	  |	 |	 |
	    |     |      |       +----------- DD%SQC - Sequence count
	    |     |      |
	    |     |      +------------------- DD%PTN - Pattern Index
	    |     |
	    |     +-------------------------- DD%VRF - Verification Required
	    |
	    +-------------------------------- DD%MBZ - Nonexistant MBZ

\
	SUBTTL DATA FORK INITIALIZATION ROUTINE

INIFRK:				;ROUTINE TO INITIALIZE FORK
	MOVE P,FPOINT(FX)	;GET OUR STACK POINTER
	MOVX F,F%FORK		;FLAG THAT WE ARE A FORK
	MOVEI PD,NCPDSP		;GET PROTOCOL DISPATCH ADDRESS
	SKIPE FRKDDT(FX)	;SHOULD WE GO DO DDT
	 CALL TODDT		;YES...GO TO DDT
DDTRET:				;THIS IS THE DDT RETURN ADDRESS
	MOVX PP,<440000,,PATERN> ;GET PROTOTYPE PATTERN POINTER
	MOVE T1,FBYTE(FX)	;GET OUR BYTE SIZE
	DPB T1,[POINT 6,PP,11]	;PUT BYTE SIZE INTO POINTER
	MOVE L1,FBYTE(FX)	;GET OUT BYTE SIZE
	CAIN L1,^D8 		;ARE WE 8 BIT BYTES?
	 SKIPA L1,[4]		;YES SO WE NEED FOUR BYTES FOR THE DD
	  MOVEI L1,1		;NO SO WE NEED ONE BYTE FOR THE DD
	SETZM FRKIO1(FX)	;ZERO BIT COUNT
	SETZM FRKIO2(FX)	;ZERO BIT COUNT
	SETZM FRKSQC(FX)	;ZERO OUT SEQUENCE NUMBER
	SETZM FRKDER(FX)	;RESET FORK DATA ERROR COUNT
	SETZM FRKERR(FX)	;RESET OUR LAST ERROR
	SETZM FRKMSG(FX)	;ZERO MESSAGE COUNT
	CALL @PD.OPN(PD)	;GET OUR CONNECTION OPEN
	SKIPE FRKSEX(FX)       	;IS THIS A SENDING FORK?
	 JRST SNDFRK		;YES
	JRST RCVFRK		;NO...MUST BE A RECEIVER
	SUBTTL RECEIVER FORK ROUTINE

RCVFRK:				;HERE IF WE ARE A RECEIVING FORK
	MOVE T1,FRKJFN(FX)	;GET THE SOCKET JFN
	HLL T2,PP		;GET THE BYTE POINTER LEFT HALF
	HRRI T2,L2		;PUT BYTE INTO DATA DESCRIPTOR
	MOVN T3,L1		;GET LENGTH OF DATA DESCRIPTOR FIELD
	CALL @PD.RCV(PD)	;READ IN THE DD
	MOVE T1,FBYTE(FX)	;GET OUR BYTE SIZE
	CAIE T1,^D36		;36 BIT BYTES?
	 LSH L2,-4		;NO SO SHIFT IT
	IFN NDEBUG,<SKIPG L2,LENGTH ;IF DEBUGING GET THE LENGTH
		     MOVEI L2,PGSIZ> ;IF RANDOM THEN IT IS A PAGE
	MOVE T1,GLOBAL		;GET THE GLOBAL FLAGS
	TXNN T1,G%SQNC		;ARE WE CHECKING SEQUENCE NUMBERS?
	 JRST RCVFR2		;NO
	LDB T1,[POINTR L2,DD%SQC] ;GET MESSAGE SEQUENCE NUMBER
	AOS T2,FRKSQC(FX)	;GET THE FORK SEQUENCE NUMBER
	ANDX T2,<.RTJST(-1,DD%SQC)>;ONLY BITS WE LIKE
	CAIE T2,(T1)		;CHECK THE SEQUENCE NUMBER
	AOS FRKDER(FX)		;NOT THE SAME SO BUMP DATA ERROR COUNT
	MOVEM T1,FRKSQC(FX)	;AND SAVE THE OLD SEQUENCE NUMBER
RCVFR2:				;HERE EVEN WHEN NOT DOING SEQUENCE CHECKING
	MOVE T1,FRKJFN(FX)	;GET THE SOCKET JFN
	HLL T2,PP		;GET THE PATTERN POINTER LEFT HALF
	HRRI T2,PATERF		;GET RIGHT HALF
	LDB T3,[POINTR L2,DD%SIZ] ;GET THE LENGTH OF DATA
	MOVE PB,T3		;SAVE BYTE COUNT FOR DCOUNT
	MOVNS T3		;GET THE NEGATIVE OF COUNT
	CALL @PD.RCV(PD)	;READ IN THE MESSAGE
	CALL DCOUNT		;UPDATE STAT COUNTS
	TXNE L2,DD%VRF		;DO WE NEED TO VERIFY THIS?
	 CALL VERIFY		;YES...SO DO IT
	JRST RCVFRK		;LOOP FOREVER
	SUBTTL SENDING FORK ROUTINE

SNDFRK:				;HERE IF WE ARE A SENDING FORK
	CALL DLENGT		;LOAD UP L2 WITH DATA DESRIPTOR
	MOVE T1,FRKJFN(FX)	;GET OUR NETWORK JFN
	HLL T2,PP		;GET THE POINTER LEFT HALF
	HRRI T2,L2		;DATA DESCRIPTOR IS IN L2
	MOVN T3,L1		;GET NUMBER OF BYTES IN DD
	MOVE T4,FBYTE(FX)	;GET OUR BYTE SIZE
	CAIE T4,^D36		;36 BIT BYTES?
	 LSH L2,4		;NO SO SHIFT DATA DESCRIPTOR
	CALL @PD.SND(PD)	;SEND OUT THE DD
	MOVE T1,FRKJFN(FX)	;GET THE SOCKET JFN
	HLL T2,PP		;GET THE PATTERN POINTER LEFT HALF
	HRR T2,PATERW		;GET THE CURRENT ACTIVE PATTERN ADDRESS
	MOVN T3,PB		;GET THE PATTERN BYTE COUNT
	CALL @PD.SND(PD)	;SEND OUT A MESSAGE
	CALL @PD.GO(PD)		;FORCE BUFFERS OUT
	CALL DCOUNT		;DO BIT COUNT STUFF
	JRST SNDFRK		;AND LOOP SOME MORE
	SUBTTL DATA FORK MISC SUBROUTINES

VERIFY:				;HERE TO VERIFY THE MESSAGE RECEIVED
	MOVE T1,PB              ;GET THE LENGTH
	MOVE T4,PB		;SAME LENGTH IN T4
	HLL T2,PP		;GET POINTER LEFT HALF
	HRRI T2,PATERF		;GET PATTERN ADDRESS
	SETZB T3,T6		;ZERO OTHER BYTE POINTER WORDS
	LDB T5,[POINTR L2,DD%PTN] ;GET THE PATTERN INDEX
	MOVE T5,PATRTN(T5)	;GET THE PATTERN ADDRESS
	HLL T5,T2		;GET POINTER LEFT HALF
	EXTEND T1,[CMPSN       	;COMPARE STRINGS
		Z		;ZERO FILL
		Z]		;ZERO FILL
	RET			;VERIFIED OK
	AOS FRKDER(FX)		;BUMP THE DATA ERROR COUNT
	RET			;AND RETURN

DCOUNT:				;ROUTINE TO INCREMENT COUNTS
	MOVE T1,FBYTE(FX)	;GET THE FORK BYTE SIZE
	MOVEI T2,1		;ONE BYTE FOR THE DD
	CAIN T1,^D8		;8 BIT BYTES?
	 MOVEI T2,4		;YES SO IT IS FOUR BYTES
	ADD T1,T2		;CORRECT BYTE COUNT FOR THE DD
	IMUL T1,PB		;GET NUMBER OF BITS
	ADDM T1,FRKIO1(FX)	;AND BUMP THE COUNT
	ADDM T1,FRKIO2(FX)	;AND BUMP THE COUNT
	AOS FRKMSG(FX)		;BUMP FORK MESSAGE COUNT
	RET			;RETURN TO CALLER

DLENGT:				;ROUTINE TO LOAD UP L2
	SKIPG T3,LENGTH		;GET CURRENT LENGTH OF MESSAGES
	 JRST [	TIME		;GET SYSTEM UPTIME
		MOVE T3,T1	;GET LENGTH INTO CORRECT PLACE
		ANDI T3,<PGSIZ-1> ;TURN OFF UNWANTED BITS
		JRST .+1]	;AND JOIN FLOW
       	MOVEI T1,^D36		;36 BITS PER WORD
	IDIV T1,FBYTE(FX)	;GET BYTES PER WORD
	IMUL T1,T3		;GET TOTAL NUMBER OF BYTES
	MOVE PB,T1		;BUT BYTE COUNT INTO CORRECT PLACE
	MOVE L2,PB		;LOAD UP LENGTH INTO L2
	MOVE T1,GLOBAL		;GET THE GLOBAL FLAGS
	TXNE T1,G%VERF		;ARE WE VERIFYING?
	 TXO L2,DD%VRF		;YES...TURN ON BIT
	AOS FRKSQC(FX)		;BUMP THE SEQUENCE NUMBER
	MOVE T1,FRKSQC(FX)	;BUMP THE SEQUENCE
	DPB T1,[POINTR L2,DD%SQC] ;DEPOSIT THE SEQUENCE NUMBER
	MOVE T1,PATERW		;GET THE CURRENT PATTERN ADDRESS
	MOVX T2,<-NNNPAT,,PATRTN> ;GET AOBJN POINTER
DLENG2:				;AOBJN LOOP
	HRRZ T3,(T2)		;GET THIS PATTERN ADDRESS
	CAIE T3,(T1)		;IS IT A MATCH?
	AOBJN T2,DLENG2		;NO SO KEEP LOOKING
	HRRZ T2,T2              ;ZERO THE LEFT HALF
	SUBI T2,PATRTN		;GET THE INDEX
	DPB T2,[POINTR L2,DD%PTN] ;DEPOSIT THE PATTERN INTO L2
	RET			;RETURN TO CALLER FOR NOW
	SUBTTL FORK TERMINATION INTERRUPT HANDLER

.FRKIN:
	CALL FRKINT		;GO TO THE WORKER ROUTINE
	DEBRK			;DISMISS THE INTERRUPT

FRKINT:				;WORKER ROUTINE FOR DEAD FORK INTERRUPTS
	SAVACS			;SAVE THE INTERRUPT ACS
	MOVSI FX,-NFKS		;GET AOBJN INDEX FOR FORK SCAN
	SETZ L2,		;RESET COUNT OF FORKS FOUND
FRKIN2:				;FORK SCAN LOOP
	SKIPN FRKERR(FX)	;DOES THIS FORK HAVE AN ERROR?
	 JRST FRKIN3		;NO
	AOJ L2,			;BUMP FOUND ONE FLAG
	CALL NEWLIN		;GET A NEW LINE
	TYPE <?FORK NUMBER >	;OUTPUT MESSAGE TO USER
	HRRZ T2,FX		;GET FORK NUMBER FOR OUTPUT
	NUMO T2,10,0		;OUTPUT FORK NUMBER
	TYPEN < HAS DIED AT PC > ;PROMPT THE ERROR PC
	NUMO FRKEPC(FX),10,0	;OUTPUT ERROR PC
	TYPE <?LAST ERROR WAS >	;PROMPT THE ERROR STRING
	MOVEI T1,.PRIOU		;OUTPUT TO TTY
	MOVE T2,FRKERR(FX)	;GET THE LAST ERROR
	HRLI T2,.FHSLF		;ASSUME THIS FORK
	SETZB T3,T4		;NO SPECIAL LIMITS
	ERSTR			;OUTPUT ERROR STRING
	 NOERR			;IGNORE ERRORS
	 NOERR			;IGNORE ERRORS
	SETZM FRKERR(FX)	;RESET FORK ERROR
	CALL NEWLIN		;GET A NEW LINE
FRKIN3:	AOBJN FX,FRKIN2		;SCAN FOR ALL FORKS
	SKIPN L2		;DID WE OUTPUT ANY ERRORS?
	 RET			;NO SO RETURN
	TYPE <>			;AN EXTRA LINE IF NEEDED
	RET			;RETURN TO CALLER
	SUBTTL NCP FUNCTION TO GET AND OPEN CONNECTIONS

NCPOPN:				;GET AN NCP JFN
	STKVAR <<NETJFB,20>>	;GET SOME TEMPORARY STORAGE
	HRROI T1,NETJFB		;GET THE BUFFER POINTER
	HRROI T2,[ASCIZ/NET:/]	;GET THE DEVICE NAME
	SETZB T3,T4		;NO FANCY LIMITS
	SOUT			;APPEND THE DEVICE NAME
	 JSYSF			;HANDLE ERRORS
	MOVE T2,FSCKTL(FX)	;GET THE LOCAL SOCKET NUMBER
	MOVEI T3,10		;USE OCTAL
	NOUT			;APPEND LOCAL SOCKET NUMBER
	 JSYSF			;HANDLE ERRORS
	MOVEI T2,"V"-100	;GET A CONTROL V
	IDPB T2,T1		;APPEND IT
	HRROI T2,[ASCIZ/#./]	;THIS IS AN ABSOLUTE SOCKET
	SETZB T3,T4		;NO FANCY ERRORS
	SOUT			;APPEND IT
	 JSYSF			;HANDLE ERRORS
	SKIPN T2,FHOSTN		;ARE WE USING A 4N HOST?
	MOVE T2,HOSTN		;NO SO GET OUR HOST NUMBER
	MOVEI T3,10		;USE OCTAL
	NOUT			;APPEND THE HOST NUMBER
	 JSYSF			;HANDLE ERRORS
	MOVEI T2,"-"		;GET A DASH
	IDPB T2,T1		;APPEND IT ALSO
	MOVE T2,FSCKTF(FX)	;GET THE 4N SOCKET
	MOVEI T3,10		;USE OCTAL
	NOUT			;APPEND IT
	 JSYSF			;HANDLE ERRORS
	SETZ T2,		;GET A NULL BYTE
	IDPB T2,T1		;APPEND IT
	MOVX T1,<GJ%SHT>	;GET GTJFN FLAGS
	HRROI T2,NETJFB		;GET THE JFN NAME
	IFE NDEBUG,<GTJFN>	;GET A JFN ON THE SOCKET
	 JSYSF			;ERRORS
	HRRZM T1,FRKJFN(FX)	;SAVE THE JFN
				;NOW OPEN THE JFN
	HRRZS T1		;ZERO LEFT HALF OF THE JFN
	MOVE T2,FBYTE(FX)	;GET THE FORK BYTE SIZE
	LSH T2,^D30		;PUT BYTE SIZE IN CORRECT PLACE
	TXO T2,5B9		;BUFFERED MODE
	SKIPE FRKSEX(FX)       	;RECEIVE CONNECTION?
	 TXOA T2,OF%WR		;NO...SEND
	  TXO T2,OF%RD		;YES...RECEIVE
	IFE NDEBUG,<OPENF>	;GET THE NETWORK CONNECTION
	 JSYSF			;HANDLE ERRORS
	RET			;RETURN TO CALLER
	SUBTTL OTHER NCP FUNCTIONS

NCPGO:				;NCP FUNCTION TO FORCE BUFFERS
	MOVE T1,FRKJFN(FX)	;GET THE SOCKET JFN
	MOVEI T2,.MOSND		;BUFFER SENDING FUNCTIONS
	IFE NDEBUG,<MTOPR>     	;FORCE THIS BUFFER TO BE SENT
	 JSYSF			;HANDLE POSSIBLE ERRORS
	RET			;RETURN TO CALLER

NCPSND:				;NCP FUNCTION TO OUTPUT MESSAGES
	IFE NDEBUG,<SOUT>	;OUTPUT THE WORD
	IFN NDEBUG,<CALL DBGSNZ> ;IF DEBUGING SLOW US DOWN
	 JSYSF			;HANDLE ERRORS
	RET			;RETURN TO CALLER

NCPRCV:				;NCP FUNCTION TO OUTPUT MESSAGES
	IFE NDEBUG,<SIN>	;READ IN A LOT OF BYTES
	IFN NDEBUG,<CALL DBGSNZ> ;IF DEBUGING SLOW US DOWN
	 JSYSF			;HANDLE ERRORS
	RET			;RETURN TO CALLER

NCPCLS:				;NCP FUNCTION TO CLOSE CONNECTIONS
	TXO T1,CZ%ABT		;ABORT ALL IO
	IFE NDEBUG,<CLOSF>	;CLOSE THE CONNECTION
	 JSYSF			;HANDLE ERRORS
	RET			;RETURN TO CALLER
	SUBTTL HELP TEXT

HLPTXT:	ASCIZ\

Command		Subcommand	Description
---------------------------------------------------------------------------
ARPANET		CYCLE		Cycle the ARPANET interface.

ARPANET		INITIALIZE	Load new host tables.

ARPANET		OFF		Disable the interface.

ARPANET		ON		Enable the interface.

ABORT				Will kill all forks and abort current
				run.

CONTINUE			Will continue the current run.  Used
				to continue data transmission after
				a STOP command.

DDT				Transfer control to UDDT if loaded.

DISABLE				Opposite effect of ENABLE.

ENABLE		FOREIGN		Enable communication with a foreign host.

ENABLE		SEQUENCE	Enable the checking of message sequence
				numbers.

ENABLE		VERIFICATION	Enable the verification of data messages.


EXIT				Abort the current run and return to
				EXEC command level.

MDDT				Transfer control to MDDT.

PUSH				Push to an inferior EXEC.

QUIT				Return to exec command level without
				any cleanup.  Continue will continue
				data transmission.

RESET				Issue a RESET JSYS and restart TRAFIC.

RETIME				Reset one of the IO rate counters.

SET		LENGTH		Set length of messages sent in 36 bit
				words.  May also be set to random.

SET		MODE		Set for SEND only, RECEIVE only, or BOTH mode.

SET		NUMBER		Set number of connections for each
				byte size.

SET		PATTERN		Set pattern of data being sent.  Options
				are ones, zeroes, alternating, and
				sequence

SET		SOCKET		Set the initial socket number to use.

SHOW				Show current settings.

START				Start generating network traffic.

STATUS				Generate a status report.

STOP				Stop generating network traffic.  The
				CONTINUE command will resume data
				transmission.

TAKE				Take commands from a command file.

\
	SUBTTL PURE DATA STORAGE

PDLPTR:	IOWD PDLSIZ,PDL		;STACK POINTER

CSBV:				;VIRGIN COMND STAT BLOCK
	CM%RAI!RPARSE		;REPARSE ADDRESS
	.PRIIN,,.PRIOU		;IO DESIGNATORS
	Z			;PROMPT TEXT
	-1,,TXTBUF		;TEXT BUFFER POINTER
	-1,,TXTBUF		;FIRST INPUT TO PARSE POINTER
	EXP TXTSIZ		;SIZE OF TEXT BUFFER
	Z			;COUNT OF UNPARSED CHARACTERS
	-1,,ATMBUF		;ATOM BUFFER POINTER
	EXP ATMSIZ		;ATOM BUFFER SIZE
	EXP GTJFNB		;POINTER TO GTJFN BLOCK
	CSBSIZ==.-CSBV		;SIZE OF COMND STATE BLOCK

PRMPTR:	-1,,[ASCIZ/TRAFIC> /]	;RUNNING PROMPT
PRMPTH:	-1,,[ASCIZ/TRAFIC% /]	;HALTED PROMPT
PRMPTD:	-1,,[ASCIZ/TRAFIC! /]	;NOT RUNNING PROMPT


PATRTN:
	EXP PATERA		;ALTERNATING ONES AND ZEROS
	EXP PATERO		;ALL ONES
	EXP PATERZ		;ALL ZEROES
	EXP PATERN		;SEQUENTIAL PATTERN
	NNNPAT==.-PATRTN        ;NUMBER OF PATTERNS
	SUBTTL LITERALS

LIT...:	   			;THIS IS WHERE LITERALS GO
	XLIST%			;TURN OFF LISTING
	LIT			;DO LITERALS
	LIST%			;TURN LISTING BACK ON
	HGHCOD==.-1		;REMEMBER THE HIGH CODE ADR
	SUBTTL FORK DATA DEFINITIONS

	LOWDAT==1000+<HGHCOD&777000> ;DATA BEGINS ON NEXT PAGE
	LOC LOWDAT

	DEFINE DEFORK(NFKS),<	;;MACRO TO DEFINE ALL FORKS
	FRKIDX==0		;;INITIALIZE THE INDEX
	REPEAT NFKS,<.DEFOR>>	;;LOOP FOR EACH FORK

	DEFINE .DEFOR,<		;;MACRO TO DEFINE A FORK
	XLIST%
	LOC FPOINT+FRKIDX	;;GO TO STACK POINTER AREA
	IOWD FRKSIZ,<FRKPDL+<FRKIDX*FRKSIZ>> ;;DEFINE INITIAL STACK POINTER
	LOC FSCKTL+FRKIDX	;;GO TO LOCAL SOCKET AREA
	SOCKET+FRKIDX		;;DEFINE INITIAL LOCAL SOCKET
	LOC FSCKTF+FRKIDX	;;GO TO FOREIGN SOCKET AREA
	IFN <FRKIDX&1>,<SOCKET+FRKIDX-1> ;;DEFINE 4N SOCKET FOR ODD FORKS
	IFE <FRKIDX&1>,<SOCKET+FRKIDX+1> ;;DEFINE 4N SOCKET FOR EVEN FORKS
	LOC FRKSEX+FRKIDX      	;;GO TO SEND/RECEIVE FLAG AREA
	IFN <FRKIDX&1>,<-1>	;;IF ODD WE ARE A SENDER
	IFE <FRKIDX&1>,<Z>	;;IF EVEN WE ARE A RECEIVER
	LOC FKEND		;;GO TO END OF FORK AREA
	FRKIDX==FRKIDX+1 	;;BUMP THE FORK INDEX
	LIST%>

FPOINT:	BLOCK NFKS		;FORK PDL STACK POINTERS
FSCKTL:	BLOCK NFKS		;LOCAL FORK SOCKETS
FSCKTF:	BLOCK NFKS		;FOREIGN FORK SOCKET
FRKSEX:	BLOCK NFKS		;FORK SEX
	FKEND==.		;END OF FORK AREAS

	DEFORK NFKS		;DEFINE ALL THE FORK DATA
	SUBTTL IMPURE DATA STORAGE

DBUGSW:	Z			;DEBUGING MODE SWITCH
CONCTS:	EXP 0			;NUMBER OF EIGHT BIT CONNECTION
	EXP 0			;NUMBER OF 32 BIT CONNECTIONS
	EXP 1			;NUMBER OF 36 BIT CONNECTIONS

	ZERO1==.		;FIRST LOCATION TO ZERO ON STARTUP
PATERW:	Z			;THE PATTERN ADDRESS
LENGTH:	Z			;THE MESSAGE LENGTH
TAKJFN:	Z			;JFN FOR TAKE FILE
CSB:	BLOCK CSBSIZ		;COMND STATE BLOCK
	CSBJFN=CSB+.CMIOJ	;IO DESIGNATORS FOR CSB
TXTBUF:	BLOCK <TXTSIZ/5>+1	;TEXT BUFFER
ATMBUF:	BLOCK <ATMSIZ/5>+1	;ATOM BUFFER
GTJFNB:	BLOCK .GJATR+1		;GTJFN BLOCK
ERRACS:	BLOCK 20		;ERROR AC BLOCK
ERRPC:	Z			;ERROR PC
PDL:	BLOCK PDLSIZ		;PDL STACK
FHOSTN:	Z			;FOREIGN HOST NUMBER TO USE
HOSTN:	Z			;LOCAL HOST NUMBER
FORKDX:	Z			;AOBJN POINTER
FORKX:	BLOCK NFKS		;FORK HANDLES TABLE
FBYTE:	BLOCK NFKS		;FORK BYTE SIZE TABLE
FRKJFN:	BLOCK NFKS		;FORK JFN TABLE
FRKIO1:	BLOCK NFKS		;FORK BIT TRANSMITTED COUNT
FRKIO2:	BLOCK NFKS		;FORK BIT TRANSMITTED COUNT
FRKMSG:	BLOCK NFKS		;FORK MESSAGE COUNT
FRKSQC:	BLOCK NFKS		;FORK MESSAGE SEQUENCE NUMBER
FRKDER:	BLOCK NFKS		;FORK DATA ERROR COUNT
FRKDDT:	BLOCK NFKS		;FORK DDT FLAGS
FRKERR:	BLOCK NFKS		;FORK LAST ERROR
FRKEPC:	BLOCK NFKS		;FORK ERROR PC
FRKPDL:	BLOCK NFKS*FRKSIZ	;AREA FOR FORK PDL STACKS
PC1:	Z			;INTERRUPT PC STORAGE
PC2:	Z
PC3:	Z
IOTIM1:	Z			;IO TIME START FOR RATE 1
IOTIM2:	Z			;IO TIME START FOR RATE 2
MSGSUM:	Z			;MESSAGE TOTAL
ERRSUM:	Z			;ERROR TOTAL
IOSUM1:	Z			;IO TOTAL RCV FOR RATE 1
IOSUM2:	Z			;IO TOTAL RCV FOR RATE 2
GLOBAL:	Z			;GLOBAL FLAGS
	ZERO2==.-1		;LAST LOCATION TO ZERO ON STARTUP

	HGHDAT==.-1		;HIGH DATA LOCATION
	SUBTTL ASSEMBLY MESSAGES

IFN DEBUG,<IF2 <DEFINE RANGES(LOWCOD,HGHCOD,LOWDAT,HGHDAT,LIT...,PSUM,IPSUM),<
PRINTX
PRINTX TRAFIC - LOWEST PURE ADDRESS            LOWCOD
PRINTX TRAFIC - LITERALS START AT ADDRESS      LIT...
PRINTX TRAFIC - HIGHEST PURE ADDRESS           HGHCOD
PRINTX TRAFIC - LENGTH OF PURE AREA            PSUM
PRINTX
PRINTX TRAFIC - LOWEST IMPURE ADDRESS          LOWDAT
PRINTX TRAFIC - HIGHEST IMPURE ADDRESS         HGHDAT
PRINTX TRAFIC - LENGTH OF IMPURE AREA          IPSUM
PRINTX
>
PSUM==HGHCOD-LOWCOD
IPSUM==HGHDAT-LOWDAT
RANGES \LOWCOD,\HGHCOD,\LOWDAT,\HGHDAT,\LIT...,\PSUM,\IPSUM
>>	;END OF IFN DEBUG

	END <3,,EVEC>		;THATS ALL FOLKS