/************************************************************************
Realms of Aurealis James Rhone aka Vall of RoA
boards.c Handling of runtime configurable
bulletin boards. (At some near pt.
these will be OLCable.)
Most functions and structures in this file have been altered to work with
the new system beginning on 12/29/97 -jtrhone.
******** Heavily modified and expanded ********
*** BE AWARE OF ALL RIGHTS AND RESERVATIONS ***
******** Heavily modified and expanded ********
All rights reserved henceforth.
Please note that no guarantees are associated with any code from
Realms of Aurealis. All code which has been released to the general
public has been done so with an 'as is' pretense. RoA is based on both
Diku and CircleMUD and ALL licenses from both *MUST* be adhered to as well
as the RoA license. *** Read, Learn, Understand, Improve ***
*************************************************************************/
#include "conf.h"
#include "sysdep.h"
#include "structures.h"
#include "utils.h"
#include "comm.h"
#include "db.h"
#include "boards.h"
#include "interpreter.h"
#include "handler.h"
#include "lists.h"
#include "acmd.h"
#include "global.h"
#include "descmenu.h"
// local global variables
binfotype board_info[MAX_BOARDS];
bmsginfo msg_index[MAX_BOARDS][MAX_BOARD_MESSAGES];
bindex master_index[MAX_MSGS];
// assemble filename into fname and return
void get_board_fname(int bnum, char *fname)
{
sprintf(fname, "%s/%d.brd", BOARD_DIR, B_VNUM(bnum));
}
// return a ptr the proto of this board
obdata *get_board_proto(int bnum)
{
int rnum;
rnum = real_object(B_VNUM(bnum));
if (rnum < 0)
{
sprintf(buf2, "SYSERR: Boards: B%d, invalid vnum.", bnum);
mudlog(buf2, BRF, LEV_IMM, TRUE);
return NULL;
}
return (&obj_proto[rnum]);
}
// assign a board some characteristics
void assign_board(int bnum, int vnum, int read, int write, int remove)
{
obdata *ob;
B_VNUM(bnum) = vnum;
READ_LVL(bnum) = read;
WRITE_LVL(bnum) = write;
REMOVE_LVL(bnum) = remove;
// now fill in rest...
B_MSGS(bnum) = 0;
B_VALID(bnum) = TRUE;
// make sure proto is a BOARD type
ob = get_board_proto(bnum);
ITEM_TYPE(ob) = ITEM_BOARD;
}
// if the BOARD_CONFIG_FILE is not found, or there is an error loading
// it, we will fill up the board info structure with default info
void use_default_boards(void)
{
mudlog("SYSUPD: Board config file not found, using defaults.", BRF, LEV_IMM, TRUE);
// # vnum read write remove
assign_board(0, 3099, 1, 1, LEV_GOD);
assign_board(1, 3098, LEV_IMM, LEV_IMM, LEV_AIMP);
assign_board(2, 3097, LEV_IMM, LEV_FREEZE, LEV_IMPL);
assign_board(3, 3096, 1, 1, LEV_IMM);
assign_board(4, 1201, LEV_IMM, LEV_IMM, LEV_GOD);
assign_board(5, 1202, LEV_IMM, LEV_IMM, LEV_GOD);
assign_board(6, 1203, 1, LEV_IMM, LEV_AIMP);
assign_board(7, 1204, 1, 1, 1 );
assign_board(8, 1205, 1, LEV_AIMP, LEV_AIMP);
}
// fill the board_info structure with values from config file
// return TRUE if successful, FALSE otherwise
BOOL load_board_config_from_file(void)
{
char letter = '\0';
FILE *fp;
int bnum, tmp1, tmp2, tmp3, tmp4;
if (!(fp = fopen(BOARD_CONFIG_FILE, "rt")))
return 0;
bnum = 0;
while (TRUE)
{
letter=fread_letter(fp);
ungetc(letter, fp);
if (bnum >= MAX_BOARDS || letter == '$' || letter == '~')
break;
fscanf(fp, "%d %d %d %d\n", &tmp1, &tmp2, &tmp3, &tmp4);
assign_board(bnum, tmp1, tmp2, tmp3, tmp4);
bnum++;
}
fclose(fp);
mudlog("SYSUPD: Board configuration read from file.", BUG, LEV_IMM, TRUE);
return TRUE;
}
// attempt to load board configuration file, if fail, use the defaults
void load_board_config(void)
{
if (!load_board_config_from_file())
use_default_boards();
}
// save the board configuration to disk
void save_board_config(void)
{
FILE *fp;
int bnum;
if (!(fp = fopen(BOARD_CONFIG_FILE, "wt")))
{
mudlog("SYSERR: Unable to save board config file.", BRF, LEV_IMM, TRUE);
return;
}
for (bnum = 0; bnum < MAX_BOARDS && B_VALID(bnum); bnum++)
fprintf(fp, "%d %d %d %d\n", B_VNUM(bnum), READ_LVL(bnum), WRITE_LVL(bnum), REMOVE_LVL(bnum));
// stick on an EOF marker...
fprintf(fp, "$~\n");
fclose(fp);
mudlog("SYSUPD: Board configuration saved.", BUG, LEV_IMM, TRUE);
}
ACMD(do_save_boards)
{
if (IS_NPC(ch))
return;
save_board_config();
send_to_char("Ok.\n\r",ch);
}
ACMD(do_blist)
{
int bnum;
if (IS_NPC(ch))
return;
strcpy(buf, "%B%6Board Info Table%0:\n\r");
for (bnum = 0; bnum < MAX_BOARDS && B_VALID(bnum); bnum++)
sprintf(buf+strlen(buf), "%%6Vnum%%0:%d, %%6Read%%0:%d, %%6Write%%0:%d, %%6Remove%%0:%d\n\r",
B_VNUM(bnum), READ_LVL(bnum), WRITE_LVL(bnum), REMOVE_LVL(bnum));
page_string(ch->desc, buf, 1);
}
BOOL board_in_table(int vnum)
{
int bnum;
for (bnum = 0; bnum < MAX_BOARDS && B_VALID(bnum); bnum++)
if (B_VNUM(bnum) == vnum)
return TRUE;
return FALSE;
}
void add_board(int vnum, int read, int write, int remove)
{
int bnum;
for (bnum = 0; bnum < MAX_BOARDS && B_VALID(bnum); bnum++)
;
if (bnum >= MAX_BOARDS)
{
mudlog("SYSERR: Board table filled up... unable to add.",BRF, LEV_IMM, TRUE);
return;
}
assign_board(bnum, vnum, read, write, remove);
}
// add a board to the board table
ACMD(do_badd)
{
obdata *ob;
char *argu = argument;
int rnum, vnum, read, write, remove;
char arg1[MAX_STRING_LENGTH], arg2[MAX_STRING_LENGTH];
char arg3[MAX_STRING_LENGTH], arg4[MAX_STRING_LENGTH];
if (IS_NPC(ch))
return;
skip_spaces(&argu);
if (!*argu)
{
send_to_char("Usage: badd <board vnum> <min to read> <min to write> <min to remove>.\n\r",ch);
return;
}
// first, make sure vnum exists and is NOT a board
half_chop(argu, arg1, argu);
if (!is_number(arg1) || (rnum = real_object((vnum = atoi(arg1)))) < 0)
{
send_to_char("Usage: badd <board vnum> <min to read> <min to write> <min to remove>.\n\r",ch);
return;
}
ob = &obj_proto[rnum];
if (ITEM_TYPE(ob) != ITEM_BOARD)
{
send_to_char("Item must be of type BOARD.\n\r",ch);
return;
}
if (board_in_table(vnum))
{
send_to_char("That board is already in the board table.\n\r",ch);
return;
}
half_chop(argu, arg2, argu);
if (!*arg2 || !is_number(arg2) || (read = atoi(arg2)) < 1 || read > LEV_IMPL)
{
send_to_char("Usage: badd <board vnum> <min to read> <min to write> <min to remove>.\n\r",ch);
return;
}
half_chop(argu, arg3, argu);
if (!*arg3 || !is_number(arg3) || (write = atoi(arg3)) < 1 || write > LEV_IMPL)
{
send_to_char("Usage: badd <board vnum> <min to read> <min to write> <min to remove>.\n\r",ch);
return;
}
half_chop(argu, arg4, argu);
if (!*arg4 || !is_number(arg4) || (remove = atoi(arg4)) < 1 || remove > LEV_IMPL)
{
send_to_char("Usage: badd <board vnum> <min to read> <min to write> <min to remove>.\n\r",ch);
return;
}
// okie, find first open slot in the table and add
add_board(vnum, read, write, remove);
do_save_boards(ch, "", 0, 0);
}
// find an available slot in the global board array
int find_slot(void)
{
int i;
for (i = 0; i < MAX_MSGS; i++)
if (!master_index[i].used)
{
master_index[i].used = TRUE;
return i;
}
return -1;
}
// return TRUE if there is a board in here...
BOOL board_in_room(int rnum)
{
obdata *ob;
for (ob = world[rnum].contents; ob; ob=ob->next_content)
if (ITEM_TYPE(ob) == ITEM_BOARD)
return TRUE;
return FALSE;
}
// find a match between objects in room and boards in room
// NOW use VNUMs
int find_board(chdata *ch)
{
obdata *obj;
int bnum;
for (obj = world[ch->in_room].contents; obj; obj = obj->next_content)
if (ITEM_TYPE(obj) == ITEM_BOARD)
for (bnum = 0; bnum < MAX_BOARDS && B_VALID(bnum); bnum++)
if (B_VNUM(bnum) == GET_OBJ_VNUM(obj))
return bnum;
return -1;
}
// use memset now... 12/29/97 -jtrhone
void clear_master_index(void)
{
memset((char *)master_index, 0, sizeof(bindex) * MAX_MSGS);
}
// initialize the boards...
void init_boards(void)
{
int bnum, msg;
char buf[MAX_INPUT_LENGTH];
clear_master_index();
load_board_config();
for (bnum = 0; bnum < MAX_BOARDS && B_VALID(bnum); bnum++)
{
if (real_object(B_VNUM(bnum)) < 0)
{
sprintf(buf, "SYSERR: Fatal board error: board vnum %d does not exist!", B_VNUM(msg));
log(buf);
B_VALID(bnum) = FALSE;
continue;
}
for (msg = 0; msg < MAX_BOARD_MESSAGES; msg++)
{
memset(&(MESSAGE(bnum, msg)), '\0', sizeof(bmsginfo));
MSG_SLOTNUM(bnum, msg) = -1;
}
Board_load_board(bnum);
}
}
// direct command to erase a message (used to be handled by do_remove) 4/14/98 -jtrhone
ACMD(do_erase)
{
if (board_in_room(ch->in_room) && board_interaction(ch, argument, get_command("erase")))
return;
send_to_char("You can't find anything to erase.\n\r",ch);
}
// used to be hard coded SPECIAL(gen_board)...
// not anymore 12/30/97 -jtrhone
// boards are now initiated at BOOTUP (look in db.c)
int board_interaction(chdata *ch, char *arg, int cmd)
{
int bnum;
if ((bnum = find_board(ch)) == -1)
{
sprintf(buf, "SYSERR: Degenerate board... via %s.", GET_NAME(ch));
mudlog(buf, BRF, LEV_IMM, TRUE);
return 0;
}
if (!B_VALID(bnum))
{
send_to_char("Board appears to be invalid... report to an immortal.\n\r",ch);
return 0;
}
if (CMD_IS(cmd, "write"))
{
Board_write_message(bnum, ch, arg);
return 1;
}
else
if (CMD_IS(cmd, "look"))
return (Board_show_board(bnum, ch, arg));
else
if (CMD_IS(cmd, "read"))
return (Board_display_msg(bnum, ch, arg));
else
if (CMD_IS(cmd, "erase"))
return (Board_remove_msg(bnum, ch, arg));
else
return 0;
}
// a descriptor menu for easier board writing and allowance of roa client usage 7/18/98 -jtrhone
// will get called after do_var_string_arg finishes and pops and calls
ROA_DESCMENU(doneposting)
{
Board_save_board(BOARD_WRITING(d->character));
BOARD_WRITING(d->character) = -1;
REMOVE_BIT(PLR_FLAGS(d->character), PLR_WRITING);
send_to_char("Board posting complete.\n\r", d->character);
// no more menus...
DESCMENU_PROMPT(d) = NULL;
DESCMENU_HANDLER(d) = NULL;
DESCMENU_DEPTH(d) = 0;
}
// ok, startem writing a message
void Board_write_message(int bnum, chdata *ch, char *arg)
{
char *tmstr, buf[MAX_INPUT_LENGTH], buf2[MAX_INPUT_LENGTH];
int len;
long ct;
if (IS_NPC(ch)) return;
if (GET_LEVEL(ch) < WRITE_LVL(bnum)) {
send_to_char("You are not holy enough to write on this board.\n\r", ch);
return;
}
if (B_MSGS(bnum) >= MAX_BOARD_MESSAGES) {
send_to_char("The board is full.\n\r", ch);
return;
}
// get the next available slot in the master_index
if ((NEW_MSG_INDEX(bnum).slot_num = find_slot()) == -1) {
send_to_char("No empty message slots available...\n\r", ch);
mudlog("SYSERR: Boards: No slots left in master index...", BRF, LEV_IMM, TRUE);
return;
}
skip_spaces(&arg);
if (!*arg) {
send_to_char("You must have a message heading.\n\r", ch);
return;
}
// get a timestamp
ct = time(0);
tmstr = (char *) asctime(localtime(&ct));
// wax the newline
*(tmstr + strlen(tmstr) - 1) = '\0';
// construct the one line heading
sprintf(buf2, "(%s)", GET_NAME(ch));
sprintf(buf, "%6.10s %-12s :: %s", tmstr, buf2, arg);
len = strlen(buf) + 1;
if (!(NEW_MSG_INDEX(bnum).heading = (char *)malloc(sizeof(char)*len)))
{
send_to_char("No memory available for message heading...\n\r", ch);
mudlog("SYSERR: Boards: No memory available for message heading...", BRF, LEV_IMM, TRUE);
return;
}
strcpy(NEW_MSG_INDEX(bnum).heading, buf);
NEW_MSG_INDEX(bnum).heading[len-1] = '\0';
NEW_MSG_INDEX(bnum).level = GET_LEVEL(ch);
act("$n starts to write a message.", TRUE, ch, 0, 0, TO_ROOM);
SET_BIT(PLR_FLAGS(ch), PLR_WRITING);
BOARD_WRITING(ch) = bnum;
descmenu_next(ch->desc, doneposting);
do_var_string_arg_desc(ch->desc, "Write your message. Terminate with a '@':\n\r",
&(master_index[NEW_MSG_INDEX(bnum).slot_num].msg),
MAX_MESSAGE_LENGTH);
B_MSGS(bnum)++;
}
// if someone looks at a board they see.....
int Board_show_board(int bnum, chdata *ch, char *arg)
{
int msg;
obdata *ob;
if (GET_LEVEL(ch) < READ_LVL(bnum)) {
send_to_char("You are unable to decipher any meaning from those words.\n\r", ch);
return 1;
}
if (!(ob = get_board_proto(bnum)))
return 0;
act("$n studies $p.", TRUE, ch, ob, 0, TO_ROOM);
strcpy(buf, "This item can be used as a board. See %Bhelp boards%0 for more info.\n\r");
if (!B_MSGS(bnum))
{
str_cat(buf, "There is nothing written on $p.\n\r", MAX_STRING_LENGTH, "Board_show_board");
act(buf, TRUE, ch, ob, 0, TO_CHAR);
return 1;
}
else
{
sprintf(buf + strlen(buf), "There are %d messages on %s.\n\r", B_MSGS(bnum), ob->shdesc);
for (msg = 0; msg < B_MSGS(bnum); msg++)
{
if (MSG_HEADING(bnum, msg))
sprintf(buf + strlen(buf), "%-2d : %s\n\r", msg + 1, MSG_HEADING(bnum, msg));
else
{
sprintf(buf2, "SYSERR: Boards: B%d, M%d missing header.", bnum, msg);
mudlog(buf2, BRF, LEV_IMM, TRUE);
send_to_char("Sorry, the board isn't working.\n\r", ch);
return 1;
}
}
}
page_string(ch->desc, buf, 1);
return 1;
}
// show msg to character
int Board_display_msg(int bnum, chdata *ch, char *arg)
{
char number[MAX_STRING_LENGTH], buffer[MAX_STRING_LENGTH];
int msg, ind;
if (!ch->desc)
return 0;
one_argument(arg, number);
if (!*number || !isdigit(*number))
return 0;
if (!(msg = atoi(number)))
return 0;
if (GET_LEVEL(ch) < READ_LVL(bnum)) {
send_to_char("You are unable to decipher any meaning from those words.\n\r", ch);
return 1;
}
if (!B_MSGS(bnum)) {
send_to_char("The board is empty!\n\r", ch);
return(1);
}
if (msg < 1 || msg > B_MSGS(bnum)) {
send_to_char("That message exists only in your imagination.\n\r", ch);
return(1);
}
ind = msg - 1;
if (MSG_SLOTNUM(bnum, ind) < 0 || MSG_SLOTNUM(bnum, ind) >= MAX_MSGS)
{
send_to_char("Sorry, the board is not working.\n\r", ch);
sprintf(buf, "SYSERR: Boards: B%d, M%d invalid slotnum.",bnum, ind);
mudlog(buf, BRF, LEV_IMM, TRUE);
return 1;
}
if (!(MSG_HEADING(bnum, ind))) {
send_to_char("That message appears to be screwed up.\n\r", ch);
sprintf(buf, "SYSERR: Boards: B%d, M%d missing heading.",bnum, ind);
mudlog(buf, BRF, LEV_IMM, TRUE);
return 1;
}
if (!(master_index[MSG_SLOTNUM(bnum, ind)].used)) {
send_to_char("That message seems to be empty.\n\r", ch);
sprintf(buf, "SYSERR: Boards: B%d, M%d empty message block.",bnum, ind);
mudlog(buf, BRF, LEV_IMM, TRUE);
return 1;
}
sprintf(buffer, "Message %d : %s\n\r\n\r%s\n\r", msg,
MSG_HEADING(bnum, ind), master_index[MSG_SLOTNUM(bnum, ind)].msg);
/* REMIND me what message i just read!! RoA James Rhone*/
sprintf(buf, "\n\rEnd of message #%d.\n\r", msg);
str_cat(buffer, buf, MAX_STRING_LENGTH, "Board_display_msg");
page_string(ch->desc, buffer, 1);
return 1;
}
// when character removes a message...
int Board_remove_msg(int bnum, chdata *ch, char *arg)
{
int ind, msg, slot_num;
char number[MAX_INPUT_LENGTH], buf[MAX_INPUT_LENGTH];
dsdata *d;
if (IS_NPC(ch))
return 0;
one_argument(arg, number);
if (!*number || !isdigit(*number))
return 0;
if (!(msg = atoi(number)))
return(0);
if (!B_MSGS(bnum)) {
send_to_char("The board is empty!\n\r", ch);
return 1;
}
if (msg < 1 || msg > B_MSGS(bnum)) {
send_to_char("That message exists only in your imagination..\n\r", ch);
return 1;
}
ind = msg - 1;
if (!MSG_HEADING(bnum, ind)) {
send_to_char("That message appears to be screwed up.\n\r", ch);
sprintf(buf, "SYSERR: Boards: B%d, M%d missing heading.",bnum, ind);
mudlog(buf, BRF, LEV_IMM, TRUE);
return 1;
}
sprintf(buf, "(%s)", GET_NAME(ch));
if (GET_LEVEL(ch) < REMOVE_LVL(bnum) && !(strstr(MSG_HEADING(bnum, ind), buf)))
{
send_to_char("You are unable to remove other's messages.\n\r", ch);
return 1;
}
if (GET_LEVEL(ch) < MSG_LEVEL(bnum, ind)) {
send_to_char("You cannot remove that message.\n\r", ch);
return 1;
}
slot_num = MSG_SLOTNUM(bnum, ind);
if (slot_num < 0 || slot_num >= MAX_MSGS)
{
sprintf(buf, "SYSERR: Boards: B%d, M%d invalid slotnum in master index.",bnum, ind);
mudlog(buf, BRF, LEV_IMM, TRUE);
send_to_char("That message is majorly screwed up.\n\r", ch);
return 1;
}
// scan people connected to make sure nobody is currently writing this message
for (d = descriptor_list; d; d = d->next)
if (!d->connected && d->str == &(master_index[slot_num].msg))
{
send_to_char("At least wait until the author is finished before removing it!\n\r", ch);
return 1;
}
master_index[slot_num].used = FALSE;
FREENULL(master_index[slot_num].msg);
FREENULL(MSG_HEADING(bnum, ind));
for ( ; ind < B_MSGS(bnum) - 1; ind++)
{
MSG_HEADING(bnum, ind) = MSG_HEADING(bnum, ind + 1);
MSG_SLOTNUM(bnum, ind) = MSG_SLOTNUM(bnum, ind + 1);
MSG_LEVEL(bnum, ind) = MSG_LEVEL(bnum, ind + 1);
}
B_MSGS(bnum)--;
send_to_char("Message removed.\n\r", ch);
sprintf(buf, "$n just removed message %d.", msg);
act(buf, TRUE, ch, 0, 0, TO_ROOM);
Board_save_board(bnum);
return 1;
}
// save an individual board to disk...
void Board_save_board(int bnum)
{
FILE *fl;
int msg;
char fname[MAX_INPUT_LENGTH], *tmp1 = 0, *tmp2 = 0;
get_board_fname(bnum, fname);
// if no messages, simply remove the file...
if (B_MSGS(bnum) <= 0)
{
unlink(fname);
return;
}
if (!(fl = fopen(fname, "wb"))) {
sprintf(buf, "SYSERR: Boards: B%d error writing to file...",bnum);
mudlog(buf, BRF, LEV_IMM, TRUE);
return;
}
// first, write the number of messages to file
fwrite(&(B_MSGS(bnum)), sizeof(int), 1, fl);
for (msg = 0; msg < B_MSGS(bnum); msg++)
{
if ((tmp1 = MSG_HEADING(bnum, msg)))
msg_index[bnum][msg].heading_len = strlen(tmp1) + 1;
else
msg_index[bnum][msg].heading_len = 0;
if (MSG_SLOTNUM(bnum, msg) < 0 || MSG_SLOTNUM(bnum, msg) >= MAX_MSGS ||
(!(tmp2 = master_index[MSG_SLOTNUM(bnum, msg)].msg)))
msg_index[bnum][msg].message_len = 0;
else
msg_index[bnum][msg].message_len = strlen(tmp2) + 1;
// for each message, write the message info out
fwrite(&(msg_index[bnum][msg]), sizeof(bmsginfo), 1, fl);
// if we have a heading, write out the heading
if (tmp1)
fwrite(tmp1, sizeof(char), msg_index[bnum][msg].heading_len, fl);
// if we have a message, write out the message
if (tmp2)
fwrite(tmp2, sizeof(char), msg_index[bnum][msg].message_len, fl);
}
// we're done...
fclose(fl);
}
// load an individual board from disk...
void Board_load_board(int bnum)
{
FILE *fl;
int msg, len1 = 0, len2 = 0;
char fname[MAX_INPUT_LENGTH], *tmp = 0;
get_board_fname(bnum, fname);
// no error, just dont load the board
if (!(fl = fopen(fname, "rb")))
{
return;
}
fread(&(B_MSGS(bnum)), sizeof(int), 1, fl);
if (B_MSGS(bnum) < 1 || B_MSGS(bnum) > MAX_BOARD_MESSAGES)
{
sprintf(buf, "SYSERR: Boards: B%d corrupt, resetting...",bnum);
mudlog(buf, BRF, LEV_IMM, TRUE);
Board_reset_board(bnum);
return;
}
for (msg = 0; msg < B_MSGS(bnum); msg++)
{
fread(&(msg_index[bnum][msg]), sizeof(bmsginfo), 1, fl);
if (!(len1 = msg_index[bnum][msg].heading_len))
{
sprintf(buf, "SYSERR: Boards: B%d M%d corrupt, resetting...",bnum, msg);
mudlog(buf, BRF, LEV_IMM, TRUE);
Board_reset_board(bnum);
return;
}
// allocate and read into
CREATE(MSG_HEADING(bnum, msg), char, len1);
fread(MSG_HEADING(bnum, msg), sizeof(char), len1, fl);
if ((len2 = msg_index[bnum][msg].message_len))
{
if ((MSG_SLOTNUM(bnum, msg) = find_slot()) == -1)
{
sprintf(buf, "SYSERR: Boards: B%d M%d no slot available, resetting.", bnum, msg);
mudlog(buf, BRF, LEV_IMM, TRUE);
Board_reset_board(bnum);
return;
}
// allocate for message block and read into
CREATE(tmp, char, len2);
fread(tmp, sizeof(char), len2, fl);
// ok, assign master index this message txt
master_index[MSG_SLOTNUM(bnum, msg)].msg = tmp;
}
}
/* NULL out remaining heading pointers -RoA 9/1/97 */
for ( ; msg < MAX_BOARD_MESSAGES; msg++)
MSG_HEADING(bnum, msg) = NULL;
fclose(fl);
}
// in case of an error, reset a particular board
void Board_reset_board(int bnum)
{
int msg;
char fname[MAX_INPUT_LENGTH];
for (msg = 0; msg < B_MSGS(bnum) - 1; msg++)
{
FREENULL(MSG_HEADING(bnum, msg));
FREENULL(master_index[MSG_SLOTNUM(bnum, msg)].msg);
master_index[MSG_SLOTNUM(bnum, msg)].used = FALSE;
memset(&(msg_index[bnum][msg]), '\0', sizeof(bmsginfo));
msg_index[bnum][msg].slot_num = -1;
}
B_MSGS(bnum) = 0;
get_board_fname(bnum, fname);
unlink(fname);
}
// free all the boards...
void free_the_boards(void)
{
int i, bnum;
for (bnum = 0; bnum < MAX_BOARDS && B_VALID(bnum); bnum++)
for (i = 0; i < B_MSGS(bnum); i++)
{
FREENULL(MSG_HEADING(bnum, i));
FREENULL(master_index[MSG_SLOTNUM(bnum, i)].msg);
}
}