I'm working on a MUD (multiplayer text game), and the helpfile system adds missing helpfiles (ones that are looked for but don't exist) in the following format, including the room number, character name, and desired helpfile. I tried to be as efficient as possible, but I'm not very experienced with C file io, and the overall code feels unwieldy.
[ 42] Legolas: Isengard
[ 9] Frodo: the One Ring
[ 666] Sauron: Doooooom
I've expanded #defines for simplicity.
int delete_helpfile_from_list(FILE *fhelp, char *helpfile) {
if (!strlen(helpfile))
return FALSE;
FILE *ftemp = fopen("../data/help_temp.txt", "w");
if (!ftemp) {
bug("helpfiles: Unable to write to help_temp.txt", 0);
return -1;
}
const size_t MAX_LINE_LENGTH = 50;
char buf[MAX_LINE_LENGTH], line_helpfile[32];
int found = FALSE;
while (fgets(buf, MAX_LINE_LENGTH, fhelp)) {
size_t len = strlen(buf);
int match = FALSE;
// Trim newline and trailing whitespace
if (len > 0 && buf[len-1] == '\n')
buf[--len] = '\0';
while (len > 0 && isspace(buf[len-1]))
buf[--len] = '\0';
// Move a pointer from the end until it reaches the colon, then move back to the first letter
char *ptr = buf + len - 1;
while (ptr >= buf && *ptr != ':')
ptr--;
ptr += 2;
// Copy the last word as the line's helpfile
strncpy(line_helpfile, ptr, buf+len-ptr);
line_helpfile[buf+len-ptr] = '\0';
match = !str_cmp(line_helpfile, helpfile);
if (match && !found)
found = TRUE;
else if (!match) {
strncat(buf, "\n", sizeof(buf) - strlen(buf) - 1);
fputs(buf, ftemp);
}
}
fclose(ftemp);
if (found) {
if (remove(HELP_FILE)) {
bug("helpfile: Can't delete help.txt", 0);
return -1;
}
if (rename("../data/help_temp.txt", HELP_FILE)) {
bug("helpfile: Can't rename help_temp.txt to help.txt", 0);
return -1;
}
}
return found;
}
void do_helpfiles(CHAR_DATA *ch, char *argument) {
if (!is_staff(ch)) {
do_function(ch, &do_help, argument);
return;
}
FILE *fhelp = fopen(HELP_FILE, "r");
if (!fhelp) {
send_to_char("Unable to read helpfiles list.\r\n", ch);
bug("helpfiles: Unable to read help.txt", 0);
return;
}
char arg[MSL], helpfile[MSL];
argument = one_argument(argument, arg);
strcpy(helpfile, argument);
if (!str_cmp(arg, "done") || !str_cmp(arg, "clear")) {
int found = delete_helpfile_from_list(fhelp, helpfile);
if (found == -1)
send_to_char("Unable to add missing helpfile to list.\r\n", ch);
else if (found)
printf_to_char(ch, "Great work! Removing all instances of %s from the helpfile list.\r\n", helpfile);
else
send_to_char("Great work on finishing a new helpfile! It currently wasn't on the list.\r\n", ch);
}
else {
char *buf;
long flen;
fseek(fhelp, 0, SEEK_END);
flen = ftell(fhelp);
fseek(fhelp, 0, SEEK_SET);
buf = (char*)malloc(flen+1);
size_t nread = fread(buf, 1, flen, fhelp);
buf[nread] = '\0';
if (!nread) {
send_to_char("Unable to read helpfiles list.\r\n", ch);
bug("helpfiles: Unable to read help.txt", 0);
}
else
page_to_char(buf, ch);
}
fclose(fhelp);
}