Skip to main content
Refactored deletion into `delete_helpfile_from_list`
Source Link
BrainFRZ
  • 841
  • 11
  • 26
  void do_helpfiles(CHAR_DATA *ch, char *argument) {
    if (!is_staff(ch)) {
      do_function(ch, &do_help, argument);
      return;
    }

    FILE *fhelp = fopen("../data/help.txt", "r");
    if (!fhelp) {
      send_to_char("Unable to read helpfiles list.\r\n", ch);
      bug("helpfiles: Unable to read help.txt", 0);
      return;
    }

    long flen;
    const size_t MAX_LINE_LENGTH = 50;
    char arg[27648], helpfile[27648];
    argument = one_argument(argument, arg);
    strcpy(helpfile, argument);

    if (!str_cmp(arg, "done") || !str_cmp(arg, "clear")) {
      if (!strlen(helpfile)) {
        send_to_char("Syntax: helpfiles done helpfile\r\n", ch);
        return;
      }

      FILE *ftemp = fopen("../data/help_temp.txt", "w");
      if (!ftemp) {
        send_to_char("Unable to write temp list file.\r\n", ch);
        bug("helpfiles: Unable to write to help_temp.txt", 0);
        fclose(fhelp);
        return;
      }

      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) {
          printf_to_char(ch, "Great work! Removing all instances of %s from the helpfile list.\r\n", helpfile);
          found = TRUE;
        }
        else if (!match) {
          strncat(buf, "\n", sizeof(buf) - strlen(buf) - 1);
          fputs(buf, ftemp);
        }
      }

      fclose(ftemp);
      fclose(fhelp);

      if (found) {
        if (remove(HELP_FILE)) {
          send_to_char("Unable to update helpfile list.\r\n", ch);
          bug("helpfile: Can't delete help.txt", 0);
          return;
        }

        if (rename("../data/help_temp.txt", "../data/help.txt")) {
          send_to_char("Unable to update helpfile list.\r\n", ch);
          bug("helpfile: Can't rename help_temp.txt to help.txt", 0);
          return;
        }
      }
      else
        send_to_char("Great work on finishing a new helpfile! It currently wasn't on the list.\r\n", ch);
    }

    else {
      char *buf = 0;
      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);
    }
  }

```
  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);
  }
  void do_helpfiles(CHAR_DATA *ch, char *argument) {
    if (!is_staff(ch)) {
      do_function(ch, &do_help, argument);
      return;
    }

    FILE *fhelp = fopen("../data/help.txt", "r");
    if (!fhelp) {
      send_to_char("Unable to read helpfiles list.\r\n", ch);
      bug("helpfiles: Unable to read help.txt", 0);
      return;
    }

    long flen;
    const size_t MAX_LINE_LENGTH = 50;
    char arg[27648], helpfile[27648];
    argument = one_argument(argument, arg);
    strcpy(helpfile, argument);

    if (!str_cmp(arg, "done") || !str_cmp(arg, "clear")) {
      if (!strlen(helpfile)) {
        send_to_char("Syntax: helpfiles done helpfile\r\n", ch);
        return;
      }

      FILE *ftemp = fopen("../data/help_temp.txt", "w");
      if (!ftemp) {
        send_to_char("Unable to write temp list file.\r\n", ch);
        bug("helpfiles: Unable to write to help_temp.txt", 0);
        fclose(fhelp);
        return;
      }

      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) {
          printf_to_char(ch, "Great work! Removing all instances of %s from the helpfile list.\r\n", helpfile);
          found = TRUE;
        }
        else if (!match) {
          strncat(buf, "\n", sizeof(buf) - strlen(buf) - 1);
          fputs(buf, ftemp);
        }
      }

      fclose(ftemp);
      fclose(fhelp);

      if (found) {
        if (remove(HELP_FILE)) {
          send_to_char("Unable to update helpfile list.\r\n", ch);
          bug("helpfile: Can't delete help.txt", 0);
          return;
        }

        if (rename("../data/help_temp.txt", "../data/help.txt")) {
          send_to_char("Unable to update helpfile list.\r\n", ch);
          bug("helpfile: Can't rename help_temp.txt to help.txt", 0);
          return;
        }
      }
      else
        send_to_char("Great work on finishing a new helpfile! It currently wasn't on the list.\r\n", ch);
    }

    else {
      char *buf = 0;
      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);
    }
  }

```
  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);
  }
deleted 16 characters in body
Source Link
BrainFRZ
  • 841
  • 11
  • 26
  void do_helpfiles(CHAR_DATA *ch, char *argument) {
    if (!(get_trustis_staff(ch) >= (111 - 9))) {
      do_function(ch, &do_help, argument);
      return;
    }

    FILE *fhelp = fopen("../data/help.txt", "r");
    if (!fhelp) {
      send_to_char("Unable to read helpfiles list.\r\n", ch);
      bug("helpfiles: Unable to read help.txt", 0);
      return;
    }

    long flen;
    const size_t MAX_LINE_LENGTH = 50;
    char arg[27648], helpfile[27648];
    argument = one_argument(argument, arg);
    strcpy(helpfile, argument);

    if (!str_cmp(arg, "done") || !str_cmp(arg, "clear")) {
      if (!strlen(helpfile)) {
        send_to_char("Syntax: helpfiles done helpfile\r\n", ch);
        return;
      }

      FILE *ftemp = fopen("../data/help_temp.txt", "w");
      if (!ftemp) {
        send_to_char("Unable to write temp list file.\r\n", ch);
        bug("helpfiles: Unable to write to help_temp.txt", 0);
        fclose(fhelp);
        return;
      }

      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) {
          printf_to_char(ch, "Great work! Removing all instances of %s from the helpfile list.\r\n", helpfile);
          found = TRUE;
        }
        else if (!match) {
          strncat(buf, "\n", sizeof(buf) - strlen(buf) - 1);
          fputs(buf, ftemp);
        }
      }

      fclose(ftemp);
      fclose(fhelp);

      if (found) {
        if (remove(HELP_FILE)) {
          send_to_char("Unable to update helpfile list.\r\n", ch);
          bug("helpfile: Can't delete help.txt", 0);
          return;
        }

        if (rename("../data/help_temp.txt", "../data/help.txt")) {
          send_to_char("Unable to update helpfile list.\r\n", ch);
          bug("helpfile: Can't rename help_temp.txt to help.txt", 0);
          return;
        }
      }
      else
        send_to_char("Great work on finishing a new helpfile! It currently wasn't on the list.\r\n", ch);
    }

    else {
      char *buf = 0;
      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);
    }
  }

```
  void do_helpfiles(CHAR_DATA *ch, char *argument) {
    if (!(get_trust(ch) >= (111 - 9))) {
      do_function(ch, &do_help, argument);
      return;
    }

    FILE *fhelp = fopen("../data/help.txt", "r");
    if (!fhelp) {
      send_to_char("Unable to read helpfiles list.\r\n", ch);
      bug("helpfiles: Unable to read help.txt", 0);
      return;
    }

    long flen;
    const size_t MAX_LINE_LENGTH = 50;
    char arg[27648], helpfile[27648];
    argument = one_argument(argument, arg);
    strcpy(helpfile, argument);

    if (!str_cmp(arg, "done") || !str_cmp(arg, "clear")) {
      if (!strlen(helpfile)) {
        send_to_char("Syntax: helpfiles done helpfile\r\n", ch);
        return;
      }

      FILE *ftemp = fopen("../data/help_temp.txt", "w");
      if (!ftemp) {
        send_to_char("Unable to write temp list file.\r\n", ch);
        bug("helpfiles: Unable to write to help_temp.txt", 0);
        fclose(fhelp);
        return;
      }

      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) {
          printf_to_char(ch, "Great work! Removing all instances of %s from the helpfile list.\r\n", helpfile);
          found = TRUE;
        }
        else if (!match) {
          strncat(buf, "\n", sizeof(buf) - strlen(buf) - 1);
          fputs(buf, ftemp);
        }
      }

      fclose(ftemp);
      fclose(fhelp);

      if (found) {
        if (remove(HELP_FILE)) {
          send_to_char("Unable to update helpfile list.\r\n", ch);
          bug("helpfile: Can't delete help.txt", 0);
          return;
        }

        if (rename("../data/help_temp.txt", "../data/help.txt")) {
          send_to_char("Unable to update helpfile list.\r\n", ch);
          bug("helpfile: Can't rename help_temp.txt to help.txt", 0);
          return;
        }
      }
      else
        send_to_char("Great work on finishing a new helpfile! It currently wasn't on the list.\r\n", ch);
    }

    else {
      char *buf = 0;
      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);
    }
  }

```
  void do_helpfiles(CHAR_DATA *ch, char *argument) {
    if (!is_staff(ch)) {
      do_function(ch, &do_help, argument);
      return;
    }

    FILE *fhelp = fopen("../data/help.txt", "r");
    if (!fhelp) {
      send_to_char("Unable to read helpfiles list.\r\n", ch);
      bug("helpfiles: Unable to read help.txt", 0);
      return;
    }

    long flen;
    const size_t MAX_LINE_LENGTH = 50;
    char arg[27648], helpfile[27648];
    argument = one_argument(argument, arg);
    strcpy(helpfile, argument);

    if (!str_cmp(arg, "done") || !str_cmp(arg, "clear")) {
      if (!strlen(helpfile)) {
        send_to_char("Syntax: helpfiles done helpfile\r\n", ch);
        return;
      }

      FILE *ftemp = fopen("../data/help_temp.txt", "w");
      if (!ftemp) {
        send_to_char("Unable to write temp list file.\r\n", ch);
        bug("helpfiles: Unable to write to help_temp.txt", 0);
        fclose(fhelp);
        return;
      }

      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) {
          printf_to_char(ch, "Great work! Removing all instances of %s from the helpfile list.\r\n", helpfile);
          found = TRUE;
        }
        else if (!match) {
          strncat(buf, "\n", sizeof(buf) - strlen(buf) - 1);
          fputs(buf, ftemp);
        }
      }

      fclose(ftemp);
      fclose(fhelp);

      if (found) {
        if (remove(HELP_FILE)) {
          send_to_char("Unable to update helpfile list.\r\n", ch);
          bug("helpfile: Can't delete help.txt", 0);
          return;
        }

        if (rename("../data/help_temp.txt", "../data/help.txt")) {
          send_to_char("Unable to update helpfile list.\r\n", ch);
          bug("helpfile: Can't rename help_temp.txt to help.txt", 0);
          return;
        }
      }
      else
        send_to_char("Great work on finishing a new helpfile! It currently wasn't on the list.\r\n", ch);
    }

    else {
      char *buf = 0;
      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);
    }
  }

```
Source Link
BrainFRZ
  • 841
  • 11
  • 26

Read a helpfiles textfile or potentially delete one if given an argument that's in the list

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.

  void do_helpfiles(CHAR_DATA *ch, char *argument) {
    if (!(get_trust(ch) >= (111 - 9))) {
      do_function(ch, &do_help, argument);
      return;
    }

    FILE *fhelp = fopen("../data/help.txt", "r");
    if (!fhelp) {
      send_to_char("Unable to read helpfiles list.\r\n", ch);
      bug("helpfiles: Unable to read help.txt", 0);
      return;
    }

    long flen;
    const size_t MAX_LINE_LENGTH = 50;
    char arg[27648], helpfile[27648];
    argument = one_argument(argument, arg);
    strcpy(helpfile, argument);

    if (!str_cmp(arg, "done") || !str_cmp(arg, "clear")) {
      if (!strlen(helpfile)) {
        send_to_char("Syntax: helpfiles done helpfile\r\n", ch);
        return;
      }

      FILE *ftemp = fopen("../data/help_temp.txt", "w");
      if (!ftemp) {
        send_to_char("Unable to write temp list file.\r\n", ch);
        bug("helpfiles: Unable to write to help_temp.txt", 0);
        fclose(fhelp);
        return;
      }

      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) {
          printf_to_char(ch, "Great work! Removing all instances of %s from the helpfile list.\r\n", helpfile);
          found = TRUE;
        }
        else if (!match) {
          strncat(buf, "\n", sizeof(buf) - strlen(buf) - 1);
          fputs(buf, ftemp);
        }
      }

      fclose(ftemp);
      fclose(fhelp);

      if (found) {
        if (remove(HELP_FILE)) {
          send_to_char("Unable to update helpfile list.\r\n", ch);
          bug("helpfile: Can't delete help.txt", 0);
          return;
        }

        if (rename("../data/help_temp.txt", "../data/help.txt")) {
          send_to_char("Unable to update helpfile list.\r\n", ch);
          bug("helpfile: Can't rename help_temp.txt to help.txt", 0);
          return;
        }
      }
      else
        send_to_char("Great work on finishing a new helpfile! It currently wasn't on the list.\r\n", ch);
    }

    else {
      char *buf = 0;
      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);
    }
  }

```