koreth@ssyx.ucsc.edu (Steven Grimm) (03/12/89)
Submitted-by: john@logajan.mn.org (John Logajan)
Posting-number: Volume 2, Issue 26
Archive-name: mailtruk
Below are five files generically named MailTruk Release V1.0.
MailTruk is a GFA Basic (2.0) implementation of uucp/uucico.
MailTruk is intended to allow non-unix/non-C Atari ST's email
access to the Usenet community.
#!/bin/sh
# shar: Shell Archiver (v1.22)
#
# Run the following text with /bin/sh to create:
# mailtruk.doc
# mailtruk.lst
# protocol.doc
# readmail.lst
# writmail.lst
#
sed 's/^X//' << 'SHAR_EOF' > mailtruk.doc &&
X
X MailTruk Documentation
X by
X John Logajan, January 1989
X 4248 Hamline Ave
X Arden Hills, MN 55112
X john@logajan.mn.org
X
X
XINTRODUCTION TO THE NETWORK
X
XWelcome to the world of uucp style data exchange. Uucp stands for
XUnix to Unix copy. Unix is an operating system used by a large
Xnumber of computers. A large network of computers running uucp
Xcompatible data exchange has evolved over the last several years.
XThis network encompasses university, corporate, governmental, and
Xindividually owned computers. It is estimated that there are over
X10,000 computers on the net, with approximately 400,000 users.
XThe two primary functions of the net are private electronic mail
Xand "broadly cast" electronic news transfer. The Usenet News
Xconsists of some 350 subject categories into which several
Xthousand articles a day are posted by users. An average day's
Xnews is typically four million characters -- and growing. Anyone
Xreceiving a full newsfeed is more and more feeling the need for
Xfaster data communications links, since such volume at 2400 baud
Xrequires five hours if uncompressed or 2.5 hours if compressed.
X
X
XINTRODUCTION TO THE MAILTRUK, READMAIL, AND WRITMAIL PROGRAMS
X
XMailTruk, ReadMail, and WritMail are uucp compatible
Xcommunications programs that run on Atari ST computers. The
Xprograms are written in GFA Basic (2.0) and are freely distributed
Xas a readable listings in the public domain. Files included in
Xthe distribution include:
XMAILTRUK.LST, READMAIL.LST, WRITMAIL.LST, MAILTRUK.DOC,
XPROTOCOL.DOC
X
XWritMail is used to write your outgoing mail. Writmail's main
Xtask is to format your message so that other computers on the net
Xrecognize what you have sent and where it is going. Each, in
Xturn, passes it along until it hopefully reaches your intended
Xrecipient.
X
XMailTruk is the actual communications program. It first dials
Xyour neighbor site, establishes protocol agreement, and then sends
Xthe messages, if any, that you have previously prepared with
XWritMail. When MailTruk has finished sending, it requests to
Xreceive any mail that the remote site has pending for you. After
Xit receives all incoming mail, MailTruk terminates the connection.
X
XReadMail allows you to read your mail in a convenient manner. The
Xmain objection to reading you mail files directly with GEM
Xcommands is that Unix machines use linefeed characters as end-of-
Xline indicators rather than the carriage return character used by
XGEM. Thus, direct reading of mail files results in a confusing
Xpresentation.
X
XAlthough MailTruk can transfer the file types used to send the
XNetwork News, additional file pre- and post-processing is required
Xto read or write News articles. ReadMail and WritMail DO NOT
Xhandle the News format. Uncompressed News would be a fairly
Xstraight forward task to handle, but compressed and batched News
Xwill require additional sophistication. Let me know if you feel
Xmotivated to write such a program!
X
X
XSETTING EVERYTHING UP
X
XFirst -- You need a site to call, account information for that
Xsite, and a modem. Since this program is being distributed over
Xthe net, if you track back from where this program came from,
Xyou're bound to run into somebody who knows your local net
Xarrangement. (I pay $25 a year to a guy who runs a "domain park"
Xfor my access. He, in turn, calls other bigger sites -- and so
Xon.)
X
XSecond -- All mail going to a particular site is placed in its own
Xdirectory. All mail coming to your site is placed in its own
Xdirectory. You should create these directories before running the
Xprograms. I am site -logajan-, I call one site -bungia-. So, I
Xcreated a directory called MAIL on my C: drive where I put all my
Xprograms, and I created two sub-directories, BUNGIA and LOGAJAN,
Xi.e. C:\MAIL\BUNGIA\
X C:\MAIL\LOGAJAN\
X
XThird -- All three programs are totally self-contained in that
Xthey do not share an external common configuration file. So you
Xwill have to insure that each of the important variables,
Xincluding the directory names mentioned above, in each of the
Xprograms is correct and consistent. The variables are grouped
Xnear the beginning of each program. You WILL have to customize
Xthese variables for these programs to work!
X
XFourth -- If you have multiple sites to call, you will have to
Xmake multiple versions of the MailTruk program (or modify it to
Xhandle multiple cases.) You will also want to write a program
Xthat recognizes messages which are just passing through, and
X"rewrites" the pertinent addresses, and places them back out in
Xthe outbound message area.
X
XFifth -- Otherwise you are a "leaf" site (you only call one
Xmachine) and any mail with your machine name in it is assumed to
Xbe to you, no matter what user name or additional path is in the
XTo: address line.
X
XSixth -- Paths; the From: and To: portion of messages; are a
Xsomewhat mysterious subject. Basically you have to know, at a
Xminimum, the recipient's user-name and machine-name, and the path
Xto the nearest smart mailer site. Otherwise you can specify the
Xentire path -- but some smart sites end up sending it the route
Xthey think is best anyhow.
X
X If I want to send to jack at atari, I enter the path as:
X bungia!atari!jack Note: nearest!next!next!farthest!user
X (my neighbor, bungia, knows the tortuous route to atari)
X
X or bungia!umn-cs!rutgers!att.att.com!wally if I want to get to
X wally at att and know the complete path.
X
XYou will often see @'s and %'s in paths. Basically you just read
Xthese in the other direction, i.e.:
X
X john@logajan.mn.org@bungia@shamash@nic.mr.net is an actual
X path TO my machine from nic.mr.net.
X
XHowever, note that WritMail forces you to state the path with at
Xleast one (!) symbol. Your neighbor's machine is always the first
Xname in the path, therefore you could do:
X
X bungia!ben@franklin.electric.com
X
X
XSeventh -- Hopefully there is enough information in the listings
Xfor you to set up your own site and get it operational.
X Good luck.
X
SHAR_EOF
chmod 0600 mailtruk.doc || echo "restore of mailtruk.doc fails"
sed 's/^X//' << 'SHAR_EOF' > mailtruk.lst &&
XRem MAILTRUK V1.0 -- GFA Basic 2.0 / Atari ST implementation of uucp/uucico.
XRem --- PUBLIC DOMAIN ---
XRem This program dials up computer sites running Unix or Unix clone uucp,
XRem allowing the transfer of e-mail, news and other data files.
XRem
XRem Totally original code by: John Logajan, January 1989.
XRem 4248 Hamline Ave
XRem Arden Hills, MN 55112
XRem (john@logajan.mn.org or ...rutgers!bungia!logajan!john)
XRem
XRem The next eight lines must be customized for each user/site.
XRem
XMysite$="logajan" ! Your site machine name. (You choose!)
XMyuser$="logajan" ! Your user/account name for remote site.
XMypw$="youguess" ! Your password for remote site.
XSitedir$="\mail\bungia" ! Directory of files to send only to that site.
XSitercv$="\mail\"+Mysite$ ! Directory for all incoming files.
XSiteph$="123-4567" ! Remote site telephone number.
XRetry!=True ! Should we retry dialing if busy/no answer.
XVoid Xbios(15,4,0,&H88,1,1,-1) ! RS232 configuration/baud rate. (See below.)
XRem
XRem Configure RS232 - Xbios(15,baud,flow,ctrl,rst,xst,scr).
XRem baud = 0/19200, 1/9600, 4/2400, 7/1200, 9/300.
XRem flow = 0/None. (UUCP forbids xoff/xon! ST's RTS/CTS works goofy!)
XRem ctrl = 8bits, 1stop, noparity.
XRem rst = recv enabled.
XRem xst = xmit enabled.
XRem scr = not used.
XRem
XRwinsiz%=3 ! Number of packets in receive window. (Standard=3)
XRpktsiz%=64 ! Number of bytes in a receive packet. (Standard=64)
XRem
XRem Assembler code for calculating the checksum (speedy.) Does the check-
XRem sum calculation on a packetsize worth of data starting at Buffer.
XRem The control byte is also included in the sum and everthing is sub-
XRem tracted from AAAA hex.
XRem Checksum=C:Chk%(L:buffer,W:packetsize,W:controlbyte)
XRem
XData "206F0004322F0008342F000A203C0000FFFF4243E358280042851A18D0453A00B345"
XData "D645B0846E02B7400441000166E40242FFFFB142303CAAAA904202800000FFFF4E75"
XRead A$
XRead B$
XA$=A$+B$
XChk$=""
XFor J%=1 To Len(A$) Step 2
X Chk$=Chk$+Chr$(Val("&H"+Mid$(A$,J%,2)))
XNext J%
XChk%=Varptr(Chk$)
XRem
XRem Assembler code for RS232 block input (speedy.) Puts x chars into a
XRem buffer, or times out after 12 seconds.
XRem Remainder=C:Rcv%(L:buffer,W:byteswanted)
XRem
XData "286F0004382F000842A73F3C00204E415C8F2E002A39000004BA068500000960"
XData "3F3C00013F3C00014E4D588F4A4067143F3C00013F3C00024E4D588F18C05344"
XData "670C60DC2C39000004BA9C856DD22F073F3C00204E415C8F20044E75"
XRead A$
XRead B$
XA$=A$+B$
XRead B$
XA$=A$+B$
XRcv$=""
XFor J%=1 To Len(A$) Step 2
X Rcv$=Rcv$+Chr$(Val("&H"+Mid$(A$,J%,2)))
XNext J%
XRcv%=Varptr(Rcv$)
XDim Rcxx%(Rpktsiz%/4+2) ! Build an internal input buffer.
XRcvbf%=Varptr(Rcxx%(0))
XDim Wfil$(2)
XWfm=0
XWfp%=Varptr(Wfm) ! Build a frame buffer.
XRs232p%=Xbios(14,0) ! Get RS232 TOS buffer info pointer.
XRinsiz%=((Rpktsiz%+6)*Rwinsiz%+128)
XDim Rin%(Rinsiz%/4+1) ! Make a large RS232 TOS input buffer.
XLpoke Rs232p%,Varptr(Rin%(0))
XDpoke Rs232p%+4,Rinsiz%
XDpoke Rs232p%+6,0 ! Flag it empty.
XDpoke Rs232p%+8,0
XOpen "",#2,"AUX:" ! Open RS232 port as file #2.
XRem
XRem You will probably need to customize the dialing part of the program,
XRem depending upon the quirks of the site you are trying to call, and
XRem your modem response codes.
XRem
XPrint "Dialing. Push SPACE key to abort connection attempt."
XRepeat
X @Ostr("ATDT"+Siteph$+"\0D") ! Dial remote site.
X @Waitfor("CONNECT",60)
X Exit If Not Retry!
X If Not Found!
X Print "Busy/no answer. Dialing again."
X Endif
XUntil Found!
XPrint "Connected."
XRetry!=False
XPause 200
XOut 1,&HD ! Send a couple of CR's to prime remote.
XPause 50
XOut 1,&HD
XPause 50
XOut 1,&HD
XPause 50
XOut 1,&HD
X@Waitfor("ogin:",30)
XPause 50
X@Ostr(Myuser$+"\0D")
X@Waitfor("sword:",30)
X@Ostr(Mypw$+"\0D")
X@Waitfor("Shere",30)
XPrint "Logged in."
XRem
XRem Initialization sequence.
XRem
X@Ostr("\10S"+Mysite$+"\0A")
X@Waitfor("ROK",30)
X@Waitfor("P",30)
X@Waitfor("g",5)
X@Ostr("\10Ug\0A")
XInita!=False
XInitb!=False
XInitc!=False
XFor Wf%=1 To 10 ! INIT with window size / data segement size.
X If Inita!=False Or Initb!=False
X Wcc%=&H38 Or Rwinsiz%
X @Wctlpkt(2) ! inita window size.
X Endif
X @Waitframe
X If Found! And (Cntrol% And &HF8)=&H38
X Inita!=True
X Xwinsiz%=Cntrol% And 7
X Rpktcod%=Int(Log(Rpktsiz%)/Log(2)-4.9)
X Wcc%=&H30 Or Rpktcod%
X @Wctlpkt(2) ! initb packet size.
X @Waitframe
X Endif
X If Found! And (Cntrol% And &HF8)=&H30
X Initb!=True
X Xpktcod%=(Cntrol% And 7)+1
X Xpktsiz%=32*2^(Xpktcod%-1)
X Xpktsizh%=Xpktsiz%+6
X Endif
X Exit If Inita! And Initb!
XNext Wf%
XIf Initb!
X Wcc%=&H28 Or Rwinsiz%
X @Wctlpkt(2) ! initc window size.
X For Wf%=1 To 3
X @Waitframe
X If Found! And (Cntrol% And &HF8)=&H28
X Initc!=True
X Endif
X Exit If Initc!
X Next Wf%
XEndif
XIf Inita!=False Or Initb!=False Or Initc!=False
X Print "Failed initilization."
X @Hangup
XEndif
XPrint "They want a sending window size = ";Xwinsiz%
XPrint "They want a sending data packet size = ";Xpktsiz%
XDim Xbuf%(2*Xpktsizh%) ! Build an outgoing data buffer.
XXppt%=Varptr(Xbuf%(0))
XRseq%=0
XRrseq%=0
XXseq%=0
XXack%=0
XRem
XRem Since we called, we are master and send our stuff first.
XRem
XSitewrk$=Sitedir$+"\WORK" ! Temporary work-list file.
XSitecfl$=Sitedir$+"\*.C"
XIf Exist(Sitewrk$)
X Kill Sitewrk$ ! Get rid of old stale one.
XEndif
XIf Exist(Sitecfl$) ! Do we have anything to send???
X Dir Sitecfl$ To Sitewrk$ ! Then make a list of those files.
X Open "I",#3,Sitewrk$
X While Not Eof(#3) ! Setup to send those files, pair by pair.
X Line Input #3,Sfil$
X Sfil$=Sitedir$+"\"+Left$(Sfil$,Instr(Sfil$,"."))
X Cfil$=Sfil$+"C"
X Wfil$(1)=Sfil$+"D"
X Wfil$(2)=Sfil$+"X"
X If Exist(Cfil$)
X Open "I",#4,Cfil$
X For Wrks%=1 To 2
X Line Input #4,Wrklin$ ! Get D. or X. worklines out of C.
X Wrklin$=Wrklin$+Chr$(0)
X If Exist(Wfil$(Wrks%))
X Print "SEND:"'Wrklin$
X Xfdone!=False
X Xrqp%=0
X While Not Xfdone! ! Send the workline.
X @Wrqtpkt
X Wend
X @Waitdata
X If Peek(Rcvbf%)<>Asc("S")
X Print "Send request failed."
X @Hangup
X Endif
X If Peek(Rcvbf%+1)=Asc("Y")
X Open "I",#1,Wfil$(Wrks%)
X Xfl%=Lof(#1)
X Xfp%=0
X Xfdone!=False
X While Not Xfdone! ! Send D. or X. file.
X @Wfilepkt
X Wend
X @Waitdata
X If Peek(Rcvbf%)<>Asc("C") Or Peek(Rcvbf%+1)<>Asc("Y")
X Print "Send failed."
X @Hangup
X Endif
X Close #1
X Else ! They won't let us do something.
X Print "Send request refused by remote site."
X Endif
X Kill Wfil$(Wrks%)
X Endif
X Next Wrks%
X Close #4
X Kill Cfil$
X Endif
X Wend
X Close #3
X Kill Sitewrk$
XEndif
XRem
XRem We are done sending, now we become slave to receive.
XRem
XWrklin$="H"+Chr$(0)
XXrqp%=0
X@Wrqtpkt
X@Waitdata
XIf Peek(Rcvbf%)=Asc("H")
X If Peek(Rcvbf%+1)=Asc("N") ! HN means they have mail for us.
X Do
X Rwfr!=False
X Wrklin$=""
X While Not Rwfr!
X @Waitdata ! Get their workline request.
X For Wf%=0 To Rpktsiz%-1
X Wlv%=Peek(Rcvbf%+Wf%)
X If Wlv%=0
X Rwfr!=True
X Else
X Wrklin$=Wrklin$+Chr$(Wlv%)
X Endif
X Exit If Rwfr!
X Next Wf%
X Wend
X Rwff$=Left$(Wrklin$,1)
X Exit If Rwff$="H" ! If H then they are done too.
X Print "RCV:"'Wrklin$
X If Rwff$="S"
X Wlst%=Instr(5,Wrklin$," ")
X Rwff$=Mid$(Wrklin$,Wlst%+1,1) ! We have to shorten the file name.
X Rfil$=Rwff$+Mid$(Wrklin$,Instr(Wlst%,Wrklin$," ")-4,4)+"."+Rwff$
X Open "O",#1,Sitercv$+"\"+Rfil$
X Wrklin$="SY"+Chr$(0) ! Tell them it's okay to send.
X Xrqp%=0
X @Wrqtpkt
X Rdone!=False
X While Not Rdone! ! Get D. or X. file contents.
X @Waitdata
X If Ptyp%=&H80
X Bput #1,Rcvbf%,Rpktsiz%
X Else
X Dif%=Peek(Rcvbf%)
X Dfc%=1
X If Dif%=>128
X Dif%=Dif%-128+Peek(Rcvbf%+1)*128
X Dfc%=2
X Endif
X Dif%=Rpktsiz%-Dif%
X If Dif%<>0
X Bput #1,Rcvbf%+Dfc%,Dif%
X Else
X Rdone!=True
X Endif
X Endif
X Wend
X Close #1
X Wrklin$="CY"+Chr$(0) ! Acknowledge successful copy.
X Xrqp%=0
X @Wrqtpkt
X Else
X Print "Illegal request from remote site:"
X Print Wrklin$
X Wrklin$=Rwff$+"N"+Chr$(0) ! Tell them sorry, but no.
X Xrqp%=0
X @Wrqtpkt
X Endif
X Loop
X Wrklin$="HY"+Chr$(0)
X Xrqp%=0
X @Wrqtpkt
X @Waitdata
X If Peek(Rcvbf%)<>Asc("H") Or Peek(Rcvbf%+1)<>Asc("Y")
X Print "Failed looking to hangup."
X @Hangup
X Endif
X @Fini
X Else
X Wrklin$="HY"+Chr$(0)
X Xrqp%=0
X @Wrqtpkt
X @Fini
X Endif
XElse
X Print "Mode switching failed."
X @Hangup
XEndif
XEnd
XProcedure Fini
X Print "Done. Terminating session."
X @Ostr("\10\09\A2\AA\08\09")
X @Waitframe
X If Frmcmd%<>8
X Print "Failed waiting for CLOSE!"
X @Hangup
X Endif
X @Ostr("\10OOOOOO\0A")
X @Waitfor("OOO",5)
X @Ostr("\10OOOOOO\0A")
X Print "Conversation complete."
X @Hangup
XReturn
XProcedure Ostr(O$) ! Send ASCII or HEX \XX (2 nybbles - uppercase.)
X L%=Len(O$)
X J%=0
X Repeat
X Inc J%
X C%=Asc(Mid$(O$,J%,1))
X If C%=&H5C
X Inc J%
X C%=Val("&H"+Mid$(O$,J%,2))
X Inc J%
X Endif
X Out 1,C%
X Until J%=L%
XReturn
XProcedure Waitfor(O$,Tx%) ! Look for O$ in input stream for Tx seconds.
X Pkey!=False ! Pressing space key aborts during dial up part.
X Found!=False
X Ol%=Len(O$)
X Cp%=1
X T%=Timer+Tx%*200
X While Timer<T%
X If Inp?(1)
X C%=Inp(1) And &H7F
X If Asc(Mid$(O$,Cp%,1))=C%
X If Cp%=Ol%
X Found!=True
X Endif
X Inc Cp%
X Else
X If Cp%<>1
X Cp%=1
X If Asc(Mid$(O$,Cp%,1))=C%
X Inc Cp%
X Endif
X Endif
X Endif
X Endif
X Exit If Found!
X If Inp?(2)
X If Inp(2)=Asc(" ") ! Abort during login if SPACE key is pressed.
X Pkey!=True
X Endif
X Endif
X Exit If Pkey!
X Wend
X If ((Not Found!) And Not Retry!) Or Pkey!
X Print "Failed waiting for: ";O$
X @Hangup
X Endif
XReturn
XProcedure Waitframe ! Wait for a six byte framing envelope.
X Found!=False
X Rr!=False
X Dpkt!=False
X Wfr%=C:Rcv%(L:Wfp%,6)
X Repeat
X Cntrol%=Peek(Wfp%+4)
X Rsum1%=Peek(Wfp%+2)
X Rsum2%=Peek(Wfp%+3)
X Xs%=Peek(Wfp%+1) Xor Rsum1% Xor Rsum2% Xor Cntrol%
X If Wfr%=0 And Peek(Wfp%)=&H10 And Xs%=Peek(Wfp%+5)
X Found!=True
X Ptyp%=Cntrol% And &HC0
X If Ptyp%=0
X Xack%=Cntrol% And 7
X Frmcmd%=Cntrol% And &H38
X If Frmcmd%=&H20
X Rr!=True
X Endif
X Else
X Dpkt!=True
X Rrseq%=(Cntrol%/8) And 7
X Rsum%=Rsum2%*256+Rsum1%
X Endif
X Else
X If Wfr%=0
X Bmove Wfp%+1,Wfp%,5
X Wfr%=C:Rcv%(L:Wfp%+5,1)
X Endif
X Endif
X Exit If Found!
X Until Wfr%<>0
XReturn
XProcedure Hangup ! Hangup.
X Print "Hanging Up!"
X @Ostr("\0D")
X Pause 60
X @Ostr("+++")
X Pause 60
X @Ostr("\0DATH\0D")
X Pause 25
X Void Xbios(30,&H10) ! Drop DTR for 1/2 second.
X Pause 25
X Void Xbios(29,&HEF) ! Raise DTR.
X End
XReturn
XRem
XRem Writes: One data packet, from file opened as #1, to RS232 opened as #2.
XRem Returns: Xfdone!=True after last packet sent.
XRem Initial: Xfl%=Lof(#1), Xfp%=0, Xppt%=base packet pointer,
XRem xpktsiz%, xpktcod%, xpktsizh%.
XRem Current: Rseq%=last rcvd packet sequence number, Xseq%=last xmited.
XRem Updates: Xseq%=xmited packet sequence number, Xfp%=xmited data pointer.
XRem
XProcedure Wfilepkt
X Xfpo%=Xfp%
X Xfp%=Xfp%+Xpktsiz%
X Xseq%=(Xseq%+1) And 7
X Xph%=Xppt%+Xseq%*Xpktsizh%
X Xpd%=Xph%+6
X Poke Xph%,&H10
X Poke Xph%+1,Xpktcod%
X If Xfp%<=Xfl%
X Bget #1,Xpd%,Xpktsiz% ! Full Packet.
X Xctrl%=&H80 Or Xseq%*8 Or Rseq%
X Xsum%=C:Chk%(L:Xpd%,W:Xpktsiz%,W:Xctrl%)
X Poke Xph%+2,Xsum%
X Xf1%=Xsum%/256
X Poke Xph%+3,Xf1%
X Poke Xph%+4,Xctrl%
X Poke Xph%+5,(Xpktcod% Xor Xsum% Xor Xf1% Xor Xctrl%)
X @Wchkwin(0)
X Else
X If Xfpo%<Xfl%
X Xbun%=Xpktsiz%-(Xfl%-Xfpo%) ! Short Packet. (If needed.)
X If Xbun%<128
X Poke Xpd%,Xbun%
X Bget #1,Xpd%+1,Xfl%-Xfpo%
X Else
X Poke Xpd%,Xbun% And &H7F Or &H80
X Poke Xpd%+1,Xbun%/128
X Bget #1,Xpd%+2,Xfl%-Xfpo%
X Endif
X Xctrl%=&HC0 Or Xseq%*8 Or Rseq%
X Xsum%=C:Chk%(L:Xpd%,W:Xpktsiz%,W:Xctrl%)
X Poke Xph%+2,Xsum%
X Xf1%=Xsum%/256
X Poke Xph%+3,Xf1%
X Poke Xph%+4,Xctrl%
X Poke Xph%+5,(Xpktcod% Xor Xsum% Xor Xf1% Xor Xctrl%)
X @Wchkwin(0)
X Else
X If Xpktsiz%<128 ! Empty Packet. (Always sent last.)
X Poke Xpd%,Xpktsiz%
X Else
X Poke Xpd%,Xpktsiz% And &H7F Or &H80
X Poke Xpd%+1,Xpktsiz%/128
X Endif
X Xctrl%=&HC0 Or Xseq%*8 Or Rseq%
X Xsum%=C:Chk%(L:Xpd%,W:Xpktsiz%,W:Xctrl%)
X Poke Xph%+2,Xsum%
X Xf1%=Xsum%/256
X Poke Xph%+3,Xf1%
X Poke Xph%+4,Xctrl%
X Poke Xph%+5,(Xpktcod% Xor Xsum% Xor Xf1% Xor Xctrl%)
X @Wchkwin(1)
X Xfdone!=True
X Endif
X Endif
XReturn
XRem
XRem This procedure sends data packets used for H,S,C type signals.
XRem It differs from the other data packets in that there are no short
XRem packets. Instead a zero follows each command string and a zero
XRem must appear as the last byte in the packet.
XRem
XProcedure Wrqtpkt ! Initial: Xrqp%=0, Wrklin$, Xfdone!=False.
X Xstp%=Varptr(Wrklin$)
X Xstl%=Len(Wrklin$)
X Xrqpo%=Xrqp%
X Xrqp%=Xrqp%+Xpktsiz%
X Xseq%=(Xseq%+1) And 7
X Xph%=Xppt%+Xseq%*Xpktsizh%
X Xpd%=Xph%+6
X Poke Xph%,&H10
X Poke Xph%+1,Xpktcod%
X Bmove Xstp%+Xrqpo%,Xpd%,Xpktsiz%
X If Xrqp%>Xstl%
X Poke Xpd%+Xpktsiz%-1,0
X Xfdone!=True
X Endif
X Xctrl%=&H80 Or Xseq%*8 Or Rseq%
X Xsum%=C:Chk%(L:Xpd%,W:Xpktsiz%,W:Xctrl%)
X Poke Xph%+2,Xsum%
X Xf1%=Xsum%/256
X Poke Xph%+3,Xf1%
X Poke Xph%+4,Xctrl%
X Poke Xph%+5,(Xpktcod% Xor Xsum% Xor Xf1% Xor Xctrl%)
X @Wchkwin(1)
XReturn
XRem
XRem This procedure sends RR's, RJ's, CLOSE, and INITA,B,C's.
XRem
XProcedure Wctlpkt(Wct%) ! wct%=0 for RR, 1 for Rj, 2 for other.
X If Wct%=0
X Wcc%=&H20 Or Rseq%
X Else
X If Wct%=1
X Wcc%=&H10 Or Rseq%
X Endif
X Endif
X Wc1%=&HAAAA-Wcc%
X Wc0%=Wc1% And &HFF
X Div Wc1%,256
X Wcx%=9 Xor Wc0% Xor Wc1% Xor Wcc%
X Out 1,&H10
X Out 1,&H9
X Out 1,Wc0%
X Out 1,Wc1%
X Out 1,Wcc%
X Out 1,Wcx%
XReturn
XRem
XRem This procedure waits to receive a data packet. It RR's them as soon
XRem as it sees them.
XRem
XProcedure Waitdata
X For Wf%=1 To 10
X @Waitframe
X If Dpkt!
X Nwp%=C:Rcv%(L:Rcvbf%,Rpktsiz%)
X Csum%=C:Chk%(L:Rcvbf%,Rpktsiz%,Cntrol%)
X If Rsum%=Csum% And ((Rseq%+1) And 7)=Rrseq% ! Verify data and seq.
X Rseq%=Rrseq%
X @Wctlpkt(0)
X Else
X Found!=False
X Endif
X Else
X Found!=False
X Endif
X Exit If Found!
X If Not Rr! ! Gets around a Telebit peculiarity.
X @Wctlpkt(1)
X Endif
X Next Wf%
X If Not Found!
X Print "Failed waiting for a data frame."
X @Hangup
X Endif
XReturn
XRem
XRem This procedure handles the windowing of sent data packets.
XRem It sends as many packets as allowed before waiting for RR's.
XRem
XProcedure Wchkwin(Flush%)
X If ((Xack%+Xwinsiz%+1) And 7)<>Xseq%
X Bput #2,Xph%,Xpktsizh%
X Else
X For Wf%=1 To 10
X @Waitframe
X If Rr!
X Bput #2,Xph%,Xpktsizh%
X Else
X Found!=False
X For Jr%=1 To Xwinsiz%
X Xjr%=(Xack%+Jr%) And 7
X Bput #2,Xppt%+Xjr%*Xpktsizh%,Xpktsizh%
X Exit If Xjr%=Xseq%
X Next Jr%
X Endif
X Exit If Rr!
X Next Wf%
X If Not Found!
X Print "Failed waiting for RR."
X @Hangup
X Endif
X Endif
X If Flush%=1
X While Xack%<>Xseq%
X For Wf%=1 To 10
X @Waitframe
X If Not Rr!
X Found!=False
X For Jr%=1 To Xwinsiz%
X Xjr%=(Xack%+Jr%) And 7
X Bput #2,Xppt%+Xjr%*Xpktsizh%,Xpktsizh%
X Exit If Xjr%=Xseq%
X Next Jr%
X Endif
X Exit If Rr!
X Next Wf%
X If Not Found!
X Print "Failed waiting for flushed RR."
X @Hangup
X Endif
X Wend
X Endif
XReturn
XRem ------------------------------------------------------------------
XRem CHECKSUM ROUTINE LISTING
XRem
XRem 206F0004 start: move.l 4(sp),a0 ; data packet start address.
XRem 322F0008 move.w 8(sp),d1 ; data packet length.
XRem 322F000A move.w 10(sp),d2 ; command byte.
XRem 203C0000FFFF move.l #$ffff,d0
XRem 4243 clr.w d3
XRem E358 ck1: rol.w #1,d0 ; do checksum on every
XRem 2800 move.l d0,d4 ; byte in the data packet.
XRem 4285 clr.l d5
XRem 1A18 move.b (a0)+,d5
XRem D045 add.w d5,d0
XRem 3A00 move.w d0,d5
XRem B345 eor.w d1,d5
XRem D645 add.w d5,d3
XRem B084 cmp.l d4,d0
XRem 6E02 bgt.s ovck
XRem B740 eor.w d3,d0
XRem 04410001 ovck: sub.w #1,d1
XRem 66E4 bne.s ck1
XRem 0242FFFF and.w #$ffff,d2
XRem B142 eor.w d0,d2 ; do checksum on command byte.
XRem 303CAAAA move.w #$aaaa,d0
XRem 9042 sub.w d2,d0 ; subtract everything from AAAA.
XRem 02800000FFFF and.l #$ffff,d0
XRem 4E75 rts
XRem ---------------------------------------------------------------------
XRem INPUT ROUTINE LISTING
XRem
XRem 286F0004 start: move.l 4(sp),a4 ; Buffer address.
XRem 382F0008 move.w 8(sp),d4 ; Packet size.
XRem 42A7 clr.l -(sp) ; Execute in superuser mode.
XRem 3F3C0020 move.w #$20,-(sp)
XRem 4E41 trap #1
XRem 5C8F addq.l #6,sp
XRem 2E00 move.l d0,d7 ; Save SUPER stack pointer.
XRem 2A39000004BA move.l $4ba,d5 ; Get initial time.
XRem 068500000960 add.l #2400,d5 ; Twelve second timeout.
XRem 3F3C0001 next: move.w #1,-(sp) ; Test for character.
XRem 3F3C0001 move.w #1,-(sp)
XRem 4E4D trap #13
XRem 588F addq.l #4,sp
XRem 4A40 tst d0
XRem 6714 beq.s nomore ; No character ready.
XRem 3F3C0001 move.w #1,-(sp) ; Else, get character.
XRem 3F3C0002 move.w #2,-(sp)
XRem 4E4D trap #13
XRem 588F addq.l #4,sp
XRem 18C0 move.b d0,(a4)+
XRem 5344 subq.w #1,d4
XRem 670C beq.s out
XRem 60DC bra.s next
XRem 2C39000004BA nomore: move.l $4ba,d6 ; Check timer.
XRem 9C85 sub.l d5,d6
XRem 6DD2 blt.s next
XRem 2F07 out: move.l D7,-(sp) ; Back to USER mode.
XRem 3F3C0020 move.w #$20,-(sp)
XRem 4E41 trap #1
XRem 5C8F addq.l #6,sp
XRem 2004 move.l d4,d0 ; D0=zero for success.
XRem 4E75 rts
XRem -------------------------------------------------------------------
X
SHAR_EOF
chmod 0600 mailtruk.lst || echo "restore of mailtruk.lst fails"
sed 's/^X//' << 'SHAR_EOF' > protocol.doc &&
X Packet Driver Protocol
X
X G. L. Chesson
X Bell Laboratories
X (Shortened by John Logajan)
XGeneral
X
X The technique depends on the
Xnotion of a transmission window to determine upper and lower
Xbounds for valid sequence numbers. The transmitter is
Xallowed to retransmit packets having sequence numbers within
Xthe window until the receiver indicates that packets have
Xbeen correctly received. Positive acknowledgement from the
Xreceiver moves the window; negative acknowledgement or no
Xacknowledgement causes retransmission. The receiver must
Xignore duplicate transmission, detect the various errors
Xthat may occur, and inform the transmitter when packets are
Xcorrectly or incorrectly received.
X
XPacket Formats
X
X The protocol is defined in terms of message transmis-
Xsions of 8-bit bytes. Each message includes one control
Xbyte plus a data segment of zero or more information bytes.
XThe allowed data segment sizes range between 32 and 4096 as
Xdetermined by the formula 32(2k) where k is a 3-bit number.
XThe packet sequence numbers are likewise constrained to 3-
Xbits; i.e. counting proceeds modulo-8.
X
X The control byte is partitioned into three fields as
Xdepicted below.
X
Xbit 7 6 5 4 3 2 1 0
X t t x x x y y y
X
XThe t bits indicate a packet type and determine the
Xinterpretation to be placed on the xxx and yyy fields. The
Xvarious interpretations are as follows:
X
X tt interpretation
X
X 00 control packet
X 10 data packet
X 11 short data packet
X
XA data segment accompanies all non-control packets. Each
Xtransmitter is constrained to observe the maximum data seg-
Xment size established during initial synchronization by the
Xreceiver that it sends to. Type 10 packets have maximal
Xsize data segments. Type 11, or short, packets have zero
Xor more data bytes but less than the maximum. The first one
Xor two bytes of the data segment of a short packet are
Xcount bytes that indicate the difference between the max-
Ximum size and the number of bytes in the short segment. If
Xthe difference is less than 127, one count byte is used. If
Xthe difference exceeds 127, then the low-order seven bits of
Xthe difference are put in the first data byte and the high-
Xorder bit is set as an indicator that the remaining bits of
Xthe difference are in the second byte.
X
X The sequence number of a non-control packet is given by
Xthe xxx field. Control packets are not sequenced. The
Xnewest sequence number, excluding duplicate transmissions,
Xaccepted by a receiver is placed in the yyy field of non-
Xcontrol packets sent to the other receiver.
X
X There are no data bytes associated with a control
Xpacket, the xxx field is interpreted as a control message,
Xand the yyy field is a value accompanying the control mes-
Xsage. The control messages are listed below in decreasing
Xpriority. That is, if several control messages are to be
Xsent, the lower-numbered ones are sent first.
X
X xxx name yyy
X
X 1 CLOSE n/a
X 2 RJ last correctly received sequence number
X 3 --- ---
X 4 RR last correctly received sequence number
X 5 INITC window size
X 6 INITB data segment size
X 7 INITA window size
X
X The CLOSE message indicates that the communications
Xchannel is to be shut down. The RJ, or reject, message
Xindicates that the receiver has detected an error and the
Xsender should retransmit after using the yyy field to update
Xthe window. The RR, or receiver
Xready, message indicates that the receiver has detected no
Xerrors; the yyy field updates the sender's window. The
XINITA/B/C messages are used to set window and data segment
Xsizes. Segment sizes are calculated by the formula 32(2yyy)
Xand window sizes may range between 1 and 7.
X
X Measurements of the protocol running on communication
Xlinks at rates up to 9600 baud showed that a window size of
X2 is optimal given a packet size greater than 32 bytes.
XThis means that the link bandwidth can be fully utilized by
Xthe software.
X
XMessage Exchanges
X
X Initialization
X
X Messages are exchanged between four cooperating enti-
Xties: two senders and two receivers. This means that the
Xcommunication channel is thought of as two independent
Xhalf-duplex data paths. For example the window and segment
Xsizes need not be the same in each direction.
X
X Initial synchronization is accomplished with two 3-way
Xhandshakes: two each of INITA/INITB/INITC. Each sender
Xtransmits INITA messages repeatedly. When an INITA message
Xis received, INITB is sent in return. When an INITB message
Xis received and an INITB message has been sent, an INITC
Xmessage is sent. The INITA and INITB messages carry with
Xthem the packet and window size that each receiver wants to
Xuse, and the senders are supposed to comply. When a
Xreceiver has seen all three INIT messages, the channel is
Xconsidered to be open. INIT messages are ignored elsewhere.
X
X Data Transport
X
X After initial synchronization each receiver sets a
Xmodulo-8 incrementing counter R to 0; each sender sets a
Xsimilar counter S to 1. The value of R is always the number
Xof the most recent correctly received packet. The value of
XS is always the first sequence number in the output window.
XLet W denote window size. Note that the value of W may be
Xdifferent for each sender.
X
X A sender may transmit packets with sequence numbers in
Xthe range S to (S+W-1) mod-8. At any particular time a
Xreceiver expects arriving packets to have numbers in the
Xrange (R+1) mod-8 to (R+W) mod-8. Packets must arrive in
Xsequence number order are are only acknowledged in order.
XThat is, the next packet a receiver will acknowledge must
Xhave sequence number (R+1) mod-8.
X
X A receiver acknowledges receipt of data packets by
Xarranging for the value of its R counter to be sent across
Xthe channel where it will be used to update an S counter.
XThis is done in two ways. If data is flowing in both direc-
Xtions across a channel then each receiver's current R value
Xis carried in the yyy field of non-control packets. Other-
Xwise when there is no bidirectional data flow, each
Xreceiver's R value is transmitted across the link as the yyy
Xfield of an RR control packet.
X
X Error handling is up to the discretion of the receiver.
XIt can ignore all errors in which case transmitter timeouts
Xmust provide for retransmission. The receiver may also gen-
Xerate RJ error control packets. The yyy field of an incom-
Xing RJ message replaces the S value of the local sender and
Xconstitutes a request for retransmission to start at that
Xsequence number.
X
X Termination
X
X The CLOSE message is used to terminate communications.
XSoftware on either or both ends of the communication channel
Xmay initiate termination. In any case when one end wants to
Xterminate it sends CLOSE messages until one is received from
Xthe other end or until a programmable limit on the number of
XCLOSE messages is reached. Receipt of a CLOSE message
Xcauses a CLOSE message to be sent.
X
X Framing
X
X The term framing is used to denote the technique by
Xwhich the beginning and end of a message is detected in a
Xbyte stream; error control denotes the method by which
Xtransmission errors are detected.
X
X A six byte framing envelope is constructed using the
Xcontrol byte C of a packet and five other bytes as depicted
Xbelow.
X <DLE><k><c0><c1><C><x>
XThe <DLE> symbol denotes the ASCII ctrl/P character. If the
Xenvelope is to be followed by a data segment, <k> has the
Xvalue log2(size)-4; i.e. 1 < k < 8. If k is 9, then the
Xenvelope represents a control packet. The <c0> and <c1>
Xbytes are the low-order and high-order bytes respectively of
Xa 16-bit checksum. For control packets, this value is
X0xAAAA minus the control byte C.
XFor data packets, the checksum is calculated by a program.
X(John Logajan's 68000 version is below.)
XThe <x> byte is the exclusive-or of <k><c0><c1><C>. Error
Xcontrol is accomplished by checking a received framing
Xenvelope for compliance with the definition, and comparing a
Xchecksum function of the data segment with <c0><c1>.
X
X This particular framing strategy assumes data segments
Xare constant-sized: the unused bytes in a short packet are
Xactually transmitted.
X
X------------------------------------------------------
XLogajan's 68000 version of the checksum program,
Xas called from a GFA Basic C: call.
X
Xstart: move.l 4(sp),a0 ;data packet start address
X move.w 8(sp),d1 ;data packet length
X move.w 10(sp),d2 ;command byte
X move.l #$ffff,d0
X clr.w d3
Xck1: rol.w #1,d0
X move.l d0,d4
X clr.l d5
X move.b (a0)+,d5
X add.w d5,d0
X move.w d0,d5
X eor.w d1,d5
X add.w d5,d3
X cmp.l d4,d0
X bgt.s ovck
X eor.w d3,d0
Xovck: sub.w #1,d1
X bne.s ck1
X and.w #$ffff,d2
X eor.w d0,d2
X move.w #$aaaa,d0
X sub.w d2,d0
X and.l #$ffff,d0 ;Checksum in D0.
X rts
X-----------------------------------------------------
XExample session:
X
XNote below: S = we send, R = we receive.
XAfter the login: and password: stuff;
X
XR Shere[=sitename]
XS Soursitename
XR ROK
XR Pg[other protcols]
XS Ug
XS INITA (with our window size)
XR INITA (with their window size)
XS INITB (with our packet size)
XR INITB (with their packet size)
XS INITC (with our window size, again)
XR INITC
XS S workline with D.file name. (If we have work, else H)
XR RR
XR SY
XS RR
XS data packets, short packet if need, followed by empty pkt.
XR RR's
XR CY
XS RR
XS S workline with X.file name.
XR RR
XR SY
XS data packets
XR RR's
XR CY
XS H (If we are done)
XR RR
XR HN (If they have work, else HY)
XS RR
XR S workline D.file
XS RR
XS SY
XR RR
XR data packets
XS RR's
XS CY
XR RR
XR S workline X.file
XS RR
XS SY
XR RR
XR data packets
XS RR's
XS CY
XR RR
XR H (If they are done too.)
XS RR
XS HY
XR RR
XR HY
XR RR
XS CLOSE
XR CLOSE
XS OOOOOO
XR OOOOOO (Hangup)
X-----------------------------------------------------
X
SHAR_EOF
chmod 0600 protocol.doc || echo "restore of protocol.doc fails"
sed 's/^X//' << 'SHAR_EOF' > readmail.lst &&
XRem READMAIL V1.0 for use with MAILTRUK, by John Logajan, Jan '89.
XRem --- PUBLIC DOMAIN ---
XRem Checks mailbox and reads letters. Saved files are always directed to the
XRem main mail directory specified below. Please customize the next two lines.
XRem
XMdir$="c:\mail\" ! Main upper level mail directory.
XMysite$="logajan\" ! Name of site mailbox directory.
XRem
XMwrk$=Mdir$+Mysite$+"WORK"
XMd$=Mdir$+Mysite$+"*.*"
XIf Exist(Mwrk$)
X Kill Mwrk$
XEndif
XIf Exist(Md$)
X Dir Md$ To Mwrk$
X Open "I",#3,Mwrk$
X M=0
X Bored!=False
X While Not Eof(#3)
X Line Input #3,Mfil$
X Mfix$=Mdir$+Mysite$+Mfil$
X If Exist(Mfix$)
X If Right$(Mfil$,2)=".X"
X Kill Mfix$
X Else
X If Mfil$<>"WORK"
X Inc M
X @More
X Repeat
X Cdn!=False
X Line Input "Next/Command";R$
X R$=Upper$(R$)
X If Len(R$)=0 Or Left$(R$,1)="N"
X Cdn!=True
X Endif
X If Left$(R$,1)="A" Or Left$(R$,1)="S"
X Snam$=Mid$(R$,3)
X If Len(Snam$)>0 And Len(Snam$)<13
X Open "I",#4,Mfix$
X If Left$(R$,1)="A"
X If Exist(Mdir$+Snam$)
X Open "A",#1,Mdir$+Snam$
X Else
X Print "File ";Mdir$;Snam$;" doesn't exist for appending";
X Print " -- Creating it."
X R$="S"
X Open "O",#1,Mdir$+Snam$
X Endif
X Else
X Open "O",#1,Mdir$+Snam$
X Endif
X Lc=0
X While Not Eof(#4)
X Inc Lc
X Line Input #4,I$
X Print #1,I$
X Wend
X Close #4
X Close #1
X If Left$(R$,1)="A"
X Print "File of ";Lc;" lines appended to ";Mdir$;Snam$
X Else
X Print "File of ";Lc;" lines saved in ";Mdir$;Snam$
X Endif
X Else
X Print "Filename - ";Snam$;" - too long."
X Endif
X Endif
X If Left$(R$,1)="D"
X Kill Mfix$
X Print "Message ";M;" deleted."
X Endif
X If Left$(R$,1)="T"
X If Exist(Mfix$)
X @More
X Else
X Print "Sorry, you have already deleted that message."
X Endif
X Endif
X If Left$(R$,1)="Q"
X Bored!=True
X Endif
X Exit If Bored!
X If Left$(R$,1)="H"
X @Hlp
X Endif
X Until Cdn!
X Endif
X Endif
X Endif
X Exit If Bored!
X Wend
X Close #3
X Kill Mwrk$
X If Not Bored!
X Print
X Print "No other mail."
X Endif
XElse
X Print "No mail."
XEndif
XPause 50
XEnd
XProcedure More
X Open "I",#4,Mfix$
X Fll%=Lof(#4)
X Llt%=0
X Dne!=False
X Print Chr$(27);"EMessage - ";M
X Llc%=23
X Do
X For Lc=1 To Llc%
X Line Input #4,C$
X Print C$
X Llt%=Llt%+Len(C$)
X If Eof(#4)
X Dne!=True
X Endif
X Exit If Dne!
X Next Lc
X Exit If Dne!
X Pc%=Int(Llt%/Fll%*100)
X Pmt:
X Print Chr$(27);"p--MORE--";Chr$(27)+"q(";Pc%;"%)";
X R%=Inp(2)
X Print Chr$(27);"l";
X If R%=Asc("Q") Or R%=Asc("q")
X Dne!=True
X Endif
X Exit If Dne!
X If R%=&HD
X Llc%=1
X Else
X Llc%=23
X Endif
X If R%=Asc("T") Or R%=Asc("t")
X Close #4
X Open "I",#4,Mfix$
X Fll%=Lof(#4)
X Llt%=0
X Print Chr$(27);"EMessage - ";M
X Llc%=23
X Endif
X If R%=Asc("H") Or R%=Asc("h")
X @Hlp
X Goto Pmt
X Endif
X Loop
X Close #4
XReturn
XProcedure Hlp
X Print
X Print "During message:"
X Print " q - skips to end."
X Print " t - reread from the top."
X Print " CR - read next line."
X Print " SPACE - read next page."
X Print " h - print this help listing."
X Print
X Print "At command prompt:"
X Print " n or CR - read next message."
X Print " d - delete current message."
X Print " (Undeleted messages remain in mailbox.)"
X Print " t - reread current message."
X Print " s filename - save message to file."
X Print " a filename - append message to file."
X Print " h - print this help listing."
X Print " q - quit back to desktop."
X Print
XReturn
X
SHAR_EOF
chmod 0600 readmail.lst || echo "restore of readmail.lst fails"
sed 's/^X//' << 'SHAR_EOF' > writmail.lst &&
XRem WRITMAIL V1.0 for use with MAILTRUK -- By John Logajan, Jan '89.
XRem --- PUBLIC DOMAIN ---
XRem User configuration area. Must be customized before using.
XRem
XUser$="john" ! your Mail name.
XFullname$="John Logajan" ! your full name.
XMachine$="logajan" ! your machine name.
XDmain$=".mn.org" ! your domain. (.uucp if unassigned)
XTimezone$="CST" ! your timezone.
XGmtfact=6 ! your timezone to GMT factor.
XMdir$="c:\mail\" ! main mail directory.
XWecall$="bungia,ziltch" ! list of machines you can call.
XSiglines=2 ! number of lines in signature. (Below)
XDim Sig$(Siglines)
XSig$(1)="- John Logajan @ 4248 Hamline Ave; Arden Hills, MN 55112 -"
XSig$(2)="- ...rutgers!bungia!logajan!john or john@logajan.mn.org -"
XRem
XPrint " WRITMAIL V1.0"
XGosub Help
XRepeat
X Line Input "Path: ",Tpath$
X If Len(Tpath$)=0
X End
X Endif
X Path$=""
X For J=1 To Len(Tpath$)
X If Mid$(Tpath$,J,1)<>"\" Then
X Path$=Path$+Mid$(Tpath$,J,1)
X Endif
X Next J
X P=1
X K=Instr(Path$,"!")
X If K=0 Then
X Print "Path must use at least one (!) symbol."
X P=0
X Else
X Neighbor$=Left$(Path$,K-1)
X Shortpath$=Mid$(Path$,K+1)
X If Instr(Wecall$,Neighbor$)=0 Then
X Print "-";Neighbor$;"- is not in our list of sites that we can call."
X P=0
X Else
X If Len(Shortpath$)=0 Then
X Print "Cannot end path with an (!) symbol."
X P=0
X Endif
X Endif
X Endif
XUntil P=1
XLine Input "Subject: ",Sub$
XIf Upper$(Sub$)="~C" Then
X End
XEndif
XDim Mes$(20000)
XM=0
XPrint
XPrint "Enter message, (.) alone sends message."
XPrint
XDo
X If M<0 Then
X M=0
X Endif
X Inc M
X Line Input "",Mes$(M)
X Exit If Mes$(M)="."
X If Upper$(Mes$(M))="~C" Then
X End
X Endif
X If Upper$(Mes$(M))="~H" Then
X Dec M
X Gosub Help
X Endif
X If Upper$(Mes$(M))="~D" Then
X M=M-2
X If M<=0 Then
X M=0
X Print "No message."
X Else
X Print
X For P=1 To M
X Print Mes$(P)
X Next P
X Endif
X Endif
X If Upper$(Mes$(M))="~V" Then
X Dec M
X If M>0 Then
X Print
X For P=1 To M
X Print Mes$(P)
X Next P
X Else
X Print "No message."
X Endif
X Endif
X If Upper$(Left$(Mes$(M),3))="~R " Then
X Rdfile$=Mid$(Mes$(M),4)
X If Exist(Rdfile$) Then
X Open "I",#1,Rdfile$
X Lc=0
X While Not Eof(#1)
X Line Input #1,Mes$(M)
X Inc M
X Inc Lc
X Wend
X Close #1
X Print "File of ";Lc;" lines read into message buffer."
X Else
X Dec M
X Print "No such file!"
X Endif
X Endif
X If Upper$(Mes$(M))="~S"
X M=M-1
X For J=1 To Siglines
X M=M+1
X Mes$(M)=Sig$(J)
X Print Mes$(M)
X Next J
X Endif
XLoop
XIf M=1 Then
X Print "No message to send -- Not sending."
X Pause 50
X End
XEndif
XSeq=10000+(Timer/100 And &H1FFF)
XSeqf$="A"+Str$(Seq And &H1FFF Or &H1000)
XDdir$=Mdir$+Neighbor$+"\"+Seqf$+".D"
XXdir$=Mdir$+Neighbor$+"\"+Seqf$+".X"
XCdir$=Mdir$+Neighbor$+"\"+Seqf$+".C"
XOpen "O",#1,Ddir$
XGosub Getdate
XYears=Year-1900
XPrint #1,"From"'Machine$;"!";User$'Dayweek$'Month$'Day'Time$'Year;Chr$(10);
XPrint #1,"Return-Path: <";Machine$;"!";User$;">";Chr$(10);
XPrint #1,"Received: by"'Machine$;Dmain$'"(MailTruk1.0)";Chr$(10);
XPrint #1," id AA";Seq;";"'Dayweek$;","'Day'Month$'Years'Time$'Timezone$;
XPrint #1,Chr$(10);
XPrint #1,"Date:"'Dayweek$;","'Day'Month$'Years'Time$'Timezone$;Chr$(10);
XPrint #1,"From:"'Machine$;Dmain$;"!";User$'"(";Fullname$;")";Chr$(10);
XPrint #1,"Message-Id: <";(((Years*100+Month)*100+Day)*100+Hgmt)*100+Minute;".";
XPrint #1,"AA";Seq;"@";Machine$;Dmain$;">";Chr$(10);
XPrint #1,"To:"'Path$;Chr$(10);
XIf Len(Sub$)>1 Then
X Print #1,"Subject:"'Sub$;Chr$(10);
XEndif
XPrint #1,Chr$(10);
XFor P=1 To M-1
X Print #1,Mes$(P);Chr$(10);
XNext P
XClose #1
XOpen "O",#2,Xdir$
XPrint #2,"U"'User$'Machine$;Chr$(10);
XPrint #2,"F"'"D.";Neighbor$;Seqf$;Chr$(10);
XPrint #2,"I"'"D.";Neighbor$;Seqf$;Chr$(10);
XPrint #2,"C rmail"'Shortpath$;Chr$(10);
XClose #2
XOpen "O",#3,Cdir$
XDest$="D."+Neighbor$+Seqf$
XBest$="D."+Machine$+Seqf$
XXest$="X."+Machine$+Seqf$
XPrint #3,"S"'Dest$'Dest$'User$'"-"'Dest$'"0666"
XPrint #3,"S"'Best$'Xest$'User$'"-"'Best$'"0666"
XClose #3
XPrint "Mail sent to outbound file area, awaiting UUCP."
XPause 50
XEnd
XProcedure Getdate ! returns Month,Day,Year,Dayweek,Dayweek$,Month$
X Local K,L ! Hour,Minute,Second,Ampm$,Hour12,Hgmt
X Month=Val(Mid$(Date$,1,2))
X Day=Val(Mid$(Date$,4,2))
X Year=Val(Mid$(Date$,7,4))
X Hour=Val(Mid$(Time$,1,2))
X Minute=Val(Mid$(Time$,4,2))
X Second=Val(Mid$(Time$,7,2))
X If Hour>=12 Then
X Ampm$="PM"
X Hour12=Hour-12
X Else
X Ampm$="AM"
X Hour12=Hour
X Endif
X If Hour12=0 Then
X Hour12=12
X Endif
X Month$=Mid$("JanFebMarAprMayJunJulAugSepOctNovDec",Month*3-2,3)
X Hgmt=Hour+Gmtfact
X If Hgmt>=24 Then
X Hgmt=Hgmt-24
X Endif
X K=Int(0.6+1/Month)
X L=Year-K
X Dayweek=Int(13*(Month+12*K+1)/5)+Int(5*L/4)-Int(L/100)+Int(L/400)+Day-1
X Dayweek=Dayweek-(7*Int(Dayweek/7))+1
X Dayweek$=Mid$("SunMonTueWedThuFriSat",Dayweek*3-2,3)
XReturn
XProcedure Help
X Print
X Print ". alone on line sends message."
X Print "~r filename -- reads in a file."
X Print "~d deletes previous line, and reprints message so far."
X Print "~c cancels message."
X Print "~h prints this help message."
X Print "~v reprints message so far."
X Print "~s adds predefined signature lines to message."
X Print "Paths are of the form: neighborsite!nextsite!...!sitex!recipient"
X Print "Subject: is optional. CR to skip it."
X Print
XReturn
X
SHAR_EOF
chmod 0600 writmail.lst || echo "restore of writmail.lst fails"
exit 0