home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************/
- /* msg.c */
- /* */
- /* Message handling for Citadel bulletin board system */
- /************************************************************************/
-
- /************************************************************************/
- /* history */
- /* */
- /* 83Mar03 CrT & SB Various bug fixes... */
- /* 83Feb27 CrT Save private mail for sender as well as recipient. */
- /* 83Feb23 Various. transmitFile() won't drop first char on WC... */
- /* 82Dec06 CrT 2.00 release. */
- /* 82Nov05 CrT Stream retrieval. Handles messages longer than MAXTEXT.*/
- /* 82Nov04 CrT Revised disk format implemented. */
- /* 82Nov03 CrT Individual history begun. General cleanup. */
- /************************************************************************/
-
- #include "b:210ctdl.h"
-
- /************************************************************************/
- /* contents */
- /* */
- /* aideMessage() saves auto message in Aide> */
- /* dGetWord() reads a word off disk */
- /* dPrintf() printf() that writes to disk */
- /* fakeFullCase() converts uppercase message to mixed case*/
- /* findPerson() load log record for named person */
- /* flushMsgBuf() wraps up message-to-disk store */
- /* getMessage() load message into RAM */
- /* getMsgChar() returns successive chars off disk */
- /* getMsgStr() reads a string out of message.buf */
- /* getWord() gets one word from message buffer */
- /* mAbort() checks for user abort of typeout */
- /* makeMessage() menu-level message-entry routine */
- /* mFormat() formats a string to modem and console */
- /* mPeek() sysop debugging tool--shows ctdlmsg.sys */
- /* mPrintf() writes a line to modem & console */
- /* mWCprintf() special mprintf for WC transfers */
- /* msgInit() sets up catChar, catSect etc. */
- /* noteLogMessage() enter message into log record */
- /* noteMessage() enter message into current room */
- /* note2Message() noteMessage() local */
- /* printMessage() prints a message on modem & console */
- /* pullIt() sysop special message-removal routine */
- /* putMessage() write message to disk */
- /* putMsgChar() writes successive message chars to disk */
- /* putWord() writes one word to modem & console */
- /* showMessages() menu-level show-roomful-of-messages fn */
- /* startAt() setup to read a message off disk */
- /* unGetMsgChar() return a char to getMsgChar() */
- /* zapMsgFile() initialize ctdlmsg.sys */
- /************************************************************************/
-
- /************************************************************************/
- /* aideMessage() saves auto message in Aide> */
- /************************************************************************/
- aideMessage(noteDeletedMessage)
- char noteDeletedMessage;
- {
- int ourRoom;
-
- /* message is already set up in msgBuf.mbtext */
- putRoom(ourRoom=thisRoom, &roomBuf);
- getRoom(AIDEROOM, &roomBuf);
-
- strCpy(msgBuf.mbauth, "Citadel");
- msgBuf.mbto[0] = '\0';
- if (putMessage( /* uploading== */ FALSE)) noteMessage(0, ERROR);
-
- if (noteDeletedMessage) {
- note2Message(pulledMId, pulledMLoc);
- }
-
- putRoom(AIDEROOM, &roomBuf);
- noteRoom();
- getRoom(ourRoom, &roomBuf);
- }
-
- /************************************************************************/
- /* dGetWord() fetches one word from current message, off disk */
- /* returns TRUE if more words follow, else FALSE */
- /************************************************************************/
- char dGetWord(dest, lim)
- char *dest;
- int lim;
- {
- char getMsgChar();
- char c;
-
- --lim; /* play it safe */
-
- /* pick up any leading blanks: */
- for (c = getMsgChar(); c == ' ' && c && lim; c = getMsgChar()) {
- if (lim) { *dest++ = c; lim--; }
- }
-
- /* step through word: */
- for ( ; c != ' ' && c && lim; c = getMsgChar()) {
- if (lim) { *dest++ = c; lim--; }
- }
-
- /* trailing blanks: */
- for ( ; c == ' ' && c && lim; c = getMsgChar()) {
- if (lim) { *dest++ = c; lim--; }
- }
-
- if (c) unGetMsgChar(c); /* took one too many */
-
- *dest = '\0'; /* tie off string */
-
- return c;
- }
-
- /************************************************************************/
- /* dPrintf() write from format+args to disk */
- /************************************************************************/
- dPrintf(format /* plus an unknown #arguments for format */)
- char *format;
- #define MAXWORD 256 /* maximum length of a word */
- {
- char *s, string[MAXWORD];
-
- string[0] = 0;
- _spr(string, &format);
-
- s = string;
- while (*s) putMsgChar(*s++);
- }
-
- /************************************************************************/
- /* fakeFullCase() converts a message in uppercase-only to a */
- /* reasonable mix. It can't possibly make matters worse... */
- /* Algorithm: First alphabetic after a period is uppercase, all */
- /* others are lowercase, excepting pronoun "I" is a special case. */
- /* We assume an imaginary period preceding the text. */
- /************************************************************************/
- fakeFullCase(text)
- char *text;
- {
- char toLower(), toUpper();
- char *c;
- char lastWasPeriod;
- char state;
-
- for(lastWasPeriod=TRUE, c=text; *c; c++) {
- if (
- *c != '.'
- &&
- *c != '?'
- &&
- *c != '!'
- ) {
- if (isAlpha(*c)) {
- if (lastWasPeriod) *c = toUpper(*c);
- else *c = toLower(*c);
- lastWasPeriod = FALSE;
- }
- } else {
- lastWasPeriod = TRUE ;
- }
- }
-
- /* little state machine to search for ' i ': */
- #define NUTHIN 0
- #define FIRSTBLANK 1
- #define BLANKI 2
- for (state=NUTHIN, c=text; *c; c++) {
- switch (state) {
- case NUTHIN:
- if (isSpace(*c)) state = FIRSTBLANK;
- else state = NUTHIN ;
- break;
- case FIRSTBLANK:
- if (*c == 'i') state = BLANKI ;
- else state = NUTHIN ;
- break;
- case BLANKI:
- if (isSpace(*c)) state = FIRSTBLANK;
- else state = NUTHIN ;
-
- if (!isAlpha(*c)) *(c-1) = 'I';
- break;
- }
- }
- }
-
- /************************************************************************/
- /* findPerson() loads log record for named person. */
- /* RETURNS: ERROR if not found, else log record # */
- /************************************************************************/
- int findPerson(name, lBuf)
- char *name;
- struct logBuffer *lBuf;
- {
- int h, i, foundIt, logNo;
-
- h = hash(name);
- for (foundIt=i=0; i<MAXLOGTAB && !foundIt; i++) {
- if (logTab[i].ltnmhash == h) {
- getLog(lBuf, logNo = logTab[i].ltlogSlot);
- if (strCmpU(name, lBuf->lbname) == SAMESTRING) {
- foundIt = TRUE;
- }
- }
- }
- if (!foundIt) return ERROR;
- else return logNo;
- }
-
- /************************************************************************/
- /* flushMsgBuf() wraps up writing a message to disk */
- /************************************************************************/
- flushMsgBuf() {
- rseek(msgfl, thisSector, 0);
- crypte(sectBuf, SECTSIZE, 0);
- if (rwrite(msgfl, sectBuf, 1) != 1) {
- printf("?ctdlmsg.sys write fail");
- }
- crypte(sectBuf, SECTSIZE, 0);
- }
-
- /************************************************************************/
- /* getMessage() reads a message off disk into RAM. */
- /* a previous call to setUp has specified the message. */
- /************************************************************************/
- getMessage() {
- char c;
-
- /* clear msgBuf out */
- msgBuf.mbauth[ 0] = '\0';
- msgBuf.mbdate[ 0] = '\0';
- msgBuf.mborig[ 0] = '\0';
- msgBuf.mboname[0] = '\0';
- msgBuf.mbroom[ 0] = '\0';
- msgBuf.mbsrcId[0] = '\0';
- msgBuf.mbtext[ 0] = '\0';
- msgBuf.mbto[ 0] = '\0';
-
- do c = getMsgChar(); while (c != 0xFF); /* find start of msg */
-
- msgBuf.mbheadChar = oldChar; /* record location */
- msgBuf.mbheadSector = oldSector;
-
- getMsgStr(msgBuf.mbId, NAMESIZE);
-
- do {
- c = getMsgChar();
- switch (c) {
- case 'A': getMsgStr(msgBuf.mbauth, NAMESIZE); break;
- case 'D': getMsgStr(msgBuf.mbdate, NAMESIZE); break;
- case 'M': /* just exit -- we'll read off disk */ break;
- case 'N': getMsgStr(msgBuf.mboname, NAMESIZE); break;
- case 'O': getMsgStr(msgBuf.mborig, NAMESIZE); break;
- case 'R': getMsgStr(msgBuf.mbroom, NAMESIZE); break;
- case 'S': getMsgStr(msgBuf.mbsrcId, NAMESIZE); break;
- case 'T': getMsgStr(msgBuf.mbto, NAMESIZE); break;
- default:
- getMsgStr(msgBuf.mbtext, MAXTEXT); /* discard unknown field */
- msgBuf.mbtext[0] = '\0';
- break;
- }
- } while (c != 'M' && isAlpha(c));
- }
-
- /************************************************************************/
- /* getMsgChar() returns sequential chars from message on disk */
- /************************************************************************/
- char getMsgChar() {
- char visible();
- char toReturn;
- int mark, val;
-
- if (GMCCache) { /* someone did an unGetMsgChar() --return it */
- toReturn= GMCCache;
- GMCCache= '\0';
- return toReturn;
- }
-
- oldChar = thisChar;
- oldSector = thisSector;
-
- toReturn = sectBuf[thisChar];
-
- #ifdef XYZZY
- if (debug) putCh(visible(toReturn));
- #endif
-
- thisChar = ++thisChar % SECTSIZE;
- if (thisChar == 0) {
- /* time to read next sector in: */
- thisSector = ++thisSector % maxMSector;
- rseek(msgfl, thisSector, 0);
- if (rread(msgfl, sectBuf, 1) >= 1000) {
- printf("?nextMsgChar-rread fail");
- }
- crypte(sectBuf, SECTSIZE, 0);
- }
- return(toReturn);
- }
-
- /************************************************************************/
- /* getMsgStr() reads a string from message.buf */
- /************************************************************************/
- getMsgStr(dest, lim)
- char *dest;
- int lim;
- {
- char c;
-
- while (c = getMsgChar()) { /* read the complete string */
- if (lim) { /* if we have room then */
- lim--;
- *dest++ = c; /* copy char to buffer */
- }
- }
- *dest = '\0'; /* tie string off with null */
- }
-
- /************************************************************************/
- /* getWord() fetches one word from current message */
- /************************************************************************/
- int getWord(dest, source, offset, lim)
- char *dest, *source;
- int lim, offset;
- {
- int i, j;
-
- /* skip leading blanks if any */
- for (i=0; source[offset+i]==' ' && i<lim; i++);
-
- /* step over word */
- for (;
-
- source[offset+i] != ' ' &&
- i < lim &&
- source[offset+i] != 0;
-
- i++
- );
-
- /* pick up any trailing blanks */
- for (; source[offset+i]==' ' && i<lim; i++);
-
- /* copy word over */
- for (j=0; j<i; j++) dest[j] = source[offset+j];
- dest[j] = 0; /* null to tie off string */
-
- return(offset+i);
- }
-
- /************************************************************************/
- /* mAbort() returns TRUE if the user has aborted typeout */
- /* Globals modified: outFlag */
- /************************************************************************/
- char mAbort() {
- char BBSCharReady(), iChar(), toUpper();
- char c, toReturn;
-
- /* Check for abort/pause from user */
- if (!BBSCharReady()) {
- toReturn = FALSE;
- } else {
- echo = NEITHER;
- c = toUpper(iChar());
- switch (c) {
- case XOFF:
- case 'P': /* pause: */
- c = iChar(); /* wait to resume */
- if (
- toLower(c) == 'd'
- &&
- aide
- ) pullMessage = TRUE;
- toReturn = FALSE;
- break;
- case 'J': /* jump paragraph:*/
- outFlag = OUTPARAGRAPH;
- toReturn = FALSE;
- break;
- case 'N': /* next: */
- outFlag = OUTNEXT;
- toReturn = TRUE;
- break;
- case 'S': /* skip: */
- outFlag = OUTSKIP;
- toReturn = TRUE;
- break;
- default:
- toReturn = FALSE;
- break;
- }
- echo = BOTH;
- }
- return toReturn;
- }
-
- /************************************************************************/
- /* makeMessage is menu-level routine to enter a message */
- /* Return: TRUE if message saved else FALSE */
- /************************************************************************/
- makeMessage(uploading)
- char uploading; /* TRUE if message is coming via WC protocol */
- {
- char putMessage();
- char allUpper, *pc, toReturn;
- char toName[NAMESIZE];
- struct logBuffer lBuf;
- int logNo;
-
- toReturn = FALSE;
-
- logNo = ERROR;/* not needed, but it's nice to initialize... */
-
- if (thisRoom != MAILROOM) msgBuf.mbto[0] = FALSE;
- else {
- if (!loggedIn) {
- strCpy(msgBuf.mbto, "Sysop");
- mPrintf(" (private mail to 'sysop')\n ");
- } else {
- getString("recipient", msgBuf.mbto, NAMESIZE);
- normalizeString(msgBuf.mbto);
- logNo = findPerson(msgBuf.mbto, &lBuf);
- if (logNo==ERROR && hash(msgBuf.mbto)!=hash("Sysop")) {
- mPrintf("No '%s' known", msgBuf.mbto);
- return FALSE;
- }
- }
- }
-
- strcpy(msgBuf.mbauth, logBuf.lbname); /* record author*/
- if (uploading || gettext("message", msgBuf.mbtext, MAXTEXT)) {
- if (!uploading) {
- for (pc=msgBuf.mbtext, allUpper=TRUE; *pc && allUpper; pc++) {
- if (toUpper(*pc) != *pc) allUpper = FALSE;
- }
- if (allUpper) fakeFullCase(msgBuf.mbtext, MAXTEXT);
- }
-
- if (toReturn=putMessage(uploading)) noteMessage(&lBuf, logNo);
- }
- return toReturn;
- }
-
- /************************************************************************/
- /* mFormat() formats a string to modem and console */
- /************************************************************************/
- mFormat(string)
- char *string;
- #define MAXWORD 256 /* maximum length of a word */
- {
- char wordBuf[MAXWORD];
- char mAbort();
- int i;
-
- for (i=0; string[i] && (!outFlag || outFlag==OUTPARAGRAPH); ) {
- i = getWord(wordBuf, string, i, MAXWORD);
- putWord(wordBuf);
- if (mAbort()) return;
- }
- }
-
- /************************************************************************/
- /* mPeek() dumps a sector in message.buf. sysop debugging tool */
- /************************************************************************/
- mPeek() {
- char visible();
- char peekBuf[SECTSIZE];
- int col, row, s;
-
- s = getNumber(" sector to dump", 0, maxMSector-1);
- rseek(msgfl, s, 0);
- rread(msgfl, peekBuf, 1);
- for (row=0; row<2; row++) {
- mPrintf("\n ");
- for (col=0; col<64; col++) {
- oChar(visible(peekBuf[row*64 +col]));
- }
- }
- }
-
- /************************************************************************/
- /* mPrintf() formats format+args to modem and console */
- /************************************************************************/
- mPrintf(format /* plus an unknown #arguments for format */)
- char *format;
- #define MAXWORD 256 /* maximum length of a word */
- {
- char mAbort();
- char string[MAXWORD], wordBuf[MAXWORD];
- int i;
-
- string[0] = 0;
- _spr(string, &format);
-
- for (i=0; string[i] && (!outFlag || outFlag==OUTPARAGRAPH); ) {
- i = getWord(wordBuf, string, i, MAXWORD);
- putWord(wordBuf);
-
- if (mAbort()) return;
- }
- }
-
- /************************************************************************/
- /* mWCprintf() formats format+args to sendWCChar() */
- /************************************************************************/
- mWCprintf(format /* plus an unknown #arguments for format */)
- char *format;
- {
- char *s;
- char string[MAXWORD];
-
- string[0] = 0;
- _spr(string, &format);
-
- s = string;
- do sendWCChar(*s); while (*s++); /* send terminal null also */
- }
-
- /************************************************************************/
- /* msgInit() sets up lowId, highId, catSector and catChar, */
- /* by scanning over message.buf */
- /************************************************************************/
- msgInit() {
- int aToI();
- int firstLo, firstHi, hereLo, hereHi; /* 32 bits by halves */
-
- startAt(0, 0);
- getMessage();
-
- /* get the ID# */
- sscanf(msgBuf.mbId, "%d %d", &firstHi, &firstLo);
- printf("message# %d %d\n", firstHi, firstLo);
- newestHi = firstHi;
- newestLo = firstLo;
-
- oldestHi = firstHi;
- oldestLo = firstLo;
-
- catSector = thisSector;
- catChar = thisChar;
-
- for (
- getMessage();
-
- sscanf(msgBuf.mbId, "%d %d", &hereHi, &hereLo),
- !(hereHi == firstHi && hereLo == firstLo);
-
- getMessage()
-
- ) {
- printf("message# %d %d\n", hereHi, hereLo);
-
- /* find highest and lowest message IDs: */
- /* 32-bit "<" by hand: */
- if ((hereHi<oldestHi) || (hereHi==oldestHi && hereLo<oldestLo)) {
- oldestHi = hereHi;
- oldestLo = hereLo;
- printf(" oldest=%u %u\n", oldestHi, oldestLo);
- }
- if ((hereHi>newestHi) || (hereHi==newestHi && hereLo>newestLo)) {
- newestHi = hereHi;
- newestLo = hereLo;
- printf(" newest=%u %u\n", newestHi, newestLo);
-
- /* read rest of message in and remember where it ends, */
- /* in case it turns out to be the last message */
- /* in which case, that's where to start writing next message*/
- while (dGetWord(msgBuf.mbtext, MAXTEXT));
- catSector = thisSector;
- catChar = thisChar;
- }
- }
- }
-
- /************************************************************************/
- /* noteLogMessage() slots message into log record */
- /************************************************************************/
- noteLogMessage(lBuf, logNo)
- struct logBuffer *lBuf;
- int logNo;
- {
- int i;
-
- /* store into recipient's log record: */
- /* slide message pointers down to make room for this one: */
- for (i=0; i<MAILSLOTS-1; i++) {
- (*lBuf).lbslot[i] = (*lBuf).lbslot[i+1];
- (*lBuf).lbId[ i] = (*lBuf).lbId[ i+1];
- }
-
- /* slot this message in: */
- (*lBuf).lbId[MAILSLOTS-1] = newestLo ;
- (*lBuf).lbslot[MAILSLOTS-1] = catSector;
-
- putLog(lBuf, logNo);
- }
-
- /************************************************************************/
- /* noteMessage() slots message into current room */
- /************************************************************************/
- noteMessage(lBuf, logNo)
- struct logBuffer *lBuf;
- int logNo;
- {
- int i, roomNo;
-
- if (!++newestLo) ++newestHi; /* 32-bit '++' by hand */
- logBuf.lbvisit[0] = newestLo;
-
- if (thisRoom != MAILROOM) {
- note2Message(newestLo, catSector);
-
- /* write it to disk: */
- putRoom(thisRoom, &roomBuf);
- noteRoom();
- } else {
- if (hash(msgBuf.mbto) != hash("Sysop")) {
- if (logNo != thisLog) {
- noteLogMessage(lBuf, logNo); /* note in recipient */
- }
- noteLogMessage(&logBuf, thisLog); /* note in ourself */
- fillMailRoom(); /* update room also */
- } else {
- getRoom(AIDEROOM, &roomBuf);
-
- /* enter in Aide> room -- 'sysop' is special */
- note2Message(newestLo, catSector);
-
- /* write it to disk: */
- putRoom(AIDEROOM, &roomBuf);
- noteRoom();
-
- getRoom(MAILROOM, &roomBuf);
- /* note in ourself if logged in: */
- if (loggedIn) noteLogMessage(&logBuf, thisLog);
- fillMailRoom();
- }
- }
-
- /* make message official: */
- catSector = thisSector;
- catChar = thisChar;
- setUp(FALSE);
- }
-
- /************************************************************************/
- /* note2Message() makes slot in current room... called by noteMess */
- /************************************************************************/
- note2Message(id, loc)
- int id, loc;
- {
- int i;
-
- /* store into current room: */
- /* slide message pointers down to make room for this one: */
- for (i=0; i<MSGSPERRM-1; i++) {
- roomBuf.vp.msg[i].rbmsgLoc = roomBuf.vp.msg[i+1].rbmsgLoc;
- roomBuf.vp.msg[i].rbmsgNo = roomBuf.vp.msg[i+1].rbmsgNo ;
- }
-
- /* slot this message in: */
- roomBuf.vp.msg[MSGSPERRM-1].rbmsgNo = id ;
- roomBuf.vp.msg[MSGSPERRM-1].rbmsgLoc = loc;
- }
-
-
- /************************************************************************/
- /* printMessage() prints indicated message on modem & console */
- /************************************************************************/
- printMessage(loc, id)
- int loc; /* sector in message.buf */
- unsigned id; /* unique-for-some-time ID# */
- {
- char dGetWord(), mAbort();
- char c, moreFollows;
- int hereHi, hereLo;
-
- startAt(loc, 0);
-
- do getMessage(); while (
- (
- sscanf(msgBuf.mbId, "%d %d", &hereHi, &hereLo),
- hereLo != id
- ) &&
- thisSector == loc
- );
- if (hereLo != id && !usingWCprotocol) {
- mPrintf("?can't find message");
- #ifdef XYZZY
- mPrintf(" loc=%d, id=%u, mbIds=%s, here=%d %d\n",
- loc, id, msgBuf.mbId, &hereHi, &hereLo
- );
- #endif
- return;
- }
-
- if (!usingWCprotocol) {
- doCR();
-
- if (msgBuf.mbdate[ 0]) mPrintf( " %s ", msgBuf.mbdate );
- if (msgBuf.mbauth[ 0]) mPrintf( "from %s", msgBuf.mbauth );
- if (msgBuf.mboname[0]) mPrintf( " @%s", msgBuf.mboname);
- if (
- msgBuf.mbroom[0]
- &&
- strCmp(msgBuf.mbroom, roomBuf.rbname) != SAMESTRING
- ) {
- mPrintf( " in %s>", msgBuf.mbroom );
- }
- if (msgBuf.mbto[ 0]) mPrintf( " to %s", msgBuf.mbto );
-
- doCR();
-
- do {
- moreFollows = dGetWord(msgBuf.mbtext, 150);
- putWord(msgBuf.mbtext);
- } while (moreFollows && !mAbort());
- doCR();
-
- } else {
- /* networking dump of message: */
-
- /* fill in local node in origin fields if local message: */
- if (!msgBuf.mborig[ 0]) strcpy(msgBuf.mborig, nodeId );
- if (!msgBuf.mboname[0]) strcpy(msgBuf.mboname, nodeName );
- if (!msgBuf.mbsrcId[0]) strcpy(msgBuf.mbsrcId, msgBuf.mbId);
-
- /* send header fields out: */
- if (msgBuf.mbauth[ 0]) mWCprintf("A%s", msgBuf.mbauth );
- if (msgBuf.mbdate[ 0]) mWCprintf("D%s", msgBuf.mbdate );
- if (msgBuf.mboname[0]) mWCprintf("N%s", msgBuf.mboname);
- if (msgBuf.mborig[ 0]) mWCprintf("O%s", msgBuf.mborig );
- if (msgBuf.mbroom[ 0]) mWCprintf("R%s", msgBuf.mbroom );
- if (msgBuf.mbsrcId[0]) mWCprintf("S%s", msgBuf.mbsrcId);
- if (msgBuf.mbto[ 0]) mWCprintf("T%s", msgBuf.mbto );
-
- /* send message text proper: */
- sendWCChar('M');
- do {
- c = getMsgChar();
- if (c=='\n') c='\r';
- sendWCChar(c);
- } while (c);
- }
- }
-
- /************************************************************************/
- /* pullIt() is a sysop special to remove a message from a room */
- /************************************************************************/
- pullIt(m)
- int m;
- {
- int i, low;
-
- /* confirm that we're removing the right one: */
- outFlag = OUTOK;
- printMessage(roomBuf.vp.msg[m].rbmsgLoc, roomBuf.vp.msg[m].rbmsgNo);
- if (!getYesNo("pull")) return;
-
- /* record vital statistics for possible insertion elsewhere: */
- pulledMLoc = roomBuf.vp.msg[m].rbmsgLoc;
- pulledMId = roomBuf.vp.msg[m].rbmsgNo ;
-
- if (thisRoom == AIDEROOM) return;
-
- /* return emptied slot: */
- for (i=m; i>0; i--) {
- roomBuf.vp.msg[i].rbmsgLoc = roomBuf.vp.msg[i-1].rbmsgLoc;
- roomBuf.vp.msg[i].rbmsgNo = roomBuf.vp.msg[i-1].rbmsgNo ;
- }
- roomBuf.vp.msg[0].rbmsgNo = ERROR; /* mark new slot at end as free */
-
- /* store revised room to disk before we forget... */
- noteRoom();
- putRoom(thisRoom, &roomBuf);
-
- /* note in Aide>: */
- sPrintf(msgBuf.mbtext, "Following message deleted by %s:", logBuf.lbname);
- aideMessage( /* noteDeletedMessage== */ TRUE);
- }
-
- /************************************************************************/
- /* putMessage() stores a message to disk */
- /* Always called before noteMessage() -- newestLo not ++ed yet. */
- /* Returns: TRUE on successful save, else FALSE */
- /************************************************************************/
- char putMessage(uploading)
- char uploading; /* true to get text via WC modem input, not RAM */
- {
- char *s, allOk;
- int putWCChar();
-
- startAt(catSector, catChar); /* tell putMsgChar where to write */
- putMsgChar(0xFF); /* start-of-message */
-
- /* write message ID */
- dPrintf("%u %u", newestHi, newestLo+1);
- putMsgChar(0);
-
- /* write date: */
- dPrintf("D%d%s%02d",
- interpret(pGetYear),
- monthTab[interpret(pGetMonth)],
- interpret(pGetDay)
- );
- putMsgChar(0);
-
- /* write room name out: */
- dPrintf("R%s", roomBuf.rbname);
- putMsgChar(0);
-
- if (loggedIn) {
- /* write author's name out: */
- dPrintf("A%s", msgBuf.mbauth);
- putMsgChar(0); /* null to end string */
- }
-
- if (msgBuf.mbto[0]) { /* private message -- write addressee */
- dPrintf("T%s", msgBuf.mbto);
- putMsgChar(0);
- }
-
- /* write message text by hand because it would overrun dPrintf buffer: */
- putMsgChar('M'); /* M-for-message. */
- if (!uploading) {
- for (s=msgBuf.mbtext; *s; s++) putMsgChar(*s);
- allOk = TRUE;
- } else {
- outFlag = FALSE; /* setup for putWCChar() */
- allOk = readFile(putWCChar);
- }
-
- if (allOk) {
- putMsgChar(0); /* null to end text */
-
- flushMsgBuf();
- } else {
- flushMsgBuf(); /* so message count is ok */
-
- /* erase start-of-message indicator: */
- startAt(catSector, catChar);
- putmsgChar(0); /* overwrite 0xFF byte */
- }
-
- return allOk;
- }
-
- /************************************************************************/
- /* putMsgChar() writes successive message chars to disk */
- /* Globals: thisChar= thisSector= */
- /* Returns: ERROR if problems else TRUE */
- /************************************************************************/
- int putMsgChar(c)
- char c;
- {
- char visible();
- int toReturn;
-
- toReturn = TRUE;
-
- #ifdef XYZZY
- if (debug) putch(visible(c));
- #endif
-
- if (sectBuf[thisChar] == 0xFF) {
- /* obliterating a msg */
- if (!++oldestLo) ++oldestHi; /* 32-bit increment by hand */
- logBuf.lbvisit[(MAXVISIT-1)] = oldestLo;
- }
-
- sectBuf[thisChar] = c;
-
- thisChar = ++thisChar % SECTSIZE;
-
- if (thisChar == 0) { /* time to write sector out a get next: */
- rseek(msgfl, thisSector, 0);
- crypte(sectBuf, SECTSIZE, 0);
- if (rwrite(msgfl, sectBuf, 1) != 1) {
- printf("?putMsgChar-rwrite fail");
- toReturn = ERROR;
- }
-
- thisSector = ++thisSector % maxMSector;
- rseek(msgfl, thisSector, 0);
- if (rread(msgfl, sectBuf, 1) >= 1000) {
- printf("?putMsgChar-rread fail");
- toReturn = ERROR;
- }
- crypte(sectBuf, SECTSIZE, 0);
- }
- return toReturn;
- }
-
- /************************************************************************/
- /* putWord() writes one word to modem & console */
- /************************************************************************/
- putWord(st)
- char *st;
- {
- char *s;
- int newColumn;
-
- for (newColumn=crtColumn, s=st; *s; s++) {
- if (*s != TAB) ++newColumn;
- else while (++newColumn % 8);
- }
- if (newColumn > termWidth) doCR();
-
- for (; *st; st++) {
-
- if (*st != TAB) ++crtColumn;
- else while (++crtColumn % 8);
-
- /* worry about words longer than a line: */
- if (crtColumn > termWidth) doCR();
-
- if (prevChar!=NEWLINE || (*st > ' ')) oChar(*st);
- else {
- /* end of paragraph: */
- if (outFlag == OUTPARAGRAPH) {
- outFlag = OUTOK;
- }
- doCR();
- oChar(*st);
- }
- }
- }
-
- /************************************************************************/
- /* showMessages() is routine to print roomful of msgs */
- /************************************************************************/
- showMessages(whichMess, revOrder)
- char whichMess, revOrder;
- {
- char toUpper(), iChar();
- char c;
- int i;
- int start, finish, increment, msgNo;
- unsigned lowLim, highLim;
-
- setUp(FALSE);
-
- /* Allow for reverse retrieval: */
- if (!revOrder) {
- start = 0;
- finish = MSGSPERRM;
- increment = 1;
- } else {
- start = (MSGSPERRM -1);
- finish = -1;
- increment = -1;
- }
-
- switch (whichMess) {
- case NEWoNLY:
- lowLim = logBuf.lbvisit[ logBuf.lbgen[thisRoom] & CALLMASK]+1;
- highLim = newestLo;
- break;
- case OLDaNDnEW:
- lowLim = oldestLo;
- highLim = newestLo;
- break;
- case OLDoNLY:
- lowLim = oldestLo;
- highLim = logBuf.lbvisit[ logBuf.lbgen[thisRoom] & CALLMASK];
- break;
- }
-
- /* stuff may have scrolled off system unseen, so: */
- /* was "if (lowLim < oldestLo)...", rigged for wraparound: */
- if (oldestLo-lowLim < 0x8000) {
- lowLim = oldestLo;
- }
- if (!expert && !usingWCprotocol) {
- mPrintf("\n <J>ump <N>ext <P>ause <S>top");
- }
-
- for (i=start; i!=finish; i+=increment) {
- if (outFlag) {
- if (
- outFlag == OUTNEXT
- ||
- outFlag == OUTPARAGRAPH
- ) outFlag = OUTOK;
- else if (outFlag == OUTSKIP) {
- echo = BOTH;
- return;
- }
- }
-
- /* "<" comparison with 64K wraparound in mind: */
- msgNo = roomBuf.vp.msg[i].rbmsgNo;
- if (
- msgNo - lowLim < 0x8000
- &&
- highLim - msgNo < 0x8000
- ) {
- printMessage(roomBuf.vp.msg[i].rbmsgLoc, msgNo);
-
- /* Pull current message from room if flag set */
- if (pullMessage) {
- pullMessage = FALSE;
- pullIt(i);
- if (revOrder) i++;
- }
-
- if (
- thisRoom == MAILROOM
- &&
- whichMess == NEWoNLY
- &&
- getYesNo("respond")
- ) {
- if (makeMessage( /* uploading== */ FALSE)) i--;
- }
- }
- }
- }
-
- /************************************************************************/
- /* startAt() sets location to begin reading message from */
- /************************************************************************/
- startAt(sect, byt)
- int sect;
- int byt;
- {
- GMCCache = '\0'; /* cache to unGetMsgChar() into */
-
- if (sect >= maxMSector) {
- printf("?startAt s=%d,b=%d", sect, byt);
- return;
- }
- thisChar = byt;
- thisSector = sect;
-
- rseek(msgfl, sect, 0);
- if (rread(msgfl, sectBuf, 1) >= 1000) {
- printf("?startAt rread fail");
- }
- crypte(sectBuf, SECTSIZE, 0);
- }
-
- /************************************************************************/
- /* unGetMsgChar() returns (at most one) char to getMsgChar() */
- /************************************************************************/
- unGetMsgChar(c)
- char c;
- {
- GMCCache = c;
- }
-
- /************************************************************************/
- /* zapMsgFl() initializes message.buf */
- /************************************************************************/
- zapMsgFile() {
- char getCh(), toUpper();
- int i, sect, val;
-
- printf("\nDestroy all current messages? ");
- if (toUpper(getCh()) != 'Y') return;
-
- /* put null message in first sector... */
- sectBuf[0] = 0xFF; /* \ */
- sectBuf[1] = '0'; /* \ */
- sectBuf[2] = ' '; /* > Message ID "0 1" */
- sectBuf[3] = '1'; /* / */
- sectBuf[4] = '\0'; /* / */
- sectBuf[5] = 'M'; /* \ Null messsage */
- sectBuf[6] = '\0'; /* / */
-
- for (i=7; i<SECTSIZE; i++) sectBuf[i] = 0;
-
- rseek(msgfl, 0, 0);
- crypte(sectBuf, SECTSIZE, 0); /* encrypt */
- if ((val = rwrite(msgfl, sectBuf, 1)) != 1) {
- printf("zapMsgFil: rwrite failed, %d records!\n", val);
- }
-
- crypte(sectBuf, SECTSIZE, 0); /* decrypt */
- sectBuf[0] = 0;
- crypte(sectBuf, SECTSIZE, 0); /* encrypt */
- for (sect=1; sect<maxMSector; sect++) {
- rseek(msgfl, sect, 0);
- if ((val = rwrite(msgfl, sectBuf, 1)) != 1) {
- printf("zapMsgFil: rwrite failed, wrote %d records!\n", val);
- }
- }
- crypte(sectBuf, SECTSIZE, 0); /* decrypt */
- }
-