19 Mar, 2015, Hades_Kane wrote in the 1st comment:
Votes: 0
So we have a custom account thing setup, and well, I think today we exceeded some system based string length or some such.

Our account information is stored in an accounts_list.txt, and whenever someone tries to add to it, the MUD is crashing (but oddly enough, not creating a coredump).

Checking the logs, the last error is on BUG: Fread_word: word too long.

Then you check both the accounts_list.txt and the account file itself (again, another .txt file), the last entries aren't saving right (truncated, or a line break missing, etc).

/*
* Read one word (into static buffer).
*/
char *fread_word( FILE *fp )
{
static char word[MAX_INPUT_LENGTH];
char *pword;
char cEnd;

do
{
cEnd = getc( fp );
}
while ( isspace( cEnd ) );

if ( cEnd == '\'' || cEnd == '"' )
{
pword = word;
}
else
{
word[0] = cEnd;
pword = word+1;
cEnd = ' ';
}

for ( ; pword < word + MAX_INPUT_LENGTH; pword++ )
{
*pword = getc( fp );
if ( cEnd == ' ' ? isspace(*pword) : *pword == cEnd )
{
if ( cEnd == ' ' )
ungetc( *pword, fp );
*pword = '\0';
return word;
}
}

bug( "Fread_word: word too long.", 0 );
exit( 1 );
return NULL;

}


#define MAX_INPUT_LENGTH	 1024


I'm thinking that maybe the accounts file has exceeded the MAX_INPUT_LENGTH.

Does this seem right?

Would I be able to increase the MAX_INPUT_LENGTH safely without messing anything else up?
19 Mar, 2015, Jindrak wrote in the 2nd comment:
Votes: 0
I'd start by checking for a possible corrupt file or missing tilde or other end of line/file item.

It's something that I've run into in the few flat files I have and can sometimes be a misleading error message due to where it is occurring. Basically the end of line/file is never being reached so the for() loop is never exited until MAX_LINE_LENGTH occurs.
19 Mar, 2015, Hades_Kane wrote in the 3rd comment:
Votes: 0
I restored a backup from last night of the two files that were changed and causing this to happen, and everything does fine until/unless someone (even another player creating a separate account) causes that file to be written to, at which case the last line of the file is truncated and the file path finishes it off.
19 Mar, 2015, quixadhal wrote in the 4th comment:
Votes: 0
LOL @ ancient C with fixed length buffers… :)

You can easily increase the size of that buffer (or MAX_STRING_LENGTH, for that matter), assuming you're compiling on a modern platform and not some antique 386sx.

What consequences will there be? Increased memory use for sure, like that matters nowadays when your sever probably has 8G or more of RAM. If you increase MAX_INPUT_LENGTH, the potential is there for people to type longer things into the command parser, which would use slightly more CPU to process. Again, not an issue on semi-modern hardware.

The biggest thing in most Dikurivative codebases is that half the places use the constants, and half of them still use numbers hard-coded…. so even though your buffer is larger, if the code that fetches stuff from the socket to put in the input buffer still uses 256 (or whatever), it may not change anything.

In your case, it sounds like buggy output code. If so, that's easier to fix than buggy input code. When you're outputting, you already know the lengths of everything and should be able to just use fprintf() to ensure nice clean formatting, rather than puttering around with writing "words" or whatever.
19 Mar, 2015, Hades_Kane wrote in the 5th comment:
Votes: 0
quixadhal said:
LOL @ ancient C with fixed length buffers… :)

You can easily increase the size of that buffer (or MAX_STRING_LENGTH, for that matter), assuming you're compiling on a modern platform and not some antique 386sx.

What consequences will there be? Increased memory use for sure, like that matters nowadays when your sever probably has 8G or more of RAM. If you increase MAX_INPUT_LENGTH, the potential is there for people to type longer things into the command parser, which would use slightly more CPU to process. Again, not an issue on semi-modern hardware.

The biggest thing in most Dikurivative codebases is that half the places use the constants, and half of them still use numbers hard-coded…. so even though your buffer is larger, if the code that fetches stuff from the socket to put in the input buffer still uses 256 (or whatever), it may not change anything.

In your case, it sounds like buggy output code. If so, that's easier to fix than buggy input code. When you're outputting, you already know the lengths of everything and should be able to just use fprintf() to ensure nice clean formatting, rather than puttering around with writing "words" or whatever.


If I were several years younger and MUDs were as popular as they once were… I sure would be looking at learning a better language :p

Thanks for the info, I felt like changing those values would be "safe" and just increase memory, but there are some aspects of the codebase I haven't had reason/need to tinker with yet, so I wanted to get some more seasoned advice :)
19 Mar, 2015, Tyche wrote in the 6th comment:
Votes: 0
Hades_Kane said:
Checking the logs, the last error is on BUG: Fread_word: word too long.

Fread_word() looks for a matching quotes if there is an opening quote, or if without quotes not used just one word which will be delimited by a space.
19 Mar, 2015, Hades_Kane wrote in the 7th comment:
Votes: 0
Now that I'm home and not at work and can use more brainpower for this… it occurs to me the issue has to be in the writing, not the reading, and that fread_word is encountering a problem because the file isn't being written as it should be.
19 Mar, 2015, Hades_Kane wrote in the 8th comment:
Votes: 0
Ok, I think I got it.

Snippet of the writing portion if creating a new account:
//End of list?
case 'E':
if (!str_cmp (word, "End"))
{
//Add the account to the end of the list
sprintf(buf2, "%s\r\nAcc %s %s\r\nEnd\r\n", buf2, ch->name, arg2);
fclose(fp);

//Reopen as blank and write full file with buf2
sprintf(buf, "%saccount_list.txt", ACCOUNT_DIR);
if ((fp = fopen (buf, "w+")) == NULL)
{
send_to_char("The account list is missing, please inform an administrator\r\n", ch);
bug ("Account list not found.", 0);
return;
}
fprintf(fp, buf2);
fclose(fp);


The declaration of buf higher in the code, I added a *5 to the size:
char buf[MSL *5];
char buf2[MSL *5];


That seems to have solved the problem.

So I was running up against a MSL limitation, but not in the way/place I was originally thinking.
20 Mar, 2015, alteraeon wrote in the 9th comment:
Votes: 0
You're not checking the return code of fgetc to look for EOF. The correct way to do this is roughly:

int x = fgetc(stream);
if (x == EOF) {
cut_end_of_file_warning();
return;
}


See also the man page for more details. Basically fgetc() can return 257 different values, one of which is outside the ascii range.

It's got nothing to do with your buffer size. You're simply reaching end of file and looping, so you'll fill any buffer you give it.

-dentin

Alter Aeon MUD
http://www.alteraeon.com
0.0/9