home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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 */