execl (path, name, msgfd, addressfd, responsefd, msg_txname, msg_sender, (domsg) ? "y" : "n", 0) char *path, *name, *msg_txname, *msg_sender; int msgfd, addressfd, responsefd;
Each program's pattern for doing the fitting entails accessing the same types of modules, using similar types of interactions.
A channel module has an I/O package, which is called by higher-level read-mail and write-mail packages. They are called by the the ``fitting'' module. Hence, a process which transfers mail in both directions between two channels ``xx'' and ``yy'' will have the basic modules relationships:
xx_rdmail xx2yy_send yy_wtmail
xx_wtmail yy2xx_send yy_rdmail
As mentioned above, channel programs commonly send only from the local machine's deliver program, through module (qu_), out to a destination channel.
Such channel programs will have the basic structure:
qu_io qu_rdmail qu2yy_send yy_wtmail yy_io
The argument list is hidden from channel programs, by mapping it into the qu_* calls.
For example, the write-mail call that sends an address can send either of two positive responses: Address ok, or Message ok. The former means that only the address was sent and that the message text must be sent separately, when the address list is completed. The latter means that a copy of the entire message was sent. A channel that can return one of the two values may not ever return the other. It is the responsibility of the xx2yy_send module to check for correct return values.
The reason for the differences is that different channels may have very different protocol characteristics. For example, the local channel expects completed delivery of the entire message for each addressee. Alternatively, the SMTP package expects the address list for a message to be sent before the (one) copy of the message text.
For the currently implemented channels, the Local delivery channel expects text-writing calls after each address call. Most other channels expect addresses to be specified before text is sent. The independent local submission and pickup modules are list oriented, although submission can accept text-per-address, somewhat awkwardly. The deliver module (qu_) will handle either mode.
In many cases, particularly initializations, the module's calls for a phase are no-ops. However, they are included for completeness and to permit easy modification.
To callers, message initialization only requires passing a mode string (usually containing an m to indicate that the mail is for a mailbox, rather than a terminal) and a return address string.
Address passing entails iteratively passing a host/local address combination and retrieving a mmdf.h reply value for the address. The host portion may not be passed to the destination channel, as in the case of the local channel since there is no question for which host the address is intended. (This does not preclude the local address portion from containing additional host references, if the one receiving the address is a relay.)
Text transfer is essentially a stream file transfer, effected by repeated calls to pass successive chunks of the message.
Session handling (in xx_io):
* xx_init Get ready to handle mail * xx_end End this session * xx_synch Re-join sub-machines
* xx_sbinit Caller will be submitting mail * xx_sbend Done submitting mail
* xx_pkinit Caller wishes to receive mail xx_pkkill Caller wishes to stop receiving
Receiving mail (in xx_rmail):
* xx_rinit Caller wishes to receive a message xx_rkill Terminate current message
xx_rainit Caller ready to receive addresses * xx_radr Get an address
* xx_rtinit Caller ready to receive text * xx_rtxt Get some message text xx_rtcpy Give me a handle to text copy
Sending mail (in xx_wtmail):
* xx_winit Caller ready to send a message xx_wkill Terminate current message
* xx_wainit Get ready for addresses * xx_wadr Here is an address * xx_waend Done sending set of addresses
* xx_wtinit Get ready for message text * xx_wtxt Here is some message text * xx_wtend End of message text
Basic I/O (in xx_io):
* xx_wrply Here is a reply * xx_rrply Get a reply
* xx_wrec Here is a record/packet * xx_wstm Here is part of a stream of text
* xx_rrec Get a record * xx_rsinit Prepare to read stream * xx_rstm Get part of a stream of text
The asterisks indicate which calls currently are used by at least one channel.
A common calling sequence will comprise:
xx_init /* init for sending */ xx_winit /* init first message */ xx_wadr /* send first address */ xx_rrply /* address acceptable? */ xx_wadr /* second address... */ xx_rrply ... xx_waend /* no more addresses */ xx_wtinit /* message text next */ xx_wtxt /* send a chunk of it */ xx_wtxt /* another... */ ... xx_wtend /* no more message */ xx_rrply /* text accepted ok?*/ xx_winit /* next message... */ ... xx_sbend /* no more sending */ xx_end /* done with channel */
Note that the only direct user calls to the xx_io part of the module are for initialization. No record or stream calls are made directly.
|SMTP||smtp||Internet RFC821 SMTP outbound|
|SMTP||smtpsrvr||Internet RFC821 SMTP inbound|
|Local||local||Local machine send|
|UUCP||uucp||UUCP outbound (calls uux)|
|List||list||Re-submit mailing list mail with header rewriting|
|Delay||delay||Delay channel (to resubmit due to NS failure)|
|Prog||sendprog*||Generalized program interface (outbound)|
|Prog||recvprog*||Generalized program interface (inbound)|
Lo_wtmail effects actual mailbox-stuffing. It does not have an associated lo_io because it was not needed.