Inside RiBBS
                   A Comprehensive Description of RiBBS Formats
                      Last update : 07/05/93 - RiBBS v2.10

  This file was created for those who wish to write programs to compliment
RiBBS, but require more information about the formats of various files that
are read/created by the BBS and some of the variables being passed to its
modules.

   It should be noted that the formats listed herein are subject to
change without notice, which may affect the workings of programs written
to follow them.


  Conventions
 -===========-

  Throughout this file, the following abbreviations will be used:

       (S) - String Data
       (Sx)- String Data, "x"=number of bytes
       (F) - Boolean Flag
       (B) - Byte Data
       (I) - Integer Data
       (R) - Real Number Data

  Note that (F) (Boolean Flag) data consumes a full byte of information
eventhough only one bit within that byte is used to determine the TRUE/FALSE
status of that flag.

  File and record offsets are expressed as a Hexadecimal number (prefixed by
a "$" character) and then its Decimal equivalent, separated by a slash.  For
example, if a field starts at the tenth byte in a file (or record) its offset
would be represented as:

   $0A/10


  Userlog Format
 -==============-

   - UserIndex -

  First, the "UserIndex" file.  This file's format is probably the simplest
one of the system.  It's purpose is to allow RiBBS to find a user's name
with as little file reading as possible (thus making it relatively fast.)
The format is as follows:

            ----------------------------
 Record 1 - | User name          (S32) |
            +--------------------------+
 Record 2 - | User name          (S32) |
            +--------------------------+
   etc.....

  This file gets recreated by UserEdit each time that you delete an entry
or change a user's name.  It is also appended to when a new user logs on.
The names here are in exactly the same order that they appear in the UserLog
file.  Thus, if you read UserIndex records and keep track of how many have
been read by the time you find the name you are looking for, you can calculate
the point in UserLog that that user's profile starts.


   - UserLog -

  The UserLog format contains a great deal more information on each user.
It too is appended when a new user logs on and is rewritten from scratch
when using the <P>urge option of UserEdit.  Each record is 197 bytes long,
and they are not in any particular order unless you've sorted them that way
with a program such as USort.  The one exception to this is the Sysop's
record, which is always the first one.  Each record looks like:

 Offset:
------------        --------------------------===>>
         ________________________          ________________________
 $00/0   | Name           (S32) |  $20/32  | City           (S20) |
         |----------------------+          |----------------------|
 $34/52  | State           (S2) |  $36/54  | Password        (S8) |
         |----------------------+          |----------------------|
 $3E/62  | Date Last On    (S8) |  $46/70  | Access Flags     (B) | -Note #1
         |----------------------+          |----------------------|
 $47/71  | Export Toggle    (B) |  $48/72  | Uppercase Toggle (B) | -Note #2
         |----------------------+          |----------------------|
 $49/73  | Clear Screen     (B) |  $4A/74  | # Uploads        (B) |
         |----------------------+          |----------------------|
 $4B/75  | # Downloads      (B) |  $4C/76  | Time Limit       (B) |
         |----------------------+          |----------------------|
 $4D/77  | Download Limit   (B) |  $4E/78  | Page Length      (B) |
         |----------------------+          |----------------------|
 $4F/79  | Time Used Today  (I) |  $51/81  | Times Called     (I) |
         |----------------------+          |----------------------|
 $53/83  | Access Level     (I) |  $55/85  | Kbytes Uploaded  (I) |
         |----------------------+          |----------------------|
 $57/87  | Kbytes Down.     (I) |  $59/89  | Msgs Posted      (I) |
         |----------------------+          +----------------------|
 $5B/91  | Download Points  (I) |
         |----------------------+---------------------------------+
 $5D/93  | Last Read Pointers              (array of 50 Integers) | -Note #3
         |----------------------+---------------------------------|
 $C1/193 | Active/Deleted   (F) |  $C2/194 | Page Pausing     (F) |
         |----------------------+          |----------------------|
 $C3/195 | UD ?             (F) |  $C4/196 | Term Type        (B) | -Note #4
         +----------------------+          +----------------------+ -Note #5

  A typical Basic09 TYPE statement to handle this might look like:

TYPE uentry=name:STRING[32]; city:STRING[20]; state:STRING[2]; password,
     day:STRING[8]; flg,exp,ucase,clr,upl,dwl,timel,dlim,PAGL:BYTE; ttoday,
     called,lv,kup,kdw,msgs,dlpoint,lastread(50):INTEGER; del,pau,ud:BOOLEAN;
     ansi;BYTE

       (Though you may need to shorten those names to make it fit.)

  Note #1 - Access Flags.  This consists of one byte; each of the eight
            bits corresponds to one flag.
                _________________________________
        Flag #- | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
                ---------------------------------

  Note #2 - Expert, Uppercase, and Clear Screen toggles are bytes that
            equal zero if that function is off, and one if the function
            is on.

  Note #3 - Last Read Pointers.  Only the first 40 of these are used for
            last read pointers, the next six bytes after the initial 40
            are the Board Select flags, and the last four bytes are not
            currently used.

            These pointers start at record offset $AD (173) and are composed
            of six bytes.  The bits in each byte each correspond to a certain
            message base (a "1" value meaning that base is selected.)

                            Board Select Pointer Format
                       (read by UserEdit as three Integers)
                       ------------------------------------
 Record Offset:
  $AD/173    0  0  0  0  0  0  0  0   --->   0  0  0  0  0  0  0  1 - values
                    (unused)                36 31 26 21 16 11  6  1 - Base #

  $AF/175    0  0  1  0  0  0  0  1   --->   0  0  0  0  0  0  0  0 - values
            37 32 27 22 17 12  7  2         38 33 28 23 18 13  8  3 - Base #

  $B1/177    0  0  0  0  0  0  0  1   --->   0  0  0  1  0  0  0  0 - values
            39 34 29 24 19 14  9  4         40 35 30 25 20 15 10  5 - Base #

            In the above example, boards 1, 2, 4, 25, and 27 are selected.

            One other note about this field.  The last integer (element #50)
            has been adopted by Craig Cross as a pointer to a record in a
            data file that is supported in his UEdit package.

  Note #4 - "ud"; there is no indication in RiBBS source code as to what
            this field is for.  Maybe it means "undefined".  Even Ron doesn't
            remember anything about this field.

  Note #5 - The terminal types are: 0-TTY, 1-ANSI, 2-OS-9.


  Message Base Files
 -==================-

  There are three files that makes up the RiBBS 2.02 message base.  "TEXT",
"IDX", and "HDR".


   - "TEXT" -

  This file is the typically the largest and is the simplest in structure of
the three message base files.  It is merely text data - there is no defined
record length.  Any attempt to make a diagram of the TEXT file here would
simply confuse the reader, so I'll skip it.  When file is first created it is
empty (or simply filled with random garbage) and is as large as you ahave
specified CreateMsg or PackMsg ("-s" option) to make it.  When messages are
posted or imported with MailImport, the "Currently Used Bytes" variable in
HDR is accessed to find out how much of the TEXT file is full of active
messages, then the program seeks that position (plus one byte) in TEXT and
starts adding the new message (each line terminated by a conventional
carriage return ($0D) character.


   - "HDR" -

  This file is unique in that it is both a variable length record file
and a fixed length record file.  Surely BASIC09 is one of the few languanges
in existence that will allow this kind of flexibility in a file.  I'll
describe this file in two sections.

  Section #1 occupies the first 399 bytes of HDR and is the variable length
record portion of the file... to put it more bluntly, it is a hodgepodge of
variables and arrays which contains plenty of room for expansion.  The format
is as follows:

  Offset         = HDR file - Section #1 =
 --------     _______________________________
  $00/0    - |       2 bytes - unused        |
             |-------------------------------|
  $02/2    - | Lowest Message Number     (I) |
             |-------------------------------|
  $04/4    - | Highest Message Number    (I) |
             |-------------------------------|
  $06/6    - | Number of Message Headers (I) |
             |-------------------------------|
  $08/8    - | # of bytes used in TEXT   (R) |
             |-------------------------------|
  $0D/13   - | Maximum size of TEXT file (R) |
             |-------------------------------|
  $12/18   - |       2 bytes - unused        |
             |-------------------------------|
  $14/20   - | Record # of first message for |
             ~ each of the 40 message bases. ~
             | Array of 40 INTEGERS/80 Bytes |
             |-------------------------------|
  $64/100  - |       20 bytes - unused       |
             |-------------------------------|
  $78/120  - | Record # of last message for  |
             ~ each of the 40 message bases. ~
             | Array of 40 INTEGERS/80 Bytes |
             |-------------------------------|
  $C8/200  - |      200 bytes - unused       |
             |_______________________________|
                   - End of Section #1 -
              _______________________________
  $190/400 - |                               |
             |      Start of Section #2      |
            \|/                             \|/

  Section #2 consists of the actual message headers, each of which contains
information such as where each message starts (in the TEXT file), how long
it is, who sent it, etc...  Each record is 150 bytes long and there may be
a maximum of 32,767 records (making the absolute maximum acceptible size of
the HDR file 4,751,615 bytes long.)

  If you plan to manipulate the HDR file's records, be SURE to add 400 when
SEEKing to a given record number since Record #1 starts at HDR file offset
of $190 (400 decimal).  Here is the format for each record:

Record Offset          Message Header Format
-------------   _________________________________
  $00/0      - | Board number (1-40)         (B) |
               |---------------------------------|
* $01/1      - | Number of Lines (0-32767)   (I) |
               |---------------------------------|
  $03/3      - | Message # (1-32767)         (I) |
               |---------------------------------|
* $05/5      - | Zone                        (I) | <-|
               |---------------------------------|   |
  $07/7      - | Net                         (I) |   |
               |---------------------------------|   |- Note #1
  $09/9      - | Node                        (I) |   |
               |---------------------------------|   |
* $0B/11     - | Point                       (I) | <-|
               |---------------------------------|
  $0D/13     - | Previous Reply Msg #        (I) | <-|
               |---------------------------------|   |
  $0F/15     - | Next Reply Msg #            (I) |   |
               |---------------------------------|   |- Note #2
  $11/17     - | Record # of previous Msg    (I) |   |
               |---------------------------------|   |
  $13/19     - | Record # of next Msg        (I) | <-|
               |---------------------------------|
  $15/21     - | Position in TEXT file where     |
               | this message begins.        (R) |
               |---------------------------------|
  $1a/26     - | Message Status Flags       (F8) | <--- Note #3
               |---------------------------------|
  $22/34     - | Person Message is "To"    (S32) |
               |---------------------------------|
  $42/66     - | Person Message is "From"  (S32) |
               |---------------------------------|
  $62/98     - | "Subject" of Message      (S32) |
               |---------------------------------|
  $82/130    - | Date/Time message created (S20) | <--- Note #4
               |_________________________________|

 ( * ) - Changed from v2.02 to v2.10

  A typical Basic09 TYPE statement might look like:

 TYPE hdrformat=board:BYTE; lines,msgnum,zone,net,node,point,prep,nrep,pmsg,
      nmsg:INTEGER; startposs:REAL; flg(8):BOOLEAN; to,from,subj:STRING[32];
      date:STRING[20]


  Note #1 - The "Zone"/"Net"/"Node"/"Point" fields contain a Fido style 4-ply
            address. If the message is Netmail posted on your system, the
            numbers in these fields correspond the the address you are
            sending the message to.  So if you were sending a message to
            Fido Address 1:202/610, the Zone field would contain 1, the Net
            field would contain the value of 202, Node would contain 610,
            and Point would hold 0.

            If the message is a local or echo message posted on your
            system, then the values in net/node are ignored by RiBBS.

            If the message was imported by Mailimport, these fields contain
            the address of the system which physically sent your system the
            message (either your echo feed hub or, in the case of direct
            Netmail, the system the mail was posted on.)  The exception to
            this is "Routed Netmail", where a net message was sent to your
            system via the echomail backbone.  If this happens, then these
            fields should contain the address of the system the message was
            posted on, eventhough it was your echo hub which physically sent
            the message to your system.  Using this information, RiBBS v2.10
            and later can successfully allow you to respond to routed netmail
            and (using Wes Gale's latest Bundle program) you can even have
            the reply host-routed back to the sender (local policy
            restrictions may apply, however.)

  Note #2 - As you probably know by now, Message Numbers and Record Numbers
            do not always coincide (and usually don't except just after
            you run PackMsg with the renumbering option.)  It is possible
            for the very first message (Record #1) to be Message #2 or #19
            or #1000 or something.

            With this in mind, note that the fields for Next/Previous Reply
            Message # do not refer the the physical record number within
            the HDR file of the previous/next message; but the next two
            fields (Record # of previous/next message) do indeed refer to
            record numbers within HDR.  Also, these pointers are "board
            specific".  For example, for a message in Board #3, these four
            pointer values will reference the previous and next messages
            that also belong on Board #3.


  Note #3 - These eight boolean status flags are defined as follows:

              Flag #1 - TRUE  = Message is Marked
              Flag #2 - TRUE  = Message is Private
              Flag #3 - TRUE  = Message has been read by recipient
              Flag #4 - TRUE  = Message is Inbound
                        FALSE = Message is Outbound
              Flag #5 - TRUE  = There is a file-attach with this net message
              Flag #6 -         reserved
              Flag #7 - FALSE = Outbound message has not yet been exported
              Flag #8 - TRUE  = Message is flagged for deletion

            Flags #4 and #7 are relevant only for Netmail and Echo messages.


  Note #4 - The date format in this field is only critically important for
            messages which you plan to export later.  In that case, the
            format must be "YY/MM/DD HH:MM:SS" (17 characters) terminated
            by an end-of-string character ($FF).  That seems to be the
            format that the Export program expects to see them.

            Messages that you have -imported-, however, may use this format
            or the alternate "mailimport -d" format, which looks something
            like "YY/MM/DD  (YY/MM/DD)", with the first date being the date
            the message was received on your system, the second date being
            the creation date of the message.


   - IDX -

  This file is merely a condensed version of the HDR file.  Its purpose is to
make high-speed message scanning faster.  You can speed things up a great deal
on the CoCo by using buffering techniques (loading several records at once and
then doing your pattern matching within an array), so the smaller the records,
the more you can read and buffer at one time.  And since you really need
little more than the recipient's name and a board number to figure out where 
a user's mail is, the IDX file is a good solution.

  The IDX file is built from scratch everytime PackMsg is run.  The HDR file
is read (record by record) and a smaller version of each record is written out
to the IDX file.  This file is also updated when a user posts a message or
Mailimport imports mail.  This, the IDX file will alway contain the same
number of records that HDR does.

  Like the HDR file, the IDX file consists of two sections.  Section #1 is
42 bytes long and the format is:

  Offset          = IDX file - Section #1 =
 --------     ________________________________
  $00/0    - | Lowest Message Number      (I) |
             |--------------------------------|
  $02/2    - | Highest Message Number     (I) |
             |--------------------------------|
  $04/4    - | Number of Message Headers  (I) |
             |--------------------------------|
  $06/6    - |       36 bytes - unused        |
             |________________________________|
                    - End of Section #1 -
              ________________________________
  $2B/43   - |                                |
             |       Start of Section #2      |
            \|/                              \|/

  Again, Section #2 is one record for each message.  Each record is 43 bytes
long - the format looks like:

Record Offset       = IDX Ffile - Section #2 =
-------------   __________________________________
  $00/0      - | Board number (1-40)          (B) |
               |----------------------------------|
  $01/1      - | Message # (1-32767)          (I) |
               |----------------------------------|
  $03/3      - | Message Status Flags        (F8) | <-- See Note #3 in the
               |----------------------------------|     above HDR description
  $0B/11     - | Person message is "To"     (S32) |
               |__________________________________|

  A typical Basic09 TYPE statement for this might look like:

 TYPE idxformat=iboard:BYTE; imsgnum:INTEGER; iflg(8):BOOLEAN;
      ito:STRING[32]



   RiBBS.CFG
  ===========

  "/DD/RiBBS.cfg" is the file that tells RiBBS "who it is", "what is where",
and a number of other details.  You can also have other copies of this file in
different places on the drive and use that alternate filename in the command
line when running RiBBSMain.  This file is built by the program RConfig and
its format looks like:

   Offset                 = RiBBS.CFG =
  --------     _______________________________________
   $00/0    - | Pathname to: Fido Export Dir    (S20) |
   $14/20   - |              Message Base       (S20) |
   $28/40   - | :::::::::::: Fido-In Area       (S20) |
   $3C/60   - |              System Data Area   (S20) |
   $50/80   - | :::::::::::: Standard Data Path (S20) |
   $64/100  - |              Log Full Pathname  (S20) |
   $78/120  - | :::::::::::: UserIndex          (S20) |
   $8C/140  - |              Editor Temp Msg    (S20) |
   $A0/160  - | :::::::::::: Opt. Local Editor  (S20) |
   $B4/180  - |              Menu Path          (S20) |
   $C8/200  - | :::::::::::: Fido-Out Area      (S20) |
              |---------------------------------------|
*  $DC/220  - |          40 bytes - unused            |
              |---------------------------------------|
* $104/260  - | Origin Address                  (S25) |
              |---------------------------------------|
* $11D/285  - | Network Domain                  (S15) |
              |---------------------------------------|
  $12C/300  - | High Baud Rate                    (I) |
              |---------------------------------------|
  $12E/302  - | Fido Zone                         (I) |
              |---------------------------------------|
  $130/304  - |      Node                         (I) |
              |---------------------------------------|
  $132/306  - |      Net                          (I) |
              |---------------------------------------|
  $134/308  - |      Point                        (I) |
              |---------------------------------------|
  $136/310  - | New User Level                    (I) |
              |---------------------------------------|
  $138/312  - | New User Flags                    (B) |
              |---------------------------------------|
  $139/313  - | New User Time Limit               (B) |
              |---------------------------------------|
  $13A/314  - | New User Download Limit           (B) |
              |---------------------------------------|
  $13B/315  - | Upload Ratio (Points)             (I) |
              |---------------------------------------|
  $13D/317  - | Download Ration (Points)          (I) |
              |---------------------------------------|
  $13F/319  - | Name Format    00=Full            (B) |
              |                01=Open                |
              |---------------------------------------|
  $140/320  - | Sysop Level                       (I) |
              |---------------------------------------|
  $142/322  - | Sysop Flags                       (B) |
              |---------------------------------------|
  $143/323  - | Message Scan   00=Disabled        (B) |
              |                01=Prompted            |
              |                05=Active              |
              |---------------------------------------|
  $144/324  - | Edition number                    (I) |
              |---------------------------------------|
  $146/326  - | Applications    0=Not Accepted    (I) |
              |                 1=Accepted            |
              |---------------------------------------|
  $148/328  - | CoCo [5] (outdated variable)      (B) |
              |---------------------------------------|
  $149/329  - | I/O Pathname                    (S32) |
              |---------------------------------------|
  $169/361  - | Message Base Read Levels          (I) |
              |    Array of 40 elements - 80 bytes    |
              |---------------------------------------|
  $1B9/441  - | Message Base Write Levels         (I) |
              |    Array of 40 elements - 80 bytes    |
              |---------------------------------------|
  $209/521  - | Message Base Names              (S20) |
              |    Array of 40 elements - 800 bytes   |
              |---------------------------------------|
  $529/1321 - | Message Base Status               (B) | <--- Note #1
              |    Array of 40 elements - 40 bytes    |
              |---------------------------------------|
  $551/1361 - | Color Palette Settings - Array   (8B) |
              |---------------------------------------|
  $559/1369 - | Message Base/# of Days to Hold    (I) |
              |    Array of 40 elements - 80 bytes    |
              |---------------------------------------|
  $5A9/1449 - | Forced Application  00=Yes        (B) |
              |                     01=No             |
              |---------------------------------------|
  $5AA/1450 - | No Input Logoff                   (B) |
              |---------------------------------------|
  $5AB/1451 - | Modem Strings: Init             (S40) |
  $5D3/1491 - |                Hang-up          (S40) |
  $5FB/1531 - | :::::::::::::: Busy             (S40) |
  $623/1571 - |                9600 bps respon. (S40) |
  $64B/1611 - | :::::::::::::: 4800      "      (S40) |
  $673/1651 - |                2400      "      (S40) |
  $69B/1691 - | :::::::::::::: 1200      "      (S40) |
  $6C3/1731 - |                 300      "      (S40) |
  $6EB/1771 - | :::::::::::::: Busy response    (S40) |
  $713/1811 - |                No Carrier rsp.  (S40) |
  $73B/1851 - | :::::::::::::: No Connect rsp.  (S40) |
              |---------------------------------------|
  $763/1891 - | Carrier Bit value                 (B) |
              |---------------------------------------|
  $764/1892 - | Carrier Call Code value           (B) |
              |---------------------------------------|
  $765/1893 - | Display User Stat Screen  TRUE=No (F) |
              |                          FALSE=Yes    |
              |---------------------------------------|
  $766/1894 - | Login Delay                       (B) | 
              |---------------------------------------|
  $767/1895 - | Connect Delay                     (B) |
              |---------------------------------------|
  $768/1896 - | Entry to BBS Message            (S80) |
              |---------------------------------------|
  $7B8/1976 - | Message Base Origin Lines       (S60) |
              |   Array of 40 elements - 2400 bytes   |
              |---------------------------------------|
 $1118/4376   | BBS Name (WaZoo "greeting")     (S60) |
              |---------------------------------------|
 $1154/4436   | Sysop Name                      (S32) |
              |---------------------------------------|
 $1174/4468   | WaZoo Allowed? (TRUE/FALSE)       (F) |
              |---------------------------------------|
 $1175/4469   | Serial number                     (R) |
              |_______________________________________|

 ( * ) - Changed from v2.02 to v2.10

 Note #1 - The Message Base Status bytes are interpreted as a field of eight
           bits, each bit corresponding to a different state.  The bit
           assignments are as follows:

            Bit -  7  6  5  4  3  2  1  0
                   -  -  -  -  -  -  -  -
                   |  |  |  |  |  |  |  |_____ 0=Public / 1=Private
                   |  |  |  |  |  |  |________ 1=Prompt for Private (bit-0=0)
                   |  |  |  |  |  |___________ unused
                   |  |  |  |  |______________ unused
                   |  |  |  |_________________ unused
                   |  |  |____________________ unused
                   |  |_______________________ 0=Local / 1=Echo
                   |__________________________ 1=NetMail


   NODELIST.IDX
  ==============

  The NODELIST.IDX in your Fido-Out area is simply a "table of contents" for
your Nodelist.  It's format is very simple.

  Offset                   = Nodelist.IDX =
 --------    _______________________________________________
  $00/0   - | Filename of current NODELIST.XXX file   (S12) |
            |-----------------------------------------------|
  $0C/12  - | Zone  (I) | Net   (I) | PosM  (I) | PosL  (I) | <- Record #1
            |-----------+-----------+-----------+-----------|
  $14/20  - | Zone  (I) | Net   (I) | PosM  (I) | PosL  (2) | <- Record #2
            |-----------+-----------+-----------+-----------|
           \|/         \|/         \|/         \|/         \|/  etc, etc....

  The program "Nodeprocess" scans the NODELIST.xxx file and builds the
Nodelist.IDX file.  Each time, it sees a line that starts with "Zone,",
"Region," or "Host," it writes a record out to the Nodelist.IDX noting
position in the NODELIST.XXX file where that line starts.

      PosM = Most significant word of position.
      PosL = Least significant word of the position.

   therefore....

  Position = (PosM*65536)+PosL

  (Note: Beware of Basic09's tendency to interpret integers larger than 32767
         as negative numbers.)


   Menus
  =======

 - MENU.LIST -

  This file is pretty simple in structure.  Each record is 92 bytes long and
formated as:

  Record Offset               = MENU.LIST =
 ---------------    _________________________________
    $00/0        - | Menu Option Text          (S80) |
                   |---------------------------------|
    $50/80       - | Menu Option Pathname      (S12) |
                   |_________________________________|
                   |                                 |
                  \|/                               \|/

Example TYPE statement:

   TYPE menu_list=mntext:STRING[80]; mnpath:STRING[12]

  The Menu Option Text is the part of the menu that the user sees.  If the
last character of the string is a ";" character, no carriage return will be
issued after that line is displayed.

  The Menu Option Pathname is only used with menu options that involve running
a module or accessing a file and contains the name/pathname of that module/
file.

  Each full menu consists of 40 of these records (whether all 40 are used or
not.)  Therefore, if you want to find the start point of a particlar menu,
calculate:

      Seek_position = (record_size * 40) * (desired_menu_number - 1)


 - MENU.LVL -

  Each record in the MENU.LVL file is 5 bytes long and looks like:

  Record Offset             = MENU.LVL =
 --------------   __________________________________
     $00/0     - | Menu Option Action Code      (B) |
                 |----------------------------------|
     $01/1     - | Menu Option Access Flags     (B) |
                 |----------------------------------|
     $02/2     - | Menu Option Letter          (S1) |
                 |----------------------------------|
     $03/3     - | Menu Option Access Level     (I) |
                 |__________________________________|
                 |                                  |
                \|/                                \|/

Example TYPE statement:

  TYPE menu_level=mnact,mnflg:BYTE; mnltr:STRING[1]; mnacc:INTEGER

  Again, each menu takes up 40 of these records and you would use the same
kind of formula mentioned in the previous section to calculate where to SEEK
to find the desired menu's data.


   MailImport Stats
   ================

  - MiStat.DAT -

  The purpose of this file (which is created when using the "-S" options with
MailImport) is to provide some raw data to a statistics program that keeps
track of how much mail was recieved, etc... (such programs are rampant in the
IBM world.)  This (optional) file resides in your BBS working directory.

  If the file does not exist, Mailimport will create it.  If the file has no
records in it, it will be deleted when Mailimport exits.  An existing mistat.dat file will be appended to and will continue to grow until you or
another program deletes it.  The idea here is for a statistics manager program
to run periodically to process this data, then delete this file.  This could 
be done once per Fido session, per day, per week, or even presumably once per
month before overfragmentation prevents it being added to.

  The last record in the file will always contain the results of the last
mail run.

 Record Offset   = MiStat.DAT =
 ------------- _________________
    $00/00  -  | Zone       (I) | --\
               |----------------|    \
    $02/02  -  | Net        (I) |     >-- System mail was received from
               |----------------|    /
    $04/04  -  | Node       (I) | --/
               |----------------+---------------------------------
    $06/06  -  | Mail Processing Start Date/Time            S(17) | 
               |--------------------------------------------------|
    $17/23  -  |  ""     ""      End Time                    S(8) |
               |--------------------------------------------------|
    $1E/30  -  | High Record in HDR when MailImport started   (I) | <- Note #1
               |--------------------------------------------------|
    $70/112 -  | Number of messages processed per board    40x(I) | <- Note #2
               |--------------------------------------------------|  |
    $C0/192 -  | Size of all messages processed per board  40x(R) | <- Note #2
               |__________________________________________________|
                     
  Exmaple TYPE statement:

  TYPE mstats=szone,snet,snode:INTEGER; stime:STRING[17]; etime:STRING[8];
              snum,smsg(40):INTEGER; ssize(40):REAL

  Note #1 - In cases where Mailimport finds mail from more than one system, 
            it will process only one system's mail (skipping the other .PKT
            files), save out a record to "mistat.dat", then go back to 
            process the other system(s) mail.  The "High Record in HDR" will
            not change even if two or more records are written out in one
            session.  This is intentional and make things easier for those
            writing programs to scan the HDR files for new records after 
            Mailimport is finished.

  Note #2 - These two arrays contain the number of messages and the total
            bytecount for messages in each of the 40 message bases.  The
            array element number points to its respective board number.


   Passwords
   =========

 - Password.CTL -

  RiBBS 2.10 has an entirely new Password.CTL file format.  It should be
sufficient for quick access and future expansion.  The records do not have
to be in numerical order by Zone/Net:Node for current programs (like
Mailimport or Bundle) to process it correctly, but if you add/delete entries
to this file, it is strongly suggested that you follow RBPass' example and
keep them sorted - just in case that becomes a future requirement.

  The records are structured like this:

  Record Offset              = Password.CTL =
 ---------------    _________________________________
     $00/00      - | Zone                        (I) |
                   |---------------------------------|
     $02/02      - | Net                         (I) |
                   |---------------------------------|
     $04/04      - | Node                        (I) |
                   |---------------------------------|
     $06/06      - | Session Level Password     (S8) |
                   |---------------------------------|
     $0E/14      - | Packet Level Password      (S8) |
                   |---------------------------------|
     $16/22      - | AreaFix Password           (S8) |
                   |---------------------------------|
     $1E/30      - | reserved for expansion     (S8) |
                   |_________________________________|

 Example TYPE statement:

 TYPE password=pzone,pnet,pnode:INTEGER; pw1,pw2,pw3,pw4:STRING[8]

  Password.CTL is fixed at exactly 100 records (3,800 bytes).  There must
be no blank entries until after the last real entry since some (if not all)
programs that read this file assume they have read the last entry when they
get a Zone:Net/Node address of "0:0/0".

  Also, the password fields themselves MUST be null padded to their full
length (no $FF string terminators allowed.)  This can be tricky in BASIC09
if you aren't paying attention to what you are doing.


   Stat
   ====

  The "STAT" file is kept in your main BBS work directory.  I won't be
including a type statement here, since this file is typically just opened
and updated one field at a time.  This file serves mainly as a scratchpad
for the BBS, aiding in keeping track of events, schedules, and settings.

 Offset                    = STAT =
--------    ________________________________________
 $00/00  -  | Current I/O Path                 (I) | <- Note #1
            |--------------------------------------|
 $02/02  -  | Today's Date                   (S20) |
            |--------------------------------------|
 $16/32  -  | Last Caller                    (S32) |
            |--------------------------------------|
 $36/54  -  | Total Calls to BBS               (R) |
            |--------------------------------------|
 $3B/59  -  | New User Calls Today             (R) |
            |--------------------------------------|
 $40/64  -  | Fido Calls since last Startup    (R) |
            |--------------------------------------|
 $45/69  -  | Number of Calls Today            (R) |
            |--------------------------------------|
 $4A/74  -  | Not used?                       (S6) | <- Note #2
            |--------------------------------------|
 $50/80  -  | Time Last Event was Processed  (S17) |
            |--------------------------------------|
 $61/97  -  | Outbound Mail Enable             (F) |
            |--------------------------------------|
 $62/98  -  | Chat Enable                      (F) |
            |--------------------------------------|
 $63/99  -  | 300 Baud Acceptance Enable       (F) |
            |--------------------------------------|
 $64/100 -  | Human Caller Acceptance Enable   (F) |
            |--------------------------------------|
 $65/101 -  | Current Schedule Number         (S1) | <- Note #3
            |______________________________________|

  Note #1 - This records contains the same information as the "la.ad1"
            variable mentioned in the "Outside Program Format" section below. 
            When running a multi-line system, this setup can cause some 
            conflict if you have both copies of the BBS sharing the same
            work directory (and hence, the same STAT file.)

  Note #2 - I could find no instance in RiBBS of this area being read or
            written to.

  Note #3 - This field contains the ASCII representation of the current
            Schedule number (i.e. "1", "2", etc...) therefore only numbers
            up to "9" are acceptible.


                        ==------------------------==


   Ouside Program Format
  =======================

  What follows is an editted version of files Ron Bihler released long ago
that reveal what you need to know to write modules that RiBBS can call with
a Menu Action #11 call.

   Have your program start with the following code.

TYPE address=ad1,ad2,ad3,ad4,local:INTEGER
PARAM la:address
PARAM name$:STRING[32]
PARAM level:INTEGER
PARAM timelimit:INTEGER
PARAM ontime$:STRING[14]
PARAM cls,cr:STRING[3]
PARAM case$:STRING[1]
PARAM info(12):STRING[32]

  la.ad1    - contains path number presently opened for IO.
  la.ad2    - used by system
  la.ad3    - Contains the TERM TYPE 0=No ansi 1=ANSI 2=OS/9 codes.
  la.ad4    - is the page length setting at present. 0 = disabled
  la.local  - 0 or 1 depending on whether ribbs is in local mode or not
  name$     - is the present users name
  level     - is the users secrutity level
  timelimit - contains the users timelimit for this call
  ontime    - contains the time the user logged on
  cls       - is the code sequence to clear users screen.
  case$     - L for lower case U for upper case.
  info      - info for the use of dumpfile.

                             -------------------

    Use of "Elapsed" to get the amount of time a user has been on:

    RUN elapsed(la,ontime,elapsedtime)

    la           : same as above
    Ontime       : same as above
    Elapsedtime  : REAL          (* Time the user has been on the system.

    Now, to find out if a user has overstayed his welcome, you can simply
    (after running "elapsed") subtract "elapsedtime" from "Tlimit"... if
    you get a value less than one, the user has exceeded his time limit.

                              -----------------

    Use of "CDCheck" to check the status of the modem carrier:

    RUN cdcheck(la,cd)

    la           : same as above
    cd           : BYTE

    If after running "cdcheck", the value of "cd" is non-zero, carrier has
    been lost.

                              -----------------

    Use of "Dumpfile" to display a file to the user:

    RUN dumpfile(la,filename,case$,info,ac)

    la           : same as above
    filename     : STRING[80]   (* contains full pathname if needed
    case         : same as above
    info         : same as above
    ac           : BYTE         (* used by system

    Some Info Data
    1.    City,State
    2.    Download Limit
    3.    ElapsedTime
    4.    Flags
    5.    timelimit
    6.    Last Person On, (Before this user)
    7.    Date$
    8.
    9.    Number of Calls User has made to system
    10    Level
    11.   Last Day user Called
    12.   Users Name

                             --------------------

    Use of "Linein" to get input from the user:

    RUN linein(la,case,b$,wnum,wrap)

    la          : same as above
    case        : same as above
    b$          : STRING[160]    (* Input Line

    wnum        : byte    When entered is the current posstion of the
                          cursor (i.e. if b$="1  [" then wnum=3 (or 0
                          if word-wrap is off.))
                          When Linein is exitted, it will contain the
                          last character before the word was wrapped.
                          In most cases, this will be the last "space"
                          character in the line (before it wrapped the
                          last word.)

     wrap       : Byte    Zero for Word Wrap Off. Or is the Max size of
                          the line to be entered.

                              -------------------

     Use of "Numin" to get numeric input from the user:

     RUN numin(la,b$,innum)

     la         : same as above
     b$         : STRING[160]    Prompt text (i.e. b$="What is your Age:")

     innum      : REAL           Returns with number input by user

                              -------------------

     Use of "Onekey" to get single key entry from the user.

     RUN onekey(la,a$,ac)

     la         : same as above
     a$         : STRING[1]      Contains keypress by user
     ac         : BYTE           ASCII value of keypress

     ("The module "Charin" works the same except that the character is not
      echoed back to the user or the local screen.)

                              ------------------- 

     Use of "Lineout" to send an output line to the user:

     RUN lineout(la,b$,case)

     la         : same as above
     b$         : STRING[160]    (* Output Line
     case       : same as above

                              ------------------

     Use of "Charout" to send one character to the remote user.

     RUN charout(la,a$,cd)

     la          : same as above
     a$          : STRING[1]       Byte to send to user

     cd          : BYTE            Like CDCheck, Charout checks for carrier
                                   status and returns the value in this param.

                         ==--------------------------==

    Most programmers find it useful to have subroutines that run Linein and
Lineout - then have each of those subroutines call yet another subroutine
that calls CDCheck and Elapsed.  This way, there is a check for carrier and
time limit each time someting is output to a user or he/she is prompted for
input.


   Running RiBBS Modules
  =======================

  I'll not try to describe how to run Editor or PutMsg here.  The RiBBS 2.02
distribution package contains the source code to a program called CREATEMSG.
It is heavily commented and is an extremely good example of exactly how one
can insert text into the message base and call the editor.

  I don't intend to document ALL RiBBS modules here - just those that seem 
to be modules that someone may wish to run from modules of their own.

  - Application -

  This program is either run from a menu option or from RiBBS when the
RConfig option for Forced Applications is set to "On".  It's called like this:

RUN application(la,name,level,tlimit,tsave,cls,cr,case$,filename,flags)

  - Chat - 

  This program is called when the user pages you for chatting, or the sysop
involks the mode with the ALT-C sequence.  For those wishing to write new 
versions of the chat module, it will be called from RiBBSmain like this:

RUN chat(la,name,a$,cls,cr,chat,tlimit,ontime)

  - Fileout -

  This module is what gives your users a menu of available protocols and
prompts them for filenames that they wish to download.  The format IS 
different from v2.02 to v2.10.  It is called like this:

RUN Fileout(la,name,dlimit,pathname,ontime,tlimit,cr,cls,case$,accum,info,
            filename,proto,lover,drv5,rbaud)

  - Upload -

  This module accepts user uploads, prompts for descriptions, and updates
Files.BBS and Desc.BBS.  Several unused parameters have been removed in
the v2.10 version.

RUN Upload(la,name,case$,cls,cr,drv5,drv7,ontime,level,tlimit,pathname,accum,
           co,baud,info)


                       = Descriptions of Parameters =

 Variable       Type                       Description
==========  ============   ===================================================
        a$  STRING[1]     -When passed to "Chat", it contains "U" or "L"
                           to specify whether the user can handle lowercase.
                           "Chat" exits back to RiBBSMain with a$ containing
                           "Y" to indicate that the sysop answered the page,
                           "N" if he/she did not.
     accum  acc           -(see note #1 on "acc" variable type below)
      baud  INTEGER       -User's baud rate - Upload passes this to XMin
     case$  STRING[1]     -"L" for lowercase, "U" for no lowercase
      chat  BOOLEAN       -TRUE if Chat status is active, FALSE if not
       cls  STRING[3]     -The ASCII sequence to clear the user's screen
     co(8)  STRING[3]     -The OS-9 foreground color sequences
        cr  STRING[3]     -The ASCII sequence to issue carriage return
    dlimit  BYTE          -User's current online download limit. This variable
                            gets decremented by Fileout for each successful
                            file transferred in a call.
      drv5  STRING[20]    -Path to the system Log file
      drv7  STRING[20]    -Temporary Editor path
  filename  STRING[80]    -This parameter will have a filename in it if
                            Fileout was run by "Browse" or something similar.
                            Also, for "Application" this variable equals the
                            the name of the applicaton script file
                            (i.e. "New2.asc")
     flags  BYTE          -The user's access flags (see the Userlog section)
  info(12)  STRING[32]    -(see description in Outside Program Format section)
        la  address       -(see description in Outside Program Format section)
     level  REAL          -User's access level. Upload passes this to Editor
     lover  BYTE          -Equals 1 if Fileout was run by "Browse" after the
                            user selected the "[L]ist" option.
      name  STRING[32]    -Name of the user online
    ontime  STRING[14]    -The time that the user logged on.  Used by Elapsed
  pathname  STRING[80]    -Pathname to the current download directory
     proto  BYTE          -The protocol number that the user selected last.
                            This variable is set to zero before the first
                            download.
*    rbaud  INTEGER       -True baud rate of the remote modem.
    tlimit  INTEGER       -The number of minutes a person has left online
                            "Upload" updates this variable so that the user is
                            penalized for upload time.
    tsave   INTEGER       -User's permanent time limit. After Application
                            modifies this variable it is unchanged by
                            RiBBSMain
                            and is saved to the Userlog when the user logs
                            off.

 ( * ) - New v2.10 parameter

Note #1 - The "acc" variable type contains several values that pertain to the
          download points/limits/totals fields in the userlog.  The TYPE
          statement to define this variable is:

 TYPE acc=dw,up:BYTE ku,kd,ms,pt,urate,drate:INTEGER


 Variable                     Description
==========   ================================================================
       dw   -The number of files downloaded. "Fileout" adds to a user's total
             for each successful transfer.
       up   -The number of files uploaded. "Upload" adds to a user's total
             for each successful submission.
       ku   -The number of Kbytes uploaded. "Upload" adds to this.
       kd   -The number of Kbytes downloaded. "Fileout" adds to this.
       ms   -Used by the system. "Upload" and "Fileout" do not reference this
             variable.
       pt   -The user's number of accumulated download points.  Both Upload
             and Fileout update this field.
    urate   -The system Upload Ratio (set in RConfig).  If zero, the points
             system is bypassed (except that "pt" continues to be updated.)
    drate   -The system Download Ration (set in RConfig).  This is how much
             download credit (in points) you allow new users.


   In closing...
 =================

  This file will probably see some changes in the not-so-distant future as
more information is needed by you RiBBS developers and as I change some of
these formats in future versions of RiBBS.  I hope that the information here
will go a long way toward encouraging you to write your own support programs
for the rest of us to share.

  Please alert me to any inaccuracies you may find in this document, this may
save some other poor (and less observant) soul from certain doom. (grin)

          -Charles West
           Arrakis BBS / RiBBS Headquarters
           300 - 9600 bps (v32/v42bis)
           (405) 752-8955 -- (1:147/61.0)
           DELPHI: SANDRIDER

-eof-