Google
 

Trailing-Edge - PDP-10 Archives - BB-D868C-BM - 4-sources/sysjob.mac
There are 32 other files named sysjob.mac in the archive. Click here to see a list.
;<4.UTILITIES>SYSJOB.MAC.16,  3-Jan-80 15:27:29, EDIT BY R.ACE
;UPDATE COPYRIGHT DATE
;<4.UTILITIES>SYSJOB.MAC.15, 13-Nov-79 15:58:43, EDIT BY MURPHY
;<4.UTILITIES>SYSJOB.MAC.14, 13-Nov-79 15:50:43, EDIT BY MURPHY
;ADD ERJMP AFTER BOUT TO PTY
;<4.UTILITIES>SYSJOB.MAC.13,  1-Oct-79 07:24:39, EDIT BY R.ACE
;<4.UTILITIES>SYSJOB.MAC.12,  1-Oct-79 07:22:44, EDIT BY R.ACE
;TCO 4.2502 - ADD ERJMP AFTER JFNS JSYS
;<4.UTILITIES>SYSJOB.MAC.11, 21-Jun-79 16:39:25, EDIT BY KIRSCHEN
;REMOVE SUPERFLUOUS MESSAGE IF CANNOT GET JOB LOCATION;<4.UTILITIES>SYSJOB.MAC.10, 11-Apr-79 10:25:03, EDIT BY KIRSCHEN
;<4.UTILITIES>SYSJOB.MAC.9, 11-Apr-79 09:59:11, EDIT BY KIRSCHEN
;SET JOB 0 LOCATION TO LOCAL NODE
;<4.UTILITIES>SYSJOB.MAC.8, 15-Mar-79 10:38:47, EDIT BY KIRSCHEN
;make fork status output be octal to agree with purge command
;<4.UTILITIES>SYSJOB.MAC.7, 12-Mar-79 14:23:25, EDIT BY KONEN
;UPDATE COPYRIGHT FOR RELEASE 4
;<4.UTILITIES>SYSJOB.MAC.6,  1-Feb-79 12:08:21, EDIT BY KIRSCHEN
;TCO 4.2180 - Add the PURGE command to kill a specific fork.
;<4.UTILITIES>SYSJOB.MAC.5, 23-Jan-79 16:21:27, Edit by KONEN
;UPDATE VERSION NUMBER FOR RELEASE 4
;<4.UTILITIES>SYSJOB.MAC.4, 13-Dec-78 14:15:56, EDIT BY DBELL
;MOVE TESTSW SO IT ISN'T CLEARED ON STARTUP
;<4.UTILITIES>SYSJOB.MAC.3, 13-Dec-78 11:24:02, EDIT BY DBELL
;TCO 4.2120 - IMPROVE HANDLING OF JOB CREATION ON PTYS
;<4.UTILITIES>SYSJOB.MAC.2, 29-Jul-78 13:18:00, EDIT BY MILLER
;MORE FIXES
;<4.UTILITIES>SYSJOB.MAC.1, 28-Jul-78 15:28:05, EDIT BY MILLER
;MAKE SYSJOB IMPERVIOUS TO FILE ERRORS



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

;EXECUTIVE TO CONTROL 'DETACHED' SYSTEM JOBS - D. MURPHY

	TITLE SYSJOB
	SEARCH MONSYM,MACSYM
	SALL
	IFNDEF .PSECT,<
	.DIRECT .XTABM>

; VERSION NUMBER DEFINITIONS

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

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

P=17
F=0
A=1
B=2
C=3
D=4
Q1=5
Q2=6
Q3=7
P1=10
P2=11
P3=12
P4=13
P5=14
NX=15			;NAME INDEX

NPDL==40

NJOBS==20		;MAX NUMBER OF SIMULTANEOUS JOBS
NAJOBS==100		;MAX NUMBER ADVANCE JOBS
NAJCW==10		;NUMBER WORDS FOR COMMAND STRING FOR EACH AJOB
NLINES==20		;MAX NUMBER PTY LINES ACTIVE
NWSBUF==^D40		;NUMBER OF WORDS PER STRING BUFFER
NLCLBF==100		;SIZE OF LOCAL TERMINAL INPUT BUFFER

OPDEF CALL [PUSHJ P,0]
OPDEF RET [POPJ P,0]
DEFINE RETSKP <
	JRST RSKP>

DEFINE PMSG (MSG)<
	HRROI 1,[ASCIZ \MSG\]
	PSOUT>

;GENERAL JSYS ERROR HANDLER

DEFINE JERR <
	CALL JERR0>
;CHARACTERS USED

ESCC=="^"		;ESCAPE CHARACTER IN PTY INPUT
ESC==33			;'ESC'

INTCCD==3		;^C IS INTERRUPT CHAR, FORCES RESTART
RSTCCD==2		;^B IS INTERRUPT CHAR, FORCES RELOAD

PTCHN==2		;CHANNELS (2 AND 3) USED BY PTYS

.TTDPI==24		;FUNCTION CODE - DECLARE PTY INTERRUPTS
.TTTIH==25		; "" - TEST INPUT HUNGRY

FRKTMF=1B1		;FORK TERMINATION NOTED BY INTERRUPT
AJCMF=1B2		;COMMAND COMING FROM AJOB STRING BUFFER

EVEC:	JRST START		;REGULAR START
	JRST DSTRT		;DETACH AND START
	VSYSJB			;VERSION NUMBER

RSKP:	AOS 0(P)
R:	RET
;THE W,X,Y,Z ARE CALCULATED BY THE MACRO LIKE THIS:

;W - THE NUMBERICAL VALUE OF VMAJOR
;
;X - THE LETTER CORRESPONDING TO THE VALUE OF VMINOR.  @=0, A=1...
;
;Y - THE NUMERICAL VALUE OF VEDIT
;
;Z - THE NUMERICAL VALUE OF VWHO

	DEFINE	.CLNAM<
	  DEFINE  .CLNM(LETTER,WHO)<
	    IRPC LETTER,<
	      IFE "A"-"'LETTER'"+VMINOR-1,<
		STOPI
		IFIDN <LETTER><@>,<
		  IFE VWHO,< .NAME(\VMAJOR,,\VEDIT,)>
		  IFN VWHO,< .NAME(\VMAJOR,,\VEDIT,-WHO)>>
		IFDIF <LETTER><@>,<
		  IFE VWHO,< .NAME(\VMAJOR,LETTER,\VEDIT,)>
		  IFN VWHO,< .NAME(\VMAJOR,LETTER,\VEDIT,-WHO)>>>>>
	IFGE VMINOR-^D26,< VMINOR==0
	  PRINTX %MINOR VERSION TOO LARGE - IGNORED>
	IFGE VWHO-7,< VMINOR== 
	  PRINTX %VWHO IS TOO LARGE - IGNORED>
	.CLNM(@ABCDEFGHIJKLMNOPQRSTUVWXYZ,\VWHO)
>

;DEFINE A .NAME MACRO TO GEN THE TEXT STRING

	DEFINE	.NAME(V,M,E,W)<
ASCIZ /V'M'('E')'W/>
;ENTRY POINTS

;DETACH AND START - MAKE PRIMARY OUTPUT FOR THIS JOB
;BE JOB 0'S LOGGING TTY

DSTRT:	DTACH
	MOVE 1,[SIXBIT /LOGDES/]
	SYSGT			;GET TABLE NUMBER FOR JOB 0 TTY
	JUMPE 2,DSTRT1		;JUMP IF NO SUCH TABLE
	HRLI 1,1		;GET ENTRY 1
	GETAB
DSTRT1:	 MOVEI 1,377777		;IF CAN'T GET JOB 0 TTY, USE NUL
	HRLI 1,-1		;SHOULD NEVER DO PRIMARY INPUT
	MOVE 2,1
	MOVEI 1,.FHSLF
	SPJFN			;MAKE PRIMARY OUTPUT TO JOB 0 TTY

;NORMAL START
;INITIALIZE STORAGE AREA; ENABLE ALL AVAILABLE CAPABILITIES
;PRINT STARTING MESSAGE; GET DBUGSW FROM SYSTEM

START:	RESET
	MOVE P,[IOWD NPDL,PDL]
	MOVE A,[STGBGN,,STGBGN+1]
	SETZM -1(A)
	BLT A,STGEND-1		;CLEAR ALL STORAGE
	SETZ F,
	CALL SETLOC		;SET JOB LOCATION IF UNDER JOB 0
	GTAD			;TRY TO GET TAD
	JUMPL 1,[MOVEI 1,^D5000	;IF NOT SET YET, WAIT AWHILE
		DISMS
		JRST START]	;THEN TRY AGAIN
	MOVEI 1,400000
	RPCAP
	MOVE 3,2
	EPCAP			;ENABLE ALL POSSIBLE CAPS
	PMSG <
SYSJOB >
	HRROI A,VTXT
	PSOUT
	PMSG < started at >
	MOVEI 1,101
	SETO B,
	MOVSI C,240
	ODTIM			;TIMESTAMP THE RESTART
	PMSG <
>
	MOVE 1,[SIXBIT /DBUGSW/]
	SYSGT			;GET DBUGSW FROM SYSTEM
	CAIN 2,0
	SETZ 1,			;ASSUME 0 IF NO DBUGSW TABLE
	MOVEM 1,DBUGSW
	; ..
;SET UP THE INTERRUPT SYSTEM

	MOVEI 1,400000		;INIT PSI SYSTEM, THIS FORK
	MOVE 2,[XWD LEVT,CHNT]
	SIR
	MOVE 2,CHNMSK
	AIC
	EIR
	GJINF			;GET OUR JOB NUMBER
	JUMPN 3,ST1		;NO INTERRUPT CHAR NEED IF NOT JOB 0
	MOVE 1,[XWD INTCCD,0]	;PUT THE INTERRUPT CHAR ON 0
	ATI
	MOVE 1,[RSTCCD,,1]	;ASSIGN RELOAD CHAR TO 1
	ATI

;STORE INFORMATION ABOUT SYSTEM TABLES

ST1:	MOVE 1,[SIXBIT /PTYPAR/]
	SYSGT			;GET NUMBER OF FIRST PTY
	HRRZM 1,FIRPTY
	MOVE 1,[SIXBIT /TTYJOB/]
	SYSGT			;GET NUMBER OF TTYJOB TABLE
	HRRZM 2,TTYJOB
	MOVE 1,[SIXBIT /JOBNAM/]
	SYSGT			;GET NUMBER OF JOBNAM TABLE
	HRRZM 2,JOBNAM
	MOVE 1,[SIXBIT /SNAMES/]
	SYSGT			;GET NUMBER OF SYSTEM PROGRAM TABLE
	HRRZM 2,SNAMES

;GET COMMAND FILE FOR STARTUP AND EXECUTE COMMANDS.  IF SYSTEM IS BEING
;DEBUGGED (DBUGSW IS 2 OR TESTSW IS NON-ZERO) USE A SPECIAL FILE
;EXECUTE ALL COMMANDS IN THE FILE AND CLOSE IT

	MOVEI A,.SFCDE		;SEE IF OK TO START
	TMON
	JUMPN B,[PMSG <SYSJOB startup deferred due to file system errors.
>
		  JRST ST3]
	MOVSI 1,(1B2+1B17)	;SETUP TO DO INITIAL COMMANDS
	HRROI 2,[ASCIZ /SYSTEM:SYSJOB.RUN/]
	MOVE 3,DBUGSW
	CAIL 3,2		;DEBUGGING?
	HRROI 2,[ASCIZ /SYSTEM:SYSJOB.DEBUG/] ;YES, USE OTHER FILE
	SKIPE TESTSW		;TESTING SYSJOB?
	HRROI 2,[ASCIZ /SYSJOB.TEST0/] ;YES, USE LOCAL FILE
	GTJFN			;GET JFN FOR DESIRED FILE
	 JRST [	PMSG <SYSJOB command file not found.
>
		JRST ST3]
	MOVEM 1,INJFN		;SAVE THE JFN
	MOVE 2,[7B5+1B19];;	;7-BIT BYTES, READ
	OPENF			;OPEN THE FILE
	 JRST [	JERR
		MOVE 1,INJFN
		RLJFN
		 JFCL
		JRST ST3]
	CALL DOCMND		;READ AND PROCESS ALL COMMANDS IN THE FILE
	MOVE 1,INJFN		;1/JFN FOR INITIAL COMMAND FILE
	CLOSF			;CLOSE THE FILE
	 JFCL
	; ..
;ALL INITIAL COMMANDS HAVE BEEN PROCESSED
;IF THIS JOB IS ATTACHED TO A TERMINAL, START A FORK TO READ COMMANDS
;FROM THE TERMINAL.

ST3:	MOVEI 1,.FHSLF		;1/FORK HANDLE FOR THIS FORK
	GPJFN			;GET PRIMARY INPUT AND OUTPUT JFNS
	HLRZ 2,2		;GET PRIMARY INPUT
	CAIE 2,-1		;CONTROLLING TTY?
	JRST ST2		;NO
	GJINF			;YES. GET INFO ON CURRENT JOB
	CAMN 4,[-1]		;IS IT ATTACHED TO A TERMINAL?
	JRST ST2		;NO, DETACHED

;JOB IS ATTACHED TO A TTY. CREATE A FORK AND MAP PART OF SYSJOB
;INTO IT.  START IT AT FRKBGN (BELOW).

	MOVSI 1,(1B1)		;YES, START FORK TO GATHER INPUT
	CFORK			;CREATE FORK WITH SAME CAPABILITIES
	 JERR
	MOVEM 1,LFORK		;SAVE FORK HANDLE
	MOVSI 1,.FHSLF		;MAKE FIRST 100 PAGES COMMON
	HRLZ 2,LFORK
	MOVE 3,[1B0+3B4+100]
	PMAP
	MOVE 1,LFORK		;1/FORK HANDLE OF LOWER FORK
	MOVEI 2,FRKBGN		;2/STARTING ADDRESS FOR LOWER FORK
	SFORK			;START FORK TO READ FIRST LINE

;CHECK FOR INPUT AND OUTPUT FOR ALL PTY'S

ST2:	CALL CHKPTY		;DO INITIAL PTY IO
	JRST WAITI		;GO TO THE MAIN LOOP

;FORK TO GATHER INPUT FROM LOCAL TTY
;NOTE: THE CODE AT ST3 CREATES A FORK AND MAPS THIS ROUTINE INTO IT.
;THIS ROUTINE IS RUN ONLY IN THE LOWER FORK.  IT READS ONE LINE OF
;INPUT FROM THE PRIMARY INPUT DEVICE AND STORES IT IN LCLBF.  WHEN
;DONE, IT SETS A FLAG (LCLIC) AND HALTS. IT IS RESTARTED WHEN THE MAIN
;PROGRAM HAS COPIED THE TEXT FROM THE BUFFER

FRKBGN:	MOVE 1,[100,,101]	;PRIMARY IO
	HRROI 2,LCLBF		;INPUT TO LOCAL BUFFER
	MOVE 3,[RD%BRK+RD%CRF+RD%JFN+NLCLBF*5]
	RDTXT
	 JFCL
	MOVEI 1,.CHLFD
	DPB 1,2			;MAKE SURE AT LEAST ONE EOL IN STRING
	AOS LCLIC
	HALTF			;WILL BE RESTARTED FOR NEXT COMMAND
;SETLOC - ROUTINE TO SET JOB LOCATION TO LOCAL NODE IF UNDER JOB 0
;
; DONE BECAUSE JOB 0 IS CREATED BEFORE THE LOCAL NODE NAME IS KNOWN

SETLOC:	GJINF			;GET OUR JOB NUMBER
	SKIPE C			;RUNNING UNDER JOB 0 ?
	RET			;NO, ALL DONE
	MOVX A,.NDGLN		;GET LOCAL NODE NAME FUNCTION
	MOVEI B,C		;ARGUMENT BLOCK STARTS IN C
	HRROI C,LOCAL		;POINT TO WHERE LOCAL NAME GOES
	NODE			;GET LOCAL NODE NAME
	 ERJMP R		;FAILED, MUST NOT BE A DECNET SYSTEM
	SETOM A			;THIS JOB
	MOVX B,.SJLLO		;SET LOCATION FUNCTION
	HRROI C,LOCAL		;POINTER TO NAME
	SETJB			;SET OUR LOCATION
	 ERJMP [ PMSG (
% SYSJOB: Cannot set job location
)
		RET]		;DONE
	RET			;DONE
;THIS IS THE BEGINNING OF THE MAIN LOOP. IT MAKES REGULAR CHECKS
;FOR I/O NEEDS OF ITS SUBJOBS AND SUBFORKS

WAITI:	MOVE 1,[SIXBIT /SYSJOB/]
	SETNM
	MOVEI 1,^D15
	TLZE F,(FRKTMF)		;IF FORK TERMINATED, DON'T DISMS
	JRST WAIT8
WAITPC:	THIBR			;WAIT UNTIL SIGNAL FROM 'SPEAK'
	 JFCL
WAIT8:	SKIPE LCLIC		;ANY LOCAL INPUT (SET BY LOWER FORK)
	JRST [	MOVE 1,[POINT 7,LCLBF] ;YES, DO IT
		MOVEM 1,AJCMP	;SETUP PTR TO INPUT STRING
		TLO F,(AJCMF)	;SAY COMMAND FROM STRING
		CALL CMND0	;DO THE COMMAND
		TLZ F,(AJCMF)
		SETZM LCLIC
		MOVE 1,LFORK	;RESTART THE FORK FOR MORE INPUT
		MOVEI 2,FRKBGN
		SFORK
		JRST .+1]

;SEE IF ANYONE HAS WRITTEN COMMANDS VIA ^ESPEAK. CHOOSE THE CORRECT FILE BASED
;ON TESTSW.  PROCESS THE COMMANDS, CLOSE THE FILE, AND DELETE IT.
;THE NEXT TIME SOMEONE DOES A ^SPEAK, A NEW FILE WILL BE CREATED.

	MOVSI 1,(1B2+1B17)
	HRROI 2,[ASCIZ /SYSTEM:SYSJOB.COMMANDS/]
	SKIPE TESTSW		;TESTING SYSJOB?
	HRROI 2,[ASCIZ /SYSJOB.TEST1/] ;YES, USE LOCAL FILE
	GTJFN			;MORE COMMANDS?
	 JRST WAIT1		;NO
	MOVEM 1,INJFN
	MOVE 2,[7B5+1B19]
	OPENF
	 JRST WAIT2		;FILE WON'T OPEN
	CALL DOCMND		;GO READ AND PROCESS ALL COMMANDS IN THE FILE
	MOVE 1,INJFN		;1/JFN FOR CURRENT FIE
	HRLI 1,400000
	CLOSF			;CLOSE BUT KEEP JFN
	 JFCL
WAIT2:	HRROI 1,DIRNAM		;1/DESTINATION POINTER
	MOVE 2,INJFN		;2/JFN FOR FILE
	MOVX 3,<FLD(.JSAOF,JS%DIR)>+JS%PAF ;3/OUTPUT DIRECTORY ONLY
	JFNS			;GET DIRECTORY FOR CURRENT FILE
	 ERJMP WAIT1		;UNEXPECTED FAILURE. DON'T DELETE FILES
	MOVE 1,INJFN		;1/JFN FOR CURRENT FILE
	SETZ 2,			;2/VERSIONS TO BE SAVED
	DELNF			;DELETE ALL VERSIONS OF THIS FILE
	 JFCL
	MOVE A,INJFN		;1/ JFN OF FILE
	RLJFN			;RELEASE IT
	 JFCL
	MOVX A,RC%EMO		;1/ USE EXACT MATCH ONLY
	HRROI B,DIRNAM		;2/POINTER TO DIRECTORY NAME
	RCDIR			;CONVERT NAME TO NUMBER
	 ERJMP WAIT1		;CAN'T DO EXPUNGE
	MOVE B,C		;DIRECTORY NUMBER
	SETZ A,			;NOTHING SPECIAL
	DELDF			;EXPUNGE THE DIRECTORY
;SEE IF FORKS THAT WERE STARTED VIA 'RUN' COMMANDS ARE ALIVE.  IF ONE
;HAS DIED, PRINT A MESSAGE

WAIT1:	MOVSI NX,-NJOBS		;CHECK STATE OF ALL JOBS
	SKIPN 1,FORKN(NX)	;JOB EXISTS?
WAIT4:	AOBJN NX,.-1		;NO, GO ON TO NEXT
	JUMPGE NX,WAIT5		;DONE WHEN ALL JOBS CHECKED
	RFSTS
	HLRZ 1,1
	TRZ 1,400000		;FLUSH FREEZE BIT IF ANY
	CAIE 1,2		;HALTED?
	CAIN 1,3
	JRST .+2		;YES
	JRST WAIT4		;NO, OK
	PMSG <** SYSJOB: subjob crashed, data follows: **
>
	CALL PSTAT		;PRINT ITS STATE
	CALL PMORT		;PRINT A POST-MORTEM
	MOVE 1,FORKN(NX)
	KFORK			;FLUSH IT
	SETZM FORKN(NX)
	SETZM NAME(NX)
	JRST WAIT4

;EXAMINE ALL ADVANCE SCHEDULED JOBS TO SEE IF NOW TIME TO RUN

WAIT5:	GTAD			;GET TIME NOW
	MOVSI 5,-NAJOBS
	SKIPN TIMES(5)		;JOB QUEUED HERE?
WAIT6:	AOBJN 5,.-1		;NO
	JUMPGE 5,WAIT7		;DONE WHEN ALL ENTRIES EXAMINED
	CAMGE 1,TIMES(5)	;IS NOW .GE. DESIRED TIME?
	JRST WAIT6		;NO, LEAVE JOB IN QUEUE
	SETZM TIMES(5)		;YES, REMOVE JOB FROM QUEUE
	MOVEI 5,0(5)		;COMPUTE POINTER TO STORED COMMAND
	IMULI 5,NAJCW
	ADD 5,[XWD 440700,AJCMD]
	MOVEM 5,AJCMP		;LEAVE POINTER FOR GCIN
	TLO F,(AJCMF)		;NOTE COMMAND FROM STORED STRING
	CALL CMND0		;DO COMMAND
	TLZ F,(AJCMF)
	JRST WAIT5

;SEE IF PTY'S HAVE INPUT OR OUTPUT WAITING

WAIT7:	CALL CHKPTY		;CHECK FOR PTY SERVICE
	JRST WAITI		;MAIN LOOP
;DO COMMANDS FROM OPEN FILE

DOCMND:	MOVE 1,INJFN
	GTSTS
	TXNE 2,GS%NAM		;IS THERE A NAME FOR THIS JFN?
	TXNE 2,GS%EOF!GS%ERR	;YES. CAN READ MORE?
	RET			;NO NAME OR EOF

;HERE WHEN INPUT FROM LOCAL TTY OR FILE IS WAITING.  COPY ALL CHARACTERS TO CMDBUF

CMND0:	MOVE 7,CMDPT0		;POINT TO START OF CMDBUF INITIALLY
	MOVEM P,CMNDP		;SAVE STACK FOR COMMAND ABORTS
CMND4:	CALL GCIN		;READ ONE CHARACTER AND ECHO IT
	CAIE 1,.CHLFD		;CHECK FOR COMMAND WORD TERMINATOR
	CAIN 1," "
	JRST CMND1		;LINE FEED OR SPACE. 
	IDPB 1,7		;COPY CHARACTER INTO CMDBUF
	JRST CMND4		;GO GET NEXT CHARACTER

;LINE FEED OR SPACE FOUND.

CMND1:	MOVEM 1,TERMCH		;SAVE TERMINATOR
	CAMN 7,CMDPT0		;NULL COMMAND?
	JRST [	CAIE 1,.CHLFD	;YES, BLANK LINE?
		JRST CMND4	;NO, TRY AGAIN
		JRST CMDEND]	;YES
	SETZ 1,
	IDPB 1,7		;PUT NULL ON STRING

;SEARCH FOR COMMAND IN TABLE AND DISPATCH TO ROUTINE TO PROCESS IT

	MOVSI 5,-LCMTB		;SET TO SEARCH COMMAND TABLE
CMND2:	MOVE 1,CMDPT0
	HRRZ 2,CMNDTB(5)	;POINTER TO KNOWN COMMAND NAME
	HRLI 2,440700
	CALL STCOMP		;SKIP IF STRINGS NEQ
	JRST [	HLRZ 1,CMNDTB(5) ;FOUND, DISPATCH TO IT
		JRST 0(1)]
	AOBJN 5,CMND2

;NOT FOUND.  PRINT COMMAND AND ERROR MESSAGE

	MOVE 1,TERMCH		;NOT FOUND, SCAN TO END OF LINE
CMND3:	CAIN 1,.CHLFD
	JRST [	PMSG < - unrecognized command.
>
		JRST CMDEND]
	CALL GCIN
	JRST CMND3

;HERE TO IGNORE REST OF LINE

CMDFLS:	SKIPA 1,TERMCH		;FLUSH REMAINDER OF LINE
	CALL GCIN
	CAIE 1,.CHLFD		;GOT TO EOL?
	JRST .-2		;NO, KEEP LOOKING

;HERE WHEN ENTIRE LINE PROCESSED

CMDEND:	MOVE P,CMNDP		;RESTORE STACK
	TLZE F,(AJCMF)		;WERE DOING STORED COMMAND?
	RET			;YES, RETURN NOW
	JRST DOCMND		;NO. GO GET NEXT ONE
;RUN COMMAND - 'RUN filespec'
;CREATES A FORK AND RUNS THE FILE 'FILESPEC' IN IT

.RUN:	MOVE 1,TERMCH
	CAIE 1," "		;PROPER TERMINATOR?
	JRST CMDFLS		;NO

;COPY FILESPEC INTO CMDBUF

	MOVE 7,CMDPT0		;GATHER FILE NAME
RUN1:	CALL GCIN		;READ AND ECHO A CHARACTER
	CAIN 1,.CHLFD		;TERMINATES WITH EOL
	JRST RUN2
	IDPB 1,7		;COPY CHARACTER INTO CMDBUF
	JRST RUN1		;GO GET NEXT CHARACTER

;LINE FEED FOUND. HAVE NAME OF FILE.  GET A JFN ON THE FILE.

RUN2:	SETZ 1,
	IDPB 1,7		;ADD NULL TO STRING
	CALL IJFNT		;INIT THE JFN TABLE
	MOVSI 1,(1B2)
	MOVEM 1,JFNTAB
	MOVEI 1,JFNTAB
	MOVE 2,CMDPT0		;FILENAME STRING
	GTJFN
	 JRST [	JERR
		JRST CMDEND]	;NOT FOUND, ETC.
	PUSH P,1		;SAVE THE JFN

;STORE THE FILENAME PORTION OF THE FILESPEC IN NAMBUF

	HRROI 1,NAMBUF
	HRRZ 2,0(P)
	MOVSI 3,(1B8)
	JFNS			;GET STRING CONTAINING NAME FIELD ONLY

;CREATE AN INFERIOR FORK AND GET THE FILE INTO IT.

	MOVSI 1,(1B1)		;GIVE NEW FORK THIS FORK'S CAPABILITIES
	CFORK			;CREATE THE FORK
	 JRST [	JERR
		JRST CMDEND]
	EXCH 1,0(P)		;1/JFN, STACK/FORK HANDLE
	HRL 1,0(P)		;XWD FORK,JFN
	GET			;GET THE FILE INTO THE NEW FORK

;STORE INFORMATION ABOUT THIS FORK IN NEXT SLOT IN TABLES

	MOVSI NX,-NJOBS		;FORK READY TO GO, MAKE TABLE ENTRY
	SKIPE FORKN(NX)		;AVAILABLE SLOT?
	AOBJN NX,.-1		;NO
	JUMPGE NX,[PMSG <Tables full.
>
		POP P,1		;1/FORK HANDLE
		KFORK		;KILL THE FORK
				JRST CMDEND]
	POP P,FORKN(NX)		;PUT FORK  HANDLE IN TABLES
	SETZM NAME(NX)		;SETUP TO PUT SIXBIT NAME IN TABLES

;CONVERT FIRST 6 CHARACTERS OF FILENAME TO SIXBIT AND STORE IN NAME TABLE

	MOVEI 4,NAME(NX)
	HRLI 4,440600
	MOVE 3,[POINT 7,NAMBUF,-1]
	MOVEI 2,6		;MAX 6 CHARS
RUN4:	ILDB 1,3
	JUMPE 1,RUN3		;END OF STRING
	SUBI 1,40		;CONVERT TO SIXBIT
	IDPB 1,4
	SOJG 2,RUN4

;START THE PROGRAM IN THE NEW FORK

RUN3:	MOVE 1,FORKN(NX)	;NOW START THE JOB
	SETZ 2,			;AT MAIN START LOC
	SFRKV
	JRST CMDEND
; PURGE COMMAND - 'PURGE fork-number'
;
; KILLS THE FORK WITH THE INDICATED NUMBER (NUMBERS DISPLAYED ON STATUS COMMAND)

.PURGE:	CALL GETNUM		;GET FORK NUMBER
	JRST KTASK		;KILL THE FORK


;KILL COMMAND - 'KILL name'
;KILLS THE FORK THAT IS RUNNING THE PROGRAM 'NAME'

.KILL:	CALL GETNAM		;GET NAME FROM COMMAND STRING AND FIND FORK
				; THAT IS RUNNING IT
	JRST KTASK		;GO KILL THE FORK

;KTASK - ROUTINE TO KILL A SYSJOB FORK
;
;ACCEPTS IN NX/ FORK TABLE INDEX
;
; KILL AND PURGE COMMANDS BRANCH HERE

KTASK:	MOVE 1,FORKN(NX)
	KFORK			;KILL THE FORK
	SETZM FORKN(NX)		;RELEASE SLOT
	SETZM NAME(NX)
	JRST CMDEND

;STOP COMMAND - 'STOP name'
;FREEZES THE FORK THAT IS RUNNING THE PROGRAM 'NAME'

.STOP:	CALL GETNAM
	MOVE 1,FORKN(NX)
	FFORK
	JRST CMDEND

;START COMMAND - 'START name'
;STARTS THE FORK THAT IS RUNNING THE PROGRAM 'NAME' (UNDOES STOP)

.START:	CALL GETNAM
	MOVE 1,FORKN(NX)
	RFORK
	JRST CMDEND

;STATUS COMMAND - 'STATUS'

.STAT:	PMSG <SYSJOB status at >
	MOVEI A,.PRIOU
	SETO B,
	MOVSI C,240
	ODTIM			;DO TIMESTAMP
	PMSG <
>

;SEARCH TABLE OF FORKS STARTED VIA RUN COMMANDS

	MOVSI NX,-NJOBS		;SCAN ALL JOBS, PRINTING FORK STATUS
	SKIPN FORKN(NX)		;SLOT IN USE?
STAT1:	AOBJN NX,.-1		;NO
	JUMPGE NX,STAT2
	CALL PSTAT		;PRINT THE STATUS
	JRST STAT1

;SEARCH TABLE OF JOBS STARTED VIA JOB COMMANDS

STAT2:	MOVSI NX,-NLINES	;SETUP TO CHECK ALL PTY LINES
STAT3:	SKIPE JOBPTY(NX)	;EXISTS?
	CALL PJSTAT		;YES, PRINT STATUS
	AOBJN NX,STAT3
	JRST CMDFLS
;PRINT STATUS FOR ONE PTY JOB
;   ##: JOB ##, TTY ##, PROGRAM

PJSTAT:	MOVEI 1,101
	HRRZ 2,NX		;PRINT SYSJOB NUMBER
	MOVE 3,[1B2+3B17+^D10]	;USING 3 COLUMNS
	NOUT
	 JERR
	MOVE 1,TTYJOB		;GET MONITOR JOB NUMBER FROM TTY
	HLL 1,JOBPTY(NX)
	TLZ 1,400000
	GETAB
	 JERR
	HLRZ 2,1
	TRNE 2,1B18		;JOB NUMBER EXISTS?
	JRST [	PMSG <: No job
>
		RET]		;NO FURTHER INFO
	PMSG <: Job >
	PUSH P,2		;SAVE JOB NUMBER
	MOVEI 1,101
	MOVEI 3,^D10		;PRINT JOB NUMBER IN DECIMAL
	NOUT
	 JERR
	PMSG <, TTY>
	MOVEI 1,101
	HLRZ 2,JOBPTY(NX)	;GET TTY NUMBER
	TRZ 2,400000
	MOVEI 3,^D8
	NOUT
	 JERR
	PMSG <, >
	POP P,2			;RECOVER JOB NUMBER
	MOVE 1,JOBNAM		;GET NAME INDEX FOR JOB
	HRL 1,2
	GETAB
	 JERR
	HRLZ 1,1
	HRR 1,SNAMES		;GET SIXBIT NAME OF JOB
	GETAB
	 JERR
	MOVEM 1,2
	MOVEI 4,6		;SET TO PRINT 6 CHARS
PJS1:	SETZ 1,
	LSHC 1,6		;SHIFT IN A CHAR
	ADDI 1,40		;CONVERT TO ASCII
	PBOUT
PJS2:	SOJG 4,PJS1
	PMSG <
>
	RET
;PRINT STATUS FOR 1 FORK

PSTAT:	MOVEI 2,0(NX)
	MOVEI 1,101
	MOVE 3,[1B2+3B17+10]
	NOUT			;PRINT LOCAL INDEX IN 3 CHAR FIELD
	 JFCL
	MOVEI 2," "
	BOUT
	MOVEI 4,NAME(NX)
	HRLI 4,440600
	MOVEI 3,6		;PRINT THE NAME, I.E. FIRST 6 CHARS
	ILDB 2,4		;OF FILE NAME
	ADDI 2,40
	BOUT
	SOJG 3,.-3
	MOVEI 2," "
	BOUT
	MOVE 1,FORKN(NX)
	RFSTS			;GET FORK STATUS
	PUSH P,2		;SAVE PC
	HLRZ 1,1
	TRZE 1,400000		;FROZEN?
	JRST [	PUSH P,1	;YES
		PMSG <stopped, >
		POP P,1
		JRST .+1]
	HRRO 1,FSTAB(1)		;MESSAGE FOR STATE OF FORK
	PSOUT
	PMSG < at >
	POP P,2			;PC
	MOVEI 2,0(2)
	MOVEI 1,101
	MOVEI 3,10
	NOUT
	 JFCL
	PMSG <  >
	MOVEI 1,101		;TIMESTAMP THE STATUS
	SETO 2,
	MOVSI 3,240
	ODTIM
	PMSG <
>
	RET
;POST MORTEM FOR DEAD FORK

PMORT:	PMSG <  JSYS error: >
	MOVEI 1,101
	HRLO 2,FORKN(NX)
	MOVEI 3,0
	ERSTR			;DO MSG FOR MOST RECENT ERROR TO TTY
	 JFCL
	 JRST [	MOVE 1,FORKN(NX) ;FAILED TO FIND MSG, PRINT NUMBER
		PUSH P,NX	;TEMP - UNTIL GETER FIXED
		GETER		;GET ERROR CODE FOR FORK
		POP P,NX	;TEMP - UNTIL GETER FIXED
		MOVEI 1,101
		HRRZ 2,2	;PRINT ONLY ERROR CODE
		MOVEI 3,10	;IN OCTAL
		NOUT
		 JFCL
		JRST .+1]
	MOVE 1,FORKN(NX)	;GET ACS FROM FORK
	MOVEI 2,FRKACS
	RFACS
	PMSG <
  Fork acs:>
	MOVSI Q1,-4		;TYPE ACS 1-4
CRASHL:	PMSG <  >
	MOVE B,FRKACS+1(Q1)
	MOVEI A,101
	MOVEI C,10
	NOUT			;PRINT AC IN OCTAL
	 JFCL
	AOBJN Q1,CRASHL
	PMSG <
>
	SKIPN DBUGSW		;DEBUG MODE?
	JRST NOFSTA		;NO, DON'T DO FILSTAT
	PMSG <  Fork 0 FILSTAT:
>
	MOVEI Q1,77		;SETUP TO SCAN ALL JFNS
FSTATL:	HRRZ A,Q1
	GTSTS			;GET STATUS OF JFN
	TLNN B,(1B10)		;FILE HERE?
	JRST FSTATN		;NO
	PUSH P,B		;SAVE BITS
	HRRZ B,Q1
	MOVEI A,101
	MOVE C,[3,,10]		;TYPE JFN NUMBER IN 3 PLACES
	NOUT
	 JFCL
	MOVEI B," "
	BOUT
	HRRZ B,Q1
	MOVEI C,0
	JFNS			;TYPE FILENAME
	 ERJMP [MOVEI B,"?"	;FAILED (CAN'T IMAGINE WHY)
		BOUT
		JRST .+1]
	MOVEI B," "
	BOUT
	POP P,D			;RECOVER BITS

DEFINE BITMSG(N,XMSG)<
	HRROI A,[ASCIZ \XMSG\]
	TLNE D,(1B'N)
	PSOUT>

	JUMPL D,FSTAT1
	PMSG <Not open >
FSTAT1:	BITMSG (1,<READ>)
	BITMSG (2,<WRITE >)
	BITMSG (3,<XCT >)
	BITMSG (9,<ERROR >)
	PMSG <
>
FSTATN:	SOJGE Q1,FSTATL
NOFSTA:	RET
;ATTIME DATE TIME; COMMAND
;SEMICOLON DELIMITS TIME

.ATTM:	MOVE 1,TERMCH
	CAIE 1," "		;PROPER TERMINATOR?
	JRST CMDFLS		;NO
	MOVE 7,CMDPT0		;SET TO READ DATIME STRING
ATTM1:	CALL GCIN
	CAIN 1,.CHLFD
	JRST CMDEND		;EOL, SOMEBODY GOOFED
	CAIN 1,";"
	JRST ATTM2		;END OF DATIME STRING
	IDPB 1,7
	JRST ATTM1

ATTM2:	SETZ 1,
	IDPB 1,7		;STRING TERMINATOR
	MOVE 1,CMDPT0
	SETZ 2,
	IDTIM			;CONVERT STRING TO INTERNAL FORMAT
	 JRST [	JERR	;DIDN'T WORK
		JRST CMDFLS]
	MOVSI 5,-NAJOBS		;FIND A FREE QUEUE SLOT
	SKIPE TIMES(5)
	AOBJN 5,.-1
	JUMPGE 5,[PMSG <
No queue slots left.
>
		JRST CMDFLS]
	MOVEM 2,TIMES(5)
	MOVEI 4,0(5)		;COMPUTE STRING PTR FOR COMMAND
	IMULI 4,NAJCW
	ADD 4,[XWD 440700,AJCMD]
	MOVEI 3,NAJCW*5		;MAX NUMBER CHARS IN STORED COMMAND
	CALL GCIN
	IDPB 1,4
	CAIE 1,.CHLFD		;STORE TO EOL
	SOJG 3,.-3		;OR UNTIL STRING FULL
	JUMPLE 3,[PMSG <
Command too long to be stored.
>
		SETZM TIMES(5)	;REMOVE FROM QUEUE
		JRST CMDFLS]
	JRST CMDEND
;JOB COMMAND - 'JOB n /text/'
;TRANSMIT TEXT TO JOB IDENTIFIED BY N. FIRST OCCURRENCE CREATES A NEW 
;JOB ON A PTY. DELIMITIERS CAN BE ANYTHING NOT IN TEXT
;THIS ROUTINE COPIES THE TEXT TO A BUFFER TO BE TRANSMITTED LATER BY
;CHKPIN

;THE CLEARING OF THE TTY INPUT BUFFER WAS ADDED AS A QUICK FIX FOR A
;BUG. IF THE USER TYPED A 'JOB' COMMAND AND FAILED TO TERMINATE IT
;WITH THE EXPECTED DELIMITER, THE COMMAND WAS WRITTEN OVER THE
;LAST 'JOB' COMMAND FOR THE SAME JOB. THUS THE REMAINDER OF THE
;PREVIOUS COMMAND WAS APPENDED TO THE NEW COMMAND.
;THIS BLT CLEARS THE BUFFER. IDEALLY WE WOULD CORRECTLY
;HANDLE THE OCCURRENCE OF AN END OF FILE WITHOUT FINDING THE DESIRED
;DELIMITER. PRESENTLY GCIN ASSUMES THE COMMAND HAS BEEN TERMINATED CORRECTLY
;WHEN END OF FILE IS DETECTED.

.JOB:	CALL GJOBN		;GET JOB NUMBER
	 JRST CMDFLS		;FAILED
	SKIPN JOBPTY(NX)	;HAVE A PTY HERE?
	JRST [	CALL GETPTY	;NO, GET ONE
		 JRST CMDFLS	;NONE AVAILABLE
		JRST .+1]
	MOVE 1,TERMCH		;FIRST NON-DIGIT READ BY GJOBN (END OF NUMBER)
JOB4:	CAIE 1," "		;VALID DELIMITER (NON-BLANK)?
	JRST JOB3		;YES. 
	CALL GCIN		;NO. GET NEXT CHARACTER
	JRST JOB4		;GO CHECK IT FOR DELIMITER
JOB3:	MOVEM 1,TERMCH		;SAVE THE TERMINATOR
	SKIPN JOBISP(NX)	;HAVE EXISTING INPUT?
	JRST [	MOVEI 1,0(NX)	;NO. 1/JOB NUMBER IN COMMAND
		CALL SETSP	;1/BYTE PTR TO START OF BUFFER FOR THIS JOB
		MOVEM 1,2	; SAVE PTR AND SET UP FOR TERMINATING BLT
		SETZM 0(1)	;CLEAR FIRST WORD OF BUFFER
		HRLS 1		;BLT FROM FIRST WORD IN BUFFER
		AOS 1		; TO NEXT UNTIL END OF BUFFER
		BLT 1,NWSBUF-1(2) ;CLEAR THE ENTIRE BUFFER
		MOVEM 2,JOBISP(NX) ;START OF PTY INPUT
		MOVEM 2,JOBISE(NX) ;END OF PTY INPUT
		JRST .+1]
	MOVEI P2,NWSBUF*5	;SETUP TO COUNT CHARS IN STRING
JOB1:	CALL GCIN		;GET CHARACTER FROM INPUT
	CAME 1,TERMCH		;THE TERMINATOR?
	JUMPN 1,[IDPB 1,JOBISE(NX) ;NO, APPEND IT TO STRING
		SOJG P2,JOB1	;LOOP UNLESS OUT OF STRING SPACE
		JRST JOB2]	;FILLED UP STRING SPACE
	SETZ 1,			;END OF STRING, APPEND NULL
	MOVE 2,JOBISE(NX)
	IDPB 1,2
	JRST CMDFLS		;FLUSH UP TO NEXT EOL

JOB2:	CALL GCIN		;FLUSH REST OF INPUT
	CAME 1,TERMCH
	JRST JOB2
	PMSG <
Too much input for line.
>
	JRST CMDFLS
;CCJOB COMMAND - 'CCJOB n'
;FORCES DOUBLE CONTROL-C TO JOB

.CCJOB:	CALL GJOBN		;GET JOB NUMBER
	 JRST CMDFLS		;NO GOOD
	SKIPN JOBPTY(NX)	;HAVE PTY HERE?
	JRST CMDEND		;NO
	HRRZ 1,JOBPTY(NX)
	MOVEI 2,"C"-100		;SEND CONTROL-C
	BOUT
	BOUT			;SEND TWO
	JRST CMDEND

;KILLJOB COMMAND - 'KILLJOB n'
;CLOSES PTY AND RELEASES BUFFERS IF ANY

.KJOB:	CALL GJOBN		;GET JOB NUMBER
	 JRST CMDFLS		;LOSER
	SKIPN JOBPTY(NX)	;PTY HERE?
	JRST CMDEND		;NO, NOTHING TO DO
	HRRZ 1,JOBPTY(NX)
	CLOSF			;CLOSE THE PTY - WILL DETACH JOB IF ANY
	 JERR			; STILL THERE
	SETZM JOBPTY(NX)	;NOTE NO PTY HERE NOW
	SETZM JOBISP(NX)	;NOTE GONE
	SETZM JOBOSP(NX)	;NOTE GONE
	JRST CMDEND
;SUBROUTINES FOR PTY LOGIC
;FIND A FREE PTY AND OPEN IT

GETPTY:	PUSH P,P1
	PUSH P,P2
	PUSH P,P3
	MOVEI P1,0		;START WITH PTY0
GETPT1:	HRROI 1,P2		;CONSTRUCT A PTY IDENT STRING IN P2
	HRROI 2,[ASCIZ /PTY/]	;START WITH NAME
	SETZ 3,
	SOUT
	MOVE 2,P1
	MOVEI 3,10
	NOUT			;NUMBER (OCTAL) IS NEXT
	 JERR
	HRROI 2,[ASCIZ /:/]	;THEN A COLON
	SETZ 3,
	SOUT
	MOVSI 1,(1B2+1B17)
	HRROI 2,P2		;POINT GTJFN AT STRING JUST MADE
	GTJFN			;TRY TO GET THIS PTY
	 JRST GETPT3		;FAILED, PROBABLY ALREADY ASSIGNED
	MOVEM 1,JOBPTY(NX)	;SO FAR SO GOOD, SAVE JFN
	MOVE 2,[07B5+3B20]	;OPEN PTY FOR IN AND OUT
	OPENF
	 JRST [	HRRZ 1,JOBPTY(NX) ;FAILED, CAN'T USE THIS ONE
		RLJFN
		 JFCL
		JRST GETPT3]	;GO TRY NEXT ONE
	ADD P1,FIRPTY		;PTY OK, COMPUTE RELATED TTY NUMBER
	TRO P1,400000		;CONSTRUCT TTY DESIGNATOR
	HRLM P1,JOBPTY(NX)	;SAVE IT FOR VARIOUS JSYSES
	HLRZ 1,JOBPTY(NX)	;GET DESIGNATOR
	MOVEI 2,.TTL36		;SET TERMINAL TYPE TO LA36 SINCE
				;OUTPUT GOES TO CTY
	STTYP
	HRRZ 1,JOBPTY(NX)	;ASSIGN INTERRUPT CHANNELS
	MOVE 2,[1B0+1B1+<PTCHN>B17+.TTDPI]
	MTOPR
	HRRZ 1,JOBPTY(NX)
	MOVEI 2,"C"-100		;SEND A ^C TO STARTUP JOB
	BOUT
	 ERJMP .+1		;IGNORE FAILURE, PRESENCE OF JOB CHECKED LATER
GETPT4:	POP P,P3
	POP P,P2
	POP P,P1
	JUMPE 1,R		;RETURN BAD
	RETSKP

GETPT3:	CAIL P1,777		;CHECK ALL POSSIBLE PTYS?
	JRST [	PMSG <
No PTYs available.
>
		SETZ 1,		;SIGNAL RETURN BAD
		JRST GETPT4]
	AOJA P1,GETPT1		;GO CHECK NEXT PTY
;GET JOB NUMBER FROM COMMAND

GJOBN:	MOVE 2,[POINT 7,3]	;COLLECT STRING BEFORE GIVING TO NIN
GJOBN2:	CALL GCIN
	CAIL 1,"0"		;IS A NUMBER?
	CAILE 1,"9"
	JRST GJOBN1		;NO
	IDPB 1,2		;YES, APPEND TO STRING
	TLNE 2,(7B2)		;TOO MANY DIGITS?
	JRST GJOBN2		;NO, KEEP GOING
	PMSG <
Too many digits in job number.
>
	RET

;FOUND NON-DIGIT

GJOBN1:	MOVEM 1,TERMCH
	SETZ 1,
	IDPB 1,2		;APPEND NULL
	HRROI 1,1(P)		;SETUP PTR TO STACK
	PUSH P,3
	MOVEI 3,^D10
	NIN			;READ JOB NUMBER IN DECIMAL
	 JERR
	POP P,3			;CLEAR STACK
	CAIL 2,0		;REASONABLE?
	CAILE 2,NLINES
	JRST [	PMSG <
Illegal job number.
>
		RET]
	MOVEM 2,NX		;RETURN IN USUAL INDEX
	RETSKP

;ROUTINE TO CHECK EVERY PTY FOR INPUT OR OUTPUT NEEDED

CHKPTY:	MOVSI NX,-NLINES	;SETUP TO CHECK ALL LINES
CHKPT1:	SKIPE JOBPTY(NX)	;PTY HERE?
	JRST [	CALL CHKPIN	;YES, CHECK INPUT
		CALL CHKPOU	;CHECK OUTPUT
		JRST .+1]
	AOBJN NX,CHKPT1
	RET
;CHKPIN - CHECK PTY FOR INPUT NEEDED

;ACCEPTS:
;	NX/ JOB NUMBER (WITHIN SYSJOB, AS IN THE 'JOB' COMMAND)

;	CALL CHKPIN

;RETURNS +1: ALWAYS

;THIS ROUTINE IS CALLED PERIODICALLY FOR EACH JOB THAT SYSJOB HAS 
;CREATED ON A PTY. WHEN SYSJOB READS A 'JOB' COMMAND, IT STORES THE
;TEXT IN A BUFFER POINTED TO BY JOBISP(NX) (SEE .JOB). THIS ROUTINE WRITES
;THAT TEXT TO THE PTY IF THE CREATED JOB IS IN INPUT WAIT ON THE PTY

CHKPIN:	CALL CHKPOU		;ALWAYS EMPTY THE OUTPUT BUFFER FIRST
	SKIPN A,JOBISP(NX)	;INPUT WAITING?
	RET			;NO
	ILDB A,A		;MAYBE, GET FIRST CHAR
	JUMPE A,[SETZM JOBISP(NX) ;NULL, CLEAR POINTER
		RET]		;AND RETURN
	HLRZ 1,JOBPTY(NX)
	MOVEI 2,.TTTIH		;SETUP FUNCTION CODE
	MTOPR			;GET INPUT HUNGRY STATUS
	 ERJMP R		;IF FAILS, ASSUME NOT HUNGRY
	JUMPE 2,R		;JUMP IF NOT HUNGRY
	CALL PTYINI		;SEE IF HAVE TO CREATE A JOB ON PTY
	 RET			;CAN'T MAKE A JOB, WAIT TILL LATER
	HRRZ 1,JOBPTY(NX)	;PTY IS HUNGRY, GIVE IT A LINE
CHKPI1:	ILDB 2,JOBISP(NX)	;GET NEXT CHARACTER OF INPUT
	JUMPE 2,[SETZM JOBISP(NX) ;NOTE NO INPUT STRING
		RET]
	CAIN 2,ESCC		;OUR ESCAPE CHARACTER?
	JRST DOESC		;YES
	CAIN 2,.CHLFD		;EOL?
	MOVEI 2,.CHCRT		;YES, CONVERT TO .CHCRT
CHKPI2:	BOUT			;SEND THE CHAR
	 ERJMP [JERR		;REPORT FAILURE (PROBABLY INPUT BUFFER FULL)
		JRST .+1]
	CAIE 2,.CHCRT		;WAS END OF LINE?
	JRST CHKPI1		;NO, KEEP SENDING
	JRST CHKPIN		;YES, SEE IF STILL HUNGRY

DOESC:	ILDB 2,JOBISP(NX)	;GET CHAR AFTER THE ESCAPE
	CAIN 2,ESCC		;ANOTHER ESCAPE?
	JRST CHKPI2		;YES, MEANS SINGLE ESCAPE
	CAIN 2,"$"		;A $ ?
	JRST [	MOVEI 2,ESC	;YES MEANS ESC (ALTMODE)
		JRST CHKPI2]
	CAIL 2,100		;DOES CHAR HAVE CONTROL EQUIV?
	CAIL 2,140
	JRST CHKPI1		;NO, SEND DIRECTLY
	SUBI 2,100		;YES, CONVERT TO CONTROL
	BOUT			;SEND IT
	 ERJMP [JERR		;REPORT FAILURE
		JRST .+1]
	JRST CHKPIN		;SEE IF STILL HUNGRY
;ROUTINE TO CREATE A JOB ON A PTY IF NECESSARY.  SKIP RETURN IF
;A JOB IS NOW ON THE PTY, NON-SKIP RETURN IF WE FAILED TO CREATE
;ANY JOB.


PTYINI:	CALL PTYJBC		;SEE IF A JOB IS ALREADY ON THE PTY
	 JRST RSKP		;YES, GOOD RETURN
	SKIPN C,PDELAY		;GET DELAY TIME
	JRST PTYING		;PROCEED IF NO DELAY
	TIME			;GET CURRENT TIME
	CAMGE A,C		;TIME FOR ANOTHER ATTEMPT?
	RET			;NO
	SETZM PDELAY		;YES, CLEAR DELAY

PTYING:	HRRZ A,JOBPTY(NX)	;GET JFN
	MOVEI B,3		;AND A CONTROL-C
	BOUT			;SEND TO PTY TO CREATE A JOB
	 ERJMP .+1		;IGNORE FAILURE, CHECKED BELOW
	CALL PTYJBC		;SEE IF JOB WAS CREATED
	 JRST RSKP		;YES, RETURN OK
	TIME			;GET CURRENT TIME
	ADDI A,^D30000		;ADD 30 SECONDS TO IT
	MOVEM A,PDELAY		;SAVE AS NEXT ALLOWABLE TIME
	RET			;RETURN BAD FOR NOW




;ROUTINE TO SEE IF A JOB EXISTS ON A PTY.  IF THE JOB IS IN THE
;PROCESS OF BEING INITIALIZED, WE WAIT FOR IT TO COMPLETE.
;SKIP RETURN IF NO JOB IS ON THE PTY, NON-SKIP IF A JOB IS THERE.


PTYJBC:	HLL A,JOBPTY(NX)	;GET TTY DESIGNATOR
	TLZ A,400000		;TURN IT INTO A TTY NUMBER
	HRR A,TTYJOB		;GET TABLE NUMBER FOR TTYJOB
	GETAB			;SEE IF LOGGED IN
	 JRST RSKP		;FAILED, ASSUME NO JOB
	JUMPGE A,R		;IF JOB NUMBER SET UP, THEN OK
	HLRZ A,A		;GET LEFT HALF
	CAIE A,-2		;UNASSIGNED?
	JRST RSKP		;YES
	MOVEI A,^D250		;NO, BEING ASSIGNED
	DISMS			;GIVE IT A CHANCE TO FINISH
	JRST PTYJBC		;AND CHECK AGAIN
;CHECK FOR OUTPUT AVAILABLE ON LINE

CHKPOU:	HLRZ 1,JOBPTY(NX)	;GET TTY DESIG
	SOBE			;ANYTHING IN OUTPUT BUFFER?
	 SKIPA			;YES, GET IT
	RET
	HRRZ 1,JOBPTY(NX)	;1/JFN OF PTY
	BIN			;GET ONE OUTPUT CHARACTER
	JUMPE 2,CHKPOU		;IGNORE NULL
	SKIPN JOBOSP(NX)	;HAVE A BUFFER FOR OUTPUT?
	JRST [	MOVEI 1,NLINES(NX) ;NO, SETUP OUTPUT BFR
		CALL SETSP
		MOVEM 1,JOBOSP(NX) ;SETUP POINTER
		JRST .+1]
	IDPB 2,JOBOSP(NX)	;PUT IN OUTPUT STRING
	CAIE 2,.CHLFD		;END OF LINE?
	JRST CHKPOU		;NO, TRY TO GET MORE
	SETZ 2,			;YES, TERMINATE STRING
	IDPB 2,JOBOSP(NX)
CHKPO2:	MOVEI 1,101
	RFPOS			;SEE WHERE CHARRIAGE IS NOW
	HRRZ 2,2
	JUMPE 2,CHKPO1		;DO CRLF IF NOT AT LEFT MARGIN
	PMSG <
>
CHKPO1:	PMSG <SJ >		;BEGIN THE HEADER
	MOVEI 1,101
	HRRZ 2,NX
	MOVE 3,[1B2+2B17+^D10]
	NOUT			;PRINT JOB NUMBER NEXT
	 JERR
	PMSG <: >
	MOVEI 1,NLINES(NX)
	CALL SETSP		;REINIT POINTER
	MOVE 2,1
	MOVEI 1,101
	SETZ 3,
	SOUT			;OUTPUT THE JOB'S LINE
	SETZM JOBOSP(NX)
	JRST CHKPOU
;NORMALIZE PTR TO BEGINNING OF BUFFER

NORMSP:	HRRZ 1,1		;REDUCE ADDRESS TO BUFFER NUMBER
	SUBI 1,SBUF
	IDIVI 1,NWSBUF
SETSP:	IMULI 1,NWSBUF		;CONVERT TO STRING PTR FOR RELATED
	ADDI 1,SBUF		; BUFFER
	HRLI 1,(<POINT 7,0>)
	RET
;GET CHAR FROM INPUT FILE, COPY TO PRIMARY OUTPUT FOR INFO
;IF F HAS AJCMF BIT SET, INPUT COMES FROM A BUFFER RATHER THAN A FILE
;AND AJCMP HAS POINTER TO BUFFER

GCIN:	TLNE F,(AJCMF)		;FROM STORED COMMAND?
	JRST [	ILDB 1,AJCMP	;YES
		PBOUT		;REPORT IT
		RET]

;INPUT IS VIA JFN

	PUSH P,2
	MOVE 1,INJFN		;1/JFN FOR INPUT
GCIN0:	BIN			;READ A CHARACTER
	ERJMP CMDEND		;IF ANY SORT OF ERROR, DONE
	CAIN 2,.CHCRT
	JRST GCIN0		;YES. SKIP IT
	JUMPE 2,CMDEND		;NULL - ASSUME EOF
	CAIN 1,100		;INPUT FROM PRIMARY?
	JRST GCIN1		;YES, ECHO ALREADY DONE
	MOVEI 1,101
	BOUT
GCIN1:	CAIL 2,"A"+40		;IF LOWERCASE A-Z CONVERT TO UPPER CASE
	CAILE 2,"Z"+40
	JRST GCIN2		;NOT LOWER CASE
	SUBI 2,40		;CONVERT TO LOWER CASE
GCIN2:	MOVE 1,2		;RETURN CHARACTER IN 1
	POP P,2
	RET

;INITIALIZE JFN TABLE

IJFNT:	MOVE 1,[XWD IJFNTT,JFNTAB]
	BLT 1,JFNTAB+7
	RET

IJFNTT:	0
	XWD 377777,377777	;NO FILE I/O
	-1,,[ASCIZ /SYS/]	;DEFAULT TO SYS
	0
	0
	XWD -1,[ASCIZ /EXE/]	;DEFAULT TO .EXE
	0
	0
;COMPARE STRINGS IN 1,2
;SKIP IF NOT EQUAL

STCOMP:	PUSH P,1
	PUSH P,2
STC1:	ILDB 1,-1(P)
	ILDB 2,0(P)
	CAIN 1,0(2)
	JUMPN 1,STC1		;EQUAL SO FAR, END OF STRINGS?
	CAIE 1,0(2)		;END OR NOT EQUAL, WHICH?
	AOS -2(P)		;NOT EQUAL, SKIP RETURN
	POP P,2
	POP P,1
	RET

;A COMMAND OF THE FORM 'KEYWORD name' HAS BEEN FOUND.  GET THE NAME
;FROM THE COMMAND AND FIND THE FORK THAT IS RUNNING THAT PROGRAM
;RETURNS INDEX INTO FORK TABLES IN FX

GETNAM:	MOVE 1,TERMCH
	CAIE 1," "		;PROPER TERMINATOR?
	JRST CMDFLS		;NO
	MOVEI 6,6		;LIMIT OF 6 CHARACTERS IN NAME
	SETZ 7,			;INITIALIZE TO STORE NAME IN AC 7
	MOVE 5,[POINT 6,7,-1]
GETN2:	CALL GCIN		;READ AND ECHO A CHARACTER
	CAIE 1,.CHLFD		;LINE FEED?
	CAIN 1," "		; OR SPACE?
	JRST GETN1		;YES. END OF NAME
	JUMPLE 6,GETN2		;DON'T STORE CHAR IF ALREADY HAVE 6
	SUBI 1,40		;CONVERT TO SIXBIT
	IDPB 1,5		;ADD TO NAME IN AC 7
	SOJA 6,GETN2		;GO GET NEXT CHARACTER

;FIND THIS NAME IN TABLE OF PROGRAMS BEING RUN.

GETN1:	MOVSI NX,-NJOBS
	CAME 7,NAME(NX)		;NAME MATCH?
	AOBJN NX,.-1		;NO
	JUMPGE NX,[PMSG <Name not found.
>
		JRST CMDEND]
	RET
;GETNUM - ROUTINE TO RETURN A FORK NUMBER FROM A COMMAND IN NX

GETNUM:	MOVE 1,TERMCH
	CAIE 1," "		;PROPER TERMINATOR?
	JRST CMDFLS		;NO
	MOVEI 6,4		;LIMIT OF 4 CHARACTERS IN NUMBER
	SETZ 7,			;INITIALIZE TO STORE NUMBER IN AC 7
	MOVE 5,[POINT 7,7,-1]	;GET POINTER FOR STORING NUMBER
GETNU2:	CALL GCIN		;READ AND ECHO A CHARACTER
	CAIE 1,.CHLFD		;LINE FEED?
	CAIN 1," "		; OR SPACE?
	JRST GETNU1		;YES. END OF NAME
	JUMPLE 6,GETNU2		;DON'T STORE CHAR IF ALREADY HAVE 6
	IDPB 1,5		;ADD TO NAME IN AC 7
	SOJA 6,GETNU2		;GO GET NEXT CHARACTER

; HERE WITH NUMBER IN ASCII IN AC 7

GETNU1:	MOVEI 1,.CHNUL		;GET A NULL
	IDPB 1,5		;STORE IN NUMBER
	HRROI 1,7		;GET POINTER TO NUMBER
	MOVEI 3,10		;OCTAL
	NIN			;INPUT THE NUMBER
	 JRST CMDFLS		;FLUSH COMMAND
	MOVE NX,2		;COPY THE FORK NUMBER
	RET			;DONE, RETURN
;JSYS ERROR

JERR0:	PMSG <
?JSYS error: >
ERMSG:	MOVEI 1,101
	HRLOI 2,.FHSLF
	SETZ 3,
	ERSTR
	 JFCL
	 JFCL
	PMSG <
>
	RET

;NUMBER PRINTERS

DECOUT:	SKIPA C,[^D10]
OCTOUT:	MOVEI C,^D8
	MOVX A,.PRIOU
	NOUT
	 JFCL
	RET
;PSI STUFF

LEVT:	PCL1
	PCL2
	PCL3

;PUTS CHANNEL NUMBER IN LOCATION IN CHNN CORRESPONDING TO LEVEL WITHOUT
;DISTURBING ANY AC'S; THEN GOES TO LOCATION TO PROCESS INTERRUPT

DEFINE CHNE (LVL,LOC)
<	XWD LVL,[MOVEM 1,CHNN+LVL-1
		MOVEI 1,.-CHNT
		EXCH 1,CHNN+LVL-1
		JRST LOC]
>

	RADIX 10
CHNT:	CHNE (2,INTCH)		;0 - INTERRUPT CH
	CHNE (2,RSTCH)		;1 - INTERRUPT CH
	CHNE (3,PTINI)		;PTY INPUT
	CHNE (3,PTOUI)		;PTY OUTPUT
	REPEAT 9-4,<CHNE (1,BADI)> ;4 - 8, NOT ENABLED
	CHNE (1,BADI)		;9 - PDL OV
	CHNE (1,BADI)		;10 - NOT ENABLED
	CHNE (1,IGNOR)		;11 - FILE ERROR
	REPEAT 15-12,<CHNE (1,BADI)> ;12-14 NOT ENABLED
	CHNE (1,BADI)		;15 - ITRAP
	CHNE (1,BADI)		;16 - MR TRAP
	CHNE (1,BADI)		;17 - MW TRAP
	CHNE (1,BADI)		;18 - MX TRAP
	CHNE (3,FRKTRM)		;19 - FORK TERMINATED
	CHNE (1,BADI)		;20 - MACH SIZE TRAP
	REPEAT 36-21,<CHNE (1,BADI)> ;21-35, NOT ENABLED
RADIX 8

CHNMSK:	1B0+1B1+3B<PTCHN+1>+1B9+1B11+1B15+1B16+1B17+1B18+1B19+1B20
		;INT CHAR, FRK TRM, ALL PANIC CHANS
;PSI HANDLERS

IGNOR:	DEBRK

;^C

INTCH:	JSP 4,LRSET
	PMSG <
SYSJOB: ^C, restarting...
>
	JRST START		;DO NORMAL START

;^B - RELOAD AND RESTART SYSJOB

RSTCH:	MOVE 1,INJFN		;SEE IF HAVE INPUT FILE
	CAIL 1,1
	CAIL 1,100		;IS A JFN?
	JRST RSTC1		;NO
	GTSTS			;YES, GET STATUS
	TLNN 2,(1B10)		;EXISTS?
	JRST RSTC1		;NO
	HRLI 1,(1B0)		;YES, CLOSE AND DELETE IT
	CLOSF
	 JFCL
	HRLI 1,0
	DELF			;DELETE AND RELEASE JFN
	 JFCL
RSTC1:	JSP 4,LRSET		;RESET EVERYTHING
	PMSG <
SYSJOB: reloading self...
>
	MOVSI 1,(1B2+1B17)
	HRROI 2,[ASCIZ /SYSTEM:SYSJOB.EXE/]
	GTJFN
	 JRST [	JERR	;SUPER LOSSAGE...
		JRST START]	;TRY TO KEEP RUNNING THIS ONE
	HRLI 1,.FHSLF
	MOVE 2,[GET]		;PUT PROGRAM IN ACS
	MOVE 3,[MOVEI 1,.FHSLF]	;AFTER GET, CHECK ENTRY VECTOR
	MOVE 4,[GEVEC]
	MOVE 5,[JRST 0(2)]	;START NEW LOAD AT MAIN START
	JRST 2
BADI:	MOVX A,.FHSLF
	CIS			;UNDO ALL INTERRUPTS
	MOVE P,[IOWD NPDL,PDL]	;RESET STACK
	PMSG <
** SYSJOB: unexpected interrupt on channel >
	MOVE 2,CHNN		;CHANNEL NUMBER FOR LEV 1
	CALL DECOUT
	PMSG <, PC=>
	MOVE B,PCL1		;PC FOR LEVEL 1
	CALL OCTOUT
	PMSG < **
Last error message is:
  >
	CALL ERMSG
	JRST WAITI		;RESTART MAIN LOOP

LRSET:	MOVEI 1,400000
	SETO 2,
	DIC
	DIR
	MOVEI 1,-4
	KFORK
	CIS
	JRST 0(4)
;FORK TERMINATED - WAKE UP RIGHT AWAY TO REPORT IT

FRKTRM:	TLO F,(FRKTMF)
	PUSH P,1
	HRRZ 1,PCL3		;PC AT INTERRUPT
	CAIE 1,WAITPC+1		;AT DISMS?
	JRST FRKT1		;NO, RUNNING, WILL NOTICE FLAG
	MOVSI 1,010000		;YES, SET USER FLAG TO RUN
	HLLM 1,PCL3
FRKT1:	POP P,1
	DEBRK

;PTY ACTIVITY
;DO PTY SERVICE AT INTERRUPT LEVEL IF MAIN PRG IS IN HIBER.
;NOTE ACS (EXCEPT 1) ASSUMED CLOBBERABLE DURING HIBER.

PTINI:
PTOUI:	PUSH P,1
	HRRZ 1,PCL3		;CHECK PC OF MAIN PRG
	CAIE 1,WAITPC+1		;AT HIBER?
	JRST [	TLO F,(FRKTMF)	;NO, REQUEST ADDITIONAL CHECK
		JRST PTI1]
	CALL CHKPTY		;MAIN PRG IN HIBER, DO PTY NOW
PTI1:	POP P,1
	DEBRK
;COMMAND TABLE

DEFINE CM (LOC,NAME)
<	XWD LOC,[ASCIZ /NAME/]
>
CMNDTB:	CM (.RUN,RUN)
	CM (.KILL,KILL)
	CM (.PURGE,PURGE)
	CM (.START,RESUME)
	CM (.STOP,FREEZE)
	CM (.STAT,STATUS)
	CM (.ATTM,ATTIME)
	CM (RSTCH,RELOAD)
	CM (.JOB,JOB)
	CM (.KJOB,KILLJOB)
	CM (.CCJOB,CCJOB)
LCMTB==.-CMNDTB

CMDPT0:	POINT 7,CMDBUF,-1	;COMMAND BUFFER INITIAL PTR

;FORK STATE DESCRIPTION MESSAGES

FSTAB:	Z [ASCIZ /Running/]
	Z [ASCIZ /IO wait/]
	Z [ASCIZ /Halted/]
	Z [ASCIZ /Crashed/]
	Z [ASCIZ /Fork wait/]
	Z [ASCIZ /DISMS/]
NFSTAB==.-FSTAB

VTXT:	.CLNAM			;CREATE VERSION TEXT

	XLIST			;'LIT' FOLLOWS
	LIT			;KEEP LITERALS WITH CODE
	LIST			;END OF 'LIT'
;STORAGE

	BLOCK 1000		;PUT STORAGE IN SEPARATE PAGE FROM CODE

STGBGN:	BLOCK 0			;CLEAR FROM HERE TO STGEND ON STARTUP
PCL1:	BLOCK 1
PCL2:	BLOCK 1
PCL3:	BLOCK 1
CHNN:	BLOCK 3
CMNDP:	BLOCK 1
PDL:	BLOCK NPDL
LOCAL:	BLOCK 2			;LOCAL NODE NAME
PDELAY:	BLOCK 1
CMDBUF:	BLOCK 30
NAMBUF:	BLOCK 11
TERMCH:	BLOCK 1
INJFN:	BLOCK 1
DBUGSW:	BLOCK 1
JFNTAB:	BLOCK 10
FRKACS:	BLOCK 20		;ACS FOR DEAD INFERIOR
JOBPTY:	BLOCK NLINES		;TTY DESIG,,PTY JFN
JOBISP:	BLOCK NLINES		;BYTE POINTER TO PTY INPUT
JOBISE:	BLOCK NLINES		;BYTE PTR TO END OF PTY INPUT
JOBOSP:	BLOCK NLINES		;BYTE POINTER TO PTY OUTPUT
SBUF:	BLOCK NLINES*2*NWSBUF	;STRING BUFFERS
LCLIC:	BLOCK 1			;COUNT OF COMMANDS FROM LOCAL TTY
LCLBF:	BLOCK NLCLBF		;BUFFER FOR LOCAL COMMANDS
LFORK:	BLOCK 1			;HANDLE FOR LOCAL INPUT FORK
FIRPTY:	BLOCK 1			;TTY NUMBER OF FIRST PTY
TTYJOB:	BLOCK 1			;TABLE NUMBER FOR TTYJOB
JOBNAM:	BLOCK 1			; " " JOBNAM
SNAMES:	BLOCK 1			; " " SNAMES
DIRNAM:	BLOCK 10		;BUFFER FOR NAME OF DIRECTORY (USED AT WAIT2)

;ATTIME TABLES

TIMES:	BLOCK NAJOBS
AJCMD:	BLOCK NAJOBS*NAJCW	;STORED COMMAND STRINGS
AJCMP:	BLOCK 1

;JOB TABLES - DO NOT REORDER
;ONE ENTRY PER FORK STARTED VIA 'RUN' COMMAND

FORKN:	BLOCK NJOBS		;FORK HANDLE
NAME:	BLOCK NJOBS		;SIXBIT NAME
STGEND:	BLOCK 0			;CLEAR FROM STGBGN TO HER ON STARTUP

;LOCATIONS FROM HERE ON ARE NOT CLEARED ON STARTUP

TESTSW:	BLOCK 1			;NON-0 IF TESTING SYSJOB

	END <3,,EVEC>