Date: Fri, 15 Mar 1991 08:50:18 EST
From: "Hunter Goatley, WKU" <goathunter%WKUVX1.BITNET@vms.ecs.rpi.edu>
To: madison@vms.ecs.rpi.edu
Message-ID: <00945a2b.35b31740.12697@WKUVX1.BITNET>
Subject: MX_BULL for [.CONTRIB]

Matt,

Below is MX_BULL, my MX to BULLETIN transport.  I like the possibilities that
MX's SITE agent gives; it's very simple, making it very flexible....

If you want to put it in [.CONTRIB], please do so.

Thanks.

Hunter Goatley, WKU, goathunter@wkuvx1.bitnet, 502-745-5251

$! ------------------ CUT HERE -----------------------
$ v='f$verify(f$trnlnm("SHARE_VERIFY"))'
$!
$! This archive created by VMS_SHARE Version 7.2-007  22-FEB-1990
$!   On 14-MAR-1991 17:00:56.58   By user GOATHUNTER
$!
$! This VMS_SHARE Written by:
$!    Andy Harper, Kings College London UK
$!
$! Acknowledgements to:
$!    James Gray       - Original VMS_SHARE
$!    Michael Bednarek - Original Concept and implementation
$!
$! TO UNPACK THIS SHARE FILE, CONCATENATE ALL PARTS IN ORDER
$! AND EXECUTE AS A COMMAND PROCEDURE  (  @name  )
$!
$! THE FOLLOWING FILE(S) WILL BE CREATED AFTER UNPACKING:
$!       1. MX_BULL.TXT;1
$!       2. MX_BULL.C;1
$!       3. MX_BULL_SITE_DELIVER.COM;1
$!       4. BUILD_MX_BULL.COM;1
$!
$set="set"
$set symbol/scope=(nolocal,noglobal)
$f=f$parse("SHARE_TEMP","SYS$SCRATCH:.TMP_"+f$getjpi("","PID"))
$e="write sys$error  ""%UNPACK"", "
$w="write sys$output ""%UNPACK"", "
$ if f$trnlnm("SHARE_LOG") then $ w = "!"
$ ve=f$getsyi("version")
$ if ve-f$extract(0,1,ve) .ges. "4.4" then $ goto START
$ e "-E-OLDVER, Must run at least VMS 4.4"
$ v=f$verify(v)
$ exit 44
$UNPACK: SUBROUTINE ! P1=filename, P2=checksum
$ if f$search(P1) .eqs. "" then $ goto file_absent
$ e "-W-EXISTS, File ''P1' exists. Skipped."
$ delete 'f'*
$ exit
$file_absent:
$ if f$parse(P1) .nes. "" then $ goto dirok
$ dn=f$parse(P1,,,"DIRECTORY")
$ w "-I-CREDIR, Creating directory ''dn'."
$ create/dir 'dn'
$ if $status then $ goto dirok
$ e "-E-CREDIRFAIL, Unable to create ''dn'. File skipped."
$ delete 'f'*
$ exit
$dirok:
$ w "-I-PROCESS, Processing file ''P1'."
$ if .not. f$verify() then $ define/user sys$output nl:
$ EDIT/TPU/NOSEC/NODIS/COM=SYS$INPUT 'f'/OUT='P1'
PROCEDURE Unpacker ON_ERROR ENDON_ERROR;SET(FACILITY_NAME,"UNPACK");SET(
SUCCESS,OFF);SET(INFORMATIONAL,OFF);f:=GET_INFO(COMMAND_LINE,"file_name");b:=
CREATE_BUFFER(f,f);p:=SPAN(" ")@r&LINE_END;POSITION(BEGINNING_OF(b));
LOOP EXITIF SEARCH(p,FORWARD)=0;POSITION(r);ERASE(r);ENDLOOP;POSITION(
BEGINNING_OF(b));g:=0;LOOP EXITIF MARK(NONE)=END_OF(b);x:=ERASE_CHARACTER(1);
IF g=0 THEN IF x="X" THEN MOVE_VERTICAL(1);ENDIF;IF x="V" THEN APPEND_LINE;
MOVE_HORIZONTAL(-CURRENT_OFFSET);MOVE_VERTICAL(1);ENDIF;IF x="+" THEN g:=1;
ERASE_LINE;ENDIF;ELSE IF x="-" THEN IF INDEX(CURRENT_LINE,"+-+-+-+-+-+-+-+")=
1 THEN g:=0;ENDIF;ENDIF;ERASE_LINE;ENDIF;ENDLOOP;t:="0123456789ABCDEF";
POSITION(BEGINNING_OF(b));LOOP r:=SEARCH("`",FORWARD);EXITIF r=0;POSITION(r);
ERASE(r);x1:=INDEX(t,ERASE_CHARACTER(1))-1;x2:=INDEX(t,ERASE_CHARACTER(1))-1;
COPY_TEXT(ASCII(16*x1+x2));ENDLOOP;WRITE_FILE(b,GET_INFO(COMMAND_LINE,
"output_file"));ENDPROCEDURE;Unpacker;QUIT;
$ delete/nolog 'f'*
$ CHECKSUM 'P1'
$ IF CHECKSUM$CHECKSUM .eqs. P2 THEN $ EXIT
$ e "-E-CHKSMFAIL, Checksum of ''P1' failed."
$ ENDSUBROUTINE
$START:
$ create 'f'
X                                    MX_BULL
X                             An MX SITE transport
X                                March 14, 1991
X
XMX_BULL is a transport between MX and BULLETIN, a VMS bulletin board program
Xby Mark London at MIT.  It is designed to be called as an MX SITE transport,
Xletting MX write messages into BULLETIN folders as they are processed, inste
Vad
Xof routing the messages to MAIL.MAI files for each folder.
X
XThe following files make up the MX_BULL distribution:
X
X   BUILD_MX_BULL.COM`09`09Command procedure to build MX_BULL.EXE
X   MX_BULL.C`09`09`09VAX C source code for MX_BULL
X   MX_BULL.TXT`09`09`09This file
X   MX_BULL_SITE_DELIVER.COM`09SITE_DELIVER.COM for MX_BULL
X
XThe current version is 01-001.
X
X
XWHAT IS BULLETIN?
X-----------------
XBULLETIN is a VMS bulletin board written by Mark London at MIT that allows
Xmultiple users to access a common message base.  Messages are divided into
Xfolders, which work much like VMS Mail folders.  Using MX_BULL, messages can
Xbe routed from Internet/Bitnet mailing lists directly to BULLETIN folders,
Xallowing all (or some) users on a system to access the mailing lists without
Xindividual subscriptions.  This can cut down on the number of incoming
XBitnet/Internet mail messages significantly, since only one copy of a messag
Ve
Xneed be sent to a site.
X
XBULLETIN can be found on a number of the DECUS VAX SIG tapes, including the
XFall 1990 tapes.  It can also be retrieved by sending a mail message to
XBULLETIN@NERUS.PFC.MIT.EDU.  The body of the message must contain one of
Xthe following commands:
X
X        SEND ALL        Sends all bulletin files.
X        SEND filename   Sends the specified file.
X        BUGS            Sends a list of the latest bug fixes.
X        HELP or INFO    Sends a brief description of BULLETIN.
X
X
XBUILDING MX_BULL.EXE
X--------------------
XMX_BULL is written in VAX C and can be compiled by executing BUILD_MX_BULL.C
VOM.
X
XMX_BULL must be linked with the BULLETIN object library, BULL.OLB.  The
Xbuild procedure for MX_BULL expects the logical BULL_SOURCE to point to the
XBULLETIN library.  You must define this logical (or edit the .COM file)
Xbefore building MX_BULL.
X
X
XINSTALLING MX_BULL
X------------------
XTo install MX_BULL, perform the following steps:
X
X1.  Using MCP, define a path named BULLETIN as a SITE transport:
X
X`09MCP> DEFINE PATH "BULLETIN" SITE
X
X2.  Using MCP, define a rewrite rule early in the list (this should actually
X    be done using CONFIG.MCP so that the order is correct):
X
X`09MCP> DEFINE REWRITE_RULE "<`7Bfolder`7D@BULLETIN>" "<`7Bfolder`7D@BULLETI
VN>"
X
X3.  If you don't have a SITE transport already defined, simply copy
X    MX_BULL_SITE_DELIVER.COM to MX_EXE:SITE_DELIVER.COM.
X
X    If you do have a SITE transport defined, you'll need to merge the MX_BUL
VL
X    stuff into the existing MX_EXE:SITE_DELIVER.COM.
X
X4.  Reset the MX routers by using MCP RESET/ALL, or shutting down MX and
X    restarting it.
X
XOnce these steps have been completed, MX_BULL is set up to begin delivering
Xmessages to BULLETIN.
X
X
XROUTING MESSAGES TO BULLETIN
X----------------------------
XMessages are routed to BULLETIN folders by addressing mail to
XMX%"folder@BULLETIN", where "folder" is the name of the target BULLETIN
Xfolder.  For example, the following commands would send a message from VMS
XMail to the BULLETIN folder GENERAL (on the local system):
X
X`09$ MAIL
X`09MAIL> SEND
X`09To:     MX%"GENERAL@BULLETIN"
X`09Subj:   This is a test....
X`09.....
X
XThe message is sent to the MX router, which in turn sends it to the MX SITE
Xagent, since the @BULLETIN path was defined as a SITE path.
X
XTo facilitate the automatic delivery of messages to BULLETIN folders, you
Xshould set up forwarding addresses for each of the BULLETIN folders:
X
X`09MAIL> SET FORWARD/USER=GENERAL MX%"""GENERAL@BULLETIN"""
X`09MAIL> SET FORWARD/USER=MX-LIST MX%"""MX-LIST@BULLETIN"""
X
XMail addressed to GENERAL or MX-LIST will automatically be forwarded to
XBULLETIN via MX_BULL.
X
XTo subscribe to a Bitnet/Internet mailing list and have the messages deliver
Ved
Xto BULLETIN, use MX's MLFAKE to send a subscription request on behalf of the
XBULLETIN folder.  For example, the user to specify would be:
X
X`09MLFAKE/USER=MX-LIST ....
X
X(Alternatively, you could create a dummy account named MX-LIST (or whatever
Xthe list name is) that exists only long enough to send the request via MAIL.
V)
X
XOnce added to the lists, incoming mail addressed to MX-LIST will get forward
Ved
Xto MX%"MX-LIST@BULLETIN", which will invoke MX_BULL.  For example, an incomi
Vng
Xmessage to my local BULLETIN folder would be addressed to:
X
X`09MX-LIST@WKUVX1.bitnet
X
XSince I have MX-LIST forwarded to MX%"MX-LIST@BULLETIN", the message is rout
Ved
Xto the BULLETIN folder.
X
XTo try to illustrate the process, assume the node is WKUVX1.bitnet.  We've
Xsubscribed a fake local user, INFO-VAX, to the MX mailing list; mail forward
Ving
Xhas been set up for INFO-VAX to send it to MX%"INFO-VAX@BULLETIN".  When mai
Vl
Xarrives addressed to INFO-VAX@WKUVX1.BITNET, the MX Router passes the messag
Ve
Xto the Local agent, which discovers that the mail is forwarded to
XMX%"INFO-VAX@BULLETIN".  The message is then sent back to the Router, which
Xfinds that BULLETIN is defined as a SITE path, so the message is passed to
XMX->SITE, which in turn calls MX_BULL.
X
X
XMX_BULL ACCOUNTING AND DEBUGGING
X--------------------------------
XMX_BULL accounting is enabled with the system logical MX_BULLETIN_ACCNTNG:
X
X`09$ DEFINE/SYS/EXEC MX_BULLETIN_ACCNTNG TRUE
X
XThis will cause MX_BULL to create MX_SITE_DIR:MX_BULLETIN_ACC.DAT.  The
Xlogical MX_BULLETIN_ACC can be defined system-wide to change the name of the
Xfile:
X
X`09$ DEFINE/SYS/EXEC MX_BULLETIN_ACC LOCALDISK:`5BDIR`5DMX_BULL.ACCOUNTING
X
XTo generate debugging logs in MX_SITE_DIR:, define the system logical
XMX_SITE_DEBUG.
X
X
XERRORS WRITING TO BULLETIN
X--------------------------
XBy default, MX_BULL_SITE_DELIVER.COM always returns success to the MX SITE
Xagent.  This was done to avoid bouncing network mail back to a mailing list.
XIn order to be notified in case of problems writing the message to BULLETIN,
Xyou can define a system logical MX_BULLETIN_POSTMASTER to be a local
Xusername to receive failed MX_BULL transactions:
X
X`09$ DEFINE/SYS/EXEC MX_BULLETIN_POSTMASTER GOATHUNTER
X
XIf BULLETIN returns an error, MX_BULL will forward the message (via the
Xcallable VMS Mail interface) to GOATHUNTER.
X
X
XBULLETIN AND "From:" ADDRESSES
X------------------------------
XIf you use the return address supplied by the MX SITE agent, the return addr
Vess
Xfor BULLETIN messages will look something like the following:
X
X`09From: MX%"@WKUVX1.BITNET:I-AMIGA@UBVM.BITNET"
X
XBy default, MX_BULL_SITE_DELIVER.COM is set up to ignore the sender's addres
Vs.
XIf you want to use the MX SITE-supplied address, simply modify the following
Xline in MX_BULL_SITE_DELIVER.COM:
X
X`09$ USE_SITE_FROM = 0`09!Change to 1 to use MX sender's address
X
XIf the sender's address is ignored (again, the default), MX_BULL will search
Xthe RFC822 headers in the message for the "From:" line.  It then pulls out
Xthe sender's address in a format suitable for using the RESPOND command in
XBULLETIN.  This lets users easily RESPOND to the sender of a message, or
XPOST a message to the list itself.
X
XNote: MX_BULL just uses the address it's given.  Some addresses are gatewaye
Vd
Xto death, leaving a bad address on the "From:" line.  This frequently happen
Vs
Xwith messages coming via UUCP through Internet to Bitnet, etc.
X
X
XAUTHOR INFORMATION
X------------------
XMX_BULL was written by:
X
X`09Hunter Goatley, VMS Systems Programmer, WKU
X
X`09E-mail: goathunter@wkuvx1.bitnet
X`09Voice:`09502-745-5251
X
X`09U.S. Mail:`09Academic Computing, STH 226
X`09`09`09Western Kentucky University
X`09`09`09Bowling Green, KY 42101
$ CALL UNPACK MX_BULL.TXT;1 1090705253
$ create 'f'
X#module MX_BULL "01-001"
X/*
X *
X *  Program:`09MX_BULL
X *
X *  Author:`09Hunter Goatley
X *`09`09Academic Computing, STH 226
X *`09`09Western Kentucky University
X *`09`09Bowling Green, KY 42101
X *`09`09goathunter@wkuvx1.bitnet
X *`09`09502-745-5251
X *
X *  Date:`09March 8, 1991
X *
X *  Functional description:
X *
X *`09This program serves as an MX SITE transport to transfer incoming
X *`09mail files to UALR's BULLETIN.
X *
X *`09The MX_SITE delivery agent takes messages routed to a SITE path and
X *`09feeds them into a subprocess that executes a command procedure named
X *`09MX_EXE:SITE_DELIVER.COM.  There are three parameters passed to the
X *`09the command procedure:
X *
X *`09`09P1`09- The name of a temporary file containing the message
X *`09`09`09  text, including all of the RFC822 headers
X *`09`09`09  (corresponding to the DATA part of an SMTP
X *`09`09`09  transaction).
X *`09`09P2`09- The name of a temporary file containing a list of
X *`09`09`09  a messages recipients, which corresponds to the
X *`09`09`09  RCPT_TO addresses of an SMTP transaction.
X *`09`09P3`09- The RFC822 address of the sender of the message,
X *`09`09`09  which corresponds to the MAIL FROM address of an
X *`09`09`09  SMTP transaction.
X *
X *`09This program expects the same parameters, except that the third
X *`09parameter is optional.  If the third parameter is omitted, BULLETIN
X *`09will scan the RFC822 headers in the message for a "From:" line.
X *`09If the third parameter is specified, it is expected to be a file
X *`09specification.  It is assumed that SITE_DELIVER.COM has written the
X *`09address to this file.
X *
X *`09The logical MX_BULLETIN_POSTMASTER can be defined as a local
X *`09username to receive error notices.  If BULLETIN returns an error
X *`09while trying to add a message, and the MX_BULLETIN_POSTMASTER
X *`09is defined as a valid local username, the message will be mailed
X *`09to that user for further handling.
X *
X *`09MX_BULLETIN_POSTMASTER must be defined system-wide in executive mode:
X *
X *`09`09$ DEFINE/SYS/EXEC MX_BULLETIN_POSTMASTER GOATHUNTER
X *
X *  Modification history:
X *
X *`0901-001`09`09Hunter Goatley`09`0914-MAR-1991 14:41
X *`09`09Added scan_for_from_line, which scans the message's RFC822
X *`09`09headers for the "From:" line.  General cleanup on a few
X *`09`09routines.  MX_BULL now provides an RESPOND-able address in
X *`09`09BULLETIN.
X *
X *`0901-000`09`09Hunter Goatley`09`09 8-MAR-1991 07:20
X *`09`09Genesis.
X *
X */
X
X/*  Include all needed structures and constants  */
X
X#include descrip
X#include lib$routines
X#include libdef
X#include lnmdef
X#include maildef
X#include rms
X#include ssdef
X#include str$routines
X#include string
X
X/* Declare the external BULLETIN routines that we call */
X
Xunsigned long int INIT_MESSAGE_ADD();
Xunsigned long int WRITE_MESSAGE_LINE();
Xunsigned long int FINISH_MESSAGE_ADD();
X
X/* Define some macros to make things a little easier */
X
X#define rms_get(rab) ((rms_status = SYS$GET(rab)))
X#define err_exit(stat) `7Btraceerr(stat); return(stat);`7D
X#define vms_errchk2() if(!(vms_status&1)) err_exit(vms_status);
X#define vms_errchk(func) `7Bvms_status=func; vms_errchk2();`7D
X
X#define tracemsg(msg) if (trace) printf("MX_BULL: %s\n",msg);
X#define traceerr(msg) if (trace) printf("MX_BULL: Error status %%X%08x\n",ms
Vg);
X
X/* Define some global variables to make things easy */
X
Xstruct FAB msgfab;`09`09`09`09/* FAB for message text */
Xstruct RAB msgrab;`09`09`09`09/* RAB for message text */
Xstruct FAB rcptfab;`09`09`09`09/* FAB for recipients file */
Xstruct RAB rcptrab;`09`09`09`09/* RAB for recipients file */
Xstruct FAB fromfab;`09`09`09`09/* FAB for FROM file */
Xstruct RAB fromrab;`09`09`09`09/* RAB for FROM file */
Xchar msgbuf`5B512`5D;`09`09`09`09/* Input buffer for msgrab */
Xchar rcptbuf`5B512`5D;`09`09`09`09/* Input buffer for rcptrab */
Xchar frombuf`5B512`5D;`09`09`09`09/* Input buffer for frombuf */
Xshort trace;
Xunsigned long int rms_status;`09`09`09/* Status of RMS calls */
Xunsigned long int vms_status;`09`09`09/* Status of other calls */
X
Xstatic $DESCRIPTOR(lnm_table,"LNM$SYSTEM_TABLE");
X
X#define itmlstend `7B0,0,0,0`7D`09`09`09/* An empty item list */
Xtypedef struct itmlst`09`09`09`09/* An item list structure */
X`7B
X  short buffer_length;
X  short item_code;
X  long buffer_address;
X  long return_length_address;
X`7D ITMLST;
X
XITMLST
X  nulllist`5B`5D = `7Bitmlstend`7D;
X
XITMLST
X  address_itmlst`5B`5D = `7B`09`09`09`09/* MAIL$SEND_ADD_ADDRESS */
X`09`7B0, MAIL$_SEND_USERNAME, 0, 0`7D,
X`09itmlstend`7D,
X  bodypart_itmlst`5B`5D = `7B`09`09`09`09/* MAIL$SEND_ADD_BODYPART */
X`09`7B0, MAIL$_SEND_RECORD, 0, 0`7D,
X`09itmlstend`7D,
X  attribute_itmlst`5B`5D = `7B`09`09`09/* MAIL$SEND_ADD_ATTRIBUTE */
X`09`7B0, MAIL$_SEND_TO_LINE, 0, 0`7D,
X`09`7B0, MAIL$_SEND_FROM_LINE, 0, 0`7D,
X`09`7B0, MAIL$_SEND_SUBJECT, 0, 0`7D,
X`09itmlstend`7D
X  ;
X
XITMLST
X  trnlnm_itmlst`5B`5D = `7B`09`09`09`09/* $TRNLNM item list */
X`09`7B0, LNM$_STRING, 0, 0`7D,
X`09itmlstend`7D
X  ;
X
X`0C
X/*
X *
X *  Function:`09open_file_rms
X *
X *  Functional description:
X *
X *`09This routine opens a sequential text file in VMS "normal text" file
X *`09format.  It uses RMS to open the file.
X *
X *  Inputs:
X *
X *`09infab`09- Address of the input FAB
X *`09inrab`09- Address of the input RAB
X *`09buff`09- Address of the input buffer
X *`09filename - Address of the filename to open (ASCIZ)
X *
X *  Outputs:
X *
X *`09fab and rab are modified if file is opened.
X *
X *  Returns:
X *
X *`09RMS status
X *
X */
Xunsigned long int
Xopen_file_rms (struct FAB *infab, struct RAB *inrab, char *buff, char *filen
Vame)
X`7B
X    unsigned long int rms_status;
X
X    *infab = cc$rms_fab;`09`09`09/* Initialize the FAB */
X    *inrab = cc$rms_rab;`09`09`09/* Initialize the RAB */
X    infab->fab$b_fns = strlen(filename);`09/* Set filename length */
X    infab->fab$l_fna = filename;`09`09/* Set filename address */
X    infab->fab$b_fac = FAB$M_GET;`09`09/* GET access only */
X    infab->fab$b_shr = FAB$M_SHRGET+FAB$M_SHRPUT+FAB$M_SHRUPD;
X    inrab->rab$l_fab = infab;`09`09`09/* Let RAB point to FAB */
X    inrab->rab$b_rac = RAB$C_SEQ;`09`09/* Sequential file access */
X    inrab->rab$w_usz = 512;`09`09`09/* Record size is 512 bytes */
X    inrab->rab$l_ubf = buff;`09`09`09/* Read to this buffer */
X
X    rms_status = SYS$OPEN (infab);`09`09/* Open the file */
X    if (!(rms_status & 1))`09`09`09/* If an error occurs, return */
X`09return (rms_status);`09`09`09/* ... a status */
X    rms_status = SYS$CONNECT (inrab);`09`09/* Connect the RAB */
X    return (rms_status);`09`09`09/* Return the RMS status */
X`7D
X`0C
X/*
X *
X *  Function:`09init_sdesc
X *
X *  Functional description:
X *
X *`09Initialize a static string descriptor.
X *
X *  Inputs:
X *
X *`09sdesc`09- Address of the descriptor to initialize
X *`09`09  (of type struct dsc$descriptor_s)
X *`09string`09- Address of null-terminated string the descriptor describes
X *
X *  Outputs:
X *
X *`09sdesc`09- Descriptor passed as sdesc is initialized
X *
X */
Xvoid
Xinit_sdesc (struct dsc$descriptor_s *sdesc, char *string)
X`7B
X    sdesc->dsc$w_length = strlen(string);`09/* Set the length`09*/
X    sdesc->dsc$b_dtype = DSC$K_DTYPE_T;`09`09/* Type is text`09`09*/
X    sdesc->dsc$b_class = DSC$K_CLASS_S;`09`09/* Class is static`09*/
X    sdesc->dsc$a_pointer = string;`09`09/* Point to the string`09*/
X`7D
X`0C
X/*
X *
X *  Function:`09add_to_bulletin_folder
X *
X *  Functional description:
X *
X *`09Adds a message to a BULLETIN folder by calling the external
X *`09BULLETIN routines INIT_MESSAGE_ADD, WRITE_MESSAGE_LINE, and
X *`09FINISH_MESSAGE_ADD.
X *
X *`09The following constants are (may be) passed to INIT_MESSAGE_ADD:
X *
X *`09`09Subject = "" `09Causes BULLETIN to scan RFC822 headers for
X *`09`09`09`09a "Subject:" or "Subj:" line
X *`09`09From = "MX%"`09Causes BULLETIN to scan RFC822 headers for
X *`09`09`09`09a "Reply-to:" or "From:" line
X *
X *  Inputs:
X *
X *`09filerab`09- Address of the message file's RAB
X *`09folder`09- Address of a string descriptor for the name of the folder
X *`09from`09- Address of a string descriptor for the "From:" address
X *
X *  Outputs:
X *
X *`09None.
X *
X *  Returns:
X *
X *`09unsigned long int - RMS status of call to INIT_MESSAGE_ADD
X *
X */
Xunsigned long int
Xadd_to_bulletin_folder(struct RAB *filerab, void *folder, void *from)
X`7B
X    unsigned long int bull_status;`09/* Status from INIT_MESSAGE_ADD */
X    struct dsc$descriptor_s msg_line;`09/* Descriptor for a line of the msg
V */
X    static $DESCRIPTOR(subject,"");`09/* Subject is "" */
X
X    /* Call BULLETIN routine to initialize adding the message */
X
X    INIT_MESSAGE_ADD (folder, from, &subject, &bull_status);
X
X    if (!(bull_status & 1))`7B`09`09`09`09`09/* Error? */
X`09return(bull_status);
X    `7D
X
X    /*`09Loop reading message lines until end-of-file.  For each line read,
X`09create a string descriptor for it and call the BULLETIN routine to
X`09add the line. */
X
X    while (rms_get(filerab) != RMS$_EOF)`7B`09`09/* Loop until EOF */
X`09filerab->rab$l_rbf`5Bfilerab->rab$w_rsz`5D = 0;`09/* End byte = NULL */
X`09init_sdesc(&msg_line, filerab->rab$l_rbf);`09/* Now build desc. */
X`09WRITE_MESSAGE_LINE (&msg_line);`09`09`09/* Add to BULLETIN */
X    `7D
X
X    FINISH_MESSAGE_ADD();`09`09/* Call BULLETIN routine to finish */
X
X    tracemsg("Message added to folder");
X    return(SS$_NORMAL);`09`09`09/* Return success to caller */
X`7D
X
X`0C
X/*
X *
X *  Function:`09scan_for_from_line
X *
X *  Functional description:
X *
X *`09The routine scans the message's RFC822 headers for the "From:" line.
X *`09It parses out the address by extracting the <address>.
X *
X *`09This routine was necessary because letting BULLETIN find the "From:"
X *`09line was resulting in a non-RESPONDable address for MX.  For example,
X *`09BULLETIN was creating:
X *
X *`09`09From: MX%"Hunter Goatley, WKU <goathunter@WKUVX1.BITNET>"
X *
X *`09but MX needs
X *
X *`09`09From: MX%"<goathunter@WKUVX1.BITNET>"
X *
X *  Inputs:
X *
X *`09filerab`09- Address of the message file's RAB
X *
X *  Outputs:
X *
X *`09final_from - Address of a character buffer to receive the final address
X *
X *  Returns:
X *
X *`09unsigned long int - binary success/failure status
X *
X *  Side effects:
X *
X *`09The message file is rewound so that subsequent GETs start at the
X *`09beginning of the message.
X *
X */
Xunsigned long int
Xscan_for_from_line(struct RAB *filerab, char *final_from)
X`7B
X    unsigned long int scan_status;`09/* Status from INIT_MESSAGE_ADD */
X    struct dsc$descriptor_s msg_line;`09/* Descriptor for a line of the msg
V */
X    char whole_from_line`5B512`5D;`09`09/* The assembled "From:" line */
X    char *filebuffer;`09`09`09/* Pointer to the input buffer */
X    int i, j, x;`09`09`09/* Work variables */
X
X    scan_status = SS$_NORMAL;`09`09`09/* Assume success */
X    whole_from_line`5B0`5D = '\0';`09`09`09/* Initialize work buffer */
X
X    /*`09Loop reading message lines until end-of-file or first null line,
X`09which should signal the end of the RFC822 header.  For each line read,
X`09check to see if we've located the "From:" line.
X    */
X
X    filebuffer = filerab->rab$l_ubf;`09`09`09/* Init buffer ptr */
X    while ((rms_get(filerab) != RMS$_EOF) &&`09`09/* Loop until EOF */
X`09   ((x = filerab->rab$w_rsz) != 0))`7B`09`09/* or null record */
X`09filebuffer`5Bx`5D = '\0';`09`09`09`09/* Set NULL byte */
X`09if (strncmp(filebuffer,"From:",5)==0)`7B`09`09/* Is it the "From:"? */
X
X`09   /* Found "From:" line */
X`09   tracemsg("Found \042From:\042 line in RFC822 header");
X`09   strcpy(whole_from_line,filebuffer);`09`09/* Copy to work buff */
X
X`09   /* The "From:" line may actually be split over several lines.
X`09      In such cases, the remaining lines are indented by 6 spaces.
X`09      To handle this, loop reading records until one is read that
X`09      doesn't begin with a blank.  As each record is read, it is
X`09      trimmed and tacked on to whole_from_line, so we end up with
X`09      the entire "From:" line in one buffer.  */
X
X`09   while((rms_get(filerab) != RMS$_EOF) &&`09/* Read rest of From: */
X`09`09 (filebuffer`5B0`5D == ' '))`7B`09`09/* ... line */
X`09      for (i = 0; filebuffer`5Bi`5D == ' '; ++i);`09/* Step over blanks *
V/
X`09      strcat(whole_from_line,&filebuffer`5Bi`5D);`09/* Tack it on end */
X`09   `7D
X
X`09   /* Now have the whole "From:" line in whole_from_line.  Since
X`09      the real address is enclosed in "<>", look for it by
X`09      searching for the last "<" and reading up to the ">".  */
X
X`09   i = strrchr(whole_from_line,'<');`09`09/* Find last "<" */
X`09   if (i != 0)`7B`09`09`09`09`09/* Found it.... */
X`09`09j = strchr(i,'>');`09`09`09/* Find last ">" */
X`09        j = j-i+1;`09`09`09`09/* Calc addr length */
X`09   `7D
X`09   else`7B
X`09`09j = strlen(whole_from_line)-6;`09`09/* Don't count From: */
X`09`09i = &whole_from_line + 6;`09`09/* in string length */
X`09   `7D
X`09   if (j < 0)`7B`09`09`09`09`09/* If neg., error */
X`09`09tracemsg("Error - unable to locate from address");
X`09`09strcpy(final_from,"");`09`09`09/* Return null string */
X`09`09scan_status = 0;`09`09`09/* Set error status */
X`09   `7D
X`09   else `7B
X`09`09tracemsg("Found sender's address in RFC822 header");
X`09`09strncpy(final_from, i, j);`09`09/* Copy to caller */
X`09   `7D`09
X`09`7D
X    `7D
X
X    SYS$REWIND(filerab);`09`09/* Rewind the file to the beginning */
X    return(scan_status);`09`09/* Return success to caller */
X`7D
X
X`0C
X/*
X *
X *  Function:`09forward_to_postmaster
X *
X *  Functional description:
X *
X *`09If an error occurs trying to write a message to a BULLETIN folder,
X *`09this routine is called to forward the message to the local
X *`09postmaster.
X *
X *  Inputs:
X *
X *`09filerab`09- Address of the message file's RAB
X *`09folder`09- Address of a string descriptor for the name of the folder
X *`09from`09- Address of a string descriptor for the "From:" address
X *`09status`09- Address of longword containing the BULLETIN error code
X *
X *  Outputs:
X *
X *`09None.
X *
X *  Returns:
X *
X *`09unsigned long int - binary status of call to INIT_MESSAGE_ADD
X *
X *  Side effects:
X *
X *`09The message file is rewound so that subsequent calls to this routine
X *`09can be made (in case the message is to be written to several folders).
X *
X */
Xunsigned long int
Xforward_to_postmaster(struct RAB *filerab, void *folder, void *from, int sta
Vtus)
X`7B
X    struct dsc$descriptor_s msg_line;`09/* Descriptor for a line of the msg
V */
X    struct dsc$descriptor_s subject;
X    char subject_buf`5B256`5D;
X    char postmaster`5B256`5D;   int postmaster_len;
X    char status_msg_buf`5B256`5D;   int status_msg_len;
X    struct dsc$descriptor_s status_msg;
X    static $DESCRIPTOR(faostr,"Failed BULLETIN message for folder !AS");
X    static $DESCRIPTOR(MXBULL,"MX->SITE (BULLETIN delivery)");
X    static $DESCRIPTOR(postmaster_lnm,"MX_BULLETIN_POSTMASTER");
X    int send_context = 0;  int x;  int y;
X
X    static char *error_msgs`5B`5D = `7B
X`09`7B"Error delivering message to BULLETIN folder.  BULLETIN error status:"
V`7D,
X`09`7B""`7D,
X`09`7B""`7D,
X`09`7B"Original message text follows:"`7D,
X`09`7B"--------------------------------------------------"`7D
X    `7D;
X
X    trnlnm_itmlst`5B0`5D.buffer_length = 255;
X    trnlnm_itmlst`5B0`5D.buffer_address = &postmaster;
X    trnlnm_itmlst`5B0`5D.return_length_address = &postmaster_len;
X
X    SYS$TRNLNM( 0, &lnm_table, &postmaster_lnm, 0, trnlnm_itmlst);
X    if (postmaster_len == 0)`09`09/* If logical is not defined, */
X`09return(SS$_NORMAL);`09`09/* then pretend it worked     */
X
X    tracemsg("Forwarding message to local postmaster....");
X    subject.dsc$w_length = 255;
X    subject.dsc$a_pointer = &subject_buf;
X    SYS$FAO(&faostr, &subject, &subject, folder);`09/* Format the subject */
X
X    address_itmlst`5B0`5D.buffer_length = postmaster_len;`09`09   /* To: */
X    address_itmlst`5B0`5D.buffer_address = &postmaster;`09`09   /* To: */
X    attribute_itmlst`5B0`5D.buffer_length = postmaster_len;`09`09   /* To: *
V/
X    attribute_itmlst`5B0`5D.buffer_address = &postmaster;`09`09   /* To: */
X    attribute_itmlst`5B1`5D.buffer_length = MXBULL.dsc$w_length;`09   /* Fro
Vm: */
X    attribute_itmlst`5B1`5D.buffer_address = MXBULL.dsc$a_pointer;`09   /* F
Vrom: */
X    attribute_itmlst`5B2`5D.buffer_length = subject.dsc$w_length;`09   /* Su
Vbject:*/
X    attribute_itmlst`5B2`5D.buffer_address = subject.dsc$a_pointer;`09   /*
V Subject:*/
X
X    vms_errchk(mail$send_begin(&send_context, &nulllist, &nulllist));
X    vms_errchk(mail$send_add_address(&send_context, &address_itmlst,
X`09`09`09&nulllist));
X    vms_errchk(mail$send_add_attribute(&send_context, &attribute_itmlst,
X`09`09`09&nulllist));
X
X    for (x = 0; x < 5; x++)`7B
X`09bodypart_itmlst`5B0`5D.buffer_length = strlen(error_msgs`5Bx`5D);
X`09bodypart_itmlst`5B0`5D.buffer_address = error_msgs`5Bx`5D;
X`09vms_errchk(mail$send_add_bodypart(&send_context,
X`09`09&bodypart_itmlst, &nulllist));
X`09if (x == 1)`7B
X`09  status_msg.dsc$w_length = 256;
X`09  status_msg.dsc$b_dtype = DSC$K_DTYPE_T;
X`09  status_msg.dsc$b_class = DSC$K_CLASS_S;
X`09  status_msg.dsc$a_pointer = &status_msg_buf;
X`09  y = SYS$GETMSG (status, &status_msg, &status_msg, 15, 0);
X`09  if (!(y & 1))
X`09     sprintf(status_msg_buf,"Error code is %%X%08x",status);
X`09  else
X`09     status_msg_buf`5Bstatus_msg.dsc$w_length`5D = '\0';
X`09  bodypart_itmlst`5B0`5D.buffer_length = strlen(status_msg_buf);
X`09  bodypart_itmlst`5B0`5D.buffer_address = &status_msg_buf;
X`09  vms_errchk(mail$send_add_bodypart(&send_context,&bodypart_itmlst,
X`09`09&nulllist));
X`09`7D
X    `7D
X
X    while (rms_get(filerab) != RMS$_EOF)`7B`09`09/* Loop until EOF */
X`09bodypart_itmlst`5B0`5D.buffer_length = filerab->rab$w_rsz;
X`09bodypart_itmlst`5B0`5D.buffer_address = filerab->rab$l_rbf;
X`09vms_errchk(mail$send_add_bodypart(&send_context,
X`09`09&bodypart_itmlst, &nulllist));
X    `7D
X
X    vms_errchk(mail$send_message(&send_context, &nulllist, &nulllist));
X    vms_errchk(mail$send_end(&send_context, &nulllist, &nulllist));
X
X    tracemsg("Message forwarded to postmaster....");
X`7D
X
X`0C
X/*
X *
X *  Function:`09log_accounting
X *
X *  Functional description:
X *
X *`09This routine will write an accounting record for the message.
X *
X *  Inputs:
X *
X *`09folder`09- Address of a string descriptor for the name of the folder
X *`09from`09- Address of a string descriptor for the "From:" address
X *`09status`09- Address of longword containing the BULLETIN error code
X *
X *  Outputs:
X *
X *`09None.
X *
X *  Returns:
X *
X *`09unsigned long int - RMS status
X *
X */
Xunsigned long int
Xlog_accounting(void *folder, void *from, int bull_status)
X`7B
X    struct FAB accfab;
X    struct RAB accrab;
X    static $DESCRIPTOR(MX_BULL_ACCNTNG,"MX_BULLETIN_ACCNTNG");
X    static $DESCRIPTOR(faostr,
X`09"!%D MX_BULL: FOLDER=\042!AS\042, ORIGIN=\042!AS\042, STATUS=%X!XL");
X    char outbufbuf`5B256`5D;
X    struct dsc$descriptor_s outbuf = `7B256, DSC$K_DTYPE_T, DSC$K_CLASS_S,
X`09`09 &outbufbuf`7D;
X
X    int status;
X    static char bullacc`5B`5D = "MX_BULLETIN_ACC";
X    static char bullaccdef`5B`5D = "MX_SITE_DIR:.DAT";
X
X    status = SYS$TRNLNM( 0, &lnm_table, &MX_BULL_ACCNTNG, 0, 0);
X    if (!(status & 1))
X`09return(SS$_NORMAL);
X
X    tracemsg("Writing accounting information to accounting log....");
X    accfab = cc$rms_fab;
X    accrab = cc$rms_rab;
X    accfab.fab$b_fns = strlen(bullacc);`09`09/* Set filename length */
X    accfab.fab$l_fna = &bullacc;`09`09/* Set filename address */
X    accfab.fab$b_dns = strlen(bullaccdef);`09/* Set filename length */
X    accfab.fab$l_dna = &bullaccdef;`09`09/* Set filename address */
X    accfab.fab$b_fac = FAB$M_PUT;`09`09/* PUT access only */
X    accfab.fab$b_shr = FAB$M_SHRGET+FAB$M_SHRPUT+FAB$M_SHRUPD;
X    accfab.fab$b_rfm = FAB$C_VAR;`09`09/* Variable length records */
X    accfab.fab$b_rat = FAB$M_CR;`09`09/* Normal "text" rat */
X    accrab.rab$l_fab = &accfab;`09`09`09/* Let RAB point to FAB */
X    accrab.rab$b_rac = RAB$C_SEQ;`09`09/* Sequential file access */
X
X    status = SYS$OPEN (&accfab);`09`09/* Try to open the file */
X    if (status & 1)`09`09`09`09/* Success? */
X`09accrab.rab$l_rop = RAB$M_EOF;`09`09/* Set to EOF */
X    else`09`09`09`09`09/* Couldn't open, so create */
X`09status = SYS$CREATE (&accfab);`09`09/* ... a new one */
X    if (status & 1)`7B`09`09`09`09/* If either was OK... */
X`09status = SYS$CONNECT (&accrab);`09`09/* Connect the RAB */
X`09if (status == RMS$_EOF)`09`09`09/* RMS$_EOF status is OK */
X`09   status = RMS$_NORMAL;`09`09/* Change it to NORMAL */
X`09if (!(status & 1))`7B`09`09`09/* If any error occurred */
X`09   tracemsg("Unable to open accounting file");
X`09   traceerr(status);
X`09   SYS$CLOSE (&accfab);`09`09`09/* Close the file */
X`09   return(status);`09`09`09/* And return the error */
X`09`7D
X    `7D
X    else
X`09return(status);
X
X    SYS$FAO(&faostr, &outbuf, &outbuf, 0, folder, from, bull_status);
X    accrab.rab$w_rsz = outbuf.dsc$w_length;
X    accrab.rab$l_rbf = outbuf.dsc$a_pointer;
X    SYS$PUT (&accrab);
X    SYS$CLOSE (&accfab);
X`7D
X`0C
X/*
X *`20
X *  Main routine
X *
X */
Xmain(int argc, char *argv`5B`5D)
X`7B
X  struct dsc$descriptor_s folder;`09/* Descriptor for the folder name */
X  struct dsc$descriptor_s from_user;`09/* Descriptor for "From:" line */
X  static $DESCRIPTOR(MX_SITE_DEBUG,"MX_SITE_DEBUG");
X
X  char *from_line;`09`09`09/* Pointer to dynamic "From:" buffer */
X  char *folder_name;`09`09`09/* Pointer to folder name in rcptbuf */
X  char *atsign;`09`09`09`09/* Pointer to "@" in rcptbuf */
X  int  x;`09`09`09`09/* Work variable */
X  unsigned long int bull_status;`09/* Status from add_to_bulletin_folder */
X
X  --argc;`09`09`09`09/* Don't count the program name */
X  if ((argc != 2) && (argc != 3)) `7B`09/* If too many or too few args, */
X    exit(LIB$_WRONUMARG);`09`09/* ...  exit with error status  */
X  `7D
X
X  vms_status = SYS$TRNLNM( 0, &lnm_table, &MX_SITE_DEBUG, 0, 0);
X  if (vms_status & 1)
X    trace = 1;
X  else
X    trace = 0;
X
X  /*  Open all input files  */
X
X  tracemsg("Opening message file....");
X  vms_errchk(open_file_rms (&msgfab, &msgrab, &msgbuf, argv`5B1`5D));
X  tracemsg("Opening recipients file....");
X  vms_errchk(open_file_rms (&rcptfab, &rcptrab, &rcptbuf, argv`5B2`5D));
X
X  if (argc == 2)`7B
X     tracemsg("Using sender address from RFC822 headers....");
X     scan_for_from_line(&msgrab, &frombuf);
X  `7D
X  else `7B
X     tracemsg("Opening sender address file....");
X     vms_errchk(open_file_rms (&fromfab, &fromrab, &frombuf, argv`5B3`5D));
X
X     tracemsg("Reading sender address from file....");
X     rms_get(&fromrab);`09`09`09/* Read the from line */
X     if (!(rms_status & 1))`09`09/* Exit if an error occurred */
X`09err_exit(rms_status);
X
X     /* Set the end of the record read, then initialize the descriptor for i
Vt */
X     frombuf`5Bfromrab.rab$w_rsz`5D = 0;
X
X     SYS$CLOSE(&fromfab);
X  `7D`09`09`09`09`09`09/* End of "if (argc == 2)"... */
X
X  /* frombuf now has the sender's address in it */
X
X  if (strlen(frombuf) == 0) `7B
X`09tracemsg("Unable to find sender's address, using MX%");
X`09init_sdesc(&from_user, "MX%");
X  `7D
X  else`7B
X
X     /* Now add the MX% prefix and the double quotes */
X     from_line = malloc(4 + strlen(frombuf) + 1 + 1);`09/* Allocate memory *
V/
X
X     /* Make the string repliable through MX by adding MX%"" to it */
X     strcpy(from_line,"MX%\042");
X     strcat(from_line,frombuf);
X     strcat(from_line,"\042");
X     if (trace)
X`09printf("MX_BULL: Sender's address is %s\n", from_line);
X     init_sdesc (&from_user, from_line);`09/* Create a string descriptor */
X  `7D
X  /*
X    Read through all the recipients, writing the message to all BULLETIN
X    folders (identified by checking for @BULLETIN in the address).
X  */
X  rms_get(&rcptrab);`09`09`09`09/* Read a recipient */
X  while ((rms_status & 1) & (rms_status != RMS$_EOF))`7B
X     tracemsg("Looking for BULLETIN folder....");
X     folder_name = &rcptbuf;`09`09`09/* Point to receipt buffer */
X     if (folder_name`5B0`5D == '<')`7B`09`09/* If line begins with "<" */
X`09++folder_name;`09`09`09`09/*  bump over it and check */
X`09atsign = strchr(rcptbuf,'@');`09`09/*  for a "@"`09`09   */
X`09if (atsign != 0)`7B`09`09`09/* If "@" was found,`09   */
X`09  if (strncmp(atsign,"@BULLETIN",9)==0)`7B/* Is it @BULLETIN?`09   */
X`09    x = atsign - folder_name;`09`09/* Length of folder name   */
X`09    folder_name`5Bx`5D = 0;`09`09`09/* Terminate folder name   */
X`09    init_sdesc (&folder, folder_name);`09/* Initialize descriptor   */
X`09    str$upcase(&folder, &folder);`09/* Convert to uppercase    */
X`09    if (trace)
X`09`09printf("MX_BULL: Found BULLETIN folder \042%s\042....\n",
X`09`09`09folder_name);
X`09    tracemsg("Adding message to BULLETIN folder....");
X`09    bull_status = add_to_bulletin_folder (&msgrab, &folder, &from_user);
X`09    if (!(bull_status & 1))`7B
X`09`09 traceerr(bull_status);
X`09`09 vms_errchk(forward_to_postmaster(&msgrab, &folder, &from_user,
X`09`09`09`09bull_status));
X`09    `7D
X`09    log_accounting(&folder, &from_user, bull_status);
X`09    SYS$REWIND(&msgrab);`09/* Rewind the file for next folder */
X
X`09  `7D
X`09`7D
X      `7D
X      rms_get(&rcptrab);`09`09/* Read next recipient */
X  `7D
X
X
X  /* Close the RMS files */
X
X  SYS$CLOSE(&msgfab);  SYS$CLOSE(&rcptfab);
X
X  tracemsg("BULLETIN message processed");
X  exit(SS$_NORMAL);`09`09/* Always return success */
X
X`7D
$ CALL UNPACK MX_BULL.C;1 574209438
$ create 'f'
X$!
X$!  SITE_DELIVER.COM for MX_BULL
X$!
X$!  Author:`09Hunter Goatley, goathunter@wkuvx1.bitnet
X$!  Date:`09March 11, 1991
X$!
X$!  By default, MX_BULL will tell BULLETIN to search the RFC822 headers
X$!  in the message for a "Reply-to:" or "From:" line.  If you want MX_BULL
X$!  to use the P3 as the "From:" line, simply set USE_SITE_FROM to 1.
X$!
X$ USE_SITE_FROM = 0`09`09`09`09!Change to 1 to use P3
X$ mxbull :== $mx_exe:mx_bull.exe
X$!
X$ set noon
X$ if f$trnlnm("SYS$SCRATCH").eqs."" then define SYS$SCRATCH MX_SITE_DIR:
X$ if USE_SITE_FROM`09`09`09`09!Use P3 as "From:"?
X$ then`09create mx_site_dir:sitesender.addr;`09!If so, write it out to a fil
Ve
X$`09open/append tmp mx_site_dir:sitesender.addr;`09!... to make sure DCL
X$`09write tmp p3`09`09`09`09!... doesn't mess it up
X$`09close tmp`09`09`09`09!...
X$`09mxbull 'p1' 'p2' mx_site_dir:sitesender.addr
X$`09delete/nolog mx_site_dir:sitesender.addr;
X$ else`09mxbull 'p1' 'p2'`09`09`09!Just let BULLETIN find "From:"
X$ endif
X$ exit 1`09!Always return success
$ CALL UNPACK MX_BULL_SITE_DELIVER.COM;1 809308643
$ create 'f'
X$ save_verify = 'f$verify(0)'
X$!
X$!  Command file to build MX_BULL (MX SITE transport for BULLETIN)
X$!
X$ say := write sys$output
X$ if f$trnlnm("BULL_SOURCE") .eqs. ""
X$ then`09say "BULL_SOURCE logical not defined; must point to BULL.OLB direct
Vory"
X$`09exit
X$ endif
X$ say "Compiling MX_BULL...."
X$ cc mx_bull
X$ say "Linking MX_BULL...."
X$ link/notrace mx_bull,bull_source:BULL.OLB/LIB,sys$input/option
XSYS$SHARE:VAXCRTL.EXE/SHARE
X$ say "Build of MX_BULL.EXE completed"
X$ exit f$verify(save_verify).or.1
$ CALL UNPACK BUILD_MX_BULL.COM;1 1551069218
$ v=f$verify(v)
$ EXIT
--------------------------------------------------------------------------------
Return-Path: <@mdmvs.ecs.rpi.edu,@vms.ecs.rpi.edu:goathunter@WKUVX1.BITNET>
Received: from vms.ecs.rpi.edu by mdmvs.ecs.rpi.edu (MX V2.2-1) with SMTP; Fri,
          15 Mar 1991 10:08:47 EST
Received: from WKUVX1  .BITNET (MXMAILER) by RPIECSVX (MX V2.2-1) with BSMTP;
          Fri, 15 Mar 1991 10:06:33 EST
Received: by WKUVX1.BITNET (MX V2.2) id 12697; Fri, 15 Mar 1991 08:50:18 EST
