diff --git a/NOTES.md b/NOTES.md
index 4ef9374b1949fecde9c9b0f8ff1aa4d8c061a6c2..2f659b47aa42988161dd84a33f85e094d2988096 100644
--- a/NOTES.md
+++ b/NOTES.md
@@ -19,6 +19,8 @@ Look up how to run migrations on the db from embedded files.
 Figure out readline completion.  Case sensitive - issue?  Building from
 repl.commands?
 
+sqlite trigger tracing: `.trace stdout --row --profile --stmt --expanded --plain --close`
+
 ## Things to do
 
   * Implement a better dclish parser.
diff --git a/accounts/accounts.go b/accounts/accounts.go
index e69a617b817dfa6a7a501f12884cea1fa46b47d0..186a1c9f08947cb6dd81c809edac64c1bc8205e0 100644
--- a/accounts/accounts.go
+++ b/accounts/accounts.go
@@ -2,15 +2,11 @@
 package accounts
 
 import (
-	"database/sql"
 	"errors"
 	"fmt"
-	"os"
-	"path"
 	"strings"
 
 	"git.lyda.ie/kevin/bulletin/folders"
-	"github.com/adrg/xdg"
 	_ "modernc.org/sqlite" // Loads sqlite driver.
 )
 
@@ -19,7 +15,6 @@ import (
 type UserData struct {
 	Account        string
 	FullName       string
-	pref           *sql.DB
 	Folders        *folders.Store
 	CurrentFolder  string
 	CurrentMessage int
@@ -49,18 +44,7 @@ func Open(acc string) error {
 		Account: acc,
 	}
 
-	prefdir := path.Join(xdg.ConfigHome, "BULLETIN")
-	err = os.MkdirAll(prefdir, 0700)
-	if err != nil {
-		return errors.New("account preference directory problem")
-	}
-	User.pref, err = sql.Open("sqlite", path.Join(prefdir, fmt.Sprintf("%s.%s", acc, ".db")))
-	if err != nil {
-		return errors.New("account preference database problem")
-	}
-	// TODO: run prefs migration - move this to a storage module.
-
-	User.Folders, err = folders.Open()
+	User.Folders, err = folders.Open(acc)
 	if err != nil {
 		return err
 	}
@@ -70,7 +54,6 @@ func Open(acc string) error {
 
 // Close closes the resources open for the account.
 func (u *UserData) Close() {
-	u.pref.Close()
 	u.Folders.Close()
 }
 
diff --git a/decus/vax91b/bulletin/bulletin6.for b/decus/vax91b/bulletin/bulletin6.for
index 7dc073d2b387b5cfc00ef4b9e3b788fcd5d421c0..55abcadcb941c99332f2c11194a742e6f4338023 100644
--- a/decus/vax91b/bulletin/bulletin6.for
+++ b/decus/vax91b/bulletin/bulletin6.for
@@ -18,122 +18,122 @@ C
 C  FUNCTION: To close out the bulletin files and enable CTRL-C & -Y
 C
 	DATA LUN /0/
- 
+
 	ENTRY CLOSE_BULLINF
 	LUN = LUN + 1			! Unit = 9
- 
+
 	ENTRY CLOSE_SYSUAF
 	LUN = LUN + 1			! Unit = 8
- 
+
 	ENTRY CLOSE_BULLNEWS
 	ENTRY CLOSE_BULLFOLDER
 	LUN = LUN + 3			! Unit = 7
- 
+
 	ENTRY CLOSE_BULLUSER
 	LUN = LUN + 2			! Unit = 4
- 
+
 	ENTRY CLOSE_BULLDIR
 	LUN = LUN + 1			! Unit = 2
- 
+
 	ENTRY CLOSE_BULLFIL
 	LUN = LUN + 1			! Unit = 1
- 
+
 	CALL ENABLE_CTRL
- 
+
 	CLOSE (UNIT=LUN)
- 
+
 	LUN = 0
- 
+
 	RETURN
 	END
- 
- 
+
+
 	SUBROUTINE CLOSE_FILE_DELETE
- 
+
 	IMPLICIT INTEGER (A-Z)
- 
+
 	DATA LUN /0/
- 
+
 	ENTRY CLOSE_BULLDIR_DELETE
 	LUN = LUN + 1			! Unit = 2
- 
+
 	ENTRY CLOSE_BULLFIL_DELETE
 	LUN = LUN + 1			! Unit = 1
- 
+
 	CALL ENABLE_CTRL
- 
+
 	CLOSE (UNIT=LUN,STATUS='DELETE')
- 
+
 	LUN = 0
- 
+
 	RETURN
 	END
- 
- 
+
+
 	SUBROUTINE OPEN_FILE(UNIT)
- 
+
 	IMPLICIT INTEGER (A-Z)
- 
+
 	INCLUDE 'BULLFILES.INC'
- 
+
 	INCLUDE 'BULLFOLDER.INC'
- 
+
 	INCLUDE 'BULLUSER.INC'
- 
+
 	INCLUDE 'BULLDIR.INC'
- 
+
 	INCLUDE '($FORIOSDEF)'
- 
+
 	INCLUDE '($PRVDEF)'
- 
+
 	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
- 
+
 	COMMON /DIR_POSITION/ DIR_NUM
- 
+
         COMMON /NEWS_OPEN/ NEWS_OPEN
- 
+
 	DATA LUN /0/
- 
+
 	LUN = UNIT - 14			! 14 gets added to LUN
- 
+
 	ENTRY OPEN_BULLNEWS
 	LUN = LUN + 5			! Unit = 14
- 
+
 	ENTRY OPEN_BULLINF
 	LUN = LUN + 1			! Unit = 9
- 
+
 	ENTRY OPEN_SYSUAF
 	LUN = LUN + 1			! Unit = 8
- 
+
 	ENTRY OPEN_BULLFOLDER
 	LUN = LUN + 3			! Unit = 7
- 
+
 	ENTRY OPEN_BULLUSER
 	LUN = LUN + 2			! Unit = 4
- 
+
 	ENTRY OPEN_BULLDIR
 	LUN = LUN + 1			! Unit = 2
- 
+
 	ENTRY OPEN_BULLFIL
 	LUN = LUN + 1			! Unit = 1
- 
+
 	IER = 0
- 
+
 	NTRIES = 0
- 
+
 	CALL SET_PROTECTION
- 
+
 	CALL DISABLE_CTRL		! No breaks while file is open
- 
+
 	IF (LUN.EQ.2.AND..NOT.REMOTE_SET) THEN
 	   DO WHILE (FILE_LOCK(IER,IER1))
- 
+
 	    OPEN (UNIT=2,FILE=FOLDER_FILE(1:TRIM(FOLDER_FILE))
      &	      //'.BULLDIR',STATUS='OLD',FORM='UNFORMATTED',
      &	      RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
      &	      ORGANIZATION='INDEXED',IOSTAT=IER,
      &	      KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
- 
+
 	    IF (IER.EQ.FOR$IOS_FILNOTFOU) THEN
 	       OPEN (UNIT=2,FILE=FOLDER_FILE(1:TRIM(FOLDER_FILE))
      &	        //'.BULLDIR',STATUS='NEW',FORM='UNFORMATTED',
@@ -158,7 +158,7 @@ C
 	   END DO
 	   DIR_NUM = -1
 	END IF
- 
+
 	IF (LUN.EQ.1.AND..NOT.REMOTE_SET) THEN
 	   DO WHILE (FILE_LOCK(IER,IER1))
 	    OPEN (UNIT=1,FILE=FOLDER_FILE(1:TRIM(FOLDER_FILE))
@@ -174,7 +174,7 @@ C
 	    IF (NTRIES.GT.30) CALL TIMER_ERR(LUN)
 	   END DO
 	END IF
- 
+
 	IF (LUN.EQ.4) THEN
 	   DO WHILE (FILE_LOCK(IER,IER1))
 	    OPEN (UNIT=4,FILE=BULLUSER_FILE,STATUS='OLD',
@@ -200,7 +200,7 @@ C
 	    IF (NTRIES.GT.30) CALL TIMER_ERR(LUN)
 	   END DO
 	END IF
- 
+
 	IF (LUN.EQ.7) THEN
 	   DO WHILE (FILE_LOCK(IER,IER1))
 	    OPEN (UNIT=7,FILE=BULLFOLDER_FILE,STATUS='OLD',
@@ -232,7 +232,7 @@ C
 	   END DO
 	   IF (IER.EQ.0) NEWS_OPEN = .FALSE.
 	END IF
- 
+
 	IF (LUN.EQ.14) THEN
 	   DO WHILE (FILE_LOCK(IER,IER1))
 	    OPEN (UNIT=7,FILE=BULLNEWS_FILE,STATUS='OLD',
@@ -253,7 +253,7 @@ C
 	   END DO
 	   IF (IER.EQ.0) NEWS_OPEN = .TRUE.
 	END IF
- 
+
 	IF (LUN.EQ.9) THEN
 	   DO WHILE (FILE_LOCK(IER,IER1))
 	    OPEN (UNIT=9,FILE=BULLINF_FILE,STATUS='UNKNOWN',
@@ -269,7 +269,7 @@ C
 	     IF (NTRIES.GT.30) CALL TIMER_ERR(LUN)
 	   END DO
 	END IF
- 
+
 	IF (IER.NE.0) THEN
 	   WRITE (6,'(
      &	    '' Cannot open file in OPEN_FILE, unit = '',I)') LUN
@@ -281,108 +281,108 @@ C
 	   END IF
 	   CALL ENABLE_CTRL_EXIT	! Enable CTRL-Y & -C & EXIT
 	END IF
- 
+
 	LUN = 0
- 
+
 	CALL RESET_PROTECTION
- 
+
 	RETURN
 	END
- 
- 
- 
+
+
+
 	SUBROUTINE TIMER_ERR(UNIT)
- 
+
 	IMPLICIT INTEGER (A-Z)
- 
+
 	CHARACTER*14 NAMES(6)
 	DATA NAMES/'directory','message','BULLUSER.DAT','BULLFOLDER.DAT',
      &			'BULLINF.DAT','BULLNEWS.DAT'/
 	INTEGER NAME(14)
 	DATA NAME/1,2,0,3,0,0,4,0,5,0,0,0,0,6/
- 
+
 	IF (TEST_BULLCP().NE.2) THEN	! If BULLCP process, don't log error
 	   WRITE(6,'('' ERROR: Unable to open '',A,
      &	    	     '' file after 30 secs.'')')
      &			NAMES(NAME(UNIT))(:TRIM(NAMES(NAME(UNIT))))
 	   WRITE (6,'('' Please try again later.'')')
 	END IF
- 
+
 	CALL ENABLE_CTRL_EXIT		! No breaks while file is open
 	END
- 
- 
- 
+
+
+
 	SUBROUTINE OPEN_FILE_SHARED
- 
+
 	IMPLICIT INTEGER (A-Z)
- 
+
 	INCLUDE '($FORIOSDEF)'
- 
+
 	INCLUDE 'BULLFILES.INC'
- 
+
 	INCLUDE 'BULLFOLDER.INC'
- 
+
 	INCLUDE 'BULLUSER.INC'
- 
+
 	INCLUDE 'BULLDIR.INC'
- 
+
 	COMMON /POINT/ BULL_POINT
- 
+
 	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
- 
+
 	COMMON /DIR_POSITION/ DIR_NUM
- 
+
         COMMON /NEWS_OPEN/ NEWS_OPEN
- 
+
 	EXTERNAL LNM_MODE_EXEC,ENABLE_CTRL_EXIT
 C
 C  The following 2 files were used prior to V1.1.
 C
 	CHARACTER*80 BULLDIR_FILE /'BULL_DIR:BULLDIR.DAT'/
 	CHARACTER*80 BULLETIN_FILE /'BULL_DIR:BULLETIN.DAT'/
- 
+
 	CHARACTER*25 SAVE_FOLDER
 	DATA SAVE_BLOCK/-1/
- 
+
 	CHARACTER*14 NAMES(6)
 	DATA NAMES/'directory','message','BULLUSER.DAT','BULLFOLDER.DAT',
      &			'BULLINF.DAT','BULLNEWS.DAT'/
 	INTEGER NAME(14)
 	DATA NAME/1,2,0,3,0,0,4,0,5,0,0,0,0,6/
- 
+
 	DATA LUN /0/
- 
+
 	ENTRY OPEN_BULLNEWS_SHARED
 	LUN = LUN + 5			! Unit = 14
- 
+
 	ENTRY OPEN_BULLINF_SHARED
 	LUN = LUN + 1			! Unit = 9
- 
+
 	ENTRY OPEN_SYSUAF_SHARED
 	LUN = LUN + 1			! Unit = 8
- 
+
 	ENTRY OPEN_BULLFOLDER_SHARED
 	LUN = LUN + 3			! Unit = 7
- 
+
 	ENTRY OPEN_BULLUSER_SHARED
 	LUN = LUN + 2			! Unit = 4
- 
+
 	ENTRY OPEN_BULLDIR_SHARED
 	LUN = LUN + 1			! Unit = 2
- 
+
 	ENTRY OPEN_BULLFIL_SHARED
 	LUN = LUN + 1			! Unit = 1
- 
+
 	IER = 0
- 
+
 	NTRIES = 0
- 
+
 	CALL DISABLE_CTRL
- 
+
 	IF (LUN.EQ.2.AND..NOT.REMOTE_SET) THEN
 	   DO WHILE (FILE_LOCK(IER,IER1))
- 
+
 	    OPEN (UNIT=2,FILE=FOLDER_FILE(1:TRIM(FOLDER_FILE))
      &	      //'.BULLDIR',STATUS='OLD',FORM='UNFORMATTED',
      &	      RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
@@ -411,7 +411,7 @@ C
 	   END DO
 	   DIR_NUM = -1
 	END IF
- 
+
 	IF (LUN.EQ.1.AND.REMOTE_SET.AND.(SAVE_BLOCK.NE.BLOCK.OR.
      &		SAVE_FOLDER.NE.FOLDER)) THEN
 	   CALL REMOTE_READ_MESSAGE(BULL_POINT,IER)
@@ -439,7 +439,7 @@ C
 	    IF (NTRIES.GT.30) CALL ENABLE_CTRL_EXIT
 	   END DO
 	END IF
- 
+
 	IF (LUN.EQ.4) THEN
 	   DO WHILE (FILE_LOCK(IER,IER1))
 	    OPEN (UNIT=4,FILE=BULLUSER_FILE,STATUS='OLD',
@@ -455,14 +455,14 @@ C
 	    IF (NTRIES.GT.30) CALL ENABLE_CTRL_EXIT
 	   END DO
 	END IF
- 
+
 	IF (LUN.EQ.7) THEN
 	   DO WHILE (FILE_LOCK(IER,IER1))
 	    OPEN (UNIT=7,FILE=BULLFOLDER_FILE,STATUS='OLD',
      &	    ACCESS='KEYED',RECORDTYPE='FIXED',
      &	    IOSTAT=IER,ORGANIZATION='INDEXED',SHARED,
      &	    KEY=(1:25:CHARACTER,26:29:INTEGER))
- 
+
 	    IF (IER.EQ.0) THEN
 	       INQUIRE(UNIT=7,RECORDSIZE=ASK_SIZE)
 	       IF (ASK_SIZE.NE.FOLDER_RECORD/4) THEN
@@ -477,20 +477,20 @@ C
 	   END DO
 	   IF (IER.EQ.0) NEWS_OPEN = .FALSE.
 	END IF
- 
+
 	IF (LUN.EQ.14) THEN
 	   DO WHILE (FILE_LOCK(IER,IER1))
 	    OPEN (UNIT=7,FILE=BULLNEWS_FILE,STATUS='OLD',
      &	    ACCESS='KEYED',RECORDTYPE='FIXED',
      &	    IOSTAT=IER,ORGANIZATION='INDEXED',SHARED,
      &	    KEY=(1:25:CHARACTER,26:29:INTEGER))
- 
+
 	    NTRIES = NTRIES + 1
 	    IF (NTRIES.GT.30) CALL ENABLE_CTRL_EXIT
 	   END DO
 	   IF (IER.EQ.0) NEWS_OPEN = .TRUE.
 	END IF
- 
+
 	IF (LUN.EQ.8) THEN
 	   DO WHILE (FILE_LOCK(IER,IER1))
 	    OPEN (UNIT=8,FILE='SYSUAF',DEFAULTFILE='SYS$SYSTEM:SYSUAF.DAT',
@@ -499,7 +499,7 @@ C
      &	     USEROPEN=LNM_MODE_EXEC)
 	   END DO
 	END IF
- 
+
 	IF (LUN.EQ.9) THEN
 	   DO WHILE (FILE_LOCK(IER,IER1))
 	     OPEN (UNIT=9,FILE=BULLINF_FILE,STATUS='OLD',
@@ -516,7 +516,7 @@ C
 	     IF (NTRIES.GT.30) CALL ENABLE_CTRL_EXIT
 	   END DO
 	END IF
- 
+
 	IF (IER.EQ.FOR$IOS_FILNOTFOU.AND.LUN.NE.8) THEN
 	   CALL OPEN_FILE(LUN)
 	ELSE IF (IER.NE.0) THEN
@@ -530,46 +530,46 @@ C
 	   END IF
 	   CALL ENABLE_CTRL_EXIT
 	END IF
- 
+
 	LUN = 0
- 
+
 	RETURN
 	END
- 
- 
+
+
 	SUBROUTINE RESET_PROTECTION
- 
+
 	IMPLICIT INTEGER (A-Z)
- 
+
 	DATA PROT_LEVEL /0/
- 
+
 	PROT_LEVEL = PROT_LEVEL - 1
 	IF (PROT_LEVEL.GT.0) RETURN
- 
+
 	CALL SYS$SETDFPROT(CUR_DEF_PROT,)	! Reset default protection
- 
+
 	RETURN
- 
+
 	ENTRY SET_PROTECTION
- 
+
 	PROT_LEVEL = PROT_LEVEL + 1
 	IF (PROT_LEVEL.GT.1) RETURN
- 
+
 	CALL SYS$SETDFPROT('FF00'X,CUR_DEF_PROT)
 		! Set protection to (SYSTEM:RWED,OWNER:RWED,WORLD,GROUP)
- 
+
 	RETURN
 	END
- 
- 
- 
- 
+
+
+
+
 	SUBROUTINE FOLDER_TO_NEWS
- 
+
 	IMPLICIT INTEGER (A-Z)
- 
+
 	INCLUDE 'BULLFOLDER.INC'
- 
+
 	NEWS_FOLDER = FOLDER
 	NEWS_FOLDER_NUMBER = FOLDER_NUMBER
 	NEWS_FOLDER_DESCRIP = FOLDER_DESCRIP(
@@ -578,11 +578,11 @@ C
 	NEWS_F_NBULL = F_NBULL
 	NEWS_F_NEWEST_BTIM(1) = F_NEWEST_BTIM(1)
 	NEWS_F_NEWEST_BTIM(2) = F_NEWEST_BTIM(2)
- 
+
 	RETURN
- 
+
 	ENTRY FOLDER1_TO_NEWS
- 
+
 	NEWS_FOLDER1 = FOLDER1
 	NEWS_FOLDER1_NUMBER = FOLDER1_NUMBER
 	NEWS_FOLDER1_DESCRIP = FOLDER1_DESCRIP(
@@ -591,11 +591,11 @@ C
 	NEWS_F1_NBULL = F1_NBULL
 	NEWS_F1_NEWEST_BTIM(1) = F1_NEWEST_BTIM(1)
 	NEWS_F1_NEWEST_BTIM(2) = F1_NEWEST_BTIM(2)
- 
+
 	RETURN
- 
+
 	ENTRY NEWS_TO_FOLDER
- 
+
 	FOLDER = NEWS_FOLDER
 	FOLDER_NUMBER = NEWS_FOLDER_NUMBER
 	FOLDER_DESCRIP = NEWS_FOLDER(:TRIM(NEWS_FOLDER))
@@ -605,11 +605,11 @@ C
 	F_NEWEST_BTIM(1) = NEWS_F_NEWEST_BTIM(1)
 	F_NEWEST_BTIM(2) = NEWS_F_NEWEST_BTIM(2)
 	FOLDER_FLAG = 0
- 
+
 	RETURN
- 
+
 	ENTRY NEWS_TO_FOLDER1
- 
+
 	FOLDER1 = NEWS_FOLDER1
 	FOLDER1_NUMBER = NEWS_FOLDER1_NUMBER
 	FOLDER1_DESCRIP = NEWS_FOLDER1(:TRIM(NEWS_FOLDER1))
@@ -619,49 +619,49 @@ C
 	F1_NEWEST_BTIM(1) = NEWS_F1_NEWEST_BTIM(1)
 	F1_NEWEST_BTIM(2) = NEWS_F1_NEWEST_BTIM(2)
 	FOLDER1_FLAG = 0
- 
+
 	RETURN
- 
+
 	END
- 
- 
- 
- 
+
+
+
+
 	SUBROUTINE CONVERT_BULLDIRS
- 
+
 	IMPLICIT INTEGER (A-Z)
- 
+
 	INCLUDE 'BULLDIR.INC'
- 
+
 	INCLUDE 'BULLFOLDER.INC'
- 
+
 	INCLUDE 'BULLFILES.INC'
- 
+
 	CHARACTER BUFFER*115
- 
+
 	WRITE (6,'('' Converting data files to new format. Please wait.'')')
- 
+
 	CALL SET_PROTECTION
- 
+
 	OPEN (UNIT=2,FILE=FOLDER_FILE(1:TRIM(FOLDER_FILE))
      &	      //'.BULLDIR',STATUS='OLD',FORM='UNFORMATTED',
      &	      RECORDTYPE='FIXED',ACCESS='DIRECT',
      &	      ORGANIZATION='RELATIVE',DISPOSE='KEEP',
      &	      IOSTAT=IER)
- 
+
 	IF (IER.NE.0) GO TO 900	! No BULLDIR file found.
- 
+
 	READ (2'1,IOSTAT=IER1) BUFFER
- 
+
 	CALL LIB$MOVC3(4,%REF(BUFFER(39:)),NBULL)
- 
+
 	OPEN (UNIT=9,FILE=FOLDER_FILE(1:TRIM(FOLDER_FILE))
      &	      //'.BULLDIR',STATUS='NEW',FORM='UNFORMATTED',
      &	      RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
      &	      ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='DELETE',
      &	      KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED',
      &	      INITIALSIZE=(((NBULL+1)*DIR_RECORD_LENGTH)/512)+5 )
- 
+
 	IF (IER.NE.0) THEN
 	   OPEN (UNIT=9,FILE=FOLDER_FILE(1:TRIM(FOLDER_FILE))
      &	      //'.BULLDIR',STATUS='NEW',FORM='UNFORMATTED',
@@ -669,16 +669,16 @@ C
      &	      ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='DELETE',
      &	      KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
 	END IF
- 
+
 	IF (IER1.NE.0) GO TO 800
- 
+
 	CALL SYS_BINTIM(BUFFER(1:11)//' '//BUFFER(12:19),NEWEST_EXBTIM)
 	CALL SYS_BINTIM(BUFFER(20:30)//' '//BUFFER(31:38),NEWEST_MSGBTIM)
 	BULLDIR_HEADER(29:40) = BUFFER(39:)
 	CALL SYS_BINTIM(BUFFER(51:61)//' '//BUFFER(62:69),SHUTDOWN_BTIM)
 	BULLDIR_HEADER(49:52) = BUFFER(70:)
 	IF (IER.EQ.0) WRITE (9,IOSTAT=IER) BULLDIR_HEADER
- 
+
 	ICOUNT = 2
 	DO WHILE (IER.EQ.0)
 	   READ (2'ICOUNT,IOSTAT=IER) BUFFER
@@ -695,18 +695,18 @@ C
 	      ICOUNT = ICOUNT + 1
 	   END IF
 	END DO
- 
+
 800	CLOSE (UNIT=9,DISPOSE='KEEP')
 	CLOSE (UNIT=2)
- 
+
 900	CALL RESET_PROTECTION
- 
+
 	RETURN
- 
+
 	END
- 
- 
- 
+
+
+
 	SUBROUTINE CONVERT_BULLFILES
 C
 C  SUBROUTINE CONVERT_BULLFILES
@@ -716,54 +716,54 @@ C	Add expiration time to directory file, add extra byte to bulletin
 C	file to show where each bulletin starts (for redunancy sake in
 C	case crash occurs).
 C
- 
+
 	IMPLICIT INTEGER (A-Z)
- 
+
 	INCLUDE 'BULLDIR.INC'
- 
+
 	INCLUDE 'BULLFOLDER.INC'
- 
+
 	INCLUDE 'BULLFILES.INC'
- 
+
 	CHARACTER*81 BUFFER
- 
+
 	WRITE (6,'('' Converting data files to new format. Please wait.'')')
- 
+
 	OPEN (UNIT=9,FILE=FOLDER_FILE(1:TRIM(FOLDER_FILE))
      &	      //'.BULLDIR',STATUS='OLD',
      &	      RECORDTYPE='FIXED',RECORDSIZE=107,ACCESS='DIRECT',
      &	      ORGANIZATION='RELATIVE',DISPOSE='KEEP',FORM='FORMATTED',
      &	      SHARED,READONLY,IOSTAT=IER)
- 
+
 	IF (IER.NE.0) CALL ERROR_AND_EXIT		! Error.  Why?
- 
+
 	OPEN (UNIT=10,FILE=FOLDER_FILE(1:TRIM(FOLDER_FILE))
      &	      //'.BULLFIL',STATUS='OLD',
      &	      RECORDTYPE='FIXED',RECORDSIZE=80,
      &	      FORM='FORMATTED',IOSTAT=IER,SHARED,READONLY)
- 
+
 	IF (IER.NE.0) CALL ERROR_AND_EXIT		! Error.  Why?
- 
+
 	CALL SET_PROTECTION
- 
+
 	OPEN (UNIT=1,FILE=FOLDER_FILE(1:TRIM(FOLDER_FILE))
      &	      //'.BULLFIL',STATUS='NEW',IOSTAT=IER,
      &	      ACCESS='DIRECT',RECORDTYPE='FIXED',RECORDSIZE=81,
      &	      FORM='FORMATTED')
- 
+
 	OPEN (UNIT=2,FILE=FOLDER_FILE(1:TRIM(FOLDER_FILE))
      &	      //'.BULLDIR',STATUS='NEW',FORM='UNFORMATTED',
      &	      RECORDTYPE='FIXED',RECORDSIZE=DIR_RECORD_LENGTH/4,
      &	      ORGANIZATION='INDEXED',IOSTAT=IER,DISPOSE='KEEP',
      &	      KEY=(9:12:INTEGER,1:8:CHARACTER),ACCESS='KEYED')
- 
+
 	NEWEST_EXTIME = '00:00:00.00'
-	READ (9'1,1000,IOSTAT=IER) 
+	READ (9'1,1000,IOSTAT=IER)
      &		NEWEST_EXDATE,NEWEST_DATE,NEWEST_TIME(:8),
      &		NBULL,NBLOCK,SHUTDOWN,SHUTDOWN_DATE,SHUTDOWN_TIME(:8)
 	NEMPTY = 0
 	IF (IER.EQ.0) CALL WRITEDIR(0,IER1)
- 
+
 	EXTIME = '00:00:00.00'
 	ICOUNT = 2
 	DO WHILE (IER.EQ.0)
@@ -780,20 +780,20 @@ C
 	      ICOUNT = ICOUNT + 1
 	   END IF
 	END DO
- 
+
 	CLOSE (UNIT=9)
 	CLOSE (UNIT=2)
 	CLOSE (UNIT=10)
 	CLOSE (UNIT=1)
- 
+
 	CALL RESET_PROTECTION
 	RETURN
- 
+
 1000	FORMAT(A11,A11,A8,A4,A4,A4,A11,A8)
 1010	FORMAT(A53,A12,A11,A8,A4,A11,A4,A4)
- 
+
 	END
- 
+
 	SUBROUTINE CONVERT_BULLFILE
 C
 C  SUBROUTINE CONVERT_BULLFILE
@@ -803,29 +803,29 @@ C
 C  NOTE: CONVERT_BULLFILES converts from 80 to 81 byte length.
 C	 This converts from 81 byte length to 128 compressed format.
 C
- 
+
 	IMPLICIT INTEGER (A-Z)
- 
+
 	INCLUDE 'BULLDIR.INC'
- 
+
 	INCLUDE 'BULLFOLDER.INC'
- 
+
 	INCLUDE 'BULLFILES.INC'
- 
+
 	CHARACTER*80 BUFFER,NEW_FILE
- 
+
 	WRITE (6,'('' Converting data files to new format. Please wait.'')')
- 
+
 	CALL CLOSE_BULLDIR
- 
+
 	CALL SET_PROTECTION
- 
+
 	CALL OPEN_BULLFOLDER
- 
+
 100	READ (7,FMT=FOLDER_FMT,ERR=200)
      &		FOLDER,FOLDER_NUMBER,FOLDER_OWNER,FOLDER_DESCRIP
      &		,FOLDER_BBOARD,FOLDER_BBEXPIRE,USERB,GROUPB,ACCOUNTB
- 
+
 	FOLDER_FILE = FOLDER_DIRECTORY(:TRIM(FOLDER_DIRECTORY))
      &		//FOLDER(:TRIM(FOLDER))
 	NEW_FILE = FOLDER_FILE(:TRIM(FOLDER_FILE))//'.BULLFILOLD'
@@ -833,20 +833,20 @@ C
      &	      ,STATUS='OLD',
      &	      RECORDTYPE='FIXED',RECORDSIZE=81,ACCESS='DIRECT',
      &	      FORM='FORMATTED',IOSTAT=IER,SHARED,READONLY)
- 
+
 	IF (IER.NE.0) CALL ERROR_AND_EXIT		! Error.  Why?
- 
+
 	OPEN (UNIT=1,FILE=FOLDER_FILE(1:TRIM(FOLDER_FILE))
      &	   //'.BULLFIL',STATUS='NEW',IOSTAT=IER,
      &	   ACCESS='DIRECT',RECORDTYPE='FIXED',RECORDSIZE=32,
      &	   FORM='UNFORMATTED')
 	IER = LIB$RENAME_FILE(FOLDER_FILE(:TRIM(FOLDER_FILE))
      &		//'.BULLFIL;-1',NEW_FILE)
- 
+
 	CALL OPEN_BULLDIR
- 
+
 	CALL READDIR(0,IER)
- 
+
 	IF (IER.EQ.1) THEN
 	 NBLOCK = 0
 	 DO I=1,NBULL
@@ -864,27 +864,27 @@ C
 	   BLOCK = SBLOCK
 	   CALL WRITEDIR(I,IER)
 	 END DO
- 
+
 	 NEMPTY = 0
 	 CALL WRITEDIR(0,IER)
 	END IF
- 
+
 	CLOSE (UNIT=10)
 	CLOSE (UNIT=1)
- 
+
 	CALL CLOSE_BULLDIR
 	GOTO 100
- 
+
 200	CALL OPEN_BULLDIR_SHARED
- 
+
 	CALL RESET_PROTECTION
- 
+
 	RETURN
- 
+
 	END
- 
- 
- 
+
+
+
 	SUBROUTINE CONVERT_BULLFOLDER(FILENAME,ASK_SIZE)
 C
 C  SUBROUTINE CONVERT_BULLFOLDER
@@ -892,46 +892,46 @@ C
 C  FUNCTION: Converts bulletin folder file to new format.
 C
 	IMPLICIT INTEGER (A-Z)
- 
+
 	INCLUDE 'BULLDIR.INC'
- 
+
 	INCLUDE 'BULLFOLDER.INC'
- 
+
 	INCLUDE 'BULLFILES.INC'
- 
+
 	INCLUDE '($SSDEF)'
- 
+
 	INCLUDE '($FORIOSDEF)'
- 
+
 	CHARACTER*(*) FILENAME
- 
+
 	CHARACTER*80 NEW_FILE
- 
+
 	WRITE (6,'('' Converting data files to new format. Please wait.'')')
- 
+
 	CALL SET_PROTECTION
- 
+
 	EODIR = MAX(INDEX(FILENAME,':'),INDEX(FILENAME,']'))
 	SUFFIX = INDEX(FILENAME(EODIR:),'.') + EODIR - 1
 	NEW_FILE = FILENAME(:SUFFIX)//'OLD'
- 
+
 	DO WHILE (FILE_LOCK(IER,IER1))
 	   OPEN (UNIT=7,FILE=FILENAME,STATUS='OLD',
      &	        ACCESS='KEYED',RECORDTYPE='FIXED',
      &	        FORM='FORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
      &	        KEY=(1:25:CHARACTER,26:29:INTEGER))
 	END DO
- 
+
 	IF (IER.NE.0) CALL ERROR_AND_EXIT		! Error.  Why?
- 
+
 	OPEN (UNIT=19,FILE=NEW_FILE,STATUS='NEW',
      &	        ACCESS='KEYED',RECORDTYPE='FIXED',
      &	        RECORDSIZE=FOLDER_RECORD,
      &	        FORM='FORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
      &	        KEY=(1:25:CHARACTER,26:29:INTEGER),DISPOSE='DELETE')
- 
+
 	IF (IER.NE.0) CALL ERROR_AND_EXIT		! Error.  Why?
- 
+
 	IF (ASK_SIZE.EQ.173/4) THEN
 	 F_NUMBER = 0
 	 DO WHILE (IER.EQ.0)
@@ -1001,52 +1001,52 @@ C
 	   END IF
 	 END DO
 	END IF
- 
+
 	CLOSE (UNIT=7)
 	CLOSE (UNIT=19,STATUS='SAVE')
- 
+
 	IER = LIB$RENAME_FILE(NEW_FILE,FILENAME)
 	IER = LIB$RENAME_FILE(BULLFOLDER_FILE//';-1',NEW_FILE)
- 
+
 	CALL RESET_PROTECTION
- 
+
 	IER = LIB$DELETE_FILE(BBOARD_DIRECTORY(:TRIM(BBOARD_DIRECTORY))
      &		//'BOARD.COM;*')	! BULLETIN$ is referenced in old file
- 
+
 	RETURN
 	END
- 
+
 	SUBROUTINE CONVERT_USERFILE
 C
 C  SUBROUTINE CONVERT_USERFILE
 C
 C  FUNCTION: Converts user file to new format which has 8 bytes added.
 C
- 
+
 	IMPLICIT INTEGER (A-Z)
- 
+
 	INCLUDE 'BULLFILES.INC'
- 
+
 	INCLUDE 'BULLUSER.INC'
- 
+
 	CHARACTER BUFFER*74,NEW_FILE*80
- 
+
 	CHARACTER*11 LOGIN_DATE,READ_DATE
 	CHARACTER*8 LOGIN_TIME,READ_TIME
- 
+
 	WRITE (6,'('' Converting data files to new format. Please wait.'')')
- 
+
 	EODIR = MAX(INDEX(BULLUSER_FILE,':'),INDEX(BULLUSER_FILE,']'))
 	SUFFIX = INDEX(BULLUSER_FILE(EODIR:),'.') + EODIR - 1
 	NEW_FILE = BULLUSER_FILE(:SUFFIX)//'OLD'
 	IER = LIB$RENAME_FILE(BULLUSER_FILE,NEW_FILE)
- 
+
 	OPEN (UNIT=9,FILE=NEW_FILE,STATUS='OLD',
      &	     ACCESS='KEYED',RECORDTYPE='FIXED',
      &	     FORM='FORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
      &	     KEY=(1:12:CHARACTER))
 	INQUIRE (UNIT=9,RECORDSIZE=RECL)
- 
+
 	IF ((RECL-28)/16.GT.FLONG) THEN
 	   WRITE (6,'('' ERROR: Old data files have more folders'',
      &		      '' than was specified with BULLUSER.INC.'')')
@@ -1059,7 +1059,7 @@ C
 	      CALL EXIT
 	   END IF
 	END IF
- 
+
 	IF (IER.EQ.0) THEN
 	   CALL SET_PROTECTION
 	   OPEN (UNIT=4,FILE=BULLUSER_FILE,STATUS='NEW',
@@ -1067,7 +1067,7 @@ C
      &	    FORM='FORMATTED',ORGANIZATION='INDEXED',IOSTAT=IER,
      &	    KEY=(1:12:CHARACTER))
 	END IF
- 
+
 	IF (IER.NE.0) THEN
 	   WRITE (6,'('' Cannot convert user file.'')')
 	   IF (IER1.EQ.0) CALL ERRSNS(IDUMMY,IER1)
@@ -1075,14 +1075,14 @@ C
 	   CALL RESET_PROTECTION
 	   CALL ENABLE_CTRL_EXIT
 	END IF
- 
+
 	DO I=1,FLONG
 	   NEW_FLAG(I) = 'FFFFFFFF'X
 	   NOTIFY_FLAG(I) = 0
 	   BRIEF_FLAG(I) = 0
 	   SET_FLAG(I) = 0
 	END DO
- 
+
 	IF (RECL.EQ.42.OR.RECL.EQ.50.OR.RECL.EQ.58.OR.RECL.EQ.66.OR.
      &		RECL.EQ.74) THEN		! Old format
 	   IF (RECL.LE.58) RECL = 50
@@ -1118,7 +1118,7 @@ C
 	ELSE					! Folder maxmimum increase
 	   OFLONG = (RECL - 28) / 16		! Old  #longwords/flag
 	   DO WHILE (IER.EQ.0)
-	    READ (9,FMT='(A12,<4+OFLONG*4>A4)',IOSTAT=IER) 
+	    READ (9,FMT='(A12,<4+OFLONG*4>A4)',IOSTAT=IER)
      &	     TEMP_USER,LOGIN_BTIM,READ_BTIM,
      &	     (NEW_FLAG(I),I=1,OFLONG),(SET_FLAG(I),I=1,OFLONG),
      &	     (BRIEF_FLAG(I),I=1,OFLONG),(NOTIFY_FLAG(I),I=1,OFLONG)
@@ -1128,18 +1128,18 @@ C
 	    END IF
 	   END DO
 	END IF
- 
+
 	IER = 0
- 
+
 	CLOSE (UNIT=9)
 	CLOSE (UNIT=4)
- 
+
 	CALL RESET_PROTECTION
- 
+
 	RETURN
 	END
- 
- 
+
+
 	SUBROUTINE READDIR(BULLETIN_NUM,ICOUNT)
 C
 C  SUBROUTINE READDIR
@@ -1154,24 +1154,24 @@ C			 number of blocks in bulletin file, etc.
 C  OUTPUTS:
 C	ICOUNT  -  The last record read by this routine.
 C
- 
+
 	IMPLICIT INTEGER (A - Z)
- 
+
 	INCLUDE 'BULLDIR.INC'
- 
+
 	INCLUDE 'BULLFOLDER.INC'
- 
+
 	COMMON /PROMPT/ COMMAND_PROMPT
 	CHARACTER*39 COMMAND_PROMPT
- 
+
 	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
- 
+
 	COMMON /DIR_POSITION/ DIR_NUM
- 
+
 	CHARACTER*3 CFOLDER_NUMBER
- 
+
 	ICOUNT = BULLETIN_NUM
- 
+
 	IF (ICOUNT.EQ.0) THEN
 	   IF (.NOT.REMOTE_SET) THEN
 	      DO WHILE (REC_LOCK(IER))
@@ -1230,19 +1230,19 @@ C
 	      RETURN
 	   END IF
 	END IF
- 
+
 	IF (IER.EQ.0) ICOUNT = ICOUNT + 1
- 
+
 	UNLOCK 2
- 
+
 	RETURN
- 
+
 	END
- 
- 
- 
- 
- 
+
+
+
+
+
 	SUBROUTINE READDIR_KEYGE(IER)
 C
 C  SUBROUTINE READDIR_KEYGE
@@ -1255,15 +1255,15 @@ C	MSG_KEY	- Message key (passed via BULLDIR.INC common block).
 C  OUTPUTS:
 C	IER  -  If not 0, no entry found.  Else contains message number.
 C
- 
+
 	IMPLICIT INTEGER (A - Z)
- 
+
 	INCLUDE 'BULLDIR.INC'
- 
+
 	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
- 
+
 	COMMON /DIR_POSITION/ DIR_NUM
- 
+
 	IF (.NOT.REMOTE_SET) THEN
 	   DO WHILE (REC_LOCK(IER))
 	      READ(2,KEYID=1,KEYGT=MSG_KEY,IOSTAT=IER) BULLDIR_ENTRY
@@ -1281,66 +1281,66 @@ C
 	ELSE
 	   CALL REMOTE_GET_HEADER(DUMMY,-1,IER)
  	END IF
- 
+
 	RETURN
- 
+
 	END
- 
- 
- 
+
+
+
 	SUBROUTINE CONVERT_HEADER_FROMBIN
- 
+
 	IMPLICIT INTEGER (A-Z)
- 
+
 	INCLUDE 'BULLDIR.INC'
- 
+
 	CHARACTER*23 DATETIME
- 
+
 	CALL SYS$ASCTIM(,DATETIME,NEWEST_EXBTIM,)
- 
+
 	NEWEST_EXDATE = DATETIME
 	NEWEST_EXTIME = DATETIME(13:)
- 
+
 	CALL SYS$ASCTIM(,DATETIME,NEWEST_MSGBTIM,)
- 
+
 	NEWEST_DATE = DATETIME
 	NEWEST_TIME = DATETIME(13:)
- 
+
 	CALL SYS$ASCTIM(,DATETIME,SHUTDOWN_BTIM,)
- 
+
 	SHUTDOWN_DATE = DATETIME
 	SHUTDOWN_TIME = DATETIME(13:)
- 
+
 	RETURN
 	END
- 
- 
- 
+
+
+
 	SUBROUTINE CONVERT_ENTRY_FROMBIN
- 
+
 	IMPLICIT INTEGER (A-Z)
- 
+
 	INCLUDE 'BULLDIR.INC'
- 
+
 	CHARACTER*23 DATETIME
- 
+
 	CALL SYS$ASCTIM(,DATETIME,EX_BTIM,)
- 
+
 	EXDATE = DATETIME
 	EXTIME = DATETIME(13:)
- 
+
 	CALL SYS$ASCTIM(,DATETIME,MSG_BTIM,)
- 
+
 	DATE = DATETIME
 	TIME = DATETIME(13:)
- 
+
 	RETURN
 	END
- 
- 
- 
- 
- 
+
+
+
+
+
 	SUBROUTINE WRITEDIR(BULLETIN_NUM,IER)
 C
 C  SUBROUTINE WRITEDIR
@@ -1354,23 +1354,23 @@ C			 If 0, write the header of the directory file.
 C  OUTPUTS:
 C	IER - Error status from WRITE.
 C
- 
+
 	IMPLICIT INTEGER (A - Z)
- 
+
 	COMMON /REMOTE_FOLDER/ REMOTE_SET,REMOTE_UNIT
- 
+
 	COMMON /DIR_POSITION/ DIR_NUM
- 
+
 	INCLUDE 'BULLDIR.INC'
- 
+
 	CONV = .TRUE.
- 
+
 	GO TO 10
- 
+
 	ENTRY WRITEDIR_NOCONV(BULLETIN_NUM,IER)
- 
+
 	CONV = .FALSE.
-	
+
 10	IF (BULLETIN_NUM.EQ.0) THEN
 	   IF (CONV) CALL CONVERT_HEADER_TOBIN
 	   IF (REMOTE_SET) THEN
@@ -1410,52 +1410,52 @@ C
 	      END IF
 	   END IF
 	END IF
- 
+
 	IF (REMOTE_SET.AND.IER.GT.0) CALL ERROR_AND_EXIT
- 
+
 	DIR_NUM = -1
- 
+
 	RETURN
- 
+
 	END
- 
- 
- 
+
+
+
 	SUBROUTINE CONVERT_HEADER_TOBIN
- 
+
 	IMPLICIT INTEGER (A-Z)
- 
+
 	INCLUDE 'BULLDIR.INC'
- 
+
 	CALL SYS_BINTIM(NEWEST_EXDATE//' '//NEWEST_EXTIME,NEWEST_EXBTIM)
- 
+
 	CALL SYS_BINTIM(NEWEST_DATE//' '//NEWEST_TIME,NEWEST_MSGBTIM)
- 
+
 	CALL SYS_BINTIM(SHUTDOWN_DATE//' '//SHUTDOWN_TIME,SHUTDOWN_BTIM)
- 
+
 	RETURN
 	END
- 
- 
- 
+
+
+
 	SUBROUTINE CONVERT_ENTRY_TOBIN
- 
+
 	IMPLICIT INTEGER (A-Z)
- 
+
 	INCLUDE 'BULLDIR.INC'
- 
+
 	CALL SYS_BINTIM(EXDATE//' '//EXTIME,EX_BTIM)
- 
+
 	CALL SYS_BINTIM(DATE//' '//TIME,MSG_BTIM)
- 
+
 	CALL GET_MSGKEY(MSG_BTIM,MSG_KEY)
- 
+
 	RETURN
 	END
- 
- 
- 
- 
+
+
+
+
 	SUBROUTINE READACL(FILENAME,ACLENT,ACLLENGTH)
 C
 C  SUBROUTINE READACL
@@ -1467,26 +1467,26 @@ C	FILENAME - Name of file to check.
 C	ACLENT - String which will be large enough to hold ACL information.
 C
 	IMPLICIT INTEGER (A-Z)
- 
+
 	INCLUDE 'BULLFILES.INC'
- 
+
 	INCLUDE '($ACLDEF)'
- 
+
 	CHARACTER ACLENT*(*),OUTPUT*80,ACLSTR*255,FILENAME*(*)
- 
+
 	CALL INIT_ITMLST	! Initialize item list
 	CALL ADD_2_ITMLST(ACLLENGTH,ACL$C_READACL,%LOC(ACLENT))
 	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
- 
+
 	IER = SYS$CHANGE_ACL(,ACL$C_FILE,FILENAME,%VAL(ACL_ITMLST),,,)
- 
+
 	BIG = .NOT.IER
 	IF (BIG) THEN
 	   IER = SYS$PARSE_ACL('(ID=*,ACCESS=NONE)',ACLENT,,)
 	   ACLLENGTH = ACL$S_ADDACLENT
 	   CTXT = 0
 	END IF
- 
+
 	DO ACC_TYPE=1,2
 	 POINT = 1
 	 OUTLEN = 0
@@ -1554,7 +1554,7 @@ C
 		 OUTPUT = ACLSTR(START_ID:END_ID)//','
 		 OUTLEN = IDLEN + 2
 	      ELSE IF (OUTLEN+IDLEN-1.EQ.80) THEN
-		 WRITE (6,'(1X,A)') 
+		 WRITE (6,'(1X,A)')
      &			OUTPUT(:OUTLEN-1)//ACLSTR(START_ID:END_ID)
 	         OUTLEN = 1
 	      ELSE
@@ -1566,28 +1566,28 @@ C
 	 END DO
 	 IF (OUTLEN.GT.1) WRITE (6,'(1X,A)') OUTPUT(:OUTLEN-2)
 	END DO
- 
+
 	RETURN
 	END
- 
- 
- 
- 
+
+
+
+
 	SUBROUTINE CONVERT_INFFILE
- 
+
 	IMPLICIT INTEGER (A-Z)
- 
+
 	INCLUDE 'BULLUSER.INC'
- 
+
 	INCLUDE 'BULLFILES.INC'
- 
+
 	OPEN (UNIT=10,FILE=BULLINF_FILE,STATUS='OLD',
      &	   ACCESS='KEYED',RECORDTYPE='FIXED',
      &	   IOSTAT=IER,ORGANIZATION='INDEXED',
      &	   KEY=(1:12:CHARACTER))
- 
+
 	INQUIRE (UNIT=10,RECORDSIZE=RECL)
- 
+
 	IF ((RECL-28)/16.GT.FLONG) THEN
 	   WRITE (6,'('' ERROR: Old data files have more folders'',
      &		      '' than was specified with BULLUSER.INC.'')')
@@ -1599,42 +1599,42 @@ C
 	      CALL EXIT
 	   END IF
 	END IF
- 
+
 	RECL = RECL/8
- 
+
 	OPEN (UNIT=9,FILE=BULLINF_FILE,STATUS='NEW',
      &	   ACCESS='KEYED',RECORDTYPE='FIXED',RECORDSIZE=FOLDER_MAX*2+3,
      &	   IOSTAT=IER,ORGANIZATION='INDEXED',
      &	   KEY=(1:12:CHARACTER))
- 
+
 	DO WHILE (IER.EQ.0)
 	 READ (10,IOSTAT=IER) TEMP_USER,((LAST_READ_BTIM(J,I),J=1,2),I=1,RECL)
 	 IF (IER.EQ.0) WRITE (9) TEMP_USER,
      &			((LAST_READ_BTIM(J,I),J=1,2),I=1,FOLDER_MAX)
 	END DO
- 
+
 	CLOSE (UNIT=10,STATUS='DELETE')
- 
+
 	CLOSE (UNIT=9)
- 
+
 	RETURN
 	END
- 
- 
+
+
 	SUBROUTINE ERROR_AND_EXIT
- 
+
 	IMPLICIT INTEGER (A-Z)
-	
+
 	CALL ERRSNS(IDUMMY,IER)
 	CALL SYS_GETMSG(IER)
 	CALL ENABLE_CTRL_EXIT
- 
+
 	RETURN
 	END
- 
- 
- 
- 
+
+
+
+
 	SUBROUTINE COPY_ACL(INFILE,OUTFILE)
 C
 C  SUBROUTINE COPY_ACL
@@ -1643,29 +1643,29 @@ C  FUNCTION:
 C	Copy ACLs from one file to another file
 C
 	IMPLICIT INTEGER (A-Z)
- 
+
 	INCLUDE '($ACLDEF)'
- 
+
 	CHARACTER*(*) INFILE,OUTFILE
- 
+
 	CALL INIT_ITMLST	! Initialize item list
 	CALL ADD_2_ITMLST(4,ACL$C_ACLLENGTH,%LOC(ACLLENGTH))
 				! Get length needed to store acl output
 	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
- 
+
 	IER = SYS$CHANGE_ACL(,ACL$C_FILE,INFILE,%VAL(ACL_ITMLST),,,,,)
- 
+
 	CALL LIB$GET_VM(ACLLENGTH+8,ACLSTR)	! Create character string to
 	CALL MAKE_CHAR(%VAL(ACLSTR),ACLLENGTH,ACLLENGTH)	! store acl
- 
+
 	CALL COPY_ACL1(INFILE,OUTFILE,%VAL(ACLSTR),ACLLENGTH)
 						! Pass location of string
 	CALL LIB$FREE_VM(ACLLENGTH+8,ACLSTR)
- 
+
 	RETURN
 	END
- 
- 
+
+
 	SUBROUTINE COPY_ACL1(INFILE,OUTFILE,ACLENT,ACLLENGTH)
 C
 C  SUBROUTINE COPY_ACL1
@@ -1674,17 +1674,17 @@ C  FUNCTION: Called by COPY_ACL to actually do the copy.  Need 2 routines
 C	since must convert location of string into a character string.
 C
 	IMPLICIT INTEGER (A-Z)
- 
+
 	INCLUDE '($ACLDEF)'
- 
+
 	CHARACTER ACLENT*(*),INFILE*(*),OUTFILE*(*)
- 
+
 	CALL INIT_ITMLST	! Initialize item list
 	CALL ADD_2_ITMLST(ACLLENGTH,ACL$C_READACL,%LOC(ACLENT))
 	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
 	IER = SYS$CHANGE_ACL(,ACL$C_FILE,INFILE,%VAL(ACL_ITMLST),,,,,)
 				! Read input file acl
- 
+
 	IF (.NOT.IER) THEN
 	   IER = SYS$PARSE_ACL('(ID=*,ACCESS=NONE)',ACLENT,,)
 	   IF (.NOT.IER) RETURN
@@ -1697,7 +1697,7 @@ C
 	      CALL END_ITMLST(ACL1_ITMLST)	! Get address of itemlist
 	      IER = SYS$CHANGE_ACL
      &			(,ACL$C_FILE,OUTFILE,%VAL(ACL1_ITMLST),,,)
- 
+
 	      CALL INIT_ITMLST	! Initialize item list
 	      CALL ADD_2_ITMLST(ACLLENGTH,ACL$C_FNDACETYP,%LOC(ACLENT))
 	      CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
@@ -1709,18 +1709,18 @@ C
 	   END DO
 	   RETURN
 	END IF
- 
+
 	CALL INIT_ITMLST	! Initialize item list
- 
+
 	POINT = 1
 	DO WHILE (POINT.LT.ACLLENGTH)	! Transfer all acls to output file
 	   CALL ADD_2_ITMLST(ICHAR(ACLENT(POINT:POINT)),ACL$C_ADDACLENT,
      &		%LOC(ACLENT(POINT:)))
 	   POINT = POINT + ICHAR(ACLENT(POINT:POINT))
 	END DO
- 
+
 	CALL END_ITMLST(ACL_ITMLST)	! Get address of itemlist
 	IER = SYS$CHANGE_ACL(,ACL$C_FILE,OUTFILE,%VAL(ACL_ITMLST),,,)
- 
+
 	RETURN
 	END
diff --git a/folders/folders.go b/folders/folders.go
index 9f4c8fa4303e78c65412b1efedbb3e67f425191c..2fd334bf4aad947db4f3fdce6adaa8cba8a31e51 100644
--- a/folders/folders.go
+++ b/folders/folders.go
@@ -5,7 +5,6 @@ import (
 	"database/sql"
 	"embed"
 	"errors"
-	"log"
 	"os"
 	"path"
 
@@ -23,11 +22,12 @@ var fs embed.FS
 
 // Store is the store for folders.
 type Store struct {
-	db *sql.DB
+	user string
+	db   *sql.DB
 }
 
 // Open opens the folders database.
-func Open() (*Store, error) {
+func Open(user string) (*Store, error) {
 	fdir := path.Join(xdg.DataHome, "BULLETIN")
 	err := os.MkdirAll(fdir, 0700)
 	if err != nil {
@@ -39,18 +39,18 @@ func Open() (*Store, error) {
 	if err != nil {
 		return nil, err
 	}
-	m, err := migrate.NewWithSourceInstance("iofs", sqldir, "sqlite://"+fdb)
+	m, err := migrate.NewWithSourceInstance("iofs", sqldir, "sqlite://"+fdb+"?_pragma=foreign_keys(1)")
 	if err != nil {
-		log.Fatal(err)
+		return nil, err
 	}
 	err = m.Up()
-	if err != nil {
+	if err != nil && err != migrate.ErrNoChange {
 		return nil, err
 	}
 	m.Close()
 
-	store := &Store{}
-	store.db, err = sql.Open("sqlite", fdb)
+	store := &Store{user: user}
+	store.db, err = sql.Open("sqlite", "file://"+fdb+"?_pragma=foreign_keys(1)")
 	if err != nil {
 		return nil, errors.New("bulletin database problem")
 	}
diff --git a/folders/sql/1_create_table.down.sql b/folders/sql/1_create_table.down.sql
index df3837bed721d8c7b22e2eaf5ded9a401202c71f..4070921fe631b62d42878b713da994824eacb233 100644
--- a/folders/sql/1_create_table.down.sql
+++ b/folders/sql/1_create_table.down.sql
@@ -1 +1,14 @@
+--- Dropped in reverse order to deal with foreign keys.
+DROP TRIGGER co_owners_after_update_update_at;
+DROP TABLE co_owners;
+
+DROP TRIGGER folders_before_delete_protect;
+DROP TRIGGER folders_after_update_update_at;
+DROP TRIGGER folders_before_update_validate;
+DROP TRIGGER folders_before_insert_validate;
 DROP TABLE folders;
+
+DROP TRIGGER users_before_delete_protect;
+DROP TRIGGER users_before_update_protect;
+DROP TRIGGER users_after_update_update_at;
+DROP TABLE users;
diff --git a/folders/sql/1_create_table.up.sql b/folders/sql/1_create_table.up.sql
index 232fd99f8a09a6d1edd860f6aecd5e56ec7d6d55..6094a1cdb7c4f74ebb93615ae3e20e45ec1e146e 100644
--- a/folders/sql/1_create_table.up.sql
+++ b/folders/sql/1_create_table.up.sql
@@ -1,18 +1,101 @@
+CREATE TABLE users (
+  login       VARCHAR(25)  NOT NULL PRIMARY KEY,
+  name        VARCHAR(53)  NOT NULL,
+  admin       INT          DEFAULT 0,
+  create_at   TIMESTAMP    DEFAULT CURRENT_TIMESTAMP NOT NULL,
+  update_at   TIMESTAMP    DEFAULT CURRENT_TIMESTAMP NOT NULL
+) WITHOUT ROWID;
+
+CREATE TRIGGER users_after_update_update_at
+  AFTER UPDATE ON users FOR EACH ROW
+  WHEN NEW.update_at = OLD.update_at    --- avoid infinite loop
+BEGIN
+  UPDATE users SET update_at=CURRENT_TIMESTAMP WHERE login=NEW.login;
+END;
+
+INSERT INTO users (login, name, admin)
+       VALUES ('SYSTEM', 'System User', 1);
+
+CREATE TRIGGER users_before_update_protect
+  AFTER UPDATE ON users FOR EACH ROW
+  WHEN OLD.login = 'SYSTEM' AND (NEW.login != OLD.login OR NEW.admin != 1)
+BEGIN
+  SELECT RAISE (ABORT, 'SYSTEM user is protected');
+END;
+
+CREATE TRIGGER users_before_delete_protect
+  BEFORE DELETE on users FOR EACH ROW
+  WHEN OLD.login = 'SYSTEM'
+BEGIN
+  SELECT RAISE (ABORT, 'SYSTEM user is protected');
+END;
+
 CREATE TABLE folders (
-  name        VARCHAR(25)  NOT NULL UNIQUE,
+  name        VARCHAR(25)  NOT NULL PRIMARY KEY,
   always      INT          DEFAULT 0,
   brief       INT          DEFAULT 0,
-  description VARCHAR(53),
-  co_owners   TEXT,
+  description VARCHAR(53)  NOT NULL,
   notify      INT          DEFAULT 0,
-  owner       TEXT,
+  owner       VARCHAR(25)  REFERENCES users(login) ON UPDATE CASCADE,
   readnew     INT          DEFAULT 0,
   shownew     INT          DEFAULT 0,
   system      INT          DEFAULT 0,
   expire      INT          DEFAULT 14,
-  visibility  TEXT         DEFAULT "public"
-);
+  visibility  TEXT         DEFAULT 'public',
+  create_at   TIMESTAMP    DEFAULT CURRENT_TIMESTAMP NOT NULL,
+  update_at   TIMESTAMP    DEFAULT CURRENT_TIMESTAMP NOT NULL
+) WITHOUT ROWID;
+
+CREATE TRIGGER folders_before_insert_validate
+  BEFORE INSERT on folders
+BEGIN
+  SELECT
+    CASE
+      WHEN NEW.name != UPPER(NEW.name) OR NEW.name GLOB '*[^A-Z0-9_-]*' THEN
+        RAISE (ABORT, 'Invalid folder name')
+    END;
+END;
+
+CREATE TRIGGER folders_before_update_validate
+  BEFORE UPDATE on folders
+BEGIN
+  SELECT
+    CASE
+      WHEN NEW.name != UPPER(NEW.name) OR NEW.name GLOB '*[^A-Z0-9_-]*' THEN
+        RAISE (ABORT, 'Invalid folder name')
+      WHEN OLD.name = 'GENERAL' AND OLD.name != NEW.name THEN
+        RAISE (ABORT, 'GENERAL folder is protected')
+    END;
+END;
+
+CREATE TRIGGER folders_after_update_update_at
+  AFTER UPDATE ON folders FOR EACH ROW
+    WHEN NEW.update_at = OLD.update_at    --- avoid infinite loop
+BEGIN
+  UPDATE folders SET update_at=CURRENT_TIMESTAMP WHERE name=NEW.name;
+END;
+
+CREATE TRIGGER folders_before_delete_protect
+  BEFORE DELETE on folders FOR EACH ROW
+  WHEN OLD.name = 'GENERAL'
+BEGIN
+  SELECT RAISE (ABORT, 'GENERAL folder is protected');
+END;
 
 INSERT INTO folders (name, description, system, shownew, owner)
-       VALUES ("GENERAL", "Default general bulletin folder.", 1, 1, "SYSTEM");
+       VALUES ('GENERAL', 'Default general bulletin folder.', 1, 1, 'SYSTEM');
+
+CREATE TABLE co_owners (
+  folder      VARCHAR(25)  REFERENCES folders(name) ON UPDATE CASCADE,
+  owner       VARCHAR(25)  REFERENCES users(login) ON UPDATE CASCADE,
+  create_at   TIMESTAMP    DEFAULT CURRENT_TIMESTAMP NOT NULL,
+  update_at   TIMESTAMP    DEFAULT CURRENT_TIMESTAMP NOT NULL,
+  PRIMARY KEY (folder, owner)
+) WITHOUT ROWID;
 
+CREATE TRIGGER co_owners_after_update_update_at
+  AFTER UPDATE ON co_owners FOR EACH ROW
+    WHEN NEW.update_at = OLD.update_at    --- avoid infinite loop
+BEGIN
+  UPDATE co_owners SET update_at=CURRENT_TIMESTAMP WHERE folder=NEW.folder AND owner=NEW.owner;
+END;
diff --git a/repl/command.go b/repl/command.go
index 378d46a922cf2ea6a93dd799b97ff66bb3f67696..77f5d1bf9a2d8ea90ad86092bd3a1de5b084fe1d 100644
--- a/repl/command.go
+++ b/repl/command.go
@@ -9,7 +9,7 @@ var commands = dclish.Commands{
 contains the message.  Otherwise, BULLETIN will prompt for the text.
 BULLETIN will ask for an expiration date and a header to contain the
 topic of the message.
- 
+
   Format:
     ADD [file-name]`,
 		MaxArgs: 1,
@@ -20,8 +20,8 @@ with the /BROADCAST qualifier.  If specified, all terminals are sent the
 message.  Otherwise, only users are sent the message.`,
 			},
 			"/BELL": {
-				Description: `This option is restricted to privileged users.  It is used in conjunction 
-with the /BROADCAST qualifier.  If specified, the bell is rung on the 
+				Description: `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 message is broadcasted.`,
 			},
 			"/BROADCAST": {
@@ -31,12 +31,12 @@ in at the time.  If the folder is remote, a message will be broadcast on
 all nodes which are connected to that folder, unless /LOCAL is specified.
 A node which does not have BULLCP running cannot have a message
 broadcasted to it, (even though it is able to create a remote folder).
- 
+
 See also /ALL and /BELL.`,
 			},
 			"/CLUSTER": {
 				Description: `/[NO]CLUSTER
- 
+
 This option specifies that broadcasted messages should be sent to all
 nodes in the cluster.  /CLUSTER is the default.`,
 			},
@@ -48,7 +48,7 @@ BULLETIN command line.`,
 			},
 			"/EXPIRATION": {
 				Description: `/EXPIRATION=time
- 
+
 Specifies the time at which the message is to expire.  Either absolute
 time: [dd-mmm-yyyy] hh:mm:ss, or delta time: dddd [hh:mm:ss] can be
 used.`,
@@ -62,7 +62,7 @@ suppressed with /NOINDENT.`,
 			},
 			"/FOLDER": {
 				Description: `/FOLDER=(foldername,[...])
- 
+
 Specifies the foldername into which the message is to  be  added.   Does
 not  change the current selected folder.  Folders can be either local or
 remote folders.  Thus, a  nodename  can  precede  the  foldername  (this
@@ -74,11 +74,11 @@ Specifying  remote nodes is only possible if that remote node is running
 a special BULLCP process.  If it isn't, the only way to add messages  to
 that  remote  node is via the /NODE command.  However, /FOLDER is a much
 quicker method, and much more versatile.
- 
+
 You can specify logical names which translate  to  one  or  more  folder
 names.   I.e.   $  DEFINE ALL_FOLDERS "VAX1,VAX2,VAX3", and then specify
 ALL_FOLDERS after /FOLDER=.  Note that the quotation marks are required.
- 
+
 When using /FOLDER for remote nodes, proxy logins are used to  determine
 if privileged options are allowed.  If they are not allowed, the message
 will still be added, but without the privileged settings.`,
@@ -89,7 +89,7 @@ message is broadcasted ONLY on the local node.`,
 			},
 			"/NODES": {
 				Description: `/NODES=(nodes[,...])
- 
+
 Specifies  to send the message to the listed DECNET nodes.  The BULLETIN
 utility  must  be  installed  properly  on  the   other   nodes.    (See
 installation  notes). You can specify a different username to use at the
@@ -97,11 +97,11 @@ other nodes by either using the USERNAME qualifier, or by specifying the
 nodename   with   2   semi-colons   followed   by   the  username,  i.e.
 nodename::username.  If you specify a username, you will be prompted for
 the password of the account on the other nodes.
- 
+
 Additionally,  you  can  specify logical names which translate to one or
 more node names.  I.e.  $ DEFINE ALL_NODES  "VAX1,VAX2,VAX3",  and  then
 specify /NODES=ALL_NODES.  Note that the quotation marks are required.
- 
+
 NOTE:  It  is  preferable  to  use /FOLDER instead of /NODE if possible,
 since adding messages via /FOLDER is much quicker.`,
 			},
@@ -120,7 +120,7 @@ user has privileges.`,
 			},
 			"/SUBJECT": {
 				Description: `/SUBJECT=description
- 
+
 Specifies the subject of the message to be added.`,
 			},
 			"/SHUTDOWN": {
@@ -128,12 +128,12 @@ Specifies the subject of the message to be added.`,
 This option is restricted to privileged users.  If specified, message
 will be automatically deleted after a computer shutdown has occurred.
 This option is restricted to SYSTEM folders.
- 
+
 If the bulletin files are shared between cluster nodes, the message
 will be deleted after the node on which the message was submitted from
 is rebooted.  If you wish the message to be deleted after a different
 node reboots, you have the option of specifying that node name.
- 
+
 NOTE: If the folder is a remote folder, the message will be deleted
 after the remote node reboots, not the node from which the message was
 added.  The nodename cannot be specified with a remote folder.`,
@@ -160,7 +160,7 @@ useful for scanning a long message.`,
 			},
 			"/HEADER": {
 				Description: `/[NO]HEADER
- 
+
 Specifies that if a message header exists, the header will be shown.
 If /HEADER or /NOHEADER is specified, the setting will apply for all
 further reads in the selected folder.  The default is /HEADER.`,
@@ -185,7 +185,7 @@ are to be changed.  If the text of the message is to be changed, a file can
 be specified which contains the text.  If the editor is used for changing
 the text, the old message text will be extracted.  This can be suppressed
 by the qualifier /NEW.
- 
+
   Format:
     CHANGE [file-name]`,
 		MaxArgs: 1,
@@ -203,7 +203,7 @@ added /EDIT to your BULLETIN command line.`,
 			},
 			"/EXPIRATION": {
 				Description: `/EXPIRATION[=time]
- 
+
 Specifies the time at which the message is to expire.  Either absolute
 time: [dd-mmm-yyyy] hh:mm:ss, or delta time: dddd [hh:mm:ss] can be
 used.  If no time is specified, you will be prompted for the time.`,
@@ -223,12 +223,12 @@ new text is to be read in.`,
 			},
 			"/NUMBER": {
 				Description: `/NUMBER=message_number[-message_number1]
- 
-Specifies the message or messages to be replaced. If this qualifier is 
+
+Specifies the message or messages to be replaced. If this qualifier is
 omitted, the message that is presently being read will be replaced.
 A range of messages can be specified, i.e. /NUMBER=1-5.  Only the expiration
 date and message headers can be changed if a range is specified.
- 
+
 The key words CURRENT and LAST can also be specified in the range,
 in place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc.`,
 			},
@@ -241,7 +241,7 @@ shutdown.  This option is restricted to SYSTEM folders.`,
 			},
 			"/SUBJECT": {
 				Description: `/SUBJECT=description
- 
+
 Specifies the subject of the message to be added.`,
 			},
 			"/SYSTEM": {
@@ -256,15 +256,15 @@ privileged command and is restricted to SYSTEM folders.`,
 	"COPY": {
 		Description: `Copies a message to another folder  without  deleting  it  from  the
 current folder.
- 
+
   Format:
- 
+
     COPY folder-name [message_number][-message_number1]
- 
+
 The folder-name is the name of the folder to which the message is to be
 copied to.  Optionally, a range of messages which are to be copied can be
 specified following the folder name, i.e. COPY NEWFOLDER 2-5.
- 
+
 The key words CURRENT and LAST can also be specified in the range,
 in place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc.`,
 		MinArgs: 1,
@@ -275,14 +275,14 @@ in place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc.`,
 			},
 			"/HEADER": {
 				Description: `/[NO]HEADER
- 
+
 Valid only if destination folder is a news group.  Specifies that header
 of message is to be included with the text when the text is copied.
 The default is /NOHEADER.`,
 			},
 			"/MERGE": {
 				Description: `Specifies that the original date and time of the copied messages are
-saved and that the messages are placed in correct chronological order 
+saved and that the messages are placed in correct chronological order
 in the new folder.  This operation is lengthy if the new folder is large.`,
 			},
 			"/ORIGINAL": {
@@ -300,14 +300,14 @@ to  specified  users.   Once  created,  that  message  is  automatically
 selected  (see information on SELECT command).  The commands that can be
 used to modify the folder's characteristics  are:  MODIFY,  REMOVE,  SET
 ACCESS, SET BBOARD, SET NODE, and SET SYSTEM.
- 
+
   Format:
     CREATE folder-name
- 
+
 The  folder-name is limited to 25 letters and must not include spaces or
 characters that are also invalid  in  filenames  (this  is  because  the
 folder is stored in a file name created with the folder name).
- 
+
 NOTE:  Creation  of folders may be a restricted command if the installer
 has  elected  to  install  it  as  such.   This  is  done  by  modifying
 BULLCOM.CLD.`,
@@ -332,26 +332,26 @@ more information.)`,
 			},
 			"/DESCRIPTION": {
 				Description: `/DESCRIPTION=description
- 
+
 Specifies the description of the folder, which is displayed using the
 SHOW FOLDER command.  If omitted, you are prompted for a description.
- 
+
 If this folder is to receive messages from a network mailing list
 via the BBOARD feature, and you wish to use the POST and RESPOND/LIST
 commands, the address of the mailing list should be included in the
 description.  This is done by enclosing the address using <> and
 placing it at the end of the description, i.e.
- 
+
               INFOVAX MAILING LIST <INFO-VAX@KL.SRI.COM>
- 
+
 If a mailer protocol is needs to be added to the network address in
 order for it to be sent by VMS MAIL, i.e. protocol%"address",  the
 appropriate protocol can be specified by either hardcoding it into the
 file BULLNEWS.INC before compiling BULLETIN, or by defining the system
 logical name BULL_NEWS_MAILER (it is the same protocol used by the NEWS
 feature in order to respond to NEWS messages).  The default protocol is
-IN%.  If desired, you can specify the protocol with the address, i.e. 
- 
+IN%.  If desired, you can specify the protocol with the address, i.e.
+
               INFOVAX MAILING LIST <IN%"INFO-VAX@KL.SRI.COM">`,
 			},
 			"/ID": {
@@ -360,12 +360,12 @@ identifier.  The creator's process must have the identifier presently
 assigned to it.  Any process which has that identifier assigned to it
 will be able to control the folder as if it were the folder's owner.
 This is used to allow more than one use to control a folder.
- 
+
 Note: This feature will not work during remote access to the folder.`,
 			},
 			"/NODE": {
 				Description: `/NODE=node
- 
+
 Specifies that the folder is a remote folder at the specified node.
 A remote folder is a folder in which the messages are actually stored
 on a folder at a remote DECNET node.  The specified node is checked to
@@ -379,7 +379,7 @@ between more than one node. This capability is only present if the BULLCP
 process is running on the remote node via the BULL/STARTUP command.
 If the remote folder name is different from the local folder name, the
 remote folder name is specified using the /REMOTENAME qualifier.
- 
+
 NOTE: If a message is added to a remote node, the message is stored
 immediately.  However, a user logging into another node might not be
 immediately alerted that the message is present.  That information is
@@ -433,7 +433,7 @@ respect to adding or modifying messages.  All users can read the folder.`,
 				Description: `Specifies that the folder is a SYSTEM folder.  A SYSTEM folder is
 allowed to have SYSTEM and SHUTDOWN messages added to it.  By default,
 the GENERAL folder is a SYSTEM folder.  This is a privileged command.
- 
+
 If this is a remote folder, /SYSTEM cannot be specified unless the
 folder at the other node is also a SYSTEM folder.`,
 			},
@@ -443,9 +443,9 @@ folder at the other node is also a SYSTEM folder.`,
 		Description: `Displays the beginning of the message you are currently reading.  If
 you  are  reading  a long message and want to display the first part
 of the message again, you can enter the CURRENT command.
- 
+
   Format:
- 
+
     CURRENT`,
 		Flags: dclish.Flags{
 			"/EDIT": {
@@ -454,7 +454,7 @@ useful for scanning a long message.`,
 			},
 			"/HEADER": {
 				Description: `/[NO]HEADER
- 
+
 Specifies that if a message header exists, the header will be shown.
 If /HEADER or /NOHEADER is specified, the setting will apply for all
 further reads in the selected folder.  The default is /HEADER.`,
@@ -468,15 +468,15 @@ delete a message.  Note that the message is not deleted immediately, but
 its expiration is set 15 minutes in the future.  This is to allow a user
 to recover the message using the UNDELETE command.  If you want the
 message deleted immediately, use the /IMMEDIATE qualifier.
- 
+
   Format:
     DELETE [message_number][-message_number1]
- 
+
 The message's relative number is found by the DIRECTORY command.  It is
 possible to delete a range of messages by specifying two numbers
 separated by a dash, i.e. DELETE 1-5.  However, a range cannot be
 specified if the folder is remote.
- 
+
 The key words CURRENT and LAST can also be specified in the range,
 in place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc.`,
 		MaxArgs: 1,
@@ -491,7 +491,7 @@ remote folder at a time.`,
 			},
 			"/NODES": {
 				Description: `/NODES=(nodes[,...])
- 
+
 Specifies to delete the message at the listed DECNET nodes.  The BULLETIN
 utility must be installed properly on the other nodes.  You can specify
 a different username to use at the other nodes by either using the
@@ -500,14 +500,14 @@ followed by the username, i.e. nodename::username.  If you specify a
 username, you will be prompted for the password of the account on the
 other nodes.  The /SUBJECT must be specified to identify the specific
 message that is to be deleted.
- 
+
 Additionally, you can specify logical names which translate to one or
 more node names.  I.e.  $ DEFINE ALL_NODES "VAX1,VAX2,VAX3", and then
 specify /NODES=ALL_NODES.  Note that the quotation marks are required.`,
 			},
 			"/SUBJECT": {
 				Description: `/SUBJECT=subject
- 
+
 Specifies the subject of the bulletin to be deleted at a remote DECNET
 node.  The DECNET node must be specified with the /NODE qualifier.
 The specified subject need not be the exact subject of the message.
@@ -524,11 +524,11 @@ on other DECNET nodes via the /NODE qualifier.`,
 	"DIRECTORY": {
 		Description: `Lists a summary of the messages.  The message number, submitter's name,
 date, and subject of each message is displayed.
- 
+
   Format:
- 
+
     DIRECTORY [folder]
- 
+
 If  a  folder is specified, that folder is selected before the directory
 is listed.  Unless otherwise specified, listing starts  with  the  first
 newest message.  If there are no new messages, listing will start at the
@@ -550,7 +550,7 @@ folder.`,
 			},
 			"/END": {
 				Description: `/END=message_number
- 
+
 Indicates the last message number you want to display.`,
 			},
 			"/FOLDERS": {
@@ -572,7 +572,7 @@ to be read.  To see all messages, use either /ALL, or reselect the
 folder.`,
 			},
 			"/SEEN": {
-				Description: `Lists messages that have been seen (indicated by a greater than sign). 
+				Description: `Lists messages that have been seen (indicated by a greater than sign).
 Using /SEEN is equivalent to selecting the folder with /SEEN, i.e. only
 seen messages will be shown and be able to be read.  To see all
 messages, use either /ALL, or reselect the folder.`,
@@ -600,27 +600,27 @@ are to be displayed.  This cannot be used in conjunction with /MARKED.`,
 			},
 			"/SEARCH": {
 				Description: `/SEARCH=[string]
- 
+
 Specifies that only messages which contain the specified string are
 to be displayed.  This cannot be used in conjunction with /MARKED.
 If no string is specified, the previously specified string is used.`,
 			},
 			"/SINCE": {
 				Description: `/SINCE=date
- 
+
 Displays a listing of all the messages created on or after the
 specified date.  If no date is specified, the default is TODAY.`,
 			},
 			"/START": {
 				Description: `/START=message_number
- 
+
 Indicates the first message number you want to display.  For example,
 to  display  all the messages beginning with number three, enter the
 command line DIRECTORY/START=3.  Not valid with /FOLDER.`,
 			},
 			"/SUBJECT": {
 				Description: `/SUBJECT=[string]
- 
+
 Specifies that only messages which contain the specified string in it's
 subject header are to be displayed.  This cannot be used in conjunction
 with /MARKED.  If no string is specified, the previously specified string
@@ -639,13 +639,13 @@ is used.`,
 		Description: `Copies the current message to the named file.  The file-name parameter
 is required.  If the file exists, the message is appended to the file,
 unless the /NEW qualifier is specified.
- 
+
   Format:
     FILE filename [message_number][-message_number1],[...]
- 
+
 A range of messages to be copied can optionally be specified, i.e.
 FILE 2-5.
- 
+
 The key words CURRENT and LAST can also be specified in the range,
 in place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc.`,
 		MinArgs: 1,
@@ -659,8 +659,8 @@ in place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc.`,
 			},
 			"/HEADER": {
 				Description: `/[NO]HEADER
- 
-Controls whether a header containing the owner, subject, and date of the 
+
+Controls whether a header containing the owner, subject, and date of the
 message is written in the file.  The default is to write the header.`,
 			},
 			"/NEW": {
@@ -677,8 +677,10 @@ file exists, the file would be appended to that file.`,
 	},
 	"HELP": {
 		Description: `To obtain help on any topic, type:
- 
-        HELP  topic`,
+
+        HELP  topic
+
+Type "HELP Topics" to get a list of topics.`,
 		MaxArgs: 1,
 		Action:  ActionHelp,
 	},
@@ -688,7 +690,7 @@ INDEX command is re-entered while the listing is in progress, the listing
 will skip to the next folder.  This is useful for skipping a particular
 folder.  It also can be used to continue the listing from where one left
 off after one has read a message.
- 
+
   Format:
        INDEX`,
 		Action: ActionIndex,
@@ -705,7 +707,7 @@ with /UNMARKED, i.e. only unmarked messages will be shown and be able
 to be read.`,
 			},
 			"/SEEN": {
-				Description: `Lists messages that have been seen (indicated by a greater than sign). 
+				Description: `Lists messages that have been seen (indicated by a greater than sign).
 Using /SEEN is equivalent to selecting the folder with /SEEN, i.e. only
 seen messages will be shown and be able to be read.`,
 			},
@@ -755,7 +757,7 @@ first folder.`,
 	},
 	"LAST": {
 		Description: `Displays the last message in the current folder.
- 
+
   Format:
        LAST`,
 		Flags: dclish.Flags{
@@ -765,7 +767,7 @@ useful for scanning a long message.`,
 			},
 			"/HEADER": {
 				Description: `/[NO]HEADER
- 
+
 Specifies that if a message header exists, the header will be shown.
 If /HEADER or /NOHEADER is specified, the setting will apply for all
 further reads in the selected folder.  The default is /HEADER.`,
@@ -775,11 +777,11 @@ further reads in the selected folder.  The default is /HEADER.`,
 	"MAIL": {
 		Description: `Invokes the VAX/VMS Personal Mail Utility (MAIL) to send the message
 which you are reading to the specified recipients.
- 
+
   Format:
- 
+
     MAIL recipient-name[s]
- 
+
 The input for the recipient name is exactly the same format as used by
 the MAIL command at DCL level.  Note that this means when specifying an
 address that has quotes, in order to pass the quotes you must specify
@@ -794,16 +796,16 @@ mailing it.`,
 			},
 			"/HEADER": {
 				Description: `/[NO]HEADER
- 
-Controls whether a header containing the owner, subject, and date of the 
+
+Controls whether a header containing the owner, subject, and date of the
 message is written in the mail.  The default is to write the header.`,
 			},
 			"/SUBJECT": {
 				Description: `/SUBJECT=text
- 
+
 Specifies the subject of the mail message. If the text consists of more
 than one word, enclose the text in quotation marks (").
- 
+
 If you omit this qualifier, the description of the message will be used
 as the subject.`,
 			},
@@ -815,12 +817,12 @@ displayed with an asterisk in the left hand column of the directory
 listing.  A marked message can serve as a reminder of important
 information.  The UNMARK command sets the current or message-id message
 as unmarked.
- 
+
    Format:
- 
+
        MARK [message-number or numbers]
        UNMARK [message-number or numbers]
- 
+
 NOTE: The list of marked messages are stored in a file username.BULLMARK.
 The files are created in the directory pointed to by the logical name
 BULL_MARK.  If BULL_MARK is not defined, SYS$LOGIN will be used.`,
@@ -832,12 +834,12 @@ displayed with an asterisk in the left hand column of the directory
 listing.  A marked message can serve as a reminder of important
 information.  The UNMARK command sets the current or message-id message
 as unmarked.
- 
+
    Format:
- 
+
        MARK [message-number or numbers]
        UNMARK [message-number or numbers]
- 
+
 NOTE: The list of marked messages are stored in a file username.BULLMARK.
 The files are created in the directory pointed to by the logical name
 BULL_MARK.  If BULL_MARK is not defined, SYS$LOGIN will be used.`,
@@ -845,23 +847,23 @@ BULL_MARK.  If BULL_MARK is not defined, SYS$LOGIN will be used.`,
 	},
 	"MODIFY": {
 		Description: `Modifies the database information for the current folder.  Only the
-owner of the folder or a user with privileges can use this command. 
- 
+owner of the folder or a user with privileges can use this command.
+
   Format:
- 
+
     MODIFY`,
 		Action: ActionModify,
 		Flags: dclish.Flags{
 			"/DESCRIPTION": {
 				Description: `Specifies a new description for the folder.  You will be prompted for
 the text of the description.
- 
+
 NOTE: If this folder is to receive messages from a network mailing list
 via the BBOARD feature, and you wish to use the POST and RESPOND/LIST
 commands, the address of the mailing list should be included in the
 description.  This is done by enclosing the address using <> and
 placing it at the end of the description, i.e.
- 
+
               INFOVAX MAILING LIST <IN%"INFO-VAX@KL.SRI.COM">`,
 			},
 			"/ID": {
@@ -870,17 +872,17 @@ identifier.  The creator's process must have the identifier presently
 assigned to it.  Any process which has that identifier assigned to it
 will be able to control the folder as if it were the folder's owner.
 This is used to allow more than one use to control a folder.
- 
+
 Note: This feature will not work during remote access to the folder.`,
 			},
 			"/NAME": {
 				Description: `/NAME=foldername
- 
+
 Specifies a new name for the folder.`,
 			},
 			"/OWNER": {
 				Description: `/OWNER=username
- 
+
 Specifies a new owner for the folder.  If the owner does not have
 privileges, BULLETIN will prompt for the password of the new owner
 account in order to okay the modification.  See also /ID.`,
@@ -890,17 +892,17 @@ account in order to okay the modification.  See also /ID.`,
 	"MOVE": {
 		Description: `Moves a message to another  folder and deletes it from  the  current
 folder.
- 
+
   Format:
- 
+
     MOVE folder-name [message_number][-message_number1]
- 
+
 The folder-name is the name of the folder to which the message is to be
 be moved to.  Optionally, a range of messages which are to be moved can be
 specified following the folder name, i.e. COPY NEWFOLDER 2-5.  However,
 if the old folder is remote, they will be copied but not deleted, as
 only one message can be delted from a remote folder at a time.
- 
+
 The key words CURRENT and LAST can also be specified in the range,
 in place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc.`,
 		MinArgs: 1,
@@ -913,7 +915,7 @@ message can be deleted from a remote folder at a time.`,
 			},
 			"/MERGE": {
 				Description: `Specifies that the original date and time of the moved messages are
-saved and that the messages are placed in correct chronological order 
+saved and that the messages are placed in correct chronological order
 in the new folder.  This operation is lengthy if the new folder is large.`,
 			},
 			"/ORIGINAL": {
@@ -934,7 +936,7 @@ useful for scanning a long message.`,
 			},
 			"/HEADER": {
 				Description: `/[NO]HEADER
- 
+
 Specifies that if a message header exists, the header will be shown.
 If /HEADER or /NOHEADER is specified, the setting will apply for all
 further reads in the selected folder.  The default is /HEADER.`,
@@ -942,22 +944,22 @@ further reads in the selected folder.  The default is /HEADER.`,
 		},
 	},
 	"PRINT": {
-		Description: `Queues a copy of the message you are currently  reading  (or  have 
+		Description: `Queues a copy of the message you are currently  reading  (or  have
 just read)  for  printing.   The file created by the PRINT command
 is not released to the print queue until you exit, unless you add
 the qualifier /NOW or change one of the print job's qualifiers.
 Multiple messages are concatenated into one print job.
- 
+
    Format:
- 
+
        PRINT [message_number][-message_number1],[...]
- 
+
 A range of messages to be printed can optionally be specified, i.e.
 PRINT 2-5.
- 
+
 The key words CURRENT and LAST can also be specified in the range,
 in place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc.
- 
+
 NOTE:  The qualifier /PRINT is present on the DIRECTORY command.  This
 provides more flexibility than is present with the PRINT command.  For
 example, if you want to print all messages with a particular string in
@@ -983,13 +985,13 @@ queue specifying the new form type as the mounted form.)`,
 			},
 			"/HEADER": {
 				Description: `/[NO]HEADER
- 
-Controls whether a header containing the owner, subject, and date of the 
+
+Controls whether a header containing the owner, subject, and date of the
 message is printed at the beginning. The default is to write the header.`,
 			},
 			"/NOTIFY": {
 				Description: `/[NO]NOTIFY
- 
+
 Indicates that you will be notified by a broadcast message  when  the
 file or files have been printed.  If /NONOTIFY is specified, there
 is no notification.  The default is /NOTIFY.`,
@@ -1000,7 +1002,7 @@ command during this session to the printer.`,
 			},
 			"/QUEUE": {
 				Description: `/QUEUE=queue_name
- 
+
 The name of the queue to which a message is to be sent.  If the /QUEUE
 qualifier  is  not  specified,  the message is queued to SYS$PRINT.`,
 			},
@@ -1012,18 +1014,18 @@ the first time you enter the command, the first message  in  the  folder
 will  be  displayed.   However, if there are new messages, the first new
 message will be displayed.  Each time you enter the  command,  the  next
 page, or if there are no more pages, the next message will be displayed.
- 
+
   Format:
     READ [message-number]
- 
+
 The message's relative number is found by the DIRECTORY command.
 If you specify a number greater than the number of messages in the
 folder, the last message in the folder will be displayed.
- 
+
 NOTE: The READ command can be abbreviated by omitting the READ command,
 i.e. typing the command "2" is equivalent to "READ 2", and simply
-hitting the <RETURN> key is equivalent to "READ". 
- 
+hitting the <RETURN> key is equivalent to "READ".
+
 BULLETIN normally stores only the latest message that has been read per
 folder. It can optionally store and display which messages have been
 read in a folder on a per message basis.  For information on this, see
@@ -1040,7 +1042,7 @@ useful for scanning a long message.`,
 			},
 			"/HEADER": {
 				Description: `/[NO]HEADER
- 
+
 Specifies that if a message header exists, the header will be shown.
 If /HEADER or /NOHEADER is specified, the setting will apply for all
 further reads in the selected folder.  The default is /HEADER.`,
@@ -1077,7 +1079,7 @@ reselect the folder.`,
 			},
 			"/PAGE": {
 				Description: `/[NO]PAGE
- 
+
 Specifies that the display of the message will pause when it reaches the
 end of the page.  If /NOPAGE is specified, the whole message will be
 displayed.  This is useful for terminals that can store more than one
@@ -1086,7 +1088,7 @@ the contents of the terminal's memory.`,
 			},
 			"/SINCE": {
 				Description: `/SINCE=date
- 
+
 Specifies to read the first message created on or after the specified
 date.  If no date is specified, the default is TODAY.`,
 			},
@@ -1095,7 +1097,7 @@ date.  If no date is specified, the default is TODAY.`,
 	"REMOVE": {
 		Description: `Removes a folder.  Only the owner of a folder or a privileged  user  can
 remove the folder.
- 
+
   Format:
     REMOVE folder-name`,
 		MinArgs: 1,
@@ -1105,7 +1107,7 @@ remove the folder.
 		Description: `Adds message with subject of message being the subject of the  currently
 read message with "RE:" preceeding it.  Format and qualifiers is exactly
 the same as the ADD command except for /NOINDENT and /EXTRACT.
- 
+
   Format:
     REPLY [file-name]`,
 		MaxArgs: 1,
@@ -1124,10 +1126,10 @@ This can be suppressed with /NOINDENT.`,
 	"RESPOND": {
 		Description: `Invokes the VAX/VMS Personal Mail Utility (MAIL) to send a reply mail
 message to the owner of the currently read message.
- 
+
   Format:
     RESPOND [file-name]
- 
+
 If you wish to use another method for sending the mail, define BULL_MAILER
 to point to a command procedure.  This procedure will then be executed in
 place of MAIL, and the parameters passed to it are the username and subject
@@ -1164,10 +1166,10 @@ See the help topic POST Signature_file for signature information.`,
 			},
 			"/SUBJECT": {
 				Description: `/SUBJECT=text
- 
+
 Specifies the subject of the mail message. If the text consists of more
 than one word, enclose the text in quotation marks (").
- 
+
 If you omit this qualifier, the description of the message will be used
 as the subject preceeded by "RE: ".`,
 			},
@@ -1180,11 +1182,11 @@ as the subject preceeded by "RE: ".`,
 	"SEARCH": {
 		Description: `Searches the currently selected folder for the  message  containing  the
 first occurrence of the specified text string.
- 
+
    Format:
- 
+
        SEARCH [search-string]
- 
+
 The search starts from the first message in the current folder.  The
 search includes both the text of the message, and the description header.
 If a "search-string" is not specified, a search is made using the
@@ -1199,7 +1201,7 @@ search can be aborted by typing a CTRL-C.`,
 			},
 			"/FOLDER": {
 				Description: `/FOLDER=(folder,[...])
- 
+
 Specifies a list of folders to be searched.  The search will start by
 selecting the first folder in the list and searching the messages for
 a match.  If, during a search, no more matches or messages are found,
@@ -1219,7 +1221,7 @@ message.`,
 			},
 			"/START": {
 				Description: `/START=message_number
- 
+
 Specifies the message number to start the search at.`,
 			},
 			"/SUBJECT": {
@@ -1233,17 +1235,17 @@ track of messages on a per message basis.  Seen messages are displayed
 with a greater than sign in the left hand column of the directory
 listing.  Once you have used the SEEN command once, messages will be
 automatically be set as being SEEN when they are read.  The UNSEEN
-command sets the current or message-id message as unseen. 
- 
+command sets the current or message-id message as unseen.
+
    Format:
- 
+
        SEEN [message-number or numbers]
        UNSEEN [message-number or numbers]
- 
+
 If you have used the SEEN command and wish to disable the automatic
 marking of messages in regular folders as SEEN when they are read, type
 the command SEEN/NOREAD.  To reenable, simply use the SEEN command again.
- 
+
 NOTE: The list of SEEN messages are stored in a
 file username.BULLMARK.  NEWSMARK. The files are created in the directory
 pointed to by the logical name BULL_MARK.  If BULL_MARK is not defined,
@@ -1257,17 +1259,17 @@ track of messages on a per message basis.  Seen messages are displayed
 with a greater than sign in the left hand column of the directory
 listing.  Once you have used the SEEN command once, messages will be
 automatically be set as being SEEN when they are read.  The UNSEEN
-command sets the current or message-id message as unseen. 
- 
+command sets the current or message-id message as unseen.
+
    Format:
- 
+
        SEEN [message-number or numbers]
        UNSEEN [message-number or numbers]
- 
+
 If you have used the SEEN command and wish to disable the automatic
 marking of messages in regular folders as SEEN when they are read, type
 the command SEEN/NOREAD.  To reenable, simply use the SEEN command again.
- 
+
 NOTE: The list of SEEN messages are stored in a
 file username.BULLMARK.  NEWSMARK. The files are created in the directory
 pointed to by the logical name BULL_MARK.  If BULL_MARK is not defined,
@@ -1281,19 +1283,19 @@ folder.   Once a folder has been selected, all commands, i.e. DIRECTORY,
 READ, etc. will apply only to those messages.  Use the CREATE command to
 create  a  folder.   Use the DIRECTORY/FOLDER command to see the list of
 folders that have been created.
- 
+
  Format:
- 
+
      SELECT [node-name::][folder-name]
- 
+
 The complete folder name need not be specified.  BULLETIN  will  try  to
 find the closest matching name.  I.e. INFOV can be used for INFOVAX.
- 
+
 Omitting the folder name will select the default general messages.
- 
+
 The  node  name can be specified only if the remote node has the special
 BULLCP process running (invoked by BULLETIN/STARTUP command.)
- 
+
 After selecting a folder, the user will notified of the number of unread
 messages,  and  the  message  pointer will be placed at the first unread
 message.`,
@@ -1310,20 +1312,20 @@ to be reselected.`,
 	"SET": {
 		Description: `The SET command  is  used  with  other  commands  to  define  or  change
 characteristics of the BULLETIN Utility.
- 
+
   Format:
- 
+
     SET option`,
 		Flags: dclish.Flags{
 			"ACCESS": {
 				Description: `Controls  access  to  a  private  folder.   A private folder can only be
 selected by users who have been granted access.  Only the owner of  that
 folder is allowed to grant access.
- 
+
   Format:
- 
+
     SET [NO]ACCESS id-name [folder-name]
- 
+
 The id-name can be one or more ids from the system Rights  Database  for
 which  access  is  being  modified.   It  can  also be a file name which
 contains a list of  ids.   For  more  information  concerning  usage  of
@@ -1331,7 +1333,7 @@ private  folders, see HELP CREATE /PRIVATE.  NOTE: Access is created via
 ACLs.  If a user's process privileges are set  to  override  ACLs,  that
 user  will  be  able  to  access  the folder even if access has not been
 granted.
- 
+
 It  is suggested that if you plan on granting access to many users, that
 you create an id using the AUTHORIZE utility and then use the SET ACCESS
 command  to  grant  access  to  that id.  Then, you can use the GRANT/ID
@@ -1341,7 +1343,7 @@ running into system quota when checking for acls on a file with a  large
 amount  of  acls.   It  is also means that you don't have to remember to
 remove the access for that user from a folder if that  user  is  removed
 from the system.
- 
+
 A user with BULLETIN privileges (see HELP SET  PRIV)  will  be  able  to
 select a protected folder regardless of the access settings.  However, a
 user without explicit access will not receive login notifications of new
@@ -1357,7 +1359,7 @@ comma must be enclosed in quotes.   UICs  can  contain  wildcards,  i.e.
 id SYS$NODE_nodename, where nodename is the decnet nodename.   Thus,  by
 specifing  this id, a folder can be restricted to a specific node, which
 is useful when the folder is shared among nodes in a cluster.
- 
+
 Alternatively,  the  id-name  can be a filename which contains a list of
 ids.  The filename should be preceeded by a "@".  If the suffix  is  not
 specified, it will be assumed that the suffix is ".DIS" .
@@ -1367,9 +1369,9 @@ is  not  specified,  the  folder will no longer be private.  If /READ is
 specified, all users will have read access, but  only  privileged  users
 will  have  write access (of course non-privileged users can gain access
 via a later SET ACCESS command.)
- 
+
 Format:
- 
+
     SET ACCESS /ALL [folder-name]
 3 /READ
 Specifies that access to the folder will be limited to being able to
@@ -1394,9 +1396,9 @@ than just once.  Non-SYSTEM message will also be  displayed  every  time
 the user actually reads that message (or a later one).  This feature  is
 meant  for  messages which are very important, and thus you want to make
 sure they are read.
- 
+
   Format:
- 
+
     SET [NO]ALWAYS`,
 			},
 			"BBOARD": {
@@ -1413,19 +1415,19 @@ which is spawned to read the mail.  The  parameters  and  the  suggested
 values  are:  PQL_DPGFLQUOTA = 10000, PQL_DWSQUOTA = 500, and PQL_DFILLM
 = 30.  If you are not using the BULLCP process, the subprocess limit for
 users must be at least 2.
- 
+
   Format:
- 
+
     SET BBOARD [username]
- 
+
 BBOARD cannot be set for remote folders.   See  also  the  command  SET
 DIGEST for options on formatting BBOARD messages.
- 
+
 If BULLCP is running, BBOARD is updated every 15 minutes.  If you want
 to length this period, define BULL_BBOARD_UPDATE to be the number of
 minutes, between updates.  I.e. DEFINE/SYSTEM BULL_BBOARD_UPDATE "30"
 will cause the updates to be don every 30 minutes.
- 
+
 NOTE: If you want to control the expiration date on a per message basis,
 you can do so by adding a special header line to the message.  The form
 is Expires: or X-Expires: followed by the date in the form DD MMM YYYY.
@@ -1433,12 +1435,12 @@ The time will always be 00:00, even if the time is specified on the line.
 3 /EXPIRATION
  /EXPIRATION=days
  /NOEXPIRATION
- 
+
 Specifies the number of days the message created by the BBOARD is to  be
 retained.   The  default  is  14  days.   The  highest limit that can be
 specified is 30 days.  This can be overridden by a user with privileges.
 If /NOEXPIRATION is specified, messages will become permanent.
- 
+
 NOTE:  This  value is the same value as specified by SET DEFAULT_EXPIRE.
 If one is changed, the other will change also.
 3 /SPECIAL
@@ -1461,37 +1463,37 @@ This  problem  is  solved  by  placing  the  word LISTSERV in the folder
 description line. Then, messages sent to the mailing list  by  the  POST
 command will be sent from the BBOARD account rather than from the user's
 account.  For example, the folder description might be:
- 
+
 FAKE MAILING LIST <FAKELIST@FAKENODE.BITNET> LISTSERV.
- 
+
 If  you  have  PMDF  or  MX  installed,  the  corresponding logical name
 PMDF_REPLY_TO or MX_REPLY_TO will be temporarily defined in order to add
 a  REPLY-TO:   line  to  the  message  header to display the real user's
 address.
- 
+
 Users  who  use the method described in HELP SET BBOARD MORE_INFORMATION
 should note the following:  When using this LISTSERV feature, the BBOARD
 account  must be a real account, not simply a VMS MAIL forwarding entry.
 Mail can only be sent from a real account.  However, if mail  forwarding
 is  set for that the account, the account does not need a real directory
 or a unique uic, since it will not need space to store mail.
- 
+
 In order to be able to send LISTSERV commands from  the  BBOARD  account
 without  having  to  actually  login  to  the BBOARD account, there is a
 utility included with BULLETIN called SETUSER.  This requires privileges
 to use.  After compiling it, use the link command:
- 
+
 	LINK SETUSER,SYS$SYSTEM:SYS.STB/SELECT
- 
+
 When  you  run  it, it will prompt for a username.  After verifying that
 the given username  is  a  valid  account,  it  will  then  change  your
 process's username.  You can then send mail from that account.
- 
+
 If you are using PMDF or MX, and wish to use this feature, you can still
 do  so  by  setting BBOARD.  As long as the BBOARD account is not a real
 account, it will work properly, even though the mail feed is not  really
 coming from the BBOARD account.
- 
+
 In order to find out if the LISTSERV mailing list will accept posts only
 from subscribed users, send  the  command  'REV  listname'.   This  will
 retrieve the file listname.LIST.  It begins with a list of keywords.  If
@@ -1501,16 +1503,16 @@ of the keywords and the meaning of their settings, send any LISTSERV the
 command  'INFO  KEY'. Note that the 'listname.LIST' files include a list
 of owners and subscribers.  If 'send' is set to 'owners',  then  neither
 the public nor the subscribers can post to the list.
- 
+
 3 More_information
 If more than one folder is to have a BBOARD setting,  only  one  of  the
 BBOARD  names  need  be  a real account.  All other names could be names
 whose mail is  forwarded  to  the  real  account.   BULLETIN  will  then
 determine  from  the mail header which folder the mail is to be sent to.
 Forwarding can be enabled for any name within MAIL by the command:
- 
+
     MAIL> SET FORWARD/USER=from_name to_name
- 
+
 Any  mail  sent  to  FROM_NAME will be forwarded to TO_NAME.  Thus, only
 TO_NAME need be a real account.  For example, if you  have  INFOVAX  and
 LASER-LOVERS  folders,  you need create only a INFOVAX account, and then
@@ -1523,7 +1525,7 @@ the  /SPECIAL  set  on  their  BBOARD  accounts  cannot  have their mail
 forwarded to BBOARD accounts that don't have /SPECIAL set.   Folders  of
 the  same  type, i.e. that use the same /SPECIAL command procedure, must
 be grouped separately.
- 
+
 The BBOARD account must match the mailing list name.  If you prefer  not
 to  have  them  match,  then  you must include the actual address of the
 mailing list in the folder description in  the  format  described  under
@@ -1537,9 +1539,9 @@ BULLETIN.   Note  the  difference between BRIEF and READNEW.  The latter
 causes a listing of the description of the new messages to be  displayed
 and  prompts  the user to read the messages.  Setting BRIEF will clear a
 READNEW setting (and visa versa).
- 
+
   Format:
- 
+
     SET [NO]BRIEF
 3 /ALL
 Specifies that the SET [NO]BRIEF option is the default for all users for
@@ -1550,12 +1552,12 @@ folder.  This is a privileged qualifier.  It will only affect brand new
 users (or those that have never logged in).  Use /ALL to modify all users.
 3 /FOLDER
    /FOLDER=foldername
- 
+
 Specifies the folder for which the option is to modified.  If not
 specified, the selected folder is modified. Valid only with NOBRIEF.
 3 /PERMANENT
    /[NO]PERMANENT
- 
+
 Specifies that BRIEF is a permanent flag and cannot be changed by the
 individual, except if changing to SHOWNEW or READNEW.  This is a
 privileged qualifier.`,
@@ -1566,11 +1568,11 @@ the notification message "there are new messages" will be displayed every
 time when logging in, until the new messages are read.  Normally, the
 BRIEF setting causes notification only at the first time that new messages
 are detected.
- 
+
   Format:
- 
+
     SET [NO]CONTINUOUS_BRIEF
- 
+
 NOTE: Both SET GENERIC and SET CONTINUOUS_BRIEF cannot be set for the
 same user.`,
 			},
@@ -1579,21 +1581,21 @@ same user.`,
 PMDF path) is to be retained.  The default  is  14  days.   The  highest
 limit  that  can  be  specified is 30 days.  This can be overridden by a
 user with privileges.
- 
+
 This  also  specifies the default expiration date when adding a message.
 If no expiration date is  entered  when  prompted  for  a  date,  or  if
 prompting  has been disabled via SET NOPROMPT_EXPIRE, this value will be
 used.
- 
+
   Format:
- 
+
     SET DEFAULT_EXPIRE days
- 
+
 If -1 is specified, messages will become permanent.  If 0 is  specified,
 no  default expiration date will be present.  The latter should never be
 specified for a  folder  with  a  BBOARD,  or  else  the  messages  will
 disappear.
- 
+
 NOTE: This value is the same value that SET BBOARD/EXPIRATION specifies.
 If one is changed, the other will change also.`,
 			},
@@ -1603,11 +1605,11 @@ written directly from a network mailing program  (i.e.  PMDF).   Several
 mailing  lists  use  digest  format  to  send  their  messages, i.e. the
 messages are concatenated into one long message.  If DIGEST is set,  the
 messages will be separated into individual BULLETIN messages.
- 
+
   Format:
- 
+
     SET [NO]DIGEST
- 
+
 The command SHOW FOLDER/FULL will show if DIGEST has been set.
 `,
 			},
@@ -1615,11 +1617,11 @@ The command SHOW FOLDER/FULL will show if DIGEST has been set.
 				Description: `Specifies that messages deleted from the  selected  folder  are  written
 into  a dump (or log) file.  The name of the log file is foldername.LOG,
 and it is located in the folder directory.
- 
+
   Format:
- 
+
     SET [NO]DUMP
- 
+
 The  command  SHOW  FOLDER/FULL  will show if dump has been set.  (NOTE:
 SHOW FOLDER/FULL is a privileged command.)`,
 			},
@@ -1627,18 +1629,18 @@ SHOW FOLDER/FULL is a privileged command.)`,
 				Description: `Specifies expiration limit that is allowed for messages.  Non-privileged
 users cannot specify an expiration  that  exceeds  the  number  of  days
 specified.  Privileged users can exceed the limit.
- 
+
     SET [NO]EXPIRE_LIMIT [days]
- 
+
 The command SHOW FOLDER/FULL will show  the  expiration  limit,  if  one
 exists.  (NOTE: SHOW FOLDER/FULL is a privileged command.)`,
 			},
 			"FOLDER": {
 				Description: `Select a folder of messages.  Identical to the SELECT command.  See help
 on that command for more information.
- 
+
   Format:
- 
+
     SET FOLDER [node-name::][folder-name]
 3 /MARKED
 Selects messages that have been marked (indicated by an asterisk).
@@ -1652,16 +1654,16 @@ many different people.  If an  account  is  specified  as  GENERIC,  new
 messages  placed in the GENERAL folder will be displayed upon logging in
 for a specific number of days,  rather  than  only  once.   The  default
 period is 7 days.  This command is a privileged command.
- 
+
   Format:
- 
+
     SET [NO]GENERIC username
- 
+
 NOTE: Both SET GENERIC and SET CONTINUOUS_BRIEF cannot be set for the
 same user.
 3 /DAYS
  /DAYS=number_of_days
- 
+
 Specifies the number days that new GENERAL messages will be displayed
 for upon logging in.
 `,
@@ -1671,9 +1673,9 @@ for upon logging in.
 keypad correspond to command definitions.  These definitions can be seen
 via the SHOW KEYPAD command.  The default is NOKEYPAD unless the /KEYPAD
 qualifier has been added to the BULLETIN command line.
- 
+
   Format:
- 
+
     SET [NO]KEYPAD
 `,
 			},
@@ -1686,9 +1688,9 @@ occur  if DISMAIL is set for an old account.  Additionally, removing the
 DISMAIL flag will not automatically enable LOGIN.  (The reason  for  the
 above  was to avoid extra overhead for constant checking for the DISMAIL
 flag.)  This command is a privileged command.
- 
+
   Format:
- 
+
     SET [NO]LOGIN username
 `,
 			},
@@ -1702,18 +1704,18 @@ the  local  folder.   When  the command is executed, the selected folder
 will then point to the remote folder.  If there  were  messages  in  the
 local folder, they will be deleted.  This feature is present only if the
 BULLCP process is running on the remote node.
- 
+
   Format:
     SET NODE nodename [remotename]
     SET NONODE
- 
+
 NOTE: If one node adds a message to a remote node, other nodes connected
 to the same folder will not immediately be aware  of  the  new  message.
 This  info  is  updated  every  15  minutes,  or if a user accesses that
 folder.
 3 /FOLDER
    /FOLDER=foldername
- 
+
 Specifies the folder for which the node information is to modified.
 If not specified, the selected folder is modified.
 `,
@@ -1721,11 +1723,11 @@ If not specified, the selected folder is modified.
 			"NOTIFY": {
 				Description: `Specifies whether you will be notified via a broadcast  message  when  a
 message is added to the selected folder.
- 
+
   Format:
- 
+
     SET [NO]NOTIFY
- 
+
 In a cluster, if the logical name MAIL$SYSTEM_FLAGS is defined so that
 bit 1 is set, users will be notified no matter which node they are logged
 in to.  If you wish to disable this, you should define BULL_SYSTEM_FLAGS
@@ -1739,12 +1741,12 @@ folder.  This is a privileged qualifier.  It will only affect brand new
 users (or those that have never logged in).  Use /ALL to modify all users.
 3 /FOLDER
    /FOLDER=foldername
- 
+
 Specifies the folder for which the option is to modified.  If not
 specified, the selected folder is modified. Valid only with NONOTIFY.
 3 /PERMANENT
    /[NO]PERMANENT
- 
+
 Specifies that NOTIFY is a permanent flag and cannot be changed by the
 individual. /DEFAULT must be specified. This is a privileged qualifier.
 `,
@@ -1756,9 +1758,9 @@ useful for terminals that can store more than one screenful at  a  time,
 and  that  have a remote printer that can then print the contents of the
 terminal's memory.  The default is PAGE, unless the default was  changed
 by specifying /NOPAGE on the command line to invoke BULLETIN.
- 
+
   Format:
- 
+
     SET [NO]PAGE
 `,
 			},
@@ -1766,17 +1768,17 @@ by specifying /NOPAGE on the command line to invoke BULLETIN.
 				Description: `Specifies  either  process  privileges  or  rights  identifiers that are
 necessary to use privileged commands.  Use the SHOW  PRIVILEGES  command
 to see what is presently set.  This is a privileged command.
- 
+
   Format:
- 
+
     SET PRIVILEGES parameters
- 
+
 The parameters are one or  more  privileges  separated  by  commas.   To
 remove  a privilege, specify the privilege preceeded by "NO".  If /ID is
 specified, the parameters are rights identifiers.
 3 /ID
  /[NO]ID
- 
+
 If specified, then the rights identifier which is specified as the
 parameter will allow users holding that rights identifier to execute
 privileged commands.  If /NOID is specified, the identifier is removed.
@@ -1791,9 +1793,9 @@ greater   than  the  expiration  limit,  and  the  user  does  not  have
 privileges, then the expiration  limit  will  be  used  as  the  default
 expiration.  (If there is no expiration limit, and the user doesn't have
 privileges, then an error will result.)  PROMPT_EXPIRE is the default.
- 
+
   Format:
- 
+
     SET  [NO]PROMPT_EXPIRE
 `,
 			},
@@ -1803,14 +1805,14 @@ read new non-system or folder messages (if any exist).  A new message is
 defined as one that has been  added  since  the  last  login,  or  since
 accessing BULLETIN.  The default setting for READNEW is dependent on how
 the folder was created by the owner.
- 
+
 In  order  to  apply  this to a specific folder, first select the folder
 (using the SELECT command), and then enter the SET READNEW command.
- 
+
   Format:
- 
+
     SET [NO]READNEW
- 
+
 NOTE:  If  you  have several folders with READNEW enabled, each folder's
 messages will be displayed separately.  However, if you EXIT the READNEW
 mode before all the folders have been displayed, you will not be alerted
@@ -1831,12 +1833,12 @@ folder.  This is a privileged qualifier.  It will only affect brand new
 users (or those that have never logged in).  Use /ALL to modify all users.
 3 /FOLDER
    /FOLDER=foldername
- 
+
 Specifies the folder for which the option is to modified.  If not
 specified, the selected folder is modified. Valid only with NOREADNEW.
 3 /PERMANENT
    /[NO]PERMANENT
- 
+
 Specifies that READNEW is a permanent flag and cannot be changed by the
 individual.  This is a privileged qualifier.
 `,
@@ -1848,12 +1850,12 @@ except you will not be prompted to read the messages.   The  default  is
 dependent  on how the folder was created by the owner.  A new message is
 defined as one that has been  added  since  the  last  login,  or  since
 accessing BULLETIN.
- 
+
 In order to apply this to a specific folder,  first  select  the  folder
 (using  the  SELECT  command),  and  then enter the SET SHOWNEW command.
- 
+
   Format:
- 
+
     SET [NO]SHOWNEW
 3 /ALL
 Specifies that the SET [NO]SHOWNEW option is the default for all users for
@@ -1866,12 +1868,12 @@ folder.  This is a privileged qualifier.  It will only affect brand new
 users (or those that have never logged in).  Use /ALL to modify all users.
 3 /FOLDER
    /FOLDER=foldername
- 
+
 Specifies the folder for which the option is to modified.  If not
 specified, the selected folder is modified. Valid only with NOSHOWNEW.
 3 /PERMANENT
    /[NO]PERMANENT
- 
+
 Specifies that SHOWNEW is a permanent flag and cannot be changed by the
 individual, except if changing to READNEW. This is a privileged qualifier.
 `,
@@ -1880,14 +1882,14 @@ individual, except if changing to READNEW. This is a privileged qualifier.
 				Description: `Specifies that the selected folder is a SYSTEM folder.  A SYSTEM folder
 is allowed to have SYSTEM and SHUTDOWN messages added to it.  This is a
 privileged command.
- 
+
   Format:
- 
+
     SET [NO]SYSTEM
- 
+
 By default, the GENERAL folder is a SYSTEM folder, and the setting for
 that folder cannot be removed.
- 
+
 If the selected folder is remote, /SYSTEM cannot be specified unless the
 folder at the other node is also a SYSTEM folder.
 `,
@@ -1907,9 +1909,9 @@ currently selected folder.
 				Description: `Shows information about a folder of messages.  Owner and description are
 shown.  If the folder name is omitted, and a folder has been selected via
 the SELECT command, information about that folder is shown.
- 
+
   Format:
- 
+
     SHOW FOLDER [folder-name]
 3 /FULL
 Control whether all information of the folder is displayed.  This
@@ -1920,10 +1922,10 @@ have access to that folder.
 			},
 			"KEYPAD": {
 				Description: `Displays the keypad command definitions.  If the keypad has been enabled
-by either the SET KEYPAD COMMAND, or /KEYPAD is specified on the command 
+by either the SET KEYPAD COMMAND, or /KEYPAD is specified on the command
 line, the keypad keys will be defined as commands.  SHOW KEYPAD is the
 equivalent of HELP KEYPAD.
- 
+
 NOTE: If the keypad is not enabled, PF2 is defined to be SET KEYPAD.
 3 /PRINT
 Prints the keypad definitions on the default printer (SYS$PRINT).
@@ -1948,13 +1950,13 @@ the  latest  message which a user has read in the folder.  If NOLOGIN is
 set for  a  user,  this  information  will  be  displayed.   This  is  a
 privileged  command.   Non-privileged users will only be able to display
 the information for their own account.
- 
+
   Format:
     SHOW USER [username]
- 
+
 The username is optional.  If omitted, the process's username  is  used.
 The  username should not be included if /ALL or /[NO]LOGIN is specified.
- 
+
 NOTE: The last logged in time displayed is that which is stored when the
 BULLETIN/LOGIN command is executed, not that  which  VMS  stores.   Some
 sites  make  BULLETIN/LOGIN  an  optional  command for users to store in
@@ -1965,27 +1967,27 @@ Specifies that information for all users is to be displayed.  This is  a
 privileged command.
 3 /LOGIN
  /[NO]LOGIN
- 
+
 Specifies that only those users which do not have NOLOGIN set are to be
 displayed.  If negated, only those users with NOLOGIN set are displayed.
 This is a privileged command.  The qualifier /ALL need not be specified.
 3 /FOLDER
    /FOLDER=[foldername]
- 
+
 Specifies to display the latest message that was read by the user(s) for
 the  specified  foldername.   A newsgroup can be specified, but the info
 can only be shown if the user has subscribed to the newsgroup.   If  the
 foldername is not specified, the selected folder will be used.
 3 /SINCE
    /SINCE=[date]
- 
+
 Specifies  to display only those users whose latest read message date is
 the same date  or  later  than  the  specified  date.   If  no  date  is
 specified,  the  date  of  the  current message is used.  Only valid for
 folders or with /LOGIN.  Use /START for newsgroups.
 3 /START
    /START=[number]
- 
+
 Specifies  to  display only those users whose latest read message number
 is equal to or greather than the specified  number.   If  no  number  is
 specified,  the  message  number  of  the current message is used.  Only
@@ -2006,7 +2008,7 @@ their  expiration  date  set to 15 minutes in the future and are deleted
 then.  Undeleting the message will reset the expiration date back to its
 original  value.   Deleted  messages  will  be  indicated as such by the
 string (DELETED) when either reading or doing a directory listing.
- 
+
   Format:
     UNDELETE [message-number]
 `,