Trailing-Edge
-
PDP-10 Archives
-
bb-kl11c-bm_tops20_v6_1_atpch1_16
-
autopatch/armail.c15
There are no other files named armail.c15 in the archive.
REP 7/2 ;15C1
SEARCH MONSYM,MACSYM
WIT
SEARCH MONSYM,MACSYM, MSUNV
REP 12/2 ;15C2
ARMEDT==VI%DEC+^D3 ;EDIT LEVEL
WIT
ARMEDT==VI%DEC+^D5 ;EDIT LEVEL
F=0
INS 19/2 ;15C3
Q2=6
Q3=7
P1=10
P2=11
P3=12
P4=13
P5=14
P6=15
INS 37/2 ;15C4
IPCPGS==10000 ; Page to send to MX
INS 7/3 ;15C5
IDNUM: BLOCK 1 ; ID number of current page to MX
MSGNUM: BLOCK 1 ; Page number of message to MX
MSGRCT: BLOCK 1 ; Number of records in current page to MX
NUMRPT: BLOCK 1 ; Number of recipients on current line
CURPTR: BLOCK 1 ; Pointer to the current line being formed
CURPT2: BLOCK 1 ; Updated pointer to the current line
USRNAM: BLOCK 1 ; Pointer to the current recipient name
PAKSTS: BLOCK 1 ; Flag indicating if last page of message
LCLRPT: BLOCK 1 ; Recipient is local
REP 13/3 ;15C6
;End of variables to replace STKVARs
WIT
CURLIN: BLOCK ^D40 ; Current line being formed
FILSPC: BLOCK ^D15 ; File spec of message file
NODNAM: BLOCK 2 ; ASCIZ name of our node
NODPTR: BLOCK 1 ; Pointer to our node
REP 26/3 ;15C7
MLRPID: BLOCK 1 ;PID OF [SYSTEM]MAILER OR -1 IF UNAVAILABLE
SCNUD: BLOCK 10 ;TEMP AREA FOR USER NAME STRING
WIT
MYPID: BLOCK 1 ; PID obtained for talking with MX
MLRPID: BLOCK 1 ;PID OF [SYSTEM]MAILER OR -1 IF UNAVAILABLE
SAVAC: BLOCK 20 ; Save accumulator block
DEL 1/10 ;15C8
; Routine to save and restore the AC's.
SAVACS: EXCH T1,0(P) ; Save T1, get return addr
PUSH P,T2
PUSH P,T3
PUSH P,T4
PUSH P,AP
PUSH P,[SVACRT] ; Save return addr
PUSH P,T1 ; RETURN ADDR
MOVE T1,-6(P) ; RESTORE T1
RET ; "RETURN" TO CALLER
SVACRT: CAIA
AOS -5(P) ; ROUTINE SKAP
POP P,AP
POP P,T4
POP P,T3
POP P,T2
POP P,T1
RET
REP 5/11 ;15C9
;RETURNS +1: COULD NOT COMMUNICATE WITH [SYSTEM]MAILER
; +2: MESSAGE SUCCESSFULLY PASSED TO MAILER (NOTE THAT THIS
; ROUTINE DOESN'T CARE WHAT HAPPENS AFTER THE MESSAGE
; HAS BEEN PUT IN MAILER'S HANDS)
DECM: SAVEAC <Q1>
; STKVAR <ARGPTR,<IPCFM,15>,<PDB,4>>
MOVEM T1,ARGPTR ;SAVE ADDRESS OF ARGUMENT BLOCK
SETZM CPYJFN ;NO JFN CURRENTLY ON MAIL.CPY
SETZM .IPCFS+PDB ;SET NO PID OBTAINED FOR ME YET
;SET UP PDB FOR SENDING MESSAGE TO [SYSTEM]MAILER
CALL GTMLR ;GET MAILER'S PID
JRST DECMX1 ;CAN'T, SO FAIL
MOVEM T1,.IPCFR+PDB ;MAKE MAILER THE RECEIVER
MOVX T1,IP%CPD ;REQUEST MONITOR TO CREATE A PID
MOVEM T1,.IPCFL+PDB
MOVEI T1,IPCFM ;GET ADDRESS OF IPCF MESSAGE
MOVEM T1,.IPCFP+PDB ;(SIZE WILL BE FILLED IN LATER)
;BUILD FILESPEC IN IPCFM FOR MAIL.CPY IN LOGGED-IN DIRECTORY
SETO T1, ;THIS JOB
HRROI T2,T4 ;GET 1 WORD INTO T4
MOVEI T3,.JILNO ;WANT LOGGED-IN DIRECTORY #
GETJI ;GET IT
JRST DECMX1 ;SHOULD NEVER FAIL
MOVE T2,T4 ;GET DIR #
HRROI T1,IPCFM ;STRING GOES HERE
DIRST ;CONVERT LOGGED-IN DIR # TO STRING
JRST DECMX1 ;SHOULD NEVER FAIL
HRROI T2,[ASCIZ/MAIL.CPY/]
SETZ T3,
SOUT ;APPEND NAME AND EXTENSION
;OPEN MAIL.CPY
GJINF ;GET CONNECTED DIRECTORY # IN T2
SETZ T1, ;NO FLAGS
DELDF ;EXPUNGE DELETED MAIL.CPY'S
MOVX T1,GJ%SHT+GJ%FOU
HRROI T2,IPCFM ;GET POINTER TO FILESPEC I JUST BUILT
GTJFN ;GET JFN ON MAIL.CPY
JRST DECMX1 ;FAILED
MOVEM T1,CPYJFN ;REMEMBER JFN
MOVE T2,[FLD(^D36,OF%BSZ)+OF%WR] ;BYTE SIZE, MODE
OPENF ;OPEN FOR OUTPUT
JRST DECMX1 ;FAILED
SETZ T1,
CALL CPY1 ;NO FLAGS FOR MAILER
;PARSE USER NAME STRING AND WRITE "TO" USER NUMBERS TO MAIL.CPY
WIT
;RETURNS +1: COULD NOT COMMUNICATE WITH MX
; +2: MESSAGE SUCCESSFULLY PASSED TO MX (NOTE THAT THIS
; ROUTINE DOESN'T CARE WHAT HAPPENS AFTER THE MESSAGE
; HAS BEEN PUT IN MX'S HANDS)
DECM: MOVEM T1,ARGPTR ;SAVE ADDRESS OF ARGUMENT BLOCK
SETZM CPYJFN ;No JFN currently on mail file
SETZM MYPID ;SET NO PID OBTAINED FOR ME YET
;SET UP PDB FOR SENDING MESSAGE TO MX
CALL GTMLR ;GET MX'S PID
JRST DECMX1 ;CAN'T, SO FAIL
SETZM IDNUM ;No message ID at this point
SETZM MSGNUM ;No message pages sent yet
SETZM MSGRCT ;No records in message yet
SETZM PAKSTS ;More pages to follow
SETZM NUMRPT ;No recipients on current line
;Open the mail file
CALL OPNFIL
JRST DECMX1 ;Failed to open the file
;Build date line and place in message file
MOVEI T1,CURLIN ;Make a pointer to the current line
HRLI T1,(POINT 7) ;This will be used alot so save it
MOVEM T1,CURPTR
MOVEM T1,CURPT2 ;Updated pointer, used in routine BLDRCP
CALL BLDDAT
;Build the sender record.
CALL BLDSND
;Build the recipient records
REP 64/11 ;15C10
SETZ Q1, ;INITIALIZE COUNT OF USER NAMES
DECM1: CALL SCNU ;SCAN A USER NAME
EXCH T1,T2 ;GET USER # IN T1, STRING POINTER IN T2
JUMPN T1,[CALL CPY1 ;IF USER # OBTAINED, WRITE IT TO FILE
AOJA Q1,.+1] ;COUNT VALID USER #
MOVE T1,T2 ;PREPARE FOR NEXT CALL TO SCNU
CAIE T3,"," ;COMMA AFTER USER NAME?
CAIN T3," " ; OR BLANK?
JRST DECM1 ;YES, TRY FOR ANOTHER USER NAME
JUMPE Q1,DECMX1 ;END OF LIST, ERROR IF NO VALID NAMES
SETZ T1,
CALL CPY1 ;TERMINATE "TO" LIST
CALL CPY1 ;NULL "CC" LIST
;WRITE SUBJECT AND MESSAGE FIELDS TO MAIL.CPY
SETZ T1,
CALL CPYST ;INITIALIZE FOR COPYING STRINGS
HRROI T1,[ASCIZ/SUBJECT: /]
CALL CPYST ;WRITE NOISE
MOVE Q1,ARGPTR ;GET ADDRESS OF ARGUMENT BLOCK
MOVE T1,1(Q1) ;GET POINTER TO SUBJECT
CALL CPYST ;OUTPUT SUBJECT FIELD
HRROI T1,[ASCIZ/
/]
CALL CPYST ;OUTPUT CRLF CRLF
MOVE T1,2(Q1) ;GET POINTER TO MESSAGE
CALL CPYST ;OUTPUT MESSAGE
MOVEI T1,1
CALL CPYST ;FINISH UP PARTIAL WORD
;CLOSE MAIL.CPY
MOVE T1,CPYJFN ;GET JFN OF MAIL.CPY
TXO T1,CO%NRJ ;KEEP JFN
CLOSF ;CLOSE MAIL.CPY
JFCL
;BUILD IPCF MESSAGE IN IPCFM CONTAINING FILESPEC OF MAIL.CPY
;AND STORE LENGTH OF MESSAGE INTO PDB
HRROI T1,IPCFM ;DESTINATION
MOVE T2,CPYJFN ;MAIL.CPY JFN
MOVE T3,[111110,,1] ;DEV,DIR,NAME,EXT,GEN,PUNCTUATE
JFNS ;GET FILESPEC
SETZ T2,
IDPB T2,T1 ;TIE IT OFF
SUBI T1,-1+IPCFM ;GET # OF WORDS IN FILESPEC
HRLM T1,.IPCFP+PDB ;STORE MESSAGE LENGTH INTO PDB
;SEND MESSAGE OFF TO MAILER
MOVEI T1,4 ;PDB SIZE
MOVEI T2,PDB ;PDB ADDRESS
MSEND ;SEND MESSAGE TO MAILER
JRST DECMX1 ;IT FAILED
JRST DECMX2 ;IT SUCCEEDED
WIT
MOVEM T1,USRNAM ;Save in case need to send another page
RCPTLP: CALL BLDRCP
MOVE T1,USRNAM ;Pick up the status from BLDRCP
CAMN T1,[-1] ;Any valid recipients found?
JRST [ SKIPG IDNUM ;The first page of the message?
JRST DECMX1 ;Yes, so really are no valid recipients
JRST SUBRE2] ;No, go build the sender record
JUMPE T1,SUBREC ;No more recipients, build sender record
CALL SNDMX ;Page is full, send off to MX
JRST DECMX1 ;An error occurred, quit
JRST RCPTLP ;Get more recipients
;Build the subject record. First make sure there is room
SUBREC: CAIG P3,BUFEND ;Still room?
JRST SUBRE2 ;Yes, build the subject record
CALL SNDMX ;Page is full, send off to MX
JRST DECMX1 ;An error occurred, quit
SUBRE2: CALL BLDSUB ;Build the subject record
;Build the message ID
CALL BLDMID
;Copy the text to the mail file and then close it
CALL BLDTXT
JRST DECMX1 ;Could not close the mail file, quit
;Build the file spec record last since MX returns an error if the file is
;still open
CAIG P3,BUFEND ;Still have room?
JRST FSPREC ;Yes, build the file spec record
CALL SNDMX ;Not enough room, send this page off
JRST DECMX1 ;An error occurred
FSPREC: CALL BLDSPC ;Build the file spec record
;Send the last page of the message
SETOM PAKSTS ;Indicate that this is the last page
CALL SNDMX ;Send the last page off
JRST DECMX1 ;An error occurred, quit
JRST DECMX2 ;Success
REP 134/11 ;15C11
JFCL
WIT
ERJMP .+1
REP 139/11 ;15C12
JFCL
MOVE T1,CPYJFN ;GET JFN ONE MORE TIME
RLJFN ;DISCARD IT
JFCL
JRST .+1]
SKIPE T1,.IPCFS+PDB ;DID I HAVE A PID?
WIT
ERJMP .+1
MOVE T1,CPYJFN ;GET JFN ONE MORE TIME
RLJFN ;DISCARD IT
ERJMP .+1
JRST .+1]
SKIPE T1,MYPID ;DID I HAVE A PID?
REP 2/12 ;15C13
;CPY1 - WRITE 1 WORD TO MAIL.CPY FILE
; T1/ WORD TO BE WRITTEN
;RETURNS +1: ALWAYS, ALL AC'S PRESERVED
CPY1: CALL SAVACS ;SAVE AC'S
MOVE T4,T1 ;COPY THE DATA TO BE WRITTEN
MOVE T1,CPYJFN ;GET JFN ON FILE
MOVE T2,[POINT 36,T4] ;GET POINTER TO DATA
MOVNI T3,1 ;WRITE 1 WORD
SOUT ;WRITE TO FILE
ERJMP .+1
RET
;CPYST - WRITE ASCIZ STRING TO MAIL.CPY FILE
; WE NEED THIS BECAUSE MAIL.CPY IS OPEN IN 36-BIT BYTE MODE
; T1/ 0 TO INITIALIZE CPYST MEMORY, OR
; 1 TO OUTPUT LAST PARTIAL WORD, OR
; STRING POINTER TO TEXT TO BE OUTPUT
;RETURNS +1: ALWAYS
CPYST: JUMPE T1,[MOVE T1,[POINT 7,CPYSTD] ;INITIALIZATION CALL
MOVEM T1,CPYSTP ;SET UP POINTER TO BUILDING AREA
SETZM CPYSTD ;CLEAR BUILDING AREA
RET]
CAIN T1,1 ;WRAP-UP CALL?
JRST [ SKIPE T1,CPYSTD ;YES, DOES A PARTIAL WORD EXIST?
CALL CPY1 ;YES, OUTPUT IT
RET]
;T1/ POINTER TO STRING TO BE OUTPUT
TLC T1,-1
TLCN T1,-1 ;OF FORM -1,,ADDR ?
HRLI T1,(POINT 7) ;YES, CONVERT TO PDP-10 BYTE POINTER
MOVE T3,T1 ;MOVE POINTER OVER TO T3
CPYST1: ILDB T2,T3 ;GET A CHARACTER FROM INPUT STRING
JUMPE T2,R ;END OF STRING, RETURN
IDPB T2,CPYSTP ;TRANSFER CHARACTER TO BUILDING AREA
MOVE T2,CPYSTP
TLNE T2,760000 ;BUILDING AREA FULL?
JRST CPYST1 ;NO, PROCESS NEXT CHARACTER
SOS CPYSTP ;YES, RESET POINTER TO BUILDING AREA
MOVE T1,CPYSTD ;GET CONTENTS OF BUILDING AREA
CALL CPY1 ;WRITE BUILDING AREA TO FILE
SETZM CPYSTD ;CLEAR IT FOR NEW DATA
JRST CPYST1 ;GET NEXT CHARACTER
;GTMLR - GET MAILER'S PID
;RETURNS +1: ERROR (E.G. PID NOT DEFINED)
; +2: SUCCESS, T1/ MAILER'S PID
GTMLR:
; STKVAR <<GTMPDB,4>,<GTMANS,2>>
SKIPE T1,MLRPID ;FIRST TIME THROUGH?
JRST [ CAMN T1,[-1] ;NO, WHAT DO I KNOW ABOUT MAILER?
RET ;COULDN'T GET MAILER'S PID
RETSKP] ;DID GET MAILER'S PID
SETOM MLRPID ;SET MAILER'S PID CURRENTLY UNKNOWN
;ASK <SYSTEM>INFO FOR MAILER'S PID
WIT
;GTMLR - GET MX'S PID
;RETURNS +1: ERROR (E.G. PID NOT DEFINED)
; +2: SUCCESS, T1/ MX'S PID
GTMLR:
;ASK <SYSTEM>INFO FOR MX'S PID
REP 20/13 ;15C14
MOVE T1,[5,,[.IPCIW ;PACKET TO REQUEST PID FOR MAILER
0
ASCIZ/[SYSTEM]MAILER/]]
WIT
MOVE T1,[5,,[.IPCIW ;PACKET TO REQUEST PID FOR MX
0
ASCIZ/MXMAIL/]]
REP 27/13 ;15C15
JRST [ MOVE T1,.IPCFS+GTMPDB ;FAILED, GET CREATED PID
WIT
JRST [ MOVE T1,.IPCFS+GTMPDB ;FAILED, GET CREATED PID
REP 39/13 ;15C16
JRST [ MOVE T1,.IPCFR+GTMPDB ;ERROR
CALLRET RELPID] ;RELEASE PID AND FAIL
MOVE T1,.IPCFR+GTMPDB ;GET MY PID
CALL RELPID ;DON'T NEED IT ANY MORE
WIT
JRST [ MOVE T1,.IPCFS+GTMPDB ;ERROR
CALLRET RELPID] ;RELEASE PID AND FAIL
MOVE T1,.IPCFR+GTMPDB ;GET MY PID
MOVEM T1,MYPID ;Save for later
REP 46/13 ;15C17
MOVE T1,.IPCFL+GTMPDB ;GET FLAGS WORD FROM PDB
TRNE T1,IP%CFE ;ERROR?
RET ;YES, FAIL
MOVE T1,1+GTMANS ;GET PID OF INFO
MOVEM T1,MLRPID ;REMEMBER IT FOR FUTURE REFERENCE
RETSKP ;RETURN SUCCESS
;SCNU - SCAN STRING FOR USER NAME
; T1/ STRING POINTER TO USER NAME STRING
;RETURNS +1: ALWAYS
; T1/ BYTE POINTER TO CHARACTER FOLLOWING USER NAME
; T2/ USER NUMBER OR 0 IF NO VALID USER NAME WAS FOUND
; T3/ CHARACTER FOLLOWING USER NAME
;NOTE: THIS ROUTINE ASSUMES THAT USER NAMES CONTAIN ONLY UPPER CASE
; LETTERS, LOWER CASE LETTERS, DIGITS, AND PERIODS
SCNU:
; STKVAR <<RDAT,3>>
MOVEM T1,RDAT ;STORE CALLER'S STRING POINTER
SETZM 1+RDAT ;CLEAR THE USER #
MOVE T1,[POINT 7,SCNUD] ;SET UP POINTER TO TEMP AREA
;SCAN STRING COPYING USER NAME INTO TEMP AREA (SCNUD) FOR RCUSR JSYS
SCNU1: ILDB T2,RDAT ;GET A CHARACTER FROM STRING
IDPB T2,T1 ;TRANSFER TO TEMP AREA
CAIN T2,.CHCNV ;QUOTING CHARACTER?
JRST [ ILDB T2,RDAT ;YES, GET CHARACTER FOLLOWING IT
DPB T2,T1 ;OVERWRITE QUOTING CHARACTER
JRST SCNU1] ;CONTINUE
CAIL T2,"a" ;LOWER CASE?
CAILE T2,"z"
SKIPA
SUBI T2,40 ;YES, CONVERT TO UPPER CASE
CAIL T2,"A" ;UPPER CASE?
CAILE T2,"Z"
SKIPA
JRST SCNU1 ;YES, CONTINUE SCAN
CAIL T2,"0" ;NUMERIC?
CAILE T2,"9"
SKIPA
JRST SCNU1 ;YES, CONTINUE SCAN
;**; [5] AT SCNU1:+17L add 1 line SM 15-Aug-85
CAIE T2,"_" ;[5] UNDERSCORE?
CAIN T2,"." ;PERIOD?
JRST SCNU1 ;YES, CONTINUE SCAN
CAIE T2,"$" ;ALLOW DOLLAR SIGNS AND
CAIN T2,"-" ; ALLOW DASHES
JRST SCNU1 ;VALID CHARACTER, CONTINUE SCAN
;END OF USER NAME FOUND
MOVEM T2,2+RDAT ;REMEMBER LAST CHARACTER FOR CALLER
SETZ T2,
DPB T2,T1 ;TIE OFF USER NAME IN TEMP AREA
MOVX T1,RC%EMO ;FLAGS (EXACT MATCH ONLY)
HRROI T2,SCNUD ;GET POINTER TO TEMP AREA
RCUSR ;CHECK OUT USER NAME
ERJMP SCNU2 ;ERROR
TXNN T1,RC%NOM ;VALID USER NAME?
MOVEM T3,1+RDAT ;YES, RETURN USER # TO CALLER
SCNU2: DMOVE T1,RDAT ;LOAD UP AC'S TO RETURN TO CALLER
MOVE T3,2+RDAT
WIT
MOVE T2,.IPCFL+GTMPDB ;GET FLAGS WORD FROM PDB
TRNE T2,IP%CFE ;ERROR?
RET ;YES, FAIL
MOVE T1,1+GTMANS ;GET PID OF MX
MOVEM T1,MLRPID ;REMEMBER IT FOR FUTURE REFERENCE
RETSKP ;RETURN SUCCESS
;Open the mail file. Save the file spec for the file spec record
OPNFIL: GJINF ;Get my user number
MOVE T2,T1 ;Place it where DIRST wants it
HRROI T1,IPCFM ;Place my user name here
DIRST ;Convert user number to user name
RET ;Should never fail
MOVEI T2,FILSPC ;Where to build the file spec
HRLI T2,(POINT 7) ;Make it a pointer
MOVE Q1,T2 ;Save for the GTJFN
MOVEI T4,[ASCIZ/POBOX:/]
HRLI T4,(POINT 7)
TRSSTR: MOVEI P1,^D29 ;Invariant byte number in file spec name
ILDB T3,T4 ;Transfer the structure name
JUMPE T3,TRSDIR ;If finished, transfer the directory name
IDPB T3,T2 ;Into the file spec record
JRST TRSSTR ;Get the next character
TRSDIR: MOVEI T3,"<" ;Get the directory name delimiter
IDPB T3,T2 ;Place in the file spec record
MOVEI T4,IPCFM ;Address of user name
HRLI T4,(POINT 7) ;Make into a pointer
DIRREC: ILDB T3,T4 ;Get the next character
CAIN T3,0 ;End of the user name
JRST FNDDIR ;Finish the directory name
IDPB T3,T2 ;Place in the file spec record
AOS P1 ;Increment the byte count
JRST DIRREC ;Get the next character
FNDDIR: MOVEI T3,">" ;Get the directory delimiter
IDPB T3,T2 ;Place in the file spec record
MOVEI T3,"M" ;Pick up first character of file name
IDPB T3,T2 ;Place in the file spec record
MOVEI T3,"S" ;Pick up second character of file name
IDPB T3,T2 ;Place in the file spec record
GETFS: PUSH P,T2 ;Save pointer in case file already exists
GTAD ;Get a string
AND T1,[070707,,070707] ;Make it SIXBIT numeric
ROT T1,^D12 ;Want the four that change most often
MOVNI T3,4 ;Need four digits
GETFCH: SETZ F, ;Clear out results from previous loop
LSHC F,6 ;Get the next SIXBIT character
ADDI F,"0" ;Change to ASCII
IDPB F,T2 ;Place in the file spec record
AOJN T3,GETFCH ;Convert any remaining
TRSEXT: MOVE T1,T2 ;SOUT wants pointer in T1
HRROI T2,[ASCIZ/.MAI.1;P770000/]
SETZ T3, ;ASCIZ string
SOUT ;Copy the extension to the file record
ERJMP .+1 ;Should never happen
MOVX T1,GJ%SHT+GJ%NEW ;Must be a new file
MOVE T2,Q1 ;Point to the file spec
GTJFN% ;Get its JFN
ERJMP [POP P,T2 ;Restore the pointer
CAIE T1,GJFX27 ;Does file already exist?
RET ;No, must be another type of error
JRST GETFS] ;Yes, try another
MOVEM T1,CPYJFN ;Save the JFN for later
ADJSP P,-1 ;Don't need the file spec pointer now
;Open the mail file
MOVE T1,CPYJFN ;Pick up the JFN
MOVE T2,[FLD(7,OF%BSZ)+OF%WR]
OPENF ;OPEN FOR OUTPUT
JRST [ MOVE T1,CPYJFN ;Error, so release the JFN
RLJFN
ERJMP .+1
RET]
RETSKP ;Succeed
;Build the date field and the first part of the from line.
;Place in the message file
BLDDAT: HRROI T2,[ASCIZ/Date: /]
SETZ T3, ;Copy ASCIZ string
SOUT ;Into the current line buffer
ERJMP .+1 ;Shouldn't happen
SETO T2, ;Want the entire date
MOVX T3,OT%4YR!OT%SPA!OT%NCO!OT%NSC!OT%SCL!OT%TMZ
ODTIM% ;Get the formatted dat
ERJMP .+1 ;Shouldn't happen
HRROI T2,[ASCIZ/
From: /]
SETZ T3, ;
SOUT
ERJMP .+1 ;Shouldn't happen
MOVE T1,CPYJFN ;Write out to the message file
MOVE T2,CURPTR ;The current line
SETZ T3, ;ASCIZ string
SOUT
ERJMP .+1 ;Shouldn't happen
INS 2/15 ;15C18
;Build the sender record
BLDSND: MOVEI P3,.HDRSZ ;Number of bytes in message so far
MOVEI P5,IPCPGS+.HDRSZ ;Address of sender record
MOVEI T2,IPCFM ;Address of the sender name
HRLI T2,(POINT 7) ;Make it into a pointer
SETZ P1, ;No bytes in this record yet
MOVE T3,P5 ;Address of the current record
ADDI T3,.RECTX ;Address of the sender name field
HRLI T3,(POINT 7) ;Make into a pointer
MOVE Q2,CURPTR ;Point to the current line buffer
TRSSND: ILDB T1,T2 ;Get the next character of send name
IDPB T1,T3 ;Place into the sender record
IDPB T1,Q2 ;Place in the current line buffer
AOS P1 ;Increment the byte count
CAIE T1,0 ;Finished?
JRST TRSSND ;No, get the next character
;Finish up the sender record
AOS T1,MSGRCT ;Increment the record count
MOVEM T1,.RECNM(P5) ;Place in the sender record
MOVEI T1,.SENDR ;Record type
MOVEM T1,.RECTY(P5) ;Place in the sender record
IDIVI P1,5 ;Number of words in this record
SKIPE P2 ;A partial word?
AOS P1 ;Yes, count as a full word
ADDI P1,.RECHS ;Include the header size
MOVEM P1,.RECLN(P5) ;Place in the record
ADD P3,P1 ;Add record size to message size
ADD P5,P1 ;Address of the next record
;Pick up the node name and append to sender's name
MOVEI T1,.NDGLN ;Want our node name
MOVEI P1,NODNAM ;Where to place it
HRLI P1,(POINT 7) ;Make into a pointer
MOVEM P1,NODPTR ;Will need it again
MOVEI T2,P1 ;Address of the argument block
NODE ;Get our node name
ERJMP [ SETZM NODNAM ;No node name
JRST CPYFRM ] ;Copy From: string
MOVEI T1,"@" ;Pick up an at sign
DPB T1,Q2 ;Overwrite the zero
MOVE T1,NODPTR ;Point to node name
MOVNOD: ILDB T2,T1 ;Get the next character
IDPB T2,Q2 ;Place in the current buffer
CAIE T2,0 ;Finished?
JRST MOVNOD ;No, continue
;Copy the From: string to the mail file
CPYFRM: MOVE T1,CPYJFN ;JFN of the mail file
MOVE T2,CURPTR ;The string to be written
SETZ T3, ;ASCIZ string
SOUT ;Copy the from string to the mail file
ERJMP .+1 ;Should not happen
MOVE T1,CPYJFN
HRROI T2,[ASCIZ/
To: /]
SETZ T3, ;ASCIZ string
SOUT ;Copy to the mail file
ERJMP .+1 ;Should not happen
RET
;Build the recipient records
;P3 contains the global message word count
;P5 address of current record
BLDRCP: MOVE Q1,CURPT2 ;Point to the start of the current line
MOVE Q2,USRNAM ;Point to current recipient name
MOVE Q3,NUMRPT ;No recipients in current line
MOVEI P4,"," ;For convience
NXTRCD: SETZ P1, ;No bytes in this record yet
SETZM LCLRPT ;Assume local
MOVE T4,P5 ;Address of the current record
ADDI T4,.RECTX ;Address of recipient field
HRLI T4,(POINT 7) ;Make into a pointer
MOVE P6,Q1 ;Save position in case recipient is invalid
NXTCHR: ILDB T2,Q2 ;Get the next character of recipient name
CAIN T2,.CHCNV ;A ^V?
JRST [ ILDB T2,Q2 ;Yes, so get the following character
JRST DEPCHR] ;And deposit it
CAIL T2,"a" ;LOWER CASE?
CAILE T2,"z"
SKIPA
JRST DEPCHR ;Lower case, so deposit it
CAIL T2,"A" ;UPPER CASE?
CAILE T2,"Z"
SKIPA
JRST DEPCHR ;Yes, so deposit it
CAIL T2,"0" ;NUMERIC?
CAILE T2,"9"
SKIPA
JRST DEPCHR ;Yes, so deposit it
CAIE T2,"_" ;UNDERSCORE?
CAIN T2,"." ;PERIOD?
JRST DEPCHR ;Yes, so deposit it
CAIE T2,"$" ;ALLOW DOLLAR SIGNS AND
CAIN T2,"-" ; ALLOW DASHES
SKIPA ;Deposit this character
JRST ENDNAM ;End of the recipient name found
DEPCHR: IDPB T2,T4 ;Place character into recipient record
IDPB T2,Q1 ;Place character into current line buffer
AOS P1 ;Increment the byte count
JRST NXTCHR ;Pick up the next character
;The end of a recipient name has been found
;First check if it is valid
ENDNAM: SKIPN P1 ;Was there a recipient?
JRST [ CAIE T2," " ;No, Another potential recipient?
CAIN T2,","
JRST NXTCHR ;Yes, check it out
MOVE Q1,P6 ;Reset the pointer
JRST LSTRCP] ;No, finished
CAIE T2,"@" ;A node name follows?
JRST CHKLCL ;No, check if local
AOS LCLRPT ;Increment the number of @'s found
JRST DEPCHR ;Pick up the node name
CHKLCL: PUSH P,T2 ;Save the terminating character
SKIPN T1,LCLRPT ;Local recipient?
JRST LCLNAM ;Yes, validate the recipient
CAIE T1,1 ;Valid node name string?
JRST INVUSR ;No, reject this recipient
SETZ T2, ;Make the recipient name ASCIZ
IDPB T2,T4 ;In the recipient record
IDPB T2,Q1 ;VALUSR expects this
AOS P1 ;Increment the record byte count
JRST VALUSR ;Complete the recipient record
LCLNAM: SETZ T2, ;Make the record ASCIZ
IDPB T2,T4
IDPB T2,Q1 ;RCUSR needs the string to be ASCIZ
AOS P1 ;Include in the byte count
MOVX T1,RC%EMO ;Want an exact match
MOVE T2,P6 ;One byte before the recipient name
RCUSR
ERJMP INVUSR ;Assume invalid
TXNN T1,RC%NOM ;Valid user name?
JRST CHKNDEF ;Yes, add node name to user name
;An invalid user. Reset the pointers and the byte count
INVUSR: POP P,T2 ;Pick up the termination character
CAIE T2," " ;Perhaps more recipients?
CAIN T2,","
SKIPA ;Yes, check it out
JRST LSTRCP ;No, finish up
MOVE Q1,P6 ;Restore the pointer to where it was
JRST NXTRCD
;Add a node name, if there is one
CHKNDE: SKIPN NODNAM ;Is there a node name?
JRST VALUSR ;No, so complete the recipient record
MOVEI T2,"@" ;Pick up an AT sign
DPB T2,Q1 ;Place in the current buffer
MOVE T1,NODPTR ;Get pointer to the ASCIZ node name
NXTNCH: ILDB T2,T1 ;Get the next node name character
IDPB T2,Q1 ;Place in the current buffer
CAIE T2,0 ;Finished?
JRST NXTNCH ;No, get the next character
;A valid user has been found. First complete the current recipient record.
VALUSR: AOS T1,MSGRCT ;Increment the record count
MOVEM T1,.RECNM(P5) ;Place in the record
MOVEI T1,.DESTN ;Type of record is recipient (destination)
MOVEM T1,.RECTYP(P5) ;Place in the record
IDIVI P1,5 ;Find the number of words in name
SKIPE P2 ;A partial word?
AOS P1 ;Yes, count as a whole word
ADDI P1,.RECHS ;Include the header size
MOVEM P1,.RECLN(P5) ;Place length into the record
;Check if the current line should be written to the mail file
MOVE AP,Q1 ;Remember position before last comma
DPB P4,Q1 ;Place a comma after the name
MOVEI T1," " ;Append a blank
IDPB T1,Q1 ;To the current line
AOS Q3 ;Increment the recipient count
CAIE Q3,3 ;Need a new line?
JRST CHKLST ;No, check if this is the last recipient
MOVEI T1,15 ;Pick up a carriage return
DPB T1,Q1 ;Overwrite the null
MOVEI T1,12 ;Pick up a line feed
IDPB T1,Q1 ;Place in the current line buffer
MOVEI T1," " ;Add blanks to the start of the new line
MOVNI T2,4 ;Add four blanks
ADDBLK: IDPB T1,Q1 ;Add the next blank
AOJN T2,ADDBLK ;Do the next
SETZ T1, ;Make it ASCIZ
IDPB T1,Q1
MOVE T1,CPYJFN ;Write to the mail file
MOVE T2,CURPTR ;Point to the current line
SETZ T3, ;ASCIZ string
SOUT
ERJMP .+1 ;Should never happen
SETZ Q3, ;Reset current line count
MOVE Q1,CURPTR ;Reset pointer to start of current line
;Check if last recipient
CHKLST: ADD P3,P1 ;Update the message size
ADD P5,P1 ;Point to the next record
POP P,T1 ;Get back the terminating character
CAIE T1," " ;If blank, there may be more
CAIN T1,"," ;IF comma, there may be more
SKIPA
JRST LSTRCP ;The last recipient has been found
;There may be more recipients. Make sure there's still space in this
;message page.
CAILE P3,BUFEND ;Still room?
JRST [ MOVEM Q2,USRNAM ;Update user pointer
MOVEM Q1,CURPT2 ;Update current line pointer
MOVEM Q3,NUMRPT ;Number of recipients on this line
RET] ;Go send off this page to MX
JRST NXTRCD ;Form the next record
;The last recipient has been found. Make sure there was at least one
;valid recipient
LSTRCP: SETOM USRNAM ;Assume no valid users
MOVE T1,MSGRCT ;Get the record count
SKIPE IDNUM ;First time through?
AOS T1 ;No, so no sender record in record count
CAIG T1,1 ;More than just the sender record?
RET ;No, then no valid users
SETZM USRNAM ;Yes, indicate so
MOVE T1,CURPTR ;Start of the current line
CAMN T1,Q1 ;Same as the updated pointer?
JRST OVWCOM ;Yes, overwrite final comma in the file
MOVEI T1,15 ;Overwrite the final comma
DPB T1,AP ;Making the string ASCIZ
MOVEI T1,12 ;Add a line feed
IDPB T1,AP ;Place as the last character
SETZ T1, ;Make it ASCIZ
IDPB T1,AP
MOVE T1,CPYJFN ;Write final line out to the mail file
MOVE T2,CURPTR ;Point to the start of the line
SETZ T3, ;ASCIZ string
SOUT
ERJMP .+1 ;Should not happen
RET
OVWCOM: MOVE T1,CPYJFN ;Pick up the message file JFN
RFPTR ;Find pointer of the file
ERJMP .+1 ;Should not happen
SUBI T2,7 ;Back up to the last comma
SFPTR ;Position the pointer there
ERJMP .+1 ;Should not happen
HRROI T2,[ASCIZ/
/]
SETZ T3, ;ASCIZ string
SOUT ;Write out to the file
ERJMP .+1 ;Should not happen
RET
;Build the subject record.
BLDSUB: MOVE Q1,ARGPTR ;Get the address of the argument block
MOVE T2,1(Q1) ;Get the pointer to the subject line
TLC T2,-1
TLCN T2,-1 ;OF FORM -1,,ADDR ?
HRLI T2,(POINT 7) ;YES, CONVERT TO PDP-10 BYTE POINTER
MOVE Q2,T2 ;Save a copy for the mail file
SETZ P1, ;No bytes in this record yet
MOVE T3,P5 ;Address of this record
ADDI T3,.RECTX ;Address of the subject field
HRLI T3,(POINT 7) ;Make it into a pointer
TRSSUB: ILDB T1,T2 ;Get the next character of the subject
IDPB T1,T3 ;Place in the subject record
AOS P1 ;Increment the byte count
CAIE T1,0 ;Finished?
JRST TRSSUB ;No, continue transferring
;Finish the subject record
AOS T1,MSGRCT ;Increment the record count
MOVEM T1,.RECNM(P5) ;Place in the subject record
MOVEI T1,.SJSTR ;Get the record type
MOVEM T1,.RECTY(P5) ;Place in the record
IDIVI P1,5 ;Get the number of words
SKIPE P2 ;A partial word?
AOS P1 ;Yes, count as a full word
ADDI P1,.RECHS ;Include the header size
MOVEM P1,.RECLN(P5) ;Place in the record
ADD P3,P1 ;Total byte count of message so far
ADD P5,P1 ;Address of the next message
;Copy the subject line to the mail file
MOVE T1,CPYJFN ;Get JFN of the mail file
HRROI T2,[ASCIZ/Subject: /]
SETZ T3, ;ASCIZ
SOUT ;Copy the string to the mail file
ERJMP .+1 ;Should not happen
MOVE T1,CPYJFN ;Get JFN of the mail file
MOVE T2,Q2 ;Pointer to the subject line
SETZ T3, ;ASCIZ
SOUT ;Copy the string to the mail file
ERJMP .+1 ;Should not happen
RET
;Build and place the message ID in the mail file
BLDMID: MOVE T1,CPYJFN ;Get JFN of the message file
HRROI T2,[ASCIZ/
Message-ID: <"ARMAIL" /]
SETZ T3, ;ASCIZ string
SOUT
ERJMP .+1 ;Should not happen
MOVE Q1,CURPTR ;Where to place the message ID
MOVEI Q2,"." ;For convience
GTAD ;Get the current date
CALL CONVRT ;Convert to ASCIZ
IDPB Q2,Q1 ;Add date delimiter
GJINF ;Get the job number and user number
PUSH P,T1 ;Save user number for awhile
MOVE T1,T3 ;Place the job number where CONVRT expects it
CALL CONVRT ;Convert job number to ASCIZ
IDPB Q2,Q1 ;Add job number delimiter
POP P,T1 ;Restore the user number
HRRZS T1 ;Want only the right half
CALL CONVRT ;Convert user number to ASCIZ
IDPB Q2,Q1 ;Add user number delimiter
SETO T1, ;For this job
MOVE T2,[-1,,Q3] ;Place runtime in Q3
MOVEI T3,.JIRT ;Want the run time
GETJI ;Get the run time
SETZ Q3, ;Give zero for an error
HRRZ T1,Q3 ;Want only the right half
CALL CONVRT ;Convert runtime to ASCIZ
MOVEI T1," " ;Separate previous info
IDPB T1,Q1 ;From the node name
MOVEI T2,"a"
IDPB T2,Q1
MOVEI T2,"t"
IDPB T2,Q1
IDPB T1,Q1
MOVE T1,NODPTR ;Get pointer to the node name
NDNAME: ILDB T2,T1 ;Get the next character
IDPB T2,Q1 ;Place in the current buffer
CAIE T2,0 ;Finished?
JRST NDNAME ;No, get the next character
MOVEI T1,">" ;Terminate the string
DPB T1,Q1 ;Overwrite the null
MOVEI T1,15 ;Get a carriage return
MOVEI T2,12 ;And a line feed
IDPB T1,Q1 ;Add a blank line
IDPB T2,Q1
IDPB T1,Q1
IDPB T2,Q1
SETZ T1, ;Make it ASCIZ
IDPB T1,Q1
MOVE T1,CPYJFN ;Get the JFN of the mail file
MOVE T2,CURPTR ;The string to copy
SETZ T3, ;ASCIZ
SOUT ;Copy the string to the mail file
ERJMP .+1 ;This should not happen
CONVRT: IDIVI T1,^D10 ;Pick off a digit
PUSH P,T2 ;Save for awhile
SKIPE T1 ;Finished?
CALL CONVRT ;No, get the next digit
POP P,T1 ;Yes,pick up the next digit from the stack
ADDI T1,"0" ;Make it ASCII
IDPB T1,Q1 ;Place in the buffer
RET
;Place the text into the mail file. Add a delimiter and close the mail file
BLDTXT: MOVE T1,ARGPTR ;Get the argument block
MOVE T2,2(T1) ;Get the pointer to the text
TLC T2,-1
TLCN T2,-1 ;Of form -1,,ADDR ?
HRLI T2,(POINT 7) ;Yes, convert to PDP-10 byte pointer
MOVE T1,CPYJFN ;Get the JFN of the mail file
SETZ T3, ;ASCIZ string
SOUT ;Copy the text to the mail file
ERJMP .+1 ;Should not happen
MOVE T1,CPYJFN ;Get the JFN of the mail file
HRROI T2,[ASCIZ/
--------
/]
SETZ T3, ;ASCIZ
SOUT ;Copy the delimiter over
ERJMP .+1 ;Should not happen
MOVE T1,CPYJFN ;Get the JFN of the mail file
TXO T1,CO%NRJ ;Do not release the JFN
CLOSF ;Close it
ERJMP [RET] ;Can't close the mail file, quit
RETSKP
;Build the file spec record
BLDSPC: SETZ P1, ;No bytes in this record yet
MOVEI T2,FILSPC ;Address of the file spec
HRLI T2,(POINT 7) ;Make into a pointer
MOVE T4,P5 ;Address of the record
ADDI T4,.RECHS ;Address of the file spec field
HRLI T4,(POINT 7) ;Make it into a pointer
TRSFIL: ILDB T1,T2 ;Get the next character
IDPB T1,T4 ;Place in the file spec record
AOS P1 ;Increment the byte count
CAIE T1,0 ;End of the string?
JRST TRSFIL ;No, continue
IDIVI P1,5 ;Find the number of words
SKIPE P2 ;A partial word?
AOS P1 ;Yes, count as a word
ADDI P1,.RECHS ;Include the header size
MOVEM P1,.RECLN(P5) ;Place length in record
AOS T1,MSGRCT ;Increment the record count
MOVEM T1,.RECNM(P5) ;Place in record
MOVEI T1,.FLSPC ;Get record type
MOVEM T1,.RECTY(P5) ;Place in the record
RET
;Send the message page to MX
SNDMX: CALL SNDOFF ;Page is full, send off to MX
RET ;An error occurred, quit
RETSKP ;No errors
;Build the message header record then send off to MX
SNDOFF: MOVEI P5,IPCPGS ;Address of header record
MOVEI T1,.POST ;Assume first page
SKIPE IDNUM ;First page?
MOVEI T1,.CONT ;No, indicate so
MOVEM T1,.PKTYP(P5) ;Place in the header record
MOVE T1,IDNUM ;Pick up the message ID
MOVEM T1,.PKID(P5) ;Place in the message
AOS T1,MSGNUM ;Increment the message page number
MOVEM T1,.PKSEQ(P5) ;Place in the message
MOVEI T1,.DONE ;Assume no more pages
SKIPN PAKSTS ;Is this true?
MOVEI T1,.MORE ;No, more to follow
MOVEM T1,.PKSTS(P5) ;Store in the message
MOVE T1,MSGRCT ;Pick up the number of records
MOVEM T1,.PKRCT(P5) ;Place in the message
;Send the message off to MX
MOVX T1,IP%CFV ;Page mode
MOVEM T1,PDB+.IPCFL ;Place in the flag word
MOVE T1,MYPID ;Pick up our PID
MOVEM T1,PDB+.IPCFS ;Place in the sender word
MOVE T1,MLRPID ;Pick up MX' PID
MOVEM T1,PDB+.IPCFR ;Place in the receiver word
MOVEI T1,IPCPGS ;Address of the message
LSH T1,-^D9 ;Change to page number
HRLI T1,1000 ;Size of the message
MOVEM T1,PDB+.IPCFP ;Place in the packet address word
MOVEI T1,4 ;Size of the packet descriptor block
MOVEI T2,PDB ;Address of the PDB
MSEND ;Send the message to MX
ERJMP GIVUP ;Can't, so give up
;Get the reply from MX
MOVEI Q1,10 ;Retry count
MOVX T1,IP%CFB!IP%CFV ;Do not block, expecting a page
MOVEM T1,PDB+.IPCFL ;Store in the flag word
MOVE T1,MYPID ;Pick up our PID
MOVEM T1,PDB+.IPCFR ;Place in the receiver word
NOTFMX: SETZM PDB+.IPCFS ;INFO will fill in the sender's PID
TRYMOR: MOVEI T1,4 ;Length of the PDB
MOVEI T2,PDB ;Address of the PDB
MRECV ;See if we have a message
ERJMP [ SOJLE Q1,GIVUP ;Time to give up?
MOVEI T1,^D1000 ;No, sleep a second
DISMS
JRST TRYMOR] ;Try again
MOVE T1,PDB+.IPCFS ;Get the PID of the sender
CAME T1,MLRPID ;From MX?
JRST NOTFMX ;Try again
HRRZ P5,PDB+.IPCFP ;Get the message page number
LSH P5,^D9 ;Make it into an address
MOVE T1,.PKSTS(P5) ;Get the status word
CAIN T1,.STABD ;Did MX abort it?
JRST GIVUP ;Yes, give up
SKIPE PAKSTS ;More pages to follow
JRST FINSND ;No, return success
;Set up for the next page
MOVE T1,.PKID(P5) ;Get the message ID
MOVEM T1,IDNUM ;Save for later
SETZM MSGRCT ;No records yet in this message
MOVEI P3,.HDRSZ ;Global word count for this message
MOVEI P5,IPCPGS+.HDRSZ ;Address of the current record
FINSND: RETSKP
GIVUP: RET
REP 12/15 ;15C19
JFCL
RET
;Some hacks to not need MACREL
WIT
ERJMP .+1
RET
; Routine to save and restore the AC's.
SAVACS: MOVEM P,SAVAC+17 ; Save all accumulators
MOVEI P,SAVAC
BLT P,SAVAC+16
MOVE P,SAVAC+17 ; Get back the stack pointer
POP P,T3 ; Get the return address
MOVEM P,SAVAC+17 ; Save original stack before call to ARMAIL
PUSH P,[SVACRT] ; Routine to restore the accumulators
PUSH P,T3 ; Go back to caller of this routine
RET
SVACRT: SKIPA ; If RET return, skip adding to the PC
AOS SAVAC+17 ; RETSKP
MOVSI P,SAVAC ; Restore the accumulators
BLT P,P
RET
;Some hacks do not need MACREL
SUM 63701