/* Config file routines

   OperStats - Copyright (c) 2000-2003 Darcy Grexton
   Contact: skold@habber.net, skold @ HabberNet

   See doc/LICENSE for licensing details.
 */

#include "../inc/operstats.h"

SRA *sralist = NULL;
ULine *ulinelist = NULL;

/* Some vars */
char s_OperServ[NICKLEN], s_StatServ[NICKLEN], s_GlobalNoticer[NICKLEN];
char tlds[64], snoopchan[32], def_akill_reason[256], joinchan[32];
char mirclink[256], mirclinkimg[256], javalinkimg[256], globalmsg[64];
char logoimg[256], network_name[32], cygnus_server[65];

Boolean_T operserv_on = FALSE, statserv_on = FALSE, globalnoticer_on = FALSE;
Boolean_T spamserv_on = FALSE, globalonakill_on = FALSE, stamplogons_on = FALSE;
Boolean_T logupdates_on = FALSE, dumpchans_on = FALSE, javaclient_on = FALSE;
Boolean_T dumpstats_on = FALSE, dumptlds_on = FALSE, sharesras_on = FALSE;
Boolean_T shareakills_on = FALSE, globalonlag_on = FALSE, globalonspeed_on = FALSE;
Boolean_T globalonauth_on = FALSE, haveserv_on = FALSE, ignoreulines_on = FALSE;
Boolean_T noisyflood_on = FALSE, dumpservers_on = FALSE;

uint8 unreal_numeric, nonwildreq, floodmsgs, ircdtype, maxclones, maxclonekills;
uint8 helpindex, securitysetting, warnclients;
uint16 update_timeout, wait_restart, floodtime, lagthreshold, ping_delay;
uint32 clonekill_time, def_akill_time;

/* Reset the state of conf values before a rehash */
void reset_conf ()
{
    *tlds = *joinchan = *snoopchan = *def_akill_reason = *mirclink = *logoimg = 0;
    *mirclinkimg = *javalinkimg = *globalmsg = *network_name = *cygnus_server = 0;

    operserv_on = statserv_on = globalnoticer_on = spamserv_on = FALSE;
    globalonakill_on = stamplogons_on = logupdates_on = haveserv_on = FALSE;
    dumpchans_on = javaclient_on = dumpstats_on = dumptlds_on = FALSE;
    sharesras_on = shareakills_on = globalonlag_on = noisyflood_on = FALSE;
    globalonspeed_on = globalonauth_on = ignoreulines_on = dumpservers_on = FALSE;

    update_timeout = ping_delay = nonwildreq = def_akill_time = 0;
    unreal_numeric = ircdtype = wait_restart = maxclones = 0;
    maxclonekills = lagthreshold = securitysetting = floodmsgs = 0;
    clonekill_time = helpindex = floodtime = 0;
}

/* Add a new SRA into the sra list. */ 
static SRA *new_sra (const char *nick, const char *pass)
{
    SRA *sra;

    sra = scalloc (sizeof (SRA), 1);

    sra->nick = sstrdup (nick);
    sra->pass = sstrdup (pass);

    sra->next = sralist;

    if (sra->next)
        sra->next->prev = sra;

    sralist = sra;

    return sra;
}

/* Add a new U:Line into the U:Lined servers list. */
static ULine *new_uline (const char *name)
{
    ULine *uline;

    uline = scalloc (sizeof (ULine), 1);

    uline->name = sstrdup (name);

    uline->next = ulinelist;
 
    if (uline->next)
	uline->next->prev = uline;
 
    ulinelist = uline;
 
    return uline;
}

/* Load and parse the conf file */
void load_conf ()
{
    FILE *f = fopen (CONFIGFILE, "r");
    char *item, *s, dBuf[BUFSIZE];
#ifdef HAVE_GETTIMEOFDAY
    struct timeval start, now, tmp;
#endif

#ifdef HAVE_GETTIMEOFDAY
    log_sameline (1, "CONF: Loading.... ");
#else
    log ("CONF: Loading....");
#endif

    if (!f)
    {
	log (RPL_NO_CONFIG);
	exit (1);
    }

#ifdef HAVE_GETTIMEOFDAY
    gettimeofday (&(start), NULL);
#endif

    while (fgets (dBuf, 2047, f))
    {
	item = strtok (dBuf, " ");
	strip (item);

	if (*item == '#' || *item == '\t' || *item == ' ' || !*item)
	    continue;

	if (!stricmp (item, "Info"))
	{
	    s = strtok (NULL, " ");
	    strip (s);

	    if (s && strchr (s, '.'))
		memcpy (me.name, s, sizeof (me.name));
	    else
		fatal (0, "Config: Info is not set properly: No server name.");

	    s = strtok (NULL, "");
	    strip (s);

	    if (s)
		memcpy (me.desc, s, sizeof (me.desc));
	    else
	    {
		char tmpchr[32];

		sprintf (tmpchr, "OperStats v%s", version);
		memcpy (me.desc, tmpchr, sizeof (me.desc));
	    }

	    continue;
	}

	if (!stricmp (item, "BindTo"))
	{
	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (me.bindhost, s, sizeof (me.bindhost));
	    else
		fatal (0, "Config: BindTo is not set properly: No host.");

	    s = strtok (NULL, " ");   
	    strip (s);

	    if (s)
		me.bindport = atoi (s);
	    else  
		fatal (0, "Config: BindTo is not set properly: No port.");

	    continue;
	}

	if (!stricmp (item, "Connect"))
	{
	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (me.uplink, s, sizeof (me.uplink));
	    else
		fatal (0, "Config: Connect is not set properly: No uplink.");

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		me.port = atoi (s);
	    else
		fatal (0, "Config: Connect is not set properly: No port.");

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (me.pass, s, sizeof (me.pass));
	    else
		fatal (0, "Config: Connect is not set properly: No password.");

	    continue;
	}

	if (!stricmp (item, "IRCdType"))
	{
	    s = strtok (NULL, "");
	    strip (s);

	    if (!s)
		fatal (0, "Config: IRCdType is not set properly: No value.");

	    if (stristr (s, "DreamForge"))
	    {
		fatal (0, "Config: Sorry, DreamForge is not supported in this release.");
		ircdtype = DREAMFORGE;
	    }

	    else if (stristr (s, "Prometheus"))
		ircdtype = PROMETHEUS;

	    else if (stristr (s, "Bahamut"))
		ircdtype = BAHAMUT;

	    else if (stristr (s, "Unreal 3") && !stristr (s, "3.2"))
	    {
		fatal (0, "Config: Sorry, Unreal versions less than 3.2 are not supported in this release.");
		ircdtype = UNREAL3;
	    }

	    else if (stristr (s, "Unreal 3.2"))
		ircdtype = UNREAL3_2;

	    else
		fatal (0, "Config: IRCdType is not set properly: Invalid value.");

	    continue;
	}

	if (!stricmp (item, "OperatorService"))
	{
	    /* In case the client info changes */
	    char nick[NICKLEN], user[USERLEN], host[HOSTLEN];
	    char real[REALLEN], mode[12];

	    operserv_on = TRUE;

	    strscpy (nick, s_OperServ, sizeof (nick));
	    strscpy (user, os.user, sizeof (user));
	    strscpy (host, os.host, sizeof (host));
	    strscpy (real, os.real, sizeof (real));
	    strscpy (mode, os.mode, sizeof (mode));

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (s_OperServ, s, sizeof (s_OperServ));
	    else
		fatal (0, "Config: OperatorService is not set properly: No nickname.");

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (os.user, s, sizeof (os.user));
	    else
		fatal (0, "Config: OperatorService is not set properly: No username.");

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (os.host, s, sizeof (os.host));
	    else
		fatal (0, "Config: OperatorService is not set properly: No hostname.");

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
	    {
		if (!strchr (s, '+'))
		    fatal (0, "Config: OperatorService: You need a + for modes!");

		memcpy (os.mode, s, sizeof (os.mode));
	    }
	    else
		fatal (0, "Config: OperatorService is not set properly: No modes.");

	    s = strtok (NULL, "");
	    strip (s);

	    if (s)
		memcpy (os.real, s, sizeof (os.real));
	    else
		fatal (0, "Config: OperatorService is not set properly: No realname.");

	    if (!(runflags & RUN_STARTING))
	    {
		/* Check if the client info changed. If so, reintroduce the
		   client with the new info.
		 */
		if (os.isonline && (strcmp (s_OperServ, nick) ||
		    strcmp (os.user, user) || strcmp (os.host, host) ||
		    strcmp (os.mode, mode) || strcmp (os.real, real)))
		{
		    send_cmd (nick, "%s :Client info changed",
			me.token ? "," : "QUIT");
		    intro_user (s_OperServ, os.user, os.host, os.real, os.mode);
		}

		/* If OperServ was previously off, and is now on, introduce
		   the pseudo client if needed.
		 */
		if (!os.isonline && operserv_on == TRUE)
		{
		    intro_user (s_OperServ, os.user, os.host, os.real, os.mode);
		    userstat++;
		    os.isonline = 1;
		}
	    }

	    continue;
	}

	if (!stricmp (item, "StatisticalService"))
	{
	    /* In case the client info changes */
	    char nick[NICKLEN], user[USERLEN], host[HOSTLEN];
	    char real[REALLEN], mode[12];

	    statserv_on = TRUE;

	    strscpy (nick, s_StatServ, sizeof (nick));
	    strscpy (user, ss.user, sizeof (user));
	    strscpy (host, ss.host, sizeof (host));
	    strscpy (real, ss.real, sizeof (real));
	    strscpy (mode, ss.mode, sizeof (mode));

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (s_StatServ, s, sizeof (s_StatServ));
	    else
		fatal (0, "Config: StatisticalService is not set properly: No nickname.");

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (ss.user, s, sizeof (ss.user));
	    else
		fatal (0, "Config: StatisticalService is not set properly: No username.");

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (ss.host, s, sizeof (ss.host));
	    else
		fatal (0, "Config: StatisticalService is not set properly: No hostname.");

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
	    {
		if (!strchr (s, '+'))
		    fatal (0, "Config: StatisticalService: You need a + for modes!");

		memcpy (ss.mode, s, sizeof (ss.mode));
	    }
	    else
		fatal (0, "Config: StatisticalService is not set properly: No modes.");

	    s = strtok (NULL, "");
	    strip (s);

	    if (s)
		memcpy (ss.real, s, sizeof (ss.real));
	    else
		fatal (0, "Config: StatisticalService is not set properly: No realname.");

	    if (!(runflags & RUN_STARTING))
	    {
		/* Check if the client info changed. If so, reintroduce the  
		   client with the new info.
		 */
		if (ss.isonline && (strcmp (s_StatServ, nick) ||
		    strcmp (ss.user, user) || strcmp (ss.host, host) ||
		    strcmp (ss.mode, mode) || strcmp (ss.real, real)))
		{
		    send_cmd (nick, "%s :Client info changed",
			me.token ? "," : "QUIT");
		    intro_user (s_StatServ, ss.user, ss.host, ss.real, ss.mode);
		}

		/* If StatServ was previously off, and is now on, introduce
		   the pseudo client if needed.
		 */
		if (!ss.isonline && statserv_on == TRUE)
		{
		    intro_user (s_StatServ, ss.user, ss.host, ss.real, ss.mode);
		    userstat++;
		    ss.isonline = 1;
		}
	    }

	    continue;
	}

	if (!stricmp (item, "GlobalNoticer"))
	{
	    /* In case the client info changes */
	    char nick[NICKLEN], user[USERLEN], host[HOSTLEN];
	    char real[REALLEN], mode[12];

	    globalnoticer_on = TRUE;

	    strscpy (nick, s_GlobalNoticer, sizeof (nick));
	    strscpy (user, gn.user, sizeof (user));
	    strscpy (host, gn.host, sizeof (host));
	    strscpy (real, gn.real, sizeof (real));
	    strscpy (mode, gn.mode, sizeof (mode));

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (s_GlobalNoticer, s, sizeof (s_GlobalNoticer));
	    else
		fatal (0, "Config: GlobalNoticer is not set properly: No nickname.");

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (gn.user, s, sizeof (gn.user));
	    else
		fatal (0, "Config: GlobalNoticer is not set properly: No username.");

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (gn.host, s, sizeof (gn.host));
	    else
		fatal (0, "Config: GlobalNoticer is not set properly: No hostname.");

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
	    {
		if (!strchr (s, '+'))
		    fatal (0, "Config: GlobalNoticer: You need a + for modes!"); 

		memcpy (gn.mode, s, sizeof (gn.mode));
	    }
	    else
		fatal (0, "Config: GlobalNoticer is not set properly: No modes.");

	    s = strtok (NULL, "");
	    strip (s);

	    if (s)
		memcpy (gn.real, s, sizeof (gn.real));
	    else
		fatal (0, "Config: GlobalNoticer is not set properly: No realname.");

	    if (!(runflags & RUN_STARTING))
	    {
		/* Check if the client info changed. If so, reintroduce the
		   client with the new info.
		 */
		if (gn.isonline && (strcmp (s_GlobalNoticer, nick) ||
		    strcmp (gn.user, user) || strcmp (gn.host, host) ||
		    strcmp (gn.mode, mode) || strcmp (gn.real, real)))
		{
		    send_cmd (nick, "%s :Client info changed",
			me.token ? "," : "QUIT");
		    intro_user (s_GlobalNoticer, gn.user, gn.host, gn.real,
			gn.mode);
		}

		/* If the GlobalNoticer was previously off, and is now on,
		   introduce the pseudo client if needed.
		 */
		if (!gn.isonline && globalnoticer_on == TRUE)
		{
		    intro_user (s_GlobalNoticer, gn.user, gn.host, gn.real,
			gn.mode);
		    userstat++;
		    gn.isonline = 1;
		}
	    }

	    continue;
	}

	if (!stricmp (item, "SpamService"))
	{
	    /* In case the client info changes */
	    char user[USERLEN], host[HOSTLEN], real[REALLEN];
	    char guest[NICKLEN];
	    uint32 guestnick;

	    spamserv_on = TRUE;

	    strscpy (user, sp.user, sizeof (user));
	    strscpy (host, sp.host, sizeof (host));
	    strscpy (real, sp.real, sizeof (real));

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (sp.nickpre, s, sizeof (sp.nickpre));
	    else
		fatal (0, "Config: SpamService is not set properly: No nickname.");

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (sp.user, s, sizeof (sp.user));
	    else
		fatal (0, "Config: SpamService is not set properly: No username.");

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (sp.host, s, sizeof (sp.host));
	    else
		fatal (0, "Config: SpamService is not set properly: No hostname.");

	    s = strtok (NULL, "");
	    strip (s);

	    if (s)
		memcpy (sp.real, s, sizeof (sp.real));
	    else
		fatal (0, "Config: SpamService is not set properly: No realname.");

	    /* Everythings ok.. Now generate a nickname to start with. */
	    guestnick = 1+(int) (99999.0*rand()/(RAND_MAX+10000.0));

	    /* Sometimes rand() gives us a 4 digit number. If we get one,
	       we'll add 10000 to it, bringing it into the 5 digit range.
	     */
	    if (guestnick < 10000)
		guestnick = guestnick + 10000;

	    snprintf (guest, sizeof (guest), "%s%d", sp.nickpre, guestnick);
	    strscpy (sp.nick, guest, sizeof (sp.nick));
	    sp.lastnick = time (NULL);

	    if (!(runflags & RUN_STARTING))
	    {
		/* Check if the client info changed. If so, reintroduce the
		   client with the new info.
		 */
		if (sp.isonline && (strcmp (sp.user, user) ||
		    strcmp (sp.host, host) || strcmp (sp.real, real)))
		{
		    send_cmd (sp.nick, "%s :Client info changed",
			me.token ? "," : "QUIT");
		    intro_user (sp.nick, sp.user, sp.host, sp.real, "+");
		}

		/* If SpamServ was previously off, and is now on,
		   introduce the pseudo client if needed.
		 */
		if (!sp.isonline && spamserv_on == TRUE)
		{
		    intro_user (sp.nick, sp.user, sp.host, sp.real, "+");
		    userstat++;
		    sp.isonline = 1;
		}
	    }

	    continue;
	}

	if (!stricmp (item, "SRA"))
	{
	    char *nick, *pass;

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		nick = s;
	    else
		nick = "";

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		pass = s;
	    else
		pass = "";

	    if (!pass)
		fatal (0, "Config: Missing password for SRA %s", nick);
	    else
		new_sra (nick, pass);

	    continue;
	}

	if (!stricmp (item, "ULine"))
	{
	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		new_uline (s);
	    else
		fatal (0, "Config: Missing server name for U:Line");
 
	    continue;
	}

	if (!stricmp (item, "Trigger"))
	{
	    char *host;
	    uint8 limit;

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		host = s;
	    else
		host = "";

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		limit = atoi (s);
	    else
		limit = 0;

	    if (!limit)
		fatal (0, "Config: Missing limit for Trigger %s", host);
	    else
		new_trigger (host, limit);

	    continue;
	}

	if (!stricmp (item, "Exception"))
	{
	    char *host;

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		host = s;
	    else
		host = "";

	    new_exception (host);

	    continue;
	}

	if (!stricmp (item, "SyncTime"))
	{
	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		update_timeout = dotime (s);  
	    else
		fatal (0, "Config: SyncTime is not set properly: No time value.");

	    continue;
	}

	if (!stricmp (item, "CygnusServer"))
	{
	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (cygnus_server, s, sizeof (cygnus_server));
	    else
		fatal (0, "Config: OperStatsServer is not set properly: No value.");
        }

	if (!stricmp (item, "MaxConnections"))
	{
	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		maxclones = atoi (s);
	    else
		fatal (0, "Config: MaxConnections is not set properly: No value.");

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		clonekill_time = dotime (s);

	    continue;
	}

        if (!stricmp (item, "MaxCloneKills"))
        {
	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		maxclonekills = atoi (s);
	    else
		fatal (0, "Config: MaxCloneKills is not set properly: No value.");

	    continue;
	}

	if (!stricmp (item, "PingDelay"))
	{
	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		ping_delay = dotime (s);
	    else
		fatal (0, "Config: PingDelay is not set properly: No time value.");

	    continue;
	}

	if (!stricmp (item, "SnoopChan"))
	{
	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (snoopchan, s, sizeof (snoopchan));
	    else
		fatal (0, "Config: SnoopChan is not set properly: No channel.");

	    continue;
	}

	if (!stricmp (item, "SecuritySetting"))
	{
	    s = strtok (NULL, "");
	    strip (s);

	    if (s)
	    {
		if (!stricmp (s, "All"))
		    securitysetting = 1;
		if (!stricmp (s, "Passwords"))
		    securitysetting = 2;
		if (!stricmp (s, "None"))
		    securitysetting = 0;
	    }
	    else
		fatal (0, "Config: SecuritySetting is not set properly: No value.");

	    continue;
	}

	if (!stricmp (item, "WarnClients"))
	{
	    s = strtok (NULL, "");
	    strip (s);

	    if (s)
		warnclients = atoi (s);
	    else
		fatal (0, "Config: WarnClients is not set properly: No value.");

	    continue;
	}

	if (!stricmp (item, "GlobalMSG"))
	{
	    s = strtok (NULL, "");
	    strip (s);

	    if (s)
		memcpy (globalmsg, s, sizeof (globalmsg));
	    else
		fatal (0, "Config: GlobalMSG is not set properly: No message.");

	    continue;
	}

	if (!stricmp (item, "JoinChan"))
	{
	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (joinchan, s, sizeof (joinchan));
	    else
		fatal (0, "Config: JoinChan is not set properly: No channel.");

	    continue;
	}

	if (!stricmp (item, "mIRCLink"))
	{
	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (mirclink, s, sizeof (mirclink));
	    else
		fatal (0, "Config: mIRCLinks is not set properly: No address.");

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (mirclinkimg, s, sizeof (mirclinkimg));
	    else
		fatal (0, "Config: mIRCLinks is not set properly: No image.");

	    continue;
	}

	if (!stricmp (item, "JavaClient"))
	{
	    javaclient_on = TRUE;

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (javalinkimg, s, sizeof (javalinkimg));
	    else
		fatal (0, "Config: JavaClient is not set properly. No Image.");

	    continue;
	}

	if (!stricmp (item, "LogoImage"))
	{
	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (logoimg, s, sizeof (logoimg));
	    else
		fatal (0, "Config: LogoImage is not set properly. No image.");

	    continue;
	}

	if (!stricmp (item, "NetworkName"))
	{
	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		memcpy (network_name, s, sizeof (network_name));
	    else
		fatal (0, "Config: NetworkName is not set properly: No value.");

	    continue;
	}

	if (!stricmp (item, "TLD"))
	{  
	    s = strtok (NULL, "");
	    strip (s);

	    if (s)
		memcpy (tlds, s, sizeof (tlds));
	    else
		fatal (0, "Config: TLD is not set properly: No TLDs");

	    continue;
        }

	if (!stricmp (item, "AKillExpire"))
	{
	    s = strtok (NULL, "");
	    strip (s);

	    if (s)
		def_akill_time = dotime (s);
	    else
		fatal (0, "Config: AKillExpire is not set properly: No time value.");

	    continue;
	}

	if (!stricmp (item, "NonWildCards"))
	{
	    s = strtok (NULL, "");
	    strip (s);

	    if (s)
		nonwildreq = atol (s);
	    else
		fatal (0, "Config: NonWildCards is not set properly: No value.");

	    continue;
	}

	if (!stricmp (item, "UnrealNumeric"))
	{
	    s = strtok (NULL, "");
	    strip (s);

	    if (s)
		unreal_numeric = atol (s);
	    else
		fatal (0, "Config: UnrealNumeric is not set properly: No value.");

	    continue;
	}

	if (!stricmp (item, "DefaultAKillReason"))
	{
	    s = strtok (NULL, "");
	    strip (s);

	    if (s)
		memcpy (def_akill_reason, s, sizeof (def_akill_reason));
	    else
		fatal (0, "Config: DefaultAKillReason is not set properl: No reason.");

	    continue;
	}

	if (!stricmp (item, "WaitRestart"))
	{
	    s = strtok (NULL, "");
	    strip (s);

	    if (s)
		wait_restart = dotime (s);
	    else
		fatal (0, "Config: WaitRestart is not set properly: No time value.");

	    continue;
	}

	if (!stricmp (item, "LagThreshold"))
	{
	    s = strtok (NULL, "");
	    strip (s);

	    if (s)
		lagthreshold = dotime (s);
	    else
		fatal (0, "Config: LagThreshold is not set properly: No time value.");

	    continue;
	}

	if (!stricmp (item, "HelpIndex"))
	{
	    s = strtok (NULL, "");
	    strip (s);

	    if (!s)
		fatal (0, "Config: HelpIndex is not set properly: No value.");

	    if (stristr (s, "Short"))
		helpindex = 1;

	    if (stristr (s, "Medium"))
		helpindex = 2;

	    if (stristr (s, "Long"))
		helpindex = 3;

	    continue;
	}

	if (!stricmp (item, "FloodTrigger"))
	{
	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		floodmsgs = atoi (s);
	    else
		fatal (0, "Config: FloodTrigger is not set properly: No message amount.");

	    s = strtok (NULL, " ");
	    strip (s);

	    if (s)
		floodtime = dotime (s);
	    else
		fatal (0, "Config: FloodTrigger is not set properly: No message time.");

	    continue;
	}

        if (!stricmp (item, "GlobalOnAKill"))
	{
	    globalonakill_on = TRUE;
	    continue;
	}

	if (!stricmp (item, "GlobalOnLag"))
	{
	    globalonlag_on = TRUE;
	    continue;
	}

	if (!stricmp (item, "GlobalOnAuth"))
	{
	    globalonauth_on = TRUE;
	    continue;
	}

	if (!stricmp (item, "ShareAKills"))
	{
	    shareakills_on = TRUE; 
	    continue; 
	}

	if (!stricmp (item, "ShareSRAs"))
	{
	    sharesras_on = TRUE;
	    continue;
	}

        if (!stricmp (item, "StampLogons"))
	{
	    stamplogons_on = TRUE;
	    continue;
	}

	if (!stricmp (item, "HaveServ"))
	{
	    haveserv_on = TRUE;
	    continue;
	}

	if (!stricmp (item, "LogUpdates"))
	{
	    logupdates_on = TRUE;
	    continue;
	}

	if (!stricmp (item, "DumpChans"))
	{
	    dumpchans_on = TRUE;
	    continue;
	}

	if (!stricmp (item, "DumpStats"))
	{
	    dumpstats_on = TRUE;
	    continue;
	}

	if (!stricmp (item, "DumpTLDs"))
	{
	    dumptlds_on = TRUE;
	    continue;
	}

	if (!stricmp (item, "DumpServers"))
	{
	    dumpservers_on = TRUE;
	    continue;
	}

	if (!stricmp (item, "IgnoreULines"))
	{
	    ignoreulines_on = TRUE;
	    continue;
	}

	if (!stricmp (item, "NoisyFlood"))
	{
	    noisyflood_on = TRUE;
	    continue;
	}

	if (!stricmp (item, "GlobalOnSpeed"))
	{
	    globalonspeed_on = TRUE;
	    continue;
	}
    }

    fclose (f);

#ifdef HAVE_GETTIMEOFDAY
    gettimeofday (&now, NULL);
    timersub (&now, &start, &tmp);
    log_sameline (0, "finished in %d ms", tv2ms (&tmp));
#endif
}

/* Sanity checks on the config options */
uint8 check_conf ()
{
    SRA *sra;
    uint8 i = 0;

    for (sra = sralist; sra; sra = sra->next)
	i++;

    if (!i)
	fatal (0, "Config: You must have at least one SRA.");

    if (!ircdtype)
	fatal (0, "Config: IRCdType must be set.");

    if (operserv_on == FALSE && statserv_on == FALSE)
	fatal (0, "Config: OperatorService and StatisticalService cannot both be disabled.");

    if (operserv_on == FALSE)
    {
	globalnoticer_on = shareakills_on = sharesras_on = stamplogons_on = globalonakill_on = FALSE;
	maxclones = maxclonekills = 0;
    }

    if (statserv_on == FALSE)
	dumpchans_on = dumpstats_on = dumptlds_on = dumpservers_on = javaclient_on = FALSE;

    if (!update_timeout)
	update_timeout = 300;

    if (!ping_delay)
	ping_delay = 60;

    if (!lagthreshold || lagthreshold < 1)
	lagthreshold = 20;

    if (!def_akill_time)
	def_akill_time = 604800; /* One week */

    if (!clonekill_time)
	clonekill_time = def_akill_time;

    if (!helpindex)
	helpindex = 2;

    if (!strlen (cygnus_server))
    {
	shareakills_on = FALSE;
	sharesras_on = FALSE;
    }

    if (!nonwildreq)
	nonwildreq = 5;

    if (update_timeout < 60)
	log ("Warning: Setting SyncTime less than 1 minute is unwise!\n");

    if (update_timeout > 28800)
    {
	log ("Warning: SyncTime cannot exceed 8 hours. Defaulting to 5 minutes.");
	update_timeout = 300;
    }

    if (wait_restart < 5)
	fatal (0, "Config: WaitRestart cannot be less than 5s.");

    if (!strlen (tlds) && (globalnoticer_on == TRUE))
    {
        printf ("Config: TLD is not set properly. GlobalNoticer disabled.\n");
	globalnoticer_on = FALSE;
    }

    if (!strlen (network_name))
	fatal (0, "Config: NetworkName must be set.");

    if ((ircdtype == UNREAL3 || ircdtype == UNREAL3_2) && !unreal_numeric)
        fatal (0, "Config: UnrealNumeric is required for UnrealIRCd.");

    if ((ircdtype == UNREAL3 || ircdtype == UNREAL3_2) && (unreal_numeric < 1 || unreal_numeric > 255))
        fatal (0, "Config: UnrealNumeric is not set properly: Must be between 1 and 255.");

    return 1;
}
