Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_SRC_3_19910112 - mm/reply.mac
There are 2 other files named reply.mac in the archive. Click here to see a list.
;[SRI-NIC]SRC:<MM>REPLY.MAC.17, 22-Aug-85 14:15:41, Edit by MKL
;at STOP do PRARG% to kill fork
;[SRI-NIC]SRC:<MM>REPLY.MAC.6, 16-Aug-85 21:24:52, Edit by MKL
;[NIC1] Scan backwards until we find a last send 
;  from a user with a different user name than our own.

	TITLE REPLY - Reply to last terminal message
	SUBTTL Frank M. Fujimoto

	SEARCH MONSYM,MACSYM
	.REQUIRE SYS:MACREL
	.TEXT "REPLY/SAVE"	;Save as REPLY.EXE
	ASUPPRESS

	VMAJOR==5
	VMINOR==3
	VEDIT==5
	VWHO==0

	COMMENT \

REPLY is a program designed for use with the Stanford Tops-20 SEND
protocol.  It looks at the user's SENDS.TXT in the login directory,
and from that determines the last sender of a terminal message.
From that information it will set up JCL and run SEND.

If the last message was from a local sender, REPLY will attempt to
send to the terminal number of the sender.  If that terminal is no
longer in use by the same user, REPLY will send to the username.

	\
SUBTTL Definitions

A=:1				;Scratch ACs
B=:2
C=:3
D=:4
PT=:5				;Byte pointer
LP=:6				;Loop for finding last sender
DBYTE=:14			;To do 'dldb'
FP=:15				;Frame pointer for TRVAR
CX=:16				;Scratch for MACREL
P=:17				;Stack pointer

	SNDPAG==10		;Map SENDS.TXT to this page
SNDADR==SNDPAG*1000

	PDLEN==100		;Length of push down stack
	BUFLEN==50		;Length of directory string buffer
	JCLLEN==300		;Most that can be put in JCL
	TRASHL==100		;Length of trash buffer
	INBUFL==240		;Length of input buffer
	OVRBFL==10		;Modest overflow buffer

	.PSDES==540000		;Designator for ps dir number
SUBTTL Impure storage

PDL:	BLOCK PDLEN		;Push down stack
BUFFER:	BLOCK BUFLEN		;To hold directory string
RECPT:	BLOCK BUFLEN		;Recipient string (TTY number usually)
RSITE:	BLOCK BUFLEN		;And the site it should go back to
RNAME:	BLOCK BUFLEN		;Pretty name or zero for net sends
SNDJCL:	BLOCK JCLLEN		;To be sent to SEND.EXE
TRASH:	BLOCK TRASHL		;To hold trash
INBUF:	BLOCK INBUFL		;Input buffer length
OVRBUF:	BLOCK OVRBFL		;Overflow buffer
GTJBLK:	BLOCK .JIMAX		;For GETJI
SNDPTR:	BLOCK 1			;Hold pointer for SNDJCL
JCLPTR:	BLOCK 1			;Point to JCL for SEND.EXE
JFN:	BLOCK 1			;Hold JFN for SENDS.TXT
BYTCNT:	BLOCK 1			;Number of bytes in file
PAGCNT:	BLOCK 1			;Number of pages in file
WHOSND:	BLOCK 1			;Who sent to us?
OURUNO:	BLOCK 1			;[NIC1] Our user number
SAVEPT:	BLOCK 1			;[NIC1] saved file pointer
SAVELP:	BLOCK 1			;[NIC1] saved last byte count
SUBTTL Macros

DEFINE EMSG (STRING) <		;;Like TMSG but does an ESOUT% instead
	HRROI A,[ASCIZ\String\]
	ESOUT%
>

DEFINE UPCASE (AC) <		;;Uppercase a letter
	CAIL AC,"a"
	 CAILE AC,"z"
	  CAIA
	   SUBI AC,"a"-"A"
>

DEFINE MATCH (AC,STRING) <	;;See if what AC points to matches string
				;;Will leave updated pointer to AC in A
				;;Returns +1 if no match, +2 if match
	CALL [	SAVEAC <B,C,D>
		MOVE A,AC	;;Get the ac here
		MOVE B,[POINT 7,[ASCIZ\STRING\]]
		JRST DOMATC ]	;;Go call handler routine
>
	      
DOMATC:	ILDB C,B		;Get a byte from the literal
	UPCASE C		;Make sure it's upper case
	JUMPE C,RSKP		;If it's a null, then we win, return +2
	ILDB D,A		;Get a byte from SENDS.TXT
	UPCASE D		;Make sure it's upper case
	CAMN C,D		;Do the two match?
	 JRST DOMATC		;Yes, get next pair of characters otherwise
	RET			;No match, return +1
SUBTTL Main program

EVEC:	JRST START
	JRST START
	BYTE (3)VWHO (9)VMAJOR (6)VMINOR (18)VEDIT
EVECL==.-EVEC

START:	RESET%			;Initialize things
	MOVE P,[IOWD PDLEN,PDL]	;Set up stack pointer
	GJINF%			;[NIC1]
	MOVEM A,OURUNO		;[NIC1]
	CALL GETJCL		;Get arguments from command line
	CALL FILE		;Open up SENDS.TXT
;[NIC1] initial pointer setup from GETSND stuck here instead
	MOVE A,[POINT 7,SNDADR]	;Pointer to file
	MOVE PT,BYTCNT		;Get how many bytes in file
	ADJBP PT,A		;Point to end of file, pointer now in PT
SSNDR:				;[NIC1]
	CALL GETSND		;Get pointer to start of last send
	MOVEM PT,SAVEPT		;[NIC1] remember where we were
	MOVEM LP,SAVELP		;[NIC1] remember byte count also
	CALL GETINF		;Find out who to send it to, tell user
	SKIPE RSITE		;[NIC1] Network send?
	 JRST FSNDR		;[NIC1] Yes, must be a different user then
	MOVX A,RC%EMO		;[NIC1] Require exact match
	HRROI B,RNAME		;[NIC1] Get name
	SETZ C,			;[NIC1] No stepping
	RCUSR%			;[NIC1] Translate user name
	TXNE A,RC%NOM		;[NIC1] Match?
	 JRST FSNDR		;[NIC1] No, then found a sender
				;[NIC1] This shouldn't happen if sender
				;[NIC1] wasn't local then must be net and
				;[NIC1] shoulda been caught above
	CAME C,OURUNO		;[NIC1] Is this us?
	 JRST FSNDR		;[NIC1] No, then send to her (we wish)
	MOVNI PT,5		;[NIC1] Go back in time a little
	ADJBP PT,SAVEPT		;[NIC1] get back saved position minus some
	MOVE LP,SAVELP		;[NIC1] get back saved byte count and update
	SUBI LP,5		;[NIC1] back it up
	MOVEM LP,BYTCNT		;[NIC1] save
	JRST SSNDR		;[NIC1] Keep searching...
FSNDR:	CALL CHKLOG		;Check if user is still there
	CALL PUTJCL		;Put JCL so sender program can see it
	CALL UNMAP		;Get rid of map to SENDS.TXT

	MOVX A,GJ%SHT!GJ%OLD	;Short form, old file
	HRROI B,[ASCIZ\SYS:SEND.EXE\]
	GTJFN%			;For SEND.EXE
	 ERCAL ERROR
	HRLI A,.FHSLF		;For this process
	MOVE D,A		;Save it
	SETO A,			;Unmapping
	MOVX B,<.FHSLF,,0>	;From the top
	MOVX C,PM%CNT!777	;To the bottom
	DMOVE 5,[  PMAP%	; 5  Unmap
		   MOVE A,D ]	; 6  Get back GET% argument
	DMOVE 7,[  GET%		; 7  Map file into ourself
		   MOVEI A,.FHSLF ] ; This process
	DMOVE 11,[ SETZ B,	; 11 Main entry point
		   SFRKV% ]	; 12 Start ourself
	JRST 5			;Do it in ACs
SUBTTL GETJCL - Process input line

GETJCL:	MOVE PT,[POINT 7,INBUF]	;Buffer for what was typed in
	MOVEI A,.RSINI		;Initialize RSCAN buffer
	RSCAN%			;Do it
	 ERCAL ERROR
	IFE. A
	  MOVEI B,.CHLFD	;Nothing there, get a linefeed
	  IDPB B,PT		;Drop it in
	  JRST JCLSND		;Go finish off JCL
	ENDIF.
	MOVNM A,C		;Save this in the register SIN% wants it in
	SUBI A,INBUFL*5-1	;Sub maximum chars we can have + 1
	MOVEM A,D		;And safely away in d
	MOVEI A,.PRIIN		;Want to get from tty input
	HRROI B,INBUF		;-1,,input buffer
	SKIPL D			;Was actual chars .ge. max chars?
	 MOVNI C,INBUFL*5-2	;Then only fill up the buffer
	SIN%			;Input the characters
	IFGE. D			;If chars left is negative, it's a safe size
	  IFE. D		;If it's = 0, then it just fits, needs a LF
	    PBIN%		;Input the lf at the end of the line
	  ELSE.
	    PUSH P,B		;Save buffer pointer
	    AOS D		;Truly reflect how many chars left in buffer
	    HRROI B,OVRBUF	;Going to overflow buffer
	    MOVN C,D		;Get -how many over characters
	    SUBI D,OVRBFL*5	;Get how many chars will be left if it's
				;larger than the overflow buffer
	    SKIPL D		;If buffer .lt. overflow buffer
	     MOVNI C,OVRBFL*5	;Make it the max number of chars then
	    SIN%		;Input for overflow buffer
	    IFG. D		;If it's within our buffer, output now
	    MOVNI C,OVRBFL*5	;SOUT% can only output this many chars
	    ELSE.
	      MOVEI A,.CHNUL	;Get a null
	      DPB A,B		;It's our terminating character
	      SETZ C,		;We're going until a null byte on the SOUT%
	    ENDIF.
	    TMSG <%Message too long, truncating ">
	    MOVEI A,.PRIOU	;To tty
	    CFIBF%		;Clear the output buffer
	    HRROI B,OVRBUF	;To our overflow buffer
	    SOUT%		;Output the overflow
	    SOSG D		;Account for LF, if it wasn't within buffer...
	    IFSKP.
	      TMSG <...>	;Say that it continues
	    ENDIF.
	    TMSG <"
    >				;End truncating message
	    POP P,B		;Get back pointer
	  ENDIF.
	  MOVEI A,.CHLFD	;Finish JCL off with a linefeed
	  IDPB A,B		;Deposit it
	ENDIF.
	SETZ C,			;Get a null
	IDPB C,B		;So we can tie off jcl with it
	DO.
	  ILDB A,PT		;get a byte
	  CAIE A,.CHCRT		;Carriage return?
	   CAIN A,.CHLFD	;or linefeed?
	    IFSKP.
	      CAIE A," "	;If a space, then use 'to'
	       LOOP.		;If neither, get more junk
	      MOVEM PT,JCLPTR	;Save pointer for later
	    ELSE.
JCLSND:	      SETO A,		;Decrement pointer
	      ADJBP A,PT	;Do it
	      MOVEM A,JCLPTR	;Save pointer for the line feed
	    ENDIF.
	ENDDO.
	HRROI A,SNDJCL		;Destination send JCL
	HRROI B,[ASCIZ\SEND \]	;Add program name
	SETZ C,			;Ending on null
	SOUT%			;Do it
	MOVEM A,SNDPTR		;Save pointer to SNDJCL
	RET
SUBTTL FILE - Open up SENDS.TXT to get last send

FILE:	GJINF%			;User number in A
	MOVE B,A
	HRLI B,.PSDES		;Make a PS dir number
	HRROI A,BUFFER		;Pointer to directory name buffer
	DIRST%			;Make a directory string
	 ERCAL ERROR
	HRROI B,[ASCIZ\SENDS.TXT\] ;Looking for this file
	SETZ C,			;End on null
	SOUT%			;Append filespec
	IDPB C,A		;Make sure null at end
	MOVX A,GJ%SHT!GJ%OLD	;Short form, old file
	HRROI B,BUFFER		;File spec
	GTJFN%			;Get a handle
	IFJER.
	  EMSG <No last send>
	  JRST STOP
	ENDIF.
	HRRZM A,JFN		;Save the jfn
	MOVE B,[FLD(7,OF%BSZ)!OF%RD] ;Text, reading
	OPENF%			;Open it
	 ERCAL ERROR
	SIZEF%			;Find out how big it is
	 ERCAL ERROR
	IFE. B
	  EMSG <No last send>
	  JRST STOP
	ENDIF.
	MOVEM B,BYTCNT		;Save byte count
	HRLZ A,JFN		;From file, first page
	MOVE B,[.FHSLF,,SNDPAG]	;Where to map it
	MOVEM C,PAGCNT		;Store for unmapping
	HRLI C,(PM%CNT!PM%RD)	;Multiple page PMAP, read access
	PMAP%			;Map file in
	RET
SUBTTL GETSND - Make pointer to start of send in PT

GETSND:	SOS LP,BYTCNT		;Get number of bytes - 1 into LP
	DO.
	  SETO DBYTE,		;decrement byte pointer
	  ADJBP DBYTE,PT
	  MOVE PT,DBYTE		;Get updated pointer into 'pointr'
	  LDB B,PT		;Get the byte
	  SOS LP		;Subtract one from count of chars seen
	  CAIN B,.CHESC		;Escape (delimiter of sends in file)?
	  IFSKP.
	    JUMPG LP,TOP.	;No, but still more chars, go ahead and loop
	   JRST [EMSG <No last send>	;[NIC1] Back too much?
	         JRST STOP]
;[NIC1]	    JRST BADFIL		;Else complain
	  ENDIF.
	  ILDB A,DBYTE		;Next char
	  CAIE A,.CHCRT		;Carriage return?
	   LOOP.
	  ILDB A,DBYTE		;Finally, need
	  CAIE A,.CHLFD		;A linefeed
	   LOOP.
	ENDDO.
	MOVE PT,DBYTE		;Save this as our real pointer, then
	RET			;All done
SUBTTL GETINF - Decide who to reply to 

GETINF:	SETZM RECPT		;No real recipient as yet
	SETZM RNAME		;Or pretty name
	SETZM RSITE		;Or site name
	MOVE A,[POINT 7,RNAME]	;Pointer to pretty name
	MOVE B,PT		;And start of message
	DO.
	  CALL CPYDLM		;Copy until delimiter
	  MOVEM A,PT		;Save pointer for later
	  CAIN C,","		;Comma?
	   JRST GCOMMA		;Yes, go process
	  CAIE C,"@"		;At-sign?
	  IFSKP.
	    MOVE A,B		;Yes, get pointer in different place
	    EXIT.
	  ENDIF.
	  CAIE C," "		;Space?
	   JRST BADFIL		;Confusing file format, give up
	  MATCH B,<at >		;Start of host?
	  IFNSK.
	    MOVE A,PT		;No, get pointer back
	    IDPB C,A		;Drop space in
	    LOOP.
	  ENDIF.
	ENDDO.
	SETZ C,			;Get a null
	IDPB C,PT		;And drop it in to RNAME
	PUSH P,A		;Save pointer to site name
	HRROI A,RECPT		;Get recipient pointer
	HRROI B,RNAME		;And name we have
	SOUT%			;Copy across
	SETZM RNAME		;Forget we had a pretty name
SSITE:	POP P,B			;Get site name pointer back
	MOVE A,[POINT 7,RSITE]	;And where it belongs
	CALL CPYDLM		;Copy until delimiter (don't care which)
	SETZ C,			;Get a null
	IDPB C,A		;Drop it in
	RET

GCOMMA:	MATCH B,< tty>		;Terminal number coming up next?
	IFNSK.
	  SETZ C,		;Nope, that must be all
	  IDPB C,PT		;Drop in a null
	  RET
	ENDIF.
	MOVE B,A		;Get source in its proper place
	MOVE A,[POINT 7,RECPT]	;Get place to put tty number
	DO.
	  ILDB C,B		;Get next byte
	  CAIL C,"0"		;Is it too small
	   CAILE C,"7"		;Or too large to be an octal digit?
	    EXIT.		;Yes, done
	  IDPB C,A		;Else drop it in
	  LOOP.
	ENDDO.
	SETZ D,			;Get a null
	IDPB D,A		;And finish it off
	CAIN C,","		;Comma?
	 RET
	CAIE C,"@"		;Is it an at-sign?
	IFSKP.
	  PUSH P,B		;Yes, save pointer
	  JRST SSITE
	ENDIF.
	CAIE C," "		;Is it a space?
	 RET			;No, must be finished
	MATCH B,<at >		;Site name following?
	 RET			;No, all done
	PUSH P,A		;Save pointer to site name
	JRST SSITE		;And go copy site name
; CPYDLM - Copy from B to A until a delimiter (returned in C, not added to A)

CPYDLM:	ILDB C,B		;Get next char
	JUMPE C,R		;Stop for null
	CAIE C," "		;Space
	 CAIN C,","		;or comma?
	  RET
	CAIE C,.CHCRT		;Carriage return
	 CAIN C,.CHLFD		;or linefeed?
	  RET
	CAIE C,.CHTAB		;Tab
	 CAIN C,"@"		;or at-sign?
	  RET
	IDPB C,A		;None of the above, drop char in
	JRST CPYDLM		;Loop back for the next
SUBTTL CHKLOG - Make sure user is still logged in to given TTY

CHKLOG:	SKIPE RSITE		;Net send?
	 RET			;Yes, no way to check it
	STKVAR <USRNUM>
	SETZM USRNUM		;No user num as yet
	MATCH <[POINT 7,RNAME]>,<not logged in>
	IFNSK.
	  MOVX A,RC%EMO		;Require exact match
	  HRROI B,RNAME		;Get pretty name
	  SETZ C,		;No stepping
	  RCUSR%		;Read user name
	  TXNE A,RC%NOM		;Was it matched?
	   RET
	  MOVEM C,USRNUM	;Save user number
	ENDIF.
	HRROI A,RECPT		;Get pointer to recipient terminal number
	MOVEI C,^D8		;Radix octal
	NIN%			;Read in the number
	 ERCAL ERROR
	MOVEI A,.TTDES(B)	;Turn into terminal designator
	HRROI B,D		;One word, into D
	MOVEI C,.JIUNO		;Read in user number
	GETJI%			;Find out who there
	 ERCAL ERROR
	CAME D,USRNUM		;Was it the user number we expected?
	IFSKP.
	  JUMPN D,R		;and real user
	  JUMPGE B,R		;or someone there?
	  TMSG <TTY>		;No, start message
	  HRROI A,RECPT		;Get terminal number
	  PSOUT%		;Type it
	  TMSG < is no longer active.>
	  JRST STOP
	ENDIF.
	SKIPN USRNUM		;Did we have a user number?
	 JRST NOWUSR		;No, but there's someone there now!
	HRROI A,RNAME		;Get pretty name (all we have left now)
	PSOUT%
	TMSG < is no longer at TTY>
	HRROI A,RECPT		;Get no-good terminal
	PSOUT%			;Add that too
	TMSG <
>
	HRROI A,[ASCIZ/Sending to username instead [Confirm] /]
	CALL CONFRM		;Ask user to say yes
	 JRST ABTSND
	SETZM RECPT		;No terminal number any more
	RET

NOWUSR:	TMSG <TTY>
	HRROI A,RECPT		;With given tty number
	PSOUT%			;Added to the string
	TMSG < now in use by >
	MOVEI A,.PRIOU		;To terminal
	MOVE B,D		;With user number we got back
	DIRST%			;Translate user number to string
	 ERCAL ERROR
	TMSG <
>
	HRROI A,[ASCIZ/Sending there anyway [Confirm] /]
	CALL CONFRM		;Make sure we want to send there
	 JRST ABTSND
	HRROI A,RNAME		;Get pointer to pretty name
	MOVE B,D		;And user there again
	DIRST%			;Translate again
	 ERCAL ERROR
	RET

ABTSND:	EMSG <Not confirmed, send aborted>
	JRST STOP
; CONFRM - Ask for carriage-return confirmation
; returns +1/not confirmed, +2/confirmed

CONFRM:	MOVE C,A		;Copy pointer
	PSOUT%			;Type it out for first time through
	HRROI A,TRASH		;Put input line here as as good a place as any
	MOVEI B,TRASHL*5-1	;Maximum length of trash buffer
	RDTTY%			;Get confirmation
	 ERCAL ERROR
	HRRZS B			;Clear flag bits
	CAIN B,TRASHL*5-3	;See if two less due to CRLF
	 RETSKP			;Skip on confirmation
	RET
SUBTTL PUTJCL - Put JCL so send can see it

PUTJCL:	TMSG < Replying to >
	MOVE A,SNDPTR		;Get pointer back
	SETZ C,			;All SOUTs end on nulls
	SKIPE RECPT		;Are we trying for a username?
	IFSKP.
	  HRROI B,RNAME		;Yes, get it back
	  SOUT%			;Send it off
	  MOVEM A,SNDPTR	;Save again
	  HRROI A,RNAME		;Get name again
	  PSOUT%		;Type it
	ELSE.
	  HRROI B,RECPT		;Get recipient
	  SOUT%			;Add to JCL
	  MOVEM A,SNDPTR	;Save pointer
	  SKIPN RNAME		;If no pretty name
	  IFSKP.
	    HRROI A,RNAME	;Get pretty name
	    PSOUT%		;Type it
	    TMSG <, TTY>	;Separate from real recipient
	  ENDIF.
	  HRROI A,RECPT		;Get recipient
	  PSOUT%		;Type that too
	  SKIPN RSITE		;Is there a site to send this to?
	  IFSKP.
	    MOVE A,SNDPTR	;Get pointer back
	    MOVEI B,"@"		;Get an at-sign
	    IDPB B,A		;Drop it in
	    HRROI B,RSITE	;Now get pointer to site name
	    SOUT%		;Add it to jcl
	    MOVEM A,SNDPTR	;Save updated pointer
	    TMSG < at >		;Pretty at-sign
	    HRROI A,RSITE	;And site name
	    PSOUT%		;Type it
	  ENDIF.
	ENDIF.
	TMSG <
>				;Finish "Replying to ..." message
	MOVE A,SNDPTR		;Get pointer back once more
	MOVEI B," "		;Space for luck
	IDPB B,A		;Drop it in
	MOVE B,JCLPTR		;And pointer to rest of JCL
	SOUT%			;Finish off jcl
	HRROI A,SNDJCL		;Get jcl for SEND.EXE
	RSCAN%			;Put it in RSCAN buffer
	 ERCAL ERROR
	RET
SUBTTL UNMAP - Cleans up SENDS.TXT

UNMAP:	SETO A,			;-1
	MOVE B,[.FHSLF,,SNDPAG]	;Where to unmap from
	MOVX C,PM%CNT		;Multiple page unmap
	HRR C,PAGCNT		;Number of pages to unmap
	PMAP%			;Unmap the file
	MOVE A,JFN		;Get the JFN back
	CLOSF%			;Close the file
	 ERCAL ERROR
	RET
subttl error handler

ERROR:	EXCH A,(P)		;Save a register, put pushed loc in A
	PUSH P,B
	PUSH P,C
	MOVEI B,-2(A)		;Point back to JSYS
	EMSG <Error at >	;Start error message
	MOVEI A,.PRIOU		;To terminal
	MOVEI C,^D8		;Octal
	NOUT%			;Output location
	 NOP
ERROR0:	TMSG < - >
	MOVEI A,.PRIOU		;To terminal again
	HRLOI B,.FHSLF		;With last error on our own fork
	SETZ C,			;No limit on how many chars to type
	ERSTR%			;print error string
	 NOP			;Undefined error number
	 NOP			;Other error
	POP P,C			;Get back registers for examination
	POP P,B
	POP P,A
STOP:	Move 1,[.PRAST,,.FHSLF]
	Movei 2,4
	Movei 3,1
	Movsi 4,2		;kill fork
	PrArg%
	HALTF%			;Stop
	EMSG <Can't continue>
	JRST STOP

BADFIL:	EMSG <Bad format for SENDS.TXT>
	JRST STOP

	END <EVECL,,EVEC>