30 Nov, 2009, Elervan wrote in the 1st comment:
Votes: 0
Hello,

I am wondering how to handle this situation. Before me I have a heavily modified ROM that has many hands touching both stable and drunk since 1996. It's a beautiful M.U.D. with a codebase that looks like a tornado went through the code. How does one clean this up? Do I even bother trying as most the code is poorly commented. Or would it be easier to simply just grab a stock ROM codebase and start re-adding features back into it? I'm not the greatest programmer in the world, but I should be able to get something done.

I do know, I use cygwin to work on things at home on my computer before uploading them to a live server for actual use. The M.U.D. compiles on cygwin, and boots in either gdb or using the startup script. (Can't seem to get the perl start to work) However, nothing happens, it boots it says its ready to rock on port ####, but after that nothing. It acts like it isn't handling connections correctly. I am assuming the issue would be in game_loop_unix? But I'm not quite sure.

– Elervan
30 Nov, 2009, David Haley wrote in the 2nd comment:
Votes: 0
Cleaning up is generally more frustrating in the short term but much easier in the long run than trying to re-add all the little changes to a stock base. A lot of people (myself included) have a tendency to want to throw their hands in the air and start from stock again to not have to deal with the mess.

How to clean up the code depends on what exactly is wrong with it. If there are few comments, one thing you can do is to add comments. You can find and eliminate redundancies by decomposing blocks into helper functions.

One thing to keep in mind is: "if it ain't broke, don't fix it" – if you start changing things for the sake of changing them, you might end up with something that is messy and doesn't work.

That said, it seems that you do actually have a broken base in that it won't take connections. Since it works in gdb, you could start by running it in gdb, trying to connect, and then break in gdb to see what it's up to. Or just run it in gdb and break without connecting, and make sure it's somewhere in the network monitoring code.
30 Nov, 2009, Elervan wrote in the 3rd comment:
Votes: 0
Thanks for the tips.

The odd thing about not accepting connections is this: on *nix it works fine. on cygwin it will compile and boot just fine, but wont' accept connections. Like I said I do most my work on this computer which uses cygwin and then use *nix for keeping it live. I'm going to take your suggestion with gdb to see where it might be stalling at on cygwin.
30 Nov, 2009, Elervan wrote in the 4th comment:
Votes: 0
Hmm ok,
I can't seem to get any info from gdb, the mud doesn't hang, it doesn't crash it just sits there waiting to accept a connection. But for some reason running it in cygwin it doesn't want to accept any.
30 Nov, 2009, Scandum wrote in the 5th comment:
Votes: 0
Might have to open the port it's using in your firewall.
30 Nov, 2009, David Haley wrote in the 6th comment:
Votes: 0
When running it on your Windows/Cygwin computer, are you also connecting to it from your Windows/Cygwin computer? It's possible that you have a firewall issue on the Windows computer.
30 Nov, 2009, Elervan wrote in the 7th comment:
Votes: 0
Yup. I've tested this with other codebases (stock rom, tbamud, wickedmud, diku) they all work fine. Something in this code that handles connections is just funky.
30 Nov, 2009, JohnnyStarr wrote in the 8th comment:
Votes: 0
This might be an obvious question, but did you look to see what comm.c has set as the mud_ipaddress or whatever your version calls it?
It will look like:
/* Set this to the IP address you want to listen on (127.0.0.1 is good for */
/* paranoid types who don't want the 'net at large peeking at their MUD)*/
char *mud_ipaddress = "0.0.0.0";

I have had conflicts with my router by not setting it to "127.0.0.1" and I was running ROM through
cygwin on a Windows box. If this is in fact the issue, it should be logged as an error.
30 Nov, 2009, kiasyn wrote in the 9th comment:
Votes: 0
0.0.0.0 should be fine as it means 'bind to all ip addresses'

if its not working, theres another problem somewhere in ti
30 Nov, 2009, Elervan wrote in the 10th comment:
Votes: 0
Yup I've looked at that as well. And it's set correctly. So I'm stumped. It works fine on any *nix OS, but for some reason just doesn't not want to work correctly with cygwin.
30 Nov, 2009, Tyche wrote in the 11th comment:
Votes: 0
Not enough information.
Like what was said, trace with gdb.
30 Nov, 2009, Elervan wrote in the 12th comment:
Votes: 0
I'd love to give you all more information from gdb. However, I get nothing from it. And I'm not familiar with adding debugging and break points into the code to give more information. I just know bt comes back with nothing. The last thing I see in gdb is this:

Mon Nov 30 16:39:38 2009 :: boot_db() - wrote exodus.pid
Mon Nov 30 16:39:38 2009 :: Exodus is ready to rock on port 4000.


Now if I ctrl + c to get back to the command prompt in gdb and do a bt I get this:

#0 0x7c8106f9 in KERNEL32!CreateThread ()
from /cygdrive/c/WINDOWS/system32/kernel32.dll
Cannot access memory at address 0x3
30 Nov, 2009, quixadhal wrote in the 13th comment:
Votes: 0
Out of curiosity… if you know it works fine on other unix-type OS's, why not run it on such? If you don't have a spare bit of hardware, you can always download a VMware image of <pick-your-distro> and run it in that. I actually do that when I'm compiling a lot, because my VM on my gaming rig is MUCH faster than my actual file server.
30 Nov, 2009, Elervan wrote in the 14th comment:
Votes: 0
Actually I prefer doing work on my pc, and hate the constant uploading/downloading of files between this and the server live is on. I figure if I keep a working copy here and do the work on here, I can just merely upload the files, recompile, reboot and wala.

Purely laziness I guess. As for VM, I would do it however this computer is not the greatest. 758 mb of 133 ram. I lag enough just having windows :)

Also, I want to figure this out because if its poor coding practice that is causing the issue, I would like to learn from it and fix it. As I said, this thing has been through some years of abuse, I just like a lot of the features it already has. I'm tempted to just code stock and re-add as then I would actually get what I want the way I want it.
30 Nov, 2009, JohnnyStarr wrote in the 15th comment:
Votes: 0
Elervan said:
Also, I want to figure this out because if its poor coding practice that is causing the issue, I would like to learn from it and fix it.


If the application runs on *nix systems, but not windows / cygwin, then it if it is poor coding then wouldn't it
be limited to OS dependant segments? If so, then you could go to anywhere (WIN32) is defined. However
cygwin runs under (UNIX) does it not? If that's the case, I doubt that it's badly written code, but rather a router / network issue.
30 Nov, 2009, quixadhal wrote in the 16th comment:
Votes: 0
Fair enough. :)

I see a lot of people who try to use cygwin because they assume that's their only choice besides setting up a whole other computer, so I tend to suggest alternatives first – and because cygwin is kinda sad these days.

There are differences between the cygwin/windows environment and the unix environment, and one of those could be your problem. First thing I'd do is download some MUD driver out there that's known to work in cygwin (SmaugFUSS does, I think), and see if you can get it up and running. If so, it's a problem with your old codebase. If not, it's a problem with your firewall/configuration/etc.

Trust me, updating your antique will be very painful… my own rust bucket was originally run on a Sun 4/110 using SunOS back in 1993, and I've dragged it kicking and screaming onto Debian linux.

If it's your code, I'd add some extra debugging to the parts where the socket connections are accepted. If you know the connection gets there, it may be an I/O issue. If you never even see the socket connection attempt, the old code might be doing some fiddling with sockets that cygwin doesn't support.

Good luck!
30 Nov, 2009, Elervan wrote in the 17th comment:
Votes: 0
Not sure how it can be a router/network issue when any other codebase I use works just fine. I have never seem to get this thing to work unless I replace game_loop_unix with a stock ROM version. I could be wrong, not sure, here's the game_loop_unix from it.

#if defined(unix)
void game_loop_unix (int control, int whosock, int areasock) {
struct timeval last_time;
fd_set in_set, out_set; /* , exc_set; */
DESCRIPTOR_DATA *d;

/* int maxdesc; */
signal (SIGPIPE, SIG_IGN);
gettimeofday (&last_time, NULL);
current_time = (time_t) last_time.tv_sec;
while (!merc_down) {
FD_ZERO (&in_set);
FD_ZERO (&out_set);

/* FD_ZERO(&exc_set); */
FD_SET (control, &in_set);
if (whosock != -1)
FD_SET (whosock, &in_set);
if (areasock != -1)
FD_SET (areasock, &in_set);

/* maxdesc = control; */
for (d = descriptor_list; d; d = d->next) {

/* maxdesc = UMAX(maxdesc, d->descriptor); */
FD_SET (d->descriptor, &in_set);
FD_SET (d->descriptor, &out_set);

/* FD_SET(d->descriptor, &exc_set); */
}
if (select (fdsize, &in_set, &out_set, NULL, NULL) < 0) {
perror ("Game_loop: select: poll");
exit (1);
}

/*
* New connection?
*/
if (FD_ISSET (control, &in_set))
init_descriptor (control);
if (whosock != -1)
if (FD_ISSET (whosock, &in_set))
dump_who (whosock);
if (areasock != -1)
if (FD_ISSET (areasock, &in_set))
dump_areas (areasock);

/*
for (d = descriptor_list; d != NULL; d = d_next)
{
d_next = d->next;
if (FD_ISSET(d->descriptor, &exc_set))
{
FD_CLR(d->descriptor, &in_set);
FD_CLR(d->descriptor, &out_set);
if (d->character && d->character->level > 1)
save_char_obj(d->character);
d->outtop = 0;
close_socket(d);
}
} */

/*
* Process input.
*/
for (d = descriptor_list; d != NULL; d = d_next) {
isorder = FALSE;
d_next = d->next;
d->fcommand = FALSE;
if (FD_ISSET (d->descriptor, &in_set)) {
if (d->character != NULL)
d->character->timer = 0;
if (!read_from_descriptor (d)) {
FD_CLR (d->descriptor, &out_set);
if (d->character != NULL && d->character->level > 1)
save_char_obj (d->character);
d->outtop = 0;
close_socket (d);
continue;
}
}
if (d->character != NULL && d->character->daze > 0)
–d->character->daze;
if (d->character != NULL && d->character->wait > 0) {
–d->character->wait;
continue;
}
read_from_buffer (d);
if (d->incomm[0] != '\0') {
d->fcommand = TRUE;
keepincomm = FALSE;
stop_idling (d->character);
if (d->connected == CON_START_MULTICLASS
|| d->connected == CON_FINISH_MULTICLASS)
multiclass (d, d->incomm);

else if (d->showstr_point)
show_string (d, d->incomm);

else if (d->pString && d->editor == EDIT_MENU)
edit_menu (d->character, d->incomm);

else if (d->pString && d->editor == SEARCH_REPLACE)
search_replace (d->character, d->incomm);

else if (d->pString && d->editor == EDIT_LINE_NUMBER)
edit_line_number (d->character, d->incomm);

else if (d->pString && d->editor == INSERT_LINE_NUMBER)
insert_line_number (d->character, d->incomm);

else if (d->pString && d->editor == DELE_LINE_NUMBER)
dele_line_number (d->character, d->incomm);

else if (d->pString && d->editor == EDIT_NEW_LINE)
edit_new_line (d->character, d->incomm);

else if (d->pString && d->editor == INSERT_NEW_LINE)
insert_new_line (d->character, d->incomm);

else if (d->pString)
string_add (d->character, d->incomm);

/* else if (d->character && d->character->pcdata && d->character->pcdata->cg_state >= CG_START_PM_YT && d->character->pcdata->cg_state <= CG_NYT_D_PM)
cardgame_menu (d->character, d->incomm);*/

else if (d->connected == CON_PLAYING) {
if (!run_olc_editor (d)) {
char mybuf[MAX_STRING_LENGTH];
char *cptr, *cptr2;
bool found, docmd = TRUE;
char *cptr3;
char mycmd[MAX_STRING_LENGTH],
bufcmd[MAX_STRING_LENGTH];
int cmd;
strcpy (mybuf, d->incomm);
cptr = mybuf;
while ((cptr2 = strchr (cptr, ';')) != NULL) {
strcpy (bufcmd, cptr2 + 1);
cptr3 = bufcmd;
while (*cptr3 != '\0') {
if (isalpha (*cptr3))
break;
cptr3++;
}
strcpy (mycmd, cptr3);
cptr3 = mycmd;
while (*cptr3 != '\0') {
if (isspace (*cptr3)) {
*cptr3 = '\0';
break;
}
cptr3++;
}
found = FALSE;
for (cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++) {
if (mycmd[0] == cmd_table[cmd].name[0]
&& !str_prefix (mycmd,
cmd_table[cmd].name)
&& (cmd_table[cmd].level <=
d->character->
trust || cmd_table[cmd].level <=
d->character->level)) {
found = TRUE;
break;
}
}
if (!found)
for (cmd = 0;
social_table[cmd].name[0] != '\0'; cmd++) {
if (mycmd[0] ==
social_table[cmd].
name[0] && !str_prefix (mycmd,
social_table
[cmd].name)) {
found = TRUE;
break;
}
}
if (found) {
*cptr2 = '\0';
substitute_alias (d, cptr);
docmd = FALSE;
keepincomm = TRUE;
strcpy (d->incomm, cptr2 + 1);
break;
} else
*cptr2 = 7;
}
if (docmd)
substitute_alias (d, d->incomm);
}
} else {
nanny (d, d->incomm);
}
if (!keepincomm)
d->incomm[0] = '\0';
}
}
update_handler ();
for (d = descriptor_list; d != NULL; d = d_next) {
d_next = d->next;
if ((d->fcommand || d->outtop > 0)
&& FD_ISSET (d->descriptor, &out_set)) {
if (!process_output (d, TRUE)) {
if (d->character != NULL && d->character->level > 1) {
save_char_obj (d->character);
}
d->outtop = 0;
close_socket (d);
}
}
}
/*
* Synchronize to a clock.
* Sleep( last_time + 1/PULSE_PER_SECOND - now ).
* Careful here of signed versus unsigned arithmetic.
*/
{
struct timeval now_time;
long secDelta;
long usecDelta;
gettimeofday (&now_time, NULL);
usecDelta =
((int) last_time.tv_usec) -
((int) now_time.tv_usec) + 1000000 / PULSE_PER_SECOND;
secDelta = ((int) last_time.tv_sec) - ((int) now_time.tv_sec);
while (usecDelta < 0) {
usecDelta += 1000000;
secDelta -= 1;
}
while (usecDelta >= 1000000) {
usecDelta -= 1000000;
secDelta += 1;
}
if (secDelta > 0 || (secDelta == 0 && usecDelta > 0)) {
struct timeval stall_time;
stall_time.tv_usec = usecDelta;
stall_time.tv_sec = secDelta;
if (select (0, NULL, NULL, NULL, &stall_time) < 0) {
perror ("Game_loop: select: stall");
//exit (1);
}
}
}
gettimeofday (&last_time, NULL);
current_time = (time_t) last_time.tv_sec;
}
return;
}


#endif /* */


It's longer than stock ROM, and if it works with stock ROM's version what in this version is causing the issue? I just find it odd that this function is what is causing it. And no it can't be a network/router issue because I've also ran this on a Fedora machine on the same network just fine.
30 Nov, 2009, Elervan wrote in the 18th comment:
Votes: 0
Yeah, while watching gdb and attempting to connect from a client, you see nothing, not even a attempt to connect. So it *has* to be the way it's handling sockets that cygwin just doesn't like. And I'm not good at adding DEBUG pieces to the code :(
30 Nov, 2009, quixadhal wrote in the 19th comment:
Votes: 0
Around lines 41, change:

Quote
if (FD_ISSET (control, &in_set))
init_descriptor (control);


to add more debugging info…. you want to print stuff to the console so you can see where your code is sitting.

Quote
if (FD_ISSET (control, &in_set)) {
fprintf(stderr, "Got a new connection!\r\n");
init_descriptor (control);
}


Do that all over the place, so you can actually SEE the program flow. gdb is a great tool, and sometimes you can set watch variables, but often just adding debug statements is the only way to know for sure where things are, espeically when you're debugging real-time code like socket handling.
30 Nov, 2009, Elervan wrote in the 20th comment:
Votes: 0
So after adding some of those fprintf lines, I should see those pop up after the mud has booted and I attempt to connect correct? If so, what happens if there is nothing showing up?
0.0/30