C
C  BULLETIN.FOR, Version 2/27/98
C  Purpose: Bulletin board utility program.
C  Environment: VAX/VMS
C  Usage: Invoked by the BULLETIN command.
C  Programmer: Mark R. London
C
C  Copyright (c) 1990
C  Property of Massachusetts Institute of Technology, Cambridge MA 02139.
C  This program cannot be copied or distributed in any form for non-MIT
C  use without specific written approval of MIT Plasma Fusion Center
C  Management.
C

	IMPLICIT INTEGER (A - Z)

	INCLUDE 'BULLFILES.INC'

	INCLUDE 'BULLDIR.INC'

	INCLUDE 'BULLFOLDER.INC'

	INCLUDE 'BULLUSER.INC'

	INCLUDE '($RMSDEF)'

	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
	CHARACTER*64 BULL_PARAMETER

	COMMON /POINT/ BULL_POINT

	COMMON /PROMPT/ COMMAND_PROMPT
	CHARACTER*40 COMMAND_PROMPT

	EXTERNAL BULLETIN_SUBCOMMANDS,LIB$GET_INPUT
	EXTERNAL CLI$_ABSENT,CLI$_NOCOMD,CLI$_NEGATED

	COMMON /COMMAND_LINE/ INCMD
	CHARACTER*256 INCMD

	COMMON /PROMPT_PROMPT/ PROMPT,LPROMPT
	CHARACTER*44 PROMPT

	COMMON /NEXT_COMMAND/ NEXT_COMMAND
	CHARACTER NEXT_COMMAND*64
	DATA NEXT_COMMAND/' '/

	COMMON /COUNT/
     &     DIR_COUNT,	   ! # directory entry to continue bulletin read from
     &     READ_COUNT,	   ! # block that bulletin READ is to continue from
     &     FOLDER_COUNT,   ! # folder entry to continue SHOW/ALL folder from
     &	   INDEX_COUNT
	DATA DIR_COUNT/0/,READ_COUNT/0/,FOLDER_COUNT/0/,INDEX_COUNT/0/

	COMMON /DCL/ DCL_CMD,DCL_COMMAND
	CHARACTER DCL_CMD*132

	CALL INIT_BULLETIN(.TRUE.)

C
C  The MAIN loop for processing bulletin commands.
C

	LPROMPT = TRIM(COMMAND_PROMPT)
	PROMPT = CHAR(10)//COMMAND_PROMPT(:LPROMPT)//' '
	LPROMPT = LPROMPT + 2

	DO WHILE (LPROMPT.GT.0)

	   IF (.NOT.DCL_COMMAND) THEN
	      CALL COMMAND_INPUT(IER)
	   ELSE
	      IF (INDEX(DCL_CMD,';').GT.0) THEN
	         INCMD = DCL_CMD(:INDEX(DCL_CMD,';')-1)
	         DCL_COMMAND = DCL_CMD(INDEX(DCL_CMD,';'):).NE.';'
	         DCL_CMD = DCL_CMD(INDEX(DCL_CMD,';')+1:)
	      ELSE
	         INCMD = DCL_CMD
	         DCL_CMD = ' '
	      END IF
 	      IER = TRIM(INCMD)
	   END IF

	   IF (IER.EQ.-2) THEN
	      IER = RMS$_EOF
	   ELSE IF (IER.LE.0) THEN
	      IER = %LOC(CLI$_NOCOMD)
	   ELSE
	      DO WHILE (IER.GT.0.AND.INCMD(:1).EQ.' ')
		 INCMD = INCMD(2:IER)
		 IER = IER - 1
	      END DO
	      IF (IER.GT.0.AND.INCMD(:1).GE.'0'.AND.INCMD(:1).LE.'9') THEN
		 INCMD = 'READ '//INCMD
	      END IF
	      IF (IER.GT.0) THEN 
		  IF (INDEX(INCMD(:IER),' ').EQ.0.AND.
     &		      INDEX(INCMD,'/').EQ.0.AND.
     &		      INDEX(INCMD,'.').GT.0) INCMD = 'SELECT '//INCMD
	      END IF
	      IER=CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS,LIB$GET_INPUT)
	   END IF

	   IF (IER.EQ.RMS$_EOF) THEN
	      CALL EXIT			! If no command, exit
	   ELSE IF (IER.EQ.%LOC(CLI$_NOCOMD)) THEN  ! If just RETURN entered
	      INCMD = ' '		! Make sure there is none
	      LEN_P = 0			! Indicate no parameter in command
	      IF (DIR_COUNT.GT.0) THEN		! If still more dir entries
		 CALL DIRECTORY(DIR_COUNT)	! continue outputting them
	      ELSE IF (INDEX_COUNT.GT.0) THEN
	         CALL FULL_DIR
	      ELSE IF (FOLDER_COUNT.GT.0) THEN	! If more folder entries
		 CALL DIRECTORY_FOLDERS(FOLDER_COUNT) ! continue outputting them
	      ELSE IF (READ_COUNT.NE.0) THEN 
		 CALL READ_MSG(READ_COUNT,BULL_POINT+1)
	         DIR_COUNT = 0
	         FOLDER_COUNT = 0
	         INDEX_COUNT = 0
	      ELSE IF (NEXT_COMMAND.NE.' ') THEN
		 INCMD = NEXT_COMMAND
	         IER = CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS,LIB$GET_INPUT)
		 CALL DO_COMMAND(INCMD)
	      ELSE				! Else try to read next bulletin
		 CALL READ_MSG(READ_COUNT,BULL_POINT+1)  ! or finish old one
	         DIR_COUNT = 0
	         FOLDER_COUNT = 0
	         INDEX_COUNT = 0
	      END IF
	      GO TO 100				! Loop to read new command
	   ELSE IF (.NOT.IER) THEN		! If command has error
	      GO TO 100				! ask for new command
	   END IF

	   CALL DO_COMMAND(INCMD)

100	   CONTINUE

	   IF (DCL_COMMAND.AND.TRIM(DCL_CMD).EQ.0) CALL EXIT

	END DO

1010	FORMAT(Q,A)

	END




	SUBROUTINE DO_COMMAND(INCMD)

	IMPLICIT INTEGER (A - Z)

	INCLUDE 'BULLFOLDER.INC'

	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
	CHARACTER*64 BULL_PARAMETER

	COMMON /COUNT/
     &     DIR_COUNT,	   ! # directory entry to continue bulletin read from
     &     READ_COUNT,	   ! # block that bulletin READ is to continue from
     &     FOLDER_COUNT,   ! # folder entry to continue SHOW/ALL folder from
     &	   INDEX_COUNT
	DATA DIR_COUNT/0/,READ_COUNT/0/,FOLDER_COUNT/0/,INDEX_COUNT/0/

	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT

	COMMON /ACCESS/ READ_ONLY
	LOGICAL READ_ONLY

	COMMON /POINT/ BULL_POINT

	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
	LOGICAL PAGING /.FALSE./

	COMMON /BULL_USER_CUSTOM/ BULL_USER_CUSTOM

	COMMON /NEXT_COMMAND/ NEXT_COMMAND
	CHARACTER NEXT_COMMAND*64

	EXTERNAL CLI$_ABSENT,CLI$_NOCOMD,CLI$_NEGATED
	EXTERNAL BULLETIN_SUBCOMMANDS

	CHARACTER HELP_DIRECTORY*64,SAVE_FOLDER*44

	CHARACTER*(*) INCMD

	NEXT_COMMAND = ' '

        IER = MINGT0(INDEX(INCMD(:TRIM(INCMD)),' '),INDEX(INCMD,'/'))
	IF (IER.GT.0) INCMD = '    '//INCMD(IER:)	! Save qualifiers
	CALL CLI$GET_VALUE('$VERB',INCMD(:4))		! Get user's command.

	IF (HLEN.EQ.0) THEN
	   IER = LIB$SYS_TRNLOG('BULL_HELP',HLEN,HELP_DIRECTORY)
	   IF (IER.NE.1) THEN
	      HELP_DIRECTORY = 'SYS$HELP:'
	      HLEN = 9
	   ELSE IF (HELP_DIRECTORY(HLEN:HLEN).NE.':'.AND.
     &	   	 HELP_DIRECTORY(HLEN:HLEN).NE.']') THEN
	      HELP_DIRECTORY = HELP_DIRECTORY(:HLEN)//':'
	      HLEN = HLEN + 1
	   END IF
	END IF

	IF (INCMD(:4).EQ.'BACK'.AND.DIR_COUNT.NE.0) THEN
	   DIR_COUNT = -1
	   CALL DIRECTORY(DIR_COUNT)
	   INCMD = ' '
C	ELSE IF (INCMD(:4).EQ.'BACK'.AND.FOLDER_COUNT.NE.0) THEN
C	      FOLDER_COUNT = -1
C	      CALL DIRECTORY_FOLDERS(FOLDER_COUNT)
C	      INCMD = ' '
	ELSE
	   DIR_COUNT = 0			! Reinit display pointers
	   READ_COUNT = 0
	   FOLDER_COUNT = 0
	   INDEX_COUNT = 0
	END IF

	IF_ADD = INCMD(:3).EQ.'ADD'
	IF (IF_ADD) IF_ADD = .NOT.CLI$PRESENT('SELECT_FOLDER')
	IF (READ_ONLY.AND.(IF_ADD.OR.INCMD(:3).EQ.'DEL'.OR.
     &	    INCMD(:4).EQ.'POST'.OR.
     &	    INCMD(:3).EQ.'CHA'.OR.INCMD(:3).EQ.'REP')) THEN
	   					! FOLDER can only be read?
	   WRITE (6,'('' ERROR: Access to folder limited to reading.'')')
	ELSE IF (INCMD(:3).EQ.'ADD') THEN	! ADD?
	   IF (REMOTE_SET.GE.3) THEN
	      IF (CLI$PRESENT('SELECT_FOLDER')) THEN
		 WRITE (6,'('' ERROR: /FOLDER not valid when posting'',
     &			    '' a message to a news group.'')')
	      ELSE
		 INCMD = 'POST '//INCMD(4:)
		 IER = CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
		 CALL RESPOND
	      END IF
	   ELSE
	      CALL ADD
	   END IF
	ELSE IF (INCMD(:3).EQ.'ATT') THEN	! ATTACH?
	   CALL ATTACH
	ELSE IF (INCMD(:4).EQ.'BACK') THEN	! BACK?
	   IF (BULL_POINT.LE.1) THEN
	      WRITE(6,'('' ERROR: There are no more preceding messages.'')')
	   ELSE
	      CALL READ_MSG(READ_COUNT,BULL_POINT-1)  ! Try to read previous
	   END IF
	ELSE IF (INCMD(:4).EQ.'CHAN') THEN		! CHANGE?
	   CALL REPLACE				! Replace old bulletin
	ELSE IF (INCMD(:4).EQ.'COPY') THEN		! COPY?
	   CALL MOVE(.FALSE.)
	ELSE IF (INCMD(:4).EQ.'CREA') THEN		! CREATE?
	   CALL CREATE_FOLDER			! Go create the folder
	ELSE IF (INCMD(:4).EQ.'CURR') THEN		! CURRENT?
	   READ_COUNT = -1		! Reread current message from beginning.
	   CALL READ_MSG(READ_COUNT,BULL_POINT)
	ELSE IF (INCMD(:4).EQ.'DELE') THEN 	! DELETE?
	   CALL DELETE_MSG			! Go delete bulletin
	ELSE IF (INCMD(:4).EQ.'DIRE') THEN		! DIRECTORY?
	   IF (CLI$PRESENT('FOLDER').AND.CLI$PRESENT('NEWS')) THEN
	      WRITE (6,'('' ERROR: /NEWS and /FOLDER cannot be ''
     &		         ''specified at the same time.'')')
	   ELSE IF (CLI$PRESENT('FOLDER').OR.		! /FOLDER specified?
     &	       CLI$PRESENT('NEWS')) THEN		! or /NEWS?
	      CALL DIRECTORY_FOLDERS(FOLDER_COUNT)	! Show all folders
	   ELSE IF (CLI$PRESENT('SELECT_FOLDER')) THEN! Folder specified?
	      CALL SELECT_FOLDER(.TRUE.,IER)		! Try to select folder
	      IF (IER) THEN				! If successful
		 CALL DIRECTORY(DIR_COUNT)		! Show messages
	      END IF
	   ELSE
	      CALL DIRECTORY(DIR_COUNT)		! Show messages
	   END IF
	ELSE IF (INCMD(:4).EQ.'FILE'.OR.
     &		 INCMD(:4).EQ.'EXTR') THEN		! FILE?
	   CALL FILE(0,.TRUE.,.FALSE.)			! Copy bulletin to file
	ELSE IF (INCMD(:4).EQ.'EXCL') THEN		! EXCLUDE?
	   CALL INCLUDE(.TRUE.)
	ELSE IF (INCMD(:1).EQ.'E'.OR.
     &		 INCMD(:4).EQ.'QUIT') THEN		! EXIT?
	   CALL EXIT				! Exit from program
	ELSE IF (INCMD(:4).EQ.'FIRS') THEN		! FIRST?
	   READ_COUNT = -1
	   BULL_READ = 1
	   CALL READ_MSG(READ_COUNT,BULL_READ)
	ELSE IF (INCMD(:4).EQ.'HELP') THEN		! HELP?
	   CALL HELP(HELP_DIRECTORY(:HLEN)//'BULL.HLB')	! Get help
	ELSE IF (INCMD(:3).EQ.'IND') THEN		! INDEX?
	   INDEX_COUNT = 1
	   CALL FULL_DIR
	ELSE IF (INCMD(:4).EQ.'INCL'.OR.		! INCLUDE?
     &	         INCMD(:4).EQ.'THRE') THEN		! THREAD?
	   CALL INCLUDE(.FALSE.)
	ELSE IF (INCMD(:4).EQ.'LAST') THEN		! LAST?
	   READ_COUNT = -1
	   BULL_READ = 9999999
	   CALL READ_MSG(READ_COUNT,BULL_READ)
	ELSE IF (INCMD(:4).EQ.'MARK') THEN		! MARK?
	   CALL TAG(.TRUE.,1)
	ELSE IF (INCMD(:4).EQ.'MAIL'.OR.
     &		 INCMD(:4).EQ.'FORW') THEN		! MAIL?
	   CALL MAIL
	ELSE IF (INCMD(:3).EQ.'MOD') THEN		! MODIFY?
	   CALL MODIFY_FOLDER
	ELSE IF (INCMD(:4).EQ.'MOVE') THEN		! MOVE?
	   CALL MOVE(.TRUE.)
	ELSE IF (INCMD(:4).EQ.'NEWS') THEN		! NEWS
	   CALL DIRECTORY_FOLDERS(FOLDER_COUNT)	! Show new folders
	ELSE IF (INCMD(:4).EQ.'NEXT'.OR.INCMD(:1).EQ.'N') THEN    ! NEXT?
	   CALL READ_MSG(READ_COUNT,BULL_POINT+1)	! Read next bulletin
	ELSE IF (INCMD(:4).EQ.'POST') THEN		! POST?
	   IF (BTEST(FOLDER_FLAG,11)) THEN
	      INCMD = 'ADD '//INCMD(5:)
	      IER=CLI$DCL_PARSE(INCMD,BULLETIN_SUBCOMMANDS)
	      CALL ADD
	   ELSE
	      CALL RESPOND
	   END IF
	ELSE IF (INCMD(:4).EQ.'PRIN') THEN		! PRINT?
	   CALL PRINT(0,.TRUE.)			! Printout bulletin
	ELSE IF (INCMD(:4).EQ.'READ') THEN		! READ?
	   IF (CLI$PRESENT('THREADS')) NEXT_COMMAND = 'READ/THREADS'
	   IER = CLI$GET_VALUE('BULLETIN_NUMBER',BULL_PARAMETER,LEN_P)
	   IF (IER.NE.%LOC(CLI$_ABSENT)) THEN		! Bulletin specified?
	      DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER) BULL_READ	! Yes
	      READ_COUNT = -1
	      CALL READ_MSG(READ_COUNT,BULL_READ)
	   ELSE
	      CALL READ_MSG(READ_COUNT,BULL_POINT+1)
	   END IF
	ELSE IF (INCMD(:3).EQ.'REM') THEN		! REMOVE?
	   CALL REMOVE_FOLDER
	ELSE IF (INCMD(:3).EQ.'REP') THEN		! REPLY?
	   IF (.NOT.BTEST(FOLDER_FLAG,11).AND.(REMOTE_SET.GE.3.OR.
     &	      INDEX(FOLDER_DESCRIP,'<').GT.0)) THEN
	      CALL RESPOND
	   ELSE
	      CALL REPLY
	   END IF
	ELSE IF (INCMD(:4).EQ.'RESP') THEN		! RESPOND?
	   CALL RESPOND
	ELSE IF (INCMD(:4).EQ.'RESE') THEN		! RESET?
	   CALL RESET
	ELSE IF (INCMD(:3).EQ.'SEA') THEN		! SEARCH?
	   NEXT_COMMAND = 'SEARCH'
	   CALL SEARCH(READ_COUNT)
	ELSE IF (INCMD(:3).EQ.'SEE') THEN		! SEEN?
	   CALL TAG(.TRUE.,2)
	ELSE IF (INCMD(:3).EQ.'SEL') THEN		! SELECT?
	   CALL SELECT_FOLDER(.TRUE.,IER)
	ELSE IF (INCMD(:3).EQ.'SET') THEN		! SET?
	   CALL CLI$GET_VALUE('SET_PARAM1',BULL_PARAMETER)
	   IF (BULL_PARAMETER(:2).EQ.'FO') THEN		! SET FOLDER?
	      CALL SELECT_FOLDER(.TRUE.,IER)
	   ELSE IF (BULL_PARAMETER(:2).EQ.'FI') THEN	! SET FILE_DIRECTORY?
	      CALL SET_CUSTOM('file_directory')
	   ELSE IF (BULL_PARAMETER(:3).EQ.'PRI') THEN		! SET PRIVS?
	      CALL SET_PRIV
	   ELSE IF (BULL_PARAMETER(:2).EQ.'PA') THEN		! SET PAGE?
	      PAGING = .TRUE.
	      WRITE (6,'('' PAGE has been set.'')')
	   ELSE IF (BULL_PARAMETER(:1).EQ.'K') THEN		! SET KEYPAD?
	      CALL SET_KEYPAD
	   ELSE IF (BULL_PARAMETER(:3).EQ.'NOK') THEN		! SET NOKEYPAD?
	      CALL SET_NOKEYPAD
	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOPA') THEN	! SET NOPAGE?
	      PAGING = .FALSE.
	      WRITE (6,'('' NOPAGE has been set.'')')
	   ELSE IF (FOLDER_NUMBER.EQ.-1.AND.REMOTE_SET.EQ.1) THEN
	      WRITE (6,'('' ERROR: Invalid command for remote folder.'')')
	   ELSE IF (BULL_PARAMETER(:2).EQ.'SY') THEN		! SET SYSTEM?
	      CALL SET_SYSTEM(.TRUE.)
	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOSY') THEN	! SET NOSYSTEM?
	      CALL SET_SYSTEM(.FALSE.)
	   ELSE IF (BULL_PARAMETER(:2).EQ.'BB') THEN		! SET BBOARD?
	      CALL SET_BBOARD(.TRUE.)
	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOBB') THEN	! SET NOBBOARD?
	      CALL SET_BBOARD(.FALSE.)
	   ELSE IF (BULL_PARAMETER(:2).EQ.'DU') THEN		! SET DUMP?
	      CALL SET_FOLDER_FLAG(.TRUE.,1,'DUMP')
	   ELSE IF (BULL_PARAMETER(:4).EQ.'NODU') THEN	! SET NODUMP?
	      CALL SET_FOLDER_FLAG(.FALSE.,1,'DUMP')
	   ELSE IF (BULL_PARAMETER(:2).EQ.'ST') THEN		! SET STRIP?
	      CALL SET_FOLDER_FLAG(.TRUE.,4,'STRIP')
	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOST') THEN	! SET NOSTRIP?
	      CALL SET_FOLDER_FLAG(.FALSE.,4,'STRIP')
	   ELSE IF (BULL_PARAMETER(:2).EQ.'DI') THEN		! SET DIGEST?
	      CALL SET_FOLDER_FLAG(.TRUE.,5,'DIGEST')
	   ELSE IF (BULL_PARAMETER(:4).EQ.'NODI') THEN	! SET NODIGEST?
	      CALL SET_FOLDER_FLAG(.FALSE.,5,'DIGEST')
	   ELSE IF (BULL_PARAMETER(:2).EQ.'AL') THEN		! SET ALWAYS?
	      CALL SET_FOLDER_FLAG(.TRUE.,7,'ALWAYS')
	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOAL') THEN	! SET NOALWAYS?
	      CALL SET_FOLDER_FLAG(.FALSE.,7,'ALWAYS')
	   ELSE IF (BULL_PARAMETER(:2).EQ.'AN') THEN	     ! SET ANONYMOUS?
	      CALL SET_FOLDER_FLAG(.TRUE.,14,'ANONYMOUS')
	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOAN') THEN     ! SET NOANONYMOUS?
	      CALL SET_FOLDER_FLAG(.FALSE.,14,'ANONYMOUS')
	   ELSE IF (BULL_PARAMETER(:3).EQ.'COM') THEN	    ! SET COMPRESS?
	      CALL SET_FOLDER_FLAG(.TRUE.,12,'COMPRESS')
	   ELSE IF (BULL_PARAMETER(:5).EQ.'NOCOM') THEN   ! SET NOCOMPRESS?
	      CALL SET_FOLDER_FLAG(.FALSE.,12,'COMPRESS')
	   ELSE IF (BULL_PARAMETER(:2).EQ.'PO') THEN	    ! SET POST_ONLY?
	      CALL SET_FOLDER_FLAG(.TRUE.,10,'POST_ONLY')
	      IF (BTEST(FOLDER_FLAG,11)) THEN
		 CALL SET_FOLDER_FLAG(.FALSE.,11,'ADD_ONLY')
	      END IF
	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOPO') THEN    ! SET NOPOST_ONLY?
	      CALL SET_FOLDER_FLAG(.FALSE.,10,'POST_ONLY')
	   ELSE IF (BULL_PARAMETER(:2).EQ.'AD') THEN	    ! SET ADD_ONLY?
	      CALL SET_FOLDER_FLAG(.TRUE.,11,'ADD_ONLY')
	      IF (BTEST(FOLDER_FLAG,10)) THEN
		 CALL SET_FOLDER_FLAG(.FALSE.,10,'POST_ONLY')
	      END IF
	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOAD') THEN    ! SET NOADD_ONLY?
	      CALL SET_FOLDER_FLAG(.FALSE.,11,'ADD_ONLY')
	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOTI') THEN	! SET NOTIFY?
	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
     &		  CLI$PRESENT('NODEFAULT').OR.
     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
     &		  THEN
		 CALL SET_FOLDER_DEFAULT(1,-1,-1)
	      ELSE
		 CALL SET_USER_FLAG(1,-1,-1)
	      END IF
	   ELSE IF (BULL_PARAMETER(:3).EQ.'EXP') THEN		! SET EXPIRE?
	      IER = CLI$GET_VALUE('EXPIRATION',BULL_PARAMETER,LEN_P)
	      IF (LEN_P.LE.3) THEN
		 READ (BULL_PARAMETER,'(I<LEN_P>)') LIMIT
		 CALL SET_FOLDER_EXPIRE_LIMIT(LIMIT)
	      ELSE
		 WRITE (6,'('' ERROR: Invalid expiration specified.'')')
	      END IF
	   ELSE IF (BULL_PARAMETER(:4).EQ.'NODE') THEN	! SET NODE?
	      CALL SET_NODE(.TRUE.)
	   ELSE IF (BULL_PARAMETER(:6).EQ.'NONODE') THEN	! SET NONODE?
	      CALL SET_NODE(.FALSE.)
	   ELSE IF (BULL_PARAMETER(:5).EQ.'NOEXP') THEN	! SET NOEXPIRE?
	      CALL SET_FOLDER_EXPIRE_LIMIT(0)
	   ELSE IF (BULL_PARAMETER(:5).EQ.'NONOT') THEN	! SET NONOTIFY?
	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
     &		  CLI$PRESENT('NODEFAULT').OR.
     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
     &		  THEN
		 CALL SET_FOLDER_DEFAULT(0,-1,-1)
	      ELSE
		 CALL SET_USER_FLAG(0,-1,-1)
	      END IF
	   ELSE IF (BULL_PARAMETER(:2).EQ.'SH') THEN		! SET SHOWNEW?
	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
     &		  CLI$PRESENT('NODEFAULT').OR.
     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
     &		  THEN
		 CALL SET_FOLDER_DEFAULT(-1,0,1)
	      ELSE
		 CALL SET_USER_FLAG(-1,0,1)
	      END IF
	   ELSE IF (BULL_PARAMETER(:3).EQ.'NOS') THEN	! SET NOSHOWNEW?
	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
     &		  CLI$PRESENT('NODEFAULT').OR.
     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
     &		  THEN
		 CALL SET_FOLDER_DEFAULT(-1,0,0)
	      ELSE
		 CALL SET_USER_FLAG(-1,0,0)
	      END IF
	   ELSE IF (BULL_PARAMETER(:1).EQ.'R') THEN		! SET READNEW?
	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
     &		  CLI$PRESENT('NODEFAULT').OR.
     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
     &		  THEN
		 CALL SET_FOLDER_DEFAULT(-1,1,0)
	      ELSE
		 CALL SET_USER_FLAG(-1,1,0)
	      END IF
	   ELSE IF (BULL_PARAMETER(:3).EQ.'NOR') THEN	! SET NOREADNEW?
	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
     &		  CLI$PRESENT('NODEFAULT').OR.
     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
     &		  THEN
		 CALL SET_FOLDER_DEFAULT(-1,0,0)
	      ELSE
		 CALL SET_USER_FLAG(-1,0,0)
	      END IF
	   ELSE IF (BULL_PARAMETER(:2).EQ.'BR') THEN		! SET BRIEF?
	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
     &		  CLI$PRESENT('NODEFAULT').OR.
     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
     &		  THEN
		 CALL SET_FOLDER_DEFAULT(-1,1,1)
	      ELSE
		 CALL SET_USER_FLAG(-1,1,1)
	      END IF
	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOBR') THEN	! SET NOBRIEF?
	      IF (CLI$PRESENT('DEFAULT').OR.CLI$PRESENT('ALL').OR.
     &		  CLI$PRESENT('NODEFAULT').OR.
     &		  CLI$PRESENT('PERMANENT').OR.CLI$PRESENT('NOPERMANENT'))
     &		  THEN
		 CALL SET_FOLDER_DEFAULT(-1,0,0)
	      ELSE
		 CALL SET_USER_FLAG(-1,0,0)
	      END IF
	   ELSE IF (BULL_PARAMETER(:2).EQ.'SU') THEN	! SET SUBSCRIBE?
	      IF (REMOTE_SET.GE.3) THEN
		 D1 = 0
		 D2 = 0
		 D3 = 0
		 CALL SET_FOLDER_DEFAULT(D1,D2,D3)
	      ELSE
		 WRITE (6,'('' ERROR: Command invalid for folder.'')')
	      END IF
	   ELSE IF (BULL_PARAMETER(:1).EQ.'A') THEN	! SET ACCESS?
	      CALL SET_ACCESS(.TRUE.)
	   ELSE IF (BULL_PARAMETER(:3).EQ.'NOA') THEN	! SET NOACCESS?
	      CALL SET_ACCESS(.FALSE.)
	   ELSE IF (BULL_PARAMETER(:1).EQ.'C') THEN	! SET CONTINUOUS_BRIEF
	      CALL SET_BRIEF_CONTINUOUS(.TRUE.)
	   ELSE IF (BULL_PARAMETER(:3).EQ.'NOC') THEN	! SET NOCONTINUOUS_BRIEF
	      CALL SET_BRIEF_CONTINUOUS(.FALSE.)
	   ELSE IF (BULL_PARAMETER(:3).EQ.'GEN') THEN	! SET GENERIC?
	      CALL SET_GENERIC(.TRUE.)
	   ELSE IF (BULL_PARAMETER(:5).EQ.'NOGEN') THEN	! SET NOGENERIC?
	      CALL SET_GENERIC(.FALSE.)
	   ELSE IF (BULL_PARAMETER(:3).EQ.'LIB') THEN	! SET LIBRARY?
	      CALL SET_LIBRARY
	   ELSE IF (BULL_PARAMETER(:3).EQ.'LOG') THEN		! SET LOGIN?
	      CALL SET_LOGIN(.TRUE.)
	   ELSE IF (BULL_PARAMETER(:5).EQ.'NOLOG') THEN	! SET NOLOGIN?
	      CALL SET_LOGIN(.FALSE.)
	   ELSE IF (BULL_PARAMETER(:3).EQ.'PRO') THEN	 ! SET PROMPT_EXPIRE?
	      CALL SET_FOLDER_FLAG(.FALSE.,3,'PROMPT_EXPIRE')
	   ELSE IF (BULL_PARAMETER(:4).EQ.'NOPR') THEN ! SET NOPROMPT_EXPIRE?
	      CALL SET_FOLDER_FLAG(.TRUE.,3,'PROMPT_EXPIRE')
	   ELSE IF (BULL_PARAMETER(:3).EQ.'DEF') THEN	! SET DEFAULT_EXPIRE?
	      CALL SET_DEFAULT_EXPIRE
	   ELSE IF (BULL_PARAMETER(:2).EQ.'NE') THEN	! SET NEWS?
	      CALL SET_NEWS
	   ELSE IF (BULL_PARAMETER(:3).EQ.'EXC') THEN	! SET EXCLUDE?
	      BULL_USER_CUSTOM = IBCLR(BULL_USER_CUSTOM,4)
	   ELSE IF (BULL_PARAMETER(:5).EQ.'NOEXC') THEN ! SET NOEXCLUDE?
	      BULL_USER_CUSTOM = IBSET(BULL_USER_CUSTOM,4)
	   ELSE IF (BULL_PARAMETER(:3).EQ.'EXL') THEN	! SET EXLIMIT?
	      CALL SET_CUSTOM('exclude_limit')
	   ELSE IF (BULL_PARAMETER(:4).EQ.'NAME') THEN  ! SET NAME?
	      CALL SET_NEWNAME
	   ELSE IF (BULL_PARAMETER(:3).EQ.'GAT') THEN	    ! SET GATEWAY?
	      CALL SET_FOLDER_FLAG(.TRUE.,15,'GATEWAY')
	   ELSE IF (BULL_PARAMETER(:5).EQ.'NOGAT') THEN   ! SET NOGATEWAY?
	      CALL SET_FOLDER_FLAG(.FALSE.,15,'GATEWAY')
	   END IF
	ELSE IF (INCMD(:4).EQ.'SHOW') THEN		! SHOW?
	   CALL CLI$GET_VALUE('SHOW_PARAM1',BULL_PARAMETER,LEN_P)
	   IF (BULL_PARAMETER(:2).EQ.'EX') THEN		! SHOW EXCLUDE?
	      CALL SHOW_EXCLUDE(0)
	   ELSE IF (BULL_PARAMETER(:2).EQ.'FL') THEN	! SHOW FLAGS?
	      CALL SHOW_FLAGS
	   ELSE IF (BULL_PARAMETER(:2).EQ.'FO') THEN	! SHOW FOLDER?
	      CALL SHOW_FOLDER
	   ELSE IF (BULL_PARAMETER(:2).EQ.'IN'.OR.
     &		    BULL_PARAMETER(:2).EQ.'TH') THEN	! SHOW INCLUDE?
	      CALL SHOW_EXCLUDE(1)
	   ELSE IF (BULL_PARAMETER(:1).EQ.'K') THEN	! SHOW KEYPAD
	      CALL SHOW_KEYPAD(HELP_DIRECTORY(:HLEN)//'BULL.HLB')
	   ELSE IF (BULL_PARAMETER(:1).EQ.'L') THEN	! SHOW LIBRARY
	      CALL SHOW_LIBRARY
	   ELSE IF (BULL_PARAMETER(:1).EQ.'N') THEN	! SHOW NEW?
	      SAVE_FOLDER_NUMBER = FOLDER_NUMBER
	      SAVE_FOLDER = FOLDER
	      CALL NEW_MESSAGE_NOTIFICATION
	      FOLDER1 = SAVE_FOLDER
	      FOLDER_NUMBER = SAVE_FOLDER_NUMBER
	      CALL SELECT_FOLDER(.FALSE.,IER)
	   ELSE IF (BULL_PARAMETER(:1).EQ.'P') THEN	! SHOW PRIVILEGES?
	      CALL SHOW_PRIV
	   ELSE IF (BULL_PARAMETER(:1).EQ.'U') THEN	! SHOW USER?
	      CALL SHOW_USER
	   ELSE IF (BULL_PARAMETER(:1).EQ.'V') THEN	! SHOW VERSION?
	      CALL SHOW_VERSION
	   END IF
	ELSE IF (INCMD(:4).EQ.'SPAW') THEN           ! SPAWN command?
	   CALL SPAWN_PROCESS
	ELSE IF (INCMD(:3).EQ.'SUB') THEN            ! SUBSCRIBE command?
	   CALL SUBSCRIBE
	ELSE IF (INCMD(:4).EQ.'UNDE') THEN		! UNDELETE?
	   CALL UNDELETE
	ELSE IF (INCMD(:3).EQ.'UNM') THEN		! UNMARK?
	   CALL TAG(.FALSE.,1)
	ELSE IF (INCMD(:4).EQ.'UNSE') THEN		! UNSEEN?
	   CALL TAG(.FALSE.,2)
	ELSE IF (INCMD(:4).EQ.'UNSU') THEN           ! UNSUBSCRIBE command?
	   CALL UNSUBSCRIBE
	END IF

	RETURN
	END




	SUBROUTINE COMMAND_INPUT(IER)

	IMPLICIT INTEGER (A - Z)

	COMMON /COMMAND_LINE/ INCMD
	CHARACTER*256 INCMD

	COMMON /PROMPT_PROMPT/ PROMPT,LPROMPT
	CHARACTER*44 PROMPT

	CALL GET_INPUT_PROMPT(INCMD,IER,PROMPT(:LPROMPT))

	RETURN
	END





	SUBROUTINE ADD
C
C  SUBROUTINE ADD
C
C  FUNCTION: Adds bulletin to bulletin file.
C
	IMPLICIT INTEGER (A - Z)

	COMMON /POINT/ BULL_POINT

	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
	CHARACTER*64 BULL_PARAMETER

	COMMON /NODE_INFO/ NODES,LOCAL_NODE_FOUND,NODE_NUM,
     &				NODE_ERROR,POINT_NODE
	CHARACTER*32 NODES(10)
	LOGICAL LOCAL_NODE_FOUND,NODE_ERROR

	COMMON /DECNET/ DECNET_PROC,ERROR_UNIT
	LOGICAL DECNET_PROC

	COMMON /EDIT/ EDIT_DEFAULT
	DATA EDIT_DEFAULT/.FALSE./

	COMMON /COMMAND_LINE/ INCMD
	CHARACTER*256 INCMD

	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT

	COMMON /LAST_RECORD_WRITTEN/ OCOUNT

	INCLUDE 'BULLDIR.INC'

	INCLUDE 'BULLUSER.INC'

	INCLUDE 'BULLFOLDER.INC'

	COMMON /INDESCRIP/ INDESCRIP
	CHARACTER*(INPUT_LENGTH) INDESCRIP

	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),NODENAME
	CHARACTER NODENAME*8

	COMMON /TAGS/ BULL_TAG,READ_TAG,BULL_NEWS_TAG

	CHARACTER INEXDATE*12,INEXTIME*12,INDENT*4

	CHARACTER INLINE*80,OLD_FOLDER*44,LOCAL_NODE*8

	EXTERNAL CLI$_ABSENT,CLI$_NEGATED,BULLETIN_SUBCOMMANDS

	EDITIT = (CLI$PRESENT('EDIT').OR.EDIT_DEFAULT).AND.
     &           (CLI$PRESENT('EDIT').NE.%LOC(CLI$_NEGATED))

	IF (CLI$PRESENT('EXTRACT').AND..NOT.EDITIT) THEN
	   WRITE (6,'('' ERROR: Cannot extract text without /EDIT.'')')
	   RETURN
	END IF

	IF (EDITIT.AND..NOT.CLI$PRESENT('EXTRACT')
     &	    .AND..NOT.CLI$PRESENT('FILESPEC')) THEN
	   CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
	END IF

	CALL DISABLE_CTRL		! Disable CTRL-Y & -C

	ALLOW = SETPRV_PRIV()

	OLD_FOLDER_NUMBER = FOLDER_NUMBER
	OLD_FOLDER = FOLDER

	LEN_P = 0

	IF (CLI$PRESENT('EXTRACT')) THEN
	   BULL_PARAMETER = 'SYS$LOGIN:BULL.SCR'
	   LEN_P = TRIM(BULL_PARAMETER)
	   OPEN(UNIT=3,FILE=BULL_PARAMETER(:LEN_P),IOSTAT=IER,
     &		RECL=LINE_LENGTH,
     &		STATUS='NEW',CARRIAGECONTROL='LIST',FORM='FORMATTED')

	   IF (IER.NE.0) THEN
	      CALL ERRSNS(IDUMMY,IER)
	      CALL SYS_GETMSG(IER)
	      GO TO 910
	   END IF

	   CALL OPEN_BULLFIL_SHARED

	   ILEN = LINE_LENGTH + 1

	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
	   END IF
	   IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
	   END IF

	   LENI = 0
	   IF (CLI$PRESENT('INDENT').NE.%LOC(CLI$_NEGATED)) THEN
	      CALL CLI$GET_VALUE('INDENT',INDENT,LENI)
	   END IF
	   DO WHILE (ILEN.GT.0)			! Copy bulletin into file
	      IF (LENI.EQ.0) THEN
	         WRITE (3,'(A)') INPUT(:ILEN)
	      ELSE
	         WRITE (3,'(A)') INDENT(:LENI)//INPUT(:ILEN)
	      END IF
	      CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
	   END DO

90	   CALL CLOSE_BULLFIL
	END IF

	SELECT_FOLDERS = .FALSE.
	IF (CLI$PRESENT('SELECT_FOLDER')) THEN
	   CALL GET_FOLDER_INFO(IER)
	   IF (.NOT.IER) GO TO 910
	   SELECT_FOLDERS = .TRUE.
	ELSE
	   NODE_NUM = 1
	   NODES(1) = OLD_FOLDER
	END IF

	IF (CLI$PRESENT('FILESPEC')) THEN
	   IER = CLI$GET_VALUE('FILESPEC',BULL_PARAMETER,LEN_P)
	   CALL DISABLE_PRIVS
	   IF (.NOT.CLI$PRESENT('EXTRACT')) THEN
	      OPEN (UNIT=3,FILE=BULL_PARAMETER(:LEN_P),STATUS='OLD',
     &		READONLY,SHARED,ERR=920,FORM='FORMATTED')
	   ELSE
	      OPEN (UNIT=4,FILE=BULL_PARAMETER(:LEN_P),STATUS='OLD',
     &		READONLY,SHARED,ERR=920,FORM='FORMATTED')
	      IER = 0
	      ICOUNT = 0
	      DO WHILE (IER.EQ.0)
		 READ (4,'(Q,A)',IOSTAT=IER) ILEN,INPUT
		 IF (IER.EQ.0) THEN
		    IF (ICOUNT.EQ.0) WRITE (3,'(A)') ' '
		    ICOUNT = ICOUNT + 1
		    WRITE (3,'(A)') INPUT(:ILEN)
		 END IF
	      END DO
	      CLOSE (UNIT=4)
	      BULL_PARAMETER = 'SYS$LOGIN:BULL.SCR'
	      LEN_P = TRIM(BULL_PARAMETER)
	   END IF
	   CALL ENABLE_PRIVS	! Reset SYSPRV privileges
	END IF

	IF (FOLDER_NUMBER.GT.0.AND.		! If folder set and
     &	    CLI$PRESENT('NODES')) THEN		! Decnet nodes specified?
	   WRITE (6,'('' ERROR: /NODES cannot be used with folder set.'')')
	   GO TO 910
	END IF

	IF (.NOT.BTEST(FOLDER_FLAG,2).AND.FOLDER_NUMBER.NE.0.AND.
     &	   (CLI$PRESENT('SYSTEM').OR.		! Is /SYSTEM switch present?
     &	    CLI$PRESENT('BROADCAST').OR.	! Is /BROADCAST swtich present?
     &	    CLI$PRESENT('SHUTDOWN'))) THEN	! Is /SHUTDOWN switch present?
	   WRITE (6,'('' ERROR: Folder is not a SYSTEM folder.'')')
	   GO TO 910
	END IF

	IF (CLI$PRESENT('SYSTEM')) THEN		! Is /SYSTEM switch present?
	   IF (.NOT.ALLOW) THEN			! If no privileges
	      WRITE(ERROR_UNIT,1070)		! Tell user
	      GO TO 910				! and abort
	   END IF
	   SYSTEM = 1				! Set system bit
	ELSE
	   SYSTEM = 0				! Clear system bit
	END IF

	IF (CLI$PRESENT('BROADCAST')) THEN	! Is /BROADCAST switch present?
	   IF (.NOT.(ALLOW.OR.OPER_PRIV())) THEN	! If no privileges
	      WRITE(ERROR_UNIT,1080)		! Tell user
	      GO TO 910				! and abort
	   ELSE IF (CLI$PRESENT('CLUSTER')) THEN
	      SYSTEM = SYSTEM.OR.8
	   END IF
	END IF

	IF (CLI$PRESENT('PERMANENT')) THEN	! Is /PERMANENT switch present?
	   IF (F_EXPIRE_LIMIT.GT.0.AND..NOT. ! Expiration limit present
     &		FOLDER_ACCESS(USERNAME,FOLDER_FLAG,FOLDER_OWNER)) THEN
	      WRITE(ERROR_UNIT,1083)
	      GO TO 910
	   ELSE
	      SYSTEM = SYSTEM.OR.2		! Set permanent bit
	      INEXDATE = '5-NOV-2100'
	      INEXTIME = '00:00:00.00'
	   END IF
	END IF

	IF (CLI$PRESENT('SHUTDOWN')) THEN	! Is /SHUTDOWN switch present?
	   IF (.NOT.ALLOW) THEN			! If no privileges
	      WRITE(ERROR_UNIT,1082)		! Tell user
	      GO TO 910				! and abort
	   ELSE
	      IER = CLI$GET_VALUE('SHUTDOWN',INLINE)
	      IF (IER.NE.%LOC(CLI$_ABSENT)) THEN
		 IF (REMOTE_SET) THEN		! Can't specify node name if
		    WRITE (6,1090)		! remote folder, as no code
		    GO TO 910			! present to send the name.
		 END IF
	         CALL GET_NODE_NUMBER_OTHER(NODE_NUMBER,NODE_AREA,INLINE)
		 IF (NODE_AREA.EQ.0) GO TO 910	! Invalid node name
	      ELSE
	         CALL GET_NODE_NUMBER(NODE_NUMBER,NODE_AREA)
	      END IF
	      SYSTEM = SYSTEM.OR.4		! Set shutdown bit
	      INEXDATE = '5-NOV-2100'
              WRITE (INEXTIME(1:),'(I2)') NODE_NUMBER/60
              WRITE (INEXTIME(3:),'(I2)') MOD(NODE_NUMBER,60)
              WRITE (INEXTIME(7:),'(I2)') NODE_AREA/60
              WRITE (INEXTIME(9:),'(I2)') MOD(NODE_AREA,60)
	      DO I=1,11
		 IF (INEXTIME(I:I).EQ.' ') INEXTIME(I:I) = '0'
	      END DO
	      INEXTIME = INEXTIME(1:2)//':'//INEXTIME(3:4)//':'//
     &			 INEXTIME(7:8)//'.'//INEXTIME(9:10)
	   END IF
	END IF

	SELECT_NODES = .FALSE.
	IF (CLI$PRESENT('NODES')) THEN
	   CALL GET_NODE_INFO
	   IF (NODE_ERROR) GO TO 940
	   SELECT_NODES = .TRUE.
	END IF

	IF ((SYSTEM.AND.7).LE.1.AND.(CLI$PRESENT('SELECT_FOLDER').OR.
     &	    CLI$PRESENT('NODES').OR..NOT.BTEST(FOLDER_FLAG,10))) THEN
	   CALL GET_EXPIRED(INPUT,IER)          ! Not permanent or shutdown 
	   IF (.NOT.IER) GO TO 910
	   INEXDATE = INPUT(:11)
	   INEXTIME = INPUT(13:23)
	END IF

	IF (INCMD(:3).EQ.'REP') THEN		! REPLY?
	   LENDES = TRIM(INDESCRIP)		! filled in by main subroutine
	ELSE IF (CLI$PRESENT('SUBJECT')) THEN	! /SUBJECT specified
	   CALL CLI$GET_VALUE('SUBJECT',INDESCRIP,LENDES)
	ELSE
	   WRITE(6,1050)			! Request header for bulletin
	   CALL GET_LINE(INDESCRIP,LENDES)	! Get input line
	   IF (LENDES.LE.0) GO TO 910
	END IF

	LENDES = MIN(LEN(INDESCRIP)-6,LENDES)	! Make room for "Subj: "

C
C  If file specified in ADD command, read file to obtain bulletin.
C  Else, read the bulletin from the terminal.
C

	IF (EDITIT.AND..NOT.DECNET_PROC) THEN	! If /EDIT specified
	   IF (LEN_P.EQ.0) THEN			! If no file param specified
	      CALL MAILEDIT('SYS$LOGIN:BULL.SCR',' ')
	      OPEN (UNIT=3,FILE='SYS$LOGIN:BULL.SCR',STATUS='OLD',
     &		 ERR=910,FORM='FORMATTED')
	      LEN_P = 1
	   ELSE
	      CLOSE (UNIT=3)
	      CALL MAILEDIT(BULL_PARAMETER(:LEN_P),'SYS$LOGIN:BULL.SCR')
	      IF (CLI$PRESENT('EXTRACT')) THEN
	         CONTEXT = 0
	         CALL LIB$FIND_FILE('SYS$LOGIN:BULL.SCR',INPUT,CONTEXT)
	         VERSION = INDEX(INPUT,';') + 1
	         IF (INPUT(VERSION:VERSION).EQ.'1') THEN
	            CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')
	         END IF
	      END IF
	      OPEN (UNIT=3,FILE='SYS$LOGIN:BULL.SCR',STATUS='OLD',
     &		 ERR=910,FORM='FORMATTED')
	   END IF
	   BULL_PARAMETER = 'SYS$LOGIN:BULL.SCR'
	   LEN_P = TRIM(BULL_PARAMETER)
	END IF

	ICOUNT = 0				! Line count for bulletin

	END = 0
	BLENGTH = 35
	IF (CLI$PRESENT('BELL')) BLENGTH = 37
	IF (LEN_P.GT.0) THEN			! If file param in ADD command
	   DO WHILE(1)				! Read until end of file to
	      READ (3,'(Q,A)',END=10) ILEN,INPUT! get record count
	      IF (ILEN.GT.LINE_LENGTH) GO TO 950
	      ICOUNT = ICOUNT + 1 + MIN(ILEN,80)
	      BLENGTH = BLENGTH + ILEN - 1 + 2
	      IF (ILEN.EQ.0) ICOUNT = ICOUNT + 1! COPY_BULL writes line with
	   END DO				! 1 space for blank line
	ELSE					! If no input file
	   BULL_PARAMETER = 'SYS$LOGIN:BULL.SCR'
	   LEN_P = TRIM(BULL_PARAMETER)
	   OPEN (UNIT=3,FILE='SYS$LOGIN:BULL.SCR',
     &		STATUS='NEW',
     &		FORM='FORMATTED',RECL=LINE_LENGTH) ! Temp file to save message
	   WRITE (6,1000)			! Request input from terminal
	   ILEN = LINE_LENGTH + 1		! Length of input line
	   ICOUNT = 0				! Character count counter
	   DO WHILE (ILEN.GE.0)			! Input until no more input
	      CALL GET_LINE(INPUT,ILEN)		! Get input line
	      IF (ILEN.GT.LINE_LENGTH) THEN	! Input line too long
		 WRITE(6,'('' ERROR: Input line length > '',I,
     &			''.  Reinput:'')') LINE_LENGTH
	      ELSE IF (ILEN.GE.0) THEN		! If good input line entered
		 ICOUNT = ICOUNT + ILEN		! Update counter
	         BLENGTH = BLENGTH + ILEN - 1 + 2
		 WRITE(3,2010) INPUT(:ILEN)	! Save line in scratch file
	      END IF
	   END DO
	   IF (ILEN.EQ.-1) GO TO 910		! CTRL_C entered, error out
10	   IF (ICOUNT.EQ.0) GO TO 910		! No lines entered, error out
	ENDIF

	REWIND (UNIT=3)

	BRDCST = .FALSE.

	IF (CLI$PRESENT('BROADCAST').AND.BLENGTH.GT.82*12+2) THEN
	   WRITE (6,'('' Message is too long for broadcasting by '',
     &	        I6,'' characters.  Limit is '',I3,''.'')')
     &			BLENGTH - 82*12 - 2, 82*12 - 2
	   CALL GET_INPUT_PROMPT(INPUT,ILEN,
     &		'Type C to broadcast anyway, A to only ADD message,'
     &   	//' or Q to Quit: ')
	   IF (STREQ(INPUT(:1),'Q')) THEN
	      GO TO 910
	   ELSE IF (STREQ(INPUT(:1),'A')) THEN
	      BRDCST = .TRUE.
	   ELSE IF (.NOT.STREQ(INPUT(:1),'C')) THEN
	      GO TO 910
	   END IF
	END IF

	IF (SELECT_NODES.AND.NODE_NUM.GT.0) THEN
	   INLINE = 'ADD'
	   IF (CLI$PRESENT('SYSTEM'))
     &	      INLINE = INLINE(:STR$POSITION(INLINE,' ')-1)//'/SYSTEM'
	   IF (CLI$PRESENT('BROADCAST').AND..NOT.BRDCST)
     &	      INLINE = INLINE(:STR$POSITION(INLINE,' ')-1)//'/BROADCAST'
	   IF (CLI$PRESENT('PERMANENT'))
     &	      INLINE = INLINE(:STR$POSITION(INLINE,' ')-1)//'/PERMANENT'
	   IF (CLI$PRESENT('SHUTDOWN'))
     &	      INLINE = INLINE(:STR$POSITION(INLINE,' ')-1)//'/SHUTDOWN'
	   IF (CLI$PRESENT('BELL'))
     &	      INLINE = INLINE(:STR$POSITION(INLINE,' ')-1)//'/BELL'

	   LEN_INLINE = STR$POSITION(INLINE,' ') - 1

	   DO POINT_NODE=1,NODE_NUM	   	! Write out command to nodes
	      INLINE = INLINE(:LEN_INLINE)

	      WRITE (POINT_NODE+9,'(A)',ERR=940) INLINE
	      IF ((SYSTEM.AND.7).LE.1)
				! If not permanent or shutdown specify date
     &		WRITE (POINT_NODE+9,'(A)',ERR=940) INEXDATE//' '//INEXTIME
	      WRITE (POINT_NODE+9,'(A)',ERR=940) INDESCRIP(:LENDES)
	      IER = 0
	      DO WHILE (IER.EQ.0)
	         READ (3,'(Q,A)',IOSTAT=IER) ILEN,INPUT
		 ILEN = MIN(ILEN,LINE_LENGTH)
		 IF (IER.EQ.0) THEN
		    WRITE (POINT_NODE+9,'(A)',ERR=940) INPUT(:ILEN)
		 END IF
	      END DO
	      WRITE (POINT_NODE+9,'(A)',ERR=940) CHAR(26)
	      READ (POINT_NODE+9,'(A)',ERR=940,END=940) INPUT
	      IF (INPUT.EQ.'END') THEN
	         WRITE (6,'('' Message successfully sent to node '',A)')
     &				NODES(POINT_NODE)
	      ELSE
	         WRITE (6,'('' Error while sending message to node '',A)')
     &				NODES(POINT_NODE)
		 WRITE (6,'(A)') INPUT(:80)
		 GO TO 940
	      END IF
	      REWIND (UNIT=3)
	   END DO
	END IF
	
	IF (SELECT_NODES.AND..NOT.LOCAL_NODE_FOUND) GO TO 95
					! Exit if local node not specified.

	IF (.NOT.SELECT_FOLDERS) THEN
	   NODE_NUM = 1				! No folders specified so just
	   NODES(1) = FOLDER			! add to select folder
	END IF

	IER = SYS_TRNLNM('SYS$NODE',LOCAL_NODE)
	LNODE = TRIM(LOCAL_NODE)	

C
C  Add bulletin to bulletin file and directory entry for to directory file.
C

	DO I = 1,NODE_NUM

	   IF (FOLDER.NE.NODES(I)) THEN
	      FOLDER_NUMBER = -1
	      FOLDER1 = NODES(I)
	      CALL SELECT_FOLDER(.FALSE.,IER)
	   ELSE
	      IER = 1
	   END IF
	   
	   IF (IER.AND..NOT.BTEST(FOLDER_FLAG,10)) THEN
	      CALL OPEN_BULLDIR			! Prepare to add dir entry

	      DESCRIP=INDESCRIP(:LENDES)	! Description header
	      EXDATE=INEXDATE			! Expiration date
	      EXTIME=INEXTIME
	      IF (BTEST(FOLDER_FLAG,14)) THEN
	         FROM = 'ANONYMOUS'
              ELSE
	         FROM = USERNAME		! Username
	      END IF

	      CALL OPEN_BULLFIL			! Prepare to add bulletin

	      CALL READDIR(0,IER1)		! Get NBLOCK
	      IF (IER1.EQ.0) NBLOCK = 0		! If new file, NBLOCK is 0

	      REWIND (UNIT=3)
	      OBLOCK = NBLOCK+1
	      IF (.NOT.BTEST(FOLDER_FLAG,14)) THEN
	         CALL STORE_BULL(LNODE+TRIM(FROM)+6,'From: '//
     &		    LOCAL_NODE(:LNODE)//FROM(:TRIM(FROM)),OBLOCK)
	      END IF
	      IF (LENDES.GT.LEN(DESCRIP)) THEN
	         CALL STORE_BULL(LENDES+6,
     &			'Subj: '//INDESCRIP(:LENDES),OBLOCK)
	      END IF
	      CALL COPY_BULL(3,1,OBLOCK,IER1)	! Add the new bulletin
	      IF (IER1.NE.0) GO TO 930		! Error in creating bulletin
	      LENGTH = OCOUNT - (NBLOCK+1) + 1

	      IF (.NOT.BRDCST.AND.CLI$PRESENT('BROADCAST').AND.
     &		 (.NOT.REMOTE_SET.OR.FOLDER_NUMBER.GT.0)) THEN
		 CALL GET_BROADCAST_MESSAGE(CLI$PRESENT('BELL'))
	      END IF

	      CALL ADD_ENTRY			! Add the new directory entry

	      CALL CLOSE_BULLFIL		! Finished adding bulletin

	      IF (FOLDER_NUMBER.GE.0) THEN
	         DIFF = COMPARE_BTIM(LAST_READ_BTIM(1,FOLDER_NUMBER+1),
     &			       F_NEWEST_BTIM)
	         CALL UPDATE_FOLDER		! Update info in folder file
C
C  If user is adding message, an no new messages, update last read time for
C  folder, so user is not alerted of new message which is owned by user.
C
	         IF (DIFF.GE.0) THEN
	            LAST_READ_BTIM(1,FOLDER_NUMBER+1) = F_NEWEST_BTIM(1)
	            LAST_READ_BTIM(2,FOLDER_NUMBER+1) = F_NEWEST_BTIM(2)
	         END IF
		 IF (BULL_TAG.AND.BTEST(BULL_TAG,1)) THEN
		    CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
		    CALL ADD_TAG(IER1,2)
		 END IF
	      END IF

	      CALL CLOSE_BULLDIR		! Totally finished with add
C
C  Broadcast the bulletin if requested.
C
	      IF (.NOT.BRDCST.AND.CLI$PRESENT('BROADCAST').AND.
     &		 (.NOT.REMOTE_SET.OR.FOLDER_NUMBER.GT.0)) THEN
		 BRDCST = .TRUE.
	         IF (.NOT.CLI$PRESENT('LOCAL')) THEN
	            CALL BROADCAST_ALL_NODES(CLI$PRESENT('ALL'),
     &			CLI$PRESENT('CLUSTER'))
		 END IF
C
C  If the folder is remote, and local node is not the node which BULLCP is
C  on, don't broadcast, as it will be broadcasted by BULLCP.  The remote
C  node will distribute the broadcast to nodes that are running BULLCP,
C  but not if the node that originated the message matches.  However, it
C  has no way of knowing that the originating node is in the same cluster
C  as that of the BULLCP node.
C
		 IF ((REMOTE_SET.AND.LOCAL_NODE(:LNODE-2).EQ.NODENAME)
     &		     .OR.CLI$PRESENT('LOCAL').OR..NOT.REMOTE_SET)
     &	            CALL BROADCAST(
     &			CLI$PRESENT('ALL'),CLI$PRESENT('CLUSTER'))
	      END IF
	   ELSE IF (.NOT.IER) THEN
	      WRITE (6,'('' ERROR: Unable to add message to '',A)')
     &				NODES(I)
	   END IF
           IF (IER.AND.(BTEST(FOLDER_FLAG,10).OR.
     &			BTEST(FOLDER_FLAG,11)).AND.REMOTE_SET.LT.3) THEN
	      IF (NEWS_FEED()) THEN
	         SLIST = INDEX(FOLDER_DESCRIP,'[')
	      ELSE
	         SLIST = INDEX(FOLDER_DESCRIP,'<')
	      END IF
	      IF (SLIST.GT.0) THEN
	         INPUT = FOLDER_DESCRIP(SLIST+1:)
	         IF (NEWS_FEED()) THEN
	            ILEN = INDEX(INPUT,']') - 1
	         ELSE
	            ILEN = INDEX(INPUT,'>') - 1
	         END IF
	         IF (ILEN.EQ.-1) ILEN = TRIM(INPUT)
	         INPUT = INPUT(:ILEN)
                 CALL ADD_PROTOCOL(INPUT,ILEN)
	         CLOSE (UNIT=3,STATUS='SAVE')
		 IF (BTEST(FOLDER_FLAG,10).OR.BTEST(FOLDER_FLAG,15)) THEN
	            CALL RESPOND_MAIL(BULL_PARAMETER(:LEN_P),INPUT,
     &		       INDESCRIP(:LENDES),STATUS)
		 ELSE
	            CALL RESPOND_MAIL(BULL_PARAMETER(:LEN_P),INPUT,
     &	   	       FOLDER(:TRIM(FOLDER))//' folder message: '//
     &		       INDESCRIP(:LENDES),STATUS)
		 END IF
	         IF (BULL_PARAMETER.EQ.'SYS$LOGIN:BULL.SCR') THEN
	            OPEN (UNIT=3,FILE=BULL_PARAMETER(:LEN_P),STATUS='OLD',
     &		       ERR=910,FORM='FORMATTED')
	         ELSE
	            OPEN (UNIT=3,FILE=BULL_PARAMETER(:LEN_P),STATUS='OLD',
     &		       READONLY,SHARED,ERR=910,FORM='FORMATTED')
	         END IF
	      END IF
	   END IF
	END DO

95	CLOSE (UNIT=3)			! Close the input file
	IF (DECNET_PROC) WRITE(5,'(''END'')') ! DECNET operation worked

	LENFRO = 0
	DO WHILE (CLI$GET_VALUE('CC',INLINE,ILEN).NE.%LOC(CLI$_ABSENT))
	   CALL ADD_PROTOCOL(INLINE,ILEN)
	   IF (LENFRO.EQ.0) THEN
	      INPUT = INLINE(:ILEN)//','
	   ELSE
	      INPUT = INPUT(:LENFRO)//INLINE(:ILEN)//','
	   END IF
	   LENFRO = LENFRO + ILEN + 1
	END DO

	IF (LENFRO.GT.1) THEN 
	   LENFRO = LENFRO - 1
	   I = 1		! Must change all " to "" in FROM field
	   DO WHILE (I.LE.LENFRO)
	      IF (INPUT(I:I).EQ.'"') THEN
	         INPUT = INPUT(:I)//'"'//INPUT(I+1:)
	         I = I + 1
		 LENFRO = LENFRO + 1
	      END IF
	      I = I + 1
	   END DO
	   CALL RESPOND_MAIL(BULL_PARAMETER(:LEN_P),INPUT,
     &			     INDESCRIP(:LENDES),STATUS)
	END IF

100	CALL ENABLE_CTRL		! Enable CTRL-Y & -C
	DO I=10,NODE_NUM+9
	   CLOSE (UNIT=I)
	END DO

	IF (NEWS_FEED()) THEN
	   SLIST = INDEX(FOLDER_DESCRIP,'<')
	   FOLDER1_DESCRIP = 
     &		FOLDER_DESCRIP(SLIST+1:INDEX(FOLDER_DESCRIP,'>')-1)
	   CALL NEWS_POST(BULL_PARAMETER(:LEN_P),.FALSE.,IER,
     &		INDESCRIP)
	END IF

200	IF (FOLDER_NUMBER.NE.OLD_FOLDER_NUMBER) THEN
	   FOLDER_NUMBER = OLD_FOLDER_NUMBER
	   FOLDER1 = OLD_FOLDER
	   CALL SELECT_FOLDER(.FALSE.,IER)
	END IF

	CALL LIB$DELETE_FILE('SYS$LOGIN:BULL.SCR;*')

	RETURN

910	WRITE(ERROR_UNIT,1010)
	CLOSE (UNIT=3,ERR=100)
	GO TO 200

920	WRITE(ERROR_UNIT,1020)
	CALL ENABLE_PRIVS
	GO TO 200

930	WRITE (ERROR_UNIT,1025)
	CALL CLOSE_BULLFIL
	CALL CLOSE_BULLDIR
	CLOSE (UNIT=3)
	GO TO 200

940	WRITE (6,1015) NODES(POINT_NODE)
	WRITE (6,1018)
	CLOSE (UNIT=3)
	GO TO 200

950	WRITE (6,1030) LINE_LENGTH
	CLOSE (UNIT=3)
	GO TO 200

1000	FORMAT (' Enter message: End with ctrl-z, cancel with ctrl-c')
1010	FORMAT (' No message was added.')
1015	FORMAT (' ERROR: Unable to reach node ',A)
1018	FORMAT (' Try using /FOLDER instead of /NODE.')
1020	FORMAT (' ERROR: Unable to open specified file.')
1025	FORMAT (' ERROR: Unable to add message to file.')
1030	FORMAT (' ERROR: Line length in file exceeds ',I,' characters.')
1050	FORMAT (' Enter description header.')
1070	FORMAT (' ERROR: SETPRV privileges are needed for system
     & messages.')
1080	FORMAT (' ERROR: SETPRV privileges are needed to broadcast
     & messages.')
1082	FORMAT (' ERROR: SETPRV privileges are needed to shutdown
     & messages.')
1083	FORMAT (' ERROR: Folder has expiration limit.')
1090	FORMAT (' ERROR: Nodename cannot be specified for shutdown
     & if folder is remote.')
2010	FORMAT(A)
2020	FORMAT(1X,A)

	END


	SUBROUTINE SUBTIME(BTIM,DAYS_BEFORE_TODAY,IER)

	IMPLICIT INTEGER (A-Z)

	CHARACTER DAYS_BEFORE_TODAY*(*),TODAY_DATE*24

	INTEGER BTIM(2),TODAY_BTIM(2)

	IER = SYS$BINTIM(DAYS_BEFORE_TODAY,BTIM)
	IF (.NOT.IER) RETURN

	BTIM(1) = -BTIM(1)		! Convert to negative delta time
	BTIM(2) = -BTIM(2)-1

	IER = SYS$ASCTIM(TLEN,TODAY_DATE,,)
	CALL SYS$BINTIM(TODAY_DATE(:TLEN),TODAY_BTIM)

	CALL LIB$SUBX(TODAY_BTIM,BTIM,BTIM)

	RETURN
	END



	SUBROUTINE BROADCAST_ALL_NODES(ALL,CLUSTER)

	IMPLICIT INTEGER (A-Z)

	INCLUDE 'BULLUSER.INC'

	INCLUDE 'BULLFOLDER.INC'

	PARAMETER BRDCST_LIMIT = 82*12 + 2 + 2
	CHARACTER*(BRDCST_LIMIT) BMESSAGE

	COMMON /BROAD_MESSAGE/ BMESSAGE,BLENGTH

	COMMON /SYSTEM_FOLDERS/ SYSTEM_FLAG(FLONG),NODENAME
	CHARACTER NODENAME*8

	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT

	CHARACTER RESPONSE*4

	IF (.NOT.TEST_BULLCP().OR.REMOTE_SET) RETURN

	CALL OPEN_BULLUSER_SHARED

	REMOTE_FOUND = .FALSE.
	TEMP_USER = ':'

	DO WHILE (.NOT.REMOTE_FOUND)
	   DO WHILE (REC_LOCK(IER))		 
	      READ (4,KEYGT=TEMP_USER,IOSTAT=IER)
     &		TEMP_USER,LOGIN_BTIM,READ_BTIM,NEW_FLAG
	   END DO
	   IF (TEMP_USER(:1).NE.':') THEN
	      CALL CLOSE_BULLUSER
	      RETURN
 	   END IF
	   REMOTE_FOUND = TEST2(NEW_FLAG,FOLDER_NUMBER)
	END DO

	CALL CLOSE_BULLUSER

100	OPEN (UNIT=17,STATUS='UNKNOWN',IOSTAT=IER,RECL=256,
     &		FILE=NODENAME(:TRIM(NODENAME))//'::"TASK=BULLETIN1"')

	IF (IER.EQ.0) THEN
	   IER = 0
	   I = 1
	   DO WHILE (IER.EQ.0.AND.I.LT.BLENGTH)
	      WRITE (17,'(4A)',IOSTAT=IER)
     &		15,-1,I,BMESSAGE(I:MIN(BLENGTH,I+127))
	       I = I + 128
	   END DO
	   IF (IER.EQ.0) WRITE (17,'(7A)',IOSTAT=IER)
     &		15,BLENGTH,I,ALL,CLUSTER,FOLDER_NUMBER,FOLDER
	ELSE
	   WRITE (6,'('' BULLCP not responding to request to'',
     &	              '' broadcast to other nodes.'')')
	   CALL GET_INPUT_PROMPT(RESPONSE,LEN,
     &		'Want to try again? (Y/N with Y as default): ')
	   IF (RESPONSE(:1).NE.'n'.AND.RESPONSE(:1).NE.'N') THEN
	      WRITE (6,'('' Trying again...'')')
	      GO TO 100
	   ELSE
	      WRITE (6,'('' Broadcast aborting. '',
     &		         ''Continuing with message addition.'')')
	   END IF
	END IF

	CLOSE (UNIT=17)

	RETURN
	END




	INTEGER FUNCTION ERROR_TRAP

	ERROR_TRAP = 1

	RETURN
	END



	SUBROUTINE REPLY

	IMPLICIT INTEGER (A - Z)

	COMMON /POINT/ BULL_POINT

	INCLUDE 'BULLDIR.INC'

	INCLUDE 'BULLFOLDER.INC'

	COMMON /INDESCRIP/ INDESCRIP
	CHARACTER*(INPUT_LENGTH) INDESCRIP

	IF (BULL_POINT.EQ.0) THEN	! If no bulletin has been read
	   WRITE(6,'('' ERROR: You have not read any message.'')')
	   RETURN			! And return
	END IF

	CALL OPEN_BULLDIR_SHARED

	CALL READDIR(BULL_POINT,IER)	! Get info for specified bulletin

	IF (IER.NE.BULL_POINT+1) THEN	! Was bulletin found?
	   WRITE(6,'('' ERROR: Bulletin was not found.'')')
	   CALL CLOSE_BULLDIR		! If not, then error out
	   RETURN
	END IF

	CALL OPEN_BULLFIL_SHARED

	ILEN = LINE_LENGTH + 1

	CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
	IF (ILEN.GT.0.AND.INPUT(:6).EQ.'From: ') THEN
	   CALL GET_BULL_LINE(BLOCK,LENGTH,INPUT,ILEN)
	END IF
	IF (ILEN.GT.0.AND.INPUT(:6).EQ.'Subj: ') THEN
	   INDESCRIP = INPUT(7:)
	ELSE
	   INDESCRIP = DESCRIP
	END IF

	CALL CLOSE_BULLFIL

	CALL CLOSE_BULLDIR

	WRITE (6,'('' Adding REPLY message with the subject:'')')
	IF (STREQ(INDESCRIP(:3),'RE:')) THEN
	   INDESCRIP = 'Re:'//INDESCRIP(4:)
	ELSE
	   INDESCRIP = 'Re: '//INDESCRIP
	END IF
	WRITE (6,'(1X,A)') INDESCRIP(:TRIM(INDESCRIP))

	CALL ADD

	RETURN
	END




	SUBROUTINE CRELNM(INPUT,OUTPUT)
	
	IMPLICIT INTEGER (A-Z)

	INCLUDE '($PSLDEF)'

	INCLUDE '($LNMDEF)'

	CHARACTER*(*) INPUT,OUTPUT

	CALL INIT_ITMLST
	CALL ADD_2_ITMLST(LEN(OUTPUT),LNM$_STRING,%LOC(OUTPUT))
	CALL END_ITMLST(CRELNM_ITMLST)

	IER = SYS$CRELNM(,'LNM$PROCESS',INPUT,PSL$C_USER,
     &		%VAL(CRELNM_ITMLST))

	RETURN
	END



	SUBROUTINE GETPRIV
C
C  SUBROUTINE GETPRIV
C
C  FUNCTION:
C	To get process privileges.
C  OUTPUTS:
C	PROCPRIV - Returned privileges
C

	IMPLICIT INTEGER (A-Z)

	COMMON /PRIVILEGES/ PROCPRIV(2),NEEDPRIV(2)

	COMMON /REALPROC/ REALPROCPRIV(2)

	INCLUDE '($JPIDEF)'

	CALL INIT_ITMLST	! Initialize item list
	CALL ADD_2_ITMLST(8,JPI$_PROCPRIV,%LOC(PROCPRIV))
	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist

	IER = SYS$GETJPIW(,,,%VAL(GETJPI_ITMLST),,,,) ! Get info

	REALPROCPRIV(1) = PROCPRIV(1)
	REALPROCPRIV(2) = PROCPRIV(2)

	RETURN
	END




	LOGICAL FUNCTION SETPRV_PRIV
	IMPLICIT INTEGER (A-Z)

	COMMON /PRIVILEGES/ PROCPRIV(2),NEEDPRIV(2)
	DATA NEEDPRIV/0,0/

	INCLUDE '($PRVDEF)'

	INCLUDE 'BULLUSER.INC'

	INCLUDE 'BULLFILES.INC'

	IF (NEEDPRIV(1).EQ.0.AND.NEEDPRIV(2).EQ.0) THEN
	   CALL OPEN_BULLUSER_SHARED		! Get BULLUSER.DAT file
	   CALL READ_USER_FILE_HEADER(IER)
	   CALL CLOSE_BULLUSER
	   NEEDPRIV(1) = USERPRIV(1)
	   NEEDPRIV(2) = USERPRIV(2)
	END IF

	IF ((PROCPRIV(1).AND.NEEDPRIV(1)).NE.0.OR.
     &	    (PROCPRIV(2).AND.NEEDPRIV(2)).NE.0) THEN
	   SETPRV_PRIV = .TRUE.
	ELSE
	   SETPRV_PRIV = .FALSE.
	END IF

	RETURN
	END



	LOGICAL FUNCTION OPER_PRIV
	IMPLICIT INTEGER (A-Z)
	COMMON /PRIVILEGES/ PROCPRIV(2),NEEDPRIV(2)
	INCLUDE '($PRVDEF)'
	OPER_PRIV = BTEST(PROCPRIV(1),PRV$V_OPER)
	RETURN
	END


 
	SUBROUTINE GETUSER(USERNAME)
C
C  SUBROUTINE GETUSER
C
C  FUNCTION:
C	To get username of present process.
C  OUTPUTS:
C	USERNAME   -   Username owner of present process.
C

	IMPLICIT INTEGER (A-Z)

	INCLUDE '($PRVDEF)'

	CHARACTER*(*) USERNAME		! Limit is 12 characters

	INCLUDE '($JPIDEF)'

	CALL INIT_ITMLST	! Initialize item list
	CALL ADD_2_ITMLST(LEN(USERNAME),JPI$_USERNAME,%LOC(USERNAME))
	CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist

	IER = SYS$GETJPIW(,,,%VAL(GETJPI_ITMLST),,,,) ! Get info

	RETURN
	END




	LOGICAL FUNCTION CAPTIVE(FLAG)

	IMPLICIT INTEGER (A - Z)

	INCLUDE '($UAIDEF)'

	INCLUDE 'BULLUSER.INC'

	DATA READ_UAI/.FALSE./

	COMMON /BULL_CUSTOM/ BULL_CUSTOM

	IF (BTEST(BULL_CUSTOM,FLAG)) THEN 
	   CAPTIVE = .FALSE.
	   RETURN
	END IF

	TYPE = 1

	IF (.NOT.READ_UAI) THEN
	   CALL INIT_ITMLST
	   CALL ADD_2_ITMLST(4,UAI$_FLAGS,%LOC(FLAGS))
	   CALL END_ITMLST(GETUAI_ITMLST)
           IER = SYS$GETUAI(,,USERNAME,%VAL(GETUAI_ITMLST),,,)
	   READ_UAI = .TRUE.
	END IF

	CAPTIVE = ((FLAGS.AND.(UAI$M_CAPTIVE.OR.UAI$M_RESTRICTED)).NE.0
     &	  .AND.1).OR.ISHFT(((FLAGS.AND.UAI$M_NOMAIL).NE.0).AND.1,1)

	RETURN
	END




        SUBROUTINE SPAWN_PROCESS

	IMPLICIT INTEGER (A - Z)

	COMMON /KEYPAD/ KEYPAD_MODE

	CHARACTER*256 COMMAND

	IF (CAPTIVE(-1)) THEN
	   WRITE (6,'('' ERROR: SPAWN not allowed from CAPTIVE account.'')')
	   RETURN
	END IF

	CALL DISABLE_PRIVS

	SAVE_KEYPAD_MODE = KEYPAD_MODE
	IF (KEYPAD_MODE.EQ.0) CALL SET_KEYPAD

	IF (CLI$PRESENT('COMMAND')) THEN
	   CALL CLI$GET_VALUE('COMMAND',COMMAND,CLEN)
	   COMMAND = '$'//COMMAND(:CLEN)
	   CALL LIB$SPAWN(COMMAND(:CLEN+1))
	ELSE
           CALL LIB$SPAWN()
	END IF

	IF (SAVE_KEYPAD_MODE.EQ.0) CALL SET_NOKEYPAD

	CALL ENABLE_PRIVS

	RETURN
        END


        SUBROUTINE ATTACH

	IMPLICIT INTEGER (A - Z)

	COMMON /KEYPAD/ KEYPAD_MODE

	COMMON /TERM_CHAN/ TERM_CHAN

	INCLUDE '($JPIDEF)'

	CHARACTER*16 PROCESS

	IF (CLI$PRESENT('PROCESS')) THEN
	   CALL CLI$GET_VALUE('PROCESS',PROCESS,PLEN)

	   CALL INIT_ITMLST	! Initialize item list
	   CALL ADD_2_ITMLST(4,JPI$_PID,%LOC(PROCESS_ID))
	   CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist

	   IER = SYS$GETJPIW(,,PROCESS(:PLEN),%VAL(GETJPI_ITMLST),,,,)
	ELSE
	   CALL INIT_ITMLST	! Initialize item list
	   CALL ADD_2_ITMLST(4,JPI$_OWNER,%LOC(PROCESS_ID))
	   CALL END_ITMLST(GETJPI_ITMLST)	! Get address of itemlist

	   IER = SYS$GETJPIW(,,,%VAL(GETJPI_ITMLST),,,,)
	END IF

	IER = SYS$CANCEL(%VAL(TERM_CHAN))

	SAVE_KEYPAD_MODE = KEYPAD_MODE
	IF (KEYPAD_MODE.EQ.0) CALL SET_KEYPAD

	IF (IER) IER = LIB$ATTACH(PROCESS_ID)
	IF (.NOT.IER) CALL SYS_GETMSG(IER)

	IF (SAVE_KEYPAD_MODE.EQ.0) CALL SET_NOKEYPAD

	RETURN
        END





	SUBROUTINE GET_BROADCAST_MESSAGE(RING_BELL)

	IMPLICIT INTEGER (A-Z)

	INCLUDE 'BULLDIR.INC'

	INCLUDE '($BRKDEF)'

	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT

C
C  The largest message that can be broadcasted is dependent on system
C  and user quotas.  The following limit is 12 lines of ( 80 characters +
C  CR/LF ) + 2 bells.  This should be more than enough room, as broadcasts
C  shouldn't be too large anyway.
C

	PARAMETER CR=CHAR(13),LF=CHAR(10),BELL=CHAR(7)

	PARAMETER BRDCST_LIMIT = 82*12 + 2 + 2
	CHARACTER*(BRDCST_LIMIT) BROAD

	COMMON /BROAD_MESSAGE/ BROAD,BLENGTH

	IF (RING_BELL) THEN	! Include BELL in message?
	   BROAD(:36) =			! Say who the bulletin is from
     &		BELL//BELL//CR//LF//LF//'NEW BULLETIN FROM: '//FROM
	   BLENGTH = 37			! Start adding next line here
	ELSE
	   BROAD(:34) =			! Say who the bulletin is from
     &		CR//LF//LF//'NEW BULLETIN FROM: '//FROM
	   BLENGTH = 35			! Start adding next line here
	END IF

	IF (REMOTE_SET) REWIND (UNIT=3)

	END = 0
	ILEN = LINE_LENGTH + 1
	I = 0
	DO WHILE (ILEN.GT.0)		! Copy bulletin into file
	   IF (REMOTE_SET) THEN
	      READ (3,'(Q,A)',IOSTAT=IER) ILEN,INPUT
	      IF (IER.NE.0) RETURN
	   ELSE
	      CALL GET_BULL_LINE(NBLOCK+1,LENGTH,INPUT,ILEN)
	   END IF
	   IF (ILEN.GT.0) I = I + 1
	   IF (ILEN.GT.0.AND.(I.GT.2.OR.(INPUT(:6).NE.'From: '.AND.
     &			INPUT(:6).NE.'Subj: '))) THEN
	      END = BLENGTH + ILEN - 1 + 2	! Check how long string will be
	      IF (END.GT.BRDCST_LIMIT) RETURN	! String too long?
	      BROAD(BLENGTH:END) = CR//LF//INPUT(:ILEN)! Else add new input
	      BLENGTH = END + 1			! Reset pointer
	   END IF
	END DO

	RETURN

	ENTRY BROADCAST(ALL,CLUSTER)

	CALL SYS$SETRWM(%VAL(1))		! Don't wait if can't broadcast

	IF (ALL) THEN				! Should we broadcast to ALL?
	   IF (CLUSTER) THEN
	      CALL SYS$BRKTHRU(,BROAD(:BLENGTH-1)//CR,,
     &		%VAL(BRK$C_ALLTERMS),,,%VAL(BRK$M_CLUSTER),,%VAL(5),,)
	   ELSE
	      CALL SYS$BRKTHRU(,BROAD(:BLENGTH-1)//CR,,
     &		%VAL(BRK$C_ALLTERMS),,,,,%VAL(5),,)
	   END IF
	ELSE	 				! Else just broadcast to users.
	   IF (CLUSTER) THEN
	      CALL SYS$BRKTHRU(,BROAD(:BLENGTH-1)//CR,,
     &		%VAL(BRK$C_ALLUSERS),,,%VAL(BRK$M_CLUSTER),,%VAL(5),,)
	   ELSE
	       CALL SYS$BRKTHRU(,BROAD(:BLENGTH-1)//CR,,
     &		%VAL(BRK$C_ALLUSERS),,,,,%VAL(5),,)
	   END IF
	END IF

	CALL SYS$SETRWM(%VAL(0))

	RETURN
	END


	SUBROUTINE GET_FOLDER_INFO(IER)
C
C  SUBROUTINE GET_FOLDER_INFO
C
C  FUNCTION: Obtains & verifies folder names from command line.
C

	IMPLICIT INTEGER (A-Z)

	INCLUDE 'BULLFOLDER.INC'

	EXTERNAL CLI$_ABSENT

	COMMON /NODE_INFO/ NODES,LOCAL_NODE_FOUND,NODE_NUM,
     &				NODE_ERROR,POINT_NODE
	CHARACTER*32 NODES(10)
	LOGICAL LOCAL_NODE_FOUND,NODE_ERROR

	COMMON /ACCESS/ READ_ONLY
	LOGICAL READ_ONLY

	CHARACTER NODE_TEMP*256

	NODE_NUM = 0				! Initialize number of nodes
	DO WHILE (CLI$GET_VALUE('SELECT_FOLDER',NODE_TEMP)
     &	    .NE.%LOC(CLI$_ABSENT))		! Get the specified nodes
	   IER = SYS_TRNLNM(NODE_TEMP,NODE_TEMP)
	   CALL STR$UPCASE(NODE_TEMP,NODE_TEMP)
	   DO WHILE (TRIM(NODE_TEMP).GT.0)
	      NODE_NUM = NODE_NUM + 1
	      COMMA = INDEX(NODE_TEMP,',')
	      IF (COMMA.GT.0) THEN
		 NODES(NODE_NUM) = NODE_TEMP(:COMMA-1)
		 NODE_TEMP = NODE_TEMP(COMMA+1:)
	      ELSE
		 NODES(NODE_NUM) = NODE_TEMP
		 NODE_TEMP = ' '
	      END IF
	      NLEN = TRIM(NODES(NODE_NUM))
	      IF (NODES(NODE_NUM)(NLEN-1:NLEN).EQ.'::') THEN
		 NODES(NODE_NUM) = NODES(NODE_NUM)(:NLEN)//'GENERAL'
	      END IF
	      FOLDER_NUMBER = -1
	      FOLDER1 = NODES(NODE_NUM)
	      CALL SELECT_FOLDER(.FALSE.,IER)
	      IF (.NOT.IER) THEN
		 WRITE (6,'('' Unable to access folder '',A)')
     &				NODES(NODE_NUM)
		 RETURN
	      ELSE IF (READ_ONLY) THEN
		 WRITE (6,'('' ERROR: No write access for folder '',A)')
     &				NODES(NODE_NUM)
		 IER = 0
		 RETURN
	      END IF
	   END DO
	END DO

	IER = 1

	RETURN
	END
	



	SUBROUTINE INIT_BULLETIN(NOX)

	IMPLICIT INTEGER (A - Z)

	INCLUDE 'BULLFILES.INC'

	INCLUDE 'BULLDIR.INC'

	INCLUDE 'BULLFOLDER.INC'

	INCLUDE 'BULLUSER.INC'

	COMMON /BULLPAR/ BULL_PARAMETER,LEN_P
	CHARACTER*64 BULL_PARAMETER

	COMMON /POINT/ BULL_POINT

	COMMON /READIT/ READIT

	COMMON /PAGE/ PAGE_LENGTH,PAGE_WIDTH,PAGING
	LOGICAL PAGING /.FALSE./
	DATA PAGE_LENGTH/24/,PAGE_WIDTH/80/

	COMMON /CTRLY/ CTRLY

	COMMON /PROMPT/ COMMAND_PROMPT
	CHARACTER*40 COMMAND_PROMPT

	COMMON /DECNET/ DECNET_PROC,ERROR_UNIT
	LOGICAL DECNET_PROC

	EXTERNAL ERROR_TRAP
	EXTERNAL BULLETIN_MAINCOMMANDS,ENABLE_CTRL_EXIT
	EXTERNAL CLI$_ABSENT,CLI$_NOCOMD,CLI$_NEGATED

	PARAMETER PCB$M_BATCH = '4000'X
	PARAMETER PCB$M_NETWRK = '200000'X
	PARAMETER LIB$M_CLI_CTRLY = '2000000'X

	COMMON /COMMAND_LINE/ INCMD
	CHARACTER*256 INCMD

	COMMON /EDIT/ EDIT_DEFAULT
	DATA EDIT_DEFAULT/.FALSE./

	COMMON /COMMAND_SWITCHES/ LOGIN_SWITCH,SYSTEM_SWITCH
	COMMON /COMMAND_SWITCHES/ SYSTEM_LOGIN_BTIM(2)
	COMMON /COMMAND_SWITCHES/ REVERSE_SWITCH,SEPARATE
	CHARACTER*4 SEPARATE

	COMMON /DEF_PROT/ ORIGINAL_DEF_PROT

	COMMON /PROMPT_PROMPT/ PROMPT,LPROMPT
	CHARACTER*44 PROMPT

	COMMON /BULL_CUSTOM/ BULL_CUSTOM

	COMMON /SAVE_FOLDERS/ SAVE_FOLDER_Q1,SAVE_FOLDER_NUM

	COMMON /COUNT/
     &     DIR_COUNT,	   ! # directory entry to continue bulletin read from
     &     READ_COUNT,	   ! # block that bulletin READ is to continue from
     &     FOLDER_COUNT,   ! # folder entry to continue SHOW/ALL folder from
     &	   INDEX_COUNT
	DATA DIR_COUNT/0/,READ_COUNT/0/,FOLDER_COUNT/0/,INDEX_COUNT/0/

	COMMON /DCL/ DCL_CMD,DCL_COMMAND
	CHARACTER DCL_CMD*132

	IER = SYS_TRNLNM_SYSTEM('BULL_CUSTOM',BULL_PARAMETER)	
	IF (IER) IER = OTS$CVT_TZ_L(BULL_PARAMETER(:TRIM(BULL_PARAMETER))
     &		,BULL_CUSTOM,,,%VAL(1)) 

	CALL LIB$GET_FOREIGN(INCMD)
	DCL_COMMAND = INDEX(INCMD,' "').GT.0.OR.INCMD(:1).EQ.'"'

	CALL LIB$ESTABLISH(ERROR_TRAP)
        IF (.NOT.CLI$GET_VALUE('PROMPT',COMMAND_PROMPT,ILEN)) THEN
           CALL LIB$REVERT
           CALL CLI$GET_VALUE('$LINE',COMMAND_PROMPT,ILEN)
	   INCMD = 'BULLETIN '//INCMD
           CALL CLI$DCL_PARSE(INCMD,BULLETIN_MAINCOMMANDS)
        ELSE
           CALL LIB$REVERT
        END IF

	IF (DCL_COMMAND) THEN
	   IER = CLI$GET_VALUE('SELECT_FOLDER',DCL_CMD,LENP)
	   IF (LENP.GT.0) THEN
	      IF (DCL_CMD(LENP:LENP).EQ.'"') DCL_CMD = DCL_CMD(:LENP-1)
	      IF (DCL_CMD(:1).EQ.'"') DCL_CMD = DCL_CMD(2:)
	   END IF
	END IF

	READIT = 0

	LOGIN_SWITCH = CLI$PRESENT('LOGIN')
	SYSTEM_SWITCH = CLI$PRESENT('SYSTEM')
	REVERSE_SWITCH = CLI$PRESENT('REVERSE')

	IER = LIB$SYS_TRNLOG('BULL_DISABLE',LEN_P,BULL_PARAMETER)
	IF (IER.EQ.1.AND.LEN_P.GT.0.AND..NOT.CLI$PRESENT('STOP')
     &	    .AND.BULL_PARAMETER(:LEN_P).NE.'ENABLE') THEN
	   IF (.NOT.LOGIN_SWITCH) THEN
	      WRITE (6,'('' BULLETIN temporarily disabled. Try later.'')')
	   END IF
	   CALL EXIT
	END IF

	CALL SYS$SETDFPROT(,ORIGINAL_DEF_PROT)
		! Save original default protection in case it gets changed

	CALL DCLEXH(%LOC(ENABLE_CTRL_EXIT))		! Declare exit handler

C
C  Check to see if CONTROL Y disabled.  If so, then never disable CONTROL Y.
C  Disabling and enabling CONTROL Y is done so that a person can not break
C  while one of the data files is opened, as that would not allow anyone
C  else to modify the files.  However, if CONTROL Y is already disabled,
C  this is not necessary, and should not be done!
C

	CALL LIB$DISABLE_CTRL(LIB$M_CLI_CTRLY,CTRLY)	! Disable CTRL-Y & -C
	CTRLY = CTRLY .AND. LIB$M_CLI_CTRLY
	CALL GETPRIV				! Check privileges
	IF (NOX) CALL CHECK_PRIV_IO(ERR)			! Check privileges on output I/O
	CALL CHECK_DIR_ACCESS()			! Check access to directories
	CALL LIB$ESTABLISH(ERROR_TRAP)
        IF (CLI$GET_VALUE('LIBRARY',BULL_PARAMETER,LEN_P)) THEN
	   FOLDER_DIRECTORY = BULL_PARAMETER(:LEN_P)
	   CALL CHECK_DIR(BULL_PARAMETER,.FALSE.)
	   FOLDER_DIRECTORY = BULL_PARAMETER
	   CALL ADD_DIRECTORIES
        END IF
        CALL LIB$REVERT
	CALL LIB$ENABLE_CTRL(CTRLY,)		! Renable CTRLY-Y & -C

	IF (ERR.EQ.1) CALL EXIT			! I/O privilege error, so exit

	CALL GETUSER(USERNAME)		! Get the process's username
	IF (.NOT.LOGIN_SWITCH) CALL CHECK_BULLETIN_PRIV(USERNAME)
					! Check if has bulletin privileges

	I = 1				! Strip off folder name if specified
	DO WHILE (I.LE.ILEN)
	   IF (COMMAND_PROMPT(I:I).EQ.' ') THEN
	      COMMAND_PROMPT = COMMAND_PROMPT(:I-1)
	      I = ILEN + 1
	   ELSE IF (COMMAND_PROMPT(I:I).EQ.'/') THEN
	      COMMAND_PROMPT = COMMAND_PROMPT(:I-1)
	      I = ILEN + 1
	   ELSE
	      I = I + 1
	   END IF
	END DO
	ILEN = 1			! Get executable name to use as prompt
	DO WHILE (ILEN.GT.0)
	   ILEN = MAX(INDEX(COMMAND_PROMPT,':'),INDEX(COMMAND_PROMPT,']'))
	   IF (ILEN.GT.0) THEN
	      COMMAND_PROMPT = COMMAND_PROMPT(ILEN+1:)
	   ELSE
	      DO I=TRIM(COMMAND_PROMPT),1,-1
		 IF (COMMAND_PROMPT(I:I).LT.'A'.OR.
     &			COMMAND_PROMPT(I:I).GT.'Z') THEN
		    COMMAND_PROMPT = COMMAND_PROMPT(:I-1)
		 END IF
	      END DO
	   END IF
	END DO
	COMMAND_PROMPT = COMMAND_PROMPT(:TRIM(COMMAND_PROMPT))//'> '
	IF (COMMAND_PROMPT.EQ.'RUN> '.OR.COMMAND_PROMPT.EQ.'RU> '.OR.
     &	    COMMAND_PROMPT.EQ.'R> ') COMMAND_PROMPT = 'BULLETIN> '

	CALL INIT_COMPRESS

	FOLDER_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))//FOLDER

	CALL CLI$GET_VALUE('SEPARATE',SEPARATE)

	IF (CLI$PRESENT('EDIT')) EDIT_DEFAULT = .TRUE.	! /EDIT switch test

	CALL FIND_BULLCP			! See if BULLCP is running

	IF (CLI$PRESENT('CLEANUP')) THEN	! Test for /CLEANUP switch
	   CALL CLI$GET_VALUE('CLEANUP',BULL_PARAMETER,LEN_P) ! Get folder #
	   READ (BULL_PARAMETER,'(I<LEN_P>)') FOLDER_NUMBER
	   CALL SELECT_FOLDER(.FALSE.,IER)	! Select folder
	   CALL CLEANUP_BULLFILE		! Cleanup empty blocks
	   CALL EXIT				! all done with cleanup
	ELSE IF (CLI$PRESENT('BBOARD')) THEN	! Test for /BBOARD switch
	   CALL BBOARD				! look for BBOARD mail
	   CALL EXIT				! all done with BBOARD
	ELSE IF (CLI$PRESENT('STARTUP').OR.	! BULLCP process control
     &	         CLI$PRESENT('STOP')) THEN
	   CALL CREATE_BULLCP
	ELSE IF (CLI$PRESENT('BULLCP')) THEN	! This is BULLCP, so start
	   IF (.NOT.CLI$GET_VALUE('SELECT_FOLDER',
     &				BULL_PARAMETER,LENP)) THEN
	      CALL RUN_BULLCP			! doing what BULLCP does!
	   ELSE IF (BULL_PARAMETER(:LENP).EQ.'NEWS') THEN
	      CALL NEWS2BULL(.FALSE.)
	   ELSE IF (BULL_PARAMETER(:LENP).EQ.'NEWS1') THEN
	      CALL NEWS2BULL(.TRUE.)
	   ELSE IF (BULL_PARAMETER(:LENP).EQ.'SMTP') THEN
	      CALL SEND_MAIL
	   END IF
	END IF

	CALL GETSTS(STS)			! Get process status word

	IF (SYSTEM_SWITCH.OR.LOGIN_SWITCH) THEN	! If BULLETIN/LOGIN or /SYSTEM
	   IF ((STS.AND.PCB$M_BATCH).GT.0) CALL EXIT	! If BATCH, exit
	   IF (NOX) CALL CRELNM('SYS$INPUT','TT')	! Input from terminal
	END IF

	IF ((STS.AND.PCB$M_NETWRK).EQ.0) THEN
	   DECNET_PROC = .FALSE.
	   ERROR_UNIT = 6

	   IF (NOX) CALL ASSIGN_TERMINAL		! Assign terminal

           CALL LIB$ESTABLISH(ERROR_TRAP)       ! Do again due to possible
           IF (.NOT.CLI$PRESENT('PROMPT')) THEN ! KEYPAD init file.
              CALL LIB$REVERT
              CALL CLI$DCL_PARSE(INCMD,BULLETIN_MAINCOMMANDS)
           ELSE
              CALL LIB$REVERT
           END IF

	   IF (.NOT.LOGIN_SWITCH) THEN
	      INCMD = 'SELECT'	! Causes nearest folder name to be selected
	      CALL SELECT_FOLDER(.FALSE.,IER)	! Select GENERAL folder
	      IF (.NOT.IER) RETURN			! If can't access, exit

	      IF (.NOT.TEST_BULLCP()) CALL DELETE_EXPIRED
						! Delete expired messages
	   END IF

C
C  Get user info stored in SYS$LOGIN.  Currently, this simply stores
C  the time of the latest message read for each folder.
C

	   CALL OPEN_USERINFO

	   CALL OPEN_OLD_TAG

	   IF (.NOT.NOX) THEN
	      CALL NEW_MESSAGE_NOTIFICATION
	      RETURN
	   END IF

C
C  Get page size for the terminal.
C

	   CALL GETPAGSIZ(PAGE_LENGTH,PAGE_WIDTH)

	   IER = CLI$GET_VALUE('WIDTH',BULL_PARAMETER,LEN_P)
	   IF (IER.NE.%LOC(CLI$_ABSENT)) THEN
	      DECODE(LEN_P,'(I<LEN_P>)',BULL_PARAMETER) PAGE_WIDTH
	   END IF

	   IF (CLI$PRESENT('PAGE')) PAGING = .TRUE.
	   IF ((STS.AND.PCB$M_BATCH).GT.0) THEN
	      PAGING = .FALSE.
	      PAGE_WIDTH = 80
	   END IF

	   IF (SYSTEM_SWITCH) THEN
	      IER = CLI$GET_VALUE('SYSTEM',BULL_PARAMETER,LEN_P)
	      IF (IER.NE.%LOC(CLI$_ABSENT)) THEN	! Days specified?
	         CALL SUBTIME(SYSTEM_LOGIN_BTIM,BULL_PARAMETER(:LEN_P),IER)
		 IF (.NOT.IER) THEN
		    WRITE (6,'('' ERROR: Invalid parameter in /SYSTEM.'')')
		    CALL EXIT
		 END IF
	      END IF
	      IF (.NOT.LOGIN_SWITCH) THEN
	         CALL MODIFY_SYSTEM_LIST(0)
                 CALL READ_IN_FOLDERS
		 FOLDER_Q = SAVE_FOLDER_Q1
		 DO I = 1,SAVE_FOLDER_NUM
	   	    CALL READ_QUEUE(%VAL(FOLDER_Q),FOLDER_Q,FOLDER_COM)
	            IF (TEST2(SYSTEM_FLAG,FOLDER_NUMBER)) THEN
		       CALL SHOW_SYSTEM
		    END IF
	         END DO
	      END IF
	   END IF

C
C  If /LOGIN, display SYSTEM bulletins and subject of non-SYSTEM bulletins.
C

	   IF (LOGIN_SWITCH.OR.SYSTEM_SWITCH) THEN	! Is /LOGIN present?
	      CALL LOGIN			! Display SYSTEM bulletins
	      IF (READIT.EQ.0) CALL EXIT	! If no READNEWs not set, exit
	   END IF

C
C  If new bulletins have been added since the last time bulletins have been
C  read, position bulletin pointer so that next bulletin read is the first new
C  bulletin, and alert user.  If READNEW set and no new bulletins, just exit.
C

	   IF (.NOT.DCL_COMMAND) CALL NEW_MESSAGE_NOTIFICATION
	ELSE
	   IF (TEST_BULLCP()) CALL EXIT
	   DECNET_PROC = .TRUE.
	   ERROR_UNIT = 5
	END IF

	RETURN
	END
