home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
vol_100
/
129_01
/
210msg.c
< prev
next >
Wrap
Text File
|
1985-03-10
|
33KB
|
1,104 lines
/************************************************************************/
/* msg.c */
/* */
/* Message handling for Citadel bulletin board system */
/************************************************************************/
/************************************************************************/
/* history */
/* */
/* 84Dec16 HAW&JLS printMessage modified for new WC protocol. */
/* 84Dec08 HAW Fix bug caused by HAW when he implemented automailresp. */
/* 84Sep18 JLS Normalize recipient's name. */
/* 84Jul03 HAW mPrintf, dPrintf, and mWCprintf upgraded to BDS 1.50a. */
/* 84Jun23 HAW & JLS Unused local variables zapped. */
/* 84Jun07 HAW Responses in Mail now automatically get recipient. */
/* 84May07 JLS & HAW Implemented the configuration switch ENTEROK. */
/* 84Mar29 HAW Start upgrade to BDS C 1.50a, identify _spr problem. */
/* 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 <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*/
/* 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);
getRoom(AIDEROOM);
strCpy(msgBuf.mbauth, "Citadel");
msgBuf.mbto[0] = '\0';
if (putMessage( /* uploading== */ FALSE)) noteMessage(0, ERROR);
if (noteDeletedMessage) {
note2Message(pulledMId, pulledMLoc);
}
putRoom(AIDEROOM);
noteRoom();
getRoom(ourRoom);
}
/************************************************************************/
/* 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;
{
int putMsgChar();
_spr(&format, putMsgChar);
}
/************************************************************************/
/* 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;
}
}
}
/************************************************************************/
/* flushMsgBuf() wraps up writing a message to disk */
/************************************************************************/
flushMsgBuf() {
seek(msgfl, thisSector, 0);
crypte(sectBuf, SECTSIZE, 0);
if (write(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;
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;
seek(msgfl, thisSector, 0);
if (read(msgfl, sectBuf, 1) >= 1000) {
printf("?nextMsgChar-read 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, oldEcho;
/* Check for abort/pause from user */
if (!BBSCharReady()) {
toReturn = FALSE;
} else {
oldEcho = echo;
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 = oldEcho;
}
return toReturn;
}
/************************************************************************/
/* makeMessage is menu-level routine to enter a message */
/* Return: TRUE if message saved else FALSE */
/************************************************************************/
makeMessage(uploading, name_Auth)
char *name_Auth; /* name of recipient unless name_Auth == 0 */
char uploading; /* TRUE if message is coming via WC protocol */
{
char putMessage();
char allUpper, *pc, toReturn;
struct logBuffer lBuf;
int logNo;
toReturn = FALSE;
logNo = ERROR;/* not needed, but it's nice to initialize... */
if (thisRoom != MAILROOM && !loggedIn && !unlogEnterOk) {
mPrintf("Must log in to enter messages except MAIL to the SYSOP\n ");
return FALSE;
}
if (thisRoom != MAILROOM) msgBuf.mbto[0] = FALSE;
else {
if (!loggedIn || (!aide && noMail)) {
strCpy(msgBuf.mbto, "Sysop");
mPrintf(" (private mail to 'sysop')\n ");
} else {
if (name_Auth == 0)
getNormStr("recipient", msgBuf.mbto, NAMESIZE);
else
strcpy(msgBuf.mbto, name_Auth);
logNo = findPerson(msgBuf.mbto, &lBuf);
if ((logNo==ERROR && hash(msgBuf.mbto) != hash("Sysop")) ||
strlen(msgBuf.mbto) == 0) {
mPrintf("No '%s' known", msgBuf.mbto);
return FALSE;
}
if (hash(msgBuf.mbto) != hash("Sysop"))
strCpy(msgBuf.mbto, lBuf.lbname);
}
}
strcpy(msgBuf.mbauth, logBuf.lbname); /* record author*/
if (uploading ||
getText("message", msgBuf.mbtext, MAXTEXT, msgBuf.mbto)) {
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);
seek(msgfl, s, 0);
read(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 */
{
int _sspr();
char mAbort();
char string[MAXWORD], wordBuf[MAXWORD], *s;
int i;
s = string;
_spr(&format, &_sspr, &s); /* _sspr is a BDS internal function for */
/* sprintf. */
*s = '\0';
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;
{
int sendWCChar();
_spr(&format, &sendWCChar);
sendWCChar(0); /* Send NULL since it did before */
}
/************************************************************************/
/* 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;
{
if (!++newestLo) ++newestHi; /* 32-bit '++' by hand */
logBuf.lbvisit[0] = newestLo;
if (thisRoom != MAILROOM) {
note2Message(newestLo, catSector);
/* write it to disk: */
putRoom(thisRoom);
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);
/* enter in Aide> room -- 'sysop' is special */
note2Message(newestLo, catSector);
/* write it to disk: */
putRoom(AIDEROOM);
noteRoom();
getRoom(MAILROOM);
/* 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.msg[i].rbmsgLoc = roomBuf.msg[i+1].rbmsgLoc;
roomBuf.msg[i].rbmsgNo = roomBuf.msg[i+1].rbmsgNo ;
}
/* slot this message in: */
roomBuf.msg[MSGSPERRM-1].rbmsgNo = id ;
roomBuf.msg[MSGSPERRM-1].rbmsgLoc = loc;
}
/************************************************************************/
/* printMessage() prints indicated message on modem & console */
/************************************************************************/
printMessage(loc, id, name_Auth)
char *name_Auth; /* Author buffer if thisRoom == mailRoom */
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 (thisRoom == MAILROOM)
strcpy(name_Auth, 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();
while (1) {
moreFollows = dGetWord(msgBuf.mbtext, 150);
putWord(msgBuf.mbtext);
if (!(moreFollows && !mAbort())) {
if (outFlag == OUTNEXT) /* If <N>ext, extra line */
doCR();
break;
}
}
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';
if (!sendWCChar(c)) break;
} while (c);
}
}
/************************************************************************/
/* pullIt() is a aide special to remove a message from a room */
/************************************************************************/
pullIt(m)
int m;
{
int i;
char blah[NAMESIZE];
/* confirm that we're removing the right one: */
outFlag = OUTOK;
printMessage(roomBuf.msg[m].rbmsgLoc, roomBuf.msg[m].rbmsgNo, blah);
if (!getYesNo("pull")) return FALSE;
/* record vital statistics for possible insertion elsewhere: */
pulledMLoc = roomBuf.msg[m].rbmsgLoc;
pulledMId = roomBuf.msg[m].rbmsgNo ;
if (thisRoom == AIDEROOM) return TRUE;
/* return emptied slot: */
for (i=m; i>0; i--) {
roomBuf.msg[i].rbmsgLoc = roomBuf.msg[i-1].rbmsgLoc;
roomBuf.msg[i].rbmsgNo = roomBuf.msg[i-1].rbmsgNo ;
}
roomBuf.msg[0].rbmsgNo = 0; /* mark new slot at end as free */
roomBuf.msg[0].rbmsgLoc = ERROR; /* mark new slot at end as free */
/* store revised room to disk before we forget... */
noteRoom();
putRoom(thisRoom);
/* note in Aide>: */
sPrintf(msgBuf.mbtext, "Following message deleted by %s:", logBuf.lbname);
aideMessage( /* noteDeletedMessage == */ TRUE);
return TRUE;
}
/************************************************************************/
/************************************************************************/
char putMessage(uploading)
char uploading;
{
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: */
seek(msgfl, thisSector, 0);
crypte(sectBuf, SECTSIZE, 0);
if (write(msgfl, sectBuf, 1) != 1) {
printf("?putMsgChar-write fail");
toReturn = ERROR;
}
thisSector = ++thisSector % maxMSector;
seek(msgfl, thisSector, 0);
if (read(msgfl, sectBuf, 1) >= 1000) {
printf("?putMsgChar-read 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 name_Auth[NAMESIZE], pulled;
char toUpper(), iChar();
int i;
int start, finish, increment, msgNo;
unsigned lowLim, highLim;
setUp(FALSE);
if (whichIO != CONSOLE && thisRoom == MAILROOM) echo = CALLER;
/* 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.msg[i].rbmsgNo;
if (
msgNo - lowLim < 0x8000
&&
highLim - msgNo < 0x8000
) {
printMessage(roomBuf.msg[i].rbmsgLoc, msgNo, name_Auth);
if (usingWCprotocol && WCError)
return;
/* Pull current message from room if flag set */
if (pullMessage) {
pullMessage = FALSE;
pulled = pullIt(i);
if (revOrder) i++;
}
else
pulled = FALSE;
if (
!usingWCprotocol
&&
!pulled
&&
strCmpU(name_Auth, logBuf.lbname) != SAMESTRING
&&
thisRoom == MAILROOM
&&
whichMess == NEWoNLY
&&
getYesNo("respond")
) {
if (makeMessage( /* uploading== */ FALSE, name_Auth)) i--;
if (whichIO != CONSOLE && thisRoom == MAILROOM)
echo = CALLER; /* Restore privacy zapped by make... */
}
}
}
echo = BOTH;
}
/************************************************************************/
/* 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;
seek(msgfl, sect, 0);
if (read(msgfl, sectBuf, 1) >= 1000) {
printf("?startAt read 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;
seek(msgfl, 0, 0);
crypte(sectBuf, SECTSIZE, 0); /* encrypt */
if ((val = write(msgfl, sectBuf, 1)) != 1) {
printf("zapMsgFil: write failed, %d records!\n", val);
}
crypte(sectBuf, SECTSIZE, 0); /* decrypt */
sectBuf[0] = 0;
crypte(sectBuf, SECTSIZE, 0); /* encrypt */
for (sect=1; sect<maxMSector; sect++) {
seek(msgfl, sect, 0);
if ((val = write(msgfl, sectBuf, 1)) != 1) {
printf("zapMsgFil: write failed, wrote %d records!\n", val);
}
}
crypte(sectBuf, SECTSIZE, 0); /* decrypt */
}
roy all current messages? ");
if (toUpper(getCh()) != 'Y') re