home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
PACKET
/
RLI120.ARK
/
MAIL.MAC
< prev
next >
Wrap
Text File
|
1987-05-11
|
24KB
|
1,107 lines
; MAIL.MAC - 5/11/87 - The MailBox.
.z80
maclib TNC.LIB
entry klmsg1,klmsg2,klmsg3,rdmsg1,rdmsg2,rdmsg3
entry msnoop,mplsno,logmnr
entry smsg1,smsg2,smsg3,smsg4,smsg5,smsg6,smsg7
entry wthdr,opnmsg,clsmsg,filmsg,lstmsg
entry newmsg,getto,change,firmsg,phdr,prtmsg,kmsg
entry svcmsg,mfcb,mbfcb,msgfcb,mrec
entry mm1,mm2,mm3,mm4,mm5,mm6,mm15
entry btchm,ucmax,ucalls,uccnt
external mfhs,mfhsl,mfhd,mlhd,mffree,mlfree,mnr
external mvers,mfree,mcnt
external tmfhs,tmnext,tmfhd,tmlhd,tmffree,tmlfree,tmnr
external tmfree,tmcnt
external mhprev,mhcur,msgnr
external mmhs,mhtitl,mhfmsg,mhlmsg,mhnext,mhnr,mhsize
external mhtype,mhstat,mhto,mhbbs,mhfrom,mhdate,mhtime
external mhread,mhtit,mhext,mmts,mtitle,mtnext,mttext
external rcv,div8,muldec,mcall,ocall,scall
external usport,usopt,usosys,usoexa,usoexb
external curtime,log,event,logtxt,date,time
external fcb,fcb1,fcb2,fcb3,opt1,opt2
external flds,f1l,f1st,f2l,f2st,f3l,f3st,f4l,f4st
external f5l,f5st,f6l,f6st,f7l,f7st
external movcal,cmd,cmdlen
external decbin,bindec,numb,@move,@upper,@fill,@mcmd
external @openr,@openw,@opena,@openn,@closew
external @ntobuf,@ctobuf
external ckname,rdcmd,fmbuf,tobuf,rfcb,wfcb,setb7
external @outch,@prtx,@cmp
external @src,@srct,@srcl,@srcn,@srcw,@srcc
external usmnr,unt,pause,waitc,iscall
external addcr0,getcmd,getdat,cmdtyp,$memry
external ername,erfind,ercant,erprot,erdone,erwhat
asciictl
bdosdef
tncdefs
timdef
btchm equ 120 ; Max length of beacon text
dseg
change: ds 1 ; True if mail file changed (send/kill)
; File control blocks.
mfcb: ds fcbsize
mrec equ mfcb+33
mbfcb: ds fcbsize
msgfcb: ds fcbsize
ver: ds 1
; Open (or create and open) the mail file.
; Allocate memory for call lists.
cseg
opnmsg: movw ucalls,$memry
ld de,(ucmax)
ld c,6
call muldec
add hl,de
ld ($memry),hl
dodosa setdma,mfhs
ld hl,mbfcb+10
call setb7 ; Set $sys attribute
ld hl,mfcb+10
call setb7 ; Set $sys attribute
dodosa open,mfcb
inc a
jr z,opnma
movb ver,mvers ; Save current version
dodosa read,mfcb
ld hl,ver
ld a,(mvers)
cp (hl) ; Is file current version?
jr z,opnmb ; Yes
mvim opt2,' ' ; Make sure no renumber
call unt ; Let untangle fix it
movb mvers,ver ; Set current version
jr opnmb
opnma: dodosa make,mfcb ; Make a mail file
call wtmfhs ; Write a blank file header
opnmb: call getto
ret
; Close the mail file.
clsmsg: dodosa close,mfcb
ret
; General "bad status" return. Returns zero flag cleared.
; Can inspect cmdtyp to find out what happened.
badret: retnz
; Check permission for the operation:
; Message to or from user, or user is system owner.
; Return zero set if permission ok.
permit: ld a,(usopt)
and usosys
jr z,pera
xor a
ret ; With zero set
pera: comp mcall,mhto,6
ret z
comp mcall,mhfrom,6
ret
; See if mail is to or from this user, or he is sysop.
; If not, see if it is to a real callsign.
; If so, then user is snooping on someone's mail
; (unless it is T or B type mail),
; so broadcast that fact to the world.
snoopq: call permit ; To or from him, or is sysop?
jr z, snoopn ; If so, no problem
ld hl, mhto ; No. See if is TO a real callsign
call iscall
jr c, snoopn ; If not, like to ALL, anyone can read it
cmpm mhtype,'T' ; Real callsign. NTS traffic msg?
jr z, snoopn ; OK, that's not really snooping
cmpm mhtype,'S' ; NTS service msg?
jr z, snoopn ; Allow that
cmpm mhtype,'B' ; Bulletin to someone?
jr z, snoopn ; That's OK, too.
prtx msnoop ; But if someone else's real mail, gripe.
or 0ffH ; and return NZ
ret
snoopn: xor a ; If ok, return Z
ret
; Make list of calls with unread messages.
; Construct a beacon line from that list.
dseg
msnoop: ds 2 ; Msg to fink on mail snooper
mplsno: ds 2 ; Msg to ask not to S while *** linked
lktflg: ds 1 ; Flag for Linked Send filtering
temp: ds 2
uccnt: ds 2 ; Count of calls mail for
ucalls: ds 2 ; Address of list of calls mail for
ucmax: ds 2 ; Max calls in unread mail list
cseg
getto: dodosa setdma,mmhs
movw temp,ucalls
lxim uccnt,0
movw mrec,mlhd
gettoa: dtz mrec
ret z
dodosa rrec,mfcb
cmpm mhstat,'N' ; Message read or forwarded yet?
jp nz,gettoc ; Yes
cmpm mhbbs,' ' ; Destination bbs specified?
jr z,gettob ; No
comp mhbbs,ocall,6 ; Is it us?
jr z,gettob ; Yes, put user call in list
; Destination bbs specified, it is not us,
; put the bbs call in the list, leave the user call out.
zmov scall,mhbbs,6
ld a,(scall)
or 80h ; Set B7 to indicate bbs not user
ld (scall),a
srclst scall,ucalls,uccnt,6,6
jr z,gettoc ; Destination bbs already on list
ld hl,(temp)
move ,scall,6 ; Add destination bbs to list
ld (temp),hl
inxm uccnt
ld de,(ucmax)
or a ; Clear carry
sbc hl,de
ret z ; List now full
jr gettoc ; Next msg
; Put the users call in the list.
gettob: srclst mhto,ucalls,uccnt,6,6
jr z,gettoc ; User already on list
ld hl,(temp)
move ,mhto,6 ; Add user to list
ld (temp),hl
inxm uccnt
ld de,(ucmax)
or a ; Clear carry
sbc hl,de
ret z ; List now full
gettoc: movw mrec,mhprev
jp gettoa
; Print the current message.
prtmsg: dodosa setdma,mmts
movw mrec,mhfmsg
prmsga: dtz mrec
ret z
dodosa rrec,mfcb
ld hl,mttext
ld e,126
prmsgb: ld a,(hl)
cp eof
ret z
ld c,a
call @outch
inc hl
dec e
jr nz,prmsgb
movw mrec,mtnext
call pause
jr prmsga
dseg
mtcnt: ds 1
mtptr: ds 2
tmhsz: ds 2
tmhlms: ds 2
tmhnx: ds 2
tmhpr: ds 2
mtemp: ds 128
cseg
; Allocate a mail file record.
alloc: dtz tmffree ; Any in free chain?
jr nz,alloca ; Yes, allocate the next one
inxm tmnext ; Allocate next at end of file.
dec hl
ret
alloca: ld (mrec),hl ; Rec # of first in free chain.
dodosa setdma,mtemp ; Read into temp buffer
dodosa rrec,mfcb
movw tmffree,mtemp ; New first in free chain
dcxm tmfree ; Decrement count of free records
ld a,l
or h
jr nz,allocb ; More free records
lxim tmlfree,0 ; No free records left
allocb: ld hl,(mrec) ; Rec #
ret
; Get new msg text record. Chain current to it. Write current.
newbuf: push de
push bc
ld hl,(mhlmsg) ; Save pointer to current record
push hl
call alloc ; Get new record
ld (mtnext),hl ; New is next from current
ld (mhlmsg),hl ; New is also last
pop hl ; Pointer to current
ld (mrec),hl ; Point IO to correct record
dodosa setdma,mmts ; Point IO to buffer
dodosa wrec,mfcb ; and write it
lxim mtnext,0 ; Mark new as end of chain
lxim mtptr,mttext ; Init pointer into buffer
mvim mtcnt,126 ; Init count to data size
pop bc
pop de
ret
; Make message header info string.
dseg
mm6: ds 2
firmsg: ds 1
cseg
mkhdr: ld hl,(mhnr)
call bindec
ld hl,($memry)
move ,numb+1,4
ld (hl),' '
inc hl
ld a,(mhtype)
ld (hl),a
inc hl
ld a,(mhstat)
ld (hl),a
inc hl
ld (hl),' '
inc hl
push hl
ld hl,(mhsize)
call bindec
pop hl
move ,numb,5
ld (hl),' '
inc hl
move ,mhto,6
ld (hl),' '
inc hl
move ,mhfrom,6
ld (hl),' '
inc hl
move ,mhbbs,6
ld (hl),' '
inc hl
move ,mhdate,6
ld (hl),' '
inc hl
ld de,mhtit
ld b,mhtitl
mkhdra: ld a,(de)
cp cr
jr z,mkhdrb
ld (hl),a
inc hl
inc de
dec b
jr nz,mkhdra
mkhdrb: call addcr0 ; Add CR,0 to end of string
ret
; Print message header info
phdr: cmpm firmsg,false
jr z,phdra
mvim firmsg,false
prtx mm6
phdra: call mkhdr
prtx $memry
ret
; Write the mail file header sector.
; Close and re-open the file so it not lost on crash.
wthdr: lxim mrec,0
dodosa setdma,mfhs
dodosa wrec,mfcb
ret
wtmfhs: call wthdr
dodosa close,mfcb
dodosa open,mfcb
ret
; Log a message event
logmnr: ld hl,(msgnr)
call bindec
move logtxt+2,numb,5
ld (hl),cr
mvim event,'M'
jp log
; Insert message into message file.
dseg
tocall: ds 6
bbcall: ds 6
fmcall: ds 6
sndtyp: ds 1
type: ds 1
svcmsg: ds 1
mm1: ds 2
mm2: ds 2
mm3: ds 2
mm4: ds 2
cseg
; Parse an optional field.
; (DE) - loc of delimiter, (HL) - loc of text, (B) - Length of text.
pfl: ld b,a
ld a,(de) ; Delimiter
ld de,bbcall
cp '@' ; BBS call?
jp z,pfla ; Yes
ld de,fmcall
cp '<' ; FROM call?
ret nz ; Unknown, ignore
pfla: ld a,b ; Field length
jp movcal ; Get call
; Parse fields 2 and 3.
p23: ld a,(f3l)
ld hl,(f3st)
ld de,(f2st)
jr pfl
; Parse fields 3 and 4.
p34: ld a,(f4l)
ld hl,(f4st)
ld de,(f3st)
jr pfl
; Parse fields 4 and 5.
p45: ld a,(f5l)
ld hl,(f5st)
ld de,(f4st)
jr pfl
; Parse fields 5 and 6.
p56: ld a,(f6l)
ld hl,(f6st)
ld de,(f5st)
jr pfl
; Parse fields 6 and 7.
p67: ld a,(f7l)
ld hl,(f7st)
ld de,(f6st)
jr pfl
savpar: fill bbcall,6,' '
zmov fmcall,mcall,6
fill mtitle,mhtitl,' '
movb type,opt2 ; Save message type
movw msgnr,mnr ; Save number for logging
movb sndtyp,opt1 ; Save source of text
ret
; Make message from file.
smsg7: call savpar
call p67 ; Parse 6 and 7
jr smsga
smsg5: call savpar
smsga: call p45 ; Parse 4 and 5
jr smsgb
smsg3: call savpar
smsgb: ld hl,fcb3
call ckname ; Legal file name?
jp z,ername ; No
openr fcb3 ; File there?
jp z,erfind ; No
jr smsgg ; Move the file to the msg
; User is going to enter the message.
smsg1: call savpar
prtx mm1 ; Ask for TO call
smsgc: call getcmd ; Get TO call
ckcmd smsgc,badret,badret
ld a,(flds)
cp 1 ; Call only?
jr z,smsge ; Yes
cp 3 ; @ or < ?
jr z,smsgd ; Yes
cp 5 ; @ and < ?
jp nz,erwhat ; No, what was?
call p45
smsgd: call p23
smsge: ld a,(f1l) ; Length of TO call
ld hl,(f1st) ; Location of TO call
jr smsgh
smsg6: call savpar
call p56 ; Parse 5 and 6
jr smsgf
smsg4: call savpar
smsgf: call p34 ; Parse 3 and 4
jr smsgg
smsg2: call savpar
smsgg: ld a,(f2l) ; Length of TO call
ld hl,(f2st) ; Location of TO call
smsgh: ld de,tocall
cp 6+1 ; Too long to be a callsign?
jp nc, erwhat ; Avoid W1XYZ@W2XYZ errors
call movcal ; Save TO call
prtx mm2 ; Ask for title
smsgi: call getdat ; Get title
ckcmd smsgi,badret,badret
movcmd mtitle,0,mhtitl-1
ld (hl),cr
cmpm sndtyp,'M'
jr z,cremsg
; Gather the message into temp file.
prtx mm3
openw msgfcb
jp z,ercant
call rcv ; Gather text into temp file
; Returns zero set if I/O err
ld a,(cmdtyp)
ckcmd smsgj,badret,badret
smsgj: openr msgfcb
jp z,ercant
; Move message from temp file into message file.
cremsg: xor a ; Not a KT msg
jr crems0
crems1: ld a, 1 ; Here from KT/SS logic
crems0: ld (lktflg),a ; Remember whether due to KT
zmov tmfhs,mfhs,mfhsl ; Make copy of file header
inxm tmnr
inxm tmcnt ; Count the active message
movw mhprev,tmlhd ; Last hdr is previous to this
call alloc ; Allocate message header record
ld (tmlhd),hl
dtz tmfhd
jr nz,cmsga
movw tmfhd,tmlhd
cmsga: ld hl,0
ld (mhnext),hl ; Mark as end of header chain
ld (mhread),hl ; Read zero times
ld (mhsize),hl ; Zero bytes
ld (mhext),hl ; No extension of header record
call alloc ; Allocate first text record
ld (mhfmsg),hl
ld (mhlmsg),hl
movw mhnr,mnr
movb mhtype,type
mvim mhstat,'N'
call curtime
zmov mhdate,date,6
zmov mhtime,time,4
zmov mhto,tocall,6
zmov mhfrom,fmcall,6
zmov mhbbs,bbcall,6
zmov mhtit,mtitle,mhtitl
lxim mtnext,0
lxim mtptr,mttext
mvim mtcnt,126+1
; Copy message text from temp file to mail file.
cmsgb: call fmbuf
jr nz,cmsgc
ld c,eof
cmsgc: ld a,c
cp lf
jr z,cmsgb
ld hl,mtcnt
dec (hl)
call z,newbuf
ld hl,(mtptr)
ld (hl),c
inc hl
ld (mtptr),hl
inxm mhsize
ld a,c
cp eof
jr nz,cmsgb
; Write the last buffer
movw mrec,mhlmsg
dodosa setdma,mmts
dodosa wrec,mfcb
; Write the message header
movw mrec,tmlhd
dodosa setdma,mmhs
dodosa wrec,mfcb
; Read previous header, update its next header pointer.
dtz mlhd
jr z,cmsgd
movw mrec,mlhd
dodosa rrec,mfcb
movw mhnext,tmlhd
dodosa wrec,mfcb
cmsgd: zmov mfhs,tmfhs,mfhsl
call wtmfhs ; Write the file header
mvim change,true
cmpm sndtyp,'M'
jr z,yy
dodosa delete,rfcb ; Delete the temp file
; Build the log file item.
yy: call uslnkq ; Gripe if that was done over a link
ld hl,(msgnr)
call bindec
move logtxt+2,numb,5
ld (hl),' '
inc hl
move ,tocall,6
ld (hl),' '
inc hl
; Put first 32 char of title in log
ld de,mtitle
ld b,32
cmsge: ld a,(de)
cp cr
jr z,cmsgf
ld (hl),a
inc hl
inc de
dec b
jr nz,cmsge
cmsgf: ld (hl),cr
mvim event,'M'
jp log
; Routine to gripe about Sends done via a Linked connect
uslnkq: ld a, (usport)
cp 'L' ; Through a gateway link?
ret nz ; No, OK.
ld a, (lktflg)
or a ; Due to KT?
ret nz ; KT's SS shouldn't generate a gripe
prtx mplsno ; Ask not to S while *** linked
ret
; Copy a message to a file.
filmsg: movb type,opt2
zmov numb,fcb2+1,5
call decbin
jp c,erwhat ; Not a number
ld (msgnr),hl
ckname fcb3
jp z,ername
dodosa setdma,mmhs
movw mrec,mlhd
flmsga: dtz mrec
jp z,erfind
dodosa rrec,mfcb
ld hl,(msgnr)
ld de,(mhnr)
or a ; Clear carry
sbc hl,de
jr z,flmsgb
movw mrec,mhprev
jr flmsga
flmsgb: cmpm type,'A'
jr z,flmsgx
openwn fcb3
jp z,waitc
jr flmsgy
flmsgx: opena fcb3
jp z,waitc
flmsgy: mvim firmsg,true
call phdr
ld hl,($memry)
call @ctobuf ; Put header into file
movw mrec,mhfmsg
flmsgc: dtz mrec
jr z,flmsgf
dodosa setdma,mmts
dodosa rrec,mfcb
ld hl,mttext
ld e,126
flmsgd: ld c,(hl)
call tobuf
ld a,c
cp eof
jr z,flmsgf
cp cr
jr nz,flmsgg
ld c,lf
call tobuf
flmsgg: inc hl
dec e
jr nz,flmsgd
movw mrec,mtnext
jr flmsgc
flmsgf: closew
jp z,ercant
jp waitc
; Delete current message from message file.
; Input: mhcur = record # of current msg header
kmsg: movw tmhsz,mhsize
movw tmhlms,mhlmsg
movw tmhnx,mhnext
movw tmhpr,mhprev
dtz tmhnx ; Is there a next hdr?
jr z,kmsgx ; No (last msg)
movw mrec,tmhnx ; Point to next hdr
dodosa setdma,mmhs ; Point I/O to hdr buffer
dodosa rrec,mfcb ; Read next hdr
movw mhprev,tmhpr ; Replace next prev with cur prev
dodosa wrec,mfcb ; Write next hdr back
kmsgx: dtz tmhpr ; Is there a previous hdr?
jr z,kmsga ; No (1st msg)
movw mrec,tmhpr ; Point to previous hdr
dodosa setdma,mmhs ; Point I/O to hdr buffer
dodosa rrec,mfcb ; Read previous hdr
movw mhnext,tmhnx ; Replace prev next with cur next
dodosa wrec,mfcb ; Write previous hdr back
; Chain message sectors into free chain
kmsga: dtz mlfree
jr z,kmsgb ; Nothing in chain yet
movw mrec,mlfree
dodosa setdma,mmts
dodosa rrec,mfcb
movw mtnext,mhcur
dodosa wrec,mfcb
; Update file header record.
kmsgb: dtz mffree
jr nz,kmsgc
movw mffree,mhcur
kmsgc: movw mlfree,tmhlms
ld hl,(tmhsz)
ld de,125
add hl,de
ld e,126
call div8
ld e,l
ld d,0
inc de ; Add header sector
ld hl,(mfree)
add hl,de
ld (mfree),hl
ld hl,(mfhd)
ld de,(mhcur)
or a ; Clear carry
sbc hl,de
jr nz,kmsgd
movw mfhd,tmhnx
kmsgd: ld hl,(mlhd)
or a ; Clear carry
sbc hl,de
jr nz,kmsge
movw mlhd,tmhpr
kmsge: dcxm mcnt ; One less message
mvim change,true
ret
; Kill a message.
dseg
mm15: ds 2
cseg
; KF and KM command.
klmsg3: movw mhcur,mfhd ; Point to first hdr
klmsga: dodosa setdma,mmhs ; Do I/O into hdr buffer
movw mrec,mhcur ; Point I/O to current hdr
ld a,l
or h ; Any more hdrs?
jp nz,xx ; Yes
cmpm change,true ; Any killed?
call z,wthdr ; Write file hdr back
jp erdone
xx: dodosa rrec,mfcb ; Read the hdr
movw temp,mhnext
ld a,(opt2) ; Type to kill
cp 'M' ; Kill mine?
jr z,klmsgb ; Yes
cp 'F' ; Kill forwarded?
jr nz,klmsgd ; No
ld a,(mhstat) ; Msg type
cp 'F' ; forwarded?
jr z,klmsgc ; Yes, kill
jr klmsgd
klmsgb: ld a,(mhstat)
cp 'Y' ; Is read?
jr nz,klmsgd ; No, dont kill
comp mhto,mcall,6 ; His message?
jr nz,klmsgd ; No, dont kill
klmsgc: movw msgnr,mhnr ; Save message # for logging
prtx mm15
call kmsg
call logmnr
klmsgd: movw mhcur,temp ; Next becomes current
jr klmsga ; Go check this one
; K <number> or KT <number> command
klmsg2: movb type,opt2 ; Save msg type
ld hl,fcb2+1
jr klmsgf
; K or KT command, prompt for message number.
klmsg1: movb type,opt2
prtx mm4
klmsge: call getcmd
ckcmd klmsge,badret,badret
ld hl,fcb1+1
klmsgf: zmov numb,,5
call decbin
jp c,erwhat ; Was not a number
ld (msgnr),hl
movw mhcur,mlhd ; Point to last hdr
dodosa setdma,mmhs ; Do I/O into hdr buffer
klmsgg: movw mrec,mhcur ; Point I/O to current hdr
ld a,l
or h ; Any more hdrs?
jp z,erfind ; No
dodosa rrec,mfcb ; Read the hdr
ld hl,(msgnr)
ld de,(mhnr)
or a ; Clear carry
sbc hl,de ; Right msg?
jr z,klmsgh ; Yes
movw mhcur,mhprev ; Previous becomes current
jr klmsgg ; Go check this one
; Found the message.
klmsgh: call permit ; Permission to kill?
jr z,klmsgi ; Yes
cmpm type,'T' ; Killing NTS traffic msg?
jp nz,erprot ; No
cmpm mhtype,'T' ; NTS traffic msg?
jp nz,erprot ; No
klmsgi: ld a, (mhtype)
push psw
zmov mtitle,mhtit,mhtitl
zmov tocall,mhfrom,6
call kmsg ; Kill the msg
call logmnr ; Log the event
pop psw ; Type of msg just killed
cp 'T' ; Was it NTS tfc?
jr nz, klmsgj ; Go if not
cmpm type,'T' ; Killing by KT command?
jr nz,klmsgj ; No
cmpm svcmsg,true ; Config says to gen svc msg?
jr z,gensvc ; Yes
klmsgj: call wthdr ; Write file hdr back
jp erdone ; Tell user it done
; Killed NTS msg, generate a service msg.
gensvc: fill bbcall,6,' ' ; Don't know bbs yet
zmov fmcall,ocall,6
ld a,'S'
ld (type),a ; S for service msg
ld (sndtyp),a ; S so will delete MSG.TMP
ld (logtxt),a ; Log as send
ld (logtxt+1),a ; Log as SS
; Create the message in MSG.TMP
openw msgfcb
ntobuf sm1,sm1l
ld hl,(msgnr) ; # of msg killed
call bindec
ntobuf numb,5
ntobuf sm2,sm2l
ntobuf ocall,6
ntobuf sm3,sm3l
ntobuf mcall,6
ntobuf sm4,sm4l
ntobuf time,4
ntobuf sm5,sm5l
ntobuf date,6
ld c,cr
call tobuf
ld c,lf
call tobuf
ld c,eof
call tobuf
closew msgfcb
openr msgfcb
movw msgnr,mnr ; Set current msg # for logging
call crems1
jp erdone ; Tell user it done
sm1: db 'Msg '
sm1l equ $-sm1
sm2: db ' was taken from '
sm2l equ $-sm2
sm3: db ' by '
sm3l equ $-sm3
sm4: db ' at '
sm4l equ $-sm4
sm5: db ' on '
sm5l equ $-sm5
; Check if user has unread mail
dseg
mm5: ds 2
cseg
newmsg: srclst mcall,ucalls,uccnt,6,6
ret nz ; User has no mail
prtx mm5 ; Has unread mail, say so
lxim msgnr,1 ; Search all msgs
mvim opt2,1 ; Option for "list unread"
jr lmsgd
; List message headers.
lstmsg: movw msgnr,usmnr ; Min msg # to list
ld a,(opt2)
cp ' ' ; Just "L"?
jr z,lmsgc ; Yes
lxim msgnr,0 ; Assume search all
cp '@' ; List msgs @ BBS?
jr z,lmsga ; Yes
cp '<' ; List msgs FROM call?
jr z,lmsga ; Yes
cp '>' ; List msgs TO call?
jr nz,lmsgc ; No
lmsga: zmov scall,fcb2+1,6 ; Save the call
jr lmsgd
lmsgc: ld a,(f2l)
or a ; Message # given?
jr z,lmsgd ; No
zmov numb,fcb2+1,5
call decbin
jp c,erwhat ; Not a number
ld (msgnr),hl
lmsgd: dodosa setdma,mmhs ; Do I/O into header buffer
mvim firmsg,true ; Force header
movw mrec,mlhd ; Point to last header
lmsge: dtz mrec ; More headers?
jr z,lmsgh ; No
dodosa rrec,mfcb ; Read the msg header
cmpm opt2,'L' ; Listing n last?
jr z,lmsgf ; Yes
ld de,(msgnr) ; Number wanted
ld hl,(mhnr) ; Message number
or a ; Clear carry
sbc hl,de ; This msg # < # wanted?
jr c,lmsgh ; Yes, done
jr lmsgg
lmsgf: dtz msgnr ; More to list?
jr z,lmsgh ; No
lmsgg: call lms ; List the msg hdr
movw mrec,mhprev ; Point to previous header
call pause ; Check for xoff
jr lmsge ; Check next msg header
lmsgh: cmpm opt2,1 ; Listing users unread?
call nz,logmnr ; Log if not
cmpm firmsg,true ; Find any to list?
jp z,erfind ; No
jp waitc
lms: cmpm mhtype,'P' ; Personal?
jr nz,lmsa ; No, ok to list
call permit ; Personal and users?
ret nz ; No, no list
lmsa: ld a,(opt2)
cp ' ' ; List specific type?
jr nz,lmsc ; Yes
lmsb: cmpm mhtype,'T' ; Traffic?
ret z ; Yes, no list
cmpm mhtype,'S' ; Traffic service?
ret z ; Yes, no list
jp phdr
lmsc: cp 'M' ; TO or FROM user only?
jr nz,lmsd ; No
comp mhto,mcall,6 ; TO this user?
jp z,phdr ; Yes
comp mhfrom,mcall,6 ; FROM this user?
jp z,phdr ; Yes
ret
lmsd: cp 1 ; TO and UNREAD only?
jr nz,lmse ; No
cmpm mhstat,'N' ; Unread?
ret nz ; No, no list
comp mhto,mcall,6 ; To user?
ret nz ; No, no list
jp phdr
lmse: cp '>' ; List msgs TO given call?
jr nz,lmsf ; No
comp mhto,scall,6 ; This msg?
ret nz ; No
jp phdr
lmsf: cp '<' ; List msgs FROM given call?
jr nz,lmsg ; No
comp mhfrom,scall,6 ; This msg?
ret nz ; No
jp phdr
lmsg: cp '@' ; List msgs @ given call?
jr nz,lmsi ; No
cmpm scall,' ' ; Call given?
jr z,lmsh ; No
comp mhbbs,scall,6 ; This msg?
ret nz ; No
jp phdr
lmsh: cmpm mhbbs,' ' ; Is an @?
ret z ; No, no list
jp phdr
lmsi: cp 'L' ; List Last n?
jr nz,lmsj ; No
dcxm msgnr ; Count this one
jp phdr
lmsj: cp 'F' ; Forwarded msgs only?
jr nz,lmsk ; No
cmpm mhstat,'F' ; This one forwarded?
ret nz ; No
jp phdr ; Yes, list
lmsk: cp 'Y' ; "Read" msgs only?
jr nz,lmsl ; No
cmpm mhstat,'Y' ; This one read?
ret nz ; No
jp phdr ; Yes, list
lmsl: ld hl,mhtype ; List msgs of given type.
cp (hl) ; This type?
ret nz ; No
jp phdr
; Read a message.
dseg
found: ds 1
rdnr: ds 2
cseg
; RM command
rdmsg3: movb type,opt2
lxim rdnr,0 ; Look at all msgs
jr rdmsgc
; R <number> command
rdmsg2: movb type,opt2
ld hl,fcb2+1
jr rdmsgb
; R command
rdmsg1: movb type,opt2
prtx mm4
rdmsga: call getcmd
ckcmd rdmsga,badret,badret
ld hl,fcb1+1
rdmsgb: zmov numb,,5
call decbin
jp c,erwhat ; Not a number
ld (rdnr),hl
rdmsgc: movw mrec,mlhd ; Point to last header
mvim found,false ; None found yet
rdmsgd: dtz mrec ; More headers?
jr z,rdmsgh ; No, done
dodosa setdma,mmhs
dodosa rrec,mfcb ; Read header
ld de,(rdnr) ; Number wanted
ld hl,(mhnr) ; Message number
or a ; Clear carry
sbc hl,de ; This msg # < # wanted?
jr c,rdmsgh ; Yes, done
jr z,rdmsgf ; Is the one wanted
cmpm type,'M' ; Read mine?
jr nz,rdmsge ; No
comp mcall,mhto,6 ; Mine?
call z,pmsg ; Yes, print it
rdmsge: movw mrec,mhprev ; No, point to previous header
jr rdmsgd ; and read it
rdmsgf: cmpm mhtype,'P' ; Private msg?
jr nz,rdmsgg ; No
call permit ; Ok to read?
jp nz,erprot ; No, tell user
rdmsgg: call snoopq ; Tell the world if snooping on other's mail
jr nz, rmsgsn ; Check whether to allow the read if snoop
rmsgsr: call pmsg ; Print the msg
jp waitc ; Done
rmsgsn: ld a,(usopt) ; Temp, key on either exclusion
and usoexa+usoexb ; If not excluded anywhere,
jr z,rmsgsr ; allow the read anyway
jp erprot ; If excluded somewhere, suppress it.
rdmsgh: cmpm found,false ; Any found?
jp z,erfind ; No
jp waitc ; Done
pmsg: inxm mhread ; Increment # times msg read
comp mhto,mcall,6 ; Users msg?
jr nz,pmsga ; No
mvim mhstat,'Y' ; Mark as read
pmsga: mvim change,true ; Mark file changed
dodosa wrec,mfcb ; Write header back
ld a,true
ld (found),a
ld (firmsg),a
call phdr ; Print msg header
call prtmsg ; Print the msg
movw msgnr,mhnr
call logmnr ; Log the event
ret
end