
    drealmBBS Admin Documentation (Revised for Release 2.1)





General contents

1. License Notes
2. What is drealmBBS, an overview
3. Packages
4. Technical support
5. Using this manual
  5.1. Sections
  5.2. Conventions
6. Getting it ready
  6.1. Pre-requisites
  6.2. Unpacking
  6.3. Compiling
  6.4. Installing
  6.5. Starting up drealmBBS
  6.6. Directories and files on typical installation
7. Configuration in general
  7.1. Dividers and limits
  7.2. The configuration files
8. Menus in general
  8.1. Menu files
  8.2. Cached or read-as-you-go
  8.3. Menu structure
  8.4. Variables in menus
  8.5. Menu navigation
9. User input and output
  9.1. Support for foreign languages
  9.2. Prompted input
  9.3. Editing
  9.4. Outputting files
  9.5. Outputting strings
  9.6. Logging
10. User access and administration
  10.1. Security issues
  10.2. Logging on
  10.3. Logging off
  10.4. Controlling access
  10.5. Creating new users
  10.6. Maintaining users
  10.7. Special help for individual users
11. Inter-user facilities
  11.1. Real-time communication
  11.2. Info about other users
12. Public Message areas
  12.1. Creating and maintaining public message areas
  12.2. Navigating message areas
  12.3. The messages
  12.4. Reading news
13. Private Mail
  13.1. Local private mail
  13.2. External private mail
  13.3. The mail messages
14. Offline reading
  14.1. Structure of grabpad
  14.2. Structure of putfile
15. File activities
  15.1. Directories
  15.2. File uploads and downloads
  15.3. File storage and descriptions
  15.4. The user's private file utilities
16. Running external programs (doors)
17. Index to menu actions


1.   License Notes

     drealmBBS - Bulletin Board System for Linux
     Copyright (c)  1994, 1995, 1996 Inge Cubitt and Peter
     Jones

     This program is free software; you can redistribute it
     and/or modify it under the terms of the GNU General
     Public License as published by the Free Software
     Foundation; either version 2 of the License, or (at your
     option) any later version.

     This program is distributed in the hope that it will be
     useful, but WITHOUT ANY WARRANTY; without even the
     implied warranty of MERCHANTABILITY or FITNESS FOR A
     PARTICULAR PURPOSE.  See the GNU General Public License
     for more details.

     You should have received a copy of the GNU General Public
     License along with this program; if not, write to the
     Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
     MA 02139, USA.

     The GNU General Public License should be in a file called
     COPYING.


2.   What is drealmBBS, an overview

     drealmBBS is a multi-user BBS system.

     drealmBBS runs a separate process for each node, and
     finds out about other nodes by interrogating certain
     files on disk and via IPC.  It needs about 1Mb virtual
     memory per user.

     ALL data is produced and stored as plain ASCII so it can
     be accessed by any other application.

     It is highly configurable.  All menu options can have
     access controlled by user level, userflags, areaflags,
     and min/max times of day.

     You may offer your callers any of eight external file
     transfer protocols, any three editors and any three
     display programs.  We have included our own line editor
     (isle) and our own display program (pager) which are both
     absolutely free of shell escapes and command access.
     There is support for output in up to 10 human languages
     or styles.

     Each BBS user has his/her own account in the passwd file,
     but may of course run drealmBBS as his shell for
     security.  Security is also aided by reverting user to
     login permissions when using external file transfer
     protocols, editors or file viewers - and other external
     programs optionally.

     Facilities include:

     Private inter-user mail, with interface to external mail.
     A quota of external mail can be set per person, and mail
     can be made available only to users over a certain level
     or with a certain flag set.

     Message areas (forums):  Public messages are posted
     without naming a recipient and can be read by anyone who
     may access a particular area.  Areas can be open or
     private, read only or read/write or moderated.  Each area
     may have an individual areamask, which represents the
     flag settings of the users who may access it. An area may
     also be restricted to people of over a certain security
     level.  In the case of a "private" area access is
     restricted to only people who are specifically named
     within that area.  Messages are linked as threads, and
     may be read threadwise, numerically, or by "reference"
     (ie always reading down through replies first).  Messages
     may be unlinked, relinked in a different way, and copied
     to other message areas.  Whole threads or branches may be
     copied to other areas, retaining their relationships.

     Voting:  Votes are attached to public messages.

     File up/downloads:  Functions to descend through
     directories and re-ascend. File descriptions held.  Files
     may be posted between individual users.  No internal
     protocol provided, you can use any which are available on
     your system.  Rename, delete, edit, view files. Searches
     recursively from any named parent directory on filenames
     or file descriptions.

     Chat:  Realtime chat on a message by message basis via
     pipes and sockets.  Users can chat and listen whilst
     doing other things.  Users can select chat reception on
     or off.  Menus may disable or enable chat at any point.
     Broadcast chat to anyone listening, or a private message
     to named person.

     Timing:  Session timers can be set on, off, or paused.
     Also total time per day can be limited.

     User defaults:  An extensive range of user default
     choices including inactivity timeout, hotkey mode, chat
     message colours.  Also interface with terminfo to allow
     user to choose his best terminal type for use with
     external programs.

     Run Unix commands or "doors" either with BBS permissions
     or with login permissions, as required for access and
     security.

     All above are under total control of configuration files
     and the semi-programmable menus.  Each line of each menu
     can be made available only at certain times, or only to
     people with a certain flag set or security level.

     The nodes themselves may be configured to only accept
     callers fulfilling certain criteria.


3.   Packages

     The following sites tend to have the latest versions of
     drealmBBS:

     The drealm BBS +44 (0)181 568 4316 (or 2204), in the
     drealmbbs file area.

     ftp://ftp.demon.co.uk/pub/unix/unix/drealm/

     ftp://tsx-11.mit.edu/pub/linux/packages/drealmbbs/

     In the same locations are the Linux Software Map entries.
     There is an IAFA-PACKAGE file in the archives.


4.   Technical support

     There are various means available by which you can obtain
     support.  If you can't reach us by one path, try another
     on the list!

     BBS:      +44 (0)181 568 4316 8N1, up to V32bis/HST 24hrs
                          568 2204 8N1        V34
               Internal mail to 'inge' or 'sysop' initially

     Email:    inge@drealm.org
               thanatos@drealm.org
               icubitt@cix.compulink.co.uk

     Usenet:   alt.bbs.drealmbbs


5.   Using this manual


5.1. Sections

     This manual is numbered using the "legal" numbering
     convention. All sections beginning with, say, "3." are
     linked under one main heading, and as the topics are
     broken down more and more finely, further numbers are
     added.  E.g 3.5.2 and 3.5.3 are both subheadings under
     3.5.  3.5 and 3.6 are both subheadings under Section 3.


5.2. Conventions

     Terms in <angle brackets> are intended for you to
     substitute your own values.

     Italics (in the printed docs only) indicate a file name
     or path.

     Terms in "quotes" indicate a literal word or something
     you should type in exactly.

     In all descriptions, file and directory names are used as
     if you are following the layout recommended in Section
     6.6 "Directories and files on typical installation".  If
     you are using a different layout, you will need to
     substitute your own names where necessary.

     Sorry feminists, but for the sake of simplicity the user
     is always referred to as "he"!


6.   Getting it ready


6.1. Pre-requisites

     Allow about 1Mb of RAM per simultaneous user, on top of
     your normal requirements for running the operating
     system.  That is assuming you also have a correct
     proportion of swap space on disk.  It can run in less
     memory space, but there will be a drop in speed.  Storage
     requirements are entirely flexible,  depending on growth
     of your bbs when it has been opened.

     The application assumes you will have certain utilities
     available:

          cat cp egrep chmod chown login sort tail ls stty
          usermod useradd userdel

     For full use of the system you will want at least one
     file transfer protocol, a text display program and an
     editor.  It is up to you to make sure whatever you offer
     is secured from escapes into the shell if your users are
     not allowed shells.  Packaged in with the distribution
     are a simple line editor (isle) and a paginating display
     program (pager) which have no shell facilities. If you
     are not using shadow passwords, and you find your
     existing useradd etc. won't work without, we have
     included a package of substitutes.

     You may also want a way of paging the SysOp, and some
     games.


6.2. Unpacking

     By now you have probably already unpacked your package.
     For those of you who have obtained this document in
     advance or who still want to know what happened, this
     describes the unpacked package structure:

     The package will unpack into a directory called dlmXX/
     (where XX is the release number).  This will be created
     beneath the directory which you were in when you unpacked
     it.

     Under dlmXX/ will be the files:
     COPYING             Licence details
     IAFA-PACKAGE        Description of package
     ns-user-0.1.tar.gz  Contains substitute useradd etc.
     README              First

     Then there will be subdirectories:
     bin/           Will contain the drealmBBS executables.
     doc/           Containing all the SysOp's documentation
     library/       Contains support text for drealmBBS
                    functions
     src/           Source code for the supplied executables
     startercfgs/   Configuration files set up with easiest
                    defaults
     startermenus/  Just enough to get you into the BBS


6.3. Compiling

     This section explains how to create executable binary
     files from the source code in the dlmXX/src directory
     should you need to, for example if you decided to change
     any of the code.  If you are going to use the binaries as
     supplied you will not need to read this section.

     1)   Change directory to dlmXX/src.

     2)   Type "make" to leave the executables in the source
          directory, or "make bin" to overwrite the supplied
          ones. Makefile is written for GNU make version 3.69.
          It will probably work on other versions of make too.
          Otherwise, sorry, but you'll have get the above
          maker or edit the makefile.

     3)   The instructions in Section 6.4 "Installing" are
          written with the assumption the binaries are in
          dlmXX/bin.


6.4. Installing

     This section assumes that either you are using the
     precompiled binary files, or that you have already
     compiled the executables from the "C" source code, and
     that now the executables are in the dlmXX/bin directory
     (where XX is the release number of the drealmBBS
     version).  It also assumes that you will be setting up
     the live directory layout as suggested in Section 6.6
     "Directories and files on typical installation".

     IMPORTANT - If you are upgrading from an earlier release
     refer to the upgrading.txt in the docs/ directory to see
     if there are any special steps you should take to bring
     your BBS data or configuration up to date.

     Follow these steps in the order listed:

     1.   Become root if possible.

     2.   Prepare a new group on your system, which will be
          used only by the BBS administrator (referred to as
          "sysop" from now on), and the BBS program itself
          (referred to as group "bbs").

     3.   Create the desired live directory structure on your
          system. Refer to Section 6.6 "Directories and files
          on typical installation".  Set ownership and
          permissions of these directories as recommended in
          that section.

          ENSURE THAT ALL DIRECTORIES NAMED IN CONFIG.DREALM
          ACTUALLY EXIST AND ARE rwx TO GROUP "bbs", or else
          change config.drealm to represent your actual setup.

     4.   If this is your first installation of drealmBBS,
          move everything from dlmXX/startermenus into
          /drealm/menus and from dlmXX/startercfgs into
          /drealm/config.   Chown and chmod them if necessary
          so they are all owned by "sysop", group "bbs" and
          mode -rw-r----- .

          Ownership can be set by the commands "chown sysop
          <files>" and "chgrp bbs <files>".  Mode -rw-r-----
          is set by the command "chmod 0640 <files>".

          The exception is config.drealm which should be
          placed in /drealm.  It must be in the same directory
          as the main drealmBBS executable for security
          reasons - it won't run otherwise!  Permissions on
          config.drealm should still be the same as for the
          other config files.

     5.   Move files from dlmXX/library into /drealm/library
          and set their attributes as for drealm config files
          above)

     6.   Move drealmBBS from dlmXX/bin to /drealm.  It should
          be owned by "sysop", group "bbs" and mode -rwx--s--x
          (that is, it runs as group "bbs" but users from any
          group can start it running).  You can give it this
          mode by the command "chmod 02711 drealmBBS"

     7.   If you wish to use the supplied line editor and
          paginator, move isle and pager to an accessible bin
          directory (such as  /usr/local/bin) and give them a
          mode of rwx--x--x  ("chmod 0711 <files>"). The
          reason they don't go in /drealm/bin is that the user
          reverts to login permissions while running them and
          cannot (or should not) have access to /drealm/bin
          contents.  Ensure this directory is in PATH as per
          config.drealm.

     8.   Move the other files from dlmXX/bin to /drealm/bin.
          The following files should be owned by "sysop",
          group "bbs" and mode -rwx--x---  ("chmod 0710
          <files>"):

               timer chatout longname stats mailtidy filetidy

          The following should be owned by root, group "bbs"
          and -rws--x---  (setuid root) which means they run
          as if the user were temporarily root.  Because they
          then become very powerful, make sure they are always
          out of reach of anyone who is using a normal shell.
          You can give them the right mode by the command
          "chmod 04710 <files>". If you wish to use these
          utilities, it is necessary to ensure that passwd,
          usermod, useradd, and userdel can be found in the
          PATH as per config.drealm :

               setpwd username adduser remuser zapuser

          In newer distributions of Linux, usermod, useradd
          and userdel are no longer installed for those of you
          who opt not to use the 'shadow' password file, so we
          have written our own (non-shadow) versions which for
          your convenience have been included in this package.
          They are in the archive called ns-user-0.1.tar.gz
          for those of you who find you are without them.

          Some systems do not allow anyone but root to chown
          files.  drealmBBS can be run without using the chown
          command, but it is used, if available, in one or two
          places.  If you have a system like this and you wish
          to use chown, place a copy of chown in the
          /drealm/bin directory and change its permissions to
          setuid as above.

          If you want people to be able to automatically log
          in as the new user after they have registered, you
          will also need to ensure that your system's login
          program runs setuid and can be found in PATH.  Or
          you can place the chmod'ed version in  /drealm/bin
          if you wish.  If you are not going to offer chown or
          login, you can indicate that in config.drealm, and
          the program will then not attempt to do such
          manoevers.  NB. /drealm/bin is automatically put at
          the front of the users' $PATH list when drealmBBS is
          running.

     9.   You may also want to move the documentation to under
          your drealm directory structure, if you want to
          clear up the dlmXX directory.

     10.  Edit all the config files to your satisfaction, not
          forgetting config.drealm.  (see Section 7
          "Configuration in general").

     11.  After a successful installation, you can delete
          anything in the dlmXX directory which was created
          when you unpacked the application.


6.5. Starting up drealmBBS


     drealmBBS can be called in two ways.  One is with an
     absolute path, when it will use that path to find its
     config.drealm file.  This won't work from the /etc/passwd
     file as paths get stripped by the time they reach the
     application, so you will need to provide a script with
     the whole call in.  The other way is to keep drealmBBS
     and config.drealm in /drealm which is the default
     directory in which it looks for config.drealm, so no path
     need be specified.


6.5.1.    Starting up drealmBBS for the first time

     1.   In config.drealm, set $sysoplevel$ to 0.  Then you
          won't have any problems performing your initial
          SysOp duties.  Be careful to raise your security
          level and change the $sysoplevel$ setting in
          config.drealm before other people start using the
          BBS.

     2.   Set $autocreate$ in config.drealm to 1 (TRUE).

     3.   You may now start up drealmBBS and it should
          automatically create your BBS account.

     NB.  If you get the message "There is already a
          <your_name> using drealmBBS", the most likely reason
          is that you have forgotten to create the /drealm/tmp
          ($tmpdir$) directory which is vital to this process!

     drealmBBS will be running presumably with the menus which
     were included with the package as examples until you
     create your own.


6.6. Directories and files on typical installation


     Suggested layout of BBS directories

     The ($$) words in brackets are the associated variables,
     and tie in with the remarks in config.drealm

      /drealm/-|--bin ($bin$)/
               |--library ($library$)/
               |--config ($configdir$)/
               |--menus ($menudir$)/
               |--data ($datadir$)/
               |--tmp ($tmpdir$)/
               |--areas ($areasdir$)/---|--area1/
               |                        |--area2/
               |
               |--users ($users$)/------|--usera/
               |                        |--userb/
               |                        |--userc/
               |
               |--mail ($maildirs$)/----|--usera/---.mail/
               |                        |--userb/---.mail/
               |
               |--privatefiles ($privatefiles$)/-|--usera/
                                                 |--userb/

      /home ($homedirs$)/---|--usera/
                            |--userb/


     All directories under drealm should be owned by "sysop"
     and group "bbs", mode  drwxrwx--- .  /drealm itself
     should be owned the same, but mode drwxrwx--x     You can
     decide what access to allow on /home based on the
     following points.

     There is no harm, and many benefits, in setting
     $privatefiles$ the same as $home$, (see Section 15.4 "The
     user's private file utilities" for more details), but the
     $users$ dir should be separate especially when the BBS
     users also have shell accounts, otherwise they may edit
     their flags and security level files from the shell!

     *******************************************************
     If you do set any drealmBBS directory to be the same as
     any existing system directory you will have to ENSURE
     THAT GROUP "BBS" HAS RWX ACCESS TO IT, or the application
     will fail.
     *******************************************************


6.6.1.    Summary of files within typical directories

     /usr/local/bin

     drealm.sh      shellscript to run drealmBBS
     isle           simple line-oriented editor. No shell
                    escapes
     pager          simple paginated file displayer. No shell
                    escapes


     /drealm

     drealmBBS      the main bbs executable setgid bbs
     config.drealm  the main configuration file.


     /drealm/bin

     chatout        chat receiver
     filetidy       clears out old private files
     longname       unearths terminal descriptions
     mailtidy       clears out old private mail
     stats          top callers, posters, averages
     timer          controller for limited time session

     setuid root utils:
     adduser        wrapper for creating a unix ID
     chmod          a setuid copy if needed
     chown          a setuid copy if needed
     remuser        wrapper for removing a unix ID
     setpwd         for SysOp to set a user's password
     username       sets the comments field in /etc/passwd
                    (for AKA)
     zapuser        throws a user offline


     /drealm/library

     Texts may be added or edited by the SysOp as needed

     fds.txt        help file for search_filedescs search
     fns.txt        help file for search_filenames
     olr.txt        help file for olr
     ps.txt         help file for plan_search
     rules          file displayed during new user
                    registration
     termtypes.txt  table of terminal types suggested
     ts.txt         help file for text_search
     ustrings.txt   strings for output as per language


     /drealm/config

     config.aflags  custom areaflag names
     config.files   file transfer protocols
     config.ftidy   for filetidy
     config.langs   choice of language strings
     config.mtidy   for mailtidy
     config.nodes   access to terminal lines
     config.stats   for stats and logins list
     config.uflags  custom userflag names
     config.user    initial user defaults, for such as page
                    length etc
     exc.1          people excluded from using line 1
     inc.1          people allowed to use line 1
     level.1        min level allowed on line 1
     only.1         only people allowed on line 1
     shells.1       shells allowed on line 1


     /drealm/menus

     *.pmp          lines executed every time a prompt is
                    issued
     *.cmd          lines executed using user input at prompt
     *.ini          lines executed when changing down to new
                    menulevel
     *.exi          lines executed when changing up from
                    menulevel
     start.cmd      lines executed only once at start of
                    session
     stop.cmd       lines executed only once at logoff


     /drealm/data
     All files in this directory will be created by the
     application. They may be edited or cleared by the SysOp
     if required (after referring to appropriate manual
     sections).

     callerstats    top callers list created by stats
     errorlog       error conditions during program execution
     inputlog       records anything typed in at prompts
     logins         record of logins
     mailreached.dd last number given out for private mail
     log            logging using "log" action
     newarealog     records all new areas and area deletions
     newdirlog      records all new directories and directory
                    newuserlog records all new accounts and
                    accounts vaped
     posterstats    top message posters list created by stats
     ratiostats     message:call ratio created by stats


     /drealm/tmp
     All files in this directory will be created by the
     application.  Interference with these files while a user
     is online will upset the current process.  You can clear
     out any you wish as long as the user has been gone a few
     minutes.

     chat.<user>    a chat socket
     conf.<user>    a lock, and indicator of connection to the
                    BBS
     callerstemp    temp file created by stats
     posterstemp    temp file created by stats
     ratiostemp     temp file created by stats


     /drealm/areas/<any_area>/
     All files in this directory will be created and
     maintained by the application.  They should not be
     manually altered unless you are willing to risk making
     the area unuseable.

     areamask       flags compared with user when accessing
                    area
     chair          list of chairmen
     description    the short area description
     flags          flags describing area status
     gagged         list of gagged users
     hdr.<number>   header of an area message
     highest        highest message in area
     info           any length info text
     level          minimum user security level to access area
     members        list of members for invite-only area
     msg.<number>   body of an area message
     msgindex       indicators of message status
     vote.<number>  voting data attached to message


     /drealm/areas/<any_area>/pending
     Directory only created If the area is "moderated"

     hdr.<timestamp>     header of a pending message
     msg.<timestamp>     body of a pending message


     /drealm/users/<any_user>
     All files in this directory will be created by the
     application.  They may also be directly edited by the
     SysOp if required, being careful to preserve structure.

     .areas/        holds last read values for message areas
     .chatdoing     current chat status
     .details       name and address etc
     .drealmrc      user selected defaults file
     .expiry        integer date of membership expiry
     .firston       date first on as above
     .flags         user's flags
     .force         present if forced by menu action 'force'
     .lastcall      date of last session in seconds since 1st
                    Jan 1970
     .laston        shows status of last session ending
     .level         user's BBS security level
     .mailalert     present if new mail arrived
     .mailallowance bytes of external mail allowance left
     .newshigh      highest news message read
     .notes         notes for SysOp to keep
     .notice        special notice for user to read
     .scanlist      user's scanlist!
     .timed         time on details for timer
     .title         shows optional 'title' in who list
     .tmpareas/     directory - saved lastread values for a
                    restore
     .totalcalls    total calls made
     .totalmessages total public messages written
     .updatealert   present if user needs to pick up new flags
                    etc


     /drealm/mail/<any_user>/.mail
     Files in this directory will be created and maintained by
     the application.  They should not be edited manually.

     hdr.<number>   private mail header
     msg.<number>   private mail message body
     .mailstore     holds value of 'stored' mail pointer


     /drealm/privatefiles/<any_user>

     .plan          user writes his own introduction
     .sig           lines appended to end of mail and articles
     grabpad        messages gathered for download
     putfile        messages uploaded ready to be posted

     also any other files the user chooses to store


     /home/<any_user>
     workpad        online text preparation space
     workpad~       backup of above while editing
     view           temporary file made by display utility


7.   Configuration in general

     The application looks for all config files, other than
     config.drealm itself, in the directory specified in
     config.drealm in the $configdir$ field.

     A minimum starter kit of config files is distributed in
     dlmXX/startercfgs and can be copied into the live
     /drealm/config directory, if you wish to start that way.


7.1. Dividers and limits

     Configuration files are made up of various numbers of
     fields, each starting and ending with double colons.  It
     is vital that all fields are preserved in any
     configuration file.  That means in effect, do not add or
     delete any sets of '::' dividers.  Some fields may be
     left blank as directed for the individual file.  Leave a
     field blank, where permitted, by simply deleting any
     characters or spaces between two sets of double colons.
     Between each valid data field comments may be stored. (NB
     THIS DOES NOT APPLY TO config.nodes which has a different
     layout).

     As a rule unless otherwise stated, all lines, strings,
     paths and directories are limited to 255 characters.

     When naming an areaflag or userflag the name may be a
     maximum of 10 characters.


7.2. The configuration files


7.2.1.    config.drealm

     The main configuration file.  You will find instructions
     for each field in the comments fields of the file and
     under relevant sections of this document.

     Before starting up drealmBBS, make sure that all fields
     in config.drealm correspond to the way your system is set
     up.

     ********************************************************
     When a directory is named in config.drealm, ensure there
     really is such a directory on your disk, and that group
     "bbs" can access it!
     ********************************************************

     As a security measure, any line containing a directory or
     path which is too long is rejected altogether, as
     truncation could result in access to an undesired
     directory.

     drealmBBS looks for its config.drealm file in the same
     directory as itself.

     The standalone housekeeping utils (such as mailtidy) are
     loaded by calling them with the path and name of the
     config.drealm file as the argument. They then read
     config.drealm to find out the directory where all the
     other config files are kept (the $configdir$ field).


7.2.2.    config.user

     This is the default user configuration.  It is used when
     a new user account is created.  It will also be used for
     existing users if their own configuation (in their
     .drealmrc) becomes corrupt.

     There are also menu commands (reset_my_defaults and
     reset_user_defaults) to read in the config.user values to
     replace those in .drealmrc.  You will find comments for
     each field of the config.user file.  The comments are not
     written over to .drealmrc.


7.2.3.    config.nodes

     One line per terminal device.  This config file does NOT
     have room for comment fields - each field contains data.
     However the top line may be used for field  headings, as
     supplied.

     For full description of this file, see Section 10.4.1
     "Access to nodes"


7.2.4.    config.uflags

     The first ten flags in each set are hard-coded and
     reserved by the application.  The 20 flag positions in
     this file allow you to designate the purpose of the
     custom userflags.  The names you give do not affect the
     function of the flags in any way, but serve simply as a
     reminder to you and a way of referencing them easily from
     the menus without remembering their numbers.

     Enter appropriate names in upper-case, with a maximum
     length of 10 characters.


7.2.5.    config.aflags

     As above but for message areas.


7.2.6.    config.stats

     Field 1 contains the time in days since the last login
     for anyone who is to be included in the stats.  0 in this
     field turns off aging checks.

     Field 2 may contain a list of names of people who will
     never be included. Many SysOps like to exclude their own
     name.

     Field 1 is also used as a test for who will appear in the
     logins list, but field 2 is ignored for this purpose!


7.2.7.    config.mtidy

     Field 1 is the mimimum age in days beyond which mail gets
     deleted.  "0" in this field is not accepted as it would
     delete all mail, and was almost certainly not intended!

     Field 2 is a list of exclusions, users who will not have
     mail deleted.


7.2.8.    config.ftidy

     As above but for filetidy.


7.2.9.    config.files

     This is for setting up the file transfer protocols which
     you intend to make available to your users. For further
     information see Section 15.2.1 "Setting up config.files".


7.2.10.   config.langs

     This contains the choices of human language you are
     offering to your users.  See Section 9.1 "Support for
     foreign languages".


7.2.11.   config.preload

     This contains the names of the menu files you would like
     cached throughout the session. See Section 8.2 "Cached or
     read-as-you-go".


8.   Menus in general


8.1. Menu files

     $menulevel$ holds the name of the menu level, not
     including file extensions like .ini or .cmd.  The
     application looks for the file with the right ending when
     the time comes.

     Menu names may be a maximum of 10 characters before the
     extension, e.g. 0123456789.cmd is the longest menu file
     name valid.

     Menus are looked for firstly in the directory pointed to
     by $menudir$.  For systems with a large number of menus,
     it is possible to create subdirectories named after the
     initial letter of the menus stored within them.  Eg
     /drealm/menus/m would contain menus starting with "m"
     such as main.cmd and main.ini.  This feature is of course
     case-sensitive.

     The one compulsory level is "top", for which there must
     be at least a top.cmd.   The following description
     assumes we are working on the menu level called "mail".

     The file called mail.ini contains the menu lines to be
     executed when the user first enters the mail level.  This
     could contain commands to list all new mail for instance.
     A .ini file is not used if the level is re-entered while
     working back towards the beginning of the menu stack.

     The file called mail.exi is run on the way out of the
     mail level, unless the user is push_levelling, ie going
     deeper into a menu level stack.

     Each sequence of user input and execution of a user
     command is one cycle.  The cycle begins by running
     mail.pmp which should contain any actions which want to
     be done just before the prompt is put out.  Don't forget
     the prompt line itself!

     The second part of the cycle is when the input obtained
     at the prompt is compared against the lines in mail.cmd
     and any matching lines are executed.  Any chat messages
     (see Section 11.1 "Real-time communication") are held
     back and queued while the actions in each cycle are
     executed.

     The file called start.cmd is executed once only when the
     user first logs in, and stop.cmd when they log out via
     log_off.  They are both optional.

     At the moment there is no fancy menu creation program, so
     you will need to use a plain text editor, or word
     processor in 'non-document' mode.  Sorry.  If anyone
     wants to volunteer a menu creation utility, please do (-:


8.2. Cached or read-as-you-go

     The default way for the application to access menus is to
     read them line by line from disk each time the user
     issues a command or needs a prompt. To use this method,
     set the C.menucache field in config.drealm to "0".  This
     method has the advantage that a user will pick up any
     menu changes immediately they are made.

     The alternative is to read some or all the menus into
     memory, which can work out faster in operation.  If
     C.menucache is set to anything higher than 0, drealmbbs
     will attempt menu cacheing mode.

     The figure given in C.menucache tells drealmBBS how many
     bytes of memory to set aside for menu storage. If you
     have not allowed enough, drealm will simply read in as
     much as it can, then revert to the normal disk-reading
     for the rest, without causing an error. It is up to you
     to work out the size of the menu files it will be
     required to store at any one time. The memory space
     required per menu is its size on disk plus 20 bytes.

     Each time a change of menu level is called for, it will
     read the .ini, .exi, .pmp and .cmd file for that level
     into memory and not bother to access the disk again for a
     menu until the next change of menu level.  However any
     menus called by the append action would still be read
     from disk each time, unless they are listed in the
     config.preload file

     In config.preload you can list any menus you would like
     to be held in memory throughout the session. For a menu
     of global options, which is appended to every menu, this
     makes very good sense.  The format of config.preload is
     one menu whole filename per line.  No path is required,
     drealmBBS will seek out the named files in its normal
     way.


8.3. Menu structure

     Fields in a menu are divided by double colons (::).  The
     lines are divided from one another by an empty field.
     I.e. there must be a set of double colons at both the
     beginning and the end of each line.  The double colon at
     the end of one line cannot be used as the start of the
     next line.

     A menu line may be carried over onto more than one
     physical line of the file. If this is done, the newline
     encountered is translated into a space. Therefore you
     will not wish to split the line in the middle of a string
     to be printed, or in the middle of a double-colon field
     separator.  (The reason for this apparently weird
     translation is that many text editors strip out leading
     and trailing spaces from lines, and the menu controller
     needs to be aware they were meant to be separate words.)

     All menu fields except the enable and continue fields
     (description of fields comes later) can be up to 255
     actual file characters (including whitespace and newlines
     etc), and the total menuline may be up to 1023 characters
     in length.  If there are variables to be translated and
     formatted in the menu field, the total translated length
     of the field must also be within 255 characters.   If a
     menu line is encountered which exceeds 1023 characters,
     the whole menu will be rejected, with varying effects
     depending on the menu and the stage of execution.

     Certain words will be trunctated if they go over a
     certain length. The maximum length of each menu keyword
     (see keywords field) may only be 20 characters, and out
     of any command line that is typed in by the user, the
     $command$ portion will be truncated to 20 chars.

     Whilst running the program most places are protected from
     over-long menu commands and user input.  In the case of
     user input this is done by refusing to accept input after
     the 255th character on the line, and in the case of menu
     lines, by failing if the line is too long.

     In the flags fields of a menu only the first 30 flags
     will be respected.


8.3.1.    The fields of a menu line

     Field 1   Enable.
               Normally "1" but can be set to "0" to disable
               the line entirely.  This useful facility avoids
               having to delete and rewrite the line when you
               don't want it temporarily.

     Field 2   Display.
               Text to be displayed if the "display_menu"
               action is invoked. This is a fully interpreted
               field and may contain any $variables$ and
               formatting codes (see Section 8.4 "Variables in
               menus").

     Field 3   Keywords.
               The string/s to be compared with the users'
               input command ($command$).  Whether or not the
               comparison is case sensitive depends on the
               $sensitive$ setting in config.drealm.

               This is a literal field and does not translate
               variables.

               Special strings are:

               *DEFAULT* Matches the user pressing Enter
               *NUMBER*  Matches any numerical string
               *NONE*    Just a convenience to mark a
                         display-only field
               *FORCE*   This line will be executed, if it
                         matches the tests regardless of what
                         key was pressed at the prompt.

     Field 4   Actions.
               The actions to be carried out if this line is
               matched.

               For most menu actions, it is enough to simply
               type the name of the action into this field and
               the user will be prompted for more details if
               necessary.  Menu actions vary as to the way
               they will take arguments and you should read
               the individual actions to find out how each
               action accepts or prompts for input.  As a
               general rule though, where an action will take
               from menu or user, it will always allow the
               menu argument to take precedence.  Where input
               is required from the user's command line, and
               the command line is empty, the user will be
               prompted.

               Parameters to the actions which are passed in
               this field, may contain $<variables>$ which
               will be translated just before execution of the
               action.

               Where a pattern is asked for as input, "*" is a
               multi-character wildcard and "?" is a single
               character wildcard (i.e. like the shell, rather
               than like grep). If leading or trailing spaces,
               balanced double-quotes should surround the
               pattern (e.g. " sp*c?s ").

               You may string together actions, separated by a
               semi-colon (;).  When there is more than one
               action in a single menu line, each action is
               only performed if the previous one returned
               with as TRUE.  If any of the actions strung
               together in this way fail, the execution of the
               whole line is evaluated as FALSE.

               Remember the total expanded length of this
               field, including whitespace characters cannot
               exceed 255.

     Field 5   Min_hour.
               On a 24 hour clock this figure is compared to
               the hour part of the system clock.  Line will
               not be matched before this hour. Set to "0" to
               turn off min hour checking.

               Variables are not allowed in this field.

     Field 6   Max_hour.
               See above.  Set to "24" will effectively turn
               off maximum hour checking.

               Variables are not allowed in this field.

     Field 7   Min_userlevel.
               Can use variable, but must evaluate to integer,
               otherwise taken as zero.

     Field 8   Max_userlevel.
               Can use variable, but must evaluate to integer,
               otherwise taken as zero.

     Field 9   Userflags.
               Userflag comparison mask.  String of characters
               represents the set of userflags in order.  In
               each position, the value must be matched
               exactly, unless you use a "?" which means it
               doesn't matter.  Eg if there is a "0" in the
               first position, the user's flag1 must be set to
               "0" or the line will fail to match.  If you
               don't care what the user's flag1 is set to,
               then place a "?" in position 1.  See Section
               10.4.4 "Flags" for further details.

     Field 10  Areaflags.
               Areaflag mask.  This will be compared based on
               the context of the current message area, which
               is always set.  It will be compared whether or
               not the menu line is anything to do with
               message area activities, so if the area status
               is irrelevant, make sure this field holds
               nothing but "?"s.

     Field 11  Continue.
               This field can hold values "-1", "0", "1", or
               "2".  The field's value is ignored unless the
               line was matched and executed.  If the line was
               a match, this field becomes important in
               deciding what to do next.

               "2"  Continue to try to match subsequent lines
                    whatever the outcome of the current line.
                    Used mainly for if you need to perform a
                    series of actions after accepting a single
                    user command.

               "1"  Only try to continue if the current line
                    finished executing with a success code.
                    See list below for details on what
                    constitutes success for each of the
                    actions.

               "0"  Don't look at any further lines.  Start a
                    new prompt/action cycle.  This is the most
                    usual setting in a simple menu.  It means
                    the user gets their prompt back more
                    quickly after a line matched.  If you put
                    the more frequently used lines at the top
                    of the menu, combined with a value of 0 in
                    this field, processing will be at its
                    quickest.

               "-1" The opposite of value '1'.  Only try to
                    continue if this line evaluated to FALSE
                    on execution.


8.4. Variables in menus

     All fields except 3, 5, 6 and 11 allow variable
     substitution

     Variables may be used either to appear on the screen as
     part of a displayed string, or as arguments to a menu
     action, or even in a test field like Min_userlevel.

     All variables are handled as strings but can be used to
     pass their numerical value, if any, to menu actions where
     appropriate.

     A variable to be translated should be started with a "\".
     There must be a fresh "\" for each variable.  Variables
     always start and end with a "$".  (e.g. \$id$ )

     Actual instances of variables which can be used in menus
     will be further explained in their relevant sections


8.4.1.    Summary of variables available to menus

     Variables listed here will also be explained in their
     relevant sections. A "c" in the middle column indicates
     the value is set in the configuration and will be static
     throughout the session.

     $areaflag$           Flag array for current message
                          area
     $areamaskflag$       Test for access to current
                          message area
     $areaname$           Current message area
     $areasdir$        c  Parent directory to public
                          message areas
     $autocreate$      c  Are shell users made into BBS
                          members when they run drealmBBS?
     $bbsname$         c  Full name of BBS
     $bbsshell$        c  What new users run as their shell
     $bbsshort$        c  One-word name of BBS
     $bin$             c  Directory containing BBS
                          executables
     $casesensitive$   c  Are menu keywords case sensitive?
     $chatdefault$        Has user selected chat on at
                          login?
     $chatincolour$       User's selected incoming chat
                          colour
     $chatnow$            Has user chosen chat on
                          currently?
     $chatoutcolour$      User's selected outgoing chat
                          colour
     $cols$               User's selected number of screen
                          columns
     $comline$            User's remaining command line
     $command$            User's latest command
     $commandstacking$ c  Does your BBS allow command
                          stacking?
     $configdir$       c  Directory containing
                          configuration files
     $configfile$      c  config.drealm really...
     $currentmail$        User's latest read private mail
                          message
     $currentmsg$         User's latest read area message
                          number
     $customvar1$         Custom variable
     $customvar2$
     $customvar3$
     $customvar4$
     $customvar5$
     $customvar6$
     $customvar7$
     $customvar8$
     $datadir$         c  Directory containing current BBS
                          data
     $dir$                Directory currently selected by
                          user
     $display$            User's selected display program -
                          Unix path/name
     $displayname$        User's selected display program -
                          friendly name
     $editor$             User's selected editor - Unix
                          path/name
     $editorname$         User's selected editor - friendly
                          name
     $erasekey$           User's selected key for erase
     $extmaillevel$    c  Minimum user level allowed
                          external mail
     $filesensitive$   c  Are file name selections case
                          sensitive?
     $firstcall$          Date of current user's first call
     $got$                Last input to menu action "get"
     $groupnum$        c  Number of unix group for "bbs"
     $highestmsg$         Highest message in current area
     $homedirs$        c  Parent directory of users' home
                          directories
     $hotkeys$            Has user selected hotkeys on?
     $id$                 Current user's unix ID
     $killkey$            User's selected key for line kill
     $language$           File extension of user's selected
                          language files
     $languagename$       Title of user's selected language
     $lastcall$           Date of current user's last call
     $library$         c  Directory containing library
                          files
     $maildirs$        c  Grandparent directory to users'
                          mailboxes
     $mailmonitor$     c  Is external mail to be limited in
                          amount?
     $mailreserves$       External mail allowance left to
                          user
     $menudir$         c  Top directory of menu files
     $menulevel$          Current menu
     $msgpointer$         User's pointer for the current
                          message area
     $myflag$             Flag array for current user
     $mylevel$            Current user's security level
     $newsarea$        c  Message area to be used as news
                          area
     $newuserflags$    c  Flags given to new user
     $newuserlevel$    c  Security level allocated to new
                          users
     $node$               Unix device name for user's node
     $pausetime$          User's selected pause for buffer
                          flushing
     $privatefiles$    c  Parent directory of users'
                          private file areas
     $pvtfileslevel$   c  Minimum security level for
                          private files access
     $pvtfilesmask$    c  Test for access to private file
                          facilities
     $pvtmaillevel$    c  Minimum security level for
                          private mail access
     $pvtmailmask$     c  Test for access to private mail
                          facilities
     $quickreturn$     c  Is quickreturn allowed?
     $random$             Integer set by last menu action
                          "random"
     $readmode$           User's selected default reading
                          mode
     $readown$            Has user elected to read his own
                          messages by default
     $recent$             User's selected catchup setting
     $reprintkey$         User's selected key for redraw
                          line
     $rows$               User's selected number of screen
                          lines
     $siglength$       c  Maximum size in bytes for a .sig
     $startarea$       c  Default message area to be joined
                          to at start
     $starttime$          Time of current session start
     $subsexpiry$         Date current user's subscription
                          expires
     $sysoplevel$      c  Minimum security level for SysOp
                          access
     $sysopname$       c  Unix ID of SysOp
     $taildir$            Subdirectory path descended into
                          by nest_dir
     $taken$              Last input to menu action "take"
     $terminal$           User's selected terminal type
     $timeout$            User's chosen inactivity timeout
     $tmpdir$          c  Directory containing temporary
                          BBS files
     $topdir$             Top directory selected by
                          start_dir
     $totalcalls$         Number of call made by current
                          user
     $totalmessages$      Number of public messages posted
                          by current user
     $users$           c  Parent directory of users' data
                          directories
     $werasekey$          User's selected key for erase
                          word
     $whichnext$          Public message which would be
                          next by default


8.4.2.    Menu actions for setting variables

     Most variables are set in the course of running the
     application, but space for 8 custom variables is provided
     and accessed via the following menu action.


8.4.2.1.  set_customvar

     args: 1,2,3,4,5,6,7, or 8 for variable name, and the rest
           of the arguments are read into the variable chosen.
     from: menu only

     Sets variable $customvar1$ (or up to 8)

     example:  set_customvar 3 What is your name?;
               prompt \$customvar3$

     Always returns TRUE


8.4.2.2.  random

     args: maximum number
     from: menu only

     Sets $random$ to an integer between 1 and maximum number
     inclusive.

     Returns FALSE if the argument is invalid, and $random$
     will be set to 0


8.4.3.    Formatting variables

     Formatting codes are applied to a variable to alter the
     way the value is expressed or how it is displayed

     Variables have a default format if no additional details
     are given, for example, just putting \$varname$ gives the
     default format.

     Where formatting advice is irrelevant to the context it
     will be ignored rather than giving an error.

     Any formatting codes applied to the variable MUST be
     enclosed within the two $'s and follow the variable name
     after a space. (e.g. \$id + w20$ )

     The chosen codes must be entered in the following order
     and are separated by spaces unless otherwise stated.

          Date formats
          Subscripting
          Logic expressions
          Style

     All are optional


8.4.3.1.  Times and dates

     These default to "Sun Feb 12 15:02:25 GMT 1995" format
     unless otherwise stated.

     $now$          current time (default format is HH:MM)
     $today$        current date (default format is DD/MM/YY)
     $elapsed$      session duration (default format is
                    HH:MM:SS)
     $starttime$    time of login
     $subsexpiry$   date of subscription expiry
     $firstcall$    date of first call
     $lastcall$     time of last log out

     Date and time variables may be formatted using a standard
     date format string of the type and syntax used by the
     date(1) or strftime(3) Unix commands except that no
     leading + is required.

     The default is for drealm to adjust the time-zone string
     where necessary to give a single word time zone.  This
     can be circumvented by specifying a format string which
     includes "%Z".

     The date format must be supplied within double quotes. If
     no format is given, a default is used.

     Examples:
     It is now \$now "%A, %e %B %Y at %T %Z"$.
     You have been on \$elapsed "%T"$.


8.4.3.2.  Subscripting

     Bearing in mind that all variables are handled as strings
     for the purposes of formatting, and that a string is
     actually an array of characters, subscripts return a
     single character from a variable.  (N.B. in drealmBBS
     they start from position 1!)  Any variable without a
     subscript or with a subscript of "0" gives the entire
     variable (string).

     All subscripts inside formatting strings should be
     prefaced with "#" (eg \$extmailmask #3$.)

     If the subscript is off the end of the string, a null
     value (i.e. nothing) is returned.

     Two special flag arrays, $areaflag$ and $myflag$, may
     take names of individual flags (in CAPITAL letters) as a
     subscript instead of just the number.  (e.g. Is this area
     moderated? \$areaflag #MODERATED y$.)


8.4.3.3.  Logic expressions

     Boolean logic format codes return FALSE if the character
     is literal '0' or null.

     Values can be displayed either as the literal value or as
     one of a set of strings indicating logical state.

     They are:

     o    "on" or "off"
     s     "set" or "unset"
     t     "true" or "false"
     y     "yes" or "no"


8.4.3.4.  Style formatting

     Allows the case, justification, and field width to be
     specified.  This is done by a simple string of
     characters.  The meanings are listed below.

     u     upper case
     c    capitalise with initial capitals per word
     l    lower case
     +    left justify (default)
     -    right justify
     wnn  set field width to nn (e.g. w20).  The width
          parameter must be the last one or the outcome may be
          unpredictable.

     Left and right justification do not have any effect,
     obviously, unless a field width is set which is greater
     than the length of the string.


8.4.3.5.  Examples of formatting


     SysOp name in block caps         \$sysopname u$
     SysOp name with initial          \$sysopname c$
     capital
     SysOp name in caps right         \$sysopname u - w15$
     justified in a 15 char field
     Initial letter of SysOp name     \$sysopname #1 u$
     as a capital
     Does this BBS have a name?       \$bbsname y$
     Is my name over 20 characters    \$id #21 y$
     long?


8.5. Menu navigation

     There is a menu stack, built up by the user during his
     browsings, which initially starts with level "top" and
     may hold a list of up to 14 menu levels, which produces a
     sort of nesting effect.  The stack may be increased,
     reduced or cleared at any time by a relevant action in
     any menu.

     In case of an error in a menu, in order to stop users
     being stuck forever in a faulty and looping menu system,
     there is a counter which will abort the application if
     there are more than 30 menu cycles without executing a
     "prompt" menu action.


8.5.1.1.  Menu actions for menu navigation


8.5.1.1.1.     display_menu

     args: menu level name (optional)
     from: menu only

     Displays the Display field of a menu for each line which
     matches the conditions.  Defaults to current menu level
     if none is passed as a parameter.

     $variables$, \b, \n, \! and \~ may be used in the display
     field just as for print (see Section 9.5.1.1.1).

     Returns TRUE unless the .cmd of the named menu level is
     unfound.


8.5.1.1.2.     start_level

     args: a valid menu level name
     from: menu only

     Clears the menu stack, executing .exi files where
     relevant, and prepares to start again at the specified
     menu level.  If this fails, level "top" is restarted.  If
     this fails, the program exits.

     Either returns TRUE or terminates the program!


8.5.1.1.3.     push_level

     args: level name
     from: menu only

     Pushes the specified menu level onto the end of the menu
     stack, and prepares to execute it.  The .ini file for the
     pushed level is executed where one exists.  Up to 14 menu
     levels may be stacked.

     Only TRUE if the named level becomes the current level as
     planned.  FALSE if no level is named.


8.5.1.1.4.     pop_level

     args: level name (optional)
     from: menu only

     If no parameter is given, pops the current level off the
     stack. Otherwise, keeps popping until the specified level
     is returned to.  If this causes the stack to empty,
     drealm restarts the stack using the named level if it can
     be found, or "top" if not.  (This may cause the program
     to exit - see startlevel.)

     All menu levels popped have their .exi files executed.

     Always returns TRUE or exits the program.


8.5.1.1.5.     swap_level

     args: level name
     from: menu only

     Replace the current level with the named level, leaving
     the rest of the stack in place.
     The .exi file of the old menu and the .ini file of the
     new menu are executed where present.

     TRUE if the named level becomes the current level as
     planned.


8.5.1.1.6.     append

     args: a valid menu level name
     from: menu only

     Processes the named menu level's .cmd file as if it were
     part of the current menu. This is done as a diversion at
     the line it is called from, and the rest of the current
     menu is dealt with when the appended menu is exhausted.

     The append action itself is TRUE if a line from the
     appended menu matched and that line itself requested the
     menu to stop parsing (ie had a stop value in the continue
     field).  Most times you would not want to bother to go on
     parsing the current menu after a line in the appended
     menu was matched, therefore put a "-1" in the Continue
     field of the line which calls append.

     Example:
     ::1::::*FORCE*::append global::0::24::0::999::?::?::-1::
     (NB display field unused)


8.5.2.    Command stacking.

     With this setting enabled in config.drealm, the command
     line is not automatically cleared down between cycles of
     the menu.  The menu cycles will take their input from the
     remainder of the input command line and a prompt will not
     be executed until further input is required.


8.5.3.    Quickreturn.

     If you have quickreturn enabled in config.drealm, and a
     user stacks his commands (i.e. he puts a series of
     commands on one line including some which will take him
     to another menu level), upon exhaustion of his command
     line he will return to the level at which he entered the
     input line.  Quickreturn facility also depends on command
     stacking being enabled.


9.   User input and output


9.1. Support for foreign languages

     For those of you who expect to receive users who speak
     languages other than the English this application was
     originally written to use, there are facilities to set up
     alternative output for them.

     In the $library$ directory distribued with this release
     is a file called ustrings.txt.  This contains all the
     strings which are used by the drealmBBS executable
     itself.  They are read in at run time, and again each
     time a user chooses to change their language.

     Each line of the strings file that begins with a "#" is a
     comment line, and is ignored by the application.  As
     distributed, the comment lines give some instruction and
     information about the active lines they accompany.  Any
     line at all without a "#", even a blank one, will be read
     in as a string to be output.

     You must not change the number of active (non-comment)
     lines in the file.  Even if you are a programmer, don't
     be tempted to adapt the code to accept extra lines,
     because we authors might choose to add more lines in
     future releases, so yours will be overwritten.  However -
     we do provide for the file called mstrings.txt to be used
     specifically for your own strings!  Active lines from the
     mstrings file will be read in at the same times as the
     ustrings file and both sets of strings may be referenced
     either in the code (if you decide to adapt parts of it
     yourself), or in menu lines.

     In order to use the mstrings file successfully, you must
     edit drealm.h so that MSTRINGCOUNT has the right number
     of strings that you will be wanting it to read in.
     MSTRINGSIZE must be the size of memory in bytes that you
     feel is needed to hold the literal strings. If necessary
     USTRINGCOUNT can be altered too.  We have started you off
     with suitable allowance for 100 strings in any mstrings
     file.

     The way of using these strings in a menu line is to enter
     them as \@mstring25@ or \@ustring367@. The reference
     number of the strings begins from 1 in each file.  The
     mstrings may include embedded $variables$ and formatting,
     including "\n" etc, but these variables will only be
     translated when used in a menu line, and might cause
     problems in a ustring line which is output directly by
     the application at lower level (really only relevant to
     SysOps adapting the source code).

     You can support users with up to 10 different languages.
     The way to do this is to create alternative ustrings and
     mstrings files with different filename extensions, such
     as ustrings.english and mstrings.german.  On the other
     hand, instead of different geographical languages you
     could use the files to hold a choice of ASCII or ANSI
     output, eg ustrings.asc and ustrings.ans.

     The file in $configdir$ called config.langs holds details
     of the languages to be offered to users. There are ten
     pairs of lines, the first of which holds the file
     extension to be used for files of that language, and the
     second holds a word or phrase which is shown to the user
     for the purposes of making their choice.

     eg:
     ::eng::
     ::American English::

     The file extension can be a maximum of 10 characters
     long.

     Any of the .txt files which were distributed in $library$
     can have versions with file extensions to match those in
     config.langs, and they will be displayed per user at the
     appropriate times.  If you have any other files of your
     own which you want to display from a menu line, you may
     also translate them and use the menu command display_lang
     to select the correct version from the library directory.

     Wherever a user has chosen a language and there is not a
     file with the appropriate language extension, drealmBBS
     will look for the matching <filename>.txt instead.  For
     this reason it is a good idea to keep all the .txt files
     we've provided in the library.  If the .txt file cannot
     be found either, drealmBBS will look for the file
     extension named in config.user.  It is not recommended
     that you rely on this fall-through often as it could get
     confusing for the users, and disk access time is wasted
     searching the directory for alternative files.

     As yet, no attempt has been made to display message or
     mail headers in anything other than English, as these are
     stored on disk and are used literally to direct the
     program. It is probable a future release will address
     this.

     The variable $language$ holds the file extension and
     $languagename$ the descriptive word or phrase as set out
     in config.langs.


9.1.1.1.  Menu actions for selecting output language


9.1.1.1.1.     set_language

     args: none
     from: -

     Allows user to select a language in which to receive his
     output.

     A mini-menu is constructed using the selection of
     languages in config.langs.  After selection, the strings
     files ustrings.<language extension> and
     mstrings.<language extension> are read into memory and
     used from then on.

     Returns TRUE provided there was no problem reading or
     writing the user's defaults file.


9.2. Prompted input

     Prompted input means waiting for a user to type something
     or press enter.  Where there is a default stated,
     pressing Enter is treated as selecting the default,
     otherwise it merely returns an empty string which may
     result in a FALSE code for the action.  Inactivity
     timeout as chosen for or by the user is in effect during
     prompted input actions.


9.2.1.1.  Menu actions for prompting input


9.2.1.1.1.     prompt

     args: the prompt message if required
     from: menu only

     Prompts the user for input, which is then put into the
     $comline$ variable (otherwise referred to as the command
     line).  If there is a force string (see Section
     10.7.1.1.3 "force_user"), this is used instead of
     prompting the user. Otherwise, the parameters are passed
     to do_print for display and a line of input is read into
     the command line.  In hot-key mode, only the first
     character pressed is used.  The first word of $comline$
     is copied to $command$ for matching against the menu
     keywords.  If the user's input begins with a punctuation
     mark, this mark is itself separated from following text
     and used as the first word.

     Always returns TRUE.


9.2.1.1.2.     prompt_cr

     args: the prompt message if required
     from: menu only

     Exactly the same as for "prompt" above, but if the user
     is in hot-key mode, that is suspended just while he types
     at the current prompt.

     This is most useful for a large menu where you have run
     out of single characters and the user might need to type
     a string of two or more, or for a numbered menu which
     goes higher than 9.


9.2.1.1.3.     get

     args: the prompt message if required
     from: menu only

     Prompts the user for input which is read into $got$,
     ignoring anything already in the command line, and can
     then be used in menus as a variable.

     TRUE if $got$ managed to get something.


9.2.1.1.4.     take

     args: prompt message if desired
     from: menu only

     This varies from get in that if there is anything already
     in the command line, this is copied to $taken$.
     Otherwise, the prompt is displayed and a line of input is
     read into $taken$ which can be used as a variable in menu
     actions.

     This action does not alter the contents of $comline$ so
     it should be followed by a flush_comline if you don't
     wish to continue processing the rest of the command line.

     TRUE if $taken$ managed to get something.


9.2.1.1.5.     set_echo

     args: 0, 1, or 2
     from: menu only

     Stops or starts drealmBBS echoing the user's prompted
           input.
     0 = do not echo
     1 = echo as normal
     2 = display a "*" for each character input

     Returns TRUE if valid argument has been passed.


9.2.1.1.6.     press_enter

     args: none
     from: -

     Prompts the user to press Enter.  Useful after a file has
     been displayed.

     Always TRUE once Enter has been pressed.


9.2.1.1.7.     continue

     args: none
     from: -

     Puts out a "[C]ontinue or [s]top?" prompt.  Continue is
     default.

     TRUE only if the user opts to continue.


9.2.1.1.8.     sure

     args: none
     from: -

     Puts out an "Are you sure? y/N" prompt.  No is default.

     TRUE only if the user specifically chooses "y".


9.2.1.1.9.     yes_no

     args: optional prompt message
     from: menu only

     Prints " Y/n " prefixed with your prompt message if
     supplied.

     User can only type in y, n or Enter.  Default is yes.

     TRUE if user does not select "n".


9.2.1.1.10.    no_yes

     args: optional prompt message
     from: menu only

     Prints " y/N " prefixed with your prompt message if
     supplied.

     User can only type in y, n or Enter.  Default is no.

     TRUE only if user specifies "y".


9.2.1.1.11.    flush_comline

     args: none
     from: -

     Clears the command line and therefore $comline$.

     Always returns TRUE.


9.3. Editing


9.3.1.    Security issues

     Some favourite editors, such as emacs or vi allow the
     user to obtain a Unix shell interface, or to name any
     file to edit.  In order to make it less hazardous to use
     such editors, while using an editor the user is returned
     from group "bbs" to their login group and permissions.
     We have also included a simple and secure line-based
     editor, called isle (Inge's Simple Line Editor) with the
     package.  Isle uses plain text only.


9.3.2.    Filtering

     If you wish to prevent certain contents such as ANSI
     graphics in user-edited files, such as mail messages,
     signatures etc, you may specify a filter of your own to
     be used.  This is set in the C.filter field of
     config.drealm.  Results of all edit sessions, including
     where text is prepared offline and uploaded, will be
     passed through this filter before being saved.


9.3.3.    Selecting editors

     In config.drealm, there is room for three editor programs
     to be specified, from which a user can choose his
     favourite.  Each editor has two fields, one to specify
     the system call to run it, ie program name, parameters
     and path if necessary, and the other for you to give it a
     friendly name for the purposes of user selection.


9.3.3.1.  Menu actions to do with selecting editors


9.3.3.1.1.     set_editor

     args: none
     from: -

     Allows the user to select their editor program from a
     list made up of the ones offered in config.drealm.

     If the editor they choose is valid, $editorname$ is set
     to the informal name of the editor, $editor$ to the
     program call, and the action returns TRUE.


9.3.4.    The editing experience

     Once a user has chosen to edit a named file, or to
     compose other text such as an area or mail message, a
     certain sequence of events is triggered.

     Let us assume the user has chosen to edit his planfile.

     Three files are always involved - the destination file,
     in this case .plan, the workpad, and workpad~ which is
     the backup file in case the user wishes to undo some
     faulty editing and reinstate previous workpad.

     In the description below it assumes the user is using the
     ustrings.txt which is distributed by the authors. If he
     is using some other language, his prompts and input will
     be different.

     First, if the destination file exists, he is told that
     the existing .plan is being loaded into workpad.
     Otherwise it says "editing new file .plan".   In the case
     of creating a new public area or private mail message, a
     file called message (in the home directory) comes into
     being as the temporary destination file.  It is destroyed
     once the message has been sent to the area or recipient.

     a prompt appears, saying:
     [E]dit online, [u]pload, use [f]ile, [o]k done, or
     [a]bandon:

     Choosing "abandon" leaves the destination file untouched
     and reinstates the workpad to how it was before beginning
     this edit session.

     "Edit online" puts him into his chosen editor, editing a
     file called workpad which will be saved to his home
     directory prior to the contents being copied to their
     final destination.

     Selecting "upload" starts an upload session and appends
     the uploaded file to his workpad.  The uploaded file is
     then deleted.

     Selecting "use file" is as for uploading but it allows
     selection of a file already in his private directory, and
     does not then delete it.

     "ok done" brings up the prompt described below:

     After editing, uploading, using a file, or selecting ok
     done, a further prompt says:
     [S]ave to .plan, [e]dit, [l]ist, [?]help, [h]old workpad,
     [c]lear workpad, [a]bandon:

     "Save" will send the contents of his workpad to the
     destination file, and he will be asked if he wishes to
     clear his workpad, just in case he wants to send a copy
     elsewhere.  The default is Yes clear it.

     "edit" will return to the [E]dit online, [u]pload, use
     [f]ile, [o]k done, or [a]bandon: prompt already
     explained.

     "list" displays the file.

     "hold workpad" keeps any editing he's done so far in his
     workpad, but leaves the destination file untouched.

     "clear workpad" clears workpad and leaves the destination
     file untouched.

     "abandon" leaves the destination file untouched and also
     reinstates the workpad to how it was before beginning
     this edit session.


9.3.4.1.  Menu actions for editing specific files


9.3.4.1.1.     edit

     args: path/file
     from: menu only

     This is for the SysOp to select the exact file a user
     should edit.  Edits the named file, The file will be
     created if it doesn't exist.

     TRUE if file is saved.


9.3.4.1.2.     edit_choice

     args: filename
     from: menu or user

     Allows selection of file to edit from within $dir$
     (currently selected directory).  Attempts to include a
     path in the filename are rejected.

     Creates file if necessary.

     TRUE if file saved.


9.4. Outputting files


9.4.1.    Security issues when displaying files

     Some favourite display programs, such as more or less
     allow the user to issue Unix shell commands.  In order to
     make it more secure to use such programs, while using an
     external display program the user is returned from group
     "bbs" to their login group and permissions.   We have
     also included a simple and secure paginator, called pager
     with the package.


9.4.2.    Selecting display programs

     In config.drealm, there is room for three display
     programs to be specified, from which a user can choose
     his favourite.  Each display has two fields, one to
     specify the system call to run it, ie program name,
     parameters and path if necessary, and the other for you
     to give it a friendly name for the purposes of user
     selection.


9.4.2.1.  Menu actions for selecting display programs


9.4.2.1.1.     set_display

     args: none
     from: -

     Allows the user to select their display program from a
     list made up of the ones offered in config.drealm.

     If the display program they choose is valid,
     $displayname$ is set to the informal name of the
     displayer, $display$ to the program call, and the action
     returns TRUE.


9.4.3.    Displaying files

     Because the user returns to his login group and
     permissions during execution of an external display
     program, the file for display is first copied to a file
     called view in his home directory, where he will have
     permission to access it.


9.4.3.1.  Menu actions for displaying files


9.4.3.1.1.     view_choice

     args: filename
     from: menu or user

     Allows selection of file to view from within $dir$
     (currently selected directory).  Any attempts to include
     a path in the filename are rejected.

     TRUE if file was found and was not empty.


9.4.3.1.2.     display

     args: one file with full paths
     from: menu only

     Display SysOp-specified files to the user.  Uses their
     selected display program.

     TRUE if the file was found and had something in it.


9.4.3.1.3.     display_lang

     args: one file basename
     from: menu only

     Action appends the user's language file extension to
     specified basename, and looks for result in $library$
     directory.  If file does not exist, looks for
     basename.txt instead.

     If matching file is found, it displays using user's
     selected display program.

     TRUE if a matching file was found and had substance.


9.5. Outputting strings


9.5.1.1.  Menu actions for outputting strings


9.5.1.1.1.     print

     args: string for printing
     from: menu only

     Displays the specified string on the user's screen.  No
     quotes are required.  In addition to $variable$
     substitution, the following are recognised:

     \n   sends a newline character to terminal
     \b   sends a backspace character to terminal
     \!   executes a [C]ontinue or [s]top sequence before
          printing any further.  If the user chooses to stop,
          the actions terminate with a FALSE code, otherwise
          the actions continue to execute.
     \~   executes a "press Enter to continue" sequence.  The
          actions continue executing after Enter is pressed.

     Always returns TRUE unless user chooses stop after \!


9.6. Logging

     Nosey SysOps will love the extensive logging
     facilities...


9.6.1.    Log files in general

     Log files are typically kept in $datadir$

     Apart from those files used by the menu actions below,
     there are:

     errorlog       written to by the application from time to
                    time.  If you are reporting a bug to the
                    authors, please save a copy of the
                    errorlog which existed at the time the
                    error occurred.
     newarealog     written to whenever a message area is
                    created or destroyed
     newdirlog      creation and destruction of directories
     newuserlog     creation and destruction of BBS user
                    accounts.
     uploadlog      records file uploads if enabled in
                    config.drealm
     logins         always written to when a user starts
                    running drealmBBS, unless their name is in
                    the exclusions list in config.stats

     Edit, clear or truncate these as you wish, in order to
                    save disk space.


9.6.1.1.  Menu actions for logging



9.6.1.1.1.     input_log_on

     args: none
     from: -

     Enables continuous low-level logging of all input by the
     user at a prompt, but not during editing etc.  Input is
     written to inputlog in $datadir$ directory.

     Only FALSE if the log file is unable to be written to.


9.6.1.1.2.     input_log_off

     args: none
     from: -

     Disables low-level logging of user input.

     Always TRUE.


9.6.1.1.3.     chat_log_on

     args: none
     from: -

     Enables continuous logging of all input to chat commands
     by the user.  Input is written to chatlog in $datadir$
     directory.

     Only FALSE if log file is unwriteable


9.6.1.1.4.     chat_log_off

     args: none
     from: -

     Disables logging of chat messages.

     Always TRUE.


9.6.1.1.5.     log

     args: narrative to log
     from: menu only

     Writes to file a line at a time, ie only one line is
     written each time the action is executed.
     The date and time of the log entry are written to file
     called log in $datadir$, followed by narrative on the
     same line.

     Only FALSE if log file is unwriteable.


9.6.1.1.6.     log_to_file

     args: pathname/logfile then narrative
     from: menu only

     Writes only the string you passed to the log.
     $variables$ may be included, if for instance you wish to
     use $id$ to log the user's name.

     Also useful for questionnaires.

     Any file may be used and it need not be in $datadir$

     Only FALSE if the named file is unwriteable.


10.  User access and administration


10.1.     Security issues

     To prevent other shell users causing malicious or
     accidental damage to your BBS data,  certain compromises
     have been made on flexibility.  One of the biggest
     problems has been an apparent variation in chown in
     sysVr4.2 which means that an owner of a file may chown
     and chgrp that file to anyone he wishes!

     So for now, drealmBBS will insist on being called with a
     full path, and on finding config.drealm in the same
     directory as itself, or without a path and finding
     config.drealm in /drealm.

     Security depends on there being a unix group which no one
     belongs to except the SysOp and his assistants, and all
     BBS files and directories (except the drealmBBS
     executable itself) being accessible only to that group.
     This gives the SysOp access to all BBS files for
     housekeeping.  When another normal user runs drealmBBS he
     is granted an effective groupid of that special group -
     but ONLY while he is actually running the BBS.  This
     allows him controlled access to the BBS files and data.

     Because users may be allowed to choose from a range of
     external editors, display programs and file transfer
     protocols, they are set back to their login group during
     the time that they are using their editor etc, so that if
     shell commands are available from within the external
     utility, the damage they can do will be limited.  So as
     to avoid permission errors during edits, displays, and
     file transfers, temporary files are created in the user's
     home directory, and it is these which are worked on.

     Some of the programs included in the package need to be
     setuid in order to work.  Mostly they are wrappers for
     existing unix utilities like useradd.  Make sure system
     programs which are needed by drealm can be found in the
     PATH as per config.drealm (see Section 6.4 "Installing")

     The drealmBBS executable itself does not run as root, but
     as setgid whatever the BBS group is, so by choosing a
     group with no special access other than to the BBS
     itself, the existing system cannot be attacked by the
     running of it.

     That deals with main system security.  For security OF
     the bbs itself, it is important to make sure the
     config.drealm file cannot be removed or overwritten by
     anyone but the SysOp himself.  It is also important to
     ensure that no one can access the user data directories
     ($users$ in config.drealm) directly. If they can, they
     might edit their .level file, increasing their BBS access
     level to that of $sysoplevel$, possibly enabling them to
     access menu features you had only intended SysOps to use!

     Suggestions as to appropriate access permissions of
     particular files and directories are to be found in the
     installation Section 6.4


10.2.     Logging on

     The normal Unix facilities are in place monitoring
     various ports and offering logins, which means drealmBBS
     may be accessed through any route, eg direct dialup, or
     telnet.  You can use the login programs supplied with
     your system, or write a more user-friendly one like we
     did.

     After a user has logged on successfully, the system looks
     in the /etc/passwd file to see what he should run first.
     For a normal Unix user, this will be a shell such as
     Cshell or Bourne Shell, from which they will issue a Unix
     command to run drealmBBS when they are ready.  For users
     who you want only to use the BBS and not have Unix
     access, the shell field in /etc/passwd should name
     drealmBBS itself, or a script to run it.

     Having started up drealmBBS (see Section 6.5 "Starting up
     drealmBBS"), a check is made to see that they are allowed
     to access it through that particular tty or port.  The
     file config.nodes controls this checking, see Section
     10.4.1 "Access to nodes"

     Because inter-user facilities would become very confused
     if people were logged on to drealm itself more than once,
     checks are done to ensure there is only one of you.

     conf.<username> in the $tmpdir$ directory contains the
     process number of the process which created it.  This is
     used to check whether the same ID is already running a
     drealmBBS and therefor ban a duplicate session.  It acts
     as a lock and is dissolved by a new lock if the number
     contained in it is dead.

     If the user is already listed as being on, he will be
     politely told and the drealmBBS session will terminate.
     However, if there is a file called .shunt in his $user$
     directory, the application will make an attempt to relog
     him in as the user named in it.  There can be many user
     IDs chained by the shunt method or more than one name in
     the .shunt, on successive lines.  In order to use this
     feature, make sure your $tmpdir$ directory does not have
     the "t" bit set or users will not be able to destroy the
     conf.<username> files created and left behind by other
     IDs which they might be trying to shunt to. Above all
     make sure the directory you have chosen as $tmpdir$
     EXISTS or no one will be allowed into drealmBBS!!!

     The variable $bbsname$ is used for various reports during
     logging in and holds the full name of your BBS.
     $bbsshort$ is a shortened single-word version of the BBS
     name for internal use and mail etc.

     .totalcalls in the user's $users$ directory is
     incremented, and the value stuffed into $totalcalls$

     .lastcall takes the startup time of this session in
     seconds past 1/1/70 and $starttime$ will return the value
     as a human-readable date.

     The file named logins in $datadir$ has a line appended to
     say when the user logged in, unless their name appears in
     the exclusions field in config.stats.  On a SysVr4.x
     system, we used this file to show other callers who has
     been on by using "system tail -20r \$datadir$/logins" in
     a menu.  Use tac on a linux system.

     The user's .drealmrc is then read, or if it is unreadable
     he uses config.user and is told there had been a problem.

     When he eventually logs in successfully, lines which
     match him in the menu start.cmd (if it exists) are
     executed, after which top.cmd will be looked for.


10.3.     Logging off

     A user may, of course, log off by simply hanging up.
     Drealm dies messily, leaving various temp files hanging
     about.  His chat process and timer if in effect will soon
     notice he has gone, and tidy themselves up.  Therefore
     try to avoid  manually tidying temp files before a user
     has been gone for a minute or so.


10.3.1.1. Menu actions for logging off


10.3.1.1.1.    log_off

     args: none
     from: -

     Fully pops the menu stack executing the relevant .exi
     files.  Executes the menu file called stop.cmd (if it
     exists). Tidies up and exits the program.  (This will
     drop line if the program is the user's shell.)

     Returns FALSE only, as if it succeeds the program has
     ended!


10.4.     Controlling access


10.4.1.   Access to nodes

     config.nodes in $configdir$ holds the data necessary for
     controlling access to individual nodes.

     The variable $node$ holds the Unix name for the port and
     can be useful in menus where you wish to run an external
     program for the user.

     There is one line per terminal device.  This config file
     does NOT have room for comment fields - each field
     contains data.  However it may have a line for field
     headings, as supplied.

     Field 1   Nodegroup.
               Arbitrary number.  Number may be used for more
               than one node, if nodes are to behave the same
               as others with the same number.  If you set all
               lines to the same number for instance, you only
               need one set of .inc, .exc, .level and .shell
               files.

               Stick to single digits if you want to use the
               GROUP flag in menus.

               0 disables use of terminal line altogether.

               In the descriptions which follow I will assume
               that there is a value 8 in this field.

     Field 2   Unix device name.
               It is this field that is 'matched' when a user
               starts up a drealmBBS session.  This field can
               contain the string  *DEFAULT* which will match
               any line.   Remember that, as *DEFAULT* will
               match any line, no line after a *DEFAULT* line
               will ever be used.

     Field 3   Informal node title
               Shown to users in logins log etc.  Field length
               limited to 80 characters.

     Fields 4-8     may have value 0,1 or 2.  0 disables
               checking, allowing all users through.  1 means
               normal checking, with an error message on
               failure. 2 means that on error there will be an
               immediate halt to the process with no error
               message.

     Field 4   Exclusions.
               If enabled it checks a file called exc.8 (8
               being the nodegroup, field 1).  If user ID is
               found in file, user may not use this line.

     Field 5   Only.
               If this field is enabled, only users named in
               only.8 may use this line.  And that is only
               also if they have not been already screened out
               in the previous field.  They will also go on to
               be tested by the following fields.

     Field 6   Inclusions.
               Users mentioned in inc.8 will be allowed in, if
               they have passed the previous two fields.  If a
               user is passed by the checking of this field,
               they are allowed in with no further testing.

     Field 7   Level.
               Users' levels are tested against the figure
               held in level.8

     Field 8   Shells.
               If enabled this field will test the user's
               shell against those listed in shells.8  If the
               user's shell (as per /etc/passwd) does not
               match any listed, the user is ejected from the
               session.

     Field 9   Error message.
               Displayed if any of the above tests fail on a
               field which was set to 1.

     Field 10  Prompt.
               Not used in the drealmBBS application as such,
               but used in the login replacement we had been
               working on and which may be released one day!

     Field 11  Screen.
               Used in login replacement as described above
               for Field 10.  The full path and name to a file
               which is displayed before the login prompt, in
               the way /etc/issue would be in a normal Linux
               login.

     Examples:
     The following is a chart of example combinations of
     settings for config.nodes

     exc=0 only=0 inc=0 level=0 shells=0  All allowed in

     exc=0 only=0 inc=1 level=0 shells=0  Allow all

     exc=0 only=0 inc=0 level=1 shells=0  Compare levels only

     exc=1 only=0 inc=0 level=0 shells=0  Disallow only if in
                                          exc list

     exc=0 only=1 inc=? level=? shells=?  Allow only if in
                                          only list

     exc=1 only=1 inc=? level=? shells=0  Disallow if in exc
                                          list Disallow if not
                                          in only list

     exc=1 only=0 inc=0 level=1 shells=0  Allow if level ok,
                                          unless in exc list

     exc=1 only=0 inc=1 level=1 shells=0  Check exclusions
                                          list and disallow
                                          named. Check inc
                                          list and allow
                                          named. All other
                                          check against level


10.4.2.   Passwords

     Passwords are held in the normal system password file and
     are used as part of a normal system login.


10.4.2.1. Menu actions for setting passwords


10.4.2.1.1.    set_password

     args: none
     from: -

     Calls the system's passwd program for the user to
     directly change his password.

     TRUE if system passwd call returns TRUE.


10.4.3.   Levels

     User levels are a useful and simple way of determining
     the amount of comparative access allowed to a user.  The
     maximum level guaranteed to work is 999.

     User levels are saved in the .level file in the user's
     $users$ directory.

     Levels are used in two main ways:

     a)   in the minlevel and maxlevel fields in each menu
          line, to decide whether the line matches for that
          user.
     b)   some arbitrary levels, as determined in
          config.drealm such as $newuserlevel$, $pvtmaillevel$
          and $sysoplevel$ are used internally by the menu
          actions themselves, during execution.


10.4.3.1. Menu actions for setting user levels


10.4.3.1.1.    set_my_level

     args: level
     from: menu only

     Changes the current user's level.

     The value is held in the $mylevel$ variable.

     TRUE if new user level is saved.


10.4.3.1.2.    set_user_level

     args: level required then username
     from: menu or user input.

     Change another named user's level.

     This is recommended for access by SysOp only as it allows
     any user or level to be named.

     TRUE if new user level is saved.


10.4.4.   Flags

     Userflags are saved in the .flags file in the $users$
     directories.  There should be a string of 30 characters,
     each one representing a flag.

     A flag does not necessarily need to be 1 or 0, any single
     character or digit will do, and increases the
     flexibility, but only a "0" will be evaluated as FALSE
     for formatting purposes (see Section 8.4.3.3 "Logic
     expressions").

     Flags 11-30 are custom-definable, and their names can be
     defined in the config.uflags file. It is not compulsory
     to give them names, but it is very much more convenient
     to remember easily what each flag represents.

     The first ten userflags are either set by the application
     or reserved.  They are:


     Userflag 1  LIVE       1 = A proper user is logged on.
     Userflag 2  Reserved
     Userflag 3  CHAIRMAN   1 = The user is a chairman of
                            his current message area.
     Userflag 4  GAGGED     1 = The user is not allowed to
                            post in current  area.
     Userflag 5  ABEND      0 = The user logged off normally
                            on the previous call.  As yet it
                            is not differentiated whether
                            they dropped line or were timed
                            out.
     Userflag 6  NODEGROUP  Adopts the first figure or
                            character of the nodegroup field
                            in config.nodes.  All line
                            groups must be a single figure
                            if you wish to use this flag
                            accurately.
     Userflags   Reserved
     7-10


10.4.4.1. Menu actions for setting userflags

     Using flag variables in menu actions such as set_my_flag,
     flag values can be set to any character, or the strings
     "on" for "1", "off" for "0" and  "toggle" from "0" to
     "1", or any value to "0", are understood.


10.4.4.1.1.    set_my_flag

     args: flag then value
     from: menu only

     Changes the current user's flag to the given value and
     stores his entire flag array in $myflag$.

     TRUE if new value is saved


10.4.4.1.2.    reset_my_flags

     args: none
     from: -

     Resets the current user's flags to the new user default,
     defined by the $newuserflags$ field in config.drealm

     TRUE if new settings are saved.


10.4.4.1.3.    set_user_flag

     args: flag, value, then  username
     from: either menu or user input

     This action is best reserved for the SysOp as it allows
     any user to be named and any of their flags to be set
     unless all parameters are satisfied from the menu line
     first.

     TRUE if new setting is saved.


10.4.4.1.4.    reset_user_flags

     args: username
     from: menu or user input

     Change a named user's flags to the default for new users.
     This value is defined in the $newuserflags$ field in
     config.drealm

     TRUE if new setting is saved.


10.4.5.   Subs expiry

     Some BBS have a subscription system, where the user pays
     a sum for a certain period of access.

     The expiry date is held as seconds from 1st Jan 1970 in a
     file called .expiry in their $users$ directory. It is
     alright for this file to be empty or non-existent.

     $subsexpiry$ will return the date in human-readable form.


10.4.5.1. Menu actions for membership administration


10.4.5.1.1.    check_expiry

     args: word to describe account (eg "subs", "membership")
     from: menu only

     If the user's account has no expiry date, this returns
     FALSE.

     If the expiry date is past, this informs them of the fact
     ("Your <word> has expired.") and returns TRUE.

     Otherwise, the user is informed of how long they have
     left ("Your <word> expires in <days> days time.") and the
     return code is FALSE.

     The reason for the apparently reversed TRUE and FALSE
     codes is you are more likely to want to execute further
     actions if the user has expired than if he hasn't.


10.4.5.1.2.    set_my_expiry

     args: days to add
     from: menu only

     Changes the current user's expiry date by the specified
     number of days.  Days may be positive or negative.

     Returns TRUE if new setting is saved.


10.4.6.   Call frequency and intervals

     The interval is the amount of time which has elapsed
     since they last logged off or left due to other reasons.


10.4.6.1. Menu actions for call intervals


10.4.6.1.1.    check_interval

     args: number of minutes required interval from end of
           last session
     from: menu only

     The idea of this is if you want to stop a caller
     returning immediately he ran out of time, to prevent him
     monopolising the lines.

     Uses timestamp on the .laston file to see how long ago he
     was on.

     Returns TRUE if user is trying to log back within less
     minutes from when they logged off than the args passed.


10.4.7.   Time allowances

     Time limits for call and/or for day can be set in menu
     lines, typically in start.cmd

     Setting the time per day actually sets the time for
     current call to the time left for that day, unless time
     for current call is already set to a shorter time.
     Whichever of the times left is shorter will be the
     deciding time limit.  Should you wish to override the
     time left, perhaps to set a longer time for the current
     call, provide a menu line to stop the timer and restart
     it with the amended time granted (see below).


10.4.7.1. The timer process

     The timer is run in the backround a separate process
     which communicates with the main drealmBBS process.  Each
     user has their own timer process if they are being timed.
     In the $tmpdir$ directory, time.<username> is the
     connecting file for the process.

     Whenever the timer is activated, the user is told how
     much time he has left.  However, not all calls to start
     the timer actually restart it.  Once the timer has been
     set running, either by the session timer or the day
     timer, any actions which would start it just make it
     compare the times and reset its countdown to whichever is
     the shorter time.

     When the timer expires, the user's drealmBBS process is
     terminated.  There is normally a 2 minute warning to the
     user.

     This is not connected with inactivity timeout.


10.4.7.2. Menu actions for timing


10.4.7.2.1.    start_daytimer

     args: minutes
     from: menu only

     Tells application how long the individual should be
     allowed for this 24 hour period.  Does all necessary
     calculations in the event that the user has already
     called that day.

     File $users$/$id$/.timed is read and updated by this
     facility.  The file has two lines:
     line 1) date in YYYY/MM/DD
     line 2) minutes already used.

     Days run from midnight to midnight, but the whole of any
     call is treated as if belonging to the day it began. I.e.
     the user has to log on again after midnight to pick up
     his next day's alllowance.

     Returns FALSE only if invalid argument given.


10.4.7.2.2.    start_timer

     args: minutes
     from: menu only

     Starts the timer counting down number of minutes
     specified.

     Returns FALSE only if invalid argument given.


10.4.7.2.3.    stop_timer

     args: none
     from: -

     Stops the timer.

     Always evaluates to TRUE


10.4.7.2.4.    suspend_timer

     args: none
     from: -

     Pauses the timer until resume_timer issued.

     Always returns TRUE.


10.4.7.2.5.    resume_timer

     args: none
     from: -

     Resumes the timer after a pause.

     Always returns TRUE.


10.4.8.   Dropped lines etc

     When a user logs on, a "1" is written to the .laston file
     in their $users$ directory, ready for them to log off
     without warning.  If they log off using the log_off menu
     action, this is converted into a "0" to show they ended
     normally.

     Also when they log on, the user's ABEND flag picks up the
     value from the .laston file as it was after their last
     call, so that penalties may be inflicted if required. "0"
     if they logged off decently after their last session.
     "1" indicates the session abended, but in this release
     there is no way of determining whether it was a dropped
     line or a timeout.


10.4.9.   Unwanted users


10.4.9.1. Menu actions for dealing with unwanted users


10.4.9.1.1.    zap_user

     args: username
     from: menu or user input

     Calls zapuser with the given user name.  This actually
     merely terminates the drealmBBS session, but effectively
     drops line on any user who has no other shell running.

     TRUE if the zapuser system command was successful.


10.4.9.1.2.    destroy_account

     args: username
     from: menu or user input

     Removes the user's bbs account.  If the user has the BBS
     as their primary shell as per /etc/passwd, it will also
     attempt to remove their Unix account, via the normal
     system user removal utility. DrealmBBS will not remove
     any user from the password file if they are a Unix shell
     user. Depending on the setup of your system as a whole,
     sometimes it is not possible to run the system command
     for removing users from drealmBBS.

     Perversely, the newuserlog file records the passing of
     destroyed users.

     Returns TRUE if a valid username was given, but won't
     cause a FALSE result if it did not remove the unix
     account for any reason.



10.5.     Creating new users

     The SysOp can create a new user account himself, but most
     BBS allow users to set up their own accounts.  If you
     wish to allow this, the best way is to set up an ID
     called "guest" first, and allow guest to run the
     make_my_account menu action.

     If you have more than one line and therefore it is
     possible more than one caller may try to use the guest
     account at once, make accounts guest1 and guest2 etc, and
     link them via the .shunt files (see Section 10.2 "Logging
     on").


10.5.1.   What happens when a BBS account is created

     The user's individual data directory is created under
     $users$.  Within this directory are created the following
     files:

     .level    storing the value set as $newuserlevel$ in
               config.drealm.
     .flags    storing the set of new userflags specified as
               $newuserflags$.
     .drealmrc created from the config.users file.
     .firston  holds the date of creation, which will be in
               the $firstcall$ variable when the user logs on
               in future.

     Then his private files directory is created under
     $privatefiles$, the .areas subdirectory is created under
     $users$/<newid>, and his mail directory is created as
     $maildirs$/<newid>/.mail

     If the new user does not already have an entry in the
     system password file, drealmBBS calls the system's
     useradd utility to create one (make sure useradd is to be
     found in the path as per config.drealm), using the shell
     specified in config.drealm, the group number in C.public
     (NOT $groupnum$) and the directory in $homedirs$.

     On some systems, the BBS will either not have an useradd
     facility, in which case you need to write a script or
     program yourself, or maybe you don't have permission for
     your BBS to add Unix accounts, in which case you have to
     ask your superuser to do it later.  Either way the BBS
     account will be made and a message will appear about the
     Unix account problem.

     The newuserlog file records the creation of new BBS
     users.

     Troubleshooting FAQ:  The most frequent reason for
     inability to create new users is that group "bbs" does
     not have permissions to use one or more of the
     directories named in config.drealm. Look in
     /drealm/data/errorlog for a clue, and fix it with the
     guidance of Section 6.6 "Directories and files on typical
     installation".


10.5.1.1. Menu actions for creating new accounts


10.5.1.1.1.    make_my_account

     args: none
     from: -

     For a guest user to set up his own account.

     Prompts for agreement to the rules (if a file called
     rules optionally exists in $library$) and choice of 8 or
     less character id and a password, then attemps to log the
     user in under the new id.

     If the unix account could not be created, the file in
     $library$ called nocreate.txt (or other language ending -
     see Section 9.1 "Support for foreign languages") is
     displayed.

     Action never returns TRUE, as if it succeeds the user
     will have started a new drealmBBS process.


10.5.1.1.2.    make_user_account

     args: new-username
     from: menu or user input

     Set up an account for the specified ID (if it is not
     already in use), creating unix accounts as well where
     relevant.

     Returns TRUE if the bbs account is created and the unix
     account could be created or was already there.


10.6.     Maintaining users


10.6.1.   Personal data

     The personal data is saved in a file called .details in
     the user's $users$ directory.  There is a line per field:

     Line 1    Date of last update
     Line 2    User account ID
     Line 3    Real name
     Line 4    Telephone
     Line 5    Address
     Line 6    Date of birth


10.6.1.1. Menu actions for updating details


10.6.1.1.1.    give_address

     args: none
     from: -

     User is prompted for an address, to be entered all on one
     line.

     Returns TRUE if an address is given.


10.6.1.1.2.    give_dob

     args: none
     from: -

     User is prompted to enter their date of birth.

     Returns TRUE if a date of birth is given


10.6.1.1.3.    give_real_name

     args: none
     from: -

     Prompts the user to give their real name.

     TRUE if name is given


10.6.1.1.4.    give_phone

     args: none
     from: -

     Prompts the user to give their phone number.

     Returns TRUE if a phone number is entered.


10.6.2.   User defaults

     As these settings are largely to do with the user's
     interface with drealmBBS' input and output, the emphasis
     is on user input at a selection prompt, rather than
     arguments passed from the menu.

     All these defaults are saved in the user's .drealmrc
     file, which is initially set according to config.users


10.6.2.1. Menu actions for terminal interface


10.6.2.1.1.    set_terminal

     args: none
     from: -

     Allows the user to change their terminal type and screen
     size.  Any terminal identified in your system's terminfo
     library will be permitted (termcap may be used if
     desired, but you'd need to edit the Makefile).
     Set_terminal will automatically display a file in
     $library$ called termtypes.txt, if you have one, as a
     guide to the user's choice.  Create one that suits your
     system and the terminal types you recommend.


     Example termtypes.txt file:
     =========================================================
     Terminal name   CC  LL  Description
     -------------   --  --  ---------------------------------
     vt100           24  80  dec vt100 (w/advanced video)
     vt320           24  80  DEC VT320 terminal
     xterm           25  80  xterm terminal emulator (color)
     xtalk           24  80  IBM PC with xtalk communication

     =========================================================

     The terminal type will be held in the $terminal$ variable
     and will also be exported into the environment as $TERM.
     Be aware that the termcap and terminfo facilities under
     Linux are not yet perfected and it may appear in some
     places that your chosen terminal settings are being
     ignored.   This area is being worked on by Linux
     developers currently.

     Action returns TRUE if new terminal is set.


10.6.2.1.2.    set_erase

     args: none
     from: -

     Allows the user to set their erase key.  ASCII value of
     key held in $erasekey$

     Returns TRUE if setting is saved.


10.6.2.1.3.    set_werase

     args: none
     from: -

     Allows the user to set their word erase key.  ASCII value
     of key held in $werasekey$

     Returns TRUE if setting is saved.


10.6.2.1.4.    set_kill

     args: none
     from: -

     Allows the user to set their line kill key.  ASCII value
     of key held in $killkey$

     Returns TRUE if setting is saved.


10.6.2.1.5.    set_reprint

     args: none
     from: -

     Allows the user to set their inputline redraw key.  ASCII
     value of key held in $reprintkey$

     Returns TRUE if setting is saved.


10.6.2.1.6.    set_rows

     args: none
     from: -

     Allows the user to state the number of lines displayed on
     their screen.  Value held in $rows$

     Succeeds TRUE if setting is stored.


10.6.2.1.7.    set_columns

     args: none
     from: -

     Allows the user to specify the number of characters to a
     line on their screen. Value held in $cols$

     TRUE if setting is saved.


10.6.2.2. Menu actions for setting misc defaults


10.6.2.2.1.    set_hotkeys

     args: none
     from: -

     Toggles the user's hotkey setting.  Result held in
     $hotkeys$

     Having hotkeys on means that the user does not have to
     press Enter when he presses a key while being prompted by
     the "prompt" menu action.  If you allow people to select
     hotkeys, you must make sure that all menu options have a
     single character to select.  Where the application needs
     a whole string, it switches from hotkeys temporarily.

     TRUE if new setting is saved.


10.6.2.2.2.    set_pausetime

     args: none
     from: -

     Allows the user to set the time they wait before
     buffer-flushing when hang up.  The time is prompted for
     in seconds and the value is available in $pausetime$.
     This is useful for poeple who find they lose logging-off
     messages because of a slow modem.

     TRUE if new setting is saved.


10.6.2.2.3.    set_timeout

     args: none
     from: -

     Allows the user to change their inactivity timeout.  The
     new value is prompted for in seconds.  Held in $timeout$

     The inactivity timer is not in effect during execution of
     external programs, whereas the session timer can be.

     TRUE if new setting is saved.


10.6.2.3. Menu actions for general defaults


10.6.2.3.1.    maintain_me

     args: none
     from: -

     Presents the user with a menu of their current details
     and defaults and allows them to change things.

     If their level is less than $sysoplevel$ they will not be
     able to change such things as their level or flags, or
     mail allowance etc.

     Always returns TRUE.


10.6.2.3.2.    maintain_user

     args: username
     from: menu or user input

     Intended for the SysOp to maintain any user.
     Presents a menu of any user's current details and allows
     full change facilities.

     TRUE if a valid username is given.


10.6.2.3.3.    update_me

     args: none
     from: -

     More or less obsolete.  Re-reads the user's own settings.

     Returns TRUE if the user's setting are read successfully.


10.6.2.3.4.    force_update

     args: username
     from: menu or user input

     Forces the named user to pick up any updates in their
     settings.  More or less obsolete.

     TRUE if a valid username is given.


10.6.2.3.5.    reset_my_defaults

     args: none
     from: -

     Restores to the current user the new user default
     settings from config.user

     Always returns TRUE


10.6.2.3.6.    reset_user_defaults

     args: username
     from: menu or user input

     Restores to the named user, the new user default settings
     from config.user

     Returns TRUE if a valid user is named.


10.6.2.3.7.    reset_guest

     args: none
     from: -

     Resets the user to the new user defaults.  Clears out the
     private mailbox, the scanlist, newshigh, private files
     directory and message pointer records.

     Always returns TRUE


10.7.     Special help for individual users


10.7.1.1. Menu actions to help a user


10.7.1.1.1.    notify_user

     args: username then string for notice
     from: menu or user input

     Writes a notice to the user, saved in file .notice in his
     $users$ directory.  Strings are appended if more are
     subsequently written to the same user.

     TRUE if string is written


10.7.1.1.2.    check_notice

     args: none
     from: -

     If the user has a .notice file, this is displayed, and
     the file is then deleted.

     Returns TRUE if a notice was displayed.


10.7.1.1.3.    force_user

     args: username then forced command line
     from: menu or user input

     Intended for a SysOp to force a user to issue a
     particular command.  This can help them to quickly find a
     menu option for example.

     The command to be forced is written to the user's .force
     file.  The force will be picked up when the target user
     would have been presented with his next menu cycle prompt
     and will be executed in the context of that menu cycle

     Returns TRUE if the force was written to file


11.  Inter-user facilities

     This section deals with what the users can find out about
     each other, and how they can communicate with other users
     who are connected at the same time.


11.1.     Real-time communication

     A user's drealmBBS process knows about other users by
     consulting files in the $tmpdir$ directory.  There is a
     conf.<username> for each person using drealmBBS and a
     chat.<username>  as the connecting file for each person
     who is receiving chat messages.

     Each user who has chat reception enabled, is running the
     supplied chatout program as a background process.  It is
     responsible for collecting, displaying, and sometimes
     queuing chat lines from other users.  It communicates
     with the drealmBBS process with Unix signals (SIGUSR1 and
     SIGUSR2) to tell it things like whether the chat buffer
     is empty or not, and when to redraw the prompt.

     $chatnow$ is TRUE if the user has chosen to receive chat
     at this moment in time whereas $chatdefault$ is whether
     he wishes to have chat on by default when the menu first
     enables it.  The user's .chatdoing file and the chat
     status field in the whos_on list is automatically
     updated, with "*listening for chat*" if they are
     receiving or queueing chat and with "*chat disabled*" if
     either the menu has disabled it or they have chosen not
     to receive chat.

     Currently most information about other users' status is
     retrieved from disk upon each call, but plans are under
     discussion for a chat-server facility which will hold
     frequently-accessed data in memory.


11.1.1.   Menu actions to show who is online


11.1.1.1. whos_on

     args: none
     from: -

     Displays a list of people using drealmBBS.  The list has
     the following format:

     Unix ID;AKA;title;doing;chat status

     e.g. inge (Inge Cubitt - SysOp) reading. *chat disabled*

     The individual fields will be described more fully under
     the sections about setting them.

     Always returns TRUE.


11.1.1.2. set_my_title

     args: title
     from: menu only

     Sets current user's title string.

     The title is intended for such as "SysOp" or "subscriber"
     etc.  Of course you can use it for what you want.  See
     whos_on for where it appears.

     The string is saved in the .title file

     TRUE if new setting is saved.


11.1.1.3. set_user_title

     args: username title
     from: menu or user input

     Intended for SysOp to set a named user's title string.

     TRUE if new setting is saved.


11.1.1.4. set_doing

     args: string describing what user is doing
     from: menu only

     Sets the doing string for current user, displayed by
     whos_on.  The idea of this is that it changes depending
     on what the user is doing, such as downloading, or
     browsing.  This is not automatic of course, the menu line
     for setting the doing string needs to be used in close
     conjunction with line that sets off downloading for
     example. The string is saved in the .doing file.

     TRUE if the string is saved.


11.1.2.   Menu actions for chatting


11.1.2.1. enable_chat

     args: none
     from: -

     Enables chat reception.  I.e. the user will receive chat
     if they have their chat on by choice, or be allowed to
     use a chat_on option if available.  Prints "Chat
     enabled." on the user's screen.

     Returns TRUE if chat is supported according to
     config.drealm.


11.1.2.2. disable_chat

     args: none
     from: -

     Disables chat reception.  I.e. the user will not receive
     chat, even if they have their chat on by choice.  Prints
     "Chat disabled." on the user's screen at the time of
     disabling.

     Even though the program automatically holds back chat
     output during each action, on our own BBS we disable chat
     just before a user does something that will take a long
     time, like downloading, so as to stop chat queues
     becoming too large  in the meantime.

     TRUE if chat is supported according to config.drealm.


11.1.2.3. chat_on

     args: none
     from: -

     Requests chat reception.  I.e. the user wishes to receive
     chat.  If chat has been enabled by a previous menu action
     then they will get it. and it prints "Chat reception now
     turned on." on the user's screen.  Otherwise they are
     told either "Chat reception already on".  If chat is not
     enabled they will get "Chat not enabled at this point"
     but $chatnow$ will be set on and they will get chat
     started as soon as it is enabled by a menu action.

     TRUE if chat reception is turned on immediately.


11.1.2.4. chat_off

     args: none
     from: -

     Requests no chat reception.  I.e. the user wished not to
     receive chat, even if chat is enabled.  (This is a user
     command.) Prints "Chat reception now turned off." or
     "Chat reception already off" on the user's screen.

     TRUE if chat is supported according to config.drealm.


11.1.2.5. set_chat

     args: none
     from: -

     Toggles the user's default chat setting.  Value is
     accessed in $chatdefault$.

     Chat on by default means that they will start up drealm
     as if they had already asked to turn chat on, therefore
     beginning to receive as soon as the first enable_chat is
     encountered.

     TRUE if new setting is saved.


11.1.2.6. set_in_colour

     args: number of colour
     from: menu or user input

     Allows the user to set the colour in which their incoming
     chat appears.  If an argument is passed it must be in the
     numeric form, but if no argument is passed, the user is
     taken into a friendly mini-menu where the names of the
     colours are shown.

     ANSI colour codes are used to colour the chat.  These
     codes are passed to the background chatout process at
     relevant times.

     The values are as follows:

     plain     10
     bold      11
     yellow    12
     red       13
     green     14
     blue      15
     cyan      16
     magenta   17
     multi     18

     The setting is held in the $chatincolour$ variable.

     If the user chooses a specific colour, they will not
     receive the colours of chat being sent, but it will all
     change to the one chosen colour. Only the "multi" setting
     allows the user to receive chat messages in the colours
     they were sent by the other users.

     "plain" is a suitable setting to use if the user's
     terminal has no ANSI capabilities.

     Returns TRUE if new setting is saved.


11.1.2.7. set_out_colour

     args: number of colour
     from: menu or user input

     Allows the user to set the colour of the chat they send
     out.  This will be appreciated by those other users who
     receive multi coloured chat.  Colours and method is as
     for set_in_colour, except that plain and multi are
     excluded.

     The value is held in the $chatoutcolour$ variable.

     Returns TRUE if new setting is saved.


11.1.2.8. say

     args: string of text for chat message
     from: user input only

     Broadcasts a chat message of "[$id$ says] <args>" to any
     other user who has chat reception enabled.

     Returns TRUE if a chat message was entered by the sender,
     regardless of receipt.


11.1.2.9. whisper

     args: intended recipient then string for message
     from: user input only

     If the recipient is using drealmBBS and has chat
     reception on, this sends a chat message of "[$id$
     whispers] string" to the named recipient only.

     Returns TRUE if a chat message was entered by the sender,
     regardless of receipt.


11.1.2.10.     emote

     args: string representing actions
     from: user input only

     For indicating personal mood action.

     Broadcasts a message of "<$id$ actions>" to all users
     receiving chat.

     Example: if user "fred" issues the command "emote smiles"
     it is broadcast as <fred smiles>

     Returns TRUE if an emote message was entered by the
     sender, regardless of receipt.


11.1.2.11.     fx

     args: string to be broadcast
     from: user input only

     To create an atmosphere effect.  Broadcasts a message of
     "<FX: string>" e.g. <FX: Footsteps approach>

     The user's id is not inserted, but it is sent in their
     normal chat colour.

     Returns TRUE if a  message was entered by the sender,
     regardless of receipt.


11.1.2.12.     broadcast

     args: string to be broadcast
     from: menu only

     Broadcasts a message to everyone with chat on and
     enabled.  Really intended for set messages accompanying
     certain events, such as "\$id$ has just logged on".

     Returns TRUE if something was broadcast, regardless of
     receipt.


11.2.     Info about other users

     Information which can be accessed about a fellow user
     without waiting for them to log on.

     The planfile which is mentioned here is saved as .plan in
     the user's $privatefiles$ directory.

     The AKA is the comments field from the /etc/passwd file


11.2.1.   Menu actions to give info about or to other users


11.2.1.1. list_users

     args: none
     from: -

     Displays a listing of the $users$ directory.

     TRUE if the command succeeds.


11.2.1.2. edit_plan

     args: none
     from: -

     Allows the user to edit their planfile.  This file is
     intended to contain personal information about the user
     which he wishes to make public - a sort of resume or
     introduction.  In drealmBBS convention this file is
     referred to as the planfile.

     Returns TRUE if the planfile is saved.


11.2.1.3. finger

     args: username
     from: menu or user input

     Displays the named user's planfile.

     Returns TRUE if the target's planfile was displayed.


11.2.1.4. grab_finger

     args: username
     from: menu or user input

     If the requester is at or above $pvtfileslevel$, this
     appends the named user's planfile to the requester's
     grabpad.

     TRUE if the user's planfile was grabbed.


11.2.1.5. plan_search

     args: pattern to search for
     from: user input

     Searches through all the users' planfiles for a matching
     pattern.  * and ? wildcards may be included.

     Returns TRUE if planfiles were searched regardless of
     outcome.


11.2.1.6. give_aka

     args: none
     from: -

     Because the ID is a maximum of 8 characters, there is an
     opportunity to display a longer name (probably but not
     necessarily the real name).  To keep this flexible it is
     not taken from the real name field as saved in the
     .details file.  This "AKA" string is inserted into the
     comments field in the password file by the username
     program supplied, which in turn calls the system's
     usermod utility.

     Any ',' and ':' entered are stripped before insertion
     into the password file.

     Obviously this AKA is then inserted by some mailers into
     external mail and shown during the shell's finger
     command.

     Returns TRUE if password file updated.


11.2.1.7. who_is

     args: username
     from: menu or user input

     Displays the AKA of the named user from the comments
     field of the password file.

     Returns TRUE if the user exists.


12.  Public Message areas

     These are individual directories, each one of which is a
     collection of related messages or articles written by
     users.  The messages can accumulate over a long period of
     time. The usual idea is to have one message area per
     subject, such as one on fishing and one on PC
     maintenance, but general chatter areas are also used.
     All the directories are under the $areasdir$ directory as
     set up in config.drealm

     A message area contains messages which may be read by
     anyone having access to the area, so differing from
     real-time chat by serving the function of everything from
     bulletins to a database which can be read by everyone who
     logs on at different times.  Of course there are ways
     provided of limiting access where required - see later.


12.1.     Creating and maintaining public message areas


12.1.1.   Menu actions for creating and removing areas


12.1.1.1. create_area

     args: new areaname
     from: menu or user input

     Creates a new area, prompting for a one line description.
     The event if successful is logged in newarealog in
     datadir.

     Creating a new area creates a directory by the area name
     under $areasdir$ and creates within it the following
     files:

     flags          using values in $newareaflags$,
     areamask       using values in $newareamask$,
     level          using value in $newarealevel$
     highest        storing '0'
     msgindex       storing '0'
     members        empty
     chair          containing the $id$ of the person creating
                    the area.
     gagged         empty
     description    containing max 50 character line prompted
                    for.

     Returns TRUE if the new area is created.  If any part of
     the creation fails the whole process is backed out.


12.1.1.2. destroy_area

     args: area-name
     from: menu or user input

     Removes an entire message area.  Only a chairman of the
     area or a SysOp may remove an area. User is asked to
     confirm.

     Also removes related pointers file
     ($users$/.areas/<areaname>) for each user.  This may take
     some time if there are many users.  Does not touch
     entries in users' scanlists, which at least informs them
     that the area is gone.

     Returns TRUE if the area is removed.


12.1.2.   Types of areas


12.1.2.1. Areaflags

     Areaflags are saved in the file called flags in the
     area's own directory.  There should be a string of 30
     characters, each one representing a flag.  The array is
     held as $areaflag$.  Flag names may be used to subscript
     into this variable.

     Every time a user changes message area, the flags for
     that area are loaded into his $areaflag$ variable.  The
     areaflags field of any menu line must match this string
     of flags if the menu line is to be executed.

     An example of how an areaflag setting might be used is if
     you had downloadable files associated with certain
     message areas.  You could set an ISFILEAREA flag for
     those which had a file collection, and offer a download
     option on the menu only when that flag was TRUE.

     As with userflags, a flag does not necessarily have to be
     a '1' or a '0', any single character or digit will do.
     Flags 11-30 are custom-definable, and their names can be
     defined in the config.aflags file.

     The first 10 areaflags are either set by the application
     or reserved.

     When not "0" they mean:

     areaflag 1  AREATRUE    1 = A current area is set.
     areaflag 2  SIGS        1 = Area appends user's .sig
                             to his messages.
     areaflag 3  ALIASES     1 = Area allows choice of
                             alias instead of userID.
     areaflag 4  READONLY    1 = Only the chairman may post
                             messages.
     areaflag 5  PRIVATE     1 = Members list will be
                             checked before allowing users
                             entry to it.
     areaflag 6  MODERATED   1 = Messages posted by
                             non-SysOp non-chairman users
                             will be held in a subdirectory
                             called  pending until a
                             chairman approves them for
                             placement using the "moderate"
                             menu action.
     areaflags   reserved
     7-10


12.1.2.2. Menu actions for setting areaflags


12.1.2.2.1.    areaflags

     args: none
     from: -

     This one is ideal for a SysOp or a very trusted chairman.
     It takes the user into a mini-menu which displays all the
     flag settings and allows him to change any flag to any
     setting.

     TRUE if the current area's flags can be changed.


12.1.2.2.2.    set_areaflag

     args: areaflag position, then value
     from: menu only

     This action allows for the setting of just one specified
     flag, to a specified value.

     This is of use where a SysOp wants to preserve a degree
     of control over the collection of areas, only allowing
     the chairman to make a few decisions.

     The value may be passed as a single character, or the
     strings "on", "off" and  "toggle" are understood.  For
     selecting the flag itself, the flag name may be given, in
     correct case (normally upper), or its numerical position
     (eg #3)

     Example: set_areaflag MODERATED toggle

     Returns TRUE if flag is set.


12.1.3.   Controlling access to a public message area


12.1.3.1. Areamasks

     The areamask is a string of 30 flags which correspond to
     userflags.  It is used for comparison with the current
     user's flags when deciding whether to allow him access to
     a message area.  For example there may be a SUBSCRIBER
     userflag and you may have a subscribers only message
     area.  "?" can be used in positions that are not required
     for comparison.  Any flag position without a "?" must be
     strictly matched by the user's corresponding flag.  The
     areamask is saved in the areamask file in the area
     directory, and in the $areamaskflag$ string variable.


12.1.3.2. Menu actions for setting areamasks


12.1.3.2.1.    maskflags

     args: none
     from: -

     This one is ideal for a SysOp or a very trusted chairman.
     It takes the user into a mini-menu which displays all the
     mask flag settings and allows him to change any flag to
     any setting.

     Returns TRUE if the current area's mask can be updated.


12.1.3.2.2.    set_maskflag

     args: mask flag then value
     from: menu only

     This action allows for the setting of just one specified
     flag, to a specified value.

     This is of use where a SysOp wants to preserve a degree
     of control over the collection of areas, only allowing
     the chairman to make a few decisions.

     The value may be passed as a single character, or the
     strings "on", "off" and  "toggle" are understood.  For
     selecting the flag itself, the flag name may be given, in
     correct case (normally upper), or its numerical position
     (eg #3)

     Example: set_maskflag CHAIRMAN on

     Returns TRUE if flag is set.


12.1.3.3. Level

     The message area can be restricted to users over a
     certain user level only.

     The level file (based on $newarealevel$) is written at
     the time of area creation.


12.1.3.3.1.    Menu actions for changing access level


12.1.3.3.1.1.  set_arealevel

     args: level
     from: menu or user input

     Sets minimum access level at which a user may access
     current message area.

     Returns TRUE if chosen level is written to disk.


12.1.4.   Menu actions for area info and administration


12.1.4.1. edit_info

     args: none
     from: -

     Intended for the chairman to edit the info file for his
     message area.  The info file is automatically displayed
     when a user enters any area for the first time.  The file
     is called info and is in the area directory.  It is
     optional.

     Returns TRUE if info file is saved.


12.1.4.2. show_info

     args: none
     from: -

     Display the area info file.  This file is also displayed
     when each user accesses the area for the first time.

     Returns success if there was any info displayed.


12.1.4.3. describe_area

     args: none
     from: -

     Prompts the user for the 50-character description that
     appears on the area list.

     TRUE if description is successfully written.


12.1.4.4. area_status

     args: none
     from: -

     Display various facts about the current area.

     If it is open or private, read/write or read-only, allows
     aliases, uses .sig files, and the total number of
     messages.

     Always returns TRUE.


12.1.4.5. participants

     args: none
     from: -

     Lists all users who have read messages in the current
     area, and the number of the last message they read.

     TRUE if any users are listed.


12.1.4.6. moderate

     args: none
     from: -

     Checks in /$areasdir$/$areaname$/pending to see if
     messages are pending approval, then offers them one by
     one.

     TRUE if messages were pending.


12.1.4.7. add_chairmen

     args: new chairmen list separated by spaces
     from: menu or user input

     Adds one or more chairmen to a message area.

     Returns TRUE if one or more chairmen added.


12.1.4.8. rem_chairmen

     args: list of one or more names, space separated
     from: menu or user input

     Remove the given names from the chairman list.

     TRUE if one or more chairmen removed.


12.1.4.9. show_chairmen

     args: none
     from: -

     Displays the list of area chairmen.

     Returns TRUE if one or more chairmen listed.


12.1.4.10.     add_members

     args: list of members, space-separated
     from: menu or user input

     Adds one or more members to a private message area.

     Returns TRUE if one or more members added.


12.1.4.11.     rem_members

     args: list of names, space separated
     from: menu or user input

     Removes the given names from the members list.

     Returns TRUE if one or more members removed.


12.1.4.12.     show_members

     args: none
     from: -

     Displays the list of area members if the area is a
     private one.

     TRUE if one or more members listed.


12.1.4.13.     add_gagged

     args: list of names, space separated
     from: menu or user input

     Gags one or more participants.

     Gagging a user means he cannot post in a particular area.

     Returns TRUE if one or more participants gagged.


12.1.4.14.     rem_gagged

     args: list of names, space separated
     from: menu or user input

     Removes the given names from the gagged list.

     TRUE if one or more participants ungagged.


12.1.4.15.     show_gagged

     args: none
     from: -

     Displays the list of gagged participants.

     TRUE if one or more participants listed.


12.2.     Navigating message areas


12.2.1.   Changing to a specific message area

     Each area the user attempts to change to is checked for
     accessibility - that it exists, that the user's flags fit
     the usermask, that his level is sufficient, and if the
     area is a private members' one that he is in the members
     list.

     If all that is in order, the process decides how far
     through the messages the user has reached.  Each user has
     a directory called .areas under his $users$ directory.
     In this there is a file for each message area he has
     accessed, and contains, in theory the highest message
     number read in that area.  In fact the value of
     $msgpointer$ (the message pointer) gets written to it
     after an area is left or the user logs off, and this can
     sometimes not be the same thing - see later.

     Using this value, the process works out how many unread
     messages there are waiting in the area.  Then it works
     out which message number would be next to read
     ($msgpointer$) when the user starts reading.  If the user
     has $recent$ set to a non-zero value, and there are more
     unread messages than this, they will be asked if they
     wish to catch up to the $recent$ newest messages.
     $msgpointer$ will be set by subtracting $recent$ from the
     highest message number ($highestmsg$).

     Userflag #CHAIRMAN is updated depending on whether user's
     name is in the area's chairmen file, and userflag #GAGGED
     is updated if the user is in the gagged list.  If this is
     the first access by the user, the area's info file is
     displayed.

     If there is a message area specified in config.drealm as
     $startarea$, drealmBBS will attempt to change area to
     this when it starts up.


12.2.1.1. Menu actions for selecting areas


12.2.1.1.1.    change_area

     args: area name
     from: menu or user input

     Checks that the user is allowed access to the chosen
     area.  Writes value of $msgpointer$ for previous area to
     file.  Changes the value in $areaname$ to chosen area.

     If there are more new messages than the user's chosen
     $recent$ setting, the user is offered the chance to catch
     up to recent (see Section 12.3.3.1.5 "set_recent").

     TRUE if the chosen area is valid and accessible by the
     user.


12.2.1.1.2.    list_areas

     args: areaflag settings to match, then minimum userlevel,
           then areamask (userflags)
     from: menu only

     Lists all areas that match the given areaflag pattern and
     are accessible to users of given level and userflags.

     If no flags are given, all are matched, if no level is
     given, all areas accessible to $sysoplevel$ are matched.
     Arguments may be ommited from the end, but not from the
     middle!

     Example:
     To show a list of all areas which are accessible to the
     current user, use
     list_areas ?????????????????????????????? \$mylevel$
     \$myflag$

     Returns TRUE if any areas are listed.


12.2.2.   Scanning areas

     Each user may optionally set up a list of areas he wishes
     to monitor regularly for new messages.  The list is saved
     in a file called .scanlist in the user's $users$
     directory.  The format of this file is one message area
     per line.  Should there be more than one area on a line,
     only the first one is accepted. There is no limit to the
     number of areas in the list.


12.2.2.1. Menu actions for scanning


12.2.2.1.1.    scan_areas

     args: "e" or "q" or none
     from: menu or user input

     The default, if no argument is passed, is as follows.
     Using the user's scanlist this searches for the next area
     in the listed order with new messages.  When it finds one
     it also checks for access rights to the area before
     stopping on it.

     It then executes change_area and returns the success or
     otherwise of that action.

     Returns TRUE if an area with new messages is changed to.

     Passing the parameter "e" (for "express") scans the
     areas, notifying how many new messages in each, but
     stopping at none.  TRUE if new messages found.

     Passing "q" (for "quiet") scans the areas without output,
     and returns TRUE if any areas in the user's scanlist
     contain new messages.


12.2.2.1.2.    edit_scanlist

     args: none
     from: -

     Allows the user to edit directly the list of areas that
     the scan command will take them through.

     Always TRUE.


12.2.2.1.3.    add_area

     args: area name or list
     from: menu or user input

     Append the named area to the scan list, having checked
     for validity.

     TRUE if the area name was added.


12.2.2.1.4.    drop_area

     args: area name or list
     from: menu or user input

     Remove all occurrences of area name from the scan list.

     TRUE if an area was dropped.


12.3.     The messages

     Messages are stored within the area directory.  They are
     uniquely numbered within the message area, ie each area's
     message numbering begins from 1 and can go up to 4000.
     Posting is not allowed beyond 4000.  Messages keep their
     original number regardless of how many earlier messages
     are deleted.  This release of drealmBBS does not offer
     message renumbering or automatic expiry, although at some
     stage in the future we hope to provide an alternative
     message base structure possibly with some FIDO
     compatibility.


12.3.1.   Structure of an area message

     Each message is made up of two files, one contains the
     message text and is named for example msg.221 and the
     other contains the header and control details, eg hdr.221

     The hdr file is made up of space separated fields:

     Field 1     '#' if normal message, 'A' if it is to be
                 displayed by special routine for ANSI graphic
                 messages.

     Field 2     Individual message number unique within area

     Fields 3-8  Date of posting

     Field 9     "from" (literal)

     Field 10    name of author or alias where allowed.
                 Maximum 14 characters

     Field 11    Strings:
                 "reply-to" if message was posted using reply
                 action "comment-to-thread" if message was
                 posted using comment
                 "BASE-MESSAGE" if message was posted using
                 post action.  This means the message is the
                 foundation of a thread.

     Field 12    Strings:
                 "#" if message was a reply
                 "@" if message was a comment
                 "-" if message was a base message

     Field 13    Parent message number, eg message this was a
                 reply to or a comment at, unless it was a
                 base message, in which case this field merely
                 holds "-"

     Field 14    String "by" if this message is a reply,
                 otherwise "-"

     Field 15    Author of parent message, if this message is
                 a reply, otherwise "-"

     Field 16    Message number of base message for the
                 thread.  If this message is itself the base
                 message, this field will have the same number
                 as the message's own number of course.

     Field 17    Number of next higher numbered message in
                 thread.  If there are no higher, field
                 contains "-"

     Field 18    Number or next lower numbered message in
                 thread.  However, if this message is itself
                 the base message, the field will contain the
                 number of the NEWEST message in the thread.

     After field 18 there will normally be a newline.

     Field 19 on Every time a user comments or replies to a
                 message, the header file is opened and the
                 message number of the latest reply is
                 appended, leaving a space character between
                 each.


12.3.2.   How they are related within an area


12.3.2.1. Indexing

     The message index is in a file called msgindex in the
     area directory.  After the dummy character for offset 0,
     each offset represents a message number.  a 'B' means the
     message is the founder or base-message of its particular
     thread.  'M' means it was posted as a reply or comment.
     'D' means it is deleted.  A place is always held for a
     message, even after deletion.

     During access to a message area, the user takes a memory
     copy of the message index, and it is this which is
     updated as he reads the messages.


12.3.2.2. Threading

     Each message is part of a thread.  The base message is
     the foundation message of the thread, and all replies and
     comments to any message in that thread are linked to it
     by data within their headers.  See Section 12.3.5
     "Posting messages" for detail about how a message is
     physically  incorporated into its thread.  A thread is a
     more or less chronological straight line in concept,
     regardless of which message was a reply to which other in
     the thread.

     There is also a concept of "branches" which are upside
     down tree-like structures, made up of a message, and its
     direct replies, and the replies to those replies etc.   A
     branch can be defined from any point along a thread, or
     from within a greater branch.


12.3.2.3. Menu actions for altering existing message threads.


12.3.2.3.1.    link_msg

     args: object message "to" target message
     from: menu or user input

     Leaving the actual message numbers unaltered, this
     removes the object message and its dependant branch from
     its original thread, and makes it part of the target
     message's thread and enters the object message's number
     in the target message's replies field, thus making it a
     branch from there.

     The object message's header is altered to display
     "linked-to" in the normal "reply-to" field.

     Object message must be higher numbered than target
     message.

     TRUE if branch is relinked.


12.3.2.3.2.    unlink_msg

     args: message-descriptor
     from: menu or user input

     Unless the message request is already a base message, it
     is severed from its parent and turned into a base
     message.

     TRUE if message is unlinked.


12.3.2.4. Message descriptors

     Message descriptors are strings recognised by menu
     actions as referring to specific messages, so they can be
     used as parameters easily, or entered by the user when
     prompted.  A valid descriptor can either be absolute, eg
     the message number itself, or relative, eg the parent
     message to the last accessed.

     Each menu action will take care of politely rejecting
     those descriptors which are unsuitable for its purpose.

     In the table below, the whole word argument is hardcoded,
     and the single letter is dependant on the language file
     (see Section 9.1 "Support for foreign languages"). The
     example as below uses the language file as distributed by
     the authors.


     "." or "current"   Message last displayed after access
                        by any method.  Message number held
                        in $current$ variable.
     ">" or "forward"   Next numerically higher message
                        relative to $current$.
     "<" or "back"      Next numerically lower relative to
                        $current$.
     "v" or "onthread"  Next higher message within the
                        thread. Relative to $current$.
     "^" or "upthread"  Next lower message within the
                        thread, relative to $current$.
     "u" or "parent"    The message to which $current$ is a
                        reply or comment, or linked-to.
     "b" or "base"      Base, or foundation message of
                        thread containing $current$.
     "a" or "first"     Earliest existing message in area.
     "z" or "last"      Latest existing message in area.
     "d" or "thread"    The entire thread which contains
                        $current$.
     "h" or "branch"    The branch hanging from $current$.
     <msg number/s>     A message number or list of numbers
                        separated by spaces.
     "n" or "next"      Refers to message in $whichnext$.
                        This is the message which is next
                        unread in default order.  See
                        Section 12.3.4.2 "Read by default
                        mode".


12.3.3.   Message pointers

     A message pointer is a single value per user per area.
     When first read into memory, to $msgpointer$ it
     represents the highest message that has been read by the
     user, using his selected default order.  During
     threadwise reading, the message pointer does not move
     until completion of each thread - so that drealm knows
     where to start looking for a new thread.   Between
     accesses to a message area, the message pointer is saved
     in the user's $users$/$id$/.areas directory, as a number
     in the file named after the message area.


12.3.3.1. Menu actions which move message pointers


12.3.3.1.1.    jump

     args: message descriptor, "start" or "end"
     from: menu or user input

     Jump is intended to move TO a specified message
     If an actual message is specified, this sets $msgpointer$
     to the given point and displays the next message in
     default order.

     "jump start" marks all messages unread and "jump end"
     marks all messages read, without displaying any message.

     Returns TRUE if valid arguments given.


12.3.3.1.2.    skip

     args: "forward" number, "back" number "thread" or
           "branch" (defaults to forward)
     from: menu or user input

     Skip is intended to move OVER specified messages.

     "skip forward" advances the messages pointer by the given
     number. "skip back" regresses the user's highest read
     pointer by the given number.  The next message in default
     order is displayed.

     If a forward skip would go above the highest message, all
     messages are marked as read.

     If a backward skip would go below zero, all messages are
     marked as unread.

     "skip thread" and "skip branch" respectively mark all
     messages in the current thread or branch read.

     TRUE if valid arguments given.


12.3.3.1.3.    store

     args: none
     from: -

     Data from message pointer files in $users$/$id$/.areas is
     copied to $users$/$id$/.tmpareas

     Always returns TRUE


12.3.3.1.4.    restore

     args: none
     from: -

     Copies back message pointer data from the .tmpareas
     directory. The user is asked to confirm this operation.

     TRUE if pointers are restored.


12.3.3.1.5.    set_recent

     args: none
     from: -

     Allows the user to set the number of new messages they
     wish to be offered when they access a message area for
     the first time.  This value is held as $recent$.
     $msgpointer$ is adjusted accordingly, after confirming
     with the user, before the user starts to read.

     Returns TRUE if new setting is saved.


12.3.4.   Reading messages

     A message is read by displaying selected fields from the
     header, followed by the subject line and then the message
     body.  Also the numbers of any replies are listed.
     User's page width and length are respected.

     Messages may be read either by selecting a specific
     message to read or by using the "next" message descriptor
     to move to the next message in default reading order
     ($readmode$).


12.3.4.1. Reading a specific message

     Reading a specific message does not move the position of
     the message pointer. This is in order that a user can
     digress to refer to other messages, yet continue to read
     new messages where he left off when he's ready.


12.3.4.1.1.    Menu actions to select and read specific msg


12.3.4.1.1.1.  read_msg

     args: message descriptor
     from: menu or user input

     Displays the message.  Does not update $msgpointer$

     TRUE if the requested message is displayed.


12.3.4.1.1.2.  text_search

     args: text-pattern inside double quotes, then "from"
           message "to" message
     from: menu or user input

     Lists lines from messages that match the pattern, between
     the two given messages (the first must be lower than the
     second).

     Patterns may contain the wildcards "*" and "?".

     Returns TRUE if valid arguments were given regardless of
     whether pattern was located.


12.3.4.1.1.3.  list_headers

     args: "from" (optional) message or "new" or "subjects" or
           "thread" or "branch"
     from: menu or user input

     Displays a short-form message header plus the subject for
     the requested messages.  "new" lists all messages past
     the current pointer.  "subjects" lists all base messages.
     "thread" lists all messages within the current thread.
     "branch" lists all messages within the current branch.

     Returns TRUE if any headers were found.


12.3.4.2. Read by default mode

     Reading by default mode is the easiest way to make sure
     no messages are either missed or read more than once.

     Using the "next" argument to read_msg allows the user to
     read the message which is next unread for him according
     to his own selected default reading mode.

     Hint: It is user-friendly to set your message menu so
     that pressing Enter (*DEFAULT*) executes the action
     "read_msg next".

     There are three default modes available.


12.3.4.2.1.    NUMERICALLY

     Messages are read in strict numerical order, ignoring any
     threading or subject links.


12.3.4.2.2.    THREADWISE

     Messages with a common base message are read before
     starting on another sequence of messages with another
     base message and so on.  Messages are read in numerical
     order within this framework.


12.3.4.2.3.    REFERENCE

     Each time a message is read, any replies to it are read
     next, and if one of those replies itself has a reply,
     that is inserted into the reading order and so forth.


12.3.4.2.4.    Menu actions for choosing default read mode


12.3.4.2.4.1.  set_readmode

     args: none
     from: -

     Allows the user to change their message reading default
     order.

     TRUE if new setting is saved.


12.3.4.2.4.2.  set_readown

     args: none
     from: -

     Toggles whether to display the user's own newly posted
     messages in default reading order.  In other words, if
     while reading a message area, the user makes some
     replies, if this setting is TRUE, he'll read the messages
     he's just posted when he gets to them.

     TRUE if new setting is saved


12.3.5.   Posting messages

     See Section 9.3.4 "The editing experience" for details of
     composing a message

     From the system's point of view, the following things
     happen when a message is posted to an area.

     The message index (file msgindex) is written to.  A 'B'
     is appended if this is a BASE-MESSAGE and a 'M' if it is
     a comment or reply.

     The header of the base message of the thread is adjusted
     so that it records the new "latest" message.  The header
     of the previous latest in the thread is adjusted to
     record the new "next" and if this was a reply or comment,
     the header of the original, or parent message has the
     number of this message appended in the replies field.

     While the header linking is going on, the thread is
     locked against other users updating the thread.  The
     relevant lock file is x.lock where x is the number of the
     base message to the thread.  Meanwhile hangup signals are
     trapped, to allow the threading to continue if the user
     drops line.  If a lock is left behind and needs removing
     manually, it  is a good idea to check on the state of the
     headers in the thread to prevent corruption of message
     area.

     The file highest has its saved value incremented by 1.

     The poster's $totalmessages$ (saved in file
     .totalmessages) is incremented by one.

     If the user has $readown$ FALSE (selected not to read his
     own new messages tagged on at the end), the message just
     posted is marked as read in the memory copy of the
     message index.


12.3.5.1. Menu actions for posting new messages


12.3.5.1.1.    quote_msg

     args: message descriptor
     from: menu or user input

     Appends the requested messages to the user's workpad
     ready for editing. The quoted sample begins "So-and-so
     wrote:" and each quoted line has a ">" at the start of
     it.

     Returns TRUE if a valid argument is given.


12.3.5.1.2.    post_msg

     args: none
     from: -

     Post a message in current area, as base message to a new
     thread.  User is prompted for subject.

     Returns TRUE if message is posted.


12.3.5.1.3.    reply_to_msg

     args: single message descriptor (optional)
     from: menu or user input

     Reply to a message in current area.  If no argument is
     passed, the reply links to $current$. The new message
     forms part of an existing thread.

     Returns TRUE if message is posted.


12.3.5.1.4.    comment_to_msg

     args: single message descriptor
     from: menu or user input

     Similar to reply_to_msg, but the author of the original
     is not named and the new message is to be regarded as a
     general contribution to the discussion rather than a
     direct reply to one message.

     Returns TRUE if message is posted.


12.3.5.2. Sigs

     Sig is short for signature.  The idea is that a user has
     a small file containing anything from his name and email
     address to a witty saying, and this file is appended to
     any message he posts.  (Sigs may be allowed or disallowed
     per message area, by setting the SIGS area flag
     appropriately)

     The file used is .sig in the user's private files
     directory.  If $privatefiles$ == $homedirs$, this file
     may also be used in some other Unix applications.


12.3.5.2.1.    Menu actions for using sigs


12.3.5.2.1.1.  edit_sig

     args: none
     from: -

     Allows the user to edit or upload their .sig file.
     Normal drealmBBS editing routine is used.

     Returns TRUE if the .sig is saved.


12.3.5.3. ANSI message flag

     This is for messages which are intended to display as
     ANSI graphics.  The ANSI flag occupies the first field in
     an area message header, the "#" becomes an "A".  When
     set, this flag causes a "Press ENTER" prompt after the
     header and at the end of the message, and no pagination
     takes place.  This prevents ANSI/RIP/etc messages being
     disturbed on display.


12.3.5.3.1.    flag_msg

     args: single message descriptor
     from: menu or user input

     Toggles the "ANSI" flag on a message.

     Returns TRUE if the requested message's flag is toggled.


12.3.6.   Deleting

     When a message is deleted, the msgindex is marked with a
     D for that position, and previous in thread, next in
     thread, and base of thread headers are adjusted to
     reflect the change in the composition of the thread.

     The thread is ultimately relinked, updating relevant
     fields, unless there are no messages left in it after the
     deletion.  If the message being deleted is the base
     message, as long as there are other messages in the
     thread remaining, the base message will remain
     physically, but the message body text will be replaced
     with "Message deleted".


12.3.6.1. Menu actions for deleting public messages


12.3.6.1.1.    delete_msg

     args: message descriptor
     from: menu or user input

     Removes the requested message if user is the author,
     chairman, or SysOp.  For "thread" and "branch", the user
     must be a chairman  and must confirm that they want to
     remove the messages.

     TRUE if requested messages are removed.


12.3.7.   Grabbing

     The aim in grabbing is to append the result to the user's
     grabpad, in such a way that it may be downloaded and read
     offline, possibly with an offline reading program.


12.3.7.1. Menu actions for grabbing public messages


12.3.7.1.1.    grab_msg

     args: message descriptor
     from: menu or user input

     Appends the requested messages to the users grabpad.  A
     "." message separator symbol will be appended on a new
     line immediately after.  See Section 14 "Offline reading"
     for more details

     TRUE if a valid argument is given.


12.3.8.   Copying


12.3.8.1. Menu actions for copying public messages


12.3.8.1.1.    copy_msg

     args: message descriptor "to" areaname
     from: menu or user input

     Copies the requested messages to the named area, if the
     user has permission to post messages in that area.

     If "thread" or "branch" being copied, this action will
     preserve threading.

     Returns TRUE if valid arguments are given.


12.3.9.   Voting

     Any message may be turned into a vote.  The author should
     list the options in the message itself.  Any single
     characters may be selected to represent the options.

     The application does not make validity checks on the
     votes cast, but it does ensure that no user votes more
     than once on any message.

     Whenever a voting message is read, a summary of votes
     cast so far is appended to the display.

     The voting data is held in the file
     $areasdir$/<area>/vote.<msgno>.  This is in the format
     <single char choice>[space]<user ID> with as many lines
     as voters.


12.3.9.1. Menu actions for voting


12.3.9.1.1.    create_vote

     args: message descriptor or defaults to current
     from: menu or user input

     Creates the file vote.<msgno> ready to receive votes.
     User must have authority over the message (eg author or
     SysOp)

     Returns TRUE if file is created.


12.3.9.1.2.    vote

     args: message descriptor or defaults to current
     from: menu or user input

     User is shown the message again and prompted to enter his
     vote.  He can only type in a single character, but no
     validity checking is done against available options.

     If the user has already voted to the message, he is told
     so and is unable to vote.

     The user's name and vote are appended to the file
     vote.<msgno>

     Returns TRUE if user casts vote and it is written to
     file.


12.4.     Reading news

     This is to encourage your users to read important news,
     where they may forget or not know how to access the news
     message area as part of their normal message reading
     habits.

     This method scores over directly displaying a file,
     because each news bulletin only need be read once by each
     user.

     Any message area can be nominated as the news area, and
     is defined in config.drealm as $newsarea$.


12.4.1.   Menu actions for reading BBS local news


12.4.1.1.1.    news

     args: none
     from: -

     Displays, in reverse numerical order, messages in the
     area named in $newsarea$.

     File $users$/$id$/.newshigh is updated with highest news
     message present so that only messages newer than that are
     offered to the user on his next login.

     User may choose to stop reading news after each item.

     Always returns TRUE.


13.  Private Mail

     Private mail is for one user to send a message to
     another, or to a list of other users.  Each recipient
     gets his own copy of the mail message to read and delete
     at his leisure.  The sender will also get a copy if it is
     internal mail.  If the sender keeps the copy, the header
     will record the fact that the recipient has read it when
     that happens.

     Mail messages are kept in the directory
     $maildir$/$id$/.mail and each message is made up of two
     files.  hdr.<number> contains the control details and
     msg.<number> contains the message text.


13.1.     Local private mail

     Local mail is defined as that which is sent between two
     BBS users on the same system.

     When sending mail to another BBS user, the sender's level
     is checked against $pvtmaillevel$ and his flags are
     checked against $pvtmailmask$ both as defined in
     config.drealm.  If he does not match up to criteria he is
     told he may only mail the SysOp.

     The recipient's level is checked for private mail access
     in the same way. If the proposed recipient does not match
     the criteria, the sender is told his target has no
     mailbox, unless the sender himself is above $sysoplevel$.

     Another useful variable is $sysopname$ which when used as
     an argument to post_mail can allow new users to post mail
     to SysOp without learning any mail commands.

     Identically numbered mail messages are sent to both the
     recipient's and the sender's directories.  The two
     purposes of this are that the sender can remind himself
     what he wrote to the person, and that the header is
     altered to show when the recipient has read his copy.

     When mail is sent locally between users, a file called
     $users$/<recipient>/.mailalert is created for the
     recipient, and this is used by the menu actions which
     check for new local mail.

     drealm uses the value saved in $datadir$/mailreached to
     allocate the next message number, and updates it each
     time a number is allocated.


13.2.     External private mail

     For the purposes of drealmBBS, external mail is defined
     as that which originates from outside the drealmBBS
     program, either on the same system or a remote one, or
     mail which is has an "@" in the recipient or sender
     field.

     External mail arrives in the normal Unix mail directory,
     and if you wish your users to read external mail from
     within the BBS, the mail gets pulled in and converted to
     drealm format by the collect_unix_mail menu action.

     For incoming mail, drealmBBS decides whether to treat any
     particular message as tollable depending on whether there
     is an "@" in the sender's ID.

     $extmaillevel$ and $extmailmask$ are defined in
     config.drealm and are compared with the user's level and
     flags to decide whether he should be able to send or
     receive external mail.

     If mailmonitor is set to "1" in config.drealm, any
     tollable mail being sent, grabbed or read for the first
     time is assessed for size in bytes (including any
     internet header information) and compared with allowance
     remaining in the $users$/$id$/.mailallowance.  This is
     also held in memory variable $mailreserves$.  After a
     mail item has been processed by one of the actions which
     decrement the mail reserves, the "T" flag is dropped so
     the user will not be charged twice for the same item.
     Normally an item will be processed regardless of size, if
     the mail reserves are anywhere above 0 at the beginning
     of the process.

     No number is allocated from mailreached to an outgoing
     external mail message.

     Due to the often large size of an internet mail message
     and to the fact that the read/unread flag is useless
     here, no copy is kept automatically.  Of course a copy
     may be created by the user mailing himself a copy at the
     same time.


13.2.1.1. Menu actions for adjusting user's mail reserves


13.2.1.1.1.    set_my_reserves

     args: amount + or -
     from: menu only

     Adjusts the current user's mail reserves.  Amount may be
     positive or negative.

     Succeeds if new setting is saved.


13.3.     The mail messages


13.3.1.   Structure of a mail message


     Field 1      The number of the message this was a
                  reply to. "base" if it was not a reply.
     Field 2      "R" or "U" to indicate read or unread.
     Field 3      "#" for internal mail, or local Unix
                  mail, "T" for external mail from other
                  sites, for toll purposes.
     Field 4      The unique number of this mail item.
     Fields 5-10  The date of sending.
     Field 11     "from".
     Field 12     Sender's ID.
     Field 13     "to".
     Field 14     Recipient's ID.
     Field 15     "-"
     Fields 16    A multi-word subject string.
     onwards


13.3.2.   How mail messages are related

     There are no indexes maintained for a private mail
     directory, mail is accessed by the program reading the
     directory and presenting the mail in numerical order as
     per file name.  The only use of the parent/reply link at
     this time is that the "parent" message descriptor may be
     used to view the parent message if it still exists in the
     reader's mail directory.


13.3.3.   Message descriptors

     There are some significant differences between private
     mail descripters and public area message descriptors.
     The relationships between mail messages are fewer, but
     actions on a collection are easier.

     In the table below, the whole word argument is hardcoded,
     and the single letter is dependant on the language file
     (see Section 9.1 "Support for foreign languages"). The
     example as below uses the language file as distributed by
     the authors.

     Valid descriptors are:

     msg no.        one message number or a
                    space-separated list of numbers
     "i" or "in"    all incoming mail messages currently
                    in the user's directory
     "o" or "out"   all copies of outgoing mail messages.
     "w" or "new"   unread mail messages
     "a" or "all"   all mail messages stored in the
                    user's directory.
     "." or         the most recent mail message read,
     "current"      provided it is still in the
                    directory.
     "~" or         the most recent new mail message
     "place"        read.  This is so that the user may
                    follow the thread back and then
                    resume reading new mail from where he
                    got to.
     "u" or         the message to which the current one
     "parent"       is a reply.
     "n" or "next"  the next unread message in numerical
                    order.


13.3.4.   Mail pointers

     Unlike the public message areas, it is not possible to
     miss messages by jumping to a higher message number.
     drealmBBS uses Field 2 in the header to see if a message
     has been read, not an index marker or other variable.

     However some menu actions exist to deliberately mark mail
     as read or unread


13.3.4.1. Menu actions for setting mail pointers


13.3.4.1.1.    unread

     args: mail message descriptor
     from: menu or user input

     Adjusts the headers of the given message/s to flag them
     as unread.

     Message descriptors "new", "next" and "out" are not
     allowed as they would not be helpful.  If "all" is
     selected, only incoming messages are flagged as unread.

     Out-tray copies of outgoing mail are never altered by
     this action, as it would be nonsense to do so.

     Returns TRUE if valid arguments were given.


13.3.4.1.2.    store_mail

     args: none
     from: -

     Saves the lowest unread mail message number at the time
     of storing.  A file in the mail directory called
     mailstore is used for this purpose.

     Always returns TRUE.


13.3.4.1.3.    restore_mail

     args: none
     from: -

     Using value saved in the mailstore file, marks that mail
     message and any higher as unread.  Does not touch copies
     of outgoing mail.

     TRUE if there was any incoming mail.


13.3.5.   Reading messages

     A mail message is read by displaying selected fields from
     the header, followed by the subject line and then the
     body.  Unlike an area message, replies are not listed.
     Whenever a mail message is read, $mailcurrent$ is updated
     to hold the number of the message just read.

     It is friendly for your users if you arrange your mail
     menu so that pressing Enter (*DEFAULT*) executes a
     "read_mail next"


13.3.5.1. Menu actions for reading private mail


13.3.5.1.1.    read_mail

     args: descriptor for single message
     from: menu or user input

     Displays a specified mail message on the screen.  Updates
     $mailcurrent$ with number of mail displayed.

     Adjusts mail reserves if appropriate.

     TRUE if a message is displayed.


13.3.6.   Posting private mail messages

     See Section 9.3.4 "The editing experience" for details of
     composing a mail message.

     If the sender has a .sig file, it will be appended to the
     mail message body.


13.3.6.1. Menu actions for sending mail


13.3.6.1.1.    quote_mail


     args: message descriptor
     from: menu or user input

     Appends the specified mail messages to the user's workpad
     ready for editing. The quoted sample begins "So-and-so
     wrote:" and each quoted line has a ">" at the start of
     it.

     TRUE if valid messages were specified.


13.3.6.1.2.    post_mail

     args: "to" recipient-list
     from: menu or user input

     Write a mail message to a single recipient or a
     space-separated list of recipients. "to" is optional. For
     sending external mail, the full email address of the
     recipient should be typed in.

     User and recipient flags and levels will be checked, and
     external mail allowance adjusted if appropriate.

     Returns TRUE if the message was successfully processed,
     or handed to the system mailer but no attempt is made to
     see whether external mail leaves the system successfully.


13.3.6.1.3.    reply_to_mail


     args: "to" message-descriptor
     from: menu or user input

     Write a mail message in reply to a specified message.
     "to" is optional.  If there is no message specified, the
     current message is assumed.  The recipient of the reply
     is the author of the specified message.

     The same access checks and mail reserves adjustments are
     applied as for post_mail.

     TRUE if the message was successfully processed, as
     post_mail above.


13.3.7.   Grabbing

     The aim in grabbing is to append the result to the user's
     grabpad, in such a way that it may be downloaded and read
     offline, possibly with an offline reading program.


13.3.7.1. Menu actions for grabbing private mail


13.3.7.1.1.    grab_mail

     args: multi-message-descriptor
     from: menu or user input

     Appends the specified mail messages to the user's
     grabpad. A "." message separator symbol will be appended
     on a new line after each message.

     External mail reserves are adjusted where appropriate,
     just as if the message had been read online.

     Returns TRUE if valid messages were specified.


13.3.8.   Copying


13.3.8.1. Menu actions for copying private mail


13.3.8.1.1.    copy_mail

     args: message-descriptor "to" area-name
     from: menu or user input

     Copies a specified message or list of messages to the
     specified message area.  In the message body, the text
     "Copied from private mail by: <user>" appears

     Returns TRUE if the message/s were copied.


13.3.8.1.2.    forward_mail

     args: message-descriptor "to" user-name
     from: menu or user input

     Forwards a single message to the specified user or
     userlist.  As at this release this only works for local
     BBS mail. In the message body, the text "Forwarded by:
     <user>" appears, but the header shows the sender as being
     the original author, so that replying can occur
     intelligently.

     Returns TRUE if the message/s were forwarded.


13.3.9.   Checking for mail

     A user will wish to know when there is new private mail
     in their mailbox.  It is recommended you execute one or
     more of these in each .pmp menu file just before the
     prompt.  They can of course also be menu options for the
     user to select.

     $users$/$id$/.mailalert is used to tell whether new local
     mail has arrived, and this file is deleted as soon as the
     user has been alerted.


13.3.9.1. Menu actions for checking for new mail


13.3.9.1.1.    check_local_mail

     args: none
     from: -

     Checks to see if there is any new internal drealmBBS mail
     for the user.  Uses presence of a .mailalert to tell.

     Displays an alert to the user and clears the flag, so the
     next time mailcheck is called it won't react, unless
     there is new mail.  Clears .mailalert as soon as user has
     been alerted.

     Returns TRUE if there is more new mail.


13.3.9.1.2.    check_unix_mail


     args: none
     from: -

     Checks to see if the unix mailbox for this account has
     been modified since the last time check_unix_mail was
     called.

     TRUE if new mail is found.


13.3.9.1.3.    collect_unix_mail

     args: none
     from: -

     Checks to see if there is anything in the unix mailbox
     for the user, and offers the chance to import it if so.

     Returns TRUE if the user decides to import the mail.


13.3.9.1.4.    list_mail

     args: message descriptor
     from: menu or user input

     Lists the headers of the specified mail messages.

     Returns TRUE if valid messages were specified.


13.3.10.  Deleting

     Deletion can be done as an automatic routine, (see
     Section 13.3.10.2 "Automatic deletion of old mail") or by
     the user himself, for the purpose of being able to keep
     track more easily of current items.  Also a message sent
     in error can be deleted from the recipient before it's
     been read.


13.3.10.1.     Menu actions for deleting mail


13.3.10.1.1.   delete_mail

     args: message-descriptor
     from: menu or user input

     Deletes the specified mail messages.

     "new" and "next" are not allowed, however new mail may be
     deleted by specifying the message number/s.

     If multiple messages are specified, the user is prompted
     for whether he wishes to confirm each deletion.

     When deleting an outgoing item which has not yet been
     read by the recipient, the user gets the choice to delete
     the recipient's copy too.

     TRUE if valid messages were specified and the operation
     was carried through.


13.3.10.2.     Automatic deletion of old mail

     Often users don't bother to keep their mailboxes tidy.
     The utility called mailtidy which is included in the
     drealmBBS package can be run from a scheduler such as
     cron.  Call the program using the config.drealm file as
     the argument, which will tell it all about where users'
     mail directories are.

     mailtidy uses the configuration file config.mtidy, in
     which Field 1 is the age in days of a mail message which
     is eligible for deletion, and Field 2 is a
     space-separated list of users whose mail should not be
     touched by the tidying routines.


14.  Offline reading

     To keep telephone charges or connect time down, many
     users prefer to download all their messages and read
     them, and prepare their replies on their local computer.

     We have not written an offline reader, although one
     exists which will read drealmBBS messages.  However, we
     have provided an interface which will support offline
     reading by providing a consistent file which can be used
     as input to such, and guidance as to how to compose
     replies.  The file grabpad, kept in the user's private
     file directory, is in plain ASCII text and can be read
     meaningfully by a human.

     The material for the return upload should be in a file
     called putfile.  Again this is a plain ASCII text file
     and can be easily composed by a human being.


14.1.     Structure of grabpad

     Each item is separated by a "." on a line by itself.
     Items may be (so far) area messages, private mail
     messages, and users' planfiles.

     In the following format descriptions you may notice that
     not all fields have been listed.  That is because the
     listed fields are intended to stay the same whatever else
     happens, whereas the others may change in future
     releases.  The fields described below may be used if
     writing an OLR program, in faith that it will not become
     useless when a future version of drealmBBS is released.

     If writing an OLR you should count newlines or
     whitespace-separated fields within the header, rather
     than performing string-slicing and pattern matching on
     the header as one string.


14.1.1.   A grabbed area message:

     Line 1    "Area: <area name>"

     Line 2    Field 1   Message number within area
               Field 2-6 Date of posting
               Field 8   Author
               Field 10  Message number it was a reply to
               Field 12  User it was a reply to (if field 10
               was numeric)
               Field 14  Number of the base message

     Line 3    Replies list
               Depending on your own OLR program, the replies
               list will probably become out of date after
               downloading.

     Line 4    "Subject: <subject string of random number of
               words>"

     Line 5 on until the message separator - message body


     Example:
     Area: chatter
     713 Thu Feb 17 20:05 1995 by inge reply-to 712 by mac
     base 709
     Replies: 714 716
     Subject: What a silly BBS

     I don't think much of this silly BBS!
     .



14.1.2.   A grabbed private mail message:

     Line 1    "Mail: "

     Line 2    Field 1   Unique message number within host
               system, except for  error messages which all
               get a number 0.
               Field 2-6 Date of posting
               Field 8   Author
               Field 10  Message number it was a reply to (if
               numeric)
               Field 12  Recipient

     Line 3    "Subject: <subject string>"

     Line 4 on until message separator - message text

     Example:

     Mail:
     2467 Sun Feb 13 19:53 1994 by android reply-to 1026 by
     inge
     Subject:  Hi again

     I have just called this BBS to give it one more try but
     it is still rubbish!
     .


14.2.     Structure of putfile

     This file is a compendium of messages for posting.

     There are five types of items, private mail post, private
     mail reply, area message post, area message reply, and
     area message comment.  All headers are made up of one
     single line, and each message is terminated by a single
     "." on a line by itself


14.2.1.    private mail post

     Field 1   The word "mail"
     Field 2   "post"
     Field 3   recipient
     Field 4   multi-word field holding subject string

     Further lines until the separator are the message body.

     example:
     mail post inge Problems with editing
     Hi Inge, I am having a few problems with the line editor
     here,
     I wonder if you can rewrite the wretched thing please!
     .


     You may also post same letter to more than one recipient
     by listing the names separated by commas - but NO spaces
     in this case.

     example:
     mail post inge,thanatos,admin For all of you
     I want you all to know I am starting my OWN bbs...
     .


14.2.2.   private mail reply to a mail you have received

     Field 1   "mail"
     Field 2   "reply"
     Field 3   message number to reply to.

     The original mail must be still in your mail tray online
     or the reply will not work.

     example:
     mail reply 1255
     Thanks for your mail inge, but I STILL think your editor
     is rubbish.
     In fact I am never going to use it to write a message
     ever again!
     .


14.2.3.    area message to everyone

     Field 1   "area"
     Field 2   areaname
     Field 3   "post"
     Field 4+  subject string

     example:
     area chatter post This system stinks
     I don't know what the rest of you think, but I think that
     this system is utter rubbish.  I would like to see it
     closed down.
     Please would everyone call my BBS instead!
     .


14.2.4.   area msg as reply or comment to one you have read

     Field 1   "area"
     Field 2   "reply" OR "comment"
     Field 3   number of message being replied to
     Field 4+  subject string

     The subject string is optional.  If none is given it will
     use the existing subject of the thread.

     example:
     area windows reply 10
     No I don't agree. You might think that software you
     mentioned is useful, but I don't!!!  Why don't you try
     the utility I have written?  It is configurablebetween
     blowing up your motherboard RAM or your printer port.
     .


14.2.5.   Menu actions for offline reading


14.2.5.1. olr

     args: none
     from: -

     Requests a putfile for upload.  Runs through putfile and
     executes the posting commands.  Collects all unread
     private mail and area messages into grabpad.  Offers the
     grabpad for download.

     The process begins by looking to see if there is a
     putfile in user's directory.

     If it finds one it asks whether to use that or upload a
     new one - or whether user simply doesn't have any
     messages of his own to post.

     If it can't find a putfile, user is asked if he would
     like to upload one.

     If there ends up being a putfile, the program goes around
     posting user's messages. If there are any it can't deal
     with, it posts a copy into user's grabpad with the error
     message it generated so he can decide what to do about
     them later when he reads his grabpad.

     Then user is asked if he wants to grab new messages now -
     and if he has a $recent$ setting, it asks if he wants
     that to be obeyed in his grab.  See help on setting user
     defaults for an explanation of recent.

     User is next offered chance to store current message
     pointers

     The process will then grab all user's public messages and
     private mail. The area names will list as they are
     scanned one by one.

     Then user will be asked if he wants to download now.  If
     he says no, the grabbed messages will remain in the
     grabpad file.

     Returns TRUE if messages are put or grabbed.


15.  File activities


15.1.     Directories

     Most file handling actions are carried out in the context
     of the currently set directory, held as the $dir$
     variable.

     The directory set in a start_dir action will always be
     held in $topdir$, and any subdirectories nested into will
     be held in $taildir$.  $topdir$/$taildir$ should give the
     same result as $dir$

     If during operation of the program, the current path in
     $dir$ is within the size limit but by changing to it the
     whole path would exceed 255, the change of directory will
     be refused rather than truncated, to preserve security.


15.1.1.   Menu actions for changing directory


15.1.1.1. start_dir

     args: path
     from: menu only

     Clears down the previous directory information and sets
     the current directory, held in $dir$, to the value given.

     TRUE if a valid directory is given, which must be one the
     user can access.


15.1.1.2. clear_dir

     args: none
     from: -

     Clears out all directory information.  Empties $dir$

     Always returns TRUE.


15.1.1.3. nest_dir

     args: name of subdirectory
     from: menu or user input

     Tacks on the directory name given to the current
     directory. The directory must exist and not make the
     entire path too long.  $dir$ and $taildir$ are updated,
     see above.

     Returns TRUE if an accessible subdirectory is given.


15.1.1.4. parent_dir

     args: none
     from: -

     Drops the last element of the current directory path.
     Will not go back past the name set with start_dir, ie
     $topdir$ is as high in the directory structure as the
     user may go using this action.

     TRUE if the parent directory was accessible, and was
     allowed under the terms of this action.


15.1.1.5. create_dir

     args: parent directory then subdirectory
     from: the parent directory must be specified in the menu,
           but the new subdirectory may be named either from
           the menu or by the user.

     Creates a directory.

     Returns TRUE if the directory was created.


15.1.1.6. remove_dir

     args: parent directory then subdirectory to be removed
     from: the parent directory must be specified in the menu
           only, but the subdirectory may be named either from
           the menu or by the user.

     Removes the named subdirectory and all its
     subsubdirectories. The directory to be removed must
     contain no files (although any deeper subdirectories may
     contain files).  User is asked to confirm.

     Returns TRUE if the directory was removed.


15.2.     File uploads and downloads

     During all file uploads or downloads, the user is set
     back to their login group, for security in case the
     transfer program allows shell commands.  Because of this,
     files are normally transferred via a temporary file under
     their home directory, which is certain to allow access to
     the user at all times.  In two of the menu actions for
     download, ending in _ub (for UnBuffered) the download is
     direct from the source.  This can be quicker, for example
     over a network, but potential drawbacks are you have to
     make sure the users have native access to all download
     sources, which may not fit in with your security needs.
     Any file placed in a public area by a drealmBBS action
     will take on the permissions specified by C.filemode in
     config.drealm so if you are allowing unbuffered file
     downloads set this to something like 0664.

     drealmBBS does not have any internal file transfer
     facilities, but will interface with any you make
     available and set up for it to use in config.files .


15.2.1.   Setting up config.files

     This is a standard configuration file with alternate
     comment and data fields, separated by :: field
     separators.

     Each protocol has 5 data fields associated with it, and
     there is room for up to 8 file transfer protocols.

     Within each group for a protocol:

     Field 1     A name to refer to it as in the options
                 which are offered to your users.  A
                 familiar word like "Xmodem" is
                 recommended.
     Field 2     The command your system will recognise as
                 the call for a download from it, using
                 this protocol, eg "sx"
     Field 3     The command recognised by your system as
                 a call to receive a file using this
                 protocol, eg "rx"
     Field 4     Some appropriate text to tell your user
                 how to abort a transfer in this protocol,
                 eg "Ctrl-X to abort"
     Field 5     "1" if batch transfers are available, "0"
                 if not"

     These fields are repeated for each protocol.


15.2.2.   Menu actions for file transfers

     Each time a user initiates an upload or download they are
     prompted to select a protocol.


15.2.2.1. download

     args: file-list
     from: menu or user input

     Sends the named files, which must be chosen from from the
     currently selected directory.  This will not work unless
     $dir$ has been set by a start_dir at any time before
     download is attempted.

     Returns TRUE if valid files were selected.


15.2.2.2. download_ub

     args: file-list
     from: menu or user input

     As download, but does not copy file to home directory
     first.  See general explanation in 15.2 above

     Returns TRUE if valid files were selected.


15.2.2.3. download_special

     args: file-list
     from: menu only

     This one is useful for a menu option which specifically
     downloads, say, a user manual or other particular file.

     Transmits the files, which must each be specified by full
     path.

     Returns TRUE if valid files were passed.


15.2.2.4. download_special_ub

     args: file-list
     from: menu only

     As download_special, but does not copy files to home
     directory first.  See general explanation in 15.2 above

     Transmits the files, which must each be specified by full
     path.

     Returns TRUE if valid files were passed.


15.2.2.5. upload

     args: filename (for non-batch protocols)
     from: menu or user input

     Receives files into the currently selected directory.
     $dir$ must have been set by a start_dir at some time
     prior to this action.

     If the upload is to the user's private directory, it will
     compare the user with $pvtfileslevel$ and $pvtfilesmask$.

     Unless the upload is into the user's private files
     directory, file descriptions are requested for each file
     received.

     Returns TRUE if user is allowed to upload.


15.3.     File storage and descriptions

     Whenever a file is transferred or uploaded to a directory
     other than a private file directory, that directory is
     treated as a public downloads area, and a description is
     prompted for, for each file which is uploaded or
     transferred there. There is a subdirectory under each
     public file area, called filedescs and under that is a
     file for each available description, bearing a name
     matching the file it is a description of.


15.3.1.   Menu actions for handling files


15.3.1.1. file_to_public

     args: See below as this is a complicated one
     from: See below

     The arguments are passed in a different order depending
     on whether they are on the menu line or from the user.

     Copies a list of one or more files to a particular
     directory. The menu line must specify, as the first
     parameter, the parent directory containing eligible
     public subdirectories.

     If there is a second parameter in the menu, this is taken
     as the destination directory.

     If there are any further parameters in the menu, these
     are taken to be the names of the files which are to be
     sent.  Files are looked for in the directory held in
     $dir$

     If no filenames were given on the menu line, they will be
     taken from the user.  If no destination directory was
     passed, that will next be taken from the user.

     If the user wants to give the whole command on the
     command line, he should type in the arguments as <file
     list> "to" <directory>.

     Note: you can use this action to get round the checking
     that `file_to_user' does, when sending a private file to
     a user, by setting the parent directory to
     $privatefiles$.

     Returns TRUE if the files are copied.


15.3.1.2. describe_file

     args: filename
     from: menu or user input

     Edit the description of the selected file in the
     currently selected directory ($dir$).

     Returns TRUE if the description is saved.


15.3.1.3. catalogue

     args: none
     from: -

     Displays the file descriptions for files in the currently
     selected directory ($dir$).

     Returns TRUE if there are files, regardless of their
     descriptions.


15.3.1.4. list_dir

     args: list-type (optional)
     from: menu or user input

     Lists the contents of the currently selected directory
     ($dir$).

     Parameter options are "l" for a Unix long-style listing,
     "c" for a list split into columns, "x" for a list
     displayed from side to side.  The default, if no
     parameter is passed is to list in one long column with no
     file details.

     Returns TRUE if there are any files and a list is
     displayed.


15.3.1.5. search_filenames

     args: top directory then pattern string
     from: menu for top dir, and either for pattern

     Pattern should be in "" if it is to include any spaces.
     Like normal text searching, the string passed may appear
     anywhere in the filename and there is no need for the
     user to pad out with '*'s

     Searches recursively through all the filenames below the
     given parent directory for strings matching the given
     pattern.  Misses out the filedescs directories.

     Returns TRUE if the operation is completed without the
     user interrupting.


15.3.1.6. search_filedescs

     args: top directory then pattern string
     from: menu for top dir, either for pattern

     Searches through all the descriptions in filedescs
     directories below the given top directory for strings
     matching the given pattern.

     Returns TRUE if the operation is completed without the
     user interrupting.


15.3.1.7. delete_file

     args: file or list
     from: menu or user input

     Remove the named file or files from the currently
     selected directory.  If there are descriptions, they are
     removed, too. User is asked to confirm.

     TRUE if any files were removed.


15.3.1.8. rename_file

     args: filename "to" filename ("to" is optional)
     from: menu or user input

     Renames the file in the currently selected directory.  If
     there is a description, that is renamed, too.

     TRUE if the file is renamed.


15.4.     The user's private file utilities

     Each user needs a directory to contain files he produces
     from such activities as grabbing for offline reading, and
     receiving files from other users.  This directory is
     specified in config.drealm as the $privatefiles$
     directory.  The user's private directory will thus be
     $privatefiles$/$id$.

     Working files, such as workpad and view, which are used
     by external editors, viewers, and transfer protocols are
     always kept in the home directory, as the user loses
     group "bbs" status for security reasons while using such
     programs.

     On a normal amateur BBS it is usually convenient to make
     this the same as the Unix home directory, (ie
     $privatefiles$ = $homedirs$) giving the user flexible
     access to all his working files at once.  However, in a
     business or institutional environment this may not be
     such a good idea as users may have material in their home
     directories which is security sensitive and should not be
     accessible to group "bbs".

     With the possible division of work/leisure use of a
     system running drealmBBS in mind, when the home and
     private files directories are separate, internal
     drealmBBS actions which use the .plan or .sig files will
     look to the ones in the $privatefiles$, where they are
     not the same, leaving the ones in the home directory
     alone.

     Where $privatefiles$ == $homedirs$, it is important to
     ensure that group "bbs" has rx access to the individual
     users' home directories if you want users to be able to
     read each others' .plan files, and rwx access to the home
     directories if you want users to be able to post each
     other files.  However, do not take away any access
     permissions already available to the home directories, or
     people will find themselves unable to log in, under the
     rules of the operating system!

     Where $privatefiles$ is not the same as $homedirs$, the
     private files directories may be owned by the "sysop" and
     by group "bbs" only.

     $pvtfileslevel$ as set in config.drealm represents the
     minimum level at which a user can have a file posted to
     him personally by another user, or that he is offered the
     chance of using a file from his directory instead of
     editing a message, and $pvtfilesmask$ is compared with
     his flags at the same time.


15.4.1.   Automatic deletion of old private files

     Often users don't bother to keep their directories tidy.
     The utility called filetidy which is included in the
     drealmBBS package can be run from a scheduler such as
     cron.  Call it using the current config.drealm as the
     argument, which will tell it where to find all the
     directories it needs.

     Filetidy uses the configuration file config.ftidy, in
     which Field 1 is the age in days of a file which is
     eligible for deletion, and Field 2 is a space-separated
     list of users whose files should not be touched by the
     tidying routines.

     No files beginning with "." are touched. That is so that
     planfiles are not destroyed, and in any case users cannot
     deliberately create .files (files beginning with a dot)


15.4.2.   Menu actions concerning private file activities


15.4.2.1. push_pfu

     args: none
     from: -

     Saves the current directory value ($dir$) and replaces it
     temporarily with the user's private files directory
     ($privatefiles$/$id$ ).

     Returns TRUE if the private files directory becomes $dir$
     successfully.


15.4.2.2. pop_pfu

     args: none
     from: -

     Restores the values saved by push_pfu.

     Always TRUE.


15.4.2.3. file_to_user

     args: See below as this is a complicated one
     from: See below

     Copies a list of one or more files to a particular user's
     private files directory. This action works within the
     context of $dir$.

     The arguments are passed in a different order depending
     on whether they are on the menu line or from the user.

     If there were any parameters on the menu line, the first
     one is taken as the intended recipient, and any further
     arguments are taken as the file names.  The files must be
     without paths, and found in $dir$.

     If no filenames were given on the menu line, they will be
     taken from the user.  If no recipient was passed, that
     will next be taken from the user.

     If the user wants to give the whole command on the
     command line, he should type in the arguments as <file
     list> "to" <user name>.

     Returns TRUE if the files are copied.


16.  Running external programs (doors)

     The basic difference between the two options here, is in
     the permissions the user has while executing them.  In
     the shell action, the user is stripped of any extra
     access he has as a concommittant of using drealmBBS and
     reverts to the permissions and group he has as per passwd
     and groups files at login. In the system action, the user
     keeps his group "bbs" identity and therefore can access
     any files which belong to the BBS even if they are
     inaccessible to outsiders.

     We envisaged the "system" action would be used for the
     SysOp to make something happen by specifying the whole
     task on the menu line, and then return to the menu,
     whereas "shell" would be used where some users have shell
     access granted, and they could specify their own
     parameters (system commands) within their input at the
     time of execution.  In fact "system" will only take its
     arguments from the menu.


16.1.1.   Menu actions for running system commands


16.1.1.1. shell

     args: shell command to be run
     from: menu or user input

     Allows the user to execute a shell command with only his
     normal login permissions effective.

     Returns TRUE depending on whether last system call
     reports success.


16.1.1.2. system

     args: shell command
     from: menu only

     Executes the shell command, with all permissions of the
     bbs group plus the user's normal permissions.  For
     safety, will only take arguments from menu.

     Returns TRUE if the system call returns TRUE


17.  Index to menu actions


     Name of action          Refer to section

     add_area                12.2.2.1.3
     add_chairmen            12.1.4.7
     add_gagged              12.1.4.13
     add_members             12.1.4.10
     append                  8.5.1.1.6
     area_status             12.1.4.4
     areaflags               12.1.2.2.1
     broadcast               11.1.2.12
     catalogue               15.3.1.3
     change_area             12.2.1.1.1
     chat_log_off            9.6.1.1.4
     chat_log_on             9.6.1.1.3
     chat_off                11.1.2.4
     chat_on                 11.1.2.3
     check_expiry            10.4.5.1.1
     check_interval          10.4.6.1.1
     check_local_mail        13.3.9.1.1
     check_notice            10.7.1.1.2
     check_unix_mail         13.3.9.1.2
     clear_dir               15.1.1.2
     collect_unix_mail       13.3.9.1.3
     comment_to_msg          12.3.5.1.4
     continue                9.2.1.1.6
     copy_mail               13.3.8.1.1
     copy_msg                12.3.8.1.1
     create_area             12.1.1.1
     create_dir              15.1.1.5
     create_vote             12.3.9.1.1
     delete_file             15.3.1.7
     delete_mail             13.3.10.1.1
     delete_msg              12.3.6.1.1
     describe_area           12.1.4.3
     describe_file           15.3.1.2
     destroy_account         10.4.9.1.2
     destroy_area            12.1.1.2
     disable_chat            11.1.2.2
     display                 9.4.3.1.2
     display_lang            9.4.3.1.3
     display_menu            8.5.1.1.1
     download                15.2.2.1
     download_special        15.2.2.3
     download_special_ub     15.2.2.4
     download_ub             15.2.2.2
     drop_area               12.2.2.1.4
     edit                    9.3.4.1.1
     edit_choice             9.3.4.1.2
     edit_info               12.1.4.1
     edit_plan               11.2.1.2
     edit_scanlist           12.2.2.1.2
     edit_sig                12.3.5.2.1.1
     emote                   11.1.2.10
     enable_chat             11.1.2.1
     file_to_public          15.3.1.1
     file_to_user            15.4.2.3
     finger                  11.2.1.3
     flag_msg                12.3.5.3.1
     flush_comline           9.2.1.1.10
     force_update            10.6.2.3.4
     force_user              10.7.1.1.3
     fx                      11.1.2.11
     get                     9.2.1.1.2
     give_address            10.6.1.1.1
     give_aka                11.2.1.6
     give_dob                10.6.1.1.2
     give_phone              10.6.1.1.4
     give_real_name          10.6.1.1.3
     grab_finger             11.2.1.4
     grab_mail               13.3.7.1.1
     grab_msg                12.3.7.1.1
     input_log_off           9.6.1.1.2
     input_log_on            9.6.1.1.1
     jump                    12.3.3.1.1
     link_msg                12.3.2.3.1
     list_areas              12.2.1.1.2
     list_dir                15.3.1.4
     list_headers            12.3.4.1.1.3
     list_mail               13.3.9.1.4
     list_users              11.2.1.1
     log                     9.6.1.1.5
     log_off                 10.3.1.1.1
     log_to_file             9.6.1.1.6
     maintain_me             10.6.2.3.1
     maintain_user           10.6.2.3.2
     make_my_account         10.5.1.1.1
     make_user_account       10.5.1.1.2
     maskflags               12.1.3.2.1
     moderate                12.1.4.6
     nest_dir                15.1.1.3
     news                    12.4.1.1.1
     no_yes                  9.2.1.1.9
     notify_user             10.7.1.1.1
     olr                     14.2.5.1
     parent_dir              15.1.1.4
     participants            12.1.4.5
     plan_search             11.2.1.5
     pop_level               8.5.1.1.4
     pop_pfu                 15.4.2.2
     post_mail               13.3.6.1.2
     post_msg                12.3.5.1.2
     press_enter             9.2.1.1.5
     print                   9.5.1.1.1
     prompt                  9.2.1.1.1
     push_level              8.5.1.1.3
     push_pfu                15.4.2.1
     quote_mail              13.3.6.1.1
     quote_msg               12.3.5.1.1
     random                  8.4.2.2
     read_mail               13.3.5.1.1
     read_msg                12.3.4.1.1.1
     rem_chairmen            12.1.4.8
     rem_gagged              12.1.4.14
     rem_members             12.1.4.11
     remove_dir              15.1.1.6
     rename_file             15.3.1.8
     reply_to_mail           13.3.6.1.3
     reply_to_msg            12.3.5.1.3
     reset_guest             10.6.2.3.7
     reset_my_defaults       10.6.2.3.5
     reset_my_flags          10.4.4.1.2
     reset_user_defaults     10.6.2.3.6
     reset_user_flags        10.4.4.1.4
     restore                 12.3.3.1.4
     restore_mail            13.3.4.1.3
     resume_timer            10.4.7.2.5
     say                     11.1.2.8
     scan_areas              12.2.2.1.1
     search_filedescs        15.3.1.6
     search_filenames        15.3.1.5
     set_areaflag            12.1.2.2.2
     set_arealevel           12.1.3.3.1.1
     set_chat                11.1.2.5
     set_columns             10.6.2.1.7
     set_customvar           8.4.2.1
     set_display             9.4.2.1.1
     set_doing               11.1.1.4
     set_echo                9.2.1.1.4
     set_editor              9.3.3.1.1
     set_erase               10.6.2.1.2
     set_hotkeys             10.6.2.2.1
     set_in_colour           11.1.2.6
     set_kill                10.6.2.1.4
     set_language            9.1.1.1.1
     set_maskflag            12.1.3.2.2
     set_my_expiry           10.4.5.1.2
     set_my_flag             10.4.4.1.1
     set_my_level            10.4.3.1.1
     set_my_reserves         13.2.1.1.1
     set_my_title            11.1.1.2
     set_out_colour          11.1.2.7
     set_password            10.4.2.1.1
     set_pausetime           10.6.2.2.2
     set_readmode            12.3.4.2.4.1
     set_readown             12.3.4.2.4.2
     set_recent              12.3.3.1.5
     set_reprint             10.6.2.1.5
     set_rows                10.6.2.1.6
     set_terminal            10.6.2.1.1
     set_timeout             10.6.2.2.3
     set_user_flag           10.4.4.1.3
     set_user_level          10.4.3.1.2
     set_user_title          11.1.1.3
     set_werase              10.6.2.1.3
     shell                   16.1.1.1
     show_chairmen           12.1.4.9
     show_gagged             12.1.4.15
     show_info               12.1.4.2
     show_members            12.1.4.12
     skip                    12.3.3.1.2
     start_dir               15.1.1.1
     start_daytimer          10.4.7.2.1
     start_level             8.5.1.1.2
     start_timer             10.4.7.2.2
     stop_timer              10.4.7.2.3
     store                   12.3.3.1.3
     store_mail              13.3.4.1.2
     sure                    9.2.1.1.7
     suspend_timer           10.4.7.2.4
     swap_level              8.5.1.1.5
     system                  16.1.1.2
     take                    9.2.1.1.3
     text_search             12.3.4.1.1.2
     unlink_msg              12.3.2.3.2
     unread                  13.3.4.1.1
     update_me               10.6.2.3.3
     upload                  15.2.2.5
     view_choice             9.4.3.1.1
     vote                    12.3.9.1.2
     whisper                 11.1.2.9
     who_is                  11.2.1.7
     whos_on                 11.1.1.1
     yes_no                  9.2.1.1.8
     zap_user                10.4.9.1.1
