Google
 

Trailing-Edge - PDP-10 Archives - BB-4170H-SM - sources/mexec.mac
There are 53 other files named mexec.mac in the archive. Click here to see a list.
; UPD ID= 234, SNARK:<4.MONITOR>MEXEC.MAC.441,  31-Jan-80 13:15:08 by ENGEL
;DON'T CALL RQTAD1 IF A KS
;<4.MONITOR>MEXEC.MAC.440,  3-Jan-80 08:09:33, EDIT BY R.ACE
;UPDATE COPYRIGHT DATE
; UPD ID= 105, SNARK:<4.MONITOR>MEXEC.MAC.439,   7-Dec-79 09:09:10 by R.ACE
;TCO 4.2591 - SECTION-0 PAGE TABLE SHARE COUNT PROBLEM FROM SSAVE
;ADD ERJMP AFTER SOUT IN LITERAL AFTER SSAVB4
;<4.MONITOR>MEXEC.MAC.438, 15-Oct-79 14:07:08, EDIT BY MILLER
;REMOVE CKDFRK BUGHLT. IF CFORK FAILS, RETURN +1
;<4.MONITOR>MEXEC.MAC.437, 12-Oct-79 14:14:29, Edit by KONEN
;CORRECT CHKAC JSYS IN DEALING WITH STRUCTURES
;<4.MONITOR>MEXEC.MAC.436, 26-Sep-79 16:46:01, EDIT BY HALL
;PEEK JSYS - CALL BLTMU1 INSTEAD OF BLTMU FOR EXTENDED ADDRESSING
;<4.MONITOR>MEXEC.MAC.435, 12-Sep-79 16:09:36, EDIT BY HALL
;STCRJB - ENTER SECTION 1 IN ORDER TO CALL BLTMU
;<4.MONITOR>MEXEC.MAC.434, 10-Sep-79 16:56:18, EDIT BY HALL
;TCO 4.2452 - IN STCRJB SET UP T2 CORRECTLY FOR CALL TO BLTMU
;<OSMAN.MON>MEXEC.MAC.1, 10-Sep-79 15:44:06, EDIT BY OSMAN
;TCO 4.2412 - Move definition of BUGHLTs, BUGCHKs, and BUGINFs to BUGS.MAC
;<4.MONITOR>MEXEC.MAC.432,  5-Sep-79 14:30:26, EDIT BY ZIMA
;More 4.2406 - clean it up a bit
;<4.MONITOR>MEXEC.MAC.431, 22-Aug-79 06:44:05, EDIT BY R.ACE
;TCO 4.2414 - ADD SE1ENT AT LOGO TO PREVENT ILLUUO'S
;<4.MONITOR>MEXEC.MAC.430, 17-Aug-79 12:58:12, EDIT BY HALL
;LDET2 - FIX TYPO IN TOMCZAK'S EDIT
;<4.MONITOR>MEXEC.MAC.429, 16-Aug-79 16:15:38, EDIT BY TOMCZAK
;TCO#4.2406 - code added in job startup, logout, and two detaching
;routines to insure that CTY always defaults to refusing links
;<4.MONITOR>MEXEC.MAC.428, 16-Aug-79 14:23:24, EDIT BY OSMAN
;CHANGE DIRBAD TO DRBAD TO NOT CONFLICT WITH DIRBAD BUGCHK IN DIRECT
;<4.MONITOR>MEXEC.MAC.427, 14-Aug-79 10:37:46, EDIT BY DBELL
;TCO 4.2395 - HANDLE ERRORS DURING SAVE JSYS WHICH CAN HANG UP A JOB
;<4.MONITOR>MEXEC.MAC.426, 11-Aug-79 08:33:57, EDIT BY HALL
;IN JOB INITIALIZATION, INITIALIZE FLKCNT AND FLKOWN
;<4.MONITOR>MEXEC.MAC.425, 30-Jul-79 09:29:36, EDIT BY MILLER
;SET JOB 0 PRIORITY WORD TO MFRKWD
;<4.MONITOR>MEXEC.MAC.424, 28-Jul-79 16:31:24, EDIT BY ZIMA
;TCO 4.2357 - Fix CRJOB security bug by connecting created job to
; creator's login directory around STCRJB+13
;<4.MONITOR>MEXEC.MAC.423, 24-Jul-79 10:10:09, EDIT BY DBELL
;MORE TCO 4.2230 - WHEN GET A JOB 0 CRASH, TYPE OUT NEW PC TO GO TO
;<4.MONITOR>MEXEC.MAC.422,  2-Jul-79 13:43:37, EDIT BY R.ACE
;FIX SPELLING OF "CANCELED"
;<4.MONITOR>MEXEC.MAC.421, 27-Jun-79 13:07:10, Edit by KONEN
;STORE ASCII TIME AND DATE FOR TYPEOUT AT BUGHLT
;<4.MONITOR>MEXEC.MAC.420, 25-Jun-79 18:38:17, Edit by LCAMPBELL
; Yet ANOTHER ancient bug at ELOGO which would cause a job to be
; unlogoutable by anyone after a user without privs tried to log it out
;<4.MONITOR>MEXEC.MAC.419, 19-Jun-79 16:36:01, Edit by LCAMPBELL
; TCO 4.2298 - Fix race at ELOGO which caused GLREM2s
;<4.MONITOR>MEXEC.MAC.418, 18-Jun-79 12:40:22, EDIT BY DBELL
;TCO 4.2291 - MAKE "SHUTDOWN COMPLETE" TYPE BY USING RIGHT TERMINAL DESIGNATOR
;<4.MONITOR>MEXEC.MAC.417, 10-Jun-79 14:57:00, EDIT BY MILLER
;DON'T CALL RUNMO1 IF A 2020
;<4.MONITOR>MEXEC.MAC.416, 30-Apr-79 12:55:43, Edit by MCLEAN
;<4.MONITOR>MEXEC.MAC.415, 25-Apr-79 15:16:58, EDIT BY OSMAN
;MOVE OURNAM INITIALIZATION TO STG
;<4.MONITOR>MEXEC.MAC.414, 25-Apr-79 00:04:16, Edit by MCLEAN
;<4.MONITOR>MEXEC.MAC.413, 25-Apr-79 00:01:32, Edit by MCLEAN
;CHANGE FROM GETOK ON LOGOUT OVER QUOTA TO LOGOUT
;<4.MONITOR>MEXEC.MAC.412, 17-Apr-79 17:25:54, EDIT BY ZIMA
;TCO 4.2233 - Pass proper flags to CHKBAT in T3 in call at EXEC0+15
;<4.MONITOR>MEXEC.MAC.411, 13-Apr-79 11:10:28, EDIT BY BOSACK
;FIX TYPO IN IMUMAP
;<4.MONITOR>MEXEC.MAC.410, 12-Apr-79 14:51:47, EDIT BY HALL
;TCO 4.2230 - SYSTEM STARTUP ERROR HANDLING -- ADD JB0INT, ETC.
;<4.MONITOR>MEXEC.MAC.409,  9-Apr-79 11:25:31, EDIT BY MILLER
;FIX CODE AT GSMDSK AND GSMD2 TO COMPUTE AVAILABLE MEMORY PROPERLY
;<4.MONITOR>MEXEC.MAC.408,  9-Apr-79 08:49:06, EDIT BY HALL
;<4.MONITOR>MEXEC.MAC.407,  5-Apr-79 14:35:47, EDIT BY HALL
;<4.MONITOR>MEXEC.MAC.406,  5-Apr-79 14:34:49, EDIT BY HALL
;<4.MONITOR>MEXEC.MAC.405,  5-Apr-79 14:21:55, EDIT BY HALL
;<4.MONITOR>MEXEC.MAC.404,  5-Apr-79 13:19:59, EDIT BY HALL
;<4.MONITOR>MEXEC.MAC.403,  5-Apr-79 12:52:54, Edit by MCLEAN
;<4.MONITOR>MEXEC.MAC.402,  5-Apr-79 12:46:56, EDIT BY HALL
;<4.MONITOR>MEXEC.MAC.401,  5-Apr-79 12:06:35, EDIT BY HALL
;BEGINNING CLEANUP OF SYSTEM STARTUP ERROR HANDLING
;<4.MONITOR>MEXEC.MAC.400,  5-Apr-79 11:08:22, Edit by MCLEAN
;REMOVE 1 ARG FROM GTOKM
;<4.MONITOR>MEXEC.MAC.399,  3-Apr-79 14:12:16, EDIT BY MILLER
;FIX USGINI TO HANDLE MANGLED CHECKPOINT FILE.
;<4.MONITOR>MEXEC.MAC.398,  2-Apr-79 21:30:32, EDIT BY ZIMA
;Add missing AC in JUMPL at LOG1+14
;<4.MONITOR>MEXEC.MAC.397, 10-Mar-79 13:30:54, EDIT BY MILLER
;FIX FAST GET CODE.
;<4.MONITOR>MEXEC.MAC.396,  7-Mar-79 18:29:12, EDIT BY MILLER
;<4.MONITOR>MEXEC.MAC.395,  7-Mar-79 17:20:37, EDIT BY MILLER
;<4.MONITOR>MEXEC.MAC.394,  7-Mar-79 16:57:50, EDIT BY MILLER
;<4.MONITOR>MEXEC.MAC.393,  7-Mar-79 14:43:00, EDIT BY MILLER
;MORE IMPROVEMENTS TO FAST GET. USE MSETPT WHENEVER POSSIBLE
;<4.MONITOR>MEXEC.MAC.392,  7-Mar-79 12:20:20, Edit by MCLEAN
;FIX IT SO FLOGO RUNS IN SECTION 1
;<4.MONITOR>MEXEC.MAC.391,  6-Mar-79 14:12:26, EDIT BY MILLER
;FIX FAST GET TO CREATE SHARE POINTERS INSTEAD OF INDIRECT POINTERS
;<4.MONITOR>MEXEC.MAC.390,  4-Mar-79 18:27:47, EDIT BY KONEN
;UPDATE COPYRIGHT FOR RELEASE 4
;<4.MONITOR>MEXEC.MAC.389,  2-Mar-79 15:28:04, Edit by MCLEAN
;FIX GTOKM MACROS FOR ERROR RETURNS
;<4.MONITOR>MEXEC.MAC.388, 26-Feb-79 16:47:02, EDIT BY HALL
;TCO 1967 - MAKE TSTFST CSKED WHILE FAST-GET TABLE IS LOCKED
;<4.MONITOR>MEXEC.MAC.387, 20-Feb-79 10:17:02, Edit by KONEN
;FIX ILMADR BUGHLT FROM CHECKPOINTING TOO LARGE A JOB NUMBER
;<4.MONITOR>MEXEC.MAC.386, 17-Feb-79 13:35:32, EDIT BY DBELL
;MAKE IMALC STORE PAGE NUMBER IN SYMPAG INSTEAD OF USING JSB STACK
;<4.MONITOR>MEXEC.MAC.385,  7-Feb-79 10:21:14, EDIT BY OSMAN
;SET UP OURNAM AND OURCNT HERE, SO NON-DECNET SYSTEMS ARE CONSISTENT
;<4.MONITOR>MEXEC.MAC.384,  4-Feb-79 22:33:30, EDIT BY GILBERT
;Start EDDT in section MSEC1 on EDDT$G to MDDT.
;<4.MONITOR>MEXEC.MAC.383, 29-Jan-79 03:56:20, EDIT BY DBELL
;CHANGE HSYPAG TO HSYBLK
;<4.MONITOR>MEXEC.MAC.382, 26-Jan-79 00:23:00, EDIT BY ZIMA
;TCO 4.2170 - Prevent UXXCKP BUGHLTS on restart when CHECKPOINT.BIN.1
; has been deleted and not expunged.
;<4.MONITOR>MEXEC.MAC.381, 18-Jan-79 19:21:50, EDIT BY MILLER
;CHANGE UNPAGE TO ONLY TURN OFF PAUSE ON END
;<4.MONITOR>MEXEC.MAC.380, 15-Jan-79 07:42:57, EDIT BY GILBERT
;More TCO 4.2155:
;	Fix various bugs in .IMOPR and boot code.
;<4.MONITOR>MEXEC.MAC.379, 14-Jan-79 15:02:29, Edit by MCLEAN
;REMOVE TTMVSP CALL
;<4.MONITOR>MEXEC.MAC.378,  8-Jan-79 06:51:34, EDIT BY GILBERT
;TCO 4.2155 - Implement hidden symbol tables:
;	Make boot process (GETSWM) understand hidden symbol tables.
;	Add .IMOPR subroutine for MDDT and SNOOP% to map symbols.
;<4.MONITOR>MEXEC.MAC.377,  5-Jan-79 13:10:55, Edit by MCLEAN
;MAKE LOGOUT HAVE GETOK FOR OVER QUOTA
;<4.MONITOR>MEXEC.MAC.375,  3-Jan-79 20:10:42, EDIT BY GILBERT
;ADD A DUMMY DEFINITION OF .IMOPR FOR DDT VERSION 41
;<4.MONITOR>MEXEC.MAC.374, 20-Dec-78 09:51:57, EDIT BY OSMAN
;<4.MONITOR>MEXEC.MAC.373, 19-Dec-78 15:47:02, EDIT BY MURPHY
;ADD BLOCK PRIORITY TO SCHED CALLS
;SET JOB'S NODE NAME TO SYSTEM'S AT INITIALIZATION
;<4.MONITOR>MEXEC.MAC.372, 11-Dec-78 19:13:10, Edit by MCLEAN
;FIX TODDT TO BE IN SEC 1
;<4.MONITOR>MEXEC.MAC.371, 28-Nov-78 10:52:35, EDIT BY MILLER
;<4.MONITOR>MEXEC.MAC.370, 26-Nov-78 19:04:31, EDIT BY MILLER
;DO OKSKED IF CALL STADYN IN ATACH FAILS
;<4.MONITOR>MEXEC.MAC.369, 23-Nov-78 15:53:41, EDIT BY JBORCHEK
;<4.MONITOR>MEXEC.MAC.368, 22-Nov-78 14:38:35, EDIT BY JBORCHEK
;DELETE LHOSTN SIMULATION BACK TO A TABLE STARTING AT NOHOST
;<4.MONITOR>MEXEC.MAC.367, 16-Nov-78 12:38:26, EDIT BY MILLER
;<4.MONITOR>MEXEC.MAC.366, 16-Nov-78 12:31:36, EDIT BY MILLER
;FIX FSTGET TO USE VECSET INSTEAD OF SEVEC
;<4.MONITOR>MEXEC.MAC.364, 10-Nov-78 10:54:33, EDIT BY OSMAN
;CHANGE CPYTUS TO CPYTU1 FOR SESSION REMARK, LOGICAL LOCATION, AND SKIP RETURN SO POINTER ISN'T UPDATED TWICE
;<4.MONITOR>MEXEC.MAC.363,  9-Nov-78 13:25:14, EDIT BY OSMAN
;TCO 4.2083 - CHANGE .WAIT TO WAIT1
;tco 4.2083 - change HALTF to WAIT in LGOUT code
;<4.MONITOR>MEXEC.MAC.360, 31-Oct-78 17:21:58, EDIT BY JBORCHEK
;MAKE LHOSTN 3 WORDS LONG
;<4.MONITOR>MEXEC.MAC.359, 24-Oct-78 16:27:19, EDIT BY OSMAN
;TCO 4.2060 - ADD .JILLO
;<4.MONITOR>MEXEC.MAC.358, 23-Oct-78 21:15:20, Edit by MCLEAN
;TCO 4.2063 ADD BATSTF FOR BATCH FLAGS
;<4.MONITOR>MEXEC.MAC.356, 23-Oct-78 16:29:54, EDIT BY ENGEL
;MAKE "FULL" "?FULL"
;<4.MONITOR>MEXEC.MAC.355, 19-Oct-78 23:26:10, Edit by MCLEAN
;ADD LOGOMS CALL FOR OPR
;SNARK:<4.MONITOR>MEXEC.MAC.354, 17-Oct-78 14:28:28, Edit by MCLEAN
;FIX LOG2 TO HAVE PID ADDRESS IN T1
;<4.MONITOR>MEXEC.MAC.353,  1-Oct-78 22:19:53, EDIT BY DBELL
;TCO 4.2027 - ADD .JISTM ENTRY TO GETJI
;<4.MONITOR>MEXEC.MAC.352, 28-Sep-78 13:55:21, Edit by LCAMPBELL
; Fix NSKDIS when detaching NVT (ARPA)
;<4.MONITOR>MEXEC.MAC.351, 26-Sep-78 14:29:59, Edit by LCAMPBELL
; Cause GTRPI to return milliseconds again
;<4.MONITOR>MEXEC.MAC.350,  8-Sep-78 09:25:18, EDIT BY ENGEL
;SAVE T3 ACROSS CALL TO GTSVIF AT GTSVI:
;<4.MONITOR>MEXEC.MAC.349,  1-Sep-78 15:20:12, EDIT BY JBORCHEK
;REMOVE SYMBOLS IMPLBT AND NOHOST
;<4.MONITOR>MEXEC.MAC.348, 28-Aug-78 19:23:29, Edit by LCAMPBELL
; Simulate IMPHRT and HSTSTS GETABs so old utilities still work.
;<4.MONITOR>MEXEC.MAC.347, 25-Aug-78 13:35:55, Edit by MCLEAN
;REMOVE CALL TO PLRSTS
;<4.MONITOR>MEXEC.MAC.346, 25-Aug-78 09:38:17, EDIT BY ENGEL
;GET RID OF OPEN FLAGS FOR THE FFFFP AT USDIN1:
;<4.MONITOR>MEXEC.MAC.345, 23-Aug-78 11:48:58, EDIT BY R.ACE
;TCO 4.1992 - CHANGE MTASSP TO CALL RUNDII INSTEAD OF RUNDIR
;<4.MONITOR>MEXEC.MAC.344, 17-Aug-78 13:38:45, Edit by LCAMPBELL
;<4.MONITOR>MEXEC.MAC.343, 17-Aug-78 12:30:49, EDIT BY LCAMPBELL
;FIX RACE IN CRJOB WHICH CAUSES WRONG AC'S TO BE PASSED OCCASIONALLY
; (MISSING MEXEC.MAC.342 HEADER LINE OMITTED BY cower)
;<4.MONITOR>MEXEC.MAC.341, 16-Aug-78 14:47:05, EDIT BY COWER
;changed getji to check that word wanted (ac3) not negative
;<4.MONITOR>MEXEC.MAC.340, 16-Aug-78 01:45:29, Edit by MCLEAN
;REMOVE SE0ENT/SE1ENT FROM TODDT
;<4.MONITOR>MEXEC.MAC.339, 16-Aug-78 01:22:46, Edit by MCLEAN
;ADD GETOK FOR ENTRY TO MDDT
;<4.MONITOR>MEXEC.MAC.338,  4-Aug-78 12:01:11, EDIT BY MILLER
;MUST BE NOSKED WHEN CALLING ASSPTL
;<4.MONITOR>MEXEC.MAC.337,  4-Aug-78 08:45:35, EDIT BY MILLER
;FIX SOME TYPEOS
;<4.MONITOR>MEXEC.MAC.336,  4-Aug-78 08:00:57, EDIT BY MILLER
;FIX FSTMAP ROUTINE.
;<4.MONITOR>MEXEC.MAC.335,  3-Aug-78 19:16:34, EDIT BY MILLER
;FIX MORE TYPEOS
;<4.MONITOR>MEXEC.MAC.334,  3-Aug-78 12:07:55, EDIT BY MILLER
;FIX TYPEOS
;<4.MONITOR>MEXEC.MAC.333,  3-Aug-78 11:14:59, EDIT BY MILLER
;TCO 1967. ADD FAST-GET CODE
;<4.MONITOR>MEXEC.MAC.332, 28-Jul-78 15:20:11, Edit by ENGEL
;ELIMINATE NOSKED AT LCTAC2+7 - FIX ARPA NSKDIS PROBLEM
;<4.MONITOR>MEXEC.MAC.331, 27-Jul-78 13:18:35, Edit by PORCHER
;FIX ILL WRITE TO CHECKPOINT FILE AT USGIN7...
;<4.MONITOR>MEXEC.MAC.330, 20-Jul-78 09:51:55, Edit by ENGEL
;FIX PROBLEM CREATED BY BORCHECK AT STCJB1 - CHANGE HRRZM TO MOVEM AND
; CHANGE THE CAMN TO USE A REGISTER
;<4.MONITOR>MEXEC.MAC.329, 14-Jul-78 12:50:26, EDIT BY MILLER
;CHANGE TODDT TO ENTER MDDT IN SECTION "MSEC1"
;TCO # 1902 - MAKE JOB 0 UPDATE FULL PAGES IN CHECKPOINT FILE
;<4.MONITOR>MEXEC.MAC.327,  6-Jul-78 01:28:45, Edit by JBORCHEK
;MUST SIMULATE SOME OF THE ARPA TABLES NOW
;<4.MONITOR>MEXEC.MAC.325, 28-Jun-78 11:10:22, EDIT BY OSMAN
;ADD .JIT20/.SJT20 - TCO # 1927
;<4.MONITOR>MEXEC.MAC.324, 26-Jun-78 02:23:37, Edit by JBORCHEK
;FIX HSTSTS TABLE SIZE
;<4.MONITOR>MEXEC.MAC.323, 23-Jun-78 15:44:36, EDIT BY OSMAN
;FREEZE FORKS ON "^P" ONLY.  (USED TO FREEZE ON "^EQUIT" TOO)
;TCO 1926
;<4.MONITOR>MEXEC.MAC.322, 21-Jun-78 00:34:01, Edit by MCLEAN
;ADD GOKLCK
;<4.MONITOR>MEXEC.MAC.321, 20-Jun-78 15:05:48, Edit by ENGEL
;ELIMINATE THE JSBSTF CALL AT JOBCF1
;<4.MONITOR>MEXEC.MAC.320, 14-Jun-78 06:01:38, Edit by JBORCHEK
;DELETE ERROR MSG DUE TO BUGTP=0
;<4.MONITOR>MEXEC.MAC.319, 13-Jun-78 13:31:59, EDIT BY MILLER
;SHUFFLE CODE AROUND GSMLER TO MAP MMAP INTO BOOT SPACE BEFORE LOCKING
;<4.MONITOR>MEXEC.MAC.318,  3-Jun-78 17:02:25, Edit by GILBERT
;Suppress SSAVE flags to DDT typeout
;<4-NEW>MEXEC.MAC.317,  1-Jun-78 17:17:15, Edit by FORTMILLER
;START BOOT AT LAST INSTRUCTION ON LAST PAGE
;<4.MONITOR>MEXEC.MAC.316, 31-May-78 13:45:43, Edit by KIRSCHEN
;MAKE RESTART SYSERR ENTRY EVEN IF NO OPERATOR ENTRY OF DATE AND TIME
;<4.MONITOR>MEXEC.MAC.315, 18-May-78 14:32:55, Edit by KIRSCHEN
;<3A.MONITOR>MEXEC.MAC.21, 16-May-78 13:07:48, EDIT BY MILLER
;TCO 1887. ADD NSWPGS GETAB ENTRY
;<4.MONITOR>MEXEC.MAC.313, 13-May-78 13:14:00, Edit by HALL
;TCO 1900 - CALL ATSINI AT RUNDD7
;<4.MONITOR>MEXEC.MAC.312, 20-Apr-78 14:41:02, EDIT BY MILLER
;MAKE SURE T3 HAS DIR NUMBER IN IT AT ATACH6
;<4.MONITOR>MEXEC.MAC.311,  9-Apr-78 01:59:06, Edit by BORCHEK
;CRJOB FIXES AT STCJB1
;<4.MONITOR>MEXEC.MAC.310,  3-Mar-78 09:56:48, EDIT BY MILLER
;DETERMINE LOW MESSAGE BY COMPARING AGAINST SYWRND
;<4.MONITOR>MEXEC.MAC.309,  1-Mar-78 13:46:08, Edit by PORCHER
;<4.MONITOR>MEXEC.MAC.308,  1-Mar-78 12:04:36, Edit by PORCHER
;Move accounting shift change initialization to before SETSPD
;<4.MONITOR>MEXEC.MAC.307, 28-Feb-78 17:29:08, Edit by PORCHER
;<4.MONITOR>MEXEC.MAC.306, 28-Feb-78 13:14:17, Edit by PORCHER
;<4.MONITOR>MEXEC.MAC.305, 28-Feb-78 11:32:10, Edit by PORCHER
;Bug fixes for accounting shift changes . . .
;<4.MONITOR>MEXEC.MAC.303, 20-Feb-78 12:24:56, Edit by PORCHER
;<4.MONITOR>MEXEC.MAC.302, 20-Feb-78 11:20:53, Edit by PORCHER
;Add stuff for accounting shift changes
;<4.MONITOR>MEXEC.MAC.301, 16-Feb-78 09:21:29, Edit by PORCHER
;Add stuff for session runtime and console time
;<4.MONITOR>MEXEC.MAC.300, 31-Jan-78 00:34:24, Edit by MCLEAN
;ADD MTA ON LINE REQUEST OF SETSPD
;<4.MONITOR>MEXEC.MAC.299, 28-Jan-78 23:15:18, Edit by PORCHER
;Make GETs of PA1050 and RMS come from SYS: if execute-only
;<4.MONITOR>MEXEC.MAC.298, 28-Jan-78 18:23:39, Edit by PORCHER
;<4.MONITOR>MEXEC.MAC.297, 28-Jan-78 17:37:53, Edit by PORCHER
;<4.MONITOR>MEXEC.MAC.296, 28-Jan-78 17:29:08, Edit by PORCHER
;Add execute-only GET code
;<4.MONITOR>MEXEC.MAC.295, 25-Jan-78 13:30:58, EDIT BY MILLER
;FIX TYPEO IN SYSJOB CHANGE
;<3A.MONITOR>MEXEC.MAC.15, 25-Jan-78 13:26:13, EDIT BY MILLER
;USE NEW RUNDIR ROUTINE TO RUN SYSJOB
;<3A.MONITOR>MEXEC.MAC.14, 25-Jan-78 12:48:19, EDIT BY MILLER
;RUN MOS DIAG IN JOB 0 AND AT SYSTEM STARTUP
;<4.MONITOR>MEXEC.MAC.292,  3-Jan-78 16:14:50, EDIT BY MILLER
;<4.MONITOR>MEXEC.MAC.291,  3-Jan-78 16:13:44, EDIT BY MILLER
;FIX MAPPING OF EPT FOR BOOT TO USE SETMPG
;<3-MONITOR>MEXEC.MAC.287, 13-Dec-77 16:23:59, Edit by HESS
;TCO 1889 - FIX TO SESSION END LOGGING
;<4.MONITOR>MEXEC.MAC.289,  6-Dec-77 20:53:30, EDIT BY MCCLURE
;CALL DUPINI
;<3.SM10-RELEASE-3>MEXEC.MAC.9,  5-Dec-77 12:59:52, EDIT BY MILLER
;DON'T RECORD "ALLOCATED BUT ZERO" PAGES
;<4.MONITOR>MEXEC.MAC.287,  5-Dec-77 12:23:04, EDIT BY MILLER
;MOVE RQTAD1 SET UP TO DTESRV
;<3.SM10-RELEASE-3>MEXEC.MAC.7,  5-Dec-77 10:33:20, EDIT BY MILLER
;DON'T SAVE ALL ZERO PAGES.
;<3-MONITOR>MEXEC.MAC.286, 17-Nov-77 16:01:05, EDIT BY KIRSCHEN
;FIX TYPO ON PREVIOUS EDIT
;<4.MONITOR>MEXEC.MAC.284, 10-Nov-77 23:53:27, EDIT BY BOSACK
;UPDATE DDTPRS IN ULKINI
;<4.MONITOR>MEXEC.MAC.283,  6-Nov-77 16:11:32, Edit by MCLEAN
;ADD CODE FOR RELOAD ON KS
;<4.MONITOR>MEXEC.MAC.282, 26-Oct-77 17:34:31, EDIT BY CROSSLAND
;FIX SO THAT SYSTEM GOING DOWN IN 2 HOURS MESSAGES OCCURS ONLY ONCE
;INCREASE OVERHEAD PAGES DURING BOOT PHASE TO ALLOW MONMIN TO WORK
;<4.MONITOR>MEXEC.MAC.281, 23-Oct-77 20:15:56, EDIT BY CROSSLAND
;MAKE HALT MESSAGE ONLY COME OUT 2 HOURS BEFORE HALT
;<4.MONITOR>MEXEC.MAC.280, 20-Oct-77 13:11:47, EDIT BY HURLEY
;FIX ATTACH AC CLOBBERAGE
;<4.MONITOR>MEXEC.MAC.279,  5-Oct-77 13:08:35, Edit by HESS
;JOB 0 - SEND MESSAGE TO PULSAR WHEN MTA STATUS CHANGE FLAG SET

;COPYRIGHT (C) 1976,1977,1978,1979,1980 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.

	SEARCH PROLOG,SERCOD,ACTSYM
	TTITLE MEXEC

;SWAPPABLE MONITOR ROUTINES, JSYS'S, ETC. - D. MURPHY


;AC DEFINITIONS USED HEREIN

DEFAC (FX,Q3)			;FORK INDEX

WRMSGF::-1			;SEND WARNING MESSAGES TO USERS IF NON-0
LOGDES::LOGTTY			;DESIGNATOR FOR LOG MSGS - DEF IN PARAMS
JB0TT::BLOCK	1		;DESIG FOR JOB 0 AND ERR MSGS (STORED IN TTINIT)
MICHN==:1B34+1B35		;CHANNELS THAT MONITOR ENABLES

	SWAPCD

;LINKAGE TO MDDT

MDDT=:<MSEC1,,MDDTX>		;TRY TO START IN SECTION 1

;REGULAR SUBSYSTEM NAMES FOR INCLUSION IN SNAMES TABLE AT STARTUP

SBSNMS:	SIXBIT /EXEC/
	SIXBIT /(PRIV)/
NSBSNM==.-SBSNMS

;TABLE DEFINES SPECIAL PURPOSE FOR FIRST FEW JOBS

SPECJT:	XWD 0,RUNDD		;JOB 0 IS ALWAYS DISK CHECKER, ETC.

NSPECJ==.-SPECJT		;NUMBER OF SPECIAL JOBS

	RESCD
;CODE TO INITIALIZE JOB ON FIRST STARTUP.  ALSO INVOKES SYSTEM
;INITIALIZATION IF FIRST JOB AFTER SYSTEM STARTED FROM SCRATCH
;SYSIFG IS 0 WHEN SYSTEM IS JUST STARTING

EXEC0::	MOVX 1,LOGIOB		;SAY JOB CREATION IN PROGRESS
	IORM 1,JOBBIT
	SETZM FPC
	MOVSI 1,(UMODF)		;SIMULATE CALL FROM USER
	MOVEM 1,FFL
	MCENTR
	SKIPE SYSIFG		;NEW SYSTEM?
	JRST GOTSWM		;NO
	MOVEI T1,MFRKWD		;GET SPECIAL PRIORITY FOR MONITOR FORKS
	MOVEM T1,JOBSKD		;AND SET THIS JOB AS SUCH
	CALL SEBINI		;INIT SYSERR FACILITY
	CALL FSIINI		;GO MOUNT THE PUBLIC STRUCTURE
	CALL SWPINI		;SWAPPER CAN NOW BE INITIALIZED
				;IT MUST BE CALLED AFTER NSSUN AND
				;  THE SDB FOR PS ARE SET UP BY FSIINI
	MOVEI T1,PSNUM		;T1/ STRUCTURE NUMBER (PUBLIC STRUCTURE)
	MOVEI T2,HOMPGA		;T2/ ADDRESS OF PAGE TO USE FOR BAT BLOCKS
	MOVX T3,MI%MSG		;T3/ FLAGS TO TELL OPERATOR, FIX INCONSISTENT
	CALL CHKBAT		;AND NOW THE BAT BLOCKS CAN BE CHECKED
				; AND THE OVERFLOW SWAPPING ADDRESSES
				; IN THE BAT BLOCKS PROCESSED
REPEAT 1,<			;TEMPORARY UNTIL REV 10 IS IN
	PUSH P,CASHF		;TURN OFF THE CACHE
	CALL CASHOF		;THIS REDUCES PROBLEMS CAUSED BY MAP INST
>
	CALL GETSWM		;GET SWAPPABLE MONITOR
REPEAT 1,<			;TEMPORARY UNTIL REV 10 IS IN
	POP P,CASHF		;RESTORE CACHE 
	SKIPE CASHF		;WAS CASH ON BEFORE?
	CALL CASHON		;YES, TURN IT BACK ON
>
	CALL RESLCK		;LOCK DOWN SOME RESIDENT FREE SPACE

;AT THIS POINT THE SWAPPABLE MONITOR HAS BEEN LOADED. IF IT IS DESIRABLE
;  TO PATCH THE SWAPPABLE MONITOR A BREAKPOINT CAN BE PUT HERE.  NO
;  PART OF THE SWAPPABLE MONITOR WILL HAVE BEEN EXECUTED YET.

;INITIALIZE THE FORK STRUCTURE FOR THIS JOB. ASSIGN FIRST WORD OF FKPTRS
;AND SYSFK TO THIS FORK. MAKE EACH REMAINING WORD OF FKPTRS POINT TO NEXT
;AVAILABLE SLOT AND FREJFK POINT TO THE FIRST AVAILABLE SLOT
;INITIALIZE REMAINING WORDS OF SYSFK TO -1

GOTSWM:	MOVEI 1,FKPTRS		;1/NAME OF FORK STRUCTURE LIST
	MOVEI 2,NUFKS		;2/NUMBER OF WORDS IN LIST
	CALL ILIST		;INITIALIZE FREE WORDS IN FKPTRS
	MOVE 1,0(1)		;POINT TO SECOND FREE SLOT
	MOVEM 1,FREJFK		;MAKE FREE LIST START WITH SECOND SLOT
	SETZM FKPTRS		;TAKE FIRST SLOT FO THIS FORK
	MOVE 1,FORKX		;GET SYSTEM-WIDE INDEX FOR THIS FORK
	HRRZM 1,SYSFK		;STORE IN JOB STORAGE AREA
				;Note that this clears all the flag bits
				; (defined in FORK) in LH of SYSFK
	MOVE 1,[XWD SYSFK+1,SYSFK+2]
	SETOM -1(1)		;INIT REMAINDER OF SYSFK TABLE
	BLT 1,SYSFK+NUFKS-1
	MOVE T1,[JTBIFR]	; Initialize JTB free bit table
	MOVEM T1,JTBFRE		;  ..
	SETOM FKLOCK		;INIT FORK LOCK FOR THIS JOB
	SETZM FLKCNT		;CLEAR NEST COUNT
	SETOM FLKOWN		;CLEAR OWNING FORK

;SET UP FOR INTERRUPTS TO BE PROCESSED BY THE MONITOR
;IF AN INTERRUPT OCCURS ON A CHANNEL WHOSE BIT IS SET IN MONCHN,
;THE MONITOR WILL GO TO EXECI
;CHANNELS 34 AND 35 ARE ACTIVATED HERE, AND CTRL/P IS ASSIGNED
;TO THEM IN THE MINI-EXEC

	SETOM TTJTIW
	MOVE 1,[XWD ITFFL,EXECI] ;GO TO EXECI ON INTERRUPT
	MOVEM 1,MONBK
	MOVEI 1,400000		;1/THIS FORK
	MOVEI 2,MICHN		;2/CHANNELS TO ENABLE
	MOVEM 2,MONCHN		;MAKE THE MONITOR TAKE INTERRUPTS ON THEM
	AIC			;ACTIVATE CHANNELS 34 AND 35

	JRST JBI0		;CONTINUE IN SWAPPABLE CODE
;JOB INITIALIZATION...
;SYSIFG IS 0 IF SYSTEM IS BEING STARTED

	SWAPCD

JBI0:	CALL JBFINI		;INIT FILE SYS FOR THIS JOB
	SKIPE SYSIFG		;SYSTEM INITIALIZED?
	JRST SYSINE		;YES

;SYSTEM IS BEING STARTED. DO ONCE-ONLY INITIALIZATION

	SETOM FGLOCK		;INIT FAST GET LOCK
	SETOM SYLNLK		;INIT SYSTEM LOGICAL NAME LOCK
	SETOM CRJLCK		;INIT LOCK OF CRJOB DATA BASE
	CALL FILINI		;INIT FILE SYSTEM
	SETOM GOKLCK		;INIT GETOK LOCK
	SETOM TIMLCK		;INIT LOCK ON TIMER Q'S
	MOVE 1,[XWD SBSNMS,SNAMES]
	BLT 1,SNAMES+NSBSNM-1	;MOVE REGULAR SUBSYSTEM NAMES TO TABLE
	MOVNI 1,NSBSNM		;INIT TABLE POINTER WITH NEG COUNT
	MOVEM 1,SNMPT
	SETOM SNMLCK		;AND INIT LOCK
	MOVE T1,[JOBONT,,JOBONT+1]
	SETOM JOBONT		;NO JOBS ARE YET OWNED BY ANYONE
	BLT T1,JOBONT+NJOBS-1	; ..
	CALL PIDINI		;INITIALIZE THE IPCF DATA BASE AND FORKS
	CALL SLNINI		;INITIALIZE SYSTEM LOGICAL NAMES
	SETOM UTLOCK		;INITIALIZE THE UTEST JSYS DATA BASE
	CALL GETNAM		;INITIALIZE STRING CONTAINING
				; MONITOR VERSION AND NAME
	CALL NAMINI		;INITIALIZE NODE NAME TO "TOPS20", IF DECNET
	MOVEI T1,TMZONE		;INITIALIZE TIMZON
	MOVEM T1,TIMZON	
	SETOM ACTLCK		;INITIALIZE LOCK ON ACCT WINDOW PAGES
	SETOM ACTOFN		;NO OFN FOR ACCT VALIDATION DATA FILE YET
	SETOM AVALON		;ALWAYS TURN ON ACCT VALIDATION TILL STATED OTHERWISE
	; ..
;JOB INITIALIZATION...
;THIS CODE IS REACHED FOR ALL JOBS, INCLUDING FIRST ONE AFTER SYSTEM
;STARTUP

SYSINE:	MOVE T1,JOBNO		;INITIALIZE THE PID QUOTA
	CALL PIDJBI		;  AND SEND QUOTA
	CALL ENQJBI		;INITIALIZE ENQ/DEQ QUOTA
	MOVE T1,JOBNO		;GET JOB NUMBER
	SETZM CRJFLG		;ASSUME NOT A CREATE-JOB STARTUP
	HLRZ T2,JOBPT(T1)	;CHECK FOR SPECIAL STARTUP FLAG
	CAIE T2,-2		;FROM CRJOB?
	JRST SYSIN1		;NO. NORMAL STARTUP.
	MOVE T2,CRJTTY		;CRJOB. HERE IS THE REQUESTED TTY.
	HRLM T2,JOBPT(T1)	;PUT IT IN JOBPT OF NEW JOB.
	MOVEM T2,CTRLTT		;AND IN THE JSB
	SETOM CRJFLG		;FLAG IN JSB THIS IS A CRJOB STARTUP
SYSIN1:	JUMPL T2,SYSIN2		;JUMP IF JOB IS DETACHED
	CALL TTYASN		;ASSIGN CONTROLLING TTY
	 JRST SYSIN9
	MOVE T2,CTRLTT		;GET TTY NUMBER
	CALL TTCKSP		;GO SEE IF SPEED SETTING NEEDED
SYSIN2:	MOVE T1,TODCLK
	MOVEM T1,CONSTO		;SET CONSOLE TIME ON
	CALL LGTAD
	MOVEM T1,CTIMON		;SET DATE/TIME CONNECT
	SETZM JSSRTM		;Reset session runtime
	SETZM JSSCTM		; and session console time
	MOVE T1,[OURNAM,,LLSR]	;BLT POINTER TO INITIALIZE NODE NAME
	BLT T1,LLSR+WPN-1	;MAKE JOB'S NODE NAME BE OUR LOCAL NAME
	MOVX T1,LOGIOB		;SAY JOB CREATION FINISHED
	ANDCAM T1,JOBBIT

;JOBS 0 THROUGH NSPECJ-1 ARE SPECIAL. SPECJT CONTAINS ADDRESS TO WHICH
;TO TRANSFER. FOR NOW, ONLY JOB 0 IS SPECIAL, AND IT GOES TO RUNDD.
;SEE IF THIS IS A SPECIAL JOB

	MOVE 1,JOBNO		;FIRST FEW JOBS ARE SPECIAL,
	CAIGE 1,NSPECJ		;IS THIS ONE OF THEM?
	JRST [	MOVEI 2,OPERDN	;YES, GET DIRECTORY NUMBER OF <OPERATOR>
		HRRM 2,JOBDIR(1) ;INDICATE LOGGED IN AS <OPERATOR>
		STOR 2,JSDIR	;SAVE AS CONNECTED DIRECTORY
		SETZRO JSCDF	;NO STRING IN JSB
		MOVE 2,STRTAB+PSNUM ;GET SDB ADDRESS OF STRUCTURE PS:
		LOAD 2,STRUC,(2) ;GET ITS UNIQUE STRUCTURE CODE
		STOR 2,JSUC	;SAVE AS CONNECTED STRUCTURE CODE
		MOVE 2,[[3
			 ASCIZ "OPERATOR"],,USRNAM]
		BLT 2,USRNAM+2	;SET UP DEFAULT USER NAME STRING
		HRRZ 2,SPECJT(1)
		JRST 0(2)]	;GO DO THE SPECIAL FUNCTION

;NOT A SPECIAL JOB. SET UP TERMINAL INFORMATION 

	MOVE A,CTRLTT		; GET CONTROLLING TERMINAL
	JUMPL A,SYSINP		;NO TTY. DON'T INIT TTY PARAMETERS
	CALL CHKPTY		;IS IT A PTY?
	 SKIPA			;NO. INIT TTY PARAMETERS
	JRST SYSINP		;YES. DON'T INIT TTY PARAMETERS
	MOVEI 1,100
	MOVEI 2,3B33		;SET TO HDX HERE, SO SETTING TO FDX
	STPAR			;BELOW WILL FORCE OUT TELNET CONTROL
	MOVE 2,NORMTF		;GET TTY TO STANDARD STATE
	SFMOD
	STPAR			;SET DEVICE PARAMETERS TOO
	MOVE B,CTRLTT		;GET CONTROLLING TERMINAL
	CALL CHKNVT		;IS IT A NETWORK TTY,
	 SKIPA 2,NORMTY		;NO. INIT TERM TO STANDARD TYPE
	MOVE T2,[.TTIDL]	;MAKE IT "IDEAL" TERMINAL
	STTYP
	MOVE 2,TTICB1
	MOVE 3,TTICB2
	SFCOC
	HRLOI T1,(TL%CRO+TL%COR+TL%SAB+TL%ABS+TL%STA)
	MOVE T2,CTRLTT		;Get controlling TTY#
	CAMN T2,CTYLNO		;Starting job on CTY?
	TXZ T1,TL%ABS		;Yes - so set refuse links
	MOVEI T2,-1		;ALL REMOTE
	TLINK			;BREAK LINKS, CLEAR ACCEPT
	 JFCL

;GO START THE EXEC. IF SYSTEM IS STAND-ALONE, TELL THE USER

SYSINP:	SKIPE CRJFLG		;IF CREATED JOB, GO SET IT UP.
	JRST STCRJB		; ..
	MOVE T1,DBUGSW
	CAIGE 1,2		;DEBUG MODE OPERATION?
	JRST STEX		;NO, GO START EXEC
	TMSG <
[Caution--System is stand-alone]
>
	JRST STEX		;WARN USERS FIRST

SYSIN9:	PUSH P,CTRLTT
	SETOM CTRLTT		;INDICATE DETACHED SO LOGOUT WON'T
	MOVE T2,JOBNO		; TRY TO WRITE ON THIS TERMINAL
	HRROS JOBPT(T2)		;..
	POP P,T1		;RESTORE LINE NUMBER
	SETZM TTACTL(T1)	;INDICATE LINE IS NOT ACTIVE
	MOVEI T1,.TTDES(T1)	;T1/ TERMINAL DESIGNATOR
	HRROI T2,[ASCIZ/?FULL
/]
	TTMSG			;INDICATE SYSTEM IF FULL
	SKIPL CRJFLG		;IS THIS JOB BEING CREATED BY CRJOB JSYS?
	JRST FLOGO		;NO. GO KILL THE JOB
	MOVEM T1,CRJANS		;YES. SAVE ERROR CODE FROM TTYASN
	JRST LOGO		;GO KILL THE JOB
;HERE AT STARTUP OF JOB BY CRJOB JSYS.

STCRJB:	MOVE Q1,JOBNO		;CARRY AROUND MY JOB NUMBER
	HRLM Q1,CRJONJ		;TELL CREATOR, IF WE GET THERE.
	MOVE Q2,CRJAC1		;AND CONTROL FLAGS OF CRJOB AC1
	MOVE T1,CRJONJ		;GET CREATOR'S JOB NUMBER
	TXNE Q2,CJ%OWN		;CREATOR WANTS TO OWN ME?
	MOVEM T1,JOBONT(Q1)	;YES. REMEMBER WHO HE IS.
	MOVE T1,CRJSLO		;SIGNAL ON LOGOUT?
	TXNN Q2,CJ%SLO		; ..
	MOVEI T1,0		;NO. CLEAR THE PID
	MOVEM T1,JSLOPD		;SAVE THE PID FOR THE SIGNAL
	JN CJ%LOG,Q2,STCJB1	;JUMP IF WANTS TO LOG IN
	HRRZ T1,CRJONJ		;NO LOGIN, GET CREATOR'S JOB NUMBER
	HRRZ T1,JOBDIR(T1)	; TO FETCH CREATOR'S LOGIN DIRECTORY
	STOR T1,JSDIR		;AND MAKE IT OUR CONNECTED DIRECTORY
	MOVE T1,STRTAB+PSNUM	;POINT TO THE PS: SDB
	LOAD T1,STRUC,(T1)	; AND FETCH THE PS: STRUCTURE UNIQUE CODE
	STOR T1,JSUC		;SET IN JSB, COMPLETING CONNECT TO PS:
	SETZM CAPENB		;MAKE SURE I HAVE NO CAPS ENABLED
	HLLZS CAPMSK		;OR POTENTIAL
	MOVE T1,CRJOJC		;GET OWNING JOB'S CAPS
	AND T1,CRJCAM		;MASKED, IF ASKED
	TXNE Q2,CJ%CAP		;DOES HE WANT TO GIVE ME HIS?
	HRRM T1,CAPMSK		;YES, I'LL TAKE THEM, UNTIL LOGIN JSYS
	JRST STCJ1A		;DONE WITH LOGIN-ISH STUFF

;HERE IF CJ%LOG IS ON IN CALL. I AM TO TRY TO LOG THIS JOB IN.

STCJB1:	HRROI B,CRJUSR		;POINT TO THE USER NAME STRING
	MOVX T1,RC%EMO		;EXACT MATCH ONLY
	RCUSR			; AND CONVERT TO USER NUMBER
	 ERJMP SCJXXX		;PASS FAILURE CODE BACK
	TXNE T1,RC%NOM!RC%AMB	;FILES ONLY, NO MATCH OR
	JRST SCJXX1		; AMBIGUOUS? FAIL. CAN'T LOG IN.
	MOVEM T3,CRJUSR		;STORE THE NUMBER
	HRRZ T3,T3		;CLEAN FOR CAMN LATER
	MOVE T4,CRJOJC		;GET CREATOR'S CAPS
	HRRZ T1,CRJONJ		;AND JOB NUMBER
	HRRZ T1,JOBDIR(T1)	;CREATOR'S LOGIN DIRECTORY
	TRNN T4,SC%WHL!SC%OPR	;PRIVILEGED CREATOR?
	CAMN T1,T3		;OR LOGGING IN AS SAME USER?
	JRST STCJ1E		;YES. NO NEED FOR PSWD CHECK.
	TXZE Q2,<CJ%NPW!CJ%NUD>	;NO, SO REQUIRE PASSWORD, AND LOGIN DATE
	JRST [	MOVEI T1,CRJBX1	;ILLEGAL REQUEST
		JRST SCJXXX]
STCJ1E:	LOAD T1,CJ%ACT,Q2	;WHAT KIND OF ACCOUNT DO WE USE?
	CAIE T1,.CJUCA		;USE CURRENT ACCOUNT OF CREATOR
	CAIN T1,.CJUAA		;OR ARG BLOCK ACCOUNT?
	JRST STCJ1C		;YES, IT'S IN THE COMMON STORAGE.
	SETZM CRJACT		;USE DEFAULT
   ;FALL THRU
   ;CAN FALL IN
STCJ1C:	MOVEI T1,0		;BUILD FLAGS FOR LOGIN JSYS
	TXNE Q2,CJ%NPW		;NO PASSWORD NEEDED?
	TRO T1,1		;RIGHT.
	TXNE Q2,CJ%NUD		;NO UPDATE LOGIN DATE?
	TRO T1,2		;RIGHT. TELL LOGIN.
	HRRM T1,CRJFLG		;STORE FOR IT TO SEE
	MOVE T1,CRJUSR		;LET'S DO THE LOGIN NOW.
	HRROI T2,CRJPSW		;PASSWORD, IF ANY.
	MOVE T3,CRJACT		;AND ACCOUNT
	LOGIN			;SEE IF THIS IS ALL VALID.
	 JRST SCJXXX		;APPARENTLY NOT.
	HRRO T1,CRJCAM		;ASKED TO LIMIT CAPABILITIES?
	ANDM T1,CAPENB		;DO SO IF NOT -1
	ANDM T1,CAPMSK		; ..
STCJ1A:	MOVE T2,CRJCPU		;GET TIME LIMIT FOR THIS JOB
	JUMPE T2,SCJBNL		;JUMP IF NO LIMIT
	MOVE T1,[.FHJOB,,.TIMRT] ;SET TIME LIMIT FOR JOB
	MOVEI T3,.ICMSE		;ON MACHINE-SIZE EXC CHANNEL, SO PANIC
	TIMER			;DO IT
	 JRST SCJXXX		;GIVE BACK FAILURE
SCJBNL:	MOVEI T1,.FHSLF		;SET UP TO DO SPJFN
	MOVE T2,CRJPJF		;FROM THIS ARGUMENT
	TXNE Q2,CJ%FIL		;IS THERE BOTH AN EXEC AND AN INFERIOR?
	TXNN Q2,CJ%ETF		; ..
	SKIPA			;NO. DO THE SPJFN HERE.
	JRST STCJ1D		;YES. ONLY DO THE SPJFN ON THE INFERIOR
	TXNE Q2,CJ%SPJ		;REQUESTED TO DO SPJFN?
	SPJFN			;YES, DO IT.
STCJ1D:	HLLZS CRJFLG		;NO FLAGS FOR A LATER LOGIN
	TXNN Q2,CJ%FIL		;WANT TO RUN A FILE?
	JRST CJSTEX		;NO. JUST GO GET THE EXEC.
STCJB2:	TXNE Q2,CJ%ETF		;WANT A FILE. AN EXEC TOO?
	JRST STCJB3		;YES.
	MOVX T1,GJ%OLD!GJ%SHT	;GET THE REQUESTED FILE IN TOP FORK
	HRROI T2,CRJFIL		;POINT TO THE TEXT
	GTJFN			;GET JFN FOR REQUESTED FILE
	 JRST SCJXXX		;CAN'T
	HRLI T1,.FHSLF		;OK, GET IT INTO THIS FORK.
	GET
	ERJMP SCJXX4		;IF GET FAILS, QUIT.
;NOTE: THIS CODE RUNS IN SECTION 0 FOR SOME UNKNOWN REASON. IN
;ORDER FOR THIS CALL TO BLTMU TO WORK CORRECTLY, THIS CODE TEMPORARILY
;ENTERS SECTION 1. IF STRCJB IS MADE TO RUN ENTIRELY IN SECTION 1, THESE
;MACROS SHOULD BE REMOVED.
	SE1ENT
	MOVEI T1,20		; Length of AC block
	XMOVEI T2,CRJFAC	; From there
	SETZ T3,
	TXNE Q2,CJ%ACS		;AC SET REQUESTED?
	CALL BLTMU
	SE0ENT
	MOVEI T1,.FHSLF		;GET THE ENTRY VECTOR
	GEVEC			;GET THE ENTRY VECTOR
	TLNN T2,777000		;TOPS10 STYLE?
	JRST STCJ2A		;NO. TOPS20 STYLE, IF ANYTHING.
	HRRZ T3,CRJEVO		;OLD STYLE. WHERE DOES START POINT?
	CAILE T3,1		;START OR REENTER, I HOPE.
	JRST SCJXX3		;NO. FAIL.
	UMOVE T2,120		;GET JOBSA
	TRNE T3,-1		;OR IF 1,
	UMOVE T2,124		;GET JOBREN
	SKIPA
STCJ2A:	ADD T2,CRJEVO		;NEW STYLE, ADD OFFSET TO BASE.
	HRRZM T2,-1(P)		;WHERE MRETN WILL GO.
	HRLI T2,1		;INDICATE JOB HAS ALREADY SET CRJANS
	HLLM T2,CRJFLG		; BY MAKING FLAG POSITIVE
	SETOM CRJANS		;SAY WE HAVE SUCCEEDED.
	PUSHJ P,SCJWTA		;WAIT FOR ATTACH, IF WANTED
	JRST MRETN		;AND GO TO USER MODE.
;HERE IF WANT BOTH A FILE AND AN EXEC.

STCJB3:	MOVX T1,GJ%OLD!GJ%SHT	;GET A JFN FOR THE FILE.
	HRROI T2,CRJFIL		;WITH SUPPLIED NAME
	GTJFN
	 JRST SCJXXX		;CAN'T FIND THE FILE.
	PUSH P,T1		;SAVE JFN A MOMENT
	MOVX T1,CR%CAP		;CREATE THE NEW FORK, MY CAPS.
	TXNE Q2,CJ%ACS		;WANT SOME AC'S LOADED?
	TXO T1,CR%ACS		;YES, HAVE CFORK LOAD THEM.
	MOVEI T2,CRJFAC		;HERE ARE THE AC'S
	CFORK			;MAKE ME A FORK! (YOU'RE A FORK)
	 JRST SCJXX2		;CAN'T DO IT.
	EXCH T1,0(P)		;GET BACK JFN, SAVE FHANDLE
	HRL A,0(P)		;SET UP FOR THE GET
	GET
	ERJMP SCJXX2		;CAN'T GET THE FILE
	MOVE T1,0(P)		;HANDLE OF INFERIOR
	MOVE T2,CRJPJF		;PRIMARY I/O FOR IT
	TXNE Q2,CJ%SPJ		;IF REQUESTED,
	SPJFN			;SET IT.
	POP P,T1		;INFERIOR FORK HANDLE.
	HRLZS T1		;FORK,,0
	HRR T1,CRJEVO		;WHERE TO START IT.
	CALL SCJPRA		;SET UP PRARG FOR EXEC
CJSTEX:	HRLI T2,1		;INDICATE JOB HAS ALREADY SET CRJANS
	HLLM T2,CRJFLG		; BY MAKING FLAG POSITIVE
	SETOM CRJANS		;DONE WITH THE JSYS
	PUSHJ P,SCJWTA		;WAIT FOR ATTACH, IF REQUESTED
	JRST STEX		;AND GO GET AND START THE EXEC.
;CALL THIS ROUTINE BEFORE GOING TO MRETN FROM CRJOB PATHS. IT WILL
;WAIT FOR JOB TO BECOME ATTACHED, IF THAT'S REQUESTED BY CALLER.

SCJWTA:	TXNN Q2,CJ%WTA		;WANT TO WAIT?
	RET			;NO.
	MOVE T1,JOBNO		;YES. GET MY JOB NUMBER
	MOVEI T1,JOBPT(T1)	;AND JOBPT SLOT FOR THIS JOB
	CALL DISGE		;WAIT FOR LH TO BECOME POSITIVE
	RET			;NOW ATTACHED. RETURN.

SCJXX3:	MOVEI T1,SFRVX1		;BAD ENTRY VECTOR OFFSET
	JRST SCJXXX		;RETURN THAT ERROR
SCJXX2:	POP P,0(P)		;ADJUST STACK POINTER
SCJXX4:	HRRZ T1,LSTERR		;AND RETURN THIS FORK'S LAST ERROR
	JRST SCJXXX		; TO CREATOR
SCJXX1:	MOVEI T1,CRJBX5		;UNKNOWN NAME FOR LOGIN
SCJXXX:	SKIPGE CRJFLG		;IS THIS JOB BEING CREATED
	HRRZM T1,CRJANS		;YES. SET RH NON-ZERO.
	MOVE T1,JOBNO		;MAKE SURE I'M NOT OWNED, SO
	SETOM JOBONT(T1)	;THIS LOGOUT CAN GO THROUGH
	JRST LOGO		;AND KILL OFF THIS STARTED JOB.

;ROUTINE TO SET UP PRARG FOR EXEC TO READ IN NEW JOB

NCJPRA==3			;NUMBER OF ARGUMENT ITEMS
LCJPRA==6			;LENGTH OF BLOCK TO SET

SCJPRA:	TRVAR <<SCJPRB,10>>	;SPACE TO BUILD PRARG BLOCK
	PUSH P,T1		;PRESERVE FORKX,,SFRKV OFFSET
	MOVEI T1,NCJPRA		;NUMBER OF ARGUMENTS
	MOVEM T1,SCJPRB		;INTO THE BLOCK
	MOVEI T1,SCJPRB		;POINT TO BLOCK WITH PUSH POINTER
	PUSH T1,[1B0+3B6+2B12+CR%PRA]	;I AM A CRJOB PRARG
	PUSH T1,[1B0+4]		;WORD 4 IS ANOTHER DATUM
	PUSH T1,[1B0+5]		;WORD 5 IS ANOTHER DATUM
	MOVE T2,CRJEXF		;FLAGS FOR EXEC IS ONE DATUM
	TXO T2,1B1		;TURN ON "THERE'S A FORK" BIT
	PUSH T1,T2		;FLAGS TO ARG BLOCK
	POP P,T2		;RESTORE FORKX,, ENT-VEC-OFFSET
	PUSH T1,T2		;PUT IT IN BLOCK
	MOVE T1,[.PRAST,,.FHSLF] ; SET MY OWN PRARG BLOCK
	MOVEI T2,SCJPRB		;HERE'S THE BLOCK TO SET
	MOVEI T3,LCJPRA		;HERE'S ITS LENGTH
	PRARG			;SET IT
	ERJMP SCJXX4		;CATCH TRAP IF FAILED
	RET			;SUCCESS.
;SYSTEM INITIALIZATION.  RUN ONCE ONLY BY JOB 0.

	SWAPCD

RUNDD::	MOVEI T1,RUNDD3		;GO TO RUNDD3 IF AN INTERRUPT OCCURS
	MOVEM T1,JB0XFR		;SAVE THE ADDRESS FOR JB0INT
	MOVEI T1,JB0INT		;GO TO THE JOB 0 INTERRUPT HANDLER ON
				; INTERRUPT FOR ENABLED CHANNELS
	HRRM T1,MONBK		;SET THIS FOR THE SCHEDULER
	MOVE T1,CTYLNO		;GET CTY LINE NUMBER
	MOVEI T1,.TTDES(T1)	;CONVERT TO 400000+N
	MOVEM T1,JB0TT		;CONTROLLING TERMINAL FOR JOB 0
	MOVSI 1,777
	ANDCAM 1,CAPENB		;FLUSH ANY SUPERIOR FORK CAPS
	CALL ASCINI		;Initialize accounting shift change stuff
	SKIPN PROFLG		;WANT PRIMARY PROTOCOL?
	JRST RUNDI7		;NO. SKIP ALL PRIMARY STUFF
	MOVEI A,.PRIOU		;YES. FIRST WAIT FOR CTY TO STOP
	DOBE			;"
	CALL TTSPIN		;INITIALIZE TERMINAL SPEEDS TO NULL
	CALL PROINI		;TURN ON PRIMARY PROTOCOL
	CALL DTRMDS		;TELL -11 NOT TO ANSWER DATA SETS

;TRY TO GET TIME AND DATE FROM THE 11. DTE SERVICE SENDS THE REQUEST TO
;THE 11 AND STORES ITS ANSWER IN TAD11. IF THE 11 DOES NOT KNOW, IT
;RETURNS -1. IN THIS CASE, ASK THE OPERATOR FOR THE TIME. IF THE 11 HAS
;IT, DON'T ASK THE OPERATOR

	SKIPE SMFLAG		;IF SM10 THEN WE ALREADY HAVE TIME AND DATE CORRECT
	JRST RUNDD3
	SETZM TAD11		;ZERO TIME CELL
	CALL RQTAD1		;REQUEST TIME/DATE FROM 11
	 JFCL			;THIS FAILURE CAN'T OCCUR
	SKIPN TAD11		;HAS 11 SENT TIME/DATE YET?
	JRST .-1		;NO. WAIT UNTIL IT DOES
	MOVE B,TAD11		;GET TIME SENT FROM -11
	SETOM TAD11		;YES. RESET TO INDICATE NOT SET BY 11
	CAMN B,[-1]		;DOES THE -11 HAVE IT?
	JRST RUNDI7		;NO
	DMOVE C,TAD11+1		;YES. GET REST OF IDCNV ARGS
	IDCNV			;CONVERT TO INTERNAL
	 JRST RUNDI7		;FAILED. GET FROM OPERATOR THEN
	MOVEM B,CRSTAD		;LET IT FIND IT LATER

	;..
;RUNDD...
;SET SYSTEM TIME AND DATE IF THE 11 PROVIDED IT

	;..
RUNDI7:	MOVEI 1,101
	DOBE
	SKIPN 1,CRSTAD		;DO WE HAVE A SAVED TIME FROM CRASH?
	JRST [	MOVX A,SF%MST	;NO. SAY IS A MANUAL START
		IORM A,FACTSW	;""
		JRST RUNDD3]
	STAD			;YES, SET IT
	 JFCL
	SETZM CRSTAD

;Initialize checkpoint interval

RUNDD3:	MOVEI T1,RUNDI4		;GO TO RUNDI4 IF AN INTERRUPT OCCURS
	MOVEM T1,JB0XFR		;SAVE THE ADDRESS FOR JB0INT
	MOVE T1,[^D<10*60000>]	;SET DEFALUT CHECKPOINT INTERVAL
	MOVEM T1,CKPINV		;...

;RUN SETSPD TO SET LINE SPEEDS, SYSTEM LOGICAL NAMES, OTHER SYSTEM
;PARAMETERS

	MOVX T1,GJ%OLD!GJ%SHT!GJ%PHY ;YES. SET LINE SPEEDS
	HRROI T2,SETSPD		;GET POINTER TO "SYSTEM:X-SETSPD.EXE"
	SETZ T3,		;3/OFFSET 0 IN ENTRY VECTOR
	CALL RUNDII		;GO RUN IT
	 JRST [	HRROI T1,[ASCIZ/
%%No SETSPD
/]
		PSOUT
		MOVEI T1,.PRIOU ;WAIT UNTIL THE TERMINAL
		DOBE		; STOPS SO THE NEXT MESSAGE IS OK
		JRST .+1]	;SAY IT FAILED
	CALL GETNAM		;DO AGAIN,SINCE SYSTEM: MAY BE REDEFINED

;IF DBUGSW IS 0 OR 1, TELL ALL USERS THAT SYSTEM IS RESTARTING

RUNDD6:	MOVE 1,DBUGSW
	CAIE 1,0
	CAIN 1,1		;REGULAR STARTUP?
	SKIPA
	JRST RUNDI4		;NO, DON'T NOTIFY WORLD
	SETO 1,
	HRROI 2,[ASCIZ /
System restarting, wait.../]
	TTMSG
	;..
;RUNDD...

;GET DATE AND TIME FROM OPERATOR UNLESS 11 SENT IT EARLIER

	;..
RUNDI4:	MOVEI T1,RUNDI1		;GO TO RUNDI1 IF AN INTERRUPT OCCURS
	MOVEM T1,JB0XFR		;SAVE THE ADDRESS FOR JB0INT
	CALL LGTAD		;DOES SYSTEM HAVE TIME AND DATE?
	CAME A,[-1]
	JRST RUNDI1		;YES
RUNDI3:	TMSG <
Enter current date and time: >
RUNDI2:	CALL RDDGTD		;GET TAD INTO 2
	PUSH P,2		;SAVE TAD JUST ENTERED
	TMSG <
You have entered >
	MOVEI 1,.PRIOU
	MOVE 2,0(P)
	MOVX 3,1B1+1B2+1B4+1B5+1B10+1B11+1B17
	ODTIM			;TYPE IT IN VERBOSE FORMAT
	MOVE 2,0(P)
	CAMGE 2,SYSTAD		;IS IT GREATER THAN SYSTEM LOAD TAD?
	JRST [	MOVEI 1,.PRIIN	;CLEAR TYPE AHEAD
		CFIBF
		MOVEI 1,.PRIOU
		DOBE		;WAIT FOR TYPE OUT TO STOP
		TMSG <,
that cannot be correct.
Please try again in form MMM-DD-YY HHMM >
		JRST RUNDI2]
	TMSG <,
 is this correct (Y,N) >
	CALL YESNO		;GET VERIFICATION
	JUMPE A,RUNDI3		;IF 'NO', TRY AGAIN
	POP P,1			;CONFIRMED, RECOVER IT
	STAD			;SET IT
	 JFCL
	; ..
;RUNDD...

;DECIDE WHETHER TO RUN CHECKD OR NOT. IF CHKBT FOUND ERRORS, FACTSW HAS
;SF%BTE SET; RUN CHECKD TO DO A BIT TABLE CONSISTENCY CHECK. IF BIT
;TABLE FILE DOESN'T EXIST, MI%ASG IS SET IN SDB. DON'T RUN CHECKD.
;(OPERATOR WILL HAVE TO RUN IT WITH THE REBUILD FUNCTION). IF DOING
;RECONSTRUCTION OF ROOT-DIRECTORY OR REBUILD OF BIT TABLE, STARTF HAS
;MI%BTB SET; RUN CHECKD TO DO A REBUILD OF THE BIT TABLE.  IF DOING
;A REFRESH OF THE FILE SYSTEM, DON'T TRY TO RUN CHECKD. IF NONE OF
;THE ABOVE, ASK THE OPERATOR UNLESS AUTO RELOADING. IN ALL CASES,
;ONLY PS IS MOUNTED AT THIS POINT, SO CHECKD IS ONLY RUN ON PS.

	;..
RUNDI1:	MOVEI T1,RUNDD1		;GO TO RUNDD1 IF AN INTERRUPT OCCURS
	MOVEM T1,JB0XFR		;SAVE THE ADDRESS FOR JB0INT
	CALL LOGSST		;LOG RESTART IN SYSERR FILE
	SKIPN AVALON		;RUNNING ACCOUNT VALIDATION?
	JRST RUNDI5		;NO, PROCEED
	CALL ENACT		;INITIALIZE THINGS FOR ACCT VALIDATION
	 JRST [	TMSG <
<SYSTEM>ACCOUNTS-TABLE.BIN not found - Account validation is disabled
>
		SETZM AVALON	;TURN OFF VALIDATION
		JRST .+1]	;AND PROCEED

RUNDI5:	MOVX T4,MI%BTB		;IF REBUILDING THE BIT TABLE (BIT IS
	TDNE T4,STARTF		; SET BY FILINI)
	JRST RUNDC2		;ALWAYS RUN CHECKD IN REBUILD MODE
	MOVE 2,DBUGSW		;IF DEBUGGING,
	CAIN 2,2
	JRST RUNDD2		;DON'T RUN CHECKD
	MOVX T4,MI%RFS		;IF REFRESHING (BIT IS SET
	TDNE T4,STARTF		; BY FSIINI)	
	JRST RUNDD2		;DON'T RUN CHECKD (IT ISN'T THERE)
	MOVE T2,STRTAB+PSNUM	;POINT TO SDB FOR PS
	MOVE T2,SDBSTS(T2)	;GET STATUS BITS FOR PS
	MOVE T1,FACTSW
	TXNE T1,SF%BTE		;BIT TABLE ERRORS?
	TXNE T2,MI%ASG		;YES. ARE DISK ASSIGNMENTS PROHIBITED?
	SKIPA			;YES. DON'T RUN CHECKD
	JRST RUNDC1		;BIT TABLE ERRORS BUT BT FILE EXISTS. RUN CHECKD
	TXNN A,SF%MST		;MANUAL STARTUP?
	JRST RUNDD2		;NO. NO QUESTIONS AND NO CHECKD
	;..
;CHECKD NOT REQUIRED.  SEE IF OPERATOR WANTS IT

	;..
	TMSG <Run CHECKD? >
	CALL YESNO
	JUMPE A,RUNDD2		;JUMP IF NO
RUNDC1:	SKIPA T1,[-1,,[ASCIZ/[Checking file consistency]
/]]
RUNDC2:	HRROI T1,[ASCIZ/[Rebuilding bit table]
/]
	PSOUT
	MOVSI 1,(GJ%OLD!GJ%PHY!GJ%SHT)
	HRROI 2,[ASCIZ /SYSTEM:CHECKD.EXE/]
	MOVX T3,SF%CDR		;SAY CHECKD NOW RUNNING
	IORM T3,FACTSW		;DO IT
	SETZ T3,		;NORMAL ENTRY POINT
	MOVX T4,MI%BTB
	TDNE T4,STARTF		;REBUILDING BIT TABLE?
	MOVEI T3,3		;YES. START AT SPECIAL ENTRY POINT
	CALL RUNDII		;GO START IT
	 JRST [	MOVX T1,SF%CDR	;NOT RUNNING
		ANDCAM T1,FACTSW
		JRST RUNDD1]	;FAILED
	SETZM STARTF		;INDICATE STARTUP IS COMPLETE
	MOVX T1,SF%CDR		;SAY CHECKD NOT RUNNING ANYMORE
	ANDCAM T1,FACTSW	;""
	JRST RUNDD2		;PROCEED

;FAILED TO FIND CHECKD WHEN RUNNING IT WAS REQUIRED BY THE SYSTEM
;OR REQUESTED BY THE OPERATOR. PRETEND THAT IT RAN AND FOUND
;ERRORS. IF IT IS RUN LATER AND FINDS PS TO BE OK, IT WILL CLEAR
;SF%CDE.
;IT ALSO CAUSES THE 'FILE STRUCTURE NEEDS REPAIR' MESSAGE BELOW
;AND PREVENTS SYSJOB FROM DOING ITS USUAL THING

RUNDD1:	MOVEI T1,RUNDD2		;GO TO RUNDD2 IF AN INTERRUPT OCCURS
	MOVEM T1,JB0XFR		;SAVE THE ADDRESS FOR JB0INT
	TMSG <
No CHECKD
>
	SETZM STARTF		;INDICATE STARTUP COMPLETED
	MOVX T4,SF%CDE		;PRETEND CHECKD FOUND ERRORS
	IORM T4,FACTSW
	;..
;RUNDD...

;IF DEBUGGING, TELL ALL USERS. IF CHECKD FOUND ERRORS, TELL ALL USERS
;THEN PROCEED AS USUAL

	;..
RUNDD2:	MOVEI 1,RUNDD7		;GO TO RUNDD7 IF AN INTERRUPT OCCURS
	MOVEM T1,JB0XFR		;SAVE THE ADDRESS FOR JB0INT
	MOVEI 1,101
	DOBE			;WAIT FOR ANY CHECKD OUTPUT
	MOVE 1,DBUGSW
	CAIL 1,2		;DEBUG MODE OPERATION?
	JRST [	SETO 1,		;YES, DIFFERENT MESSAGE
		HRROI 2,[ASCIZ /
[System is stand-alone]
/]
		TTMSG
		JRST RUNDE1]
	MOVX 1,SF%CDE
	TDNE 1,FACTSW		;DID CHECKD FIND DISK ERRORS?
	JRST [	HRROI 2,[ASCIZ /
[System not in operation - file structure needs repair]
/]
		SETO 1,
		TTMSG
		JRST RUNDE1]

;INITIALIZE SYSERR LOGGING AND START ACCOUNTING

RUNDE1:	MOVE 1,JB0TT		;JOB 0 TTY
	CAIE 1,377777		;REAL TTY?
	JRST RUNDD4		;YES
	MOVSI 1,(GJ%FOU!GJ%PHY!GJ%SHT)	;NONE, SO OPEN FILE FOR MESSAGES
	HRROI 2,[ASCIZ /PS:<SYSTEM>ERROR.REPORT/]
	GTJFN
	 BUG(NOSERF)
	MOVE 2,[44B5+1B20]
	OPENF
	 BUG(SERFOF)
RUNDD4:	HRRM 1,PRIMRY		;USE IT FOR OUTPUT 
	CALL SERINI		;START SYSERR LOGGING
	CALL USGINI		;START ACCOUNTING
	;..
;RUN SETSPD AGAIN. THIS TIME, START IT AT A SPECIAL PLACE TO MAKE
;IT COPY THE DUMP FILE.

	;..
	MOVX T1,SF%CDE		;DON'T CREATE DUMP.CPY IF THE BIT
	TDNE T1,FACTSW		; TABLE IS BAD
	JRST RUNDD7		;CHECKD FOUND ERRORS IN THE BT
	MOVX T1,GJ%OLD!GJ%PHY!GJ%SHT
	HRROI T2,SETSPD		;GET POINTER TO "SYSTEM:X-SETSPD.EXE"
	MOVEI T3,3		;3/ OFFSET 3 IN ENTRY VECTOR
	CALL RUNDII		;GO RUN IT
	 JFCL			;IGNORE FAILURE

;DO NETWORK-RELATED FUNCTIONS

RUNDD7:	MOVEI T1,RUNDD8		;GO TO RUNDD8 IF AN INTERRUPT OCCURS
	MOVEM T1,JB0XFR		;SAVE THE ADDRESS FOR JB0INT
	CALL IMPBEG		;START NCP FORK, IF ANY.
	CALL KDPINI		;INIT THE KDP(KMC11/DUP11) CODE
	CALL NSPINI		;INIT DECNET FORK AND DATA BASE
	CALL ATSINI		;INITIAALIZE APPLICATIONS TERMINAL SERVICE
	TMSG <
Running DDMP

>
RUNDD8:	MOVEI T1,RUNDD5		;GO TO RUNDD5 IF AN INTERRUPT OCCURS
	MOVEM T1,JB0XFR		;SAVE THE ADDRESS FOR JB0INT
	AOS SYSIFG		;INDICATE NO LONGER IN STARTUP
				; (NEXT JOB WON'T GO THROUGH RUNDD)
	CALL DONSJ		;START NEXT SPECIAL JOB

;CREATE FORK UNDER JOB 0 AND RUN SYSJOB IN IT. SYSJOB READS A COMMAND
;FILE, WHOSE NAME IS DETERMINED BY THE SETTING OF DBUGSW. IF CHECKD
;HAS NOT BLESSED PS (SF%CDE IS SET IN FACTSW), SYSJOB DOES NOT READ
;A COMMAND FILE.  AMONG OTHER THINGS, THIS WILL PREVENT LOGINS FROM
;TERMINALS OTHER THAN THE CTY

	MOVX T1,<GJ%OLD!GJ%PHY!GJ%SHT>
	HRROI T2,[ASCIZ /SYSTEM:SYSJOB.EXE/]
	SETZM T3		;MAIN ENTRY POINT
	CALL RUNDIR		;RUN SYSJOB AND RETURN
	 JRST [	 TMSG<
No SYSJOB
>
		JRST .+1]
RUNDD5:	MOVEI 1,1		;KEEP JOB 0 IN QUEUE 1 ALWAYS
	MOVEM 1,JOBBIT		;SET PRIORITY FOR CHKR
	MOVEI T1,CHKR		;GO TO CHKR IF AN INTERRUPT OCCURS
	MOVEM T1,JB0XFR		;SAVE THE ADDRESS FOR JB0INT
	SETZM EXPFRK		;CLEAR FORK HANDLE
	SKIPN SMFLAG		;IF NOT 2020
	CALL RUNMO1		; RUN MOS MEM DIAG
	JRST CHKR		;GO DO BACKGROUND
;JB0INT - HERE WHEN INTERRUPT OCCURS IN FORK 0

;THIS ROUTINE IS POINTED TO BY MONBK. THE SCHEDULER TRANSFERS
;CONTROL TO HERE WHEN AN INTERRUPT OCCURS ON CHANNEL 34 OR 34 IN
;FORK 0. JB0XFR CONTAINS THE ROUTINE TO WHICH THIS CODE TRANSFERS
;AFTER CLEANING THINGS UP

JB0INT:	MOVE P,UPP		;RESET THE STACK
	ADD P,BHC+4		; TO SIMULATE JSYS ENTRY
	MOVEI 1,<UACB>B39-1	;SETUP AC BASE
	MOVEM 1,ACBAS		; TO POINT TO THE FIRST BLOCK
	MOVEI T1,J0EMER		;IN CASE OF EMERGENCY
	HRRM T1,MONBK		; DON'T EVEN DO ALL THIS
	SETZM NSKED		;BE OKSKED
	SETZM CRSKED		;BE NOT 'CRITICAL SECTION'
	SETZM SLOWF
	SETOM INTDF		;IN CASE OVERLY OKINT
	CALL CLRINT		;CLEAR THE INTERRUPT SYSTEM
	MOVE T1,FORKX		;T1/ FORK NUMBER
	SETZM T2		;T2/ ALL INTERRUPT LEVELS
	CALL JSBSTF		;CLEAN THE JSB STACK
	MOVE T1,FORKX		;T1/ FORK NUMBER
	SETZM T2		;T2/ ALL LEVELS
	CALL GOKFRE		;CLEAN UP GETOK QUEUES (SHOULDN'T HAVE ANY)
	HRROI T1,[ASCIZ /
%MONITOR: Job 0 crash, continuing at PC /]
	PSOUT			;TELL OPERATOR THAT WE DIED
	MOVEI T1,.PRIOU		;GET READY
	MOVE T2,JB0XFR		;CONTINUATION ADDRESS
	MOVEI T3,^D8		;OCTAL
	NOUT			;GIVE THE PC
	ERJMP .+1		;IGNORE ERRORS
	HRROI T1,[ASCIZ/
/]				;FINISH WITH A CRLF
	PSOUT			;TYPE IT
	MOVEI T1,JB0INT		;BACK TO HERE IF ANOTHER INTERRUPT
	HRRM T1,MONBK		; NOW THAT WE SURVIVED THIS ROUTINE
	MOVE T1,JB0XFR		;SEE WHERE WE ARE TO GO NEXT
	JRST 0(T1)		; AND GO THERE

;HERE WHEN AN ERROR OCCURRED WHILE IN JB0INT. GIVE UP.

J0EMER:	BUG (STRTER)

;CLRINT - CLEAR THE INTERRUPT SYSTEM

CLRINT:	MOVEI 1,400000		;DEACTIVATE SOFTWARE INTERRUPT CHANNELS
	SETO 2,			; FOR THIS PROCESS

	DIC
	CALL DTIALL		;IN CASE PROGRAM TURNED ANY ON
	MOVE 2,PSIBW	
	CIS			;CLEAR ALL INTERRUPTS IN PROGRESS
	RET
;ROUTINE TO RUN A PROGRAM IN A FORK UNDER JOB 0
; A/ GTJFN T1 ARGS
; B/ GTJFN T2 ARGS
; C/ OFFSET IN ENTRY VECTOR WHERE WE START FORK
;	CALL RUNDII
;	  or
;	CALL RUNDIR
;RETURNS +1: FAILED, PROGRAM NOT RUN
;	 +2: RUNDII - PROGRAM RAN TO COMPLETION, FORK KILLED
;	     RUNDIR - PROGRAM STARTED,  A/ FORK HANDLE

RUNDIR:	TDZA T4,T4		;NO WAIT FLAG
RUNDII::SETOM T4		;WAIT FLAG
	STKVAR<EVEC,WFLAG,FKHNDL,FILJFN>
	MOVEM C,EVEC		;SAVE OFFSET IN ENTRY VECTOR
	MOVEM T4,WFLAG		;SAVE WAIT FLAG
	GTJFN
	 RET			;FAILED
	MOVEM T1,FILJFN		;SAVE JFN
	MOVX T1,CR%CAP		;XMIT CAPABILITIES
	CFORK			;CREATE A FORK FOR CHECKD
	 JRST [	EXCH T1,FILJFN	;SAVE ERROR CODE. GET JFN
		RLJFN		;RELEASE IT
		 NOP
		MOVE T1,FILJFN	;GET BACK ERROR CODE
		RET]		;AND DONE
	MOVEM T1,FKHNDL		;SAVE FORK HANDLE
	PUSH P,CAPENB		;SAVE ENABLED CAPABILITIES
	HLLOS CAPENB		;MAKE THIS A WHEEL
	MOVE T2,JOBBIT		;SET TO SAME AS OURS
	SPRIW			;BY SETTING PRIORITY WORD
	ERJMP .+1		;JUST IN CASE
	POP P,CAPENB		;RESTORE CAPABILITIES
	HRL T1,FKHNDL		;FORK HANDLE TO LH
	HRR T1,FILJFN		;JFN TO RH
	GET
	 ERJMP [MOVE T1,FKHNDL	;GET FORK HANDLE
		KFORK		;KILL THE FORK
		RET]		;AND DONE
	MOVE T1,FKHNDL		;GET FORK HANDLE
	MOVE 2,EVEC		;2/OFFSET IN ENTRY VECTOR
	SFRKV			;START AT MAIN ENTRY
	 ERJMP [MOVE T1,FKHNDL	;GET HANDLE
		KFORK		;KILL FORK
		RET]
	SKIPN WFLAG		;WANT TO WAIT?
	RETSKP			;NO. RETURN NOW
	WFORK
	KFORK
	RETSKP			;ALL DONE
;ROUTINE TO MAKE RESTART ENTRY IN SYSERR FILE

LOGSST:	TRVAR <<RDDBFR,.RLBSZ>>
	SAVEQ
	JE SF%MST,FACTSW,LOGSS1	;JUMP IF AUTO RESTART
LOGSS2:	TMSG <Why reload? >	;MANUAL RESTART, FIND OUT WHY
	HRROI T1,RDDBFR
	MOVX T2,RD%BRK+RD%BEL+RD%CRF+20*5
	MOVEI T3,0
	RDTTY			;GET ANSWER
	 JFCL
	LDB T3,[POINT 7,RDDBFR,6] ;GET FIRST CHAR OF ANSWER
	CAIN T3,"?"		;HELP WANTED?
	JRST [	HRROI T1,LOGSMG	;YES, TYPE MESSAGE
		PSOUT
		JRST LOGSS2]	;TRY AGAIN
	CAIN T3,.CHLFD		;NULL ANSWER?
	JRST [	HRROI T1,[ASCIZ/? Null answer is not allowed!
/]
		PSOUT
		JRST LOGSS2]
	SETZ T3,		;FLUSH TERMINATOR (PRESUMABLY NL)
	DPB T3,T1
LOGSS1:	MOVX T1,RL%LEN
	MOVX T2,RL%SIZ
	CALL ALCSEB		;GET SYSERR STORAGE
	 JRST [BUG(SYSERF)
		RET]
	MOVEM T1,Q1
	MOVE T2,[-NWHYIT,,WHYIT]
	CALL SEBCPY		;COPY DATA INTO BLOCK
	 JFCL
	MOVE T2,[-1,,[SEBPTR RL%OPR,SBTSTR,RDDBFR]]
	MOVE T3,FACTSW
	TXNN T3,SF%MST		;USE OPR ANSWER IF MANUAL START
	MOVE T2,[-1,,[SEBPTR RL%HLT,SBTWD,BUGHLT]]
	MOVE T1,Q1		;USE BUGHLT ADDRESS OTHERWISE
	CALL SEBCPY
	 JFCL
	MOVE T1,Q1
	CALL QUESEB		;QUEUE BLOCK FOR SYSERR FILE
	RET

LOGSMG:	ASCIZ \One of the following:
  SA - Machine was being used for standalone
  PM - Machine was down for preventive maintenance
  CM - Machine was down for corrective maintenance
  CR - Crash
or any one-line statement of the reason for this reload.
\

;POINTER TABLE TO BUILD RELOAD ENTRY

WHYIT:	SEBPTR 0,SBTEVC,SEC%RL	;EVENT CODE (IMMEDIATE)
	SEBPTR RL%SVN,SBTSTR,SVN ;SYSTEM NAME
	SEBPTR RL%STD,SBTWD,SYSTAD ;BUILD TAD
	SEBPTR RL%VER,SBTWD,[EXP SVNM] ;SYSTEM VERSION NUMBER
	SEBPTR RL%SER,SBTWD,APRSER ;APR SERIAL NUMBER
NWHYIT==.-WHYIT
;LOCAL ROUTINE TO READ TAD FROM CTY
;	CALL RDDTAD
; RETURN +1 ALWAYS, 2/ TAD

RDDGTD:	STKVAR <<RDDBFR,20>>
RDDGT1:	HRROI 1,RDDBFR
	MOVE 2,[RD%BRK+RD%BEL+RD%RAI+20*5]
	MOVEI 3,0
	RDTTY			;READ LINE FROM CTY
	 JRST RDDGT2		;FAILED, REPROMPT
	TXNN 2,RD%BTM		;BREAK CHAR TERMINATED INPUT?
	JRST RDDGT2		;NO, GARBAGE INPUT
	HRROI 1,RDDBFR
	MOVEI 2,0
	IDTIM			;CONVERT STRING TO TAD
	 JRST RDDGT2		;INVALID, REPROMPT
	RET			;OK, RETURN IT

RDDGT2:	TMSG <
? Invalid, please try again in form MMM-DD-YY HHMM: >
	JRST RDDGT1		;TRY AGAIN

;EACH SPECIAL JOB CALLS THIS TO DETACH AND START THE NEXT ONE

DONSJ:	CALL LOGONM		;RECORD START OF CURRENT JOB ON LOGGING TERMINAL
	MOVE 4,CTRLTT		;SAVE THIS JOB'S CONTROLLING TERMINAL
	DTACH			;DETACH THE CURRENT JOB
	MOVE 1,JB0TT
	HRRM 1,PRIMRY		;USE JOB 0 TTY FOR ANY OUTPUT
	MOVE 1,JOBNO		;GET CURRENT JOB NUMBER
	CAIL 1,NSPECJ-1		;MORE SPECIAL JOBS TO DO?
	JRST [	MOVX T1,SF%PTY!SF%CTY ;NO. ALLOW CTY AND PTY LOGINS
		IORM T1,FACTSW
		RET]		; AND DON'T CREATE ANOTHER JOB
	MOVE 2,4		;YES. GET LINE NUMBER FOR CALL
	CALLRET SPCSTJ		;START ANOTHER JOB ON SAME TTY

SPCSTJ:	NOSKED
	PUSH P,T2		;SAVE LINE NUMBER
	CALL STADYN		;GET ADDRESS OF DYNAMIC DATA
	 SKIPA			;NOT FULLY ACTIVE
	JRST [	POP P,2
		OKSKED
		RET]
	JUMPG T2,SPCST1		;IF TEMPORARILY ACTIVE, WAIT
	POP P,2			;GET LINE NUMBER BACK
	SETOM TTACTL(T2)	;INDICATE JOB STARTING
	MOVEI 1,JOBSRT		;REQUEST JOB STARTUP FROM SCHED
	HRL 1,2
	CALL SCDRQ7
	OKSKED
	RET

;LINE IS TEMPORARILY IN USE. WAIT UNTIL IT'S AVAILABLE

SPCST1:	POP P,1			;RESTORE LINE NUMBER
	OKSKED
	HRLZS T1		;T1/ (LINE NUMBER,,ROUTINE)
	HRRI T1,TSACT1		;ROUTINE TO WAIT FOR LINE
	PUSH P,T2
	MOVSI T2,FHV1		;LOW BLOCK PRIORITY
	HDISMS
	POP P,T2
	JRST SPCSTJ
;GET SWAPPABLE MONITOR

	RESCD

;BOOT DEVICE TABLE--DISPATCH ON CONTENTS OF BOOTFL TO SELECT DEVICE

BOOTD:	PHASE 0
	JRST GSMDSK		;0 - DSK (VBOOT)
	REPEAT 2,<JRST GSMDSK>	;EVERYTHING IS DISK
IRBOOT::!JRST GSMIRB		;INTERNAL REBOOT
	DEPHASE
NBOOTD==.-BOOTD

GETSWM::
	SETZM SWPMWF		; INITIALIZE SWAPPABLE MON WRITERS FLAG
	SETOM SWPMLF		; INIT COUNT OF LOCKERS OF SWP MON
	SKIPN EDDTF		;KEEP EDDT?
	CALL ULKINI		;NO, UNLOCK IT
	NOSKED
	MOVE 1,BOOTFL		;GET DEVICE SELECTOR
	CAIL 1,NBOOTD		;LEGAL?
	BUG(ILBOOT)
	JRST BOOTD(1)		;GO TO SELECTED BOOTSTRAP

;COMMON EXIT POINT FOR ALL DEVICES

LOKSM3:	SETZ T1,
	MOVEI T2,HOMPGA
	CALL SETMPG		;CLEAR BOOT PAGE
	MOVE T1,DBUGSW		;WRITE PROTECT?
	CAIE T1,2		;?
	CALL SWPMWP		;YES - IF NOT DEBUGGING
	OKSKED
	SKIPE SMLKF		;KEEP SWPMON LOCKED?
	CALL SWPMLK		;YES, RE-LOCK IT
	RET

RS(SWPMBP,1)			;STORAGE FOR SWPMON BOUND PAIR
RS(BOOTST,^D20)			;STORAGE FOR VBOOT COMMAND
;INTERNAL REBOOT - ASSUMES SWAP MON MAP FROM PREVIOUS RUN IS
;SAVED IN LOW CORE

GSMIRB:	CALL RESSMM		;RESTORE MON MAP
	JRST LOKSM3		;DONE

;THE DECTAPE BOOTSTRAP
;HERE TO BOOTSTRAP THE SWAPABLE MONITOR FROM DISK

GSMDSK:	HRRZ T1,BUTPGS		;GET END PAGE OF VBOOT AREA
	HLRZ T2,BUTPGS		;GET START PAGE OF VBOOT AREA
	SUB T1,T2		;COMPUTE # OF PAGES IN VBOOT AREA
	SUBI T1,1		;TWO LESS SINCE WE DON'T LOCK BOOT'S EPT/MMAP
	LSH T1,-PGSFT		;GET PAGES
	MOVE T2,TOTRC		;GET TOTAL FREE
	SUB T2,T1		;COMPUTE FREE PAGES AFTER VBOOT
	SUB T2,SUMNR		;DISCOUNT FORK OVERHEAD PAGES
	SKIPG P1,T2		;SAVE IN P1
	BUG(BOOTCR)
	LSH P1,PGSFT		;CONVERT TO WORDS

; MAP BOOTSTRAP PAGES

	HRRZ P2,BUTPHY		;GET CORE ADDRESS OF FIRST PAGE
	LSH P2,-^D9		;CONVERT TO CORE PAGE #
	HLL P2,BUTPHY		;GET - # OF PAGES TO MAP
	MOVE P3,BUTVIR		;GET FIRST VIRTUAL ADR TO MAP
GSMD1:	HRRZ T1,P2		;GET PAGE # TO MAP
	MOVE T2,P3		;GET VIRTUAL ADDRESS
	CALL MAPPHA		;GO MAP A PHYSICAL PAGE
	 BUG(BOOTMP)
	ADDI P3,PGSIZ		;NEXT VIRTUAL ADDRESS
	AOBJN P2,GSMD1		;MAP REMAINING PAGES

	HRL T1,MMSPTN		;GET SPTN OF MONITOR MAP
	HRRI T1,KIEPT/PGSIZ	;FORM I.D. OF EPT
	HLRZ T2,BUTEPT		;GET VIRTUAL ADDRESS OF BOOT'S EPT
	TXO T2,PTRW		;ACCESS BITS
	CALL SETMPG		;GET INDIRECT POINTER TO EPT
	MOVEI T1,MMAP		;BUILD POINTER FOR VBOOT TO PAGE TABLE
	LSH T1,-PGSFT		; ...
	HRL T1,MMSPTN		; ...
	HRRZ T2,BUTEPT		;GET ADDRESS OF VBOOT PAGE TABLE PAGE
	TXO T2,PTRW		;TURN ON ACCESS BITS
	CALL SETMPG		;SET MAP

	HLLZ T1,BUTPGS		;GET STARTING ADDRESS FOR VBOOT
	HLR T1,BUTEPT		;GET ADDRESS OF VBOOT MMAP PAGE
	SUBI T1,1		;WANT LAST PAGE BELOW MMAP LOCKED
	CALL CGPLK		;CREATE A GROUP OF PAGES AND LOCK
GSMLER:	 BUG(BOOTLK)
	HRRZ T1,BUTEPT		;GET ADDRESS OF VBOOT EPT PAGE
	HRLZI T1,PGSIZ(T1)	;GET FIRST ADDRESS TO LOCK ABOVE EPT
	HRR T1,BUTPGS		;GET ADDRESS OF LAST PAGE TO LOCK
	CALL CGPLK		;CREATE AND LOCK
	 JRST GSMLER
	MOVEM T1,BOOTST		;SAVE PHYSICAL ADDR OF VBEND

	;..
;HERE TO LOAD THE SWAPABALE MONITOR. IT IS READ IN SECTIONS
;AS LARGE AS THE AMOUNT OF FREE CORE AFTER THE BOOTSTRAP.

	MOVEI P2,NRCOD-1000	;INITIALIZE SWPMON LOAD LOOP
GSMD2:	MOVEI T1,1000(P2)	;FIRST PAGE IN CURRENT GROUP
	ADDI T1,-1000(P1)	;COMPUTE LAST LOADABLE PAGE
	LSH T1,-PGSFT		;AS A PAGE #
	CAMLE T1,SWCEND		;UNDER END OF SWPMON?
	MOVE T1,SWCEND		;NO USE END INSTEAD
	LSH T1,PGSFT		;CONVERT BACK TO ADDR
	HRLI T1,1000(P2)	;NEW FROM PAGE
	MOVE P2,T1		;SAVE BOUND PAIR
	CALL CGPLK		;CREATE AND LOCK
	 JRST GSMLER		; LOCK FAILURE

	MOVE P3,[POINT 7,BOOTST] ;BUILD VBOOT COMMAND STRING
	MOVE T1,[POINT 7,BUTCMD]	;POINTER TO FILE SPEC
	CALL BSCPY		;COPY TO OUTPUT STRING
	MOVE T1,[POINT 7,[ASCIZ '/L(']] ;LOAD ONLY
	CALL BSCPY
	HLRZ T1,P2		;LOWER BOUND
	LSH T1,-PGSFT		;AS A PAGE NUMBER
	CALL BSOCT		;CONVERT TO STRING
	MOVEI T1,","
	IDPB T1,P3
	HRRZ T1,P2		;UPPER BOUND
	LSH T1,-PGSFT		;AS A PAGE NUMBER
	CALL BSOCT		; ...
	MOVE T1,[POINT 7,[ASCIZ /)
/]]
	CALL BSCPY		;END OF COMMAND
	;...
;WE ARE NOW READY TO LOAD A SECTION OF THE SWAPABLE MONITOR.
;CALL VBOOT TO DO THE IO.

	PUSH P,P1		;SAVE FREE CORE
	PUSH P,P2		;SAVE BOUND PAIR
	HLRZ T1,BUTEPT		;GET ADDRESS OF VBOOT EPT PAGE
	SETMM (T1)		;INSURE EPT UPDATED
	CALL PHYIOW		;WAIT FOR ALL IO TO FINISH
	PIOFF			;DISABLE INTERRUPT SYSTEM
	MOVEM P,FPC		;SAVE STACK POINTER
	MOVE T1,[POINT 7,BOOTST] ;GET POINTER TO COMMAND STRING
	HRRZ T2,BUTPGS		;GET ADDRESS OF LAST PAGE IN VBOOT AREA
VBCALL::JSP 16,777(T2)		;GO LOAD SOME MONITOR
				; CALL BOOT AT LAST INSTRUCTION ON
				; LAST PAGE WHICH IS A JRST TO VBOOT
	 BUG(BOOTER)
	MOVE P,FPC		;RECOVER STACK
	XCT SETPPI		;RESTORE APR PI ASSMT
	PION

	POP P,P2		;RESTORE BOUND PAIR
	POP P,P1		;RESTORE FREE CORE
	MOVE T1,P2		;UNLOCK SWPMON PAGES
	CALL GPULK		;...
	HRRZ T1,P2		;ARE WE DONE?
	LSH T1,-PGSFT		;...
	CAME T1,SWCEND		;...
	JRST GSMD2		;NO - ANOTHER CYCLE
	CALL GSMDX		;RESET VBOOT AREA
	JRST LOKSM3		;YES - ADJUST SWPMON

;SUBROUTINE TO RELEASE VBOOT AREA

GSMDX:	HLLZ T1,BUTPGS		;GET START ADDRESS OF VBOOT AREA
	HLRZ T2,BUTEPT		;GET ADDRESS OF VBOOT EPT PAGE
	HRRI T1,-PGSIZ(T2)	;GET LAST ADDRESS TO UNLOCK
	CALL GPULK		;...
	HRRZ T2,BUTEPT		;GET ADDRESS OF VBOOT EPT PAGE
	HRLZI T1,PGSIZ(T2)	;GET FIRST ADDRESS TO UNLOCK
	HRR T1,BUTPGS		;GET LAST ADDRESS TO UNLOCK
	CALL GPULK		;...
	HLRZ P1,BUTPGS		;GET START ADDRESS OF VBOOT PAGES
	HRRZ P2,BUTPGS		;GET ENDING ADDRESS OF VBOOT PAGES
GSMD3:	HRRZ T2,P1		;GET ADDRESS
	SETZ T1,		;DESTROY PAGE
	CALL SETMPG		; ...
	ADDI P1,1000		;NEXT PAGE
	CAMG P1,P2		;DONE ?
	JRST GSMD3		;NO - LOOP
	RET			;DONE
;SUBROUTINES FOR BOOTSTRAP MANIPULATION

;SUBROUTINE TO COPY FROM BP IN T1 TO BP IN P3

BSCPY:	ILDB T2,T1		;GET A CHAR
	JUMPE T2,R		;DONE?
	IDPB T2,P3		;NO - COPY CHAR
	JRST BSCPY		;LOOP

;SUBROUTINE TO OUTPUT T1 TO BP IN P3 AS A DECIMAL NUMBER

BSDEC:	MOVEI T3,^D10		;DECIMAL
	CALL BSRAD		;CONVERT
	RET

;SUBROUTINE TO OUTPUT T1 TO BP IN P3 AS AN OCTAL NUMBER

BSOCT:	MOVEI T3,^D8		;OCTAL
	CALL BSRAD		;CONVERT
	RET

;COMMON/CONVENTIONAL PDP10 UNSIGNED RADIX PRINT

BSRAD:	IDIV T1,T3		;GET Q & R
	MOVEI T2,"0"(T2)	;CONVERT TO ASCII
	HRLM T2,(P)		;SAVE
	SKIPE T1		;DONE?
	CALL BSRAD		;NO - RECURSE
	HLR T2,(P)		;GET CHAR
	IDPB T2,P3		;OUTPT
	RET
;'MINI-EXEC' - SIMPLE COMMAND INTERPRETER FOR SPECIAL FUNCTIONS

	SWAPCD
EXEC2:	MOVEI 1,100		;ESTABLISH CORRECT TTY MODES
	MOVE 2,NORMTF
	SFMOD
	MOVE 2,TTICB1
	MOVE 3,TTICB2
	SFCOC
	CALL DTIALL		;DISABLE ALL TERMINAL INTERRUPTS
	MOVE 1,[XWD 20,^D34]	;T1/ CTRL/P ON CHANNEL 34
	ATI			;ASSIGN CONTROL-P FOR INTERRUPTS
	MOVE 1,[ITFFL,,EXECI]	;SETUP TO GET INTERRUPTS IN MON
	MOVEM 1,MONBK
	MOVEI 1,.FHSLF		;T1/ THIS FORK
	MOVEI 2,MICHN		;T2/ CHANNELS TO ACTIVATE (34 AND 35)
	MOVEM 2,MONCHN		;SAVE THE CHANNELS
	AIC			;ACTIVATE THEM
	MOVE 2,JOBNO
	HRRZ 1,JOBDIR(2)
	JUMPE 1,[SETZM CAPMSK	;IF NOT LOGGED, FLUSH ALL CAPS
		SETZM CAPENB
		MOVE 3,CTRLTT
		CAME 3,CTYLNO	;ALLOW MINI-EXEC ONLY ON CTY
		JRST .+1
		HRLOI 3,777000	;GIVE ALL CAPS
		MOVEM 3,CAPMSK
		MOVEM 3,CAPENB
		MOVEI 3,OPERDN	;YES, GET DIRECTORY NUMBER OF <OPERATOR>
		MOVEM 3,JOBDIR(2) ;INDICATE LOGGED IN AS <OPERATOR>
		STOR 3,JSDIR	;SAVE AS CONNECTED DIRECTORY
		SETZRO JSCDF	;NO STRING IN JSB
		MOVE 3,STRTAB+PSNUM ;GET SDB ADDRESS OF STRUCTURE 0 (PUBLIC)
		LOAD 3,STRUC,(3) ;GET ITS UNIQUE STRUCTURE CODE
		STOR 3,JSUC	;SAVE AS CONNECTED STRUCTURE CODE
		MOVE 3,[[3
			 ASCIZ "OPERATOR"],,USRNAM]
		BLT 3,USRNAM+2	;SET DEFAULT USER NAME TO OPERATOR
		JRST .+1]
	JN JBMX,,EXECT0		;IF BEEN IN MX BEFORE, DONT CHECK CAPS
	MOVE 1,CAPENB		;LOOK AT CAPS, ALLOW MINI-EXEC
	TRNN 1,SC%WHL		;ONLY IFWHEEL
	JRST [	SKIPE FORKN	;OTHERWISE,
		HALTF		;HALTF IF BELOW EXEC
		SETONE JSFLO	;REMEMBER THE FORCED LOGOUT
		JRST LOGO]	;LOGOUT IF TOP FORK
	SETONE JBMX		;REMEMBER THAT JOB WAS IN MINI-EXEC
	; ..
;MINI-EXEC...

EXECT0:	HRROI 1,[ASCIZ /MX>/]
	PSOUT			;DO PROMPT
EXECT1:	PBIN			;GET USER INPUT
	CAIN T1,.CHCRT		;FLUSH CR
	JRST EXECT1
	CAIL 1,"A"+40		;LC CHAR?
	CAILE 1,"Z"+40
	SKIPA			;NO
	SUBI 1,40		;YES, CONVERT
	CAIN T1,.CHLFD		;IGNORE BLANK LINE
	JRST EXECT0
	MOVSI 4,-NXCMD		;SCAN COMMAND TABLE
EXECT2:	HLRZ 2,XCMD(4)		;GET KEY LETTER FOR THIS COMMAND
	CAMN 1,2		;SAME AS JUST TYPED?
	JRST [	HRRZ 2,XCMD(4)	;YES, GET DISPATCH ADDRESS
		JRST 0(2)]	;GO TO IT
	AOBJN 4,EXECT2		;TRY ALL COMMANDS
	JRST EXERR		;NOT FOUND, INDICATE ERROR

;MINI-EXEC COMMANDS

DEFINE CM (NAM,LOC)<
	XWD "NAM",LOC>

XCMD:	CM B,EBLT		;BLT SWP MON
	CM D,EDMP		;DUMP ON FILE
	CM E,GEX		;EXEC
	CM G,EGET		;GET FILE
	CM J,EJMP		;JUMP TO ADDRESS
	CM R,EREST		;RESET
	CM S,EST		;START
	CM <^>,MRETN		;DO MRETN
	CM </>,TODDT		;GO TO MDDT
NXCMD==.-XCMD
;'/' - ENTER MDDT

TODDT:	SE1ENT
	GTOKM (.GOMDD,)		;ASK FOR PRIVS
	JRST MDDTX		;GO TO DDT


;'BLT SWP MON' - BLT SWAPPABLE CODE TO USER SPACE.  SHOULD DO RESET FIRST,
;THEN DUMP ON DTA--

EBLT:	TMSG <LT SWP MON>
	CALL OKGO
	MOVE 2,SWCEND		;LST PAGE
	LSH 2,^D9
	MOVE T1,[NRCOD,,NRCOD]
	XBLTMU [BLT 1,777(2)]
	JRST EXEC2
;'RESET'

EREST:	TMSG <ESET>
	CALL OKGO
	MOVEI 1,-4
	KFORK			;KILL ALL FORKS
	MOVNI 1,1
	MOVSI 2,400000
	MOVE 3,[1B0+1000]	;CLEAR ALL PAGES FROM USER MAP
	PMAP
	MOVNI 1,1		;CLOSE ALL FILES
	CLOSF
	JFCL
	JRST EXEC2

;OKGO - ROUTINE TO LOOK FOR CONFIRMATION AFTER MINI-EXEC HAS 
;TYPED THE COMPLETION OF THE COMMAND. 

;	CALL OKGO

;RETURNS +1: CONFIRMATION FOUND
;IF NO CONFIRMATION WAS FOUND, GOES TO ERROR ROUTINE

OKGO:	PBIN
	CAIN T1,.CHCRT		;FLUSH CR
	JRST OKGO
	CAIN T1,.CHLFD		;CRLF MEANS GO
	RET
NODD1:	POP P,1			;ANYTHING ELSE MEANS ABORT
	JRST EXERR

;'EXEC'

GEX:	TMSG <XEC>
	CALL OKGO		;CONFIRM

;HERE TO GET A NEW COPY OF THE EXEC. REACHED FROM MINI-EXEC 'EXEC'
;COMMAND OR WHEN A NEW JOB IS BEING CREATED.  IF FILE EXISTS,
;GOES TO START IT. IF NOT, PRINTS MESSAGE AND GOES TO MINI-EXEC

STEX:	MOVSI 1,(GJ%OLD!GJ%PHY!GJ%SHT)	;OLD FILE+SHORT FORM
	HRROI 2,[ASCIZ /SYSTEM:EXEC.EXE/]
	GTJFN
STEXF:	JRST [	SKIPE CRJFLG	;IS THIS A CRJOB FAILURE?
		JRST CRJMEX	;YES. GO GIVE FAIL CODE
		HRROI T1,[ASCIZ /NO EXEC/]
		PSOUT
		JRST EXCRR]
	HRLI 1,.FHSLF
	GET
	ERJMP STEXF		;CATCH FAILURE OF GET
	SKIPN CRJFLG		;CREATED JOB?
	JRST GEX1
	HRLI T2,1		;INDICATE JOB HAS ALREADY SET CRJANS
	HLLM T2,CRJFLG		; BY MAKING FLAG POSITIVE
	JRST GEX1

CRJMEX:	MOVEI T1,CRJBX2		;PREVENT CRJOB GETTING INTO MINIEXEC
	SKIPGE CRJFLG		;JOB STILL BEING CREATED
	MOVEM T1,CRJANS		;YES.  GIVE FAIL CODE TO CREATOR,
	JRST LOGO		;AND FLUSH OUT THIS JOB.
;'JUMP TO ADDRESS' - JUMP TO USER ADDRESS

EJMP:	TMSG <UMP TO >
	MOVEI 1,100
	MOVEI 3,^D8		;GET OCTAL ADDRESS
	NIN
	 JRST EXERR
	HRRZM 2,-1(P)		;SAVE ADDRESS
	BKJFN			;BACKUP TO READ TERMINATOR
	 JFCL
	CALL OKGO
	JRST MRETN		;RETURN TO USER ADDRESS ON STACK
;'GET FILE'

EGET:	TMSG <ET FILE >
	MOVSI 1,(1B2+1B4+1B16+1B17) ;OLD FILE,CONFIRM,IFOF,SHORT
	MOVE 2,[XWD 100,101]
	GTJFN
	JRST EXERR
	HRLI 1,400000		;THIS FORK
	GET
	JRST EXEC2

;'START' - STARTS PROGRAM GOTTEN VIA 'GET'

EST:	TMSG <TART>
	CALL OKGO
GEX1:	HRRZ 1,ENTVEC
	JUMPN 1,.+2
	UMOVE 1,120		;USE JOBSA
	HRRZM 1,-1(P)
	JRST MRETN

;'DUMP ON FILE'

EDMP:	TMSG <UMP ON FILE >
	MOVSI 1,(1B0+1B3+1B4+3B17) ;NEW V,PNT O/N,CONFRM,IFOF,SHRT
	MOVE 2,[XWD 100,101]
	GTJFN
	JRST EXERR
	HRLI 1,400000		;THIS FORK
	MOVE 2,[XWD -1000,520000] ;SAVE ALL ADDRESS SPACE
	SETZ 3,
	SSAVE
	JRST EXEC2

;ERROR CONDITION - PRINT A QUESTION MARK AND GO BACK TO START OF
;MINI-EXEC

EXERR:	TMSG <  ?>
	MOVEI 1,100
	CFIBF			;CLEAR INPUT BUFFER

;PRINT CARRIAGE RETURN/LINE FEED

EXCRR:	SKIPE CRJFLG		;IS THIS A CRJOB?
	JRST CRJMEX		;YES. GET OUT OF MINIEXEC.
	TMSG <
>
	JRST EXEC2

EXCRRW:	TMSG <
>
	JRST EXEC2
;PSI TRAPPED TO HERE

EXECI::	EXCH 1,ITFFL		;SAVE 1, GET TRAP FL
	TLNN 1,(UMODF)		;USER?
	JRST EXECI1		;NO
	HLLZM 1,FFL		;SET FLAGS
	MOVE 1,ITFPC		;SET PC
	MOVEM 1,FPC		;YES, ENTER MONITOR AT THAT LOC
	MOVE 1,ITFFL		;RESTORE AC1
EXECI2:	MCENTR
	SETOM PRIMRY
	SKIPE CRJFLG		;IS THIS A CRJOB?
	JRST CRJMEX		;YES. GET OUT OF MINIEXEC.
	MOVEI 1,100
	CFIBF			;CLEAR INPUT BUFFER
	CALL CLRINT		;CLEAR THE SOFTWARE INTERRUPT SYSTEM
	TRNN 2,2		;CHANNEL 34?
	JRST EXECI3
	MOVEI 1,-4
	FFORK			;FREEZE FORKS
	MOVEI 1,101
	CFOBF			;CLEAR OUTPUT BUFFER
	TMSG <
ABORT
>
	JRST EXEC2

EXECI1:	MOVE P,UPP		;RESTORE TOP OF PDL
	MOVE 2,1(P)		;GET USER PC
	MOVEM 2,FPC		;STORE PC
	HRLI 1,(UMODF)
	MOVEM 1,FFL
	JRST EXECI2

EXECI3:	TMSG <
INTERRUPT AT >
	MOVEI 1,101
	HRRZ 2,UPP
	HRRZ 2,1(2)		;GET TOP PC
	MOVEI 3,10		;RADIX
	NOUT			;PRINT ADDRESS
	 JFCL
	JRST EXCRRW		;TO MINI-EXEC IF SC%WHL
;JSYS TO ENTER MDDT

.MDDT::	MCENT
	MOVEI 1,SC%WHL+SC%OPR
	TDNN 1,CAPENB
	JRST WHEELX		;NO PRIVS
	JRST TODDT

	RESCD

;HERE WHEN USER TYPES "EDDT$G" IN MDDT.  DON'T GO TO EDDT UNLESS IT
;IS LOADED AND LOCKED DOWN.  USERS WHO WANT TO ANYWAY CAN TYPE "DDTX$G".

EDDT=:<MSEC1,,.>		;START IN SECTION 1 ON EDDT$G FROM MDDT

	SKIPE DDTPRS		;IS EDDT PRESENT AND LOCKED?
	JRST DDTX		;YES, GO TO IT
	TMSG <
? EDDT is not locked down - call LCKINI from MDDT first
>
	JRST MDDTX		;RETURN TO MDDT


;BUGHLT IN JOB CONTEXT TRAPS TO HERE

EXBUGH::MOVE 1,UPDL		;RESET STACK, ETC.
	MOVEM 1,FPC		;SET PC
	MOVSI 1,(UMODF)
	MOVEM 1,FFL
	MCENTR
	SETOM TRAPC
	SETZM NSKED
	SETZM INTDF
	SKIPN JOBNO		;JOB 0?
	JRST CHKRI		;YES, INTERRUPT
	HRRZ 1,PRIMRY
	HRROI 2,[ASCIZ /
BUGHLT at /]
	SETZ 3,
	SOUT
	HRRZ 2,BUGHLT
	MOVEI 3,^D8
	NOUT
	JFCL
	TMSG <
>
	JRST ITRAP

	SWAPCD
;HALT SYSTEM - REQUIRES SC%MNT (OR SC%WHL ETC.) CAPABILITY
;ACCEPTS TIME OF SYSTEM SHUTDOWN AND INITIATES SHUTDOWN PROCESS,
;INCLUDING NOTIFYING USERS, ETC.  ALSO ACCEPTS TIME WHEN SYSTEM
;WILL BE BACK UP WHICH IS AVAILABLE FOR USER INFORMATION ONLY.
; 1/ SHUTDOWN TIME (GTAD FORMAT)
; 2/ EXPECTED UP TIME (GTAD FORMAT)
;	HSYS
; RETURNS +1: ERROR
; RETURNS +2: SUCCESS

.HSYS::	MCENT
	MOVE 2,CAPENB		;CHECK USER CAPABILITIES
	TXNN 2,SC%WHL+SC%OPR+SC%MNT ;USER ALLOWED TO DO HALT?
	RETERR(CAPX2)		;NO, RETURN BAD
	JUMPG 1,HSYS1		;JUMP UNLESS ABORTING SHUTDOWN
	MOVE T1,HSYST1		;GET OLD TIME
	JUMPE T1,HSYS0		;IF NONE, DONT TYPE MESSAGE
	SETZM HSYST1		;CLEAR OLD TIME
	CALL TADDIF		;GET MILLISECONDS TO SHUTDOWN
	HRROI T2,[ASCIZ/
[Shutdown canceled]
/]
	SKIPL HSYST3		;WAS A MESSAGE EVER PRINTED
	CALL ALLMSG		;YES, INFORM USERS OF CANCELLATION
HSYS0:	SMRETN			;SUCCESSFUL RETURN

HSYS1:	PUSH P,1		;HOLD THE DESIRED SHUTDOWN
	CALL TADDIF		;COMPUTE MILLISECONDS TO SHUTDOWN
	TLNE 1,770000		;OVER A WEEK AHEAD, OR NEGATIVE?
	RETERR(TIMEX2)		;YES, GIVE BAD TIME FAILURE
	POP P,2			;RECOVER SHUTDOWN TIME
	MOVEM 2,HSYST1		;STORE FOR EXEC TO SEE
	SETOM HSYST3		;FLAG FOR FIRST MESSAGE
	UMOVE 2,2		;GET EXPECTED UP TIME
	CAMG 2,HSYST1		;CHECK RANGE
	SETZ 2,			;JUNK, ASSUME UNKNOWN
	MOVEM 2,HSYST4		;SAVE FOR EXEC TO TELL USERS
	AOS JB0FLG		;POKE JOB 0 TO DO MSG
	SMRETN

;COMPUTE TIME UNTIL SHUTDOWN IN MILLISECONDS
; A/ TAD OF SHUTDOWN
;	CALL TADDIF
; RETURN +1, A/ MILLISECONDS TO SHUTDOWN

TADDIF:	PUSH P,1
	CALL LGTAD		;GET CURRENT TIME AND DATE
	POP P,2
	SUBM 2,1		;GET POSITIVE DIFFERENCE OF TIMES
	CAML T1,[^D8,,0]	;WITHIN 8 DAYS?
	JRST [	MOVSI T1,377777	;NO, RETURN VERY LARGE NUMBER
		RET]
	MUL T1,[^D<24*3600*1000>]	;MILLISECONDS/DAY
	DIV T1,[1B17]		;SHIFT BINARY POINT
	RET
;HSYST1 AND HSYST4 ARE A GETAB TABLE

NHSYST==2			;NUMBER OF VALUES IN GETAB TABLE
NR HSYST1,1			;SYSTEM SHUTDOWN TIME OR 0
NR HSYST4,1			;EXPECTED UP TIME

NR HSYST2,1			;INTERVAL (IN MS) TO NEXT MSG TIME
NR HSYST3,1			;TIME OF NXT MSG IN MS BEFORE SHUTDOWN

;POINTS (IN MINUTES BEFORE SHUTDOWN) AT WHICH TO DO NOTIFICATION

CTIMS:	^D<BYTE (9) 60,30,15,10>
	^D<BYTE (9) 5,1,0>
;ROUTINE TO TYPE SYSTEM SHUTDOWN MESSAGE IF NECESSARY.
;CALLED ONLY BY JOB 0 CHKR.

CHKHSY:	SKIPN A,HSYST1		;SHUTDOWN ABORTED?
	RET			;YES
	CALL TADDIF		;COMPUTE TIME UNTIL SHUTDOWN
	MOVE 3,HSYST3		;DUE TIME FOR MESSAGE
	CAMN 3,[-1]		;FIRST TIME HERE?
	JRST CHKHS3		;YES - GIVE MESSAGE ANYWAY
	CAMLE 1,HSYST3		;NO - MESSAGE DUE NOW?
	JRST [	SUB 1,HSYST3	;NO, COMPUTE INTERVAL TO NEXT MSG
		MOVEM 1,HSYST2	;LEAVE IT FOR CHKR
		RET]		;RETURN QUIETLY
CHKHS3:	ADDI 1,^D30000		;ROUND TO NEAREST MINUTE
	IDIVI 1,^D60000		;CONVERT TO INTEGER MINUTES
	JUMPLE 1,CHKHS4		;IF NO TIME LEFT, GO KILL SYSTEM
	CALL THSYS		;SEND MSG TO ALL TTYS
	CAILE 1,^D60		;LESS THAN AN HOUR?
	JRST [	MOVEI 2,^D60	;NO - SET NEXT MESSAGE FOR 1 HOUR NOW
		CAILE 1,^D120	;BETWEEN 1 AND 2 HOURS
		MOVEI 2,^D120	;MAKE FIRST NOTICE BE AT 1 HOUR
		JRST CHKHS5]
	MOVE 3,[POINT 9,CTIMS]	;SETUP TO FIND NEXT NOTIFY TIME
	ILDB 2,3		;GET A TIME FROM LIST
	CAMG 1,2		;SHORTER THAN ACTUAL TIME REMAINING?
	JRST .-2		;NO, KEEP LOOKING
CHKHS5:	IMULI 2,^D60000		;CONVERT MINUTES TO MILLISECONDS
	MOVEM 2,HSYST3		;SET AS NEXT MESSAGE TIME
	JRST CHKHSY		;FINAL CHECK AND RETURN

;SHUTDOWN TIME HAS ARRIVED, COMMENCE SHUTDOWN.

CHKHS4:	MOVX T1,SF%RMT!SF%LCL!SF%PTY
	ANDCAM T1,FACTSW	;ONLY ALLOW CTY TO LOGIN
	CALL DWNMSG		;SEND LAST MESSAGE
	SETZM HSYST1		;CLEAR FLAGS IN CASE RESTARTED
	MOVSI 1,(1B1)		;CREATE FORK WITH SAME CAPS
	CFORK
	 BUG(HSYFRK)
	MOVEI 2,HSYS4		;SET IT TO START NEXT SHUTDOWN PHASE
	MSFRK			;START FORK IN MONITOR MODE
	RET
;FORK STARTED AT SHUTDOWN TIME
;COMMENCE SHUTDOWN. PREVENT NEW JOBS, LOGOUT EXISTING JOBS, HALT.

HSYS4:	MOVSI 1,(UMODF)
	MOVEM 1,FFL		;ESTABLISH USUAL JSYS CONTEXT
	SETZM FPC		;SET PC
	MCENTR
	MOVX T1,SF%RMT!SF%LCL!SF%PTY
	ANDCAM T1,FACTSW	;ONLY ALLOW CTY TO LOGIN
	MOVE 6,[XWD -NJOBS+1,1]	;START WITH JOB 1
	SKIPGE JOBRT(6)		;LOOK FOR EXISTING JOB
HSYS41:	AOBJN 6,.-1
	JUMPGE 6,HSYS7		;JUMP IF DONE
	HLRZ 1,JOBPT(6)		;CHECK CTRLTT FOR JOB
	CAMN 1,CTYLNO		;CTY?
	JRST HSYS41		;YES, DON'T FLUSH
	MOVEI 1,0(6)		;GET JOB NUMBER
	LGOUT			;LOG IT OUT
	 JFCL
	JRST HSYS41

HSYS7:	MOVEI 5,^D120000	;MAX TIME TO WAIT FOR JOBS TO FINISH
	ADD 5,TODCLK		;LOGGING OUT
HSYS8:	CAMG 5,TODCLK		;WAITED MAX TIME?
	JRST HSYS9		;YES, PROCEED WITH SHUTDOWN
	MOVE T2,HSYST4		;GET TIME BACK UP
	MOVEI T1,0		;SHOULD BE CODE FOR REASON FOR HALT
	CALL IMPHLT		;TELL THE NETWORK WE ARE GOING AWAY
	MOVE 6,[XWD -NJOBS+1,1]	;START WITH JOB 1
	SKIPGE JOBRT(6)		;SEE IF ANY JOBS STILL EXIST
HSYS81:	AOBJN 6,.-1
	JUMPGE 6,HSYS9		;NONE FOUND, PROCEED
	HLRZ 1,JOBPT(6)		;CHECK FOR CTY JOB
	CAMN 1,CTYLNO
	JRST HSYS81		;YES, IGNORE
	MOVEI 1,^D1000		;NO, WAIT 1 SEC., THEN CHECK AGAIN
	DISMS
	JRST HSYS8

HSYS9:	SETZM DDTIME		;POKE DDMP
	AOS JB0FLG
	MOVEI 5,^D10		;WAIT 10 SEC MAX FOR JOB 0
HSYS91:	MOVEI 1,^D1000		;WAIT 1 SEC
	DISMS
	SKIPN DDTIME		;DDMP FINISHED?
	SOJG 5,HSYS91		;NO, WAIT MORE
	JUMPLE 5,HSYS9		;IF TIMED OUT, TRY AGAIN
	SKIPE IOIP		;WRITES IN PROGRESS?
	JRST .-1		;YES, WAIT FOR COMPLETION
	MOVE T1,CTYLNO
	TXO T1,.TTDES		;MAKE VALID DESIGNATOR
	HRROI T2,[ASCIZ /
Shutdown complete
/]
	TTMSG			;NOTIFY OPERATOR
	MOVEI T1,^D15000
	DISMS
	HALTF
;ROUTINE TO SEND GOING DOWN MESSAGE TO ALL LINES

THSYS:	STKVAR <TIM,<MSG,20>>
	MOVEM T1,TIM		;SAVE NUMBER OF MINUTES
	HRROI T1,MSG		;INIT PTR TO MSG
	HRROI T2,[ASCIZ /
[System going down/]
	SETZ T3,
	SOUT
	MOVE T2,TIM		;GET TIME
	CAILE T2,^D60		;LESS THAN ONE HOUR?
	JRST THSYS1		;NO - SPECIAL MESSAGE
	HRROI T2,[ASCIZ / in /]
	SETZ T3,
	SOUT
	MOVE T2,TIM		;GET TIME
	CAIN T2,1		;THE 'ONE' CASE?
	JRST [	HRROI T2,[ASCIZ /one minute!!]
/]
		JRST HSYS51]	;YES, SPECIAL MESSAGE
	MOVEI T3,^D10
	NOUT
	 JFCL
	HRROI T2,[ASCIZ / minutes/]
	SETZ T3,
	SOUT			;APPEND TO MESSAGE
THSYS1:	HRROI T2,[ASCIZ / at /]
	SETZ T3,0
	SOUT
	MOVE T2,HSYST1		;TELL ACTUAL TIME
	MOVEI T3,0
	ODTIM			;IN MESSAGE
	HRROI T2,[ASCIZ /]
/]
HSYS51:	SETZ T3,
	SOUT
	HRROI T2,MSG		;POINT TO CONSTRUCTED MSG
	CALL ALLMSG		;SEND TO ALL LINES
	MOVE T1,TIM		;RESTORE TIME
	RET

;ROUTINE TO SEND LAST MESSAGE, INCLUDING EXPECTED UPTIME.

DWNMSG:	STKVAR <<MSG,20>>
	HRROI T1,MSG
	HRROI T2,[ASCIZ /
[System down/]
	SETZ T3,
	SOUT
	SKIPN HSYST4		;HAVE AN UPTIME?
	JRST DWNMS1		;NO
	HRROI T2,[ASCIZ /, up again at /]
	SOUT
	MOVE T2,HSYST4		;GET UPTIME
	MOVEI T3,0		;STANDARD FORMAT
	ODTIM			;CONVERT TIME TO TEXT
DWNMS1:	HRROI T2,[ASCIZ /]
/]
	SETZ T3,
	SOUT
	HRROI T2,MSG		;HAVE TEXT, NOW SEND IT TO ALL LINES
	CALL ALLMSG
	RET
;PERIODIC (10 SEC) CHECK OF THINGS

CHKR::	SETZM JB0FLG		;CLEAR REQUEST FLAG
	MOVE 1,TODCLK
	ADD T1,CHKPER		;NOW PLUS MAX CHECK PERIOD
	MOVEM 1,CHKTIM		;LEAVE FOR SCHED TO CHECK
	CALL RESLCK		;LOCK OR UNLOCK RESIDENT FREE SPACE
	CALL DTEPOL		;GO SEE IF ANY DTE'S NEED ATTENTION
	SKIPL DRMJ0R		;DRUM JOB 0 REQUEST?
	CALL CHKDRM		;YES
	MOVE 1,DSKRCE		;DISK RECOVERABLE ERRORS
	CAME 1,CHKDRE		;DIFFERENT THAN LAST CHECK?
	CALL CHKDE1		;YES, GO PRINT INFO
	MOVE 1,DSKNRE		;DISK NON-REC ERRORS
	CAME 1,CHKDNE		;DIFFERENT?
	CALL CHKDSK		;PRINT INFO
	SKIPE MTAJB0		;MTA ON LINE INTERRUPT?
	CALL MTASSP		;YES REQUEST SETSPD
	SKIPE USGBEG		;CHECK USAGE QUEUE
	CALL USGMES		;HAVE SOMETHING - EMPTY QUEUE
	CALL CHKCKP		;CHECK ON CHECKPOINT
	CALL CHKASC		;Check for accounting shift change
	CALL DDMP0		;DISK BACKUP
	CALL CHKBGS		;CHECK IF TIME TO STORE ASCII TIME
	SKIPE HSYST1		;SHUTDOWN PROCESS ACTIVE?
	CALL CHKHSY		;YES, CHECK IT
	MOVE A,TODCLK
	CAMGE A,UMSGTM		;TIME FOR USER MESSAGES?
	JRST CHKUM1		;NO
	CALL CHKDKS		;CHECK DISK SPACE
	CALL CHKDMS		;CHECK DRUM SPACE
	CALL CHKSPT		;CHECK SPT SPACE
	MOVE A,TODCLK		;SET TIME FOR NEXT MSG
	ADD A,[^D<5*60000>]	;IN 5 MINUTES
	MOVEM A,UMSGTM
CHKUM1:	CALL CHKNET		;CHECK STATE OF ARPANET
	CALL CHKMOS		;CHECK IF MEMORY DIAG NEEDS TO RUN
	MOVEI 1,^D30000		;SETUP TO DISMISS FOR 30 SEC
	SKIPE HSYST1		;IS SHUTDOWN ACTIVE?
	JRST [	CAMLE 1,HSYST2	;YES, NXT MSG DUE WITHIN 30 SEC?
		MOVE 1,HSYST2	;YES, DISMISS UNTIL MSG DUE
		JRST .+1]
	CALL SETBKT		;SETUP TIME FOR DISMISS TEST
	HRRI 1,JB0TST		;OR JB0FLG
	MOVSI T2,FHV1		;LOW BLOCK PRIORITY
	HDISMS
	JRST CHKR

;MAXIMUM CHECK PERIOD - USED TO SET SCHEDULER ALARM

CHKPER:	^D<4*60000>		;4 MINUTES

	RESCD

JB0TST:	SKIPE JB0FLG		;EXPLICIT REQUEST?
	JRST 1(4)		;YES, WAKEUP
	JRST BLOCKT		;NO, GO TEST TIME

	SWAPCD

NR UMSGTM,1			;TIME OF NEXT USER MESSAGES
NR MOSFRK,1			;FORK I.D. OF MEM DIAG FORK
NR MTCHNG,1			;FLAG FOR MTA STATUS CHANGE
CHKH1:	CALL TTDECP		;OUTPUT DECIMAL
	MOVEI 2," "
	BOUT
CHKR1:	CALL LGTAD		;CURRENT TIME AND DATE
	JUMPL 1,CHKR2		;IF NOT SET
	MOVE 2,1
	MOVEI 1,101
	SETZ 3,
	ODTIM			;INCLUDE TAD WITH MESSAGE
CHKR2:	TMSG <
>
	RET

;INITIATE PAGE MOVEMENT TO DISK IF APPROPRIATE

DDMP0:	MOVE A,DRMFRE		;DRUM SPACE LOW?
	CAMGE A,DRMIN0
	JRST [	TMSG <DDMP: SWAP SPACE LOW ACTION.
>
		JRST DDMPA]
	MOVE A,TODCLK		;TIME FOR NEXT CYCLE?
	CAMGE A,DDTIME
	RET			;NO
DDMPA:	CALL DDMP		;DO THE WORK
	 RET			;DDMP FAILED. RUN IT AGAIN ASAP
	MOVX A,^D60000		;SET TIME FOR NEXT CYCLE AS 1 MINUTE
	ADD A,TODCLK		; FROM NOW.
	MOVEM A,DDTIME
	RET
; ROUTINE TO REQUEST SETSPD FOR MAGTAPE ON LINE

MTASSP:	SETZM MTAJB0		;CLEAR REQUEST FLAG
	MOVX T1,GJ%OLD!GJ%PHY!GJ%SHT
	HRROI T2,SETSPD		;GET POINTER TO "SYSTEM:X-SETSPD.EXE"
	MOVEI T3,4		;START AT ENTRY VECTOR POSITION 4
	CALL RUNDII		;RUN SETSPD AND WAIT UNTIL IT'S DONE
	 JFCL			;IGNORE FAILURE
	RET
;ROUTINE CALLED BY CHKR TO SEE IF ANY ACTION NEEDED FOR THE
;MOS MEMORY DIAGNOSTIC

CHKMOS:	SKIPN T1,MOSFRK		;NOW RUNNING?
	JRST CHKMO1		;NO. SEE IF WE SHOULD RUN IT
	RFSTS			;YES. SEE WHAT IT IS DOING
	LOAD T1,RF%STS,T1	;GET ITS STATUS
	CAIE T1,.RFHLT		;HALTED?
	CAIN T1,.RFFPT		;OR ERROR?
	SKIPA T1,MOSFRK		;YES.
	RET			;NO. ALL DONE THEN
	KFORK			;KILL THE PROCESS
	SETZM MOSFRK		;NO MORE FORK HERE

;HERE IF NO FORK NOW RUNNING. SEE IF ONE NEEDED

CHKMO1:	SKIPE ERRTBL		;HAVE SOME ENTRIES TO PROCESS
	CALL RUNMOS		;YES. START THE DIAG
	RET			;DONE

;ROUTINE TO RUN THE MOS MEM DIAGNOSTIC

RUNMOS:	TDZA T3,T3		;MAIN ENTRY POINT
RUNMO1:	MOVEI T3,1		;SYS START UP ENTRY
	MOVX T1,<GJ%OLD!GJ%SHT!GJ%PHY>
	HRROI T2,[ASCIZ /SYSTEM:TGHA.EXE/] ;THE DIAG
	CALL RUNDIR		;RUN TGHA
	 RET			;DIDN'T DO IT.
	MOVEM T1,MOSFRK		;SAVE FORK HANDLE FOR LATER
	RET			;AND DONE
;ROUTINE CALLED BY JOB 0 TO FINISH LOADING UP SYSERR BLOCK
;  FOR BUGHLT'S AND BUGCHK'S
;ACCEPTS IN T1/	ADDRESS OF SYSERR BLOCK
;RETURNS +1:	ALWAYS

LOGBUG::SAVEQ			;SAVE PERMANENT ACS
	TRVAR <BUGSP,BUGPNM,BUGTAD>
	MOVEM T1,Q1		;SAVE POINTER TO SYSERR BLOCK
	MOVEI T1,.PRIOU		;SEND MESSAGE TO CTY
	MOVE T4,SEBDAT+BG%FLG(Q1) ;GET TYPE OF BUG CHECK
	HRROI T2,[ASCIZ/
********************
*BUG/]
	SETZ T3,
	SOUT			;START MESSAGE
	HRROI T2,[ASCIZ/HLT "/]
	CAIN T4,BG%CHK		;BUGCHK?
	HRROI T2,[ASCIZ/CHK "/]	;YES
	CAIN T4,BG%INF		;INFORMATIONAL BUG CHECK?
	HRROI T2,[ASCIZ/INF "/]	;YES
	SOUT
	MOVE T4,[POINT 6,SEBDAT+BG%NAM(Q1)]
LOGBF1:	ILDB T2,T4		;NOW TYPE OUT 6 CHAR NAME
	JUMPE T2,LOGBF2		;IF AT END, STOP TYPING
	ADDI T2," "		;TRANSLATE SIXBIT TO ASCII
	BOUT			;OUTPUT CHARACTER
	TLNE T4,770000		;AT END OF NAME YET?
	JRST LOGBF1		;NO, LOOP BACK FOR REST OF CHARS
LOGBF2:	HRROI T2,[ASCIZ/" at /]
	SOUT
	MOVE T2,SEBDAT+BG%DAT(Q1) ;GET TIME AND DATE OF BUG CHECK
	ODTIM			;TYPE OUT TIME AND DATE
	SETZB T2,BUGSP		;CLEAR POINTERS
	SKIPN Q2,BUGTP		;TABLE POINTER EXIST?
	 JRST LOGBF4
	HRROI T2,[ASCIZ/
*/]
	SOUT
LOGBF3:	MOVE T4,0(Q2)		;SEARCH FOR ADDRESS IN TABLE
	HLRZ T2,T4		;GET ADDRESS
	CAME T2,SEBDAT+BG%ADR(Q1)	;FOUND IT?
	AOBJN Q2,LOGBF3		;NO, LOOP BACK TIL WE DO
	JUMPGE Q2,[HRROI T2,[ASCIZ/Message not found for this address/]
		JRST LOGBF4]
	HRROI T2,0(T4)		;GET POINTER TO MESSAGE STRING
	HRRZM T2,BUGSP		;SAVE IT FOR SYSERR BLOCK
LOGBF4:	SOUT			;TYPE OUT STRING
	SETZM BUGPNM		;START WITH A NULL PROGRAM NAME
	SKIPGE SEBDAT+BG%JOB(Q1)	;IS THERE A JOB?
	JRST LOGBF5		;NO, SKIP JOB/USER LINE
	HRROI T2,[ASCIZ/
*Job: /]
	SOUT
	HRRZ T2,SEBDAT+BG%JOB(Q1)	;GET JOB NUMBER
	MOVEI T3,12		;TYPE IT IN DECIMAL
	NOUT
	 JFCL
	MOVE T2,JOBPNM(T2)	;GET PROGRAM NAME
	MOVEM T2,BUGPNM		;SAVE NAME OF PROGRAM
	HRROI T2,[ASCIZ/, User: /]
	SETZ T3,
	SOUT
	HRRZ T2,SEBDAT+BG%USR(Q1)	;GET USER LOGGED IN DIR NUMBER
	HRLI T2,USRLH		;TURN IT INTO PROPER FORMAT USER NUMBER
	DIRST			;TYPE OUT USER NAME
	 MOVEI T1,.PRIOU	;FAILED. RESTORE DESTINATION ADDRESS
LOGBF5:	SKIPG Q2,SEBDAT+BG%RCT(Q1)	;GET COUNT OF REGISTERS SAVED
	JRST LOGBF7		;NO REGISTERS TO BE TYPED
	HRROI T2,[ASCIZ/
*Additional data: /]
	SOUT
	MOVEI T4,SEBDAT+BG%REG(Q1)	;GET POINTER TO REGISTER AREA
LOGBF6:	MOVE T3,[NO%MAG+10]	;TYPE THEM IN UNSIGNED OCTAL
	MOVE T2,0(T4)		;GET NEXT REG TO TYPE
	NOUT
	 JFCL
	SOJLE Q2,LOGBF7		;DONE?
	HRROI T2,[ASCIZ/, /]	;NO
	SETZ T3,
	SOUT
	AOJA T4,LOGBF6		;GO TYPE OUT REST

LOGBF7:	HRROI T2,[ASCIZ/
********************
/]
	SETZ T3,
	SOUT
	MOVE T1,CRSTD1		;GET DATE OF BUGCHK
	CAMN T1,[-1]		;IS THERE ONE SET?
	CALL LGTAD		;NO, SEE IF IT IS SET NOW
	MOVEM T1,BUGTAD		;SAVE DATE AND TIME OF BUGCHK
	MOVE T1,Q1		;GO COPY REST OF DATA TO BLOCK
	MOVE T2,[-NBUGET,,BUGET]
	CALL SEBCPY
	 JFCL
	SOS BUGCNT		;COUNT DOWN THE QUEUED UP BLOCK COUNT
	SETZM BUGCHK		;CLEAR OUT LAST BUGCHK ADR
	RET			;FINISHED

BUGET:	SEBPTR BG%SVN,SBTSTR,SVN ;SYSTEM NAME
	SEBPTR BG%PNM,SBTWD,BUGPNM ;PROGRAM NAME
	SEBPTR BG%DAT,SBTWD,BUGTAD ;TIME AND DATE OF CRASH
	SEBPTR BG%MSG,SBTSTR,@BUGSP ;BUG MESSAGE
NBUGET==.-BUGET
;SEND TEXT TO ALL LINES, WAIT FOR COMPLETION
; 2/ PTR TO ASCIZ MESSAGE
;	CALL ALLMSG
; RETURN +1 ALWAYS, WAIT LONG ENOUGH FOR MESSAGE TO APPEAR ON 110 BAUD
;LINES.

ALLMSG::SETO 1,			;SAY ALL LINES
	HLRZ 3,2		;CHECK LH OF POINTER
	CAIN 3,-1		;DEFAULT?
	HRLI 2,(<POINT 7,0>)	;YES, DO IT
	TTMSG			;TYPE THE STUFF
	RET			; AND RETURN
CHKDRM:	HRROI 1,[ASCIZ /
*****DRUM ERR: /]
	PSOUT
	MOVSI 6,-NDRMEW		;# OF DRUM ERROR WORDS
	HRRI 6,DRMCFE		;FINISH AOBJN PTR
CHKD1:	MOVE B,0(6)		;GET WORD
	CALL TTOCTP		;PRINT IT
	TMSG <
	>
	AOBJN 6,CHKD1
	SETOM DRMJ0R		;RESET REQUEST FLAG
	RET			;RETURN

CHKDMS:	MOVE 1,DRMFRE
	CAMLE 1,DRMIN0		;DRUM SPACE LOW?
	RET			;NO
	HRROI 2,[ASCIZ /
[Caution--Swapping space low]
/]
;	SKIPE WRMSGF		;WARN USERS?
;	CALL ALLMSG		;YES, DO IT
	HRROI 1,[ASCIZ /
*****Swapping space low, /]
	PSOUT
	MOVE 2,DRMFRE
	JRST CHKH1		;PRINT FREE COUNT

CHKSPT:	MOVE 1,SPTC
	CAMGE 1,SPC1		;SPT LOW?
	RET			;NO
	HRROI 2,[ASCIZ /
[Caution--SPT space low]
/]
;	SKIPE WRMSGF		;WARN USERS?
;	CALL ALLMSG		;YES, DO IT
	HRROI 1,[ASCIZ /
*****SPT space low, /]
	PSOUT
	MOVN 2,[NOFN-SSPT]
	SUB 2,SPTC		;SPACE LEFT
	JRST CHKH1
;CHECK DSK SPACE

CHKDKS:	SKIPGE T1,EXPFRK	;EXPUNGE FORK RUNNING?
	RET			;YES - EXIT QUIETLY
	JUMPE T1,CKDKS1		;NO - EXISTS?
	SETZM EXPFRK		;YES - KILL IT
	KFORK			;...
CKDKS1:	SETZM T1		;ASSUME PUBLIC STRUCTURE
	CALL GSTRPG		;GET COUNT OF USED AND FREE PAGES ON STRUCTURE
	MOVE T1,T2		;GET FREE COUNT
	SUB 1,SYSSPC		;LESS 'BUFFER'
	CAILE 1,SYWRND		;LOW?
	RET			;NO
	PUSH P,2		;SAVE FREE COUNT
	HRROI 2,[ASCIZ /
[Caution--Disk space low on PS:]
/]
	SKIPE WRMSGF		;WARN USERS?
	CALL ALLMSG		;YES, DO IT
	SKIPN T1,EXPTIM		;ENOUGH TIME SINCE LAST EXPUNGE?
	MOVX T1,<^D<30*60000>>	;DONT DO EXPUNGES IN FIRST 30 MIN 
	CAMG T1,TODCLK
	CALL EXPALL		;YES, DO EXPUNGE *
	HRROI 1,[ASCIZ /
*****Disk space low on PS:, /]
	PSOUT
	POP P,2			;RESTORE COUNT OF FREE PAGES
	CALLRET CHKH1

;ROUTINE TO DO EXPUNGE * WHEN DISK SPACE LOW
;START FORK AND MARK IT RUNNING
;	CALL EXPALL
;RETURNS +1 ALWAYS

NR EXPTIM,1		;TIME OF LAST EXPUNGE PLUS MIN INTERVAL
NR EXPFRK,1		;        0 := NO EXPUNGE FORK
			; -1,,FRKH := FORK RUNNING
			;  0,,FRKH := EXPUNGE DONE

EXPALL:	MOVX T1,CR%CAP		;PASS CAPABILITIES DOWN
	CFORK			;CREATE FORK
	 BUG (EXPAFK)
	HRROM T1,EXPFRK		;MARK FORK RUNNING
	MOVEI T2,EXPAL0		;START INFERIOR
	MSFRK			; IN MONITOR MODE
	RET			;RETURN (WAIT TILL DONE)

;EXPUNGE FORK STARTS HERE

EXPAL0:	MOVSI T1,(UMODF)	;SET FUNNY JSYS CONTEXT
	MOVEM T1,FFL
	SETZM FPC		;SET PC
	MCENTR
	CALL EXPAL1		;AWAY WE GO
	HRRZS EXPFRK		;SAY WE ARE DONE
	HALTF			;AND STOP

EXPAL1:	MOVX T2,SF%CDE!SF%BTE
	TDNE T2,FACTSW		;ANY BIT TABLE ERRORS?
	RET			;YES. DON'T EXPUNGE
	HRROI T2,[ASCIZ /
[Deleted files will be expunged in 30 seconds]
/]
	CALL ALLMSG
	MOVEI T1,^D30000
	DISMS			;GIVE USERS TIME TO UNDELETE
	MOVX T1,RC%AWL		;ALLOW WILD CARDS
	HRROI T2,[ASCIZ "PS:<*>"]
	RCDIR			;GET FIRST DIRECTORY NUMBER
	 ERJMP [BUG (EXPRCD)
		JRST EXPAL3]	;WE TRIED
EXPAL2:	SETZ T1,		;NOTHING SPECIAL
	MOVE T2,T3		;PUT DIRECTORY NUMBER IN RIGHT PLACE
	DELDF			;EXPUNGE
	 ERJMP .+1		;IGNORE FAILURES
	MOVX T1,RC%STP!RC%AWL	;STEP TO NEXT
	MOVE T3,T2		;WHERE WE LEFT OFF
	HRROI T2,[ASCIZ "PS:<*>"] ;WHERE WE STARTED
	RCDIR			;...
	 ERJMP EXPAL3		;QUIT ON FAILURE
	TXNN T1,RC%NMD		;DONE?
	JRST EXPAL2		;NO - KEEP GOING

EXPAL3:	MOVX T1,<^D<30*60000>>	;DONE, SET NEXT POSSIBLE TIME
	ADD T1,TODCLK
	MOVEM T1,EXPTIM
	HRROI T2,[ASCIZ /
[System expunge completed]
/]
	SKIPE WRMSGF
	CALL ALLMSG		;NOTIFY USERS
	RET			;DONE
CHKDSK:	RET			;NOP

CHKDE1:	RET			;NOP

;UTILITY NUMBER PRINTERS
;DECIMAL PRINT FOR LESS THAN 18 BIT NUMBERS
;OCTAL PRINT FOR MORE THAN 18 BIT NUMBERS DOES DDT HALFWORD FORMAT.

;B/ NUMBER TO PRINT
;	CALL TTXXXP	;XXX=(DEC,OCT)
;NUMBER PRINTED TO PRIMARY OUTPUT

TTDECP:	SKIPA C,[EXP ^D10]	;IN DECIMAL
TTOCTP::MOVEI C,^D8		;IN OCTAL
	MOVEI A,.PRIOU		;OUTPUT TO PRIMARY
	TLNN B,-1		;LH NON-0?
	JRST TTOCT1		;NO, SIMPLE PRINT
	PUSH P,B		;SAVE DATA
	HLRZ B,B		;PRINT LH
	NOUT
	 JFCL
	MOVEI B,","		;PRINT ,,
	BOUT
	BOUT
	POP P,B			;RECOVER DATA
	HRRZ B,B
TTOCT1:	NOUT			;PRINT RH
	 JFCL
	RET

;ANY INTERRUPT WILL EVENTUALLY TRAP TO HERE

CHKRI:	MOVE P,UPP
	ADD P,BHC+2		;RESET STACK
	SETZM SLOWF
	SETOM INTDF
	SETZM PSIBW
	HRROI 1,[ASCIZ /
*****Job 0 crash, continuing
/]
	PSOUT
	JRST CHKR

NR CHKDRE,1			;COUNT OF REC. ERRORS AT LAST REPORT
NR CHKDNE,1			; "" NON-REC. ""
NR CHKDMC,1
;CHKBGS - CHECK IF TIME TO STORE NEW ASCII TIME AND DATE FOR TYPEOUT
;	  AT BUGHLT TIME
;
;RETURNS:  +1,	ALWAYS

CHKBGS:	MOVE T1,TODCLK		;GET CURRENT DATE AND TIME
	CAML T1,BUGTMS		;TIME TO STORE ASCII STRING?
	SKIPGE TADIDT		;HAS TIME BEEN SET
	RET			;NO, NOT YET
	ADDI T1,BUGINT		;GET NEXT TIME FOR STORING STRING
	MOVEM T1,BUGTMS		;STORE
	MOVE T1,[POINT 7,BUGTIM] ;GET BYTE POINTER FOR STORING TIME
	MOVNI T2,1		;GET CURRENT TIME AND DATE
	SETZ T3,		; IN DEFAULT FORMAT
	ODTIM
	MOVE T2,"/"		;STORE DELIMITER FOR BUGMSG ROUTINE
	IDPB T2,T1
	RET
;ROUTINE TO FINISH LOGGING OF PARITY ERROR - RUN IN JOB 0 CONTEXT

; T1/ ADDRESS OF SYSERR BLOCK

PFCPJ0::SAVEQ
	HLRZ FX,SEBDAT+PT%JOB(T1) ;GET FORKX AT TRAP
	CAIE FX,-1
	SKIPGE FKPT(FX)
	RET			;IN SCHED OR FORK KILLED, NO DATA
	LOAD T2,FKJOBN		;GET JOB NUMBER
	HRRM T2,SEBDAT+PT%JOB(T1) ;REPORT IT
	HRRZ T3,JOBDIR(T2)	;GET LOGGED-IN DIRECTORY
	HRLI T3,USRLH		;MAKE IT A USER NUMBER
	MOVEM T3,SEBDAT+PT%USR(T1) ;REPORT IT
	MOVE T3,JOBPNM(T2)	;GET PROGRAM NAME
	MOVEM T3,SEBDAT+PT%PGM(T1) ;REPORT IT
	RET
;HERE ON FIRST OCCURRANCE OF MUUO IN FORK.  MAP TOPS10 COMPATIBILITY
;MODULE INTO USER ADDRESS SPACE.
;THIS CODE ALSO IMPLEMENTS THE VIROS/TOPS10 TEST UUO.  IF
;THE USER DOES A GETTAB (CALLI 41) WITH ARGUMENT 112,,11 (TABLE
;11, WORD 112) THEN BITS 18-23 TELL WHAT KIND OF MONITOR IT IS.
;IN PARTICULAR, 4 MEANS VIROS.
;THIS CODE CHECKS FOR THIS SPECIFIC CALLI AND ARGUMENT SO THAT
;THE USER PROGRAM CAN EXECUTE IT WITHOUT ACTUALLY INVOKING THE
;COMPATIBILITY MODULE.

GETPAT::MOVE 7,1		;SAVE LOGICAL 40
	MCENTR			;GETS HERE FROM UUO HANDLER
	MOVE 1,7		;GET UUO
	TLZ 1,(777B17)		;DON'T LOOK AT AC, I, X
	CAME 1,[047000,,41]	;WAS IT A CALLI 41 ?
	JRST GETPA1		;NO, CONTINUE
	LDB 2,[POINT 4,7,12]	;YES, CHECK ARGUMENT
	UMOVE 1,0(2)		;GET CONTENTS OF DESIGNATED AC
	CAME 1,[112,,11]	;IS IT MAGIC NUMBER?
	JRST GETPA1		;NO, CONTINUE
	MOVEI 1,4B23		;YES, RETURN ANOTHER MAGIC NUMBER
	UMOVEM 1,0(2)		;RETURN IT IN DESIGNATED AC
	SMRETN

GETPA1:	SKIPGE PATADR		;FORCED INCOMPATABLILITY?
	ITERR(ILINS4)		;YES - GIVE ERROR.
	HRROI 2,[ASCIZ /SYS:PA1050.EXE/]
	CALL GETSEG		;Get PA1050
	 ITERR(ILINS3)		;NO FILE
	MOVEM 1,PATADR		;Save entry vector from file in reserved word
	UMOVE 2,3(1)		;VIRTUAL 40 FOR PAT
	HRRM 2,PATU40
	UMOVE 2,4(1)		;PC WORD FOR PAT
	HRRM 2,PATUPC
	AOJ 1,			;INITIAL ENTRY IS 1, REGULAR 0
	HRLI T2,(UMODF)
	EXCH T2,0(P)		;GET FLAGS
	MOVE T3,-1(P)		;FIND PC
	HRRZM T1,-1(P)		;SET PC
	MOVE T1,T3		;SET PC IN USER MEMORY
	HLL T1,T2
	XCTU PATUPC
	MOVE 1,7
	XCTU PATU40
	JRST MRETN		;GO TO COMPATIBILITY
;HERE ON FIRST RAF JSYS TO LOAD RMS.EXE INTO FORK ADDRESS SPACE

GETDMS::MOVE 7,1		;SAVE LOGICAL 40
	MCENTR			;ENTER MONITOR CONTEXT
	HRROI T2,[ASCIZ/SYS:RMS.EXE/]
	CALL GETSEG		;Get RMS into this process
	 ITERR(ILINS5)		;NO FILE
	MOVEM 1,DMSADR		;Save entry vector from file in reserved place
	UMOVE 2,3(1)		;VIRTUAL 40 FOR DMS
	HRRM 2,DMSU40
	UMOVE 2,4(1)		;PC WORD FOR DMS
	HRRM 2,DMSUPC
	AOJ 1,			;INITIAL ENTRY IS 1, REGULAR 0
	HRLI T2,(UMODF)
	EXCH T2,0(P)		;SET NEW PAC, GET OLD ONE
	MOVE T3,-1(P)		;GET PC
	HRRZM T1,-1(P)		;SET PC
	MOVE T1,T3
	HLL T1,T2
	XCTU DMSUPC
	MOVE 1,7
	XCTU DMSU40
	JRST MRETN		;GO TO DMS


; GETSEG - Get a segment into this process
;
; Call:
;	T2/	String pointer to file name of segment
;	CALL GETSEG
;
; Returns:
;	+1:	No such file (GTJFN failed)
;	+2:	Success, entry vector from file in T1
;
; Clobbers T1, T2
;
GETSEG:
	MOVE T1,FORKN		;Get current JRFN
	CALL CKNXOR		;Skip if not execute-only
	 SKIPA T1,[EXP GJ%PHY!GJ%SHT!GJ%OLD] ;Execute-only-- make sure physical  SYS:
	MOVX T1,GJ%SHT!GJ%OLD	;Not execute-only, just get file
	GTJFN			;Get a JFN on file
	 RET			;Error-- return +1 from GETSEG
	PUSH P,ENTVEC		;Save old entry vector
	HRLI T1,.FHSLF		;Get into this process
	GET			;Get it
	POP P,T1		;Restore old entry vector
	EXCH T1,ENTVEC		;Put old entry vector back, get one from file in T1
	RETSKP			;Return +2 from GETSEG
;THE CHKAC JSYS - CHECK THE ACCESSABILITY OF A FILE OR DIRECTORY

;ACCEPTS IN 1/	COUNT OF ARGUMENTS
;	    2/	LOCATION OF ARGUMENT BLOCK
;	CHKAC
;RETURNS +1:	ERROR - ERROR CODE IN AC 1
;	 +2:	AC 1 = 0	ACCESS NOT ALLOWED
;		AC 1 = -1	ACCESS IS ALLOWED

;ARGUMENT BLOCK:
;	.CKAAC	DESIRED ACCESS CODE
;	.CKALD	LOGGED IN USER NUMBER OF THE USER DOING THE ACCESSING
;	.CKACD	CONNECTED STRUCTURE,,DIRECTORY OR POINTER TO STRUCTURE/
;		DIRECTORY STRING
;	.CKAEC	ENABLED CAPABILITIES OF THE USER
;	.CKAUD	STRUCTURE,,DIRECTORY OR POINTER TO STRUCTURE/DIRECTORY STRING
;		FOR FILE BEING ACCESSED
;		IF CK%JFN IS SET IN AC1, THIS IS JFN FOR FILE
;	.CKAPR	PROTECTION OF FILE BEING ACCESSED

.CHKAC::MCENT			;ENTER JSYS
	STKVAR <<SVT3T4,2>>
	UMOVE Q1,2		;GET LOCATION OF ARGUMENT BLOCK
	XCTU [HRRZ T1,1]	;GET LENGTH OF ARGUMENT BLOCK
	XCTU [HLL Q1,1]		;GET THE FLAGS
	TXNN Q1,CK%JFN		;SPECIFIING A JFN?
	CAIG T1,.CKAPR		;NO, NEED A PROTECTION
	CAILE T1,.CKAUD		;YES, DO NOT NEED THE PROTECTION WORD
	XCTU [SKIPA T1,.CKAEC(Q1)] ;LENGTH IS OK, GET CAPABILITIES
	RETERR (CKAX1)		;LENGTH IS TOO SHORT
	TRNE T1,SC%WHL!SC%OPR	;IS THIS USER A WHEEL?
	JRST CHKACT		;YES, ACCESS IS LEGAL ALWAYS
	XCTU [HRRZ P1,.CKAAC(Q1)] ;GET ACCESS CODE
	UMOVE T1,.CKAUD(Q1)	;GET THE JFN OR DIRECTORY DESIGNATOR
	TXNE Q1,CK%JFN		;IS USER GIVING A JFN?
	JRST CHKAC2		;YES
	CALL CNVSTD		;CONVERT TO A DIRECTORY NUMBER
	 RETERR ()		;ILLEGAL FORMAT OF STRING
CHKAC2:	MOVE P2,T1		;SAVE JFN OR DIR NUMBER IN P2
	UMOVE T1,.CKALD(Q1)	;GET THE LOGGED IN USER NUMBER
	LOAD T2,NMFLG,T1	;GET BITS 0-2
	CAIN T2,NUMVAL		;IS THIS A NUMBER?
	JRST CHKAC3		;YES, DONT NEED TO CONVERT THE STRING
	CALL CNVSTU		;CONVERT STRING TO USER NUMBER
	 RETERR ()		;FAILED
CHKAC3:	CALL CNVDIR		;CONVERT IT TO A DIR NUMBER
	MOVE P3,T1		;SAVE DIRECTORY # IN P3
	UMOVE T1,.CKACD(Q1)	;GET CONNECTED DIR # INTO P4
	CALL CNVSTD		;GET DIR NUMBER FROM STRING
	 RETERR ()		;FAILED TO GET A DIRECTORY NUMBER
	MOVE P4,T1		;SAVE DIR NUMBER FOR LATER
	TXNN Q1,CK%JFN		;GIVING A JFN?
	XCTU [HRLZ P5,.CKAPR(Q1)] ;NO, GET PROTECTION
	TXNE Q1,CK%JFN		;USER GIVING A JFN?
	JRST [	HRRZ T1,P2	;YES, GET IT
		CALL GETFPD	;GET PROT AND DIR #
		 RETERR (CKAX4)	;BAD JFN
		MOVE P2,T1	;SAVE DIR #
		HRLZ P5,T2	;SAVE PROTECTION
		JRST .+1]
	MOVE T1,P2		;MAP IN DIRECTORY OF FILE
	CALL SETDIR		;FIRST CHECK LEGALITY OF DIR #
	 RETERR (CKAX2)		;ILLEGAL DIR # 
	ULKDIR			;UNLOCK DIR, BUT STAY NOINT
	CAIL P1,.CKADR		;IS THIS A DIRECTORY ACCESS CHECK?
	JRST CHKDIR		;YES, GO SET UP DIR PROTECTION VALUE
	MOVEI T4,<DP%RD>B35	;MUST ALSO CHECK READ ACCESS TO DIR
CHKAC0:	MOVSI Q2,40		;SET UP MASK WORD
	MOVN T1,P1		;GET CODE
	LSH Q2,0(T1)		;FORM THE ACCESS CHECK MASK
	TDNE Q2,P5		;IS THIS MODE ALLOWED FOR WORLD?
	JRST [	MOVE T1,DIRORA	;YES, NOW SEE IF LEGAL TO REF DIR
		LOAD T1,DRPRT,(T1) ;GET DIRECTORY PROTECTION
		TDNE T4,T1	;LEGAL TO REFERENCE IT?
		JRST CHKACT	;YES, THIS IS LEGAL THEN
		JRST .+1]	;NO, GO SEE IF THIS IS OWNER OR GROUP
	HLLZ T1,P5		;MAKE OWNER SUPERSET OF GROUP
	LSH T1,6
	IORM T1,P5		;DONT ALLOW GROUP MORE PRIVS THAN OWNER
	LSH Q2,^D12		;NOW SEE IF LEGAL FOR OWNER
	LSH T4,^D12		;DO SAME FOR DIR PROTECTION MASK
	MOVE T3,DIRORA		;GET BASE ADR OF MAPPED DIR
	LOAD T3,DRPRT,(T3)	;GET DIR PROTECTION
	MOVE T2,T3
	LSH T2,6		;MAKE OWNER SUPERSET OF GROUP
	IORM T2,T3		;T3 = DIR PROTECTION
	TDNE T4,T3		;LEGAL ACCESS FOR OWNER IN DIRECTORY?
	TDNN Q2,P5		;YES, IS FILE ACCESS LEGAL?
	JRST CHKACF		;IF NOT LEGAL FOR OWNER, THEN FALSE
	CAME P3,P2		;IS THIS FILE IN SAME DIR AS USER?
	CAMN P4,P2		;EITHER LOGGED IN OR CONNECTED
	JRST CHKACT		;YES, RETURN TRUE
	DMOVEM T3,SVT3T4	;SAVE T3 AND T4
	SETZ P4,		;FLAG FOR DIFFERENT STRUCTURES
	HLRZ T1,P2		;GET STRUCTURE TO ACCESS
	HLRZ T2,P3		;GET LOGGED IN STRUCTURE UNIQUE CODE
	CAMN T1,T2		;ARE THEY THE SAME?
	JRST CHKAC4		;YES, FORGET DOMESTIC STR TEST
	HLRZ T1,P2		;GET STRUCTURE UNIQUE CODE
	CALL CNVSTR		;GET STRUCTURE NUMBER
	 RETERR ()		;COULDN'T FIND STRUCTURE
	MOVE T2,T1		;SAVE STRUCTURE NUMBER
	CALL ULKSTR		;UNLOCK STRUCTURE FROM CNVSTR
	MOVE T2,STRTAB(T2)	;GET STRUCTURE DATA BLOCK ADDRESS
	MOVE T1,SDBSTS(T1)	;GET STATUS OF STRUCTURE
	TXNN T1,MS%DOM		;IS IT DOMESTIC?
	JRST CHKACF		;NO, RETURN FALSE
	MOVEI T2,MAXLW+1	;GET SOME JSB FREE SPACE
	CALL ASGJFR		; IN WHICH TO STORE USER NAME
	 RETERR (SACTX2)	;INSUFFICIENT RESOURCES
	MOVE P4,T1		;STORE FREE SPACE BLOCK ADDRESS
	AOS T1			;DON'T STEP ON HEADER
	HRLI T1,-1		;MAKE IT A POINTER
	MOVE T2,P3		;GET LOGGED IN DIRECTORY
	HRLI T2,USRLH		;MAKE IT A USER NUMBER
	DIRST			;GET USER NAME
	 JRST [ MOVEI T1,JSBFRE	;RELEASE FREE SPACE
		MOVE T2,P4
		CALL RELFRE
		RETERR ()]
	MOVE T1,P4		;GET ADDRESS OF NAME
	HLRZ T2,P2		;GET STUCTURE UNIQUE CODE
	CALL DIRLKX		;DOES USER HAVE A DIRECTORY ON THIS STR?
	 JRST [ MOVEI T1,JSBFRE	;NO DIRECTORY ON THAT STRUCTURE
		MOVE T2,P4	;RELEASE FREE SPACE
		CALL RELFRE
		JRST CHKACF]	;RETURN FALSE
	MOVE T2,P4		;GET ADDRESS OF JSB SPACE
	MOVE P4,T1		;STORE DIRECTORY NUMBER
	MOVEI T1,JSBFRE
	CALL RELFRE		;RETURN JSB SPACE
	HLL P4,P2		;ADD STR UNIQUE CODE TO DIR NUMBER
	CAMN P2,P4		;TRYING TO ACCESS OUR OWN DIRECTORY?
	JRST CHKACT		;YES, RETURN SUCCESS
	MOVE T1,P2		;MAP IN DESIRED DIRECTORY AGAIN
	CALL SETDIR
	 RETERR ()
	ULKDIR			;UNLOCK DIRECTORY
CHKAC4:	DMOVE T3,SVT3T4		;RESTORE T3 AND T4
	LSH Q2,-6		;NO, NOW SEE IF THIS IS SAME GROUP
	LSH T4,-6		;SAME FOR GROUP
	TDNE T4,T3		;LEGAL ACCESS TO DIR BY GROUPS?
	TDNN Q2,P5		;YES, LEGAL FOR GROUP?
	JRST CHKACF		;NO, RETURN FALSE
	CALL CPYDGP		;COPY DIR GROUPS INTO JSB
	 JRST CHKACF		;NO GROUPS
	MOVE P6,T1		;SAVE THE JSB POINTER
	SKIPN T1,P4		;TRYING TO ACCESS DIR ON PS:?
	MOVE T1,P3		;YES, GET LOGGED IN DIRECTORY
	CALL SETDIR		;GET INFO ABOUT THIS USER
	 RETERR (CKAX2)		;ILLEGAL DIRECTORY NUMBER
	ULKDIR			;UNLOCK THE DIRECTORY LOCK FROM GETDDB
	MOVE Q1,P6		;GET AOBJN POINTER TO DIR GROUP LIST
CHKAC1:	HLRZ T1,0(Q1)		;GET FIRST MEMBER OF GROUP
	CALL CHKUGP		;CHECK IT AGAINST USER GROUPS
	 SKIPA			;NO MATCH
	JRST [	MOVE A,P6	;MATCH FOUND
		CALL RELGRP	;RELEASE THE SPACE IN THE JSB
		JRST CHKACT]	;RETURN TRUE
	HRRZ T1,0(Q1)		;GET NEXT MEMBER OF GROUP
	CALL CHKUGP		;CHECK FOR MATCH
	 SKIPA			;NO MATCH
	JRST [	MOVE A,P6	;MATCHED!
		CALL RELGRP	;RELEASE THE JSB SPACE
		JRST CHKACT]	;RETURN TRUE
	AOBJN Q1,CHKAC1		;LOOP UNTIL LIST IS FINISHED
	MOVE A,P6		;RELEASE THE SPACE IN JSB
	CALL RELGRP
CHKACF:	TDZA T1,T1		;RETURN FALSE
CHKACT:	SETO T1,		;TRUE
	UMOVEM T1,1		;STORE ANSWER
	SMRETN			;AND RETURN

CHKDIR:	CAIL P1,.CKADR		;IS THIS A LEGAL FUNCTION CODE
	CAILE P1,.CKACF
	RETERR (CKAX3)		;NO, ILLEGAL ACCESS CODE
	SUBI P1,.CKADR		;SET UP FOR MASK BUILDING
	MOVE T4,DIRORA		;GET BASE OF DIR AREA
	LOAD T4,DRPRT,(T4)	;GET DIR PROTECTION
	HRL P5,T4		;ONLY WANT 18 BITS
	MOVEI T4,77		;DONT CARE ABOUT DIR PROTECTION CHECK
	JRST CHKAC0		;GO FINISH JSYS


;ROUTINE TO COPY A LIST OF GROUPS TO THE JSB
;	CALL CPYDGP	OR	CALL CPYUGP
;RETURNS +1:	NO GROUPS
;	 +2:	AOBJN POINTER TO LIST IN JSB RETURNED IN T1

CPYDGP::SE1CAL			;ENTER SEC 1
	MOVE D,DIRORA		;GET BASE OF DIR AREA
	LOAD D,DRDGP,(D)	;GET DIR GROUP LIST
	JRST CPYUG0		;ENTER COMMON CODE

CPYUGP::SE1CAL			;ENTER SEC 1
	MOVE D,DIRORA		;GET BASE OF DIR AREA
	LOAD D,DRUGP,(D)	;GET USER GROUP LIST
CPYUG0:	JUMPE D,R		;IF 0, NO LIST
	STKVAR <CPYUGA>
	ADD D,DIRORA		;GET ABS ADR OF LIST
	LOAD C,BLKTYP,(D)	;GET TYPE OF THIS BLOCK
	CAIE C,.TYGDB		;MUST BE A DIRECTORY GROUP BLOCK
	RET			;DIR IS SCREWED UP
	LOAD B,BLKLEN,(D)	;GET LENGTH OF BLOCK
	SOS B			;SKIP OVER HEADER
	MOVEM D,CPYUGA		;SAVE ADR OF LIST
	CALL ASGJFR		;GET A BLOCK FROM JSB
	 RET			;NO ROOM
	MOVE D,CPYUGA		;GET BACK ADR OF LIST
	HRRZ B,0(A)		;GET LENGTH OF DIR LIST
	MOVNS B			;SET UP AN AOBJN POINTER TO JSB
	HRL A,B
	MOVE C,A		;LEAVE POINTER IN A
CPYUGL:	MOVE B,1(D)		;GET NEXT ELEMENT IN LIST
	MOVEM B,0(C)		;STORE IN JSB
	AOS D			;STEP TO NEXT ELEMENT IN LIST
	AOBJN C,CPYUGL		;LOOP TIL LIST IS COPIED
	RETSKP			;RETURN SUCCESSFUL WITH POINTER IN A


;ROUTINE TO RELEASE A GROUP LIST FROM JSB
;ACCEPTS IN A/	POINTER TO LIST
;	CALL RELGRP
;RETURNS +1:	ALWAYS

RELGRP::HLRE B,A		;GET LENGTH OF BLOCK
	HRRZS	A		;INSURE IN THIS SECTION
	MOVNM B,(A)		;STORE LENGTH IN BLOCK
	HRRZ B,A		;GET ADR OF BLOCK
	MOVEI A,JSBFRE
	CALLRET RELFRE		;RELEASE THE BLOCK
;MDDT INTERNAL SUBROUTINE CALL.  THIS SUBROUTINE IS THE INTERFACE
;BETWEEN MDDT AND THE REST OF THE MONITOR.  CALL:
;
;	AC1/	FUNCTION CODE
;	AC2-AC4/ ARGUMENTS
;	CALL .IMOPR
;	  ERROR RETURN
;	SUCCESSFUL RETURN



.IMOPR::JUMPLE T1,R		;FAIL IF NOT POSITIVE
	CAIG T1,IMMAX		;FUNCTION LEGAL?
	SKIPN HSYBLK		;SYMBOLS HIDDEN? (FUNCTIONS SO FAR NEED THIS)
	RET			;NO, GIVE ERROR RETURN
	JRST @IMTAB-1(T1)	;GO TO PROPER ROUTINE



IMTAB:	IFIW	IMALC		;(1) ALLOCATE PAGES FOR USE
	IFIW	IMMAP		;(2) MAP PAGES OF THE SYMBOL SPACE
	IFIW	IMUMAP		;(3) UNMAP PAGES OF SYMBOLS

	IMMAX==.-IMTAB		;HIGHEST FUNCTION




;FUNCTION .IMALC.  ALLOCATES A PAGE FOR USE IN MAPPING SYMBOLS.  PAGE
;IS RELEASED WHEN FORK IS DESTROYED.  MULTIPLE CALLS WILL RETURN THE
;SAME PAGE.  ARGUMENTS:
;
;	T2/	NUMBER OF PAGES DESIRED (ONLY 1 IS LEGAL NOW)
;
;RETURNS PAGE NUMBER OF FIRST PAGE IN T1.


IMALC:	CAIE T2,1		;ASKING FOR ONE PAGE?
	RET			;NO, FAIL
	NOINT			;PREVENT INTERRUPTIONS
	SKIPE T1,SYMPAG		;PREVIOUSLY ALLOCATED A PAGE?
	JRST IMALCH		;YES, RETURN IT
	CALL ASGPAG		;GET A NEW JSB PAGE
	SETZ T1,		;NONE AVAILABLE
	MOVEM T1,SYMPAG		;REMEMBER FOR LATER USE
IMALCH:	OKINT			;INTERRUPTS OK NOW
	LSH T1,-PGSFT		;CONVERT TO PAGE NUMBER
	JUMPN T1,RSKP		;SKIP RETURN IF GOT A PAGE
	RET			;OTHERWISE FAIL
;FUNCTION .IMMAP.  MAP PAGES OF THE SYMBOL SPACE.  USED BY MDDT
;AND SNOOP JSYS.  ARGUMENTS:
;
;	T2/	PAGE IN SYMBOL SPACE TO MAP
;	T3/	PAGE IN MONITOR SPACE TO MAP TO
;	T4/	COUNT OF PAGES TO MAP.  1B0 SET IF WRITE ENABLED


IMMAP:	MOVE T1,T2		;SET UP PAGE NUMBER TO MAP
	HRL T1,SYMBAS		;AND PUT IN SPT INDEX OF SYMBOL MAP
	TDNN T2,[-1,,777000]	;SYMBOL SPACE EXISTS ONLY IN SECTION 0
IMMAP1:	TDNE T3,[-1,,776000]	;SEE IF PAGE IS SECTION 0 OR 1
	RET			;IF NOT, ERROR
	ANDI T3,777		;MAKE SECTION 1 SAME AS SECTION 0
	MOVE T2,T3		;GET PAGE WHERE WE MAP TO
	LSH T2,PGSFT		;TURN INTO ADDRESS
	TXZE T4,1B0		;WANT IT WRITE-ENABLED?
	TXO T2,PTRW		;YES, SET WRITE BIT
	TLNN T4,-1		;CHECK REST OF LEFT HALF
	TRNN T4,-1		;AND MAKE SURE HAVE NONZERO COUNT
	RET			;NO, ERROR
	ADDI T3,-1(T4)		;CALCULATE LAST PAGE TO BE MAPPED
	TRNE T3,777000		;MAKE SURE IT STAYS IN SECTION 0
	RET			;NO, ERROR
	MOVE T3,T4		;PUT COUNT IN RIGHT AC
	CALL MSETMP		;DO THE MAPPING
	RETSKP			;GOOD RETURN



;FUNCTION .IMUMP.  UNMAP SYMBOL PAGES.  ARGUMENTS ARE:
;
;	T2/	PAGE IN NORMAL SPACE WHERE SYMBOLS WERE MAPPED
;	T3/	COUNT OF PAGES TO UNMAP


IMUMAP:	MOVE T4,T3		;MOVE ARGS TO RIGHT ACS
	MOVE T3,T2		;SO CAN JOIN OTHER ROUTINE
	SETZM T1		;ZERO FOR UNMAP
	CALLRET IMMAP1		;GO DO THE WORK
;LOGOUT

.LGOUT::MCENT
	CAME 1,[-1]		;SELF?
	JRST ELOGO		;NO
	MOVSI 1,(SC%LOG)
	TDNN 1,CAPMSK		;LOG PERMITTED?
	RETERR (LOUTX4)		;NO, ERROR RETURN
	SETONE JSELO		;FLAG THAT JOB EXECUTED ITS OWN LGOUT
LOGO:	SE1ENT			;GET TO SECTION 1
	MOVE T1,JOBNO		;GET CORRECT JOB NUMBER
	CALL LGOGOK		;CHECK TO SEE IF LOGO LEGAL
	SKIPN FORKN		;TOP FORK?
	JRST FLOGO1		;YES
	NOINT
	HLRZ 1,FORKN		;NO, GET ITS NUMBER
	HRRZ 2,SYSFK(1)
	NOSKED
	MOVSI 1,400000+PSILOB
	IORM 1,FKINT(2)		;REQUEST LOGOUT
	CALL PSIR4
	OKSKED
	OKINT
	JRST WAIT1		;WAIT FOR TOP FORK TO KILL THE JOB
;THE FOLLOWING CODE DOES THE ACTUAL LOGOUT.  IT RUNS ONLY IN
;THE TOP FORK OF THE JOB BEING LOGGED OUT

FLOGO1:	MOVX 1,LOGIOB		;SAY JOB DESTRUCTION IN PROGRESS
	IORM 1,JOBBIT
	MOVEI 1,400000
	SETO 2,
	DIC			;DEACTIVATE INTERRUPTS AND KEYS
	CALL DTIALL
	CALL NETLGO		;RELEASE ANY JOB-WIDE NETWORK RESOURCES
	MOVEI T1,-4
	KFORK			;DELETE FORKS
	MOVE T1,JOBNO		;MARK THAT I AM NO LONGER OWNED
	SETOM JOBONT(T1)		; ..
	MOVSI T3,-NJOBS		;LOG OUT ANY JOBS WHICH I OWN
SJLGO1:	HRRZ T2,JOBONT(3)	;DO I OWN THIS ONE?
	CAME T2,JOBNO		; ..
	JRST SJLGO2		;NO.
	MOVEI T1,0(T3)		;YES. LOG IT OUT.
	LGOUT
	 JFCL			;SHOULD HAVE WORKED.
	SETOM JOBONT(T3)		;MAKE IT UNOWNED, SO IT FINISHES
SJLGO2:	AOBJN T3,SJLGO1		;SEE IF I OWN ANY MORE JOBS
;FALL THRU
;FALLS THRU FROM ABOVE
SJLGO4:	SETO T1,			;CLEAR USER MAP OF TOP FORK
	MOVSI 2,400000
	MOVE 3,[1B0+1000]	;REQUEST 1000 PAGES
	PMAP
	MOVE FX,FORKX
	LOAD 1,FKJSB		;GET JSB
	CALL WTSPT		;WAIT FOR SHR CNT OF 1
	SKIPL CTRLTT
	RESET			;RESET TTY MODES, ETC.
	CALL UNPAGE		;CLEAR PAGE MODE
	MOVE 1,[CZ%ARJ+CZ%ABT+400000] ;WAIT+FLUSH NONX + THIS FORK
	CLZFF
	MOVE 1,FORKX		;NOW KILL PIDS OF THIS FORK
	CALL PIDKFK		; INCLUDING JOB WIDE PIDS
	CALL CLKREL		;RELEASE TIMER BLOCKS
	MOVE 4,JOBNO
	HRRZ 1,JOBDIR(4)	;GET LOGIN DIR
	JUMPE 1,LOG1		;DON'T EXPUNGE IF NOT LOGGED IN
	HRLI T1,USRLH		;GET USER NUMBER
	CALL CNVDIR		;CONVERT IT TO A DIRECTORY NUMBER
	MOVE T2,T1		;SET UP FOR DELDF
	MOVX T1,DD%DTF		;DELETE TEMPORARY FILES
	PUSH P,T2		;SAVE DIR NUMBER
	DELDF			;EXPUNGE LOGIN DIR
	 ERJMP .+1		;DONT STOP ON ERRORS
	CALL GTCSCD		;GET CONNECTED STRUCTURE,,DIRECTORY
	POP P,T3		;GET BACK DIR # FROM LAST DELDF
	CAMN T2,T3		;ARE THEY THE SAME?
	JRST LOG0		;YES, DO NO EXPUNGE AGAIN
	MOVE T2,T1		;GET DIR NUMBER INTO 2
	MOVX T1,DD%DTF		;DELETE TEMPORARY FILES
	DELDF			;EXPUNGE CONNECTED DIR
	 ERJMP .+1		;DONT STOP ON ERRORS
LOG0:	CALL LOGSTR		;GO DECREMENT MOUNT COUNT FOR ALL STR'S
				; THIS JOB HAS MOUNTED
	MOVNI 1,1		;NOW RELEASE ALL ASSIGNED DEVICES
	RELD
	 JFCL
	MOVE 1,LOGDES
	DOBE			;WAIT FOR LOG TTY INACTIVE
	CALL LOGTOT		;SUMMARY TO LOG TTY
	CALL LOGTUS		;Perform USAGE for logout
LOG1:	HRRE 1,CTRLTT
	JUMPL 1,LOG2		;CONTROL TTY?
	MOVEI 1,400000(1)	;YES, PRINT LOGOUT MESSAGE
	RFMOD			;TURN OFF PAGE MODE
	TXZ 2,TT%PGM		;TO ALLOW THE MESSAGE TO COME OUT
	STPAR
	CALL LOGTOT
	HRLOI T1,(TL%CRO+TL%COR+TL%SAB+TL%ABS)
	MOVE T2,CTRLTT
	CAMN T2,CTYLNO		;Logging off CTY?
	TXZ T1,TL%ABS		;Yes - set refuse links
	MOVEI T2,-1
	TLINK			;BREAK LINKS, SET ACCEPT
	 JFCL
	HRRE 1,CTRLTT		;GET TTY #
	JUMPL T1,LOG2		;NONE
	MOVEI 1,400000(1)	;GET DESIGNATOR
	DOBE			;WAIT FOR THE MESSAGE TO COMPLETE
	MOVE 1,JOBNO
	HRRZ 1,JOBDIR(1)
	JUMPN 1,LOG2		;HANG UP LINE IF JOB WAS NOT LOGGED IN
	MOVE 2,CTRLTT
	CALL TTHNGU		;HANG UP LINE
LOG2:	MOVEI T1,SPIDTB+.SPQSR	;GET PID ADDRESS
	SKIPE SPIDTB+.SPQSR	;IS QUASAR RUNNING?
	CALL LOGOMS		;YES, SEND IT A MESSAGE
	 JFCL
	MOVEI T1,SPIDTB+.SPOPR	;GET ORION PID ADDRESS
	SKIPE SPIDTB+.SPOPR	;RUNNING?
	CALL LOGOMS		;YES, SEND IT A MESSAGE
	 JFCL
	SKIPE T1,JSLOPD		;IS THERE A PID IN JSB FOR LGOUT MSG?
	CALL LOGOMO		;YES. SEND THE LOGOUT MESSAGE TO CREATOR
	 JFCL
	JRST HLTJB
LGOGOK:	SAVET
	HRRZ T1,JOBDIR(T1)	;DIRECTORY
	JUMPE T1,R		;QUIT NOT LOGGED IN
	HRLI T1,USRLH
	CALL CNVDIR		;GET DIRECTORY NUMBER
	GTDAL			;GET ALLOCATION
	ERJMP R			;QUIT SOME ERROR
	UMOVE T1,T1		;GET ORIG ARGUMENT
	GTOKM (.GOLGO,<T2,T3,T1>,[RETERR ()])	 ;ASK PERMISSION
	RET			;RETURN TO CALLER
;LOGSTR - ROUTINE TO DECREMENT MOUNT COUNT FOR ALL STRUCTURES THIS
;	  JOB HAS MOUNTED.
;
;CALL:		CALL LOGSTR
;RETURNS: +1 ALWAYS

LOGSTR:	SAVEP
	LOCK JSSTLK		;LOCK THE JSB STRUCTURE INFO DATA
	MOVSI P1,-STRN		;SET UP TO LOOP OVER STR INFO BLOCKS IN JSB
	MOVEI P2,JSSTRT		;GET ADDRESS OF FIRST BLOCK TO LOOK AT

LGST10:	JE <JSMCI,JSXCL>,(P2),LGST20 ;IF THIS JOB DIDN'T MOUNT THIS STR, CHECK NEXT
	LOAD T1,JSSTN,(P2)	;GET UNIQUE CODE FOR THIS STRUCTURE
	CALL CNVSTR		;GET STRUCTURE # AND LOCK THE STRUCTURE
	 JRST LGST20		;FAILED, MUST ALREADY BE DISMOUNTED, GO ON
	MOVEM T1,P3		;SAVE STRUCTURE NUMBER
	JN JSXCL,(P2),[	MOVX T1,D1%INI ;IF MOUNTED EXCLUSIVELY BY THIS JOB,
			ANDCAM T1,DEVCH1+DVXST0(P3) ; MAKE STR GENERALLY AVAILABLE
			JRST .+1]
	JE JSMCI,(P2),LGST15	;IF MOUNT COUNT NOT INCREMENTED, GO UNLOCK STR
	MOVE T1,P3		;GET STRUCTURE NUMBER AGAIN
	MOVE T2,P2		;GET ADDRESS OF STR INFO BLOCK IN JSB
	MOVE T3,JOBNO		;GET JOB NUMBER
	CALL DECMNT		;GO DECREMENT THE MOUNT COUNT FOR THIS STR
	 JFCL			;IGNORE FAILURE, GO ON
LGST15:	MOVE T1,P3		;RESTORE STRUCTURE NUMBER
	CALL ULKSTR		;UNLOCK THE STRUCTURE NOW
LGST20:	ADDI P2,JSSTMX		;GET ADDRESS OF NEXT STR INFO BLOCK IN JSB
	AOBJN P1,LGST10		;GO CHECK NEXT STR INFO BLOCK

	UNLOCK JSSTLK		;DONE, UNLOCK THE JSB STR INFO LOCK
	RET			;RETURN
;THE FOLLOWING IMPLEMENTS LOGOUT OF A JOB OTHER THAN SELF.
;LEGAL IF USER IS SC%WHL OR SC%OPR, OR IF OTHER JOB IS SAME USER

ELOGO:	MOVE T2,JOBNO		;GIVEN JOB NUMBER TO LOGOUT
	CAIN T2,0(T1)		;SELF?
	RETERR(LOUTX1)		;YES, CAN'T SAY IT THAT WAY
	JUMPE T1,[RETERR (LOUTX5)] ;CANNOT LOGOUT JOB 0
	CAIGE T1,NJOBS		;REASONABLE NUMBER?
	CAIG T1,0
	RETERR(LOUTX2)		;NO
	MOVE P1,T1		; preserve target job number
	CALL LGOGOK		;GETOK CHECK
	NOSKED			; prevent races
	SKIPGE JOBRT(P1)	;EXISTS?
	RETERR(LOUTX2,OKSKED)	; no, fail
	MOVE T1,P1		; target job number
	CALL SETJSB		; map its JSB
	MOVE P2,T1		; preserve JSB address
	HRRZ T3,JOBDIR(P1)	;LOGIN DIRECTORY OF OBJECT JOB
	MOVE T1,JOBNO		; our job number
	XOR T3,JOBDIR(T1)	; our directory number
	TRNN T3,-1		;SAME AS THIS JOB?
	JRST ELOGO1		;YES, THAT'S OK
	HLRE T1,JOBPT(P1)	;GET TTY OF THE JOB BEING LOGGED OUT
	JUMPL T1,ELOGO3		;JUMP IF DETACHED
	CALL PTGETJ		;GET CONTROLLING JOB # IF TTY IS A PTY
	JUMPL T1,ELOGO3		;JUMP IF NOT A PTY JOB
	CAMN T1,JOBNO		;JOB BEING CONTROLLED BY JOB DOING THE LGOUT
	JRST ELOGO1		;YES, SO DO IT
ELOGO3:	HRRZ T3,JOBONT(P1)	;DO I OWN THAT JOB IN CRJOB SENSE?
	CAMN T3,JOBNO		; ..
	JRST ELOGO1		;YES. OK TO LOG IT OUT.
	MOVEI T3,SC%WHL+SC%OPR	;OTHERWISE MUST BE SC%WHL
	TDNN T3,CAPENB
	JRST [	CALL CLRJSB		; unmap the JSB
		RETERR(LOUTX3,OKSKED)]	; quit
ELOGO1:	SETOM JOBONT(P1)	;MAKE IT UNOWNED SO IT CAN LOG OUT
	SETONE JSOLO,(P2)	;FLAG IN IT THAT SOMEONE LGOUT'ED IT
	MOVE T1,JOBNO		;AND WHO IT WAS
	MOVEM T1,JSLOJB(P2)	; ..
	CALL CLRJSB		;LET GO OF THE JSB
	MOVE T1,P1		; target job number
	CALL ELOGOO		;LOG OUT THE TARGET JOB
	OKSKED
	SMRETN			;AND DONE
;ROUTINE CALLED TO LOGOUT ANOTHER JOB.
;ACCEPTS:	A/ JOB NUMBER
;RETURNS:	+1 WITH LOGOUT REQUESTED

	RESCD			;MUST BE RESIDENT AS CALLED BY SCHEDULER

ELOGOO::NOSKD1			; prevent races
	SKIPGE JOBRT(T1)	; job exist?
	JRST [	OKSKD1			; no, fail
		RET]			;  ..
	HRRZ 2,JOBPT(1)		;TOP FORK OF OBJECT JOB
	MOVSI 1,400000+PSILOB
	IORM 1,FKINT(2)		;REQUEST LOGOUT
	CALL PSIR4
	OKSKD1			;ALLOWING SCHEDULING AGAIN
	RET			;AND DONE

;THE FOLLOWING IS RUN IN THE TOP FORK OF A JOB TO RESPOND TO
;A LOGOUT REQUEST FROM ANOTHER JOB

	SWAPCD			;IS SWAPPABLE
FLOGO::	MOVSI 1,(UMODF)		;FAKE USER PC
	MOVEM 1,FFL
	SETZM FPC
	SE1ENT			;ENTER SECTION 1
	MCENTR			;SIMULATE ENTRY FROM USER
	JRST FLOGO1		;NOW GO DO ORDINARY LOGOUT
;LOGGING FUNCTIONS

;TYPE LOGOUT MESSAGE, DESTINATION DESIGNATOR IN 1

LOGTOT::HRROI 2,[ASCIZ /Killed/]
	CALLRET LOGUSD		;Log job and time used info, setup time for USAGE
				; and return from LOGTOT

;Perform USAGE for logout

LOGTUS:	MOVEI T1,.USLGO		;LOGOUT FUNCTION
	MOVEI T2,LOGLST
	USAGE			;USAGE JSYS
	 ERCAL XUSAGE		;REPORT FAILURE
	RET			;Return from LOGTUS
;LOGON MESSAGE, CALLED FROM .LOGIN

LOGONM::SKIPL 1,LOGDES
	DOBE			;WAIT FOR OTHER USE OF TTY TO FINISH
	HRROI 2,[ASCIZ /Login/]
	CALL LOGMES
	MOVE T2,CTRLTT		;T2/ LINE NUMBER
	CALL LOGJOB
	PUSH P,1
	MOVEI T1,.USLGI		;LOGIN FUNCTION
	MOVEI T2,LOGLST		;POINT TO PARAMETERS
	USAGE
	 ERCAL XUSAGE		;REPORT USAGE FAILURE
	POP P,1
	CALLRET LOGCR		;AND CRLF

XUSAGE:	BUG (UXXFAI)
	RET			;CONTINUE

;PARAMETER BLOCK FOR LOGIN/LOGOUT/SESSION CHANGE CALLS

LOGLST:	USENT. (.UTSEN,1,1)	;SESSION ENTRY TYPE
	USRTM. (JBRUNT)		;RUN-TIME
	USACT. (<-1,,ACCTSR>)	;ACCOUNT
	USSST. (CTIMON)		;SESSION START DATE/TIME
	USJTY. (-1)		;BATCH T/S FLAG
	USBJN. (JBBNAM)		;BATCH JOB NAME
	USBSN. (JBBSEQ)		;BATCH SEQ NUMBER
	USCOM. (<-1,,JSSRM+1>)	;SESSION REMARK
	USCCT. (CONCON)		;CONSOLE CONNECT TIME
	USPNM. (<SIXBIT "MONITR">,US%IMM)
	USPVR. ([EXP SVNM])	;MONITOR NAME AND VERSION
	USNM2. (<-1,,USRNAM+1>)	;USER NAME
	0			;END OF LIST
;CHANGED ACCOUNT NUMBER MESSAGE

LOGCJM::SKIPL 1,LOGDES
	DOBE
	HRROI 2,[ASCIZ /Changed/]
	CALL LOGUSD		;Log job and time used, setup for time for USAGE
	MOVE T2,JBRUNT		;Get session runtime
	ADDM T2,JSSRTM		;Update session runtime start for next session
	MOVE T2,CONCON		;Get session connect time
	ADDM T2,JSSCTM		;Update session console time start
	PUSH P,1		;SAVE OUTPUT DESIGNATOR
	MOVEI T1,.USSEN		;SESSION ENTRY CODE
	MOVEI T2,LOGLST		;PARAMS
	USAGE
	 ERCAL XUSAGE
	POP P,1			;RESTORE
	RET			;Return from LOGCJM
;Print job info, time used, and setup times for USAGE

LOGUSD:	CALL LOGMES		;Print message type
	MOVE T2,CTRLTT		;Get controlling terminal number
	CALL LOGJOB		;Type job and terminal info

	HRROI T2,[ASCIZ /,  Used /]
	CALL LOGMES		; . . .
	MOVE T2,JOBNO		;Get this job's number
	MOVE T2,JOBRT(T2)	;Get runtime of job
	MOVE T3,T2		;Copy it again
	SUB T3,JSSRTM		;Compute session runtime
	MOVEM T3,JBRUNT		;Save for USAGE
	CALL LOGTIM		;Print runtime

	HRROI T2,[ASCIZ / in /]
	CALL LOGMES		; . . .
	MOVE T2,TODCLK		;Get current uptime
	SUB T2,CONSTO		;Compute console time logged in
	MOVE T3,T2		;Copy console time
	SUB T3,JSSCTM		;Compute console time this session
	MOVEM T3,CONCON		;Save console time for USAGE
	CALL LOGTIM		;Print console time

	SKIPN JSSRTM		;Session start
	SKIPE JSSCTM		; at beginning of job?
	 SKIPA			;No-- print time this session
	JRST LOGUS2		;Yes-- don't repeat ourselves

	HRROI T2,[ASCIZ /,
  Used this session /]
	CALL LOGMES		; . . .
	MOVE T2,JBRUNT		;Get session time
	CALL LOGTIM		;Print it
	HRROI T2,[ASCIZ / in /]
	CALL LOGMES		; . . .
	MOVE T2,CONCON		;Get console time this session
	CALL LOGTIM		;Print it
LOGUS2:
	CALLRET LOGCR		;Finish with CRLF

;PRINT TIME FROM 2

LOGTIM:	JUMPL 1,R
	IDIVI 2,^D1000		;MS TO SECS
	IDIVI 2,^D60		;PEEL OFF SECONDS
	PUSH P,3
	IDIVI 2,^D60		;PEEL OFF MINUTES
	PUSH P,3
	CALL LOGNUM		;PRINT HOURS
	MOVEI 2,":"
	BOUT
	POP P,2
	CALL LOG2NM		;PRINT MINUTES
	MOVEI 2,":"
	BOUT
	POP P,2
	CALL LOG2NM		;PRINT SECONDS
	RET
;ATACH AND DETACH MESSAGES

;DETMSG - RECORD DETACHING OF JOB

;ACCEPTS:
;	T2/ LINE NUMBER

DETMSG:	STKVAR <DETMLN>
	MOVEM T2,DETMLN		;SAVE LINE NUMBER
	HRROI 2,[ASCIZ /Detached/] ;WORD FOR LOG TTY
	SKIPL 1,LOGDES
	DOBE
	CALL LOGMES
	MOVE T2,DETMLN		;T2/ LINE NUMBER
	CALL LOGJOB
				;*** DETACH ***
	CALLRET LOGCR		;CRLF AND RETURN

DETMS0:	ASUBR <ATAJN,ATALN>	;JOB # , LINE #
	HRROI 2,[ASCIZ /Detached job /]
	SKIPL 1,LOGDES
	DOBE
	CALL LOGMES
	MOVE 2,ATAJN		;GET REMOTE JOB NUMBER
	CALL LOGNUM
	HRROI 2,[ASCIZ / from TTY /]
	JRST ATAMS3

ATAMSG:	ASUBR <ATAJN,ATALN>	;JOB # , LINE #
	SKIPL 1,LOGDES
	DOBE
	HRROI 2,[ASCIZ /Attached job /]
	CALL LOGMES
	MOVE T2,ATAJN		;GET JOB NUMBER
	CALL LOGNUM		;PRINT IT
	HRROI 2,[ASCIZ / to TTY /]
ATAMS3:	CALL LOGMES
	MOVE T2,ATALN		;LINE NUMBER
	MOVEI 3,^D8		;PRINT IN OCTAL
	CALL LGNOUT
	CALL LOGJ2		;PRINT AND STORE TOD
				;*** ATTACH ***
	CALLRET LOGCR		; END WITH CRLF
;PRINTS  JOB 1, TTY 40, AT 12:34:56
;  OR    JOB 1, DETACHED, AT 12:34:56

;ACCEPTS:
;	T2/ LINE NUMBER

LOGJOB:	STKVAR <LOGJLN>
	MOVEM T2,LOGJLN		;T2/ LINE NUMBER
	HRROI 2,[ASCIZ / Job /]
	CALL LOGMES
	MOVE 2,JOBNO
	CALL LOGNUM
	MOVE 2,JOBNO
	HRRZ 2,JOBDIR(2)
	JUMPE 2,LOGJ3		;LOGGED IN NOW?
	HRROI 2,[ASCIZ /, User /]
	CALL LOGMES
	MOVE 2,JOBNO
	HRRZ 2,JOBDIR(2)
	HRLI 2,USRLH		;TURN IT INTO A 36 BIT USER NUMBER
	MOVE 3,1		;SAVE OUTPUT DESIGNATOR
	CAIL 1,0
	DIRST			;DIRECTORY NAME
	 MOVE 1,3		;IF ERROR, RESTORE OUTPUT DESIGNATOR
	HRROI 2,[ASCIZ /, Account /]
	CALL LOGMES
	CALL LOGACC
LOGJ3:	MOVE 2,LOGJLN
	JUMPL 2,LOGJ1		;IF NO CTRL TTY (DETACHED JOB)
	HRROI 2,[ASCIZ /, TTY /]
	CALL LOGMES
	MOVE 2,LOGJLN
	MOVEI 3,^D8		;PRINT TTY NUMBER IN OCTAL
	CALL LGNOUT
LOGJ2:	HRROI 2,[ASCIZ /,
  at /]
	CALL LOGMES
	PUSH P,1		;SAVE DESIGNATOR
	CALL LGTAD		;DO LOCAL GTAD
	MOVE 2,1
	POP P,1			;RESTORE DESTINATION
	JUMPL 1,R
	SETZ 3,			;STANDARD DATE AND TIME
	CAIL 2,0
	ODTIM
	RET

LOGJ1:	HRROI 2,[ASCIZ /, Detached/]
	CALL LOGMES
	JRST LOGJ2
LOGACC:	HRROI T2,ACCTSR		;POINT TO STRING
	MOVEI T3,0		;TERMINATE ON NULL
	CAIL T1,0		;VALID PNTR
	SOUT			;YES - OUTPUT STRING
	RET			;RETURN

LOGMES:	SETZ 3,
	SOUT
	RET

LOG2NM:	SKIPA 3,[EXP NO%LFL!NO%ZRO+^D2B17+^D10] ;Decimal, two digits
LOGNUM:	MOVEI 3,^D10		;DECIMAL FOR TIMES, ETC.
LGNOUT:	NOUT
	 JFCL
	RET

LOGCR:	HRROI 2,[ASCIZ /
/]
	SETZ 3,
	SOUT
	RET

;PRINTS   [JOB N DETACHED BY NAME] TO TTY OF JOB BEING ATTACHED
; OR UNATTACHED.
;ACCEPTS:	1/JOB # OF JOB BEING UNATTACHED
;		2/LINE # OF JOB BEING UNATTACHED
;		3/DIR # OF USER UNATTACHING THE JOB
;		4/TTY # OF USER UNATTACHING THE JOB

DETMS1:	TRVAR <<MSGBUF,25>,JOB,LINE,DIRN,DTTYN,TMPPTR>
	MOVEM 1,JOB		;SAVE INPUTS
	MOVEM 2,LINE
	MOVEM 3,DIRN
	MOVEM 4,DTTYN		;SAVE TTY # OF DETACHER
	HRROI 1,MSGBUF		;START FILLING BUFFER
	CALL LOGCR		;CRLF
	HRROI 2,[ASCIZ/[Job /]
	CALL LOGMES
	HRRZ 2,JOB		;JOB # TO BE PRINTED
	CALL LOGNUM
	HRROI 2,[ASCIZ/ detached by /]
	CALL LOGMES
	MOVE 2,DIRN
	MOVEM 1,TMPPTR		;SAVE PLACE IN BUFFER IN CASE DIRST FAILS
	DIRST			;GET USER WHO'S UNATTACHING THE JOB
	ERJMP DIRFIX
DETMS2:	SKIPGE DTTYN		;IS DETACHER ON A TTY?
	JRST DETMS3		;NO
	HRROI 2,[ASCIZ/ on terminal /]
	CALL LOGMES
	MOVE 2,DTTYN		;Get the TTY number
	MOVEI 3,10		;OCTAL NUMBER
	CALL LGNOUT
DETMS3:	HRROI 2,[ASCIZ/]/]
	CALL LOGMES
	CALL LOGCR		;CLOSE WITH CRLF
	MOVEI 1,.FHSLF
	ADD 1,LINE		;TTY LINE NUMBER
	HRROI 2,MSGBUF		;POINT TO NOW-COMPLETED MESSAGE
	TTMSG			;SEND IT OUT
	RET

;UNATTACHER NOT LOGGED IN

DIRFIX:	MOVE 1,TMPPTR		;RESTORE BUFFER POINTER
	HRROI 2,[ASCIZ/user/]
	CALL LOGMES		;PLACE PSEUDO-NAME IN BUFFER
	JRST DETMS2		;FINISH ASSEMBLING THE MESSAGE
;INFO JSYS'S

.GJINF::MCENT
	CALL GTCSCD		;GET CONNECTED STRUCTURE CODE,,DIRECTORY
	MOVE 2,1		;RETURN CONNECTED STR/DIR NUMBER
	MOVE 3,JOBNO
	HRRZ 1,JOBDIR(3)
	SKIPE 1			;IF NOT LOGGED IN, RETURN 0
	HRLI 1,USRLH		;TURN THIS INTO A 36 BIT USER NUMBER
	MOVE 4,CTRLTT
MR4:	UMOVEM 4,4
MR3:	UMOVEM 3,3
MR2:	UMOVEM 2,2
MR1:	UMOVEM 1,1
	JRST MRETN

.TIME::	MCENT
	MOVE 1,TODCLK		;TIME SINCE SYSTEM STARTED
	MOVEI 2,^D1000		;DIVISOR FOR SECONDS
	JRST MR2		;RETURN 2 AC'S

.RUNTM::MCENT
	NOSKED
	CALL UCLOCK		;UPDATE CLOCKS
	OKSKED
	CALL FLOCK		;LOCK THE FORK STRUCTURE
	XCTU [HRRZ 1,1]	;FORK HANDLE
	CAIN 1,-5		;WHOLE JOB?
	JRST RUNTM1		;YES
	CALL SETJFK
	CALL SETLF1
	MOVE 1,FKRT(1)		;FORK RUN TIME FROM PSB
	JRST RUNTM2

RUNTM1:	NOINT
	MOVE 1,JOBNO
	MOVE 1,JOBRT(1)
RUNTM2:	MOVE 3,TODCLK		;CURRENT TIME
	SUB 3,CONSTO		;LESS TIME ON, FOR CONSOLE TIME USED
	MOVEI 2,^D1000		;MILLISECONDS
RETA3:	UMOVEM 1,1		;RETURN VALUES IN 1,2,3
	UMOVEM 2,2
	UMOVEM 3,3
	JRST CLFRET

.GTRPI::MCENT
	CALL FLOCK		;LOCK THE FORK STRUCTURE
	CALL SETLFK
	MOVE 2,USWPCT(1)
	MOVE 3,PTTIM(1)
	IDIVI 3,^D100		;RETURN MILLISEC, NOT HPTIM UNITS
	MOVE 1,UTRPCT(1)
	JRST RETA3
;GET DIRECTORY ALLOCATION
;ACCEPTS IN 1/	DIR # OR -1 FOR CONNECTED DIR
;	GTDAL
;RETURNS +1:	1/	LOGGED IN QUOTA
;		2/	CURRENT ALLOCATION
;		3/	LOGGED OUT QUOTA

.GTDAL::MCENT
	UMOVE T1,1		;GET DIR #
	CAMN T1,[-1]		;-1 MEANS CONNECTED DIRECTORY
	CALL GTCSCD		;GET CONNECTED DIR NUMBER
	CALL IGTDAL		;USE INTERNAL ROUTINE
	 ITERR()		;FAILED
	JRST MR3		;RETURN 1, 2 AND 3

;INTERNAL GTDAL, 1/ DIRECTORY #

IGTDAL::STKVAR <IGTDN>
	MOVEM T1,IGTDN		;SAVE DIR #
	CALL SETDIR		;MAP THE DIRECTORY IN
	 RETBAD ()		;FAILED
	HRRZ T1,IGTDN		;DIRECTORY NUMBER
	LOAD T2,CURSTR		;STRUCTURE NUMBER
	CALL GETCAL		;GET CURRENT ALLOCATION
	 JRST [	MOVE T3,DIRORA	;DIR NOT OPENED
		LOAD T1,DRLIQ,(T3) ;LOGGED IN QUOTA
		LOAD T2,DRDCA,(T3) ;CURRENT ALLOCATION
		LOAD T3,DRLOQ,(T3) ;LOGGED OUT QUOTA
		JRST IGTDX]	;EXIT
	MOVE T3,DIRORA		;GET BASE ADR OF MAPPED DIR
	MOVN T2,T1		;NEGATE PAGES LEFT
	LOAD T1,DRLIQ,(T3)	;GET LOGGED IN QUOTA
	ADD T2,T1		;ACTUAL USED
	LOAD T3,DRLOQ,(T3)	;GET LOGGED OUT QUOTA
IGTDX:	CALL USTDIR		;UNLOCK THE DIR
	RETSKP			;GOOD RETURN

;HIGH PRECISION TIME JSYS
;MADE RESIDENT FOR SPEED

	RESCD

.HPTIM::MCENT
	CAIL 1,0		;CHECK RANGE OF ARG
	CAIL 1,NHPTIM
	RETERR(HPTX1)		;UNDEFINED CLOCK
	JRST HPTTAB(1)

HPTTAB:	JRST HPT0		;ELAPSED TIME
	JRST HPT1		;FORK RUNTIME
NHPTIM==.-HPTTAB

HPT0:	NOSKED
	JSP 4,MTIME		;READ TODCLK IN 1E-5 SECOND UNITS
	OKSKED
	UMOVEM 1,1
	SMRETN

HPT1:	NOSKED
	CALL UCLOCK		;UPDATE USER RUNTIMES
	OKSKED
	MOVE 1,FKRT		;GET MILLISECOND PART
	IMULI 1,NTMS		;CONVERT TO HP UNITS
	ADD 1,RUNT2		;INCLUDE FRACTION OF MILLISECOND
	UMOVEM 1,1
	SMRETN

	SWAPCD

;GET NUMBER OF TABLE AND FIRST WORD GIVEN SIXBIT SYMBOL
; 1/ SIXBIT 'TABLENAME'
;	SYSGT
; RETURN +1 ALWAYS, 
;  1/ -LENGTH,,TABLENUMBER  OR 0

.SYSGT::MCENT
	MOVSI 4,-GTBSIZ
	CAMN 1,SYMTAB(4)
	JRST SYSGT1
	AOBJN 4,.-2
	XCTU [SETZM 2]		;NOT FOUND RETURN 0
	JRST MRETN

SYSGT1:	HLRZ 2,GTTAB(4)		;SIZE
	MOVN 2,2		;NEGATE IT
	HRLI 4,0(2)		;COMBINE WITH TABLE NUMBER
	UMOVEM 4,2		;GIVE TO USER
	HRRZ T3,T4		;GET TABLE NUMBER
	SETZ T2,		;GET OFFSET ZERO
	XCT GTGET(T3)		;GO GET THE FIRST ENTRY
	UMOVEM 1,1		;GIVE FIRST WORD TO USER
	JRST MRETN

;GET TABLE ENTRY
; 1/ INDEX,,TABLENUMBER
;	GETAB
; RETURN +1: ERROR
; RETURN +2: 1/ DATA

.GETAB::MCENT
	MOVSI 2,(1B1)
	TDNN 2,CAPMSK		;GETAB CAPABILITY EXISTS?
	RETERR(GTABX3)		;NO
	HLRZ 2,1		;INDEX OR -1
	MOVEI 3,0(1)		;TABLE NUMBER
	CAIL 3,GTBSIZ		;LEGAL NUMBER?
	RETERR(GTABX1)		;NO
	HLRZ 1,GTTAB(3)		;GET SIZE OF TABLE
	CAIN 2,-1		;INDEX OF -1?
	JRST RETN1		;YES, RETURN NEG OF TABLE SIZE
	CAIL 2,0(1)		;INDEX WITHIN BOUNDS?
	RETERR(GTABX2)
	XCT GTGET(T3)		;GET WORD
	UMOVEM 1,1		;RETURN IT TO USER
	SMRETN

RETN1:	XCTU [MOVNM 1,1]	;RETURN NEG OF LENGTH
	SMRETN
;TABLES FOR GTTAB
;ALL TABLES DEFINED WITH FOLLOWING MACRO WHICH TAKES NAME OF
;ANOTHER MACRO TO CALL FOR EACH TABLE.
;*NOTE* TABLE INDICES ARE DEFINED IN MONSYM - ORDER AND PLACE
;MUST BE PRESERVED IF TABLES ARE ADDED OR DELETED.  PLACE
;MAY BE HELD BY CALL WITH NO ARGS.

;THE ARGUMENT TO GTABS IS A MACRO TO BE CALLED FOR EACH TABLE.
;FIVE ARGUMENTS ARE GIVEN, SIXBIT TABLE NAME, LOCATION, LENGTH, ROUTINE,
;SYMBOLIC VALUE FOR TABLE NUMBER (FROM MONSYM)

DEFINE GTABS (XXX)<
	XXX JOBTTY,JOBPT,NJOBS
	XXX JOBRT,JOBRT,NJOBS
	XXX TICKPS,[^D1000],1
	XXX			;;FORMERLY JOBDIR
	XXX TTYJOB,0,NLINES,GTBTTF
	XXX NCPGS,TOTRC,1
	XXX DEVNAM,DEVNAM,NDEV
	XXX DEVCHR,DEVCHR,NDEV
	XXX DEVUNT,DEVUNT,NDEV
	XXX DSKERR,DSKRCE,NDSKEW
	XXX DRMERR,DRMCFE,NDRMEW
	XXX SYSVER,SVN,NSVNT
	XXX SYSTAT,SKDTM0,NSTAT
	XXX QTIMES,QSUM,MAXQ+1
	XXX JOBNAM,JOBNAM,NJOBS
	XXX SNAMES,SNAMES,NNAMES
	XXX STIMES,STIMES,NNAMES
	XXX SPFLTS,SPFLTS,NNAMES
	XXX SSIZE,SSIZE,NNAMES
	XXX SNBLKS,SNBLKS,NNAMES
	XXX DBUGSW,DBUGSW,2
	XXX LOGDES,LOGDES,2
	XXX PTYPAR,0,1,GTBPTY
	XXX SYMTAB,SYMTAB,GTBSIZ
	XXX DWNTIM,HSYST1,NHSYST
	XXX JOBPNM,JOBPNM,NJOBS
	XXX BLDTD,SYSTAD,1
	XXX			;;FORMERLY LSTDRN
	XXX APRID,APRSER,1
	XXX HQLAV,HQLAV,NRJAVS
	XXX LQLAV,LQLAV,NRJAVS
	XXX NETRDY,IMPRDY,IMPGTN	;ARPANET
;THE FOLLOWING TWO TABLES ARE LEFT FOR COMPATABILITY REASONS ONLY
;THEY RETURN HOST STATUS BY THE OLD-STYLE 8 BIT HOST NUMBER
	XXX IMPHRT,0,IMPLBT,GTBHRT	;ARPANET
	XXX HSTSTS,0,NHSTST,GTBHSS	;ARPANET
	XXX HSTNAM,HSTNAM,NHSTN		;ARPANET
;SIMULATE GHOSTN AND NETAWD
	XXX HOSTN,0,NHOSTS,GHOSTN	;ARPANET
	XXX NETLSK,LSKT,NSKT		;ARPANET
	XXX NETFSK,FSKT,NSKT		;ARPANET
	XXX NETAWD,0,NSKT,GNTAWD	;ARPANET
	XXX NETBAL,NETBAL,NSKT		;ARPANET
	XXX NETSTS,NETSTS,NSKT		;ARPANET
	XXX NETBUF,NETBUF,NSKT		;ARPANET
	XXX NETBTC,NETBTC,NSKT		;ARPANET
	XXX IMPLT1,IMPLT1,IMPNLK,,.IMPL1 ;ARPANET
	XXX IMPLT2,IMPLT2,IMPNLK,,.IMPL2 ;ARPANET
	XXX IMPLT3,IMPLT3,IMPNLK,,.IMPL3 ;ARPANET
	XXX IMPLT4,IMPLT4,IMPNLK,,.IMPL4 ;ARPANET
	XXX LHOSTN,NOHOST,2		;ARPA HOST NUMBER, NVT COUNTER
	XXX JBONT,JOBONT,NJOBS		;OWNING JOB
	XXX NSWPGS,NSWPGS,1		;DEFAULT SWAPPING PAGES
   >

;ASSEMBLE SYMBOL TABLE

DEFINE SYMT (NAM,LOC,SIZ,ROUT,VALUE)<
   IFB <NAM>,<0>		;;LEAVE 0 IF PLACE RESERVED
   IFNB <NAM>,<
      IFB <VALUE>,<		;;IF VALUE WAS NOT SPECIFIED
	..X==.'NAM		;;GET NAME FROM MONSYM
.'NAM::!SIXBIT /NAM/>		;;CHECK TABLE INDEX, ASSEMBLE SIXBIT
      IFNB <VALUE>,<		;;IF VALUE WAS SPECIFIED
	..X==VALUE		;;GET NAME FROM MONSYM
VALUE::!SIXBIT /NAM/>>>		;;CHECK TABLE INDEX, ASSEMBLE SIXBIT

SYMTAB::!PHASE 0			;;MAKE TAGS BE RELATIVE TO 0
	GTABS SYMT		;;ASSEMBLE SYMTAB, CHECK INDEX MNEMONICS
GTBSIZ::DEPHASE

;ASSEMBLE POINTERS AND SIZES

DEFINE LOCT (NAM,LOC,SIZ,ROUT,VALUE)<
   IFB <NAM>,<0>		;;LEAVE 0 IF PLACE RESERVED
   IFNB <NAM>,<
	XWD SIZ,LOC>>

GTTAB::	GTABS LOCT

;DEFINE PROCESSING ROUTINE

DEFINE ACTR (NAM,LOC,SIZ,ROUT,VALUE)<
   IFB <NAM>, <SETZM T1>	;;NULL TABLE GIVES NULL ANSWER
   IFNB <NAM>,< IFB <ROUT>, <CALL GTGETR> ;;DFAULT PROCESSOR
   IFNB <ROUT>, <CALL ROUT> 	;;DO SPECIFIED PROCESS
        >
   >

GTGET:	GTABS ACTR		;DEFINE PROCESSING TABLES

;GENERAL GETTAB ROUTINE.
;	3/ TABLE NUMBER
;	2/ TABLE OFFSET
;RETURNS: +1 WITH T1/ ANSWER

GTGETR:	ADD T2,GTTAB(T3)	;GET TABLE BASE
	HRRZS T2		;CLEAR INDEX
	MOVE T1,0(T2)		;FETCH TABLE ENTRY
	RET			;AND DONE
;SUBSYSTEM STATISTICS LOGIC
; 1/ SIXBIT NAME OF SYSTEM PROGRAM BEING RUN OR (PRIV)
; 2/ SIXBIT NAME OF PROGRAM
;	SETSN
; RETURN +1: ALWAYS, NAME SET IN STATISTICS TABLE

.SETSN::MCENT
	NOINT
	MOVE 3,JOBNO
	MOVEM 2,JOBPNM(3)	;SET JOB PROGRAM NAME
	AOSE SNMLCK		;LOCK TABLE
	CBLK1			;OR WAIT TILL LOCKABLE
	HRLZ 3,SNMPT		;NEG COUNT OF ENTRIES
	CAMN 1,SNAMES(3)	;DESIRED NAME?
	JRST SNM1		;YES
	AOBJN 3,.-2		;NO, LOOKED AT ALL?
	MOVEI 3,0(3)
	CAIL 3,NNAMES-1		;TABLE NOW FULL?
	SKIPA 1,[SIXBIT /.OTHER/] ;YES, USE CATCH-ALL NAME
	SOS SNMPT		;UPDATE POINTER
	MOVEM 1,SNAMES(3)	;ADD NAME TO TABLE
SNM1:	MOVE 2,JOBNO
	HRRM 3,JOBNAM(2)	;PUT INDEX IN JOB TABLE
	SETOM SNMLCK		;UNLOCK TABLE
	OKINT
	SMRETN

NR SNMPT,1			;NEG COUNT OF ENTRIES IN SNAMES
NR SNMLCK,1			;LOCK FOR SNAMES TABLE

;PROGRAM NAME LOGIC

;SET NAME
; 1/ SIXBIT NAME OF PROGRAM
;	SETNM
; RETURN +1: ALWAYS, NAME SET AS PROGRAM NAME FOR JOB

.SETNM::MCENT
	MOVE 3,JOBNO		;GET THIS JOB NUMBER
	MOVEM 1,JOBPNM(3)	;SET THE NAME
	JRST MRETN

;GET NAME
;	GETNM
; RETURN +1: ALWAYS, 1/ SIXBIT NAME OF PROGRAM

.GETNM::MCENT
	MOVE 1,JOBNO
	MOVE 1,JOBPNM(1)
	JRST MR1		;RETURN 1 AC
;GETNAM -- SUBROUTINE TO CONSTRUCT VERSION AND SYSTEM NAME FROM TEXT
; IN THE FILE SYSTEM:MONNAM.TXT, OR IF THE FILE DOES NOT EXIST,
; TO USE THE DEFAULT TEXT ASSEMBLED INTO THE MONITOR IN THE BLOCK
; LABLED TSVN.  THE FORMAT OF THE RESULTING  TEXT IS:

; V D.DD.DD <TEXT>

; WHERE THE FIRST SEVERAL CHARACTERS IDENTIFY THE MONITOR VERSION AND ALWAYS
; COME FROM THE PREASSEMBLED STRING; AND THE <TEXT> COMES EITHER FROM
; THE FILE OR FROM THE PREASSEMBLED STRING.  THE ENTIRE STRING MAY
; BE UP TO 132(10) CHARACTERS LONG, SO <TEXT> MAY BE 122(10),
; OR 172(8) CHARACTERS LONG.  <TEXT> IN THE FILE SHOULD BE TERMINATED BY 
; EOL.


GETNAM:	STKVAR <A1>		;RESERVE SPACE FOR ONE TEMP
	MOVE T1,[POINT 7,SVN]	;BYTE POINTER TO DESTINATION
	MOVEM T1,A1		;SAVE UPDATED PTR. TO DEST. STRING
	MOVX T1,GJ%SHT!GJ%OLD	;FLAG FOR SHORT GTJFN CALL AND OLD FILE ONLY
	HRROI T2,[ASCIZ /SYSTEM:MONNAM.TXT/] ;IMPLICIT STRING PTR TO FILE NAME	
	GTJFN			;IS THERE A FILE?
	 JRST GETNA1		;NO FILE - DOESN'T MATTER WHY
	MOVX T2,<OF%RD+FLD(7,OF%BSZ)> ;FILE EXISTS, SET UP OPENF CALL
	OPENF			; ..
	 JRST GETNA1		;UNSUCCESFUL FOR ANY REASON, USE 
				; DEFAULT STRING
	MOVEI T3,<NSVNT-VTSVNT>*5-1	;MAX. # OF BYTES WE CAN MOVE
	MOVE T4,A1		;RECALL BYTE PTR TO BUFFER
GETNA2:	BIN			;GET NEXT CHARACTER FROM FILE
	CAIE T2,.CHCRT		;IS IT A CARRIAGE RETURN?
	CAIN T2,.CHLFD		;NO, IS IT A LINE FEED?
	JRST GETNA3		;A CR OR A LF WAS ENCOUNTERED
	JUMPE T2,GETNA3		;JUMP ALSO IF IT'S A NULL
	IDPB T2,T4		;IT'S A GOOD CHARACTER, PUT INTO BUFFER
	SOJG T3,GETNA2		;JUMP IF WE HAVN'T EXHAUSTED ALL BUT
				; ONE BYTE POSITION IN BUFFER.
;MANUAL MERGE OF 1B CHANGES
GETNA3:	CLOSF			;YES, CLOSE FILE, RELEASE JFN
	 JFCL			;IGNORE FAILURE
	MOVE T1,T4		;GET STRING POINTER AGAIN
	HRROI T2,VTSVN		;IMPLICIT STRING POINTER TO VERSION
	SETZ T3,		;STOP ON A NULL
	SOUT			;MOVE PREASSEMBLED VERSION TO BUFFER
	RET			;EXIT

GETNA1:	HRROI T1,SVN		;IMPLICIT BYTE POINTER OF DESTINATION
	HRROI T2,TSVN		;IMPLICIT BYTE POINTER TO PREASSEMBLED
				; MONITOR NAME
GETNA5:	SETZ T3,		;SPECIFY TERMINATION ON A NULL
	SOUT			;MOVE PREASSEMBLED STRING TO BUFFER
				; THE MOVE INCLUDED A TERMINATING NULL 
	RET			; SO -- WE'RE DONE
		
;GET JOB INFORMATION
; 1/ JOB #, OR -1 FOR SELF, OR TTY # + 400000
; 2/ -N,,USER ADR
; 3/ FIRST ENTRY DESIRED
;	GETJI
; RETURN +1: FAILURE
; RETURN +2: SUCCESS, ENTRIES STORED IN USER ARRAY
;REQUIRES GETAB CAPABILITY IF JOB OTHER THAN SELF

.GETJI::MCENT
	UMOVE P2,3		;GET NUMBER OF FIRST ENTRY DESIRED
	HRL P2,P2		;DUPLICATE IN BOTH HAVLES
	JUMPL P2,[RETERR (GTJIX1)] ;INSURE NOT NEGATIVE
	ADD P2,[-NGTJIT,,0]	;SETUP AOBJN PTR TO FIRST ENTRY
	JUMPGE P2,[RETERR (GTJIX1)] ;ALREADY BEYOND END OF TABLE
	UMOVE P3,2		;GET USER 'S ADR POINTER
	CAMN 1,[-1]		;SELF?
	JRST [	MOVE 1,JOBNO	;YES, GET THIS JOB NUMBER
		JRST GETJI5]	;SKIP CAPABILITY CHECK
	MOVX 2,SC%GTB
	TDNN 2,CAPMSK		;HAS GETAB CAPABILITY?
	RETERR (GTABX3)		;NO
	TRZE 1,400000		;TTY DESIGNATOR?
	JRST [	CAIL 1,0	;YES, LEGAL LINE NUMBER?
		CAIL 1,NLINES
		RETERR (GTJIX2)	;NO
		MOVE T2,T1	;T2/ LINE NUMBER
		CALL GTCJOB	;GET OWNING JOB NUMBER
	 	 JRST GETJI6	;JUMP IF NOT ACTIVE
		CAIN T3,-1	;IS THERE AN OWNING JOB?
		JRST GETJI6	;NO.
		MOVE T2,T3	;YES. PRESERVE JOB NUMBER
		HLRZ T3,JOBPT(T2) ;GET CONTROLLING TTY FOR JOB
		CAME 3,1	;SAME AS GIVEN TTY?
		JRST GETJI1	;NO, TTY IS ASSIGNED NOT CONTROLLING
		MOVE 1,2	;SETUP JOB NUMBER
		JRST .+1]	;CONTINUE WITH JOB NUMBER
	CAIL 1,0		;LEGAL JOB NUMBER?
	CAIL 1,NJOBS
	RETERR (GTJIX3)		;NO
GETJI5:	NOSKED			;DON'T ALLOW JOB TO LOG OUT
	SKIPGE JOBRT(T1)	;JOB EXISTS?
	RETERR (GTJIX4,<OKSKED>) ;NO. GIVE APPROPRIATE ERROR
	MOVEM 1,P1		;SAVE JOB NUMBER
	CALL SETJSB		;MAP IN JSB OF OBJECT JOB
	OKSKED			;OK TO ALLOW SCHEDULING. JOB CAN'T LOGOUT
				; SINCE ITS JSB IS MAPPED
	MOVEM T1,P4		;SAVE JSB OFFSET
GETJI2:	XCT GETJIT(P2)		;GET ITEM
	 UMOVEM 1,0(P3)		;GIVE IT TO USER (ROUTINES THAT SKIP HAVE ALREADY DONE THIS)
	AOBJP P3,GETJI3		;COUNT USER'S COUNT AND ADR
	AOBJN P2,GETJI2		;COUNT OUR COUNT AND ADR
GETJI3:	CALL CLRJSB		;UNMAP JSB OF OBJECT JOB
GETJIX:	UMOVEM P3,2		;UPDATE USERS PTR
	SMRETN
;GETJI...
;HERE IF TTY GIVEN AND NO CONTROLLING JOB
;GETJI6 - NO JOB OWNS THIS TERMINAL; GETJI1 - A JOB OWNS THIS TERMINAL
;BUT IT IS NOT THE JOB'S CONTROLLING TERMINAL

GETJI6:	SETOM T2		;INDICATE NO OWNING JOB
	SKIPA
GETJI1:	TLO 2,(1B1)		;SAY ASSIGNED
GETJI4:	XCTU [SKIPE 3]		;DOES USER WANT FIRST ENTRY?
	JRST GETJIX		;NO, NOTHING TO DO
	UMOVEM 2,0(P3)		;YES, STORE IT
	AOBJN P3,.+1		;UPDATE HIS POINTER
	JRST GETJIX		;RETURN

;TABLE OF GETJI ITEMS - WORD IS EXECUTED TO GET ITEM IN AC1

GETJIT:	MOVE 1,P1		;JOB NUMBER
	HLRE 1,JOBPT(P1)	;TTY NUMBER OR -1 IF DETACHED
	CALL GETSN5		;GET LOGIN DIRECTORY NUMBER
	CALL GETSN4		;GET CONNECTED STRUCTURE,,DIRECTORY
	CALL GETSN1		;SUBSYSTEM NAME
	MOVE 1,JOBPNM(P1)	;PROGRAM NAME
	MOVE 1,JOBRT(P1)	;RUN TIME
	CALL GETSN3		;JOB NUMBER OF OWNER OF PTY IF ANY
	CALL GETRTL		;GET RUNTIME LIMIT OF JOB
	CALL GETBB		;GET BATCH BIT
	CALL GETJID		;GET DENSITY
	LOAD T1,JSMTP,(P4)	;GET MAGTAPE PARITY DEFAULT
	CALL GETJIM		;GET MAGTAPE DATA MODE
	CALL GETJRS		;GET MAGTAPE RECORD SIZE
	LOAD T1,JSDFS,(P4)	;GET DEFERRED SPOOLING BIT
	CALL GETSN6		;GET THE LOGGED IN DIRECTORY NUMBER
	CALL GETJSR		;GET SESSION REMARK
	MOVE T1,LSTLGN(P4)	;PICK UP LAST LOGIN D&T
	MOVE T1,JSSRTM(P4)	;(.JISRT) Get session start runtime
	MOVE T1,JSSCTM(P4)	;(.JISCT) Get SESsion start console time
	CALL GETT20		;GET TOPS20 COMMAND LEVEL FLAG
	MOVE T1,SRTTIM(P4)	;GET TIME JOB WAS INITIALIZED
	MOVE T1,BATSTF(P4)	;GET BATCH STREAM AND FLAGS WORD
	CALL GETLL		;GET LOGICAL LOCATION
NGTJIT==.-GETJIT

;ACTION ROUTINES FOR ITEMS NOT AVAILABLE IN SINGLE MOVE

;GET CONNECTED STRUCTURE,,DIRECTORY

;GET CONNECTED STRUCTURE,,DIRECTORY

GETSN4:	MOVE T1,P4		;T1/OFFSET FOR ADDRESSING JSB
	CALL GTOJCD		;GET CONNECTED STRUCTURE CODE,,DIRECTORY
	RET

;GET LOGGED DIR NUMBER

GETSN5:	HRRZ T1,JOBDIR(P1)	;GET DIR NUMBER
	SKIPE T1		;IF NOT LOGGED IN, RETURN 0
	HRLI T1,USRLH		;MAKE IT BE A 36 BIT USER NUMBER
	RET

;GET -1 OR 0 FOR TOPS20 COMMAND LEVEL OR USER LEVEL

GETT20:	LOAD T1,JBT20,(P4)	;GET TOPS20 BIT
	MOVN T1,T1		;BIT ON => -1 (AT TOPS20 COMMAND LEVEL), BIT OFF => 0 (NOT AT T20)
	RET

;GET THE LOGGED IN DIRECTORY NUMBER

GETSN6:	MOVEI T1,PSNUM		;DIR IS ON PUBLIC STR
	CALL STRCNV		;CONVERT IT
	 RETERR (,<CALL CLRJSB>)
	HRLZS T1		;GET UNIQUE CODE IN THE LEFT HALF
	HRR T1,JOBDIR(P1)	;GET THE DIRECTORY NUMBER
	RET			;AND RETURN

;GET SUBSYSTEM NAME

GETSN1:	HRRZ 1,JOBNAM(P1)	;GET STATISTICS INDEX
	MOVE 1,SNAMES(1)	;GET NAME
	RET

;GET JOB NUMBER OF OWNER OF PTY

GETSN3:	HLRE 1,JOBPT(P1)	;GET CONTROLLING TTY
	JUMPL 1,RETO		;RETURN -1 IF DETACHED
	CALL PTYGFK		;GET FORK WHICH OWNS PTY
	 JRST RETO		;NO PTY, RETURN -1
	MOVEM 1,FX
	LOAD 1,FKJOBN		;GET JOB NUMBER WHICH OWNS FORK
	RET


;GET BATCH BIT

GETBB:	HLRE T1,JOBPT(P1)	;GET CONTROLING TTY
	JUMPL T1,RETZ		;IF NONE, JOB NOT CONTROLLED BY BATCH
	CALL PTYGBB		;GET BATCH BIT
	 JRST RETZ		;NOT A PTY
	RET			;ANSWER IS IN T1


;GET MAGTAPE DENSITY

GETJID:	LOAD T1,JSMTD,(P4)	;GET DEFAULT DENSITY
	SKIPN T1		;USING SYSTEM DEFAULT?
	MOVEI T1,MTDFDN		;YES
	RET


;GET MAGTAPE DATA MODE

GETJIM:	LOAD T1,JSMTM,(P4)	;GET DEFAULT DATA MODE
	SKIPN T1		;USING SYSTEM DEFAULT
	MOVEI T1,MTDFDM		;YES
	RET


;GET MAGTAPE RECORD SIZE

GETJRS:	LOAD T1,JSMTR,(P4)	;GET RECORD SIZE
	SKIPN T1		;USING SYSTEM DEFAULT?
	MOVEI T1,MTDFRS		;YES
	RET
;GET RUNTIME LIMIT FOR THIS JOB

GETRTL:	LOAD T1,JOBRTP,(P1)	;GET POINTER TO RUNTIME LIMIT BLK
	JUMPE T1,R		;WAS NONE
	LOAD T1,TIMTIM,(T1)	;GET ACTUAL LIMIT
	RET

;GET SESSION REMARK

GETJSR:	MOVEI T2,JSSRM(P4)	;ADDRESS OF REMARK IN JSB
GU1:	UMOVE T1,0(P3)		;PLACE WHERE USER WANTS REMARK PUT
	HRRZ T3,P3		;GET USER ADDRESS FOR UPDATED POINTER
	CALL CPYTU1		;COPY REMARK TO USER SPACE
	RETSKP			;SKIP SO POINTER DOESN'T GET UPDATED TWICE!

;GET LOGICAL LOCATION

GETLL:	MOVEI B,LLSR-1(P4)	;ADDRESS OF LOCATION STRING (MINUS ONE FOR CPYTU1)
	CALLRET GU1		;USE STANDARD MAGIC FOR FINISHING UP
;CONVERT ASCIZ PTR TO SIXBIT WORD
; 1/ BYTE PTR TO ASCIZ STRING
;	CALL ASZSIX
; RETURN +1: FAILURE, ILLEGAL CHARACTER
; RETURN +2: 1/ WORD OF SIXBIT
;  ASCIZ STRING LONGER THAN 6 CHARACTERS IS TRUNCATED

ASZSIX::STKVAR <WSIX>		;DECLARE LOCAL VAR FOR SIXBIT WORD
	SETZM WSIX		;CLEAR SIXBIT WORD
	MOVE 3,[POINT 6,WSIX]
	MOVEI 4,6		;6 CHARS MAX
SNM3:	XCTBU [ILDB 2,1]	;GET CHAR FROM USER
	JUMPE 2,SNM4		;END OF STRING IF NULL
	CAIL 2,40		;LEGAL CHARACTER?
	CAIL 2,140
	RET			;NO, DO +1 RETURN
	SUBI 2,40		;CONVERT TO SIXBIT
	IDPB 2,3		;BUILD SIXBIT
	SOJG 4,SNM3		;COUNT CHARS
SNM4:	MOVE 1,WSIX		;GET SIXBIT
	RETSKP
;LIGHTS, SWITCHES, AND OTHER MAINTENANCE STUFF

.SWTCH:: MCENT
	MOVE 2,CAPENB
	TXNN 2,SC%WHL+SC%OPR+SC%MNT ;SUFFICIENT CAPABILITIES?
	JRST CAPXR		;NO
	SETZ T1,		;INIT ANSWER
	UMOVEM 1,1
	SMRETN

.LITES::MCENT
	MOVE 2,CAPENB
	TRNN 2,SC%WHL+SC%OPR+SC%MNT ;REQUIRES STATUS
	JRST CAPXR
	SMRETN

.USRIO::MCENT
	MOVEI 1,SC%WHL+SC%OPR+SC%MNT
	TDNN 1,CAPENB		;REQUIRES STATUS
CAPXR:	RETERR(CAPX2)		;RETURN BAD, USER LACKS CAPABILITIES
	MOVSI 1,(1B6)		;USER IO BIT
	IORM 1,0(P)		;PUT IT ON
	SMRETN
;PEEK - AC1:  N,,MONLOC
;       AC2:     USRLOC

.PEEK::	MCENT
	MOVEI 3,SC%WHL+SC%OPR+SC%MNT
	TDNN 3,CAPENB		;HAS NECESSARY CAPS?
	RETERR(CAPX2)		;NO
	MOVSI 5,0(1)		;SETUP BLT ARGS - FROM
	HRRI 5,0(2)		; .. TO
	MOVEI 6,0(2)
	HLRZ 3,1		;COUNT
	HRRZ T4,T1		; FIND MONITOR LIMIT
	ADD T4,T3
	ADDI 6,-1(3)		; .. TO LIMIT

;CHECK ALL PAGES OF SOURCE BLOCK FOR PROPER ACCESS

	MOVEI 1,0(1)		;GET MONITOR ADDRESS
PEEK1:	PUSH P,1
	MRPAC			;GET ACCESS OF MONITOR PAGE
	TLNN T1,-1		;LEGAL RANGE? ** TO BE CHANGED FOR XADR **
	TLNN 2,(PA%RD)		;READABLE?
	RETERR(PEEKX2)		;NO
	POP P,1
	IORI 1,777		;BUMP ADDRESS TO NEXT PAGE
	ADDI 1,1
	CAMGE 1,T4		;CHECKED ALL PAGES?
	JRST PEEK1		;NO, GO CHECK NEXT ONE
	UMOVE T3,T2		;GET TO ADDRESS FROM USER
	UMOVE T2,T1		;GET FROM ADDRESS AGAIN
	HLRZ T1,T2		;FIND SIZE
	HRLI T2,MSEC1		;SECTION 1 IN MONITOR
	CALL BLTMU1		;TRANSFER FROM MONITOR TO USER
	SMRETN

;ERROR - SC%WHL OR SC%OPR REQUIRED BUT NOT ENABLED

WHEELX:	ITERR(WHELX1)
;DETACH FROM CONTROLLING TTY

.DTACH::MCENT
	MOVEI T1,-1		;FINISH OUTPUT ON CONTROLLING TERMINAL
	DOBE			; BECAUSE TTYDAS WILL RELEASE BUFFERS
	CALL LDTACH		;DO THE WORK
	JRST MRETN

;DTACH CALLED INTERNALLY

LDTACH:	STKVAR <LDTALN>
LDTAC2:	SKIPGE T2,CTRLTT	;DOES JOB HAVE A CONTROLLING TERMINAL?
	RET			;NO. DON'T DO ANYTHING
	HRLOI T1,(TL%CRO+TL%COR+TL%SAB+TL%ABS)
	CAMN T2,CTYLNO		;Detaching CTY?
	TXZ T1,TL%ABS		;Always leave CTY refusing links
	MOVEI T2,-1
	TLINK			;BREAK LINKS
	 JFCL
	CALL LCKDVL		;LOCK DEVICE LOCK, NO NOINT
	MOVE T2,CTRLTT		;GET JOB'S CONTROLLING TERMINAL
	MOVEM T2,LDTALN		;SAVE LINE NUMBER
	CALL STADYN		;POINT TO DYNAMIC DATA
	 JRST LDTAC3		;NOT ACTIVE. SHOULDN'T HAPPEN
	CALL TTFWAK		;WAKE UP PROCESS IN INPUT WAIT ON THIS LINE
	MOVE T2,LDTALN		;T2/ LINE NUMBER
	CALL TTYDAS		;DEASSIGN DYNAMIC DATA
	 JRST [	UNLOCK DEVLCK	;FAILED - UNLOCK DEVICE LOCK
		OKINT		;LCKDVL WENT NOINT
		TXZN T1,1B0	;ERROR OR WAIT?
		RET		;ERROR. CURRENTLY NO WAY TO HANDLE THIS
		HRL T1,LDTALN	;T1/(LINE NUMBER,,ADDRESS OF TEST ROUTINE)
		MDISMS		;WAIT UNTIL DEALLOCATION IS POSSIBLE
		JRST LDTAC2]	;TRY AGAIN
LDTAC3:	SETOM CTRLTT		;INDICATE JOB DOESN'T HAVE CONTROLLING TERMINAL
	MOVE T1,JOBNO
	HRROS JOBPT(T1)
	UNLOCK DEVLCK		;UNLOCK DEVICE LOCK
	HRRE T1,JOBDIR(T1)
	CAIE T1,0		;LOGGED IN?
	JRST [	MOVE T2,LDTALN	;T2/ LINE NUMBER
		CALL DETMSG	;YES. NOTE EVENT ON LOGGING TERMINAL
		JRST .+1]
	OKINT
	RET

;LDET2 - DETACH JOB FROM TERMINAL WITHOUT DEALLOCATING TERMINAL DATA

;RETURNS +1: ALWAYS

;PRESERVES T2

LDET2:	STKVAR<LDETSV>
	HRLOI T1,(TL%CRO+TL%COR+TL%SAB+TL%ABS)
	MOVE T2,CTRLTT		;GET CONTROLLING TERMINAL
	CAMN T2,CTYLNO		;Check for CTY
	TXZ T1,TL%ABS		;CTY should default to refuse links
	MOVEI T2,-1
	TLINK			;BREAK LINKS
	 JFCL
	CALL UNPAGE		;CLEAR PAGING
	MOVE 2,CTRLTT		;T2/ CONTROLLING TERMINAL NUMBER
	MOVEM T2,LDETSV		;SAVE IT
	MOVE 1,JOBNO
	HRRE T1,JOBDIR(T1)	;GET LOGGED IN DIRECTORY
	CAIE T1,0		;LOGGED IN?
	CALL DETMSG		;YES, DO MESSAGE AND EFACT
	SETOM CTRLTT		;INDICATE NO CONTROLLING TERMINAL
	MOVE T1,JOBNO		;GET JOB NUMBER
	HRROS JOBPT(T1)		;INDICATE NO CONTROLLING TERMINAL
	MOVE T2,LDETSV		;T2/ LINE NUMBER
	CALL LCKTTY		;POINT TO DYNAMIC DATA
	 SKIPA			;NOT ACTIVE
	CALL TTFWAK		;WAKE FORK IN INPUT WAIT ON THIS LINE
	CALL ULKTTY		;ALLOW DEALLOCATION
	MOVE T2,LDETSV		;RESTORE LINE NUMBER
	RET

;ROUTINE TO TURN OFF PAGE MODE FOR CONTROLLING TERMINAL.
;CLOBBERS A AND B

UNPAGE:	MOVEI A,.PRIOU		;THE CONTROLLING TERMINAL
	MOVEI B,.MOXOF		;CLEAR PAUSE ON END
	SETZM C
	MTOPR			;DO IT
	RET			;AND DONE
;PROCEDURE TO HANDLE DATASET CARRIER OFF OR PTY CLOSED.
;DETACH JOB IMMEDIATELY, LOGOUT AFTER 5 MINUTES IF NOT REATTACHED.
;INVOKED ON REQUEST BY PSI SERVICE

JOBCOF::SKIPGE SLOWF		;IN JSYS CONTEXT?
	JRST [	MCENTR		;NO, GET THERE
		PUSH P,[MRETN]	;SETUP RETURN
		JRST .+1]
	SAVET
	MOVE 1,JOBNO
	SKIPGE B,CTRLTT		;HAVE A CONTROLLING TTY?
	JRST JOBCF1		;NO
	CALL GTCJOB		;GET ITS OWNING JOB
	 JRST JOBCF2		;NONE. GO ON
	CAIN C,0(A)		;SAME AS THIS ONE?
	JRST JOBCF1		;YES. GO ON
JOBCF2:	SETOM CTRLTT		;NO. CLEAR THIS ASSIGNMENT
	HRROS JOBPT(A)		;ALSO CLEAR CONTROLLING TTY HERE
JOBCF1:	HRRZ 1,JOBDIR(1)	;SEE IF NOW LOGGED IN
	JUMPE 1,FLOGO		;LOGOUT IMMEDIATELY IF NOT
	MOVE T1,FORKX		;GET OUT FORK INDEX
	CALL LDTACH		;DO LOCAL DETACH
	CALL FFORKI		;INDIRECTLY FREEZE ALL INFERIORS
	MOVE 1,[^D<5*60000>]	;SETUP TO WAIT 5 MINUTES
	CALL SETBKT		;COMPUTE BLOCKT DATA
	HRRI 1,COFTST		;SETUP SPECIAL TEST
	MOVSI T2,FHV1		;LOW BLOCK PRIORITY
	HDISMS
	MOVE 1,JOBNO		;SEE IF NOW ATTACHED
	SKIPGE JOBPT(1)
	JRST FLOGO		;NOT ATTACHED, SO LOGOUT
	NOINT			;KEEP CONTROL
	HLRZ T2,JOBPT(T1)	;GET CONTROLLING TTY
	MOVEI T3,"C"-100	;FAKE A CONTROL-C
	CALL TTPSRQ		;""
	CALL RFORKI		;RESUME ALL INDIRECTLY FROZEN INFERIORS
	OKINT			;ALLOW INTS AGAIN
	RET

;SCHEDULER TEST FOR ABOVE. WAITS UNTIL JOB ATTACHED OR SPECIFIED TIME
;ELAPSED

	RESCD

COFTST:	LOAD 2,FKJOBN		;GET JOB NUMBER
	SKIPL JOBPT(2)		;NOW ATTACHED?
	JRST 1(4)		;YES, WAKEUP
	JRST BLOCKT		;NO, GO TEST TIME

	SWAPCD
;ATTACH JOB TO TTY

;ACCEPTS:
;	T1/ FLAGS,,JOB NUMBER TO ATTACH TO
;	T2/ USER NUMBER OF JOB IN AC 1
;	T3/ POINTER TO PASSWORD STRING
;	T4/ DESIGNATOR FOR TERMINAL TO BE USED IF AT%TRM FUNCTION OF 1
;	    IS ON.

;	ATACH

;RETURN +1: FAILURE, ERROR CODE IN 1
;RETURN +2: SUCESS.

.ATACH::MCENT
	ACVAR <Q1,Q2,Q3>	;DEFINE ALL Q'S TO USE AS WORK REGS
	STKVAR <ATACJN,ATACDR,ATACLN>
	UMOVE Q1,1		;BITS MODIFYING THE ATACH
	TXNE Q1,AT%TRM		;PROXY ATTACH
	JRST ATACH1		;YES.  DO NOT CARE ABOUT USER NUMBER
	HLRZ T3,T2		;GET UNIQUE CODE OF USER NUMBER
	CAIE T3,USRLH		;IS THIS A LEGAL USER NUMBER?
	RETERR (ATACX3)		;NO, GIVE ERROR RETURN
ATACH1:	MOVEI T1,0(T1)		;GET OBJECT JOB NUMBER
	JUMPE T1,[RETERR (ATACX1)] ;CAN'T ATTACH TO JOB 0
	MOVEM T1,ATACJN		;SAVE JOB NUMBER TO ATTACH TO
	CAIGE T1,NJOBS		;REASONABLE JOB NUMBER?
	SKIPGE JOBRT(T1)	;AND JOB EXISTS?
ATACH5:	RETERR(ATACX1)		;NO
	TXNN Q1,AT%TRM		;PROXY ATTACH
	JRST ATACH8		;NO.
	UMOVE Q3,4		;GET TTY NUMBER TO ATACH THE JOB TO
	ANDI Q3,377777		;JUST LINE NUMBER PART
	CAIL Q3,NLINES		;EXISTANT LINE?
	RETERR ATACX1		;NO. FAIL.
ATACH8:	HRRZ T3,JOBDIR(T1)	;DIRECTORY OF  OTHER JOB
	MOVEM T3,ATACDR		;SAVE DIRECTORY NO. FOR FACT FILE
	CAIE T3,0(T2)		;SAME AS SPECIFIED?
	RETERR(ATACX3)		;NO

;SEE IF USER CAN LEGALLY ATTACH OTHER JOB.  ATTACH IS LEGAL IF
;BOTH JOBS ARE SAME USER, IF THIS USER IS SC%WHL, OR IF
;USER GIVES PROPER PASSWORD
;ALSO, ATACH IS LEGAL IF JOB BEING ATTACHED IS OWNED BY THE
;SAME USER AS THE OWNER OF THE PTY CONTROLLING THE JOB DOING THE
;ATACH AND THE JOB DOING THE ATACH IS NOT YET LOGGED IN.
;ALSO, IF OWNER OF PTY IS AN ENABLED WHEEL OR OPR, JOB
;ON PTY MAY ALWAYS DO ATACH.
;ALSO, LEGAL IF OBJECT JOB IS OWNED BY ATACH-ER, DUE TO CRJOB.

	MOVE T2,JOBNO		;GET THIS JOB NUMBER
	HRRZ T2,JOBDIR(T2)	;GET USER NUMBER FOR THIS JOB
	CAMN T2,T3		;SAME AS OTHER JOB?
	JRST ATACH3		;YES, NO FURTHER LEGALITY CHECKS
	JUMPN T2,ATACH6		;PTY OWNER IS IRRELEVANT IF NOT LOGGED IN
	MOVE T1,CTRLTT		;SEE IF I AM ON A PTY
	CALL PTGETJ		;GET CONROLLING JOB # OR -1
	JUMPL T1,ATACH6		;NON-PTY DOING THE ATACH IF -1
	HRRZ T4,JOBDIR(T1)	;T4 GETS OWNER OF PTY
	XCTU [HRRZ T3,T2]	;GET OWNER OF JOB BEING ATACHED
	CAMN T3,T4		;THE SAME?
	JRST ATACH3		;YES, SO NO PASSWORD NEEDED
	CALL GJCAPS		;GET CAPABILITIES OF OWNER OF PTY
	TXNE T1,SC%WHL+SC%OPR	;PRIVILEGED?
	JRST ATACH3		;YES, SO NO PASSWORD NEEDED
ATACH6:	MOVE T3,ATACDR		;GET DIR NUMBER
	MOVEI T1,SC%WHL+SC%OPR
	TDNE T1,CAPENB		;THIS USER HAS CAPS?
	JRST ATACH3		;YES, NO FURTHER CHECKS
	MOVE T1,ATACJN		;SEE IF I OWN THE JOB
	HRRZ T1,JOBONT(T1)	;OWNER FIELD
	CAMN T1,JOBNO		;IS IT ME?
	JRST ATACH3		;YES, THEN IT'S LEGAL.
	UMOVE T1,2		;GET USER NUMBER FOR PASSWORD CHECK
	CALL CNVDIR		;GET USER'S LOGGED-IN DIRECTORY NUMBER
	UMOVE T2,T3		;GET PTR TO PASSWORD STRING
	TRNE T3,-1		;FAIL IF JOB NOT LOGGED IN
	CALL PASSWC		;PROPER PASSWORD?
	 JRST [	MOVE T2,T1	;SAVE FLAG
		MOVEI T1,^D3000	;NO, DELAY TO FOIL PASSWORD THIEVES
		SKIPN T2	;NEED TO SLEEP?
		DISMS
		RETERR(ATACX4)]	;NOW BOMB OUT
;USER HAS PROVEN RIGHT TO DO THIS. THE FOLLOWING DATA IS AVAILABLE:
;	JOBNO/ JOB NUMBER OF CALLER OF JSYS
;	CTRLTT/ TERMINAL AT WHICH CALLER IS RUNNING
;	ATACJN/ JOB NUMBER TO BE ATTACHED TO THIS TERMINAL

;USER WANTS TO ASSOCIATE THE JOB IN ATACJN WITH THE TERMINAL IN CTRLTT
;IF THE JOB IS CURRENTLY ATTACHED, IT MUST BE DETACHED FIRST

ATACH3:	TXNE Q1,AT%TRM+AT%NAT	;IS MY TTY TO BE USED?
	JRST ATACH9		;NOT BY DEFAULT, ANYWAY.
	SKIPGE Q3,CTRLTT	;YES. GET MY TTY
	RETERR ATACX2		;I DON'T HAVE ONE. FAIL.
ATACH9:	TXNN Q1,AT%TRM		;USING A DIFFERENT LINE?
	JRST ATACHB		;NO
	HRRZ T2,Q3		;YES, BETTER ASSIGN SOME DYNAMIC DATA
	CALL TTYASC		;ASSIGN AS CONSOLE
	 RETERR
ATACHB:	MOVE T1,ATACJN		;GET BACK OBJECT JOB NUMBER
	CALL SETJSB		;SETUP OTHER JOB'S JSB
	MOVEI Q2,0(T1)		;SAVE OFFSET FOR OTHER JOB'S JSB
	SKIPGE T2,CTRLTT(Q2)	;OTHER JOB NOW ATTACHED?
	JRST ATACH2		;NO. DON'T DETACH IT

;OBJECT JOB IS ATTACHED. DETACH IT FROM ITS CURRENT CONTROLLING
;TERMINAL AND DEALLOCATE THAT TERMINAL'S DATA

	MOVEM T2,ATACLN		;SAVE ITS CONTROLLING TERMINAL
	CALL LCKDVL		;LOCK DEVICE LOCK, GO NOINT
	NOSKED			;MUST DETACH IT FIRST
	CALL STADYN		;POINT TO DYNAMIC DATA
	 JRST [	OKSKED		;NOT ACTIVE. DON'T DEASSIGN IT
		JRST ATACH7]
	CALL TTFWAK		;WAKE FORK IN INPUT WAIT ON THIS LINE
	OKSKED
	MOVE T2,ATACLN		;T2/ LINE NUMBER
	CALL TTYDAS		;DEASSIGN THE LINE
	 JRST [	PUSH P,T1	;SAVE THE ERROR CODE
		CALL CLRLFK	;UNMAP THE JSB
		UNLOCK DEVLCK	;UNLOCK DEVICE LOCK
		OKINT		;LCKDVL WENT NOINT
		POP P,T1	;GET THE CODE BACK
		TXZN T1,1B0	;NEED TO WAIT?
		RETERR		;NO. RETURN FAILURE
		HRL T1,ATACLN	;T1/(LINE NUMBER,,ADDRESS OF TEST ROUTINE)
		MDISMS		;WAIT UNTIL DEALLOCATION IS POSSIBLE
		JRST ATACH3]	;TRY AGAIN
ATACH7:	UNLOCK DEVLCK		;UNLOCK DEVICE LOCK
	OKINT			;LCKDVL WENT NOINT
	SETOM CTRLTT(Q2)	;INDICATE JOB HAS NO CONTROLLING TERMINAL
	MOVE T1,ATACJN		;GET OBJECT JOB NUMBER
	HRROS JOBPT(T1)		;NO CONTROLLING TERMINAL AGAIN
	MOVE T2,ATACLN		;T2/ LINE NUMBER OF DETACHED JOB
	MOVE T3,JOBNO		;GET THIS JOB NUMBER
	HRRZ T3,JOBDIR(T3)	;GET USER NUMBER FOR THIS JOB
	HRLI T3,USRLH		;MAKE IT BE A USER NUMBER
	MOVE T4,CTRLTT		;AND TTY # OF DETACHER
	CALL DETMS1		;TELL JOB IT'S BEING DETACHED
	; ..
;OBJECT JOB HAS BEEN DETACHED. DETACH CALLER FROM CONTROLLING TERMINAL
;AND ATTACH OBJECT JOB TO THAT TERMINAL. DON'T DEALLOCATE THE DYNAMIC
;DATA FOR THE TERMINAL

	;..
ATACH2:	TXNE Q1,AT%NAT		;REQUESTED NO ATTACH?
	JRST ATACH4		;YES
	MOVEM Q3,ATACLN		;NO, MAKE SURE LINE RIGHT
	MOVE T2,Q3		;prepare for LDET2
	NOINT			; ..
	CAMN Q3,CTRLTT		;NEED TO GIVE AWAY MY TERMINAL?
	CALL LDET2		;YES, DETACH THIS JOB BUT KEEP DYNAMIC DATA 
	NOSKED

;ASSIGN OBJECT JOB TO CORRECT TERMINAL

	MOVE T4,ATACJN		;GET OBJECT JOB
	MOVEM Q3,CTRLTT(Q2)	;SET CTRLTT IN DEST JOB
	HRLM Q3,JOBPT(T4)
	MOVEI T1,.TTDES(Q3)	;T1/ DEVICE DESIGNATOR FOR TERMINAL
	CALL CHKDES 		;GET INDEX TO DEVICE TABLES
	 BUG(TTBAD1)
	MOVE T1,ATACJN		;GET OTHER JOB NUMBER
	HRLM T1,DEVUNT(T2)	;INDICATE OTHER JOB OWNS THE TERMINAL
	MOVE T2,ATACLN		;T2/ TERMINAL NUMBER
	MOVE T1,TTSPSI(Q2)	;T1/ INTERRUPT WORD FOR OTHER JOB
	MOVE T3,TTSDPS(Q2)	;T3/ DEFERRED INTERRUPT WORD FOR OTHER JOB
	CALL TTSINT		;SET INTERRUPT WORDS FOR THIS TERMINAL
	MOVE T1,ATACJN		;T1/ OTHER JOB
	CALL STCJOB		;SET THIS AS CONTROLLING THE TERMINAL
	OKSKED
	OKINT
	CALL CLRLFK		;CLEAR MAPPING OF JSB
	MOVE T1,ATACJN
	MOVE T2,ATACLN		;SET UP JOB/LINE INFO
	CALL ATAMSG		;DO LOGGING STUFF
	MOVE T1,JOBNO
	HRRE T1,JOBDIR(T1)
	JUMPE T1,LOGO		;VANISH IF NOT LOGGED IN
	SMRETN

;HERE IF CALLER REQUESTED "NO ATTACH", I.E. DETACHING REMOTE JOB

ATACH4:	CALL CLRLFK		;CLEAR MAPPING OF JSB
	MOVE T1,ATACJN		;SET JOB #
	MOVE T2,ATACLN		; AND LINE #
	CALL DETMS0		;DO LOG MSG AND FACT FILE ENTRY
	SMRETN
;GET AND SAVE ROUTINES
;AC USAGE:
; P5 - PTN OF UPT,,0
; P4 - File status save for execute-only GET
; P3 - UPPER LIMIT PAGE
; P2 - LOWER LIMIT PAGE
; P1 - FORK HANDLE,,JFN (AC1 ARG AFTER CHECKING)
;  F - (RH) FLAGS FROM CALL
;	(LH) internal flags:
GTFEXO==1B0		;Doing execute-only GET
GTFNVG==1B1		;Process is not virgin
GTFSPC==1B2		;DOING "SPECIAL" GET
;
;FPG0A USED AS WINDOW TO USER SPACE

.GET::	MCENT
	ACVAR <Q1,Q2,Q3>	;NEED TO USE ALL OF THE Q REGS
	JUMPE T1,FLSCSH		;SEE IF WANT TO FLUSH FAST-GET CACHE
	HRRZ F,1		;SAVE FLAGS FROM CALL
	TXZE F,GT%FL2		;ADDITIONAL FLAGS GIVEN?
	JRST [	MOVX T4,SC%WHL!SC%OPR ;YES.
		TXNN F,GT%ADR	;ALL OF THE ADDRESS SPACE?
		TDNN T4,CAPENB	;PRIVILEGED USER?
		TXZ T3,G2%FCH	;NO. CAN'T ADD TO CACHE THEN
		TXNE T3,G2%FCH	;WANT TO CACHE THIS PROGRAM?
		TXO F,GTFSPC	;YES. REMEMBER THIS
		JRST .+1]	;AND PROCEED
	MOVEI P3,777		;SETUP DEFAULT LIMITS
	MOVEI P2,0
	TXNE F,GT%ADR		;USER GIVING LIMITS?
	JRST [	XCTU [HLRZ P2,2] ;YES, GET THEM
		XCTU [HRRZ P3,2]
		JRST .+1]
GET01:
	CALL GTSVID		;CHECK PARAMETERS, ETC.
	MOVE P1,P6		;COPY JFN
	TXO T2,OF%RD		;Must have READ
	TLNN T3,777		;DISK?
	TXO T2,OF%EX		;Yes, request READ and EXECUTE
	OPENF			;OPEN FILE FOR INPUT (T1 set up by GTSVID)
	 JRST GET02		;Error-- try for just EXECUTE
	JRST GET03		;OK-- Go get the file

; Try to open the file for execute-only access

GET02:
	TLNN T3,777		;Disk file?
	 TXNE F,GTFNVG!GT%ADR	;Yes-- is this virgin process, and no address limits?
	  ITERR ()		;No to either question, return error from OPENF
	HRRZ T1,P1		;Get JFN
	TXZ T2,OF%RD		;Try to open file without READ (just EXECUTE)
	OPENF			; . . .
	 ITERR ()		;If we can't even get EXECUTE, give up now

; File is open for only EXECUTE access
; Try to make process execute-only

	CALL FLOCK		;Lock process structure
	HLRZ T1,P1		;Get specified process handle
	CALL STJFKR		;Convert RFH to JRFN
	 JRST [	CALL FUNLK		;Invalid process handle-- unlock process structure
		MOVE 5,T1		;Save the error code
		JRST GETE2]		;Clean up and give error
	CALL SETEXO		;Set process as execute-only
	 JRST [	CALL FUNLK		;Process is not virgin-- unlock process structure
		TXO F,GTFNVG		;Remember process is not virgin
		HRRZ T1,P1		;Get JFN back
		TXO T1,CO%NRJ		;Don't release the JFN yet
		CLOSF			;Close the file now
		 JFCL			; . . .
		JRST GET01]		;Re-try the OPENF with READ and EXECUTE
					;This time return the OPENF error
	CALL FUNLK		;Unlock process structure

; The process is now execute-only
; Now set READ access and the execute-only GET bit (so PMAP works)

	NOINT			;Protect the use of READ access and
				; the execute-only GET bit
	TXO F,GTFEXO		;Remember that we are doing all this stuff so
				; we can undo it in the end
	HRRZ T1,P1		;Get the JFN
	CALL SREADF		;Set READ access and restrict access to this process
	MOVE P4,T2		;Save old state of status
	CALL SETGXO		;Enable this process for execute-only GET

; File is open. Check out the process.

GET03:
	CALL GTSVIF		;Setup PTN in P5
	 JRST [	MOVE 5,T1		;Error-- Save the error code
		JRST GETE2]		;Clean up and return error

; Now do the GET

GET2:
   REPEAT 0,<			;OLD FAST GET CODE
	CALL TSTFST		;SEE IF A FAST GET CAN BE DONE
	 SKIPA			;COULDN'T
	JRST DONEG		;DID IT. ALL DONE THEN
   >				;END OF OLD FAST GET CODE
	HRRZ 1,P1		;JFN
	BIN			;GET IOWD COUNT,ADR
	 ERJMP GETE3		;FAILED. GO CLEAN UP AND GIVE ERROR RETURN
	MOVE 6,2
	HLRZ 2,2
	CAIN 2,EXEFIL		;AN EXE FILE?
	JRST GETEXE		;YES. GO DO IT THEN
	TXNE F,GTFSPC		;DOING SPECIAL GET?
	JRST GETE1		;YES. MUST BE EXE FILE
	CAIL 2,1000		;CHECK FOR SHARE SAVE FILE
	CAIL 2,10000
	JRST .+2
	JRST SGET		;SHARE SAVE
	JUMPGE 6,GET1		;POSITIVE MEANS END

;FILE IS ZERO-COMPRESSED

	ADDI 6,1
	NOINT			;BE NOINT WHILE PAGE MAPPED
	CALL GET3		;SET MAP FOR PAGE
	JRST GET5

GET4:	TRNN 6,777		;JUST CROSSED PAGE BOUNDARY?
	CALL GET3		;YES, REMAP
GET5:	JUMPL 5,[TLNE 5,(1B1)	;GET A LOAD ERROR?
		JRST GETE5	;YES.
		BIN		;NO. USE BIN TO SKIP THIS BLOCK
		 ERJMP GETE4	;FAILED. GO CLEAN UP AND GIVE ERROR RETURN
		AOBJN 6,GET4	;THROW WORD AWAY
		JRST GET5A]
	HRRZ 2,6		;COMPUTE (NEG) NO. WDS LEFT ON PAGE
	ANDI 2,PGSIZ-1
	SUBI 2,PGSIZ
	HLRE 3,6		;GET (NEG) NO. WDS LEFT IN PTR
	CAMGE 3,2		;GET 'MINIMUM'
	MOVE 3,2
	PUSH P,3		;SAVE IT
	MOVE 2,5		;CONSTRUCT IFIW FOR @
	TXO 2,IFIW
	MOVEI 2,@2		;CONSTRUCT PTR TO DEST
	HRLI 2,(<POINT 36,0>)
	SIN			;MOVE WORDS TO DEST
	 ERJMP GETE4		;FAILED. GO CLEAN UP AND GIVE ERROR RETURN
	POP P,2			;RECOVER STARTING COUNT
	SUB 3,2			;COMPUTE WORDS MOVED
	HRL 3,3			;PUT COUNT IN BOTH HALVES
	ADD 6,3			;UPDATE AOBJN PTR
	JUMPL 6,GET4		;LOOP UNLESS PTR EXHAUSTED
GET5A:	CALL GET3X		;CLEAN UP MAPPINGS
	JRST GET2		;NEXT BLOCK
;CHECK AND REMAP PAGE

GET3:	CALL GET3X		;UNDO PREVIOUS MAPPING IF ANY
	NOINT			;BE NOINT WHILE PAGES MAPPED
	LDB 2,[POINT 9,6,26]	;PAGE NUMBER NEXT REFERENCE
	CAMG 2,P3		;PAGE WITHIN LIMITS?
	CAMGE 2,P2
	JRST [	MOVSI 5,(1B0)	;NO, SET FLAG TO PREVENT STORE
		RET]
	MOVE 1,2		;PAGE NUMBER
	TXNN F,GT%NOV		;WANT TO AVOID OVERLAYS?
	JRST GET3N		;NO. GO ON THEN
	HLL 1,P1		;YES. GET FH
	RPACS			;GET ACCESS INFO FOR THIS PAGE
	TXNN 2,PA%PEX!PA%IND	;DOES THIS PAGE EXIST?
	JRST GET3N		;NO. GO ON THEN
	MOVSI 5,(3B1)		;YES. GIVE ERROR
	RET			;AND DONE
GET3N:	HLL 1,P5		;GET PTN OF USER PAGE TABLE
	MOVE 2,[PTRW+FPG0A]
	CALL SETMPG		;SETUP WINDOW TO USER PAGE
	MOVE 5,6		;MAKE @5 POINT TO FPG0A
	ANDI 5,777000		; I.E. FPG0-USERPAGE
	MOVN 5,5
	ADDI 5,FPG0A
	HRLI 5,6		;GIVE IT AN INDEX
	HRRZ 1,P1		;RESTORE JFN TO 1
	RET

;UNMAP WINDOW PAGE

GET3X:	SETZ 1,
	MOVEI 2,FPG0A
	CALL SETMPG
	OKINT
	RET
;HERE WHEN READ ENTRY VECTOR WORD (LAST WORD IN FILE)

GET1:	CALL VECSET		;SET THE ENTRY VECTOR

; Common exit for all flavors of GET

DONEG:	CALL GETEND		;Clean up file, etc.
	JRST MRETN

;COMMON ROUTINE TO SET THE ENTRY VECTOR
;6/ VECTOR

VECSET:	CALL FLOCK
	HLRZ 1,P1		;FORK HANDLE
	CALL SETLFK		;MAP PSB
	MOVEM 6,ENTVEC(1)	;STORE ENTRY VECTOR DATA
	CALL CLRLFK
	CALL FUNLK
	RET			;AND DONE

;COMMON SETUP FOR GET, SAVE, SSAVE
; Sets up:
;	P6/	User AC1 (XWD process handle, JFN)
;	P5/	XWD PTN of process, 0
;	T1, T2 for OPENF
;	T3/	Device characteristics

GTSVI:	STKVAR <HLDT3>
	CALL GTSVID		;Do device stuff, setup P6, T1, T2, T3
	MOVEM T3,HLDT3		;SAVE T3 ACROSS CALL
	CALL GTSVIF		;Do process stuff, setup P5
	 ITERR ()		;Failed, return error in T1
	MOVE T3,HLDT3		;RESTORE T3
	RET			;Return from GTSVI

;Setup device stuff:  P6, T1, T2, T3

GTSVID:
	UMOVE P6,1		;SAVE ARG
	TRZ P6,770000		;FLUSH MISC BITS FROM JFN
	HRRZ T1,P6		;JFN
	DVCHR			;GET DEVICE CHARACTERISTICS
	MOVE T3,T2		;Move device characteristics
	HRRZ T1,P6		;JFN
	MOVSI T2,(^D36B5)	;BYTE SIZE FOR BIN/BOUT XFER
	RET

;Setup process stuff:  P5
;Returns +1 (error code in T1), +2 (OK)

GTSVIF:
	PUSH P,T1		;Save register
	HLLZ T1,P6		;Get process handle from call
	CALL FKHPTX		;Convert RFH.0 to PTN.0 and check for execute-only
	 JRST [	POP P,(P)		;Bad process handle-- clean stack
		RET]			; and return +1 from GTSVIF
	MOVEM T1,P5		;Remember the PTN
	POP P,T1		;Restore . . .
	RETSKP			;Return +2 from GTSVIF

; GETEND - clean up at end of GET

GETEND:
	TXNN F,GTFEXO		;Doing execute-only GET?
	 JRST GETEN1		;No, just close file
	MOVE T2,P4		;Get old file status
	CALL CREADF		;Restore state to what it was at OPENF
	CALL CLRGXO		;Disable execute-only GET
	OKINT			;Now we can be interupted
GETEN1:
	HRRZ T1,P1		;Get JFN
	CLOSF			;Attempt to close file
	 JFCL			;Can't-- maybe pages still mapped
	RET			;Return from GETEND
; Errors during GET . . .

;ERROR DURING GET.  GO OKINT IF NOW NOINT AND SAVE ERROR CODE

GETE5:	MOVEI 1,GETX3		;SAY OVERLAY ERROR
	MOVEM 1,LSTERR		;MAKE THIS THE ERROR
GETE4:	OKINT			;ALLOW INTERRUPTS
GETE3:	MOVE 5,LSTERR		;GET MOST RECENT ERROR
	JRST GETE2		;GO CLEAN UP AND TAKE ERROR RETURN

;UNEXPECTED END OF FILE DURING GET

GETE1:	MOVEI 5,GETX1		;FORCE RETURN OF ILLEGAL FILE FORMAT ERROR

;AN ERROR OCCURRED. AC 5 HAS THE ERROR CODE. CLEAN UP AND TAKE ERROR RETURN

GETE2:	CALL GETEND		;Close file and clean up
	SETZ 1,
	MOVEI 2,FPG0A
	CALL SETMPG		;ENSURE TEMP PAGE CLEARED
	CAIN 5,IOX4		;DID WE GET END OF FILE?
	 ITERR (GETX1)		;YES. RETURN ILLEGAL SAVE FILE FORMAT
	MOVE 1,5		;NO. RETURN THE REAL ERROR
	ITERR
;THE FILE IS AN EXE FILE. THE FIRST BLOCK MUST BE A DIRECTORY IN
;ORDER FOR CONTROL TO REACH THIS CODE

;DEFINITIONS FOR EXE FILES

EXEFIL==1776			;BLOCK TYPE FOR DIR AND FOR GETTING
				;TO THIS CODE
EXEEND==1777			;END OF ALL BLOCKS
EXEVEC==1775			;ENTRY VECTOR BLOCK
EXEWRB==1B2			;WRITE REQUEST IN FLAG BITS
EXESHR==1B1			;PAGE IS SHARABLE
EXEZRO==1B3			;PAGE EXISTS BUT IS ZERO

;BITS IN Q1 REMEMBERED DURING PROCESSING

EXEDIR==1B0			;SAW A DIRECTORY BLOCK
EXVEC==1B1			;SAW AN ENTRY BLOCK
NDSK==1B2			;IF ON, NOT A DISK

;FIELD DEFINITIONS FOR THE BLOCK CONTENTS

DEFSTR(EXADR,,35,27)		;FILE PAGE ADDRESS
DEFSTR(EXCNT,,8,9)		;COUNT FIELD
DEFSTR(EXPAG,,35,27)		;PROCESS PAGE ADDRESS

GETEXE:	TRVAR <DIRPAG,WRKPAG,DIRLPR,DIRCNT,CURPAG,SPCCNT,ENTVCW> ;VARIABLES FOR NON-DISK DEVICES
	SETZM SPCCNT
	SETZM ENTVCW		;INIT SPECIAL GET WORDS
	MOVX Q1,EXEDIR		;SAW A DIR
	MOVEI 6,0(6)		;GET COUNT OF DIR WORDS
	SOS 6			;DISCOUNT THE HEADER
	LSH 6,-1		;2 WORDS PER ENTRY
	MOVEM 6,DIRCNT		;NUMBER OF PAIRS
	CALL CHECKG		;MUST BE ON DISK
	 SKIPA			;NOT DISK
	JRST DOEN1		;GO SEE ABOUT DIR ENTRIES
	TXNE F,GTFSPC		;SPECIAL GET?
	JRST GETE1		;YES. CAN'T DO IT THEN
	NOINT			;MUST BE NOINT FOR REMAINDER OF JSYS
	TXO Q1,NDSK		;NOT A DISK
	CALL ASGPGS		;GET DIR PAGE
	 ITERR (GJFX22,OKINT)	;JSB MUST BE FULL
	MOVEM A,DIRPAG		;SAVE PAGE
	SOS A			;LOOPER WORD IS ONE LESS
	HRLI A,-1000		;# OF WORDS 
	MOVEM A,DIRLPR		;SET UP LOOP VALUE
	CALL ASGPGS		;GET PAGE FOR THE SIN
	 JRST [	MOVE A,DIRPAG
		CALL RELPGS	;CLEAN UP
		ITERR (GJFX22,OKINT)] ;NO ROOM
	MOVEM A,WRKPAG		;SAVE WORK PAGE ADDRESS
	OKINT			;ALLOW INTS NOW
	MOVE B,DIRPAG		;THE DIRECTORY PAGE
	HRLI B,(POINT ^D36,)	;MAKE IT A BYTE POINTER
	MOVNI C,777		;REST OF PAGE
	CALL SINN		;READ IT IN
	MOVEI A,1		;THE CURRENT PAGE
	MOVEM A,CURPAG		;REMEMBER THIS
DOEN1:	JUMPE 6,DOCAT		;IF NO DIR ENTRIES, GO AWAY
;LOOP TO PROCESS ALL OF THE DIRECTORY ENTRIES. EACH ENTRY IS TWO
;WORDS THE FIRST OF WHICH DESCRIBES THE FILE AND THE SECOND,
;DESCRIBING THE PROCESS

DOENT:	CALL GTWRD		;GET NEXT DIR WORD
	MOVE Q3,B		;SAVE IT
	CALL GTWRD		;GET NEXT DIR WORD
	JE <EXEZRO,EXADR>,Q3,ALLZER ;IF NON-EX, IGNORE IT
	SETZ C,			;CLEAR ACCESS BITS
	TXO C,PM%RD!PM%EX	;TURN ON READ AND EXECUTE
	TXNE Q3,EXEWRB!EXESHR	;WANT SOME FLAVOR OF WRITE?
	TXO C,PM%CPY		;YES. GIVE HIM COPY ON WRITE
	LOAD A,EXPAG,B		;GET PROCESS PAGE ADDRESS
	LOAD D,EXCNT,B		;GET REPEAT COUNT
	ADD D,A			;CALCULATE LAST PAGE TO AFFECT
	CAML D,P2		;WITHIN BOUNDS?
	CAMLE A,P3		;?
	JRST ALLZER		;NO. DONT LOAD IT THEN
	LOAD B,EXADR,Q3		;STARTING FILE PAGE
	CAMLE D,P3		;VERIFY UPPER BOUND
	MOVE D,P3		;TOO LARGE. USE USER'S
	CAMGE A,P2		;VERIFY LOWER BOUND
	CALL [	ADD B,P2	;TOO LOW. COMPUTE PROPER FILE PAGE
		SUB B,A		;""
		MOVE A,P2	;AND USE USER'S LIMIT
		RET]		;AND PROCEED
	SUB D,A			;GET NEW REPEAT COUNT
	AOS D			;ONE MORE FOR GOOD MEASURE
	JXE Q3,EXADR,[	SETOM B	;IF ALL ZERO, MAKE DELETE ARG
			JRST DOENT0] ;AND PROCEED
	TXNE Q1,NDSK		;IS THIS A DISK?
	JRST [	CALL NTDISK	;NOT DISK
		JRST ALLZER]	;DONE
DOENT0:	EXCH A,B		;MAKE ARGS CORRECT
	CALL MAPIT		;GET IT MAPPED
	 JRST [	MOVE 5,1	;GET THE ERROR
		JRST GETE2]	;AND GO ERROR OUT
	CAMN T1,[-1]		;DOING UNMAP ONLY?
   REPEAT 0,<			;OLD FAST GET CODE
	JRST [	TXNN F,GTFSPC	;YES. A SPECIAL GET?
		JRST ALLZER	;NO. GO ON THEN
		MOVE A,D	;YES. GET COUNT
		CALL MAKPGS	;MAKE NON-EX POINTERS IN MAP
		JRST ALLZER]	;DONE
   >				;END OF OLD FAST GET CODE
	JRST ALLZER
	ADDM D,SPCCNT		;NO. ACCOUNT FOR PAGES
ALLZER:	SOSLE DIRCNT		;MORE TO DO?
	JRST DOENT		;YES. GO DO THEM
	JRST DOCAT		;ALL DONE

;ROUTINE TO GET NEXT WORD FROM DIRECTORY

GTWRD:	TXNE Q1,NDSK		;A DISK?
	JRST GTWRD1		;NO
	MOVEI A,0(P1)		;JFN
	BIN 			;GET ENTRY
	 ERJMP GETE3		;FAILURE. GO CLEAN UP AND TAKE ERROR RETURN
	RET			;ALL DONE

GTWRD1:	MOVE A,DIRLPR		;CURRENT POINTER
	AOBJP A,DRBAD		;MORE?
	MOVE B,0(A)		;GET DATUM
	MOVEM A,DIRLPR		;SAVE POINTER
	RET			;AND DONE
;ROUTINE TO GET IN FILE PAGE FOR NON-DISK DEVICE AND TO PUT
;DATA IN PROPER USER'S PAGE
;ACCEPTS:
;	A/ FIRST PROCESS PAGE NUMBER
;	B/ FIRST FILE PAGE NUMBER
;	D/ REPEAT COUNT

NTDISK:	STKVAR <SAVA,SAVB,SAVD>	;WORK REGISTERS
	MOVEM A,SAVA		;SAVE ARGS
	MOVEM B,SAVB		;SAVE B
	MOVEM D,SAVD
	CAME B,CURPAG		;AT PROPER FILE PAGE?
	JRST [	CAMG B,CURPAG	;NO. WANT TO MOVE FORWARD?
		JRST DRBAD	;NO. ERROR
		SUB B,CURPAG	;GET # OF PAGES TO WASTE
		ADDM B,CURPAG	;NEW CURRENT
		LSH B,^D9	;*512
		MOVNI C,0(B)	;NEGATIVE COUNT
		MOVEI B,B	;DUMMY POINTER
		MOVEI A,0(P1)	;JFN
		CALL SINN	;GET DATA
		JRST .+1]	;GO INLINE
RDPAGE:	MOVE A,SAVA		;GET CURRENT PROCESS PAGE
	HLL A,P1		;FORK HANDLE
	RPACS			;SEE ABOUT IT
	TXNE F,GT%NOV		;WANT TO CHECK FOR OVERLAYS?
	TXNN B,PA%PEX!PA%IND	;YES. IS THIS ONE?
	SKIPA			;NO. GO ON
	JRST DIREO3		;YES. GO ERROR OUT
	TLNE B,(1B5)		;NON-EX?
	TXNE B,PA%WT!PA%CPY	;HAVE WRITE ACCESS?
	SKIPA			;YES. ALLOW IT
	JRST WASTE		;NO. FORGET IT THEN
	HLL A,P5		;GET PTN OF PROCESS'S UPT
	MOVE B,WRKPAG		;GET WORK PAGE
	TXO B,PA%WT		;NEED WRITE ACCESS
	CALL SETMPG		;DO MAPPING
WASTE:	MOVE B,WRKPAG
	HRLI B,(POINT ^D36,)	;MAKE IT A POINTER
	MOVNI C,1000		;COUNT
	CALL SINN		;GET PAGE
	SETZ A,			;FOR THE UNMAP
	MOVE B,WRKPAG		;THE PAGE ADDRESS
	CALL SETMPG		;UNMAP WORK PAGE
	AOS CURPAG		;HAVE STEPPED A PAGE
	AOS SAVA		;NEXT PROCESS
	AOS SAVB		;NEXT FILE PAGE
	SOSG SAVD			;MORE?
	RET			;NO
	JRST RDPAGE		;YES

;ROUTINE TO EXECUTE A SIN AND CHECK FOR EOF AND ERROR
;ACCEPTS:
;	B/ BP
;	C/COUNT

SINN:	MOVEI A,0(P1)		;GET JFN
	SIN			;SO THE SIN
	 ERJMP DIRERR		;FAILED. GO CLEAN UP AND TAKE ERROR RETURN
	RET			;OK
;LOOP TO READ THE NEXT BLOCK TYPE AND DISPATCH TO THE PROPER
;ACTION

DOCAT:	CALL GTWRD		;GET NEXT DIR WORD
	MOVE 6,B		;SAVE IT
	HLRZ B,6		;TYPE
	CAIN B,EXEVEC		;VECTOR BLOCK?
	JRST SETVEC		;YES. GO DO IT
	CAIE B,EXEEND		;END OF INFORMATION?
	JRST SKPBLK		;NO. UNKNOWN BLOCK
	TXNE Q1,EXVEC		;AT THE END. SEEN A VECTOR TYPE YET?
	JRST DONEG1		;YES. ALL DONE THEN
	MOVSI 6,(JRST)		;NO. MAKE UP ONE
	CALL VECSET		;AND GO SET IT
DONEG1:	TXNE F,GTFSPC		;DOING A SPECIAL GET?
	CALL FSTENT		;YES. MAKE ENTRY IN CACHE THEN
	TXNN Q1,NDSK		;A DISK?
	JRST DONEG		;YES. ALL DONE
	MOVE A,WRKPAG		;NO. RELEASE STORAGE
	NOINT			;PROTECT STRUCTURES
	CALL RELPGS		;RELEASE
	MOVE A,DIRPAG		;THE OTHER PAGE
	CALL RELPGS
	OKINT			;ALLOW INTS
	HRRZ A,P1		;GET JFN
	MOVEI B,.MOFWF		;SPACE FORWARD OVER TAPE MARK
	MTOPR
	 ERJMP .+1		;DONT CARE ABOUT ERRORS
	JRST DONEG		;AND DONE

;UNKNOWN BLOCK TYPE. SKIP THE BLOCK

SKPBLK:	MOVEI D,-1(6)		;NUMBER TO SKIP
	JUMPE D,DOCAT		;IF NONE, ALL DONE
	CALL GTWRD		;GET ONE
	SOJG D,.-1		;DO ALL
	JRST DOCAT		;NO. GET NEXT CATEGORY

;ERROR OCCURRED IN READING THE FILE. SAVE ERROR CODE IN AC 5 AND GO 
;CLEAN UP

DRBAD:	MOVEI 5,GETX1		;Say invalid file format
	JRST DIREO1		; . .

DIREO3:	SKIPA 5,[GETX3]		;SAY HAD OVERLAY ERROR
DIRERR:	MOVE 5,LSTERR		;GET LAST ERROR

;AN ERROR OCCURRED DURING READING OF THE FILE. AC 5 CONTAINS THE ERROR CODE.
;CLEAN UP AND TAKE ERROR RETURN

DIREO1:	MOVE A,WRKPAG		;FREE WORK PAGE
	NOINT			;PROTECT STRUCTURES
	CALL RELPGS
	MOVE A,DIRPAG		;FREE DIR PAGE
	CALL RELPGS		;FREE THIS ONE TOO
	OKINT			;ALLOW INTS
	JRST GETE2		;AND GO ERROR OUT
;ROUTINE TO SET THE ENTRY VECTOR FROM AN EXE VECTOR BLOCK

SETVEC:	TXOE Q1,EXVEC		;SEEN ONE YET?
	JRST GETE1		;YES. BOMB HIM THEN
	HRRZ B,6		;GET COUNT
	CAIGE B,3		;PROPER TYPE?
	JRST SKPBLK		;NO. FORGET IT THEN
	PUSH P,B		;SAVE THE COUNT
	CALL GTWRD		;GET NEXT WORD
	MOVSI 6,0(B)		;THE COUNT
	CALL GTWRD		;GET NEXT WORD
	HRRI 6,0(B)		;GET ADDRESS
	CALL VECSET		;SET IT IN THE PROCESS
	MOVEM 6,ENTVCW		;SAVE ENTRY VECTOR WORD
	POP P,6			;RESTORE THE COUNT
	MOVEI 6,-2(6)		;GET COUNT MINUS TWO
	JRST SKPBLK		;SKIP THE REST
;ENCOUNTERED CODE FOR SHARED SAVE.  EACH PAGE TO BE PUT IN THE
;FORK IS INDICATED BY ONE WORD WHERE:
; B0-8: ACCESS BITS, B0=WRITE COPY
; B9-17: FORK PAGE NUMBER TO RECEIVE PAGE
; B18-35: FILE PAGE NUMBER OF SOURCE PAGE

;IN ORDER TO USE THE MULTI-PAGE PMAP AND SAVE TIME, THIS
;ROUTINE SCANS THE INPUT FOR SUCCESSIVE FORK/FILE PAGES AND
;DOES AS MANY AS POSSIBLE WITH EACH PMAP

SGET:	CAIE 2,1000		;CORRECT TYPE NUMBER?
	JRST GETE1		;NO, STRANGE FILE
	MOVEI Q3,0(6)		;SAVE COUNT
	CALL CHECKG		;MAKE SURE IS DISK
	 ITERR(SSAVX1)		;MUST BE DISK
	HRRZ 1,P1		;JFN
SGT5:	BIN			;GET FIRST WORD
	 ERJMP GETE3		;FAILED. GO CLEAN UP AND TAKE ERROR RETURN
SGT4:	CALL SGCHKL		;CHECK LIMITS
	 JRST [	SOJG Q3,SGT5	;NOT WITHIN LIMITS, SKIP PAGE
		JRST GET2]	;COUNT DONE
	PUSH P,2		;SAVE FIRST WORD OF THIS GROUP
	PUSH P,2		;SAVE COPY OF IT FOR INCREMENTING
	JRST SGT2		;ENTER LOOP TO SCAN FOR SEQUENTIAL PAGES

;GET NEXT INPUT WORD, SEE IF BOTH FORK AND FILE PAGE ARE 1
;BEYOND LAST INPUT WORD

SGT1:	BIN
	 ERJMP GETE3		;FAILED. GO CLEAN UP AND TAKE ERROR RETURN
	CAMN 2,0(P)		;THIS PAGE SAME AS EXPECTED ONE?
	CALL SGCHKL		;AND WITHIN LIMITS?
	 JRST SGT3		;NO, MUST GO DO PREVIOUS INPUT
SGT2:	MOVE 2,[1,,1]		;BUMP FORK AND FILE PAGE NUMBERS
	ADDM 2,0(P)
	SOJG Q3,SGT1		;COUNT TOTAL PAGES
	POP P,4			;COUNT DONE, ALL INPUT NOW READ
	POP P,2			;RECOVER FIRST WORD OF GROUP
	SUBI 4,0(2)		;COMPUTE COUNT OF PAGES IN GROUP
	CALL SGTDO		;DO PMAP
	 JRST [	MOVE 5,1	;GET THE ERROR
		JRST GETE2]	;AND GIVE IT
	JRST GET2		;CONTINUE WITH FILE

SGT3:	POP P,4			;RECOVER INCREMENTED PAGE NUMBERS
	EXCH 2,0(P)		;RECOVER FIRST WORD OF GROUP, SAVE NEXT
	SUBI 4,0(2)		;COMPUTE COUNT OF PAGES IN GROUP
	CALL SGTDO		;DO PMAP
	 JRST [	MOVE 5,1	;GET THE ERROR
		JRST GETE2]	;AND GIVE IT
	POP P,2			;RECOVER LAST INPUT
	HRRZ 1,P1		;RESTORE JFN
	JRST SGT4		;GO START SCAN OF NEXT GROUP
;ROUTINE USED BY ABOVE TO SETUP AND DO PMAP

SGTDO:	MOVEI 1,0(2)		;FILE PAGE NUMBER
	LDB 3,[POINT 9,2,8]	;ACCESS
	LDB 2,[POINT 9,2,17]	;MEMORY PAGE
	ROT 3,-^D9
	TLZE 3,(1B0)		;WRITE COPY REQUEST?
	TLO 3,(PM%CPY)		;YES, SET APPROPRIATE BITS

;ENTRY FOR EXE FILES
MAPIT:	CALL CHKLOD		;SEE IF OVERLAY CHECKS WANTED
	 RETBAD (GETX3)		;YES. AND IT DID
	SKIPL T1		;DOING DELETE?
	HRL 1,P1		;NO, JFN TO LH
	HLL 2,P1		;FORK HANDLE TO LH
	HRRI 3,0(4)		;COUNT OF SUCCESSIVE PAGES TO DO
	TXO 3,1B0		;SAY DO MULTIPLE PAGES
	TXNE F,GT%PRL		;WANT PRELOADING?
	TXO T3,PM%PLD		;YES. TURN ON BIT FOR PMAP
;	TXNE F,GTFSPC		;DOING SPECIAL GET?
;	TXO T3,PM%IND		;YES. REQUEST INDIRECT POINTERS THEN
	PMAP
	RETSKP

;LOCAL ROUTINE TO CHECK PAGE AGAINST LIMITS

SGCHKL:	LDB 3,[POINT 9,2,17]	;GET PAGE NUMBER
	CAMG 3,P3		;TOO HIGH?
	CAMGE 3,P2		;OR TOO LOW?
	SOS 0(P)		;YES, CAUSE FAIL RETURN
	RETSKP

;LOCAL ROUTINE TO VERIFY FILE IS FROM DISK

CHECKG:	HRRZ 1,P1		;JFN
	DVCHR
	TLNE 2,777		;DISK FILE?
	RET			;NO
	RETSKP			;YES

;LOCAL ROUTINE TO CHECK FOR OVERLAYS

CHKLOD:	SAVET			;SAVE ALL REGS
	TXNN F,GT%NOV		;WANT TO PREVENT OVERLAYS?
	RETSKP			;NO. RETURN GOOD AND ALLOW MAP
	MOVE 1,2		;STARTING PAGE IN PROCESS
	HLL 1,P5		;PTN OF THE PROCESS
	MOVEI 2,0(4)		;NUMBER OF PAGES
	CALL MSCANP		;SEE IF ANY EXIST IN THIS RANGE
	JUMPN 2,R		;YES. ERROR THEN
	RETSKP			;NO. ALLOW MAP
   REPEAT 0,<			;OLD FAST GET CODE

;TEST IF A FAST GET CAN BE DONE

;LOCAL DEFINITIONS FOR DATA STRUCTURE

DEFSTR (FGOFN,,35,12)		;THE OFN
DEFSTR (FGSPT,,23,12)		;THE PROTOTYPE MAP
DEFSTR (FGCNT,,11,11)		;THE SHARE COUNT
DEFSTR (FGVLD,,0,1)		;VALID BIT
	FGEVEC==1		;THE ENTRY VECTOR
	FGLLCK==2		;LOCK WORD

TSTFST:	SKIPE FSTTBL		;ANY ENTRIES IN THE CACHE?
	SKIPE P2		;YES. DOING ENTIRE ADDRESS SPACE?
	RET			;NO. CAN'T DO IT THEN
	TXNN F,GT%NOV		;CHECKING FOR OVERLAYS?
	CAIE P3,PGSIZ-1		;YES. UP TO THE END?
	RET			;NO. CAN'T DO IT
	CALL CHECKG		;ON DISK?
	 RET			;NO. CAN'T DO IT THEN
TSTFSN:	CSKED			;CRITICAL SECTION WHILE TABLE LOCKED
	LOCK FGLOCK		;LOCK UP THE TABLE
	CALL FNDOFN		;GET OFN FROM THE JFN
	 RETBAD (,<UNLOCK FGLOCK
		ECSKED>)
	MOVEI T4,FSTTBL+1	;START OF ENTRIES
	MOVE T3,FSTTBL		;COUNT
TSTFS0:	JE FGVLD,(T4),TSTFSX	;VALID?
	LOAD T2,FGOFN,(T4)	;GET OFN FROM TABLE
	CAIN T1,0(T2)		;SAME AS THE ONE IN THE JFN?
	JRST FSTGT1		;YES. GOT ONE
TSTFSX:	ADDI T4,FSN		;NEXT ENTRY
	SOJG T3,TSTFS0		;NO. DO THEM ALL
	RETBAD (,<UNLOCK FGLOCK
		ECSKED>)		;NOT FOUND

;FOUND A MATCHING ENTRY

FSTGT1:	AOS FGLLCK(T4)		;INCREMENT USE COUNT
	UNLOCK FGLOCK		;UNLOCK STRUCTURE LOCK
	NOINT			;DON'T GO NOINT BECAUSE USE COUNT IS UP
	ECSKED			;NOT CRITICAL WHEN TABLE UNLOCKED
	MOVE T1,T4		;COPY ENTRY
	CALLRET FSTGET		;DO FAST GET
;ROUTINE TO DO A FAST GET. AT THIS POINT
;FAST TABLE ENTRY IS LOCKED
;	T1/ ENTRY IN FAST GET TABLE
;	P1/ THE JFN
;	P6/ FORK HANDLE,,0

;RETURNS:	+1 SOME SORT OF FAILURE. MUST DO IT THE LONG WAY
;		+2 SUCCESS
;ONLY DOES A GET ON THE ENTIRE PROCESS SPACE.

FSTGET:	ACVAR <W1,W2,W3>	;WORK REGS
	STKVAR <WRKPG1,WRKPG2,SAVENT,<STRADR,2>,PSPTN,FSTOFN,FSTSPN,FSTSPP> ;SOME WORK LOCATIONS
	MOVEM T1,SAVENT		;SAVE TABLE INDEX
	LOAD T1,FGSPT,(T1)	;GET SPTN
	MOVEM T1,PSPTN		;SAVE SPTN OF PROTOTYPE MAP
	HLLZ T1,P1		;GET FORK HANDLE,,0
	CALL FKHPTX		;GET PTN OF PROCESS
	JRST [	MOVE T1,SAVENT
		SOS FGLLCK(T1)	;REDUCE USE COUNT
		OKINT
		RET]		;SO FAIL
	HLLZ P5,T1		;SAVE SPTN
	CALL ASGPAG		;GET A PAGE FOR MAPPING FORKS' PT
	 JRST [	MOVE T1,SAVENT
		SOS FGLLCK(T1) ;FREE LOCK
		OKINT
		RET]
	MOVEM T1,WRKPG1		;SAVE PAGE
	CALL ASGPAG		;GET A PAGE TO MAP PROTOTYPE MAP
	 JRST [	MOVE T1,WRKPG1
		CALL RELPAG	;FAILED. RELEASE THIS
		MOVE T1,SAVENT
		SOS FGLLCK(T1)
		OKINT
		RET]
	MOVEM T1,WRKPG2		;SAVE THIS AS WELL

;NOW MAP THE FORK'S PT AND THE PROTOTYPE MAP

	MOVE T2,T1		;COPY PAGE
	MOVE T1,PSPTN		;GET PROTOTYPE MAP PAGE
	TXO T2,<PM%RD>		;ONLY NEED TO READ IT
	CALL SETMPG
	HLRZ T1,P5		;SPTN OF FORK'S PT
	MOVE T2,WRKPG1
	TXO T2,<PM%RD!PM%WT>
	CALL SETMPG		;MAP THIS AS WELL
	; ..
;PAGES ARE NOW MAPPED AND PROCESS VERIFIED. SCAN TABLE AND
;SET UP MAP

	MOVE T3,SAVENT		;GET FAST-GET ENTRY
	LOAD T1,FGOFN,(T3)	;GET THE OFN
	LOAD T2,FGCNT,(T3)	;GET THE COUNT
	MOVEM T1,FSTOFN		;SAVE OFN FOR LATER
	HRRZ T1,P1		;GET THE JFN
	CALL MJFCNT		;AND UPDATE THE JFN COUNT AS WELL
	 NOP
	MOVE W1,WRKPG2		;GET PROTOTYPE PT
	MOVE W2,WRKPG1		;GET FORK'S PAGE TABLE
	MOVE W3,IMMPTR		;GET IMMEDIATE PAGE POINTER
	TXO W3,UAAB		; TO CHECK FOR PLACE HOLDER
FSTSCN:	CALL FLOCK		;LOCK THE PROCESS STRUCTURE
FSTSC5:	SKIPE T1,0(W1)		;ANYTHING HERE?
	JRST FSTSC0		;YES. GO PROCESS IT
FSTS22:	ADDI W1,1		;NO. NEXT PAGE
	ADDI W2,1		;SAME HERE
FSTSC2:	TRNE W1,PGSIZ-1		;ALL DONE YET?
	JRST FSTSC5		;NO. GO DO NEXT ONE
	JRST FSTDON		;YES.
;FOUND A PAGE IN THE PROTOTYPE PAGE TABLE

FSTSC0:	SKIPE 0(W2)		;PROCESS HAVE A PAGE HERE?
	JRST FSTSC1		;YES. MUST DELETE FIRST
	CAMN T1,W3		;NO. IS THIS A PLACE-HOLDER?
	JRST FSTS22		;DONE.
	MOVEI T4,1		;INIT MAP COUNTER
	LOAD T2,IPPGN,0(W1)	;GET STARTING PAGE NUMBER
	MOVEM T2,FSTSPN		;AND SAVE IT
	MOVEM W2,FSTSPP		;SAVE STARTING PROCESS PAGE
LOOP:	ADDI W1,1		;NEXT PAGE
	ADDI W2,1		;AND SAME HERE
	TRNN W1,PGSIZ-1		;AT THE END YET?
	JRST LOPMAP		;YES. DO MAPPING THEN
	SKIPE 0(W2)		;SOMETHING HERE IN THE PROCESS?
	JRST LOPMAP		;YES. DO MAPPING THEN
	LOAD T3,IPPGN,0(W1)	;NO. GET PAGE # THEN
	CAIE T3,1(T2)		;THE EXPECTED ONE?
	JRST LOPMAP		;NO. DO MAP NOW
	MOVE T2,T3		;YES. SAVE PAGE #
	ADDI T4,1		;ANOTHER PAGE IN THE COLLECTION
	JRST LOOP		;AND EXAMINE MEXT PAGE

;READY TO DO MAP

LOPMAP:	CALL GPAC		;GET USER ACCESS BITS FROM PAGE POINTER
	MOVE T3,T1		;COPY ACCESS BITS TO PROPER REG
	MOVE T1,FSTSPN		;GET STARTING PAGE # IN FILE
	HRL T1,FSTOFN		;FORM SOURCE ADDRESS
	MOVE T2,FSTSPP		;GET PROCESS PAGE ADDRESS
	SUB T2,WRKPG1		;COMPUTE PROCESS PAGE NUMBER
	HLL T2,P5		;GET PROCESS PAGE NUMBER
	CALL MSETPT		;MAP IT
	JRST FSTSC2		;AND PROCEED

;PROCESS HAS A PAGE IN THE SLOT.

FSTSC1:	DMOVEM W1,STRADR	;SAVE START OF SCAN
FSTSC4:	ADDI W2,1		;NEXT PAGE
	ADDI W1,1
	TRNN W2,PGSIZ-1		;AT THE END?
	JRST FSTSC3		;YES.
	SKIPE 0(W1)		;ANYTHING HERE?
	SKIPN 0(W2)		;YES. ANYTHING IN PROCESS?
	SKIPA			;NO. DO DELETER NOW
	JRST FSTSC4		;YES TO BOTH. CONTINUE SCAN
FSTSC3:	CALL FUNLK		;RELEASE PROCESS LOCK
	SUB W2,1+STRADR		;COMPUTE PAGES SCANNED
	SETOM T1
	MOVE T2,1+STRADR	;GET START OF RANGE
	SUB T2,WRKPG1		;GET STARTING PAGE NUMBER
	HLL T2,P1		;PROCESS HANDLE
	MOVE T3,W2		;COUNT
	TXO T3,PM%CNT		;SET REPEAT COUNT
	PMAP			;DELETE PAGES
	DMOVE W1,STRADR		;RESTORE START OF RANGE
	JRST FSTSCN		;AND GO AGAIN
;MAP ALL DONE. ADJUST COUNTS AND CLEAN UP
;INCREASE SHARE COUNT HERE
;

FSTDON:	CALL FUNLK		;RELEASE PROCESS LOCK
	MOVE T1,WRKPG1
	CALL RELPAG		;CLEAN UP
	MOVE T1,WRKPG2
	CALL RELPAG		;""
	HLLZ T1,P5		;GET IDENT
	MOVEI T2,PGSIZ
	CALL PREPG		;PRELOAD THE PAGES
	 NOP
	MOVE T2,SAVENT
	SKIPE 6,FGEVEC(T2)	;HAVE A VECTOR TO SET?
	CALL VECSET		;YES. SET IT THEN
	MOVE T1,SAVENT
	SOS FGLLCK(T1)		;FREE LOCK
	OKINT			;MATCH NOINT DONE EARLIER
	RETSKP			;AND DONE
   >				;END OF OLD FAST GET CODE
;ROUTINE TO MAKE AN ENTRY IN THE FAST GET CACHE

FSTENT:	SAVEAC <P2>		;GET A WORK REG
	LOCK FGLOCK		;LOCK UP THE TABLE
	MOVE P2,[-FSMAX,,FSTTBL]
	SKIPE 0(P2)		;ANYTHING HERE?
	JRST [	AOBJN P2,.-1	;NO. ANY MORE TO DO?
		UNLOCK FGLOCK	;DONE WITH TABLE
		RET]		;NO. DONE THEN
	CALL FNDOFN		;FIND OFN PLEASE
	 RET			;OOPS. GIVE UP THEN
	MOVEM T1,0(P2)		;STASH OFN FOR LATER USE
	UNLOCK FGLOCK		;DONE WITH TABLE
	CALLRET UPSHR		;UP THE SHARE COUNT

   REPEAT 0,<			;OLD CODE
FSTENT:	STKVAR <SVX,FSTPAG>		;SAVE ENTRY INDEX HERE
	CALL ASGPAG		;GET A WORK PAGE
	 RET			;COULDN'T
	MOVEM T1,FSTPAG		;SAVE IT
	NOINT
	LOCK FGLOCK		;GET LOCK
	MOVEI T4,FSTTBL+1	;START OF THE TABLE
	HRLI T4,-FSMAX		;THE TABLE SIZE
FSTEN0:	JN FGVLD,(T4),FSTEN1	;IF VALID, CAN'T USE IT
	MOVEM T4,SVX		;FOUND ONE. SAVE IT
	HLLZ T1,P1		;GET FORK HANDLE,,0
	CALL FkhPTN		;GET HANDLE
	 JRST FSTENX		;BOO HIS
	HLLZ P5,T1		;SAVE SPTN OF PROCESS PAGE TABLE
	NOSKED
	CALL ASSPTL		;GET AN SPT ENTRY
	OKSKED
	MOVE T4,SVX
	STOR T1,FGSPT,(T4)	;SAVE SPTN
	MOVE T2,ENTVCW		;GET ENTRY VECTOR WORD
	MOVEM T2,FGEVEC(T4)	;SAVE IT
	CALL SWPIN4		;ASSIGN PAGE TO SPTN
	CALL FNDOFN		;GET OFN FOR THE GET FILE
	 JRST [	MOVE T4,SVX
		LOAD T1,FGSPT,(T4) ;GET SPTN
		CALL DESPT	;RELEASE IT
		JRST FSTENX]	;AND GO ERROR OUT
	MOVE T4,SVX		;GET BACK INDEX
	STOR T1,FGOFN,(T4)
	MOVEI T2,1		;INCREMENT OFN COUNT
	CALL MUPSHR		;DO IT NOW
	HLRE T2,T4		;GET THIS OFFSET
	ADDI T2,FSMAX+1
	CAMLE T2,FSTTBL		;THIS NEW HIGHEST ENTRY?
	MOVEM T2,FSTTBL		;YES. STORE IT
	MOVE T2,SPCCNT
	STOR T2,FGCNT,(T4)	;SAVE THE SHARE COUNT
	; ..
;FSTENT CONTINUED
;NOW COPY THE PT

	LOAD T1,FGSPT,(T4)	;GET BACK PT
	MOVE T2,[PTRW+FPG0A]
	CALL SETMPG		;MAP SPTN
	MOVE T2,FSTPAG		;GET PAGE
	HLRZ T1,P5		;GET SPT OF FORKS' UPT
	TXO T2,PTRW
	CALL SETMPG		;MAP THIS AS WELL
	HRL T1,FSTPAG		;SOURCE ADDRESS
	HRRI T1,FPG0A		;DESTINATION ADDRESS
	BLT T1,FPG0A+PGSIZ-1	;COPY MAP
	MOVE T1,FSTPAG		;GET WORK PAGE
	CALL RELPAG		;GET RID OF IT
	SETZM T1
	MOVEI T2,FPG0A
	CALL SETMPG		;UNMAP SPTN
	MOVE T4,SVX
	SETONE FGVLD,(T4)	;SAY ENTRY NOW VALID
FSTENX:	UNLOCK FGLOCK		;DONE WITH LOCK
	OKINT
	RET			;AND DONE WITH ROUTINE

;STEP TO NEXT ENTRY

FSTEN1:	ADDI T4,FSN-1
	AOBJN T4,FSTEN0		;DO THEM ALL
	JRST FSTENX		;NONE FOUEN
   >				;END OF OLD FAST GET CODE
;SPECIAL ROUTINE USED BY GET WHEN BUILDING A PROTOTYPE
;GET ADDRESS SPACE. WILL CREATE PRIVATE POINTERS TO UNASSIGNED
;ADDRESSES TO USE AS PLACE HOLDERS.

MAKPGS:	ASUBR<COUNT,ID>
	HLLZ T1,ID		;GET FORK HANDLE
	CALL FKHPTX		;GET SPTN OF PROCESS PAGE TABLE
	 RETBAD ()
	HLRZS T1		;GET UPT INDEX
	NOINT
	MOVE T2,[PTRW+FPG0A]
	CALL SETMPG		;MAP PAGE TABLE
	HRRZ T3,ID		;GET FIRST PAGE
	MOVN T4,COUNT		;GET NUMBER TO DO
	HRL T3,T4
	MOVE T4,IMMPTR
	TXO T4,UAAB		;MAKE THEM ALL UNASSIGNED
MAKPG0:	MOVEM T4,FPG0A(T3)	;STORE ONE
	AOBJN T3,MAKPG0		;DO THEM ALL
	SETZM T1
	CALL SETMPG		;UNDO MAPPING
	OKINT
	RET			;AND DONE

;ROUTINE TO FIND THE OFN IN A JFN.
;	P1/ THE JFN
;RETURNS:	+1 ALWAYS. T1/ THE OFN

FNDOFN:	SAVEAC <F>		;SAVE FLAGS
	SETZM F
	HRLZ T1,P1		;GET JFN
	CALL JFNOFN		;GET OFN FOR PAGE 0
	 RET			;JFN WENT AWAY
	HLRZS T1		;YES. GET PT0 THEN
	RETSKP			;DONE
;USER REQUEST TO FLUSH THE CACHE

FLSCSH:	MOVX T4,SC%OPR!SC%WHL	;CHECK PRIVILEGES
	TDNN T4,CAPENB		;HAVE ENOUGH?
	ITERR (CAPX1)		;NO. DON'T DO IT THEN
FLSCS0:	LOCK FGLOCK		;LOCK THE CACHE
   REPEAT 0,<			;OLD CODE
FLSSC2:	SETZM P2
	SKIPN FSTTBL		;ANY ENTRIES?
	JRST FLSDON		;NO. ALL DONE THEN
	MOVN P1,FSTTBL		;YES. GET NUMBER
	HRLZS P1
	HRRI P1,FSTTBL+1	;SCAN TABLE
FLSCSL:	JE FGVLD,(P1),FLSX	;THIS ONE VALID?
	SKIPE FGLLCK(P1)	;YES. ANY USERS?
	AOJA P2,FLSX

;FOUND ONE TO DO

	LOAD T1,FGOFN,(P1)	;GET THE OFN
	CALL RELOFN		;RELEASE IT
	LOAD T1,FGSPT,(P1)	;GET SPTN
	CALL DESPT		;RELEASE IT
	SETZRO FGVLD,(P1)	;SAY ENTRY IS NOW FREE
FLSX:	ADDI P1,FSN-1		;NEXT ENTRY
	AOBJN P1,FLSCSL		;DO THEN ALL
	JUMPN P2,[UNLOCK FGLOCK
		MOVEI T1,^D500	;WAIT A WHILE
		DISMS
		JRST FLSCS0]	;AND TRY AGAIN
FLSDON:	SETZM FSTTBL		;NO ENTRIES NOW
   >				;END OF OLD CODE
	MOVE P2,[-FSMAX,,FSTTBL] ;SCAN WHOLE TABLE
FLSLOP:	SKIPN T1,0(P2)		;ANYTHING HERE?
	JRST FLSX		;NO.
	CALL RELOFN		;YES. NOT USING OFN ANYMORE
	SETZM 0(P2)		;AND NOT USING ENTRY
FLSX:	AOBJN P2,FLSLOP		;DO THEM ALL
	UNLOCK FGLOCK		;YES. UNLOCK THE LOCK
	MRETNG			;AND DONE
;SAVE, GIVEN LIST OF BLOCK DESCRIPTORS OR ONE BLOCK DESCRIPTOR
;AC USAGE:
; P6 - FORK HANDLE,,JFN (AC1 ARG AFTER CHECKING, ETC)
; P5 - PTN OF UPT,,0
; P1 - DESCRIPTOR LIST
;  7 - CURRENT DESCRIPTOR

.SAVE::	MCENT
	MOVE P1,2		;SAVE DESCRIPTOR
	CALL GTSVI
	CALL GTSVDV		;SEE IF THE DEVICE IS LEGAL (DISK, MAGTAPE OR DECTAPE)
	 ITERR (SAVX1)		;ILLEGAL DEVICE TO SAVE ONTO; ABORT THE JSYS
	HRRI 2,1B20		;WRITE FILE
	OPENF
	 ITERR			;OPENF FAILED. ABORT THE JSYS
	TLNE P1,-1		;SOMETHING IN LH?
	JRST SAVE3		;YES, IT'S ONE DESCRIPTOR
SAVE2:	UMOVE 7,0(P1)		;GET NEXT DESCRIPTOR
	JUMPE 7,SAVE1		;CHECK FOR END OF LIST OF DESCRIPTORS
	CALL SAVEB		;WRITE BLOCK
	AOJA P1,SAVE2

SAVE3:	MOVE 7,P1
	CALL SAVEB
SAVE1:	HLRZ 1,P6		;FORK HANDLE
	CALL FLOCK		;LOCK THE FORK STRUCTURE
	CALL SETLFK
	PUSH P,ENTVEC(1)	;GET ENTRY VECTOR POINTER
	CALL CLRLFK		;CLEAR PSB MAPPING
	CALL FUNLK		;UNLOCK FORKS
	POP P,2			;RECOVER ENTRY VECTOR
	HRRZ 1,P6		;JFN
	BOUT			;WRITE ENTRY VECTOR POINTER
	CLOSF
	 JFCL
	JRST MRETN
;SAVE, PROCESS ONE BLOCK

SAVEB:	HLRZ 6,7		;MAKE LH COUNT NEGATIVE
	TRZE 6,400000		;LARGER THAN 377777?
	PUSH P,[SAVEBL]		;YES, DO IN TWO PARTS
	MOVNI 6,0(6)
	HRLI 7,0(6)
	SETO 4,			;SAY NO PAGE NOW MAPPED
	NOINT			;BE NOINT WHILE PAGE MAPPED
SAVEB1:	JUMPGE 7,SAVUMP		;DONE, CLEAN UP
	MOVE 6,7		;SETUP TO SCAN FOR NON-0'S
	LDB 1,[POINT 9,6,26]	;GET PAGE NUMBER
	CAIN 1,0(4)		;DIFFERENT FROM CURRENT MAPPING?
	JRST SAVE3A		;NO, SAME
	MOVEI 4,0(1)
	HLL 1,P5		;FORK HANDLE
	PUSH P,1
	SETZ 1,
	MOVEI 2,FPG0A
	CALL SETMPG		;REMOVE EXISTING CONTENTS OF WINDOW
	OKINT
	MOVE 1,0(P)
	CALL MRPACS		;SEE IF PAGE EXISTS
	POP P,2
	NOINT			;BE NOINT WHILE PAGE MAPPED
	TLNN 1,(PA%RD)		;CAN IT BE READ?
	JRST SAVE3B		;NO, FORGET IT
	MOVE 1,2
	MOVE 2,[PTRW+FPG0A]
	CALL SETMPG		;MAP PAGE
SAVE3A:	HRRZ 5,6		;SETUP RELATIVE ADDRESS IN WINDOW
	ANDI 5,PGSIZ-1
	ADDI 5,FPG0A
	JRST SAVE8

SAVE3B:	ANDI 6,777000
	ADDI 6,1000		;TO NEXT PAGE
	SUBI 6,0(7)
	HRLI 6,0(6)		;COUNT OF WORDS SKIPPED IN BOTH HALVES
	ADD 7,6			;UPDATE COUNT AND ADDRESS
	JRST SAVEB1

SAVEBL:	HRLI 7,400000		;DID N-400000 BEFORE, DO LAST 400000 NOW
	NOINT
	JRST SAVEB1
SAVE12:	TRNN 6,777		;NEW PAGE?
	JRST SAVE5		;YES
SAVE8:	SKIPN 0(5)		;NON-0 WORD?
	JRST SAVE6		;NO, GO CHECK FOR MORE
SAVE7:	ADDI 5,1
	AOBJN 6,SAVE12
	MOVE 6,7		;END OF BLOCK
	CALL SAVED
	JRST SAVEB1

;WRITE ALL OR PART OF ONE PAGE.

SAVED:	HLRE 2,6		;COUNT OF WORDS JUST SCANNED
	ADD 5,2			;RESET WINDOW POINTER
	HRRZ 1,P6		;JFN
	MOVE 2,6
	SUBI 2,1		;OUTPUT IOWD CNT,ADR
	BOUT
	 ERJMP SAVERR		;FAILED
	HLRE 3,6		;GET (NEG) COUNT
	PUSH P,3		;SAVE IT
	HRRZ 2,5		;GET STARTING ADR
	HRLI 2,(<POINT 36,0>)	;CONSTRUCT BYTE PTR TO IT
	SOUT			;OUTPUT THE BLOCK
	 ERJMP SAVERR		;FAILED
	POP P,2			;RECOVER STARTING COUNT
	SUB 3,2			;COMPUTE NO. WDS MOVED
	ADDM 3,5		;UPDATE WINDOW PTR
	HRL 3,3			;PUT COUNT IN BOTH HALVES
	ADDM 3,7		;UPDATE AOBJN PTR
	RET


SAVERR:	CALL SAVUMP		;UNMAP ANY PAGE AND GO OKINT
	ITERR (,<MOVE T1,LSTERR>)	;THEN GIVE THE ERROR

SAVUMP:	SETZ T1,		;REMOVE MAPPING
	MOVEI T2,FPG0A		;THAT WE HAD DONE
	CALL SETMPG		;DO IT
	OKINT			;CAN INTERRUPT NOW
	RET			;DONE
;FOUND 0 WORD, CHECK FOR MORE

SAVE6:	MOVEI 2,0(6)
	CAIN 2,0(7)		;FIRST WORD OF BLOCK OR PAGE?
	JRST SAVE9		;YES
	HLRZ 2,6
	SETCMI 3,0(6)
	CAIE 2,-1		;END OF BLOCK, OR
	TRNN 3,777		;END OF PAGE?
	JRST SAVE5		;YES, FINISH BLOCK
	SKIPE 1(5)		;SUCCESSIVE 0?
	JRST SAVE7		;NO, CONTINUE SCAN
SAVE5:	MOVNI 6,0(6)		;COMPUTE NUMBER OF WORD TO DUMP
	ADDI 6,0(7)		;(-CURRENT)+OLD = -DIFFERENCE
	MOVSI 6,0(6)
	HRRI 6,0(7)		;FIRST ADDRESS
	CALL SAVED		;WRITE BLOCK
	JRST SAVEB1

;SCAN OVER BLOCK OF 0'S

SAVE10:	TRNE 6,777		;END OF PAGE?
	SKIPE 0(5)		;OR NON-0 WORD?
	JRST SAVE11		;YES
SAVE9:	ADDI 5,1
	AOBJN 6,SAVE10
SAVE11:	MOVE 7,6		;UPDATE POINTER
	JRST SAVEB1		;RECHECK PAGE, ETC.
;GTSVDV - ROUTINE TO CHECK FOR LEGAL DEVICE FOR SAVE AND SSAVE

;ACCEPTS IN T3: DEVICE CHARACTERISTICS AS RETURNED IN T2 BY DVCHR

;RETURNS +1: ILLEGAL DEVICE
;	 +2: LEGAL DEVICE

;ALLOWS DISK, NUL, MAGTAPE AND DECTAPE
;CLOBBERS T4

GTSVDV:
	LDB T4,[POINTR (T3,DV%TYP)] ;GET THE DEVICE TYPE
	CAIE T4,.DVDSK		;IS IT A DISK?
	CAIN T4,.DVNUL		;OR NUL DEVICE?
	RETSKP			;YES. GOOD
	CAIE T4,.DVMTA		;NO. IS IT A MAGTAPE?
	CAIN T4,.DVDTA		;NO. IS IT A DECTAPE?
	RETSKP			;GOOD CHOICE.  TAKE THE SKIP RETURN
	RET			;NOT DISK, MAGTAPE OR DECTAPE. NONSKIP RETURN.
;SSAVE - CREATES EXE FILES

;ACCEPTS FROM USER:
;  1/ (FORK HANDLE,,JFN)
;  2/ EITHER (0,,ADDRESS OF TABLE) IF TABLE IS MORE THAN 1 WORD OR
;     TABLE WORD
;  3/ FLAGS - NOT IMPLEMENTED
;  A TABLE OF WORDS OF THE FORM
;       (- NUMBER OF PAGES IN GROUP,,ACCESS+1ST CORE PAGE)
;    EACH OF WHICH REPRESENTS A GROUP OF CONTIGUOUS PAGES

; CALL:	SSAVE

;RETURN + 1:ALWAYS
;           ITERR HANDLES ERRORS

;SAVES USER'S CORE IMAGE (LH T1) INTO FILE (RH T1)
;HEADER GOES INTO PAGES 0, 1, AND 2 (IF NEEDED)

;AC USAGE:
;  ALL REGISTERS EXCEPT Q3 ARE USED. SEE INDIVIDUAL ROUTINES FOR
;   COMMENTS

; STRINGS IN DIRECTORY WORDS.  IF COMMENT, DEFINED IN GET

	DEFSTR(EXFLG,,8,9)	;ACCESS BITS 1ST WORD
;	DEFSTR(EXPAG,,35,27)	;FILE PAGE NUMBER 1 ST WORD
;	DEFSTR(EXCNT,,8,9)	;REPEAT COUNT 2ND WORD
;	DEFSTR(EXADR,,35,27)	;CORE PAGE NUMBER 2ND WORD

; ACCESS BITS INPUT AND SHIFTED TO LH
	SSCPY==1B0		;COPY ON WRITE
	SSACC==1B1		;TAKE ACCESS FROM PAGE
	SSWRT==1B3		;ALLOW WRITE

; ACCESS FOR EXE FILE

	EXEWRB==1B2		;WRITABLE
	EXESHR==1B1		;SHARABLE

; BLOCK TYPES  (DEFINED IN GET)

;	EXEFIL=1776		;DIRECTORY
;	EXEEND=1777		;END
;	EXEVEC=1775		;ENTRY VECTOR

;NOTE: THE EXE FILE FORMAT ALLOWS UP TO THREE PAGES OF DIRECTORY.
;HOWEVER, SSAVE IS CURRENTLY LIMITED TO ONE PAGE.

	SSDATA==1		;FIRST DATA PAGE IN OUTPUT FILE

.SSAVE::MCENT
	CALL SSAVA		;CALL ROUTINE TO DO THE SSAVE
	 ITERR			;ERROR RETURN FROM SSAVA
	JRST MRETN		;RETURN FROM SSAVE
;SSAVA - DOES THE WORK FOR SSAVE

;ACCEPTS:
;  SAME AS FOR .SSAVE ABOVE

;CALL:	CALL SSAVA

;RETURN + 1:ERROR CODE IN T1
;       + 2:SUCCESS

;FUNCTION:
;  1) READS THE USER'S INPUT
;  2) SETS UP TO PROCESS EACH GROUP OF PAGES AND CALLS SSAVB
;  3) WRITES THE FILE HEADER INFO

;CALLED BY SSAVE

;AC USAGE:
;  P1/ LOCATION OF CURRENT ENTRY IN DIRECTORY
;  P3/ NEXT FILE PAGE
;  P4/ CURRENT TABLE WORD
;  P6/ (FORK HANDLE,,JFN) AS INPUT IN AC 1
;  T1-T4/ TEMPORARY STORAGE

;TEMPORARY STORAGE: 
;  SSDIR - ADDRESS OF START OF SCRATCH PAGE IN WHICH DIRECTORY IS BUILT
;  SSAC2 - AC2 AS SPECIFIED BY THE USER'S CALLING ROUTINE
;  SSDEV - INDICATES TYPE OF OUTPUT DEVICE AND STATE OF PROCESSING

SSAVA:	STKVAR <SSDIR,SSAC2,SSCORE,SSDEV>
	SETOM SSDEV  		;INITIALIZE TO INDICATE DISK
	CALL GTSVI		;INPUT: USER'S T1/ (FORK HANDLE,,JFN)
				; OUTPUT: T1/JFN, T2/^D36B5, 
				; T3/ DEVICE CHARACTERISTICS,
				; P5/PTN FOR PAGE 0 OF FORK,P6/FORK HANDLE,,JFN
	CALL GTSVDV		;SEE IF THIS IS A LEGAL DEVICE
	 RETBAD (SSAVX1)	;NO. RETURN AN ERROR AND ABORT THE JSYS
	TLNE T3,777		;LEGAL. DISK?
	AOS SSDEV		;NO. INDICATE FIRST PASS ON SEQUENTIAL
	HRRI T2,OF%WR		;WRITE ACCESS - LEFT HALF SET UP FOR
				; 36-BIT BYTES IN GTSVI
	OPENF			;OPEN OUTPUT FILE FOR WRITE
	 RETBAD			;ERROR ON OPEN - CODE IN T1
	SKIPGE SSDEV		;WORKING ON DISK?
	JRST [	HRRZ T1,P6	;YES. T1/JFN
		MOVEI T2,SSDATA*1000 ;T2/POINTER TO START OF 1ST DATA PAGE
		SFPTR		;SET FILE POINTER 
	 	 RETBAD		;FAILED. ERROR IN T1
		JRST .+1]
	NOINT
	CALL ASGPGS		;GET SCRATCH PAGE TO BUILD DIRECTORY IN
	 JRST [	OKINT
	 	RETBAD(SSAVX3)]	;FAILED
	MOVEM T1,SSDIR		;SAVE ADDRESS OF FREE PAGE
	CALL ASGPGS		;GET A PAGE TO MAP USER'S PAGE INTO
	JRST [	MOVEI P4,SSAVX3	;FAILED. SET ERROR CODE
		JRST SSAV6]
	MOVEM T1,SSCORE		;SAVE ADDRESS OF THE PAGE 
	OKINT			;ALLOW INTERRUPTS
	MOVEI P3,SSDATA		;P3/START OF DATA AREA IN FILE
	;..
;HERE BEGINS A LOOP THAT IS PROCESSED ONCE FOR DISK AND TWICE FOR SEQUENTIAL
;DEVICES.  IN THE CASE OF DISK, SSAVB IS CALLED ONCE FOR EACH ENTRY IN THE 
;CALLER'S TABLE.  SSAVB COPIES THE CORE PAGES ONTO DISK (IF NON-ZERO) AND
;BUILDS THE DIRECTORY.  WHEN ALL THE GROUPS HAVE BEEN DONE, THIS ROUTINE WRITES
;THE HEADER PAGES.  FOR A SEQUENTIAL DEVICE, THE FIRST PASS SIMPLY CREATES THE
;DIRECTORY AND WRITES THE HEADER PAGES, SINCE THEY PRECEDE ALL DATA.  SSAVB IS
;CALLED AGAIN TO WRITE THE DATA PAGES.

	;..
SSAV7:	MOVE P1,SSDIR		;P1/START OF DIRECTORY AREA. 
	UMOVE T1,2		;T1 / INPUT AC2 - TABLE WORD OR ADDRESS OF TABLE
	MOVEM T1,SSAC2		;SAVE INPUT AC2 IN TEMPORARY STORAGE
	JUMPL T1,SSAV3		;NEGATIVE IF SINGLE DESCRIPTOR

;TABLE HAS MORE THAN ONE WORD.  T1 POINTS TO CURRENT WORD

SSAV2:	UMOVE P4,0(T1)		;GET NEXT DESCRIPTOR
	JUMPE P4,SSAV1		;0 INDICATES END OF TABLE
	MOVE T2,SSDIR		;PASS ADDRESS OF DIRECTORY SCRATCH  PAGE 
	MOVE T3,SSCORE		;PASS ADDRESS OF CORE SCRATCH PAGE
	MOVE T4,SSDEV		;PASS DEVICE FLAG 
	CALL SSAVB		;GO PROCESS THIS GROUP OF PAGES
	 JRST SSAV5			;ERROR FROM SSAVB - CODE IN T1
	AOS T1,SSAC2		;INCREMENT ADDRESS AND LOAD INTO T1
	JRST SSAV2		;GO GET THE NEXT TABLE WORD

;TABLE HAS ONE WORD. T1 CONTAINS IT.

SSAV3:	MOVE P4,T1		;SINGLE DESCRIPTOR INPUT IN AC 2
	MOVE T2,SSDIR		;PASS ADDRESS OF CORE SCRATCH PAGE 
	MOVE T3,SSCORE		;PASS ADDRESS OF CORE SCRATCH PAGE
	MOVE T4,SSDEV		;PASS DEVICE FLAG
	CALL SSAVB		;GO PROCESS THIS GROUP OF PAGES
	 JRST SSAV5
	;..
;ALL GROUPS HAVE BEEN PROCESSED.  SSDEV INDICATES STATE:
; -1: WORKING ON DISK.  DIRECTORY HAS BEEN BUILT IN SCRATCH PAGE,
;     AND DATA PAGES HAVE BEEN WRITTEN.  WRITE DIRECTORY AND QUIT.
;  0: FIRST PASS ON A SEQUENTIAL DEVICE.  DIRECTORY HAS BEEN BUILT
;     IN SCRATCH PAGE.  WRITE IT AND GO START OVER TO WRITE THE
;     DATA PAGES
;  1: SECOND PASS ON A SEQUENTIAL DEVICE.  DIRECTORY WAS WRITTEN ON
;     FIRST PASS, DATA PAGES ON SECOND.  QUIT.

;NOTE:WHEN SSAVE SUPPORTS MULTIPLE-PAGE DIRECTORIES, THIS CODE
;SHOULD, WHEN SSDEV=0, DETERMINE THE NUMBER OF PAGES IN THE
;DIRECTORY.  IF IT IS LESS THAN 3, IT SHOULD REDUCE ALL THE FILE
;PAGE NUMBERS IN THE DIRECTORY APPROPRIATELY AND SET P3 TO POINT
;TO THE FIRST PAGE AFTER THE DIRECTORY (I.E,. 1 OR 2)

	;..
SSAV1:	SKIPLE SSDEV		;SECOND PASS FOR SEQUENTIAL?
	JRST SSAV8		;YES. ALL DONE. FILE POINTER IS AT END
	SKIPE SSDEV		;NO. PROCESSING DISK?
	JRST [	HRRZ T1,P6	;YES. T1/JFN
		RFPTR		;GET PRESENT FILE POINTER
	 	 JRST SSAV5	;FAILED
		MOVEM T2,P4	;SAVE FILE POINTER
		SETZ T2,	;POINT TO BEGINNING OF FILE
		SFPTR		;SET FILE POINTER TO START DIRECTORY
	 	 JRST SSAV5	;FAILED
		JRST .+1]

;WRITE THE DIRECTORY BLOCK

	SUB P1,SSDIR		;SUBTRACT START OF SCRATCH PAGE FROM CURRENT LOC
	MOVE T2,P1		;NUMBER OF SUBGROUPS DONE *2
	JUMPE T2,SSAV4		;DON'T WRITE DIRECTORY IF NO SUBGROUPS
	ADDI T2,1		;NUMBER OF WORDS IN DIRECTORY (INCLUDES TITLE)
	HRLI T2,EXEFIL		;T2/ (TYPE NO.,,NUMBER WORDS)
	HRRZ T1,P6		;T1/ JFN FOR FILE
	BOUT			;WRITE FIRST WORD OF DIRECTORY
	HRRZ T3,P1		;T3/ (-NUMBER SUBGROUPS IN DIRECTORY)
	MOVNS T3
	MOVX T2,<POINT 36,0>	;T2/POINTER FOR 36-BIT BYTES
	HRR T2,SSDIR		; IN SCRATCH PAGE
	SOUT			;WRITE DIRECTORY
	;..
;ENTRY VECTOR BLOCK

	;..
	HRRI T2,3		;WORD COUNT FOR ENTRY VECTOR BLOCK
	HRLI T2,EXEVEC		;T2/(TYPE NO,,NUMBER WORDS)
	BOUT			;WRITE FIRST WORD OF ENTRY VECTOR BLOCK
	HLRZ T1,P6		;FORK HANDLE
	CALL FLOCK		;LOCK THE FORK STRUCTURE
	CALL SETLFK		;MAP PSB OF FORK (RETURNS OFFSET IN T1)
	MOVE T2,ENTVEC(T1)	;GET THIS FORK'S ENTRY VECTOR WORD
	MOVEM T2,P5		;SAVE ENTRY VECTOR WORD
	CALL CLRLFK		;UNMAP THE PSB
	CALL FUNLK		;UNLOCK THE FORK STRUCTURE
	MOVE T2,P5		;T2/ ENTRY VECTOR WORD
	MOVE T4,T2		;T4/ (ENTRY VECTOR COUNT,,ADDRESS)
	HLRZS T2		;MOVE ENTRY VECTOR COUNT FOR OUTPUT
	HRRZ T1,P6		;JFN FOR OUTPUT FILE
	BOUT			;WRITE ENTRY VECTOR COUNT
	HRRZ T2,T4		;ADDRESS OF ENTRY VECTOR FOR OUTPUT
	BOUT			;WRITE ENTRY VECTOR ADDRESS

;END BLOCK

	HRLI T2,EXEEND
	HRRI T2,1		;T2/ (TYPE NUMBER,,NUMBER WORDS)
	BOUT			;WRITE END BLOCK

;HEADER WRITTEN (DIRECTORY, ENTRY VECTOR, ETC.).  EITHER WORKING
;ON DISK (SSDEV=-1) OR FIRST PASS FOR SEQUENTIAL DEVICE (SSDEV=0)

SSAV4:	SKIPGE SSDEV		;WORKING ON DISK?
	JRST [	HRRZ T1,P6	;YES. T1/JFN
		MOVE T2,P4	;T2/ORIGINAL FILE POINTER (AFTER DATA)
		SFPTR		;SET FILE POINTER AFTER ALL EXISTING PAGES
	 	 JRST SSAV5	;ERROR FROM SFPTR - CODE IN T1
		JRST SSAV8]	;DONE. GO CLOSE THE FILE

;FIRST PASS FOR SEQUENTIAL DEVICE.  WRITE THE REST OF THE PAGE AND
;GO REPEAT THE BUILDING PROCESS TO WRITE THE DATA

	HRRZ T1,P6		;T1/JFN FOR FILE
	SETZM T2		;T2/DATA TO BE WRITTEN
	MOVEI T4,-1000+5	;NEGATIVE SPACE AVAILABLE FOR DIRECTORY
	ADD T4,P1		;NEGATIVE SPACE REMAINING
	HRLZ T4,T4		;TO LEFT HALF FOR COUNTING
	JUMPGE T4,SSAV10	;DON'T WRITE IF PAGE IS FULL
SSAV9:	BOUT			;WRITE A WORD
	AOBJN T4,SSAV9		;CONTINUE UNTIL PAGE COMPLETED
	
SSAV10:	MOVEI P3,SSDATA		;YES. P3/ADDRESS OF 1ST DATA PAGE
	AOS SSDEV		;INDICATE SECOND PASS
	JRST SSAV7		;GO WRITE THE DATA PAGES
;ALL OUTPUT DONE.  CLOSE FILE AND RELEASE SCRATCH PAGES

SSAV8:	HRRZ T1,P6		;JFN
	CLOSF			;CLOSE FILE
	 JFCL
	MOVE T1,SSDIR		;T1/ADDRESS OF DIRECTORY SCRATCH PAGE
	NOINT			;NO INTERRUPTS WHILE RELEASING PAGES
	CALL RELPGS		;RELEASE THE SCRATCH PAGE
	MOVE T1,SSCORE		;T1/ADDRESS OF CORE SCRATCH PAGE
	CALL RELPGS		;RELEASE THE PAGE
	OKINT			;ALLOW INTERRUPTS
	RETSKP			;SUCCESSFUL RETURN

;ERROR OCCURRED AFTER EITHER OR BOTH PAGES WERE OBTAINED.  RELEASE THEM.
;THE FAILING ROUTINE SET THE ERROR CODE IN T1.

SSAV5:	MOVEM T1,P4		;SAVE THE ERROR CODE
	NOINT			;NO INTERRUPTS WHILE RELEASING PAGES
	MOVE T1,SSCORE		;T1/ADDRESS OF CORE SCRATCH PAGE
	CALL RELPGS		;RELEASE THE PAGE

SSAV6:	MOVE T1,SSDIR		;T1/ADDRESS OF DIRECTORY SCRATCH PAGE
	CALL RELPGS		;RELEASE THE PAGE
	MOVE T1,P4		;RESTORE THE ERROR CODE
	OKINT
	RETBAD			;ERROR RETURN
;SSAVB - PROCESSES ONE WORD FROM USER TABLE

;ACCEPTS:
; T2/STARTING ADDRESS OF SCRATCH PAGE TO CONTAIN DIRECTORY
; T3/STARTING ADDRESS OF SCRATCH PAGE TO CONTAIN USER'S CORE PAGE
; T4/-1 OR 1 IF DATA PAGES SHOULD BE WRITTEN. 0 IF BUILD DIRECTORY ONLY
; P1/ADDRESS OF NEXT ENTRY IN THE DIRECTORY
; P3/ NEXT FILE PAGE
; P4/ TABLE WORD AS ENTERED (ACCESS IN 18-26) (SAVED IN SSWORD)
; P6/ FORK HANDLE,,JFN 

;CALL:	CALL SSAVB

;RETURN + 1:ERROR - CODE IN T1
;       + 2:SUCCESS

; SSAVB PROCESSES ONE GROUP OF PAGES AS REQUESTED BY ONE WORD IN
;  THE INPUT TABLE. CONTIGUOUS PAGES FORM ONE SUBGROUP (AND
; THUS ONE ENTRY IN THE DIRECTORY) UNTIL A PAGE DIFFERS FROM ITS
; PREDECESSOR IN ONE OF THE FOLLOWING WAYS:
;  A. PAGE N EITHER
;     1. IS ALL ZERO
;     2. DOES NOT EXIST, OR
;     3. IS NOT READABLE
;     AND N-1 IS NONE OF THE ABOVE
;  B. PAGE N-1 IS ANY OF THE ABOVE AND PAGE N IS NONE
;  C. PAGES N-1 AND N HAVE DIFFERENT ACCESS
; AT THAT POINT THE DIRECTORY ENTRY FOR N-1 IS COMPLETED AND A
; NEW SUBGROUP BEGINS WITH N.

;EACH DIRECTORY ENTRY IS TWO WORDS AS FOLLOWS:
;  - - - - - - - - - - - - - - - - - - - -
;  !ACCESS	  	!FILE PAGE NUMBER!
;  !REPEAT COUNT	!CORE PAGE NUMBER!
;  - - - - - - - - - - - - - - - - - - - -

;WHERE THE PAGE NUMBERS EACH OCCUPY 27 BITS AND REPRESENT THE STARTING PAGES
;IN A GROUP.  THE REPEAT COUNT IS 1 LESS THAN THE NUMBER OF PAGES
;IN A GROUP

;AC USAGE:
; P1/ADDRESS IN SCRATCH PAGE OF FIRST WORD OF CURRENT DIRECTORY ENTRY
; P2/ NUMBER OF PAGES PROCESSED THIS SUBGROUP
; P4/ ADDRESS OF FIRST WORD OF SCRATCH PAGE FOR DIRECTORY
; P5/ ACCESS TO GO WITH PAGE IN FILE
; Q1/ -NUMBER OF PAGES IN GROUP AS INPUT BY USER
; Q2/ NEXT CORE PAGE
; T1-T3/ TEMPORARY STORAGE

;TEMPORARY STORAGE:
; SSWORD - TABLE WORD CURRENTLY BEING DONE (SPECIFIED BY USER IN CALL)
; SSFLAG - FIRST TIME FLAG (0 ON FIRST ENTRY TO ROUTINE)
; SSCORE - SCRATCH PAGE FOR MAPPING USER'S CORE PAGE
; SSDEV -  CONTENTS OF T4 AS PASSED ON ENTRY
SSAVB:	STKVAR <SSFLAG,SSWORD,SSCORE,SSDEV,SSPACC>
	MOVEM T3,SSCORE		;SAVE ADDRESS OF CORE SCRATCH PAGE
	MOVEM T4,SSDEV		;SAVE DEVICE FLAG
	TLC P4,777000		;MAKE SURE COUNT .L. 1000 PAGES
	TLCE P4,777000		;I.E. BITS 0-8 SHOULD BE 1
	RETBAD(SSAVX2)		;LOSE - RETURN CODE IN T1

	MOVEM P4,SSWORD		;SAVE TABLE WORD
	MOVEM T2,P4		;P4/ADDRESS OF DIRECTORY SCRATCH PAGE
	SETZ P2,		;CLEAR COUNT OF PAGES IN SUBGROUP
	SETZM SSFLAG		;CLEAR FIRST TIME FLAG
	HRRZ Q2,SSWORD		;Q2/ NEXT CORE PAGE
	TRZ Q2,777000		;CLEAR ACCESS BITS
	HLRO Q1,SSWORD		;-COUNT OF PAGES

	;..
;SSB10 BEGINS LOOP THROUGH ALL PAGES IN A GROUP AS DESCRIBED BY ONE 
;WORD IN INPUT TABLE. ENDS BEYOND SSAVB5.
 
	;..
SSB10:	HLLZ T1,P6		;FORK HANDLE TO LH
	HRR T1,Q2		;CORE PAGE TO RH OF T1
	RPACS			;GET STATE OF THIS MEM PAGE INTO AC 2
	MOVEM T2,SSPACC		;SAVE ACCESS BITS FOR PAGE
	MOVX P5,<EXEWRB>_-^D27	;SET WRITABLE IN CASE ALL-ZERO OR DOESN'T EXIST
				; (NINE-BIT FIELD RIGHT-JUSTIFIED)
	TXNN T2,PA%PEX		;DOES IT EXIST?
	JRST SSAVB6		;NO. TREAT AS IF ALL-ZERO
	TXNN T2,PA%RD		;YES. READABLE?
	JRST SSAVB6		;NO, TREAT AS IF ALL-ZERO

;MAP THE USER'S PAGE INTO CORE SCRATCH PAGE

	HLL T1,P6		;USER'S FORK HANDLE
	HRR T1,Q2		;CORE PAGE
	CALL FKHPTN		;INPUT: T1/ (FORK HANDLE,,PAGE)
	  ITERR ()		;ILL FORMED RFH
				; OUTPUT: T1/ (PTN,,PAGE)
	MOVE T2,SSCORE		;T2/ADDRESS OF CORE SCRATCH PAGE 
	TXO T2,PM%RD		;READ ACCESS
	CALL SETMPG		;INPUT: T1/ (PTN,,PAGE)
				; T2/(ACCESS ,,MONITOR ADDRESS)
				; SETS UP INDIRECT POINTER TO USER PAGE


; CHECK PAGE FOR ALL ZEROES. GO TO SSAVB6 IF ZERO, SSAVB2 OTHERWISE

	MOVSI T1,-1000		;SET UP COUNTERS
	HRR T1,SSCORE		;POINT TO START OF SCRATCH PAGE
SSAVB9:	SKIPE (T1)		;IS WORD 0?
	JRST SSAVB2		;NO- PAGE CAN'T BE ALL-ZERO
	AOBJN T1,SSAVB9		;KEEP LOOKING
	TXO P5,<EXEZRO>_-^D27	;SET ALL-ZERO BIT
	;..

;CURRENT PAGE ALL ZERO, NOT READABLE, OR DOESN'T EXIST (NOT MAPPED)
;LOOK AT DIRECTORY FOR CURRENT GROUP.  IF SAME AS THIS PAGE, ADD TO 
;CURRENT GROUP.  OTHERWISE, START NEW GROUP

	;..
SSAVB6:	SKIPN SSFLAG		;FIRST TIME THROUGH?
	JRST [	SETOM SSFLAG	;YES. SET THE FLAG
		JRST SSAVB1]	; AND GO SET UP THE DIRECTORY
	LOAD T1,EXFLG,(P1) 	;PUT ACCESS BITS INTO T1 RIGHT-JUST
	CAME T1,P5		;IS ACCESS FOR THIS PAGE SAME
				; AS FOR CURRENT GROUP?
	JRST SSAVB7		;NO. START NEW SUBGROUP
	LOAD T1,EXADR,(P1)	;YES. LOOK AT FILE PAGE NUMBER  
				;  IN FIRST WORD
	JUMPE T1,SSAVB5		;T1 ZERO IF WORKING ON GROUP OF ALL ZEROES

;PREVIOUS GROUP WAS NON-ZERO OR HAD DIFFERENT ACCESS.  FINISH DIRECTORY
;FOR PREVIOUS GROUP AND START DIRECTORY FOR NEW GROUP

SSAVB7:	CALL SSAVC		;FINISH DIRECTORY FOR PREVIOUS GROUP
	 RETBAD

; SET UP DIRECTORY FOR ALL-ZERO BLOCK

SSAVB1:	SETZM (P1)		;SET FILE PAGE NUMBER IN FIRST WORD TO 0
	STOR P5,EXFLG,(P1)	;MOVE ACCESS TO FIRST WORD 
	STOR Q2,EXPAG,1(P1) 	;MOVE CORE PAGE NO TO 2ND WORD
	JRST SSAVB5
;CURRENT PAGE NOT ALL ZERO

;NOTE: THIS BLOCK ASSUMES CERTAIN BIT PATTERNS FOR INPUT TO SSAVE
; AND OUTPUT FROM RPACS.  CHANGING EITHER WILL AFFECT THIS CODE.

SSAVB2:	MOVE T2,SSPACC		;T2/ACCESS FOR USER'S PAGE
	HRL T3,SSWORD		;MOVE ACCESS TO LH OF T3
	TXNE T3,SSACC		;ACCESS PER CORE PAGE REQUESTED?
	JRST [	TXZ T2,SSCPY	;YES. 'AND' ACCESS REQUESTED (LH T3)
				; WITH PAGE ACCESS (LH T2)
		TXNE T2,PA%CPY	;MOVE COPY ON WRITE BIT TO BIT 0 IN T2
		TXO T2,SSCPY	; TO CORRESPOND TO T3
		AND T2,T3	;AND INTO T2
		JRST SSB12]	;T2 CONTAINS ACCESS TO BE GIVEN
	MOVE T2,T3		;NO. SAVE ACCESS REQUEST IN T2
SSB12:	SETZ T3,
	TXNE T2,SSWRT		;WRITE?
	JRST [	TXO T3,EXESHR!EXEWRB ;YES. SET SHARABLE AND WRITABLE
		JRST SSB11]
	TXNE T2,SSCPY		;NO. COPY ON WRITE?
	TXO T3,EXEWRB		;YES. SET WRITABLE
SSB11:	LOAD P5,EXFLG,T3	;SAVE RIGHT-JUSTIFIED IN P5

;LOOK AT DIRECTORY FOR CURRENT GROUP.  IF SAME AS THIS PAGE, ADD TO
;CURRENT GROUP.  OTHERWISE, START NEW GROUP.

	SKIPN SSFLAG		;FIRST TIME THROUGH?
	JRST [	SETOM SSFLAG	;YES. SET FIRST TIME FLAG
		JRST SSAVB3]	;GO SET UP DIRECTORY
	LOAD T1,EXFLG,(P1) 	;PUT ACCESS BITS INTO T1 RIGHT-JUST
	CAME T1,P5		;IS ACCESS FOR THIS PAGE SAME AS FOR
				; CURRENT GROUP?
	JRST SSAVB8		;NO. START NEW SUBGROUP
	LOAD T1,EXADR,(P1) 	;YES. LOOK AT FILE PAGE NUMBER IN 1ST WORD
	JUMPN T1,SSAVB4		;T1 NOT ZERO IF WORKING ON GROUP OF
				; NON-ZERO

;PREVIOUS GROUP WAS ALL-ZERO OR DIFFERENT ACCESS.  FINISH DIRECTORY
;FOR PREVIOUS GROUP AND START DIRECTORY FOR A NEW ONE.

SSAVB8:	CALL SSAVC		;FINISH DIRECTORY FOR PREVIOUS GROUP
	 RETBAD

; SET UP DIRECTORY FOR NON-ZERO BLOCK

SSAVB3:	STOR P5,EXFLG,(P1)	;MOVE ACCESS TO FIRST WORD
	STOR P3,EXADR,(P1) 	;MOVE FILE PAGE NO. TO 1ST WORD
	STOR Q2,EXPAG,1(P1) 	;MOVE CORE PAGE NO TO 2ND WORD
	;..
;COPY NON-ZERO PAGE TO FILE (Q2 POINTS TO CORE PAGE, P3 TO FILE PAGE)

	;..
SSAVB4:	SKIPE SSDEV		;ARE WE WRITING THE DATA PAGES?
	JRST [	HRRZ T1,P6	;YES.T1/JFN
		MOVE T2,[POINT ^D36,0]	;T2/(36 BIT BYTES,,
		HRR T2,SSCORE	;START OF CORE SCRATCH PAGE)
		MOVNI T3,1000	;T3/NEGATIVE BYTE COUNT
		SOUT		;WRITE THE PAGE
		 ERJMP SSAVB0	;FAILED
		JRST .+1]
	AOS P3			;POINT TO NEXT FILE PAGE

;PREPARE FOR NEXT PAGE

SSAVB5:	SETZ T1,		;T1/0 FOR UNMAP
	MOVE T2,SSCORE		;T2/ADDRESS OF CORE SCRATCH PAGE
	CALL SETMPG		;UNMAP THE CORE SCRATCH PAGE
	AOS P2			;INCREMENT PAGE COUNT FOR SUBGROUP
	AOS Q2			;INCREMENT CORE PAGE NO.
	AOJL Q1,SSB10		;INCREMENT DECREASING PAGE COUNT.
				; DONE IF ZERO

; ALL PAGES FOR ONE ENTRY IN INPUT TABLE ARE DONE

	CALL SSAVC		;FINISH LAST DIRECTORY ENTRY AND REINITIALIZE
	 RETBAD
	RETSKP			;SUCCESS

;HERE IF SOUT FAILED WRITING THE .EXE FILE

SSAVB0:	SETZ T1,		;UNMAPPING
	MOVE T2,SSCORE		;ADDRESS OF PAGE TO UNMAP
	CALL SETMPG		;UNMAP THE WINDOW
	HRRZ T1,LSTERR		;GET ERROR CODE RETURNED BY SOUT
	RETBAD			;RETURN ERROR TO CALLER
;SSAVC - CLEANS UP THE DIRECTORY WHEN A SUBGROUP ENDS

;ACCEPTS:
; P4/ADDRESS OF SCRATCH PAGE
;  P1/ ADDRESS OF CURRENT ENTRY IN DIRECTORY
;  P2/ NUMBER OF PAGES IN THIS SUBGROUP

;CALL:	CALL SSAVC

;RETURN + 1:ERROR (DIRECTORY EXCEEDS ONE PAGE)
;       + 2:SUCCESS

;CALLED BY SSAVB

;THIS ROUTINE FILLS IN THE REPEAT COUNT IN THE DIRECTORY ENTRY
;FOR THE CURRENT GROUP.  THE OTHER FIELDS HAVE BEEN SET IN SSAVB
;WHEN THE GROUP BEGAN.

SSAVC:	JE <EXEZRO,EXADR>,(P1),[SETZM 0(P1) ;IF ALLOCATED BUT ZERO
		SETZM 1(P1) 	;CLEAR ENTRY
		JRST SSAVC1]	;AND WRAP UP
	SOS P2			;DECREMENT PAGE COUNT
	STOR P2,EXCNT,1(P1) 	;SAVE  IN 2ND WORD
	ADDI P1,2		;POINT TO NEXT LOCATION IN DIRECTORY
	MOVE T1,P4		;START OF DIRECTORY SCRATCH PAGE
	ADDI T1,772		;LAST WORD OF SCRATCH PAGE
	CAML P1,T1		;P1 POINTS TO FIRST OF PAIR - IS IT
				; BEYOND WORD 771?
	RETBAD(SSAVX4)		;YES. RETURN ERROR
	
SSAVC1:	SETZ P2,		;CLEAR COUNT OF PAGES IN GROUP
	RETSKP
;USAGE UTILITIES FOR JOB 0

;USAGE VARIABLES

NR CKPGID,1			;PAGE IDENT OF CURRENT MAPPED PAGE UN CHECKPOINY FILE

;INIT USAGE DATA BASE

USGINI:	ACVAR <Q1,Q2,Q3>	;PRESERVE ALL TEMP WORK REGS
	STKVAR <CKPNJ,CKIDNT>
	SETOM USGLOK		;CLEAR LOCKS
	SETZM USQCNT		;EMPTY QUEUE
	SETZM USGBEG		;INIT QUEUE
	MOVEI T1,USGBEG-1
	MOVEM T1,USGEND		;TO BE EMPTY
	SETZM USGEOF		;INIT EOF POINTER
	SETZM CKPJFN		;NO JFN'S YET
	SETZM USGJFN		;...
	SETZM CKPGID		;NO PAGE MAPPED
	MOVE T1,TODCLK		;SETUP FIRST CHECKPOINT INTERVAL
	ADD T1,CKPINV
	MOVEM T1,CKPTIM		;TIME FOR FIRST CHECKPOINT
	MOVX T1,SF%CDE		;FILE SYSTEM OK?
	TDNE T1,FACTSW
	JRST [	TMSG <? System accounting will not be done due to file system errors
>
		RET]
USGIN1:	HRROI T2,USGFIL		;FILESPEC FOR USAGE FILE
	CALL USGOPN		;OPEN FILE
	 JRST [	CALL CRUSGF	;NONE - CREATE USAGE FILE
		 BUG (UXXCRE)
		JRST USGIN1]	;TRY AGAIN
	MOVEM T1,USGJFN		;STORE JFN
	TXO T1,CO%NRJ		;RETAIN JFN
	CLOSF			;THIS SHOULD CORRECT PAGE COUNT
	 JFCL			;SHOULDN'T HAPPEN
	MOVX T2,44B5+OF%RD!OF%WR!OF%RTD
	MOVE T1,USGJFN		;FETCH JFN
	OPENF			;OPEN FOR REAL NOW
	 BUG (UXXOPN)
	HRRZ T1,T1		;GET RID OF OPEN FLAGS
	FFFFP			;FIND-FIRST-FREE-FILE PAGE
	HRRZ Q1,T1		;SAVE PAGE NUMBER
	MOVE T1,USGJFN		;JFN AGAIN
	MOVE T2,[1,,.FBBYV]	;GET PAGE COUNT
	MOVEI T3,T4		; INTO T4
	GTFDB
	HRRZS T4		;PAGE # ONLY
	CAME Q1,T4		;CORRECT NUMBER
	BUG (USGHOL)
	JUMPE Q1,USGIN4		;EMPTY FILE IF 0
USGIN2:	SETZ Q2,		;INIT TO WORD 0
	JUMPL Q1,USGIN3		;MUST BE EMPTY IF NONE LEFT
	SOS T1,Q1		;WANT LAST PAGE
	HRL T1,USGJFN		; FROM USAGE FILE
	MOVX T2,PM%RD		;READ ONLY
	CALL USGMAP		;MAP PAGE
	MOVEI Q2,777		;SCAN BACK FROM END OF PAGE
	SKIPN T1,FPG0A(Q2)	; FOR FIRST NON-ZERO WORD
	SOJGE Q2,.-1		;...
	AOJE Q2,[SOJA Q1,USGIN2] ;PAGE WAS ALL ZEROS
				;ADJUST COUNT TO FIRST AVAIL WORD
	;..
	;..
USGIN3:	IMULI Q1,PGSIZ		;CALC EOF POINTER
	ADD Q1,Q2
USGIN4:	MOVEM Q1,USGEOF		;SETUP LOC

;CHECKPOINT INIT

USGIN5:	HRROI T2,CKPFIL		;FILE NAME FOR CHECKPOINT
	CALL USGOPN		;OPEN IT
	 JRST [	CALL CRCKPT	;NON-EX CREATE NEW ONE
		 BUG (UXXCKP)
		JRST USGIN5]
	MOVEM T1,CKPJFN		;SAVE JFN
	HRLZS T1		;START AT PAGE 0
	MOVEM T1,CKIDNT		;SAVE IDENT
	MOVX T2,PM%RD
	CALL USGMAP		;MAP PAGE
	MOVE Q1,FPG0A+1		;GET # OF JOBS IN FILE
	ERJMP CKPBAD		;IF NON-EX PAGE, FILE IS BAD
	MOVE T1,FPG0A+3		;SIZE OF CHECKPOINT RECORD
	CAIN T1,CKPSIZ		;BETTER BE SAME
	CAIGE Q1,NJOBS		;.GE. MAX JOBS IN MONITOR
CKPBAD:	JRST [	BUG (UXXFIT)
		CALL UNMAPC
		MOVE T1,CKPJFN	;CLOSE AND DELETE (EXPUNGE)
		TXO T1,CO%NRJ
		CLOSF
		 JFCL
		MOVE T1,CKPJFN
		TXO T1,DF%EXP
		DELF
		 JFCL
		SETZM CKPJFN
		JRST USGIN5]	;START OVER FOR CHECKPOINT
	MOVEM Q1,CKPNJ		;SAVE NUMBER OF JOBS IN FILE
	MOVE T1,FPG0A+2		;GET DATE/TIME OF LAST CHECKPOINT
	MOVEM T1,CKPDTL		;SAVE
	SKIPN USGEOF		;USAGE FILE EMPTY?
	JRST USGI6B		;YES - SKIP THIS
	HRLZ T1,CKPJFN		;START AT PAGE 0 AGAIN
USGIN6:	MOVEI Q2,PGSIZ/CKPSIZ	;NUMBER OF JOBS/PAGE
	SETZ Q3,		;INIT OFFSET
	MOVX T2,PM%RD
	MOVEM T1,CKIDNT		;SAVE IDENT
	CALL USGMAP
	SKIP FPG0A		;TEST PAGE FOR GOODNESS
	ERJMP CKPBAD		;NOT GOOD IF INTERRUPT TAKES
USGI6A:	SKIPLE T4,FPG0A(Q3)	; .GT. 0 MEANS WRITE IN PROGRESS
	MOVEM T4,USGEOF		;THIS IS ACTUAL USGEOF
	ADDI Q3,CKPSIZ		;STEP TO NEXT ENTYR
	SOJLE Q1,USGI6B		;MORE JOBS TO DO?
	SOJG Q2,USGI6A		;YES - MORE IN THIS PAGE?
	MOVE T1,CKIDNT		;RESTORE LAST PAGE MAPPED
	AOJA T1,USGIN6		;STEP TO NEXT PAGE

USGI6B:	CALL UNMAPC		;UNMAP CHECKPOINT PAGE; THIS IS THE LAST TIME
				; WE WILL BE USING ONLY READ ACCESS
	MOVE T1,USGJFN		;GET USAGE FILE JFN
	MOVE T2,USGEOF		;CURRENT EOF
	SFPTR			;SET TO START WRITTING HERE
	 JFCL			;IGNORE ERRORS
	MOVX T1,SF%USG		;TURN ON USAGE JSYS
	IORM T1,FACTSW		;...
	;..
	;..
				;WRITE RESTART RECORD NOW
	MOVEI T1,.USENT		;GENERATE ENTRY
	MOVEI T2,RSTLST		;POINT TO RESTART LIST
	USAGE			;THIS WILL MAKE A RECORD ON USQ
	CALL USGMES		;IMMEDIATELY WRITE INTO FILE
	MOVEI Q1,1		;MERGE CHECKPOINT FILE
	SOS CKPNJ		; FOR JOBS 1 THRU NJOBS-1
	CALL LGTAD		;GET DATE/TIME
	MOVE Q2,T1		;SAVE IN Q2
USGIN7:	MOVE T1,Q1		;JOB #
	CALL USGSPG		;SET PAGE FOR THIS JOB
	MOVEI T2,.UTCKP		;RECORD TYPE FOR CHECKPOINT MERGE
	HRLM T2,1(T4)		;STORE IN HEADER
	HRRZ T3,1(T4)		;GET RECORD LENGTH
	ADD T3,T4		;ADD IN BASE
	HRLM T2,0(T3)		;STORE TYPE IN TRAILER ALSO
	MOVEM Q2,2(T4)		;SET ENTRY DATE/TIME TO NOW.
	CALL USGUP0		;UPDATE FOR THIS JOB
	CAMGE Q1,CKPNJ		;DONE?
	AOJA Q1,USGIN7		;NO - INCR AND PROCEDE
	CALL UNMAPC		;UNMAP CHECKPOINT PAGE
	CALLRET NXTASC		;Find next acct shift change time
				; and return from USGINI


;Initialize accounting shift change stuff
;Must be done before SETSPD is run!!!

ASCINI:	SETZM ASCPTR		;Indicate no accounting shift changes yet
	SETZM ASCTIM		; and no time set for next one
	SETOM ASCLOK		;Leave ASCPTR lock unlocked
	RET			;Return from ASCINI

;RESTART ENTRY DATA LIST

RSTLST:	USENT. (.UTRST,1,1)	;RESTART RECORD TYPE
	USSNM. (<-1,,SVN>)	;SYSTEM NAME STRING
	USMVR. ([EXP SVNM])	;SYSTEM VERSION NUMBER
	USPNM. (<SIXBIT "MONITR">,US%IMM)
	USPVR. ([EXP SVNM])	;MONITOR NAME/VERSION FOR USAGE
	USMBD. (SYSTAD)		;MONITOR BUILD DATE/TIME
	USLCK. (CKPDTL)		;DATE/TIME OF LAST CHECKPOINT
	USCP0. (APRSER)		;APR SERIAL NUMBER
	0			;END OF LIST
;ROUTINE TO OPEN A FILE FOR READ/WRITE

USGOPN:	MOVX T1,GJ%SHT!GJ%PHY!GJ%OLD
	GTJFN
	 RET			;NON-EX RETURN
	MOVX T2,44B5+OF%RD!OF%WR!OF%RTD
	OPENF			;OPEN FILE
	 RET			;FAILURE
	RETSKP			;OK - RETURN

;ROUTINE TO CREATE USAGE FILE

CRUSGF:	MOVX T1,GJ%SHT!GJ%PHY!GJ%FOU
	HRROI T2,USGFIL
	GTJFN
	 RET			;ERROR
	MOVX T2,44B5+OF%WR	;WRITE FIRST
	OPENF
	 RET			;FAILURE
	CALL USGNOD		;SET NO-DUMP
	HRLI T1,.FBBYV		;CHANGE THIS WORD
	TXO T1,CF%NUD
	MOVX T2,FB%RET		;RETENTION COUNT
	MOVEI T3,0		; TO BE 0
	CHFDB
	HRRZS T1		;JFN ONLY AGAIN
	CLOSF			;FIX ON DISK
	 JFCL
	RETSKP			;GOOD RETURN
;ROUTINE TO COPY CHECKPOINT ENTRY TO USAGE FILE
; T1/ PAGE IDENT
; T4/ ENTRY ADDRESS

USGUP0:	CALL USGUPS		;Perform file update
	SETOM 0(T4)		;SET ENTRY FREE
	RET			;RETURN FROM USGUP0

; Subroutine to copy current checkpoint entry into USAGE file entry

USGUPS:	SKIPGE 0(T4)		;ENTRY ACTIVE?
	 RET			;NO - NOTHING TO DO
	MOVE T1,USGEOF		;GET CURRENT EOF
	MOVEM T1,0(T4)		;SAVE IN CHECKPOINT
	MOVE T1,USGJFN		;JFN FOR USAGE FILE
	MOVEI T2,1(T4)		;ADDRS OF DATA
	HRLI T2,(POINT 36,,)	;FORM BP
	HRRZ T3,0(T2)		;GET LENGTH OF ITEM
	ADDM T3,USGEOF		;UPDATE USAGE EOF POINTER
	MOVNS T3		;MAKE NEGATIVE
	SOUT			;DUMP INTO FILE
	 ERCAL USGIOE		;REPORT IO ERROR
	MOVE T1,USGEOF		;CALC PAGE JUST WRITTEN
	LSH T1,-PGSFT
	HRL T1,USGJFN		;FORM IDENT
	MOVEI T2,1		;DO ONE PAGE
	UFPGS			;UPDATE FILE PAGE
	 ERCAL USGIOE		;REPORT FAILURE
	RET			;Return from USGUPS

;IO ERROR IN USAGE FILE

USGIOE:	MOVE T1,USGEOF		;REPORT BAD PAGE
	LSH T1,-PGSFT
	BUG (UXXWER,<<T1,D>>)
	RET			;CONTINUE
;ROUTINE TO CREATE A CHECKPOINT FILE

CRCKPT:	STKVAR <SCKJFN>
	HRROI T2,CKPFIL
	MOVX T1,GJ%SHT!GJ%PHY!GJ%NEW ;NEW ONLY
	GTJFN
	 ERJMP [MOVX T1,GJ%SHT!GJ%PHY!GJ%DEL	;HANDLE CASE OF THE
		HRROI T2,CKPFIL	; DELETED BUT NOT EXPUNGED FILE
		GTJFN		; TO PREVENT UXXCKP BUGHLTS
		 ERJMP R	;NOT THAT CASE
		HRLI T1,.FBCTL	;WORD IN FDB TO CHANGE
		MOVX T2,FB%DEL	;TO UNDELETE FILE
		SETZM T3	;CLEAR DELETED BIT
		CHFDB		;DO IT
		 ERJMP R	;FAILURE
		HRRZS T1	;CLEAR STUFF FROM LEFT HALF
		JRST .+1]	;AND CONTINUE
	MOVEM T1,SCKJFN		;SAVE FOR LATER
	MOVX T2,44B5+OF%WR!OF%RD ;READ/WRITE
	OPENF
	 RET			;FAILURE
	CALL USGNOD		;SET NO-DUMP
	NOINT			;APPEASE FREE SPACE ROUTINES
	MOVEI T1,CKPSIZ		;ALLOCATE BUFFER
	CALL ASGSWP		; FOR CHECKPOINT RECORD
	 RETBAD (,OKINT)	;NONE TO BE HAD
	MOVE Q2,T1		;SAVE BASE ADDRS
	MOVEI Q1,NJOBS		;INIT FOR NUMBER OF JOBS
	SETOM 0(Q2)		;-1 SHOWS FREE ENTRY
	MOVEM Q1,1(Q2)		;STORE # OF JOBS IN JOB 0
	CALL LGTAD
	MOVEM T1,2(Q2)		;DATE/TIME OF LAST CHECKPOINT
	MOVEI T1,CKPSIZ		;SIZE OF CHECKPOINT RECORD
	MOVEM T1,3(Q2)
	MOVE T1,SCKJFN		;GET JFN
	HRLI Q2,(POINT 36,,)	;FORM BP
CRCKP1:	MOVE T2,Q2		;COPY BP
	MOVNI T3,CKPSIZ		;SIZE OF ENTRY
	SOUT			;WRITE IT
	 ERJMP [OKINT		;UNDO NOINT
		RETBAD ()]	;AND GIVE ERROR
	SOJG Q1,CRCKP1		;LOOP OVER ALL JOBS
	CLOSF			;CLOSE FILE
	 JFCL
	HRRZ T1,Q2		;ADDRS OF TEMP BLOCK
	MOVEI T2,CKPSIZ		; ITS SIZE
	CALL RELSWP		;RELEASE STORAGE
	OKINT			;UNDO NOINT
	RETSKP			;GOOD RETURN
;ROUTINE TO UPDATE CHECKPOINT PAGE AND UNMAP IT

UNMAPC:	MOVEI T2,1		;1 PAGES
	SKIPE T1,CKPGID		;PAGE IDENT OF LAST PAGE MAPPED
	UFPGS			;UPDATE ON DISK
	 JFCL			;WE TRIED
	SETZB T1,CKPGID		;UNMAP PAGE, MARK NO PAGE MAPPED
	MOVEI T2,FPG0A
	CALLRET SETMPG		;...


;ROUTINE TO SET (MAP) CHECKPOINT FILE PAGE FOR JOB N
; T1/ JOB #
;RETURNS:	T4/ ENTRY ADDRESS
;		T1/ PAGE IDENT

USGSPG:	IMULI T1,CKPSIZ		;CALC CHECKPOINT LOC
	IDIVI T1,PGSIZ		;T1 := PAGE , T2 := LINE
	PUSH P,T2		;SAVE LINE
	HRL T1,CKPJFN		;FORM JFN,,PN
	MOVX T2,PM%RD!PM%WR	;READ/WRITE
	CALL USGMAP
	POP P,T4		;RESTORE OFFSET
	ADDI T4,FPG0A		;ADD IN BASE
	RET			; AND RETURN

;ROUTINE TO SET FB%NOD (NODUMP) FOR FILE JFN IN T1

USGNOD:	HRLI T1,.FBCTL		;SAY WORD 1
	TXO T1,CF%NUD		;NO UPDATE DIRECTORY
	MOVX T2,FB%NOD		;SET BIT AND MASK
	MOVX T3,FB%NOD
	CHFDB			;WRITE INTO FDB
	HRRZS T1		;RETURN JFN INTACT
	RET

;ROUTINE TO MAP A PAGE OF A FILE INTO FPG0
;CALL: T1/ JFN,,PAGE#
;      T2/ ACCESS BITS

USGMAP:	CAMN A,CKPGID		;IS THIS PAGE ALREADY MAPPED?
	 RET			;YES-- RETURN NOW FROM USGMAP
	PUSH P,T2		;SAVE ACCESS INFO
	PUSH P,T1		;SAVE PAGE ID
	MOVEI T2,1		;ONE PAGE TO UPDATE
	SKIPE T1,CKPGID		;GET CURRENT PAGE THAT'S MAPPED
	UFPGS			;UPDATE IT
	 JFCL			;WE TRIED
	POP P,T1		;RESTORE PAGE IDENT
	MOVEM T1,CKPGID		;REMEMBER NEW PAGE IDENT
	CALL JFNOFN		;CONVERT TO OFN,,PN
	 BUG (UXXMAP)
	POP P,T2		;RESTORE ACCESS INFO
	HRRI T2,FPG0A		;ADDRS TO MAP PAGE
	CALLRET SETMPG		;MAP THE PAGE
;USAGE QUEUED MESSAGE HANDLER

USGMES:	ACVAR <Q1,Q2,Q3>	;SAVE REGS
USGMS0:	SKIPN Q1,USGBEG		;ANYTHING ON QUEUE?
	RET			;NO - DONE
	LOAD T1,UQFCN,(Q1)	;GET FCN CODE
	CAILE T1,USGLGL		;CHECK VALID
USGBFC:	BUG (UXXILL)
	CALL @USGREQ(T1)	;DISPATCH
	CALL OFFUSQ		;REMOVE FROM QUEUE
	JRST USGMS0		;LOOP TILL DONE

;DISPATCH TABLE

USGREQ:	DTBDSP (USGENT)		;0 - WRITE ENTRY INTO FILE
	DTBDSP (USGCLS)		;1 - CLOSE OUT FILE
	DTBDSP (USGCKU)		;2 - CHECKUOINT
	DTBDSP (USGLGI)		;3 - LOGIN
	DTBDSP (USGLGO)		;4 - LOGOUT
	DTBDSP (USGSEN)		;5 - SESSION ENTRY
	DTBDSP (USGBFC)		;6 - ILLEGAL
	DTBDSP (USGBFC)		;7 - ILLEGAL
	DTBDSP (USGASU)		;10 - Accounting shift change
   USGLGL==.-USGREQ-1
;JOB 0 ROUTINE TO PERFORM CHECKPOINT TIMING

CHKCKP:	MOVE T1,TODCLK		;CURRENT TIME
	CAMGE T1,CKPTIM		;TIME FOR CHECKPOINT?
	RET			;NO - RETURN
	ACVAR <Q1,Q2,Q3>	;SAVE REGS
	MOVE T1,FACTSW		;CHECK IF ACCOUNTING
	TXNE T1,SF%USG		;???
	CALL USGCKP		;YES - CHECKPOINT ALL JOBS
	MOVE T1,TODCLK		;RESET NEXT TIME
	ADD T1,CKPINV		;ADD INTERVAL
	MOVEM T1,CKPTIM		;SAVE NEW TIME
	RET			;RETURN


;Job 0 routine to perform automatic accounting shift change

CHKASC:	SKIPE T1,ASCTIM		;Get next accounting shift change time
	CAMLE T1,TODCLK		;Time for change yet?
	 RET			;Not yet.
	ACVAR <Q1,Q2,Q3>	;Need all the Q's for this...
	MOVE T1,FACTSW		;Get current state bits
	TXNE T1,SF%USG		;Doing accounting today?
	 CALL USGASC		;Yes-- perform accounting shift change
;	CALLRET NXTASC		;Compute next time for change and return from CHKASC
; NXTASC - Compute next accounting shift change time
;
; Register usage in this routine:
; T1/	Current DOW/time table entry
; T2/	Time selected from table (-1 if none found yet)
; T3/	Bit for current DOW (day-of-week) being tested
; T4/	Current pointer to DOW/time table
; Q1/	Bit for DOW of today
; Q2/	Current time in seconds since midnight of the day being tested
;	(will be negative if other than today)

; DOW/time table entry format:
; LH:	Bit n on means that this entry valid on day-of-week (DOW) n
;	(0=Monday)
; RH:	Time-of-day when shift will occur on selected DOWs, in 
;	seconds since midnight.

NXTASC::
	ACVAR <Q1,Q2,Q3>	;Need all the Q's
	LOCK ASCLOK		;Lock time table database

	MOVX T2,-1		;Use current date/time
	MOVX T4,0		;No options
	ODCNV			;Get time, day-of-week, etc.
	 ERJMP NXTAS7		;No date/time-- set next time to never
	HRRZ Q2,T4		;Save the seconds since midnight now
	MOVX Q1,1B0		;Get first bit for Monday
	MOVNI T1,(T3)		;Get -ve day of week (0=Monday)
	LSH Q1,(T1)		;Get bit for this day of week in Q1
	MOVE T3,Q1		;Start testing at today's DOW

	MOVX T2,^D<24*60*60>	;Indicate no time found yet

; Loop through table, once for each DOW in the future, until
;  next accounting shift change time is found

NXTAS1:	SKIPN T4,ASCPTR		;Get AOBJN pointer to DOW/time table
	 JRST NXTAS7		;No table-- set next time to infinity

; Loop through table for this DOW to see if any changes this day

NXTAS2:	MOVE T1,(T4)		;Get entry from table
	TDNN T1,T3		;Entry in effect this DOW?
	 JRST NXTAS3		;No-- skip it
	CAIGE Q2,(T1)		;Has the time for this change already past?
	CAIG T2,(T1)		; or have we already found an earlier time?
	 JRST NXTAS3		;Yes to either question-- skip entry
	HRRZ T2,T1		;Found a reasonable time-- remember it

NXTAS3:	AOBJN T4,NXTAS2		;Loop through whole table

	CAIGE T2,^D<24*60*60>	;Find a valid entry?
	 JRST NXTAS8		;Yes-- go compute time from now

; No time found this DOW-- step to next day in future and search table again

	TDNE T3,Q1		;Back to today?
	 JUMPL Q2,NXTAS7	;Yes-- give up if not first time
	SUBI Q2,^D<24*60*60>	;Step current time back another day
	LSH T3,-1		;Shift to next DOW
	TXNE T3,1B7		;Beyond Sunday?
	 MOVX T3,1B0		;Yes-- reset back to Monday
	JRST NXTAS1		;Keep searching table

; No table or no entries with any DOW's-- set next time to infinity

NXTAS7:	SETZ T2,		;Indicate no time set
	JRST NXTAS9		;Store and return

; Found next applicable table entry-- find out when the change should occur

NXTAS8:	SUB T2,Q2		;Compute seconds from now till
				; when entry time will occur
	IMULI T2,^D1000		;Convert to TODCLK units of MS
	ADD T2,TODCLK		;Compute TODCLK time when we will change

NXTAS9:	MOVEM T2,ASCTIM		;Save next change time
	UNLOCK ASCLOK		;Unlock ASCPTR database
	RET			;Return from NXTASC
;WRITE ENTRY INTO FILE FROM QUEUE

USGENT:	MOVE T1,USGJFN		;GET JFN
	MOVEI T2,UQDAT(Q1)	;POINT TO DATA
	HRLI T2,(POINT 36,,)	;FORM BP
	HRRZ T3,UQDAT(Q1)	;GET LENGTH OF ITEM
	ADDM T3,USGEOF		;UPDATE EOF POINTER
	MOVNS T3		;NEGATE
	SOUT			;WRITE IN FILE
	 ERCAL USGIOE		;REPORT ERROR
	MOVE T1,USGEOF		;CALC PAGE JUST WRITTEN
	LSH T1,-PGSFT
	HRL T1,USGJFN		;FORM IDENT
	MOVEI T2,1		;DO ONE PAGE
	UFPGS			;UPDATE FILE PAGE
	 ERCAL USGIOE		;OH WELL...
	RET			;DONE

;CLOSE OUT CURRENT FILE AND START A NEW ONE

USGCLS:	STKVAR <NJFN>
	CALL CRUSGF		;CREATE A NEW FILE
	 JRST [	BUG (UXXCL1)
		RET]		;JUST EXIT - NOTHING DONE
	HRROI T2,USGFIL		;NOW OPEN IT
	CALL USGOPN
	 JRST [	BUG (UXXCL2)
		RET]		;TOUGH AGAIN
	MOVEM T1,NJFN		;SAVE NEW JFN
	MOVE T1,USGJFN		;GET CURRENT JFN
	HRLI T1,.FBCTL		;THIS WORD
	TXO T1,CF%NUD		;DONT UPDATE DIR
	MOVX T2,FB%NOD		;SET TO CLEAR THIS BIT
	SETZ T3,		; TO ALLOW FILE TO DUMP
	CHFDB
	 ERJMP .+1		;WE TRIED
	HRRZS T1		;RESTORE JFN
	CLOSF			;CLOSE OUT FILE
	 BUG (UXXCL3)
	SETZM USGEOF		;SETUP FOR NEW FILE
	MOVE T1,NJFN
	MOVEM T1,USGJFN		;NOW HAVE NEW FILE TO USE
	UNLOCK (USGLOK)		;UNLOCK WAITER
	RET			;RETURN
;ROUTINE TO SET CHECKPOINT FROM QUEUE
;RETURNS: Q2/ PAGE IDENT

UCKSET:	HRRZ T1,UQDAT+2(Q1)	;GET JOB #
	CALL USGSPG		;SET CHECKPOINT PAGE
	MOVE Q2,T1		;SAVE IDENT
	MOVEI T1,2(T4)		;SET FROM,,TO FOR CLEAR
	HRLI T1,1(T4)		;...
	SETZM 1(T4)		;ZERO FIRST WORD
	BLT T1,CKPSIZ-1(T4)	;CLEAR
	MOVEI T1,1(T4)		;POINT TO DESTINATION
	HRLI T1,UQDAT(Q1)	; LHS := DATA
	HRRZ T2,UQDAT(Q1)	;GET LENGTH
	ADD T2,T4		;LAST WORD OF XFER
	BLT T1,0(T2)		;MOVE DATA
	SETZM 0(T4)		;MARK ITEM INUSE
	RET			;RETURN DONE

;HANDLE USAGE LOGIN

USGLGI:	CALL UCKSET		;COPY DATA TO CHECKPOINT
	CALLRET UNMAPC		;EXIT AND UNMAP PAGE

;HANDLE USAGE LOGOUT

USGLGO:	CALL UCKSET		;COPY DATA TO CHECKPOINT
	MOVE T1,Q2		;SETUP IDENT
	CALL USGUP0		;UPDATE USAGE FILE (CLEAR CKPT)
	CALLRET UNMAPC		;EXIT AND UNMAP PAGE

;HANDLE SESSION END

USGSEN:	HRRZ T1,UQDAT+2(Q1)	;SETUP JOB NUMBER
	CALL USGSPG		;MAP CHECKPOINT ENTRY
	PUSH P,T4		;SAVE ADDRS
	HRRZ T3,1(T4)		;CALC POINTER TO CHECKPOINT DATA
	ADDI T3,CKOFF(T4)
	HRRZ T2,UQDAT(Q1)	;CALC POINTER INTO QUEUE ENTRY
	ADDI T2,CKOFF+1(Q1)	; FOR CKPT DATA
	MOVE T4,1(T2)		;UPDATE CHECKPOINT FILE
	MOVEM T4,1(T3)		; DATA FOR RUNTIME AND
	MOVE T4,2(T2)		; CONSOLE CONNECT TIME
	MOVEM T4,2(T3)
	POP P,T4		;RESTORE ADDRS
	CALL USGUP0		;MERGE INTO USAGE FILE(T1 AND T4 SETUP)
	CALL UCKSET		;COPY NEW CHECKPOINT INFO
	HRRZ T1,1(T4)		;NOW SETUP TO CLEAR CHECKPOINT
	ADDI T1,CKOFF(T4)
	SETZM 1(T1)		;DATA FOR RUTIME AND CONNECT
	SETZM 2(T1)		;...
	CALLRET UNMAPC		;UNMAP CHECKPOINT PAGE
;ROUTINE TO UPDATE CHECKPOINT ENTRY FOR A SINGLE JOB
; T1/ JOB NUMBER

CPOINT:	SETZM ASCFLG		;Don't perform accounting shift change
CPONT0:	ACVAR <Q1,Q2,Q3>	;SAVE REGS
	STKVAR <PGID,CPAD,CPIP>	;Page ident, chekpoint address,
				; checkpoint item AOBJN pointer
	MOVE Q1,T1		;SAVE JOB # IN Q1
	CALL USGSPG		;SET CHECKPOINT PAGE
	MOVEM T1,PGID		;Save checkpoint page address in PGID
	MOVEM T4,CPAD		;Save address within page in CPAD
	HRRZ Q3,1(T4)		;GET LENGTH OF ENTRY
	ADDI Q3,CKOFF(T4)	;POINT TO CHECKPOINT DATA
	HRLI Q3,-CKITMS		;FORM AOBJN PNTR
	MOVEM Q3,CPIP		;Save checkpoint item pointer
	CALL LGTAD		;GET CURRENT DATE/TIME
	MOVEM T1,2(T4)		; INTO CHECKPOINT RECORD
	MOVE T1,Q1		;JOB #
	NOSKED			;DO THIS NOSKED
	SKIPN JOBDIR(T1)	;JOB LOGGED IN?
	JRST [	OKSKED		;NO - JUST RETURN
		JRST CPNT3]
	CALL SETJSB		;MAP JSB FOR JOB
	OKSKED			;JOB IS NOW FIXED IN MY MAP
	MOVE T3,T1		;SAVE PNTR IN T3
	MOVEI Q2,0		;INIT INDEX TO 0
CPNT1:	XCT CPTBL(Q2)		;FETCH WORD
	MOVEM T1,0(Q3)		;STORE
	AOS Q2			;STEP TO NEXT TABLE ENTRY
	AOBJN Q3,CPNT1

	SKIPN ASCFLG		;This accounting shift change also?
	 JRST CPNT2		;No-- go on

; Accounting shift change-- update USAGE file

	MOVE T1,PGID		;Get page ident
	MOVE T4,CPAD		;Address within page
	PUSH P,T3		;Save JSB pointer
	CALL USGUPS		;Make new USAGE entry
	SETZM 0(T4)		;Indicate checkpoint entry still in use
	POP P,T3		;Restore JSB pointer

; Reset job statistics and set new checkpoint entry

	MOVE Q3,CPIP		;Get checkpoint item pointer
	MOVEI Q2,0		;INIT INDEX TO 0
CPNT11:	MOVE T1,0(Q3)		;Get old value
	XCT SETBL(Q2)		;Reset current value of data item
	XCT CPTBL(Q2)		;Get new value of data item
	MOVEM T1,0(Q3)		;STORE
	AOS Q2			;STEP TO NEXT TABLE ENTRY
	AOBJN Q3,CPNT11

CPNT2:	CALL CLRJSB		;UNMAP JSB
CPNT3:	RET			;RETURN FROM CPOINT

;CHECKPOINT DATA TABLE

CPTBL:	MOVE T1,CTIMON(T3)	;(0) SESSION START TIME
	CALL CPGCON		;(1) GET CONNECT TIME
	CALL CPGRTM		;(2) JOB RUN TIME

;Checkpoint data routines

CPGCON:	MOVE T1,TODCLK		;CURRENT DATE/TIME
	SUB T1,CONSTO(T3)	; LESS START TIME
	SUB T1,JSSCTM		; from start of session
	RET			;GIVES CONNECT TIME

CPGRTM:	MOVE T1,JOBRT(Q1)	;Get job runtime
	SUB T1,JSSRTM(T3)	; from start of session
	RET			;Return from CPGRTM

;Session End data table

SETBL:	CALL SESCTI		;(0) Date/time of session start
	ADDM T1,JSSCTM(T3)	;(1) Console time start of session
	ADDM T1,JSSRTM(T3)	;(2) Runtime start of session

;Session End data routines

SESCTI:	CALL LGTAD		;Get current date/time
	MOVEM T1,CTIMON(T3)	;Set start of new session
	RET			;Return from SESCTI
;PERFORM CHECKPOINT OVER ALL JOBS

USGCKU:	CALL USGCKP		;DO WORK
	JRST USGULR		;Unlock waiter and return

;Perform accounting shift change

USGASU:	CALL USGASC		;Do work
USGULR:	UNLOCK (USGLOK)		;UNLOCK WAITER
	RET			;RETURN

;Internal routine to perform checkpoint of all jobs
; or accounting shift change

USGCKP:	SETZM ASCFLG		;Note not accounting shift change
	JRST USGC00		;Continue

USGASC:	SETOM ASCFLG		;Note accounting shift change
USGC00:	MOVEI Q1,NJOBS-1	;MAX JOBS TO DO

; Loop over all active jobs

USGCK0:	SKIPN JOBDIR(Q1)	;JOB EXIST AND IS LOGGED IN?
	JRST USGCK1		;NO - STEP TO NEXT
	MOVE T1,Q1		;COPY JOB #
	CALL CPONT0		;CHECKPOINT ONE JOB
USGCK1:	SOJG Q1,USGCK0		;LOOP OVER ALL
	MOVEI T1,0		;MAP JOB 0 ENTRY
	CALL USGSPG		;...
	MOVE Q1,T4		;POINTER TO ENTRY
	MOVE Q2,T1		;PAGE IDENT
	CALL LGTAD		;GET CURRENT DATE/TIME
	MOVEM T1,2(Q1)		;UPDATE DATE/TIME OF CKPOINT
	MOVE T1,Q2		;UNMAP PAGE
	CALLRET UNMAPC		; AND EXIT
	RESCD

	TNXEND
	END