10 Apr, 2009, Lancsta wrote in the 1st comment:
Votes: 0
First off Sunder is ROM based, but since the original account system is from Godwars, I thought I'd post here.

I have random data like race names, object short_descr, titles, all sorts of things. The accounts file is an online file, and a heavily modified version of Brian "Jobo" Graversen's account system. I think it may be being pulled from load_char where it looks up the account. Just a notice we didn't install or modify this code, it was stock in Sunder. I can pastebin any of the other functions when I get back from work. Thanks for any input.

if (!str_cmp (word, "Acct"))
{
struct account_type *tmp;
int i = 0;
char *tword;
bool foundmatch = FALSE;
fMatch = TRUE;

tword = fread_string (fp);

for ( tmp = account_list; tmp != NULL; tmp = tmp->next )
{
if (!strcmp (tword, tmp->acc_name) )
{
ch->pcdata->account = tmp;
foundmatch = TRUE;
break;
}
}
if (!foundmatch)
bugf ( "Can't find an account for %s. Probably fatal.", ch->name );

/* Sanity Check - in case the mud crashed before saving account data or sumthin. */
foundmatch = FALSE;
for (i = 0 ; i < MAX_CHARS ; i++)
{
if (ch->pcdata->account->char_name[i])
{
if (!strcmp (ch->name, ch->pcdata->account->char_name[i]) )
{
foundmatch = TRUE;
break;
}
}
}
if (!foundmatch) /* This time, not so fatal - run through the list again */
{
for (i = 0 ; i < MAX_CHARS ; i++)
{ /* Got a live one! */
if (!ch->pcdata->account->char_name[i])
{
foundmatch = TRUE;
ch->pcdata->account->char_name[i] = str_dup (ch->name);
break;
}
}
}
if (!foundmatch) /* This time more annoying, but still not fatal. */
{
bugf ( "Existing Char %s:%s no account slot.",
ch->name, ch->pcdata->account->acc_name );
}
free_string ( tword );
break;
}
10 Apr, 2009, Davion wrote in the 2nd comment:
Votes: 0
Where exactly is the random data showing up? I'm guessing by the title it appears in the file once it's been written, if so, we'd need the code where it writes the account, not where it loads. Possibly in fwrite_char()
10 Apr, 2009, Lancsta wrote in the 3rd comment:
Votes: 0
It shows up in the accounts list itself where it lists the players.
Lancsta~
password~
15 0 3 1
Testingchar~
Tyr~
Testingchar~

NEXT~

That's what the accounts list looks like per account. One issue is that every account is in this one huge list. First is the account name, password, account info ie. status heros, perm_death players, then it lists the players per the account. Lately it's been duplicating the player names, like Testingchar.

void fwrite_accounts ( void )                                                   
{
FILE *fptr;
char buf[MAX_STRING_LENGTH*10];
int i;
struct account_type *tmp;

// buf[0] = '\0';

#if !defined(WIN32)
SNP ( buf, "cp -f %s%s %s%s.bak > /dev/null", DATA_DIR, ACCOUNT_FILE, DATA$

if ( system ( buf ) == 1 )
{
bugf ( "Failed to BACKUP ACCOUNTS File. Aborting Write." );
}
#endif

buf[0] = '\0';

SNP ( buf, "%s%s", DATA_DIR, ACCOUNT_FILE );

if ( ( fptr = fopen ( buf, "w+" ) ) == NULL )
{
bugf ( "Failed Opening ACCOUNTS File for writing." );
return;
}

for ( tmp = account_list; tmp != NULL; tmp = tmp->next )
{
if (tmp->status == ACCT_REJECTED_DELETE)
continue; /* Acct Deleted */

fprintf ( fptr, "%s~\n", tmp->acc_name );
fprintf ( fptr, "%s~\n", tmp->password );
fprintf ( fptr, "%d %d %d %d\n", tmp->status,
tmp->permadead, tmp->heroes, tmp->legends );

for (i = 0; i < MAX_CHARS; i++)
{
if (tmp->char_name[i])
{
fprintf (fptr, "%12s~\n", tmp->char_name[i] );
}
}
fprintf (fptr, "NEXT~\n" );
}

fprintf ( fptr, "END~\n" );
fclose ( fptr );
return;
}

That's how it writes the accounts.
10 Apr, 2009, Scandum wrote in the 4th comment:
Votes: 0
if (!strcmp (ch->name, ch->pcdata->account->char_name[i]) )


should probably be:

if (!strcasecmp (ch->name, ch->pcdata->account->char_name[i]) )


Since strcmp might fail if Bubba logs in as BubbA, which would result in duplicate names. No idea about the random data.
10 Apr, 2009, elanthis wrote in the 5th comment:
Votes: 0
Sounds like the char_list array is not being initialized properly, or you have a memory corruption bug.

Check the account initialization code for the account_list stuff. Compile with all warnings on (-Wall), fix anything that comes up. Also run under Valgrind if you can't spot any initialization errors, which will find any memory corruption bugs (writing to freed pointers, writing past the end of arrays, etc.). GDB could also be a help here.
10 Apr, 2009, Lancsta wrote in the 6th comment:
Votes: 0
elanthis said:
Sounds like the char_list array is not being initialized properly, or you have a memory corruption bug.

Check the account initialization code for the account_list stuff. Compile with all warnings on (-Wall), fix anything that comes up. Also run under Valgrind if you can't spot any initialization errors, which will find any memory corruption bugs (writing to freed pointers, writing past the end of arrays, etc.). GDB could also be a help here.


Yeah I've ran Valgrind a few times trying to spot it. I was even able to recreate the issue a few times by creating multiple characters under an account, creating multiple accounts, and doing copyovers. I know it sounds awful but that was the only way to really "catch" an idea of where it was happening.

I've also got this already setup with my Makefile.
LIBS     = -lz
FLAGS = -O2 -Wall -g3 $(PROF) $(NOCRYPT)
INCLUDES = -I.
PROF = -DOLD_RAND -DNOCRYPT
C_FLAGS = $(FLAGS) $(INCLUDES)
L_FLAGS = $(FLAGS) -O2 $(PROF) $(INCLUDES)
EXE = sundermud
CC = gcc
O_DIR = o/

Thanks for all the input guys definately a different approach that I hadn't thought of with this damn thing.
Here's a pastbin of the system itself.
Account system paste-bin

I also noticed, not sure if it matters, that in interp.c
struct account_type *account_list;
While in globals.h
extern struct account_type *account_list;
Interp doesn't have any account info in it at all.
18 Apr, 2009, Lancsta wrote in the 7th comment:
Votes: 0
Just wondering if anyone else had any more suggestions. It seems that after someone creates a new player in "account b" for example, and then someone else creates a new player, in "account d". The name for "account d" is also rewritten over the name in "account b". I noticed this happens after a copyover or reboot. Sometimes item descriptions, character titles, ip addys, all sorts of stuff gets written. I've looked over and over and can't figure it out. Valgrind doesn't show any leaks at all.
18 Apr, 2009, Davion wrote in the 8th comment:
Votes: 0
Just took a quick peek at the account system. You might want to try zero'ing the data for the player names. That might be your best bet.

tmp = alloc_perm ( sizeof ( struct account_type ), "account_type:load" );
tmp->next = NULL;
tmp->acc_name = str_dup ( word ); /* Email Address of Account */

That section right there sets the default values for the account. In here, just add something like

for(i = 0; i < MAX_CHARS ; ++i ) tmp->char_name[i] = 0;


See if that helps. Usually when initializing a new data structure it's a really good idea to set all the values to something (if you have no default value for it, just use 0, or NULL). This way you don't end up with random stuff in your pointers. You can accomplish this a lot easier in C by either using 'calloc()' to allocate things, as it automatically zero's the entire chunk of memory. You can declare a 'dummy' object as a static (much like how everything in recycle.c works) because by default static variables are zeroed as well.
19 Apr, 2009, Lancsta wrote in the 9th comment:
Votes: 0
I totally felt you on that one, it made total sense. But I can't throw that in load_accounts, because it just blanks out the entire list. I'm thinking of just converting back to the original account system, with the login option screen. I'm really hesitant on this because I like not having to choose from login. I'm going to try to rewrite it so every account get's it's own file, instead of having one huge list that gets parsed everytime an account is changed, created, or added to.
20 Apr, 2009, Sharmair wrote in the 10th comment:
Votes: 0
When you initialize your new struct (either setting the members to zero or some default value),
you should do is as close to the creation of that struct as possible (if you were using C++ here,
you would do it in the constructor), in your case here, it looks like it would be done right after
the alloc_perm call and BEFORE you set any data from the load. It might even be better to
get the new struct with a function (maybe called new_account) to wrap the actual allocation
and initialization of the struct in one place.
0.0/10