; 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 or KT 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 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