Google
 

Trailing-Edge - PDP-10 Archives - BB-H138C-BM - galaxy-sources/orion.mac
There are 38 other files named orion.mac in the archive. Click here to see a list.
TITLE	ORION	Main Module for Operator Interface
	SUBTTL	Cliff Romash/Murray Berkowitz 21 Nov 1979

;
;
;
;           COPYRIGHT (c) 1975,1976,1977,1978,1979 BY
;           DIGITAL EQUIPMENT CORPORATION, MAYNARD, MA.
;
;     THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY  BE  USED
;     AND COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE
;     AND WITH THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE.   THIS
;     SOFTWARE  OR ANY OTHER COPIES THEREOF MAY NOT BE PROVIDED OR
;     OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON.  NO  TITLE  TO
;     AND OWNERSHIP OF THE SOFTWARE IS HEREBY TRANSFERRED.
;     
;     THE INFORMATION  IN  THIS  SOFTWARE  IS  SUBJECT  TO  CHANGE
;     WITHOUT  NOTICE  AND SHOULD NOT BE CONSTRUED AS A COMMITMENT
;     BY DIGITAL EQUIPMENT CORPORATION.
;     
;     DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY
;     OF  ITS  SOFTWARE  ON  EQUIPMENT  WHICH  IS  NOT SUPPLIED BY
;     DIGITAL.


	SEARCH GLXMAC,ORNMAC,QSRMAC
	PROLOG(ORION)
	ERRSET			;SETUP ALL ERROR ROUTINES EXTERNAL
	PARSET			;PARSER ROUTINES


	EXTERNAL TABSRC		;TABLE SEARCH
	EXTERNAL ARGRTN		;SETUP ARGUMNET IN MESSAGE
	EXTERNAL BLDOBJ		;BUILD AN OBJECT
	EXTERNAL CMDEND		;FINISH COMMAND AND SEND TO QUASAR
	INTERNAL .JBVER		;AVAILABLE FOR OPRLOG
	INTERNAL CHKWHL		;CHECK FOR WHEEL ROUTINE
	INTERNAL GETJOB		;GET JOB INFO
	INTERNAL SNDAOP		;SEND MESSAGE TO ALL OPRS

	ENTRY	OPRENB		;OPR ENABLED FOR NODE
	EXTERNAL	QSREDT,PAREDT,LOGEDT,ERREDT,NETEDT

	MYEDT==240		;ORION EDIT LEVEL

	ORNWHO==0
	ORNVER==4
	ORNMIN==0
	ORNEDT==MYEDT+PAREDT+QSREDT+ERREDT+LOGEDT+NETEDT
	.JBVER==137

	%%.ORV==<VRSN.(ORN)>
	LOC	.JBVER
	EXP	%%.ORV
	RELOC
	SUBTTL	Table of Contents

;               TABLE OF CONTENTS FOR ORION
;
;
;                        SECTION                                   PAGE
;    1. Table of Contents.........................................   3
;    2. Revision History..........................................   4
;    3. Global Storage............................................   5
;    4. Main Data Storage.........................................   6
;    5. DATA FOR WTO MESSAGES.....................................   7
;    6. Interrupt System Storage Areas............................   8
;    7. GLXLIB INITIALIZATION BLOCK...............................   9
;    8. Entry  Point and Initialization...........................  10
;    9. Main Loop.................................................  11
;   10. SLEEPR  --      SLEEP ROUTINE FOR ORION...................  12
;   11. PROIPC  --      PROCESS IPCF MESSAGE......................  13
;   12. SYSMSG  --      PROCESS SYSTEM MESSAGES...................  14
;   13. ORNINT  --      ORION SETUP ROUTINES......................  15
;   14. MSGCHK  --      CONSISTENCY CHECK THE MESSAGE TO ORION....  16
;   15. OPRHEL  --      HELLO MESSAGE FROM OPR....................  17
;   16. APLHEL  --      APPLICATION HELLO MESSAGE.................  18
;   17. CHKNOD  --      VALIDATE THE OPR NODE DATA................  19
;   18. OPRSET  --      PROCESS SETUP REPLY FROM OPR..............  20
;   19. SNDSET  --      SEND A SETUP TO OPR.......................  21
;   20. TEXT    --      Routine to Process a TEXT Message.........  22
;   21. SPGOUT  --      Setup Output Page to Send.................  23
;   22. W$WTOR  --      Process a WTOR Message....................  24
;   23. W$KWTO  --      KILL A WTOR REQUEST BY CODE...............  25
;   24. W$NODE  --      DETERMINE NODE TO OUTPUT MESSAGE TO.......  25
;   25. W$KMES  --      KILL THE MESSAGE AND NOTIFY OPERATOR......  26
;   26. W$WTO  --      PROCESS A WTO MESSAGE.....................  27
;   27. W$CHEK  --      CHECK IF WTO/WTOR ALLOWED FOR JOB.........  27
;   28. W$LOGM  --      LOG A MESSAGE TO LOG......................  28
;   29. W$VALID  --      Validate WTO, WTOR and ACK Messages.......  29
;   30. WTOTXT, WTOTYP, WTOANS AND WTOACD ROUTINES................  30
;   31. WTOJOB,WTOERR,WTORTE AND WTODES...........................  31
;   32. WTOOBJ  --      PROCESS WTO OBJECT BLOCK..................  32
;   33. WTOOCD  --      OBJECT TYPE BLOCK.........................  33
;   34. W$MTXT  --      GET THE TEXT INTO THE MESSAGE.............  34
;   35. W$CRLF  --      END THE TEXT LINE WITH CRLF...............  35
;   36. W$TAB  --      TAB A LINE IN FOR MESSAGE.................  35
;   37. OPRMES  --      BUILD  A MESSAGE FOR OPR..................  36
;   38. W$MESS  --      SETUP A WTO/WTOR/ACK MESSAGE..............  37
;   39. W$JOBH  --      SETUP A JOB HEADER MESSAGE................  38
;   40. GETJOB  --      GET THE JOB INFORMATION...................  39
;   41. GETUSR  --      GET USER INFO FOR NOTIFY..................  40
;   42. GETNAM  --      GET THE USER NAME.........................  41
;   43. W$SHOW  --      SHOW ACK MESSAGE FROM QUASAR..............  42
;   44. CHKQSR  --      CHECK FOR QUASAR CODE.....................  42
;   45. W$ASND  --      SEND ACK TO OPR...........................  42
;   46. W$ACKM  --      Process an ACK Message....................  43
;   47. TXTMOV  --      Text Move Routine.........................  43
;   48. CMDMES  --      COMMAND MESSAGE PROCESSOR.................  44
;   49. COMMAN  --  Routine to Handle Parser Command Message......  45
;   50. FNDAPL  --      FIND THE APPLICATION......................  46
;   51. Dispatch Table for Command Messages.......................  47
;   52. TAKCMD  --      TAKE COMMAND SETUP ROUTINE................  48
;   53. TAKEND  --      END OF TAKE COMMAND.......................  48
;   54. TAKABT  --      ABORT TAKE COMMAND ROUTINE................  48
;   55. GETPAG  --      GET AN OUTPUT PAGE IN MO..................  49
;   56. RELPAG  --      RETURN OUTPUT PAGE FOR REUSE..............  49
;   57. ENABLE AND DISABEL COMMANDS...............................  50
;   58. ENALOG  --      ENABLE LOG COMMAND........................  51
;   59. ENAOBJ  --      ENABLE OBJECT MESSAGES....................  52
;   60. ENASET  --      SET THE OPERATOR MESSAGES.................  53
;   61. NOTIFY COMMAND............................................  54
;   62. SEND COMMAND..............................................  55
;   63. SENDOP  --      SEND TO OPERATOR COMMAND..................  56
;   64. BLDSND  --      BUILD THE SEND TEXT.......................  57
;   65. SNDALL  --      SEND MESSAGE TO ALL(/NODE)................  58
;   66. SNDTTY  --      SEND A MESSAGE TO A TERMINAL..............  59
;   67. SHOW Command..............................................  60
;   68. SHWOPR  --      SHOW OPERATORS IN SYSTEM..................  61
;   69. SHWMSG  --      SHOW MESSAGES ROUTINE.....................  62
;   70. FINSHW  --      Finish off a SHOW Message.................  63
;   71. MSGNOD  --  Routine to Build Display Blocks for a Node....  64
;   72. BLDDPY  --      BUILD MESSAGE INTO OUTPUT.................  64
;   73. OPRLST  --  Routine to Build Display Blocks for an Operator  65
;   74. OPRDPY  --      Build Operator Info.......................  66
;   75. OPRENB  --      OPERATOR ENABLED FOR NODE.................  67
;   76. GETMSG  --      GET A MESSAGE GIVEN THE NUMBER............  68
;   77. REPORT  --      REPORT SYSTEM ERRORS TO SYSERR............  69
;   78. RESPOND COMMAND...........................................  70
;   79. PRVCHK AND CHKWHL -- Check if Sender Privileged...........  71
;   80. G$ACK   --      SEND ACK TO  SENDER.......................  72
;   81. BLDACK  --      BUILD THE ACK MESSAGE.....................  73
;   82. FNDMSG  --      ROUTINE TO FIND A MESSAGE FOR NODE........  74
;   83. CHKMSG  --      SEARCH NODE FOR A MESSAGE.................  75
;   84. NXTMSG  --      GET NEXT MESSAGE..........................  75
;   85. ADDNOD  --      ROUTINE TO ADD A NODE.....................  76
;   86. LOCNOD  --      LOCATE THE NODE BLOCK.....................  76
;   87. ADDOPR  --      ADD OPR TO DATA BASE AND NODE LIST........  77
;   88. EXPTAB  --      EXPAND OPR TABLE ROUTINE..................  78
;   89. VALOPR  --      VALIDATE THE OPR FOR ORION................  79
;   90. DELOPR  --      DELETE OPR ENTRY AND TABLE DATA...........  80
;   91. SNDLST  --      SEND UNSENT MESSAGES TO OPR/OBJECT........  81
;   92. RSDPID  --      RESEND MESSAGES TO A PARTICULAR PID.......  82
;   93. MOVARG  --      SETUP ARGUMENT IN OUTPUT MESSAGE..........  83
;   94. SNDAOP  --      SEND TO ALL OPRS A MESSAGE................  84
;   95. SNDOPR  --      SEND TO ALL OPRS..........................  85
;   96. CHKOSD  --      CHECK MESSAGE FLAGS FOR OPR...............  86
;   97. MOVBLK  --      MOVE A GALAXY BLOCK ROUTINE...............  87
;   98. REQMSG  --      REQUEUE THE MESSAGE FOR RESENDING.........  88
;   99. RSDMSG  --      RESEND MESSAGE ROUTINE....................  89
;  100. REQNST  --      REQUEUE MESSAGES NOT SENT.................  90
;  101. ADDSFL  --      ADD SEND FAILURE TO TABLE.................  91
;  102. DELSFL  --      DELETE SEND FAILURE ENTRY.................  92
;  103. CHKSFL  --      CHECK SEND FAILURE ENTRIES................  92
;  104. CLRSFL  --      CLEAR SEND FAILURE LIST...................  93
;  105. SNDQSR  --      ROUTINE TO SEND MESSAGE TO QUASAR.........  94
;  106. SNDMSG  --      SEND A MESSAGE TO A PID...................  94
;  107. SPDOPR  --      SEND MESSAGE TO AN OPR....................  95
;  108. SNDPID  --      SEND MESSAGE TO ANY PID( NOT OPR).........  96
;  109. Interrupt Handler.........................................  97
;  110. Default PDBs for OPRCMD...................................  98
;  111. SETOUT  --      SETUP OUTPUT OF DATA......................  99
;  112. SNDOUT  --      OUTPUT ROUTINES FOR DN60..................  99
;  113. OUTRTN  --      OUTPUT ROUTINE FOR LINKS..................  99
;  114. SETPTR  --      SETUP POINTERS FOR OUTPUT.................  99

COMMENT \

THIS MODULE IS THE MAIN LOOP FOR ORION. IT RECEIVES ALL IPCF MESSAGES
AND DISPATCHES TO THE CORRECT PROCESSING ROUTINE. IT ALSO CONTAINS
ALL THE CODE TO INITIALIZE THE NEEDED GLX MODULES.

\
SUBTTL	Revision History

COMMENT \

Edit	Module	When		Change

1	ORION	31-May-77	First Development version on SYS (TOPS20)

2	ORION	1-Jun-77	Change to sparse dispatch table.
				Clean up ENABLE command.

3	ORION	1-Jun-77	Add support for WTO message for simple
				display only.

4	ORION	2-Jun-77	Provide primitive linked list facility
				to queue messages received for display.

5	ORION	6-Jun-77	Change to use OTS library.

6	ORION	9-Jun-77	Implement RESPOND command.

7	ORION	10-Jun-77	Implement ALIGN command.

10	ORION	10-Jun-77	Implement CANCEL command.

11	ORION	13-Jun-77	Add code to send SET commands to
				NETCON (for now).

12	ORION	14-Jun-77	Implement REQUEUE command.

13	ORION	14-Jun-77	Change to use saved contents on .CMNUM and .CMNUX
				as pointer, not number

14	ORION	14-Jun-77	Implement /JOBNAME and /SEQUENCE switches
				on CANCEL and REQUEUE commands.

15	ORION	15-Jun-77	Implement SET command for GALAXY
				components.

16	ORION	20-Jun-77	Clean up AC usage.

17	ORION	23-Jun-77	Use Software Interrupts so we can use sleeps to
				do timing.
20	ORION	24-Jun-77	Clean up WTO and Display code. Add routines
				to build DISPLAY message and to send to all
				OPR's on a node.
				Use GALAXY wide TEXT message instead of
				ACKNOWLEDGEMENT message
21	ORION	27-Jun-77	Fix build-a-display routine.

22	ORION	28-Jun-77	Remove internal list structure symbols
				to ORNMAC where they belong.

23	ORION	29-Jun-77	Implement Acknowledgement scheme for commands
				so as to get errors to the operator that typed
				the command.
24	ORION	6-Jul-77	Implement the SHOW command for status and 
				parameters
25	ORION	8-Jul-77	Add privilege checking.

26	ORION	26-Aug-77	Reorganize main loop to make errors work
				Also, throw away messages from [SYSTEM]INFO

27	ORION	20-Sep-77	Make this version 2. Note that this edit is
				not in chronological order due to parallel
				development.

30	ORION	21-Jul-77	Add TOPS10 interrupt system

31	ORION	18-Aug-77	Make BLDOBJ store high part of range correctly

32	ORION	19-Aug-77	Remove IFC stopcode and make it an error

33	ORION	19-Aug-77	Make CANCEL and REQUEUE commands
				not allow ranges.

34	ORION	22-Aug-77	Ensure that high part of range is greater
				than low part

35	ORION	23-Aug-77	Clean up SET command--add ranges, other parameters

36	ORION	20-Sep-77	Fix bug in SET command dispatch--caused
				?Illegal uuo

37	ORION	23-Sep-77	Add SUPPRESS command

40	ORION	26-Sep-77	Change all string store code to use one common routine

41	ORION	13-Oct-77	Add HOLD and RELEASE commands

42	ORION	13-Oct-77	Fix bugs in SUPPRESS and SET commands.

43	ORION	20-Oct-77	Add SET TERMINAL NODE and SET TERMINAL
				MESSAGES commands to add an operator to
				the node list.

44	ORION	21-Oct-77	Add SEND BATCH-STREAM and EXAMINE
				commands

45	ORION	2-Nov-77	Add new WTO/WTOR scheme.

46	ORION	8-Nov-77	Add OPD.FL word to OPERATOR DISPLAY message
				and flag that a response was requested.

47	ORION	11-Nov-77	Change BLDDPY to build new format Operator
				Display message. Also, only sequence messages
				that get queued up.

50	ORION	13-Nov-77	Add code for SHOW MESSAGES commands

51	ORION	14-Nov-77	Change WTOPER to never queue up WTO's

52	ORION	16-Nov-77	Change messages with no node to go to
				central site

53	ORION	18-Nov-77	Add DISCARD command to throw away an
				outstanding message

54	ORION	18-Nov-77	Allow a WTO to be an valid ack

55	ORION	23-Nov-77	Change the format of SHOW STATUS and SHOW PARAMETERS

56	ORION	5-Dec-77	Change format of the Ack list to accomodate
				multiple SHOW STATUS etc. messages.

57	ORION	6-Dec-77	Change to use symbols for command message

60	ORION	7-Dec-77	Fix up PRVCHK for the -10

61	ORION	15-Dec-77	Fix bug in SHWLOP to make SHOW STATUS/PARAMETERS
				work.

62	ORION	15-Dec-77	Add ROUTE command

63	ORION	17-Jan-78	Add symbols for CARD-PUNCH,PLOTTER
				and PAPER-TAPE PUNCH

64	ORION	9-May-78	Add new command messages and WTO

65	ORION	16-May-78	Add new WTO message and validation

66	ORION	19-May-78	Fix the Respond Command

67	ORION	23-May-78	Fix Log File Symbols

70	ORION	24-May-78	Update -20 Privilege check and FORWARDSPACE/
				BACKSPACE

71	ORION	2-Jun-78	Remove G$ACKL and ACK code. Also fix
				SET command

72	ORION	5-Jun-78	Convert ALIGN, SUPPRESS and SHOW CONTROL
				FILE to new messages

73	ORION	8-Jun-78	Create OPRLOG for LOGGING ORION Messages

74	ORION	9-Jun-78	New WTO formats and WTO logging

75	ORION	15-Jun-78	ADD new Show Messages

76	ORION	12-July-78	Add Send and Route Commands

77	ORION	15-July-78	Remove .REQUIRE Statements

100	ORION	17-July-78	Add Hold and Release code as well as new
				DEVICE option for START Command
101	ORION	18-July-78	Add Portion of Enable for Output-display
				setting
102	ORION	3-Aug-78	Add Set Job command and fix GETPAG and 
				RELPAG to cover more than one page.
103	ORION	4-Aug-78	Change ROUTE command to send one block
				on the ROUTE Node command
104	ORION	4-Aug-78	Add SHOW Route Command Message and SET
				JOB_PRIORITY Command Message
105	ORION	16-Aug-78	Add NCP support
106	ORION	21-AUG-78	FIX NEED APLHEL CODE AND CHANGE FINPAG TO RELPAG
				AND OUTPAG TO GETPAG
107	ORION	28-Aug-78	Add the REPORT command
110	ORION	31-Aug-78	Add SHOW ACK for QUASAR SHOW MESSAGES
111	ORION	5-Sept-78	Fix SIXBIT conversion to make sure in
				Upper case
112	ORION	11-Sept-78	BEGIN TO SETUP FOR MODULE OPRQSR
113	ORION	17-SEPT-78	CREATE ORNERR FOR ALL ORION ERRORS
114	ORION	20-Sept-78	Add WTOMAX symbol to check maximum allowable
				wto message size
115	ORION	29-Sept-78	Make the P$KEYW,etc. routines part of 
				OPRPAR as P$KEYW,etc.
116	ORION	4-Oct-78	Add Resend Logic for IPCF Failures
117	ORION	18-Oct-78	Add -20 Node Jsys for getting Central site node
120	ORION	23-Oct-78	Add New TABAPL Macro for Application Table Names
121	ORION	23-Oct-78	Add NXTMSG Routine and Update FNDMSG and CHKMSG
				Also add WT.KIL for Deleting a WTOR Message
122	ORION	24-Oct-78	Have Commands that come from Invalid OPR return
				Error Message
123	ORION	30-Oct-78	Add -20 Tape and Disk Command Support
124	ORION	3-Nov_78	Add Application code Block for WTO messages 
				.WTACD AND SHOW STATUS AND PARAMETERS CODE
125	ORION	3-Nov-78	Add Code for Show Status and Show Parameter
				messages
				Also Move SHWSTS,SHWPRM,SHWQUE,SHWCTL,SHWRTE TO
				OPRQSR AS Q$SHWQ,Q$SHWS,Q$SHWP,Q$SHWC,Q$SHWR
126	ORION	7-Nov-78	Add Code for Monitor Logout Messages
127	ORION	9-Nov-78	Add I%HOST Code to get Central Site from library
130	ORION	10-Nov-78	Add Notify Command
131	ORION	15-Nov-78	Fix WTOR so WDAJOB is saved for Job
132	ORION	28-Nov-78	Add RECOGNIZE Command for -10 and UNLOAD
				Command for -20. Also make DISMOUNT -20
				only for Disk Structures
133	ORION	29-Nov-78	Add I%JINF code to GETJOB and allow .WTTYP
				without privileges
134	ORION	30-Nov-78	Add DELETE command and fixup REQUEST number
135	ORION	1-Dec-78	Add MODIFY Code and QUEUE-CREATE ENABLE/DISABLE
				for JOBNAME AND SEQUENCE number
136	ORION	1-Dec-78	Add SEND ALL CODE although still need -10
				Monitor Work
137	ORION	4-Dec-78	Add Verification for Remote Nodes and not allow
				Batch Control
140	ORION	7-Dec-78	Fix ENABLE QUEUE to have to be WHEEL or OPERATOR
141	ORION	8-Dec-78	Add New Batch Field Code for -20
142	ORION	14-Dec-78	Fix W$WTO Bug for Lines with no Blanks that
				exceed line length
143	ORION	15-Dec-78	Add DN200 OPR/ORION support
144	ORION	20-Dec-78	Resolve Privileges for DN200 OPR
145	ORION	21-Dec-78	Fix ORION for DN200..need two channels per 
				process
146	ORION	26-Dec-78	Modify Setup Message to accept Text as second
				Block
147	ORION	5-Jan-79	Change KEYTAB Macro to ORNDSP to be compatible
				with new PARUNV
150	ORION	8-Jan-79	Change to use new GLXLIB with PIBBLK for pids
151	ORION	9-Jan-79	Fix SHOW MESSAGE /NODE:
152	ORION	10-Jan-79	Fix Remote OPR check for the -20. OPR now has
				Remote Operator Flag Set in  Message
153	ORION	10-Jan-79	Add SEND OPR /NODE:
				USE NODE NAME FOR -10 IN G$CNTL
154	ORION	11-Jan-79	G$NODE for the Node Location info on the -20
155	ORION	15-Jan-79	Add SHOW OPERATORS Command
156	ORION	15-Jan-79	Add Timer to do Checkpoints for Log
157	ORION	18-Jan-79	Change MT.TXT message to use .CMTXT instead of
				.WTTXT
160	ORION	19-Jan-79	Add New Enable Code
161	ORION	23-Jan-79	Finish ENABLE Commands and add ACK for SENDS
162	ORION	26-JAN-79	MAKE ENABLE LOG PRIVILEDGED AND SEND TO ALL
				OPERATOR CHANGE IN LOGGING STATE
163	ORION	26-JAN-79	HAVE GETJOB SAVE JOB NUMBER IN JOBNUM
164	ORION	30-JAN-79	MODIFY CHKNOD TO WORK FOR NON-NETWORK SYSTEMS
165	ORION	1-Feb-79	Fix CHKMSG to Verify correct PID on W$KWTO
				before returning. This eliminates positioning
				problems
166	ORION	2-FEB-79	ADD BELLS TO SEND AND SEND ALL
167	ORION	6-FEB-79	ADD DN60 SUPPORT
170	ORION	6-FEB-79	ADD ARCHEIVE NOTIFY FOR THE -20
171	ORION	21-FEB-79	Do not create SERVER links when Debugging
				although a call to N$INIT can be used to
				get debugging links
172	ORION	21-FEB-79	RELEASE PAGE ON ACKS WHERE OPR NOT VALID
173	ORION	27-Feb-79	Add Take abort code and bells to WTOR messages
174	ORION	7-Mar-79	Modify ENABLE support code
175	ORION	11-Mar-79	Add Code to Set up Job location to Host name
				if running under Job 0 on the -20
176	ORION	11-Mar-79	Add IB.FLG (IP.STP ) to get ORION Crashes
177	ORION	13-Mar-79	Restrict Remote Show Messages to just that Node
200	ORION	19-Mar-79	Remove $STOP for Large WTO message. Just
				Truncate
201	ORION	23-Mar-79	Add Screening of Mount Messages and IBM Messages
				with the .WTOCD block in the WTO message
202	ORION	26-Mar-79	Add IDENTIFY Command for Tapes
203	ORION	27-Mar-79	Fix SEND ALL bug
204	ORION	2-April-79	Add DN60 Internal Command Parsing Support
				Also send Packets where possible
205	ORION	10-April-79	Check for OPRs that have logged out on Monitor
				Logout Messages
206	ORION	12-April-79	Add SWITCH Command for the -20
207	ORION	18-April-79	Fix Send Command
210	ORION	24-Apr-79	Pass Node Name for Dn60 Instead of Port and Line
				in the Output Display Messages
211	ORION	2-May-79	Remove Debug Check from Wheel Check.
				Fix Report Bug
212	ORION	14-May-79	Send WTOR replies to the terminal if WT.NFY is 
				on in WTOR and the Send fails from PID going 
				away.
213	ORION	16-May-79	Change FNDNOD and remove G$DN60
214	ORION	17-May-79	Add G$ASND to force messages to OPR on SEND 
				OPERATOR and ENA/DIS Logging
215	ORION	18-May-79	Fix SEND ACK bug of not releasing Output page 
				on ack code of zero error.
216	ORION	21-May-79	Correct Privilege checking of OPRHEL message
				USE P2,P3 IN RSDMSG INSTEAD OF T1,T2
217	ORION	22-May-79	Have EXPTAB Update OPR data base with new
				table addresses
				Add DELNOD code and .QONWA for deleting an
				OPR if Node goes away
220	ORION	30-May-79	Support the Wait action routine in OPRPAR
				Change the BLDSND format
221	ORION	1-Jun-79	Have DELNOD only delete Oprs for DN60 Nodes
222	ORION	4-Jun-79	Change the W$CHEK routine to bypass wheels and
				to be called before messages are built
223	ORION	12-Jun-79	Remove the use of PB as a parser AC or P$ 
				routine requirement.
224	ORION	14-Jun-79	On WTO/WTOR/ACK check for .OTMNT format 
				of the Object Block
225	ORION	2-Jul-79	Add ENABLE/DISABLE FILE-RETREVIAL WAITS
226	ORION	9-Jul-79	Remove the MOUNT command
227	ORION	11-Jul-79	Remove the Unload command and add new form of
				DISMOUNT
230	ORION	13-Aug-79	Support WT.KAL for user to cancel all messages
				for a Job
231	ORION	14-Aug-79	Add DN60 Node Online and Offline support
232	ORION	20-Aug-79	Correct Ack bug on killed WTO messages
233	ORION	11-Sept-79	Create ERRALL routine to send error messsages
				to all Operators
234	ORION	12-Sept-79	Add  word to .ACKID block to RESPOND message to 
				contain terminal number or SIXBIT node name
				indicating where message came from
235	ORION	13-Sept-79	Trap returned IPCF messages and check for OPR's
				to delete
236	ORION	8-Oct-79	Add -10 MDA commands

237	ORION	21-Nov-79	Remove .REQUEST ARMAIL.  ARMAIL should be
				explicitly specified to LINK.
240	ORION	21-Nov-79	Increase PDL size to accomodate HELP for DN60
				opr.
\
	SUBTTL	Global Storage
G$STAD:				;START OF ORIONS DATA BASE
G$ERR::	BLOCK	1			;ERROR CODE FOR ACK'ING THIS MESSAGE

G$SEQ:: BLOCK	1			;GLOBAL SEQUENCE NUMBER FOR
					;OPR DISPLAYS.

G$SND::	BLOCK	1			;SENDER'S PID

G$PRVS:: BLOCK	1			;SENDER'S PRIVS

G$SID:: BLOCK	1			;SENDER'S ID

G$NODL:: BLOCK	1			;NODE LIST NUMBER

G$CNTL:: BLOCK	1			;NODE NUMBER OF CENTRAL SITE

G$NOW::  BLOCK	1			;CURRENT TIME OF DAY

G$CHKP:: BLOCK	1			;TIME FOR NEXT CHECKPOINT

G$FLAG:: BLOCK	1			;.MSFLG FROM IPCF MESSAGE

G$OPRA:: BLOCK	1			;OPR ADDRESS ORIGINATING REQUEST

G$ASND:: BLOCK	1			;FLAG TO FORCE SENDS OF MESSAGE

G$JDAT:: BLOCK	1			;BATCH-STREAM..WTO BITS

G$OUTP:: BLOCK	1			;OUTPUT MESSAGE PAGE FLAG

G$ARG1:: BLOCK	1			;ERROR ARGUMENT 1

G$ARG2:: BLOCK	1			;ERROR ARGUMENT 2

G$ARG3:: BLOCK	1			;ERROR ARGUMENT 3

G$SNDF:: BLOCK	1			;COUNT OF SEND FAILURES

G$RSDL:: BLOCK	1			;LIST NUMBER FOR RESEND ENTRIES

G$NSNT:: BLOCK	1			;COUNT OF MESSAGES NOT SENT YET

G$SNDL:: BLOCK	1			;LIST FOR MESSAGES NOT SENT YET

G$RSDC:: BLOCK	1			;NUMBER OF MESSAGES TO RESEND COUNT

G$MSGC:: BLOCK	1			;NUMBER OF THE MESSAGE BEING PROCESSED

G$SFPD:: BLOCK	1			;SEND FAILURE PID

G$MJOB:: BLOCK	1			;ORIONS JOB NUMBER

G$MAXP:: BLOCK	1			;MAXIMUM PACKET SIZE

IFN	FTJSYS,<
G$NETL:: BLOCK	1			;NETWORK SERVER LIST

G$NODE:: BLOCK	2			;SPACE FOR NODE STRING ON THE -20

>;END FTJYS
	SUBTTL	Main Data Storage



	;TEMPORARY STORAGE FOR TEXT MOVER
TXTPTR:	BLOCK	1			;SAVE AREA FOR BYTE POINTER

PARBLK:	BLOCK	PAR.SZ			;PARSER CALL BLOCK
PARBUF:	BLOCK	1			;PARSER BUFFER POINTER
SNDBLK:	BLOCK	SAB.SZ			;SEND BLOCK FOR MESSAGES
SNDPTR:	BLOCK	1			;SEND ROUTINE POINTER
TABADR:	BLOCK	1			;OPR DATA BASE ADDRESS
TABFRE:	BLOCK	1			;OPR DATA BASE FREE COUNT
TABCNT:	BLOCK	1			;OPR DATA BASE AVAILABLE COUNT

;BYTE POINTER FOR COMMON TEXT STORAGE ROUTINE
STRBP:	BLOCK	1			;BYTE POINTER WORD

IFN FTUUOS,<
;PLACE FOR OPERATORS PPN
FFAPPN:	BLOCK	1			;OPR PPN ON -10
>   ;END IFN FTUUOS
	SUBTTL	DATA FOR WTO MESSAGES

WDATXT:	BLOCK	1			;WTO TEXT DATA ADDRESS
WDAOBJ:	BLOCK	1			;WTO OBJECT BLOCK ADDRESS
WDADES:	BLOCK	1			;WTO DESTINATION VALUE
WDAJOB: BLOCK	1			;WTO JOB NUMBER
WDAERR:	BLOCK	1			;WTO ERROR CODE
WDARTE:	BLOCK	1			;WTO ROUTE CODE
WDATYP:	BLOCK	1			;WTO TYPE CODE
WDAANS:	BLOCK	1			;WTO ANSWER BLOCK
WDAFLG:	BLOCK	1			;WTO FLAG WORD
WDAAFL:	BLOCK	1			;APPLICATION FLAG
WDAACD:	BLOCK	1			;WTO APPLICATION CODE BLOCK
WDAEND==.-1				;END OF WTO FIELDS

WTOCNT:	BLOCK	1			;COUNT OF OUTPUT BYTES IN MESSAG
WTOPTR:	BLOCK	1			;OUTPUT BYTE POINTER
SRCPTR:	BLOCK	1			;SOURCE POINTER
DESPTR:	BLOCK	1			;DESTINATION POINTER
DESCNT:	BLOCK	1			;DESTINATION COUNT
RSDCNT:	BLOCK	1			;RESEND COUNT OF OPRS TO SEND TO
MSGCNT:	BLOCK	1			;COUNT OF OPRS RECIEVING THIS MESSAGE
OPRRCT:	BLOCK	1			;COUNT OF ENTRIES IN RESEND LIST
OPRRSL:	BLOCK	1			;OPR RESEND LIST NUMBER
PAGFLG:	BLOCK	1			;PAGE MESSAGE TO BE SENT
NOALTN:	BLOCK	1			;NO ALTERNATE NODES ON SEND FLAG
SCRWRD:	BLOCK	1			;SCRATCH WORD FOR EACH COMMAND

	;JOB RELATED DATA FOR LOG AND DISPLAY

JOBNUM:: BLOCK	1			;JOB NUMBER
JOBTTY:: BLOCK	1			;JOB TERMINAL NUMBER
JOBUSN:: BLOCK	2			;JOB USER NAME
JOBNAM:: BLOCK	1			;JOB PROGRAM NAME
JOBJLT:: BLOCK	1			;JOB LOGGED IN TIME
JOBID:: BLOCK	1			;JOB NUMBER OR PPN

JOBTER:: BLOCK	1			;ITEXT ADDRESS FOR TERMINAL DATA
JOBTXT:: BLOCK	1			;ITEXT FOR JOB HEADER LINE

SFLADR:	BLOCK	1			;ADDRESS OF SEND FAIL PIDS TABLE
SFLCNT:	BLOCK	1			;NUMBER OF POSSIBLE ENTRIES IN TABLE
SFLFRE:	BLOCK	1			;NUMBER OF FREE ENTRIES

	;NSP DATA FOR LINKS

IFN	FTJSYS,<
TRMFRK:: BLOCK	1			;FORK TERMINATION FLAG
NSPCON:: BLOCK	1			;CONNECT INTERRUPT FLAG -1..CONNECT
NSPACT:: BLOCK	1			;FLAG FOR NSP SETUP -1..ACTIVE
NODNAM:: BLOCK	2			;NODE NAME FOR CURRENT CONNECT
SRVDAT:: BLOCK	2			;STORAGE FOR SERVER DATA CHECK
SRVTBL:: BLOCK	SRV.SZ*NUMSRV		;ALLOCATE TABLE SPACE
SRVACS:: BLOCK	20			;BLOCK FOR THE ACS
NFYDIR:	BLOCK	1			;NOTIFY DIRECTORY BLOCK
NFYSUB:	BLOCK	1			;SUBJECT POINTER
NFYTXT:	BLOCK	1			;TEXT POINTER

SCHBLK:	BLOCK	10			;SCHEDULER DATA WORDS
>;END FTJSYS


DATASZ==.-G$STAD			;SIZE OF THE DATA BASE

PDLSIZ==^D400				;PUSH DOWN LIST SIZE
PDL:	BLOCK	PDLSIZ			;PUSH DOWN LIST
FNDXCT:	CAMN	P1,MSL.ID(S2)		;MATCH INSTRUCTION
NULTXT::	ITEXT	(<>)
		SUBTTL	Interrupt System Storage Areas

;STORAGE FOR SOFTWARE INTERRUPT SYSTEM

IFN FTJSYS,<

LEVTAB:: EXP	LEV1PC
	EXP	LEV2PC
	EXP	LEV3PC

LEV1PC:	BLOCK	1
LEV2PC:	BLOCK	1
LEV3PC:	BLOCK	1
	
	DEFINE	CHNBLD(AA,BB),<
	XWD	IPCLEV,N$INI'AA##
	XWD	IPCLEV,N$INI'BB##
	>;END CHNBLD

CHNTAB:: BLOCK	1
	XWD	IPCLEV,INT
	BLOCK	CHNSRV-2
	ZZ==0
	YY==1
	REPEAT NUMSRV,<CHNBLD(\ZZ,\YY)
	ZZ==ZZ+2
	YY=ZZ+1>
	BLOCK	^D36-<CHNSRV+<2*NUMSRV>>	;EDIT 145

>	;END INF FTJSYS

IFN FTUUOS,<
INTVEC:
IPCINT:	$BUILD	.PSVIS+1
	$SET(.PSVNP,,INT)
	$EOB
>	;END IFN FTUUOS
	SUBTTL	GLXLIB INITIALIZATION BLOCK

IPBBLK:	$BUILD	IB.SZ
	$SET(IB.FLG,IP.STP,1)		;SET FOR STOPCODES TO CATCH ANY CRASHES
	$SET(IB.PRG,,%%.MOD)		;PROGRAM NAME
IFN	FTDN60,<
	$SET(IB.OUT,,OUTRTN)		;NO DEFAULT SETUP
>;END FTDN60
IFE	FTDN60,<
	$SET(IB.OUT,,.RETT)		;NULL OUTPUT ROUTINE
>;END FTDN60
IFN FTJSYS,<
	$SET(IB.INT,,<LEVTAB,,CHNTAB>)
> ;END IFN FTJSYS
IFN FTUUOS,<
	$SET(IB.INT,,INTVEC)
> ;END FTUUOS
	$SET(IB.PIB,,PIBBLK)		;ADDRESS OF PID BLOCK
	$EOB

IFN	FTUUOS,<
PIBBLK:	$BUILD	PB.MNS			;SIZE OF PID BLOCK
	$SET(PB.HDR,PB.LEN,PB.MNS)	;BLOCK LENGTH
>;END FTUUOS
IFN	FTJSYS,<
PIBBLK:	$BUILD	PB.MXS			;SIZE OF BLOCK
	$SET(PB.HDR,PB.LEN,PB.MXS)	;MAXIMUM SIZE OF BLOCK
>;END FTUUOS
	$SET(PB.SYS,IP.MNP,^D10)	;ALLOW FOR 10. PIDS
	$SET(PB.SYS,IP.BQT,-1)		;SEND AND RECEIVE TO MAX.
	$SET(PB.FLG,IP.RSE,1)		;RETURN ON SEND ERRORS
	$SET(PB.FLG,IP.PSI,1)		;CONNECT PID TO PSI
	$SET(PB.FLG,IP.SPB,1)		;SET IF IPCF SENDER WAS PRIVILEGED
	$SET(PB.FLG,IP.JWP,1)		;GET JOB WIDE PID
	$SET(PB.INT,IP.SPI,SP.OPR)	;SYSTEM ORION
IFN	FTJSYS,<
	$SET(PB.INT,IP.CHN,1)		;CHANNEL FOR IPCF
	$SET(PB.LOC,,<-1,,G$NODE>)	;SPACE FOR LOCATION STRING
>;END FTJSYS
IFN	FTUUOS,<
	$SET(PB.INT,IP.CHN,<IPCINT-INTVEC>) ;OFFSET FOR IPCF BLOCK
>;END FTUUOS
	$EOB


	;DEFINE THE OBJECT BLOCK

	DEFINE	X(A,B),<$SET(.OT'B,,.ZZ)
		.ZZ==.ZZ+1>

OBJBLK:	$BUILD	.OTMAX+1		;MAXIMUM NUMBER OF OBJECTS
	.ZZ==1				;SETUP ENTRIES
	OBJORN				;EXPAND ENTRIES
	$EOB				;END OF BLOCK
SUBTTL	Entry  Point and Initialization

ORION:	RESET				;RESET THE WORLD
	MOVE	P,[-PDLSIZ,,PDL]	;SET UP A PUSHDOWN POINTER
	MOVX	S1,IB.SZ		;GET THE SIZE OF THE IPB
	MOVEI	S2,IPBBLK		;GET ADDRESS OF THE IPB
	PUSHJ	P,I%INIT##		;INITIALIZE THE IPCF INTERFACE
	MOVEI	S1,DATASZ		;SIZE OF THE DATA BASE
	MOVEI	S2,G$STAD		;START OF DATA BASE
	PUSHJ	P,.ZCHNK		;ZERO THE DATA BASE
	PUSHJ	P,I%NOW			;GO GET THE DATE/TIME
	MOVEM	S1,G$NOW		;SAVE AS THE CURRENT TIME
	SETZM	G$SEQ			;CLEAR GLOBAL SEQUENCE NUMBER
	PUSHJ	P,L%CLST		;CREATE NODE LIST
	MOVEM	S1,G$NODL		;SAVE THE NUMBER
	PUSHJ	P,L%CLST		;CREATE A LIST
	MOVEM	S1,G$RSDL		;SAVE AS RESEND LIST
	PUSHJ	P,L%CLST		;CREATE A LIST
	MOVEM	S1,G$SNDL		;SAVE AS UNSENT LIST
	PUSHJ	P,L$INIT##		;INIT LOG ROUTINE
	SKIPE	LOGINT##		;LOGGING ENABLED?
	PUSHJ	P,L$OPNL##		;OPEN ORIONS LOG FILE
	PUSHJ	P,EXPTAB		;SETUP OPR TABLE AND OPR RESEND TABLE
	PUSHJ	P,I%ION			;LIBRARY TURN ON INTERRUPTS
	PUSHJ	P,ORNINT		;SETUP ORION NEEDED DATA
	JRST	MAIN			;NOW GO ENTER MAIN LOOP
SUBTTL	Main Loop

;THIS ROUTINE RECEIVES THE NEXT IPCF MESSAGE FROM THE QUEUE WHEN IT IS
;AVAILABLE, CHECKS ITS FORMAT, AND DISPATCHS ON ITS TYPE

MAIN:	PUSHJ	P,C%RECV		;WAIT FOR MESSAGE
	JUMPT	MAIN.1			;IF A MESSAGE, PROCESS IT
IFN	FTJSYS,<
	SKIPE	NSPCON			;DID WE GET A CONNECT
	PUSHJ	P,N$CONN##		;PROCESS THE CONNECT
	SKIPE	TRMFRK			;FORK TERMINATIONS?
	PUSHJ	P,N$TERM##		;TERMINATE FORK AND LINKS
>;END FTJSYS
	PUSHJ	P,SLEEPR		;GO TO SLEEP ROUTINE
	JRST 	MAIN			;GO TO MAIN
MAIN.1:	MOVE	P1,S1			;COPY MDB ADDR TO P1
	LOAD	S1,MDB.FG(P1),IP.CFC	;GET SYSTEM SENDER WORD
	JUMPN	S1,SYSMSG		;IGNORE MESSAGES FROM IPCC OR INFO
	LOAD	S1,MDB.FG(P1),IP.CFM	;LOOK AT PACKET HEADER
	CAXN	S1,.IPCFN		;IS IS A RETURNED MESSAGE?
	JRST	MAIN.3			;CHECK FOR OPR AND THEN PITCH
	PUSHJ	P,PROIPC		;CALL DISPATCH AND CHECKING AS SUBROUTINE
	MOVE	S1,.MSFLG(MI)		;GET MESSAGE FLAGS
	MOVEM	S1,G$FLAG		;SAVE THE MESSAGE FLAGS
	SKIPE	G$ERR			;WAS THERE AN ERROR
	PUSHJ	P,L$ERR##		;LOG THE ERROR
	LOAD	S1,G$FLAG,MF.ACK	;ACK REQUESTED?
	SKIPN	G$ERR			;ALWAYS SEND ACK ON ERROR
	SKIPE	S1			;SKIP IF NOT
	PUSHJ	P,G$ACK			;ACKNOWLEDGE THE MESSAGE
MAIN.2:	PUSHJ	P,C%REL			;RELEASE THE MESSAGE
	JRST	MAIN			;AND LOOK FOR MORE MESSAGES
MAIN.3:	MOVE	S1,MDB.SP(P1)		;GET THE SENDERS PID
	PUSHJ	P,VALOPR		;CHECK IS IT WAS AN OPR
	JUMPF	MAIN.2			;RELEASE IT AND CONTINUE ON
	MOVE	S1,MDB.SP(P1)		;GET THE SENDERS PID
	PUSHJ	P,DELOPR		;DELETE THE OPR
	JRST	MAIN.2			;CONTINUE ON
	SUBTTL	SLEEPR	--	SLEEP ROUTINE FOR ORION

	;THIS ROUTINE WILL SLEEP FOR THE DESIRED TIME

SLEEPR:	PUSHJ	P,RSDMSG		;RESEND ALL MESSAGES
	MOVEI	S1,0			;CLEAR S1
	SKIPE	G$RSDC			;ANY MESSAGES TO RESEND
	MOVEI	S1,15			;YES..SLEEP 15 SECONDS
	SKIPE	LOGINT##		;IS LOGGING ENABLED?
	SKIPN	S1,G$CHKP		;WAS A CHECKPOINT SET
	JRST	SLEE.1			;NO..JUST GO TO SLEEP
	SUB	S1,G$NOW		;GET THE TIME REMAINING
	SKIPG	S1			;STILL TIME TO GO
	  JRST	SLEE.2			;NO..CHECKPOINT AND RETURN
	IDIVI	S1,3			;MAKE INTO SECONDS
SLEE.1:	PUSHJ	P,I%SLP			;SLEEP FOR AWHILE
	PUSHJ	P,I%NOW			;GET CURRENT TIME
	MOVEM	S1,G$NOW		;SAVE FOR LOGGING,,ETC
	POPJ	P,			;RETURN
SLEE.2:	PUSHJ	P,L$CHKP##		;DO THE CHECKPOINT
	SETZM	G$CHKP			;CLEAR THE CHECKPOINT TIMER
	JRST	SLEEPR			;TRY TO SLEEP AGAIN
	SUBTTL	PROIPC	--	PROCESS IPCF MESSAGE

PROIPC:	AOS	G$MSGC			;BUMP COUNT OF MESSAGES
	SETZM	G$ERR			;CLEAR THE ERROR WORD
	SETZM	G$OPRA			;CLEAR OPERATOR ADDRESS WORD
	SETZM	G$ASND			;ALWAYS SEND FLAG OFF
	LOAD	S1,MDB.PV(P1)		;GET THE SENDER'S PRIVS
	STORE	S1,G$PRVS		;SAVE FOR ALL
	LOAD	S1,MDB.SD(P1)		;GET SENDER'S ID
	STORE	S1,G$SID		;SAVE FOR ANYONE
	MOVE	S1,MDB.SP(P1)		;GET THE PID
	MOVEM	S1,G$SND		;SAVE THE PID
	SKIPN	G$SND			;CHECK FOR ZERO PID
	  PJRST  E$IPS			;INVALID PID SPECIFIED
	LOAD	MI,MDB.MS(P1),MD.ADR	;GET THE ADDRESS OF THE MESSAGE
	LOAD	S1,.MSTYP(MI),MS.CNT	;GET THE LENGTH FROM THE HEADER
	LOAD	S2,MDB.MS(P1),MD.CNT	;AND FROM THE MDB
	CAMLE	S1,S2			;SENDER'S LENGTH BETTER BE CORRECT
	JRST	E$BML			;BAD MESSAGE LENGTH
	LOAD	T1,.MSTYP(MI),MS.TYP	;GET MESSAGE TYPE
	MOVEM	T1,G$ARG1		;SAVE MESSAGE TYPE
	CAIG	T1,.OMOFF		;VALID ORION MESSAGE
	JRST	PROI.2			;CHECK QUASAR MESSAGES
	CAIN	T1,.OMCMD		;IS IT A COMMAND
	JRST	PROI.1			;BYPASS MSGCHK AND CONTINUE
	PUSHJ	P,MSGCHK		;CONSISTENCY CHECK THE MESSAGE
	JUMPF	.POPJ			;BAD RETURN..RETURN
PROI.1:	LOAD	S1,.MSTYP(MI),MS.TYP	;GET THE MESSAGE TYPE
	MOVEI	S2,MANTAB		;ENABLE DISPATCH TABLE
	PUSHJ	P,TABSRC		;SEARCH THE TABLE
	JUMPF	E$IMT			;ERROR..IGNORE THE MESSAGE
	JRST	(S2)			;PROCESS THE ROUTINE
PROI.2:	CAIE	T1,.QONWA		;NODE WENT AWAY
	$RETF				;RETURN FALSE
	PJRST	DELNOD			;DELETE NODE ROUTINE

MANTAB:	$STAB
	.OMWTO,,W$WTO			;WRITE TO OPERATOR
	.OMCMD,,COMMAN			;COMMAND MESSAGE(FROM OPR PARSER PROGRAM)
	.OMWTR,,W$WTOR			;WTOR FOR NOW
	.OMACK,,W$ACKM			;WTO FOR NOW
	.OMACS,,W$SHOW			;SHOW ACK RESPONSE FROM QUASAR
	.OMOHL,,OPRHEL			;OPR HELLO MESSAGE
	.OMOSR,,OPRSET			;OPR SETUP REPLY
	.OMAHL,,APLHEL			;APPLICATION HELLO MESSAGE
	.OMLOG,,W$LOGM			;LOG MESSAGE
	.OMNFY,,NOTIFY			;NOTIFY CODE
	.OMTKE,,TAKEND			;END OF TAKE COMMAND
IFN	FTDN60,<
	.OMD60,,CMDMES			;COMMAND MESSAGE FROM CDRIVE
>;END FTDN60
	.OMDSP,,RETMES			;RETURNED DN60 DISPLAY MESSAGE
	$ETAB
	SUBTTL	SYSMSG	--	PROCESS SYSTEM MESSAGES

	;THIS ROUTINE WILL PROCESS LOGOUT MESSAGES FROM EITHER SYSTEM


	SYSPRM	LOGMSK,RHMASK,FWMASK	;MASK TO GET JOB NUMBER
	SYSPRM	OB.BSN,OB.BSN,OB%BSN	;BATCH STREAM NUMBER FIELD

SYSMSG:	PUSH	P,[MAIN.2]		;SETUP RETURN ADDRESS
	LOAD	MI,MDB.MS(P1),MD.ADR	;GET MESSAGE ADDRESS
	LOAD	S2,LGO.HD(MI),LOGMSK	;GET FUNCTION CODE
	CAIE	S2,.IPCSL		;LOGOUT MESSAGE
	POPJ	P,			;RETURN
	LOAD	S1,LGO.JB(MI),LG.JOB	;GET THE JOB NUMBER
	STORE	S1,G$PRVS,MD.PJB	;SAVE THE JOB NUMBER
	MOVX	S2,MSL.JB		;MATCH ON JOB NUMBER
	HRRM	S2,FNDXCT		;SAVE IN COMPARE
	PUSHJ	P,FNDMSG		;FIND THE MESSAGE
	JUMPF	SYSM.2			;NONE..TRY ANY OPRS TO DELETE
SYSM.1:	SETZ	P1,			;CLEAR P1 FOR SCRATCH
	EXCH	P1,G$ERR		;SAVE ERROR CODE
	MOVX	S1,E$JLO		;JOB LOGGED OUT
	PUSHJ	P,W$KMES		;KILL THE MESSAGE
	PUSHJ	P,L$KMJB##		;LOG THE MESSAGE
	MOVEM	P1,G$ERR		;RESTORE THE ERROR CODE
	LOAD	S1,G$PRVS,MD.PJB	;GET JOB NUMBER
	PUSHJ	P,NXTMSG		;GET THE NEXT MESSAGE
	JUMPT	SYSM.1			;KILL OTHER MESSAGES ALSO
SYSM.2:	LOAD	P3,G$PRVS,MD.PJB	;GET JOB NUMBER
	MOVE	P1,TABADR		;GET THE TABLE ADDRESS
	MOVE	P2,TABCNT		;MAXIMUM NUMBER OF ENTRIES
	SUB	P2,TABFRE		;GET ACTIVE OPRS
	SKIPN	P2			;ANY OPRS RUNNING?
	$RETT				;NONE SETUP SO FAR..RETURN
SYSM.3:	SKIPN	T2,TOP.OA(P1)		;GET OPR ENTRY ADDRESS
	JRST 	SYSM.5			;ZERO..TRY NEXT ONE
	CAME	P3,OPR.JB(T2)		;CHECK JOB FOR MATCH
	JRST	SYSM.4			;MATCH..SETUP FOR RETURN
	MOVE	S1,OPR.PD(T2)		;GET THE PID
	PUSHJ	P,DELOPR		;DELETE THE OPR
SYSM.4:	ADDI	P1,TOP.SZ		;BUMP TO NEXT ENTRY
	SOJG	P2,SYSM.3		;LOOP THROUGH ALL ENTRIES
	$RETF				;OPR NOT HERE..RETURN FALSE
SYSM.5:	ADDI	P1,TOP.SZ		;BUMP TO NEXT ENTRY
	JRST	SYSM.3			;TRY NEXT ONE
	SUBTTL	ORNINT	--	ORION SETUP ROUTINES

	;THIS ROUTINE WILL GET THE REQUIRED MONITOR INFORMATION NEEDED
	;BY ORION FOR PROCESSING.

ORNINT:	PUSHJ	P,I%HOST		;GET HOST NAME/NUMBER
	MOVEM	S1,G$CNTL		;SAVE THE HOST NAME IN SIXBIT.
	PUSHJ	P,C%MAXP		;GET MAXIMUM PACKET SIZE
	MOVEM	S1,G$MAXP		;SAVE MAXIMUM PACKET SIZE

IFN FTUUOS,<
	;FIND THE OPERATOR PPN
	MOVX	S1,%LDFFA		;GETTABB THE FAILSAFE PPN
	GETTAB	S1,			;...
	  $STOP(CFO,Can't Find Operator PPN)
	MOVEM	S1,FFAPPN		;SAVE FOR LATER
>   ;END IFN FTUUOS
	MOVE	S1,G$CNTL		;NODE OF CENTRAL SITE
	PUSHJ	P,CHKNOD		;CHECK THE NODE
	JUMPT	ORNI.1			;ADD THE NODE
	MOVE	S1,G$CNTL		;GET THE CENTRAL SITE
	SETZ	S2,			;ZERO THE NODE NUMBER
ORNI.1:	PUSHJ	P,ADDNOD		;SETUP THE NODE
	MOVX	T1,ND.SYS		;MARK AS SYSTEM OPERATOR
	IORM	T1,NOD.FL(S1)		;S1 ADDRESS OF NODE LIST ENTRY
	SETOM	S1			;SET FOR MY JOB
	MOVX	S2,JI.JNO		;GET MY JOB NUMBER
	PUSHJ	P,I%JINF		;GET THE JOB INFO
	MOVEM	S2,G$MJOB		;SAVE MY JOB NUMBER
IFN	FTJSYS,<
	SKIPN	DEBUGW			;ARE WE DEBUGGING?
	PUSHJ	P,N$INIT##		;NO..SETUP THE NSP SRV IF CAN
	SKIPE	S1,G$MJOB		;ARE WE RUNNING UNDER JOB 0
	$RETT				;NO..JUST RETURN
	SETZB	T3,T4			;CLEAR T3 AND T4
	MOVE	T1,[POINT 6,G$CNTL]	;GET THE LOCATION
	MOVE	T2,[POINT 7,T3]		;PLACE TO STORE STRING
	MOVEI	P1,6			;MAXIMUM LENGTH
ORNI.2:	ILDB	S2,T1			;GET A BYTE
	JUMPE	S2,ORNI.3		;O.K. SET THE LOCATION
	ADDI	S2,40			;CONVERT TO ASCII CHARACTER
	IDPB	S2,T2			;SAVE THE BYTE
	SOJG	P1,ORNI.2		;CHECK NUMBER OF CHARACTERS
ORNI.3:	MOVX	S2,.SJLLO		;SETUP LOCATION
	HRROI	T1,T3			;GET STRING
	SETJB				;SET IT UP
	ERJMP	.+1			;IGNORE ERROR FOR NOW
>;END FTJSYS
	POPJ	P,			;RETURN
	SUBTTL	MSGCHK	--	CONSISTENCY CHECK THE MESSAGE TO ORION

	;THIS ROUTINE WILL CHECK OUT THE LENGTH AND HEADER INFO FOR
	;THE MESSAGE AND ALL ARGUMNET BLOCKS SPECIFIED

MSGCHK:	LOAD	S2,MDB.MS(P1),MD.CNT	;GET THE SIZE OF THE MESSAGE
	MOVE	T1,MI			;SAVE START ADDRESS IN T1
	ADDI	T1,(S2)			;COMPUTE ENDING ADDRESS OF MESSAGE
	LOAD	T2,.MSTYP(MI),MS.CNT	;GET THE COUNT FROM MESSAGE
	ADDI	T2,(MI)			;COMPUTE LENGTH OF MESSAGE
	CAMLE	T2,T1			;WITHIN ACTUAL LIMITS
	PJRST	E$MTS			;MESSAGE TO SHORT
	MOVEI	S1,.OHDRS(MI)		;GET ADDRESS OF FIRST ARGUMENT
	CAMLE	S1,T1			;LENGTH WITHIN BOUNDS
	PJRST	E$MTS			;MESSAGE TO SHORT
	SKIPN	T2,.OARGC(MI)		;ANY ARGUMENTS IN MESSAGE
	JRST	MSGC.3			;YES..CHECK THEM OUT
MSGC.1:	SKIPG	T2			;VALID COUNT FIELD
	PJRST	E$ICS			;INVALID COUNT SPECIFIED
	SKIPA				;SKIP OVER INCREMENT FIRST TIME
MSGC.2:	ADDI	S1,1			;POINT TO NEXT HEADER
	MOVEI	T3,ARG.HD(S1)		;ADDRESS OF ARGUMENT HEADER
	CAMLE	T3,T1			;ADDRESS IN MESSAGE
	PJRST	E$BML			;BAD MESSAGE LENGTH SPECIFIED
	LOAD	S2,ARG.HD(S1),AR.LEN	;GET THE LENGTH
	SKIPG	S2			;MAKE SURE POSITIVE
	PJRST	E$IAL			;INVALID ARGUMENT LENGTH
	ADDI	S1,-1(S2)		;COMPUTE ADDRESS OF NEXT ARGUMENT
	CAMLE	S1,T1			;STILL WITHIN BOUNDS
	JRST	E$BML			;BAD MESSAGE LENGTH
	SOJG	T2,MSGC.2		;PROCESS ALL ARGUMENTS
MSGC.3:	SUBI	S1,1			;DECREMENT BY 1
	CAMLE	S1,T1			;SHOULD BE EXACT OR LESS
	JRST	E$BML			;BAD MESSAGE LENGTH
	$RETT				;RETURN TRUE
	SUBTTL	RETMES	--	RETURNED DN60 DISPLAY MESSAGE

	;This routine will resend the Display message that was sent to 
	;Quasar to the Central Site Operator

RETMES:	PUSHJ	P,SPGOUT		;SETUP PAGE FOR OUTPUT
	MOVE	S1,G$CNTL		;GET CENTRAL SITE NODE ENTRY
	PUSHJ	P,FNDNOD		;FIND THE NODE
	JUMPT	SNDAOP			;SEND TO ALL OPERATOR AND RETURN
	JRST	S..CNE			;NO CENTRAL SITE NODE
	SUBTTL	OPRHEL	--	HELLO MESSAGE FROM OPR

	;THIS MESSAGE IS SENT BY OPR TO SIGNON TO ORION
	;IF SUCCESSFUL ORION WILL CREATE THE APPROPRIATE NODE AND
	;OPR ENTRIES AND SEND A SETUP TO THE OPR OF THE CURRENT
	;RUNTIME VALUES.

OPRHEL:	SKIPG	T2,.OARGC(MI)		;VALID ARGUMENT COUNT
	PJRST	E$ICS			;INVALID COUNT SPECIFIED
	LOAD	T1,.OHDRS+ARG.HD(MI),AR.TYP ;GET THE TYPE
	CAIE	T1,.OPHEL		;HELLO BLOCK?
	PJRST	E$ITM			;INVALID TYPE IN MESSAGE
	SOJG	T2,E$ICS		;INVALID ARGUMENT COUNT
	LOAD	S1,.OHDRS+OPH.OV(MI)	;GET ORNMAC VERSION NUMBER
	CAIE	S1,%%.OPR		;SAVE VERSION
	PJRST	E$WVN			;WRONG VERSION NUMBER ERROR..
	SETZ	S2,			;CLEAR NODE NUMBER VALUE
	SKIPN	S1,.OHDRS+OPH.ND(MI)	;GET THE HELLO NODE FIELD
	MOVE	S1,G$CNTL		;0 USE CENTRAL SITE
	MOVEM	S1,G$ARG1		;SAVE THE NODE NAME
	DMOVE	P1,S1			;SAVE NODE VALUES IN P1 AND P2
	CAMN	S1,G$CNTL		;WAS IT CENTRAL SITE?
	JRST	OPRH.1			;YES.. JUST ADD THE OPR
	PUSHJ	P,CHKNOD		;CHECK NODE FOR VALID.. S1/NODE
	JUMPF	E$ION			;INVALID OPR NODE
	DMOVE	P1,S1			;SAVE NODE VALUES IN P1 AND P2
	PUSHJ	P,PRVCHK		;PRIVILEGE CHECK
	JUMPF	E$IPE			;INSUFFICIENT PRIVILEGES ENABLED
OPRH.1:	DMOVE	S1,P1			;RESTORE NODE VALUES
	PUSHJ	P,ADDOPR		;ADD OPR TO DATA BASE
	JUMPF	E$OPD			;OPR PID ALREADY DEFINED
	CAMN	P1,G$CNTL		;IS IT CENTRAL SITE
	PJRST	SNDSET			;SEND SETUP AND RETURN
	MOVX	S1,OP.RMT		;GET REMOTE OPERATOR FLAG
	TDNN	S1,.OFLAG(MI)		;WAS IT SET
	PJRST	SNDSET			;SEND SETUP AND RETURN
	MOVX	S1,OP.REM		;GET REMOTE FLAG
	IORM	S1,OPR.FL(S2)		;SAVE IN FLAG WORD
	PJRST	SNDSET			;SEND SETUP AND RETURN
	SUBTTL	APLHEL	--	APPLICATION HELLO MESSAGE

	;THIS MESSAGE IS SENT BY AN APPLICATION TO SIGNON TO ORION
	;THIS ROUTINE WILL CHECK OUT THE NAME AND IF VALID ASSIGN AN
	;IDENTIFIER TO THE APPLICATION AND RETURN THE VALUE TO THE
	;APPLICATION.

APLHEL:	PUSHJ	P,CHKWHL		;PRIVILEGE CHECK
	JUMPF	E$IPE			;INSUFFICIENT PRIVILEGES ENABLED
	SKIPG	T2,.OARGC(MI)		;ARGUMENT COUNT GREATER THAN 0
	PJRST	E$ICS			;INVALID COUNT SPECIFIED
	CAIE	T2,1			;BETTER BE JUST ONE ARGUMENT
	PJRST	E$ICS			;INVALID COUNT SPECIFIED
	LOAD	T1,.OHDRS+ARG.HD(MI),AR.TYP ;GET THE ARGUMENT TYPE
	CAIE	T1,.AHNAM		;APPLICATION HELLO NAME
	PJRST	E$ITM			;INVALID TYPE IN MESSAGE
	LOAD	T1,.OHDRS+ARG.HD(MI),AR.LEN ;GET LENGTH OF BLOCK
	CAIGE	T1,1			;BETTER BE GREATER THAN 1
	PJRST	E$IAL			;INVALID ARGUMENT LENGTH SPECIFIED
	HRROI	S2,.OHDRS+ARG.DA(MI)	;ADDRESS OF TEST STRING 
	MOVEI	S1,APLTAB		;TABLE HEADER
	PUSHJ	P,S%TBLK		;LOOKUP ENTRY IN TABLE
	TXNN	S2,TL%EXM		;EXACT MATCH ON STRING
	JRST	E$ANI			;INVALID APPLICATION NAME
	MOVEI	S2,APLTAB+1		;ADDRESS OF FIRST ENTRY
	HLRZM	S2,G$ARG1		;SAVE NAME FOR MESSAGES
	SUB	S1,S2			;GET TABLE OFFSET
	MOVE	T1,S1			;SAVE THE OFFSET
	MOVE	S2,G$SND		;GET SENDERS PID
	MOVEM	S2,APLPID(T1)		;SAVE PID IN TABLE
	PUSHJ	P,GETPAG		;GET MESSAGE OUT PAGE..MO SET ON RETURN
	MOVX	S1,.OMHAC		;HELLO ACKNOWLEDGMENT
	STORE	S1,.MSTYP(MO),MS.TYP	;SAVE THE TYPE
	AOS	.OARGC(MO)		;BUMP ARGUMENT COUNT
	MOVX	S1,.AHTYP		;APPLICATION HELLO TYPE CODE
	STORE	S1,.OHDRS+ARG.HD(MO),AR.TYP ;SAVE TYPE IN HEADER
	MOVX	S1,ARG.SZ		;MINIMUM SIZE OF BLOCK
	STORE	S1,.OHDRS+ARG.HD(MO),AR.LEN ;SAVE LENGTH OF BLOCK
	MOVE	S1,APLCOD(T1)		;GET APPLICATION CODE
	STORE	S1,.OHDRS+ARG.DA(MO)	;SAVE DATA IN BLOCK
	MOVEI	S1,.OHDRS+ARG.SZ	;SIZE OF THE MESSAGE
	STORE	S1,.MSTYP(MO),MS.CNT	;SAVE COUNT IN MESSAGE
	MOVE	P3,T1			;SAVE TABLE OFFSET
	MOVE	S1,G$SND		;GET SENDERS PID
	MOVEI	S2,PAGSIZ		;SEND THE PAGE
	PUSHJ	P,SNDPID		;SEND THE MESSAGE
	JUMPT	.POPJ			;RETURN
	SETZM	APLPID(P3)		;CLEAR TABLE ENTRY
	PUSHJ	P,RELPAG		;RETURN THE PAGE
	PJRST	E$AHF			;APPLICATION HELLO FAILURE

	DEFINE	X(A,B,C),<ORNDSP(,<A>,<B>)>

APLTAB:	$STAB
	TABAPL				;EXPAND APPLICATION TABLES
	$ETAB

APLPID: BLOCK	NUMAPL		;PID TABLE OF APPLICATIONS

	DEFINE	X(A,B,C),<EXP	.KY'B>

APLCOD:	TABAPL				;EXPAND THE APPLICATION SYMBOLS
	SUBTTL	CHKNOD	--	VALIDATE THE OPR NODE DATA

	;THIS ROUTINE WILL VALIDATE THE OPR NODE IN MESSAGE WITH
	;THE NODE THE OPR SIGNED ON WITH TO INSURE NODE IS VALID
	;ON RETURN TRUE:
	;		S1/ NODE NAME IN SIXBIT
	;		S2/ NODE NUMBER (IF APPLICABLE)

IFN	FTUUOS,<
CHKNOD:	MOVSI	T1,.NDRNN		;NODE NUMBER TO NAME CONVERSION
	HRRI	T1,T2			;ADDRESS BLOCK IN T1
	HRRZI	T2,2			;2 ARGS SPECIFIED..LENGTH
	MOVE	T3,S1			;NODE NUMBER TO CONVERT,,RIGHT HALF
	NODE.	T1,			;ISSUE NODE UUO
	  $RETF				;ERROR..RETURN FALSE
	TLNN	T1,770000		;SIXBIT ANSWER..NODE NAME
	JRST	CHKN.1			;SET UP NODE NUMBER
	MOVE	S2,S1			;PUT NUMBER IN S2
	MOVE	S1,T1			;PUT NAME IN S1
	$RETT				;RETURN TRUE
CHKN.1:	MOVE	S2,T1			;PUT NUMBER IN S2
	$RETT				;RETURN S1,,NODE NAME
>;END FTUUOS

IFN	FTJSYS,<
CHKNOD:	MOVE	T3,S1			;HOLD THE NODE NAME
	CAMN	S1,G$CNTL		;IS IT CENTRAL SITE?
	JRST	CHKN.1			;YES..RETURN
	MOVX	S1,.NDVFY		;NODE VERIFY FUNCTION
	MOVEI	S2,T1			;ADDRESS OF THE BLOCK
	HRROI	T1,G$NODE		;GET THE NODE
	SETZM	T2			;CLEAR THE FLAGS
	NODE				;DO THE NODE JSYS
	ERJMP	.RETF			;ERROR..RETURN FALSE
	TXNN	T2,ND%EXM		;DID IT MATCH
	$RETF				;RETURN FALSE
CHKN.1:	MOVE	S1,T3			;GET NODE NAME BACK IN SIXBIT
	SETZ	S2,			;CLEAR AC 2
	$RETT				;RETURN TRUE
>;END FTJSYS
	SUBTTL	OPRSET	--	PROCESS SETUP REPLY FROM OPR

	;THIS ROUTINE WILL PROCESS A SETUP REPLY FROM OPR AND
	;ENABLE OPR FOR APPROPRIATE MESSAGES

OPRSET:	SKIPG	.OARGC(MI)		;VALID ARGUMENT COUNT
	PJRST	E$ICS			;INVALID COUNT SPECIFIED
	MOVE	S1,G$SND		;GET SENDERS PID
	PUSHJ	P,VALOPR		;VALIDATE THE NODE
					;RETURNS TRUE S2 OPR ENTRY ADDRESS
	JUMPF	E$ISM			;INVALID SETUP MESSAGE
	MOVEM	S2,G$OPRA		;SAVE THE OPR ADDRESS
	LOAD	T1,.OHDRS+ARG.HD(MI),AR.TYP ;GET TYPE CODE
	CAIN	T1,.ORFAL		;FAILURE RETURN
	PJRST	OPRS.1			;FIX OPR DATA BASE
	CAIE	T1,.ORSUC		;SUCCESSFUL??
	PJRST	E$ITM			;INVALID TYPE IN MESSAGE
	MOVX	S1,OP.NST		;OPR NOT SETUP
	TDNN	S1,OPR.FL(S2)		;WAS OPR ALREADY SETUP
	PJRST	OPRS.3			;YES..ERROR
	ANDCAM	S1,OPR.FL(S2)		;MARK AS SETUP
	SKIPG	G$NSNT			;ANY UNSENT MESSAGES
	$RETT				;NO JUST RETURN
	MOVE	S1,OPR.ND(S2)		;GET NODE ADDRESS
	MOVE	S1,NOD.FL(S1)		;GET THE FLAG WORD
	TXNN	S1,ND.SYS		;SYSTEM NODE
	$RETT				;NO..JUST RETURN
	MOVX	S1,R.SOPR		;ONLY SENDS TO OPR
	PUSHJ	P,SNDLST		;TRY SENDING THE MESSAGES
	$RETT				;RETURN TRUE

OPRS.1:	SOSG	.OARGC(M)		;ANY ARGUMNETS LEFT
	  JRST	OPRS.2			;NO..IGNORE TEXT LOGGING
	LOAD	T1,.OHDRS+ARG.HD(MI),AR.LEN ;GET THE LENGTH
	ADDI	T1,.OHDRS(M)			;POSITION TO NEXT ARGUMENT
	LOAD	S1,ARG.HD(T1),AR.TYP	;GET ARGUMENT TYPE
	CAIE	S1,.CMTXT		;TEXT ??
	  JRST	OPRS.2			;NO..IGNORE TEXT
	MOVEI	S1,ARG.DA(T1)		;ADDRESS OF THE TEXT
	PUSHJ	P,L$SETF##		;LOG SETUP FAILURE
OPRS.2:	MOVE	S1,G$SND		;GET THE SENDERS PID
	PUSHJ	P,DELOPR		;DELETE THE OPR BLOCK
	$RETT				;RETURN TRUE
OPRS.3:	MOVE	S1,G$SND		;GET THE SENDERS PID
	PUSHJ	P,DELOPR		;DELETE THE OPR
	PJRST	E$OAS			;OPR ALREADY SETUP..OPR DELETED
	SUBTTL	SNDSET	--	SEND A SETUP TO OPR

	;THIS ROUTINE SEND THE CURRENT SETTINGS TO OPR IN RESPONSE TO
	;THE HELLO MESSAGE

SNDSET:	PUSHJ	P,GETPAG		;PAGE FOR OUTPUT IN MO
	MOVX	S1,.OMOST		;OPR SETUP CODE
	STORE	S1,.MSTYP(MO),MS.TYP	;SAVE IN MESSAGE
	MOVX	S1,.OHDRS		;SIZE OF MESSAGE FOR NOW
	STORE	S1,.MSTYP(MO),MS.CNT	;SAVE THE COUNT IN MESSAGE
	MOVE	S1,G$SND		;GET OPR PID
	MOVEM	S1,G$ARG1		;SAVE THE PID
	MOVX	S2,PAGSIZ		;SEND A PAGE
	PUSHJ	P,SPDOPR		;SEND THE MESSAGE
	JUMPT	.POPJ			;O.K...RETURN
	PJRST	E$OSF			;OPR SETUP FAILURE
	$RETF				;RETURN FALSE FROM SEND
SUBTTL	TEXT	--	Routine to Process a TEXT Message

;THIS ROUTINE JUST SHIPS THE MESSAGE ON TO THE APPROPRIATE OPERATOR
;IF MF.NOM IS SET, THE MESSAGE IS THROWN AWAY

TEXT:	LOAD	S1,.MSCOD(MI)		;GET THE CODE TO LOOK FOR
	PUSHJ	P,VALOPR		;FIND THE OPR ENTRY
	JUMPF	E$ODE			;OPR NO LONGER EXISTS
	LOAD	S1,.MSFLG(MI)		;GET FLAG WORD
	TXNE	S1,MF.NOM		;NO MESSAGE..IN ACK
	$RETT				;YES..JUST RETURN
	PUSHJ	P,SPGOUT		;SETUP OUTPUT PAGE
	AOS	OPR.OC(S2)		;BUMP MESSAGE OUT COUNT
	MOVE	S1,OPR.PD(S2)		;GET THE PID TO SEND TO
	MOVEI	S2,PAGSIZ		;GET SIZE OF MESSAGE
	PUSHJ	P,SPDOPR		;SEND PID TO OPR
	$RETT				;RETURN TRUE ALWAYS
	SUBTTL	SPGOUT	--	Setup Output Page to Send

	;This Routine will make an Output Page to Send where
	;we wish to send the input message out

SPGOUT:	PUSHJ	P,GETPAG		;GET A PAGE
	HRLI	S1,(MI)			;SOURCE ADDRESS
	HRRI	S1,(MO)			;DESTINATION
	BLT 	S1,PAGSIZ-1(MO)		;MOVE THE DATA
	$RETT				;RETURN
	SUBTTL	W$WTOR	--	Process a WTOR Message

W$WTOR:	MOVE	P1,.OFLAG(MI)		;GET FLAG WORD
	TXNE	P1,WT.KIL		;CHECK FOR KILL MESSAGE
	PJRST	W$KWTO			;PROCESS KILL MESSAGE
	PUSHJ	P,W$CHEK		;CHECK IF USER ALLOWED TO SEND
	JUMPF	.POPJ			;ERROR..RETURN
	PUSHJ	P,W$VALID		;VALIDATE A WTO MESSAGE
	JUMPF	.POPJ			;FAILS...RETURN
	PUSHJ	P,OPRMES		;SETUP THE MESSAGE
	MOVX	S1,.OMWTR		;GET THE DISPLAY TYPE
	STORE	S1,.MSTYP(MO),MS.TYP	;SAVE TYPE IN MESSAGE
	AOS	G$SEQ			;ASSIGN A SEQUENCE NUMBER
	MOVEI	T1,[ITEXT(< ^7/[74]/^D/G$SEQ/^7/[76]/	>)]
	PUSHJ	P,W$MESS		;BUILD OUTPUT MESSAGE
	JUMPT	WTOR.1			;O.K. CONTINUE ON
	SOS	G$SEQ			;DECREMENT MESSAGE COUNT FROM FAILURE
	PJRST	WTERRO			;WT ERROR RETURN
WTOR.1:	PUSHJ	P,L$WTOR##		;LOG THE WTOR MESSAGE
	PUSHJ	P,W$NODE		;GET THE NODE TO SEND TO
	MOVE	T1,S1			;SAVE THE ENTRY ADDRESS
	LOAD	S1,NOD.ML(T1)		;GET MESSAGE LIST NUMBER
	PUSHJ	P,L%LAST		;POSITION TO THE END
	LOAD	S1,NOD.ML(T1)		;GET MESSAGE LIST NUMBER
	LOAD	S2,ARG.HD+.OHDRS(MO),AR.LEN ;GET LENGTH OF ARGUMENT
	MOVE	T3,S2			;SAVE SIZE IN T3
	ADDI	S2,MSL.SZ		;GET SIZE OF TOTAL ENTRY
	PUSHJ	P,L%CENT		;CREATE AN ENTRY
	MOVE	T2,S2			;SAVE ADDRESS OF THE ENTRY
	HRLI	S1,ARG.HD+.OHDRS(MO)	;GET START OF BLT
	HRRI	S1,MSL.SZ(T2)		;ADDRESS OF DESTINATION
	ADDI	T3,MSL.SZ(T2)		;GET ENDING ADDRESS
	BLT	S1,-1(T3)		;MOVE THE DATA
	MOVE	S1,G$SND		;SENDERS PID
	MOVEM	S1,MSL.PD(T2)		;SAVE IN MESSAGE BLOCK
	MOVEM	T1,MSL.ND(T2)		;SAVE NODE ADDRESS IN MESSAGE LIST
	AOS	NOD.CT(T1)		;BUMP THE NODE COUNT
	MOVE	S1,.MSCOD(MI)		;GET MESSAGE HEADER CODE
	MOVEM	S1,MSL.CD(T2)		;SAVE THE MESSAGE CODE
	MOVE	S1,G$SEQ		;GET THE SEQUENCE NUMBER
	MOVEM	S1,MSL.ID(T2)		;SAVE SEQUENCE NUMBER
	SKIPN	S1,WDAJOB		;WAS THERE A JOB NUMBER
	LOAD	S1,G$PRVS,MD.PJB	;GET SENDERS JOB NUMBER
	MOVEM	S1,MSL.JB(T2)		;SAVE JOB NUMBER
	MOVX	T3,MS.TER		;TERMINAL NOTIFY ON FAILURE
	MOVX	S2,WT.NFY		;GET THE NOFITFY TERMINAL FLAG
	TDNN	S2,.OFLAG(MI)		;WAS IT SET?
	JRST	WTOR.2			;NO..BYPASS SETTING LOGGED IN TIME
	IORM	T3,MSL.FL(T2)		;SAVE THE FLAG BIT WITH MESSAGE
	MOVX	S2,JI.JLT		;GET LOGGED IN TIME FOR JOB
	PUSHJ	P,I%JINF		;GET LOGGED IN TIME
	MOVEM	S2,MSL.JT(T2)		;SAVE THE VALUE FOR LATER
WTOR.2:	MOVE	S1,T1			;NODE ENTRY
	PJRST	SNDAOP			;SEND TO ALL OPERATORS
	SUBTTL	W$KWTO	--	KILL A WTOR REQUEST BY CODE

	;THIS ROUTINE WILL KILL A WTOR REQUEST BY CODE AND INFORM 
	;ALL OPRS OF THE DELETED MESSAGE

W$KWTO:	MOVEI	S2,[ITEXT(< by User ^U/G$SID/ Job ^D/G$PRVS,MD.PJB/>)]
	MOVEM	S2,G$ARG3		;SAVE USER INFO FOR KILL
	TXNN	P1,WT.SJI		;DID USER WISH TO SUPPRESS JOB INFO
	JRST	WTOK.0			;NO..LOOK FOR MESSAGE NOW
	PUSHJ	P,CHKWHL		;CHECK IF PRIVILEGED
	JUMPF	E$IPE			;INSUFFICIENT PRIVILEGES
	MOVEI	S2,NULTXT		;SETUP NULL TEXT
	MOVEM	S2,G$ARG3		;SAVE THE ARGUMENT
WTOK.0:	MOVX	S1,MSL.CD		;GET THE CODE FIELD
	MOVE	P3,.MSCOD(MI)		;GET THE ACK CODE TO CHECK FOR
	TXNE	P1,WT.KAL		;KILL ALL FOR THE JOB
	   JRST [MOVX	S1,MSL.JB	;SETUP JOB NUMBER FOR THE MATCH
		LOAD P3,G$PRVS,MD.PJB	;GET THE JOB NUMBER
		JRST 	.+1]		;CONTINUE ON
	HRRM	S1,FNDXCT		;SAVE FOR COMPARE
	MOVE	S1,P3			;GET THE MESSAGE CODE
	MOVEM	S1,G$ARG1		;SAVE CODE FOR POSSIBLE ERROR
	SETZM	G$ARG2			;CLEAR MESSAGE KILLED COUNT
	PUSHJ	P,FNDMSG		;TRY TO FIND A MESSAGE
	JUMPF	E$NMC			;NO MESSAGES WITH CODE
WTOK.1:	SETZ	P1,			;CLEAR P1 FOR SCRATCH
	EXCH	P1,G$ERR		;SAVE ERROR CODE
	MOVEI	S1,E$CWM		;SETUP USER CANCEL MESSAGE
	PUSHJ	P,W$KMES		;KILL THE MESSAGE
	PUSHJ	P,L$KMES##		;LOG THE MESSAGE
	MOVEM	P1,G$ERR		;RESTORE THE ERROR CODE
WTOK.2:	MOVE	S1,P3			;GET THE CODE AGAIN
	PUSHJ	P,NXTMSG		;GET NEXT MESSAGE
	JUMPT	WTOK.1			;PROCESS SECOND MESSAGE
	SETZM	G$ERR			;CLEAR ERROR CODE
	SKIPE	G$ARG2			;ANY MESSAGES KILLED
	JRST	WTOK.3			;CHECK FOR ACK
	MOVE	S1,P3			;GET THE CODE
	MOVEM	S1,G$ARG1		;SAVE THE CODE
	PJRST	E$NMC			;NO MESSAGE CANCELED
WTOK.3:	LOAD	S1,.MSFLG(MI),MF.ACK	;ACK REQUESTED?
	SKIPN	S1			;USER WANT AN ACK
	$RETT				;NO..JUST RETURN
	PJRST	E$MCJ			;MESSAGES CANCELED FOR JOB
	SUBTTL	W$NODE	--	DETERMINE NODE TO OUTPUT MESSAGE TO

W$NODE:	SKIPN	S1,WDADES		;ANY DESTINATION SET
	JRST	WTNO.1			;NO..USE CENTRAL SITE
	PUSHJ	P,FNDNOD		;CHECK THIS NODE
	JUMPT	.POPJ			;O.K...FOUND IT
WTNO.1:	MOVE	S1,G$CNTL		;GET CENTRAL SITE NODE
	PUSHJ	P,FNDNOD		;LOCATE THIS ONE
	JUMPT	.POPJ			;BETTER SUCCEED
	$STOP(CNE,Central Site Node not Present)
	SUBTTL	W$KMES	--	KILL THE MESSAGE AND NOTIFY OPERATOR


W$KMES:	PUSHJ	P,(S1)			;SETUP MESSAGE
	MOVE	S1,MSL.ID(S2)		;GET SEQUENCE NUMBER
	MOVEM	S1,G$ARG1		;SAVE THE NUMBER
	MOVE	S1,MSL.ND(S2)		;GET NODE MESSAGE FOUND AT
	PUSH	P,S1			;SAVE NODE LIST ADDRESS
	SOS	NOD.CT(S1)		;DECREMENT MESSAGE NODE COUNT
	MOVE	S1,NOD.ML(S1)		;GET MESSAGE LIST NUMBER
	PUSHJ	P,L%DENT		;DELETE THE MESSAGE
	PUSHJ	P,BLDACK		;BUILD ACK MESSAGE
	POP	P,S1			;GET NODE ADDRESS
	PUSHJ	P,SNDAOP		;SEND IT TO ALL OPRS AT NODE
	AOS	G$ARG2			;BUMP KILLED COUNT
	$RETT				;RETURN TRUE
	SUBTTL	W$WTO	--	PROCESS A WTO MESSAGE

	;THIS ROUTINE WILL PROCESS A WTO MESSAGE AND SEND IT TO
	;THE APPROPRIATE OPERATOR

W$WTO:	PUSHJ	P,W$CHEK		;CHECK IF USER ALLOWED TO SEND
	JUMPF	.POPJ			;ERROR..RETURN
	PUSHJ	P,W$VALID		;VALIDATE THE MESSAGE
	JUMPF	.POPJ			;ERROR..RETURN
	PUSHJ	P,OPRMES		;BUILD OUTPUT MESSAGE
	PUSHJ	P,W$MESS		;SETUP OUTPUT TEXT
	JUMPF	WTERRO			;WT ERROR RETURN
	PUSHJ	P,L$WTO##		;LOG WTO MESSAGE
WTOSND:	PUSHJ	P,W$NODE		;GET THE NODE FOR MESSAGE
	PJRST	SNDAOP			;SEND THE MESSAGE


WTERRO:	PUSHJ	P,RELPAG		;RETURN THE PAGE
	$RETF				;RETURN FALSE


	SUBTTL	W$CHEK	--	CHECK IF WTO/WTOR ALLOWED FOR JOB

W$CHEK:	PUSHJ	P,CHKWHL		;CHECK IF PRIVILEGED
	JUMPT	.POPJ			;O.K.. IGNORE THE CHECK
	LOAD	S1,G$PRVS,MD.PJB	;GET THE JOB NUMBER
	MOVX	S2,JI.BAT		;GET BATCH DATA AND OPR FIELDS
	PUSHJ	P,I%JINF		;GET THE DATA
	LOAD	S1,S2,OB.WTO		;GET THE WTO FLAGS
	SKIPN	S1			;ANY VALUE SET
	$RETT				;NO..ITS O.K...RETURN
	CAIN	S1,.OBNOM		;NO MESSAGES ALLOWED
	PJRST	E$WNA			;WTO(R) NOT ALLOWED
	LOAD	S1,.MSTYP(MI),MS.TYP	;GET MESSAGE TYPE
	CAIN	S1,.OMWTR		;WAS IT A WTOR
	PJRST	E$WNA			;NOT ALLOWED FOR USER
	$RETT				;RETURN TRUE
	SUBTTL	W$LOGM	--	LOG A MESSAGE TO LOG

	;THIS MESSAGE IS A WTO/WTOR/ACK TYPE MESSAGE JUST PLACING INFO IN LOG
	;AND NOT SENDING IT.. IF THERE IS NO LOG THE MESSAGE WILL BE IGNORED

W$LOGM:	SKIPN	LOGINT			;LOGGING ENABLED
	$RETT				;NO..JUST RETURN..IGNORE IT
	PUSHJ	P,W$VALID		;VALIDATE THE MESSAGE
	JUMPF	.POPJ			;ERROR..RETURN
	PUSHJ	P,OPRMES		;BUILD OUTPUT MESSAGE
	PUSHJ	P,W$MESS		;SETUP OUTPUT TEXT
	JUMPF	WTERRO			;WT ERROR RETURN
	PUSHJ	P,L$LOG##		;LOG WTO MESSAGE
	PJRST	RELPAG			;RELEASE PAGE AND RETURN
	SUBTTL	W$VALID	--	Validate WTO, WTOR and ACK Messages

	;THIS ROUTINE WILL TAKE THE FREE FORMATTED WTO, WTOR
	;AND ACK MESSAGES AND MAP THEM INTO THE FIXED FORMATED MESSAGE
	;CURRENTLY USED BY OPR AND ORION. THE ROUTINE WILL VALIDATE 
	;THE FIELDS AND PRIVILEGE CHECK APPROPRIATE FIELDS. ERRORS WILL
	;BE GENERATED FOR ALL DUPLICATION OF ENTRIES IN THE MESSAGE.

W$VALID:	LOAD	S1,.MSTYP(MI),MS.CNT	;GET THE MESSAGE LENGTH
	MOVEM	S1,G$ARG1		;SAVE MESSAGE LENGTH IN ARGUMENT
	CAILE	S1,WTOMAX		;CHECK IF WITHIN BOUNDS
	PJRST	E$WTL			;WTO MESSAGE TO LARGE
	SKIPG	P2,.OARGC(MI)		;GET THE ARGUMENT COUNT
	PJRST	E$ICS			;INVALID ARGUMENT COUNT SPECIFIED
	TXZ	FLAG,F.WFLG		;CLEAR WTO FLAGS
	MOVE	S1,[WDATXT,,WDATXT+1]	;WTO TEXT DATA POINTER
	SETZM	WDATXT			;CLEAR FIRST WORD
	BLT	S1,WDAEND		;CLEAR THE DATA WORDS
	MOVX	S1,WO.JOB		;JOB MESSAGE FLAG
	MOVX	S2,WT.JOB		;JOB MESSAGE FLAG FROM MESSAGE
	TDNE	S2,.OFLAG(MI)		;WAS IT SET
	IORM	S1,WDAFLG		;SET THE FLAG
	MOVX	S1,WO.OAC		;OPERATOR ACTION MESSAGE
	LOAD	S2,.MSTYP(MI),MS.TYP	;GET MESSAGE TYPE
	CAIN	S2,.OMWTR		;WAS IT WTOR
	IORM	S1,WDAFLG		;SET THE FLAG
	MOVEI	S1,.OHDRS(MI)		;ADDRESS OF FIRST ARGUMENT
	PUSHJ	P,P$SETU		;SETUP THE PARSER POINTER
	MOVX	S1,WO.EVM		;CHECK IF OTER MESSAGE
	SKIPN	WDAFLG			;ANYTHING SET?
	IORM	S1,WDAFLG		;TURN ON OTHER FLAG
VALW.1:	PUSHJ	P,P$NARG		;GET THE NEXT ARGUMENT
	MOVE	P1,S2			;SAVE ARGUMENT ADDRESS
	LOAD	P3,ARG.HD(S2),AR.LEN	;SAVE THE ARGUMENT LENGTH
	CAILE	S1,.WTLST		;VALID ARGUMENT TYPE
	JRST	VALW.2			;INVALID TYPE..ERROR AND RELEASE
					;PAGE
	HRRZ	S2,WTODSP(S1)		;GET THE PROCESSING ROUTINE
	PUSHJ	P,(S2)			;PROCESS THE ARGUMENT
	JUMPF	.POPJ			;BAD RETURN..RETURN
	PUSHJ	P,P$NEXT		;POSITION TO THE NEXT ONE
	SOJG	P2,VALW.1		;PROCESS THE REST OF THE ARGUMENTS
	SKIPN	S1,WDATYP		;WAS THERE A TYPE FIELD
	$RETT				;NO...JUST RETURN
	LOAD	S2,ARG.HD-1(S1),AR.LEN	;GET THE LENGTH OF THE BLOCK
	MOVEI	T1,TYPMIN		;ASSUME SMALL TYPE SIZE
	SKIPN	WDAOBJ			;WAS THERE AN OBJECT BLOCK?
	MOVEI	T1,TYPMAX		;NO..ALLOW LARGER TYPE TEXT
	SKIPE	WDAACD			;APPLICATION CODE
	MOVEI	T1,TYPAPL		;YES..SET ALLOWED TYPE SIZE
	CAMG	S2,T1			;WAS LENGTH IN BOUNDS
	$RETT				;YES..RETURN TRUE
	ADDI	T1,-1(S1)		;GET ADDRESS OF LAST WORD
	SETZM	0(T1)			;CLEAR THE WORD
	$RETT				;RETURN TRUE
VALW.2:	PJRST	E$ITM			;INVALID TYPE ARGUMENT IN MESSAGE

	;DISPATCH TABLE FOR WTO WTOR AND ACK PROCESSING

WTODSP:	.WTTXT,,WTOTXT			;PROCESS MAIN TEXT STRING
	.WTOBJ,,WTOOBJ			;PROCESS OBJECT BLOCK
	.WTDES,,WTODES			;PROCESS DESTINATION NODE
	.WTJOB,,WTOJOB			;PROCESS JOB NUMBER
	.WTERR,,WTOERR			;PROCESS ERROR CODE
	.WTRTE,,WTORTE			;PROCESS ROUTE CODE
	.WTTYP,,WTOTYP			;PROCESS TYPE TEXT
	.WTANS,,WTOANS			;PROCESS ANSWER BLOCK
	.WTACD,,WTOACD			;PROCESS APPLICATION CODE BLOCK
	.WTOCD,,WTOOCD			;PROCESS OBJECT TYPE BLOCK
	SUBTTL	WTOTXT, WTOTYP, WTOANS AND WTOACD ROUTINES

	;THESE ROUTINES WILL SETUP DATA POINTER TO FIELDS AND VALIDATE
	;FIELDS FOR PRIVILEGES WHERE REQUIRED

WTOTXT:	TXOE	FLAG,F.WTXT		;HAVE WE PROCESSED TEXT BEFORE
	PJRST	E$DTM			;DUPLICATE TYPE IN MESSAGE
	MOVEI	S1,ARG.DA(P1)		;POINTER TO ACTUAL TEXT
	MOVEM	S1,WDATXT		;TEXT POINTER FIELD
	$RETT				;RETURN TRUE

WTOTYP:	TXOE	FLAG,F.WTYP		;TYPE MESSAGE SEEN
	PJRST	E$DTM			;DUPLICATE TYPE IN MESSAGE
	MOVEI	S1,ARG.DA(P1)		;POINTER TO ACTUAL TEXT
	MOVEM	S1,WDATYP		;TYPE DATA FIELD
	$RETT				;RETURN TRUE

WTOANS:	TXOE	FLAG,F.WANS		;ANSWER BLOCK SPECIFIED SO FAR
	PJRST	E$DTM			;DUPLICATE TYPE IN MESSAGE
	LOAD	S1,.MSTYP(MI),MS.TYP	;GET MESSAGE TYPE
	CAIE	S1,.OMWTR		;WTOR MESSAGE
	PJRST	E$IWF			;INVALID WTO FIELD
	MOVEI	S1,ARG.DA(P1)		;POINTER TO ACTUAL TEXT
	MOVEM	S1,WDAANS		;SAVE ANSWER DATA POINTER
	$RETT				;RETURN TRUE
WTOACD:	TXOE	FLAG,F.WACD		;CODE SPECIFIED SO FAR
	PJRST	E$DTM			;DUPLICATE TYPE IN MESSAGE
	TXNE	FLAG,F.WOBJ!F.WOCD	;WAS THERE AN OBJECT BLOCK
	PJRST	E$AON			;APPLICA AND OBJECT NOT ALLOWED	TOGETHER
	MOVE	S1,ARG.DA(P1)		;GET THE CODE TYPE
	MOVEM	S1,G$ARG1		;SAVE THE ARGUMENT
	PUSHJ	P,FNDAPL		;FIND THE APPLICATION
	JUMPF	E$ACI			;APPLICATION CODE INVALID
	SUBI	S1,APLBEG		;GET VALUE FROM APPL DESIGNATOR
	SETZ	T2,			;CLEAR A FLAG
	TXO	T2,1B0			;SETUP STARTING APPLICATION
	MOVNS	S1,S1			;GET SHIFT VALUE
	LSH	T2,(S1)			;SETUP MESSAGE FLAG
	IORM	T2,WDAAFL		;SAVE THE VALUE
	MOVE	T1,APLTAB+1(S2)		;GET COMMAND TABLE ENTRY
	HLRZM	T1,WDAACD		;SAVE THE NAME
	HLRZM	T1,G$ARG1		;SAVE NAME FOR POSSIBLE ERRORS
	SKIPN	S1,APLPID(S2)		;IS THERE A PID THERE
	PJRST	E$ANS			;APPLICATION NOT SIGNED ON
	CAME	S1,G$SND		;BETTER BE FOR SAME JOB
	PJRST	E$CPM			;CODE PID MISMATCH FOR APPLICATION
	$RETT				;RETURN TRUE
	SUBTTL	WTOJOB,WTOERR,WTORTE AND WTODES 



WTOJOB:	TXOE	FLAG,F.WJOB		;JOB NUMBER SEEN SO FAR
	PJRST	E$DTM			;YES..DUPLICATE TYPE IN MESSAGE
	PUSHJ	P,CHKWHL		;PRIVILEGE CHECK JOB FIELD
	JUMPF	E$WJP			;WTO JOB FIELD REQUIRES PRIVILEGES
	LOAD	S1,ARG.DA(P1)		;GET JOB NUMBER
	MOVEM	S1,WDAJOB		;SAVE THE JOB NUMBER
	CAIE	P3,ARG.SZ		;PROPER SIZE FIELD
	PJRST	E$IAL			;INVALID ARGUMENT LENGTH
	$RETT				;RETURN TRUE





WTOERR:	TXOE	FLAG,F.WERR		;ERROR CODE SEEN BEFORE
	PJRST	E$DTM			;DUPLICATE TYPE IN MESSAGE
	LOAD	S1,ARG.DA(P1)		;GET DATA FIELD
	MOVEM	S1,WDAERR		;SAVE ERROR CODE
	CAIE	P3,ARG.SZ		;PROPER SIZE FIELD
	PJRST	E$IAL			;INVALID ARGUMENT LENGTH
	$RETT				;RETURN TRUE


WTORTE:	TXOE	FLAG,F.WRTE		;ROUTE CODE SEEN BEFORE
	PJRST	E$DTM			;DUPLICATE TYPE IN MESSAGE
	LOAD	S1,ARG.DA(P1)		;GET THE ROUTE CODE
	MOVEM	S1,WDARTE		;SAVE THE ROUTE CODE
	CAIE	P3,ARG.SZ		;PROPER SIZE FIELD
	PJRST	E$IAL			;INVALID ARGUMENT LENGTH
	$RETT				;RETURN TRUE


WTODES:	TXOE	FLAG,F.WDES		;DESTINATION CODE SPECIFIED
	PJRST	E$DTM			;DUPLICATE TYPE IN MESSAGE
	LOAD	S1,ARG.DA(P1)		;GET DESTINATION CODE
	MOVEM	S1,WDADES		;SAVE DESTINATION DATA
	CAIE	P3,ARG.SZ		;PROPER SIZE FIELD
	PJRST	E$IAL			;INVALID ARGUMENT LENGTH
	CAME	S1,[-1]			;IS IT FOR ALL NODES
	$RETT				;RETURN TRUE
	PUSHJ	P,CHKWHL		;IS IT A WHEEL?
	JUMPT	.POPJ			;O.K...RETURN
	PJRST	E$IPE			;INSUFFICIENT PRIVILEGES
	SUBTTL	WTOOBJ	--	PROCESS WTO OBJECT BLOCK

	;THIS ROUTINE WILL ANALYZE AN OBJECT BLOCK AND PLACE THE 
	;DATA IN THE OUTPUT MESSAGE

WTOOBJ:	TXOE	FLAG,F.WOBJ		;OBJECT BLOCK PROCESSED
	PJRST	E$DTM			;DUPLICATE TYPE IN MESSAGE
	PUSHJ	P,CHKWHL		;PRIVILEGES REQUIRED FOR OBJECT
	JUMPF	E$WOP			;OBJECT BLOCK REQUIRES PRIVILEGES 
	TXNE	FLAG,F.WACD!F.WOCD	;APPLICATION CODE SET
	PJRST	E$AON			;APPLIC AND OBJECT NOT ALLOWED TOGETHER
	PUSHJ	P,WTOC.1		;PROCESS THE CODE
	JUMPF	.POPJ			;PASS FALSE UP
	MOVE	S1,OBJ.TY+ARG.DA(P1)	;GET OBJECT TYPE
	CAIN	S1,.OTMNT		;WAS IT A MOUNT MESSAGE
	JRST	WTOO.1			;BYPASS UNIT CHECK
	LOAD	T1,OBJ.UN+ARG.DA(P1),OU.LRG ;GET LOW RANGE NUMBER
	SKIPGE	T1			;MUST BE > = 0
	PJRST	E$IOU			;ILLEGAL RANGE UNIT
	LOAD	T2,OBJ.UN+ARG.DA(P1),OU.HRG ;GET HIGH RANGE
	SKIPE	T2			;BETTER BE ZERO
	PJRST	E$RIW			;RANGE INVALID IN WTO OBJECT BLOCK
WTOO.1:	MOVEI	S1,ARG.DA(P1)		;ADDRESS OF OBJECT BLOCK
	MOVEM	S1,WDAOBJ		;SAVE IN OBJECT WORD
	LOAD	T1,OBJ.ND+ARG.DA(P1)	;GET NODE NAME FROM BLOCK
	SKIPN	WDADES			;DESTINATION SET
	MOVEM	T1,WDADES		;SAVE NODE NAME FOR DESTINATION
	$RETT				;RETURN TRUE
	SUBTTL	WTOOCD	--	OBJECT TYPE BLOCK

	;THIS ROUTINE WILL SETUP THE OBJECT TYPE FOR SCREENING AND
	;MAKE SURE THAT NO OBJECT OR APPLICATION WERE SPECIFIED

WTOOCD:	TXOE	FLAG,F.WOCD		;OBJECT TYPE PROCESSED
	PJRST	E$DTM			;DUPLICATE TYPE IN MESSAGE
	PUSHJ	P,CHKWHL		;PRIVILEGES REQUIRED FOR OBJECT
	JUMPF	E$WTP			;OBJECT BLOCK REQUIRES PRIVILEGES 
	TXNE	FLAG,F.WACD!F.WOBJ	;APPLICATION CODE SET
	PJRST	E$AON			;APPLIC AND OBJECT NOT ALLOWED TOGETHER
WTOC.1:	MOVE	S1,OBJ.TY+ARG.DA(P1)	;GET OBJECT TYPE
	MOVEM	S1,G$ARG1		;SAVE THE OBJECT TYPE IN CASE OF ERROR
	SKIPG	S1			;VALID OBJECT TYPE?
	PJRST	E$IOT			;INVALID OBJECT TYPE
	CAILE	S1,.OTMAX		;VALID TYPE FIELD
	PJRST	E$IOT			;INVALID OBJECT TYPE
	MOVE	S1,OBJBLK(S1)		;GET THE APPROPRIATE FLAG OFFSET
	IMULI	S1,3			;MULTIPLY BY 3(NUMBER OF FLAGS)
	MOVN	S1,S1			;MAKE IT NEGATIVE
	MOVE	T1,WDAFLG		;GET FLAG VALUES
	ANDCAM	T1,WDAFLG		;CLEAR THE VALUES
	LSH	T1,(S1)			;POSITION THE FLAGS
	IORM	T1,WDAFLG		;RESET THE VALUES
	$RETT				;RETURN
	SUBTTL	W$MTXT	--	GET THE TEXT INTO THE MESSAGE

	;THIS ROUTINE WILL GET THE WTO,WTOR AND ACK TEXT INTO THE
	;MESSAGE FOR OUTPUT AND LOGGING
	;THIS ROUTINE IS CALLED WITH S1 CONTAINING THE LINE SIZE DESIRED
	;AND ALL LINES AFTER FIRST WILL BE PRECEDED BY TWO TABS

W$MTXT:	MOVE	T1,WDATXT		;ADDRESS OF THE TEXT
	HRLI	T1,(POINT 7,0)		;MAKE A BYTE POINTER
	MOVE	T2,WTOPTR		;DESTINATION POINTER IN T2
	MOVE	T4,WTOCNT		;GET COUNT OF SPACE IN MESSAGE
	SKIPN	P1			;SPECIAL FORMATTING
	PUSHJ	P,W$TAB			;OUTPUT A TAB
	PUSHJ	P,W$TAB			;YES..ONLY ONE TAB
	SETZM	SRCPTR			;CLEAR SAVED SOURCE POINTER
MTXT.0:	MOVE	T3,S1			;SIZE OF THE LINE DESIRED
MTXT.1:	ILDB	S2,T1			;GET THE BYTE FROM SOURCE
	JUMPE	S2,MTXT.5		;NULL...END OF DATA
	CAIN	S2,.CHCRT		;IS IT A CARRIAGE RETURN
	JRST	MTXT.1			;YES..IGNORE IT
	CAIE	S2,.CHLFD		;IS IT A LINE FEED
	JRST	MTXT.2			;NO..SAVE BYTE
	MOVEI	S2," "			;GET A BLANK
	SETZM	T3			;RESET LINE COUNT
MTXT.2:	CAIE	S2," "			;IS IT A BLANK
	JRST	MTXT.3			;NO JUST SAVE THE DATA
	MOVEM	T1,SRCPTR		;SAVE THE SOURCE POINTER
	MOVEM	T2,DESPTR		;SAVE DESTINATION POINTER
	MOVEM	T4,DESCNT		;MESSAGE COUNT FIELD
MTXT.3:	SOJLE	T4,MTXT.7		;DECREMENT THE COUNT
	IDPB	S2,T2			;PLACE BYTE IN DESTINATION
	SOJG	T3,MTXT.1		;GET THE NEXT BYTE
	SKIPN	SRCPTR			;HAVE A BLANK IN MESSAGE
	JRST	MTXT.4			;FINISH LINE
	SETZM	T1			;CLEAR T1 FOR SRCPTR RESET
	EXCH	T1,SRCPTR		;GET THE SOURCE POINTER AND RESET IT
	MOVE	T2,DESPTR		;GET DESTINATION POINTER
	MOVE	T4,DESCNT		;GET DESTINATION COUNT
MTXT.4:	PUSHJ	P,W$CRLF		;END THE LINE
	JUMPF	MTXT.7			;NO MORE ROOM
	SKIPN	P1			;SPECIAL FORMATTING
	PUSHJ	P,W$TAB			;OUTPUT A TAB
	PUSHJ	P,W$TAB			;YES..ONLY ONE TAB
	JUMPF	MTXT.7			;NO MORE ROOM
	JRST	MTXT.0			;GET NEXT LINE
MTXT.5:	PUSHJ	P,W$CRLF		;END THE LINE
	JUMPF	MTXT.7			;NO MORE ROOM
MTXT.6:	MOVEI	S2,0			;GET A NULL
	IDPB	S2,T2			;SAVE BYTE IN MESSAGE
	MOVEM	T4,WTOCNT		;RESTORE COUNT FOR MESSAGE
	MOVEM	T2,WTOPTR		;RESTORE DESTINATION POINTER
	$RETT				;RETURN TRUE
MTXT.7:	;$STOP(MTL,WTO MESSAGE IS TOO LARGE) ;
	JRST	MTXT.6			;FINISH OFF AND RETURN
	SUBTTL	W$CRLF	--	END THE TEXT LINE WITH CRLF

	;THIS ROUTINE WILL PUT CRLF ON LINE FROM W$MTXT

W$CRLF:	MOVEI	S2,.CHCRT		;GET A CARRIAGE RETURN
	IDPB	S2,T2			;SAVE IN DESTINATION
	SOJL	T4,.RETF		;NO MORE ROOM RETURN FALSE
	MOVEI	S2,.CHLFD		;GET A LINE FEED
	IDPB	S2,T2			;SAVE IN DESTINATION
	SOJL	T4,.RETF		;NO MORE ROOM.RETURN FALSE
	$RETT				;RETURN TRUE


	SUBTTL	W$TAB	--	TAB A LINE IN FOR MESSAGE

W$TAB:	MOVEI	S2,11			;PUT OUT A TAB
	IDPB	S2,T2			;SAVE IN DESTINATION
	SOJL	T4,.RETF		;NO MORE ROOM RETURN FALSE
	$RETT				;RETURN TRUE
	SUBTTL	OPRMES	--	BUILD  A MESSAGE FOR OPR

	;THIS ROUTINE WILL BUILD THE TEXT MESSAGE FOR OPR AND TO BE USED
	;BY LOGGING IF ENABLED


OPRMES:	PUSHJ	P,GETPAG		;GET THE OUTPUT MESSAGE IN MO
	MOVX	S1,.OMDSP		;GET THE DISPLAY TYPE
	STORE	S1,.MSTYP(MO),MS.TYP	;SAVE TYPE IN MESSAGE
	MOVEI	S1,<PAGSIZ-<ARG.DA+2+.OHDRS>>*5 ;NUMBER OF BYTES AVAILABLE
					;SAVE ROOM FOR TRUNCATING
	MOVEM	S1,WTOCNT		;SAVE IN WTOCNT
	MOVSI	S1,(POINT 7,0)		;SETUP BYTE POINTER
	HRRI	S1,ARG.DA+1+.OHDRS(MO)	;ADDRESS TO SAVE TEXT
	MOVEM	S1,WTOPTR		;SAVE THE BYTE POINTER
	MOVE	S1,G$NOW		;GET THE TIME
	MOVEI	P3,ARG.HD+.OHDRS(MO)	;ADDRESS OF FIRST ARGUMENT
	MOVEM	S1,ARG.DA(P3)		;SAVE THE TIME-STAMP
	MOVX	S1,.ORDSP		;OPR DISPLAY BLOCK
	STORE	S1,ARG.HD(P3),AR.TYP	;SAVE THE TYPE
	$RETT				;RETURN TRUE
	SUBTTL	W$MESS	--	SETUP A WTO/WTOR/ACK MESSAGE

W$MESS:	SKIPN	S2,.OFLAG(MI)		;ANY FLAGS SET IN MESSAGE
	JRST	WTOM.1			;NO..PROCESS MESSAGE
	TXNN	S2,WT.PRV		;ANY PRIVILEGED BITS LIT
	JRST	WTOM.1			;NO..CONTINUE ON
	PUSHJ	P,CHKWHL		;WAS USER PRIVILEGED??
	JUMPF	E$IPE			;INSUFFICIENT PRIVILEGE 
	TXZ	S2,WT.JOB		;JOB MESSAGE FLAG
	JUMPE	S2,WTOM.1		;NONE ON..PASS CHECK
WTOM.1:	LOAD	S1,.MSTYP(MI),MS.TYP	;GET MESSAGE TYPE
	CAIE	S1,.OMWTR		;WAS IT A WTOR??
	MOVEI	T1,[ITEXT(	)]	;NO..SAVE TAB FOR FIRST FIELD
	MOVEI	T2,[ITEXT()]		;SAVE NULL OBJECT POINTER
	MOVEI	T3,[ITEXT()]		;SAVE NULL TYPE POINTER
	TXNN	FLAG,F.WOBJ		;WAS THERE AN OBJECT BLOCK
	JRST	WTOM.2			;CHECK OUT TYPE
	MOVEI	T2,[ITEXT(<^B/@WDAOBJ/>)];GET OBJECT BLOCK
	MOVE	S1,@WDAOBJ+OBJ.TY	;GET TYPE FIELD
	CAIE	S1,.OTBAT		;WAS IT BATCH?
	JRST	WTOM.2			;NO..CONTINUE ON
	SKIPE	WDAJOB			;WAS THERE A JOB NUMBER
	MOVEI	T2,[ITEXT(<^B/@WDAOBJ/ JOB #^D/WDAJOB/ >)]
WTOM.2:	TXNE	FLAG,F.WACD		;WAS THERE AN APPLICATION  CODE
	MOVEI	T2,[ITEXT(<^T/@WDAACD/>)];SETUP APPLICATION CODE LINE
					;*** SET LENGTH ON APPLICATION CODE
	TXNN	FLAG,F.WTYP		;TYPE FIELD PRESENT
	JRST	WTOM.3			;NO SKIP OVER
	MOVEI	T3,[ITEXT(<  --^T/@WDATYP/-->)]
	MOVX	S1,WT.NDA		;NO DASHES ON TYPE
	TDNE	S1,.OFLAG(MI)		;WAS IT SPECIFIED
	MOVEI	T3,[ITEXT(<  ^T/@WDATYP/>)]
WTOM.3:	$TEXT	(WTORTN,<^I/(T1)/^I/(T2)/^I/(T3)/^A>)
	TXNE	FLAG,F.WOBJ!F.WACD	;OBJECT OR APPLICATION BLOCK
	JRST	WTOM.4			;YES..BYPASS W$JOBH
	MOVX	S1,WT.SJI		;SUPPRESS JOB INFO
	TDNN	S1,.OFLAG(MI)		;WAS IT SET?
	PUSHJ	P,W$JOBH		;SETUP W$JOBH FIELD
WTOM.4:	$TEXT	(WTORTN,<>)		;OUTPUT CR,LF
	SKIPN	WDATXT			;CHECK IF ANY TEXT DATA
	JRST	MSGFIN			;NO..FINISH THE MESSAGE
	MOVX	S1,WT.NFO		;NO FORMATTING OF MESSAGE
	TDNE	S1,.OFLAG(MI)		;SPECIAL FORMATTING
	JRST	WTOM.6			;YES ..DO IT
	SETZM	P1			;CLEAR FORMATTING FLAG
	MOVEI	S1,^D60			;LINE SIZE
	PUSHJ	P,W$MTXT		;GET THE TEXT FOR WTO
	JRST	MSGFIN			;FINISH THE MESSAGE
	SUBTTL	MSGFIN	--	FINISH OFF DISPLAY MESSAGE


MSGFIN::	SETZ	S1,			;SETUP A NULL
	IDPB	S1,WTOPTR		;SAVE A NULL ON THE END
	HRRZ	S1,WTOPTR		;GET LAST ADDRESS
	ADDI	S1,1			;BUMP IT BY 1
	ANDI	S1,777			;GET MESSAGE LENGTH
	STORE	S1,.MSTYP(MO),MS.CNT	;SAVE THE COUNT
	SUBI	S1,.OHDRS		;SIZE OF ARGUMENT BLOCK
	STORE	S1,ARG.HD(P3),AR.LEN	;SAVE ARGUMENT LENGTH
	AOS	.OARGC(MO)		;BUMP THE ARGUMENT COUNT
	$RETT				;RETURN
WTOM.6:	MOVX	S1,^D80			;SETUP FOR LARGER LINE
	SETOM	P1			;SET FLAG FOR FORMATTING
	PUSHJ	P,W$MTXT		;GET THE DATA
	JRST	MSGFIN			;FINISH THE MESSAGE

WTORTN:	SOSGE	WTOCNT			;ROOM IN MESSAGE
	$RETF				;FALSE RETURN..TRUNCATE MESSAGE
	IDPB	S1,WTOPTR		;SAVE THE BYTE
	$RETT				;RETURN TRUE
	SUBTTL	W$JOBH	--	SETUP A JOB HEADER MESSAGE

	;THIS ROUTINE WILL SETUP THE JOB INFORMATION FOR WTO/WTOR
	;MESSAGES

W$JOBH:	LOAD	S1,G$PRVS,MD.PJB	;GET THE JOB NUMBER
	PUSHJ	P,GETJOB		;GET THE JOB INFO
	TXNE	FLAG,F.WTYP		;WAS THERE A TYPE BLOCK
	$TEXT	(WTORTN,<
		^A>)			;CR,LF,TAB,TAB
	$TEXT	(WTORTN,<^I/@JOBTXT/^A>)	;OUTPUT THE JOB DATA
	$RETT				;RETURN
	SUBTTL	GETJOB	--	GET THE JOB INFORMATION

	;THIS ROUTINE WILL OBTAIN JOB INFORMATION ABOUT A USER GIVEN
	;THE JOB NUMBER
	;CALL	S1/	JOB NUMBER
	;
	;	S1 PRESERVED

GETJOB:: MOVEM	S1,JOBNUM			;SAVE THE JOB NUMBER
	MOVX	S2,JI.PRG		;GET PROGRAM NAME
	PUSHJ	P,I%JINF		;GET THE INFO
	JUMPF	GETJ.3			;ERROR..RETURN
	MOVEM	S2,JOBNAM		;PROGRAM NAME
	MOVX	S2,JI.USR		;GET USER # OR PPN
	PUSHJ	P,I%JINF		;GET VALUE
	JUMPF	GETJ.3			;ERROR..SETUP DEFAULT
	SKIPN	S2			;VALID USER NUMBER
	JRST	GETJ.3			;NO..USE DEFAULT
	MOVEM	S2,JOBID		;SAVE THE ID
IFN	FTUUOS,<
	PUSHJ	P,GETNAM		;GET THE USER NAME
>;END FTUUOS
	MOVX	S2,JI.TNO		;GET THE TERMINAL NUMBER
	PUSHJ	P,I%JINF		;GET THE DATA
	JUMPF	GETJ.3			;ERROR..RETURN
	SKIPGE	S2			;VALID TERMINAL?
	  JRST	[MOVEI	T1,[ITEXT (<Detached>)] ;NO DETACHED
		SETZM	JOBTTY		;SET TERMINAL TO ZERO
		JRST	GETJ.1]		;SAVE VALUE AND CONTINUE
	MOVEM	S2,JOBTTY		;SAVE THE TERMINAL NUMBER
	MOVEI	T1,[ITEXT (<at Terminal ^O/JOBTTY/>)]
GETJ.1:	MOVEM	T1,JOBTER		;SAVE JOB TERMINAL DATA
	MOVX	S2,JI.BAT		;GET BATCH INFO
;*** 7.01 DEPENDENT CODE
	PUSHJ	P,I%JINF		;GET JOB INFO
	JUMPF	GETJ.2			;ERROR..RETURN
	TXNN	S2,OB.BSS		;BATCH STREAM NUMBER SET?
	JRST	GETJ.2			;NO..CONTINUE ON
	MOVEM	S2,G$JDAT		;JOB DATA FLAG
	MOVEI	S2,[ITEXT (<in Batch-Stream ^D/G$JDAT,OB.BSN/>)]
	MOVEM	S2,JOBTER		;SAVE TERMINAL DATA
GETJ.2:	MOVEI	T1,[ITEXT (<JOB ^D/JOBNUM/ ^P/JOBID/ ^I/USRNAM/^I/@JOBTER/>)]
	MOVEM	T1,JOBTXT		;SAVE JOB TEXT POINTER
	$RETT				;RETURN TRUE
GETJ.3:	MOVEI	T1,[ITEXT (<JOB ^D/JOBNUM/ ^P/G$SID/>)]
	MOVEM	T1,JOBTXT		;SAVE AS JOBTXT
	SETOM	JOBTTY			;NO JOB FLAG
	MOVEI	T1,NULTXT		;NULL TEXT
	MOVEM	T1,JOBTER		;NO TERMINAL DATA
	$RETT				;RETURN TRUE

IFN	FTJSYS,<
USRNAM==NULTXT
>;END FTJSYS
IFN	FTUUOS,<
USRNAM:	ITEXT	(<^W6/JOBUSN/^W/JOBUSN+1/ >)
>;END FTUUOS
	SUBTTL	GETUSR	--	GET USER INFO FOR NOTIFY

	;THIS ROUTINE WILL GET EXTRA INFO REQUIRED BY NOTIFY AND USE
	;GET JOB TO GET THE REST

	;CALL	S1/	JOB NUMBER

GETUSR:: PUSHJ	P,GETJOB		;GET JOB INFO
	SKIPLE	JOBTTY			;HAVE VALID TERMINAL
	JRST	GETU.1			;O.K. CONTINUE ON
	SKIPL	JOBTTY			;CHECK FOR NOT VALID OR DETACHED
	PJRST	E$NJD			;NOTIFY JOB DETACHED
	PJRST	E$JDE			;NOTIFY JOB INVALID
GETU.1:	MOVX	S2,JI.JLT		;JOB LOGGED IN TIME
	PUSHJ	P,I%JINF		;GET THE DATA
	MOVEM	S2,JOBJLT		;SAVE JOB LOGGED IN TIME
	$RETT				;O.K..RETURN TRUE
	SUBTTL	GETNAM	--	GET THE USER NAME

	;THIS ROUTINE WILL GET USER NAME FOR A  GIVEN JOB
	;CALL S1/	JOB NUMBER

IFN	FTUUOS,<
GETNAM:	HRLZ	S2,S1			;PLACE JOB NUMBER IN LEFT HALF
	HRRI	S2,.GTNM1		;GET THE USER NAME
	GETTAB	S2,			;GETTAB IT
	  JRST	GETJ.3			;ERROR..RETURN
	MOVEM	S2,JOBUSN		;SAVE IN USER NAME
	HRLZ	S2,S1			;JOB NUMBER IN LEFT HALF
	HRRI	S2,.GTNM2		;SECOND HALF OF NAME
	GETTAB	S2,			;GET IT
	  JRST	GETJ.3			;ERROR..RETURN
	MOVEM	S2,JOBUSN+1		;SAVE THE USER NAME SECOND PART
	POPJ	P,			;RETURN
>;END FTUUOS
	SUBTTL	W$SHOW	--	SHOW ACK MESSAGE FROM QUASAR

	;THIS MESSAGE IS AN ANSWER TO A SHOW COMMAND FROM QUASAR
	;AND IS ALREADY FORMATED.

W$SHOW:	PUSHJ	P,CHKQSR		;CHECK IF QUASAR
	JUMPF	E$ARP			;ERROR..RETURN
	LOAD	S1,.MSFLG(MI)		;GET FLAG WORD
	TXNE	S1,MF.NOM		;NULL ACK
	PJRST	ACKM.1			;LOG THE NULL ACK AND RETURN
	PUSHJ	P,SPGOUT		;SETUP PAGE FOR OUTPUT
	PUSHJ	P,L$SHWA##		;LOG THE MESSAGE
	PUSHJ	P,W$ASND		;SEND THE ACK
	$RETT				;RETURN

	SUBTTL	CHKQSR	--	CHECK FOR QUASAR CODE

	;THIS ROUTINE WILL VERIFY THE MESSAGE ID FROM QUASAR 

CHKQSR:	PUSHJ	P,CHKWHL		;CHECK IF WHEEL
	JUMPF	.POPJ			;INSUFFICIENT PRIVILEGES
	LOAD	S1,MDB.SI(P1)		;GET SYSTEM PID VALUES
	TXZN	S1,<SI.FLG>		;CLEAR FLAG IF SET
	$RETF				;NOT QUASAR...RETURN FALSE
	CAIE	S1,SP.QSR		;FROM QUASAR..
	$RETF				;NOT QUASAR...RETURN FALSE
	$RETT				;O.K..RETURN TRUE

	SUBTTL	W$ASND	--	SEND ACK TO OPR

	;THIS ROUTINE WILL SEND THE MESSAGE TO THE APPROPRIATE OPR
	;AND UPDATE THE COUNTS

W$ASND:	SKIPN	S1,.MSCOD(MI)		;GET THE ACK CODE
	PJRST	ASND.2			;INVALID ACK CODE
	CAMN	S1,[-1]			;IS IT A -1 CODE
	PJRST	RELPAG			;YES..THEN DO NOT SEND TO ANYONE
	PUSHJ	P,VALOPR		;VALIDATE OPR
	JUMPF	ASND.1			;OPR NOT VALID..RELEASE PAGE AND RETURN
	MOVEM	S2,G$OPRA		;SAVE THE OPR ADDRESS 
	AOS	OPR.OC(S2)		;BUMP OUTPUT COUNT
	MOVE	S1,OPR.PD(S2)		;GET OPR PID
	MOVEI	S2,PAGSIZ		;GET SIZE OF MESSAGE
	PJRST	SPDOPR			;SEND THE MESSAGE
ASND.1:	PUSHJ	P,RELPAG		;RELEASE THE PAGE
	PJRST	E$ODE			;OPR DOESN'T EXIST ERROR
ASND.2:	PUSHJ	P,RELPAG		;RELEASE THE PAGE
	PJRST	E$IAC			;INVALID ACK CODE
	SUBTTL	W$ACKM	--	Process an ACK Message

	;THIS ROUTINE WILL VALIDATE AND THEN PROCESS AN
	;ACKNOWLEDGEMENT MESSAGE

W$ACKM:	PUSHJ	P,CHKWHL		;CHECK IF PRIVILEGED
	JUMPF	E$ARP			;ACK REQUIRES PRIVILEGES
	LOAD	S1,.MSFLG(MI)		;GET FLAG WORD
	TXNE	S1,MF.NOM		;NULL ACK
	JRST	ACKM.1			;YES..LOG AND RETURN
	PUSHJ	P,W$VALID		;VALIDATE THE WTO MESSAGE
	JUMPF	.POPJ			;FALSE RETURN...RETURN
	SETZM	WDAFLG			;CLEAR THE FLAGS FOR ACKS
	SETZM	WDAAFL			;CLEAR APPL FLAG FOR ACKS
	PUSHJ	P,OPRMES		;BUILD THE MESSAGE
	PUSHJ	P,W$MESS		;SETUP THE DATA
	JUMPF	WTERRO			;WT ERROR RETURN
	PUSHJ	P,L$ACK##		;LOG THE ACK MESSAGE
	PUSHJ	P,W$ASND		;SEND THE ACK
	$RETT				;RETURN
ACKM.1:	PUSHJ	P,L$NACK##		;LOG NULL ACK
	$RETT				;RETURN


	SUBTTL	TXTMOV	--	Text Move Routine

	;CALLED WITH 
	;	S1/	ADDRESS OF THE DESTINATION
	;	S2/	ADDRESS OF THE SOURCE
	;
	;RETURNS
	;	S1/	UPDATED BYTE POINTER


TXTMOV:	HRLI	S2,(POINT 7,0)		;MAKE A BYTE POINTER
	HRLI	S1,(POINT 7,0)		;BYTE POINTER FOR DESTINATION
	MOVEM	S2,TXTPTR		;SAVE THE SOURCE POINTER
TXTM.1:	ILDB	S2,TXTPTR			;GET FIRST BYTE OF DATA
	JUMPE	S2,TXTM.2		;NULL BYTE ..EXIT
	IDPB	S2,S1			;SAVE THE BYTE
	JRST	TXTM.1			;GET NEXT BYTE
TXTM.2:	IDPB	S2,S1			;SAVE THE NULL FOR ASCIZ
	$RETT				;RETURN
	SUBTTL	CMDMES	--	COMMAND MESSAGE PROCESSOR

	;THIS ROUTINE WILL PROCESS A COMMAND PASSED IN THE MESSAGE AND
	;PASS IT ON TO THE APPROPRIATE OPR (DN60 ONLY)
	PPPLLL==777000			;PORT /LINE MASK

IFN	FTDN60,<
CMDMES:	PUSHJ	P,CHKWHL		;BETTER BE WHEEL OR OPERATOR
	JUMPF	.POPJ			;ERROR..RETURN
	MOVEI	S1,.OHDRS(MI)		;GET THE START OF THE BLOCKS
	PUSHJ	P,P$SETU		;SETUP THE POINTER
	PUSHJ	P,P$NFLD		;GET NEXT FIELD
	JUMPF	E$ITM			;INVALID TYPE ARGUMENT
	CAIE	S1,.ORNOD		;WAS IT A NODE BLOCK
	PJRST	E$ITM			;INVALID TYPE ARGUMENT
	MOVE	T3,ARG.DA(S2)		;GET THE NODE NAME IN SIXBIT
	PUSHJ	P,P$NFLD		;GET THE NEXT FIELD
	JUMPF	E$ITM			;INVALID TYPE MESSAGE
	CAIE	S1,.ORD60		;WAS IT A DN60 BLOCK
	PJRST	E$ITM			;INVALID BLOCK TYPE
	DMOVE	P1,ARG.DA(S2)		;GET THE DATA WORDS
	HLRZ	S1,P1			;GET THE PORT NUMBER
	HRRO	S2,P1			;SETUP -1,, LINE NUMBER
	STORE	S1,S2,PPPLLL		;SAVE  AS -1,,PPPLLL
	MOVEM	S2,.MSCOD(MI)		;SAVE ACK CODE
	EXCH	S2,G$SND		;SAVE AS THE SENDER
	MOVE	S1,G$SND		;GET THE HANDLE
	PUSHJ	P,VALOPR		;VALIDATE THE OPR
	JUMPF	E$ONS			;OPR NOT SETUP
	MOVEM	S2,G$OPRA		;SAVE OPR ADDRESS
	PUSHJ	P,P$TEXT		;CHECK FOR A TEXT BLOCK
	JUMPF	E$ITM			;INVALID TYPE BLOCK
	MOVEI	S1,ARG.DA(S1)		;ADDRESS OF THE STRING
	MOVEM	S1,PARBLK+PAR.SR	;SAVE THE TEXT ADDRESS
	MOVEI	S1,INITCM##		;ADDRESS OF THE TABLES
	MOVEM	S1,PARBLK+PAR.TB	;SAVE THE TABLE ADDRESS
	MOVEI	S1,PAR.SZ		;SIZE OF THE BLOCK
	MOVEI	S2,PARBLK		;ADDRESS OF THE BLOCK
	PUSHJ	P,PARSER##		;PROCESS THE MESSAGE
	JUMPT	CMDM.1			;O.K..
	MOVE	T1,PRT.EM(S2)		;ADDRESS OF THE MESSAGE
	MOVEM	T1,G$ARG1		;SAVE THE MESSAGE
	PJRST	E$PER			;PARSER ERROR RETURN
CMDM.1:	MOVE	MI,PRT.CM(S2)		;GET MESSAGE ADDRESS
	JRST	COMMAN			;PROCESS THE COMMAND
>;END FTDN60
SUBTTL	COMMAN  --  Routine to Handle Parser Command Message

;THIS ROUTINE TAKES THE MESSAGE SENT BY THE PARSER AS THE RESULT OF A
;VALID COMMAND AND DISPATCHES TO THE APPROPRIATE ACTION ROUTINE BASED
;ON THE COMMAND TYPE
;IT IS CALLED WITH MI POINTING TO THE PAGE CONTAINING THE MESSAGE

COMMAN:	MOVE	S1,G$SND		;GET THE SENDERS PID
	PUSHJ	P,VALOPR		;VALIDATE THE OPERATOR
	JUMPF	E$ONS			;OPR NOT SETUP
	MOVEM	S2,G$OPRA		;SAVE OPR ENTRY ADDRESS
IFN	FTJSYS,<
	MOVX	T1,MD.PWH!MD.POP	;GET WHEEL AND OPR FLAGS
	MOVX	S1,OP.REM		;IS IT REMOTE OPERATOR
	TDNE	S1,OPR.FL(S2)		;CHECK THE FLAG
	ANDCAM	T1,G$PRVS		;YES..CLEAR PRIVILEGES FOR MESSAGES
>;END FTJSYS
	MOVE	T1,OPR.FL(S2)		;GET THE FLAGS
	TXNE	T1,OP.NST		;CHECK IF SETUP?
	PJRST	E$ONS			;OPERATOR NOT SETUP
	TXNE	T1,OP.ABT		;WAS ABORT SET
	$RETT				;YES..EXIT NOW
	PUSHJ	P,L$CMD##		;LOG THE COMMAND
	SKIPG	T1,.OARGC(MI)		;GET THE ARGUMENT COUNT
	JRST	E$ICS			;INVALID COUNT SPECIFIED
	CAILE	T1,COM.AL		;LESS THAN MAX SIZE
	JRST	E$ICS			;WRONG COUNT SPECIFIED
	MOVX	T2,CM.NPR		;NO PROCESSING REQUIRED
	TDNE	T2,.OFLAG(MI)		;CHECK IF SET??
	$RETT				;YES..RETURN TRUE
COMM.1:	SKIPN	S2,COM.PB(MI)		;WAS PARSER BLOCK FILLED IN
	PJRST	E$CMI			;COMMAND MESSAGE INVALID
	SKIPE	S1,COM.TY(MI)		;CHECK FOR APPLICATION MESSAGE
	JRST	COMM.6			;YES..SEND TO APPLICATION
	ADDI	S2,(MI)			;POINT PB AT THE BLOCK
	MOVE	S1,S2			;GET THE BLOCK POINTER
	PUSHJ	P,P$SETU		;SETUP THE POINTER
	PUSHJ	P,P$KEYW		;GET THE FIRST KEYWORD
	JUMPF	COMM.3			;INVALID COMMAND
	MOVSI	T1,-COMLEN		;GET NEGATIVE TABLE LENGTH FOR AOBJN
COMM.2:	HLRZ	T2,COMTAB(T1)		;GET THE CODE FOR THIS INDEX
	CAME	T2,S1			;MATCH?
	AOBJN	T1,COMM.2		;LOOP 'TILL COUNT EXPIRES OR MATCH IS FOUND
	JUMPGE	T1,E$IFC		;ILLEGALLY FORMATTED COMMAND
	HRRZ	T1,COMTAB(T1)		;GET DISPATCH ADDRESS FROM TABLE
	HRRZ	T2,@T1			;GET THE ROUTINE ADDRESS IN T2
	PUSHJ	P,GETPAG		;OUTPUT PAGE IN MO
	HLRZ	S1,@T1			;PLACE CODE TYPE IN S1
	STORE	S1,.MSTYP(MO),MS.TYP	;SAVE TYPE IN MESSAGE
	MOVEI	P3,.OHDRS(MO)		;FREE POINTER FOR OUTPUT
	PUSHJ	P,(T2)			;DISPATCH TO CORRECT ROUTINE
	JUMPF	COMM.3			;BAD RETURN..SHOW ERROR
	SKIPN	G$ERR			;ANY ERROR CODES SET
	$RETT				;RETURN
	JRST	COMM.5			;DUMP ERROR IN LOG
COMM.3:	PUSHJ	P,E$IFC			;ILLEGALLY FORMATTED COMMAND
	JRST	COMM.5			;PUT MESSAGE IN LOG
COMM.4:	PUSHJ	P,E$MTS			;MESSAGE TOO SHORT
COMM.5:	CAME	MO,G$OUTP		;WAS PAGE RELEASE ALREADY
	PJRST	RELPAG			;NO,,RELEASE PAGE AND RETURN
	$RETT				;JUST RETURN
COMM.6:	PUSHJ	P,FNDAPL		;FIND THE APPLICATION
	JUMPF	E$IFC			;INVALID FIELD IN COMMAND
COMM.7:	MOVE	T1,APLTAB+1(S2)		;GET COMMAND TABLE ENTRY
	HLRZM	T1,G$ARG1		;SAVE THE NAME
	SKIPN	T2,APLPID(S2)		;IS THERE A PID THERE
	  JRST	TAKABT			;INVALID APPLICATION SPECIFIED
	MOVE	T1,G$SND		;GET SENDERS PID
	MOVEM	T1,.MSCOD(MI)		;SAVE IN CODE WORD
	PUSHJ	P,SPGOUT		;SETUP THE OUTPUT PAGE
	MOVEI	S2,PAGSIZ		;SEND A PAGE
	MOVE	S1,T2			;GET THE PID
	PUSHJ	P,SNDPID		;SEND THE MESSAGE
	JUMPT	.POPJ			;O.K..RETURN
	PUSHJ	P,RELPAG		;RELEASE THE PAGE
	PJRST	TAKABT			;DO TAKE FILE ABORT
	SUBTTL	FNDAPL	--	FIND THE APPLICATION

	;THIS ROUTINE WILL FIND THE APPLICATION
	;
	;S1/	CODE OF APPLICATION
	;
	;RETURN TRUE:	S1/	CODE OF APPLICATION
	;		S2/	OFFSET INTO CODE TABLE

FNDAPL:	MOVSI	S2,-NUMAPL		;GET NUMBER OF ENTRIES
	SKIPN	S2			;ANY ENTRIES
	$RETF				;NONE..RETURN FALSE
FNDA.1:	MOVE	T1,APLCOD(S2)		;GET THE FIRST ENTRY
	CAMN	S1,T1			;DOES IT MATCH
	$RETT				;MATCH..RETURN TRUE
	AOBJN	S2,FNDA.1		;TRY NEXT ENTRY
	$RETF				;NOT FOUND..RETURN FALSE
SUBTTL	Dispatch Table for Command Messages


;EACH ENTRY HERE HAS THE APPROPRIATE KEYWORD CODE IN THE LH AND
;THE ADDRESS OF THE ROUTINE FOR THAT COMMAND IN THE RIGHT HALF

COMTAB:	.KYALI,,[.OMALI,,Q$ALGN##]	;ALIGN COMMAND
	.KYBKS,,[.OMBKS,,Q$BSPACE##]	;BACKSPACE COMMAND
	.KYCNC,,[.OMCAN,,Q$CANCEL##]	;CANCEL COMMAND
	.KYCLO,,[0,,L$CLOS##]		;CLOSE COMMAND
	.KYCNT,,[.OMCON,,Q$CONTIN##]	;CONTINUE COMMAND
IFN	FTDN60,<
	.KYDEF,,[.OMDEF,,Q$DEFINE##]	;DEFINE COMMAND
>;END FTDN60
	.KYDEL,,[.OMDEL,,Q$DELETE##]	;DELETE COMMAND
	.KYDIS,,[.OMDIS,,DISABLE]	;DISABLE MESSAGE
	.KYDSM,,[.OTDSM,,Q$DISMOUNT##]	;DISMOUNT COMMAND
	.KYENA,,[.OMENA,,ENABLE]	;ENABLE MESSAGE
	.KYFWS,,[.OMFWS,,Q$FSPACE##]	;FORWARDSPACE COMMAND
	.KYHLD,,[.OMHLD,,Q$HOLD##]	;HOLD
	.KYIDN,,[.OTIDN,,Q$IDENTIFY##]	;IDENTIFY COMMAND
TOPS10<	.KYLOC,,[.OMLOC,,Q$LOCK##]>	;LOCK COMMAND
	.KYMOD,,[.OMMOD,,Q$MODIFY##]	;MODIFY COMMAND
;	.KYMTN,,[.OTMTS,,Q$MOUNT##]	;MOUNT COMMAND FOR TAPES
	.KYPAU,,[.OMPAU,,Q$PAUSE##]	;PAUSE COMMAND
IFN	FTUUOS,<
	.KYREC,,[.OTREC,,Q$RECOGNIZE##]	;RECOGNIZE COMMAND
>;END FTUUOS
	.KYREL,,[.OMREL,,Q$RELEASE##]	;RELEASE, PROCESSED LIKE HOLD
	.KYREQ,,[.OMREQ,,Q$REQUE##]	;REQUEUE COMMAND
	.KYRPT,,[0,,REPORT]		;REPORT COMMAND
	.KYRTE,,[.OMRTE,,Q$ROUTE##]	;ROUTE COMMAND
	.KYRSP,,[.OMRSP,,RESPON]	;RESPOND COMMAND
	.KYSND,,[.OMDSP,,SEND]		;SEND COMMAND
	.KYSET,,[.OMSET,,Q$SET##]	;SET COMMAND
	.KYSHW,,[.OMSHS,,SHOW]		;SHOW COMMAND ..DEFAULT TYPE OF STATUS
	.KYSHD,,[.OMSHT,,Q$SHUTDN##]	;SHUTDOWN COMMAND
	.KYSTA,,[.OMSTA,,Q$START##]	;START COMMAND
	.KYSUP,,[.OMSUP,,Q$SUPPRE##]	;SUPPRESS COMMAND
TOPS20 <.KYSWI,,[.OTSWI,,Q$SWITCH##]>	;SWITCH COMMAND
	.KYTAK,,[0,,TAKCMD]		;TAKE COMMAND
TOPS10	<.KYULC,,[.OMULC,,Q$ULOCK##]>	;UNLOCK COMMAND
;	.KYUNL,,[.OTUNL,,Q$UNLOAD##]	;UNLOAD COMMAND
COMLEN==.-COMTAB
	SUBTTL	TAKCMD	--	TAKE COMMAND SETUP ROUTINE

	;THIS COMMAND WILL SETUP THE OPR AS IN A TAKE COMMAND
	;BY TURNING ON A FLAG IN THE OPR DATA BASE

TAKCMD:	PUSHJ	P,RELPAG		;RETURN THE PAGE
	MOVE	S1,G$OPRA		;GET OPR ADDRESS
	MOVX	S2,OP.TAK		;GET TAKE FLAG
	IORM	S2,OPR.FL(S1)		;SAVE THE FLAG
	$RETT				;AND RETURN


	SUBTTL	TAKEND	--	END OF TAKE COMMAND

	;THIS ROUTINE WILL CLEAR TAKE FILE FLAGS IN OPR DATA BASE

TAKEND:	MOVE	S1,G$SND		;GET THE SENDER
	PUSHJ	P,VALOPR		;VALIDATE THE OPERATOR
	JUMPF	E$ONS			;OPR NOT SETUP
	MOVEM	S2,G$OPRA		;SAVE OPR ADDRESS
	MOVX	S1,OP.TAK!OP.ABT	;GET TAKE FLAG
	ANDCAM	S1,OPR.FL(S2)		;CLEAR THE FLAG
	$RETT				;RETURN

	SUBTTL	TAKABT	--	ABORT TAKE COMMAND ROUTINE

	;THIS ROUTINE WILL GENERATE ERROR FOR TAKE FILE ABORT
	;WHERE G$ARG1 ALREADY CONTAINS THE ADDRESS OF THE STRING
	;FOR THE ERROR MESSAGE

TAKABT:	MOVE	S2,G$OPRA		;GET OPR ADDRESS
	MOVE	S1,OPR.FL(S2)		;GET THE FLAGS
	TXNN	S1,OP.TAK		;WAS IT A TAKE COMMAND
	PJRST	E$IAP			;INVALID PROCESS..NOT RUNNING
	TXOE	S1,OP.ABT		;WAS ABORT SET
	$RETT				;YES...JUST RETURN
	MOVEM	S1,OPR.FL(S2)		;RESET THE FLAGS
	MOVE	S1,COM.CM(MI)		;GET OFFSET FOR TEXT
	ADDI	S1,ARG.DA(MI)		;POINTER TO TEXT
	MOVEM	S1,G$ARG2		;SAVE THE ADDRESS
	MOVE	S2,S1			;GET THE ADDRESS
	HRLI	S2,(POINT 7,0)		;MAKE A POINTER
TAKA.1:	ILDB	S1,S2			;GET A BYTE
	JUMPE	S1,TAKA.2		;NULL EXIT
	CAIE	S1,.CHCRT		;IS IT A CARRIAGE RETURN
	JRST	TAKA.1			;TRY NEXT ONE
	SETZ	S1,0			;MAKE A NULL
	DPB	S1,S2			;REPLACE WITH A NULL
TAKA.2:	PJRST	E$TAB			;TAKE ABORT
	SUBTTL	GETPAG	--	GET AN OUTPUT PAGE IN MO

	;THIS ROUTINE WILL GET A PAGE ADDRESS SETUP IN MO BY EITHER
	;GETTING A NEW PAGE OR USING A RETURNED PAGE TO RELPAG

GETPAG:: SKIPE	S1,G$OUTP		;ANY OUTPUT PAGE SETUP
	JRST	OUTP.1			;YES..USE IT
	PUSHJ	P,M%GPAG		;GET A PAGE
	JRST	OUTP.2			;BYPASS THE CLEARING OF PAGE
OUTP.1:	SETZM	G$OUTP			;CLEAR THE FLAG
	PUSHJ	P,.ZPAGA		;CLEAR THE PAGE
OUTP.2:	MOVE	MO,S1			;SAVE ADDRESS IN MO
	$RETT				;RETURN TRUE





	SUBTTL	RELPAG	--	RETURN OUTPUT PAGE FOR REUSE

	;SETS UP SAVED WORD G$OUTP WITH ADDRESS OF PAGE

RELPAG:: SKIPE	S1,G$OUTP		;IS THERE A PAGE ALREADY
	JRST	FINP.1			;ALREADY SET..FREE THE PAGE
	MOVEM	MO,G$OUTP		;SAVE PAGE ADDRESS
	$RETT				;RETURN
FINP.1:	PUSHJ	P,M%RPAG		;RELEASE THE PAGE
	MOVEM	MO,G$OUTP		;REPLACE WITH CURRENT PAGE
	$RETT				;RETURN TRUE
	SUBTTL	ERRALL	--	Error Message to All


	;This routine will Build the ACK for an error and send it to
	;all Operators on the system


ERRALL:: LOAD	S1,G$PRVS,MD.PJB	;GET JOB NUMBER
	PUSHJ	P,GETJOB		;GET JOB INFO
	PUSHJ	P,BLDACK		;BUILD THE ACK
	SETOM	S1			;SEND TO ALL
	SETZM	G$ERR			;CLEAR ERROR WORD
	SETOM	G$ASND			;FORCE MESSAGE OUT
	PJRST	SNDAOP			;SEND TO ALL OPERATOR
SUBTTL	ENABLE AND DISABLE COMMANDS

	;THE ENABLE AND DISABLE COMMANDS ARE COMPLEMENTS OF EACH OTHER
	;FOR ALL ACTIONS

DISABLE:	SETOM	P1			;SET FLAG FOR DISABLE
	SKIPA				;SKIP OVER ENABLE SETUP
ENABLE:	SETZM	P1			;SET FLAG FOR ENABLE
	PUSHJ	P,P$KEYW		;GET A KEYWORD
	JUMPF	.POPJ			;ERROR..CHECK OTHER OPTIONS
	MOVEI	S2,ENADSP		;ENABLE DISPATCH TABLE
	PUSHJ	P,TABSRC		;SEARCH THE TABLE
	JUMPF	.POPJ			;ERROR..RETURN
	PJRST	(S2)			;PROCESS ROUTINE AND RETURN


ENADSP:	$STAB
	.KYAVR,,Q$ETAPE##		;ENABLE AVR
	.KYQUE,,ENAQUE			;ENABLE QUEUE REQUESTS
	.KYLGG,,ENALOG			;ENABLE LOGGING
	.KYOPD,,ENAODP			;ENABLE OUTPUT-DISPLAY
TOPS20<	.KYCLS,,ENACLS>			;ENABLE CLASS SCHEDULER
TOPS20<	.KYRET,,ENARET>			;ENABLE FILE-RETREVIAL WAITS
TOPS10<	.KYASR,,Q$ESTR##>		;ENABLE ASR
	$ETAB
	SUBTTL	ENAODP	--	ENABLE OUTPUT-DISPLAY

ENAODP:	PUSHJ	P,P$KEYW		;GET A KEYWORD
	JUMPF	.POPJ			;ERROR..RETURN
	SETZ	P2,			;CLEAR THE FLAG
	CAIG	S1,.OTMAX		;OBJECT SPECIFIED
	JRST	ENAOBJ			;ENABLE/DISABLE BY OBJECT
	CAIL	S1,APLBEG		;IS IT AN APPLICATION
	JRST	ENAAPL			;YES..ENABLE BY APPLICATION
	CAIE	S1,.KYALM		;IS IT ALL MESSAGES
	$RETF				;NO..RETURN FALSE
	SETZ	P2,0			;CLEAR P2
ENAO.1:	PUSHJ	P,P$SWIT		;CHECK FOR A SWITCH
	JUMPF	ENAO.2			;FAILS DO THE SET
	MOVX	S2,OP.AJB		;SETUP ALL JOB MESSAGES
	CAIN	S1,.SWJOB		;IS IT JOB MESSAGES
	JRST	ENAO.3			;DO THE SET AND TRY NEXT ONE
	MOVX	S2,OP.AOP		;OPERATOR ACTION MESSAGES
	CAIN	S1,.SWOAM		;OPERATOR ACTION MESSAGES
	JRST	ENAO.3			;DO THE SET AND GET NEXT ONE
	MOVX	S2,OP.OTH		;GET OTHER(INFORMATION MESSAGES)
	CAIN	S1,.SWOTH		;WAS IT OTHER
	JRST	ENAO.3			;SET THE VALUE
	$RETF				;BAD VALUE
ENAO.2:	SKIPN	P2			;ANY VALUES SET
	MOVX	P2,OP.ALL		;SETUP ALL
	PJRST	ENASET			;SET THE VALUES FOR OPR
ENAO.3:	IOR	P2,S2			;SAVE THE FLAGS
	JRST	ENAO.1			;TRY AGAIN


ENAQUE:	PUSHJ	P,CHKWHL		;MAKE SURE PRIVILEGED
	JUMPF	E$IPE			;INSUFFICIENT PRIVILEGES
	PJRST	CMDEND			;FINISH COMMAND AND SEND
	SUBTTL	ENALOG	--	ENABLE LOG COMMAND

	;THIS ROUTINE WILL EITHER OPEN OR CLOSE THE LOG FILE WHERE POSSIBLE
	;ELSE GENERATE AN ERROR

ENALOG:	PUSHJ	P,CHKWHL		;IS IT A WHEEL?
	JUMPF	E$IPE			;NO..INSUFFIECINT PRIVILEGES
	PUSHJ	P,P$CFM			;IS THERE A CONFIRM?
	JUMPF	.POPJ			;NO..BAD COMMAND
	SKIPN	P1			;DISABLING?
	  JRST	ENAL.1			;ENABLE LOG
	PUSHJ	P,L$REL##		;RELEASE THE LOG FILE
	JUMPF	.RETT			;ERROR RETURN.. MESSAGE GENERATED
	SETZM	LOGINT##		;LOGGING DISABLED
	SETZM	G$CHKP			;CLEAR THE CHECKPOINT TIMER
	PUSHJ	P,E$LFC			;SET LOG FILE CLOSED
ENAL.0:	PUSHJ	P,RELPAG		;RELEASE THE PAGE
	PJRST	ERRALL			;ERROR MESSAGE TO ALL OPERATORS
ENAL.1:	PUSHJ	P,L$OPNL##		;OPEN THE LOG
	JUMPF	.RETT			;ERROR..RETURN
	SETOM	LOGINT##		;MARK LOGGING ENABLED
	PUSHJ	P,E$OLO			;ORION LOG FILE OPEN
	PJRST	ENAL.0			;FINISH IT OFF
	SUBTTL	ENAOBJ	--	ENABLE OBJECT MESSAGES

	;THIS ROUTINE WILL SET APPROPRIATE FIELDS FOR OBJECT DISPLAYS

ENAOBJ:	MOVE	T4,S1			;SAVE THE VALUE
	TXO	P2,WO.ALL		;SET ALL FLAGS
	PUSHJ	P,P$SWIT		;CHECK FOR A SWITCH
	JUMPF	ENABO2			;NO..PROCESS AS IS
	TXZ	P2,WO.ALL		;GE CURRENT VALUES
ENABO1:	CAIN	S1,.SWALL		;WAS IT AN ALL
	TXO	P2,WO.ALL		;SET ALL FLAGS
	CAIN	S1,.SWJOB		;WAS IT JOB MESSAGES
	TXO	P2,WO.JOB		;SET JOB MESSAGE
	CAIN	S1,.SWOAM		;OPERATOR ACTION MESSAGE
	TXO	P2,WO.OAC		;SET OPR MESSAGES
	CAIN	S1,.SWOTH		;WAS IT OTHER
	TXO	P2,WO.EVM		;SET EVERYTHING
	JUMPE	P2,.RETF		;NONE SET..ERROR
	PUSHJ	P,P$SWIT		;CHECK FOR OTHER SWITCHES
	JUMPT	ENABO1			;TRY NEXT ONE
ENABO2:	MOVE	T4,OBJBLK(T4)		;GET CURRENT VALUE
	IMULI	T4,3			;COMPUTE VALUE
	MOVN	T4,T4			;GET NEGATIVE VALUE
	LSH	P2,(T4)			;POSITION IT
	PJRST	ENASET			;SET THE VALUE


ENAAPL:	MOVE	T4,S1			;GET THE VALUE
	SUBI	T4,APLBEG		;GET VALUE FROM OFFSET
	TXO	P2,1B0			;SET FIRST BIT
	MOVNS	T4,T4			;GET NEGATIVE VALUE
	LSH	P2,(T4)			;POSITION IT
ENAA.0:	MOVE	S2,G$OPRA		;GET OPR ENTRY ADDRESS
	SKIPE	P1			;ENABLE...
	JRST	ENAA.1			;NO...DISABLE VALUES
	ANDCAM	P2,OPR.AF(S2)		;UPDATE THE VALUES
	SKIPA				;SKIP LAST VALUES
ENAA.1:	IORM	P2,OPR.AF(S2)		;UPDATE THE VALUES
	PJRST	E$ODM			;OUTPUT DISPLAY MODIFIED
	SUBTTL	ENASET	--	SET THE OPERATOR MESSAGES

ENASET:	MOVE	S2,G$OPRA		;GET OPR ENTRY ADDRESS
	SKIPE	P1			;ENABLE...
	JRST	ENAS.1			;NO...DISABLE VALUES
	ANDCAM	P2,OPR.OF(S2)		;UPDATE THE VALUES
	SKIPA				;SKIP LAST VALUES
ENAS.1:	IORM	P2,OPR.OF(S2)		;UPDATE THE VALUES
	CAME	P2,[OP.ALL]		;WAS IT FOR ALL
	PJRST	E$ODM			;NO JUST SEND ACK
	MOVX	P2,OP.AAP		;SET FOR ALL APPLICATIONS
	JRST	ENAA.0			;SET THOSE ALSO
	SUBTTL	ENACLS	--	ENABLE CLASS SCHEDULER COMMANDS


	;CLASS SCHEDULER SETTING FOR THE -20

IFN	FTJSYS,<
ENACLS:	PUSHJ	P,CHKWHL		;IS IT A WHEEL?
	JUMPF	E$IPE			;NO..INSUFFIECINT PRIVILEGES
	SETZM	P2			;SCHEDULER VALUES
ENAC.1:	PUSHJ	P,P$CFM			;END OF COMMAND
	JUMPT	ENAC.3			;DO THE FUNCTION
	PUSHJ	P,P$SWIT		;CHECK FOR A SWITCH
	JUMPF	.POPJ			;ERROR..RETURN
	CAIE	S1,.SWCAS		;WAS IT CLASS ASSIGNMENTS
	JRST	ENAC.2			;NO..TRY WINDFALL
	PUSHJ	P,P$KEYW		;GET THE KEYWORD
	JUMPF	.POPJ			;ERROR..RETURN
	SETZM	T2			;CLEAR INDICATOR WORD
	CAIN	S1,.KYACT		;IS IT BY ACCOUNT?
	MOVX	T2,SK%ACT		;GET THE ACCOUNT FLAG
	IOR	P2,T2			;PLACE VALUES IN P2
	JRST	ENAC.1			;CHECK FOR END
ENAC.2:	CAIE	S1,.SWWFL		;WINDFALL?
	$RETF				;NO..BAD COMMAND
	PUSHJ	P,P$KEYW		;GET THE KEYWORD
	JUMPF	.POPJ			;ERROR..RETURN
	SETZM	T2			;CLEAR THE VALUE
	CAIN	S1,.KYWHD		;WAS IT WITHHELD
	MOVX	T2,SK%WDF		;WITHHOLD WINDFALL
	IOR	P2,T2			;PLACE VALUE IN P2
	JRST	ENAC.1			;CHECK FOR THE END
ENAC.3:	SKIPE	P1			;ENABLE COMMAND
	MOVX	P2,SK%STP		;TURN OF SCHEDULER
	MOVX	S1,.SKICS		;GET THE FUNCTION
	MOVEI	S2,T1			;BLOCK IN T1
	MOVEI	T1,2			;LENGTH OF THE BLOCK
	MOVE	T2,P2			;GET THE DATA
	SKED%				;DO THE FUNCTION
	  ERJMP	ENAC.4			;TRAP ERROR
	MOVEI	S1,[ASCIZ/Enabled/]	;ENABLED
	SKIPE	P1			;ENABLING?
	MOVEI	S1,[ASCIZ/Disabled/]	;DISABLED
	MOVEM	S1,G$ARG1		;SAVE THE ERROR
	PJRST	E$CSE			;CLASS SCHEDULER ENABLED/DISABLED
ENAC.4:	MOVE	S1,[EXP -2]			;LAST -20 ERROR
	MOVEM	S1,G$ARG1		;SAVE THE ARGUMENT
	PJRST	E$CSF			;CLASS SCHEDULER ERROR
>;END FTJSYS
	SUBTTL	ENARET	--	ENABLE FILE RETREVIAL WAITS

IFN	FTJSYS,<
ENARET:	PUSHJ	P,CHKWHL		;IS IT A WHEEL?
	JUMPF	E$IPE			;NO..INSUFFIECINT PRIVILEGES
	MOVEI	T1,[ASCIZ/Enable/]	;GET THE ENABLE
	SKIPE	P1			;ENABLE OR DISABLE?
	MOVEI	T1,[ASCIZ/Disable/]	;DISABLING
	MOVEM	T1,G$ARG1		;SAVE THE VALUE
	MOVE	S2,P1			;VALUE SAME AS ENABLE/DISABLE VALUE
	MOVEI	S1,.SFRTW		;SET FUNCTION CODE
	SMON				;SET THE VALUE
	ERJMP	E$RWF			;TRAP THE ERROR AND GENERATE A MESSAGE
	PJRST	E$FRW			;FILE RETREVIAL WAITS MODIFIED
>;END FTJSYS
	SUBTTL	NOTIFY COMMAND

	;OUTPUT TO TERMINAL FOR QUASAR

NOTIFY:	PUSHJ	P,CHKWHL		;MUST BE WHEEL
	JUMPF	E$NRW			;NOTIFY REQUIRES WHEEL
	MOVEI	S1,.OHDRS(MI)		;SETUP POINTER TO BLOCK
	PUSHJ	P,P$SETU		;SETUP THE PARSER POINTER
	MOVX	S1,NT.MLU		;NOTIFY VIA MAIL
	TDNE	S1,.OFLAG(MI)		;IS IT SET?
	JRST	NOTI.1			;YES..DO MAIL
	PUSHJ	P,L$NTFY##		;LOG THE NOTIFY
	PUSHJ	P,P$NARG		;GET THE NEXT ARGUMENT
	MOVE	P1,S2			;SAVE THE BLOCK ADDRESS
	CAIE	S1,.JOBID		;JOB ID BLOCK
	PJRST	E$IFC			;BAD MESSAGE
	LOAD	S1,JBI.JB(P1)		;GET THE JOB NUMBER
	PUSHJ	P,GETUSR		;GET USER INFO
	JUMPF	.POPJ			;NOT THERE..RETURN
	LOAD	S1,JBI.LI(P1)		;GET LOGGED IN TIME
	CAME	S1,JOBJLT		;SAME JOB
	PJRST	E$JDE			;JOB TO NOTIFY NOT THERE
	PUSHJ	P,P$NEXT		;GET TO NEXT FIELD
	PUSHJ	P,P$TEXT		;TEXT BLOCK
	JUMPF	E$IFC			;BAD MESSAGE
	MOVEI	S2,ARG.DA(S1)		;POINT TO THE DATA
	MOVE	S1,JOBTTY		;GET TERMINAL NUMBER
	PUSHJ	P,SNDTTY		;SEND THE MESSAGE
	$RETT				;RETURN
NOTI.1:
IFN	FTUUOS,<
	$RETT				;RETURN FOR NOW
>;END FTUUOS
IFN	FTJSYS,<
	PUSHJ	P,P$TEXT		;GET THE TEXT
	JUMPF	E$IFC			;ILLEGALLY FORMATTED COMMAND
	HRROI	S2,ARG.DA(S1)		;POINTER TO TEXT
	MOVEM	S2,NFYTXT		;NOTIFY TEXT POINTER
	PUSHJ	P,P$DIR			;GET THE DIRECTORY
	JUMPF	E$IFC			;BAD COMMAND
	MOVEM	S1,NFYDIR		;NOTIFY DIRECTORY
	PUSHJ	P,P$NFLD		;GET NEXT FIELD DATA
	JUMPF	E$IFC			;SHOULDN'T FAIL
	CAIE	S1,.NTSUB		;IS IT THE SUBJECT
	PJRST	E$IFC			;BAD COMMAND
	HRROI	S1,ARG.DA(S2)		;GET THE DATA POINTER
	MOVEM	S1,NFYSUB		;NOTIFY SUBJECT
	PUSHJ	P,MLINIT##		;INIT THE CALL
	MOVEI	S1,NFYDIR		;GET ADDRESS OF BLOCK
	MOVEI	S2,1			;DEC MAIL
	PUSHJ	P,MLTOWN##		;MAIL IT
	PUSHJ	P,MLDONE##		;FINISHED IT..
	$RETT				;RETURN
>;END FTJSYS
	SUBTTL	SEND COMMAND

	;THIS ROUTINE WILL SEND A MESSAGE TO THE SPECIFIED OBJECT
	;FOR BATCH THE MESSAGES ARE SENT TO QUASAR AND THEN TO BATCH


SEND:	SETZM	SCRWRD			;CLEAR THE SCRATCH WORD FOR A FLAG
	PUSHJ	P,BLDOBJ		;GET THE OBJECT BLOCK
	JUMPF	SEND.4			;NO..TRY FOR ALL
	MOVEI	P1,.OHDRS+ARG.DA(MO)	;ADDRESS OF OBJECT BLOCK
	MOVE	S2,OBJ.TY(P1)		;GET THE OBJECT TYPE
	CAIN	S2,.OTBAT		;WAS IT BATCH?
	SETOM	SCRWRD			;SET THE FLAG WORD
	PUSHJ	P,BLDSND		;BUILD THE SEND MESSAGE
	JUMPF	.POPJ			;ERROR..RETURN
	MOVE	P2,S1			;ADDRESS OF MESSAGE TEXT
	SKIPN	SCRWRD			;BATCH OBJECT ?
	JRST	SEND.1			;NO..TRY OTHER OPTIONS
	MOVX	S1,.OMSND		;SEND BATCH MESSAGE
	STORE	S1,.MSTYP(MO),MS.TYP	;SAVE THE TYPE
	HRRZ	S2,SNDPTR		;GET THE ENDING ADDRESS
	SUBI	S2,-1(P3)		;GET SIZE OF THE BLOCK
	MOVX	S1,.CMTXT		;GET NODE TYPE
	PUSHJ	P,ARGRTN		;SETUP ARGUMENT BLOCK
	MOVE	S1,OBJ.ND(P1)		;GET NODE IN OBJECT BLOCK
	PUSHJ	P,OPRENB		;IS OPR ENABLED FOR THIS NODE
	JUMPF	.POPJ			;NO..RETURN
	PJRST	CMDEND			;END THE COMMAND
SEND.1:	MOVE	S2,OBJ.TY(P1)		;GET THE OBJECT TYPE
	CAIN	S2,.OTJOB		;WAS IT A SEND TO JOB
	JRST	SEND.2			;YES..PROCESS IT
	CAIN	S2,.OTTRM		;WAS IT A TERMINAL
	JRST	SEND.3			;YES..PROCESS IT
	$RETF				;INVALID COMMAND
SEND.2:	LOAD	S1,OBJ.UN(P1)		;GET THE JOB NUMBER
	MOVX	S2,JI.TNO		;GET TERMINAL NUMBER
	PUSHJ	P,I%JINF		;GET TERMINAL NUMBER
	JUMPF	E$CSU			;CAN'T SEND TO USER
	CAMN	S2,[EXP -1]		;DETATCHED
	JRST	E$CSU			;YES, DON'T SEND IT
	MOVEM	S2,OBJ.UN(P1)		;SAVE FOR CONSISTENCY
SEND.3:	MOVE	S1,OBJ.UN(P1)		;GET TERMINAL NUMBER
	MOVEI	S2,ARG.DA(P2)		;ADDRESS OF MESSAGE
	PUSHJ	P,SNDTTY		;SEND THE MESSAGE
	PJRST	E$SCC			;SEND COMPLETED  AND RELEASE PAGE
SEND.4:	SKIPE	S1,OBJ.TY+ARG.DA(P3)	;WAS THERE AN OPERATOR FOUND
	JRST	SENDOP			;YES..CHECK OUT THE OPERATOR
	PUSHJ	P,P$KEYW		;WAS IT A KEYWORD
	JUMPF	.POPJ			;ERROR..
	CAIE	S1,.KYALL		;BETTER BE ALL
	JRST	SENDOP			;TRY SEND TO OPERATOR
	PUSHJ	P,P$SWIT		;CHECK FOR NODE SWITCH
	JUMPF	SEND.5			;ERROR...RETURN
	CAIE	S1,.SWNOD		;WAS IT A NODE SWITCH
	$RETF				;NO..RETURN..BAD MESSAGE
	PUSHJ	P,P$NODE		;GET THE NODE FIELD
	MOVE	P1,S1			;SAVE THE VALUE FOR NODE ***
SEND.5:	PUSHJ	P,BLDSND		;BUILD THE SEND
	JUMPF	.POPJ			;ERROR..RETURN
	MOVE	P2,S1			;ADDRESS OF MESSAGE TEXT
	PUSHJ	P,SNDALL		;DO THE SEND TO ALL
	PJRST	RELPAG			;RELEASE THE PAGE AND RETURN



SNDRTN:	IDPB	S1,SNDPTR		;SAVE THE BYTE
	$RETT				;RETURN TRUE
	SUBTTL	SENDOP	--	SEND TO OPERATOR COMMAND

	;THIS ROUTINE WILL BUILD AND QUEUE UP A MESSAGE TO OPRS
	;BASED ON THE SEND COMMAND

SENDOP:	CAIE	S1,.KYOPR		;MAKE SURE IT IS AN OPERATOR
	$RETF				;NO..INVALID COMMAND
	SETOM	G$ASND			;FORCE MESSAGE TO OPRS
	PUSHJ	P,P$SWIT		;CHECK FOR A SWITCH
	JUMPT	SENO.1			;CHECK OUT SWITCH
	MOVE	S1,G$OPRA		;GET OPERATOR ADDRESS
	MOVE	S2,OPR.ND(S1)		;GET NODE ADDRESS
	MOVE	P2,NOD.NM(S2)		;GET NODE NAME
	CAME	P2,G$CNTL		;IS IT CENTRAL SITE?
	JRST	SENO.2			;NO..USE LOCAL NODE
	PUSHJ	P,BLDSND		;BUILD THE SEND
	JUMPF	.POPJ			;ERROR RETURN
	SETOM	S1			;SEND TO ALL OPERATORS
	PJRST	SNDAOP			;SEND TO ALL AND RETURN
SENO.1:	CAIE	S1,.SWNOD		;WAS IT A NODE
	$RETF				;NO..ERROR..RETURN
	PUSHJ	P,P$NODE		;GET THE NODE
	JUMPF	.POPJ			;ERROR ..RETURN
	MOVE	P2,S1			;SAVE THE NODE VALUE
SENO.2:	MOVEM	P2,G$ARG1		;SAVE THE NODE NAME
	MOVE	S1,P2			;GET NODE NAME
	PUSHJ	P,FNDNOD		;FIND THE NODE
	JUMPF	E$NON			;NO OPERATORS AT NODE
	MOVE	P2,S2			;GET NODE ENTRY ADDRESS
	PUSHJ	P,BLDSND		;BUILD THE SEND MESSAGE
	JUMPF	.POPJ			;ERROR..ABORT NOW
	SETOM	NOALTN			;NO ALTERNATE NODES
	MOVE	S1,P2			;GET NODE ENTRY ADDRESS
	PUSHJ	P,SNDNAL		;SEND TO ALL OPERATORS NO ALTERNATES
	JUMPT	.POPJ			;O.K..JUST RETURN..PAGE RELEASE ALREADY
	JRST	E$NON			;NO OPERATORS AT NODE
	SUBTTL	BLDSND	--	BUILD THE SEND TEXT

	;THIS ROUTINE WILL BUILD THE SEND MESSAGE TO BE SEND TO 
	;USER, BATCH OR OPERATOR

BLDSND:	PUSHJ	P,P$TEXT		;GET THE TEXT
	JUMPF	.POPJ			;NO TEXT..RETURN
	HRLI	T1,(POINT 7,0)		;SETUP BYTE POINTER
	HRRI	T1,ARG.DA(P3)		;ADDRESS FOR THE TEXT
	MOVEM	T1,SNDPTR		;SAVE THE SEND BYTE POINTER
	MOVE	T2,G$OPRA		;GET OPR ADDRESS
	MOVE	T1,OPR.ND(T2)		;GET NODE ADDRESS
	MOVE	T3,G$CNTL		;GET NODE OF CENTRAL SITE
	MOVEI	S2,TTYTXT		;ASSUME TTYTXT
	CAME	T3,NOD.NM(T1)		;CENTRAL SITE
	MOVEI	S2,NODTXT		;NO..USE NODE TEXT
	$TEXT	(SNDRTN,<^M^J^C/G$NOW/ From Operator ^I/(S2)/:
	=^7/[76]/^T/1(S1)/
^0>)
	HRRZ	S2,SNDPTR		;GET THE ADDRESS
	AOS	S1,S2			;BUMP AND SAVE IN S1
	SUB	S2,P3			;COMPUTE THE BLOCK SIZE
	MOVEI	S1,.CMTXT		;GET BLOCK TYPE
	MOVE	T4,P3			;GET TEXT ADDRESS
	PUSHJ	P,ARGRTN		;SAVE THE ARGUMENT
	ANDI	P3,777			;GET THE MESSAGE LENGTH
	STORE	P3,.MSTYP(MO),MS.CNT	;SAVE THE MESSAGE COUNT
	MOVE	S1,T4			;GET TEXT ADDRESS
	$RETT				;RETURN TRUE

NODTXT:	ITEXT	(<^N/NOD.NM(T1)/>)
TTYTXT:	ITEXT	(<Terminal ^O/OPR.TN(T2)/>)
	SUBTTL	SNDALL	--	SEND MESSAGE TO ALL(/NODE)

	;THIS ROUTINE WILL SEND A MESSAGE TO ALL TERMINAL OR ALL AT A NODE

SNDALL:

IFN	FTUUOS,<
	PJRST	E$CNI			;COMMAND NOT IMPLEMENTED
>;END FTUUOS

IFN	FTJSYS,<
	SETOM	S1			;SEND TO ALL TERMINALS
	HRROI	S2,ARG.DA(P2)		;POINT TO THE TEXT ARGUMENT
	TTMSG				;SEND THE TEXT
	ERJMP	.RETF			;FAILED RETURN FALSE
	$RETT				;RETURN TRUE
>;END FTJSYS
	SUBTTL	SNDTTY	--	SEND A MESSAGE TO A TERMINAL

	;THIS ROUTINE WILL SEND A MESSAGE  TO A TERMINAL
	;
	;CALL	S1/	TERMINAL NUMBER
	;	S2/	ADDRESS OF TEXT


	;CHECK IF TERMINAL WANTS MESSAGES

SNDTTY:

IFN	FTUUOS,<
	PUSHJ	P,.SAVET		;SAVE AC'S
	TXO	S1,.UXTRM		;MAKE SURE IT IS A UDX
	MOVX	T1,<3,,T2>		;SET UP ARG POINTER
	MOVX	T2,.TOOUS		;LOAD OUTSTR FUNCION
	MOVE	T3,S1			;GET TERMINAL NUMBER
	TXO	T3,.UXTRM		;MAKE IT A UDX
	MOVE	T4,S2			;GET MESSAGE ADDRESS
	TRMOP.	T1,			;OUTPUT THE STRING
	  PJRST	E$CSU			;GIVE AN ERROR
	$RETT				;RETURN TRUE
>;END FTUUOS

IFN	FTJSYS,<
	TRO	S1,400000		;FLAG IT AS A TERMINAL NUMBER
	HRRO	S2,S2			;POINT AT THE TEXT
	TTMSG				;SEND THE TEXT
	ERJMP	.RETF			;FAILED ..RETURN FALSE
	$RETT				;RETURN TRUE
>;END FTJSYS
SUBTTL	SHOW Command

SHOW:	PUSHJ	P,P$KEYW		;GET A KEYWORD
	JUMPF	.POPJ			;MUST BE A KEYWORD..ELSE RETURN
	MOVSI	S2,-SHWLEN		;MAKE AOBJN POINTER TO DISPATCH TABLE
SHOW.1:	HLRZ	T1,SHWDSP(S2)		;GET AN ENTRY FROM TABLE
	CAMN	T1,S1			;DOES THIS ENTRY MATCH?
	JRST	SHOW.2			;YES, GO PROCESS IT
	AOBJN	S2,SHOW.1		;NO, LOOK AT NEXT
	$RETF				;NO MATCH, BAD COMMAND
SHOW.2:	HRRZ	S2,SHWDSP(S2)		;GET THE ADDRESS TO DISPATCH TO
	JRST	(S2)			;EXECUTE THE ROUTINE

SHWDSP:
	.KYSTS,,Q$SHWS##		;SHOW STATUS
	.KYMSG,,SHWMSG			;SHOW MESSAGES
	.KYQUE,,Q$SHWQ##		;SHOW QUEUES
	.KYPRM,,Q$SHWP##		;SHOW PARAMETERS
	.KYOPR,,SHWOPR			;SHOW OPERATORS
	.KYRTE,,Q$SHWR##		;SHOW ROUTE TABLES
	.KYCTL,,Q$SHWC##		;SHOW CONTROL-FILE
TOPS20<	.KYSCH,,SHWSCH>			;SHOW SCHEDULER
SHWLEN==.-SHWDSP
	SUBTTL	SHWOPR	--	SHOW OPERATORS IN SYSTEM

	;THIS ROUTINE WILL DISPLAY OPR ON SYSTEM TO OPR ISSUING THE COMMAND

SHWOPR:	MOVX	S1,.OMDSP		;SETUP OPR DISPLAY MESSAGE
	STORE	S1,.MSTYP(MO),MS.TYP	;SAVE THE TYPE COUNT
	PUSHJ	P,P$CFM			;CHECK FOR CONFIRM
	JUMPT	SHWO.1			;O.K. PROCESS ALL
	PUSHJ	P,P$SWIT		;CHECK FOR A SWITCH
	JUMPF	.POPJ			;NO SWITCH ERROR
	CAIE	S1,.SWNOD		;WAS IT A NODE
	$RETF
	PUSHJ	P,P$NODE		;GET THE NODE VALUE
	JUMPF	.POPJ			;INVALID MESSAGE
	MOVEM	S1,G$ARG1		;SAVE NODE NAME
	PUSHJ	P,FNDNOD		;VALIDATE THE NODE
	JUMPF	E$NON			;NO SUCH NODE
	MOVE	P1,S1			;SAVE THE NODE ADDRESS
	MOVE	S1,NOD.NM(S1)		;GET THE NODE NAME
	PUSHJ	P,OPRENB		;CHECK IF ENABLED FOR NODE
	JUMPF	.POPJ			;INVALID NODE
	MOVEI	S1,SHOT.1		;SHOW OPERATOR TEXT
	PUSHJ	P,SHWMTX		;SHOW MESSAGE TEXT POINTER
	MOVE	S2,P1			;PUT NODE ADDRESS IN S2
	PUSHJ	P,OPRLST		;OPERATORS AT NODE
	JUMPT	FINSHW			;HAVE SOME..SEND IT
	PJRST	E$NON			;NO MESSAGES FOR THE NODE
SHWO.1:	MOVEI	S1,SHOT.1		;SHOW OPERATOR TEXT
	PUSHJ	P,SHWMTX		;SHOW MESSAGE TEXT
	SETZM	P1			;CLEAR MESSAGES FLAG
	MOVE	S1,G$NODL		;GET NODE LIST NUMBER
	PUSHJ	P,L%FIRST		;GET FIRST ENTRY
SHWO.2:	PUSHJ	P,OPRLST		;OPERATORS AT NODE
	SKIPF				;NO MESSAGES SKIP FLAG SETTING
	SETOM	P1			;MESSAGES FOUND
	MOVE	S1,G$NODL		;GET NODE LIST NUMER
	PUSHJ	P,L%NEXT		;GET NEXT ENTRY
	JUMPT	SHWO.2			;PROCESS MESSAGES
	SKIPE	P1			;SEND ANY MESSAGES
	JRST	FINS.1			;YES..SEND MESSAGE
	PJRST	E$NOD			;NO OPERATORS DEFINED


SHWMTX:	MOVE	T1,G$NOW		;GET CURRENT TIME
	MOVEM	T1,ARG.DA(S1)		;SAVE TIME IN THE BLOCK
	MOVS	T1,S1			;SOURCE TEXT ADDRESS
	HRR	T1,P3			;DESTINATION ADDRESS
	LOAD	T2,(S1),AR.LEN		;LENGTH OF THE BLOCK
	ADD	P3,T2			;GET END ADDRESS
	BLT	T1,-1(P3)		;MOVE THE TEXT
	AOS	.OARGC(MO)		;BUMP ARGUMENT COUNT
	$RETT				;RETURN

SHMT.1:	XWD	SHLTXT,.ORDSP		;TEXT BLOCK
	BLOCK	1			;ROOM FOR TIME STAMP
	ASCIZ/		--  System Messages Outstanding  --
/
SHLTXT==.-SHMT.1			;SIZE OF THE BLOCK
SHOT.1:	XWD	SHOTLN,.ORDSP		;TEXT BLOCK
	BLOCK	1			;ROOM FOR TIME STAMP
	ASCIZ/		--  System Operators  --

	 NODE	   TERMINAL	JOB		USER
	------	   --------	---	------------------------
/
SHOTLN=.-SHOT.1			;SIZE OF THE BLOCK
	SUBTTL	SHWSCH	--	SHOW SCHEDULER INFORMATION

	;THIS COMMAND IS TO DUMP THE SCHEDULER INFORMATION ON THE -20
	

IFN	FTJSYS,<
SHWSCH:	PUSHJ	P,CHKWHL		;CHECK PRIVILEGES
	JUMPF	E$IPE			;INSUFFICIENT PRIVILEGES AND RETURN
	PUSHJ	P,P$CFM			;END OF COMMAND?
	JUMPF	.POPJ			;ERROR..RETURN
	PUSHJ	P,RELPAG		;RELEASE GIVEN PAGE 
	PUSHJ	P,OPRMES		;SETUP THE MESSAGE
	MOVEI	S1,.SKRBC		;READ BIAS CONTROL
	MOVEI	S2,T1			;BLOCK IN T1
	MOVEI	T1,2			;LENGTH OF  BLOCK
	SKED%				;GET THE DATA
	   ERJMP SCHERR			;SCHEDULER ERROR
	MOVE	P1,T2			;SAVE THE VALUE
	MOVEI	S1,.SKRCV		;GET SCHEDULER DATA
	SKED%				;GET THE VALUE
	  ERJMP SCHERR			;SCHEDULER ERROR
	MOVE	P2,T2			;SAVE SCHEDULER INFO
	MOVEI	S1,[ASCIZ/On/]		;ASSUME ON
	TXNE	P2,SK%STP		;CHECK IF OFF
	MOVEI	S1,[ASCIZ/Off/]		;YES..
	$TEXT	(WTORTN,<		--  System Scheduler Information --

		Class Scheduler: ^T/(S1)/		Bias Control: ^D/P1/>)
	MOVEI	P1,[ITEXT(<None set>)]	;ASSUME NONE-SET
	TXNE	P2,SK%DRG		;BATCH ON DREGS QUEUE?
	MOVEI	P1,[ITEXT(<Background>)]	;YES.. SETUP BACKGROUND
	TXNE	P2,SK%STP		;CHECK IF ON
	JRST	SCHS.1			;NO..BYPASS CLASS SCHEDULER BATCH READ
	MOVEI	S1,.SKBCR		;READ BATCH CLASS SETTINGS
	MOVEI	S2,T1			;ADDRESS OF THE BLOCK
	MOVEI	T1,2			;LENGTH OF THE BLOCK
	SKED%				;GET THE VALUE
	  ERJMP  SCHERR			;ERROR..RETURN
	SKIPL	T2			;ANY SET(-1=NONE)
	MOVEI	P1,[ITEXT(<^D/T2/>)]	;GET THE NUMBER
SCHS.1:	$TEXT	(WTORTN,<						Batch Class: ^I/(P1)/>)
	TXNE	P2,SK%STP		;CLASS SCHEDULER ON
	JRST	SCHS.4			;NO..FINISH OFF COMMAND
	MOVEI	T3,0			;START WITH CLASS 0
	$TEXT	(WTORTN,<
					    ------Load Averages-------
		CLASS    SHARE(%)   USE(%)  1-MIN     5-MIN     15-MIN>)
SCHS.2:	MOVEI	S1,.SKRCS		;READ CLASS INFORMATION
	MOVEI	S2,SCHBLK		;SCHEDULER BLOCK
	MOVEI	T1,7			;LENGTH OF BLOCK
	MOVEM	T1,SCHBLK+.SACNT	;SAVE THE LENGTH
	MOVEM	T3,SCHBLK+.SACLS	;SAVE THE CLASS
	SKED%				;GET THE DATA
	  ERJMP	SCHS.3			;NO MORE..DONE NOW
	SKIPN	T4,SCHBLK+.SASHR	;ANY SHARE?
	AOJA	T3,SCHS.2		;NO..TRY NEXT ONE
	MOVE	S1,.SASHR+SCHBLK	;GET THE SHARE
	FMPRI	S1,(100.)		;GET WHOLE NUMBER
	FIXR	S1,S1			;GET INTERGER NUMBER
	MOVEM	S1,.SASHR+SCHBLK	;SAVE THE NUMBER
	MOVE	S1,.SAUSE+SCHBLK	;GET THE USE
	FMPRI	S1,(100.)		;MAKE A WHOLE NUMBER
	FIXR	S1,S1			;MAKE INTERGER NUMBER
	MOVEM	S1,.SAUSE+SCHBLK	;SAVE THE NUMBER
	MOVE	S1,.SA1ML+SCHBLK	;GET THE 1 MINUTE LOAD
	FMPRI	S1,(100.)		;GET WHOLE NUMBER
	FIXR	S1,S1			;GET INTERGER NUMBER
	IDIVI	S1,^D100			;NOW GET NUMBER AND FRACTION
	HRL	S2,S1			;PLACE IN LEFT HALF
	MOVEM	S2,.SA1ML+SCHBLK	;SAVE NUMBERS BACK
	MOVE	S1,.SA5ML+SCHBLK	;GET THE 5 MINUTE LOAD
	FMPRI	S1,(100.)		;GET WHOLE NUMBER
	FIXR	S1,S1			;GET INTERGER NUMBER
	IDIVI	S1,^D100		;NOW GET NUMBER AND FRACTION
	HRL	S2,S1			;PLACE IN LEFT HALF
	MOVEM	S2,.SA5ML+SCHBLK	;SAVE NUMBERS BACK
	MOVE	S1,.SA15L+SCHBLK	;GET THE 15 MINUTE LOAD
	FMPRI	S1,(100.)		;GET WHOLE NUMBER
	FIXR	S1,S1			;GET INTERGER NUMBER
	IDIVI	S1,^D100			;NOW GET NUMBER AND FRACTION
	HRL	S2,S1			;PLACE IN LEFT HALF
	MOVEM	S2,.SA15L+SCHBLK	;SAVE NUMBERS BACK
	$TEXT	(WTORTN,<		  ^D/SCHBLK+.SACLS/       ^D3R/SCHBLK+.SASHR/       ^D3R/SCHBLK+.SAUSE/    ^D3R/SCHBLK+.SA1ML,LHMASK/.^D2R0/SCHBLK+.SA1ML,RHMASK/    ^D3R/SCHBLK+.SA5ML,LHMASK/.^D2R0/SCHBLK+.SA5ML,RHMASK/    ^D3R/SCHBLK+.SA15L,LHMASK/.^D2R0/SCHBLK+.SA15L,RHMASK/>)
	AOJA	T3,SCHS.2		;NO..TRY NEXT ONE
SCHS.3:	MOVEI	S1,[ASCIZ/Allocated/]	;DEFAULT FOR WINDFALL
	MOVEI	S2,[ASCIZ/Policy Program/];DEFAULT FOR CLASS ASSIGNMENTS
	TXNE	P2,SK%WDF		;WITHHOLD WINDFALL?
	MOVEI	S1,[ASCIZ/Withheld/]	;YES
	TXNE	P2,SK%ACT		;CLASS BY ACCOUNTS
	MOVEI	S2,[ASCIZ/Account/]	;YES
	$TEXT	(WTORTN,<
		Windfall: ^T/(S1)/		Classes by ^T/(S2)/>)
SCHS.4:	PUSHJ	P,MSGFIN		;FINISH THE MESSAGE
	PUSHJ	P,L$SHWM##		;LOG THE MESSAGE
	MOVE	S1,G$SND		;GET SENDERS PID
	MOVEI	S2,PAGSIZ		;PAGE MESSAGE
	PUSHJ	P,SPDOPR		;SEND TO OPR
	$RETT				;RETURN O.K.
SCHERR:	PJRST	E$SFF			;SCHEDULER FUNCTION FAILED
>;END FTJSYS
	SUBTTL	SHWMSG	--	SHOW MESSAGES ROUTINE

	;THIS ROUTINE WILL BUILD A MESSAGE FOR OPR WITH OUTSTANDING
	;WTOR MESSAGES

SHWMSG:	MOVX	S1,.OMDSP		;SETUP OPR DISPLAY MESSAGE
	STORE	S1,.MSTYP(MO),MS.TYP	;SAVE THE TYPE COUNT
	PUSHJ	P,P$CFM			;CHECK FOR CONFIRM
	JUMPT	SHWM.3			;O.K. PROCESS ALL
	PUSHJ	P,P$SWIT		;CHECK FOR A SWITCH
	JUMPF	SHWM.2			;NO..TRY FOR A NUMBER
	CAIE	S1,.SWNOD		;WAS IT A NODE
	$RETF
	PUSHJ	P,P$NODE		;GET THE NODE VALUE
	JUMPF	.POPJ			;INVALID MESSAGE
	MOVEM	S1,G$ARG1		;SAVE NODE NAME
	PUSHJ	P,FNDNOD		;VALIDATE THE NODE
	JUMPF	E$NMN			;NO SUCH NODE
	MOVE	P1,S1			;SAVE THE NODE ADDRESS
	MOVE	S1,NOD.NM(S1)		;GET THE NODE NAME
	PUSHJ	P,OPRENB		;CHECK IF ENABLED FOR NODE
	JUMPF	.POPJ			;INVALID NODE
	MOVEI	S1,SHMT.1		;SHOW MESSAGE  TEXT
	PUSHJ	P,SHWMTX		;SHOW MESSAGE TEXT POINTER
	MOVE	S2,P1			;PUT NODE ADDRESS IN S2
	PUSHJ	P,MSGNOD		;OUTPUT THE MESSAGES
SHWM.1:	JUMPT	FINSHW			;HAVE SOME..SEND IT
	PJRST	E$NMN			;NO MESSAGES FOR THE NODE
SHWM.2:	PUSHJ	P,P$NUM			;GET A NUMBER
	JUMPF	.POPJ			;INVALID COMMAND
	MOVEM	S1,G$ARG1		;SAVE THE MESSAGE NUMBER
	PUSHJ	P,GETMSG		;GET THE MESSAGE
	JUMPF	E$NSM			;NO SUCH MESSAGE
	MOVEI	S1,SHMT.1		;SHOW MESSAGE  TEXT
	PUSHJ	P,SHWMTX		;SHOW MESSAGE TEXT
	PUSHJ	P,BLDDPY		;MOVE THE MESSAGE
	JRST	FINSHW			;FINISH OFF THE MESSAGE
SHWM.3:	MOVEI	S1,SHMT.1		;SHOW MESSAGE  TEXT
	PUSHJ	P,SHWMTX		;SHOW MESSAGE TEXT
	MOVE	S2,G$OPRA		;GET THE OPR ADDRESS
	MOVE	S2,OPR.ND(S2)		;GET THE NODE ADDRESS
	MOVE	S1,NOD.NM(S2)		;GET THE NAME
	MOVEM	S1,G$ARG1		;SAVE THE VALUE
	MOVX	S1,ND.SYS		;CHECK FOR SYSTEM OPERATOR
	TDNN	S1,NOD.FL(S2)		;SYSTEM OPERATOR?
	   JRST	SHWM.5			;NO ..DO JUST THIS NODE
	SETZM	P1			;CLEAR MESSAGES FLAG
	MOVE	S1,G$NODL		;GET NODE LIST NUMBER
	PUSHJ	P,L%FIRST		;GET FIRST ENTRY
SHWM.4:	PUSHJ	P,MSGNOD		;GET MESSAGES FOR THIS NODE
	SKIPF				;NO MESSAGES SKIP FLAG SETTING
	SETOM	P1			;MESSAGES FOUND
	MOVE	S1,G$NODL		;GET NODE LIST NUMER
	PUSHJ	P,L%NEXT		;GET NEXT ENTRY
	JUMPT	SHWM.4			;PROCESS MESSAGES
	SKIPE	P1			;SEND ANY MESSAGES
	JRST	FINS.1			;YES..SEND MESSAGE
	PJRST	E$NOM			;NO OUTSTANDING MESSAGES
SHWM.5:	PUSHJ	P,MSGNOD		;OUTPUT THE MESSAGES
	JUMPT	FINS.1			;FINISH OFF THE MESSAGE
	PJRST	E$NMN			;NO MESSAGES FOR NODE
	SUBTTL	FINSHW	--	Finish off a SHOW Message

	;This Routine will finish off a SHOW OPERATOR or SHOW MESSAGES
	;command and LOG it.

FINSHW:	PUSHJ	P,P$CFM			;END OF MESSAGE
	JUMPF	.POPJ			;ERROR..RETURN
FINS.1:	ANDI	P3,777			;GET MESSAGE LENGTH
	STORE	P3,.MSTYP(MO),MS.CNT	;SAVE LENGTH IN MESSAGE
	PUSHJ	P,L$SHWM##		;LOG THE SHOW MESSAGE
	MOVE	S1,G$SND		;GET THE SENDERS PID
	MOVEI	S2,PAGSIZ		;SEND A PAGE
	PUSHJ	P,SPDOPR		;SEND THE MESSAGE
	$RETT				;RETURN TRUE
SUBTTL	MSGNOD	--  Routine to Build Display Blocks for a Node

;CALLED WITH S2 CONTAINING THE ADDRESS OF AN ENTRY IN THE NODE LIST
;MO MUST POINT AT A OPERATOR DISPLAY MESSAGE

MSGNOD:	LOAD	S1,NOD.ML(S2)		;GET THIS NODE'S MESSAGE LIST NUMBER
	MOVE	T1,S1			;SAVE MESSAGE LIST NUMBER
	PUSHJ	P,L%FIRST		;FIND THE FIRST MESSAGE
	JUMPF	.POPJ			;NONE FOR THIS NODE,RETURN
MSGN.1:	PUSHJ	P,BLDDPY		;GO BUILD A DISPLAY BLOCK
MSGN.2:	MOVE	S1,T1			;COPY MESSAGE LIST NUMBER TO S1
	PUSHJ	P,L%NEXT		;FIND NEXT ENTRY
	JUMPT	MSGN.1			;LOOP FOR ALL MESSAGES
	$RETT				;LOOP IF NO MORE


	SUBTTL	BLDDPY	--	BUILD MESSAGE INTO OUTPUT

;THIS ROUTINE WILL MOVE TEXT BLOCK FROM MESSAGE LIST TO OUTPUT MESSAGE MO
;CALLED WITH:	S2	ADDRESS OF MESSAGE ENTRY

BLDDPY:	MOVSI	T3,MSL.SZ(S2)		;ADDRESS OF MESSAGE TEXT
	HRR	T3,P3			;FIRST FREE OUTPUT ADDRESS
	LOAD	T4,MSL.SZ(S2),AR.LEN	;LENGTH OF THE BLOCK
	ADD	P3,T4			;COMPUTE ENDING ADDRESS
	CAIL	P3,777(MO)		;MAKE SURE WILL FIT IN MESSAGE
	PJRST	BLDD.1			;NO..SEND AND CONTINUE ON
	BLT	T3,-1(P3)		;MOVE THE BLOCK
	AOS	.OARGC(MO)		;CLEAR THE ARGUMENT COUNT
	$RETT				;RETURN TRUE
BLDD.1:	PUSH	P,S2			;SAVE MESSAGE ADDRESS
	MOVX	S1,WT.MOR		;SET MORE COMING FLAG
	IORM	S1,.OFLAG(MO)		;TURN ON THE FLAG
	PUSHJ	P,FINS.1		;SEND THE MESSAGE
	PUSHJ	P,GETPAG		;GET A PAGE FOR OUTPUT
	MOVX	S1,.OMDSP		;SETUP DISPLAY MESSAGE
	STORE	S1,.MSTYP(MO),MS.TYP	;SAVE THE TYPE
	MOVEI	P3,.OHDRS(MO)		;GET FIRST FREE ADDRESS
	POP	P,S2			;RESTORE S2
	JRST	BLDDPY			;TRY THIS ONE AGAIN
SUBTTL	OPRLST	--  Routine to Build Display Blocks for an Operator

;CALLED WITH S2 CONTAINING THE ADDRESS OF AN ENTRY IN THE NODE LIST
;MO MUST POINT AT A OPERATOR DISPLAY MESSAGE

OPRLST:	PUSHJ	P,OPRSPT		;OPR SETUP POINTERS
	LOAD	S1,NOD.OP(S2)		;GET THE OPERATOR LIST NUMBER
	MOVE	T1,S1			;SAVE OPERATOR LIST NUMBER
	PUSHJ	P,L%FIRST		;FIND THE FIRST MESSAGE
	JUMPF	.POPJ			;NONE FOR THIS NODE,RETURN
OPRL.1:	MOVE	S1,OPR.ND(S2)		;GET NODE ENTRY ADDRESS
	PUSHJ	P,OPRDPY		;GO BUILD A DISPLAY BLOCK
OPRL.2:	MOVE	S1,T1			;COPY MESSAGE LIST NUMBER TO S1
	PUSHJ	P,L%NEXT		;FIND NEXT ENTRY
	JUMPT	OPRL.1			;LOOP FOR ALL MESSAGES
	HRRZ	S2,WTOPTR		;GET LAST ADDRESS
	SUBI	S2,-1(P3)		;GET THE LENGTH
	MOVEI	S1,.CMTXT		;GET ARGUMENT TYPE
	PUSHJ	P,ARGRTN		;SAVE THE ARGUMENT
	$RETT				;LOOP IF NO MORE
	SUBTTL	OPRDPY	--	Build Operator Info

;THIS ROUTINE WILL PLACE TEXT IN THE MESSAGE
;CALLED WITH:	S1	NODE ENTRY ADDRESS
;		S2	ADDRESS OF OPERATOR ENTRY

OPRDPY:	$TEXT	(OPRRTN,<	^W6/NOD.NM(S1)/	     ^O3R/OPR.TN(S2)/	^D3R/OPR.JB(S2)/	^I/OPRUSN/^U/OPR.US(S2)/>)
	POPJ	P,			;RETURN

IFN	FTJSYS,<
OPRUSN==NULTXT
>;END FTJSYS
IFN	FTUUOS,<
OPRUSN:	ITEXT	(<^W6/OPR.UN(S2)/^W/OPR.UN+1(S2)/ >)
>;END FTUUOS

OPRRTN:	IDPB	S1,WTOPTR		;SAVE THE BYTE
	$RETT				;RETURN TRUE
OPRR.1:	MOVX	S1,WT.MOR		;SET MORE COMING FLAG
	IORM	S1,.OFLAG(MO)		;TURN ON THE FLAG
	PUSHJ	P,FINS.1		;SEND THE MESSAGE
	PUSHJ	P,GETPAG		;GET A PAGE FOR OUTPUT
	MOVX	S1,.OMDSP		;SETUP DISPLAY MESSAGE
	STORE	S1,.MSTYP(MO),MS.TYP	;SAVE THE TYPE
	MOVEI	P3,.OHDRS(MO)		;GET FIRST FREE ADDRESS
	PUSHJ	P,OPRSPT		;OPR SET POINTER
	JRST	OPRDPY			;TRY THIS ONE AGAIN


	;S2 MUST BE PRESERVED

OPRSPT:	MOVEI	S1,ARG.DA(P3)		;FREE LOCATION IN MESSAGE
	HRLI	S1,(POINT 7,)		;MAKE A BYTE POINTER
	MOVEM	S1,WTOPTR		;SAVE THE POINTER
	MOVEI	S1,ARG.DA(P3)		;GET THE POINTER
	MOVEI	T1,PAGSIZ		;SIZE OF A PAGE
	ANDI	S1,777			;MAKE AS OFFSET
	SUBI	T1,-1(S1)		;GET NUMBER OF FREE WORDS
	IMULI	T1,NCHPW		;NUMBER OF CHARACTERS PER WORD
	MOVEM	T1,WTOCNT		;COUNT OF SPACE REMAINING
	POPJ	P,			;RETURN
	SUBTTL	OPRENB	--	OPERATOR ENABLED FOR NODE

	;THIS ROUTINE WILL CHECK TO SEE IF THE OPERATOR IS ENABLED 
	;FOR THE NODE SPECIFIED.
	;CALL	S1/	NODE NAME TO CHECK


OPRENB:	MOVEM	S1,G$ARG2		;SAVE NODE NAME
	PUSHJ	P,CHKWHL		;CHECK IF PRIVILEGED
	JUMPT	.POPJ			;O.K..RETURN
	PUSHJ	P,.SAVE2		;SAVE AN AC
	MOVE	P1,G$ARG2		;SAVE THE NODE
	MOVE	S2,G$OPRA		;GET OPR ADDRESS
	MOVE	S2,OPR.ND(S2)		;GET THE NODE ADDRESS
	MOVE	P2,S2			;GET NODE ADDRESS
	MOVE	S2,NOD.NM(S2)		;GET NODE NAME
	MOVEM	S2,G$ARG1		;SAVE NODE DATA
	TLNE	P1,770000		;CHECK IF NODE NAME OR NUMBER
	JRST	OPRE.1			;CHECK NODE NAME
	CAMN	P1,NOD.NU(P2)		;MATCH THE NODE NUMBER
	$RETT				;O.K...RETURN TRUE
	JRST	OPRE.2			;CHECK FOR OTHER NODES
OPRE.1:	CAMN	P1,NOD.NM(P2)		;MATCH NODE NAME
	$RETT				;RETURN TRUE
OPRE.2:	MOVE	S2,NOD.FL(P2)		;GET FLAGS FOR NODE
	TXNE	S2,ND.SYS		;SYSTEM OPERATOR
	$RETT				;O.K..RETURN TRUE
	TXNN	S2,ND.NLE		;NODE LIST ENABLED
	PJRST	E$INS			;INVALID NODE SPECIFIED
	MOVE	S1,NOD.AI(P2)		;ALTERNATE INPUT  LIST NUMBER
	PUSHJ	P,L%FIRST		;GET FIRST ENTRY
	JUMPF	E$INS			;INVALID NODE SPECIFIED
OPRE.3:	CAME	P1,NAL.NM(S2)		;SAME NODE NAME
	CAMN	P1,NAL.NU(S2)		;NO..WHAT ABOUT SAME NUMBER
	JRST	OPRE.4			;NO..GET NEXT ENTRY
	$RETT				;O.K...RETURN TRUE
OPRE.4:	MOVE	S1,NOD.AI(P2)		;GET NODE ALTERNATE INPUT LIST
	PUSHJ	P,L%NEXT		;GET NEXT ENTRY
	JUMPT	OPRE.3			;CHECK OUT THE ENTRY
	PJRST	E$INS			;INVALID NODE..AND RETURN
	SUBTTL	GETMSG	--	GET A MESSAGE GIVEN THE NUMBER
	
	;THIS ROUTINE WILL BE CALLED WITH THE MESSAGE NUMBER IN S1
	;AND RETURN TRUE WITH MESSAGE ENTRY ADDRESS IN S2

GETMSG:	MOVE	S2,G$OPRA		;GET THE OPR ENTRY ADDRESS
	MOVE	S2,OPR.ND(S2)		;GET NODE ENTRY ADDRESS
	MOVEI	T1,MSL.ID		;GET MESSAGE ID
	HRRM	T1,FNDXCT		;SAVE FOR COMPARE
	PUSHJ	P,CHKMSG		;CHECK FOR MESSAGE..THIS NODE
	JUMPT	.POPJ			;O.K. FOUND..SEND ANSWER
	MOVE	S2,G$OPRA		;GET OPR ADDRESS
	MOVE	S2,OPR.ND(S2)		;GET NODE ENTRY
	MOVX	T1,ND.SYS		;IS IT A SYSTEM OPERATOR
	TDNN	T1,NOD.FL(S2)		;CHECK FOR SYS OPERATOR
	JRST	GETM.1			;NO..CHECK FOR ALTERNATE NODES
	MOVE	S1,P1			;GET NUMBER OF ANSWER
	MOVEI	T1,MSL.ID		;GET MESSAGE ID
	HRRM	T1,FNDXCT		;SAVE FOR COMPARE
	PJRST	FNDMSG			;CHECK FOR MESSAGE AND RETURN
GETM.1:	MOVX	T1,ND.NLE		;ANY ALTERNATE NODES
	TDNN	T1,NOD.FL(S2)		;CHECK IF SETUP
	$RETF				;NO..NO SUCH MESSAGE
	MOVE	T4,S2			;SAVE NODE ENTRY ADDRESS
	MOVE	S1,NOD.AI(S2)		;ALTERNATE INPUT LIST NUMBER
	PUSHJ	P,L%FIRST		;POSITION TO THE FIRST
	JUMPF	.POPJ			;ERROR ..RETURN
GETM.2:	MOVE	S1,P1			;MESSAGE NUMBER
	MOVE	S2,T4			;NODE ENTRY ADDRESS
	MOVEI	T1,MSL.ID		;GET MESSAGE ID
	HRRM	T1,FNDXCT		;SAVE FOR COMPARE
	PUSHJ	P,CHKMSG		;CHECK FOR MESSAGE AT THIS NODE
	JUMPT	.POPJ			;YES..HAVE MESSAGE..RETURN
	MOVE	S1,NOD.AI(T4)		;ALTERNATE INPUT LIST NUMBER
	PUSHJ	P,L%NEXT		;GET THE NEXT ENTRY
	JUMPT	GETM.2			;CHECK OUT THIS NODE
	$RETF				;RETURN FALSE
	SUBTTL	REPORT	--	REPORT SYSTEM ERRORS TO SYSERR

	;THIS COMMAND WILL LOG THE ENTRY TO SYSERR

		;NEEDED SYMBOLS

	SLMTTY==0			;JOB#,,TTY#
	SLMPPN==1			;PPN OR POINTER TO BLOCK
	SLMWHO==2			;REPORTED BY FIELD
	SLMDEV==3			;DEVICE TO REPORT
	SLMMSG==4			;POINTER TO REASON

	ER.SLM==16			;TOPS-10 ERROR TYPE
	SEC%SL==116			;TOPS-20 ERROR TYPE
	SYSCOD==777000,,0		;MASK FOR STORING CODE ON -20

REPORT:	MOVEI	P1,.OARGC(MO)		;GET POINTER TO DATA AREA
	PUSHJ	P,P$SIXF		;GET THE REPORTER NAME
	JUMPF	.POPJ			;NOT THERE..ERROR
	MOVEM	S1,SLMWHO(P1)		;SAVE THE ID
	PUSHJ	P,P$SIXF		;GET THE DEVICE NAME
	JUMPF	.POPJ			;ERROR..RETURN
	MOVEM	S1,SLMDEV(P1)		;SAVE DEVICE NAME
	LOAD	S1,G$PRVS,MD.PJB	;GET JOB NUMBER
	HRLM	S1,SLMTTY(P1)		;SAVE JOB NUMBER
	PUSHJ	P,GETJOB		;GET JOB INFO OF SENDER
	MOVE	S1,JOBTTY		;GET TERMINAL NUMBER
	HRRM	S1,SLMTTY(P1)		;SAVE TERMINAL NUMBER

IFN	FTUUOS,<
REPO.1:	SKIPN	S1,G$SID		;GET SENDERS ID
	PJRST	E$IUM			;INVALID USER IN MESSAGE
	MOVEM	S1,SLMPPN(P1)		;SAVE THE PPN
	MOVEI	P2,SLMMSG+1		;OFFSET FOR TEXT START
>;END FTUUOS

IFN	FTJSYS,<
REPO.1:	MOVE	S2,G$SID		;GET SENDERS ID
	HRROI	S1,SLMMSG+1		;GET PLACE TO STORE IT
	MOVEM	S1,SLMPPN(P1)		;SAVE THE POINTER
	ADDI	S1,(P1)			;ADD IN ACTUAL DISPLACEMENT
	DIRST				;MAKE A STRING FROM NUMBER
	  JRST	E$IUM			;INVALID USER IN MESSAGE
	IBP	S1			;INCREMENT THE BYTE POINTER
	HRRZ	P2,S1			;GET LAST ADDRESS
	ADDI	P2,1			;POINT TO NEXT FREE LOCATION
	SUB	P2,P1			;GET RELATIVE OFFSET
>;END FTJSYS
	
	PUSHJ	P,P$TEXT		;GET THE EXPLANATION
	JUMPF	.POPJ			;ERROR..RETURN
	SUBI	S2,1			;DECREMNT COUNT BY HEADER SIZE
	MOVN	T1,S2			;GET SIZE OF BLOCK
	MOVS	T2,T1			;PLACE COUNT IN LEFT HALF
	HRR	T2,P2			;GET ADDRESS FOR DATA
	MOVEM	T2,SLMMSG(P1)		;SAVE POINTER IN BLOCK
	MOVEI	S2,ARG.DA(S1)		;GET ADDRESS OF TEXT
	MOVE	S1,P2			;GET ADDRESS OF DESTINATION
	ADD	S1,P1			;GET ACTUAL LOCATION
	PUSHJ	P,TXTMOV		;MOVE THE TEXT
	HRRZ	S1,S1			;GET ENDING ADDRESS
	
IFN	FTUUOS,<
REPO.2:	SUBI	S1,-1(P1)		;GET THE LENGTH
	ADDI	S1,2			;SIZE OF HEADER
	MOVE	T1,S1			;SAVE LENGTH IN T1
	MOVX	S1,ER.SLM		;GET TYPE OF SYERR ENTRY
	STORE	S1,.OFLAG(MO)		;SAVE IN MESSAGE
	MOVX	S1,.DMERR		;DAEMON FUNCTION CODE
	STORE	S1,.MSCOD(MO)		;SAVE IN MESSAGE
	MOVS	T2,T1			;PLACE LENGTH IN LEFT HALF
	HRRI	T2,.MSCOD(MO)		;GET STARTING ADDRESS
	DAEMON	T2,			;DO THE FUNCTION
	  PJRST	E$SUF			;SYSERR UPDATE FAILED
>;END FTUUOS

IFN	FTJSYS,<
REPO.2:	SUBI	S1,-1(P1)		;GET THE LENGTH
	ADDI	S1,4			;ADD 4 WORD HEADER
	MOVE	T1,S1			;SAVE THE LENGTH
	MOVX	S1,SEC%SL		;GET FUNCTION CODE
	STORE	S1,.MSTYP(MO),SYSCOD	;SAVE THE CODE
	MOVEI	S1,.MSTYP(MO)		;START OF FUNCTION
	MOVE	S2,T1			;LENGTH OF THE BLOCK
	SYERR				;DO THE SYSERR UPDATE
	ERJMP	E$SUF			;SYSERR UPDATE FAILED
>;END FTJSYS
	PJRST	E$SEM			;SYSERR ENTRY MADE
	SUBTTL	RESPOND COMMAND

	;THIS ROUTINE WILL PROCESS A RESPOND MESSAGE TO A WTO AND PASS
	;THE ANSWER TO THE REQUESTOR

RESPON:	PUSHJ	P,P$NUM		;GET THE NUMBER FROM MESSAGE
	JUMPF	.POPJ			;NO..INVALID MESSAGE..RETURN
	MOVE	P1,S1			;SAVE MESSAGE NUMBER IN P1
	PUSHJ	P,GETMSG		;GET THE MESSAGE
					;O.K..IN S2
	JUMPF	RESP.5			;NO..GIVE ERROR
RESP.1:	MOVE	P2,S2			;SAVE THE MESSAGE ADDRESS
	MOVE	S1,MSL.ND(P2)		;GET THE NODE MESSAGE FOUND OUT
	MOVE	S1,NOD.NM(S1)		;GET THE NODE NAME
	PUSHJ	P,OPRENB		;SEE IF OPR ENABLED FOR NODE
	JUMPF	RESP.6			;NO..SETUP ERROR
	MOVEI	T1,MSL.SZ(P2)		;GET START OF MESSAGE
	LOAD	S1,MSL.CD(P2)		;GET SENDERS CODE
	STORE	S1,.MSCOD(MO)		;SAVE IN MESSAGE
RESP.2:	PUSHJ	P,P$CURR		;GET THE CURRENT POINTER
	MOVE	T4,S1			;SAVE THE BLOCK POINTER
	PUSHJ	P,P$TEXT		;GET THE TEXT ADDR AND LEN
	JUMPF	.POPJ			;NOT TEXT..ERROR..RETURN
	PUSHJ	P,MOVARG		;BUILD TEXT ARGUMENT
	MOVE	S1,G$SND		;GET PID OF OPR SENDING IT
	MOVEM	S1,ARG.DA(P3)		;SAVE THE PID IN BLOCK
	MOVE	S1,G$OPRA		;GET THE OPR ADDRESS
	MOVE	T1,OPR.TN(S1)		;GET THE TERMINAL NUMBER
	MOVE	S2,OPR.ND(S1)		;GET THE NODE ENTRY
	MOVE	S2,NOD.NM(S2)		;GET THE NODE NAME
	CAME	S2,G$CNTL		;SAME AS OUR NODE.. USE TERMINAL
	MOVE	T1,S2			;GET THE NODE NAME
	MOVEM	T1,ARG.DA+1(P3)		;SAVE THE DATA
	MOVEI	S1,.ACKID		;GET ACK ID
	MOVEI	S2,ARG.SZ+1		;SIZE OF BLOCK
	PUSHJ	P,ARGRTN		;SAVE THE ARGUMENT
	ANDI	P3,777			;GET MESSAGE LENGTH
	STORE	P3,.MSTYP(MO),MS.CNT	;SAVE MESSAGE LENGTH
	LOAD	S1,MSL.PD(P2)		;PID OF THE SENDER
	MOVEI	S2,PAGSIZ		;PAGE MODE MESSAGE
	PUSHJ	P,SNDPID		;SEND THE MESSAGE
	JUMPT	RESP.4			;O.K. RELEASE MESSAGE AND RETURN
	MOVX	S1,MS.TER		;NOTIFY ANYWAY?
	TDNE	S1,MSL.FL(P2)		;CHECK IF SET
	JRST	RESP.7			;YES.. OUTPUT TO USER TERMINAL
	MOVEM	P1,G$ARG1		;SAVE THE NUMBER
RESP.3:	PUSHJ	P,E$MNV			;MESSAGE NO LONGER VALID..
	PUSHJ	P,RELPAG		;RELEASE THE PAGE
RESP.4:	MOVE	S2,MSL.ND(P2)		;NODE MESSAGE FOUND AT
	SOS	NOD.CT(S2)		;DECREMENT THE COUNT
	MOVE	S1,NOD.ML(S2)		;GET THE LIST NUMBER
	PUSHJ	P,L%DENT		;DELETE THE ENTRY
	$RETT				;RETURN TRUE
RESP.5:	MOVEM	P1,G$ARG1		;SAVE THE NUMBER
	PUSHJ	P,E$NSM			;NO SUCH MESSAGE
	$RETT				;RETURN TRUE
RESP.6:	MOVEM	P1,G$ARG1		;SAVE THE MESSAGE NUMBER ARG1
	MOVE	S1,MSL.ND(P2)		;GET NODE ADDRESS
	MOVE	S1,NOD.NM(S1)		;GET NODE NAME
	MOVEM	S1,G$ARG2		;SAVE ARG2
	PJRST	E$ONE			;OPR NOT ENABLED FOR NODE
RESP.7:	MOVE	S1,MSL.JB(P2)		;GET THE JOB NUMBER
	PUSHJ	P,GETUSR		;GET THE USER INFO
	JUMPT	RESP.8			;O.K.. CONTINUE ON
	SETZM	G$ERR			;CLEAR ERROR CODE
	MOVEM	P1,G$ARG1		;SAVE THE MESSAGE NUMBER
	JRST	RESP.3			;GENERATE AN ERROR
RESP.8:	MOVE	S1,MSL.JT(P2)		;GET THE JOB LOGGED IN TIME
	CAME	S1,JOBJLT		;SAME JOB?
	JRST	RESP.3			;NO..GENERATE AN ERROR
	MOVE	S1,T4			;GET THE CURRENT PARSER POINTER
	PUSHJ	P,P$SETU		;SETUP THE PARSER POINTER
	MOVEI	P3,.OHDRS(MO)		;OUTPUT POINTER
	PUSHJ	P,BLDSND		;BUILD THE SEND
	MOVEI	S2,ARG.DA(S1)		;POINT TO THE DATA
	MOVE	S1,JOBTTY		;GET TERMINAL NUMBER
	PUSHJ	P,SNDTTY		;SEND THE MESSAGE
	PUSHJ	P,RELPAG		;RELEASE THE PAGE
	JRST	RESP.4			;AND RELEASE THE MESSAGE
	SUBTTL	PRVCHK AND CHKWHL -- Check if Sender Privileged

;CALLED WITH S1 CONTAINING THE NODE FOR WHICH A REMOTE OPERATOR CAN BE ALLOWED
;	AND S2 CONATINING THE NODE NUMBER IF NEEDED

;ASSUMES THAT G$PRVS AND G$SID HAVE BEEN SET UP
;RETURNS TRUE IF PRIVILEGED, FALSE OTHERWISE

IFN FTJSYS,<
PRVCHK:	PJRST	CHKWHL			;CHECK FOR WHEEL OR OPERATOR
> ;END IFN FTJSYS

IFN FTUUOS,<
PRVCHK:	PUSHJ	P,CHKWHL		;CHECK FOR WHEEL OR OPERATOR
	JUMPT	.POPJ			;O.K...RETURN
	HRRZ	T1,FFAPPN		;GET RIGHT HALF OF PPN
	MOVE	T2,G$SID		;AND SENDERS ID
	CAIE	T1,(T2)			;IF THESE DON'T MATCH, LOSE
	$RETF				;NO GOOD..RETURN FALSE
	HLRZS	T2			;GET HIS PROJECT NUMBER
	SUBI	T2,100			;SUBTRACT OFF FIRST REMOTE OPR OFFSET
	CAMN	T2,S2			;SAME AS ONE WE WANT?
	$RETT				;YES, WIN
	$RETF				;NO GOOD..RETURN FALSE
>   ;END IFN FTUUOS

CHKWHL:	MOVX	S1,MD.PWH!MD.POP	;CHECK FOR WHEEL OR OPERATOR
TOPS10	<SKIPN	DEBUGW		>	;WERE WE DEBUGGING
	TDNE	S1,G$PRVS		;WAS SENDER PRIVILEGED
	$RETT				;YES..RETURN TRUE
	$RETF				;NO..RETURN FALSE
	SUBTTL	G$ACK	--	SEND ACK TO  SENDER

;THIS ROUTINE SENDS AN ACKNOWLEDGEMENT MESSAGE IF ONE WAS REQUESTED.
;IF THERE WAS NO ERROR, A FLAG IS SET IN THE MESSAGE HEADER

G$ACK:	PUSHJ	P,BLDACK		;BUILD AN ACK MESSAGE
	LOAD	S1,.MSCOD(MI)		;GET CODE FROM ORIGINAL MESSAGE
	STORE	S1,.MSCOD(MO)		;AND SAVE IT IN ACK MESSAGE
	SKIPN	S1,G$SND		;PID TO SEND TO
	  PJRST	RELPAG			;INVALID PID, SKIP SEND AND RELEASE PAGE
	MOVEI	S2,PAGSIZ		;GET PAGE SIZE
	PUSHJ	P,SNDPID		;SEND THE MESSAGE
	JUMPT	.POPJ			;O.K. RETURN
	PJRST	RELPAG			;RELEASE PAGE AND RETURN
	SUBTTL	BLDACK	--	BUILD THE ACK MESSAGE

	;THIS ROUTINE WILL BUILD AN ACK MESSAGE TO BE SENT ON ERROR
	;OR FOR MESSAGES TO OPR FROM ORION

BLDACK:	PUSHJ	P,GETPAG		;GET PAGE FOR OUTPUT
	MOVX	S1,MT.TXT		;GET MESSAGE TYPE CODE
	STORE	S1,.MSTYP(MO),MS.TYP	;SAVE MESSAGE TYPE
	SKIPE	G$ERR			;WAS THERE AN ERROR??
	JRST	BLDA.1			;YES, NEED TO BUILD TEXT MESSAGE
	MOVX	S1,MF.NOM		;FLAG THIS AS JUST AN ACK
	IORM	S1,.MSFLG(MO)		;SAVE IN MESSAGE HEADER
	MOVX	S1,.OHDRS		;ACK HEADER SIZE
	STORE	S1,.MSTYP(MO),MS.CNT	;SAVE IN HEADER
	$RETT				;RETURN
BLDA.1:	MOVE	S1,G$ERR		;GET THE ERROR CODE
	MOVE	S2,STSTBL(S1)		;GET STATUS FLAGS
	MOVEM	S2,.MSFLG(MO)		;SAVE THE FLAGS IN MESSAGE
	SKIPGE	S1,G$ERR		;GET ERROR CODE
	JRST	BLDA.3			;NO..PROCESS AS ITEXT
	MOVE	S2,TXTTBL(S1)		;ADDRESS OF MESSAGE
	MOVEI	S1,ARG.DA+.OHDRS(MO)	;ADDRESS TO STORE DATA
	PUSHJ	P,TXTMOV		;MOVE THE DATA
BLDA.2:	HRRZS	S1			;GET ENDING ADDRESS
	ADDI	S1,1			;BUMP IT BY 1
	ANDI	S1,777			;GET MESSAGE LENGTH
	STORE	S1,.MSTYP(MO),MS.CNT	;SAVE COUNT IN MESSAGE
	SUBI	S1,.OHDRS		;GET SIZE OF BLOCK
	STORE	S1,ARG.HD+.OHDRS(MO),AR.LEN	;SAVE ARGUMENT LENGTH 
	MOVX	S1,.CMTXT		;GET TEXT CODE
	STORE	S1,ARG.HD+.OHDRS(MO),AR.TYP	;SAVE ARGUMENT TYPE
	AOS	.OARGC(MO)		;BUMP ARGUMENT COUNT
	$RETT				;RETURN
BLDA.3:	MOVEI	S2,ARG.DA+.OHDRS(MO)	;GET PLACE TO STORE TEXT
	HRLI	S2,(POINT 7,0)		;MAKE A POINTER
	MOVEM	S2,TXTPTR		;SAVE THE POINTER
	$TEXT	(ACKERR,<^I/@TXTTBL(S1)/^0>)	;PLACE TEXT IN MESSAGE
	MOVE	S1,TXTPTR		;GET TXTPTR
	JRST	BLDA.2			;FINISH OFF THE MESSAGE
ACKERR:	IDPB	S1,TXTPTR		;SAVE THE CHARACTER
	$RETT				;RETURN TRUE
	SUBTTL	FNDMSG	--	ROUTINE TO FIND A MESSAGE FOR NODE

	;THIS ROUTINE WILL SEARCH ALL NODES AND CHECK FOR MESSAGE
	;
	;CALL	S1/	MESSAGE NUMBER
	;
	;RETURN	TRUE	S2/ ADDRESS OF MESSAGE ENTRY


FNDMSG:	PUSHJ	P,.SAVE2		;SAVE P1 AND P2
	MOVE	P1,S1			;RELOCATE SEQUENCE NUMBER
FNDM.1:	MOVE	S1,G$NODL		;GET NODE LIST NUMBER
	PUSHJ	P,L%FIRST		;FIND THE FIRST ONE
	JUMPF	.RETF			;EMPTY NODE LIST
FNDM.2:	MOVE	S1,P1			;MESSAGE TO SEARCH FOR
	PUSHJ	P,CHKM.1		;CHECK NODE FOR MESSAGE
	JUMPT	FNDM.3			;FOUND ..RETURN
	MOVE	S1,G$NODL		;GET NODE LIST NUMBER AGAIN
	PUSHJ	P,L%NEXT		;LOOK FOR THE NEXT NODE
	JUMPT	FNDM.2			;LOOP
	$RETF				;FAILURE
FNDM.3:	MOVE	P1,S2			;SAVE THE ENTRY
	MOVE	S1,G$NODL		;GET NODE LIST NUMBER
	PUSHJ 	P,L%RENT		;REMEMBER THE ENTRY
	MOVE	S2,P1			;RESTORE MESSAGE ADDRESS
	$RETT				;RETURN TRUE
	SUBTTL	CHKMSG	--	SEARCH NODE FOR A MESSAGE

	;THIS ROUTINE WILL CHECK FOR THE MESSAGE AT A NODE
	;
	;CALL	S1/	MESSAGE NUMBER
	;	S2/	NODE ADDRESS
	;
	;RETURN	TRUE:	S2/	MESSAGE ADDRESS

CHKMSG:	PUSHJ	P,.SAVE2		;SAVE P1 AND P2
CHKM.1:	DMOVE	P1,S1			;SAVE THE MESSAGE ID AND NODE ADDRESS
	LOAD	S1,NOD.ML(P2)		;GET THE MESSAGE LIST NUMBER
	PUSHJ	P,L%FIRST		;FIND THE FIRST MESSAGE
	JUMPF	.POPJ			;RETURN..IF NONE THERE
CHKM.2:	XCT	FNDXCT				;EXECUTE THE MATCH
	JRST	CHKM.4			;SAVE THE ENTRY
CHKM.3:	MOVE	S1,NOD.ML(P2)		;GET MESSAGE LIST NUMBER AGAIN
	PUSHJ	P,L%NEXT		;FIND NEXT MESSAGE IN THE LIST
	JUMPT	CHKM.2			;CHECK THIS ENTRY
	$RETF				;NO..RETURN FALSE
CHKM.4:	HRRZ	S1,FNDXCT		;GET THE COMPARE TYPE
	CAIE	S1,MSL.CD		;WAS IT THE CODE
	JRST	CHKM.5			;IGNORE NEXT CHECK
	MOVE	S1,G$SND		;GET SENDERS PID
	CAME	S1,MSL.PD(S2)		;IS IT SAME PID
	JRST	CHKM.3			;NO..GET NEXT ENTRY
CHKM.5:	MOVE	P1,S2			;SAVE THE MESSAGE ADDRESS
	MOVE	S1,NOD.ML(P2)		;GET MESSAGE LIST NUMBER
	PUSHJ	P,L%RENT		;REMEMBER THIS ENTRY
	MOVE	S2,P1			;RESTORE MESSAGE ADDRESS
	$RETT				;RETURN TRUE


	SUBTTL	NXTMSG	--	GET NEXT MESSAGE

	;THIS ROUTINE WILL GET NEXT MESSAGE AFTER FNDMSG HAS FOUND ONE
	;
	;	S1/	MESSAGE NUMBER  OR ID

NXTMSG:	PUSHJ	P,.SAVE2		;SAVE P1 AND P2
	MOVE	P1,S1			;SAVE MESSAGE ID
	MOVE	S1,G$NODL		;GET NODE LIST
	PUSHJ	P,L%PREM		;GET REMEMBERED ENTRY
	JUMPF	FNDM.1			;SEARCH THE LIST
	MOVE	P2,S2			;SAVE NODE ADDRESS
	MOVE	S1,NOD.ML(P2)		;GET MESSAGE LIST ADDRESS
	PUSHJ	P,L%PREM		;GET REMEMBERED ENTRY
	JUMPF	NXTM.1			;NONE SET..CHECK ALL MESSAGES AT NODE
	$STOP(REI,<Remembered Entry ^O/S2/ in list ^D/S1/ Invalid>)
NXTM.1:	MOVE	S2,P2			;GET NODE ADDRESS
	JRST	FNDM.2			;PROCESS MESSAGE NOW
	SUBTTL	ADDNOD	--	ROUTINE TO ADD A NODE

COMMENT	\
ROUTINE TO SEE IF NODE IS ENTERED IN THE NODE LIST. IF NOT
ONE IS ENTERED AND THE MESSAGE AND OPR PID LISTS ARE GENERATED.

ON ENTRY:  S1=SIXBIT NODE NAME TO SEARCH FOR
	  S2/NODE NUMBER
TRUE RETURN: S1=ADR OF NODE BLOCK
\

ADDNOD:	PUSHJ	P,FNDNOD		;LOCATE THE NODE BLOCK
	JUMPT	.POPJ			;O.K...RETURN
	MOVE	S1,G$NODL		;GET LIST NUMBER AGAIN
	PUSHJ	P,L%LAST		;POSITION TO END OF LIST
	MOVE	S1,G$NODL		;GET LIST NUMBER AGAIN
	MOVEI	S2,NOD.SZ		;NUMBER OF WORDS
	PUSHJ	P,L%CENT		;CREATE THE ENTRY
	STORE	T1,NOD.NM(S2)		;PLANT THE NODE NAME
	STORE	T2,NOD.NU(S2)		;SAVE NODE NUMBER
	MOVE	T1,S2			;COPY ENTRY ADDRESS TO T1
	PUSHJ	P,L%CLST		;CREATE A MESSAGE LIST
	STORE	S1,NOD.ML(T1)		;STORE MESSAGE LIST NUMBER
	SETZM	NOD.CT(T1)		;CLEAR MESSAGE COUNT
	SETZM	NOD.TM(T1)		;AUTO DISPLAY TIME
	PUSHJ	P,L%CLST		;CREATE A PID LIST
	STORE	S1,NOD.OP(T1)		;STORE THE OPR LIST NUMBER
	MOVE	S1,T1			;COPY ENTRY ADDRESS TO T1
	$RETT				;RETURN TRUE



	SUBTTL	FNDNOD	--	LOCATE THE NODE BLOCK

	;THIS ROUTINE WILL LOCATE A GIVEN NODE IN THE NODE LIST
	;AND RETURN TRUE IF FOUND WITH S2 ADDRESS OF ENTRY

;LOCNOD:	PUSHJ	P,CHKNOD		;CHECK THE NODE
;	JUMPF	.POPJ			;BAD NODE..RETURN
FNDNOD:	DMOVE	T1,S1			;COPY OUR ARG TO T1,T2
	MOVE	S1,G$NODL		;GET NODE LIST NUMBER
	PUSHJ	P,L%FIRST		;POSITION TO FIRST
	JUMPF	.POPJ			;NONE..RETURN FALSE
LOCN.1:	TLNN	T1,770000		;WAS IT SIXBIT?
	JRST	LOCN.3			;TRY NODE NUMBER
	CAME	T1,NOD.NM(S2)		;IS THIS THE NODE WE WANT?
	JRST	LOCN.4			;NOT THIS ONE, GO LOOK AT NEXT
LOCN.2:	MOVE	S1,S2			;COPY ENTRY ADDRESS TO S1
	$RETT				;AND RETURN
LOCN.3:	CAMN	T1,NOD.NU(S2)		;MATCH NODE NUMBER?
	JRST	LOCN.2			;SET NODE AND RETURN
LOCN.4:	MOVE	S1,G$NODL		;GET NOD LIST NUMBER
	PUSHJ	P,L%NEXT		;STEP TO NEXT ENTRY
	JUMPT	LOCN.1			;SEE IF ITS THE ONE
	DMOVE	S1,T1			;RESTORE NODE VALUES
	POPJ	P,			;NO..PASS FALSE UP
	SUBTTL	DELNOD	--	DELETE THE NODE

	;This Routine will Delete a Node entry (Oprs at the Node).

DELNOD:	LOAD	S1,.OHDRS+ARG.HD(MI),AR.TYP	;GET THE MESSAGE TYPE
	CAIE	S1,.OROBJ		;OBJECT BLOCK?
	$RETF				;ERROR..RETURN
	LOAD	T1,.OHDRS+ARG.DA+OBJ.ND(MI)	;GET THE NODE NAME
	MOVX	S1,%ONLINE		;GET THE ONLINE FLAG
	TDNE	S1,.MSFLG(MI)		;WAS IT ONLINE?
	JRST	NODONL			;NODE ONLINE PROCESSING
	MOVE	S1,G$NODL		;GET THE NODE LIST
	PUSHJ	P,L%FIRST		;GET THE FIRST
	SKIPT				;O.K.. SKIP
	$STOP(NDE,NODE DATABASE EMPTY)
DELN.1:	MOVX	T2,ND.D60		;DN60 NODE
	TDNN	T2,NOD.FL(S2)		;IS IT A DN60 NODE?
	JRST	DELN.3			;NO..GET NEXT NODE
	CAME	T1,NOD.NM(S2)		;CHECK THE NODE NAME
	JRST	DELN.3			;NO.. TRY NEXT ONE
	MOVE	T2,S2			;SAVE NODE LIST ENTRY
DELN.2:	MOVE	S1,NOD.OP(T2)		;GET THE OPR LIST NUMBER
	PUSHJ	P,L%FIRST		;POSITION TO FIRST
	JUMPF	DELN.4			;O.K..EXIT NOW
	MOVE	S1,OPR.PD(S2)		;GET THE PID
	PUSHJ	P,DELOPR		;DELETE THE OPR
	JRST	DELN.2			;TRY AGAIN
DELN.3:	MOVE	S1,G$NODL		;GET THE NODE LIST
	PUSHJ	P,L%NEXT		;GET THE NEXT ONE
	JUMPT	DELN.1			;TRY IT
	$RETT				;RETURN
DELN.4:	MOVE	S1,G$NODL		;GET THE NODE LIST NUMBER
	$CALL	L%DENT			;DELETE THE ENTRY
	JUMPT	.POPJ			;O.K. RETURN
	$STOP	(DDF,Delete DN60 Node Failed)


	SUBTTL	NODONL	--	Node Online for DN60

	;This Routine will create the Opr and Node for a Dn60 Operator

NODONL:	SKIPN	P1,.OFLAG(MI)		;PORT ,,LINE MEANS DN60 ?
	$RETT				;NO ...RETURN
	HLRZ	S1,P1			;GET THE PORT NUMBER
	HRRO	S2,P1			;SETUP -1,, LINE NUMBER
	STORE	S1,S2,PPPLLL		;SAVE  AS -1,,PPPLLL
	EXCH	S2,G$SND		;SAVE AS THE SENDER
	MOVE	S1,.OHDRS+ARG.DA+OBJ.ND(MI) ;GET THE NODE NAME
	MOVEM	S1,G$ARG1		;SAVE THE NODE
	SETZ	S2,			;CLEAR NODE NUMBER
	PUSHJ	P,ADDOPR		;ADD THE OPERATOR
	JUMPF	E$OAE			;OPR ALREADY EXISTS
	MOVE	S1,OPR.ND(S2)		;GET THE NODE ADDRESS
	MOVX	T1,ND.D60		;SET AS DN60 NODE
	IORM	T1,NOD.FL(S1)		;SET THE FLAG
	MOVE	S1,OPR.FL(S2)		;GET THE FLAG WORD
	TXO	S1,OP.REM!OP.D60	;SET THE FLAGS
	TXZ	S1,OP.NST		;MARK AS SETUP
	MOVEM	S1,OPR.FL(S2)		;RESTORE THE FLAGS
	$RETT				;O.K. RETURN
	SUBTTL	ADDOPR	--	ADD OPR TO DATA BASE AND NODE LIST

	;THIS ROUTINE WILL CREATE AN ENTRY IN THE OPR TABLE AS WELL AS
	;THE NODE-OPR LIST
	;CALLED	S1+S2/NODE NAME AND NUMBER
	;RETURN TRUE:	S2/ ADDRESS OF OPR ENTRY

ADDOPR:	PUSHJ	P,.SAVE2		;SAVE P1 AND P2
	DMOVE	P1,S1			;SAVE THE NODE DATA
	MOVE	S1,G$SND		;GET THE OPRS PID
	PUSHJ	P,VALOPR		;CHECK IF SETUP
	JUMPT	.RETF			;FOUND...ERROR
	DMOVE	S1,P1			;RESTORE NODE DATA
	PUSHJ	P,ADDNOD		;LOCATE THE NODE OR CREATE NODE
					;S1 HAS NODE ENTRY ADDRESS ON RETURN
	MOVE	T1,S1			;SAVE NODE ADDRESS IN T1
	MOVX	S1,ND.SYS		;CHECK IF SYSTEM NODE
	TDNN	S1,NOD.FL(T1)		;CHECK IF SET IN FLAG WORD
	JRST	ADDO.1			;NO..NOT HAVE TO BE PRIVILEGED
	PUSHJ	P,CHKWHL		;CHECK IF WHEEL OR OPERATOR
	JUMPF	E$IPE			;INSUFFICIENT PRIVILEGES 
ADDO.1:	MOVE	S1,NOD.OP(T1)		;NODE LIST OF OPRS FOR NODE
	MOVE	T2,S1			;SAVE OPR LIST NUMBER IN T2
	MOVEI	S2,OPR.SZ		;SIZE OF OPR ENTRY
	PUSHJ	P,L%CENT		;CREATE AN ENTRY
	MOVE	S1,G$SND		;GET THE PID OF OPR..
	STORE	S1,OPR.PD(S2)		;SAVE PID IN ENTRY
	AOS	NOD.OC(T1)		;BUMP THE ACTIVE OPERATOR COUNT
	MOVX	S1,OP.NST		;NOT SETUP FLAG
	IORM	S1,OPR.FL(S2)		;SAVE IN OPR ENTRY FLAGS
	STORE	T1,OPR.ND(S2)		;SAVE NODE ENTRY ADDRESS IN OPR ENTRY
	STORE	T2,OPR.LS(S2)		;SAVE OPR LIST NUMBER IN LIST
ADDO.2:	MOVE	P1,S2			;SAVE OPR LIST ADDRESS IN P1
	SKIPN	TABFRE			;ANY FREE ENTRIES IN LIST
	PUSHJ	P,EXPTAB		;EXPAND THE OPR TABLE
	MOVE	S1,TABADR		;ADDRESS OF TABLE
ADDO.3:	SKIPN	TOP.PD(S1)		;IS THIS A FREE ENTRY
	JRST	ADDO.4			;FOUND ENTRY..PROCESS IT
	ADDI	S1,TOP.SZ		;TABLE ENTRY SIZE
	JRST	ADDO.3			;TRY NEXT ONE
ADDO.4:	MOVE	T1,S1			;SAVE CURRENT ADDRESS IN T1
	SOS	TABFRE			;DECREMENT FREE COUNT
	MOVE	T2,G$SND		;GET THE PID
	STORE	T2,TOP.PD(T1)		;SAVE PID IN TABLE
	STORE	P1,TOP.OA(T1)		;SAVE OPR ENTRY ADDRESS IN TABLE
	STORE	T1,OPR.TP(P1)		;SAVE TABLE ADDRESS IN OPR ENTRY
	MOVEM	P1,G$OPRA		;SAVE OPR ADDRESS
	PUSHJ	P,L$AOPR##		;ADD THE OPERATOR LOGGING
	MOVE	S1,G$SID		;GET USER NUMBER OR PPN
	MOVEM	S1,OPR.US(P1)		;SAVE USER IN OPR BLOCK
IFN	FTUUOS,<
	LOAD	S1,G$PRVS,MD.PJB	;GET THE JOB NUMBER
	PUSHJ	P,GETNAM		;GET THE USER NAME
	DMOVE	S1,JOBUSN		;GET USER NAME
	DMOVEM	S1,OPR.UN(P1)		;SAVE THE NAME
>;END FTUUOS
	LOAD	S1,G$PRVS,MD.PJB	;GET JOB NUMBER
	MOVEM	S1,OPR.JB(P1)		;SAVE OPR JOB NUMBER
	MOVX	S2,JI.TNO		;GET TERMINAL NUMBER
	PUSHJ	P,I%JINF		;GET JOB INFO
	JUMPF	ADDO.5			;IGNORE IF FALSE***
	MOVEM	S2,OPR.TN(P1)		;SAVE TERMINAL NUMBER
ADDO.5:	MOVE	S2,P1			;GET OPR ADDRESS
	$RETT				;RETURN TRUE
	SUBTTL	EXPTAB	--	EXPAND OPR TABLE ROUTINE

	;THIS ROUTINE WILL EXPAND THE OPR TABLE TO MAKE ROOM
	;FOR MORE ENTRIES
	;AS WELL AS THE OPR RESEND TABLE LENGTH

EXPTAB:	MOVE	S1,TABCNT		;GET COUNT OF ENTRIES NOW
	ADDI	S1,^D10			;INCREMENT TABLE BY 10 ENTRIES
	IMULI	S1,TOP.SZ		;OPR TABLE SIZE
	PUSHJ	P,M%GMEM		;GET THE MEMORY
	EXCH	S2,TABADR		;SAVE NEW ADDRESS AND GET OLD
	JUMPE	S2,EXPT.1		;FIRST TIME..NO TABLE SO FAR
	MOVE	T1,S2			;SAVE ADDRESS IN T1
	HRL	S2,S2			;SOURCE ADDRESS IN LEFT HALF
	HRR	S2,TABADR		;DESTINATION ADDRESS IN RIGHT
	MOVE	S1,TABCNT		;NUMBER OF ENTRIES
	IMULI	S1,TOP.SZ		;MULTIPLY BY ENTRY SIZE
	ADD	S1,TABADR		;ADD IN TABLE ADDRESS
	BLT	S2,-1(S1)		;MOVE THE TABLE
	MOVE	S2,T1			;PUT OLD ADDRESS IN S2
	MOVE	S1,TABCNT		;NUMBER OF ENTRIES
	IMULI	S1,TOP.SZ		;SIZE OF TABLE
	PUSHJ	P,M%RMEM		;RELEASE THE MEMORY
EXPT.1:	MOVE	S1,OPRRCT		;GET OPR COUNT
	ADDI	S1,^D10			;GET INCREMENT SIZE
	PUSHJ	P,M%GMEM		;GET SOME MEMORY
	EXCH	S1,OPRRCT		;GET THE OLD COUNT AND REPLACE WITH NEW
	EXCH	S2,OPRRSL		;RESEND LIST ADDRESS
	JUMPE	S2,EXPT.2		;FIRST TIME..=0 GO TO EXPT.1
	PUSHJ	P,M%RMEM		;RETURN THE OLD LIST
EXPT.2:	MOVEI	S1,^D10			;NUMBER OF ENTRIES TO INCREMENT
	ADDM	S1,TABCNT		;SAVE TABLE ENTRIES
	ADDM	S1,TABFRE		;SAVE FREE ENTRY COUNT
	MOVE	S1,TABADR		;GET THE TABLE ADDRESS
	MOVE	S2,TABCNT		;GET THE TABLE COUNT
EXPT.3:	SKIPN	T1,TOP.OA(S1)		;VALID ENTRY?
	$RETT				;NO..END OF LIST
	MOVEM	S1,OPR.TP(T1)		;RESET THE ADDRESS
	ADDI	S1,TOP.SZ		;GET NEXT ADDRESS
	SOJG	S2,EXPT.3		;TRY THE NEXT ONE
	$RETT				;ALL DONE..RETURN
	SUBTTL	VALOPR	--	VALIDATE THE OPR FOR ORION

	;THIS ROUTINE WILL CHECK TO SEE IF A GIVEN OPR PID IS VALID
	;TO SEND COMMANDS TO ORION

	;RETURNS S2/ ADDRESS OF OPR LIST ENTRY

VALOPR:	MOVE	S2,TABADR		;GET THE TABLE ADDRESS
	SKIPN	T1,TABCNT		;MAXIMUM NUMBER OF ENTRIES
	$RETF				;NONE SETUP SO FAR..RETURN
VALO.1:	CAMN	S1,TOP.PD(S2)		;CHECK PID FOR MATCH
	JRST	VALO.2			;MATCH..SETUP FOR RETURN
	ADDI	S2,TOP.SZ		;BUMP TO NEXT ENTRY
	SOJG	T1,VALO.1		;LOOP THROUGH ALL ENTRIES
	$RETF				;OPR NOT HERE..RETURN FALSE
VALO.2:	MOVE	S2,TOP.OA(S2)		;OPR LIST ENTRY ADDRESS
	$RETT				;RETURN TRUE
	SUBTTL	DELOPR	--	DELETE OPR ENTRY AND TABLE DATA

	;THIS ROUTINE WILL REMOVE AN OPR ENTRY FROM THE TABLE
	;OF OPRS AS WELL AS FROM THE NODE LIST OF OPRS.


DELOPR:	PUSHJ	P,.SAVET		;SAVE T REGS
	PUSHJ	P,VALOPR		;VALIDATE THE OPR
	SKIPT				;O.K...SKIP
	$RETF				;JUST RETURN FALSE
	MOVE	T1,OPR.TP(S2)		;ADDRESS OF OPR TABLE ENTRY
	AOS	TABFRE			;BUMP FREE ENTRY COUNT
	MOVE	T2,OPR.PD(S2)		;OPR PID 
	SETZM	TOP.OA(T1)		;CLEAR ADDRESS OF ENTRY
	SETZM	TOP.PD(T1)		;CLEAR PID
	MOVE	S1,OPR.LS(S2)		;OPR LIST NUMBER
	PUSHJ	P,L%FIRST		;POSITION TO FIRST
	SKIPT				;OPR DELETE FATAL ERRO
	$STOP(ODE,OPR Delete Entry Error)
DELO.1:	CAMN	T2,OPR.PD(S2)		;FOUND THE ENTRY
	JRST	DELO.2			;YES...DELETE ENTRY
	MOVE	S1,OPR.LS(S2)		;GET LIST NUMBER FROM ENTRY
	PUSHJ	P,L%NEXT		;GET NEXT ENTRY
	JUMPT	DELO.1			;CHECK OUT ENTRY
	PUSHJ	P,S..ODE		;FATAL ERROR EXIT
DELO.2:	MOVE	T1,OPR.ND(S2)		;GET NODE ADDRESS
	SOS	NOD.OC(T1)		;REDUCE OPRS AT NODE COUNT
	MOVEM	S2,G$OPRA		;SAVE OPR ADDRESS
	PUSHJ	P,L$DOPR##		;DELETE THE OPERATOR LOGGING
	MOVE	S2,G$OPRA		;GET OPR ADDRESS
	MOVE	S1,OPR.LS(S2)		;LIST NUMBER
	PUSHJ	P,L%DENT		;DELETE THE ENTRY
	JUMPF	S..ODE			;OPR DELETE ERROR
	POPJ	P,			;RETURN

	;***NODE COUNT OF OPRS GOES TO ZERO..NODE NOT THERE..DELETE NODE
	SUBTTL	SNDLST	--	SEND UNSENT MESSAGES TO OPR/OBJECT

	;THIS ROUTINE WILL TRY TO SEND THE UNSENT MESSAGES TO THE
	;APPROPRIATE OPR OR OBJECT

	;CALL	S1/	MESSAGES TO SEND

SNDLST:	PUSHJ	P,.SAVE1		;SAVE AN AC
	MOVE	P1,S1			;SAVE THE FLAGS
	MOVE	S1,G$SNDL		;GET SEND LIST
	PUSHJ	P,L%FIRST		;POSITION TO THE FIRST
	JUMPF	.RETT			;NONE..RETURN
SNDL.1:	TDNN	P1,RSD.FL(S2)		;CHECK FLAGS FOR OBJECT
	JRST	SNDL.2			;NO MATCH..TRY NEXT ONE
	MOVE	S1,G$SND		;GET SENDERS PID(OBJECT)
	PUSHJ	P,RSDPID		;RESEND TO PID AND DELETE IF O.K.
	JUMPF	.RETT			;ERROR..STOP SENDING
SNDL.2:	MOVE	S1,G$SNDL		;GET SEND LIST
	PUSHJ	P,L%NEXT		;POSITION TO THE NEXT ENTRY
	JUMPT	SNDL.1			;O.K...TRY NEXT ONE
	$RETT				;RETURN O.K.
	SUBTTL	RSDPID	--	RESEND MESSAGES TO A PARTICULAR PID

	;CALL 	S1/	PID TO RESEND TO

RSDPID:	PUSHJ	P,.SAVE1		;SAVE 1 FOR SCRATCH
	MOVE	MO,RSD.MS(S2)		;GET MESSAGE ADDRESS
	ADDI	MO,(S2)			;GET ACTUAL ADDRESS
	MOVE	P1,S2			;SAVE ENTRY ADDRESS
	LOAD	S2,.MSTYP(MO),MS.CNT	;GET MESSAGE SIZE
	PUSHJ	P,CHKSFL		;CHECK FOR SEND FAILURES
	JUMPT	RSDP.3			;YES..JUST REQUEUE
	PUSHJ	P,SNDMSG		;SEND THE MESSAGE
	JUMPF	RSDP.2			;FAIL..QUEUE UP FOR RESEND
RSDP.1:	SOS	G$NSNT			;DECREMENT NOT SENT COUNT
	MOVE	S1,G$SNDL		;GET SEND LIST
	PJRST	L%DENT			;DELETE THE ENTRY AND RETURN
RSDP.2:	MOVE	S1,SNDBLK+SAB.PD	;GET THE PID
	PUSHJ	P,ADDSFL		;ADD THE SEND FAILURE
	MOVE	S1,G$RSDL		;QUEUE UP FOR RESEND
	PUSHJ	P,L%LAST		;POSTION TO THE END
	LOAD	S2,RSD.HD(P1),RS.LEN	;GET THE LENGTH OF ENTRY
	MOVE	S1,G$RSDL		;GET LIST NUMBER
	PUSHJ	P,L%CENT		;CREATE AN ENTRY
	MOVE	S1,G$SND		;GET SENDERS PID
	MOVE	T1,RSD.PD(P1)		;GET PID OFFSET
	ADDI	T1,(P1)			;POINT TO PID AREA
	MOVEM	S1,(T1)			;SAVE THE PID
	AOS	RSD.CT(P1)		;BUMP COUNT OF PIDS
	MOVE	S1,P1			;OLD ENTRY
	PUSHJ	P,MOVBLK		;MOVE THE BLOCK TO OTHER LIST
	AOS	G$RSDC			;BUMP THE RESEND COUNT
	SETZM	RSDCNT			;CLEAR THE RESEND COUNT
	JRST	RSDP.1			;NOW DELETE OLD ONE
RSDP.3:	MOVEM	S1,SNDBLK+SAB.PD		;SAVE THE PID
	JRST	RSDP.2			;REQUEUE THE MESSAGE
	SUBTTL	MOVARG	--	SETUP ARGUMENT IN OUTPUT MESSAGE

	;THIS ROUTINE WILL MOVE AN ARGUMENT BLOCK FROM INPUT TO OUTPUT
	;MESSAGE
	;
	;CALL	S1/	ADDRESS OF SOURCE TEXT
	;	S2/	LENGTH IN WORDS OF TEXT
	;
	;RETURN	P3/ UPDATED TO NEXT FREE OUTPUT LOCATION

MOVARG:: HRL	T1,S1			;ADDRESS OF TEXT SOURCE
	HRRI	T1,ARG.HD(P3)		;DESTINATION ADDRESS
	ADD	P3,S2			;GET ENDING ADDRESS
	BLT	T1,-1(P3)		;MOVE TEXT TO MESSAGE
	AOS	.OARGC(MO)		;BUMP THE ARGUMENT COUNT
	$RETT				;RETURN TRUE


	;*** CHECK FOR NULL ANSWER...
	SUBTTL	SNDAOP	--	SEND TO ALL OPRS A MESSAGE

	;THIS ROUTINE WILL SEND A MESSAGE TO ALL OPRS AT A GIVEN NODE
	;OR TO SYSTEM NODE IF NO OPRS AT THAT NODE
	;OR IF -1 IS SET IN NODE ADDRESS TO ALL OPRS AT ALL NODES

SNDAOP:	SETZM	NOALTN			;ALTERNATE NODE IF NODE FAILS

	;THIS ENTRY IS FOR NO ALTERNATES AND CALLER AS MADE NOALTN -1 TO
	;PREVENT SEARCH OF OTHER NODES IF FAILS
SNDNAL:	PUSHJ	P,.SAVE1		;GET AN AC FOR SCRATCH
	MOVE	P1,S1			;SAVE THE NODE LIST ENTRY
	SETZM	MSGCNT			;CLEAR COUNT OF SENDS
	SETZM	RSDCNT			;SET RESEND COUNT INDICATOR
	CAMN	P1,[-1]			;IS IT -1
	JRST	SNDA.8			;YES..SEND TO ALL NODES
	PUSHJ	P,SNDOPR		;SEND TO THE OPRS AT NODE
	JUMPT	SNDA.5			;SENT O.K. CHECK RESENDS
	SKIPE	NOALTN			;SEND TO ALTERNATES ON FAILURE?
	POPJ	P,			;NO..RETURN..PASSING FALSE UP
SNDA.1:	MOVE	T1,NOD.FL(P1)		;GET ENTRIES FLAGS
	TXNE	T1,ND.SYS		;WAS IT THE SYSTEM NODE
	JRST	SNDA.5			;YES..CHECK RESEND AND RETURN
	MOVE	S1,G$NODL		;GET NODE LIST ENTRY
	PUSHJ	P,L%FIRST		;GET THE FIRST ENTRY
SNDA.2:	MOVE	T1,NOD.FL(S2)		;CHECK FLAGS OF ENTRY
	TXNE	T1,ND.SYS		;SYSTEM OPR?
	JRST	SNDA.4			;YES..SEND TO ALL AT THIS NODE
SNDA.3:	MOVE	S1,G$NODL		;GET THE NODE LIST
	PUSHJ	P,L%NEXT		;GET THE NEXT ENTRY
	JUMPT	SNDA.2			;O.K. TRY NEXT ENTRY
	JRST	SNDA.5			;CHECK SEND AND RESEND INFO
SNDA.4:	MOVE	P1,S2			;GET THE ENTRY ADDRESS
	PUSHJ	P,SNDOPR		;SEND TO ALL OPRS
					;CHECK RESEND AND SEND AFTER RETURN
SNDA.5:	SKIPG	RSDCNT			;ANY RESENDS?
	JRST	SNDA.6			;YES.. REQUEUE THE MESSAGE
	MOVX	S1,R.SOPR		;RESENDS FOR OPR
	MOVE	S2,G$RSDL		;RESENDS..(SEND FAILURE LIST)
	AOS	G$RSDC			;BUMP THE RESEND COUNT
	JRST	SNDA.7			;REQUEUE AND RELEASE
SNDA.6:	SKIPLE	S1,MSGCNT		;SENT MESSAGE TO ANYONE??
	PJRST	RELPAG			;YES..RELEASE PAGE AND RETURN
	AOS	G$NSNT			;BUMP NOT SENT COUNT
	MOVX	S1,R.SOPR!R.NSNT	;OPR MESSAGE NOT SENT
	MOVE	S2,G$SNDL		;LIST FOR UNSENT MESSAGES
SNDA.7:	PUSHJ	P,REQMSG		;REQUEUE THE MESSAGE
	PJRST	RELPAG			;RELEASE THE PAGE AND RETURN
SNDA.8:	MOVE	S1,G$NODL			;GET NODE LIST NUMBER
	PUSHJ	P,L%FIRST		;POSITION TO THE FIRST
SNDA.9:	MOVE	P1,S2			;GET THE ADDRESS IN P1
	PUSHJ	P,SNDOPR		;SEND TO ALL OPRS AT NODE
	MOVE	S1,G$NODL		;GET NODE LIST NUMBER
	PUSHJ	P,L%NEXT		;GET THE NEXT ENTRY
	JUMPF	SNDA.5			;ANALYZE RESULTS AND RETURN
	JRST	SNDA.9			;TRY NEXT ONE
	SUBTTL	SNDOPR	--	SEND TO ALL OPRS

	;THIS ROUTINE WILL SEND THE MESSAGE TO ALL OPRS AND RETURN FALSE
	;IF NO OPRS AT NODE OTHERWISE WILL BE QUEUED UP FOR THE OPR


SNDOPR:	MOVE	T4,MSGCNT		;SAVE MESSAGE COUNT VALUE
	MOVE	T3,RSDCNT		;GET THE CURRENT RESEND COUNT
	LOAD	S1,NOD.OP(P1)		;GET OPR LIST NUMBER
	PUSHJ	P,L%FIRST		;POSITION TO FIRST ENTRY
	JUMPF	.POPJ			;RETURN FALSE
SNDO.1:	MOVE	T2,OPR.FL(S2)		;GET THE OPRS FLAGS
	TXNE	T2,OP.NST		;IS OPR SETUP?
	JRST	SNDO.6			;IGNORE THIS OPR
	PUSHJ	P,CHKOSD		;CHECK IF OPR WANTS MESSAGE
	JUMPF	SNDO.5			;NO..BYPASS THIS OPR
SNDO.2:	MOVEM	S2,G$OPRA		;SAVE THE OPR ADDRESS
	LOAD	S1,OPR.PD(S2)		;GET THE OPRS PID
	MOVE	T2,S1			;SAVE THE PID
	PUSHJ	P,CHKSFL		;CHECK FOR SEND FAILURES ON PID
	JUMPT	SNDO.4			;MARK FOR RESEND
	LOAD	S2,.MSTYP(MO),MS.CNT	;GET THE MESSAGE LENGTH
	PUSHJ	P,SNDMSG		;SEND THE MESSAGE
	JUMPT	SNDO.5			;O.K. COUNT IT AND SEND TO OTHERS
	AOS	G$SNDF			;BUMP SEND FAILURE COUNT
	CAXE	S1,ERNSP$		;NO SUCH PID??
	JRST	SNDO.4			;MARK TO RESEND
SNDO.3:	MOVE	S1,T2			;GET THE BAD PID
	PUSHJ	P,DELOPR		;DELETE THE OPERATOR
	JRST	SNDO.6			;TRY NEXT OPERATOR
SNDO.4:	MOVE	S1,T2			;GET THE PID
	PUSHJ	P,ADDSFL		;ADD SEND FAILURE PID
	JRST	SNDO.6			;TRY NEXT OPR
SNDO.5:	AOS	MSGCNT			;BUMP THE SEND COUNT
SNDO.6:	LOAD	S1,NOD.OP(P1)		;GET OPR PID LIST
	PUSHJ	P,L%NEXT		;GET THE NEXT ENTRY
	JUMPT	SNDO.1			;TRY NEXT OPR
	CAML	T4,MSGCNT		;SEND ANY MESSAGES
	CAMGE	T3,RSDCNT		;REQUEUE ANY MESSAGES
	$RETT				;YES..RETURN TRUE
	$RETF				;NO..SENDS
	SUBTTL	CHKOSD	--	CHECK MESSAGE FLAGS FOR OPR

	;THIS ROUTINE WILL DETERMINE IF OPR WANTS TO SEE THE MESSAGE
	;AND
	;
	;RETURN	TRUE:	OPR WANTS TO SEE IT
	;RETURN FALSE:	OPR DOESN'T WANT TO SEE IT

CHKOSD:	SKIPE	G$ASND			;ALWAYS SEND MESSAGE?
	$RETT				;YES..MAKE OPR SEE IT
	SKIPE	S1,WDAAFL		;APPLICATION FLAGS
	JRST	CHKO.1			;YES..CHECK THOSE
	MOVE	S1,WDAFLG		;GET THE FLAGS FROM MESSAGE
	MOVE	T2,OPR.OF(S2)		;OBJECT FLAGS
	AND	T2,[OP.ALL]		;GET JUST DISPLAY OPTIONS
	TXC	T2,OP.ALL		;COMPLEMENT THE FLAGS
CHKO.0:	SKIPN	T1,T2			;SAVE IN T1
	$RETF				;RETURN FALSE
	IOR	T2,S1			;TURN ON ALL CURRENT DISPLAYS
	CAME	T2,T1			;STILL MATCH SETTINGS
	$RETF				;RETURN FALSE
	$RETT				;RETURN TRUE
CHKO.1:	MOVE	T2,OPR.AF(S2)		;GET APPLICATION SETTINGS
	AND	T2,[OP.AAP]		;ALL APPLICATIONS
	TXC	T2,OP.AAP		;ALL APPLICATIONS
	JRST	CHKO.0			;FINISH IT OFF
	SUBTTL	MOVBLK	--	MOVE A GALAXY BLOCK ROUTINE

	;THIS ROUTINE WILL MOVE A STANDARD GALAXY BLOCK FROM 
	;SOURCE ADDRESS TO DESTINATION ADDRESS
	;THE LENGTH IS GOTTEN FROM SOURCE FIRST WORD..(HEADER)
	;
	;CALL	S1/	SOURCE ADDRESS
	;	S2/	DESTINATION ADDRESS
	;
	;RETURN	S2/	UPDATED DESTINATION ADDRESS
	;
	;SCRATCH AC T1

MOVBLK:	HRL	T1,S1			;GET SOURCE ADDRESS IN LEFT HALF
	HRR	T1,S2			;AND DESTINATION IN RIGHT HALF
	LOAD	S1,ARG.HD(S1),AR.LEN	;GET THE LENGTH OF BLOCK
	ADD	S2,S1			;GET ENDING ADDRESS
	BLT	T1,-1(S2)		;MOVE THE BLOCK
	$RETT				;RETURN TRUE
	SUBTTL	REQMSG	--	REQUEUE THE MESSAGE FOR RESENDING

	;THIS ROUTINE WILL SETUP THE RESEND ENTRY FOR A MESSAGE
	;
	;CALL	S1/	FLAGS FOR REQUEUE
	;	S2/	LIST NUMBER TO REQUEUE IN
	;
	;RETURN	S2/	ENTRY ADDRESS

REQMSG:	DMOVE	T3,S1			;SAVE S1 AND S2 IN T3 AND T4
	MOVE	S1,T4			;GET RESEND LIST ADDRESS
	PUSHJ	P,L%LAST		;POSITION TO THE END
	LOAD	S2,.MSTYP(MO),MS.CNT	;GET THE MESSAGE COUNT
	ADDI	S2,RSD.SZ		;GET SIZE OF BLOCK AND PID LIST HEADER
	SKIPG	S1,RSDCNT		;ANY RESENDS
	MOVEI	S1,1			;ALWAYS LEAVE 1
	ADD	S2,S1			;GET THE NEW COUNT
	MOVE	S1,T4			;GET RESEND LIST NUMBER
	MOVE	T1,S2			;SAVE SIZE OF ENTRY
	PUSHJ	P,L%CENT		;CREATE AN ENTRY
	STORE	T1,RSD.HD(S2),RS.LEN	;SAVE THE LENGTH
	MOVE	S1,G$NOW		;GET THE TIME
	MOVEM	S1,RSD.TM(S2)		;SAVE TIME IN ENTRY
	MOVE	T2,S2			;SAVE ENTRY ADDRESS
	MOVEI	S1,RSD.SZ		;GET RESEND BLOCK SIZE
	MOVEM	S1,RSD.PD(S2)		;SAVE AS PID OFFSET
	MOVEI	T1,RSD.SZ+1		;OFFSET FOR MESSAGE..LEAVE FOR 1 PID
	SKIPG	RSDCNT			;MOVE PID LIST IF ANY
	JRST	REQM.1			;ASSUME 1
	HRL	S1,OPRRSL		;ADDRESS OF RESEND LIST
	HRRI	S1,RSD.SZ(S2)		;START OF FREE AREA
	MOVEI	T1,RSD.SZ(S2)		;ADDRESS OF DESTINATION STARTING POINT
	ADD	T1,RSDCNT		;ADD IN NUMBER OF PIDS
	BLT	S1,-1(T1)		;MOVE THE PIDS
	SUB	T1,S2			;GET THE OFFSET
REQM.1:	MOVEM	T1,RSD.MS(S2)		;SAVE OFFSET FOR MESSAGE
	MOVE	T2,S2			;SAVE MESSAGE ADDRESS
	ADD	S2,T1			;POSITION TO TEXT
	MOVEI	S1,.MSTYP(MO)		;GET THE MESSAGE ADDRESS
	PUSHJ	P,MOVBLK		;MOVE THE BLOCK
	IORM	T3,RSD.FL(T2)		;NO..SAVE THE FLAGS
	MOVE	S2,T2			;SAVE THE ADDRESS
	SETZ	S1,			;CLEAR S1
	EXCH	S1,RSDCNT		;RESET AND GET RSDCNT
	MOVEM	S1,RSD.CT(S2)		;SAVE THE COUNT
	$RETT				;RETURN S2, ENTRY ADDRESS
	SUBTTL	RSDMSG	--	RESEND MESSAGE ROUTINE

	;THIS ROUTINE WILL TRY TO SEND ANY MESSAGES QUEUED UP IN THE SYSTEM
	;AND WILL DELETE FROM THE QUEUE WHEN SENT TO ALL PIDS OR RETRY COUNT 
	;EXHAUSTED

RSDMSG:	SKIPN	G$RSDC			;ANY MESSAGES TO RESEND
	$RETT				;NO..RETURN O.K.
	PUSHJ	P,CLRSFL		;CLEAR SEND FAILURE LIST
	SETZM	RSDCNT			;CLEAR THE RESEND COUNT
	PUSHJ	P,.SAVE3		;GET SOME SCRATCH ACS
	MOVE	S1,G$RSDL		;GET RESEND LIST NUMBER
	PUSHJ	P,L%FIRST		;POSITION TO THE FIRST ENTRY
	SKIPT				;SKIP IF THERE
	$STOP(RCO,G$RSDC OFF.. DOES NOT MATCH LIST DATA)
	MOVE	P1,S2			;SAVE ADDRESS IN S2
RSDM.1:	MOVE	P2,RSD.CT(P1)		;GET COUNT OF PIDS
	MOVE	P3,RSD.PD(P1)		;GET PID OFFSET
	ADDI	P3,(P1)			;COMPUTE MESSAGE ADDRESS
RSDM.2:	SKIPN	S1,(P3)			;GET THE FIRST PID
	JRST	RSDM.4			;ZERO..GET NEXT ENTRY
	PUSHJ	P,CHKSFL		;CHECK FOR SEND FAILURE ON PID
	JUMPT	RSDM.4			;CHECK NEXT ONE
	MOVE	MO,RSD.MS(P1)		;GET MESSAGE ADDRESS
	ADDI	MO,(P1)			;GET ACTUAL ADDRESS
	LOAD	S2,.MSTYP(MO),MS.CNT	;GET MESSAGE LENGTH
	PUSHJ	P,SNDMSG		;SEND THE MESSAGE
	JUMPF	RSDM.7			;SEND FAILURE..UP COUNTS
	MOVX	S1,R.NSNT		;CLEAR THE NOT SENT FLAG
	ANDCAM	S1,RSD.FL(P1)		;CLEAR IT IN BLOCK
RSDM.3:	SETZM	(P3)			;CLEAR THE PID ENTRY
	SOSG	RSD.CT(P1)		;ANY MORE PIDS LEFT
	JRST	RSDM.5			;NO..REMOVE ENTRY
RSDM.4:	AOS	P3			;NEXT PID
	SOJG	P2,RSDM.2		;CHECK IF MORE
	JRST	RSDM.6			;GET NEXT ENTRY
RSDM.5:	MOVX	S1,R.NSNT		;GET THE NOT SENT FLAG
	TDNE	S1,RSD.FL(P1)		;WAS IT EVER SENT
	PUSHJ	P,REQNST		;REQUEUE FOR NOT SENT
	MOVE	S1,G$RSDL		;GET THE RESEND LIST
	PUSHJ	P,L%DENT		;DELETE THE ENTRY
	SOSGE	G$RSDC			;DECREMENT RESEND COUNT
	$STOP(RCN,G$RSDC is Negative Database Confused)
RSDM.6:	MOVE	S1,G$RSDL		;GET THE LIST NUMBER
	PUSHJ	P,L%NEXT		;GET THE NEXT ENTRY
	JUMPF	.RETT			;DONE..RETURN
	SETZM	RSDCNT			;CLEAR THE RESEND COUNT
	MOVE	P1,S2			;SAVE THE MESSAGE ADDRESS
	JRST	RSDM.1			;TRY THIS ONE
RSDM.7:	AOS	G$SNDF			;BUMP SEND FAILURE COUNT
	AOS	RSD.RT(P1)		;BUMP THE RETRY COUNT...****
	CAXE	S1,ERNSP$		;NO SUCH PID??
	JRST	RSDM.8			;NO..RETRY LATER
	MOVE	S1,RSD.FL(P1)		;GET THE FLAGS
	TXNN	S1,R.SOPR		;WAS IT OPR RESEND
	JRST	RSDM.3			;DELETE PID FROM ENTRY
	MOVE	S1,(P3)			;GET THE PID
	PUSHJ	P,DELOPR		;DELETE THE OPR
	JRST	RSDM.3			;TRY NEXT ONE
RSDM.8:	MOVE	S1,(P3)			;GET THE PID
	PUSHJ	P,ADDSFL		;ADD THE SEND FAILURE
	JRST	RSDM.4			;FINISH OFF ENTRY
	SUBTTL	REQNST	--	REQUEUE MESSAGES NOT SENT

	;THIS ROUTINE WILL MOVE A RESEND BACK TO THE NEVER SENT QUEUE IF MESSAGE
	;NOT SENT AND OPR INVALID

REQNST:	MOVE	S1,G$SNDL		;NOT SENT LIST
	PUSHJ	P,L%LAST		;POSITION TO LAST
	AOS	G$NSNT			;BUMP NOT SENT COUNT
	MOVE	S1,G$SNDL		;GET LIST NUMBER AGAIN
	LOAD	S2,RSD.HD(P1),RS.LEN	;GET LENGTH OF BLOCK
	PUSHJ	P,L%CENT		;CREATE AN ENTRY
	MOVE	S1,P1			;ADDRESS OF OLD ONE
	PJRST	MOVBLK			;MOVE THE BLOCK AND RETURN
	SUBTTL	ADDSFL	--	ADD SEND FAILURE TO TABLE
	;
	;S1/	PID TO ADD

ADDSFL:	MOVEM	S1,G$SFPD		;SAVE THE PID
	SKIPN	SFLFRE			;ANY AVAILABLE ENTRIES
	PUSHJ	P,ADDP.3		;NO...GET SOME MORE
	PUSHJ	P,.SAVE2		;GET A SCRATCH AC
	MOVE	S1,G$SFPD		;GET THE PID
	PUSHJ	P,CHKS.0		;CHECK IF IN LIST
	JUMPT	ADDP.5			;BUMP THE COUNT AND RETURN
	MOVE	S2,SFLADR		;GET ADDRESS OF TABLE
ADDP.1:	SKIPN	SFL.PD(S2)		;IS THE ENTRY AVAILABLE
	JRST	ADDP.2			;YES..USE IT
	ADDI	S2,SFL.SZ		;BUMP TO NEXT ONE
	JRST	ADDP.1			;TRY AGAIN
ADDP.2:	MOVE	S1,G$SFPD		;GET THE PID
	MOVEM	S1,SFL.PD(S2)		;SAVE PID IN TABLE
	AOS	SFL.CT(S2)		;BUMP COUNT OF MESSAGES
	SOS	SFLFRE			;DECREMENT FREE LOCATIONS
ADDRTY:	AOS	S2,RSDCNT		;BUMP RESEND COUNT AND PLACE IN S2
	ADD	S2,OPRRSL		;GET ADDRESS FOR ENTRY
	MOVEM	S1,-1(S2)		;SAVE THE PID
	$RETT				;RETURN
ADDP.3:	PUSHJ	P,.SAVE2		;SAVE P1
	MOVE	S1,SFLCNT		;GET NUMBER OF ENTRIES
	ADDI	S1,^D10			;INCREMENT COUNT
	IMULI	S1,SFL.SZ		;GET SIZE NEEDED FOR TABLE
	PUSHJ	P,M%GMEM		;GET THE MEMORY
	MOVE	P1,S2			;SAVE THE ADDRESS
	SKIPN	SFLCNT			;ZERO COUNT
	JRST	ADDP.4			;YES..UPDATE AND RETURN
	MOVE	P2,SFLCNT		;GET COUNT OF ENTRIES
	IMULI	P2,SFL.SZ		;COMPUTE LENGTH OF TABLE
	ADD	P2,S2			;GET ENDING ADDRESS OF NEW TABLE
	HRL	S1,SFLADR		;GET ADDRESS OF OLD TABLE
	HRR	S1,S2			;AND ADDRESS OF NEW TABLE
	BLT	S1,-1(P2)		;MOVE THE TABLE
	MOVE	S1,SFLCNT		;GET OLD COUNT
	IMULI	S1,SFL.SZ		;MULTIPLY BY ENTRY SIZE
	MOVE	S2,SFLADR		;GET OLD ADDRESS
	PUSHJ	P,M%RMEM		;RETURN THE MEMORY
ADDP.4:	MOVEM	P1,SFLADR		;SAVE NEW ADDRESS
	MOVEI	S1,^D10			;GET INCREMENT
	ADDM	S1,SFLCNT		;SAVE NEW COUNT
	ADDM	S1,SFLFRE		;SAVE NEW FREE COUNT
	$RETT				;RETURN
ADDP.5:	AOS	SFL.CT(P2)		;INCREMENT THE COUNT
	MOVE	S1,G$SFPD		;GET THE BAD PID
	PJRST	ADDRTY			;ADD TO RETRY LIST
	$RETT				;RETURN
					;P2 SET FROM CHKSFL(CHKS.0)
	SUBTTL	DELSFL	--	DELETE SEND FAILURE ENTRY

	;THIS ROUTINE WILL REMOVE ENTRY FROM SEND FAILURE PID TABLE

DELSPL:	PUSHJ	P,.SAVE2		;SAVE TWO ACS
	PUSHJ	P,CHKS.0		;CHECK AND GET ACS RETURNED
	SKIPT				;O.K. ENTRY ADDRESS IN T2
	$STOP(DSP,Delete Send Failure PID Table Entry Inconsistency)
	SETZM	SFL.PD(P2)		;CLEAR PID ENTRY
	SETZM	SFL.CT(P2)		;CLEAR THE COUNT ENTRY
	AOS	SFLFRE			;BUMP FREE COUNT
	$RETT				;RETURN



	SUBTTL	CHKSFL	--	CHECK SEND FAILURE ENTRIES

	;THIS ROUTINE WILL CHECK FOR PID IN TABLE


	;CALL	S1/	PID TO CHECK
	;
	;RETURN	 TRUE:	FOUND ENTRY
	;RETURN FALSE: DIDN'T FIND ENTRY

CHKSFL:	PUSHJ	P,.SAVE2		;GET TWO SCRATCH ACS
CHKS.0:	MOVE	P1,SFLCNT		;GET NUMBER OF ENTRIES
	CAMN	P1,SFLFRE		;ARE ANY ENTRIES USED
	$RETF				;NO..RETURN FALSE
	MOVN	P1,P1			;SETUP AOBJN POINTER
	HRLZS	P1			;MAKE AOBJN POINTER
	MOVE	P2,SFLADR		;GET THE ADDRESS
CHKS.1:	CAMN	S1,SFL.PD(P2)		;CHECK FOR PID
	$RETT				;RETURN TRUE
	ADDI	P2,SFL.SZ		;GET TO NEXT ENTRY
	AOBJN	P1,CHKS.1		;TRY NEXT ONE
	$RETF				;COULDN'T FIND
	SUBTTL	CLRSFL	--	CLEAR SEND FAILURE LIST

	;THIS ROUTINE WILL CLEAR TABLE SO WE CAN RECONSTRUCT IT

CLRSFL:	SKIPN	S1,SFLCNT		;ANY ENTRIES
	$STOP(SFI,Send Failure Table Inconsistent)
	MOVEM	S1,SFLFRE		;RESET FREE COUNT
	IMULI	S1,SFL.SZ			;COMPUTE SIZE
	MOVE	S2,SFLADR		;GET THE ADDRESS
	PJRST	.ZCHNK			;CLEAR AND RETURN
	SUBTTL	SNDQSR	--	ROUTINE TO SEND MESSAGE TO QUASAR

;THIS ROUTINE WILL SEND THE APPROPRIATE MESSAGE TO QUASAR


SNDQSR::
	MOVEI	S2,PAGSIZ		;SIZE OF THE MESSAGE
SNDQ.1:	MOVE	S1,G$SND		;GET THE SENDERS PID
	STORE	S1,.MSCOD(MO)		;SAVE IN MESSAGE
	MOVX	S1,SP.QSR+SI.FLG	;INDICATE TO QUASAR
	STORE	S1,SNDBLK+SAB.SI	;IN SAB
	SETZM	SNDBLK+SAB.PD		;CLEAR PID WORD
	PUSHJ	P,SNDM.1		;SEND THE MESSAGE
	JUMPT	.POPJ			;O.K...RETURN
	MOVEI	S1,[ASCIZ/QUASAR/]	;GET QUASARS NAME
	MOVEM	S1,G$ARG1		;SAVE STRING
	PJRST	TAKABT			;DO TAKE ABORT

	SUBTTL	SNDMSG	--	SEND A MESSAGE TO A PID

;ON ENTRY S1=PID TO SEND TO
;	S2 = LENGTH OF MESSAGE (1000 IMPLIES A PAGE MODE SEND)
;	MO=ADDRESS OF MESSAGE BLOCK

SNDMSG:	STORE	S1,SNDBLK+SAB.PD	;SAVE IN ARG BLOCK
	SETZM	SNDBLK+SAB.SI		;NOT TO SPECIAL PID
SNDM.1:	STORE	S2,SNDBLK+SAB.LN	;SAVE LENGTH IN SAB
	STORE	MO,SNDBLK+SAB.MS	;SAVE ADDRESS IN ARG BLOCK
IFN	FTDN60,<
	HLRZ	T1,SNDBLK+SAB.PD	;GET THE PID
	CAIN	T1,-1			;CHECK FOR -1
	JRST	SNDM.4			;DN60 ACK/WTO
>;END FTDN60
SNDM.2:	SETZM	PAGFLG			;CLEAR A FLAG
	MOVE	T1,SNDBLK+SAB.LN	;GET THE LENGTH
	CAIE	T1,PAGSIZ		;GET THE PAGE SIZE
	JRST	SNDM.3			;NO..SEND AS IS
	LOAD	T1,.MSTYP(MO),MS.CNT	;GET MESSAGE LENGTH
	CAMLE	T1,G$MAXP		;CAN WE SEND A PACKET
	JRST	SNDM.3			;NO..
	SETOM	PAGFLG			;SET THE FLAG
	MOVEM	T1,SNDBLK+SAB.LN	;RESET THE LENGTH
SNDM.3:	MOVX	S1,SAB.SZ		;GET LENGTH IN S1
	MOVEI	S2,SNDBLK		;AND ADDRESS IN S2
	PUSHJ	P,C%SEND		;SEND THE MESSAGE
	JUMPF	.POPJ			;ERROR..RETURN
	SKIPN	PAGFLG			;WAS IT A PAGE?
	$RETT				;NO..JUST RETURN
	PJRST	RELPAG			;RELEASE PAGE AND RETURN
;	PRESERVE S2 FOR THE MESSAGE LENGTH
IFN	FTDN60,<
SNDM.4:	MOVE	T1,G$OPRA		;GET THE OPR ADDRESS
	MOVX	S1,OP.D60		;GET D60 FLAG
	TDNN	S1,OPR.FL(T1)		;IS IT A DN60 MESSAGE?
	JRST	SNDM.2			;NO.. DO NORMAL IPCF SENDING
	MOVE	S1,OPR.ND(T1)		;GET NODE ADDRESS
	MOVE	S1,NOD.NM(S1)		;GET NODE NAME
;	MOVE	S1,OPR.PL(T1)		;GET THE PORT LINE WORD
	MOVEM	S1,G$SND		;SAVE AS RETURN CODE
	MOVEI	S1,.OMDSP		;MAKE SURE DISPLAY TYPE
	STORE	S1,.MSTYP(MO),MS.TYP	;SAVE THE TYPE
	JRST	SNDQ.1			;SEND IT TO QUASAR
>;END FTDN60
	SUBTTL	SPDOPR	--	SEND MESSAGE TO AN OPR

	;THIS ROUTINE WILL SEND MESSAGE TO AN OPR AND REQUEUE ON A 
	;FAILURE

SPDOPR:	SETZM	RSDCNT			;CLEAR RESEND COUNT
	PUSHJ	P,CHKSFL		;CHECK SEND FAILURES
	JUMPT	SPDO.0			;REQUEUE MESSAGE
	PUSHJ	P,SNDMSG		;SEND THE MESSAGE
	JUMPT	.POPJ			;O.K..JUST RETURN
	CAXN	S1,ERNSP$		;NO SUCH PID?
	JRST	SPDO.3			;YES..DELETE OPR AND RELEASE MESSAGE
	MOVE	S1,SNDBLK+SAB.PD	;GET THE PID
SPDO.0:	PUSHJ	P,ADDSFL		;ADD PID TO SEND FAILURE LIST
SPDO.1:	MOVX	S1,R.SOPR		;SETUP AS OPR RESEND
SPDO.2:	MOVE	S2,G$RSDL		;RESEND LIST
	AOS	G$RSDC			;BUMP THE RESEND COUNT
	PUSHJ	P,REQMSG		;REQUEUE THE MESSAGE
	PJRST	RELPAG			;RELEASE THE PAGE AND RETURN
SPDO.3:	MOVE	S1,SNDBLK+SAB.PD	;GET THE PID
	PUSHJ	P,VALOPR		;VALIDATE THE OPR
	SKIPT				;CONTINUE
	$STOP(ODI,OPR Database Inconsistent)
	MOVE	S1,SNDBLK+SAB.PD	;GET THE PID
	PUSHJ	P,DELOPR		;DELETE THE OPR
	PUSHJ	P,RELPAG		;RELEASE THE PAGE
	$RETF				;AND RETURN FALSE
	SUBTTL	SNDPID	--	SEND MESSAGE TO ANY PID( NOT OPR)

	;THIS ROUTINE WILL SEND MESSAGE TO ANY PID AND REQUEUE ON FAILURE

SNDPID:	SETZM	RSDCNT			;CLEAR RSDCNT
	PUSHJ	P,CHKSFL		;CHECK SEND FAILURE TABLE
	JUMPT	SNDP.1			;REQUEUE THE MESSAGE
	PUSHJ	P,SNDMSG		;SEND THE MESSAGE
	JUMPT	.POPJ			;O.K..RETURN TRUE
	CAXN	S1,ERNSP$		;NO SUCH PID
	$RETF				;RETURN FALSE..NO SUCH PID
	MOVE	S1,SNDBLK+SAB.PD	;GET THE PID
SNDP.1:	PUSHJ	P,ADDSFL		;ADD SEND FAILURE LIST
SNDP.2:	SETZ	S1,			;NO FLAGS
	PJRST	SPDO.2			;REQUEUE MESSAGE AND RETURN
SUBTTL	Interrupt Handler

INT:	$BGINT	IPCLEV
	PUSHJ	P,C%INTR		;SIGNAL THE INTERRUPT
	$DEBRK
	SUBTTL	Default PDBs for OPRCMD

IFN	FTDN60,<
	.REQUIRE	OPRCMD		;BRING IN OPRCMD

TXTLIN:: MOVEI S2,[ASCIZ/Multiple Line Text Not allowed for Remote Operators/]
	$RETF
WAITAC:: MOVEI	S2,[ASCIZ/Wait Command Not allowed for Remote Operators/]
	$RETF
TAKOPR::
ENTFDB::
WAIOPR::
EXTFDB::$CRLF(<$PREFILL(BADFDB)>)

SETTRM::
SETRTN::
PUSHRT::
BADFDB:	MOVEI	S2,[ASCIZ/Command Invalid for Remote Operators/]
	$RETF

CMDACT::	$RETT

>;END FTDN60
	SUBTTL	SETOUT	--	SETUP OUTPUT OF DATA

	;THIS ROUTINE WILL SETUP A DISPLAY MESSAGE FOR A DN60 OPERATOR

IFN	FTDN60,<
SETOUT:: PUSHJ	P,SETPTR		;SETUP THE POINTER
	MOVEM	S1,WTOPTR		;SAVE THE POINTER
	$TEXT	(,<^M^J^N/G$CNTL/::^A>)	;OPR HEADER LINE
	POPJ	P,			;RETURN

	SUBTTL	SNDOUT	--	OUTPUT ROUTINES FOR DN60

	;THIS ROUTINE WILL SEND DATA TO QUASAR FOR OUTPUT TO DN60

SNDOUT:: MOVX	S1,0			;GET A NULL
	IDPB	S1,WTOPTR		;END WITH A NULL
	HRRZ	S1,WTOPTR		;GET END ADDRESS
	ADDI	S1,1			;BUMP IT BY 1
	ANDI	S1,777			;GET MESSAGE LENGTH
	STORE	S1,.MSTYP(MO),MS.CNT	;SAVE THE COUNT
	SUBI	S1,.OHDRS		;GET THE BLOCK SIZE
	STORE	S1,.OHDRS+ARG.HD(MO),AR.LEN	;SAVE THE BLOCK LENGTH
	MOVX	S1,.CMTXT		;GET TEXT TYPE
	STORE	S1,.OHDRS+ARG.HD(MO),AR.TYP	;SAVE THE TYPE
	MOVE	S1,G$SND		;PID TO SEND TO
	MOVEI	S2,PAGSIZ		;GET PAGE SIZE
	PJRST	SNDPID			;SEND TO QUASAR VIA PID
	SUBTTL	OUTRTN	--	OUTPUT ROUTINE FOR LINKS

	;THIS IS THE TEXT DEFAULT OUTPUT ROUTINE AND WILL SETUP DATA FOR THE 
	;LINKS

OUTRTN:	SOSG	WTOCNT			;ROOM LEFT
	JRST	OUTR.1			;NO..SEND AND MAKE ROOM
	IDPB	S1,WTOPTR		;SAVE THE BYTE
	$RETT				;RETURN TRUE
OUTR.1:	PUSH	P,S1			;SAVE THE BYTE
	PUSHJ	P,SNDOUT		;SEND THE OUTPUT
	PUSHJ	P,SETPTR		;RESET THE POINTERS
	MOVEM	S1,WTOPTR		;SAVE THE POINTER
	POP	P,S1			;RESTORE THE VALUE
	JRST	OUTRTN			;SAVE THE CHARACTER NOW
	SUBTTL	SETPTR	--	SETUP POINTERS FOR OUTPUT

	;THIS ROUTINE WILL SETUP THE POINTERS AND RETURN WITH S1 CONTAINING
	;THE NEW BYTE POINTER

SETPTR:	PUSHJ	P,GETPAG		;GET A PAGE
	MOVX	S1,.OMDSP		;GET MESSAGE TYPE
	STORE	S1,.MSTYP(MO),MS.TYP	;SAVE THE MESSAGE TYPE
	MOVEI	S1,<PAGSIZ-<.OHDRS+ARG.DA+1>>*5 ;GET ROOM FOR DATA
	MOVEM	S1,WTOCNT		;SAVE THE COUNT
	MOVE	S1,G$OPRA		;GET OPR ADDRESS
	MOVE	S1,OPR.ND(S1)		;GET THE PORT LINE DATA
	MOVE	S1,NOD.NM(S1)		;GET THE NODE NAME
	MOVEM	S1,.MSCOD(MO)		;SAVE THE CODE IN THE MESSAGE
	MOVSI	S1,(POINT 7,)		;SETUP THE BYTE POINTER
	HRRI	S1,.OHDRS+ARG.DA(MO)	;GET BUFFER ADDRESS
	POPJ	P,			;RETURN S1 BYTE POINTER

SHWDAY:: PUSHJ	P,SETOUT		;SETUP THE OUTPUT
	$TEXT	(,<^H/[-1]/>)
	PUSHJ	P,SNDOUT		;SEND THE OUTPUT
	PJRST	P$NPRO##		;NO PROCESSING REQUIRED

>;END FTDN60
	END	ORION