Unverified Commit 1a9e6c25 authored by Kevin Lyda's avatar Kevin Lyda
Browse files

Start with the version in lt89b1.

parent e1ebc1b8
Loading
Loading
Loading
Loading

src/aaareadme.1st

0 → 100644
+158 −0
Original line number Diff line number Diff line
Note:  Source code is in BULLETIN.ZOO.  Use ZOO to extract files if needed.

The following are instructions for creating and installing the BULLETIN
utility. None of the command procedures included here are sophisticated, so it
is likely that several modifications will have to be made by the installer.
The installer should enable all privileges before installation.

One of the main uses of BULLETIN, besides storage of messages that are manually
entered by users, is storage of messages from network mailing lists.  This is
done by using the BBOARD feature, which is enabled using the SET BBOARD command
inside BULLETIN.  The alternative method is for mail messages to be written
directly by a mailing program by calling internal BULLETIN routines.  Such a
a program has been written for the popular mail utility PMDF.  If you wish to
do so for another utility, read the text file WRITEMSG.TXT.  I would be glad to
include any such programs with my distribution if you think such a program
would be of use to other users.

1) CREATE.COM
   This will compile and link the BULLETIN sources. Also, there are several
   INCLUDE files for the fortran sources (.INC files). BULLETIN will create it's
   data files in the directory pointed to by the logical name BULL_DIR.  If you
   elect not to use this definition, BULLFILES.INC should be modified.
   Note that after this procedure compiles the sources, it puts the objects
   into an object library, and then deletes all the OBJ files in the directory.

   NOTE 1: If you elect to have folders with the BBOARD feature that receives
   messages from outside networks, you may have to modify the subroutine
   which executes the RESPOND command.  That command sends messages to either
   the originator of the message or the mailing list associated with the
   folder.  These routines assume that one can simply use the VMS MAIL
   utility to do so.

   NOTE 2: The maximum number of folders for this distribution is 96 folders.
   If you wish to increase this, modify BULLUSER.INC and recompile the sources.
   When the new executable is run, it will create a new BULLUSER.DAT data file
   and rename the old one to BULLUSER.OLD.  You cannot reduce the number of
   folders.

   BULLETIN will work for both V4 & V5.  However, you will have to reassemble
   ALLMACS.MAR if you are upgrading from V5, i.e.
		$ MAC ALLMACS
		$ LIB BULL ALLMACS
		$ DELETE ALLMACS.OBJ;
		$ @BULLETIN.LNK
		$ COPY BULLETIN.EXE BULL_DIR:
		$ RUN SYS$SYSTEM:INSTALL
		BULL_DIR:BULLETIN/REPLACE

2) INSTALL.COM
   The following procedure copies the executable image to SYS$SYSTEM and
   installs it with certain privileges.  It also installs the necessary
   help files in SYS$HELP.  (BULLETIN help file is installed into the
   system help library HELPLIB.HLB.  If you don't wish this done, delete
   or modify the appropriate line in the procedure.  Also, the help
   library for the BULLETIN program, BULL.HLB, can be moved to a different
   directory other than SYS$HELP.  If this is done, the system logical name
   BULL_HELP should be defined to be the directory where the library is
   to be found.)

3) LOGIN.COM
   This contains the commands that should be executed at login time
   by SYS$MANAGER:SYLOGIN.COM.  It defines the BULLETIN commands.
   It also executes the command BULLETIN/LOGIN in order to notify
   the user of new messages.  NOTE: If you wish the utility to be a
   different name than BULLETIN, you should modify this procedure.
   The prompt which the utility uses is named after image executable.
   If you want messages displayed upon logging in starting from
   oldest to newest (rather than newest to oldest), add /REVERSE to
   the BULLETIN/LOGIN command.  Note that users with the DISMAIL
   flag setting in the authorization file will not be notified of
   new messages.  See help on the SET LOGIN command within the BULLETIN
   utility for more information on this.  Also, please note that when
   a brand new user to the system logins, to avoid overwhelming the new
   user with lots of messages, only PERMANENT SYSTEM messages are displayed.

   If you want SYSTEM messages, i.e. messages which are displayed in full
   when logging in, to be continually displayed for a period of time rather
   than just once, you should add the /SYSTEM= qualifier.  This is documented
   in BULLETIN.HLP, although there it is referred to only with respect to
   a user wanting to review system messages.  It can be added with /LOGIN.

4) BULLSTART.COM
   This procedure contains the commands that should be executed after
   a system startup.  It should be executed by SYS$MANAGER:SYSTARTUP.COM.
   It installs the BULLETIN utility with correct privileges.  It also
   includes the command BULLETIN/STARTUP.  This starts up a detached process
   with the name BULLCP.  It periodically check for expire messages, cleanup
   empty space in files, and converts BBOARD mail to messages.  It also allows
   other DECNET nodes to share it's folders.  If you don't want this feature
   and don't plan on having multiple folders or make use of BBOARD, you could
   eliminate this command if you like.  However, it is highly recommended that
   you create this process to avoid extra overhead when users login.  NOTE:
   BULLCP normally is created so it is owned by the DECNET account.  If that
   account does not exist, BULLCP will be owned by the account that issues
   the BULLETIN/START command.  In that case, access via other DECNET nodes
   will not be available.

   If you are installing BULLETIN on a cluster and plan to have the bulletin
   files be shared between all of the cluster nodes, you only need to have
   this process running on one node. On all other nodes, the system logical
   name BULL_BULLCP should be defined (to anything you want) so as to notify
   BULLETIN that BULLCP is running. (On the local node where BULLCP is running,
   this logical name is automatically defined.)

   The use of the MARK command to mark messages require that a file be
   created for each user which saves the marked info.  That file file is
   stored in the directory pointed to by the logical name BULL_MARK.  You can
   either let users who want to use this command define it themselves, or
   you can define it for them, i.e. DEFINE/SYSTEM BULL_MARK SYS$LOGIN.

5) INSTRUCT.COM
   This procedure adds 2 permanent messages which give a very brief
   description about the BULLETIN utility, and how to turn off optional
   prompting of non-system messages (via SET NOREADNEW).

6) BOARD_SPECIAL.COM
   This command procedure describes and illustrates how to use the
   SET BBOARD/SPECIAL feature.  This feature allows the use of BBOARD
   where the input does not come from VMS MAIL.  For example, this could
   be used in the case where mail from a non-DEC network is not stored
   in the VMS MAIL.  Another example is BOARD_DIGEST.COM.  This file
   takes mail messages from "digest" type mailing lists and splits them
   into separate BULLETIN messages for easier reading.

   To use this feature, place the special command procedure into the
   bulletin file directory using the name BOARD_SPECIAL.COM.  If you want
   to have several different special procedure, you should name the command
   procedure after the username specified by the SET BBOARD command.

7) INSTALL_REMOTE.COM
   This procedure, in conjunction with REMOTE.COM and DCLREMOTE.COM allows
   a user to install new versions of BULLETIN on several DECNET nodes from
   a single node, rather than having to login to each node.  This is
   especially useful when a new version modifies the format of one of the
   data file.  Older versions of BULLETIN will not run with newer formats
   and will either issue error statements when run, or may cause major
   problems by attempting to change the files back to the old format.
   (NOTE: Don't attempt to use this if different nodes are running
   different versions of VMS, i.e. V4 and V5, as they require different
   linked executables.)

8) MASTER.COM
   If you are using PMDF, and want to use the BBOARD option, a set of
   routines are included which will allow PMDF to write message directly
   into folders, which is a much more effecient way of doing it than
   the normal BBOARD method of using VMS MAIL.  Read PMDF.TXT for how
   to do this.

9) BULLETIN.COM
   If one wants BULLETIN to be able to send messages to other DECNET
   node's GENERAL folder, but wants to avoid running the process created
   by BULLETIN/STARTUP on this node, another method exists.  This is the
   "older" (and slower) method.  BULLETIN.COM must be put in each node's
   DECNET default user's directory (usually [DECNET]).  Once this is done,
   the /NODE qualifier for the ADD & DELETE commands can be used.
   NOTE:  Privileged functions such as /SYSTEM will work on other nodes
   if you have an account on the other node with appropriate privileges.
   You will be prompted for the password for the account on the remote node.

src/aaareadme.txt

0 → 100644
+24 −0
Original line number Diff line number Diff line
               BULLETIN 

Note:  Source code is in BULLETIN.ZOO.  Use ZOO to extract files if needed.

BULLETIN was written for the Public Domain by Mark London at MIT.

     The BULLETIN utility permits a user to create messages for
reading by other users.  Users may be notified upon logging on
that new messages have been added, and what the topic of the
messages are.  Actual reading of the messages is optional.  (See
the command SET READNEW for info on automatic reading.)  Messages
are automatically deleted when their expiration data has passed.
     The program runs like VAX mail.  The different interest
groups or BULLETIN boards are implemented in the form of
'Folders', just like a filing cabinet.  A Folder contain various
messages on the same general topic.  A message is a piece of text
written by a user or staff person and added to a particular
folder.  All users are not permitted to submit messages to all
folders.

     A message consists of an expiration date, a subject line
and the text of the message.  BULLETIN will prompt the user for
these things when a message is being added.

src/allmacs.mar

0 → 100644
+270 −0
Original line number Diff line number Diff line
;
;  Name: SETACC.MAR
;
;  Type: Integer*4 Function (MACRO)
;
;  Author: M. R. London
;
;  Date: Jan 26, 1983
;
;  Purpose: To set the account name of the current process (which turns out
;	to be the process running this program.)
;
;  Usage:
;	status = SETACC(account)
;
;	status		- $CMKRNL status return. 0 if arguments wrong.
;	account		- Character string containing account name
;
;  NOTES:
;	Must link with SS:SYS.STB
;

	.Title SETACC
	.IDENT /830531/
;
;  Libraries:
;
	.LIBRARY	/SYS$LIBRARY:LIB.MLB/
;
;  Global variables:
;
	$PCBDEF
	$JIBDEF
;
;  local variables:
;

	.PSECT	 DATA,NOEXE

NEWACC:	.BLKB	12				; Contains new account name
;
;  Executable:
;
	.PSECT	CODE,EXE,NOWRT	; Executable code

	.ENTRY	SETACC,^M<R2,R3,R4,R5,R6,R7>
	CLRL	R0				; 0 is error code
	MOVZBL	(AP),R6				; Get number of arguments
	CMPL	R6,#1				; Correct number of arguments?
	BNEQ	5$				; If not, return
	MOVZBL	@4(AP),R6			; Get size of string
	MOVL	4(AP),R7			; Get address of descriptor
	MOVL	4(R7),R7			; Get address of string
	MOVC5	R6,(R7),#32,#8,NEWACC		; Get new account name string
	$CMKRNL_S ROUTIN=10$			; Must run in kernel mode
5$:	RET
10$:	.WORD	^M<>				; Entry mask
	MOVL	@#CTL$GL_PCB,R6			; Address of current process
	MOVL	PCB$L_JIB(R6),R6		; Address of Job Info Block
						; NOTE: MOVC destroys r0-r5
	MOVC3	#8,NEWACC,JIB$T_ACCOUNT(R6) 	; change account JIB
	MOVC3	#8,NEWACC,CTL$T_ACCOUNT 	; change account in P1
	MOVZWL	#SS$_NORMAL,R0			; Normal ending
	RET
;
;  Name: SETUIC.MAR
;
;  Type: Integer*4 Function (MACRO)
;
;  Author: M. R. London
;
;  Date: May 31, 1983
;
;  Purpose: To set the UIC of the current process (which turns out
;	to be the process running this program.)
;
;  Usage:
;	status = SETUIC(group number, user number)
;
;	status		- $CMKRNL status return. 0 if arguments wrong.
;	group number	- longword containing UIC group number
;	user number	- longword containing UIC user number
;
;  NOTES:
;	Must link with SS:SYS.STB
;

	.Title SETUIC	Set uic
	.IDENT /830531/
;
;  Libraries:
;
	.LIBRARY	/SYS$LIBRARY:LIB.MLB/
;
;  Global variables:
;
	$PCBDEF
;
;  Executable:
;
	.PSECT	SETUIC_CODE,EXE,NOWRT	; Executable code

	.ENTRY SETUIC,^M<R2,R3>
	CLRL	R0				; 0 is error code
	MOVZBL	(AP),R2				; Get number of arguments
	CMPL	R2,#2				; Are there 2 arguments
	BNEQ	5$				; If not, return
	MOVL	@4(AP),R3			; Group number into R3
	ROTL	#16,R3,R3			; Move to upper half of R3
	ADDL2	@8(AP),R3			; User number to top half of R3
	$CMKRNL_S ROUTIN=10$			; Must run in kernel mode
5$:	RET
10$:	.WORD	^M<>				; Entry mask
	MOVL	@#CTL$GL_PCB,R2			; Address of current process
	MOVL	R3,PCB$L_UIC(R2)		; Set UIC to specified
	MOVZWL	#SS$_NORMAL,R0			; Normal ending
	RET
;
;  Name: SETUSER.MAR
;
;  Type: Integer*4 Function (MACRO)
;
;  Author: M. R. London
;
;  Date: Jan 26, 1983
;
;  Purpose: To set the Username of the current process (which turns out
;	to be the process running this program.)
;
;  Usage:
;	status = SETUSER(username)
;
;	status		- $CMKRNL status return. 0 if arguments wrong.
;	username	- Character string containing username
;
;  NOTES:
;	Must link with SS:SYS.STB
;

	.Title SETUSER	Set uic
	.IDENT /830531/
;
;  Libraries:
;
	.LIBRARY	/SYS$LIBRARY:LIB.MLB/
;
;  Global variables:
;
	$PCBDEF
	$JIBDEF
;
;  local variables:
;

	.PSECT	 SETUSER_DATA,NOEXE

NEWUSE:	.BLKB	12				; Contains new username
OLDUSE: .BLKB	12				; Contains old username
;
;  Executable:
;
	.PSECT	SETUSER_CODE,EXE,NOWRT	; Executable code

	.ENTRY	SETUSER,^M<R2,R3,R4,R5,R6,R7,R8>        
	CLRL	R0				; 0 is error code 
	MOVZBL	(AP),R8				; Get number of arguments
	CMPL	R8,#1				; Correct number of arguments
	BLSS	5$				; If not, return
	MOVZBL	@4(AP),R6			; Get size of string
	MOVL	4(AP),R7			; Get address of descriptor
	MOVL	4(R7),R7			; Get address of string
	MOVC5	R6,(R7),#32,#12,NEWUSE		; Get new username string
	CMPL	R8,#2				; Old username given?
	BLSS	2$				; No
	MOVZBL	@8(AP),R6			; Get size of string
	MOVL	8(AP),R7			; Get address of descriptor
	MOVL	4(R7),R7			; Get address of string
	MOVC5	R6,(R7),#32,#12,OLDUSE		; Get old username string
	$CMKRNL_S ROUTIN=20$		   	; Must run in kernel mode
	TSTL	R0				; If old username is checks with
   	BEQL	2$				; present process name, change
	MOVL	#2,R0				; to new username, else flag
	RET					; error and return
2$:	$CMKRNL_S ROUTIN=10$			; Must run in kernel mode
5$:	RET
10$:	.WORD	^M<>				; Entry mask
	MOVL	@#CTL$GL_PCB,R7			; Address of current process
	MOVL	PCB$L_JIB(R7),R7		; Address of Job Info Block
						; NOTE: MOVC destroys r0-r5
	MOVC3	#12,NEWUSE,JIB$T_USERNAME(R7) 	; change username JIB
	MOVC3	#12,NEWUSE,CTL$T_USERNAME 	; change username in P1    
	MOVZWL	#SS$_NORMAL,R0			; Normal ending
	RET
20$:	.WORD	^M<>				; Entry mask
	MOVL	@#CTL$GL_PCB,R7			; Address of current process
	MOVL	PCB$L_JIB(R7),R7		; Address of Job Info Block
						; NOTE: MOVC destroys r0-r5
	CMPC	R6,OLDUSE,JIB$T_USERNAME(R7) 	; change username JIB
	RET


	.TITLE	READ_HEADER - Read Image Header
	.IDENT	/1-001/

; This subroutine returns the image identification and link time.
;
; Format:
;
;   status.wlc.v = READ_HEADER( ident.wt.ds [,time.wt.ds] )
;
; Parameters:
;
;   ident	The image identification text.
;
;   time	The image link time (text format).


;   Date	By		Comments
;  4/10/87	D.E. Greenwood	Originally written by John Miano, 24-June-1986 -
;				obtained from April 87 DECUS L&T Sig Newsletter
	.LIBRARY	"SYS$LIBRARY:LIB"

	$DSCDEF
	$IHDDEF
	$IHIDEF
	$SSDEF

; Argument pointer offsets

	$OFFSET 4,POSITIVE,<IDENT,TIME>

	.PSECT READ_HEADER, RD, NOWRT, EXE, LONG
	.ENTRY READ_HEADER, ^M< R2, R3, R4, R5, R6, R7, R8, R11 >

	CMPL	(AP),#1 		; Make sure that there is at least
	BGEQ	ENOUGH_ARGUMENTS	;  one argument to this routine
	MOVL	#SS$_INSFARG, R0
	RET

ENOUGH_ARGUMENTS:

; Get the identification of the image.

	MOVL	@#CTL$GL_IMGHDRBF, R11	; R11 - Address of image buffer
	MOVL	(R11), R6		; R6  - Address of image header

	CVTWL	IHD$W_IMGIDOFF(R6), R7
	MOVAB	(R6)[R7], R7		; R7 - Address of ID Block

	CVTBL	IHI$T_IMGID(R7),R0	; Length of the ID string
	MOVL	IDENT(AP), R8
	MOVC5	R0, <IHI$T_IMGID+1>(R7), #32, -
		DSC$W_LENGTH(R8), @DSC$A_POINTER(R8)

	CMPL	(AP), #2
	BGEQ	RETURN_TIME
	MOVZBL	#1, R0
	RET

RETURN_TIME:

; Get the time the image was linked and convert it to ASCII

	$ASCTIM_S -
		TIMBUF=@TIME(AP), -
		TIMADR=IHI$Q_LINKTIME(R7)

	RET

	.END

src/board_digest.com

0 → 100644
+77 −0
Original line number Diff line number Diff line
$!
$! BOARD_DIGEST.COM
$!
$! Command file invoked by folder associated with a BBOARD which is
$! is specified with /SPECIAL.  It will convert "digest" mail and
$! split it into separate messages.  This type of mail is used in
$! certain Arpanet mailing lists, such as TEXHAX and INFO-MAC.
$!
$ FF[0,8] = 12			! Define a form feed character
$ SET PROTECT=(W:RWED)/DEFAULT
$ SET PROC/PRIV=SYSPRV
$ USER := 'F$GETJPI("","USERNAME")
$ EXTRACT_FILE = "BULL_DIR:" + "''USER'" + ".TXT"
$ DEFINE/USER EXTRACT_FILE BULL_DIR:'USER'
$ MAIL
READ
EXTRACT EXTRACT_FILE
DELETE
$ OPEN/READ INPUT 'EXTRACT_FILE'
$ OPEN/WRITE OUTPUT 'EXTRACT_FILE'
$ READ INPUT FROM_USER
$AGAIN:
$ READ/END=ERROR INPUT BUFFER
$ IF F$EXTRACT(0,3,BUFFER) .NES. "To:" THEN GOTO SKIP
$ USER = F$EXTRACT(4,F$LEN(BUFFER),BUFFER)
$ GOTO AGAIN1
$SKIP:
$ IF F$EXTRACT(0,15,BUFFER) .NES. "---------------" THEN GOTO AGAIN
$AGAIN1:
$ READ/END=ERROR INPUT BUFFER
$ IF F$EXTRACT(0,15,BUFFER) .NES. "---------------" THEN GOTO AGAIN1
$ FROM = " "
$ SUBJ = " "
$NEXT:
$ READ/END=EXIT INPUT BUFFER
$FROM:
$ IF F$EXTRACT(0,5,BUFFER) .NES. "From:" THEN GOTO SUBJECT
$ FROM = BUFFER 
$ GOTO NEXT
$SUBJECT:
$ IF F$EXTRACT(0,8,BUFFER) .NES. "Subject:" THEN GOTO NEXT
$ SUBJ = BUFFER - "Subject:"
$F2:
$ IF F$LENGTH(SUBJ) .EQ. 0 THEN GOTO WRITE
$ IF F$EXTRACT(0,1,SUBJ) .NES. " " THEN GOTO WRITE
$ SUBJ = F$EXTRACT(1,F$LENGTH(SUBJ),SUBJ)
$ GOTO F2
$WRITE:
$ WRITE OUTPUT FROM_USER
				! Write From: + TAB + USERNAME
$ WRITE OUTPUT "To:	" + USER
				! Write To: + TAB + BBOARDUSERNAME
$ WRITE OUTPUT "Subj:	" + SUBJ
				! Write Subject: + TAB + mail subject
$ WRITE OUTPUT ""		! Write one blank line
$ IF FROM .NES. " " THEN WRITE OUTPUT FROM
$READ:
$ READ/END=EXIT/ERR=EXIT INPUT BUFFER
$ IF F$EXTRACT(0,15,BUFFER) .EQS. "---------------" THEN GOTO READ1
$ WRITE OUTPUT BUFFER
$ GOTO READ
$READ1:
$ READ/END=EXIT/ERR=EXIT INPUT BUFFER
$ IF F$LOCATE(":",BUFFER) .EQ. F$LENGTH(BUFFER) THEN GOTO READ1
$ WRITE OUTPUT FF
$ FROM = " "
$ SUBJ = " "
$ GOTO FROM
$EXIT:
$ CLOSE INPUT
$ CLOSE OUTPUT
$ PUR 'EXTRACT_FILE'
$ EXIT
$ERROR:
$ CLOSE INPUT
$ CLOSE OUTPUT
$ DELETE 'EXTRACT_FILE';

src/board_special.com

0 → 100644
+108 −0
Original line number Diff line number Diff line
$!
$! BOARD_SPECIAL.COM
$!
$! Command file invoked by folder associated with a BBOARD which is
$! is specified with /SPECIAL.  This can be used to convert data to
$! a message via a different means than the VMS mail.  This is done by
$! converting the data to look like output created by the MAIL utility,
$! which appears as follows:
$!
$!	First line is 0 length line.
$!	Second line is "From:" followed by TAB followed by incoming username
$!	Third line is "To:" followed by TAB followed by BBOARD username
$!	Fourth line is "Subj:" followed by TAB followed by subject
$!	The message text then follows.
$!	Message is ended by a line containing a FORM FEED.
$!
$! This command file should be put in the BBOARD_DIRECTORY as specified
$! in BULLFILES.INC.  You can also have several different types of special
$! procedures.  To accomplish this, rename the file to the BBOARD username.
$! i.e. if you specify SET BBOARD FOO/SPECIAL, you could name the file
$! FOO.COM and it will execute that rather than BOARD_SPECIAL.COM.
$!
$! The following routine is the one we use to convert mail from a non-DEC
$! mail network.  The output from this mail is written into a file which
$! is slightly different from the type outputted by MAIL.
$!
$! (NOTE: A username in the SET BBOARD command need only be specified if
$! the process which reads the mail requires that the process be owned by
$! a specific user, which is the case for this sample, and for that matter
$! when reading VMS MAIL.  If this is not required, you do not have to
$! specify a username.)
$!
$ USERNAME := 'F$GETJPI("","USERNAME")'		! This trims trailing spaces
$ IF F$SEARCH("MFE_TELL_FILES:"+USERNAME+".MAI") .EQS. "" THEN EXIT
$ SET DEFAULT BULL_DIR:	! BULLETIN looks for text in BBOARD directory
$ SET PROTECT=(W:RWED)/DEFAULT
$ IF F$SEARCH("MFEMSG.MAI") .NES. "" THEN -
  DELETE MFEMSG.MAI;*		! Delete any leftover output files.
$ MSG := $MFE_TELL: MESSAGE
$ DEFINE/USER SYS$COMMAND SYS$INPUT
$ MSG				! Read MFENET mail
copy * MFEMSG
delete *
exit
$ FF[0,8] = 12			! Define a form feed character
$ OPEN/READ/ERROR=EXIT INPUT MFEMSG.MAI
$ OUTNAME = USERNAME+".TXT"	! Output file will be 'USERNAME'.TXT
$ OPEN/WRITE OUTPUT 'OUTNAME'
$ READ/END=END INPUT DATA		! Skip first line in MSG output
$HEADER:
$ FROM = ""
$ SUBJ = ""
$ MFEMAIL = "T"
$NEXTHEADER:
$ IF (FROM.NES."") .AND. (SUBJ.NES."") THEN GOTO SKIPHEADER
$ READ/END=END INPUT DATA		! Read header line in MSG output
$ IF DATA .EQS. "" THEN GOTO SKIPHEADER	! Missing From or Subj ??
$ IF FROM .NES. "" THEN GOTO SKIPFROM
$ IF F$LOCATE("From: ",DATA) .NES. 0 THEN GOTO 10$
$ MFEMAIL = "F"
$ FROM= F$EXTRACT(6,F$LENGTH(DATA),DATA)
$ GOTO NEXTHEADER
$10$:
$ IF F$LOCATE("Reply-to: ",DATA) .NES. 0 THEN GOTO 20$
$ MFEMAIL = "F"
$ FROM= F$EXTRACT(10,F$LENGTH(DATA),DATA)
$ GOTO NEXTHEADER
$20$:
$ IF F$LOCATE("From ",DATA) .NES. 0 THEN GOTO SKIPFROM
$ FROM= F$EXTRACT(5,F$LENGTH(DATA),DATA)
$ GOTO NEXTHEADER
$SKIPFROM:
$ IF SUBJ .NES. "" THEN GOTO SKIPSUBJ
$ IF F$LOCATE("Subject",DATA) .NES. 0 THEN GOTO SKIPSUBJ
$ SUBJ= F$EXTRACT(F$LOCATE(": ",DATA)+2,F$LENGTH(DATA),DATA)
$ GOTO NEXTHEADER
$SKIPSUBJ:
$ GOTO NEXTHEADER
$SKIPHEADER:
$ WRITE OUTPUT "From:	" + FROM
				! Write From: + TAB + USERNAME
$ WRITE OUTPUT "To:	" + USERNAME
				! Write To: + TAB + BBOARDUSERNAME
$ WRITE OUTPUT "Subj:	" + SUBJ
				! Write Subject: + TAB + mail subject
$ WRITE OUTPUT ""		! Write one blank line
$ IF (DATA.EQS."") .OR. MFEMAIL THEN GOTO SKIPBLANKS
$50$:
$ READ/END=END INPUT DATA		! Skip rest of main header
$ IF DATA .NES. "" THEN GOTO 50$
$60$:
$ READ/END=END INPUT DATA		! Skip all of secondary header
$ IF DATA .NES. "" THEN GOTO 60$
$SKIPBLANKS:
$ READ/END=END INPUT DATA		! Skip all blanks
$ IF DATA .EQS. "" THEN GOTO SKIPBLANKS
$NEXT:				! Read and write message text
$ WRITE OUTPUT DATA
$ IF DATA .EQS. FF THEN GOTO HEADER
			! Multiple messages are seperated by form feeds
$ READ/END=END INPUT DATA
$ GOTO NEXT
$END:
$ CLOSE INPUT
$ CLOSE OUTPUT
$ DELETE MFEMSG.MAI;
$EXIT:
$ EXIT
Loading