home *** CD-ROM | disk | FTP | other *** search
- // JAM message writing programme.
-
- // Written by and contributed to the public domain by
- // Michael Lecuyer, Viola. DE, December 1993.
-
- // V1.0 Nov 14, 1993 - intial coding
- // V1.1 Nov 15, 1993 - a change to remove external reference that didn't exist
- // Nov 17, 1993 - Using a local time function for write time.
- // - Uses MSGID and PID subfields
- // - Set up proper CRC's for msgid
- // - translating '\n' to 0x0D
- // V1.2 Dec 8, 1993 - Added the flags to write_jam(). Now it's the caller's
- // responsibility to set the flags correctly.
-
-
-
-
- /*
- Note from the JAM docs:
-
- All applications that support JAM must include one of the following
- notices in their documentation and somewhere in the product's credit
- section:
-
- "JAM(mbp) - Copyright 1993 Joaquim Homrighausen, Andrew Milner,
- Mats Birch, Mats Wallin.
- ALL RIGHTS RESERVED."
-
- or
-
- "This product uses the JAM(mbp) API -
- Copyright 1993 Joaquim Homrighausen, Andrew Milner, Mats Birch,
- Mats Wallin. ALL RIGHTS RESERVED."
-
- No organization, company, person, entity, or other being may impose
- any fees for any reason for providing this document or the
- accompanying API. This document and the accompanying API may not be
- sold or otherwise transferred for personal or company gain under any
- circumstances.
-
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <time.h>
- #include <dos.h>
- #include <io.h>
-
- // Set up the JAM API definitions
-
- #include "jammb.h"
- #include "writejam.h"
-
- // ----------------------------------------------------
- // THREE Tunable Paramaters You Might Be Interested In:
- // ----------------------------------------------------
-
- #define WORKBUFSIZE 300 // the size of this determines the maximum amount
- // of space for fields. Under RA the most
- // this might need to be is 35 (to) + 35 (from) +
- // subject line length + a little overhead.
- // or about 300 bytes.
-
- #define PIDString "TEST" // Your process ID name - whatever you want this
- // to be. This identifies the process that
- // created the message. Keep it short.
- // (used in jam_load_fields()) for the Process
- // ID subfield.
-
- #define MAXPIDLen 50 // Maximum length of the PIDstring and other data.
- // See jam_load_fields() for details.
-
- #if defined(TRUE) || defined(FALSE)
- undef TRUE
- undef FALSE
- #endif
-
- #define TRUE 1
- #define FALSE 0
-
- static char *gen_msgid(void);
- static int getpid(void);
- static int jam_load_fields(char *from, char *to, char *subject);
- static int write_jam_msg(char *text, unsigned long flags);
- static void jam_close(void);
- static void jam_msg_init(void);
-
- static JAMAPIREC JamRec; // The JAM message base boat anchor structure
-
- // Write a message to the JAMbase.
- // Incoming are the path to the JAMbase (as found in Messages.ra),
- // the FROM field (author), the TO field (recipient),
- // the SUBJECT field and the text of the message and the flags.
- // The flags are found in the JAM.H file and are described in
- // JAM.DOC.
- //
- // Returns FALSE (0) if the process failed, TRUE (1) if everything went
- // well.
- //
- int write_jam(char *jambase, char *from, char *to, char *subject, char *text, unsigned long flags)
- {
- // Start up the JAM api - either open an existing base or start a new one.
-
- if(!JAMsysInitApiRec(&JamRec, jambase, WORKBUFSIZE))
- return FALSE; // Caused by out of memory condition.
-
- // Open the JAMbase - if that fails try creating the message base.
-
- if (!JAMmbOpen(&JamRec))
- {
- if(!JAMmbCreate(&JamRec))
- {
- printf("Unable to create messagebase: %s, code: %d, errno: %d\n", jambase, JamRec.APImsg, JamRec.Errno);
- JAMsysDeinitApiRec(&JamRec);
-
- return FALSE;
- }
- }
-
- // set up the message constants.
-
- jam_msg_init();
-
- // JAM uses subfields for the to & from & other fields - set them up
-
- if (jam_load_fields(from, to, subject) == FALSE)
- {
- jam_close(); // usually caused by insufficient space - WORKBUFSIZE too small
- return FALSE;
- }
-
- // actually write out the message. If we fail clean up and return.
-
- if (write_jam_msg(text, flags) == FALSE)
- {
- jam_close(); // many things cause this problem - can't lock messagebase or
- return FALSE; // can't write files. Look at JamRec.APImsg and JamRec.Errno
- }
-
- jam_close(); // Close everything to keep things tidy - and reclaim memory
-
- return TRUE;
- }
-
- // Put out the copyright information as requested by the jam developers
- // and a credit to Michael Lecuyer
- //
- void JAMcopyright(void)
- {
- puts("JAMutil\n"
- "Copyright 1993 Joaquim Homrighausen, Andrew Milner, Mats Birch, and\n"
- " Mats Wallin. ALL RIGHTS RESERVED\n"
- " Written by Mats Wallin & Mats Birch\n"
- );
- }
-
- // Intialize the message
- // Although we set everything to 0 there are a few fields which
- // must have a default value - the unused CRC's should contain -1.
- //
- static void jam_msg_init(void)
- {
- UINT32 tm;
-
- // Clear out the messag header in case there's old data lying around
-
- memset(&JamRec.Hdr, '\0', sizeof(JAMHDR));
-
- // Set the time up for this message
-
- JAMsysTime(&tm);
- JAMsysMkTime(JAMsysLocalTime(&tm));
- JamRec.Hdr.DateWritten = tm;
-
- // These CRC's are set to nothing (-1) initially.
-
- JamRec.Hdr.ReplyCRC = (UINT32) -1L;
- JamRec.Hdr.MsgIdCRC = (UINT32) -1L;
- JamRec.Hdr.PasswordCRC = (UINT32) -1L;
- JamRec.Idx.UserCRC = (UINT32) -1L;
- }
-
- // Load all the fields we saved away into the messagebase
- // Also calculate the CRC of some of the fields.
- //
- // Return TRUE if all is well, else FALSE
- //
- static int jam_load_fields(char *from, char *to, char *subject)
- {
- UINT32 subfield_pos = 0;
- char *msgid = gen_msgid();
- char pid[MAXPIDLen]; // This has to be large enough for PID string + PID number
- char *tmpuser;
-
- if(!JAMmbAddField(&JamRec, JAMSFLD_SUBJECT, 1, strlen(subject), &subfield_pos, subject))
- return FALSE;
-
- if(!JAMmbAddField(&JamRec, JAMSFLD_SENDERNAME, 1, strlen(from), &subfield_pos, from))
- return FALSE;
-
- if(!JAMmbAddField(&JamRec, JAMSFLD_RECVRNAME, 1, strlen(to), &subfield_pos, to))
- return FALSE;
-
- // Lowercase the name in a temporary place so we don't kill the original.
-
- tmpuser = strdup(to);
- if (tmpuser == NULL)
- return FALSE; // out of memory condition
-
- strlwr(tmpuser);
- JamRec.Idx.UserCRC = JAMsysCrc32(tmpuser, strlen(tmpuser), (UINT32) -1L);
- free(tmpuser);
-
- sprintf(pid, "%s %0X", PIDString, getpid());
- if(!JAMmbAddField(&JamRec, JAMSFLD_PID, 1, strlen(pid), &subfield_pos, pid))
- return FALSE;
-
- if(!JAMmbAddField(&JamRec, JAMSFLD_MSGID, 1, strlen(msgid), &subfield_pos, msgid))
- return FALSE;
- JamRec.Hdr.MsgIdCRC = JAMsysCrc32(msgid, strlen(msgid), (UINT32) -1L);
-
- JamRec.Hdr.SubfieldLen = subfield_pos;
-
- return TRUE;
- }
-
-
- // Write out the message to the JAM base.
- // This involves finding a message number - for all operations the message
- // base must be locked.
- // For some strange reason RA expects the carriage returns to be
- // 0x0D. Newlines from C arrive as 0X0A. Translate them if they occur.
- //
- // Return TRUE if all is well, else FALSE
- //
- static int write_jam_msg(char *text, unsigned long flags)
- {
- UINT32 msg_number; // Next available message number for this message
- char *p;
- int locktry; // lock counter
-
- // set up some information in advance of locking the database
-
- JamRec.Hdr.TxtLen = strlen(text);
- JamRec.Hdr.Attribute = flags;
-
- // The text arrives with \n's which turn into 0x0A's which are
- // not recognized by RA. Change them to 0x0D's
-
- for (p = text; *p; p++)
- if (*p == 0x0A)
- *p = 0x0D;
-
- // attempt to lock the database a hearty number of times!
- // Note: some systems do this retry business within the lock function.
- // Other runtime libraries don't. Each compiler's manual page is hazy
- // as to what their retry strategy is.
-
- #if defined(_MSC_VER) || defined(_QC)
- if (!JAMmbLockMsgBase(&JamRec, TRUE)) // lock the message base, get header info
- {
- printf("Failed to get lock, apimsg = %d\n", JamRec.APImsg);
- return FALSE; // Failed to get lock
- }
-
- #else
- for (locktry = 0; locktry < 10; locktry++)
- {
- if (JAMmbLockMsgBase(&JamRec, TRUE) == 0) // lock the message base, get header info
- sleep(1); /* Wait one second */
- else
- break;
- }
- if (locktry >= 10)
- return FALSE;
- #endif
-
- // Get the message number for the new message
- // Use the size of the IDX file divided by the size of the IDX record
- // (giving the number of records in the file) and add the JAM base
- // first message number.
-
- msg_number = (UINT32)((filelength(JamRec.IdxHandle) / (UINT32)sizeof(JAMIDXREC))) + JamRec.HdrInfo.BaseMsgNum;
- JamRec.Hdr.MsgNum = msg_number;
-
- // Get the offset in the header file for this message header
-
- JamRec.Idx.HdrOffset = filelength(JamRec.HdrHandle);
-
- // Store the index record with the pointer & user CRC information.
-
- if(!JAMmbStoreMsgIdx(&JamRec, msg_number))
- return FALSE;
-
- // And get the offset in the text file for the next text
-
- JamRec.Hdr.TxtOffset = filelength(JamRec.TxtHandle);
-
- // And the header record
-
- if(!JAMmbStoreMsgHdr(&JamRec, msg_number))
- return FALSE;
-
- // Write all the subfields
-
- if(JAMsysWrite(NULL, JamRec.HdrHandle, JamRec.WorkBuf, (INT32)JamRec.Hdr.SubfieldLen) != (int)JamRec.Hdr.SubfieldLen)
- return FALSE;
-
-
- // Save the text buffer away into it's file.
-
- if(!JAMmbStoreMsgTxtBuf(&JamRec, text, JamRec.Hdr.TxtLen, 1))
- return FALSE;
-
- // keep track of the number of messages in the JAMbase
-
- JamRec.HdrInfo.ActiveMsgs++;
-
- // unlock the message base, post header info - the TRUE flag.
-
- JAMmbUnLockMsgBase(&JamRec, TRUE);
-
- return TRUE;
- }
-
- // Close the Jam Base
- //
- static void jam_close(void)
- {
- JAMmbClose(&JamRec);
- JAMsysDeinitApiRec(&JamRec);
- }
-
- // Generate a unique message ID
- // Since this is a local message just use the time of day.
- //
- static char *gen_msgid(void)
- {
- static char msgid[70]; // a short message id will do
- time_t tm;
- char number[15];
-
- time(&tm);
-
- strftime(msgid, sizeof(msgid), "%d %b, %y %H:%M:%S ", localtime(&tm));
-
- itoa(getpid(), number, sizeof(number));
-
- strcat(msgid, number);
-
- return msgid;
- }
-
- // With the 3.0 C++ borland C compiler getpid() is part of the runtime
- // library. Faked here for other compilers.
- //
- static int getpid(void)
- {
- union REGS inreg, outreg;
- struct SREGS sreg;
-
- // do a dosint of 62 to get the PSP address.
-
- inreg.h.ah = 0x62;
-
- intdosx(&inreg, &outreg, &sreg);
-
- return outreg.x.bx;
- }
-
-