Annotation of sbbs/sbbs2/smb/docs/smb.src, revision 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.