The following are instructions for creating the BULLETIN executable and 
installation of the utility.  A brief explanation of how the internals
of the BULLETIN utility works can be found in BULLETIN.TXT .  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.

1) CREATE.COM
   This will compile and link the BULLETIN sources. Also, there are several
   INCLUDE files for the fortran sources (.INC files). BULLFILES.INC must first
   be modified before this procedure is run. It contains the names of data files
   which BULLETIN creates. It also has the username for the BBOARD account.
   BBOARD is an option by which mail sent to the specified username will be
   converted into bulletins.  This allows a user on a different system, which is
   connected via a network, to be able to submit a bulletin.  This feature can
   be disabled if it is not desired by specifying the username NONE.  In any
   case, you should edit BULLFILES.INC and specify the appropriate device and
   directories in which you desire that the files be located.  (NOTE: Although
   the BBOARD feature can be used over DECNET, a more sophisticated method
   is available to easily allow one to add bulletins to other DECNET nodes
   with all the features of BULLETIN.  See below).

2) STARTUP.COM
   The data files that BULLETIN creates should be owned by a system UIC,
   and MUST be protected from users being able to have access them.
   STARTUP.COM sets the process UIC to [1,4] (you should change this if
   you want something else), sets the WORLD and GROUP protection to NONE,
   adds the bulletin found in the file INSTRUCT.TXT (it is added with
   /PERMANENT, so it never expires), and then resets the UIC and PROTECTION
   to what they were before running the procedure.
   INSTRUCT.BUL contains a bulletin with instructions to the users as to
   how to use the BULLETIN utility.  You may want to modify it.

3) 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.

4) LOGIN.COM
   This contains the comands 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 bulletins.  If desired, the /READNEW qualifier
   can also be added.  If there are any new non-system bulletins, this
   qualifier creates a prompt asking the user if the non-system
   bulletins are to be displayed or not.  Normally, only system bulletins
   are displayed in full, and only the subjects of the non-system
   bulletins are displayed.  ( Some systems might have a lot of users
   who are not interested in reading the non-system bulletins, in 
   which case /READNEW should probably not be added.  Instead, you could
   let users enable this feature by entering the BULLETIN utility and
   typing the command SET READNEW ).  (NOTE: Since /LOGIN and /READNEW
   are system commands, they are not included in the help file).

5) BULLSTART.COM
   This procedure contains the commands that should be executed after
   a system startup.  It should be executed by SYS$MANAGER:SYSTARTUP.COM
   as a batch job.  It simply installs the BULLETIN utility with correct
   privileges.

6) BULLETIN.COM
   If one wants the feature of using BULLETIN between DECNET nodes,
   this file must be put in each node's DECNET default user's directory
   (usually [DECNET]).  Once this is done, the /NODE qualifer for the
   ADD command can be used.
   NOTE:  Presently, privileged functions such as /SYSTEM will work
   on other nodes only if you have an account on the other node with
   the same username, and with appropriate privileges.  You will be
   prompted for the password for the account on the remote node.  However,
   due to unknown reasons, the software I have to check the password will
   only work for passwords that have been set under V4.x.  If the password
   was created under V3.x, the program will not work, and you password will
   be treated as invalid.
$ SET PROTECT=(W:RWED)/DEFAULT
$ MAIL
READ
EXTRACT/ALL USRD$:[BBOARD]BBOARD.MAI
DELETE/ALL
	MODULE BULLETIN_SUBCOMMANDS

	DEFINE VERB ADD
		PARAMETER P1, LABEL = FILESPEC, VALUE(TYPE=$FILE)
		QUALIFIER BELL
		QUALIFIER BROADCAST
		QUALIFIER EDIT
		QUALIFIER NODES, LABEL=NODES, VALUE(REQUIRED,LIST)
		QUALIFIER PASSWORD, LABEL=PASSWORD, VALUE(REQUIRED)
		QUALIFIER PERMANENT
		QUALIFIER SHUTDOWN
		QUALIFIER SYSTEM
		QUALIFIER USERNAME, LABEL=USERNAME, VALUE(REQUIRED)
	DEFINE VERB BACK
	DEFINE VERB DELETE
		PARAMETER P1, LABEL = BULLETIN_NUMBER, VALUE(TYPE=$FILE)
	DEFINE VERB DIRECTORY
	DEFINE VERB EXIT
	DEFINE VERB FILE
		PARAMETER P1, LABEL = FILESPEC, VALUE(TYPE=$FILE,REQUIRED),
			PROMPT="File"
		QUALIFIER HEADER, DEFAULT
	DEFINE VERB HELP
		PARAMETER P1, LABEL = HELP_TOPIC, VALUE(TYPE=$REST_OF_LINE)
	DEFINE VERB NEXT
	DEFINE VERB READ
		PARAMETER P1, LABEL = BULLETIN_NUMBER, VALUE(TYPE=$NUMBER)
	DEFINE VERB REPLACE
		PARAMETER P1, LABEL = FILESPEC, VALUE(TYPE=$FILE)
		QUALIFIER EXPIRATION
		QUALIFIER HEADER
		QUALIFIER NUMBER, VALUE(TYPE=$NUMBER,REQUIRED)
		QUALIFIER TEXT
	DEFINE VERB SET
		PARAMETER P1, LABEL = SET_PARAM1, VALUE(REQUIRED),
			PROMPT="What"
1 ADD
Adds a bulletin to the bulletin file.  A file can be specified which
contains the bulletin.  Otherwise, BULLETIN will prompt for the text.
BULLETIN will ask for an expiration date and a header to contain the
topic of the bulletin.

Format
  ADD [file-name]

All the qualifiers except for /EDIT and /NODES are restricted to users
with SETPRV privileges.
2 /BELL
This option is restricted to privileged users.  It is used in conjunction 
with the /BROADCAST qualifier.  If specified, the bell is rung on the 
terminals when the bulletin is broadcasted.
2 /BROADCAST
This option is restricted to privileged users.  If specified, bulletin
is both saved in the bulletin file and broadcasted to all users logged
in at the time.
2 /EDIT
Determines whether or not the EDT editor is invoked to edit the bulletin
you are sending.
2 /NODES=(nodes[,...])
Specifies to send the bulletin to other DECNET nodes.  The BULLETIN utility
must be installed properly on the other nodes.  You will prompted for the
username to use at the other node.  If you give a different username than
that of the local node, or if privileged qualifiers are specified, you will
be prompted for the password of your account on the other nodes.  At
present, if the password is invalid, the bulletin will be rejected on the
node, but no error message will be displayed on the local node that this
happened. 
2 /PERMANENT
This option is restricted to privileged users.  If specified, bulletin
will be a permanent bulletin and will never expire.
2 /SHUTDOWN
This option is restricted to privileged users.  If specified, bulletin
will be automatically deleted after a computer shutdown has occurred.
2 /SYSTEM
This option is restricted to privileged users.  If specified, bulletin
is both saved in the bulletin file and displayed in full as a system
notice when a user logs in.  System notices should be as brief as possible
to avoid the possibility that system notices could scroll off the screen.
1 BACK
Displays the bulletin preceding the current bulletin.
1 DELETE
Deletes the specified bulletin.  If no bulletin is specified, the current
bulletin is deleted.  Only the original owner or a privileged user can
delete a bulletin.

Format
  DELETE [bulletin-number]

The bulletin's relative number is found by the DIRECTORY command.
1 DIRECTORY
Lists a summary of the bulletins.  The bulletin number, submitter's name,
date, and subject of each bulletin is displayed.
1 EXIT
Exits the BULLETIN program.
1 FILE
Copies the current bulletin to the named file.  The file-name parameter
is required, and consists of up to 9 alpha-numeric characters in length.

Format:
    FILE file-name
2 /HEADER

/[NO]HEADER

Controls whether a header containing the owner, subject, and date of the 
bulletin is written in the file.  The default is to write the header.
1 Bulletin
The BULLETIN utility permits a user to create a bulletin for reading by 
all users.  Users are notified upon logging in that new bulletins have
been added, and what the topic of the bulletins are.  Actual reading of
the bulletins is optional. (See the command SET READNEW for info on
automatic reading.)  Bulletins are automatically deleted when their
expiration date has passed.

1 HELP
To obtain help on any topic, type:

	HELP  topic
1 NEXT
Skips to the next bulletin and displays it.  This is useful when paging
through the bulletins and you encounter a particularly long bulletin
that you would like to skip over.
1 READ
Displays the specified bulletin.  If you do not specify a bulletin, then
the first time you enter the command, the oldest bulletin will be
displayed.  However, if there are new bulletins, the first new bulletin
will be displayed.  Each time you enter the command, the next page, or if
there are no more pages, the next bulletin will be displayed. 

Format
  READ [bulletin-number]

The bulletin's relative number is found by the DIRECTORY command.

Pressing just <RETURN> performs the same as the READ command.
1 REPLACE
Replaces an existing bulletin in the bulletin file.  This is for changing
part or all of a bulletin without causing users who have already seen the
bulletin to be notified of it a second time.  If the text of the bulletin
is to be changed, a file can be specified which contains the text.
Otherwise, BULLETIN will prompt for the text.  The expiration date and
header can also be changed.  If neither /EXPIRATION, /HEADER, nor /TEXT
are specified, it is assumed the whole bulletin will be replaced.

Format
  REPLACE [file-name]
2 /EXPIRATION
Specifies that the bulletin expiration date is to be replaced.
2 /HEADER
Specifies that the bulletin header is to be replaced.
2 /NUMBER=n
Specifies the bulletin number to be replaced.  If this qualifier is 
omitted, the bulletin that is presently being read will be replaced.
2 /TEXT
Specifies that the bulletin text is to be replaced.
1 SET
Defines or changes characteristics associated with automatic reading
of bulletins.

Format:

    SET option
2 READNEW
Controls whether you will be prompted upon logging in if you wish to read 
new non-system bulletins (if any exist).  The default is that you are not
prompted.  (Previously this was done by including the BULLETIN/READNEW
command in one's login command procedure).

  Format:

    SET [NO]READNEW
	COMMON /BULL_DIR/ DESCRIP,FROM,DATE,TIME,BLOCK,LENGTH,EXDATE
     &	,NEWEST_EXDATE,NEWEST_DATE,NEWEST_TIME,SYSTEM,NBULL,NBLOCK
     &  ,SHUTDOWN,SHUTDOWN_DATE,SHUTDOWN_TIME
	CHARACTER*53 DESCRIP
	CHARACTER*12 FROM
	CHARACTER*11 DATE,EXDATE,NEWEST_EXDATE,NEWEST_DATE,SHUTDOWN_DATE
	CHARACTER*8 TIME,NEWEST_TIME,SHUTDOWN_TIME
	LOGICAL SYSTEM
$ DEFINE SYS$INPUT SYS$NET
$ BULLETIN
1 BULLETIN
Invokes the PFC BULLETIN Utility.  This utility is used for reading, adding
and deleting bulletins.  Any user can submit a bulletin.  Users are
notified at login time that new bulletins have been added and the topics of
those bulletins are displayed.  Reading of those bulletins is optional.
(Use the command SET READNEW while in BULLETIN for setting automatic
reading.)  Privileged users can add system bulletins that are displayed
in full at login time.  These bulletins are also saved, and can be read
by BULLETIN.  Bulletins are automatically deleted after a specified
expiration date, or they can manually be deleted by either the submitter
of the bulletin or a privileged user. 

BULLETIN has an interactive help available while using the utility.

 Format:

      BULLETIN
$ LINK/NOTRACE BULLETIN,HPWD,BULLSUBS,BULLCOM,BULLMAIN,CLIDEF,USEROPEN,SETUSER,SETUIC,-
SYS$SYSTEM:SYS.STB/SEL
This file describes the general operation of the BULLETIN utility.

BULLETIN uses 3 files to store its data: BULLETIN.DAT, BULLDIR.DAT, &
BULLUSER.DAT.  These files are opened with the shared attribute as much as
possible to allow simultaneous operations on the files.  However, when a
bulletin is added or deleted, the file cannot be shared, as this might cause
the file to be corrupted.  Because of this problem, files are closed as soon as
possible so that it may be quickly opened for adding and deleting files. 
During read operations, the information is passed to temporary storage, the
file is closed, and then the information is sent to the terminal. This avoids a
possible problem where the terminal output is stopped by the user, therefore
delaying the closing of the file.  Also, the use of CTRL-Y & CTRL-C is disabled
while the file is opened to avoid lockout problems.

BULLETIN.DAT stores the actual bulletins in a fixed 80 character length file.
Bulletins are store sequentially datewise.  New bulletins are appended to the
end of the file.  When a bulletin is deleted, all the following bulletins are
moved up in the file to remove the gap, and the file is then truncated to
remove the unused space. 

BULLDIR.DAT is a fixed record length file storing directory entries for each
bulletin in BULLETIN.DAT. Each entry contains the header information, length,
and starting record position in BULLETIN.DAT.  The first line of BULLDIR.DAT is
a header containing the date of the next expiration that will occur, the date
of the latest sumbitted bulletin, the number of bulletins, and the total size
of BULLETIN.DAT.  The last two numbers make it easier to add bulletins. The
directory entries then follow, again stored sequentially datewise. 

NOTE: There are several advantages to keeping a seperate directory file versus
storing the header information with the actual bulletin.  Obviously, it avoids
having to scan through a large bulletin file just to extract header
information.  This operation is done when a DIRECTORY listing is requested in
BULLETIN.  More importantly when a login occurs, non-system bulletins just
require that the header information be displayed.  Having a file with pointers
to where the bulletin is stored also avoids requiring the software to read all
the previous bulletins in order to arrive at the desired bulletin.  The main
disadvantage is the extra time spent on locating the second file.  This time
appears to be minimal. In all the software, the convention is to open the
directory file first, and then if needed to open the bulletin file.  When
adding and delete files, this becomes important, as files are opened unshared. 
A deadlock might occur if one user opens the bulletin file first while another
user opens the directory file, and then each try to open the alternate file.

BULLUSER.DAT is a relative indexed file, where the keyword is the username of
the user.  Each entry contains the latest time that the user logged in, plus
the latest time that the BULLETIN utility was used to read bulletins.  A header
entry with a blank username stores the latest bulletin date.  The information
in this file is used for checking to see if the user should be alerted to new
bulletins or not.
C
C  THE FIRST 3 FILES ARE FILES CREATED AND USED BY BULLETIN.
C  SEE BULLETIN.TXT FOR MORE INFORMATION. SPECIFY THE DEVICE/DIRECTORY
C  IN WHICH YOU DESIRE THAT THEY BE KEPT.  THE FOURTH FILE IS SIMPLY
C  THE MAIL FILE FROM WHICH MESSAGES ARE CONVERTED TO NON-SYSTEM
C  BULLETINS (AFTER WHICH THE MAIL IS DELETED.)  IF YOU DO NOT WISH
C  THE BBOARD OPTION, CHANGE THE DEFINITION FOR BBOARD TO BE: /'NONE'/.
C  IF IT IS NOT SELECTED, YOU DO NOT HAVE TO MODIFY THE REST OF THE
C  BBOARD VARIABLES.  IF IT IS SELECTED, YOU MUST SPECIFY THE UIC
C  NUMBER OF THE BBOARD ACCOUNT.  YOU MUST ALSO SPECIFY BBOARD_FILE,
C  WHICH IS A TEMPORARY FILE WHICH IS USED TO CONVERT THE BBOARD MAIL
C  TO A SEQUENTIAL FILE.
C
	COMMON /FILES/ BULLDIR_FILE,BULLETIN_FILE,BULLUSER_FILE,BBOARD_USER
	COMMON /FILES/ BBOARD_UIC,BBOARD_FILE,BBOARD_COMMAND
	CHARACTER*80 BULLDIR_FILE /'IML$EXE:BULLDIR.DAT'/
	CHARACTER*80 BULLETIN_FILE /'IML$EXE:BULLETIN.DAT'/
	CHARACTER*80 BULLUSER_FILE /'IML$EXE:BULLUSER.DAT'/
	CHARACTER*12 BBOARD_USER /'BBOARD'/,BBOARD_UIC/'[330,5]'/
	CHARACTER*80 BBOARD_FILE/'USRD$:[BBOARD]BBOARD.MAI'/
C
C  THE BBOARD.COM IS INCLUDED WITH THE SOURCES AND IS USED IF THE BBOARD
C  FEATURE IS DESIRED.  IT IS NOT CREATED, SO YOU MUST MOVE IT TO THE
C  DESIRED DIRECTORY.  YOU MUST ALSO EDIT IT SO THAT THE FILE SPECIFIED
C  IN THE 'EXTRACT' LINE MATCHES THE FILE SPECIFIED BY BBOARD_FILE.
C
	CHARACTER*80 BBOARD_COMMAND/'IML$EXE:BBOARD.COM'/
	PARAMETER ADD_FLAG = '1'X
	PARAMETER BACK_FLAG = '2'X
	PARAMETER DELETE_FLAG = '4'X
	PARAMETER DIRECTORY_FLAG = '8'X
	PARAMETER EXIT_FLAG = '10'X
	PARAMETER FILE_FLAG = '20'X
	PARAMETER HELP_FLAG = '40'X
	PARAMETER NEXT_FLAG = '80'X
	PARAMETER READ_FLAG = '100'X
	PARAMETER SYSTEM_FLAG = '200'X
	PARAMETER BROADCAST_FLAG = '400'X
	PARAMETER BADSWITCH_FLAG = '800'X
	PARAMETER REPLACE_FLAG = '1000'X
	PARAMETER EXPIRE_FLAG = '2000'X
	PARAMETER HEADER_FLAG = '4000'X
	PARAMETER TEXT_FLAG = '8000'X
	PARAMETER NUMBER_FLAG = '10000'X
	PARAMETER SHUTDOWN_FLAG = '20000'X
	PARAMETER PERMANENT_FLAG = '40000'X

	COMMON /BULLPAR/ FLAGS,BULL_PARAMETER,LEN_P,NUMBER_PARAM
	CHARACTER*64 BULL_PARAMETER
	INTEGER FLAGS
	MODULE BULLETIN_MAINCOMMANDS
	DEFINE VERB BULLETIN
		QUALIFIER READNEW
		QUALIFIER LOGIN
$ RUN SYS$SYSTEM:INSTALL
SYS$SYSTEM:BULLETIN/SHARE/OPEN/HEAD/PRIV=(OPER,SYSPRV,CMKRNL)
/EXIT

	COMMON /BULL_USER/ USERNAME,LOGIN_DATE,LOGIN_TIME,READ_DATE,
     &		READ_TIME,FLAGS
	CHARACTER*12 USERNAME
	CHARACTER*11 LOGIN_DATE,READ_DATE
	CHARACTER*8 LOGIN_TIME,READ_TIME
	DIMENSION FLAGS(2)

	.LIBRARY	/SYS$LIBRARY:LIB.MLB/
	$CLIDEF	GLOBAL
	.END
$ FORTRAN BULLETIN
$ FORTRAN BULLSUBS
$ MAC CLIDEF
$ MAC HPWD
$ MAC SETUIC
$ MAC SETUSER
$ MAC USEROPEN
$ SET COMMAND/OBJ BULLCOM
$ SET COMMAND/OBJ BULLMAIN
$ @BULLETIN.LNK
.TITLE HPWD - hash user password
.IDENT 'V02-002'

; This code was gotten by disassembling the AUTHORIZE program.
; It is quite shameful that DEC has not seen fit to provide
; this as a system service.

;  If you want lots of good comments, see the fiche.

;	e _lib$code:_lib$code+68


; Inputs: PWDDSC -- Addres of password descriptor
;	  ENCRYPT -- Encryption algorithm index (byte)
;	  SALT - random number (word)
;	  USRDSC - Address of username descriptor

; output:  OUTDSC  -- Address of encrypted output descriptor

OUTDSC=4
PWDDSC=OUTDSC+4
ENCRYPT=PWDDSC+4
SALT=ENCRYPT+4
USRDSC=SALT+4

.PSECT _LIB$CODE	RD,NOWRT,PIC,SHR,BYTE,EXE

;  AUTODIN-II polynomial table used by CRC algorithm
AUTODIN:
	.LONG ^X000000000,^X01DB71064,^X03B6E20C8,^X026D930AC,^X076DC4190
	.LONG ^X06B6B51F4,^X04DB26158,^X05005713C,^X0EDB88320,^X0F00F9344
	.LONG ^X0D6D6A3E8,^X0CB61B38C,^X09B64C2B0,^X086D3D2D4,^X0A00AE278
	.LONG ^X0BDBDF21C

; Purdy polynomial coefficients.  Prime, but don't need to be
Purdy_Poly:
c:
	.LONG -83,-1
	.LONG -179,-1
	.LONG -257,-1
	.LONG -323,-1
	.LONG -363,-1

.ENTRY	LGI$HPWD,^M<R2,R3,R4>
	MOVAQ   @outdsc(AP),R4
	MOVAQ   @4(R4),R4
	TSTB    encrypt(AP)
	BGTRU   10$
	MNEGL   #1,R0
	MOVAQ   @pwddsc(AP),R1
	CRC     autodin,R0,(R1),@4(R1)
	CLRL    R1
	MOVQ    R0,(R4)
	BRB     20$

10$:	CLRQ    (R4)
	MOVAQ   @pwddsc(AP),R3
	BSBB    COLLAPSE_R2
	ADDW2   salt(AP),3(R4)
	MOVAQ   @usrdsc(AP),R3
	BSBB    COLLAPSE_R2
	PUSHAQ  (R4)
	CALLS   #1,PURDY

20$:	MOVL    #1,R0
	RET


COLLAPSE_R2:
	MOVZWL  (R3),R0
	BEQL    20$
	MOVAL   @4(R3),R2
	PUSHR	#^M<R1,R2>
	MOVL	R0,R1
5$:	CMPB	(R2)+,#32
	BNEQ	7$
	DECL	R1
7$:	SOBGTR  R0,5$
	MOVL	R1,R0
	POPR	#^M<R1,R2>
10$:	BICL3	#-8,R0,R1
	ADDB2   (R2)+,(R4)[R1]
	SOBGTR  R0,10$
20$:	RSB

a=59
n0=1@24-3
n1=1@24-63


.ENTRY	PURDY,^M<r2,r3,r4,r5>
	MOVQ	@4(AP),-(SP)
	BSBW	PQMOD_R0
	MOVAQ	(SP),R4
	MOVAQ	PURDY_POLY,R5
	MOVQ    (R4),-(SP)
	PUSHL   #n1
	BSBB    PQEXP_R3
	MOVQ    (R4),-(SP)
	PUSHL   #n0-n1
	BSBB    PQEXP_R3
	MOVQ    (R5)+,-(SP)
	BSBW    PQADD_R0
	BSBW    PQMUL_R2
	MOVQ    (R5)+,-(SP)
	MOVQ    (R4),-(SP)
	BSBW    PQMUL_R2
	MOVQ    (R5)+,-(SP)
	BSBW    PQADD_R0
	MOVQ    (R4),-(SP)
	BSBB    PQMUL_R2
	MOVQ    (R5)+,-(SP)
	BSBW    PQADD_R0
	MOVQ    (R4),-(SP)
	BSBB    PQMUL_R2
	MOVQ    (R5)+,-(SP)
	BSBW    PQADD_R0
	BSBW    PQADD_R0
	MOVQ    (SP)+,@4(AP)
	MOVL    #1,R0
	RET

PQEXP_R3:
	POPR    #^M<r3>
	MOVQ    #1,-(SP)
	MOVQ    8+4(SP),-(SP)
	TSTL    8+8(SP)
	BEQL    30$
10$:	BLBC    8+8(SP),20$
	MOVQ    (SP),-(SP)
	MOVQ    8+8(SP),-(SP)
	BSBB    PQMUL_R2
	MOVQ    (SP)+,8(SP)
	CMPZV   #1,#31,8+8(SP),#0
	BEQL    30$
20$:	MOVQ    (SP),-(SP)
	BSBB    PQMUL_R2
	EXTZV   #1,#31,8+8(SP),8+8(SP)
	BRB     10$

30$:	MOVQ    8(SP),8+8+4(SP)
	MOVAQ   8+8+4(SP),SP
	JMP     (R3)

u=0
v=u+4
y=u+8
z=y+4

PQMOD_R0:
	POPR    #^M<R0>
	CMPL    v(SP),#-1
	BLSSU   10$
	CMPL    u(SP),#-a
	BLSSU   10$
	ADDL2   #a,u(SP)
	ADWC    #0,v(SP)
10$:	JMP     (R0)

PQMUL_R2:
	POPR    #^M<r1>
	MOVL    SP,R2
	PUSHL   z(R2)
	PUSHL   v(R2)
	BSBB    EMULQ
	BSBB    PQMOD_R0
	BSBB    PQLSH_R0
	PUSHL   y(R2)
	PUSHL   v(R2)
	BSBB    EMULQ
	BSBB    PQMOD_R0
	PUSHL   z(R2)
	PUSHL   u(R2)
	BSBB    EMULQ
	BSBB    PQMOD_R0
	BSBB    PQADD_R0
	BSBB    PQADD_R0
	BSBB	PQLSH_R0
	PUSHL   y(R2)
	PUSHL	u(R2)
	BSBB	EMULQ
	BSBB    PQMOD_R0
	BSBB    PQADD_R0	
	MOVQ    (SP)+,Y(R2)
	MOVAQ   Y(R2),SP
	JMP     (R1)

EMULQ:
	EMUL    4(SP),8(SP),#0,-(SP)
	CLRL    -(SP)
	TSTL    4+8+4(SP)
	BGEQ    10$
	ADDL2   4+8+8(SP),(SP)
10$:	TSTL    4+8+8(SP)
	BGEQ    20$
	ADDL2   4+8+4(SP),(SP)
20$:	ADDL2   (SP)+,4(SP)
	MOVQ    (SP)+,4(SP)
	RSB     

PQLSH_R0:
.ENABLE LSB
	POPR    #^M<r0>
	PUSHL   v(SP)
	PUSHL   #a
	BSBB    EMULQ
	ASHQ    #32,Y(SP),Y(SP)
	BRB	10$

PQADD_R0:
	POPR    #^M<R0>
10$:	ADDL2   u(SP),y(SP)
	ADWC    v(SP),z(SP)
	BLSSU   20$
	CMPL    z(SP),#-1
	BLSSU   30$
	CMPL    y(SP),#-a
	BLSSU   30$
20$:	ADDL2   #a,y(SP)
	ADWC    #0,z(SP)
30$:	MOVAQ   Y(SP),SP
	JMP     (R0)
.END
$ COPY BULLETIN.EXE SYS$SYSTEM:
$ SET FILE SYS$SYSTEM:BULLETIN.EXE/OWN=[1,4]
$ RUN SYS$SYSTEM:INSTALL
SYS$SYSTEM:BULLETIN/SHARE/OPEN/HEAD/PRIV=(OPER,SYSPRV,CMKRNL)
/EXIT
$ LIB/CREATE/HELP SYS$HELP:BULL
$ LIB/HELP SYS$HELP:BULL BULLCOMS
$ LIB/HELP SYS$HELP:HELPLIB BULLETIN
This message is being displayed by the BULLETIN facility.  This is a non-DEC
facility, so it is not described in the manuals.  System messages, such as this
one, are displayed in full.  Only topics will be displayed for non-system
messages.  Messages are submitted using the BULLETIN command.  Any user may
submit a non-system message.  Only privileged users can submit a system
message. For more information, see the on-line help (via HELP BULLETIN). 
$ BULL*ETIN :== $SYS$SYSTEM:BULLETIN
$ BULLETIN/LOGIN
;
;  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	SCH$GL_CURPCB,R2		; Address of current process
	MOVL	R3,PCB$L_UIC(R2)		; Set UIC to specified
	MOVZWL	#SS$_NORMAL,R0			; Normal ending
	RET
	.END
;
;  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	SCH$GL_CURPCB,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	SCH$GL_CURPCB,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
	.END
$ UIC := 'F$GETJPI("","UIC")
$ SET UIC [1,4]
$ SET PROTECT=(SYSTEM:RWE,OWNER:RWE,WORLD,GROUP)/DEFAULT
$ RUN BULLETIN
ADD/PERMANENT/SYSTEM INSTRUCT.TXT
INFORMATION ON HOW TO USE THE BULLETIN UTILITY.
EXIT
$ SET UIC 'UIC'
$ DEFAULT := 'F$FILE("SYS$LOGIN:LOGIN.COM","PRO")
$ SET PROTECT=('DEFAULT')/DEFAULT
;------------------------------------------------------------------------------
;
;		Name: USER_OPEN
;
;		Type: Multilple Function (MACRO)
;
;     		Author:	T.W.Fredian
;			MIT Plasma Fusion Center
;
;		Date:	January 26, 1983
;
;    		Version:
;
;    		Purpose: Used to permit qio access to files with fortran.
;			 Returns channel and file size information and
;			 provides file truncation capability. Files opened
;			 with these useopens cannot be accessed using fortran
;			 reads and writes and the dispose= keyword on the
;			 close of the file will have no effect. To make the
;			 logical unit reuseable for normal RMS access you must
;			 deassign the channel using SYS$DASSGN(%VAL(channel))
;			 and then use the close (unit= ) statement.
;
;               Types of useropens provided:
;
;                   USER_OPEN$OLD        - open old file
;                   USER_OPEN$NEW        - open new file
;                   USER_OPEN$TRUNCATE   - open old file and truncate it
;                                          to the size specified by the
;                                          INITIALSIZE keyword of the open
;
;              To receive the channel, open RMS status and size of the file
;              include a common USER_OPEN as follows:
;
;              Common /USER_OPEN/ CHANNEL,STATUS,SIZE
;              Integer*4 CHANNEL - I/O channel assigned to the file
;              Integer*4 STATUS  - RMS status return of open
;              Integer*4 SIZE    - Size of the file opened in blocks
;
;------------------------------------------------------------------------------
;
;	Call seqence: NONE - USEROPEN keyword of fortran OPEN statement
;                     for example:
;
;           External USER_OPEN$NEW
;           .
;           .
;           .
;           OPEN (UNIT=lun,FILE=filename,....,USEROPEN=USER_OPEN$NEW)
;
;------------------------------------------------------------------------------
;
; 	Description:
;
; Entry mask for USER_OPEN$OLD
; Get the FAB address
; Set the user file open bit
; Open old file
; Save the channel
; Save the size
; Save the status
; Return

; Entry mask for USER_OPEN$NEW
; Get the FAB address
; Set the user file open bit
; Open new file
; Save the channel
; Save the size
; Save the status
; Return

; Entry mask for USER_OPEN$TRUNCATE
; Get the FAB address
; Get the RAB address
; Save the size
; Open old file
; Connect file to record stream
; Load the size of the file in the RAB
; Set the access mode to relative file address
; Find the last record in the file
; Place the end of file marker at this location
; Mark the file to be truncated on close
; Close the file
; Return

; End
;
;+-----------------------------------------------------------------------------

	.TITLE	USER_OPEN
	.IDENT	/V_830128/

;
;------------------------------------------------------------------------------
;
; Global variables:
;
	.PSECT	USER_OPEN	LONG,PIC,OVR,GBL,SHR,NOEXE

CHANNEL:	.BLKL	1			; Channel number
STATUS:		.BLKL	1			; Status return of open
SIZE:		.BLKL	1			; Size of file

;
;------------------------------------------------------------------------------
;
; Executable:
;
	.PSECT	$CODE	LONG,PIC,USR,CON,REL,LCL,SHR,EXE,RD,NOWRT,NOVEC

	.ENTRY	USER_OPEN$OLD,^M<R2>		; Entry mask for USER_OPEN$OLD
        MOVL	4(AP),R2			; Get the FAB address
	INSV	#1,#FAB$V_UFO,#1,FAB$L_FOP(R2)	; Set the user file open bit
	$OPEN	FAB=(R2)			; Open old file
        MOVL	FAB$L_STV(R2),CHANNEL		; Save the channel
	MOVL	FAB$L_ALQ(R2),SIZE		; Save the size
	MOVL	R0,STATUS			; Save the status
	RET					; Return

        .ENTRY  USER_OPEN$NEW,^M<R2>		; Entry mask for USER_OPEN$NEW
	MOVL	4(AP),R2			; Get the FAB address
	INSV	#1,#FAB$V_UFO,#1,FAB$L_FOP(R2)	; Set the user file open bit
	INSV	#0,#FAB$V_CBT,#1,FAB$L_FOP(R2)	; Disable contiguous best try
	$CREATE	FAB=(R2)			; Open new file
        MOVL	FAB$L_STV(R2),CHANNEL		; Save the channel
	MOVL	FAB$L_ALQ(R2),SIZE		; Save the size
	MOVL	R0,STATUS			; Save the status
	RET					; Return

	.ENTRY	USER_OPEN$TRUNCATE,^M<R2,R3,R4,R5>	; Entry mask for USER_OPEN$TRUNCATE
        MOVL	4(AP),R2			; Get the FAB address
	MOVL	8(AP),R3			; Get the RAB address
	MOVL	FAB$L_ALQ(R2),R4		; Save the size
	INCL	R4				; Increment the size
	INSV	#0,#FAB$V_SQO,#1,FAB$L_FOP(R2)	; Clear the sequential only bit
	$OPEN	FAB=(R2)			; Open old file
	BLBC	R0,CLOSE			; If unsuccessful branch to close
	$CONNECT RAB=@8(AP)			; Connect file to record stream
        BLBC	R0,CLOSE			; If unsuccessful branch to close
	MOVL	R4,RAB$L_RFA0(R3)		; Load the size of the file in the RAB
	MOVW	#0,RAB$W_RFA4(R3)
	MOVB	#RAB$C_RFA,RAB$B_RAC(R3)	; Set the access mode to relative file address
	$FIND	RAB=(R3)			; Find the last record in the file
	BLBC	R0,CLOSE			; If unsuccessful branch to close
	$TRUNCATE RAB=(R3)			; Place the end of file marker at this location
	INSV	#1,#FAB$V_TEF,#1,FAB$L_FOP(R2)	; Mark the file to be truncated on close
CLOSE:	PUSHL	R0				; Save error status
	$CLOSE	FAB=(R2)			; Close the file
	POPL	R0				; Restore error status
	MOVL    R0,STATUS			; Return the status
	RET					; Return

	.END					; End

