home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************/
- /* roomb.c */
- /* room code for Citadel bulletin board system */
- /************************************************************************/
-
- /************************************************************************/
- /* History */
- /* */
- /* 83Feb26 CrT bug in makeRoom when out of rooms fixed. */
- /* 83Feb26 CrT matchString made caseless, normalizeString() */
- /* 83Feb26 CrT "]" directory prompt, user name before prompts */
- /* 82Dec06 CrT 2.00 release. */
- /* 82Nov02 CrT Cleanup prior to V1.2 mods. */
- /* 82Nov01 CrT Proofread for CUG distribution. */
- /* 82Mar27 dvm conversion to v. 1.4 begun */
- /* 82Mar25 dvm conversion for TRS-80/Omikron test started */
- /* 81Dec21 CrT Log file... */
- /* 81Dec20 CrT Messages... */
- /* 81Dec19 CrT Rooms seem to be working... */
- /* 81Dec12 CrT Started. */
- /************************************************************************/
-
- #include "b:210ctdl.h"
-
- /************************************************************************/
- /* Contents */
- /* */
- /* editText() handles the end-of-message-entry menu */
- /* findRoom() find a free room */
- /* getNumber() prompt user for a number, limited range */
- /* getRoom() load given room into RAM */
- /* getString() read a string in from user */
- /* getText() reads a message in from user */
- /* getYesNo() prompts for a yes/no response */
- /* givePrompt() gives usual "THISROOM>" prompt */
- /* indexRooms() build RAM index to ctdlroom.sys */
- /* makeRoom() make new room via user dialogue */
- /* matchString() search for given string */
- /* noteRoom() enter room into RAM index */
- /* putRoom() store room to given disk slot */
- /* renameRoom() sysop special to rename rooms */
- /* replaceString() string-substitute for message entry */
- /* zapRoomFile() erase & re-initialize ctdlroom.sys */
- /************************************************************************/
-
- /************************************************************************/
- /* editText() handles the end-of-message-entry menu. */
- /* return TRUE to save message to disk, */
- /* FALSE to abort message, and */
- /* ERROR if user decides to continue */
- /************************************************************************/
- int editText(buf, lim)
- char *buf;
- int lim;
- {
- char iChar(), toUpper();
- char c;
- int i;
-
- do {
- outFlag = OUTOK;
- mprintf("\n entry cmd: ");
- switch (c=toUpper(iChar())) {
- case 'A':
- mprintf("bort\n ");
- if (getYesNo(" confirm")) return FALSE;
- break;
- case 'C':
- mprintf("ontinue\n ");
- return ERROR;
- case 'P':
- mprintf("rint formatted\n ");
- doCR();
- mPrintf( " ");
- printDate(
- interpret(pGetYear ),
- interpret(pGetMonth),
- interpret(pGetDay )
- );
- if (loggedIn) mprintf(" from %s", msgBuf.mbauth);
- doCR();
- mformat(buf);
- break;
- case 'R':
- mprintf("eplace string\n ");
- replaceString(buf, lim);
- break;
- case 'S':
- mprintf("ave buffer\n ");
- return TRUE;
- default:
- tutorial("edit.mnu");
- break;
- }
- } while (haveCarrier || onConsole);
- return FALSE;
- }
-
- /************************************************************************/
- /* findRoom() returns # of free room if possible, else ERROR */
- /************************************************************************/
- int findRoom() {
- int roomRover;
-
- for (roomRover=0; roomRover<MAXROOMS; roomRover++) {
- if (!(roomTab[roomRover].rtflags & INUSE)) return roomRover;
- }
- return ERROR;
- }
-
- /************************************************************************/
- /* getNumber() prompts for a number in (bottom, top) range. */
- /************************************************************************/
- int getNumber(prompt, bottom, top)
- char *prompt;
- unsigned bottom;
- unsigned top;
- {
- unsigned try;
- char numstring[NAMESIZE];
-
- do {
- outFlag = OUTOK;
- getstring(prompt, numstring, NAMESIZE);
- try = atoi(numstring);
- if (try < bottom) mprintf("Sorry, must be at least %d\n", bottom);
- if (try > top ) mprintf("Sorry, must be no more than %d\n", top);
- } while ((try < bottom || try > top)
- && (haveCarrier || onConsole)
- );
- return try;
- }
-
- /************************************************************************/
- /* getRoom() */
- /************************************************************************/
- getRoom(rm, buf)
- int rm;
- int *buf;
- {
- int rread();
- unsigned val;
-
- /* load room #rm into memory starting at buf */
- thisRoom = rm;
- rseek(roomfl, rm*SECSPERROOM, 0);
- if ((val = rread(roomfl, &roomBuf, SECSPERROOM)) >= 1000) {
- printf(" ?getRoom(): rread failed, val=%d\n", val);
- }
- crypte(&roomBuf, (SECSPERROOM * SECTSIZE), rm);
- }
-
- /************************************************************************/
- /* getString() gets a string from the user. */
- /************************************************************************/
- getString(prompt, buf, lim)
- char *prompt;
- char *buf;
- int lim; /* max # chars to read */
- {
- char iChar();
- char c;
- int i;
-
- outFlag = OUTOK;
-
- if(strLen(prompt) > 0) {
- doCR();
- mprintf("Enter %s\n : ", prompt, lim);
- }
-
- i = 0;
- while (
- c = iChar(),
-
- c != NEWLINE
- && i < lim
- && (haveCarrier || onConsole)
- ) {
- outFlag = OUTOK;
-
- /* handle delete chars: */
- if (c == BACKSPACE) {
- oChar(' ');
- oChar(BACKSPACE);
- if (i > 0) i--;
- else {
- oChar(' ');
- oChar(BELL);
- }
- } else buf[i++] = c;
-
- if (i >= lim) {
- oChar(BELL);
- oChar(BACKSPACE); i--;
- }
-
- /* kludge to return immediately on single '?': */
- if (*buf == '?') {
- doCR();
- break;
- }
- }
- buf[i] = '\0';
- }
-
- /************************************************************************/
- /* getText() reads a message from the user */
- /* Returns TRUE if user decides to save it, else FALSE */
- /************************************************************************/
- char getText(prompt, buf, lim)
- char *prompt;
- char *buf;
- int lim; /* max # chars to read */
- {
- char iChar(), visible();
- char c, sysopAbort;
- int i, toReturn;
-
- outFlag = OUTOK;
- if (!expert) tutorial("entry.blb");
-
- outFlag = OUTOK;
- if (!expert) mprintf( "Enter %s (end with empty line)", prompt);
-
- outFlag = OUTOK;
- doCR();
- mPrintf( " ");
- printDate(
- interpret(pGetYear ),
- interpret(pGetMonth),
- interpret(pGetDay )
- );
-
- if (loggedIn) mprintf("from %s", msgBuf.mbauth);
- doCR();
-
- lim--;
- i = 0;
- toReturn = TRUE;
- sysopAbort = FALSE;
- do {
- if (whichIO == MODEM) {
- fastIn(toReturn == ERROR);
- if (whichIO != MODEM) sysopAbort = TRUE;
- } else {
- /* this code would handle the modem as well... */
- /* fastIn() is a later addition to handle people */
- /* who like to upload fast without handshaking */
- while (
- !( (c=iChar()) == NEWLINE && buf[i-1] == NEWLINE )
- && i < lim
- && (haveCarrier || onConsole)
- ) {
- if (debug) putCh(visible(c));
-
- if (c != BACKSPACE) buf[i++] = c;
- else {
- /* handle delete chars: */
- oChar(' ');
- oChar(BACKSPACE);
- if (i>0 && buf[i-1] != NEWLINE) i--;
- else oChar(BELL);
- }
- }
-
- buf[i] = 0x00; /* null to terminate message */
-
- if (i == lim) mprintf(" buffer overflow\n ");
- }
- toReturn = sysopAbort ? FALSE : editText(buf, lim);
- } while ((toReturn == ERROR) && (haveCarrier || onConsole));
- return toReturn;
- }
-
- /************************************************************************/
- /* getYesNo() prompts for a yes/no response */
- /************************************************************************/
- char getYesNo(prompt)
- char *prompt;
- {
- char iChar(), toUpper();
- int toReturn;
-
- for (
- doCR(),
- toReturn = ERROR;
-
- toReturn == ERROR && (haveCarrier || onConsole);
- ) {
- outFlag = OUTOK;
- mprintf("%s? (Y/N): ", prompt);
-
- switch (toUpper(iChar())) {
- case 'Y': toReturn = TRUE ; break;
- case 'N': toReturn = FALSE; break;
- }
- doCR();
- }
- return toReturn;
- }
-
- /************************************************************************/
- /* givePrompt() prints the usual "CURRENTROOM>" prompt. */
- /************************************************************************/
- givePrompt() {
- doCR();
-
- if (loggedIn) printf("(%s)\n", logBuf.lbname);
-
- if (roomBuf.rbflags & CPMDIR) mprintf("%s] ", roomBuf.rbname);
- else mprintf("%s> ", roomBuf.rbname);
- }
-
- /************************************************************************/
- /* indexRooms() -- build RAM index to room.buf */
- /************************************************************************/
- indexRooms() {
- int goodRoom, m, roomCount, slot;
-
- roomCount = 0;
- for (slot=0; slot<MAXROOMS; slot++) {
- getRoom(slot, &roomBuf);
- if (roomBuf.rbflags & INUSE) {
- roomBuf.rbflags ^= INUSE; /* clear "inUse" flag */
- for (m=0, goodRoom=FALSE;
-
- m<MSGSPERRM && !goodRoom;
-
- m++
- ) {
- /* comparison done with 64K wraparound in mind: */
- if (roomBuf.vp.msg[m].rbmsgNo - oldestLo < 0x800) {
- goodRoom = TRUE;
- }
- }
- if (goodRoom || (roomBuf.rbflags & PERMROOM)) {
- roomBuf.rbflags |= INUSE;
- }
-
- if (roomBuf.rbflags & INUSE) roomCount++;
- else {
- roomBuf.rbflags = 0;
- putRoom(slot, &roomBuf);
- }
- }
- noteRoom();
- }
- #ifdef XYZZY
- printf(" %d of %d rooms in use\n", roomCount, MAXROOMS);
- #endif
- }
-
- /************************************************************************/
- /* makeRoom() constructs a new room via dialogue with user. */
- /************************************************************************/
- makeRoom() {
- char getYesNo();
- char *nm[NAMESIZE];
- char *oldName[NAMESIZE];
- int i;
-
- /* update lastMessage for current room: */
- logBuf.lbgen[thisRoom] = roomBuf.rbgen << GENSHIFT;
-
- strcpy(oldName, roomBuf.rbname);
- if ((thisRoom=findRoom()) == ERROR) {
- indexRooms(); /* try and reclaim an empty room */
- if ((thisRoom=findRoom()) == ERROR) {
- mprintf(" ?no room");
- /* may have reclaimed old room, so: */
- if (roomExists(oldName) == ERROR) strcpy(oldName, "Lobby");
- getRoom(roomExists(oldName), &roomBuf);
- return;
- }
- }
-
- getString("name for new room", nm, NAMESIZE);
- normalizeString(nm);
- if (roomExists(nm) >= 0) {
- mprintf(" A '%s' already exists.\n", nm);
- /* may have reclaimed old room, so: */
- if (roomExists(oldName) == ERROR) strcpy(oldName, "Lobby");
- getRoom(roomExists(oldName), &roomBuf);
- return;
- }
- if (!expert) tutorial("newroom.blb");
-
- roomBuf.rbflags = INUSE;
- if (getYesNo(" Make room public")) roomBuf.rbflags |= PUBLIC;
-
- mprintf("'%s', a %s room",
- nm,
- roomBuf.rbflags & PUBLIC ? "public" : "private"
- );
-
- if(!getYesNo("Install it")) {
- /* may have reclaimed old room, so: */
- if (roomExists(oldName) == ERROR) strcpy(oldName, "Lobby");
- getRoom(roomExists(oldName), &roomBuf);
- return;
- }
-
- strcpy(roomBuf.rbname, nm);
- for (i=0; i<MSGSPERRM; i++) {
- roomBuf.vp.msg[i].rbmsgNo = 0; /* mark all slots empty */
- roomBuf.vp.msg[i].rbmsgLoc = ERROR;
- }
- roomBuf.rbgen = (roomBuf.rbgen +1) % MAXGEN;
-
- noteRoom(); /* index new room */
- putRoom(thisRoom, &roomBuf);
-
- /* update logBuf: */
- logBuf.lbgen[thisRoom] = roomBuf.rbgen << GENSHIFT;
- }
-
- /************************************************************************/
- /* matchString() searches for match to given string. Runs backward*/
- /* through buffer so we get most recent error first. */
- /* Returns loc of match, else ERROR */
- /************************************************************************/
- char *matchString(buf, pattern, bufEnd)
- char *buf, *pattern, *bufEnd;
- {
- char *loc, *pc1, *pc2;
- char foundIt;
-
- for (loc=bufEnd, foundIt=FALSE; !foundIt && --loc>=buf;) {
- for (pc1=pattern, pc2=loc, foundIt=TRUE ; *pc1 && foundIt;) {
- if (! (toLower(*pc1++) == toLower(*pc2++))) foundIt=FALSE;
- }
- }
-
- return foundIt ? loc : ERROR;
- }
-
- /************************************************************************/
- /* normalizeString() deletes leading & trailing blanks etc. */
- /************************************************************************/
- normalizeString(s)
- char *s;
- {
- char *pc, *s2;
-
- pc = s;
-
- /* find end of string */
- while (*pc) {
- if (*pc < ' ') *pc = ' '; /* zap tabs etc... */
- pc++;
- }
-
- /* no trailing spaces: */
- while (pc>s && isSpace(*(pc-1))) pc--;
- *pc = '\0';
-
- /* no leading spaces: */
- while (*s == ' ') {
- for (pc=s; *pc; pc++) *pc = *(pc+1);
- }
-
- /* no double blanks */
- for (; *s; s++) {
- if (*s == ' ' && *(s+1) == ' ') {
- for (pc=s; *pc; pc++) *pc = *(pc+1);
- }
- }
- }
-
- /************************************************************************/
- /* noteRoom() -- enter room into RAM index array. */
- /************************************************************************/
- noteRoom()
- {
- int i, last;
-
- last = 0;
- for (i=0; i<MSGSPERROOM; i++) {
- if (roomBuf.vp.msg[i].rbmsgNo > last) {
- last = roomBuf.vp.msg[i].rbmsgNo;
- }
- }
- roomTab[thisRoom].rtlastMessage = last ;
- strcpy(roomTab[thisRoom].rtname, roomBuf.rbname) ;
- roomTab[thisRoom].rtgen = roomBuf.rbgen ;
- roomTab[thisRoom].rtflags = roomBuf.rbflags;
- }
-
- /************************************************************************/
- /* putRoom() stores room in buf into slot rm in room.buf */
- /************************************************************************/
- putRoom(rm, buf)
- int rm;
- int *buf;
- {
- int rwrite();
- unsigned val;
-
- crypte(&roomBuf, (SECSPERROMM * SECTSIZE), rm);
-
- rseek(roomfl, rm*SECSPERROOM, 0);
- if ((val = rwrite(roomfl, &roomBuf, SECSPERROOM)) != SECSPERROOM) {
- printf("?putRoom()%d", val);
- }
-
- crypte(&roomBuf, (SECSPERROMM * SECTSIZE), rm);
- }
-
- /************************************************************************/
- /* renameRoom() is sysop special fn */
- /* Returns: TRUE on success else FALSE */
- /************************************************************************/
- renameRoom() {
- char getYesNo(), toUpper();
- char nm[NAMESIZE];
- char c, goodOne, wasDirectory;
- int r;
-
- if ( /* clearer than "thisRoom <= AIDEROOM"*/
- thisRoom == LOBBY
- ||
- thisRoom == MAILROOM
- ||
- thisRoom == AIDEROOM
- ) {
- mPrintf("? -- may not edit this room.\n ");
- return FALSE;
- }
-
- if (!getYesNo("confirm")) return FALSE;
-
- if (getYesNo("Change name")) {
- getString("new room name", nm, NAMESIZE);
- normalizeString(nm);
- r = roomExists(nm);
- if (r>=0 && r!=thisRoom) {
- mprintf("A %s exists already!\n", nm);
- } else {
- strcpy(roomBuf.rbname, nm); /* also in room itself */
- }
- }
- mprintf("%s, ", roomBuf.rbflags & PUBLIC ? "public" : "private");
- mprintf(
- "%s, ",
- (
- (roomBuf.rbflags & PERMROOM)
- ?
- " permanent"
- :
- " temporary"
- )
- );
- wasDirectory = roomBuf.rbflags & CPMDIR;
- mprintf("%sdirectory room\n ", wasDirectory ? "" : "non");
-
- roomBuf.rbflags = INUSE;
-
- if (getYesNo("Public room")) {
- roomBuf.rbflags |= PUBLIC;
- } else {
- roomBuf.rbgen = (roomBuf.rbgen +1) % MAXGEN;
- }
-
- if (!onConsole) roomBuf.rbflags |= wasDirectory;
- else if (getYesNo("Directory room")) {
- roomBuf.rbflags |= CPMDIR;
-
- printf(" now space %c%c\n", 'A'+roomBuf.rbdisk, '0'+roomBuf.rbuser);
-
- for (goodOne=FALSE; !goodOne; ) {
- getString("disk", nm, NAMESIZE);
- c = toUpper(nm[0]);
- if (c>='A' && c<='P') {
- roomBuf.rbdisk = c - 'A';
- goodOne = TRUE;
- } else mprintf("?");
- }
-
- roomBuf.rbuser = getNumber("user", 0, 31);
- printf(" space %c%c\n", 'A'+roomBuf.rbdisk, '0'+roomBuf.rbuser);
- }
-
-
- if (
- roomBuf.rbflags & CPMDIR
- ||
- getYesNo("permanent")
- ) {
- roomBuf.rbflags |= PERMROOM;
- }
-
- noteRoom();
- putRoom(thisRoom, &roomBuf);
-
- return TRUE;
- }
-
- /************************************************************************/
- /* replaceString() corrects typos in message entry */
- /************************************************************************/
- replaceString(buf, lim)
- char *buf;
- int lim;
- {
- char oldString[2*SECTSIZE];
- char newString[2*SECTSIZE];
- char *loc, *textEnd;
- char *pc;
- int incr;
-
- for (textEnd=buf; *textEnd; textEnd++); /* find terminal null */
-
- getString("string", oldString, (2*SECTSIZE));
- if ((loc=matchString(buf, oldString, textEnd)) == ERROR) {
- mprintf("?not found.\n ");
- return;
- }
-
- getString("replacement", newString, (2*SECTSIZE));
- if ( (strLen(newString)-strLen(oldString)) >= (&buf[lim]-textEnd) ) {
- mprintf("?Overflow!\n ");
- return;
- }
-
- /* delete old string: */
- for (pc=loc, incr=strLen(oldString); *pc=*(pc+incr); pc++);
- textEnd -= incr;
-
- /* make room for new string: */
- for (pc=textEnd, incr=strLen(newString); pc>=loc; pc--) {
- *(pc+incr) = *pc;
- }
-
- /* insert new string: */
- for (pc=newString; *pc; *loc++ = *pc++);
- }
-
- /************************************************************************/
- /* zapRoomFile() erases and re-initilizes room.buf */
- /************************************************************************/
- zapRoomFile()
- {
- char getCh(), toUpper();
- int i;
-
- printf("\nWipe room file? ");
- if (toUpper(getCh()) != 'Y') return;
-
- roomBuf.rbflags = 0;
- roomBuf.rbgen = 0;
- roomBuf.rbdisk = 0;
- roomBuf.rbuser = 0;
- roomBuf.rbname[0] = 0; /* unnecessary -- but I like it... */
- for (i=0; i<MSGSPERRM; i++) {
- roomBuf.vp.msg[i].rbmsgNo = roomBuf.vp.msg[i].rbmsgLoc = 0;
- }
-
- printf("maxrooms=%d\n", MAXROOMS);
-
- for (i=0; i<MAXROOMS; i++) {
- printf("clearing room %d\n", i);
- putRoom(i, &roomBuf);
- }
-
- /* Lobby> always exists -- guarantees us a place to stand! */
- thisRoom = 0 ;
- strcpy(roomBuf.rbname, "Lobby") ;
- roomBuf.rbflags = (PERMROOM | PUBLIC | INUSE);
- putRoom(LOBBY, &roomBuf);
-
- /* Mail> is also permanent... */
- thisRoom = MAILROOM ;
- strcpy(roomBuf.rbname, "Mail") ;
- roomBuf.rbflags = (PERMROOM | PUBLIC | INUSE);
- putRoom(MAILROOM, &roomBuf);
-
- /* Aide> also... */
- thisRoom = AIDEROOM ;
- strcpy(roomBuf.rbname, "Aide") ;
- roomBuf.rbflags = (PERMROOM | INUSE);
- putRoom(AIDEROOM, &roomBuf);
- }
-