From ncr-sd!hp-sdd!hplabs!sri-unix!husc6!uwvax!uwmacc!vms.macc.wisc.edu!dorl Mon Sep 7 16:14:53 PDT 1987 The following programs implement a 'TEST' foreign mail protocol for use with the DEC VMS Mail utility. Its purpose is to show the various calls made by Mail and their parameters. As always, the MAILSHR programs are courtesy of Kevin Carosso @ Hughes Aircraft Co. By the way, does anyone really know if programs such as my Prot.For in the following example share their data space with other invocations of the protocol or if each instance gets its own copy? Mike Dorl MACC University of Wisconsin dorl@vms.macc.wisc.edu ----------------- :Prot.For : ----------------- Integer *4 Function Mail_Out_Connect $ (Context, Type, Protocol, NodeName, $ LogLink, Rat, RFm, Flags, File) Implicit Integer (A-Z) C Parameter definitions Integer Context Integer Type Character *(*) Protocol Character *(*) NodeName Integer LogLink Integer Rat Integer RFm Integer Flags Integer File C Local definitions Integer *4 Context_Block(100) C Begin Context = %Loc(Context_Block) Context_Block(1) = 1234321 Print '(A)', ' Mail_Out_Connect' Print '(A,Z)', ' Context = ', Context Print '(A,I)', ' Type = ', %Loc(Type) Print '(A)', ' Prot = ' // '"' // Protocol // '"' Print '(A)', ' Node = ' // '"' // NodeName // '"' Print '(A,Z)', ' LogLink = ', %Loc(LogLink) Print '(A,Z)', ' Rat = ', %Loc(Rat) Print '(A,Z)', ' RFm = ', %Loc(RFm) Print '(A,Z)', ' Flags = ', %Loc(Flags) Print '(A,Z)', ' File = ', %Loc(File) Mail_Out_Connect = 1 Return End Integer *4 Function Mail_Out_Line $ (Context, Type, Node, Text) Implicit Integer (A-Z) C Parameter definitions Integer Context Integer Type Character *(*) Node Character *(*) Text Print '(A)', ' Mail_Out_Line' Print '(A,Z)', ' Context = ', Context Print '(A,I)', ' Type = ', %Loc(Type) Print '(A)', ' Node = "' // Node // '"' Print '(A)', ' Text = "' // Text // '"' Mail_Out_Line = 1 Return End Integer *4 Function Mail_Out_Check $ (Context, Type, Node, Address, Error) Implicit Integer (A-Z) C Parameter definitions Integer Context Integer Type Character *(*) Node Character *(*) Address Integer Error C Begin Print '(A)', ' Mail_Out_Check' Print '(A,Z)', ' Context = ', Context Print '(A,I)', ' Type = ', %Loc(Type) Print '(A)', ' Node = "' // Node // '"' Print '(A)', ' Address = "' // Address // '"' Print '(A,I)', ' Error = ', %Loc(Error) If ((%Loc(Type) .eq. 2) .and. (Address .eq. 'ERROR')) Then Mail_Out_Check = 2 print '(A)', ' Status = 2' Else Mail_Out_Check = 1 EndIf Return End Integer *4 Function Mail_Out_File $ (Context, Type, Node, Rab, Error) Implicit Integer (A-Z) Include '($RABDef)/list' C Parameter definition Integer Context Integer Type Character *(*) Node Record /RABDef/ Rab Integer Error C Local Definitions Character *80 Image C Begin Print '(A)', ' Mail_Out_File' Print '(A,Z)', ' Context = ', Context Print '(A,I)', ' Type = ', %Loc(Type) Print '(A)', ' Node = "' // Node // '"' Print '(A,I)', ' Rab = ', %Loc(Rab) Print '(A,I)', ' Error = ', %Loc(Error) Print '(A)', ' Message text:' Status = Sys$Disconnect (RAB) RAB.RAB$L_ROP = IAnd ( RAB.RAB$L_ROP, Not(RAB$M_BIO)) Status = Sys$Connect (RAB) RAB.RAB$L_UBF = %Loc(Image) RAB.RAB$W_USz = 80 Do While (Status) Status = Sys$Get (RAB) If (Status) Then Print '(x,A)', Image (1:RAB.RAB$W_RSz) EndIf EndDo Mail_Out_File = 1 Return End Integer *4 Function Mail_Out_DeAccess $ (Context,Type) C Parameter definition Integer Context Integer Type C Begin Print '(A)', ' Mail_Out_DeAccess' Print '(A,Z)', ' Context = ', Context Print '(A,I)', ' Type = ', %Loc(Type) Mail_Out_DeAccess = 1 Return End Integer *4 Function Mail_In_Connect Print '(A)', ' Mail_In_Connect' Mail_In_Connect = 1 Return End Integer *4 Function Mail_In_Line Print '(A)', ' Mail_In_Line' Mail_In_Line = 1 Return End Integer *4 Function Mail_In_File Print '(A)', ' Mail_In_File' Mail_In_File = 1 Return End Integer *4 Function Mail_IO_Read Print '(A)', ' Mail_IO_Read' Mail_IO_Read = 1 Return End Integer *4 Function Mail_IO_Write Print '(A)', ' Mail_IO_Write' Mail_IO_Write = 1 Return End c Integer *4 Function MailShr$_UnkFunc c c Print '(A)', ' MailShr$UnkFunc' c c MailShr$UnkFunc = 1 c c Return c c End ----------------- :MailShr.Mar : ----------------- .Title MAILSHR - Foreign mail protocol interface ; ; Written by Kevin Carosso @ Hughes Aircraft Co., SCG/CTC, January 11, 1985 ; ;--------------------------------------------------------------------------- ; This is invoked by MAIL when it encounters the foreign mail protocol. ; This module really has nothing protocol-specific to it and can be used ; to dispatch to any handler. The handler should supply the following ; action routines: ; ; status := MAIL_OUT_CONNECT (context : unsigned; ; LNK_C_OUT_CONNECT : immediate; ; protocol, node : string_descriptor; ; MAIL$_LOGLINK : immediate; ; file_RAT, file_RFM : immediate; ; MAIL$GL_FLAGS : immediate; ; attached_file : descriptor := immediate 0) ; ; status := MAIL_OUT_LINE (context : unsigned; ; [LNK_C_OUT_SENDER | LNK_C_OUT_TO | ; LNK_C_OUT_SUBJ] : immediate; ; node, sender_name : string_descriptor) ; ; status := MAIL_OUT_CHECK (context : unsigned; ; [LNK_C_OUT_CKUSER | ; LNK_C_OUT_CKSEND] : immediate; ; node, addressee : string_descriptor; ; procedure MAIL$READ_ERROR_TEXT); ; ; status := MAIL_OUT_FILE (context : unsigned; ; LNK_C_OUT_FILE : immediate; ; node : string_descriptor; ; rab : $RAB_TYPE; ; procedure UTIL$REPORT_IO_ERROR); ; ; status := MAIL_OUT_DEACCESS (context : unsigned; ; LNK_C_OUT_DEACCESS : immediate); ; ; status := MAIL_IN_CONNECT (context : unsigned; ; LNK_C_IN_CONNECT : immediate; ; input_tran : string_descriptor; ; file_RAT, file_RFM : immediate; ; MAIL$GL_FLAGS : immediate; ; MAIL$Q_PROTOCOL : string_descriptor; ; pflags : immediate); ; ; status := MAIL_IN_LINE (context : unsigned; ; [LNK_C_IN_SENDER | LNK_C_IN_CKUSER | ; LNK_C_IN_TO | LNK_C_IN_SUBJ] : immediate; ; returned_line : string_descriptor); ; ; status := MAIL_IN_FILE (context : unsigned; ; LNK_C_OUT_FILE : immediate; ; 0 : immediate; ; rab : $RAB_TYPE; ; procedure UTIL$REPORT_IO_ERROR); ; ; status := MAIL_IO_READ (context : unsigned; ; LNK_C_IO_READ : immediate; ; returned_text_line : string_descriptor); ; ; status := MAIL_IO_WRITE (context : unsigned; ; LNK_C_IO_WRITE : immediate; ; text_line : string_descriptor); ; ;--------------------------------------------------------------------------- ; ; Define major and minor protocol identifiers. MAIL requires that these ; be 1. The shareable image MUST be linked with the options file MAILSHR.OPT ; that promotes these symbols to UNIVERSAL symbols so they will end up ; in the shareable image's symbol table. ; MAIL$C_PROT_MAJOR == 1 MAIL$C_PROT_MINOR == 1 ; ; Constants for dispatcher, taken from MAIL.SDL listing ; LNK_C_FIRST = 0 LNK_C_OUT_CONNECT == 0 LNK_C_OUT_SENDER == 1 LNK_C_OUT_CKUSER == 2 LNK_C_OUT_TO == 3 LNK_C_OUT_SUBJ == 4 LNK_C_OUT_FILE == 5 LNK_C_OUT_CKSEND == 6 LNK_C_OUT_DEACCESS == 7 LNK_C_IN_CONNECT == 8 LNK_C_IN_SENDER == 9 LNK_C_IN_CKUSER == 10 LNK_C_IN_TO == 11 LNK_C_IN_SUBJ == 12 LNK_C_IN_FILE == 13 LNK_C_IO_READ == 14 LNK_C_IO_WRITE == 15 LNK_C_LAST = 15 ; ; Here's the main routine that is called by MAIL. Note that we don't really ; do any work here, just dispatch the call to the appropriate handler. The ; reason I do it this way is that I am not interested in writing the handlers ; in MACRO, and I cannot easily deal with different numbers of arguments in ; the same procedure in other languages. ; ; ; General argument offset to the function code: ; LNK_FUNCTION = 8 ; ; Shareable image transfer vectors ; .Transfer MAIL$PROTOCOL .Mask MAIL$PROTOCOL jmp L^MAIL$PROTOCOL + 2 .Entry MAIL$PROTOCOL, ^M caseb LNK_FUNCTION(ap), #LNK_C_FIRST, - ; Dispatch to handler # 10$: .word Dispatch_out_connect - 10$ ; LNK_C_OUT_CONNECT .word Dispatch_out_line - 10$ ; LNK_C_OUT_SENDER .word Dispatch_out_check - 10$ ; LNK_C_OUT_CKUSER .word Dispatch_out_line - 10$ ; LNK_C_OUT_TO .word Dispatch_out_line - 10$ ; LNK_C_OUT_SUBJ .word Dispatch_out_file - 10$ ; LNK_C_OUT_FILE .word Dispatch_out_check - 10$ ; LNK_C_OUT_CKSEND .word Dispatch_out_deaccess - 10$ ; LNK_C_OUT_DEACCESS .word Dispatch_in_connect - 10$ ; LNK_C_IN_CONNECT .word Dispatch_in_line - 10$ ; LNK_C_IN_SENDER .word Dispatch_in_line - 10$ ; LNK_C_IN_CKUSER .word Dispatch_in_line - 10$ ; LNK_C_IN_TO .word Dispatch_in_line - 10$ ; LNK_C_IN_SUBJ .word Dispatch_in_file - 10$ ; LNK_C_IN_FILE .word Dispatch_IO_read - 10$ ; LNK_C_IO_READ .word Dispatch_IO_write - 10$ ; LNK_C_IO_WRITE unknown: pushl LNK_FUNCTION(ap) ; FAO parameter in the function code pushl #1 pushl #MAILSHR$_UNKFUNC ; Signal unknown function code calls #3, G^LIB$SIGNAL ; if we fall through dispatcher. movl #MAILSHR$_UNKFUNC, r0 ret ; ; The dispatchers ; Dispatch_out_connect: callg (ap), MAIL_OUT_CONNECT ret Dispatch_out_line: callg (ap), MAIL_OUT_LINE ret Dispatch_out_check: callg (ap), MAIL_OUT_CHECK ret Dispatch_out_file: callg (ap), MAIL_OUT_FILE ret Dispatch_out_deaccess: callg (ap), MAIL_OUT_DEACCESS ret Dispatch_in_connect: callg (ap), MAIL_IN_CONNECT ret Dispatch_in_line: callg (ap), MAIL_IN_LINE ret Dispatch_in_file: callg (ap), MAIL_IN_FILE ret Dispatch_IO_read: callg (ap), MAIL_IO_READ ret Dispatch_IO_write: callg (ap), MAIL_IO_WRITE ret .end ----------------- :MailShr.Opt : ----------------- universal=MAIL$C_PROT_MAJOR, MAIL$C_PROT_MINOR ------------------------- :MailShr_Errs.Msg : ------------------------- .Title MAILSHR error messages .Facility MAILSHR,1/prefix=MAILSHR$_ .Ident 'MAILSHR Version 1.0' .Severity error UNKFUNC /FAO=1 .End ----------------- :LinkProt.Com : ----------------- $Link/share=TMailProt/NoTrace Prot,MailShr,MailShr_errs,MailShr.opt/opt ----------------- :InstallProt.Com: ----------------- $Run Sys$System:Install whatever:tmailprot.exe/delete whatever:tmailprot.exe/open/priv=(sysprv,detach) $ $define/sys/exec mail$protocol_test test_mailprot $define/sys/exec test_mailprot whatever:tmailprot.exe $ From ncr-sd!hp-sdd!hplabs!ucbvax!ISUMVS.BITNET!GA.JPH Thu Sep 3 14:41:34 PDT 1987 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: OUT_DEACCESS: 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