;-*-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 ; 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 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: - 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 ;- HRLZS B HRR B,BUFMID ; .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", ;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, ;-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=*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