Annotation of sbbs/sbbs2/smb/docs/smb.src, revision 1.1.1.1

1.1       root        1: 
                      2: 
                      3: 
                      4: 
                      5: 
                      6: 
                      7: 
                      8: 
                      9: 
                     10: 
                     11: 
                     12: 
                     13: 
                     14: 
                     15: 
                     16: 
                     17: 
                     18: 
                     19: 
                     20:                      Synchronet Message Base Specification
                     21:                                                                 Version 1.21
                     22:                                                           Updated 08/31/95
                     23: 
                     24:                                                Copyright 1995 Digital Dynamics
                     25: 
                     26:                                   PO Box 501
                     27:                              Yorba Linda, CA 92686
                     28: 
                     29:                                 Voice: 714-529-6328   BBS: 714-529-9525 V.32/V.32bis
                     30:                                   FAX: 714-529-9721            714-529-9547 V.FC
                     31:                                  Fido: 1:103/705          ftp: netcom.com /pub/sb/sbbs
                     32: 
                     33: Table of Contents
                     34: =================
                     35: &&Contents
                     36: 
                     37: Introduction....................................................@@INTRO___
                     38: Implementation Levels...........................................@@IMPLEVEL
                     39: Definitions.....................................................@@DEFINES_
                     40:         Acronyms................................................@@ACRONYMS
                     41:         Data Types..............................................@@DATATYPE
                     42: File Formats....................................................@@FILEFORM
                     43:         Index.....................(*.SID).......................@@SID_FORM
                     44:         Header....................(*.SHD).......................@@SHD_FORM
                     45:         Header Allocation.........(*.SHA).......................@@SHA_FORM
                     46:         Data......................(*.SDT).......................@@SDT_FORM
                     47:         Data Allocation...........(*.SDA).......................@@SDA_FORM
                     48:         CRC History...............(*.SCH).......................@@SCH_FORM
                     49: Header Field Types..............................................@@HFIELD_T
                     50: Data Field Types................................................@@DFIELD_T
                     51: Messsage Attributes.............................................@@ATTRBITS
                     52: Translation Types...............................................@@XLATTYPE
                     53: Agent Types.....................................................@@AGENTTYP
                     54: Network Types...................................................@@NETWORKS
                     55: Media Types.....................................................@@MEDIATYP
                     56: Message Storage Pseudo Code.....................................@@STORPCOD
                     57: Message Retrieval Pseudo Code...................................@@READPCOD
                     58: SMBUTIL.........................................................@@SMBUTIL_
                     59: CHKSMB..........................................................@@CHKSMB__
                     60: FIXSMB..........................................................@@FIXSMB__
                     61: SMBLIB (C library)..............................................@@SMBLIB__
                     62:                Data Types and Constants..(SMBDEFS.H)...................@@SMBDEFS_
                     63:         Global Variables..........(SMBVARS.C)...................@@SMBVARS_
                     64:         Function Prototypes.......(SMBLIB.H)....................@@SMBLIB.H
                     65:         Library Functions.........(SMBLIB.C)....................@@SMBLIB.C
                     66:                Miscellaneous.............(CRC*.* and LZH.*)............@@SMB_MISC
                     67: SMBLIB Storage Example..........................................@@SMB_PUT_
                     68: SMBLIB Retrieval Example........................................@@SMB_GET_
                     69: SMBLIB Performance Issues.......................................@@PERFORM_
                     70: Bibliography....................................................@@BIBLIOGR
                     71: Implementations.................................................@@IMPLEMEN
                     72: 
                     73: Introduction
                     74: ============
                     75: &&Introduction
                     76: $$INTRO___
                     77: 
                     78: Q. What is SMB?
                     79: 
                     80: A. SMB (Synchronet Message Base) is a technical specification for the storage
                     81:    format of electronic mail messages. These e-mail messages may all be
                     82:    contained in one database, or, more commonly, separated into catagorized
                     83:    databases. These message databases (or message bases) are also referred to
                     84:    as "sub-boards", "forums", "conferences", and "SIGs". The messages may be
                     85:    directed to an individual person, sent to a group of individuals, or sent
                     86:    to everyone who can read messages in that message base. Messages may be
                     87:    created and read soley at one physical location, or imported from and
                     88:    exported to a message network that may span continents. Message bases that
                     89:    are connected to a message network are often called "echoes".
                     90: 
                     91: 
                     92: Q. Why SMB?
                     93: 
                     94: A. The Synchronet Message Base is designed to store high volumes of messages
                     95:    while maintaining optimum search, retrieval, and creation performance.
                     96:    These messages are not limited to mere text. In addition to text, SMB
                     97:    defines the storage of digitized sound, MIDI, graphics, fonts, animation,
                     98:    as well as other multimedia data and triggers for localized multimedia.
                     99:    SMB thrives on a multi-user environment where messages are being created,
                    100:    read, modified, and deleted by multiple tasks simultaneously. With the
                    101:    large message networks of today being the rule, rather than the exception,
                    102:    and high volumes of messages being imported on a daily, sometimes hourly
                    103:    basis, creation and deletion speed is of the utmost importance. This is
                    104:    where SMB really shines. Being extensible enough to handle message formats
                    105:    from networks of today and tomorrow, and fast enough to import more messages
                    106:    that humanly readable, the SMB format will more than meet your message
                    107:    storage needs.
                    108: 
                    109: 
                    110: Q. Why a specification?
                    111: 
                    112: A. Message bases are often accessed and modified by a number of different
                    113:    programs. Often these programs are developed by individuals or companies
                    114:    other than the original designer of the message base format. This
                    115:    specification is an attempt to aid developers in creating programs that
                    116:    access or modify a message base stored in the SMB format.
                    117: 
                    118: 
                    119: Q. Who can use this specification?
                    120: 
                    121: A. Anyone that has interest in the Synchronet Message Base format at either
                    122:    an educational or professional level. Specifically, software developers
                    123:    interested or currently involved in the development of message readers,
                    124:    editors, echomail (toss/scan) programs, message transfer agents (MTAs),
                    125:    network gateways, and bulletin board systems. Much of the information in
                    126:    this specification is intended for those with preexisting programming
                    127:    knowledge, so those with little or no programming experience may find it
                    128:    hard to comprehend.
                    129: 
                    130: 
                    131: Q. What does the SMB specification include?
                    132: 
                    133: A. The text you are reading is part of the SMB specification: a single text
                    134:    document that defines the storage format of each of the six files of an
                    135:    SMB format message base and how they are related to each other.
                    136: 
                    137:    Included with this specification is C source code to be used as an example
                    138:    to programmers of how to access an SMB format message base and public domain
                    139:    library functions (SMBLIB) that can be compiled and linked into programs
                    140:    that access an SMB format message base developed by third parties. An SMB
                    141:    utility program (SMBUTIL) is also included with C source code as an example
                    142:    of how to use the SMBLIB functions.
                    143: 
                    144: 
                    145: Q. Where did the SMB specification come from?
                    146: 
                    147: A. Digital Dynamics (southern California based software development company)
                    148:    released "Synchronet Multinode BBS Software Version 1a" in June of 1992 as
                    149:    one of the first BBS packages to be designed from the ground-up to operate
                    150:    in a multinode environment with incredible speed and reliability, with a
                    151:    large suite of multinode specific features and design innovations.
                    152: 
                    153:    The original message base format was designed with localized messaging and
                    154:    low volume message networks in mind. By January of 1993, it was clear that
                    155:    high volume message networks (FidoNet, RelayNet, Usenet, etc.) were the
                    156:    preference of most BBS users and a new message base format was required to
                    157:    allow for high volume message storage, improved storage, retrieval, and
                    158:    maintenance performance, as well as lower storage space requirements.
                    159: 
                    160:    Rather than introduce another new message format, Digital Dynamics sought
                    161:    to implement an existing public specification for a format that would meet
                    162:    current and future message storage needs. More than a few specifications
                    163:    were seriously considered at one time or another, but after careful
                    164:    examination, design flaws and lack of extensibility eliminated them from the
                    165:    long term plans of Digital Dynamics and Synchronet BBS Software. Thus began
                    166:    the design of the "Synchronet Message Base" (SMB) format.
                    167: 
                    168:    At the request of many message related program developers, Digital Dynamics
                    169:    created and released the SMB specification before the release of "Synchronet
                    170:    Version 2.00" to allow lead-time on developing support programs for the new
                    171:    format.
                    172: 
                    173:    Digital Dynamics strongly encourages developers of message related programs
                    174:    (including software that directly competes with Synchronet or other Digital
                    175:    Dynamics products) to implement support for SMB. Though this is a public
                    176:    specification and Digital Dynamics encourages developer suggestions, it will
                    177:    remain under the sole control of Digital Dynamics unless specifically stated
                    178:    otherwise in a future revision of this specification.
                    179: 
                    180:    Digital Dynamics requests that any organizations that wish to adopt or
                    181:    ratify this specification, in part or whole, notify Digital Dynamics through
                    182:    any of the contact methods listed at the beginning of this document.
                    183: 
                    184: 
                    185: Q. How does SMB store messages?
                    186: 
                    187: A. Each message base is stored in a set of binary files. This set consists
                    188:    of between three and six files depending the storage method used. The base
                    189:    filename (maximum of eight characters under DOS) is the same for all six
                    190:    files of the same message base and unique amoung the filenames of other
                    191:    message bases in the same directory. The six files each have a different
                    192:    three character extension. The first character of the extension is always
                    193:    the letter 'S' (for SMB), while the second and third characters define the
                    194:    contents of the file.
                    195: 
                    196:    Two of the six files associated with each message base are not recreatable
                    197:    and therefore are the most important when considering data integrity. These
                    198:    two files are the data file (with a .SDT extension) and header file (.SHD
                    199:    extension). Both of these files use 256 byte blocks and have associated
                    200:    block allocation tables (stored in .SDA and .SHA respectively) so that
                    201:    deleted message blocks may be used by new messages without creating odd
                    202:    sized unused 'holes' in the files. The block allocation table files (.SDA
                    203:    and .SHA) can be recreated with the information stored in the header (.SHD)
                    204:    file. When using Hyper Allocation storage method, the allocation files (.SDA
                    205:    and .SHA) are not used.
                    206: 
                    207:    For fast indexing, there is a small fixed length index file (with a .SID
                    208:    extension). This file allows for the immediate location of message header
                    209:    records based on sender's name or user number, recipient's name or user
                    210:    number, subject, message number, or message attributes. This file can be
                    211:    recreated with the data stored in the header (.SHD) file.
                    212: 
                    213:    The last file is an optional CRC history (.SCH) file. It contains 32-bit
                    214:    CRCs of a configurable number of messages imported or created locally. This
                    215:    is to help eliminate duplicate messages created by user or program error.
                    216:    The CRC history file can be recreated with the combination of information
                    217:    stored in the data (.SDT) and header (.SHD) files.
                    218: 
                    219: Q. How fast do messages import into an SMB message base?
                    220: 
                    221: A. This is a very important question for systems for that import large volumes
                    222:    of messages. Of course, the answer depends on the storage format which you
                    223:    are importing from, the average length of messages, the design of the
                    224:    program which is peforming the import process, as well as the hardware and
                    225:    system software being used. What's important is that SMB will allow the
                    226:    fastest import process possible with any given combination of the above
                    227:    factors.
                    228: 
                    229:    Since system storage capacity is rarely infinite, neither is the number
                    230:    of messages which can be stored in a message base. System operators must
                    231:    define the maximum number of messages to be stored in a message base, the
                    232:    maximum age of the messages in that message base, or a combination of both.
                    233:    When using the Self-packing storage method (defined later in this document),
                    234:    the smaller the number of messages stored in a message base, the faster the
                    235:    import process. The SMB format is flexible enough to support multiple levels
                    236:    of import performance based on optimizations for storage space or speed.
                    237:    Most system operators will almost invariably choose speed over space, but
                    238:    which choices are available is determined by the importing program. This
                    239:    specification defines three storage methods, from slowest to fastest:
                    240:    Self-packing, Fast Allocation, and Hyper Allocation. Other options defined
                    241:    in this specification may affect storage performance, including duplicate
                    242:    message checking and message compression/encryption.
                    243: 
                    244: 
                    245: Q. How much storage is required for an SMB message base?
                    246: 
                    247: A. The biggest factor in determining storage requirements for a message base
                    248:    is the maximum number of messages to be stored in the base (defined by the
                    249:    system operator) and the average size of each message. The minimum required
                    250:    storage for a message base is 32 bytes plus 532 bytes per message (plus four
                    251:    bytes per message if duplicate message checking is used and three bytes
                    252:    per message if Self-packing or Fast Allocation storage methods are used).
                    253: 
                    254:    The SMB format was originally designed to be "self-packing", meaning purged
                    255:    (deleted) message header and data blocks will be used automatically by new
                    256:    messages. Relying solely on self-packing, an SMB format message base will
                    257:    never "shrink" in size. This is not to say that it will continually "grow"
                    258:    in size, but that without specific packing procedures, deleted message
                    259:    blocks may remain unused for extended periods of time, meanwhile using some
                    260:    amount of storage space that could be recovered using specific packing
                    261:    procedures. The Fast Allocation and Hyper Allocation storage methods do not
                    262:    use deleted message blocks for new messages so specific packing procedures
                    263:    must be used if any messages are deleted and that storage space is to ever
                    264:    be recovered.
                    265: 
                    266:    Limiting the maximum age of messages in an SMB message base is another way
                    267:    to control the storage requirements. While maximum message age definition is
                    268:    optional, the definition of the maximum number of messages is not.
                    269: 
                    270: Q. How many messages can be stored per SMB message base?
                    271: 
                    272: A. Without considering storage limitations or message data lengths greater than
                    273:    256, the theoretical maximum number of messages that can be stored in a
                    274:    single SMB message base is 16.7 million. Considering the variable length
                    275:    nature of message and header data, it is suggested that the system operator
                    276:    allow no more than 1 million messages per base.
                    277: 
                    278:    To determine an estimated maximum number of messages for a message base
                    279:    using the average message data length as a factor, use the following
                    280:    formula:
                    281: 
                    282:    4.2 billion divided by the average message length rounded up to be evenly
                    283:    divisible by 256.
                    284: 
                    285:    If the average message data length is 1500 bytes, the estimated maximum
                    286:    number of messages would be 2,734,375 (4.2 billion divided by 1536).
                    287: 
                    288:    Implementations of this format may be further limited by available system
                    289:    memory.
                    290: 
                    291: Implementation Levels
                    292: =====================
                    293: &&Implementation Levels
                    294: $$IMPLEVEL
                    295: The SMB format can be implemented to varying degrees between programs without
                    296: creating compatibilty issues. Rather than have developers specifically state
                    297: which features they have and have not implemented, we have defined seven levels
                    298: of implementation (represented by Roman numerals I through VII). For a program
                    299: or software package to meet an implementation level, it must have all of the
                    300: features listed for that level and all of those for each level below it. The
                    301: minimum suggested imlementation is level I. The SMBUTIL program included with
                    302: this specification is an example of a level I implementation with features
                    303: from some of the higher implementation levels.
                    304: 
                    305: Level I
                    306: -------
                    307: The minimum suggested level of implementation. Messages contain merely ASCII
                    308: text displayable on an ANSI terminal. Messages can be added to the message
                    309: base and if the maximum number of messages is exceeded, messages are removed
                    310: or marked for deletion.
                    311: 
                    312: Level II
                    313: --------
                    314: The addition of file attachments, multiple index/header entries per message
                    315: (multiple destinations), multiple text bodies for the separation of message
                    316: text and tag/origin lines (for example), forwarding, threading, and specific
                    317: FidoNet kludge header field support makes this level of implementation more
                    318: realistic for bulletin board system and EchoMail software implementation.
                    319: 
                    320: Synchronet Multinode BBS Software v2.00 has a level II implementation of this
                    321: specification.
                    322: 
                    323: Level III
                    324: ---------
                    325: This implementation adds support for translation strings defined later in this
                    326: document for data compression, encryption, escaping, and encoding. This level
                    327: is still limited to basic ASCII text and ANSI escape sequence entry and
                    328: retrieval.
                    329: 
                    330: Synchronet Multinode BBS Software v2.10 has a level III implementation of this
                    331: specification.
                    332: 
                    333: Level IV
                    334: --------
                    335: The storage and retrieval of embedded and attached images is added in this
                    336: level of implementation. Supported images are limited to single binary or text
                    337: data blocks that can be displayed or transferred to the user (automatically,
                    338: or by request) if their display and translation protocols define specific
                    339: support for the image type.
                    340: 
                    341: Level V
                    342: -------
                    343: This level of implementation adds support for embedded and attached sound data.
                    344: This includes digitized sound and MIDI data. Supported sounds are limited to
                    345: single binary or text data blocks that can be played or transferred to the user
                    346: (automatically or by request) if their presentation and translation protocols
                    347: define specific support for the sound type.
                    348: 
                    349: Level VI
                    350: --------
                    351: Localized sound and image data can be triggered by messages stored and
                    352: retrieved in an implementation of this level.
                    353: 
                    354: Level VII
                    355: ---------
                    356: Complete multimedia support is reached in this implementation level with
                    357: support for embedded and attached animation, sound, and video data.
                    358: 
                    359: 
                    360: Definitions
                    361: ===========
                    362: &&Definitions
                    363: $$DEFINES_
                    364: 
                    365: Control Characters
                    366: ------------------
                    367: When specifying control characters (ASCII 1 through 31), the caret symbol "^"
                    368: or the abreviation "ctrl-" followed by a character will be used to indicate the
                    369: value. ^A is equivalent to ASCII 1, ^B ASCII 2, etc. The case of the control
                    370: character is not significant (i.e. ^z and ^Z are equivalent). The control
                    371: character ^@ (ASCII 0) will be specified as NULL or 0.
                    372: 
                    373: 
                    374: Hexadecimal
                    375: -----------
                    376: Base sixteen numbering system which includes the digits 0-9 and A-F.
                    377: Hexadecimal numbers are represented in this document with a prefix of "0x" or
                    378: "\x" or a suffix of "h". Hexadecimal letter digits are not case sensitive
                    379: (i.e. the number 0xff is the same as 0xFF).
                    380: 
                    381: 
                    382: File dump
                    383: ---------
                    384: When example file dumps are displayed, the format is similar to that of the
                    385: output from the DOS DEBUG program. With the exception of the ASCII characters,
                    386: all numbers are in hexadecimal.
                    387: 
                    388: Offset    Byte values                                          ASCII characters
                    389: 
                    390: 000000   53 4D 42 1A 10 01 20 00       F4 01 00 00 F4 01 00 00    SMB... .�...�...
                    391: 000010    20 00 00 00 D0 07 00 00   D0 07 00 00 00 00 00 00     ...�...�.......
                    392: 
                    393: 
                    394: Bit values
                    395: ----------
                    396: Bit (or flag) values are represented in C notation as (1<<x) where x is the bit
                    397: number. (i.e. bit number 7 (1<<7) is the same as 0x80).
                    398: 
                    399: 
                    400: Word storage
                    401: ------------
                    402: All words (16-bit) and double words (32-bit) are stored in Intel 80x86 (little
                    403: endian) format with bytes stored from low to high (reverse of the Motorola
                    404: 680x0 word storage format).
                    405: 
                    406: A 16-bit word with the value 1234h is stored as 34h 12h.
                    407: 
                    408: Translation strings
                    409: -------------------
                    410: Translation strings (xlat variables) are arrays of words (16-bit) in the order
                    411: of the original storage translation. The last translation type is followed by a
                    412: 16-bit zero (defined later as XLAT_NONE). If there are no translations, then
                    413: the first and only element of the array is XLAT_NONE.
                    414: 
                    415: If multiple translations are used, the translation order must be reversed
                    416: upon retrieval to obtain the proper data.
                    417: 
                    418: 
                    419: Local e-mail
                    420: ------------
                    421: When referring to the local e-mail message base of a Synchronet BBS, we are
                    422: referring specifically the message base with the name "MAIL" stored in the
                    423: "DATA" directory (e.g. \SBBS\DATA\MAIL).
                    424: 
                    425: Messages stored in this message base are different in the following respects:
                    426: 
                    427:        The SMB_EMAIL status header attribute is set ON
                    428:        Hyper Allocation storage method is not supported
                    429:        The "To" and and "From" fields of the message indexes do NOT contain CRCs
                    430: 
                    431: Acronyms:
                    432: ========
                    433: &&Definition of Acronyms
                    434: $$ACRONYMS
                    435: 
                    436: ANSI            American National Standards Institute
                    437: ASCII           American Standard Code for Information Interchange
                    438: BBS             Bulletin Board System
                    439: C               The C programming language as defined by ANSI X3.159-1989
                    440: CR              Carriage Return character (ASCII 13)
                    441: CRC             Cyclic Redundancy Check
                    442: CRC-16                 Standard 16-bit CRC using 1021h polynomial (seed 0)
                    443: CRC-32                 Standard 32-bit CRC using EDB88320h polynomial (seed -1)
                    444: CRLF            Carriage Return character followed by a Line Feed character
                    445: FSC             FidoNet Standards Commitee (FTS proposal)
                    446: FTN             FidoNet Technology Network
                    447: FTS             FidoNet Technical Standard
                    448: LF              Line Feed character (ASCII 10)
                    449: QWK                    Compressed message packet format for message reading/networking
                    450: RFC             Request for Comments
                    451: SMB             Synchronet Message Base
                    452: UT              Universal Time (formerly called "Greenwhich Mean Time")
                    453: 
                    454: Data types
                    455: ==========
                    456: &&Definition of Data Types
                    457: $$DATATYPE
                    458: 
                    459: uchar           Unsigned 8-bit value (0 through 255).
                    460:                 C example:
                    461: 
                    462:                 #define uchar unsigned char
                    463: 
                    464: 
                    465: short           Signed 16-bit value (-32768 through 32767).
                    466:                                "short" is a C keyword indicating "short int".
                    467: 
                    468: 
                    469: ushort          Unsigned 16-bit value (0 through 65535).
                    470:                 C example:
                    471: 
                    472:                 #define ushort unsigned short
                    473: 
                    474: 
                    475: ulong           Unsigned 32-bit value (0 through 4294967295).
                    476:                 C example:
                    477: 
                    478:                 #define ulong unsigned long
                    479: 
                    480: 
                    481: time_t          Unsigned 32-bit value.
                    482:                 Seconds since 00:00 Jan 01 1970 (Unix format).
                    483:                 Used for all time/date storage in SMB as part of the when_t
                    484:                 data type. This time format will support dates through the year
                    485:                 2105.
                    486:                 time_t is defined by ANSI C as a long (signed) which can
                    487:                 limit its date support to the year 2038 depending on the
                    488:                 library routines used.
                    489: 
                    490: 
                    491: ASCII           String (aka character array) of 8-bit ASCII characters.
                    492:                 Characters with the bit 7 set (80h through FFh) represent
                    493:                 the IBM PC extended ASCII character set. When data or header
                    494:                 fields of this type are stored in the header, a NULL
                    495:                 terminator may or may not be present.
                    496:                 C example:
                    497: 
                    498:                 uchar str[80];
                    499: 
                    500: 
                    501: ASCIIZ          ASCII string with (non-optional) NULL terminator.
                    502:                 C example:
                    503: 
                    504:                 uchar str[81];
                    505: 
                    506: nulstr          ASCII string immediately terminated by NULL.
                    507:                 C example:
                    508: 
                    509:                 uchar *nulstr="";
                    510: 
                    511: 
                    512: undef           Data buffer with undefined contents.
                    513:                 C example:
                    514: 
                    515:                 uchar buf[BUF_LEN];
                    516: 
                    517: when_t          Date/Time stamp including time-zone adjustment information.
                    518:                 C example:
                    519: 
                    520:                 typedef struct {
                    521: 
                    522:                     time_t  time;   // Time stamp (in local time)
                    523:                     short   zone;   // Zone constant or Minutes (+/-) from UT
                    524: 
                    525:                     } when_t;
                    526: 
                    527:                 time:
                    528: 
                    529:                 A time value of 0 is invalid and indicates an uninitialized
                    530:                 time stamp.
                    531: 
                    532:                                Time stamps are always stored in universal time. i.e.
                    533:                                Regardless of what the local time zone is, Jan 1st 1994 00:00
                    534:                                will always be stored as 2D24BD00h.
                    535: 
                    536:                 zone:
                    537: 
                    538:                                If the zone is in the range -720 to +720, it represents the
                    539:                                number of minutes east or west of UT. Values in this range
                    540:                                should only be used for time zones not otherwise represented
                    541:                                here.
                    542: 
                    543:                 If the zone is greater than 720 or less than -720, then the
                    544:                 following bits have special meaning:
                    545: 
                    546:                 (1<<12)         // Non-US time zone     (east of UT)
                    547:                 (1<<13)         // Non-US time zone     (west of UT)
                    548:                 (1<<14)         // U.S. time zone
                    549:                 (1<<15)         // Daylight savings
                    550: 
                    551:                 The lower 12 bits (0 through 11) contain the number of minutes
                    552:                 east or west of UT (not accounting for daylight savings).
                    553: 
                    554:                 If the time zone is one specified in the U.S. Uniform Time Act,
                    555:                 the following values represent the zone:
                    556: 
                    557:                 AST 0x40F0      // Atlantic             (-04:00)
                    558:                 EST 0x412C      // Eastern              (-05:00)
                    559:                 CST 0x4168      // Central              (-06:00)
                    560:                 MST 0x41A4      // Mountain             (-07:00)
                    561:                 PST 0x41E0      // Pacific              (-08:00)
                    562:                 YST 0x421C      // Yukon                (-09:00)
                    563:                 HST 0x4258      // Hawaii/Alaska        (-10:00)
                    564:                 BST 0x4294      // Bering               (-11:00)
                    565: 
                    566:                 With bit 15 set, the following values represent the same zone
                    567:                 with the presence of daylight savings:
                    568: 
                    569:                 ADT 0xC0F0      // Atlantic             (-03:00)
                    570:                 EDT 0xC12C      // Eastern              (-04:00)
                    571:                 CDT 0xC168      // Central              (-05:00)
                    572:                 MDT 0xC1A4      // Mountain             (-06:00)
                    573:                 PDT 0xC1E0      // Pacific              (-07:00)
                    574:                 YDT 0xC21C      // Yukon                (-08:00)
                    575:                 HDT 0xC258      // Hawaii/Alaska        (-09:00)
                    576:                 BDT 0xC294      // Bering               (-10:00)
                    577: 
                    578:                 The following non-standard time zone specifications may also be
                    579:                 used:
                    580: 
                    581:                 MID 0x2294      // Midway               (-11:00)
                    582:                 VAN 0x21E0      // Vancouver            (-08:00)
                    583:                 EDM 0x21A4      // Edmonton             (-07:00)
                    584:                 WIN 0x2168      // Winnipeg             (-06:00)
                    585:                 BOG 0x212C      // Bogota               (-05:00)
                    586:                 CAR 0x20F0      // Caracas              (-04:00)
                    587:                 RIO 0x20B4      // Rio de Janeiro       (-03:00)
                    588:                 FER 0x2078      // Fernando de Noronha  (-02:00)
                    589:                 AZO 0x203C      // Azores               (-01:00)
                    590:                 LON 0x1000      // London               (+00:00)
                    591:                 BER 0x103C      // Berlin               (+01:00)
                    592:                 ATH 0x1078      // Athens               (+02:00)
                    593:                 MOS 0x10B4      // Moscow               (+03:00)
                    594:                 DUB 0x10F0      // Dubai                (+04:00)
                    595:                 KAB 0x110E      // Kabul                (+04:30)
                    596:                 KAR 0x112C      // Karachi              (+05:00)
                    597:                 BOM 0x114A      // Bombay               (+05:30)
                    598:                 KAT 0x1159      // Kathmandu            (+05:45)
                    599:                 DHA 0x1168      // Dhaka                (+06:00)
                    600:                 BAN 0x11A4      // Bangkok              (+07:00)
                    601:                 HON 0x11E0      // Hong Kong            (+08:00)
                    602:                 TOK 0x121C      // Tokyo                (+09:00)
                    603:                 SYD 0x1258      // Sydney               (+10:00)
                    604:                 NOU 0x1294      // Noumea               (+11:00)
                    605:                 WEL 0x12D0      // Wellington           (+12:00)
                    606: 
                    607: fidoaddr_t      FidoNet address stored as four ushorts that represent the zone,
                    608:                 network, node, and point (in that order).
                    609:                 C example:
                    610: 
                    611:                 typedef struct {
                    612: 
                    613:                     ushort zone,
                    614:                            net,
                    615:                            node,
                    616:                            point;
                    617: 
                    618:                     } fidoaddr_t;
                    619: 
                    620: 
                    621: typestr_t       ASCIIZ string with ushort type prefix.
                    622:                 C example:
                    623: 
                    624:                 typedef struct {
                    625: 
                    626:                     ushort  type;   // Specifier for type of 'str'
                    627:                     uchar   str[];  // ASCIIZ filename or other string data
                    628: 
                    629:                     } typestr_t;
                    630: 
                    631: 
                    632: mattach_t       File attachment information with type prefix, translation
                    633:                 string, and filename.
                    634:                 C example:
                    635: 
                    636:                 typedef struct {
                    637: 
                    638:                     ushort  type;   // Attachment type
                    639:                     ushort  xlat[]; // Translations of data in attachment
                    640:                     uchar   str[];  // ASCIIZ filename
                    641: 
                    642:                     } mattach_t;
                    643: 
                    644: vattach_t              Video file attachment information with type, compression,
                    645:                                translation string, and filename.
                    646:                 C example:
                    647: 
                    648:                 typedef struct {
                    649: 
                    650:                     ushort  type;   // Attachment type
                    651:                                        ushort  comp;   // Compression method
                    652:                     ushort  xlat[]; // Translations of data in attachment
                    653:                     uchar   str[];  // ASCIIZ filename
                    654: 
                    655:                                        } vattach_t;
                    656: 
                    657: mtext_t         Message text with translation string prefix.
                    658:                 C example:
                    659: 
                    660:                 typedef struct {
                    661: 
                    662:                     ushort  xlat[]; // Translations of text
                    663:                     uchar   text[]; // Actual text data
                    664: 
                    665:                                        } mtext_t;
                    666: 
                    667: 
                    668: ftext_t         Formatted message text with translation string prefix and
                    669:                 format type.
                    670:                 C example:
                    671: 
                    672:                 typedef struct {
                    673: 
                    674:                                        ushort  type;   // See Image Types for valid types
                    675:                                        ushort  xlat[]; // Translations of data
                    676:                                        uchar   data[]; // Actual formatted text data
                    677: 
                    678:                                        } ftext_t;
                    679: 
                    680: 
                    681: membed_t        Embedded data with type prefix, translation string, and ASCIIZ
                    682:                 description.
                    683:                 C example:
                    684: 
                    685:                 typedef struct {
                    686: 
                    687:                     ushort  type;   // Specifier for type of 'dat'
                    688:                     ushort  xlat[]; // Translations of embedded data
                    689:                     uchar   name[]; // ASCIIZ char description of embedded data
                    690:                                        uchar   data[]; // Binary data
                    691: 
                    692:                     } membed_t;
                    693: 
                    694: vembed_t               Embedded video data with type, compression method, translation
                    695:                                string, and ASCIIZ description.
                    696:                 C example:
                    697: 
                    698:                 typedef struct {
                    699: 
                    700:                     ushort  type;   // Specifier for type of 'dat'
                    701:                                        ushort  comp;   // Compression method
                    702:                     ushort  xlat[]; // Translations of embedded data
                    703:                     uchar   name[]; // ASCIIZ char description of embedded data
                    704:                                        uchar   data[]; // Binary data
                    705: 
                    706:                                        } vembed_t;
                    707: 
                    708: File formats
                    709: ============
                    710: &&File Formats
                    711: $$FILEFORM
                    712: &&Index (*.SID) File Format
                    713: $$SID_FORM
                    714: 
                    715: Index File (*.SID)
                    716: ------------------
                    717: The index file for each message base contains one record per message in the
                    718: base. Each record is fixed length using the following format:
                    719: 
                    720: Index Record:
                    721: ------------
                    722: C example:
                    723: 
                    724: typedef struct {
                    725: 
                    726:        ushort  to;     // 16-bit CRC of recipient name (lower case) or user number
                    727:        ushort  from;   // 16-bit CRC of sender name (lower case) or user number
                    728:        ushort  subj;   // 16-bit CRC of title/subject (lower case)
                    729:        ushort  attr;   // attributes (MSG_PRIVATE, MSG_READ, etc. flags)
                    730:        ulong   offset; // byte offset of message header in header file
                    731:        ulong   number; // message serial number (1 based)
                    732:        time_t  time;   // import date/time stamp (Unix format)
                    733: 
                    734:     } idxrec_t;
                    735: 
                    736: 
                    737: Example file dump (16 messages starting with message number 15):
                    738: ---------------------------------------------------------------
                    739: 000000   36 4F 13 07 2A 77 00 00       20 00 00 00 0F 00 00 00    6O..*w.. .......
                    740: 000010    BE 62 76 2C 36 4F 46 0A   7F B2 00 00 20 01 00 00    �bv,6OF.�.. ...
                    741: 000020    10 00 00 00 C7 29 78 2C   36 4F 70 6F 46 FF 00 00    ....�)x,6OpoF�..
                    742: 000030    20 02 00 00 11 00 00 00   AD D3 7A 2C 70 6F 13 07     .......��z,po..
                    743: 000040    46 FF 00 00 20 03 00 00   12 00 00 00 D6 F8 7F 2C    F�.. .......��,
                    744: 000050    36 4F E1 EA E7 E9 00 00   20 04 00 00 13 00 00 00    6O����.. .......
                    745: 000060    1E 7B 85 2C 37 0D 2E DF   4D 79 00 00 20 05 00 00    .{�,7..�My.. ...
                    746: 000070    14 00 00 00 5C E1 A1 2C   90 54 2D 5A 86 62 00 00    ....\�,�T-Z�b..
                    747: 000080    20 06 00 00 15 00 00 00   39 2E A2 2C 70 6F 1A 8B     .......9.�,po.�
                    748: 000090    46 FF 00 00 20 07 00 00   16 00 00 00 D0 7B A8 2C    F�.. .......�{�,
                    749: 0000A0    2E DF 1A 8B 4D 79 00 00   20 08 00 00 17 00 00 00    .�.�My.. .......
                    750: 0000B0    FF 7B A8 2C B4 D9 35 7C   23 B1 00 00 20 09 00 00    �{�,��5|#�.. ...
                    751: 0000C0    18 00 00 00 CE D4 BA 2C   36 4F BC D8 B2 E7 00 00    ....�Ժ,6O�ز�..
                    752: 0000D0    20 0A 00 00 19 00 00 00   14 5F C3 2C BA A8 4E B0     ........_�,��N�
                    753: 0000E0    67 76 00 00 20 0B 00 00   1A 00 00 00 6F 89 C3 2C    gv.. .......o��,
                    754: 0000F0    36 4F 0C 01 19 9C 00 00   20 0C 00 00 1B 00 00 00    6O...�.. .......
                    755: 000100    F8 30 C6 2C 36 4F FA 48   0E 55 00 00 20 0D 00 00    �0�,6O�H.U.. ...
                    756: 000110    1C 00 00 00 6A 94 D3 2C   36 4F F1 CE CF A2 00 00    ....j��,6O��Ϣ..
                    757: 000120    20 0E 00 00 1D 00 00 00   53 DB D5 2C 8D A6 21 CE     .......S��,��!�
                    758: 000130    F7 AB 00 00 20 0F 00 00   1E 00 00 00 31 29 DC 2C    ��.. .......1)�,
                    759: 
                    760: 
                    761: Field descriptions:
                    762: ------------------
                    763: To:
                    764: The 'To' field is the CRC-16 of the name of the intended recipient agent of
                    765: this message or the intended recipient's user number. If the CRC is stored, the
                    766: text must be converted to lower case (A-Z changed to a-z) before the CRC is
                    767: calculated. If the message is forwarded to another agent, the original or new
                    768: index record must be changed to contain the CRC-16 of the new recipient name or
                    769: user number. This field must always contain the recipient user number for local
                    770: e-mail on a Synchronet BBS. Outbound netmail stored in the Synchronet local
                    771: e-mail message base will contain 0 in this field.
                    772: 
                    773: From:
                    774: This field, similar to the 'To' field, contains the CRC-16 of the name of the
                    775: sending agent of this message or the sender's user number. If the CRC is
                    776: stored, the text must be converted to lower case (A-Z changed to a-z) before
                    777: the CRC is calculated. If the message is forwarded to another agent, the
                    778: original or new index record must be changed to contain the CRC-16 of the new
                    779: sender name or user number. If the message was imported into the local e-mail
                    780: message base on a Synchronet BBS via netmail, this field will contain 0.
                    781: 
                    782: Subj:
                    783: The 'Subj' field contains the CRC-16 of the message's subject. The subject
                    784: must be converted to lower case (A-Z changed to a-z) and all preceeding
                    785: "re: "'s and "re:"'s removed before calculating the CRC-16.
                    786: 
                    787: Attr:
                    788: This ushort is a bit field of the specific attributes for this message.
                    789: It is a clone of the 'attr' element of the msghdr_t structure.
                    790: 
                    791: Offset:
                    792: This ulong is the offset (in bytes) in the header file for this message's
                    793: header record.
                    794: 
                    795: Number:
                    796: This ulong is the serial number of this message. Valid values are 1 through
                    797: 0xffffffff. No two index records in the same message base may have the same
                    798: message number. All index records must have sequential, but not necessarily
                    799: consequetive, message numbers.
                    800: 
                    801: Time:
                    802: This field is the date/time stamp the message was imported to or posted in
                    803: the message base. It is a clone of the 'when_imported.time' element of the
                    804: msghdr_t structure.
                    805: 
                    806: Header File (*.SHD)
                    807: ===================
                    808: &&Header File (*.SHD) Format
                    809: $$SHD_FORM
                    810: 
                    811: Each SMB header file is made up of two distinct sections: base header records
                    812: and message header records (usually the bulk of the file).
                    813: 
                    814: Base Header Records:
                    815: -------------------
                    816: Base header records are blocks of data that apply to the entire message base
                    817: and are of variable length. This specification defines only one base header
                    818: record, the "Status info" (smbstatus_t) record. This status info record must be
                    819: the first base header record in the file and must be modified if additional
                    820: base header records are added.
                    821: 
                    822: Additional header records allow other developers to store configuration and
                    823: status information particular to their application needs. It also allows for
                    824: future header record definitions as part of this specification without causing
                    825: backward compatibility issues.
                    826: 
                    827: Each base header record contains a fixed length portion (smbhdr_t) and an
                    828: optional variable length portion.
                    829: 
                    830: Whenever a base header record is read or updated (written), it must first
                    831: be successfully locked and subsequently unlocked.
                    832: 
                    833: The first base header record (Status Info) is used as a semaphore when writing
                    834: to the message index (.SID) file and, when using the Hyper Allocation storage
                    835: method, writing to the message data (.SDT) file. This record must be
                    836: succesfully locked before writing and subsequently unlocked. This is to insure
                    837: that multiple applications simultaneously writing to the same message base
                    838: does result in corrrupted data.
                    839: 
                    840: 
                    841: Message Header Records:
                    842: ----------------------
                    843: Following the last base header record is the first message header record. Each
                    844: header record is stored in one or more 256 byte blocks. There must be exactly
                    845: one active message header record for every index record in the index file.
                    846: (Note: This does not include deleted message headers that have not been
                    847: overwritten by a new message header).
                    848: 
                    849: Each message header record contains a fixed length portion (msghdr_t), a list
                    850: of zero or more fixed length data fields (dfield_t), and a list of three or
                    851: more variable length header fields (hfield_t).
                    852: 
                    853: The value of the data stored in the zero or more unused bytes of the last
                    854: header record block have an undefined value, though whenever possible
                    855: developers should initialize to binary zero for human readability.
                    856: 
                    857: Whenever a message header record is read or updated (written), it must first
                    858: be successfully locked and subsequently unlocked.
                    859: 
                    860: Base Header Record (Fixed Portion):
                    861: ----------------------------------
                    862: C example:
                    863: 
                    864: typedef struct {
                    865: 
                    866:     uchar   id[4];          // text or binary unique hdr ID
                    867:     ushort  version;        // version number (initially 100h for 1.00)
                    868:     ushort  length;         // length including this struct
                    869: 
                    870:     } smbhdr_t;
                    871: 
                    872: 
                    873: Base Header Record Field Descriptions:
                    874: -------------------------------------
                    875: Id:
                    876: This is a four byte unique ID identifying the type of the base header record.
                    877: The bytes may contain any value, but printable ASCII characters are preferred.
                    878: The only ID defined in this specification is "SMB^Z" used by the Status Info
                    879: base header record.
                    880: 
                    881: Version:
                    882: This is a version number of the base header record type. Base header records
                    883: of different versions may have different formats or contain different
                    884: information. This is to aid the application in determining if the record
                    885: is pertinent and if so, to what degree. The Status Info base header record
                    886: uses this version field to define the version of the format for the entire
                    887: message base (currently 0x121 for version 1.21).
                    888: 
                    889: Length:
                    890: This is entire length in bytes of this header record (including both fixed
                    891: and variable portions).
                    892: 
                    893: 
                    894: Base Header #1 (Status info) Record (Variable Portion):
                    895: ------------------------------------------------------
                    896: C example:
                    897: 
                    898: typedef struct {
                    899: 
                    900:        ulong   last_msg;               // last message number posted or imported
                    901:        ulong   total_msgs;     // total messages currently in message base
                    902:     ulong   header_offset;  // byte offset to first header record
                    903:     ulong   max_crcs;       // Maximum number of CRCs to keep in history
                    904:        ulong   max_msgs;               // Maximum number of messages to keep in base
                    905:     ushort  max_age;        // Maximum age of messages (days) to keep in base
                    906:        ushort  attr;                   // Attribute bits
                    907: 
                    908:     } smbstatus_t;
                    909: 
                    910: Base Header #1 (Status Info) Record (Variable Portion) Field Descriptions:
                    911: -------------------------------------------------------------------------
                    912: Last_msg:
                    913: This is the serial number of the last message imported or posted into this
                    914: message base. The index, header, and data records for this message may possibly
                    915: not exist (due to deletion). This field is used for determining the message
                    916: number to give to a new message being imported or posted into this message
                    917: base. This field must be updated for every message added to the message base.
                    918: 
                    919: Total_msgs:
                    920: This is the total number of active messages currently in the message base.
                    921: This number should match the number of records in the index (.SID) file
                    922: and active header records in the header (.SHD) file. This field must be
                    923: updated whenever a message is added to or removed from the message base.
                    924: 
                    925: Header_offset:
                    926: This is the byte offset to the first message header record. It is useful
                    927: for skipping all the base header records and going directly to the first
                    928: message header record.
                    929: 
                    930: Max_crcs:
                    931: This is the maximum number of message CRCs to store in the CRC history (.SCH)
                    932: file for duplicate message checking. If this field contains 0, then duplicate
                    933: message checking is disabled.
                    934: 
                    935: Max_msgs:
                    936: This is the preferred maximum number of messages to keep in this message
                    937: base as specified by the system operator. It is used by maintenance programs
                    938: that trim the message base down by removing old messages. This field should
                    939: be ignored by applications importing or posting messages allowing them to
                    940: exceed this maximum at will.
                    941: 
                    942: Max_age:
                    943: This field is the maximum age (in days) of messages to keep in the message
                    944: base. It is used by maintenance programs to purge out-dated messages from
                    945: the message base.
                    946: 
                    947: Attr:
                    948: This is a bit field containing specific attributes (or flags) that may define
                    949: the way messages are stored or retrieved from the this message base. The
                    950: following attributes are defined:
                    951: 
                    952:        SMB_EMAIL               (1<<0)
                    953: 
                    954:        Indicates the message base is specifically for messages to or from local
                    955:        users. When this bit is set, the idxrec.to and idxrec.from fields will
                    956:        contain the user numbers (or 0 for non-user destination/source) instead of
                    957:        the CRC-16 of the agent name.
                    958: 
                    959:        SMB_HYPERALLOC  (1<<1)
                    960: 
                    961:        Indicates the message base uses the Hyper Allocation storage method. This
                    962:        bit should not be cleared by an application without first deleting all the
                    963:        messages in the message base. This is due to the fact the Hyper Allocation
                    964:        is not downward compatible with the Self-packing and Fast Allocation
                    965:        storage methods.
                    966: 
                    967: When used with Synchronet BBS software, a message base must NOT have both of
                    968: the above attributes set. The only message base that should have the SMB_EMAIL
                    969: attribute set is the DATA\MAIL message base.
                    970: 
                    971: 
                    972: Base Header #1 (Status info) Record Contents:
                    973: --------------------------------------------
                    974: smbhdr.id="SMB\x1a";        // SMB^Z
                    975: smbhdr.version=0x121;          // v1.21
                    976: smbhdr.length=sizeof(smbhdr_t)+sizeof(smbstatus_t); smbstatus_t status;
                    977: 
                    978: 
                    979: Additional Base Headers:
                    980: -----------------------
                    981: Additional headers from developers must have initial 8 bytes in smbhdr_t
                    982: format, length must include size of smbhdr_t, and header_offset of smbstatus_t
                    983: must be changed to include the size of the additional header(s).
                    984: 
                    985: 
                    986: Example file dump (base header portion only):
                    987: --------------------------------------------
                    988: 000000   53 4D 42 1A 20 01 20 00       F4 01 00 00 F4 01 00 00    SMB. . .�...�...
                    989: 000010    20 00 00 00 D0 07 00 00   D0 07 00 00 00 00 00 00     ...�...�.......
                    990: 
                    991: 
                    992: Message Header Record (Fixed portion):
                    993: -------------------------------------
                    994: C example:
                    995: 
                    996: typedef struct {
                    997: 
                    998:     uchar   id[4];          // SHD^Z (same for all types and versions)
                    999:     ushort  type;           // Message type (this is the definition of type 0)
                   1000:     ushort  version;        // Version of type (initially 100h for 1.00)
                   1001:     ushort  length;         // Total length of fixed portion + all fields
                   1002:     ushort  attr;           // Attributes (bit field) (duplicated in SID)
                   1003:     ulong   auxattr;        // Auxillary attributes (bit field)
                   1004:     ulong   netattr;        // Network attributes (bit field)
                   1005:     when_t  when_written;   // Date/Time message was originally created
                   1006:     when_t  when_imported;  // Date/Time message was imported (locally)
                   1007:     ulong   number;         // Message number (unique, not necessarily seq.)
                   1008:     ulong   thread_orig;    // Original message number in thread
                   1009:     ulong   thread_next;    // Next message in thread
                   1010:     ulong   thread_first;   // Number of first reply to this message
                   1011:     uchar   reserved[16];   // 16 reserved bytes for future use
                   1012:     ulong   offset;         // Offset for buffer into data file (0 or mod 256)
                   1013:     ushort  total_dfields;  // Total number of data fields
                   1014: 
                   1015:     } msghdr_t;
                   1016: 
                   1017: typedef struct {
                   1018: 
                   1019:     ushort  type;           // See "Data Field Types" values
                   1020:     ulong   offset;         // Offset into buffer 
                   1021:     ulong   length;         // Length of data field in buffer
                   1022: 
                   1023:     } dfield_t;
                   1024: 
                   1025: typedef struct {
                   1026: 
                   1027:     ushort  type;           // See "Header Field Types" for values
                   1028:     ushort  length;         // Length of buffer
                   1029:     uchar   dat[length];
                   1030: 
                   1031:     } hfield_t;
                   1032: 
                   1033: Example file dump (one header record, both fixed and variable length portions):
                   1034: ------------------------------------------------------------------------------
                   1035: 000020   53 48 44 1A 00 00 20 01       F5 00 00 00 00 00 00 00    SHD... .�.......
                   1036: 000030    00 00 00 00 46 DB F7 2C   00 00 7D D7 29 2D 00 00    ....F��,..}�)-..
                   1037: 000040    01 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00    ................
                   1038: 000050    00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00    ................
                   1039: 000060    00 00 00 00 02 00 00 00   00 00 00 00 4A 01 00 00    ............J...
                   1040: 000070    02 00 4A 01 00 00 53 00   00 00 00 00 13 00 4D 61    ..J...S.......Ma
                   1041: 000080    72 69 61 6E 6E 65 20 4D   6F 6E 74 67 6F 6D 65 72    rianne Montgomer
                   1042: 000090    79 30 00 0C 00 43 61 72   6F 6C 20 47 61 69 73 65    y0...Carol Gaise
                   1043: 0000A0    72 60 00 07 00 46 61 72   6E 68 61 6D A4 00 14 00    r`...Farnham�...
                   1044: 0000B0    31 3A 31 33 38 2F 31 30   32 2E 30 20 32 63 66 38    1:138/102.0 2cf8
                   1045: 0000C0    30 35 37 36 A5 00 14 00   31 3A 33 34 33 2F 31 30    0576�...1:343/10
                   1046: 0000D0    30 2E 30 20 32 63 66 33   62 39 30 61 A3 00 23 00    0.0 2cf3b90a�.#.
                   1047: 0000E0    31 33 38 2F 31 30 32 20   31 20 32 37 30 2F 31 30    138/102 1 270/10
                   1048: 0000F0    31 20 32 30 39 2F 32 30   39 20 31 30 33 2F 30 20    1 209/209 103/0 
                   1049: 000100    33 35 35 02 00 02 00 02   00 03 00 08 00 01 00 8A    355............�
                   1050: 000110    00 66 00 00 00 00 00 00   00 00 00 00 00 00 00 00    .f..............
                   1051: 
                   1052: Contents of example header:
                   1053: --------------------------
                   1054: id                                      SHD^Z
                   1055: type                            0000h
                   1056: version                         0120h
                   1057: length               245
                   1058: attr                 0000h
                   1059: auxattr              00000000h
                   1060: netattr              00000000h
                   1061: when_written         Sat Nov 27 17:57:10 1993
                   1062: when_imported        Tue Jan 04 15:54:21 1994
                   1063: number               1
                   1064: thread_orig          0
                   1065: thread_next          0
                   1066: thread_first         0
                   1067: reserved[16]         
                   1068: offset               0
                   1069: total_dfields        2
                   1070: 
                   1071: dfield[0].type       00h
                   1072: dfield[0].offset     0
                   1073: dfield[0].length     330
                   1074: dfield[1].type          02h
                   1075: dfield[1].offset     330
                   1076: dfield[1].length     83
                   1077: 
                   1078: hfield[0].type       00h
                   1079: hfield[0].length     19
                   1080: hfield[0]_dat        Marianne Montgomery
                   1081: hfield[1].type          30h
                   1082: hfield[1].length     12
                   1083: hfield[1]_dat        Carol Gaiser
                   1084: hfield[2].type          60h
                   1085: hfield[2].length     7
                   1086: hfield[2]_dat        Farnham
                   1087: hfield[3].type          A4h
                   1088: hfield[3].length     20
                   1089: hfield[3]_dat        1:138/102.0 2cf80576
                   1090: hfield[4].type          A5h
                   1091: hfield[4].length     20
                   1092: hfield[4]_dat        1:343/100.0 2cf3b90a
                   1093: hfield[5].type          A3h
                   1094: hfield[5].length     35
                   1095: hfield[5]_dat        138/102 1 270/101 209/209 103/0 355
                   1096: hfield[6].type          02h
                   1097: hfield[6].length     2
                   1098: hfield[6]_dat           02 00
                   1099: hfield[7].type          03h
                   1100: hfield[7].length     8
                   1101: hfield[7]_dat        01 00 8A 00 66 00 00 00
                   1102: 
                   1103: Fixed Portion Field descriptions:
                   1104: --------------------------------
                   1105: Id:
                   1106: This field (regardless of the header type or version) must always contain the
                   1107: the string "SHD^Z". This is to aid in the restoration of a corrupted header
                   1108: file and give a visual indication of the beginning of a new header record when
                   1109: viewing dumps of the header file.
                   1110: 
                   1111: Type:
                   1112: This is the message header type. Only one type is currently defined by this
                   1113: specification (type 0). Any and all future header types will have the first
                   1114: 4 fields (10 bytes) in the same format of type 0. This allows other types
                   1115: (with different lengths) to be skipped because the 4th field (length) will
                   1116: always be in the same position.
                   1117: 
                   1118: Version:
                   1119: This is the version of this header type. This specification defines version
                   1120: 1.21 of message header type 0 (stored as 121h).
                   1121: 
                   1122: Length:
                   1123: This is the total length of this message header record (including both fixed
                   1124: and variable length portions, but NOT including unused block space).
                   1125: 
                   1126: Attr:
                   1127: This is a bit field (16-bit) containing basic message attributes (flags) for
                   1128: this message. An exact duplicate of this field is stored in the index file as
                   1129: well. They must always match.
                   1130: 
                   1131: Auxattr:
                   1132: This is a bit field (32-bit) containing the auxillary attributes (flags) for
                   1133: this message. The attributes stored in this variable are more specific in
                   1134: nature and less critical than those in the Attr field.
                   1135: 
                   1136: Netattr:
                   1137: This is a bit field (32-bit) containing the network attributes (flags) for this
                   1138: message. The attributes stored in this variable are related solely to message
                   1139: networking.
                   1140: 
                   1141: When_written:
                   1142: This is the date and time when the message was originally created.
                   1143: 
                   1144: When_imported:
                   1145: This is the date and time when the message was posted on or imported into the
                   1146: local message system.
                   1147: 
                   1148: Number:
                   1149: This is the message's unique serial number (from 1 to FFFFFFFFh). This field
                   1150: is duplicated in the index file. They must always match.
                   1151: 
                   1152: Thread_orig:
                   1153: If this message is a reply, then this field contains the number of the original
                   1154: message that was replied to. If this message was not a reply, this field will
                   1155: contain the value 0.
                   1156: 
                   1157: Thread_next:
                   1158: If this message is a reply, and there are later replies to that message
                   1159: (the message number contained in the Thread_orig field), then this field will
                   1160: contain the number of the next reply in the chain. If this message is the only
                   1161: reply to the orignal message, this field will contain the value 0.
                   1162: 
                   1163: Thread_first:
                   1164: If there are any replies to this message (after it has been posted), this field
                   1165: will contain the number of the first reply to this message. If there are no
                   1166: replies to this message, this field will contain the value 0.
                   1167: 
                   1168: Reserved:
                   1169: Unused bytes, reserved for future definition in the message header type 0
                   1170: specification.
                   1171: 
                   1172: Offset:
                   1173: The byte offset into the data file, specifying the start of the buffer for
                   1174: all data associated with this message. This value must be either 0 or modula
                   1175: 256. When retrieving the actual data portion of data fields, the physical
                   1176: offset into the file will be the offset of the message data buffer (this field)
                   1177: plus the offset of the individual data field (msghdr_t.offset+dfield_t.offset).
                   1178: 
                   1179: Total_dfields:
                   1180: This field contains the total number of data fields associated with this
                   1181: message. The value of this field must match the actual number of data fields
                   1182: stored in the header (dfield_t data types following the fixed portion of the
                   1183: message header).
                   1184: 
                   1185: 
                   1186: Variable Portion Field descriptions:
                   1187: -----------------------------------
                   1188: See the Header Field Type and Data Field Type sections for the descriptions
                   1189: of the values contained in these fields.
                   1190: 
                   1191: Message Header Block Allocation (*.SHA)
                   1192: =======================================
                   1193: &&Header Allocation File (*.SHA) Format
                   1194: $$SHA_FORM
                   1195: 
                   1196: If this message base uses the Hyper Allocation storage method (the
                   1197: SMB_HYPERALLOC bit is set in the smbstatus_t.attr field), then this file is
                   1198: not created or used.
                   1199: 
                   1200: This file contains no header or signature data. Each byte (uchar) in the file
                   1201: specifies the allocation state of the corresponding 256 byte block in the
                   1202: header (*.SHD) file. A value of 0 indicates a free header block, and a value of
                   1203: 1 indicates an allocated block. Other non-zero values are undefined.
                   1204: 
                   1205: This file must always be opened DENY ALL (non-shareable).
                   1206: 
                   1207: Message Data (*.SDT)
                   1208: ====================
                   1209: &&Data File (*.SDT) Format
                   1210: $$SDT_FORM
                   1211: 
                   1212: This file contains no header or signature data. It contains the text and other
                   1213: embedded data for the messages in a single message base. The data for each
                   1214: message always begins on a 256 byte block boundary. The data in the unused
                   1215: portion of a data block is undefined, but should be initialized to NULL
                   1216: whenever possible.
                   1217: 
                   1218: This file must always be opened DENY NONE (shareable).
                   1219: 
                   1220: Data fields of type TEXT_BODY and TEXT_TAIL must have all trailing white space
                   1221: and control characters removed (i.e. the last character of the data record
                   1222: must be in the range 21h to FFh). The only exception to this rule, is if the
                   1223: TEXT_BODY is terminated with multiple contiguous CRLFs, only the last CRLF
                   1224: should be removed. A CRLF should always be appended to the text data when it is
                   1225: displayed.
                   1226: 
                   1227: When reading from this file, it is a good idea to make sure the message header
                   1228: for the data being read is currently locked (though no single message header
                   1229: should be locked for extended durations of time). This will insure that no
                   1230: other application will write to this portion of the file while it's being
                   1231: read (read from disk, not displayed).
                   1232: 
                   1233: When using the Hyper Allocation storage method, the Status Info message base
                   1234: header must be successfully locked before writing to this file and subsequently
                   1235: unlocked.
                   1236: 
                   1237: Message Data Block Allocation (*.SDA)
                   1238: =====================================
                   1239: &&Data Allocation File (*.SDA) Format
                   1240: $$SDA_FORM
                   1241: 
                   1242: If this message base uses the Hyper Allocation storage method (the
                   1243: SMB_HYPERALLOC bit is set in the smbstatus_t.attr field), then this file is
                   1244: not created or used.
                   1245: 
                   1246: This file contains no header or signature data. Each word (ushort) in the file
                   1247: specifies the allocation state of the corresponding 256 byte block in the data
                   1248: (*.SDT) file. A value of 0 indicates a free block, and a non-zero value
                   1249: indicates the number of message header records associated with this message
                   1250: data (most often 1). Each block can be used by up to 65,535 header records.
                   1251: 
                   1252: This file must always be opened DENY ALL (non-shareable).
                   1253: 
                   1254: CRC history for duplicate message checking (*.SCH)
                   1255: ==================================================
                   1256: &&CRC History File (*.SCH) Format
                   1257: $$SCH_FORM
                   1258: 
                   1259: This file is optional and contains no header or signature data. Each long word
                   1260: (ulong) in the file contains a CRC-32 of previously posted/imported messages.
                   1261: These CRCs can be used to check a candidate message for posting/import to be
                   1262: sure the message isn't a duplicate created by human or program error. The
                   1263: maximum number of CRCs to store is defined in the first message base header
                   1264: record (smbstatus_t.max_crcs).
                   1265: 
                   1266: The CRC is calculated on the first TEXT_BODY data field before any translations
                   1267: are applied (e.g. encoding, compression, encryption).
                   1268: 
                   1269: This file must always be opened DENY ALL (non-shareable).
                   1270: 
                   1271: Header Field Types:
                   1272: ==================
                   1273: &&Header Field Types
                   1274: $$HFIELD_T
                   1275: 
                   1276: These are the defined valid values for hfield_t.type:
                   1277: 
                   1278: Name     : SENDER
                   1279: Value    : 00h
                   1280: Data     : ASCII
                   1281: Multiple : Yes, order significant
                   1282: Required : Yes
                   1283: Summary  : Name of agent that sent this message
                   1284: 
                   1285: If blank (0 length or nulstr), assumed "Anonymous". If multiple SENDER fields
                   1286: exist, then the message has been forwarded and the order of the fields in the
                   1287: record must match the forwarding order (chronologically). When forwarding a
                   1288: message, the original SENDER field should be left intact and new SENDER,
                   1289: FORWARDED, and RECIPIENT fields added to the end of the record.
                   1290: 
                   1291: Name     : SENDERAGENT
                   1292: Value    : 01h
                   1293: Data     : ushort
                   1294: Multiple : Yes, order significant
                   1295: Required : No
                   1296: Default  : AGENT_PERSON or previous SENDERAGENT if exists
                   1297: Summary  : Type of agent that sent this message
                   1298: 
                   1299: If multiple SENDER fields exist, then the message has been forwarded. If any of the
                   1300: forwarding agents is of a type other than AGENT_PERSON, then this field must
                   1301: follow that SENDER field to specify the agent type.
                   1302: 
                   1303: Name     : SENDERNETTYPE
                   1304: Value    : 02h
                   1305: Data     : ushort
                   1306: Multiple : Yes, order significant
                   1307: Required : No
                   1308: Default  : NET_NONE or previous SENDERNETTYPE if exists
                   1309: Summary  : Type of network message was sent from
                   1310: 
                   1311: If multiple SENDERNETADDR fields are included, a SENDERNETTYPE field should be
                   1312: included before each to determine what data type the address is stored in.
                   1313: 
                   1314: Name     : SENDERNETADDR
                   1315: Value    : 03h
                   1316: Data     : undef
                   1317: Multiple : Yes, order significant
                   1318: Required : No
                   1319: Default  : Previous SENDERNETADDR if exists
                   1320: Summary  : Network address for agent that sent this message
                   1321: 
                   1322: The SENDERNETTYPE field indicates the data type of this field. If the
                   1323: SENDERNETTYPE is of type NET_INTERNET, the local-part of the Internet
                   1324: address is optional. If the local-part separator character ('@') is omitted,
                   1325: the SENDER field is assumed to be the local-part of the address.
                   1326: 
                   1327: Name     : SENDEREXT
                   1328: Value    : 04h
                   1329: Data     : ASCII
                   1330: Multiple : Yes, order significant
                   1331: Required : No
                   1332: Default  : Previous SENDEREXT if exists
                   1333: Summary  : Extension of sending agent
                   1334: 
                   1335: This field is useful for storing the sending agent's extension, when the
                   1336: agent's extension binds more tightly than the agent's name.
                   1337: 
                   1338: For example, Synchronet Multinode BBS Software stores local e-mail with the
                   1339: sending and receiving agent's user numbers stored as their respective
                   1340: extensions. This is done so that if a user name changes for some reason,
                   1341: messages will not "disappear" from the user's mail box.
                   1342: 
                   1343: If the SMB_EMAIL status header attribute is set, then the "From" field in the
                   1344: index must contain the binary value of this field rather than the CRC-16 of the
                   1345: SENDER (name) field.
                   1346: 
                   1347: Name     : SENDERPOS
                   1348: Value    : 05h
                   1349: Data     : ASCII
                   1350: Multiple : Yes, order significant
                   1351: Required : No
                   1352: Default  : Previous SENDERPOS if exists
                   1353: Summary  : Position of sending agent
                   1354: 
                   1355: Primarily for documentary purposes, this field contains the position of the
                   1356: sending agent (i.e. President, Sysop, C.E.O., MIS Director, etc).
                   1357: 
                   1358: It can also be useful for getting a message or reply to the intended
                   1359: recipient when the agent name is not located or is unknown, but the position
                   1360: of the agent is known and specified.
                   1361: 
                   1362: Name     : SENDERORG
                   1363: Value    : 06h
                   1364: Data     : ASCII
                   1365: Multiple : Yes, order significant
                   1366: Required : No
                   1367: Default  : Previous SENDERORG if exists
                   1368: Summary  : Organization name of sending agent
                   1369: 
                   1370: Primarily for documentary purposes, this field contains the organization to
                   1371: which the sending agent belongs (i.e. Microsoft, Joe's BBS, SoCal User's Group,
                   1372: etc).
                   1373: 
                   1374: Name     : AUTHOR
                   1375: Value    : 10h
                   1376: Data     : ASCII
                   1377: Multiple : Yes
                   1378: Required : No
                   1379: Default  : First SENDER
                   1380: Summary  : Name of agent that created this message
                   1381: 
                   1382: This field can only be added by the process that originally creates the
                   1383: message. It should not be included if same as first SENDER field. If multiple
                   1384: AUTHOR fields exist, then the message was created by multiple agents and is
                   1385: considered valid. The order of multiple AUTHOR fields in the record is not
                   1386: significant.
                   1387: 
                   1388: Name     : AUTHORAGENT
                   1389: Value    : 11h
                   1390: Data     : ushort
                   1391: Multiple : Yes, order significant
                   1392: Required : No
                   1393: Default  : SENDERAGENT or previous AUTHORAGENT if exists
                   1394: Summary  : Type of agent that created this message
                   1395: 
                   1396: This field can only be added by the process that originally creates the
                   1397: message. It should not be included if same as first SENDERAGENT field. If
                   1398: multiple AUTHOR fields exist, then the message was created by multiple agents
                   1399: and if the agent type for any of the authors is other than AGENT_PERSON, an
                   1400: AUTHORAGENT field must follow to specify the agent type.
                   1401: 
                   1402: Name     : AUTHORNETTYPE
                   1403: Value    : 12h
                   1404: Data     : ushort
                   1405: Multiple : Yes, order significant
                   1406: Required : No
                   1407: Default  : SENDERNETTYPE or previous AUTHORNETTYPE if exists
                   1408: Summary  : Type of network this author is member of
                   1409: 
                   1410: Name     : AUTHORNETADDR
                   1411: Value    : 13h
                   1412: Data     : undef
                   1413: Multiple : Yes, order significant
                   1414: Required : No
                   1415: Default  : SENDERNETADDR or previous AUTHORNETADDR if exists
                   1416: Summary  : Network address of this author
                   1417: 
                   1418: Name     : AUTHOREXT
                   1419: Value    : 14h
                   1420: Data     : ASCII
                   1421: Multiple : Yes, order significant
                   1422: Required : No
                   1423: Default  : SENDEREXT or previous AUTHOREXT if exists
                   1424: Summary  : Extension of this author
                   1425: 
                   1426: Name     : AUTHORPOS
                   1427: Value    : 15h
                   1428: Data     : ASCII
                   1429: Multiple : Yes, order significant
                   1430: Required : No
                   1431: Default  : SENDERPOS or previous AUTHORPOS if exists
                   1432: Summary  : Position of this author
                   1433: 
                   1434: Name     : AUTHORORG
                   1435: Value    : 16h
                   1436: Data     : ASCII
                   1437: Multiple : Yes, order significant
                   1438: Required : No
                   1439: Default  : SENDERORG or previous AUTHORORG if exists
                   1440: Summary  : Organization this author belongs to
                   1441: 
                   1442: Name     : REPLYTO
                   1443: Value    : 20h
                   1444: Data     : ASCII
                   1445: Multiple : Yes, but only last is valid
                   1446: Required : No
                   1447: Default  : SENDER
                   1448: Summary  : Name of agent that replies should go to
                   1449: 
                   1450: Name     : REPLYTOAGENT
                   1451: Value    : 21h
                   1452: Data     : ushort
                   1453: Multiple : Yes, but only last is valid
                   1454: Required : No
                   1455: Default  : SENDERAGENT
                   1456: Summary  : Type of agent that replies should go to
                   1457: 
                   1458: Name     : REPLYTONETTYPE
                   1459: Value    : 22h
                   1460: Data     : ushort
                   1461: Multiple : Yes, but only last is valid
                   1462: Required : No
                   1463: Default  : SENDERNETTYPE
                   1464: Summary  : Type of network that replies should go to
                   1465: 
                   1466: Name     : REPLYTONETADDR
                   1467: Value    : 23h
                   1468: Data     : undef
                   1469: Multiple : Yes, but only last is valid
                   1470: Required : No
                   1471: Default  : SENDERNETADDR
                   1472: Summary  : Network address that replies should go to
                   1473: 
                   1474: Name     : REPLYTOEXT
                   1475: Value    : 24h
                   1476: Data     : ASCII
                   1477: Multiple : Yes, but only last is valid
                   1478: Required : No
                   1479: Default  : SENDEREXT
                   1480: Summary  : Extension of agent that replies should go to
                   1481: 
                   1482: Name     : REPLYTOPOS
                   1483: Value    : 25h
                   1484: Data     : ASCII
                   1485: Multiple : Yes, but only last is valid
                   1486: Required : No
                   1487: Default  : SENDERPOS
                   1488: Summary  : Position of agent that replies should go to
                   1489: 
                   1490: Name     : REPLYTOORG
                   1491: Value    : 26h
                   1492: Data     : ASCII
                   1493: Multiple : Yes, but only last is valid
                   1494: Required : No
                   1495: Default  : SENDERORG
                   1496: Summary  : Organization of agent that replies should go to
                   1497: 
                   1498: Name     : RECIPIENT
                   1499: Value    : 30h
                   1500: Data     : ASCII
                   1501: Multiple : Yes, order significant
                   1502: Required : Yes
                   1503: Default  : "All"
                   1504: Summary  : Name of agent to receive this message
                   1505: 
                   1506: If multiple RECIPIENT fields exist, the message has been forwarded and for each
                   1507: additional RECIPIENT field (after the initial RECIPIENT), there should be a
                   1508: FORWARDED field. The order of the RECIPIENT fields in the record must match the
                   1509: order in which the message was sent and forwarded (chronologically).
                   1510: 
                   1511: Name     : RECIPIENTAGENT
                   1512: Value    : 31h
                   1513: Data     : ushort
                   1514: Multiple : Yes, order significant
                   1515: Required : No
                   1516: Default  : AGENT_PERSON or previous RECIPIENTAGENT if exists
                   1517: Summary  : Type of agent to receive this message
                   1518: 
                   1519: If multiple RECIPIENT fields exist, the message has been forwarded. If any of
                   1520: the recipient agents are of a type other than AGENT_PERSON, this field must
                   1521: follow the RECIPIENT field to specify the agent type.
                   1522: 
                   1523: Name     : RECIPIENTNETTYPE
                   1524: Value    : 32h
                   1525: Data     : ushort
                   1526: Multiple : Yes, order significant
                   1527: Required : No
                   1528: Default  : NET_NONE or previous RECIPIENTNETTYPE if exists
                   1529: Summary  : Type of network to receive this message
                   1530: 
                   1531: Name     : RECIPIENTNETADDR
                   1532: Value    : 33h
                   1533: Data     : undef
                   1534: Multiple : Yes, order significant
                   1535: Required : No
                   1536: Default  : Previous RECIPIENTNETADDR if exists
                   1537: Summary  : Address of network to receive this message
                   1538: 
                   1539: Name     : RECIPIENTEXT
                   1540: Value    : 34h
                   1541: Data     : ASCII
                   1542: Multiple : Yes, order significant
                   1543: Required : No
                   1544: Default  : Previous RECIPIENTEXT if exists
                   1545: Summary  : Extension of agent to receive this message
                   1546: 
                   1547: If SMB_EMAIL status header attribute is set, then the "To" field in the index
                   1548: must contain the binary value of this field rather than the CRC-16 of the
                   1549: RECIPIENT (name) field. This is the case specifically with the local e-mail
                   1550: message base on a Synchronet BBS.
                   1551: 
                   1552: Name     : RECIPIENTPOS
                   1553: Value    : 35h
                   1554: Data     : ASCII
                   1555: Multiple : Yes, order significant
                   1556: Required : No
                   1557: Default  : Previous RECIPIENTPOS if exists
                   1558: Summary  : Position of agent to receive this message
                   1559: 
                   1560: Name     : RECIPIENTORG
                   1561: Value    : 36h
                   1562: Data     : ASCII
                   1563: Multiple : Yes, order significant
                   1564: Required : No
                   1565: Default  : Previous RECIPIENTORG if exists
                   1566: Summary  : Type of agent to receive this message
                   1567: 
                   1568: Name     : FORWARDTO
                   1569: Value    : 40h
                   1570: Data     : ASCII
                   1571: Multiple : Yes, order significant
                   1572: Required : No
                   1573: Summary  : Name of agent this message is to be forwarded to
                   1574: 
                   1575: Name     : FORWARDTOAGENT
                   1576: Value    : 41h
                   1577: Data     : ushort
                   1578: Multiple : Yes, order significant
                   1579: Required : No
                   1580: Default  : RECIPIENTAGENT or previous FORWARDTOAGENT if exists
                   1581: Summary  : Type of agent this message is to be forwarded to
                   1582: 
                   1583: Name     : FORWARDTONETTYPE
                   1584: Value    : 42h
                   1585: Data     : ushort
                   1586: Multiple : Yes, order significant
                   1587: Required : No
                   1588: Default  : RECIPIENTNETTYPE or previous FORWARDTONETTYPE if exists
                   1589: Summary  : Type of network this message is to be forwarded to
                   1590: 
                   1591: Name     : FORWARDTONETADDR
                   1592: Value    : 43h
                   1593: Data     : undef
                   1594: Multiple : Yes, order significant
                   1595: Required : No
                   1596: Default  : RECIPIENTNETADDR or previous FORWARDTONETADDR if exists
                   1597: Summary  : Network address this message is to be forwarded to
                   1598: 
                   1599: Name     : FORWARDTOEXT
                   1600: Value    : 44h
                   1601: Data     : ASCII
                   1602: Multiple : Yes, order significant
                   1603: Required : No
                   1604: Default  : RECIPIENTEXT or previous FORWARDTOEXT if exists
                   1605: Summary  : Extension of agent this message is to be forwarded to
                   1606: 
                   1607: Name     : FORWARDTOPOS
                   1608: Value    : 45h
                   1609: Data     : ASCII
                   1610: Multiple : Yes, order significant
                   1611: Required : No
                   1612: Default  : RECIPIENTPOS or previous FORWARDTOPOS if exists
                   1613: Summary  : Position of agent this message is to be forwarded to
                   1614: 
                   1615: Name     : FORWARDTOORG
                   1616: Value    : 46h
                   1617: Data     : ASCII
                   1618: Multiple : Yes, order significant
                   1619: Required : No
                   1620: Default  : RECIPIENTORG or previous FORWARDTOORG if exists
                   1621: Summary  : Organization of agent this message is to be forwarded to
                   1622: 
                   1623: Name     : FORWARDED
                   1624: Value    : 48h
                   1625: Data     : when_t
                   1626: Multiple : Yes, order significant
                   1627: Required : Yes, if forwarded
                   1628: Summary  : Date/Time this message was forwarded to another agent
                   1629: 
                   1630: Name     : RECEIVEDBY
                   1631: Value    : 50h
                   1632: Data     : ASCII
                   1633: Multiple : Yes, order significant
                   1634: Required : Yes, if receiving agent is other than RECIPIENT
                   1635: Summary  : Name of agent that received this message
                   1636: 
                   1637: Name     : RECEIVEDBYAGENT
                   1638: Value    : 51h
                   1639: Data     : ushort
                   1640: Multiple : Yes, order significant
                   1641: Required : No
                   1642: Default  : RECIPIENTAGENT or previous RECEIVEDBYAGENT if exists
                   1643: Summary  : Type of agent that received this message
                   1644: 
                   1645: Name     : RECEIVEDBYNETTYPE
                   1646: Value    : 52h
                   1647: Data     : ushort
                   1648: Multiple : Yes, order significant
                   1649: Required : No
                   1650: Default  : RECIPIENTNETTYPE or previous RECEIVEDBYNETTYPE if exists
                   1651: Summary  : Type of network that received this message
                   1652: 
                   1653: Name     : RECEIVEDBYNETADDR
                   1654: Value    : 53h
                   1655: Data     : undef
                   1656: Multiple : Yes, order significant
                   1657: Required : No
                   1658: Default  : RECIPIENTNETADDR or previous RECEIVEDBYNETADDR if exists
                   1659: Summary  : Network address that received this message
                   1660: 
                   1661: Name     : RECEIVEDBYEXT
                   1662: Value    : 54h
                   1663: Data     : ASCII
                   1664: Multiple : Yes, order significant
                   1665: Required : No
                   1666: Default  : RECIPIENTEXT or previous RECEIVEDBYEXT if exists
                   1667: Summary  : Extension of agent that received this message
                   1668: 
                   1669: Name     : RECEIVEDBYPOS
                   1670: Value    : 55h
                   1671: Data     : ASCII
                   1672: Multiple : Yes, order significant
                   1673: Required : No
                   1674: Default  : RECIPIENTPOS or previous RECEIVEDBYPOS if exists
                   1675: Summary  : Position of agent that received this message
                   1676: 
                   1677: Name     : RECEIVEDBYORG
                   1678: Value    : 56h
                   1679: Data     : ASCII
                   1680: Multiple : Yes, order significant
                   1681: Required : No
                   1682: Default  : RECIPIENTORG or previous RECEIVEDBYORG if exists
                   1683: Summary  : Organization of agent that received this message
                   1684: 
                   1685: Name     : RECEIVED
                   1686: Value    : 58h
                   1687: Data     : when_t
                   1688: Multiple : Yes, order significant
                   1689: Required : Yes, if received
                   1690: Default  : NULL
                   1691: Summary  : Date/Time this message was received
                   1692: 
                   1693: Name     : SUBJECT
                   1694: Value    : 60h
                   1695: Data     : ASCII
                   1696: Multiple : No
                   1697: Required : Yes, but may be blank (0 length or nulstr)
                   1698: Summary  : Subject/title of message
                   1699: 
                   1700: Name     : SUMMARY
                   1701: Value    : 61h
                   1702: Data     : ASCII
                   1703: Multiple : No
                   1704: Required : No
                   1705: Summary  : Summary of message contents, created by AUTHOR
                   1706: 
                   1707: Name     : COMMENT
                   1708: Value    : 62h
                   1709: Data     : ASCII
                   1710: Multiple : Yes
                   1711: Required : No
                   1712: Summary  : Comment about this message, created by SENDER
                   1713: 
                   1714: This field is useful for adding notes to a message when forwarding to a new
                   1715: recipient.
                   1716: 
                   1717: Name     : CARBONCOPY
                   1718: Value    : 63h
                   1719: Data     : ASCII
                   1720: Multiple : Yes
                   1721: Required : No
                   1722: Summary  : List of agents this message was also sent to
                   1723: 
                   1724: This field is optional and only for the use of notifying the recipient of who
                   1725: else received the message.
                   1726: 
                   1727: Name     : GROUP
                   1728: Value    : 64h
                   1729: Data     : ASCII
                   1730: Multiple : Yes
                   1731: Required : No
                   1732: Summary  : Name of group of users to receive message on recipient system
                   1733: 
                   1734: This field is used when sending to a group name across a network, where the
                   1735: group can be expanded into multiple header records for each agent on the
                   1736: destination system.
                   1737: 
                   1738: Name     : EXPIRATION
                   1739: Value    : 65h
                   1740: Data     : when_t
                   1741: Multiple : No
                   1742: Required : No
                   1743: Summary  : Date/Time that this message will expire
                   1744: 
                   1745: Name     : PRIORITY
                   1746: Value    : 66h
                   1747: Data     : ulong
                   1748: Multiple : No
                   1749: Required : No
                   1750: Default  : 0
                   1751: Summary  : Message priority (0 is lowest, FFFFFFFFh is highest)
                   1752: 
                   1753: Name     : FILEATTACH
                   1754: Value    : 70h
                   1755: Data     : ASCII
                   1756: Multiple : Yes
                   1757: Required : No
                   1758: Summary  : Name/file specification of attached file(s)
                   1759: 
                   1760: Name of attached file(s). Wildcards allowed. MSG_FILEATTACH attribute must be
                   1761: set. If the MSG_FILEATTACH attribute is set but this field is not included,
                   1762: the SUBJECT field is assumed to be the filename(s).
                   1763: 
                   1764: Name     : DESTFILE
                   1765: Value    : 71h
                   1766: Data     : ASCII
                   1767: Multiple : Yes, order significant
                   1768: Required : No
                   1769: Summary  : Destination name for attached file(s)
                   1770: 
                   1771: Wildcards allowed. FILEATTACH field must also be included.
                   1772: 
                   1773: Name     : FILEATTACHLIST
                   1774: Value    : 72h
                   1775: Data     : ASCII
                   1776: Multiple : Yes
                   1777: Required : No
                   1778: Summary  : Name of ASCII list of attached filenames
                   1779: 
                   1780: Wildcards not allowed in ASCII list filename. Wildcards allowed in ASCII list.
                   1781: MSG_FILEATTACH attribute must be set.
                   1782: 
                   1783: Name     : DESTFILELIST
                   1784: Value    : 73h
                   1785: Data     : ASCII
                   1786: Multiple : Yes, order significant
                   1787: Required : No
                   1788: Summary  : Name of ASCII list of destination filenames
                   1789: 
                   1790: Wildcards not allowed in ASCII list filename. Wildcards allowed in ASCII list.
                   1791: 
                   1792: Name     : FILEREQUEST
                   1793: Value    : 74h
                   1794: Data     : ASCII
                   1795: Multiple : Yes
                   1796: Required : No
                   1797: Summary  : Name of requested file
                   1798: 
                   1799: Wildcards allowed. MSG_FILEREQUEST attribute must be set
                   1800: 
                   1801: Name     : FILEPASSWORD
                   1802: Value    : 75h
                   1803: Data     : ASCII
                   1804: Multiple : Yes, order significant
                   1805: Required : No
                   1806: Summary  : Password for FILEREQUEST
                   1807: 
                   1808: Name     : FILEREQUESTLIST
                   1809: Value    : 76h
                   1810: Data     : ASCII
                   1811: Multiple : Yes
                   1812: Required : No
                   1813: Summary  : Name of ASCII list of filenames to request
                   1814: 
                   1815: Wildcards allowed.
                   1816: 
                   1817: Name     : FILEPASSWORDLIST
                   1818: Value    : 77h
                   1819: Data     : ASCII
                   1820: Multiple : Yes, order significant
                   1821: Required : No
                   1822: Summary  : Name of ASCII list of passwords for FILEREQUESTLIST
                   1823: 
                   1824: Name     : IMAGEATTACH
                   1825: Value    : 80h
                   1826: Data     : mattach_t
                   1827: Multiple : Yes, order significant
                   1828: Required : No
                   1829: Summary  : Type and filename of attached image file for display
                   1830: 
                   1831: MSG_FILEATTACH attribute must be set. See Image Types for valid
                   1832: mattach_t.type values.
                   1833: 
                   1834: Name     : ANIMATTACH
                   1835: Value    : 81h
                   1836: Data     : mattach_t
                   1837: Multiple : Yes, order significant
                   1838: Required : No
                   1839: Summary  : Type and filename of attached graphical animation file for display
                   1840: 
                   1841: MSG_FILEATTACH attribute must be set. See Animation Types for valid
                   1842: mattach_t.type values.
                   1843: 
                   1844: Name     : FONTATTACH
                   1845: Value    : 82h
                   1846: Data     : mattach_t
                   1847: Multiple : Yes, order significant
                   1848: Required : No
                   1849: Summary  : Type and filename of attached font definition file
                   1850: 
                   1851: MSG_FILEATTACH attribute must be set. See Font Types for valid mattach_t.type
                   1852: values.
                   1853: 
                   1854: Name     : SOUNDATTACH
                   1855: Value    : 83h
                   1856: Data     : mattach_t
                   1857: Multiple : Yes, order significant
                   1858: Required : No
                   1859: Summary  : Type and filename of attached sound file for playback
                   1860: 
                   1861: MSG_FILEATTACH attribute must be set. See Sound Types for valid mattach_t.type
                   1862: values.
                   1863: 
                   1864: Name     : PRESENTATTACH
                   1865: Value    : 84h
                   1866: Data     : mattach_t
                   1867: Multiple : Yes, order significant
                   1868: Required : No
                   1869: Summary  : Type and filename of attached presentation definition file
                   1870: 
                   1871: MSG_FILEATTACH attribute must be set. See Present Types for valid
                   1872: mattach_t.type values.
                   1873: 
                   1874: Name     : VIDEOATTACH
                   1875: Value    : 85h
                   1876: Data    : vattach_t
                   1877: Multiple : Yes, order significant
                   1878: Required : No
                   1879: Summary  : Type and filename of attached interleaved video/sound file
                   1880: 
                   1881: MSG_FILEATTACH attribute must be set. See Video Types for valid
                   1882: vattach_t.type values and Video Compression Types for valid vattach_t.comp
                   1883: values.
                   1884: 
                   1885: Name     : APPDATAATTACH
                   1886: Value    : 86h
                   1887: Data     : mattach_t
                   1888: Multiple : Yes, order significant
                   1889: Required : No
                   1890: Summary  : Name of attached application data file for process/display
                   1891: 
                   1892: MSG_FILEATTACH attribute must be set. See Application Data Types for valid
                   1893: mattach_t.type values.
                   1894: 
                   1895: Name     : IMAGETRIGGER
                   1896: Value    : 90h
                   1897: Data     : typestr_t
                   1898: Multiple : Yes, order significant
                   1899: Required : No
                   1900: Summary  : Type and filename of image file to trigger for display
                   1901: 
                   1902: See Image Types for valid typestr_t.type values.
                   1903: 
                   1904: Name     : ANIMTRIGGER
                   1905: Value    : 91h
                   1906: Data     : typestr_t
                   1907: Multiple : Yes, order significant
                   1908: Required : No
                   1909: Summary  : Type and filename of animation file to trigger for display
                   1910: 
                   1911: See Animation Types for valid typestr_t.type values.
                   1912: 
                   1913: Name     : FONTTRIGGER
                   1914: Value    : 92h
                   1915: Data     : typestr_t
                   1916: Multiple : Yes, order significant
                   1917: Required : No
                   1918: Summary  : Type and filename of font definition file to trigger
                   1919: 
                   1920: See Font Types for valid typestr_t.type values.
                   1921: 
                   1922: Name     : SOUNDTRIGGER
                   1923: Value    : 93h
                   1924: Data     : typestr_t
                   1925: Multiple : Yes, order significant
                   1926: Required : No
                   1927: Summary  : Type and filename of sound file to trigger for playback
                   1928: 
                   1929: See Sound Types for valid typestr_t.type values.
                   1930: 
                   1931: Name     : PRESENTTRIGGER
                   1932: Value    : 94h
                   1933: Data     : typestr_t
                   1934: Multiple : Yes, order significant
                   1935: Required : No
                   1936: Summary  : Type and filename of presentation definition file to trigger
                   1937: 
                   1938: See Present Types for valid typestr_t.type values.
                   1939: 
                   1940: Name     : VIDEOTRIGGER
                   1941: Value    : 95h
                   1942: Data     : typestr_t
                   1943: Multiple : Yes, order significant
                   1944: Required : No
                   1945: Summary  : Type and filename of interleaved video/sound file to trigger
                   1946: 
                   1947: See Video Types for valid typestr_t.type values.
                   1948: 
                   1949: Name     : APPDATATRIGGER
                   1950: Value    : 96h
                   1951: Data     : typestr_t
                   1952: Multiple : Yes, order significant
                   1953: Required : No
                   1954: Summary  : Type and filename of application data file to trigger
                   1955: 
                   1956: See Application Data Types for valid typestr_t.type values.
                   1957: 
                   1958: Name     : FIDOCTRL
                   1959: Value    : A0h
                   1960: Data     : ASCII
                   1961: Multiple : Yes, order significant
                   1962: Required : No
                   1963: Format   : keyword ":" [" "] appdata
                   1964: Summary  : FTS/FSC-compliant control information line
                   1965: 
                   1966: Any FidoNet FTS/FSC-compliant control information ("kludge") line that
                   1967: does not have an equivalent representation here. All data not unique to the
                   1968: actual control line, including leading and trailing white space, Ctrl-A (01h)
                   1969: character and terminating CR must be ommited. Defined in FTS-0001.
                   1970: 
                   1971: Name     : FIDOAREA
                   1972: Value    : A1h
                   1973: Data     : ASCII
                   1974: Multiple : No
                   1975: Required : No
                   1976: Summary  : FTN EchoMail conference name.
                   1977: 
                   1978: Defined in FTS-0004.
                   1979: 
                   1980: Name     : FIDOSEENBY
                   1981: Value    : A2h
                   1982: Data     : ASCII
                   1983: Multiple : Yes, order significant
                   1984: Required : No
                   1985: Format   : net"/"node [" "[net"/"]node] [...]
                   1986: Summary  : Used to store two-dimensional (net/node) SEEN-BY information
                   1987: 
                   1988: Often used in FTN EchoMail environments. Only the actual SEEN-BY data is stored
                   1989: and SEEN-BY: is stripped along with any leading and trailing white space
                   1990: characters. Defined in FTS-0004.
                   1991: 
                   1992: Name     : FIDOPATH
                   1993: Value    : A3h
                   1994: Data     : ASCII
                   1995: Multiple : Yes, order significant
                   1996: Required : No
                   1997: Format   : net"/"node [" "[net"/"]node] [...]
                   1998: Summary  : Used to store two-dimensional (net/node)
                   1999: 
                   2000: Defined in FTS-0004. ^aPATH: is stripped along with any leading and trailing
                   2001: white space characters.
                   2002: 
                   2003: Name     : FIDOMSGID
                   2004: Value    : A4h
                   2005: Data     : ASCII
                   2006: Multiple : No
                   2007: Required : No
                   2008: Format   : origaddr " " serialno
                   2009: Summary  : MSGID field as specified in FTS-0009.
                   2010: 
                   2011: Name     : FIDOREPLYID
                   2012: Value    : A5h
                   2013: Data     : ASCII
                   2014: Multiple : No
                   2015: Required : No
                   2016: Format   : origaddr " " serialno
                   2017: Summary  : REPLY field as specified in FTS-0009.
                   2018: 
                   2019: Name     : FIDOPID
                   2020: Value    : A6h
                   2021: Data     : ASCII
                   2022: Multiple : No
                   2023: Required : No
                   2024: Format   : pID " " version [" "serialno]
                   2025: Summary  : Indentification string of program that created this message
                   2026: 
                   2027: Defined FSC-0046. "^aPID:" and any white space is not included.
                   2028: 
                   2029: Name     : FIDOFLAGS
                   2030: Value    : A7h
                   2031: Data     : ASCII
                   2032: Multiple : Yes
                   2033: Required : No
                   2034: Summary  : Used to store the FTN FLAGS kludge information
                   2035: 
                   2036: Note that all FLAG options that have binary representation in the message
                   2037: header must be removed from the FLAGS string prior to storing it. Only the
                   2038: actual flags option string is stored and ^aFLAGS is stripped along with any
                   2039: leading and trailing white space characters. Defined in FSC-0053.
                   2040: 
                   2041: Name     : RFC822HEADER
                   2042: Value    : B0h
                   2043: Data     : ASCII
                   2044: Multiple : Yes, order significant
                   2045: Required : No
                   2046: Format   : field-name ":" [field-body] [CRLF]
                   2047: Summary  : Undefined RFC-822 header field
                   2048: 
                   2049: Internet Message storage format, that does not have an equivalent
                   2050: representation here. Folded header fields are allowed. Terminating CRLF may be
                   2051: ommited.
                   2052: 
                   2053: Name     : RFC822MSGID
                   2054: Value    : B1h
                   2055: Data     : ASCII
                   2056: Multiple : No
                   2057: Required : No
                   2058: Format   : "<" addr-spec ">"
                   2059: Summary  : Message-ID field as specified in RFC-822.
                   2060: 
                   2061: Name     : RFC822REPLYID
                   2062: Value    : B2h
                   2063: Data     : ASCII
                   2064: Multiple : No
                   2065: Required : No
                   2066: Format   : "<" addr-spec ">"
                   2067: Summary  : In-Reply-To field as specified in RFC-822.
                   2068: 
                   2069: Name     : UNKNOWN
                   2070: Value    : F0h
                   2071: Data     : undef
                   2072: Multiple : Yes
                   2073: Required : No
                   2074: Summary  : Undefined header field of undefined type
                   2075: 
                   2076: This field is useful for retaining binary header fields (that do not have an
                   2077: equivalent representation here) between message storage formats.
                   2078: 
                   2079: Name     : UNKNOWNASCII
                   2080: Value    : F1h
                   2081: Data     : ASCII
                   2082: Multiple : Yes
                   2083: Required : No
                   2084: Summary  : Undefined header field of type ASCII
                   2085: 
                   2086: This field is useful for retaining ASCII header fields (that do not have an
                   2087: equivalent representation here) between message storage formats.
                   2088: 
                   2089: Name     : UNUSED
                   2090: Value    : FFh
                   2091: Data     : undef
                   2092: Multiple : Yes
                   2093: Required : No
                   2094: Summary  : Unused (deleted) header field
                   2095: 
                   2096: The data contained in this header field is of an unknown type and should not be
                   2097: processed.
                   2098: 
                   2099: 
                   2100: Note:
                   2101: ----
                   2102: Specifically, not defined are the values F000h through FFFFh. These values
                   2103: are to be used for user or system defined header fields. Digital Dynamics
                   2104: requests that any developers or organizations that wish to have additional
                   2105: header fields added to this specification notify Digital Dynamics through any
                   2106: of the contact methods listed at the beginning of this document.
                   2107: 
                   2108: Data Field Types:
                   2109: ================
                   2110: &&Data Field Types
                   2111: $$DFIELD_T
                   2112: 
                   2113: These are the defined valid values for dfield_t.type:
                   2114: 
                   2115: 
                   2116: Val Name                Data        Description
                   2117: --- ----                ----        -----------
                   2118: 00h TEXT_BODY           mtext_t     Displayable text (body of message).
                   2119:                                     Included in duplicate message checking.
                   2120:                                                                        All terminating white space and control
                   2121:                                                                        characters are to be truncated from data
                   2122:                                                                        (except when multiple contiguous CRLFs
                   2123:                                                                        terminate the text, only the last CRLF
                   2124:                                                                        is removed).
                   2125: 
                   2126: 01h TEXT_SOUL           mtext_t     Non-displayed text.
                   2127:                                     Not normally displayed. Not necessarily
                   2128:                                     displayable.
                   2129:                                     Included in duplicate message checking.
                   2130: 
                   2131: 02h TEXT_TAIL                  mtext_t         Displayable text (tag/tear/origin lines,
                   2132:                                                                        etc).
                   2133:                                     Not included in duplicate message checking.
                   2134:                                                                        All terminating white space and control
                   2135:                                     characters are to be truncated from data.
                   2136: 
                   2137: 03h TEXT_WING           mtext_t     Non-displayed text.
                   2138:                                     Not normally displayed. Not necessarily
                   2139:                                     displayable.
                   2140:                                     Not included in duplicate message checking.
                   2141: 
                   2142: 10h FTEXT_BODY                 ftext_t         Formatted equivalent of TEXT_BODY to be
                   2143:                                                                        displayed in place of TEXT_BODY if format
                   2144:                                                                        is supported. See Image Types for valid
                   2145:                                                                        values of ftext_t.type.
                   2146: 
                   2147: 12h FTEXT_TAIL                 ftext_t         Formatted equivalent of TEXT_TAIL to be
                   2148:                                                                        displayed in place of TEXT_TAIL if format
                   2149:                                                                        is supported. See Image Types for valid
                   2150:                                                                        values of ftext_t.type.
                   2151: 
                   2152: 20h IMAGEEMBED          membed_t    Type and data of embedded raster image file
                   2153:                                     for display.
                   2154:                                                                        See Image Types for valid membed.type
                   2155:                                                                        values.
                   2156: 
                   2157: 21h ANIMEMBED                  membed_t        Type and data of embedded graphical
                   2158:                                                                        animation file for display.
                   2159:                                                                        See Animation Types for valid membed.type
                   2160:                                     values.
                   2161: 
                   2162: 22h FONTEMBED                  membed_t        Type and data of embedded font definition
                   2163:                                                                        file. See Font Types for valid
                   2164:                                                                        membed_t.type values.
                   2165: 
                   2166: 23h SOUNDEMBED          membed_t    Type and data of embedded sound file for
                   2167:                                     playback.
                   2168:                                                                        See Sound Types for valid membed_t.type
                   2169:                                                                        values.
                   2170: 
                   2171: 24h PRESENTEMBED        membed_t    Type and data of embedded presentation
                   2172:                                     definition file.
                   2173:                                     See Present Types for valid membed_t.type
                   2174:                                     values.
                   2175: 
                   2176: 25h VIDEOEMBED                 vembed_t        Type and data of embedded video/sound file
                   2177:                                     for playback.
                   2178:                                                                        See Video Types for valid vembed_t.type
                   2179:                                     values.
                   2180:                                                                        See Video Compression Types for valid
                   2181:                                                                        vembed_t.comp values.
                   2182: 
                   2183: 26h APPDATAEMBED               membed_t        Type and data of embedded application data
                   2184:                                                                        file for process/display.
                   2185:                                     See Application Data Types for valid
                   2186:                                     membed_t.type values.
                   2187: 
                   2188: FFh UNUSED              undef       Space allocated for future update/expansion
                   2189: 
                   2190: 
                   2191: Specifically, not defined are the values F000h through FFFFh. These values
                   2192: are to be used for user or system defined data fields. Digital Dynamics
                   2193: requests that any developers or organizations that wish to have additional
                   2194: data fields added to this specification notify Digital Dynamics through any
                   2195: of the contact methods listed at the beginning of this document.
                   2196: 
                   2197: 
                   2198: Message Attributes:
                   2199: ------------------
                   2200: &&Message Attributes
                   2201: $$ATTRBITS
                   2202: 
                   2203: These are the bit values for idxrec_t.attr and msghdr_t.attr:
                   2204: 
                   2205: MSG_PRIVATE         (1<<0)  // Private
                   2206: MSG_READ            (1<<1)  // Read by addressee
                   2207: MSG_PERMANENT       (1<<2)  // Permanent
                   2208: MSG_LOCKED          (1<<3)  // Msg is locked, no editing possible
                   2209: MSG_DELETE          (1<<4)  // Msg is marked for deletion
                   2210: MSG_ANONYMOUS       (1<<5)  // Anonymous author
                   2211: MSG_KILLREAD        (1<<6)  // Delete message after it has been read
                   2212: MSG_MODERATED          (1<<7)  // This message must be validated before export
                   2213: MSG_VALIDATED       (1<<8)  // This message has been validated by a moderator
                   2214: 
                   2215: 
                   2216: Auxillary Attributes:
                   2217: --------------------
                   2218: These are the bit values for msghdr_t.auxattr:
                   2219: 
                   2220: MSG_FILEREQUEST     (1<<0)  // File request
                   2221: MSG_FILEATTACH      (1<<1)  // File(s) attached to Msg
                   2222: MSG_TRUNCFILE       (1<<2)  // Truncate file(s) when sent
                   2223: MSG_KILLFILE        (1<<3)  // Delete file(s) when sent
                   2224: MSG_RECEIPTREQ      (1<<4)  // Return receipt requested
                   2225: MSG_CONFIRMREQ      (1<<5)  // Confirmation receipt requested
                   2226: MSG_NODISP          (1<<6)  // Msg may not be displayed to user
                   2227: 
                   2228: 
                   2229: Network Attributes:
                   2230: ------------------
                   2231: These are the bit values for msghdr_t.netattr:
                   2232: 
                   2233: MSG_LOCAL           (1<<0)  // Msg created locally
                   2234: MSG_INTRANSIT       (1<<1)  // Msg is in-transit
                   2235: MSG_SENT            (1<<2)  // Sent to remote
                   2236: MSG_KILLSENT        (1<<3)  // Kill when sent
                   2237: MSG_ARCHIVESENT     (1<<4)  // Archive when sent
                   2238: MSG_HOLD            (1<<5)  // Hold for pick-up
                   2239: MSG_CRASH           (1<<6)  // Crash
                   2240: MSG_IMMEDIATE       (1<<7)  // Send Msg now, ignore restrictions
                   2241: MSG_DIRECT          (1<<8)  // Send directly to destination
                   2242: MSG_GATE            (1<<9)  // Send via gateway
                   2243: MSG_ORPHAN          (1<<10) // Unknown destination
                   2244: MSG_FPU             (1<<11) // Force pickup
                   2245: MSG_TYPELOCAL       (1<<12) // Msg is for local use only
                   2246: MSG_TYPEECHO        (1<<13) // Msg is for conference distribution
                   2247: MSG_TYPENET         (1<<14) // Msg is direct network mail
                   2248: 
                   2249: Translation Types:
                   2250: -----------------
                   2251: &&Translation Types
                   2252: $$XLATTYPE
                   2253: 
                   2254: Definition for values of *.xlat[x]:
                   2255: 
                   2256: XLAT_NONE           0       // No translation/End of translation list
                   2257: XLAT_LF2CRLF        1       // Expand sole LF to CRLF
                   2258: XLAT_ESCAPED        2       // 7-bit ASCII escaping for ctrl and 8-bit data
                   2259: XLAT_HUFFMAN        3       // Static and adaptive Huffman coding compression
                   2260: XLAT_LZW                       4               // LZW (Lempel-Ziv-Welch) encoding for compression
                   2261:                                                        // Terry Welch, IEEE Computer Vol 17, No 6
                   2262:                                                        // June 1984, pp 8-19
                   2263: XLAT_LZC                       5               // LZC (modified LZW) encoding for compression
                   2264:                                                        // Unix compress program
                   2265: XLAT_RLE            6       // Run length encoding compression
                   2266: XLAT_IMPLODE           7               // Implode compression (PKZIP v1.x)
                   2267: XLAT_SHRINK            8               // Shrink compression (PKZIP v1.x)
                   2268: XLAT_LZH                       9               // LZH dynamic Huffman coding
                   2269:                                                        // Haruyasu Yoshizaki, LHarc
                   2270:                                                        // November, 1988
                   2271: 
                   2272: Agent Types:
                   2273: -----------
                   2274: &&Agent Types
                   2275: $$AGENTTYP
                   2276: 
                   2277: AGENT_PERSON           0               // To or from person
                   2278: AGENT_PROCESS       1       // Unknown process, identified by agent name
                   2279: 
                   2280: Agent types E000h through EFFFh are reserved for Synchronet process types
                   2281: (defined specifically by Digital Dynamics).
                   2282: 
                   2283: Note:
                   2284: ----
                   2285: Specifically not defined are agent types F000h through FFFFh. These values
                   2286: are to be used for user or system defined agent types. Digital Dynamics
                   2287: requests that any developers or organizations that wish to have additional
                   2288: agent types added to this specification notify Digital Dynamics through any
                   2289: of the contact methods listed at the beginning of this document.
                   2290: 
                   2291: Network Types:
                   2292: -------------
                   2293: &&Network Types
                   2294: $$NETWORKS
                   2295: 
                   2296:                                                        // Net Type                     Address Format
                   2297:                                                        // -----------------------------------
                   2298: NET_NONE                       0               // Locally created              none
                   2299: NET_UNKNOWN            1               // Unknown                              undef
                   2300: NET_FIDO                       2               // FTN network                  fidoaddr_t
                   2301: NET_POSTLINK           3               // PostLink network     none
                   2302: NET_QWK                        4               // QWK based network    ASCII
                   2303: NET_INTERNET           5               // The Internet                 ASCII
                   2304: NET_WWIV                       6               // WWIV based network   ulong
                   2305: NET_MHS                        7               // MHS network                  ASCII
                   2306: 
                   2307: 
                   2308: Media Types:
                   2309: ===========
                   2310: &&Media Types
                   2311: $$MEDIATYP
                   2312: 
                   2313: Image Types:
                   2314: -----------
                   2315: 
                   2316: IMAGE_UNKNOWN       0x00    // Use image signature header to determine format
                   2317: IMAGE_ASC           0x01    // ASCII text/IBM extended ASCII graphics
                   2318: IMAGE_ANS           0x02    // ANSI X3.64 terminal escape sequences
                   2319: IMAGE_AVT           0x03    // AVATAR terminal escape sequences
                   2320: IMAGE_LVI           0x04    // LVI terminal escape sequences
                   2321: IMAGE_GIF           0x05    // Compuserve Graphics Interchange Format (GIF)
                   2322: IMAGE_TIF           0x06    // Tagged Image Format (AKA TIFF)
                   2323: IMAGE_JPG           0x07    // Joint Photographers Electronics Group (JPEG)
                   2324: IMAGE_T16           0x08    // TrueVision 16-bit bitmap (TGA)
                   2325: IMAGE_T24           0x09    // TrueVision 24-bit bitmap (TGA)
                   2326: IMAGE_T32           0x0a    // TrueVision 32-bit bitmpa (TGA)
                   2327: IMAGE_PCX           0x0b    // ZSoft PaintBrush graphics
                   2328: IMAGE_BMP           0x0c    // Windows bitmap
                   2329: IMAGE_RLE           0x0d    // Windows bitmap (compressed)
                   2330: IMAGE_DIB           0x0e    // Display independant bitmap
                   2331: IMAGE_PCD           0x0f    // Kodak PhotoCD
                   2332: IMAGE_G3F           0x10    // Group 3 FAX
                   2333: IMAGE_EPS           0x11    // Ecapsulated PostScript
                   2334: IMAGE_RTF           0x12    // Rich text format
                   2335: IMAGE_RIP           0x13    // Remote Imaging Protocol Script (RIPscrip)
                   2336: IMAGE_NAP           0x14    // NAPLPS
                   2337: IMAGE_CDR           0x15    // Corel Draw!
                   2338: IMAGE_CGM           0x16    // Computer graphics metafile
                   2339: IMAGE_WMF           0x17    // Windows metafile
                   2340: IMAGE_DFX           0x18    // Autodesk AutoCAD
                   2341: IMAGE_IFF                      0x19    // Amiga Interchange File Format
                   2342: IMAGE_HTM                      0x20    // HyperText Markup Language (MTML) Document
                   2343: IMAGE_OS2                      0x21    // OS/2 bitmap (BMP)
                   2344: 
                   2345: Animation Types:
                   2346: ---------------
                   2347: 
                   2348: ANIM_UNKNOWN        0       // Use file signature header to determine format
                   2349: ANIM_FLI            1       // Autodesk animator
                   2350: ANIM_FLC            2       // Autodesk
                   2351: ANIM_GL             3       // Grasprt
                   2352: ANIM_IFF                       4               // Amiga Interchange File Format
                   2353: 
                   2354: 
                   2355: Video Types:
                   2356: -----------
                   2357: 
                   2358: VIDEO_UNKNOWN       0       // Use file signature header to determine format
                   2359: VIDEO_QTIME         1       // Apple Quick-time
                   2360: VIDEO_FQTIME        2       // Apple Flattened Quick-time
                   2361: VIDEO_AVI           3       // Windows Auto/Video Interleave
                   2362: VIDEO_ULT           4       // OS/2 Ultimotion
                   2363: 
                   2364: Video Compression Types:
                   2365: -----------------------
                   2366: 
                   2367: VCOMP_UNKNOWN          0               // Use file signature header to determine codec
                   2368: VCOMP_RLE                      1               // Apple animation
                   2369: VCOMP_SMC                      2               // Apple graphics
                   2370: VCOMP_RPZA                     3               // Apple video
                   2371: VCOMP_KLIC                     4               // Captain crunch
                   2372: VCOMP_CVID                     5               // CinePak
                   2373: VCOMP_RT21                     6               // Intel indeo R2
                   2374: VCOMP_IV31                     7               // Intel indeo R3
                   2375: VCOMP_YVU9                     8               // Intel YVU9
                   2376: VCOMP_JPEG                     9               // JPEG
                   2377: VCOMP_MRLE                     10              // Microsoft RLE
                   2378: VCOMP_MSVC                     11              // Microsoft video 1
                   2379: 
                   2380: 
                   2381: Font Types:
                   2382: ----------
                   2383: 
                   2384: FONT_UNKNOWN        0       // Use file signature header to determine format
                   2385: FONT_TTF            1       // Windows TrueType
                   2386: FONT_PFB            2       // PostScript Type 1 Font Binary
                   2387: FONT_PFM            3       // PostScript Type 1 Font Metric
                   2388: FONT_AMIGA                     4               // Amiga Bitmapped
                   2389: FONT_AGFA                      5               // CompuGraphic Fonts
                   2390: 
                   2391: 
                   2392: Sound Types:
                   2393: -----------
                   2394: 
                   2395: SOUND_UNKNOWN       0       // Use file signature header to determine format
                   2396: SOUND_MOD           1       // MOD format
                   2397: SOUND_VOC           2       // Sound Blaster VOC format
                   2398: SOUND_WAV                      3               // Windows 3.1 WAV RIFF format
                   2399: SOUND_MID           4       // MIDI format
                   2400: SOUND_GMID          5       // General MIDI format (standardized patches)
                   2401: SOUND_SMP                      6               // Turtle Beach SampleVision format
                   2402: SOUND_SF                       7               // IRCAM format
                   2403: SOUND_AU                       8               // Sun Microsystems AU format
                   2404: SOUND_IFF                      9               // Amiga Interchange File Format
                   2405: 
                   2406: Application Data Types:
                   2407: ----------------------
                   2408: 
                   2409: APPDATA_UNKNOWN     0       // Use file signature header to determine format
                   2410: APPDATA_WORDPERFECT 1       // WordPerfect Document
                   2411: APPDATA_WKS         2       // Lotus 123 Worksheet (?)
                   2412: APPDATA_WK1         3       // Lotus 123 Worksheet rev 1
                   2413: APPDATA_WK2         4       // Lotus 123 Worksheet rev 2
                   2414: APPDATA_WK3         5       // Lotus 123 Worksheet rev 3
                   2415: APPDATA_DBF         6       // dBase III data file
                   2416: APPDATA_PDX         7       // Paradox data file
                   2417: APPDATA_EXCEL          8               // Excel data file
                   2418: APPDATA_QUATRO         9               // Borland Quatro Pro file
                   2419: APPDATA_WORD           10              // Microsoft Word
                   2420: 
                   2421: Message Storage Pseudo Code
                   2422: ===========================
                   2423: &&Message Storage Pseudo Code
                   2424: $$STORPCOD
                   2425: 
                   2426: The following is a "C like" pseudo code listing example of adding a message to
                   2427: an SMB message base. SMBLIB contains C functions to do most of the following
                   2428: operations. We are supplying this pseudo code as a general definition of the
                   2429: order of required operations in writing to the message base. Many details have
                   2430: been left out to simplify the code and to demonstrate only the basic
                   2431: principles.
                   2432: 
                   2433: shd = open ( MSGBASE.SHD , READ/WRITE/DENY_NONE )
                   2434: sdt = open ( MSGBASE.SDT , READ/WRITE/DENY_NONE )
                   2435: sid = open ( MSGBASE.SDT , READ/WRITE/DENY_NONE )
                   2436: 
                   2437: lock ( shd , smbhdr )
                   2438: read ( shd , smbstatus )
                   2439: 
                   2440: if ( smbstatus.attr & SMB_HYPERALLOC )
                   2441:        msg.hdr.offset = filelength ( sdt )
                   2442: 
                   2443: else {
                   2444:        number_of_blocks = length_of_message_data / SDT_BLOCK_LEN
                   2445:        if ( length_of_message_data % SDT_BLOCK_LEN )   /* unevenly divisible */
                   2446:                number_of_blocks = number_of_blocks + 1
                   2447: 
                   2448:        sda = open ( MSGBASE.SDA , READ/WRITE/DENY_ALL )
                   2449: 
                   2450:        if ( fast_allocation_mode )
                   2451:                seek ( sda , END_OF_FILE )
                   2452: 
                   2453:        else {
                   2454:                seek ( sda , BEGINNING_OF_FILE )
                   2455:                while ( not end_of_file ( sda ) ) {
                   2456:                        read ( sda , allocated , number_of_blocks * 2 )
                   2457:                        if ( allocated = 0 ) {
                   2458:                                seek_backwards ( sda , number_of_blocks * 2 )
                   2459:                                break
                   2460:                        }
                   2461:                }
                   2462:        }
                   2463: 
                   2464:        msg.hdr.offset = ( current_position ( sda ) / 2 ) * SDT_BLOCK_LEN
                   2465: 
                   2466:        allocated = 1
                   2467: 
                   2468:        write ( sda , allocated , number_of_blocks * 2 )
                   2469: 
                   2470:        close ( sda )
                   2471: }
                   2472: 
                   2473: seek ( sdt , msg.hdr.offset )
                   2474: 
                   2475: write ( sdt , message_data )
                   2476: 
                   2477: if ( smbstatus.attr & SMB_HYPERALLOC )
                   2478:        msg.idx.offset = filelength ( shd )
                   2479: 
                   2480: else {
                   2481:        number_of_blocks = length_of_message_header / SHD_BLOCK_LEN
                   2482:        if ( length_of_message_header % SHD_BLOCK_LEN )   /* unevenly divisible */
                   2483:                number_of_blocks = number_of_blocks + 1
                   2484: 
                   2485:        sha = open ( MSGBASE.SHA , READ/WRITE/DENY_ALL )
                   2486: 
                   2487:        if ( fast_allocation_mode )
                   2488:                seek ( sha , END_OF_FILE )
                   2489: 
                   2490:        else {
                   2491:                seek ( sha , BEGINNING_OF_FILE )
                   2492:                while ( not end_of_file ( sha ) ) {
                   2493:                        read ( sha , allocated , number_of_blocks )
                   2494:                        if ( allocated = 0 ) {
                   2495:                                seek_backwards ( sha , number_of_blocks )
                   2496:                                break
                   2497:                        }
                   2498:                }
                   2499:        }
                   2500: 
                   2501:        msg.idx.offset = ( current_position ( sha ) * SHD_BLOCK_LEN )
                   2502:        msg.idx.offset = msg.idx.offset + smbstatus.header_offset
                   2503: 
                   2504:        allocated = 1
                   2505: 
                   2506:        write ( sha , allocated , number_of_blocks )
                   2507: 
                   2508:        close ( sha )
                   2509: }
                   2510: 
                   2511: seek ( shd , msg.idx.offset )
                   2512: 
                   2513: msg.hdr.number = smbstatus.last_msg+1
                   2514: 
                   2515: write ( shd , msg.hdr )
                   2516: 
                   2517: smbstatus.total_msgs = smbstatus.total_msgs + 1
                   2518: smbstatus.last_msg = msg.hdr.number
                   2519: 
                   2520: write ( shd , smbstatus )
                   2521: 
                   2522: write ( sid , msg.idx )
                   2523: 
                   2524: unlock ( shd , smbstatus )
                   2525: 
                   2526: Message Retrieval Pseudo Code
                   2527: =============================
                   2528: &&Message Retrieval Pseudo Code
                   2529: $$READPCOD
                   2530: 
                   2531: shd = open ( MSGBASE.SHD , READ/WRITE/DENY_NONE )
                   2532: sdt = open ( MSGBASE.SDT , READ/WRITE/DENY_NONE )
                   2533: sid = open ( MSGBASE.SDT , READ/WRITE/DENY_NONE )
                   2534: 
                   2535: read ( sid , msg.idx )
                   2536: 
                   2537: seek ( shd , msg.idx.offset )
                   2538: 
                   2539: lock ( shd , msg.hdr )
                   2540: 
                   2541: read ( shd , msg.hdr )
                   2542: 
                   2543: seek ( sdt , msg.hdr.offset )
                   2544: 
                   2545: read ( sdt , msg.hdr.data_length )
                   2546: 
                   2547: unlock ( shd , msg.hdr )
                   2548: 
                   2549: SMBUTIL
                   2550: =======
                   2551: &&SMBUTIL
                   2552: $$SMBUTIL_
                   2553: 
                   2554: SMBUTIL is a utility that can perform various functions on an SMB message base.
                   2555: The primary purpose of SMBUTIL is as an example to C programmers of how to use
                   2556: the SMBLIB functions to access and modify an SMB message base. The complete C
                   2557: source code for SMBUTIL is included and functions from it can be used or
                   2558: modified by developers at their own discretion. The following files make up
                   2559: SMBUTIL:
                   2560: 
                   2561: SMBUTIL.EXE    Compiled and linked for 16-bit DOS (ready to run)
                   2562: SMBUTIL.C              C functions
                   2563: SMBUTIL.H              C definitions and variable prototypes
                   2564: SMBUTIL.WAT    Makefile for Watcom C/C++ (type wmake -f smbutil.wat)
                   2565: SMBUTIL.BOR    Makefile for Borland C/C++ (type make -f smbutil.bor)
                   2566: 
                   2567: The usage syntax is as follows:
                   2568: 
                   2569: SMBUTIL [/opts] cmd smb_filespec.shd
                   2570: 
                   2571: where cmd is one or more of the following:
                   2572: 
                   2573:           l[n] = list msgs starting at number n
                   2574:           r[n] = read msgs starting at number n
                   2575:           v[n] = view msg headers starting at number n
                   2576:           k[n] = kill (delete) n msgs
                   2577:           i<f> = import from text file f
                   2578:           s    = display msg base status
                   2579:           c    = change msg base status
                   2580:           m    = maintain msg base - delete old msgs and msgs over max
                   2581:        p[k] = pack msg base (k specifies minimum packable Kbytes)
                   2582: 
                   2583: where opts is one or more of the following:
                   2584: 
                   2585:           a    = always (force) packing
                   2586:           z<n> = set time zone (n=min +/- from UT or 'EST','EDT','CST',etc)
                   2587: 
                   2588: and smb_filespec is the base filename or file specification (wildcards) for the
                   2589: message base. If wildcards are used, the ".SHD" extension must be specified.
                   2590: 
                   2591: An example command line:
                   2592: 
                   2593: SMBUTIL MP C:\SBBS\DATA\SUBS\*.SHD
                   2594: 
                   2595: would maintain and pack all the message bases found in the C:\SBBS\DATA\SUBS
                   2596: directory.
                   2597: 
                   2598: CHKSMB
                   2599: ======
                   2600: &&CHKSMB
                   2601: $$CHKSMB__
                   2602: 
                   2603: CHKSMB is a utility that performs a comprehensive analysis of a message base
                   2604: to find any possible errors and calculate the number of packable bytes. It does
                   2605: not "fix" a message base if any errors are found, it only reports the specific
                   2606: errors (and exits with a non-zero error level). If any errors are reported,
                   2607: packing the message base with SMBUTIL may rebuild the damaged files. If that
                   2608: doesn't work, then use FIXSMB as a last resort.
                   2609: 
                   2610: C source code for CHKSMB is also included as an example to programmers of how
                   2611: to use SMBLIB functions.
                   2612: 
                   2613: The usage syntax is as follows:
                   2614: 
                   2615: CHKSMB [/opts] smb_filespec.shd
                   2616: 
                   2617: where opts is one or more of the following:
                   2618: 
                   2619:                q       = quiet mode (no beeps)
                   2620:                s       = stop after an errored message base (for use with wildcards)
                   2621:                p       = pause after an errored message base (wait for key press)
                   2622:                t       = don't check for unsupported translation strings (faster)
                   2623:                e       = display extended information on corrupted messages
                   2624: 
                   2625: An example command line:
                   2626: 
                   2627: CHKSMB /QP C:\SBBS\DATA\SUBS\*.SHD
                   2628: 
                   2629: would check all the message bases in the C:\SBBS\DATA\SUBS directory, without
                   2630: beeping on errors, and pausing after an errored message base.
                   2631: 
                   2632: FIXSMB
                   2633: ======
                   2634: &&FIXSMB
                   2635: $$FIXSMB__
                   2636: 
                   2637: FIXSMB is a utility that will rebuild the index and allocation files for a
                   2638: message base. Since the message headers are not necessarily stored
                   2639: sequentially, the order of the messages in the index may be changed when the
                   2640: index is rebuilt. Messages are also re-numbered, so only use this program if
                   2641: the index is corrupted and the messages are extremely important.
                   2642: 
                   2643: C source code for FIXSMB is also included as an example to programmers of how
                   2644: to use SMBLIB functions.
                   2645: 
                   2646: The usage syntax is as follows:
                   2647: 
                   2648: FIXSMB [/M] smb_file
                   2649: 
                   2650: An example command line:
                   2651: 
                   2652: FIXSMB \SBBS\DATA\MAIL
                   2653: 
                   2654: Only use the "/M" command line switch if fixing an older Synchronet e-mail
                   2655: message base (created with SBBS v2.1 or earlier). Once the SMB_EMAIL status
                   2656: attr is set ("SMBUTIL S" will report a status attr of 1), the "/M" is not
                   2657: required.
                   2658: 
                   2659: SMBLIB
                   2660: ======
                   2661: &&SMBLIB
                   2662: $$SMBLIB__
                   2663: 
                   2664: SMBLIB is a library of C functions for accessing and storing messages in an
                   2665: SMB format message base. It can eliminate much of the development time for
                   2666: developers that wish to use the library in whole or in part, or use the
                   2667: functions as examples for their own message base function library. The library
                   2668: consists of the following files:
                   2669: 
                   2670: SMBDEFS.H              Constant definitions, macros, and data types
                   2671: SMBLIB.H               Library constants and function prototypes
                   2672: SMBLIB.C               Function definitions
                   2673: SMBVARS.C              Global variable definitions (doubles as declaration file)
                   2674: 
                   2675: For developers to use this library with their program, they must include the
                   2676: "SMBLIB.H" header file at the top of each C file that uses any of the library
                   2677: functions, global variables, data types, macros, and constants. This can be
                   2678: done by simply adding the following line to each .C file:
                   2679: 
                   2680: #include "smblib.h"
                   2681: 
                   2682: If SMBLIB.H is included, there is no need to include SMBDEFS.H or SMBVARS.C.
                   2683: 
                   2684: To link the library functions and variables with a main program, the files
                   2685: SMBVARS.OBJ and SMBLIB.OBJ must be linked with the main program .OBJ files.
                   2686: If the operating system is DOS, be sure that all .OBJ files are compiled for
                   2687: the same memory model.
                   2688: 
                   2689: Example MAKEFILEs for compiling and linking SMBUTIL with Borland C/C++
                   2690: (SMBUTIL.BOR) and Watcom C/C++ (SMBUTIL.WAT) are included.
                   2691: 
                   2692: SMBDEFS.H
                   2693: =========
                   2694: &&SMBDEFS.H
                   2695: $$SMBDEFS_
                   2696: 
                   2697: The SMBDEFS.H file contains important constant definitions and data types (also
                   2698: defined in this document). If ever this document and SMBDEFS.H are inconsistent
                   2699: with each other, then SMBDEFS.H is to be considered correct and this document
                   2700: in error. If such a discrepency is found, please notifiy Digital Dynamics so it
                   2701: can be corrected in a future revision of the specification.
                   2702: 
                   2703: Most notable of the data types is a structure called smbmsg_t (not defined
                   2704: in this document). It contains the fixed and variable portions of a message's
                   2705: header record as well as convenience pointers to the sender's name
                   2706: (smbmsg_t.to), recipient's name (smbmsg_t.from), network addresses, and more.
                   2707: If multiple SENDER header fields are included (for example), then smbmsg_t.to
                   2708: will point to the last SENDER header field in the header record. Convenience
                   2709: pointers for other data items work in the same fasion if multiple header fields
                   2710: of the same type exist in the header record.
                   2711: 
                   2712: Variables of the smbmsg_t data type (and pointers to variables of smbmsg_t
                   2713: type) are used as arguments to many of the SMBLIB functions.
                   2714: 
                   2715: SMBVARS.C
                   2716: =========
                   2717: &&SMBVARS.C
                   2718: $$SMBVARS_
                   2719: 
                   2720: The SMBVARS.C file contains definitions of the global variables used by the
                   2721: SMBLIB functions. It is a fairly small file since there are a small number of
                   2722: global variables (by design). This file is used for both definitions and
                   2723: declarations, so no "extern" declarations need to be made in developers source
                   2724: code as long as SMBVARS.C or (preferably) SMBLIB.H is included in the source
                   2725: code.
                   2726: 
                   2727: SMBLIB.H
                   2728: =======
                   2729: &&SMBLIB.H
                   2730: $$SMBLIB.H
                   2731: 
                   2732: The SMBLIB.H file contains prototypes of all the functions in the SMBLIB.C
                   2733: file. It is necessary to include this file in C source code if any of the
                   2734: SMBLIB functions are used. The following C source line will include this file:
                   2735: 
                   2736: #include "smblib.h"
                   2737: 
                   2738: and should be placed near the top of all C source files that use SMBLIB
                   2739: functions, variables, constants, or data types.
                   2740: 
                   2741: Function prototypes are necessary for compilers to know the correct calling
                   2742: syntax of a function and detect incorrect usage. Prototypes are also useful
                   2743: as a quick reference for programmers as to the correct calling syntax of a
                   2744: specific function.
                   2745: 
                   2746: SMBLIB.C
                   2747: =======
                   2748: &&SMBLIB.C
                   2749: $$SMBLIB.C
                   2750: 
                   2751: The SMBLIB.C file contains the actual SMBLIB library functions. This source
                   2752: file is not a stand alone program, but instead must be compiled and linked
                   2753: with a main source file to create the executable program.
                   2754: 
                   2755: The functions in this file are organized in a logical order, but their order
                   2756: is actually irrelevant to the compiling, linking, and execution of the
                   2757: resulting program.
                   2758: 
                   2759: A comment block preceeds each function, explaining what the function does,
                   2760: how the passed parameters are used, and what the return code (if any)
                   2761: indicates. A more detailed explanation of each function is included here:
                   2762: 
                   2763: int smb_open(int retry_time)
                   2764: ----------------------------
                   2765: The smb_open() function must be called before the message base is accessed
                   2766: (read from or written to). The parameter, retry_time, is the maximum number
                   2767: of seconds to wait while retrying to lock the message base header. If
                   2768: retry_time is 0, then the message base header is not locked or read (this is
                   2769: called "Fast Open" and should only be used when speed is more important than
                   2770: checking for compatibility and validity upon opening). The global variable
                   2771: smb_file must be initialized with the path and base filename of the message
                   2772: base. This function returns 0 on success, 1 if the .SDT file could not be
                   2773: opened, 2 if the .SHD file could not be opened, and 3 if the .SID file could
                   2774: not be opened. If the message base header could not be locked, this function
                   2775: returns -1. If the message base ID is incorrect, it returns -2. And if the
                   2776: message base is of an incompatible version, it returns -3.
                   2777: 
                   2778: The errno global variable (standard of most C libraries) will most likely
                   2779: contain the error code for open failure.
                   2780: 
                   2781: int smb_open_da(int retry_time)
                   2782: -------------------------------
                   2783: The smb_open_da() function is used to open the data block allocation file for
                   2784: writing messages to a message base. The parameter, retry_time, is the maximum
                   2785: number of seconds to wait while retrying to open the file. This function
                   2786: returns 0 on success. -1 is returned if an open error other than "Access
                   2787: Denied" is returned from the operating system, and the global variable errno
                   2788: will contain the error code. -2 is returned if the retry_time has been
                   2789: reached, and -3 is returned if the file descriptor could not be converted to
                   2790: a stream by the fdopen() function.
                   2791: 
                   2792: fclose(sda_fp) should be called immediately after all necessary file access
                   2793: has been completed.
                   2794: 
                   2795: This function is not used with the Hyper Allocation storage method.
                   2796: 
                   2797: int smb_open_ha(int retry_time)
                   2798: -------------------------------
                   2799: The smb_open_ha() function is used to open the header block allocation file for
                   2800: writing messages to a message base. The parameter, retry_time, is the maximum
                   2801: number of seconds to wait while retrying to open the file. This function
                   2802: returns 0 on success. -1 is returned if an open error other than "Access
                   2803: Denied" is returned from the operating system, and the global variable errno
                   2804: will contain the error code. -2 is returned if the retry_time has been
                   2805: reached, and -3 is returned if the file descriptor could not be converted to
                   2806: a stream by the fdopen() function.
                   2807: 
                   2808: fclose(sha_fp) should be called immediately after all necessary file access
                   2809: has been completed.
                   2810: 
                   2811: This function is not used with the Hyper Allocation storage method.
                   2812: 
                   2813: int smb_create(ulong max_crcs, ulong max_msgs, ushort max_age, ushort attr
                   2814:        ,int retry_time)
                   2815: --------------------------------------------------------------------------
                   2816: The smb_create() function is used to create a new message base or reset an
                   2817: existing message base. The parameters max_crcs, max_msgs, max_age, and attr
                   2818: are used to set the initial status of the message base status header. The
                   2819: parameter, retry_time is the maximum number of seconds to wait while retrying
                   2820: to lock the message base header. This functions returns 0 on success or 1 if
                   2821: the message base header could not be locked.
                   2822: 
                   2823: int smb_trunchdr(int retry_time)
                   2824: --------------------------------
                   2825: The smb_trunchdr() function is used to truncate the header file when packing
                   2826: the message base and writing the new header information back to the header
                   2827: file. The parameter, retry_time is the maximum number of seconds to wait while
                   2828: retrying to truncate the header file. Returns 0 on success, -1 if error was
                   2829: other than "Access Denied", or -2 if retry_time reached.
                   2830: 
                   2831: int smb_locksmbhdr(int retry_time)
                   2832: ----------------------------------
                   2833: The smb_locksmbhdr() function is used to lock the first message base (status)
                   2834: header. The parameter, retry_time is the number of seconds to wait while
                   2835: retrying to lock the header. The smb_unlocksmbhdr() function should always be
                   2836: used to unlock the header after accessing the message base header (usually
                   2837: with smb_getstatus() and/or smb_putstatus()). Returns 0 if successful, -1 if
                   2838: unsuccessful.
                   2839: 
                   2840: int smb_unlocksmbhdr()
                   2841: ----------------------
                   2842: The smb_unlocksmbhdr() function is used to unlock a previously locked message
                   2843: base header (using smb_lockmsghdr()). Returns 0 on success, non-zero on
                   2844: failure.
                   2845: 
                   2846: int smb_getstatus(smbstatus_t *hdr)
                   2847: -----------------------------------
                   2848: The smb_getstatus() function is used to read the status message base header
                   2849: into the hdr structure. Returns 0 on success, 1 on failure.
                   2850: 
                   2851: int smb_putstatus(smbstatus_t hdr)
                   2852: ----------------------------------
                   2853: The smb_putstatus() function is used to write the status information to the
                   2854: first message base header. The parameter hdr, contains the status information
                   2855: to be written. Returns 0 on success, 1 on failure.
                   2856: 
                   2857: int smb_getmsgidx(smbmsg_t *msg)
                   2858: --------------------------------
                   2859: The smb_getmsgidx() function is used to get the byte offset for a specific
                   2860: message header in the message header file based on the message base index.
                   2861: 
                   2862: If msg->hdr.number is non-zero when this function is called, then the index
                   2863: will be searched for this message number. If the message number is found in
                   2864: the index, the msg->idx.offset is set to the byte offset of the message header
                   2865: record in the header file and msg->offset is set to the record offset of the
                   2866: index record in the index file, and the function returns 0. If the message
                   2867: number is not found in the index, the function returns 1.
                   2868: 
                   2869: If msg->hdr.number is zero, msg->idx.offset and msg->idx.number are obtained
                   2870: from the index record at record offset msg->offset. If msg->offset is an
                   2871: invalid record offset when this function is called, the function returns 1.
                   2872: Otherwise, the function returns 0.
                   2873: 
                   2874: int smb_getlastidx(idxrec_t *idx)
                   2875: ---------------------------------
                   2876: Reads the last index record of the currently open message base into the
                   2877: idxrec_t structure pointed to by idx. Returns 0 if successful, -1 if the index
                   2878: is empty or unopened, or -2 if the record can't be read.
                   2879: 
                   2880: int smb_getmsghdrlen(smbmsg_t msg)
                   2881: ----------------------------------
                   2882: The smb_getmsghdrlen() function is used to calculate the total length of
                   2883: message header msg including both fixed and variable length portions. This
                   2884: function returns the length of the header record in bytes.
                   2885: 
                   2886: long smb_getmsgdatlen(smbmsg_t msg)
                   2887: -----------------------------------
                   2888: The smb_getmsgdatlen() function is used to calculate the total length of the
                   2889: data for message msg. This function returns the length of all data fields
                   2890: combined.
                   2891: 
                   2892: int smb_lockmsghdr(smbmsg_t msg, int retry_time)
                   2893: ------------------------------------------------
                   2894: The smb_lockmsghdr() function is used to lock the header record for message
                   2895: msg. The parameter retry_time is the maximum number of seconds to wait while
                   2896: retrying to lock the header. Returns 0 on success, -1 on failure. The function
                   2897: smb_unlockmsghdr() should immediately be called after accessing the message
                   2898: header (usually with smb_getmsghdr() or smb_putmsghdr()).
                   2899: 
                   2900: int smb_getmsghdr(smbmsg_t *msg)
                   2901: --------------------------------
                   2902: The function smb_getmsghdr() is used to read the header record for message
                   2903: msg. msg->idx.offset must be initialized to the byte offset of the header
                   2904: record in the header file before this function is called. The function
                   2905: smb_freemsgmem() must be called to free the memory allocated by this function
                   2906: for the header and data felds. This function returns 0 on success, -1 if
                   2907: the fixed portion of the message header record could not be read, -2 if the
                   2908: message header ID was incorrect, -3 if memory could not be allocated, -4
                   2909: if a data field could not be read, -5 if the fixed length portion of a header
                   2910: field could not be read, -6 if the variable length portion of a header field
                   2911: could not be read, -7 if one or more of the mandatory header fields (SENDER,
                   2912: RECIPIENT, or SUBJECT) are missing, -8 if total_dfields extends beyond the
                   2913: end of the header record, or -9 if incompatible header version.
                   2914: 
                   2915: Several convenience pointers in the msg structure are initialized by this
                   2916: function to point to the last occurance of the SENDER (msg->from), RECIPIENT
                   2917: (msg->to), SUBJECT (msg->subj), etc.
                   2918: 
                   2919: int smb_unlockmsghdr(smbmsg_t msg)
                   2920: ----------------------------------
                   2921: The smb_unlockmsghdr() function is used to unlock a previously locked message
                   2922: header (with smb_lockmsghdr()). This function returns 0 on success, non-zero
                   2923: on failure.
                   2924: 
                   2925: int smb_addcrc(ulong max_crcs, ulong crc, int retry_time)
                   2926: ---------------------------------------------------------
                   2927: The smb_addcrc() function is used to add a CRC-32 to the CRC history file
                   2928: for a message base, automatically checking for duplicates. The parameter
                   2929: max_crcs should be the max_crcs defined in the status header of the message
                   2930: base. The parameter crc, is the CRC-32 of the TEXT_BODY and TEXT_SOUL data
                   2931: fields for the message. The parameter retry_time is the maximum number of
                   2932: seconds to wait when retrying to open the CRC history file.
                   2933: 
                   2934: This function returns -1 if there was an open error, -2 if the retry_time
                   2935: was reached, -3 if there was a memory allocation error, 1 if the CRC already
                   2936: exists in the CRC history file (indicating a duplicate message), or 0 on
                   2937: success (and no duplicate).
                   2938: 
                   2939: int smb_hfield(smbmsg_t *msg, ushort type, ushort length, void *data)
                   2940: ---------------------------------------------------------------------
                   2941: The smb_hfield() function is used to add a header field to the structure msg.
                   2942: The parameters type, length, and data, must be specified according to the
                   2943: header field values listed in this specification. This function returns 0
                   2944: on success, non-zero on memory allocation error. The function smb_freemsgmem()
                   2945: must be called to free the memory allocated by this function.
                   2946: 
                   2947: int smb_dfield(smbmsg_t *msg, ushort type, ulong length)
                   2948: --------------------------------------------------------
                   2949: The smb_dfield() function is used to add a data field to the structure msg.
                   2950: The parameters type and length must be specified according to the data field
                   2951: values listed in this specification. This function returns 0 on success,
                   2952: non-zero on memory allocation error. The function smb_freemsgmem() must be
                   2953: called to free the memory allocated by this function.
                   2954: 
                   2955: int smb_addmsghdr(smbmsg_t *msg,smbstatus_t *status,int storage,int retry_time)
                   2956: -------------------------------------------------------------------------------
                   2957: The smb_addmsghdr() function is used to add a new message header to the message
                   2958: header file and update the index file. The msg and status structures are
                   2959: updated to reflect the new total messages, last message number, etc. The
                   2960: storage parameter is used to indicate the storage method to use (either
                   2961: SMB_SELFPACK, SMB_FASTALLOC, or SMB_HYPERALLOC). If the storage type is
                   2962: SMB_SELFPACK, the header block allocation file will be searched for unused
                   2963: block(s) to store this header. If the storage type is SMB_FASTALLOC or
                   2964: SMB_HYPERALLOC, the header is stored at the end of the header file. Returns 0
                   2965: on success, non-zero on failure. The parameter retry_time is the maximum number
                   2966: of seconds to wait while retrying to lock and open files.
                   2967: 
                   2968: int smb_putmsg(smbmsg_t msg)
                   2969: ----------------------------
                   2970: The smb_putmsg() function calls both the smb_putmsghdr() and smb_putmsgidx()
                   2971: functions to write the header and index elements of a message to the
                   2972: appropriate files. Returns 0 on success, non-zero on failure.
                   2973: 
                   2974: int smb_putmsgidx(smbmsg_t msg)
                   2975: -------------------------------
                   2976: The smb_putmsgidx() function is used to store a message index in the message
                   2977: index file. The message index can be for a new message or an existing
                   2978: message. Returns 0 on success, non-zero on failure.
                   2979: 
                   2980: int smb_putmsghdr(smbmsg_t msg)
                   2981: -------------------------------
                   2982: The smb_putmsghdr() function is used to store a message header in the message
                   2983: header file. The message header can be for a new message or an existing
                   2984: message. Returns 0 on success, non-zero on failure.
                   2985: 
                   2986: void smb_freemsgmem(smbmsg_t msg)
                   2987: ---------------------------------
                   2988: Frees allocated memory for the header and data fields in the msg structure.
                   2989: This function must be called to free the memory allocated by the functions
                   2990: smb_hfield(), smb_dfield(), and smb_getmsghdr().
                   2991: 
                   2992: long smb_hdrblocks(ulong length)
                   2993: --------------------------------
                   2994: The smb_hdrblocks() function is used to calculate the number of blocks
                   2995: required to store a message header of length size (in bytes). This function
                   2996: returns the number of blocks required.
                   2997: 
                   2998: long smb_datblocks(ulong length)
                   2999: --------------------------------
                   3000: The smb_datblocks() function is used to calculate the number of blocks
                   3001: required to store message data of length size (in byte). This function returns
                   3002: the number of blocks required.
                   3003: 
                   3004: long smb_allochdr(ulong length)
                   3005: -------------------------------
                   3006: The smb_allochdr() function is used to search for free blocks to store a
                   3007: message header of length bytes and mark the free blocks as allocated in the
                   3008: header allocation file. This function returns the byte offset to the header
                   3009: record or a negative number on error. The function smb_open_ha() should be
                   3010: called prior to calling this function and fclose(sha_fp) should be called
                   3011: after. The function is called from smb_addmsghdr(), so you probably have no
                   3012: need to call this function directly.
                   3013: 
                   3014: long smb_fallochdr(ulong length)
                   3015: --------------------------------
                   3016: The smb_fallochdr() function works exactly the same as the smb_allochdr()
                   3017: function except it is much faster because the header allocation file is not
                   3018: searched for free blocks. The function is called from smb_addmsghdr(), so you
                   3019: probably have no need to call this function directly.
                   3020: 
                   3021: long smb_hallochdr(ulong header_offset)
                   3022: ---------------------------------------
                   3023: This smb_hallochdr() functions works exactly the same as the smb_fallochdr()
                   3024: function except the status.header_offset is passed as the argument and the
                   3025: header allocation (.SHA) file is not updated so smb_open_ha() need not be
                   3026: called. The function is called from smb_addmsghdr(), so you probably have no
                   3027: need to call this function directly.
                   3028: 
                   3029: long smb_allocdat(ulong length, ushort headers)
                   3030: -----------------------------------------------
                   3031: The smb_allocdat() function is used to search for free blocks to store length
                   3032: amount of data for a message. The parameter headers, indicates the number of
                   3033: message headers that are associated with this data. Normally, the headers
                   3034: parameter will be 1, unless this message is part of a mass mailing. The offset
                   3035: to the allocated data blocks is returned, or a negative value on error. The
                   3036: function smb_open_da() should be called prior to calling this function and
                   3037: fclose(sda_fp) should be called after.
                   3038: 
                   3039: long smb_fallocdat(ulong length, ushort headers)
                   3040: ------------------------------------------------
                   3041: The smb_fallocdat() function works exactly the same as the smb_allocdat()
                   3042: function except it is much faster because the data allocation file is not
                   3043: searched for free blocks.
                   3044: 
                   3045: long smb_hallocdat()
                   3046: --------------------
                   3047: The smb_hallocdat() function works exactly the same as the smb_hallocdat()
                   3048: function except no argument is passed and the data allocation file (.SDA) is
                   3049: not updated so smb_open_da() need not be called.
                   3050: 
                   3051: int smb_incdat(ulong offset, ulong length, ushort headers)
                   3052: ----------------------------------------------------------
                   3053: The smb_incdat() function is used to increment the header counter in the data
                   3054: allocation file for the data starting at the byte offset and length size in
                   3055: bytes. The parameter headers, indicates the number of headers to add to the
                   3056: current allocation value in the data allocation file. Returns 0 on success,
                   3057: non-zero on failure.
                   3058: 
                   3059: int smb_freemsg(smbmsg_t msg, smbstatus_t status)
                   3060: -------------------------------------------------
                   3061: The smb_freemsg() function is used to free the disk space allocated for the
                   3062: header and data fields of the message msg. Returns 0 on success, non-zero on
                   3063: failure. The parameter, status, must be the current status from the message
                   3064: base header for this message base.
                   3065: 
                   3066: int smb_freemsgdat(ulong offset, ulong length, ushort headers)
                   3067: --------------------------------------------------------------
                   3068: The smb_freemsgdat() function is used to decrement the data block allocation
                   3069: records in the data allocation file associated with the data in the data file
                   3070: by the value of the headers parameter (normally 1). The parameter offset
                   3071: indicates the byte offset to the beginning of the message data in the data
                   3072: file and the parameter length is the total length of the message data.
                   3073: Returns 0 on success, non-zero on failure.
                   3074: 
                   3075: int smb_freemsghdr(ulong offset, ulong length)
                   3076: ----------------------------------------------
                   3077: The smb_freemsghdr() function is used to set the header block allocation
                   3078: records in the header allocation file to 0 (indicated non-allocated block).
                   3079: The parameter offset indicates the byte offset to the beginning of the header
                   3080: record being freed and the parameter length indicates the total length of the
                   3081: header record. Returns 0 on success, non-zero on failure.
                   3082: 
                   3083: int smb_stack(int op)
                   3084: ---------------------
                   3085: The smb_stack() function is used to save and restore message base information
                   3086: so that multiple message bases can be open simultaneously. The stack can
                   3087: save up to 4 message bases (allowing 5 simultaneously open message bases).
                   3088: The stack is a "last in, first out" storage area for open message bases.
                   3089: If the op parameter is SMB_STACK_PUSH, smb_stack() will save (push) the current
                   3090: message base onto the stack. Calling smb_stack(SMB_STACK_POP) will restore
                   3091: (pop) the most recently pushed message base off the stack. Calling
                   3092: smb_stack(SMB_STACK_XCHNG) will exchange the most recently pushed message base
                   3093: and the current message base (replacing the top of the stack with the current
                   3094: message base).
                   3095: 
                   3096: void smb_close()
                   3097: ----------------
                   3098: Closes the header, data, and index files for the currently open message base.
                   3099: 
                   3100: 
                   3101: Miscellaneous SMBLIB Files
                   3102: ==========================
                   3103: &&Miscellaneous SMBLIB Files
                   3104: $$SMB_MISC
                   3105: 
                   3106: CRC32.H                C header file for CRC-32 calculations
                   3107: -----------------------------------------------------
                   3108: This file contains a static 32-bit CRC table (crc32tbl[]) and a macro (ucrc32)
                   3109: that uses this table to calculate 32-bit CRCs one byte at a time.
                   3110: 
                   3111: Example:
                   3112: 
                   3113:        ulong crc=0xffffffff;
                   3114: 
                   3115: for(i=0;i<length;i++)
                   3116:        crc=ucrc32(buf[i],crc);
                   3117: crc=~crc;
                   3118: 
                   3119: 
                   3120: CRC16.C                C functions for 16-bit CRC calculations
                   3121: -------------------------------------------------------
                   3122: This file contains a function (ucrc16), to calculate 16-bit CRCs one byte at a
                   3123: time and a function (crc16) that uses the ucrc16() function to calculate the
                   3124: 16-bit CRC of an ASCIIZ character string.
                   3125: 
                   3126: Example:
                   3127: 
                   3128:        ushort crc;
                   3129: 
                   3130: crc=crc16("Text");
                   3131: 
                   3132: LZH.H                  Function prototypes for LZH.C
                   3133: ---------------------------------------------
                   3134: This file contains function prototypes for the two most important functions
                   3135: in LZH.C, lzh_encode() and lzh_decode().
                   3136: 
                   3137: Example:
                   3138: 
                   3139:        uchar str[256],lzh[512];
                   3140:        long length;
                   3141: 
                   3142: strcpy(str,"This is a string of text");
                   3143: length=lzh_encode(str,strlen(str),lzh);
                   3144: lzh_decode(lzh,length,str);
                   3145: 
                   3146: 
                   3147: LZH.C           C functions for LZH encoding (compression/decompression)
                   3148: ------------------------------------------------------------------------
                   3149: This file contains the functions for encoding and decoding LZH compressed
                   3150: data. If the macro LZH_DYNAMIC_BUF is defined when this file is compiled,
                   3151: temporary buffers will be dynamically allocated as opposed to static. This
                   3152: may be slower than the static buffer method, but frees the allocated memory
                   3153: after encoding or decoding. If free memory for your application is an issue,
                   3154: then define this macro when compiling this file.
                   3155: 
                   3156: Example (Borland C):
                   3157: 
                   3158: bcc -c -DLZH_DYNAMIC_BUF lzh
                   3159: 
                   3160: Example (Watcom C):
                   3161: 
                   3162: wcc -dLZH_DYNAMIC_BUF lzh
                   3163: 
                   3164: SMBLIB Storage Example
                   3165: ======================
                   3166: &&SMBLIB Storage Example
                   3167: $$SMB_PUT_
                   3168: 
                   3169: #include "smblib.h"
                   3170: #include "crc16.c"
                   3171: 
                   3172: int main(void)
                   3173: {
                   3174:        char    str[256]                                                // General purpose string
                   3175:                   ,*msg_text="Hello, world!"       // Message text
                   3176:                   ,nul_buf[SDT_BLOCK_LEN]={0}          // NULL initialized buffer
                   3177:                   ;
                   3178:        int     i                                                               // General purpose integer
                   3179:                   ,storage=SMB_SELFPACK                        // Default storage method
                   3180:                   ,retry=10                                            // Retry for opening/locking files
                   3181:                   ;
                   3182:        ushort  max_age=0                                               // Default maximum age of messages
                   3183:                   ,xlat=XLAT_NONE                                      // Translation string
                   3184:                   ,tzone=PST                                           // Time zone
                   3185:                   ,copies=1                                            // Number of copies of this msg
                   3186:                   ;
                   3187:        ulong   max_msgs=500                                    // Default max number of msgs
                   3188:                   ,max_crcs=0                                          // Default max crcs
                   3189:                   ,length                                                      // Length of msg text
                   3190:                   ,offset                                                      // Offset to msg text in data file
                   3191:                   ;
                   3192:        smbmsg_t        msg;                                            // Message structure
                   3193:        smbstatus_t status;                                     // Message base status record
                   3194: 
                   3195: strcpy(smb_file,"MSGBASE");                 // We'll use "MSGBASE" for the name
                   3196: if((i=smb_open(retry))!=0) {                           // Can't open!?!
                   3197:        printf("smb_open returned %d\n",i);
                   3198:        return(1); }
                   3199: 
                   3200: if(!filelength(fileno(shd_fp)))                        // Message base not created yet
                   3201:        smb_create(max_crcs                                     // Create with default settings
                   3202:                          ,max_msgs
                   3203:                          ,max_age
                   3204:                          ,storage==SMB_HYPERALLOC
                   3205:                                        ? SMB_HYPERALLOC : 0    // SMB_EMAIL if this was e-mail
                   3206:                          ,retry
                   3207:                          );
                   3208: 
                   3209: if((i=smb_locksmbhdr(retry))!=0) {                     // Can't lock status base header
                   3210:        printf("smb_locksmbhdr returned %d\n",i);
                   3211:        smb_close();
                   3212:        return(1); }
                   3213: 
                   3214: if((i=smb_getstatus(&status))!=0) {            // Can't read status base header
                   3215:        smb_unlocksmbhdr();
                   3216:        smb_close();
                   3217:        printf("smb_getstatus returned %d\n",i);
                   3218:        return(1); }
                   3219: 
                   3220: if(status.attr&SMB_HYPERALLOC)
                   3221:        storage=SMB_HYPERALLOC;
                   3222: else
                   3223:        storage=SMB_SELFPACK;
                   3224: 
                   3225: length=strlen(msg_text);                                       // Get length of message
                   3226: length+=sizeof(xlat);                                          // Add length of xlat string
                   3227: 
                   3228: if(storage==SMB_HYPERALLOC)                            // Allocate space for message text
                   3229:        offset=smb_hallocdat();
                   3230: else {
                   3231:        if((i=smb_open_da(retry))!=0) {
                   3232:                smb_unlocksmbhdr();
                   3233:                printf("smb_open_da returned %d\n",i);
                   3234:                smb_close();
                   3235:                return(1); }
                   3236:        if(storage==SMB_FASTALLOC)
                   3237:                offset=smb_fallocdat(length,copies);
                   3238:        else
                   3239:                offset=smb_allocdat(length,copies);
                   3240:        fclose(sda_fp); }
                   3241: 
                   3242: fseek(sdt_fp,offset,SEEK_SET);                         // Seek to beginning of data block
                   3243: fwrite(&xlat,sizeof(xlat),1,sdt_fp);           // Write xlat string
                   3244: fwrite(msg_text,strlen(msg_text),1,sdt_fp); // Write message text
                   3245: fwrite(nul_buf,SDT_BLOCK_LEN-length            // Write NULLs out to end of block
                   3246:        ,1,sdt_fp);
                   3247: fflush(sdt_fp);                                                        // Flush output buffer
                   3248: smb_unlocksmbhdr();                                            // Unlock status base header
                   3249: 
                   3250: memset(&msg,0,sizeof(smbmsg_t));                       // Initialize header to NULL
                   3251: memcpy(msg.hdr.id,"SHD\x1a",4);             // Always set to SHD^Z
                   3252: msg.hdr.version=SMB_VERSION;
                   3253: msg.hdr.when_written.time=time(NULL);
                   3254: msg.hdr.when_written.zone=tzone;
                   3255: msg.hdr.when_imported.time=time(NULL);
                   3256: msg.hdr.when_imported.zone=tzone;
                   3257: msg.hdr.offset=offset;
                   3258: 
                   3259: strcpy(str,"All");                          // Send message to "All"
                   3260: if((i=smb_hfield(&msg,RECIPIENT,strlen(str),str))!=0) {
                   3261:        printf("smb_hfield returned %d\n",i);
                   3262:        smb_freemsgdat(offset,length,copies);
                   3263:        smb_close();
                   3264:        return(1); }
                   3265: strlwr(str);                                                           // If this were e-mail, idx.to
                   3266: msg.idx.to=crc16(str);                                         // would be the "to" user number
                   3267: 
                   3268: strcpy(str,"Sysop");                        // Send message from "Sysop"
                   3269: if((i=smb_hfield(&msg,SENDER,strlen(str),str))!=0) {
                   3270:        printf("smb_hfield returned %d\n",i);
                   3271:        smb_freemsgdat(offset,length,copies);
                   3272:        smb_freemsgmem(msg);
                   3273:        smb_close();
                   3274:        return(1); }
                   3275: strlwr(str);                                                           // If this were e-mail, idx.from
                   3276: msg.idx.from=crc16(str);                                       // would be the "from" user number
                   3277: 
                   3278: strcpy(str,"This is a test");               // Set the message subject/title
                   3279: if((i=smb_hfield(&msg,SUBJECT,strlen(str),str))!=0) {
                   3280:        printf("smb_hfield returned %d\n",i);
                   3281:        smb_freemsgdat(offset,length,copies);
                   3282:        smb_freemsgmem(msg);
                   3283:        smb_close();
                   3284:        return(1); }
                   3285: strlwr(str);
                   3286: msg.idx.subj=crc16(str);
                   3287: 
                   3288: if((i=smb_dfield(&msg,TEXT_BODY,length))!=0) {
                   3289:        printf("smb_dfield returned %d\n",i);
                   3290:        smb_freemsgdat(offset,length,copies);
                   3291:        smb_freemsgmem(msg);
                   3292:        smb_close();
                   3293:        return(1); }
                   3294: 
                   3295: if((i=smb_addmsghdr(&msg,&status,storage,retry))!=0) {
                   3296:        printf("smb_addmsghdr returned %d\n",i);
                   3297:        smb_freemsgdat(offset,length,copies);
                   3298:        smb_freemsgmem(msg);
                   3299:        smb_close();
                   3300:        return(1); }
                   3301: 
                   3302: smb_freemsgmem(msg);                                           // Unnecessary if exiting main()
                   3303: smb_close();                                                           // Unnecessary if exiting main()
                   3304: return(0);
                   3305: }
                   3306: 
                   3307: SMBLIB Retrieval Example
                   3308: ========================
                   3309: &&SMBLIB Retrieval Example
                   3310: $$SMB_GET_
                   3311: 
                   3312: #include "smblib.h"
                   3313: 
                   3314: int main(void)
                   3315: {
                   3316:        char            ch;                                             // General purpose character
                   3317:        int             i,                                                      // General purpose integer
                   3318:                                retry=10;                                       // Retry for opening/locking files
                   3319:        ushort          xlat;                                           // Translation string
                   3320:        ulong           l;                                                      // General purpose long integer
                   3321:     smbmsg_t    msg;                        // Message structure
                   3322: 
                   3323: strcpy(smb_file,"MSGBASE");                 // We'll use "MSGBASE" for the name
                   3324: if((i=smb_open(retry))!=0) {                           // Can't open!?!
                   3325:        printf("smb_open returned %d\n",i);
                   3326:        return(1); }
                   3327: 
                   3328: if(!filelength(fileno(shd_fp))) {                      // Message base not created yet
                   3329:        printf("Empty\n");
                   3330:        smb_close();
                   3331:        return(0); }
                   3332: 
                   3333: for(msg.offset=0;!ferror(sid_fp);msg.offset++) {
                   3334: 
                   3335:        fseek(sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
                   3336:        if(!fread(&msg.idx,1,sizeof(idxrec_t),sid_fp))
                   3337:                break;
                   3338: 
                   3339:        if((i=smb_lockmsghdr(msg,retry))!=0) {
                   3340:                printf("smb_lockmsghdr returned %d\n",i);
                   3341:                break; }
                   3342:        if((i=smb_getmsghdr(&msg))!=0) {
                   3343:                smb_unlockmsghdr(msg);
                   3344:                printf("smb_getmsghdr returned %d\n",i);
                   3345:                break; }
                   3346:        if((i=smb_unlockmsghdr(msg))!=0) {
                   3347:         smb_freemsgmem(msg);
                   3348:         printf("smb_unlockmsghdr returned %d\n",i);
                   3349:         break; }
                   3350: 
                   3351:        printf("Subj : %s\n",msg.subj);
                   3352:        printf("To   : %s\n",msg.to);
                   3353:        printf("From : %s\n",msg.from);
                   3354:        printf("Date : %s\n",ctime((time_t *)&msg.hdr.when_written.time));
                   3355: 
                   3356:        for(i=0;i<msg.hdr.total_dfields;i++)
                   3357:                switch(msg.dfield[i].type) {
                   3358:                        case TEXT_BODY:                         // Only show BODY and TAIL data fields
                   3359:                        case TEXT_TAIL:
                   3360:                                fseek(sdt_fp,msg.hdr.offset+msg.dfield[i].offset
                   3361:                                        ,SEEK_SET);
                   3362:                                fread(&xlat,sizeof(xlat),1,sdt_fp);
                   3363:                                if(xlat!=XLAT_NONE)     // No translations supported
                   3364:                                        continue;
                   3365:                                for(l=sizeof(xlat);l<msg.dfield[i].length;l++) {
                   3366:                                        ch=fgetc(sdt_fp);
                   3367:                                        if(ch)
                   3368:                                                putchar(ch); }
                   3369:                                printf("\n");
                   3370:                                break; }
                   3371:        printf("\n");
                   3372: 
                   3373:        smb_freemsgmem(msg); }                  // Free memory allocated by smb_getmsghdr()
                   3374: 
                   3375: smb_close();
                   3376: return(0);
                   3377: }
                   3378: 
                   3379: SMBLIB Performance Issues
                   3380: =========================
                   3381: &&SMBLIB Performance Issues
                   3382: $$PERFORM_
                   3383: 
                   3384: Since importing messages is the usually the most time consuming task likely
                   3385: undertaken by an SMB application, it is also the most susceptable to design
                   3386: issues that effect performance.
                   3387: 
                   3388: Opening and Closing
                   3389: -------------------
                   3390: When importing multiple messages for a single message base, it appears logical
                   3391: to open the message base, import all the messages, then close it. This indeed
                   3392: is preferred over opening and closing the message base for each message.
                   3393: 
                   3394: When importing multiple messages for possibly non-consecutive message bases,
                   3395: developers may easily make the mistake of opening and closing the message base
                   3396: for each message. This is not necessary and can considerably hinder the
                   3397: import performance. The easiest solution is to only close the message base and
                   3398: open a new one if the next message to be imported is not for the same message
                   3399: base as the previously imported message. Example:
                   3400: 
                   3401: smb_file[0]=0;
                   3402: for(i=0;i<total_messages_to_be_imported;i++) {
                   3403:        if(stricmp(get_messagebase_for_this_message(i),smb_file)) {
                   3404:                if(smb_file[0])         /* We've already opened one */
                   3405:                        smb_close();
                   3406:                strcpy(smb_file,get_messagebase_for_this_message(i));
                   3407:                smb_open(10); }
                   3408:        /* Import this message */
                   3409:        }
                   3410: if(smb_file[0])
                   3411:        smb_close();
                   3412: 
                   3413: A more advanced method is to keep multiple message bases open at the same time.
                   3414: Due to the likely limitation of total file handles on the system, it is
                   3415: suggested to keep the number of simultaneously open message bases at or below
                   3416: 3. SMBLIB includes the function smb_stack() to easily "push" and "pop" message
                   3417: bases without closing them (push is the equivalent to "save" and pop is the
                   3418: equivalent to "restore"). The downside of this function is that you cannot
                   3419: access message bases on the stack without actually popping them off (in reverse
                   3420: of the order they were pushed). You can however "exchange" the current message
                   3421: base with the message base on the top of the stack (most recently pushed).
                   3422: To intelligently juggle more than two open message bases, the developer should
                   3423: create their own equivalent of the smb_stack() function so they can access the
                   3424: message bases on the stack without popping them off. An example of keeping a
                   3425: maximum of two message bases open using smb_stack():
                   3426: 
                   3427:        char last_messagebase[128],new_messagebase[128];
                   3428: 
                   3429: smb_file[0]=0;
                   3430: last_messagebase[0]=0;
                   3431: for(i=0;i<total_messages_to_be_imported;i++) {
                   3432:        strcpy(new_messagebase,get_messagebase_for_this_message(i));
                   3433:        if(stricmp(new_messagebase,smb_file)) {         /* Not current message base */
                   3434:                if(smb_file[0]) {                                               /* We've already opened one */
                   3435:                        if(!stricmp(new_messagebase,last_messagebase)) { /* Same as last */
                   3436:                                strcpy(last_messagebase,smb_file);
                   3437:                                smb_stack(SMB_STACK_XCHNG); }           /* Retore previous base */
                   3438:                        else {
                   3439:                                if(last_messagebase[0]) {
                   3440:                                        smb_stack(SMB_STACK_XCHNG);
                   3441:                                        smb_close();
                   3442:                                        strcpy(last_messagebase,new_messagebase); }
                   3443:                                else {
                   3444:                                        strcpy(last_messagebase,smb_file);
                   3445:                                        smb_stack(SMB_STACK_PUSH); }    /* Save current base */
                   3446:                                strcpy(smb_file,new_messagebase);
                   3447:                                smb_open(10); } }
                   3448:                else {
                   3449:                        strcpy(smb_file,new_messagebase);
                   3450:                        smb_open(10); } }
                   3451:        /* Import this message */
                   3452:        }
                   3453: if(smb_file[0])
                   3454:     smb_close();
                   3455: if(last_messagebase[0]) {
                   3456:        smb_stack(SMB_STACK_POP);
                   3457:        smb_close(); }
                   3458: 
                   3459: The second example would be of negligible performance gain over the first
                   3460: example (6 open operations versus 7) if the messages to import were in the
                   3461: following order:
                   3462: 
                   3463: msg[0] --> msgbase[0]          // 0 opened
                   3464: msg[1] --> msgbase[1]          // 0 pushed 1 opened
                   3465: msg[2] --> msgbase[1]
                   3466: msg[3] --> msgbase[2]          // 1 closed 0 popped 0 closed 2 opened
                   3467: msg[4] --> msgbase[0]          // 2 pushed 0 opened
                   3468: msg[5] --> msgbase[2]          // 0 pushed 2 popped (exchanged)
                   3469: msg[6] --> msgbase[3]          // 2 closed 0 popped 0 closed 3 opened
                   3470: msg[7] --> msgbase[0]          // 3 pushed 0 opened
                   3471: 
                   3472: The second example would be of significant performance gain over the first
                   3473: example (4 open operations versus 8) if the messages to import were in the
                   3474: following order:
                   3475: 
                   3476: msg[0] --> msgbase[0]          // 0 opened
                   3477: msg[1] --> msgbase[1]          // 0 pushed 1 opened
                   3478: msg[2] --> msgbase[0]          // 1 pushed 0 popped (exchanged)
                   3479: msg[3] --> msgbase[1]          // 0 pushed 1 popped (exchanged)
                   3480: msg[4] --> msgbase[0]          // 1 pushed 0 popped (exchanged)
                   3481: msg[5] --> msgbase[2]          // 0 pushed 1 popped (exchanged) 1 closed 2 opened
                   3482: msg[6] --> msgbase[3]          // 2 pushed 0 popped (exchanged) 0 closed 3 opened
                   3483: msg[7] --> msgbase[2]          // 3 pushed 2 popped (exchanged)
                   3484: 
                   3485: More advanced use of "stack-like" message base file handle storage can easily
                   3486: reduce the number of open operations, therefore increasing import performance
                   3487: under more adverse message base ordering conditions.
                   3488: 
                   3489: Compression
                   3490: -----------
                   3491: If any message data compression features are offered by the application, it
                   3492: is important the the application not unnecessarily compress data that will
                   3493: not save any storage space. While this may seem an obvious statement, please
                   3494: review the following pseudo-code example:
                   3495: 
                   3496: if ( message_data_length < SDT_BLOCK_LEN )
                   3497:        // Store uncompressed data
                   3498: else {
                   3499:        // Compress data
                   3500:        if ( ( compressed_data_length / SDT_BLOCK_LEN )
                   3501:                < ( message_data_length / SDT_BLOCK_LEN ) ) // Saves a block or more
                   3502:                // Store compressed data
                   3503:        else
                   3504:                // Store uncompressed data
                   3505:        }
                   3506: 
                   3507: Since the SMB format stores message data in fixed length blocks, there is no
                   3508: point in storing a message in compressed format if it requires the same number
                   3509: of blocks as the uncompressed format (i.e. a message that is two blocks in
                   3510: length in uncompressed format and only a block and a half in length when
                   3511: compressed should not be stored in compressed format since it still requires
                   3512: two full blocks of storage). It is important to note that in the above example,
                   3513: the length of the data translation string was not taken into account in
                   3514: determining the number of required blocks. Also, the smb_datblocks() function
                   3515: is normally used in determing the number of required blocks to store a given
                   3516: data length and it is a little more involved than simply dividing the length of
                   3517: the data by SDT_BLOCK_LEN.
                   3518: 
                   3519: 
                   3520: Bibliography
                   3521: ============
                   3522: &&Bibliography
                   3523: $$BIBLIOGR
                   3524: 
                   3525: Title    : The C Programming Language
                   3526: Publisher : Prentice Hall
                   3527: Author   : Brian W. Kernighan and Dennis M. Ritchie
                   3528: 
                   3529: Document  : ARPANET Request for Comments (RFC) #822
                   3530: Title    : Standard for the Format of ARPA Internet text messages
                   3531: Publisher : SRI International
                   3532: Author   : David H. Crocker, University of Delaware
                   3533: 
                   3534: Document  : FTS-0001
                   3535: Publisher : FSC
                   3536: Author   : Randy Bush, Pacific Systems Group
                   3537: 
                   3538: Document  : FTS-0004
                   3539: Title    : EchoMail Specification
                   3540: Publisher : FSC
                   3541: Author   : Bob Hartman
                   3542: 
                   3543: Document  : FTS-0009
                   3544: Title    : A standard for unique message identifiers and reply chain linkage
                   3545: Publisher : FSC
                   3546: Author   : Jim Nutt
                   3547: 
                   3548: Document  : FSC-00046
                   3549: Title    : A Product Idenfifier for FidoNet Message Handlers
                   3550: Publisher : FSC
                   3551: Author   : Joaquim H. Homrighausen
                   3552: 
                   3553: Document  : FSC-00053
                   3554: Title    : Specifications for the ^aFLAGS field
                   3555: Publisher : FSC
                   3556: Author   : Joaquim H. Homrighausen
                   3557: 
                   3558: 
                   3559: Implementations
                   3560: ===============
                   3561: &&Implementations
                   3562: $$IMPLEMEN
                   3563: 
                   3564: Product   : Synchronet Multinode BBS Software
                   3565: Developer : Digital Dynamics
                   3566: Level    : III
                   3567: Version   : 2.20
                   3568: 
                   3569: Product   : Synchronet/FidoNet Import/Export Utility (SBBSFIDO)
                   3570: Developer : Digital Dynamics
                   3571: Level    : III
                   3572: Version   : 2.23
                   3573: 
                   3574: Product   : Synchronet UTI (Universal Text Interface) Driver
                   3575: Developer : Digital Dynamics
                   3576: Level    : III
                   3577: Version   : 2.23
                   3578: 
                   3579: Product   : SBBSecho FidoNet Packet Tosser for Synchronet
                   3580: Developer : Digital Dynamics
                   3581: Level    : III
                   3582: Version   : 1.11
                   3583: 
                   3584: Product   : NetXpress Internet UUCP for Synchronet
                   3585: Developer : Merlin Systems
                   3586: Level    : II
                   3587: Version   : 1.50
                   3588: 
                   3589: Product   : InterEcho FidoNet Packet Tosser
                   3590: Developer : InterMail Sales Inc
                   3591: Level    : II
                   3592: Version   : 1.11

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.