I've known a surprising number of developers who say, "Why use any higher level abstractions, you can just do this all in C, and the code will be cleaner and easier to read." Sometimes, they're right. Other times… not so much. And then there are the developers who find C too abstract for their tastes, and eschew things like structs.

That's what Renee encountered when inheriting a chat server written in C. I'm guessing it was an IRC server, based on some terminology in the code.

bool channelexists[MAXCHANNELS];
char channelname[MAXCHANNELS][25];
char channeltopic[MAXCHANNELS][205];
char channeltopic_setby[MAXCHANNELS][50];
long channeltopic_settime[MAXCHANNELS];
bool channel_mode_registered[MAXCHANNELS];
bool channel_mode_onlyopstopic[MAXCHANNELS];
bool channel_mode_autovoice[MAXCHANNELS];
bool channel_mode_moderated[MAXCHANNELS];
bool channel_mode_private[MAXCHANNELS];
bool channel_mode_blockcolours[MAXCHANNELS];
bool channel_mode_inviteonly[MAXCHANNELS];
bool channel_mode_ircopsonly[MAXCHANNELS];
long channel_creationtime[MAXCHANNELS];
bool channel_bereitswho[MAXCHANNELS];
char channel_pw[MAXCHANNELS][CHANPWLEN + 1];
int channel_userlimit[MAXCHANNELS];
unsigned char channel_bans[MAXCHANNELS][MAXBANSPERCHAN][MAXUSERMASKLEN];
char channel_bans_actor[MAXCHANNELS][MAXBANSPERCHAN][50];
long channel_bans_time[MAXCHANNELS][MAXBANSPERCHAN];
int channel_invite[MAXCHANNELS][MAXINVITESPERCHAN];
long channel_invite_time[MAXCHANNELS][MAXINVITESPERCHAN];

This is an incomplete list of all of their global variables. These variables were allocated at application startup. There wasn't a single dynamic memory allocation anywhere in the entire program, actually.

For some of these arrays, the index was the user ID. So, for example:

int useraddchan(int userid,int chanid,char isop) {
 int r;
 r = 0;
 while (r < MAXCHANSPERUSER) {
  if (client_inchannel[userid][r] < 0) {
   client_inchannel[userid][r] = chanid;
   client_inchannel_op[userid][r] = false;
   client_inchannel_hop[userid][r] = false;
   client_inchannel_voice[userid][r] = false;
   if (MAINTENANCEMODE == 0) {client_inchannel_admin[userid][r] =
isop;}else{client_inchannel_admin[userid][r] = false;}
   return;
  }
  r += 1;
 }
}

I really enjoy how this function doesn't actually return a value on any code path. Really great.

And note that MAINTENANCEMODE flag.

//Activate the following mode if the server keeps crashing.
//It disables complex functions (oper login and gline/kill still
// possible) to lower the crash risk
#define MAINTENANCEMODE 0

If the server keeps crashing, you can recompile it in maintenance mode. I think that should be a "when", frankly.

[Advertisement] Utilize BuildMaster to release your software with confidence, at the pace your business demands. Download today!