[comp.os.vms] VMS MAIL Foreign Protocol Guide

GA.JPH@ISUMVS.BITNET.UUCP (09/02/87)

Fellow netlanders:

   There as been considerable interest in the VMS MAIL foreign protocol
interface recently.  The following is a quick guide to this interface, based on
what I have learned over the past few months.  This information is mostly
complete and correct as far as I know.  If you cut on the dotted lines and print
on a printer with 60 or 66 lines/page the page breaks will fall nicely.

------------------------------ cut here ----------------------------------------



                          VMS MAIL Foreign Protocol


                               John P. Hascall
                            Iowa State University
                              Computation Center


   When VMS mail is given a "foreign protocol" address (either at the To: prompt
or on the command line) of the form:

   protocol%"address"

or mail is invoked with the command:

   MAIL/PROTOCOL=protocol_MAILSHR file-name.type;ver

it uses LIB$FIND_IMAGE_SYMBOL to merge SYS$SHARE:protocol_MAILSHR.EXE into its
address space.  Mail then enters into a "conversation" with this image.  The
requirements the image must meet and the conversation are detailed below.



IMAGE REQUIREMENTS:

   1)  Entry Point:        MAIL$PROTOCOL

   2)  Installed:          /SHARE/OPEN/HEADER/PRIV=(WORLD,NETMBX,OPER,SYSPRV)
                           (the same privileges as MAIL)

   3)  Universal Symbols:  MAIL$C_PROT_MAJOR == 1, MAIL$C_PROT_MINOR == 1
                           (see the linker manual for more on universal symbols)

   4)  Code:               The usual rules for producing a sharable image.
                           (see the linker manual)



CONVERSATION

   Once VMS mail has determined that the suitable foreign protocol image exists,
it calls the routine MAIL$PROTOCOL several times with varying arguments.  There
are two different conversations depending on how MAIL was invoked.  If an
address like protocol%"address" was specified then mail enters an "out-going"
conversation.  If MAIL was invoked with /PROTOCOL=protocol_MAILSHR
file-name.type.ver then MAIL enters an "in-coming" conversation to deliver the
message in the file.

   For either type of conversation MAIL calls MAIL$PROTOCOL several times.  Each
time MAIL$PROTOCOL is called the arguments are:

        0(AP)   - Number of arguments
        4(AP)   - Address of a Context variable        (argument 1)
        8(AP)   - Function code                        (argument 2)
      .
          . arguments 3, 4, 5... depend on the function code
          .

   For an out-going conversation MAIL$PROTOCOL is called with the following
function codes in this order (unless an error occurs or the user aborts the
message (i.e., presses C), in which case LNK_C_OUT_DEACCESS is called
immediately):

   LNK_C_OUT_CONNECT    =       0       ; Outbound connect
   LNK_C_OUT_SENDER     =       1       ; Sender Text (the From: line)
   LNK_C_OUT_CKUSER     =       2       ; Recipient (this code will be repeated
                                          once for each recipient and then once
                                          more with a NULL recipient.
   LNK_C_OUT_TO         =       3       ; Recipients Text (the To: line)
   LNK_C_OUT_SUBJ       =       4       ; Subject Text (the Subject: line)
   LNK_C_OUT_FILE       =       5       ; The body of the message.
   LNK_C_OUT_CKSEND     =       6       ; Send the message.
   LNK_C_OUT_DEACCESS   =       7       ; End conversation

and for an incoming message:

   LNK_C_IN_CONNECT     =       8       ; Inbound connect
   LNK_C_IN_SENDER      =       9       ; return the sender text (From: line)
   LNK_C_IN_CKUSER      =      10       ; return the next recipient (username)
                                        ; or a NULL byte to indicate no more
                                        ; (is called repeatedly)
   LNK_C_IN_TO          =      11       ; return the recipient text (To: line)
   LNK_C_IN_SUBJ        =      12       ; return the subject text (Subj: line)
   LNK_C_IN_FILE        =      13       ; input the text of the file
   LNK_C_OUT_DEACCESS   =       7       ; end conversation

and some utility function codes (which may be called at any time they are
necessary):

   LNK_C_IO_READ        =      14       ; read a line (this function is never
                                          invoked as I can tell)
   LNK_C_IO_WRITE       =      15       ; write a line (used to send us either
                                          an error code or error message)


   The first two arguments to MAIL$PROTOCOL are always the pointer to the
context variable and the function code.  The remaining arguments depend on
the function code.  They are as follows:

OUT_CONNECT:    12(AP)          ; address of a descriptor of a string which
                                  is the protocol name
                16(AP)          ; address of a descriptor of a string which
                                  is our node name
                20(AP)          ; MAIL$_LOGLINK  [logical link] (immediate)
                24(AP)          ; RAT of mail file (immediate)
                28(AP)          ; RFM of mail file (immediate)
                32(AP)          ; MAIL$GL_FLAGS  [global flags] (immediate)
                36(AP)          ; address of a descriptor of a string which
                                  is the attached file (whatever that means)

OUT_SENDER:     12(AP)          ; address of descriptor of senders node name
                16(AP)          ; address of descriptor of senders username

OUT_CKUSER:     12(AP)          ; address of descriptor of recipients node name
                16(AP)          ; address of descriptor of recipients username
                20(AP)          ; address of a routine to call if a recipient
                                  is bad

OUT_TO:         12(AP)         ; address of descriptor of local node name
                16(AP)         ; address of descriptor of To: line text

OUT_SUBJ:       12(AP)         ; address of descriptor of local node name
                16(AP)         ; address of descritpor of Subject: line text

OUT_FILE:       12(AP)         ; address of descriptor of local node name
                16(AP)         ; address of RAB of file to be mail, file is
                                 opened for BLOCK I/O and connected already
                20(AP)         ; address of a routine to call in case of
                                 an I/O error

OUT_CKSEND:     <no other arguments>

OUT_DEACCESS:   <no other arguments>

IN_CONNECT:     12(AP)                  ; addr of descr of input translate table
                16(AP)                  ; RAT (immediate)
                20(AP)                  ; RFM (immediate)
                24(AP)                  ; MAIL$GL_SYSFLAGS
                28(AP)                  ; address of descriptor of protocol name
                32(AP)                  ; server flags (???)

IN_SENDER:      12(AP)                  ; addr of descr to return From: text to

IN_CKUSER:      12(AP)                  ; addr of descr to return recip username

IN_TO:          12(AP)                  ; addr of descr to return To: text to

IN_SUBJ:        12(AP)                  ; addr of descr to return Subj: text to

IN_FILE:        12(AP)                  ; ??? Unknown argument
                16(AP)                  ; address of RAB
                20(AP)                  ; addr to call in case of an I/O error

IO_READ:        12(AP)                  ; addr of descr to return something

IO_WRITE:       12(AP)                  ; addr of descr of an error code or an
                                          error message MAIL has sent us


NOTES

   Since this is a sharable image, it may be being executed by more than one
process at a time.  When a connect function is received, use LIB$GET_VM to
allocate enough memory for all the information you need for a mail message and
store the address of this block in the provided context variable.  On successive
calls the context variable will point to the block for that message.  You can
delete this virtual memory upon receiving the OUT_DEACCESS function.

   I have the framework of an interface to this protocol which is available.
This program is based on one written by Gerard K.  Newman of the San Diego
Supercomputer Center to whom I am grateful for making my investigation of this
topic much shorter and easier by giving me a copy of his interface (wish I'd had
it when I started, as I did a great deal of "re-inventing the wheel").  I hope
to spare the the rest of you some of this re-inventing.

   If anyone has any additional information or corrections on this subject, I
would be like to keep this information as complete and correct as possible.
-------------------------- end of text -----------------------------------------


John Hascall
(GA.JPH@ISUMVS.BITNET) or (GAJPH@ISUMVS.BITNET if the "." is a problem)

Iowa State University Computation Center
104 Computer Science
Ames, Iowa  50010
(515) 294-9889