1
0
mirror of https://github.com/PDP-10/its.git synced 2026-01-28 04:57:43 +00:00
Files
PDP-10.its/src/sysen1/gmsgs.93
Lars Brinkhoff 508f8970b3 Some Y2K fixes.
2017-01-11 16:16:14 -08:00

1381 lines
38 KiB
Plaintext
Executable File
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
;-*-MIDAS-*-
TITLE GMSGS
;COPY ALL RECENT SYSTEM MESSAGES INTO A USER'S
;MAIL FILE, AND ADVANCE THE USER'S DATE-FILE
;TO INDICATE HE HAS SEEN THOSE MESSAGES.
;ALSO, IF THERE ARE ANY MESSAGES, TYPE OUT
;"THERE ARE MESSAGES", UNLESS THE COMMAND LINE CONTAINS
;"/S" FOR "SILENT".
;NORMALLY, MESSAGES GO AT THE FRONT, LATEST FIRST,
;BUT IF THE COMMAND STRING HAS "/R" IN IT, THE MESSAGES
;GO AT THE END, EARLIEST FIRST.
;UNLESS, OF COURSE, THE USER SPECIFIES /G, TO CAUSE THEM TO BE
;WRITTEN TO THE FILE <HSNAME>;<XUNAME> GMSGS. USE OF THIS
;OPTION IS HIGHLY RECOMMENDED, SINCE IT PREVENTS CLOBBERING
;YOUR MAIL FILE WITH TIMING CONFLICTS WITH COMSAT.
;THE USER TO SNARF THE MESSAGES OF MAY BE SPECIFIED IN THE
;COMMAND STRING, OR MAY BE ALLOWED TO DEFAULT TO THE
;XUNAME.
;THE NAMES OF THE MACHINES WHOSE MESSAGES SHOULD BE SNARFED
;(SUCH AS *AI, *DM, *MC, *ML, OR * FOR ALL MACHINES)
;MAY ALSO BE SPECIFIED.
;IF /D IS SPECIFIED, THEN THE DISTRIB:
;AND EXPIRES: FIELDS OF MESSAGES (NORMALLY HIDDEN)
;WILL BE SHOWN.
;IF /M IS SPECIFIED, THE MESSAGES ARE MAILED THROUGH THE COMSAT
;TO THE USER, INSTEAD OF PUT DIRECTLY IN HIS MAIL FILE.
;/G MAKES GMSGS NOT BREAK THE MAIL FILE, AND WRITE TO A GMSGS
;FILE INSTEAD.
;/N MAKES GMSGS TYPE (THERE IS MAIL) IF THE USER'S
;MAIL FILE IS INITIALLY MORE RECENT THAN HIS MSGS FILE.
;/T MAKES GMSGS PRINT THE MESSAGES ON THE TELETYPE
;INSTEAD OF PUTTING THEM IN THE MAIL FILE
;/Z SWITCH: SHOW SYS:SYSTEM MAIL AND THE LIKE. THIS IS
;MOSTLY FOR THE BENEFIT OF ZMAIL
;This program is also a Chaosnet server
;Connect to contact name GMSGS, space, hsname, semicolon, xuname, space, jcl line.
;Any teletype output will come back down the Chaosnet connection.
;EOF will be sent and "finished" after the file is written and
;before the program dies.
loc 40
0 ? 0 ? 0 ? 0
-crtlen,,crtab
loc 100
.INSRT RMS;MACROS >
.insrt syseng;msgs >
.insrt system;chsdef >
crtab: msgs"critic
crtlen==.-crtab
chaos: 0 ;-1 if this is a Chaos server
pktbuf: block %cpmxw
INC==1 ;DISK INPUT (MESSAGES AND MAIL FILE)
OUTC==2 ;DISK OUTPUT
FDRC==3 ;INPUT OF .MSGS. DIRECTORY
TYOC==4 ;TYPEOUT
MSGC==5 ;Channel to open SYS;:MSGS TIMES on.
CHSI==6 ;Chaosnet input
CHSO==TYOC ;Chaosnet output is TYOC
ERRC==7 ;ERR device
LOCKC==10 ;LOCK device
IFNDEF PDLL,PDLL==60 ;PDL LENGTH.
IFNDEF CMDL,CMDL==10 ;JCL-COMMAND BUFFER LENGTH.
BEG: MOVE P,[-PDLL,,PDL-1]
.SUSET [.RHSNAM,,HSNAME]
.SUSET [.RXUNAM,,USER]
.SUSET [.RJNAME,,A]
CAMN A,[SIXBIT /EXPIRE/]
JRST [ SYSCAL RQDATE,MOVEM MSGTDT ;READ IN TODAY'S DATE.
.LOSE %LSSYS
CALL EXPIRE
.LOGOUT 1, ]
CAME A,[SIXBIT/CHAOS/]
JRST BEG0
SETOM CHAOS ;We are a Chaosnet server
.CALL [SETZ ? 'CHAOSO ? MOVEI CHSI ? MOVEI CHSO ? SETZI 5 ]
.LOGOUT 1,
MOVE A,[.BYTE 8 ? %COLSN ? 0 ? 0 ? 5]
MOVEM A,PKTBUF
MOVE A,[.BYTE 8 ? "G ? "M ? "S ? "G]
MOVEM A,PKTBUF+%CPKDT
MOVE A,[.BYTE 8 ? "S]
MOVEM A,PKTBUF+%CPKDT+1
.CALL [ SETZ ? 'PKTIOT ? MOVEI CHSO ? SETZI PKTBUF ]
.LOSE %LSSYS
.CALL [ SETZ ? 'NETBLK ? MOVEI CHSO ? MOVEI %CSLSN ? SETZM A ]
CAIA
CAIE A,%CSRFC
.LOGOUT 1,
MOVSI A,%COOPN_10.
MOVEM A,PKTBUF
.CALL [ SETZ ? 'PKTIOT ? MOVEI CHSO ? SETZI PKTBUF ]
.LOSE %LSSYS
.CALL [ SETZ ? 'PKTIOT ? MOVEI CHSI ? SETZI PKTBUF ]
.LOSE %LSSYS
;The connection is now open and the RFC is in PKTBUF
MOVE A,[240800,,PKTBUF+%CPKDT+1]
LDB C,[$CPKNB+PKTBUF]
SUBI C,6 ;GMSGS space
MOVE B,[440600,,HSNAME] ;Get hsname
SETZM HSNAME
CHJCL0: ILDB D,A
CAIN D,";
SOJA C,CHJCL1
CAIGE D,140
SUBI D,40
TLNE B,770000
IDPB D,B
SOJG C,CHJCL0
CHJCL1: MOVE B,[440600,,USER] ;Get xuname
SETZM USER
CHJCL2: ILDB D,A
CAIN D,40
SOJA C,CHJCL3
CAIGE D,140
SUBI D,40
TLNE B,770000
IDPB D,B
SOJG C,CHJCL2
CHJCL3: MOVE B,[440700,,CMD] ;Rest of RFC is JCL
CHJCL4: ILDB D,A
IDPB D,B
SOJG C,CHJCL4
MOVEI D,^M
IDPB D,B
BEG0: SYSCAL RQDATE,MOVEM MSGTDT ;READ IN TODAY'S DATE.
SETOM MSGTDT
SKIPGE MSGTDT
JRST [ MOVEI A,[ASCIZ /The system does not know the date right now -- GMSGS.
/]
CALL TELL
JRST NOMSGS]
CALL MORCOR ;GET SOME CORE TO HACK WITH
CALL EXPIRE ;DELETE EXPIRED MESSAGES.
.SUSET [.ROPTIO,,A]
TLO A,%OPLOK\%OPLKF
.SUSET [.SOPTIO,,A]
SKIPE CHAOS
JRST BEG1
SETZM CMD
TLNE A,%OPCMD
.BREAK 12,[5,,CMD]
BEG1: SYSCAL SSTATU,[ REPEAT 6,[? %CLOUT,,B]]
.LOSE %LSSYS
MOVEM B,ITSNAM ;DISCOVER WHICH ITS WE'RE ON.
MOVE A,[.BYTE 7 ? ^M]
SKIPN CMD
MOVEM A,CMD ;NO COMMAND STRING JUST LIKE A BLANK COMMAND STRING.
MOVE A,[440700,,CMD]
MOVEM A,CMDBP ;PREPARE TO READ IT.
SAVE P ;SAVE POINTER TO LAST THING BELOW OUR ARGS
MSGSR1: CALL RDSIX ;READ AN ARG (A SIXBIT WORD) AND PUSH IT IF NOT BLANK.
JUMPE A,MSGSR2
LDB B,[360600,,A]
CAIE B,'* ;1ST CHAR NOT STAR => IT'S THE USER'S NAME.
JRST [ MOVEM A,USER
SKIPN CHAOS
.BREAK 12,[..RMAIL,,ITSNAM] ;find out where his mail goes.
JRST MSGSR2]
SETOM SPCDST ;IF IT'S *AI, ETC, SAY WE GOT A SPECIFIED KEYWORD
EXCH A,(P) ;AND "PUSH" IT UNDERNEATH THE SAVED STACK POINTER.
SAVE A
MSGSR2: CAIE I,^M ;LOOP AROUND TILL CR IS REACHED.
JRST MSGSR1
MOVE B,ITSNAM ;Remember our ITS name
LSH B,-6
TLO B,(SIXBIT/*/)
REST D
CAMN D,P ;NOW, IF THERE WERE NO ARGS PUSHED,
SAVE B ;PUSH THE "*AI", ETC. AS A DEFAULT.
SAVE D ;(UNDERNEATH THE SAVED STACK POINTER, OF COURSE)
SKIPE CHAOS
JRST .+3
.OPEN TYOC,['!TTY]
.LOSE %LSSYS
;SET UP FOR READING IN APPROPRIATE MSGS FILES.
SKIPN GMSGSF
SKIPE TTYF
SETZM MAILF ;/T OVERRIDES /M (ELSE /T/M WOULD DO GARBAGE).
SKIPE TTYF
SETOM SILNT ;NO NEED TO TELL IF OUTPUT TO TTY
MOVE B,[SIXBIT /GMSGS/]
SKIPE GMSGSF ;IF WE'RE WINNING, NOT CLOBBERING OUR MAIL FILE
MOVEM B,MALNAM ; USE THIS FILENAME INSTEAD
MOVEI B,BUFBOT ;INITIALIZE THE INPUT BUFFER.
MOVEM B,BUFMID ;SAY THAT NOTHING IS IN IT YET.
MOVEI B,MEMTOP
MOVEM B,BUFTOP ;SAY HOW MUCH SPACE THERE IS TO READ INTO.
SKIPE TTYF
JRST MSG0 ;DON'T READ IN EXISTING MAIL FILE IF /T
SKIPN MAILF ;DON'T READ IN EXISTING MAIL FILE IF /M
SKIPN REVERS ;IN BACKWARDS MODE, THE EXISTING MAIL FILE
JRST MSG0
CALL LODOLD ;GOES AT THE FRONT.
MOVE B,BUFMID
CAIN B,BUFBOT ;IF IT EXISTS AND IS NONEMPTY,
JRST MSG0
CALL ENDFIL ;REMOVE TRAILING ^C'S, ^L'S FROM IT.
MOVEI A,40 ;BUT ENDFIL INSERTS AN EXTRA ^_;
DPB A,D ;REPLACE IT WITH A SPACE.
JRST MSG0
;DEFINITIONS FOR MSGS
UNFN1==0 ;COPIED FROM ITS, NEAR QSKO
UNFN2==1
UNRNDM==2
UNDATE==3
UNLINK==1
UNIGFL==200064 ;BITS IN RH OF UNRNDM, SET => FILE INACCESSABLE.
LUNBLK==5 ;LENGTH OF NAME-BLOCK.
MSG0: move a,user
movei b,msgc
move c,[-msglen,,msgpag]
call msgs"usrget
.lose
movem a,msgloc
move c,msgs"me$mdt(a)
movem c,msgdat ;print a file iff more recent than msgdat.
SETOM MSGLDT ;NO FILES TYPED YET.
SKIPE NOTIFF ;IF /N, MAYBE SAY "THERE IS MAIL".
CALL THRSML
;READ IN THE .MSGS. (OR WHATEVER SNAME) DIRECTORY.
.SUSET [.SSNAM,,MSGSNM]
.OPEN FDRC,MSGF2 ;OPEN DIR. IN IMAGE BLOCK MODE.
JSR OPNERR
MSGS1: MOVE D,[-2000,,VPAGAD]
.IOT FDRC,D ;READ THE WHOLE DIR.
.CLOSE FDRC,
MOVEI A,VPAGAD
ADD A,VPAGAD+1 ;ADDR. OF 1ST NAME-ENTRY.
MOVEI B,VPAGAD+2000 ;ADDR AFTER LAST.
MOVSI C,400000 ;DON'T INCLUDE ACCESS DATE IN SORT KEY.
PUSHJ P,SORT
MOVEI A,VPAGAD-LUNBLK
ADD A,VPAGAD+1 ;ONE OF THESE ADDR'S IS THE BEGINNING;
MOVEI D,VPAGAD+2000 ;THE OTHER IS THE END.
SKIPE REVERS ;IT DEPENDS WHICH DIRECTION WE'RE GOING.
EXCH A,D ;FILES ARE REALLY LATEST FIRST NOW
MOVEM D,LAST ;SO REVERSE MEANS DOWNWARD IN CORE ADDRESSES
MOVEI D,LUNBLK
MOVEM D,INCREM
SKIPE REVERS
MOVNS INCREM
MSGSNF: ADD A,INCREM ;LOOK AT NEXT FILE.
CAMN A,LAST
JRST MSGSX ;IF ALL SEEN.
SKIPN D,UNFN1(A)
JRST MSGSNF ;IGNORE IF FN1 BLANK.
MOVEM D,MSGF3+1 ;SAVE FN1 FOR OPEN.
SKIPN D,UNFN2(A)
JRST MSGSNF
MOVEM D,MSGF3+2
LDB D,[360600,,MSGF3+1]
CAIN D,'_ ;IGNORE FILE IF FN1 STARTS WITH _.
JRST MSGSNF
MOVE D,UNRNDM(A)
TLNE D,UNLINK\UNIGFL
JRST MSGSNF ;IGNORE LINKS AND INACCESSABLE FILES.
MOVE C,UNDATE(A)
CAMG C,MSGDAT
JRST MSGSNF ;IF PRINTED MESSAGES SINCE WAS CREATED, SKIP.
;DROPS THROUGH
;THE FILE WE'RE LOOKING AT IS RECENT ENOUGH; PUT IT IN USER'S MAIL FILE.
.OPEN INC,MSGF3
JRST MSGSNF
CALL INCO1
call sdist
jrst [ .access inc,[0]
call inco1
jrst msgsd1 ]
MSGSD3: MOVE B,[404040,,404040]
MOVE C,[440600,,B] ;READ IN 1 SIXBIT WORD FROM THE FILE.
MSGSD5: CALL INCI
CAIL D,140
SUBI D,40
CAIE D,",
CAIG D,40
JRST MSGSD4
TLNE C,770000
IDPB D,C
JRST MSGSD5
MSGSD4: XOR B,[404040,,404040]
JUMPE B,MSGSD6 ;IGNORE NULL WORDS.
MOVE G,P ;NOW COMPARE THE WORD AGAINST THE ARGS ON THE STACK.
POP G,C ;GET THE POINTER TO BENEATH THE ARGS, FOR END TEST
MSGSD7: CAMN B,(G) ;POP 1 ARG AND COMPARE
JRST MSGSDW ;MATCH => IGNORE REST OF DISTRIB: LINE, AND PRINT MESSAGE
POP G,H
CAMN H,[SIXBIT/*/]
JRST MSGSDW ;KEYWORD * MATCHES ANYTHING
CAME G,C
JRST MSGSD7
MSGSD6: CAIL D,40 ;THIS WORD LOSES. IF NOT AT END OF LINE, READ ANOTHER.
JRST MSGSD3
;THE WHOLE DISTRIB: LOSES - DON'T PRINT THIS FILE.
CALL MSGEXP ;EVEN THOUGH WE WON'T PRINT IT, DELETE IT IF OLD ENOUGH.
JFCL
JRST MSGSNF
;COME HERE IF THE FILE'S DISTRIB: SAYS WE SHOULD PRINT IT.
MSGSDW: CALL MSGEXP ;DON'T PRINT, AND MAYBE EVEN DELETE FILE, IF EXPIRED.
JRST MSGSNF
CALL MSGIL ;NOT EXPIRED; SKIP PAST THE "EXPIRES:" LINE.
JRST MSGSNF ;NOTHING ELSE LEFT?
JRST MSGSD1 ;PRINT THE FILE.
;TEST FILE ON INC FOR HAVING EXPIRED. SKIP IF IT HASN'T.
;IF IT HAS EXPIRED AND HAS BEEN BACKED UP ON TAPE, DELETE IT.
MSGEXP: CALL MSGIL ;SKIP THE REST OF THE "DISTRIB:" LINE.
JRST MSGEXD ;NO MORE IN FILE => SAY IT LOSES.
MOVEI G,40
CALL MSGI1 ;SKIP PAST "EXPIRES: ".
JRST MSGEXD ;NO SPACE FINDABLE?
MOVE G,[CALL INCI]
CALL RDATE ;READ THE EXPIRATION DATE.
CAML C,MSGTDT ;EXPIRED BEFORE NOW?
JRST POPJ1 ;NO, FILE SHOULD BE PRINTED.
MSGEXD: SYSCAL RDMPBT,[MOVEI INC ? MOVEM C]
RET
JUMPE C,CPOPJ ;EXPIRED BUT NOT DUMPED => DON'T PRINT.
; SYSCAL DELETE,[MSGF3 ? MSGF3+1 ? MSGF3+2]
JFCL
RET ;ALREADY ON BACKUP TAPE => DELETE IT TOO.
;IGNORE ONE LINE FROM THE FILE ON INC.
MSGIL: MOVEI G,^J
MSGI1: CALL INCI ;IGNORE UP TO THE CHAR IN G.
CAIE D,^L
CAIN D,^C
RET
CAIE D,(G)
JRST MSGI1
POPJ1: AOS (P)
RET
; CALL SDIST
; Search for "DISTRIB: " field in message from INC, possibly skipping
; unfortunate "Recieved:" fields. Skip if found.
sdst3: caie d,^C ; File ran out?
cain d,^L
popj p,
sdst2: call inci ; Search for start of new line
caie d,^J
jrst sdst3
sdist: call inci
caie d,"R ; Perhaps "Recieved:"
cain d,"r ; "recieved:" also possible I guess...
jrst sdst2 ; OK before the "DISTRIB: "
caie d,"D ; Either "DISTRIB: " line, or unknown
popj p,
sdst4: ;; See that rest of line is "ISTRIB: ", if not, give up.
irp ch,,["I,"S,"T,"R,"I,"B,72,40]
call inci
caie d,ch
popj p,
termin
aos (p)
popj p,
;READ AHEAD INTO INCTB FROM THE FILLE OPEN ON INC.
INCO1: SAVE D
INCPP: MOVE D,[440700,,INCTB]
MOVEM D,INCIP
MOVE D,[-INCL,,INCTB]
.IOT INC,D
HRRM D,INCEP
MOVEI D,^C ;STORE ^C AFTER LAST WD READ.
DPB D,INCEP
POPDJ: REST D
RET
;READ 1 CHAR FROM BLOCK-MODE INC.
INCI: MOVE D,INCIP ;UNLESS PTR IS AT END OF BUFFER,
CAMN D,[010700,,INCTB+INCL-1]
CALL INCO1
ILDB D,INCIP
POPJ P,
INCL==100
INCTB: BLOCK INCL ;BUFFER FOR I/O USING INCI.
ASCIC//
INCEP: 350700,,
INCIP: 0
;READ A DATE USING READ-CHAR INSTRICTION IN G. DATE RETURNED IN C.
;CHAR THAT TERMINATED THE DATE IS LEFT IN D.
RDATE: SETZ D,
SAVE D
CALL MSGNUM ;CREATION MONTH.
DPB C,[270400,,(P)]
CALL MSGNUM ;CREATION DAY.
DPB C,[220500,,(P)]
CAIE D,^M ;IF USER ISN'T SPEC'ING THE YEAR,
JRST RDATE1
MOVE C,MSGTDT
LDB C,[330700,,C] ;USE TODAY'S YEAR.
JRST RDATE2
RDATE1: CALL MSGNUM ;CREATION YEAR.
RDATE2: DPB C,[330700,,(P)]
CALL MSGNUM ;HOUR.
IMULI C,3600.
ADDM C,(P)
CALL MSGNUM ;MINUTE.
IMULI C,60.
ADDM C,(P)
CALL MSGNUM ;SECOND
ADD C,(P)
ADDI C,(C) ;DOUBLE THE R.H.
POP1J: SUB P,[1,,1]
RET
;READ IN A DECIMAL NUMBER, STOPPING AT A NON-DIGIT.
;USE THE INSTRUCTION IN G TO READ 1 CHARACTER.
MSGNUM: SETZ C,
CAIN D,^M ;DON'T GO ON PAST CR.
RET
MSGNU1: XCT G
CAIL D,"0
CAILE D,"9 ;TERMINATE ON NON-DIGIT.
RET
IMULI C,10.
ADDI C,-"0(D)
JRST MSGNU1
;A FILE'S DISTRIB LOOKS GOOD, AND IT HASN'T EXPIRED, SO PRINT IT.
MSGSD1: HRRZ B,BUFMID ;FIRST, MAKE SURE THERE'S SPACE FOR THE NAME OF THE FILE.
ADDI B,4
CAML B,BUFTOP
CALL MORCOR
HRRZ B,BUFMID
SOS B
PUSH B,[ASCII/MSG: /]
HRLI B,010700 ;THEN, PUT IN THE NAME OF THE FILE.
MOVE C,MSGF3+1
CALL SIXOUT
MOVEI C,40
IDPB C,B
MOVE C,MSGF3+2
CALL SIXOUT ;WE HAVE USED 5+6+1+6 = 17 CHARS SO FAR.
MOVE C,[^M^J*2] ;FILL UP 4TH WORD WITH A CRLF.
IORM C,(B)
SKIPN SHODIST ;IF USER SPECIFIED /D,
JRST MSGHID
HRRZM B,BUFMID
AOS BUFMID
.OPEN INC,MSGF3
JRST MSGRND
CALL LODFIL ;READ IN WHOLE FILE, SHOWING DISTRIB.
JRST MSGRND
MSGHID: MOVE C,B ;IF HE DIDN'T SPECIFY, READ IN FILE BUT
HRLI C,010700 ;DISCARD THE DISTRIB: AND EXPIRES:.
MSGRLP: HRRZM C,BUFMID ;SINCE THEY MIGHT NOT BE MULTIPLE OF 5 CHARS
AOS BUFMID ;WE MUST TRANSFER A CHARACTER AT A TIME.
MOVEI B,2(C)
CAML B,BUFTOP
CALL MORCOR
MOVE B,[ASCIC//]
MOVEM B,1(C)
CALL INCI
CAIN D,^C
JRST MSGRND
IDPB D,C
JRST MSGRLP
MSGRND: .CLOSE INC,
CALL ENDFIL
MOVEM D,LSTEPT
SETZM MSGLDT ;INDICATE AT LEAST ONE MESSAGE HAS BEEN FOUND.
JRST MSGSNF ;SEE IF THERE ARE MORE OF THEM.
MSGF2: 6,,SIXBIT/ DSK.FILE.(DIR)/
;COME HERE AFTER HANDLING ALL THE MSGS THAT ARE TO BE HANDLED.
;WRITE THEM OUT IF THERE ARE ANY.
MSGSX: move g,p
skipe spcdst
call arc ;process any mailing list files.
caia
hrrzm p,msgldt
SKIPE SYSMLF ;/Z ?
PUSHJ P,GSYSML
SKIPGE MSGLDT ;Did we find anything? either an announcement or a mailing list?
JRST MSGSX5
SKIPE TTYF ;If so, output the data as appropriate.
JRST [ SYSCAL OPEN,[ [3,,OUTC] ? [SIXBIT/TTY/]]
.LOSE %LSFIL
CALL WRITE1 ;OUTPUT THE BUFFERFULL OF MESSAGES TO THE TTY.
JRST WRITE2]
SKIPE MAILF ;MAYBE PASS THE MESSAGES TO THE COMSAT.
JRST WRMAIL
SKIPN REVERS ;IN NORMAL ORDER, LOAD OLD MAIL FILE AFTER MESSAGES
CALL LODOLD
;ALL THE NEW CONTENTS OF <USER> <MACHINE>MAIL ARE NOW IN THE BUFFER.
WRITE: SYSCAL OPEN,[ [3,,OUTC] ? [sixbit /DSK/] ? ['_GMSGS] ? ['OUTPUT] ? hsname]
JSR OPNERR
CALL WRITE1 ;OUTPUT THE BUFFERFULL OF MESSAGES
;TRANSLATE NORMAL NAMES TO FIND OUT WHAT TO RENMWO TO.
SYSCAL TRANS,[%CLBIT,,.UAO ? [sixbit /DSK/] ? USER ? MALNAM ? HSNAME
%CLOUT,,A ? %CLOUT,,A ? %CLOUT,,B]
.LOSE %LSSYS
SYSCAL RENMWO,[1000,,OUTC ? A ? B]
.LOSE %LSFIL
WRITE2: .CLOSE OUTC,
SKIPE NOTIFF ;IF /N, READ TIME ONCE AGAIN, SO MSGS WILL BE LATER
SYSCAL RQDATE,[MOVEM MSGTDT] ;THAN THE MAIL FILE WE JUST WROTE.
JFCL
;NOW UPDATE THE USER'S DATE-FILE.
MSGSX5: move a,msgloc ;Set the date for this user in the database
syscal RQDATE,[%clout,,msgs"me$mdt(a)] ;to the current date
.lose %lssys
call msgs"unmap ;All done with the :MSGS database
jfcl ; Can't happen, always skips
MSGSX3: SKIPGE MSGLDT
JRST NOMSGS
;NOW INFORM USER THAT THERE WERE MESSAGES.
MOVEI A,[ASCIZ/
(There are messages)
/]
SKIPN SILNT
CALL TELL
DPAUSE
SKIPN CHAOS
.BREAK 16,340000
CHDUN: .CALL [SETZ ? 'FINISH ? SETZI CHSO ]
.LOGOUT 1, ;.LOSE %LSSYS - temporary fix by cstacy
MOVSI A,%COEOF_10.
MOVEM A,PKTBUF
.CALL [SETZ ? 'PKTIOT ? MOVEI CHSO ? SETZI PKTBUF]
.LOSE %LSSYS
.CALL [SETZ ? 'FINISH ? SETZI CHSO ]
.LOSE %LSSYS
.LOGOUT 1,
;JSR HERE IF ERROR OPENING FILE
OPNERR: 0
SKIPN CHAOS
JRST OPNER1
.OPEN ERRC,[.UAI,,'ERR ? 1]
.LOSE %LSFIL
MOVEI A,[ASCIZ/FILE SYSTEM ERROR: /]
PUSHJ P,TELL
OPNER0: .IOT ERRC,A
CAIGE A,40
JRST CHDUN ;File names could be nice--hard to get, though
.IOT TYOC,A
JRST OPNER0
OPNER1: SOS OPNERR
SOS OPNERR
.CALL [SETZ ? SIXBIT/LOSE/ ? MOVEI %LSFIL ? SETZ OPNERR]
.LOSE %LSSYS
TELL: HRLI A,440700
TELL1: ILDB B,A
JUMPE B,CPOPJ
SKIPN CHAOS
JRST TELL2
CAIN B,^M
TROA B,200 ;LISP MACHINE CHARACTER SET
CAIE B,^J
TELL2: .IOT TYOC,B
JRST TELL1
NOMSGS: DPAUSE ;COME HERE IF THERE ARE NO MESSAGES.
SKIPN CHAOS
.BREAK 16,140000
JRST CHDUN
THRSML: CALL LODOLO ;IS THERE AN OLD MAIL FILE?
CAIA
RET ;NO.
SYSCAL RFDATE,[MOVEI INC ? MOVEM A]
RET
CAMG A,MSGDAT ;IS IT MORE RECENT THAN PREVIOUS GMSGS?
RET
MOVEI A,[ASCIZ /
(There is mail)
/]
JRST TELL
WRITE1: MOVEI A,BUFBOT ; A: origin of stuff to output
WRITE9: MOVE B,BUFMID
SUBM A,B ; B: -<amount to output>
JUMPE B,CPOPJ ; None => Done
HRLI A,(B) ; A: AOBJN
TLO A,700000 ; Round AOBJN down to safe negative range
.IOT OUTC,A ; A: new origin
JRST WRITE9 ; Go try to output more
; This old code zeros your mail file if it gets longer than 128K!
; MOVN B,BUFMID
; ADDI B,BUFBOT ;-<# WORDS READ INTO BUFFER>
; HRLZS B
; HRRI B,BUFBOT ;AOBJN PTR TO FILLED PART OF BUFFER.
; .IOT OUTC,B
; RET
WRMAIL: MOVE D,LSTEPT ;COME HERE TO MAIL THE MESSAGES.
MOVEI A,40
DPB A,D ;FLUSH THE ^_ AT THE END OF THE LAST MESSAGE.
MOVE D,[440700,,MAILBF]
SETZ C, ;C COUNTS CHARS PUT IN STRING.
MOVEI A,[ASCIZ/FROM:QR"/]
CALL WRMLAS
MOVE A,USER
CALL WRMLSX
MOVEI A,[ASCIZ/
TO:"/]
CALL WRMLAS
SKIPN A,NAMBBP ;NAME SPECIFIED ON JCL?
JRST WRMAI3
MOVEI G,0 ;TERMINATE WITH A 0
DPB G,NAMEBP
CALL WRMLA1
JRST WRMAI4
WRMAI3: MOVE A,USER
CALL WRMLSX
WRMAI4: MOVEI A,[ASCIZ/
TEXT;-1/]
CALL WRMLAS
MOVEI A,40 ;PAD UNTIL EXACTLY 2 CHARS LEFT IN WORD
WRMAI2: HLRZ C,D
CAIN C,170700
JRST WRMAI1
IDPB A,D
JRST WRMAI2
WRMAI1: MOVEI A,[ASCIZ/
/]
CALL WRMLAS ;THEN PUT A CRLF IN THOSE 2.
SYSCAL OPEN,[[3,,OUTC] ? ['DSK,,] ? ['_GMSGS] ? ['OUTPUT] ? ['.MAIL.]]
JSR OPNERR
MOVNI D,1-MAILBF(D)
MOVSS D
HRRI D,MAILBF
.IOT OUTC,D
CALL WRITE1
SYSCAL RENMWO,[ MOVEI OUTC ? [SIXBIT/MAIL/] ? [SIXBIT/>/]]
.LOSE %LSFIL
JRST WRITE2
;OUTPUT ASCIZ STRING <- A THROUGH BP IN D.
WRMLAS: HRLI A,440700
WRMLA1: ILDB B,A
JUMPE B,CPOPJ
IDPB B,D
JRST WRMLA1
;OUTPUT SIXBIT WORD IN A THROUGH BP IN D.
WRMLSX: SETZ B,
ROTC A,6
ADDI B,40
IDPB B,D
JUMPN A,WRMLSX
RET
;Get system messages of the SYS:SYSTEM MAIL type as if they were *MSGS
GSYSML: IRPS FN1,,[SYSTEM LOCAL NET]
MOVE A,[.BAI,,'SYS]
MOVE B,[SIXBIT/FN1/]
MOVE C,[SIXBIT/MAIL/]
.OPEN INC,A
CAIA
PUSHJ P,GSYSM1
TERMIN
.CLOSE INC,
POPJ P,
GSYSM1: HRLZM A,SYMINF
MOVEM B,SYMINF+1
MOVEM C,SYMINF+2
.CALL [SETZ ? 'RFDATE ? MOVEI INC ? SETZM C]
.LOSE %LSSYS
CAMG C,MSGDAT
POPJ P, ;Old message
;Create a bogus header, author@machine date Re: filename
MOVEM C,SYMINF+3
.CALL [SETZ ? SIXBIT/RAUTH/ ? MOVEI INC ? SETZM SYMINF+4]
.LOSE %LSSYS
HRRZ B,BUFMID ;First, make sure there's space
ADDI B,30
CAML B,BUFTOP
CALL MORCOR
HRRZ B,BUFMID ;B byte pointer to message output
HRLI B,440700
MOVE D,SYMINF+4
CALL SIXTYP
MOVEI D,[ASCIZ/@MIT-/]
CALL ASZTYP
.CALL [SETZ ? 'SSTATU ? REPEAT 5,[MOVEM D ? ] SETZM D]
.LOSE %LSSYS
CALL SIXTYP
MOVEI D,40
IDPB D,B
MOVEI A,"/
LDB D,[270400,,SYMINF+3] ;MONTH
CALL 2DTYP
IDPB A,B
LDB D,[220500,,SYMINF+3] ;DAY
CALL 2DTYP
IDPB A,B
LDB D,[330700,,SYMINF+3] ;YEAR
CALL 2DTYP
MOVEI A,40
IDPB A,B
MOVEI A,":
HRRZ D,SYMINF+3
LSH D,-1 ;TIME IN SECONDS
IDIVI D,3600.
PUSH P,E
CALL 2DTYP ;HOURS
IDPB A,B
POP P,D
IDIVI D,60.
PUSH P,E
CALL 2DTYP ;MINUTES
IDPB A,B
POP P,D
CALL 2DTYP ;SECONDS
MOVEI D,[ASCIZ/ Re: [This is the file /]
CALL ASZTYP
MOVE D,SYMINF
CALL SIXTYP
MOVEI D,[ASCIZ/: /]
CALL ASZTYP
MOVE D,SYMINF+1
CALL SIXTYP
MOVEI A,40
IDPB A,B
MOVE D,SYMINF+2
CALL SIXTYP
MOVEI A,"]
IDPB A,B
;4 more characters to go, but must get to word boundary for LODFIL
;Output spaces as needed
GSYSM2: HLRZ A,B
CAIN A,350700
JRST GSYSM3
MOVEI A,40
IDPB A,B
JRST GSYSM2
GSYSM3: MOVEI D,[ASCIZ/
/]
CALL ASZTYP
AOS B
HRRZM B,BUFMID
;Gasp. Header all done, output text of file.
CALL LODFIL
.CLOSE INC,
CALL ENDFIL
MOVEM D,LSTEPT
SETZM MSGLDT ;INDICATE AT LEAST ONE MESSAGE HAS BEEN FOUND.
RET
SWPS==LUNBLK
;SORT THE .MSGS. DIRECTORY
;A POINTS TO FIRST ENTRY
;B POINTS TO LAST ENTRY + 1
;C HAS ONE BIT SET, THAT BIT MOST SIGNIFICANT BIT TO SORT ON
;IN PRACTICE, C WILL HOLD 4000,, .
SORT: HRLM B,(P) ;SAVE UPPER BOUND
CAIL A,-SWPS(B)
JRST SORT7 ;ONE OR ZERO ENTRIES
PUSH P,A ;SAVE LOWER BOUND
SORT3: TDNE C,UNDATE(A) ;BIT SET IN LOWER ENTRY?
JRST SORT4 ;NO, INCREMENT TO NEXT AND MAYBE TRY AGAIN
SUBI B,SWPS ;YES, NOW BACK UP UPPER POINT
TDNN C,UNDATE(B) ;BIT CLEAR IN UPPER ENTRY?
JRST SORT5 ;NO, CHECK FOR END, DECREMENT B, AND TRY AGAIN
REPEAT SWPS,[ ;BIT SET IN LOWER ENTRY AND CLEAR IN UPPER => EXCHANGE ENTRIES
MOVE D,.RPCNT(A)
EXCH D,.RPCNT(B)
MOVEM D,.RPCNT(A)
]
SORT4: ADDI A,SWPS ;INCREMENT LOWER BOUND POINTER TO NEXT ENTRY
SORT5: CAME A,B ;ANY MORE ENTRIES LEFT?
JRST SORT3 ;YES, GO PROCESS THEM
;A AND B NOW BOTH POINT TO FIRST ENTRY WITH BIT SET
ROT C,-1 ;ROTATE BIT INDICATOR TO NEXT (LESS SIGNIFICANT) BIT
POP P,A ;RESTORE LOWER BOUND OF ENTIRE SORT
JUMPL C,SORT6 ;JUMP IF NO MORE KEY TO SORT ON
PUSHJ P,SORT ;SORT BOTTOM PART OF TABLE
HLRZ B,(P) ;RESTORE UPPER BOUND (SORT CLOBBERED A TO MIDDLE)
PUSHJ P,SORT ;SORT TOP PART OF TABLE
SORT6: ROT C,1 ;BACK UP KEY AGAIN SO AS TOO "NOT CLOBBER C"
SORT7: HLRZ A,(P) ;MAKE A POINT ABOVE TABLE ENTRIES SORTED
POPJ P,
; Grab the lock for the inbox we will be hacking.
lock: push p,a
push p,b
move a,user ; FN1
rot a,1
add a,malnam ; FN2
rot a,1
add a,hsname ; DIR
idivi a,777773 ; Largest prime < 1,,0
hrli b,(sixbit /MBX/)
skipe locknm
jrst lock2
movem b,locknm
;; Open LOCK:MBXxxx in hang mode:
lock1: syscal open,[moves a ? movsi 10\.uao ? movei lockc
[sixbit /LOCK/] ? move locknm]
cain a,%ensdv ; No LOCK device in this ITS?
jrst lock3 ; Then pretend we won anyway (we're no
; worse off than we used to be!)
syscal lose,[movei %lssys(a) ? movei lock1]
.lose %lssys
lock2: came b,locknm ; Already holding a lock, better be this
.lose ; one!
lock3: pop p,b
pop p,a
popj p,
ifn 0,[ ;; (Nothing needs to do this now, we just hold the lock until the
;; job is killed.)
; Unlock any lock being held.
unlock: skipn locknm ; If not holding a lock, caller may be
.lose ; badly confused!
setzm locknm
.close lockc,
popj p,
] ; ifn 0
;TRY TO LOAD THE OLD MAIL FILE, IF THERE IS ONE.
LODOLD: CALL LODOLO
CALL LODFIL
RET
;OPEN THE OLD MAIL FILE, DETERMINE WHICH DEVICE TO WRITE NEW ONE ON.
;SKIP IF THERE IS NO OLD MAIL FILE.
LODOLO: call lock ; Start by locking this inbox
lodol3: syscal OPEN,[ %clbit,,.bai ? %climm,,inc ? [sixbit /DSK/]
user ? MALNAM ? hsname ? %clerr,,b]
caia
ret
cain b,%ensfl
jrst popj1 ;There's no old file. Write the new one on DSK.
syscal lose,[movei %lsfil ? movei lodol3] ;Lose if file locked.
.lose %lssys
;READ INTO THE BUFFER THE FILE OPEN ON INC. ALL FILES READ INTO THE
;BUFFER GET READ IN AT BUFMID, AND BUFMID IS ADVANCED TO POINT AFTER
;THE FILE READ IN.
LODFIL: MOVN B,BUFTOP
ADD B,BUFMID ;-<AMOUNT OF MEMORY SPACE AVAIL ABOVE FILLED PART OF BUFFER>
HRLZS B
HRR B,BUFMID ;<AOBJN PTR TO UNFILLED PART OF BUFFER>
.IOT INC,B
HRRZM B,BUFMID ;UPDATE BUFMID, SINCE WE JUST FILLED MORE OF THE BUFFER.
JUMPL B,CPOPJ ;IF WE REACHED EOF, WE'RE FINISHED.
CALL MORCOR
JRST LODFIL ;READ IN MORE OF THE FILE.
;GET 1 MORE K OF CORE.
MORCOR: MOVE B,BUFTOP ;OTHERWISE WE FILLED UP THE BUFFER, SO GET MORE MEMORY.
LSH B,-12
.CORE 1(B) ;GET 1 MORE K OF CORE.
JRST [MOVEI C,30. ? .SLEEP C, ? JRST .-1]
MOVEI B,2000 ;BE AWARE WE NOW HAVE 1K MORE SPACE.
ADDM B,BUFTOP
RET
;AFTER LOADING A FILE, SET UP TO CONCATENATE ANOTHER FILE TO IT.
;LEAVE IN D A B.P. TO THE ^_ WHICH IS PUT AT THE END OF THE FILE,
;IN CASE CALLER DESIRES TO REPLACE IT WITH A SPACE.
ENDFIL: MOVE B,BUFMID ;NOW STRIP OFF TRAILING ^C'S AND ^L'S
HRLI B,350700 ;B.P. TO CHAR AFTER THE LAST CHAR READ IN.
UNPAD: DBP7 B
LDB C,B
CAIE C,^C ;GO BACKWARDS TILL REACH THE FIRST NON-^C NON-^L.
CAIN C,^L
JRST UNPAD
JUMPE C,UNPAD ;^@ ALSO COUNTS AS PADDING.
PUSH P,B
JRST UNPAD2
UNPAD1: DBP7 B ;THEN PEEK BACK AT THE END OF THE LAST LINE
UNPAD2: LDB D,B
CAIE D,^M
CAIN D,^J
JRST UNPAD1
CAIN D,40
JRST UNPAD1
POP P,B
MOVEI C,^_ ;UNLESS LAST LINE ENDS IN A ^_, INSERT ONE.
CAIN D,^_ ;IF ALREADY A ^_, USE A SPACE INSTEAD.
MOVEI C,40 ;REPLACE THE FIRST ^C OR ^L WITH IT.
IDPB C,B
MOVE D,B
PAD: TLNN B,760000 ;THEN FILL SPACE IN WORD, AFTER THAT CHAR, WITH BLANKS.
AOJA B,ENDFI1
MOVEI C,40
IDPB C,B
JRST PAD
ENDFI1: HRRZM B,BUFMID ;NOW PUT CRLF AFTER THE MESSAGE,
ADDI B,1 ;FIRST MAKING SURE THERE'S ROOM IN CORE.
CAML B,BUFTOP
CALL MORCOR
MOVE B,[.BYTE 7 ? 40 ? 40 ? 40 ? ^M ? ^J]
MOVEM B,@BUFMID
AOS BUFMID
RET
;C HAS A SIXBIT WORD; TYPE IT IN ASCII ONTO THE B.P. IN B,
;ALWAYS USING 6 CHARACTERS.
SIXOUT: MOVEI E,6
SIXOU1: ROTC C,6
ANDI D,77
ADDI D,40
IDPB D,B
SOJG E,SIXOU1
RET
;SIMILAR BUT FLUSHES TRAILING SPACES. OUTPUTS FROM D.
SIXTYP: SETZ C,
LSHC C,6
ADDI C,40
IDPB C,B
JUMPN D,SIXTYP
RET
ASZTYP: HRLI D,440700
ASZTY1: ILDB C,D
JUMPE C,CPOPJ
IDPB C,B
JRST ASZTY1
2DTYP: IDIV D,100.
MOVE D,E
IDIVI D,10.
ADDI D,"0
ADDI E,"0
IDPB D,B
IDPB E,B
RET
;The * names which specify topics also specify mailing list archive files to look at.
;These are actually links on .MSGS. which point to the real files.
;If the user specifies *FOO, look for a file .MSGS.;_FOO >.
;G points to the word in the stack which follows the list of names
;and contains a pointer to the first of the names.
;If an archive file is updated since we last looked,
;then a notification message is put in the user's mail file.
;We skip if there was any new archive file.
arc: pop g,a
setz b, ;B gets -1 if we find anything.
arc1: save a
save g
save b
move c,1(a) ;Take name and replace "*" with "_".
tlz c,770000
tlo c,<'_>_12.
syscal open,[%climm,,inc ? %clbit,,.bai ? ['dsk,,] ? c ? [sixbit />/] ? ['.MSGS.]]
jrst arc2 ;ignore any files that don't exist.
syscal rfdate,[%climm,,inc ? %clout,,c]
.lose %lsfil
camg c,msgdat ;is this file more recent than our last look?
jrst arc2
move c,buftop
sub c,bufmid
caige c,100 ;Make sure we have at least 100 words of memory,
call morcor ;which will be more than enough.
move c,bufmid
move d,bufmid
hrli d,arcmsg ;copy our phony message into the output.
blt d,arcmsl-1(c)
movei d,arcfil(c)
hrli d,440700
syscal rfname,[%climm,,inc ? %clout,,arcdev
%clout,,arcf1 ? %clout,, arcf2 ? %clout,,arcsnm]
.lose %lsfil
movei b,arcdev ;Get file's names and output into phony message.
call rfn"pfn
movei b,40 ;Replace zero terminator with a space.
idpb b,d
movei c,arcmsl(c)
movem c,bufmid
hrli c,170700
sos c
movem c,lstept ;Save pointer to the ^_ ending the phony message.
.close inc,
setom (p)
arc2: rest b
rest g
rest a
add a,[1,,1] ;After all files, return
came a,g
jrst arc1
skipe b ;skipping if the flag was set.
aos (p)
popj p,
arcdev: 0 ;These words get the real file names of the
arcf1: 0 ;file which has new material in it.
arcf2: 0
arcsnm: 0
arcmsg: ascii /There is new material in the file / ;35 characters
arcfil==.-arcmsg
ascii / / ;25 chars. Space for filename.
ascii /

/
arcmsl==.-arcmsg
rfn"$$pfn==1
rfn"psixtp: popj p,
.insrt syseng;rfn
;READ A SIXBIT NAME FROM THE COMMAND STRING INTO A.
;PROCESS ANY SWITCHES THAT MAY OCCUR - THEY TERMINATE THE NAME.
;IF WE FIND A WORD THAT DOESN'T START WITH *,
;WE LEAVE A BP TO ILDB THE FIRST CHARACTER IN NAMBBP AND A BP TO THE TERMINATOR IN NAMEBP.
RDSIX: SETZ A,
SETZ H,
SETZ C,
MOVE B,[440600,,A]
MOVE G,CMDBP
RDSIX1: MOVE C,G
ILDB I,G
CAIE I,", ;COMMA, SPACE AND CONTROL CHARS END A NAME.
CAIG I,40
JRST RDSIX2
CAIN I,"/ ;SLASH BEGINS A SWITCH
JRST RDSWIT
SKIPN H ;REMEMBER BP TO CHAR BEFORE START OF NON-NULL TEXT OF THIS WORD.
MOVE H,C
CAIL I,140 ;CONVERT LOWER CASE TO UPPER.
SUBI I,40
SUBI I,40 ;CONVERT TO SIXBIT
TLNE B,770000 ;IGNORE LETTERS AFTER THE 6TH.
IDPB I,B
JRST RDSIX1
RDSIX2: MOVEM G,CMDBP ;MARK WHAT WE HAVE JUST READ AS DONE WITH.
JUMPE H,CPOPJ ;IF WE FOUND A NON-NULL WORD,
MOVE B,H
ILDB B,B ;AND IT DIDN'T START WITH "*",
CAIN B,"*
POPJ P,
MOVEM H,NAMBBP ;REMEMBER POINTERS TO START AND END AS THE ASCII FOR
MOVEM G,NAMEBP ;THE SPECIFIED USER'S NAME.
CPOPJ: RET
RDSWIT: MOVEM C,CMDBP ;IF WE ALREADY HAVE A NON-NULL NAME, THE SWITCH TERMINATES IT,
JUMPN A,CPOPJ ;SO RETURN. NEXT CALL TO RDSIX WILL HANDLE THE SWITCH.
ILDB I,G ;HANDLE A SWITCH
CAIE I,^C
CAIN I,^M ;MUSTN'T FAIL TO NOTICE END OF COMMAND STRING
JRST RDSIX2 ;EVEN IF IT'S IN A SWITCH.
CAIL I,140
SUBI I,40
CAIN I,"D
SETOM SHODIS ;/D => SHOW DISTRIB: AND EXPIRES: FIELDS.
CAIN I,"R
SETOM REVERS ;/R => REVERSE ORDER (MESSAGES GO AT END)
CAIN I,"S
SETOM SILNT ;/S => DON'T TYPE ANYTHING OUT.
CAIN I,"M
SETOM MAILF ;/M => MAIL THE MESSAGES THROUGH THE COMSAT INSTEAD OF DIRECTLY.
CAIN I,"G ;/G => USE GMSGS FILE INSTEAD OF CLOBBERING MAIL FILE
SETOM GMSGSF
;;UNCOMMENT THE NEXT BIT WHEN BABYL UNDERSTANDS GMSGS FILES
; SKIPN MAILF
; SKIPE GMSGSF
; CAIA
; SYSCAL OPEN,[%CLIMM,,INC ? [SIXBIT /DSK/] ? XUNAME
; [SIXBIT /BABYL/] ? HSNAME]
; CAIA
; SETOM GMSGSF
CAIN I,"N
SETOM NOTIFF ;/N => IF MAIL FILE IS MORE RECENT THAN MSGS, NOTIFY USER.
CAIN I,"T
SETOM TTYF ;/T => PRINT MSGS ON TTY INSTEAD.
CAIN I,"Z ;/Z => SHOW SYS:SYSTEM MAIL AND THE LIKE (MAINLY FOR ZMAIL)
SETOM SYSMLF
JRST RDSIX1
;DELETES ALL EXPIRED MESSAGES FROM .MSGS.;
;A MESSAGE EXPIRES AT THE TIME IT SAYS IT DOES IN THE "EXPIRES:"
;FIELD, OR 30 DAYS AFTER IT WAS WRITTEN.
;THE DATE AND TIME EXPIRE WAS LAST RUN IS RECORDED BY
;THE DATE OF THE FILE .MSGS.;_LAST_ EXPIRE
;UNLESS THERE IS A JCL COMMAND STRING "OVERRIDE<CR>",
;IF IT IS MORE THAN 3 DAYS SINCE THE DATE AND TIME
;REMEMBERED BY THAT FILE, NOTHING WILL BE DELETED
;AND A COMPLAINT WILL BE MAILED TO BUG-EXPIRE.
DIRBFL==2000 ;LENGTH OF BUFFER FOR READING .MSGS.; U.F.D.
; First see if today's date is reasonable. If the date known by the
; system is wrong, we could massacre .MSGS.; completely. We defend
; against that by storing the date of the last EXPIRE doneas the
; creation date of .MSGS.;_LAST_ EXPIRE. If the current date is less
; than a day since then, we just don't bother to do anything (why waste
; time reaping too often?). If the current date is more than 3 days
; since then, we assume that something very strange is going on. In
; that case, we send a message to BUG-EXPIRE reporting what happened,
; and rename .MSGS.;_LAST_ EXPIRE to .MSGS.;_LAST_ EXPIR?, which has the
; effect of preventing any more messages from being sent to BUG-EXPIRE
; redundantly, without losing the information of when the last EXPIRE
; was done. This condition must be fixed manually by a human, by
; creating a new _LAST_ EXPIRE file. A day later, a reap will be done.
; Since dates are kept as days since start of century, there is a
; problem with wraparound at the start of a century, which is checked
; for specially.
EXPIRE: MOVE A,MSGTDT
CALL QTONUM ;GET DAY AND YEAR AS NUMBER IN B
MOVE E,B
SYSCAL OPEN,[[.UAI,,INC] ? ['DSK,,] ? [SIXBIT /_LAST_/] ? ['EXPIRE] ? ['.MSGS.]]
POPJ P,
SYSCAL RFDATE,[MOVEI INC ? MOVEM A]
POPJ P,
.CLOSE INC,
CALL QTONUM ;Compare with date of last running of EXPIRE.
CAIGE E,3 ;If today's date just wrapped around, special action needed.
JRST [ SUB B,E
JUMPL B,DATEOK
JUMPE B,CPOPJ
CAIL B,MAXDAT-3 ;See if date of prev. run is close enough to wrapping.
JRST DATEOK
JRST DATEBD]
CAMLE B,E
JRST DATELS ;Previous run is in the future???
CAMN B,E ;Don't bother reaping twice in a day.
POPJ P,
ADDI B,3
CAML B,E ;More than 3 days ago => suspect that hardware forgot the date.
JRST DATEOK
DATEBD: SKIPA A,[-DISTRL,,DISTRS]
DATELS: MOVE A,[-INSANL,,INSANE]
COMPLN: SYSCAL OPEN,[[.BAO,,INC] ? ['DSK,,] ? [SIXBIT /MAIL/] ? [SIXBIT />/] ? ['.MAIL.]]
.LOSE %LSFIL
.IOT INC,A
.CLOSE INC,
SYSCAL DELETE,[['DSK,,] ? [SIXBIT /_LAST_/] ? [SIXBIT /EXPIR?/] ? ['.MSGS.]]
JFCL
SYSCAL RENAME,[['DSK,,] ? [SIXBIT /_LAST_/] ? [SIXBIT /EXPIRE/] ? ['.MSGS.]
[SIXBIT /_LAST_/] ? [SIXBIT /EXPIR?/]]
JFCL
POPJ P,
DISTRS: ASCIC /FROM-JOB:GMSGS
FROM:Q"BUG-GMSGS
TO:"SYS-OPERATING-TROUBLE
SUBJECT:Is I.T.S. mistaken as to today's date?
TEXT;-1
Although GMSGS is supposed to delete expired messages from .MSGS.
automatically every day, it detected that the date of its previous run
was more than three days in the past. This may or may not indicate
that something is still wrong; just in case, GMSGS didn't do anything.
Please make sure that I.T.S. knows the correct date, using
PDSET if necessary, and then create a new file .MSGS.;_LAST_ EXPIRE.
/
DISTRL==.-DISTRS
INSANE: ASCIC /FROM-JOB:GMSGS
FROM:Q"BUG-GMSGS
TO:"BUG-GMSGS
TO:"SYS-OPERATING-TROUBLE
SUBJECT:Is I.T.S. mistaken as to today's date?
TEXT;-1
Although GMSGS is supposed to delete expired messages from .MSGS.
automatically every day, it detected that the date of its previous run
was IN THE FUTURE??? Something must be wrong, so GMSGS didn't do anything.
Please make sure that I.T.S. knows the correct date, using
PDSET if necessary, and then create a new file .MSGS.;_LAST_ EXPIRE.
/
INSANL==.-INSANE
;Come here after deciding that it's actually safe to delete files.
DATEOK: MOVE A,MSGTDT
CALL QTONUM
MOVEM B,TODAY ;COMPUTE # DAYS SINCE START OF CENTURY.
SYSCAL OPEN,[[.BII,,INC] ? ['DSK,,] ? ['.FILE.] ? [SIXBIT /(DIR)/] ? ['.MSGS.]]
JFCL
MOVE A,[-DIRBFL,,VPAGAD]
.IOT INC,A ;READ IN THE .MSGS.; DIRECTORY
.CLOSE INC,
MOVEI I,VPAGAD-LUNBLK
ADD I,VPAGAD+1 ;GET ADDRESS OF 1ST NAME-ENTRY IN DIRECTORY.
EXPIRL: ADDI I,LUNBLK ;LOOK AT NEXT FILE.
CAIN I,VPAGAD+DIRBFL
JRST EXPIRD
SKIPE UNFN1(I)
SKIPN UNFN2(I)
JRST EXPIRL ;IGNORE FILES THAT AREN'T REALLY IN EXISTENCE.
LDB D,[360600,,UNFN1(I)]
CAIN D,'_ ;IGNORE FILE IF FN1 STARTS WITH _.
JRST EXPIRL
MOVE D,UNRNDM(I) ;IGNORE LINKS AND INACCESSIBLE FILES.
TLNE D,UNLINK\UNIGFL
JRST EXPIRL
SYSCAL OPEN,[[10+.BAI,,INC] ? ['DSK,,] ? UNFN1(I) ? UNFN2(I) ? ['.MSGS.]]
JRST EXPIRL ;10 BIT SAYS DON'T CHANGE REF DATE.
CALL INCO1 ;INITIALIZE BUFFERED READING OF FILE WITH INCI.
call sdist ;DOES THE FILE START WITH "DISTRIB: "?
jrst expns ;NO "DISTRIB:" => FILE DOESNT SAY WHEN IT
; EXPIRES SO USE CREATION DATE + 30 DAYS.
CALL MSGIL ;SKIP THE REST OF THE "DISTRIB:" LINE.
JRST EXPIR1 ;NO MORE IN FILE => SAY IT HAS EXPIRED ALREADY.
MOVEI G,40
CALL MSGI1 ;SKIP PAST "EXPIRES: ".
JRST EXPIR1 ;NO SPACE FINDABLE?
MOVE G,[CALL INCI]
CALL RDATE ;READ THE EXPIRATION DATE.
MOVE A,C
CALL QTONUM ;TURN INTO NUMBER OF DAYS.
JRST EXPLCT
EXPNS: MOVE A,UNDATE(I)
CALL QTONUM ;TURN FILE DATE INTO NUMBER
ADDI B,30. ;GET DATE OF 30 DAYS AFTER FILE CREATED.
EXPLCT: CAMGE B,TODAY ;EXPIRED BEFORE NOW?
JRST EXPIR1
MOVE C,TODAY
CAIL B,MAXDAT-100. ;IF EXP. DATE IS JUST BELOW WRAPAROUND, AND TODAY'S
CAIL C,100. ;DATE JUST AFTER IT, FILE HAS EXPIRED.
JRST EXPIRL
EXPIR1: SYSCAL RDMPBT,[MOVEI INC ? MOVEM C]
JRST EXPIRL
JUMPE C,EXPIRL ;EXPIRED BUT NOT ON BACKUP TAPE => DON'T DELETE
SYSCAL DELETE,[['DSK,,] ? UNFN1(I) ? UNFN2(I) ? ['.MSGS.]]
JFCL
JRST EXPIRL
;Here when have deleted all appropriate files on .MSGS.;
EXPIRD: MOVE A,[.UAI,,INC]
.CALL EXPFIL ;Open _LAST_ EXPIRE for reading.
.LOSE %LSFIL ;I know it's there! I saw it.
SYSCAL SFDATE,[MOVEI INC ? MOVE MSGTDT]
.LOSE %LSFIL ;Set its creation date to right now.
POPJ P,
EXPFIL: SETZ ? SIXBIT/OPEN/ ? A
['DSK,,] ? [SIXBIT /_LAST_/] ? ['EXPIRE] ? SETZ ['.MSGS.]
;CONVERT DISK-FORMAT DATE (RQDATE, RFDATE), IN A,
;TO NUMBER OF DAYS SINCE START OF CENTURY (APPROX), IN B.
;APPROXIMATION IGNORES LEAP YEARS, ASSUMING 366 DAYS PER YEAR;
;IT IS MONOTONIC, BUT CAN JUMP BY 1 DAY AT END OF FEB.
;THEREFORE, ADDING A SMALL INTEGER TO
;THE OUTPUT OF QTONUM INTRODUCES AN INACCURACY OF 1 DAY.
QTONUM: SAVE C
LDB B,[330700,,A]
IMULI B,366. ;ADD # DAYS IN COMPLETE PAST YEARS (APPROX)
LDB C,[270400,,A]
ADD B,MONTAB(C) ;ADD EXACT # DAYS IN COMPLETE PAST MONTHS
CAILE C,6 ;FOR CONCISENESS, LENGTH OF JAN THRU MAY ISN'T
ADDI B,31.+29.+31.+30.+31.+30. ;INCLUDED IN TABLE FOR 2ND HALF YEAR.
LDB C,[220500,,A]
ADDI B,-1(C) ;ADD IN # OF DAYS IN THIS MONTH.
REST C
RET
MONTAB: 0 ;EXTRA WORD, SINCE MONTHS NUMBERED STARTING FROM 1.
0 ? 31. ? 31.+29. ? 31.+29.+31. ? 31.+29.+31.+30. ? 31.+29.+31.+30.+31.
0 ? 31. ? 31.+31. ? 31.+31.+30. ? 31.+31.+30.+31. ? 31.+31.+30.+31.+30.
MAXDAT==100.*366. ;VALUE AT WHICH DAY COUNTS WRAP AROUND TO 0, BECAUSE
;THE QDATES THEY ARE COMPUTED FROM DO LIKEWISE.
;WHEN COMPARING TWO DATES, MUST CHECK FOR POSSIBILITY THAT THE LATER ONE
;HAS WRAPPED AROUND, BUT THE EARLIER ONE HAS NOT. IN SUCH A CASE, THE
;LATER DATE IS NEAR ZERO AND THE EARLIER ONE IS JUST BELOW MAXDAT.
TODAY: 0 ;TODAY'S DATE, AS # DAYS FROM START OF CENTURY.
PDL: BLOCK PDLL
CMD: BLOCK CMDL ;DDT'S COMMAND READ INTO THIS BLOCK.
.GLOBAL PAT,PATCH,PATCHE
PAT:
PATCH: BLOCK 40
PATCHE: -1
CMDBP: 0 ;BP FOR READING CMD.
;; The next three words must be in this order.
ITSNAM: 0 ;THE ITS TO MAIL IT TO.
USER: 0 ;NAME OF USER WHOSE MAIL IS BEING SNARFED.
HSNAME: 0 ;DIR TO FIND MAIL-FILE ON.
MALNAM: SIXBIT /MAIL/ ;SECOND FILENAME TO USE (MAIL OR GMSGS) (SEE /G SW)
LOCKNM: 0 ; Name of currently held LOCK: device lock.
REVERS: 0 ;-1 => /R PUT MESSAGES AT END, EARLIEST FIRST.
;NORMALLY MESSAGES GO AT FRONT OF MAIL FILE,
;LATEST FIRST. SET BY "R" SWITCH IN COMMAND LINE.
GMSGSF: 0 ;-1 => /G SWITCH: WRITE GMSGS FILE INSTEAD OF MAIL FILE
MAILF: 0 ;-1 => /M SWITCH: MAIL THE MESSAGES THROUGH THE COMSAT.
TTYF: 0 ;-1 => /T SWITCH: TYPE MESSAGES INSTEAD.
SILNT: 0 ;-1 => /S DON'T TYPE OUT "THERE ARE MESSAGES"
SPCDST: 0 ;-1 => KEYWORDS FOR DISTRIB: WERE SPEC'D IN COMMAND.
NOTIFF: 0 ;-1 => /N SWITCH: NOTIFY USER IF HE HAS NON-GMSGS
;NEW MAIL (ARRIVED SINCE LAST GMSGS).
SHODIS: 0 ;-1 => /D SWITCH: SHOW DISTRIB: AND EXPIRES: FIELDS.
SYSMLF: 0 ;-1 => /Z SWITCH: SHOW SYS:SYSTEM MAIL AND THE LIKE
NAMBBP: 0 ;NONZERO => BYTE PTR TO START OF NAME
NAMEBP: 0 ;NONZERO => BYTE PTR TO END OF NAME
DEBUG: 0 ;-1 => DEBUGGING.
;:MSGS STUFF
MSGDAT: 0 ;DATE S.T. EARLIER MSGS AREN'T TYPED.
MSGLDT: 0 ;BEFORE 1ST FILE, -1; ELSE DATE OF LAST FILE STARTED.
MSGTDT: 0 ;TODAY'S DATE AND TIME.
MSGF3: SIXBIT/ "DSK/
0?0
MSGSNM: SIXBIT /.MSGS./ ;F.D. TO LOOK IN
MSGLOC: 0 ;LOCATION OF THIS USER'S ENTRY IN :MSGS TIMES
SYMINF: BLOCK 5 ;INFORMATION ABOUT SYSTEM MAIL BEING PROCESSED
VPAGAD: BLOCK 2000 ;.MSGS.; DIRECTORY READ IN HERE.
LAST: 0 ;ADDRESS OF FIRST THING WE'LL LOOK AT
;THAT IS NOT A FILEBLOCK.
;VPAGAD+2000 IF INCREM > 0,
;<ADDR OF 1ST FILEBLOCK>-LUNBLK IF INCREM < 0.
INCREM: 0 ;INCREMENT FROM ONE FILEBLOCK TO THE NEXT.
;EITHER LUNBLK OR -LUNBLK.
CONSTA
VARIAB
MAILBF: REPEAT 10.,ASCII/ / ;BUFFER FOR HEADER OF FILE TO WRITE ON .MAIL.
LSTEPT: 0 ;POINTER TO ^_ AT END OF LAST MESSAGE SAVED HERE.
BUFMID: BUFBOT ;POINTS INTO BUFFER, AT BEGINNING OF EMPTY PART.
BUFTOP: MEMTOP ;POINTS AT TOP OF EMPTY PART (=TOP OF MEMORY)
msgpag==<.+1777>&-2000/2000
msglen=20
MEMTOP=<msgpag+msglen>*2000
BUFBOT==memtop ;BEGINNING OF BUFFER.
;IN THE BUFFER, THE PART FROM BUFBOT TO @(BUFMID)-1 IS FILLED.
;THE PART FROM @(BUFMID) TO @(BUFTOP)-1 IS EMPTY.
END BEG