.TITLE MACRO MAILRRR (Return Receipt Requested) ;======================================================================== ;= = ;= Name : Hunter Goatley = ;= Program : MAILRRR.MAR (MAIL Return Receipt Requested) = ;= Language : VAX-11 MACRO-32 assembler = ;= Purpose : Show whether or not VMS mail has been read by = ;= the receiver = ;= Date : September 4, 1985 = ;= System : VAX 11/785 VAX/VMS v4.1 = ;= Shop : WKU/ACRS = ;= = ;= Suggestion : "Mail Call", Gary C. Kessler, THE DEC = ;= PROFESSIONAL, March 1985, Vol. 4, No. 3, = ;= pp. 45-48 = ;= = ;= Modified by S. Pratty to : = ;= i) correctly locate recipient's name in mail.mai = ;= ii) use the correct-size buffer to read mail.mai = ;= iii) correctly handle mail sent /self = ;= iv) locate user-set mail directory to sys$login = ;= (held in vmsmail.dat) = ;= = ;= Date : September , 1987 = ;= = ;= Reuters Ltd. = ;= 85 Fleet Street = ;= London EC4P 4AJ = ;= England = ;= = ;= 011-44-1-250-1122 = ;= = ;= = ;= Modifications required still : = ;= i) work across decnet - needs to locate '::' string, start = ;= up a remote server, get the answer back ; remote server = ;= needs to work as per normal apart from returning answer = ;= back to caller . = ;= = ;======================================================================== ;= = ;= This VAX-11 MACRO program shows whether or not a VMS mail = ;= message has been read by the receiver of the message. The = ;= VMS MAIL utility provides no means of determining if a = ;= message sent by a user was read by the receiver. = ;= = ;= This version must either be installed with SYSPRV privilege = ;= or executed by users with SYSPRV, since the program accesses = ;= SYSUAF.DAT , VMSMAIL.DAT , and the receiver's MAIL.MAI file. = ;= = ;= The executing user is assumed to be the sender. He/she is = ;= prompted for the name of the receiver. The program checks = ;= the SYSUAF.DAT file to make sure the username entered is = ;= valid; if not, a message is printed to the screen and the = ;= program prompts for a name again. If the user has a SYSUAF = ;= record, its default login device and directory are obtained. = ;= VMSMAIL.DAT is checked for a mail directory or default , = ;= and the program tries to open a MAIL.MAI file there. If the = ;= file is not there or cannot be opened, a message is printed = ;= stating that the receiver has no messages from the sender. = ;= Otherwise, the header for each MAIL message is read from = ;= the MAIL file and the sender field is checked for a match = ;= with the executing username. If there is a match, the date, = ;= subject, and status are printed. If a message is in the = ;= NEWMAIL folder, it is assumed that it has not been read; if = ;= it is in any other folder, it is assumed to have been read. = ;= The program exits on either ^Z, ^C, or at the prompt. = ;= If the program is interrupted (by ^Y), the scrolling region = ;= for the screen will still be set -- always exit by one of the = ;= three methods described above. = ;= = ;======================================================================== ;= = ;= System services used : = ;= = ;= $ASSIGN Assign an I/O channel to the terminal = ;= = ;= $EXIT Return to VMS = ;= = ;= $QIOW All terminal I/O = ;= = ;======================================================================== ;= = ;= VAX Record Management Services (RMS) used : = ;= = ;= $CLOSE Close SYSUAF , VMSMAIL and MAIL.MAI = ;= = ;= $CONNECT Associate a RAB with a file = ;= = ;= $FAB Create a Fiel Access Block for SYSUAF, = ;= VMSMAIL, and the user's MAIL.MAI file = ;= = ;= $FAB_STORE Macro to store the specific MAIL.MAI = ;= file name in the FAB = ;= = ;= $GET Get records from SYSUAF,VMSMAIL,MAIL.MAI= ;= = ;= $OPEN Open SYSUAF.DAT,VMSMAIL.DAT,MAIL.MAI = ;= = ;= $RAB Create a Record Access Block for SYSUAF,= ;= VMSMAIL and MAIL.MAI = ;= = ;======================================================================== .PAGE .SUBTITLE Storage Area ; ;======================================================================== ;= = ;= D E F I N E D S T O R A G E = ;= = ;======================================================================== ; TAB= 9 LF = 10 CR = 13 ESC= 27 ; ;================================ ;= = ;= MACRO library calls = ;= = ;================================ ; $RMSDEF $RABDEF $FABDEF ; ;*** File Access Block for SYSUAF.DAT ; SYSFAB: $FAB FNM=, - FAC=GET, - ; File Access GET only SHR= ; Allow other access to go on ; while searching ; ;*** Record Access Block for SYSUAF.DAT ; SYSRAB: $RAB FAB=SYSFAB, - ; The File Access Block RAC=KEY, - ; Record Access --- keyed KRF=0, - ; Key of Reference (position 0) KSZ=16, - ; Key size --- 16 characters KBF=TESTNAME, - ; Key buffer is TESTNAME USZ=1420, - ; Size of buffer to receive rec UBF=SYSREC ; Addr of buffer to receive rec ; ;*** File Access Block for VMSMAIL.DAT ; VMSFAB: $FAB FNM=, - FAC=GET, - ; File Access GET only SHR= ; Allow other access to go on ; while searching ; ;*** Record Access Block for VMSMAIL.DAT ; VMSRAB: $RAB FAB=VMSFAB, - ; The File Access Block RAC=KEY, - ; Record Access --- keyed KRF=0, - ; The key of reference KSZ=16, - ; Key size --- 16 characters KBF=TESTNAME, - ; Key buffer is TESTNAME USZ=256, - ; Size of buffer to receive rec UBF=VMSREC ; Addr of buffer to receive rec ; ;*** File Access Block for MAIL.MAI ; MAILFAB: $FAB FAC=GET, - ; File ACcess => GET only SHR= ; Allow other access to go on ; The filename will be added at ; at run-time ; ;*** Record Access Block for MAIL.MAI ; MAILRAB: $RAB FAB=MAILFAB, - ; The File Access block RAC=SEQ, - ; Sequential organization ROP=WAT, - ; Wait until I/O is complete KRF=1, - ; The key of reference USZ=2048, - ; The size of buffer to receive UBF=MAILREC ; The addr of buffer to receive ; JPI_LIST: ; $GETJPI item list .WORD 12 ; ... Get the username .WORD JPI$_USERNAME .ADDRESS USERNAME .LONG UN_LEN .LONG 0 ; USERNAME: ; Buffer to hold the username .BLKB 12 ; of the sender TESTNAME: ; Buffer to hold the username .ASCII / / ; of the receiver .=.+20 UN_LEN: .LONG 0 ; The length of the sender name TN_LEN: .LONG 0 ; The length of receiver name TTNAME: .ASCID /SYS$COMMAND/ ; The output name (terminal) TTCHAN: .LONG 0 ; I/O channel assigned to TT: NEWMAIL: .ASCII /NEWMAIL/ ; Used to check if msg read MAIL_FILE: ; The filename and extension of .ASCII /MAIL.MAI/ ; the MAIL file FILESPEC: ; Buffer for complete file spec .BLKB 80 .PAGE .SUBTITLE Screen I/O ; ;======================================================================== ;= = ;= Screen I/O ---- ANSI ESCAPE sequences, prompts, etc. = ;= = ;======================================================================== ; HEAD2: .ASCII / /"[4mDate/Time"/[m / .ASCII /[4mStatus//[m //[4mSubject/ .ASCII /[m/ PROMPT: .ASCII / Enter the user name to check ( to stop) : / .ASCII /[K/ NO_MSSG:.ASCII / ************ NO MESSAGES ************/ .ASCII NO_USER:.ASCII / ************ No such user ************/ .ASCII HEADER: .ASCII /[2J//[1;25H/"[7m VAX/VMS Mail Status Check " .ASCII /[m/ ; OUTBUF: .ASCII / / ; The output buffer DT: .BLKB 23 ; Spot for date/time of mssg .ASCII / / ; Received or not picked up .ASCII / / .BLKB 23 ; The suubject of the mail mssg BLANKS: .BYTE ^X20[256] ; 256 blanks (clear buffers) PRMPT_LINE: ; ANSI ESC seq -> send the .ASCII /[3;1H/ ; cursor to line 3, column 1 UNDLIN: .ASCII /[4m/ ; ANSI ESC seq -> underline mode CLRATT: .ASCII /[m/ ; " " " -> turn off attr .ASCII /[K/ ; Clear to end of line CLR_END:.ASCII /[J/ ; Clear from current cursor ; position to end of display DEFSCR: .ASCII /[9;23r/ ; Define scrolling region CLEAR: .ASCII /[1;24r//[2J/ ; Reset scrolling region & clear FROM: .ASCII /From: //[4m/ ; "From: " (with underlining) TO: .ASCII /[K//To: //[4m/ ; "To: " (W/ under) YES: .ASCII /RECEIVED / NO: .ASCII /NOT PICKED UP / CRLF: .BYTE CR,LF ; combo ; DATE: ; Descriptor for ASCII date/time .LONG 23 ; of mail message .ADDRESS DT INBUFF: .BLKB 80 ; Input buffer for prompted info ; SYSREC: .=.+1420 ; Buffer to hold SYSUAF record VMSREC: .=.+256 ; Buffer to hold VMSMAIL record MAILREC: ; Buffer to hold MAIL.MAI record .=.+2048 .PAGE .SUBTITLE MAIN Routine ; ;======================================================================== ;= = ;= M A I N R O U T I N E = ;= = ;======================================================================== ; .ENTRY MAILRRR,^M<> ; Entry point of program CLRL R10 ; Clear the YES messages flag $ASSIGN_S - ; Assign the terminal an I/O channel DEVNAM=TTNAME, - CHAN=TTCHAN BSBW SET_CTRLC ; Set the ^C interrupt handler MOVAB DEFSCR,R0 ; Move addr of ANSI escape sequence to MOVZBL #7,R1 ; set scrolling region BSBW PUT_OUT ; Send the sequence to the terminal MOVAB HEADER,R0 ; Move the HEADER addr to R0 for PUT_OUT MOVZBL #51,R1 ; Move the length to R1 for PUT_OUT BSBW PUT_OUT ; Print the header ; ;******* Get the name of the sender ; $GETJPIW_S - ; Get the name of the sender ITMLST=JPI_LIST LOCC #^A/ /,#12,USERNAME ; Find the end of the username BEQL LOOP ; Not found - name is 12 chars - cont SUBL3 #USERNAME,R1,UN_LEN ; Get the actual length of the username ; ...($GETJPI returns 12 - blanks pad) ; ;***** Get the name of the MAIL recipient ; LOOP: MOVC3 #16,BLANKS,TESTNAME ; Clear TESTNAME MOVC3 #256,BLANKS,VMSREC ; Clear the VMSMAIL buffer $QIOW_S CHAN=TTCHAN, - ; Prompt the user for the name to FUNC=#IO$_READPROMPT, - ; of the user to check P1=INBUFF, - P2=#80, - P4=#0, - P5=#PROMPT, - P6=#53 LOCC #^X1A,#80,INBUFF ; Did user enter a ^Z? BEQL 1$ ; No -- continue BRW BYE ; Yes -- exit the program 1$: LOCC #CR,#80,INBUFF ; Find the indicating end of name SUBL3 #INBUFF,R1,R2 ; Was only character entered? BNEQ 5$ ; NO - continue BRW BYE ; YES - exit the program 5$: MOVL R2,TN_LEN ; Move the length of TESTNAME to TN_LEN MOVC3 R2,INBUFF,TESTNAME ; Move the name to TESTNAME ; ;*** Convert the name to uppercase ; MOVL TN_LEN,R0 ; Get the length of the username entered MOVAB TESTNAME,R1 ; Move the starting address 7$: CMPB #^X60,(R1) ; Is character >= "a" BGTR 9$ ; No - don't touch it. Yes - continue BICB2 #^B00100000,(R1) ; Convert each character to uppercase ; (turn off bit 5) 9$: INCL R1 ; Bump up pointer into TESTNAME SOBGTR R0,7$ ; Finished? No - convert next ; BSBW PUT_HEADINGS ; Print the headings ; ;**** Check to see if the recipient name entered is a valid username ; CMPL #16,TN_LEN ; Is name entered longer than 16 chars? BGEQ 10$ ; Yes -- no such username BRW NO_SUCH_USER 10$: $OPEN FAB=SYSFAB ; Open SYSUAF to read TESTNAME record BLBS R0,20$ ; Error opening? Go to ERROR BRW ERROR 20$: $CONNECT RAB=SYSRAB ; Connect the RAB with SYSUAF BLBS R0,30$ ; Error connecting? Go to ERROR BRW ERROR ; 30$: $GET RAB=SYSRAB ; Read the TESTNAME record CMPL #RMS$_RNF,R0 ; Was record found? BNEQ 35$ BRW NO_SUCH_USER 35$: $CLOSE FAB=SYSFAB ; Close the SYSUAF file ; ;****** Check in VMSMAIL.DAT - want presence of a mail_directory ; 50$: $OPEN FAB=VMSFAB ; Open VMSMAIL to read TESTNAME record BLBS R0,70$ ; Error opening? Go to ERROR BRW ERROR 70$: $CONNECT RAB=VMSRAB ; Connect the RAB with VMSMAIL BLBS R0,80$ ; Error connecting? Go to ERROR BRW ERROR ; 80$: $GET RAB=VMSRAB ; Read the TESTNAME record CMPL #RMS$_RNF,R0 ; Was record found? BNEQ 85$ BRW NO_SUCH_USER 85$: $CLOSE FAB=VMSFAB ; Close the VMSMAIL file ; ;****** Get the recipient's default device and directory (home of the MAIL.MAI) ;****** and build the complete MAIL.MAI file specification ; LOCC #^A":",#32,SYSREC+117 ; Find ":" indicating end of device name SUBL3 #SYSREC+117,R1,R6 ; Get the length of the def dev name INCL R6 ; Bump to include ":" MOVL R6,R8 ; Save the number of chars in def dev MOVC3 R6,SYSREC+117,FILESPEC ; Move the def dev to FILESPEC LOCC #^A"]",#40,SYSREC+149 ; Find "]" indicating end of default dir SUBL2 #SYSREC+149,R1 ; Get the length of the def dir ; INCL R1 ; dont bump to include "]" ADDL2 R1,R8 ; Add to the number of chars in def dev MOVC3 R1,SYSREC+149,FILESPEC[R6] ; Move the def dir name to FILESPEC MATCHC #1,#^A"[",#256,VMSREC ; Look for beginning of mail_directory BNEQ 86$ ; Ok , not found ; SUBL2 #1,R3 ; Bump back to point to beginning LOCC #^A"]",#256,(R3) ; Look for end of mail_directory INCL R1 ; Bump up to include "]" SUBL2 R3,R1 ; Get length of string to move ADDL3 R1,R8,R6 ; Temp store (total length of FILESPEC) MOVC3 R1,(R3),FILESPEC[R8] ; Move the mail_directory to FILESPEC MOVL R6,R8 ; Bump up R8 (total length of FILESPEC) BRB 87$ ; Thats it 86$: MOVC3 #1,#^A"]",FILESPEC[R8] ; Use default directory - Thats it INCL R8 ; Bump up R8 (total length of FILESPEC) ; 87$: MOVC3 #8,MAIL_FILE,FILESPEC[R8] ; Move MAIL.MAI to the filespec ADDL2 #8,R8 ; Bump up R8 (total length of FILESPEC) $FAB_STORE - ; Store FILESPEC (the receiver's mail FAB=MAILFAB, - ; filename) in the FAB for MAIL FNA=FILESPEC, - FNS=R8 ; ;******* Open the recipient's MAIL file (if there), read in each mail header, ;******* to see if the file was sent by the USERNAME, and, if so, put the ;******* message status into the output buffer ; $OPEN FAB=MAILFAB ; Open the user's mail file BLBS R0,40$ ; Error opening? No messages from user BRW NO_MESS 40$: $CONNECT RAB=MAILRAB ; Connect RAB with MAIL.MAI BLBS R0,HERE ; Error connecting? BRW NO_MESS ; No messages from user HERE: $GET RAB=MAILRAB ; Get the first mail header CMPL #RMS$_RNF,R0 ; Was record found? BNEQ 4$ ; Yes - continue BRW NO_MESS ; No -- goto error routine 4$: CMPL #RMS$_EOF,R0 ; Was end of file found? BNEQ 5$ ; Yes - continue BRW NO_MESS ; No -- goto error routine 5$: MATCHC UN_LEN,USERNAME,UN_LEN,MAILREC+73 ; Is mail from running user? BNEQ HERE ; No -- get next record ; ;******* Here if message was from USERNAME ; CMPC3 #7,NEWMAIL,MAILREC+9 ; Has file been read (NEWMAIL)? TSTL R0 ; Is this in NEWMAIL folder? BNEQ 10$ ; Yes - move the RECEIVED status MOVC3 #14,NO,OUTBUF+32 ; Move "NOT PICKED UP" to OUTBUF BRB 12$ ; Go find the subject of the message 10$: MOVC3 #14,YES,OUTBUF+32 ; Move "RECEIVED" to OUTBUF ; 12$: MATCHC #12,USERNAME,#128,MAILREC+86 ; Look for beginning of SUBJ BEQL 13$ ; Mail sent /SELF MATCHC TN_LEN,TESTNAME,#128,MAILREC+86 ; Look for beginning of SUBJ 13$: ADDL2 #4,R3 ; Bump up to point to beginning LOCC #^X05,#23,(R3) ; Look for end of Subj: BEQL 15$ ; Not found --- truncate subject SUBL2 R3,R1 ; Get length of string to move BRB 20$ ; Go move it 15$: MOVL #23,R1 ; Here if truncate -- set length to 30 20$: MOVC3 R1,(R3),OUTBUF+51 ; Move the Subj: string to OUTBUF ; $ASCTIM_S - ; Convert the date/time of the mail TIMBUF=DATE, - ; message to ASCII and put it in TIMADR=MAILREC ; the output buffer MOVAB OUTBUF,R0 ; Move addr of OUTBUF for PUT_OUT MOVZBL #74,R1 ; Move length for PUT_OUT BSBW PUT_OUT ; Print the output buffer MOVAB CRLF,R0 ; Send a to the terminal MOVZBL #2,R1 ; .... BSBW PUT_OUT ; .... MOVC3 #77,BLANKS,OUTBUF ; Clear the output buffer MOVB #1,R10 ; Set YES messages flag BRW HERE ; Go get the next mail record ; ;******* Here if there are no messages from USERNAME ; NO_MESS: BLBS R10,STOP ; Is YES messages flag set? Yes, exit CLRL R10 ; Clear messages flag MOVAB NO_MSSG,R0 ; Move mssg addr for PUT_OUT MOVZBL #48,R1 ; Move mssg length for PUT_OUT BSBW PUT_OUT ; Print the message ; ;******* Here when all messages in the mail file have been checked ; STOP: $CLOSE FAB=MAILFAB ; Close the MAIL.MAI file MOVC3 #30,BLANKS,TESTNAME ; Clear the TESTNAME buffer MOVC3 #256,BLANKS,VMSREC ; Clear the VMSMAIL buffer BSBW GOTO_PRMPT ; Send the cursor to the prompt line CLRL R10 ; Clear messages flag BRW LOOP ; Go get next username (if there is one) ; ;******* Here if TESTNAME was not found in SYSUAF ; NO_SUCH_USER: $CLOSE FAB=SYSFAB ; Close the SYSUAF file MOVAB NO_USER,R0 ; Move mssg addr to R0 for PUT_OUT MOVZBL #48,R1 ; Move the message length for PUT_OUT BSBW PUT_OUT ; Print the message BSBW GOTO_PRMPT ; Send the cursor to the prompt line BRW LOOP ; Go get next username ; ;******* Here if , ^Z, or ^C was entered at prompt for username ; BYE: MOVAB CLEAR,R0 ; Move the ANSI escape sequence and MOVZBL #11,R1 ; length to reset the scrolling BSBW PUT_OUT ; region and clear the screen $EXIT_S ; ;******* Here if there was an error somewhere ; ERROR: PUSHL R0 ; Push message code onto stack CALLS #1,G^LIB$SIGNAL ; Print the error message MOVAB CLEAR,R0 ; Move the ANSI escape sequence and MOVZBL #7,R1 ; length to reset the scrolling BSBW PUT_OUT ; region $EXIT_S ; Return to VMS .PAGE .SUBTITLE PUT_HEADINGS subroutine ;======================================================================== ;= = ;= Subroutine PUT_HEADINGS = ;= = ;= Functional description : = ;= = ;= This routine prints the headings "From: ", "To: ", = ;= "Date/Time", etc. = ;= = ;= Parameters : = ;= = ;= None = ;= = ;= Implicit inputs : = ;= = ;= CRLF, OUTBUF, USERNAME, UN_LEN, TESTNAME, TN_LEN, = ;= BLANKS, CLR_END = ;= = ;= Effects : = ;= = ;= None = ;= = ;======================================================================== ; PUT_HEADINGS: PUSHR #^M ; Save registers MOVAB CRLF,R0 ; Send a combination to the TT: MOVZBL #2,R1 ; ..... BSBW PUT_OUT ; ..... BSBW PUT_OUT ; ..... MOVAB OUTBUF,R6 ; Move addr of OUTBUF to R6 for FROM: MOVC3 #12,FROM,(R6) ; Move "From: " and underline ESC seq ADDB2 #12,R6 ; Bump up OUTBUF pointer MOVC3 UN_LEN,USERNAME,(R6) ; Move the username to OUTBUF ADDB2 UN_LEN,R6 ; Bump up OUTBUF pointer MOVC3 #3,CLRATT,(R6) ; Move ESC exit underline sequence MOVC3 #14,TO,3(R6) ; Move "To: " and underline sequence ADDB2 #17,R6 ; Bump up pointer MOVC3 TN_LEN,TESTNAME,(R6) ; Move testname to OUTBUF ADDL2 TN_LEN,R6 ; Bump up pointer MOVC3 #6,CLRATT,(R6) ; Move ESC exit underline sequence ADDB2 #6,R6 ; Bump up pointer MOVAB OUTBUF,R0 ; Move OUTBUF addr for PUT_OUT SUBL3 #OUTBUF,R6,R1 ; Move length for PUT_OUT BSBW PUT_OUT ; Print it MOVC3 #80,BLANKS,OUTBUF ; Clear the output buffer MOVAB CRLF,R0 ; Send a combination to the TT: MOVZBL #2,R1 ; ..... BSBW PUT_OUT ; ..... BSBW PUT_OUT ; ..... MOVAB HEAD2,R0 ; Move HEAD2 addr for PUT_OUT MOVZBL #83,R1 ; Move length to PUT_OUT BSBW PUT_OUT ; Print it MOVAB CLR_END,R0 ; Move addr of ANSI erase to end of MOVZBL #3,R1 ; display and send to the terminal BSBW PUT_OUT POPR #^M ; Restore registers RSB ; Return to main .PAGE .SUBTITLE GOTO_PRMPT subroutine ; ;======================================================================== ;= = ;= Subroutine GOTO_PRMPT = ;= = ;= Functional description : = ;= = ;= Send the cursor to the prompt line -- the flow of = ;= control falls through to subroutine PUT_OUT = ;= = ;======================================================================== ; GOTO_PRMPT: PUSHR #^M ; Save registers MOVAB PRMPT_LINE,R0 ; Move the ANSI escape sequence and its MOVZBL #6,R1 ; length that will send the cursor BSBB PUT_OUT ; Send the cursor to the command line POPR #^M ; Restore registers RSB ; to the prompt line .PAGE .SUBTITLE PUT_OUT subroutine ; ;======================================================================== ;= = ;= Subroutine PUT_OUT = ;= = ;= Functional description : = ;= = ;= Send the contents of a buffer to the terminal = ;= = ;= Parameters : = ;= = ;= Address of buffer in R0 = ;= Length of buffer in R1 = ;= = ;= Effects : = ;= = ;= None = ;= = ;======================================================================== ; PUT_OUT: PUSHR #^M ; Save the registers destroyed $QIOW_S CHAN=TTCHAN, - ; Send ASCII characters to the terminal FUNC=#IO$_WRITEVBLK, - ; ...Address in R0 P1=(R0), - ; ...Length in R1 P2=R1 POPR #^M ; Restore registers RSB .PAGE .SUBTITLE SET_CTRLC subroutine ; ;======================================================================== ;= = ;= Subroutine SET_CTRLC = ;= = ;= Functional description : = ;= = ;= This routine establishes a ^C handler. = ;= = ;= Parameters : = ;= = ;= None = ;= = ;= Effects : = ;= = ;= None = ;= = ;======================================================================== ; SET_CTRLC: ; Enable the ^C handler PUSHR #^M ; Save the registers destroyed $QIOW_S CHAN=TTCHAN, - ; Enable a ^C AST handler FUNC=#IO$_SETMODE!IO$M_CTRLCAST, - P1=C_AST ; The AST entry address POPR #^M ; Restore registers RSB ; ;======================================================================== ;= = ;= CONTROL-C handling routine --- exit the program = ;= = ;======================================================================== ; C_AST: .WORD 0 ; Entry mask -- save no regs JMP BYE ; Jump to exit the program .END MAILRRR