home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Black Box 4
/
BlackBox.cdr
/
bbs_ra
/
msgq160s.arj
/
QMSGBASE.C
< prev
next >
Wrap
Text File
|
1991-07-28
|
25KB
|
1,040 lines
/*
* QMSGBASE.C - Low level message base functions
*
* Msged/Q message editor for QuickBBS Copyright 1990 by P.J. Muller
*
*/
/*
* Used by Msged/Q and MsgLink
*
* External variables:
* char *bbspath Prefix for *.BBS filenames
* int usernum For LASTREAD.BBS, set this to 0 if not needed
*
* Conditional Compilation:
* NOBINSEARCH Define this for slow linear indexing
* OLDBINIDX
*/
#include <string.h>
#include <io.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <sys/stat.h>
#include "qtypes.h"
#include "quickbbs.h"
#include "qmsgbase.h"
#include "p2c.h"
#define PATHLEN 70
extern char *bbspath; /* Path prefix for filenames */
extern int usernum; /* user number for lastread.bbs */
static int lastread[BLIM]; /* last msg read in each board */
static int current[BLIM]; /* current msgnum in each board */
static BOOLEAN lastreaddirty = FALSE;
static BOOLEAN currentdirty = FALSE;
static INFORECORD msginfo; /* MSGINFO.BBS */
IDXRECORD *msgidx; /* MSGIDX.BBS */
int filemsgs; /* length of index and header files */
/* file descriptors indexes, be careful when changing this (for loops) */
enum {f_idx,f_info,f_hdr,f_txt,f_toidx,f_cur,f_last};
static int F[f_last+1];
static char *FN[]={"msgidx.bbs","msginfo.bbs","msghdr.bbs","msgtxt.bbs",
"msgtoidx.bbs","current.bbs","lastread.bbs"};
#define f_first f_idx /* loops from f_first to f_last */
/* functions local to this module */
static BOOLEAN updatecurlast(void);
static BOOLEAN flushfile(int fd);
static BOOLEAN updatetosslog(int num, BOOLEAN echomail, BOOLEAN delete);
/*
* Return a pointer to a static expanded path
*/
char *expandbbs(char *fname)
{
static char name[PATHLEN];
name[0] = EOS;
if (bbspath != NULL)
strcpy(name, bbspath);
strcat(name, fname);
return(name);
} /* expandbbs */
/*
* Open all the message base files
* Returns TRUE if ok
*/
BOOLEAN openmsgbase()
{
struct stat st;
BYTE i;
for (i = f_first; i <= f_last; i++) /* open all files */
if ((F[i] = open(expandbbs(FN[i]),
O_RDWR|O_BINARY|O_CREAT, S_IREAD|S_IWRITE)) == -1)
return(FALSE);
memset(&msginfo, 0, sizeof(msginfo)); /* clear the record */
fstat(F[f_info], &st);
if (st.st_size == 0) { /* just created */
write(F[f_info], (char *)&msginfo, sizeof msginfo);
flushfile(F[f_info]);
} else {
read(F[f_info], (char *)&msginfo, sizeof msginfo); /* read existing */
} /* if */
memset(&st, 0, sizeof(st));
fstat(F[f_hdr], &st);
filemsgs = (int)(st.st_size/sizeof(MSGHEADER)); /* number of messages */
if ((msgidx = calloc(filemsgs+1,sizeof(IDXRECORD))) == NULL)
return FALSE;
read(F[f_idx], (char *)msgidx, (size_t)filemsgs*sizeof(IDXRECORD));
memset(lastread, 0, sizeof(lastread));
lseek(F[f_last], (long)usernum * sizeof(lastread), SEEK_SET);
read(F[f_last], (char *)lastread, sizeof(lastread));
/* pssst: could check for errors here */
memset(current, 0, sizeof(current));
lseek(F[f_cur], (long)usernum * sizeof(lastread), SEEK_SET);
read(F[f_cur], (char *)current, sizeof(current));
for (i = 0; i < BLIM; i++) {
int first,last;
if (msginfo.activemsgs[i] == 0) /* empty board? */
continue;
first = firstmsg(i+1);
last = lastmsg(i+1);
if (lastread[i] > last)
lastread[i] = last;
else if ((lastread[i] < first) && (lastread[i] != 0))
lastread[i] = first;
else if (!msgat(i+1,lastread[i]))
lastread[i] = msgprev(i+1,lastread[i]);
if (current[i] > lastread[i])
current[i] = lastread[i];
else if (current[i] < first)
current[i] = first;
} /* for */
return TRUE;
} /* openmsgbase */
/*
* Return the number of messages in a board
*/
#define COUNTMSG(board) (msginfo.activemsgs[(board)-1]) /* local version */
int countmsg(BYTE board) /* for external calls */
{
return COUNTMSG(board);
} /* countmsg */
/*
* Update the current and lastread pointers to disk
*/
static BOOLEAN updatecurlast(void)
{
struct stat st;
int count;
BOOLEAN result = TRUE;
if (currentdirty) {
BYTE b;
for (b = 0; b < BLIM; b++)
if (COUNTMSG(b+1) == 0)
current[b] = 0;
st.st_size = 0;
fstat(F[f_cur], &st);
count = (int)(st.st_size/sizeof(current)); /* current size of file */
if (usernum <= count) {
if (lseek(F[f_cur], (long)usernum * sizeof(current), SEEK_SET) == -1)
result = FALSE;
if (write(F[f_cur], (char *)current, sizeof(current)) != sizeof(current))
result = FALSE;
} else {
while (count <= usernum) {
if (lseek(F[f_cur], (long)count * sizeof(current), SEEK_SET) == -1)
result = FALSE;
if (write(F[f_cur], (char *)current, sizeof(current)) != sizeof(current))
result = FALSE;
++count;
} /* while */
} /* else */
} /* if */
if (lastreaddirty) {
BYTE b;
for (b = 1; b <= BLIM; b++)
if (lastread[b-1] > lastmsg(b))
setlastread(b, lastmsg(b));
if (lseek(F[f_last], (long)usernum * sizeof(lastread), SEEK_SET) == -1)
result = FALSE;
if (write(F[f_last], (char *)lastread, sizeof(lastread)) != sizeof(lastread))
result = FALSE;
} /* if */
return(result);
} /* updatecurlast */
/*
* Close all message base files
* Return TRUE if ok
*/
BOOLEAN closemsgbase()
{
BYTE i;
BOOLEAN result = TRUE;
if (!updatecurlast())
result = FALSE;
for (i = f_first; i <= f_last; i++)
if (F[i] != 0)
if (close(F[i]) == -1)
result = FALSE;
free(msgidx);
msgidx = NULL;
for (i = f_first; i <= f_last; i++)
F[i] = 0;
return(result);
} /* closemsgbase */
/*
* Update the directory entry of a file
*/
static BOOLEAN flushfile(int fd)
{
int new;
if ((new = dup(fd)) == -1) /* duplicate the file handle */
return(FALSE);
if (close(new) == -1) /* and close the duplicate */
return(FALSE);
return(TRUE);
} /* flushfile */
/*
* Flush message base
* Make sure FAT is updated by closing and opening all message files
*/
BOOLEAN flushmsgbase()
{
BYTE i;
BOOLEAN result = TRUE;
if (!updatecurlast())
result = FALSE;
for (i = f_first; i <= f_last; i++) /* flush all files */
if (!flushfile(F[i]))
result = FALSE;
return(result);
} /* flushmsgbase */
/*
* Return the current message of a board
*/
int curmsg(BYTE board)
{
return(current[board-1]);
} /* curmsg */
/*
* Return the 'lastread' message of a board
*/
int lastreadmsg(BYTE board)
{
return(lastread[board-1]);
} /* lastreadmsg */
/*
* Set the 'current' message of a board
*/
void setcur(BYTE board, int msgnum)
{
currentdirty = TRUE;
current[board-1] = msgnum;
} /* setcur */
/*
* Set the 'lastread' message of a board
*/
void setlastread(BYTE board, int msgnum)
{
lastreaddirty = TRUE;
lastread[board-1] = msgnum;
} /* setlastread */
/*
* Return the number of the message in the board
* Returns 0 if message not in board
*/
int boardmsg(BYTE board, int cur)
{
register IDXRECORD *step;
register int fcount;
int count = 0;
for (step = msgidx, fcount = filemsgs; fcount--; step++)
if ((step->board == board) && (step->msgnum != -1)) {
++count;
if (step->msgnum == cur)
return count;
} /* if */
return 0;
} /* boardmsg */
/*
* Return the number of first message found in the board
* Return 0 if the board is empty
*/
int firstmsg(BYTE board)
{
register IDXRECORD *step;
int count;
if (COUNTMSG(board) == 0) return 0;
for (step = msgidx, count = filemsgs; count--; step++)
if ((step->board == board) && (step->msgnum != -1))
return(step->msgnum);
return 0;
} /* firstmsg */
/*
* Return the number of the last message in the board
* Return 0 if the board is empty
*/
int lastmsg(BYTE board)
{
register IDXRECORD *step;
int count;
if (COUNTMSG(board) == 0) return 0;
for (step = &msgidx[filemsgs-1], count = filemsgs; count--; step--)
if ((step->board == board) && (step->msgnum != -1))
return(step->msgnum);
return 0;
} /* lastmsg */
/*
* Binary search in msgidx
* Handles deleted entries (out of sort) by skipping alternatingly
* left and right from the middle until a non-deleted entry is found.
* May become slower when there are a lot of deleted entries.
*/
#ifndef NOBINSEARCH
#ifdef OLDBINIDX
static int binidx(int num, BOOLEAN *found)
{
int mid, stab, skip, skipend;
register int left = 0;
register int right = (filemsgs-1);
*found = TRUE;
while (left <= right) {
skip = 1;
mid = (left+right)/2;
skipend = (max(mid-left,right-mid))*2 + 1;
do {
if ((mid >= left) && (mid <= right))
if ((stab = msgidx[mid].msgnum) != -1)
break; /* found non-deleted msg */
mid += skip; /* do a sideways step */
skip = (skip < 0) ? (-skip)+1 : -(skip+1); /* +1 -2 +3 -4 +5 -6 ... */
} while (abs(skip) <= skipend);
if (stab == -1) break; /* return FALSE */
if (num == stab)
return(mid);
if (num < stab)
right = mid-1;
else
left = mid+1;
} /* while */
*found = FALSE;
return(left);
} /* binidx */
#else
static int binidx(int num, BOOLEAN *found)
{
# define X ((unsigned int)num)
# define A(i) ((unsigned int)msgidx[i].msgnum)
# define M ((unsigned int)-1)
# define N filemsgs
register unsigned int a,b;
*found = FALSE;
if (N <= 0) return 0;
a = 0; b = N-1;
while (a != b) {
register unsigned int m = (a+b) / 2;
if (A(m) == X)
a = b = m;
else if (A(m) < X)
a = m+1;
else if ((A(m) > X) && (A(m) != M))
b = m;
else if ((A(b) > X) && (A(m) == M))
--b;
else if ((A(b) <= X) && (A(m) == M))
a = b;
}
*found = (A(a) == X);
return a;
}
#undef X
#undef A
#undef M
#undef N
#endif
#endif
/*
* Return the number of the next message in the board
* Return last message if next message not found
*/
int msgnext(BYTE board, int cur)
{
int step;
if (COUNTMSG(board) == 0) return 0;
#ifdef NOBINSEARCH
step = -1;
#else
{ BOOLEAN found; /* not used */
step = binidx(cur,&found);
}
#endif
while (++step < filemsgs) /* not full match, look further */
if (msgidx[step].board == board) /*&& (msgidx[step].msgnum != -1)*/
if (msgidx[step].msgnum > cur)
return(msgidx[step].msgnum);
return(lastmsg(board)); /* no greater msg found, 'cur' must be last message */
} /* msgnext */
/*
* Return the number of the previous message in the board
* Return first message if previous not found
*/
int msgprev(BYTE board, int cur)
{
int step;
if (COUNTMSG(board) == 0) return 0;
#ifdef NOBINSEARCH
step = filemsgs;
#else
{ BOOLEAN found; /* not used */
step = binidx(cur,&found);
}
#endif
while (--step >= 0)
if ((msgidx[step].board == board) && (msgidx[step].msgnum != -1))
if (msgidx[step].msgnum < cur)
return(msgidx[step].msgnum);
return(firstmsg(board)); /* no smaller msg found, 'cur' must be first */
} /* msgprev */
/*
* Return the file message number of a message (may be 0)
* Return -1 if not found
*/
int filemsg(int msgnum)
{
int step;
if ((msgnum > msginfo.highmsg) || (msgnum < msginfo.lowmsg))
return(-1);
#ifdef NOBINSEARCH
for (step = 0; step < filemsgs; step++)
if (msgidx[step].msgnum == msgnum)
return(step);
#else
{ BOOLEAN found;
step = binidx(msgnum,&found);
if (found)
return(step);
}
#endif
return(-1);
} /* filemsg */
/*
* Return TRUE if there is a 'msgnum' in the Board
*/
BOOLEAN msgat(BYTE board, int msgnum)
{
int fmsg;
if ((msgnum == -1) || ((fmsg = filemsg(msgnum)) == -1))
return FALSE;
return(msgidx[fmsg].board == board);
} /* msgat */
/*
* Read a message header
* Return TRUE if ok
*/
BOOLEAN readheader(int msgnum, MSGHEADER *m)
{
int n;
if ((n = filemsg(msgnum)) == -1)
return FALSE;
if (lseek(F[f_hdr], (long)n * sizeof(MSGHEADER), SEEK_SET) == -1)
return FALSE;
if (read(F[f_hdr], (char *)m, sizeof(MSGHEADER)) != sizeof(MSGHEADER))
return FALSE;
p2c_strn(m->posttime,5); /* pascal to c strings */
p2c_strn(m->postdate,8);
p2c_strn(m->to,35);
p2c_strn(m->from,35);
p2c_strn(m->subj,72);
return TRUE;
} /* readheader */
/*
* Write the header of a message
* Message number must be in index file in memory
*/
BOOLEAN writeheader(MSGHEADER *hdr)
{
MSGHEADER m; /* local copy */
int fmsg;
m = *hdr; /* make a local copy */
if ((fmsg = filemsg(m.msgnum)) == -1) return FALSE;
c2p_str(m.posttime);
c2p_str(m.postdate);
c2p_str(m.to);
c2p_str(m.from);
c2p_str(m.subj);
if (lseek(F[f_hdr], (long)fmsg * sizeof(MSGHEADER),SEEK_SET) == -1) return FALSE;
if (write(F[f_hdr], (char *)&m, sizeof(MSGHEADER)) != sizeof(MSGHEADER)) return FALSE;
return TRUE;
} /* writeheader */
/*
* Allocate and read the text of a message
* Return NULL if not ok
* MSGLINK.C knows a lot about this function, e.g. which fields of
* m it doesn't access...
*/
char *readtext(MSGHEADER *m)
{
char *text, *step;
int count;
if (m->numrecs == 0) /* is empty message */
return(calloc(1,1)); /* empty string or NULL */
if (lseek(F[f_txt], (long)m->startrec * 256, SEEK_SET) == -1)
return NULL;
if ((text = calloc(m->numrecs,256)) == NULL)
return NULL;
step = text; /* now read the text */
for (count = 0; count < m->numrecs; count++) {
/* working(YES); */
if (read(F[f_txt], step, 256) != 256) {
free(text);
return NULL;
} /* if */
p2c_str(step); /* pascal to c string */
step += strlen(step); /* move step to EOS */
} /* for */
/* working(NO); */
return(realloc(text, strlen(text)+1)); /* return text or NULL */
} /* readtext */
/*
* Increment message counters in msginfo.bbs
* Return TRUE if ok
*/
BOOLEAN incmsginfo(BYTE board)
{
msginfo.highmsg++;
msginfo.totalactive++;
msginfo.activemsgs[board-1]++;
if (lseek(F[f_info],0L,SEEK_SET) == -1)
return FALSE;
if (write(F[f_info], (char *)&msginfo, sizeof(msginfo)) != sizeof(msginfo))
return FALSE;
return TRUE;
} /* incmsginfo */
/*
* Return the next available message number for message creation
*/
int newmsgnum()
{
return(msginfo.highmsg+1);
} /* newmsgnum */
/*
* Set one record of msgidx.bbs
* Return TRUE if ok
*/
BOOLEAN writemsgidx(int fmsg, int msgnum, BYTE board)
{
if (fmsg >= filemsgs) {
filemsgs = fmsg+1;
if ((msgidx = realloc(msgidx, filemsgs*sizeof(IDXRECORD))) == NULL)
return(FALSE); /* pssst: this is a DISASTER! */
} /* if */
msgidx[fmsg].msgnum = msgnum;
msgidx[fmsg].board = board;
if (lseek(F[f_idx],(long)fmsg * sizeof(IDXRECORD),SEEK_SET) == -1)
return FALSE;
if (write(F[f_idx], (char *)&msgidx[fmsg], sizeof(IDXRECORD)) != sizeof(IDXRECORD))
return FALSE;
return TRUE;
} /* writemsgidx */
/*
* Write the msgtxt.bbs and msghdr.bbs files
* Return TRUE if ok
*/
BOOLEAN writemsgtxthdr(MSGHEADER *hdr, BOOLEAN oldmsg, char *textbuf)
{
MSGHEADER oldhdr;
int needrecs; /* number of records needed */
long pos;
int c1, ch;
static char wstr[256];
needrecs = ((strlen(textbuf)+254) / 255);
if (oldmsg) { /* get old header */
if (!readheader(hdr->msgnum, &oldhdr))
return FALSE;
} else oldhdr.numrecs = 0;
if ((!oldmsg) || (needrecs > oldhdr.numrecs)) { /* need more records */
if ((pos = lseek(F[f_txt],0L,SEEK_END)) == -1) return FALSE;
hdr->startrec = (int)(pos/256);
} else { /* overwrite old text */
if (lseek(F[f_txt], (long)oldhdr.startrec * 256,SEEK_SET) == -1) return FALSE;
hdr->startrec = oldhdr.startrec;
} /* else */
hdr->numrecs = 0;
c1 = 0; /* now write the text */
memset (wstr, 0, sizeof(wstr));
for (;;) {
ch = *textbuf++;
if ((c1 == 255) || (ch == EOS)) {
wstr[0] = c1; /* terminate current string */
if (write(F[f_txt], wstr, sizeof(wstr)) != sizeof(wstr)) return FALSE;
hdr->numrecs++; /* next record number */
if (ch == 0)
break; /* out of forever */
else {
memset(wstr, 0, sizeof(wstr));
c1 = 0;
} /* else */
} /* if */
wstr[++c1] = ch;
} /* forever */
if (!writeheader(hdr)) return FALSE;
return TRUE;
} /* writemsgtxthdr */
/*
* Overwrite or add to msgtoidx.bbs
* Return TRUE if ok
*/
BOOLEAN writetoidx(int fmsg, char *to)
{
static char buf[36];
memset(buf,0,sizeof(buf));
strncpy(buf,to,35);
c2p_str(buf);
if (lseek(F[f_toidx], (long)fmsg * 36, SEEK_SET) == -1) return FALSE;
if (write(F[f_toidx], buf,sizeof(buf)) != sizeof(buf)) return FALSE;
return TRUE;
} /* writetoidx */
/*
* Read from MSGTOIDX.BBS
* Return pointer to static area or NULL if error
*/
char *readtoidx(int fmsg)
{
static char buf[36];
if (lseek(F[f_toidx], (long)fmsg * 36, SEEK_SET) == -1) return NULL;
if (read(F[f_toidx], &buf[0], sizeof(buf)) != sizeof(buf)) return NULL;
p2c_strn(buf,35);
return(buf);
} /* readtoidx */
/*
* Write ECHOMAIL.BBS or NETMAIL.BBS
* Return TRUE if ok
*/
static BOOLEAN updatetosslog(int num, BOOLEAN echomail, BOOLEAN delete)
{
int fd, pos, *tosslog;
struct stat st;
char *name = (echomail ? "echomail.bbs" : "netmail.bbs");
if ((fd = open(expandbbs(name), O_RDWR|O_BINARY|O_CREAT,
S_IREAD|S_IWRITE)) == -1)
return FALSE;
fstat(fd, &st); /* get size */
tosslog = (int *)malloc((int)st.st_size+2); /* add space for insert */
if ((tosslog != NULL) && (st.st_size != 0)) {
read(fd,(char *)tosslog, (int)st.st_size);
for (pos = (int)(st.st_size/2-1); pos >= 0; pos--)
if (tosslog[pos] == num) break;
} else pos = -1;
if (delete) { /* remove a number */
if (pos >= 0) { /* was found */
if (st.st_size-pos*2 > 2)
memmove(&tosslog[pos], &tosslog[pos+1], st.st_size-pos*2-2); /* delete */
lseek(fd,0L,SEEK_SET); /* rewind */
st.st_size -= 2; /* shorten it */
write(fd,(char *)tosslog,st.st_size); /* all but last */
chsize(fd,st.st_size); /* change file size */
} /* if */
} else { /* add a number */
if (pos < 0) { /* was not found (not serious) */
int len = st.st_size/2; /* number of elements */
pos = 0;
while ((pos < len) && (tosslog[pos] < num)) /* search */
pos++;
if (pos < len) /* make space */
memmove(&tosslog[pos+1], &tosslog[pos], (len-pos)*2);
tosslog[pos] = num; /* enter new */
st.st_size += 2; /* add to length */
lseek(fd,0L,SEEK_SET); /* rewind */
write(fd,(char *)tosslog,st.st_size); /* and write it */
} /* if */
} /* else */
if (tosslog != NULL) free(tosslog);
if (close(fd) == -1) return FALSE;
if (st.st_size == 0) /* if empty, remove it */
unlink(expandbbs(name));
return TRUE;
} /* updatetosslog */
/*
* Delete the message (only on current area because of tosslog)
* Return TRUE if ok
*/
BOOLEAN msgdelete(int msgnum, BOOLEAN echomail, BOOLEAN netmail)
{
MSGHEADER hdr, to, from;
int fmsg;
BYTE board;
int nto = 0;
int nfrm = 0;
if ((fmsg = filemsg(msgnum)) == -1)
return FALSE; /* no such message! */
board = msgidx[fmsg].board; /* board number of the message */
/* First set the deleted bit in MSGHDR.BBS */
if (!readheader(msgnum, &hdr))
return FALSE;
if (hdr.bits.is_del)
return TRUE; /* strange... but true? */
hdr.bits.is_del = 1; /* mark it deleted */
if (!writeheader(&hdr))
return FALSE;
/* Now modify the reply links */
nto = hdr.reply; /* 'to' means link 'to' this header */
nfrm = hdr.up; /* 'from' means link 'from' this header */
if (nto != 0)
if (!readheader(nto, &to))
nto = 0;
if (nfrm != 0)
if (!readheader(nfrm, &from))
nfrm = 0;
from.reply = nto;
to.up = nfrm;
if (nto != 0) /* write the headers */
writeheader(&to); /* ignore errors */
if (nfrm != 0)
writeheader(&from);
/* Update MSGIDX.BBS */
if (!writemsgidx(fmsg, -1, 0))
return FALSE;
/* Update MSGINFO.BBS */
msginfo.totalactive--;
msginfo.activemsgs[board-1]--;
if (msgnum == msginfo.lowmsg) /* was the low message */
msginfo.lowmsg++; /* so increment it */
/* I am not convinced that this is correct... What happens if the new
'lowmsg' doesn't exist? Ahh well... no documentation... ho hum. */
if (lseek(F[f_info],0L,SEEK_SET) == -1)
return FALSE;
if (write(F[f_info], (char *)&msginfo, sizeof(msginfo)) != sizeof(msginfo))
return FALSE;
/* Update MSGTOIDX.BBS */
if (!writetoidx(fmsg, "* Deleted *"))
return FALSE;
if (echomail) {
if (!updatetosslog(fmsg,TRUE,TRUE))
return FALSE;
} else if (netmail) {
if (!updatetosslog(fmsg,FALSE,TRUE))
return FALSE;
} /* else */
return TRUE; /* all done */
} /* msgdelete */
/*
* Write a message into the message base
* This is about the highest level function provided
*/
BOOLEAN writebase(MSGHEADER *header, BYTE board, char *textbuf,
BOOLEAN echomail, BOOLEAN netmail)
{
int fmsg;
BOOLEAN oldmsg;
fmsg = filemsg(header->msgnum);
oldmsg = (fmsg != -1);
if (!oldmsg)
fmsg = filemsgs; /* next message */
if (!writetoidx(fmsg, header->to))
return(FALSE);
if (!oldmsg)
if (!incmsginfo(board))
return(FALSE);
if (!writemsgidx(fmsg, header->msgnum, board))
return(FALSE);
if (!writemsgtxthdr(header, oldmsg, textbuf))
return(FALSE);
if (echomail) {
if (!updatetosslog(fmsg,TRUE,FALSE))
return(FALSE);
} else if (netmail) {
if (!updatetosslog(fmsg,FALSE,FALSE))
return(FALSE);
} /* else */
return(TRUE);
} /* writebase */
/*
* Convert the time and date to Dos 32-bit format
*/
DWORD dostime(char *t, char *d, BOOLEAN fudge)
{
int day, mon, year, hour, min;
struct ftime dtime;
sscanf(t, "%d:%d", &hour, &min);
sscanf(d, "%d-%d-%d", &mon, &day, &year);
if (fudge) /* a little more variation */
dtime.ft_tsec = ((clock()/(int)CLK_TCK)/2) % 30;
else
dtime.ft_tsec = 0;
dtime.ft_min = min;
dtime.ft_hour = hour;
dtime.ft_day = day;
dtime.ft_month = mon;
dtime.ft_year = year-80;
return(*((DWORD*)((void *)&dtime)));
} /* dostime */
/*
* Check the message base files
* Call immediately after openmsgbase()
* Returns (in result and var parameter board):
* CHK_NOERR - no errors found
* CHK_NONINC - message numbers non-increasing in board (MSGIDX.BBS)
* CHK_COUNTS - message counts in MSGINFO.BBS different from MSGIDX.BBS
* CHK_HDR - length of MSGHDR.BBS different from MSGIDX.BBS
* CHK_TO - length of MSGTOIDX.BBS different from MSGIDX.BBS
*/
int checkmsgbase(BYTE *boardresult)
{
WORD board[BLIM], msgs[BLIM];
IDXRECORD *idx;
WORD count;
struct stat st;
*boardresult = 0;
memset(&board[0],0,sizeof board); /* last number in board */
memset(&msgs[0],0,sizeof msgs); /* number of messages */
for (idx = msgidx, count = 0; count < filemsgs; ++idx, ++count) {
if (idx->msgnum == -1)
continue; /* skip deleted messages */
if (idx->msgnum <= board[idx->board-1]) {
/* non-increasing number found in board */
*boardresult = idx->board; /* return board number */
return CHK_NONINC; /* non-increasing */
} /* if */
board[idx->board-1] = idx->msgnum; /* last num seen for board */
++msgs[idx->board-1]; /* another message in board */
} /* for */
for (count = 0; count < BLIM; ++count)
if (msgs[count] != msginfo.activemsgs[count]) {
/* count of messages is wrong */
*boardresult = count+1;
return CHK_COUNTS; /* count wrong */
} /* if */
if (fstat(F[f_hdr],&st) != 0)
st.st_size = 0;
count = st.st_size/sizeof(MSGHEADER); /* records in MSGHDR.BBS */
if (count != filemsgs)
return CHK_HDR; /* not same as MSGIDX.BBS */
if (fstat(F[f_toidx],&st) != 0)
st.st_size = 0;
count = st.st_size/36; /* records in MSGTOIDX.BBS */
if (count != filemsgs)
return CHK_TO; /* not same as MSGIDX.BBS */
return CHK_NOERR; /* no errors found */
} /* checkmsgbase */