|o||All library-global identifiers are prefixed with 'JAM_'. All file-global identifiers are prefixed with 'jam_'. Local identifiers do not have prefixes.|
All variables have a suffix describing their basic type. Suffixes used
in this library are:
_I - integer (int Example_I) _C - character (char Example_C) _S - struct (struct Example_S) _P - pointer (void* Example_P) _A - array
Suffixes are then combined, to show the correct type:
_PI - pointer to integer (int* Example_PI) _PC - pointer to char (char* Example_PC) _AC - array of char (char Example_AC[x]) _PPS - pointer to pointer to struct (struct** Example_PPS)
|o||Functions do not have suffixes|
The library is divided into five groups:
o Message base functions o Message functions o Subfield functions o LastRead functions o Miscellanous functions
These functions handle JAM message bases, by opening, locking, scanning etc the contents of a message base. These are fairly straight-forward and simple routines that you should have little, if any, trouble with.
A message base is identified by a message base handle, which is obtained from either JAM_OpenMB(3) or JAM_CreateMB(3). All functions that read or write from the message base take this handle as parameter, to know which message base to use.
JAM_OpenMB(3) Open a message base JAM_CloseMB(3) Close message base JAM_CreateMB(3) Create a new message base JAM_RemoveMB(3) Remove a message base JAM_LockMB(3) Lock message base for exclusive access JAM_UnlockMB(3) Unlock message base JAM_ReadMBHeader(3) Read message base header JAM_WriteMBHeader(3) Write message base header JAM_FindUser(3) Find message to a user JAM_GetMBSize(3) Get the number of messages in message base
These functions handle individual JAM messages. A JAM message contains of three parts:
o Message Header o Message Header Subfields o Message Text The message header is a simple C structure and the message text is a simple text buffer. The subfields, however, are a bit more tricky. These contain everything that is not covered by the header, including the TO, FROM, SUBJECT fields, origin and destination network adresses etc. There can be an unlimited number of subfields to a message. In this routine library the subfields are encapsulated by a 'subfield packet', which is handled by its own set of routines. See a later section of this document for an explanation of those. JAM_ReadMsgHeader(3) Read a message's header and its subfields JAM_ReadMsgText(3) Read a message's text JAM_AddMessage(3) Add a message to message base JAM_AddEmptyMessage(3) Add a empty message entry to a message base JAM_ChangeMsgHeader(3) Change a message's header JAM_ClearMsgHeader(3) Clear a message header structure JAM_DeleteMessage(3) Delete message from messagebase
As described earlier, a subfield is a part of the message header. Due to the complexity of the different network types in use, it is not feasible to try and cram all data into one header struct. Therefore, JAM uses a fairly small header struct and instead marks all additional data fields as 'subfields'.
In order to make life a little more easy, I have used the concept of a container for all subfields. I call it a 'Subfield Packet'. It is identified by a struct pointer, and should be looked upon as a file or a list that you manipulate via the following five functions:
JAM_NewSubPacket(3) Create a new subfield packet JAM_DelSubPacket(3) Delete a subfield packet JAM_GetSubfield(3) Get a subfield from a subfield packet (not reentrant) JAM_GetSubfield_R(3) Get a subfield from a subfield packet (reentrant) JAM_PutSubfield(3) Put a subfield into a subfield packet
JAM implements the often-used concept of high water marking for remembering which user read how many messages in each area.
Personally I think this concept stinks, since it does not store *which* messages a user has read, only the number of the highest message he has read. But since it's a part of JAM and it's fairly straightforward and easy, I've implemented two support functions for it.
I would, however, strongly recommend all BBS programmers to use proper message mapping systems instead, so your users can read their messages in whatever order they wish.
JAM_ReadLastRead(3) Read a lastread record JAM_WriteLastRead(3) Write a lastread record
JAM_Crc32(3) Calculate CRC32 on a block of data JAM_Errno(3) Specify I/O error
JAMLIB 1.0 was originally released by Bjorn Stenberg 1996-03-06. Since the original license did not permit modification of the library, Johan Billing contacted Bjorn Stenberg and asked him to change the license. Bjorn Stenberg agreed to change the license to the GNU Lesser General Public License 1999-12-21.
After that, some minor additions and bug fixes were made by Johan Billing and JAMLIB 1.1 was released under the new license.
Somewhen, after 1.2 release or so, Sir Raorn moved JAMlib to GNU autotools, again with some minor additions an bugfixes.
All original code except for the CRC32 routine was written by Bjorn Stenberg. The CRC32 code was rewritten by Johan Billing for JAMLIB 1.1 to replace the original CRC32 code whose origin and copyright was unclear. The jam.h header file is a compilation of the best from the various header files in the JAMAPI package with some of additions by Bjorn Stenberg as well. Additions and modifications by Johan Billing and Sir Raorn.
The JAM message base proposal is:
JAM(mbp) - Copyright 1993 Joaquim Homrighausen, Andrew Milner, Mats Birch, Mats Wallin. ALL RIGHTS RESERVED
For questions about JAMLIB, please contact:
Sir Raorn <email@example.com>
Johan Billing <firstname.lastname@example.org>
If you wish to contact Bjorn Stenberg, his current e-mail address (as of 1999-12-21) is email@example.com.
If you are extra curious about the JAM message format, I suggest you get a hold of an archive called JAMAPI.ARJ. That archive contains a file called JAM.DOC which is the file I have used as reference for the development of these routines.