.TITLE SPOOL - LP SPOOLER V01-03 .NLIST TTM ; ; THIS PROGRAM FOR THE FORGROUND IS A LINE PRINTER SPOOLER, ; ; IT HAS TWO MODES OF OPERATION. ; ; FIRST, IF NO /D SWITCH IS GIVEN ANYWHERE IN THE COMMAND LINE, ; 1 OR MORE COPIES OF ALL SPECIFIED FILES WILL BE LISTED AND ; SPOOL WILL TERMINATE AUTOMATICALLY. ; ; SECOND, IF A /D SWITCH IS GIVEN, SPOOL WILL LIST AND DELETE ; ALL SPECIFIED FILES AND THEN SLEEP FOR 30 SEC. THEN ; IT WILL SEARCH THE DIRECTORY AGAIN TO SEE IF ANY NEW FILES MATCHING ; THE NAMES SPECIFIED HAVE BEEN ADDED TO THE DISK, AND IF SO, IT ; WILL LIST AND DELETE THEM BEFORE SLEEPING AGAIN. THIS CONTINUES ; UNTIL SPOOL IS TERMINATED WITH CTRL/C. ; ; THE DEFAULT DEVICE IS DK0: AND THE DEFAULT EXTENSION IS .LST. ; THE DEFAULT SWITCH IS /C:1. ; UP TO SIX (6) FILENAME.EXT COMBINATIONS ; TO BE ENTERED IN CONJUNCTION WITH THE FOLLOWING SWITCHES: ; ; /C:N -- WHICH PRODUCES N COPIES OF THE FILENAME.EXT ; THAT PROCEDES THE SWITCH. ; /D -- WHICH CAUSES ALL THE INPUT FILENAME.EXTS ; TO BE DELETED FROM THE SPECIFIED OR DEFAULT ; DEVICE AFTER THE FILES HAVE BEEN SPOOLED. ; /D:N -- WHICH CAUSES ALL SPECIFIED INPUT FILES TO BE ; DELETED AFTER THEY HAVE BEEN SPOOLED AND N ; NUMBER OF COPIES GENERATED FROM THEFILENAME.EXT ; THAT PRECEDES THE /D SWITCH. ; ; IF THE /C SWITCH IS USED ON THE INPUT LINE WITHOUT THE /D ; THE FILES SPECIFIED WILL BE LISTED, AND THE SPOOLER ; WILL DISENGAGED AFTER ONE PASS THRU THE DEVICE DIRECTORY. ; THE WILD CARD CONSTRUCTION WILL BE HONORED IN THE ; FILENAME OF EXTENSION POSITION. THEREFORE, ; *.FOR/C:2 -- WILL LIST ALL THE FORTRAN PROGRAMS TWICE ; THEN DISENGAGED THE SPOOLER. ; HARDY.*/C:2/D -- WILL LIST ALL THE FILES THAT BEGIN ; WITH HARDY TWICE, DLETE THEM AND ; CONTINUE TO SCAN THE DIRECTORY. ; *.FOR/C:2,HARDY/D:3 -- WILL LIST ALL THE FORTRAN PROGRAMS ; TWICE THEN DELETE THEM, LIST ALL THE ; HARDY.* FILES THREE TIME AND THEN DELETE ; THEM, AFTER WHICH THE SPOOLER ; WILL CONTINUE TO SCAN THE DEVICE DIRECTORY ; FOR MORE FILES OF THE SAME FORMAT. ; ; BUILDING SPOOL: ; ; .R MACRO ; *LREADY=LREADY ; *SPOOL=SPOOL ; CTRL/C ; .R LINK ; *SPOOL=SPOOL,LREADY/R ; CTRL/C ; ; RUNNING SPOOL: ; ; .LOAD LP ; .FRUN SPOOL ; ENTER COMMAND LINE WHEN ASK. ; ; KILLING SPOOL: ; ; CTRL/F (TO ADDRESS FORGROUND) ; CTRL/C ; CTRL/C ; . ; ; ; MARTY ROTH ; MEAD TECHNOLOGY LABS ; 3481 DAYTON-XENIA RD. ; DAYTON OH 45432 ; ; .MCALL ..V2..,.REGDEF .MCALL .READW,.WRITW,.LOOKUP,.DELETE,.CSISPC,.TTYIN .MCALL .PRINT,.TTYOUT,.SRESET,.RCTRLO,.CLOSE,.EXIT .MCALL .DSTATUS,.TWAIT,.FETCH .GLOBL LREADY ; ..V2.. .REGDEF USRSWP = 46 ;USR SWAP LOCATION POINTER ERRBYT = 52 ;ERROR CODE CR = 15 ;CARRIAGE RETURN LF = 12 ;LINE FEED FILBLK = CSIBLK+36 ; START: MOV #BUFF,@#USRSWP ;MAKE USR SWAP OVER BUF MOV SP,(PC)+ ;SAVE STACK POINTER STKSAV: .WORD 0 .PRINT #IDENT ; .DSTATUS #IOB,#LP ;MUST BE IN MEMORY ; BCS 1$ ;ILLEGAL DEVICE ; TST IOB+4 ;TEST ENRY POINT BR BEGIN ; BNE BEGIN ;BR TO BEGIN IF LOADED ABORT: .PRINT #MSG0 ;BACK TO USER FOR A LOAD LP .EXIT ; ;COME HER ON BAD COMMAND STRING BADCOM: MOV STKSAV,SP ;RESET STACK, FALL THRU TO BEGIN .PRINT #MSG2 ;TELL HIM ABOUT A BAD SWITCH ; BEGIN: MOV #ONEPAS, R0 MOV #CSIBLK, R1 SUB R1, R0 LOOP: CLR (R1)+ DEC R0 BNE LOOP .CLOSE #0 ;WE WILL USE CH 0, SO CLEAN IT UP INCB ONEPAS ;TURN ON ONE PASS SWITCH .RCTRLO ;RESET CTRL/O FLAG SO .PRINT #MSG1 ;PROMPTING MSG WILL PRINT MOV #CSIBLK,R2 ;POINT TO COMMAND STRING BUFFER MOV R2,R1 ;COPY THE POINTER AND INPUT COMMAND 1$: .TTYIN ;A CHARACTER AT A TIME CMP #CR,R0 ;CARRIAGE RETURN? BEQ 1$ ;YES, IGNORE IT. MOVB R0,(R2)+ ;MOVE IT INTO BUFFER AND CMPB #LF,R0 ;TEST FOR END OF LINE. BNE 1$ ;NO,GET ANOTHER CHAR. CLRB -(R2) ;YES, CLEAR OUT THE LINE FEED .CSISPC R1,#DEFEXT,R1 ;PROCESS THE COMMAND JSR PC, DEVCHK MOV (SP)+,R3 ;TEST# OF SWITCHES; C BIT UNCHANGED ; BNE BADCOM ;NO SWITCHES ALLOWED BCS BADCOM ;SYNTAX ERROR BEQ 6$ ;SKIP THIS CODE IF NONE WERE FOUND ; ; ROUTINE TO BUILD A TABLE OF SWITCHES FOR EACH FILE ENTRY. ; ONE BYTE FOR THE DELETION ; ONE BYTE FOR MULTIPLE COPIES ; ONE WORD FOR THE NUMBER OF COPIES IF ANY. ; 2$: MOVB 1(SP), R2 ;GET THE FILE ASSOCIATION NUMBER BIC #177600, R2 ;CLEAR THE GARBAGE BITS SUB #3, R2 ;POINT TO THE INPUT FILES ONLY BMI BADCOM ;BRANCH TO BAD COMMAND IF LESS THAN 0 ASL R2 ;MULTIPLY BY 2 FOR EVEN BOUNDARIES ADD #SWHTBL, R2 ;SET UP POINTER INTO SWITCH TABLE MOVB (SP), R4 ;GET THE ASCII SWITCH VALUE BIC #177600, R4 ;CLEAR ANY GARBAGE BITS CMPB #'D, R4 ;IS THIS A DELETE SWITCH ? BNE 4$ ;NO, BUT POSSIBLE ALLOWABLE SWITCH CLRB ONEPAS ;TURN ON RECYCLE FLAG BR 11$ ;GO CHECK FOR SWITCH VALUE 4$: CMPB #'C, R4 ;IS THIS A COPY FLAG ? BNE BADCOM ;NO, BAD SWITCH 11$: MOV (SP)+, R0 ;POP OF FIRST SWITCH WORD BPL 5$ ;BRANCH IF SWITCH COUNT NOT PRESENT MOV (SP)+, (R2) ;MOVE NUMBER OF COPIES 5$: DEC R3 BNE 2$ INCB SEARCH ;TURN ON SEARCH BIT FOR LATER 6$: .LOOKUP #IOB,#1,#LP MOV CSIBLK+36.,R0 ;GET FILE EXTENSION TO PRINT. BNE 7$ ;BRANCH IF USR SPECIFIED, MOV (PC)+,R0 ;ELSE USE LST EXTENSION .RAD50 /LST/ 7$: MOV R0,LST... ;SAVE THE EXTENSION FOR LATER. MOV CSIBLK+30.,R0 ;GET THE INPUT DEVICE NAME BNE 8$ ;BRANCH IF USER SPECIFIED, MOV (PC)+,R0 ;ELSE USE THE .RAD50 /DK0/ ;DEFAULT DEVICE. 8$: MOV R0,@R1 ;SET DEVICE NAME IN FILE CLR 2(R1) ;DESCRIPTOR BLOCK, CLEARING ;OUT ANY FILE NAME .DSTATUS #IOB,R1 ;INPUT DEVICE HANDLER MUST BE RESIDENT BCS 9$ ;ILLEGAL DEVICE TST IOB+4 ;TEST ENTRY POINT BNE 10$ ;BRANCH IF ALL OK, 9$: .PRINT #MSG3 ;ELSE PRINT MESSAGE JMP BEGIN 10$: .PRINT #GOMSG ;INFORM USER THAT SYSTEMS ARE GO .LOOKUP #IOB,#0,R1 ;OPEN CHANNEL TO READ DIRECTORY BCS BADERR .ENABL LSB FINDLP: MOV #BUFF,R2 ;R2->BUFFER MOV #1,R3 ;INIT R3 1$: ASL R3 ;MULTIPLY BY 2 ADD #4,R3 ;AND ADD R TO GET BLOCK NUMBERS ;OF DIRECTORY SEGMENT (STARTING ;AT BLOCK 6 OF DEVICE). REREAD: .READW #IOB,#0,R2,#1000,R3 ;READ A DIRECTORY SEGMENT BCS BADERR ;ERROR READING DIRECTORY!! TSTB NXT ;READ THE NEXT FILE IN SAME SEGMENT BNE 2$ ;YES, SKIP TO STATUS CHECK MOV R2,R5 ;COPY POINTER ADD #12,R5 ;MOVE PAST DIRECTORY HEADER 2$: BIT #4000,@R5 ;TEST FOR END OF SEGMENT BEQ 4$ ;BRANCH IF MORE TO GO CLRB NXT ;RESET ROLLOUT FLAG MOV 2(R2),R3 ;GET LINK TO NEXT SEGMENT BNE 1$ ;BRANCH IF ANOTHER SEGMENT EXISTS, TSTB ONEPAS ;ONEPASS THUR THE DIRECTORY ? BEQ 3$ ;NO, CONTINUE NORMALLY .PRINT #MSG5 .EXIT 3$: .TWAIT #IOB,#TIMBLK ;ELSE WAIT A WHILE BR FINDLP ;WE'RE AWAKE, LOOK FOR A FILE 4$: BIT #2000,(R5)+ BEQ 10$ ; ; ROUTINE TO SEARCH FILE TABLE FOR FILENAME.EXT MATCH ; TSTB SEARCH ;TABLE SERCH REQUIRED ? BEQ 9$ ;NO, SKIP THIS SECTION MOV #FILBLK,R0 ;SET UP TABLE ADDRESS 5$: TST (R0) ;END OF FILE TABLE ? BEQ 10$ ;YES, END FILE TABLE SEARCH CMP #132500,2(R0) ;NO, IS THIS A WILD CARD ? BEQ 6$ ;YES, GO CHECK EXT CMP (R5),2(R0) ;NO, DOES FILE NAME MATCH ? BNE 7$ ;NO, CHECK NEXT ENTRY CMP 2(R5),4(R0) ;YES, STILL A MATCH ? BNE 7$ ;NO, CHECK NEXT ENTRY 6$: CMP 4(R5),6(R0) ;YES, DOES EXT MATCH ? BEQ 8$ ;YES, PREPARE TO COPY CMP #132500,6(R0) ;IS THIS A WILD CARD OPERATION ? BEQ 8$ ;YES, SET UP TO COPY IT 7$: ADD #10, R0 ;NO, CHECK NEXT ENTRY BR 5$ ;BY REPEATING PROCESS 8$: MOV R0,R4 ;GET ADDRESS OF TABLE INDEX SUB #FILBLK,R4 ;NOW GET ACTUAL INDEX ASR R4 ;DIVIDE BY 2 ASR R4 ADD #SWHTBL,R4 ;AND GET INDEX INTO COUNTER TABLE MOV (R4)+, COPIES ;SET UP NUMBER OF COPIES BEQ COPIER INCB COP BR COPIER 9$: CMP 4(R5),(PC)+ ;DOES THE EXTENSION MATCH? LST...: .WORD 0 BEQ COPIER ;YES, GO PRINT IT 10$: ADD #14,R5 ;NO, BR 2$ BADERR: .PRINT #MSG4 ;PRINT A MESSAGE BR 1$ ;THEN TRY NEXT SEGMENT .DSABL LSB ; ;THIS ROUTINE PRINTS THE SPOOLED FILE JUST FOUND ; COPIER: MOV (R5)+,2(R1) ;COPY FILE NAME AND EXTENSION MOV (R5)+,4(R1) ;INTO FILE DESCRIPTOR BLOCK MOV (R5)+,6(R1) ;FOR A LOOKUP. TSTB ONEPAS ;SAVE THE DIRECTORY POINTERS ? BEQ 8$ ;NO, FILES WILL BE DELETED CMP (R5)+, (R5)+ ;ADVANCE TO NEXT TST (R5)+ ;FILE ENTRY BEFORE ROLLOUT MOV R2, -(SP) ;SAVE BUFFER POINTER ON STACK MOV R3, -(SP) ;SAVE BLOCK ADDRESS MOV R5, -(SP) ;SAVE POINTER INTO BUFFER INCB NXT ;INDICATE THAT POINTERS HAVE BEEN ROLLED OUT 8$: .LOOKUP #IOB,#2,R1 ;LOOKUP THE FILE ON CHANNEL 2 BCS 7$ ;SOMETHING FUNNY HAPPENED 4$: CLR R5 ;OK, COPY IT, R5 IS BLOCK # 1$: .READW #IOB,#2,R2,#1000,R5 ;READ 1000 WORDS BCS 2$ ;ERROR ON READ MOV R0,R4 ;COPY ACTUAL WORD COUNT .WRITW #IOB,#1,R2,R4,R5 ;AND WRITE IT TO CHANNEL 1 TST (R5)+ ;BUMP BLOCK # BY 2 BR 1$ ;CONTINUE UNTIL EOF. 2$: TSTB @#ERRBYT ;WAS ERROR JUST AN EOF? BEQ 3$ ;YES. .CLOSE #2 ;NO, CLOSE THE FILE AND .PRINT #ERRIN ;REPORT AN INPUT ERROR JMP FINDLP ;THEN FIND ANOTHER FILE. 3$: TSTB COP ;MULTIPLE COPIES REQUIRED ? BEQ 6$ ;NO, GO CLOSE FILE DEC COPIES ;MORE COPIES TO PRINT ? BNE 4$ ;YES, CONTINUE COPING 6$: .CLOSE #2 ;ON EOF, CLOSE THE FILE TSTB ONEPAS ;DELETE AND RECYCLE ? BNE 5$ ;NO, GET NEXT FILE .DELETE #IOB,#3,R1 ;MUST DELETE USEING AN INACTIVE CHANEL 5$: TSTB ONEPAS ;RESTORE DIRECTORY POINTERS ? BEQ 7$ ;NO, DELETE IS IN EFFECT MOV (SP)+, R5 ;YES, RESTORE MOV (SP)+, R3 ;ALL ROLLOUT MOV (SP)+, R2 ;POINTERS JMP REREAD ;AND REREAD DIRECTORY SEGMENT 7$: JMP FINDLP ;THEN CONTINUE ; DEVCHK: TST CSIBLK ;DID USER SPECIFY OUTPUT DEVICE ? BEQ 102$ ;NO, CHECK LP AND KB CMP LP,CSIBLK ;DID HE SPECIFY THE LP ? BEQ 102$ ;YES, GO CHECK LP STATUS CMP KB,CSIBLK ;NO, DID HE SPECIFY THE KB ? BNE 101$ ;NO, LET SPECIFY HIS OWN DEVICE MOV KB,LP ;YES, SET UP FOR KB DEVICE BR 103$ ;NOW, GO CHECK STATUS ON KB 101$: MOV CSIBLK,LP ;SET UP USER OWN DEVICE BR 103$ ;GO CHECK STATUS OF THAT DEVICE 102$: CLR R0 JSR PC,LREADY ;SEE IF THE SYSTEM HAS A LP TST R0 ;0 => NO LP, 1 => LP EXISTS BNE 103$ ;LP EXISTS, SEE IF IT IN CORE MOV KB,LP ;LP DOES NOT EXIST, DEFAULT TO ;TO THE KB 103$: .DSTATUS #IOB, #LP ;IS THE HANDLER RESIDENT ? BCS 104$ ;NO, GO FETCH IT TST IOB+4 ;YES, IS IT RUNNABLE ? BNE 105$ ;YES, LET'S GO 104$: .FETCH FREE, #LP ;TRY TO FETCH IT BCS 106$ ;NO CAN DO, ABORT AND EXIT 105$: RTS PC 106$: JMP ABORT LP: .RAD50 /LP / ;SPOOLER OUTPUT DEVICE KB: .RAD50 /KB / ;DEFAULT OUTPUT DEVICE IOB: .BLKW 5 ;EMT ARGUMENT BLOCK .NLIST BIN MSG0: .ASCIZ /LOAD LP/ MSG1: .ASCIZ /FILES TO SPOOL??/ MSG2: .ASCIZ /!!! BAD SWITCH !!!/ MSG3: .ASCIZ /DEVICE?/ MSG4: .ASCIZ /ERR READ DIR/ MSG5: .ASCIZ /!!! LP: SPOOLER DISENGAGED !!!/ GOMSG: .ASCIZ /!!! LP: SPOOLER ENGAGED !!!/ ERRIN: .ASCIZ /READ ERR/ IDENT: .ASCIZ /SPOOLER V01-03/ .EVEN .LIST BIN TIMBLK: .WORD 0,60.*15. DEFEXT: .RAD50 /LST/ ;CSI DEFAULT EXTENSION .WORD 0,0,0 CSIBLK: .BLKW 39. ;CSI WORK AREA SWHTBL: .BLKW 6. ;SWITCH TABLE ONEPAS: .BYTE 0 SEARCH: .BYTE 0 DELETE: .BYTE 0 COP: .BYTE 0 NXT: .BYTE 0 SPARE: .BYTE 0 COPIES: .WORD 0 BUFF: .BLKW 10000 FREE: .+2 ;POINTER TO FREE CORE .END START