Logo Search packages:      
Sourcecode: iacd version File versions  Download package

conf.c

#define _GNU_SOURCE

#include "config.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

#include "conf.h"
#include "log.h"
#include "util.h"

static int p_read = 0;
static iac_confpair_t *p_config[IAC_CONF_HASHSIZE];

extern iac_server_configuration_t iac_cfg;

void
p_conf_fsck(void)
{
    int i;
    iac_confpair_t *cp, *next;

    for (i=0; i < IAC_CONF_HASHSIZE; i++) {
        for (cp = p_config[i]; cp; cp = next) {
            next = cp->next;
            RL_FREE(cp->key);
            RL_FREE(cp->data);
            RL_FREE(cp);
        }
    }
}

unsigned int
p_conf_hash(const char *id)
{
   unsigned int h = 0;
   unsigned char *p = NULL;
   
   for (p = (unsigned char *) id; *p != '\0'; p++)
      h = 37 * h + *p;
   
   return h % IAC_CONF_HASHSIZE;
}


void
p_conf_fsck_blocked(iac_block_t *bl)
{
    iac_block_t *next = NULL;

    while (bl) {
        next = bl->next;
        RL_FREE(bl->mask);
        RL_FREE(bl->reason);
        RL_FREE(bl);
        bl = next;
    }
}

void
p_conf_fsck_scripts(iac_script_t *s)
{
    iac_script_t *next = NULL;

    while ( s )
    {
        next = s->next;
        free(s->nick);
        free(s->cmd);
        free(s->char_regex);
        free(s);
        s = next;
    }
}


void
p_conf_fsck_operators(iac_operator_line_t *ol)
{
    iac_operator_line_t *next;

    while (ol) {
        next = ol->next;
        RL_FREE(ol->nick);
        RL_FREE(ol->mask);
        RL_FREE(ol->password);
        RL_FREE(ol);
        ol = next;
    }
}

void
p_conf_fsck_links(iac_link_line_t *ll)
{
    iac_link_line_t *next;

    while (ll) {
        next = ll->next;
        RL_FREE(ll->host);
        RL_FREE(ll->ip);
        RL_FREE(ll->addr);
        RL_FREE(ll->password);
        RL_FREE(ll->options);
        RL_FREE(ll->mask);
        RL_FREE(ll);
        ll = next;
    }
}

void
p_conf_fsck_channels(rl_htable_t *channels)
{
    if (channels)
      rl_hashtable_del(channels);
}

void
iac_conf_read(iac_client_conn_t *src, const char *path)
{
    static FILE *fd = NULL;
    char line[3000];

    if ( !fd )
    {
        if ( (fd = fopen(path, "r")) == NULL) {
            iac_log(IAC_WARN, "[WWW] - Unable to open config file %s: %s\n",
                path, strerror(errno));
            return;
        }
    } else {
        if ( (fd = freopen(path, "r", fd)) == NULL) {
            iac_log(IAC_WARN, "[WWW] - Unable to open config file %s: %s\n",
                path, strerror(errno));
            return;
        }
    }

    iac_log(IAC_VERBOSE, "[   ] - Reading config file %s\n", path);

    /*
     * kill old hashtable
     */
    if (p_read)
        p_conf_fsck();

    p_read = 1;

    /*
     * swooooooooooshhhh
     */
    memset(p_config, 0, sizeof(p_config));

    p_conf_fsck_links(iac_cfg.links);
    iac_cfg.links = NULL;
    p_conf_fsck_operators(iac_cfg.operators);
    iac_cfg.operators = NULL;
    p_conf_fsck_blocked(iac_cfg.blocked);
    iac_cfg.blocked = NULL;
    p_conf_fsck_channels(iac_cfg.channels);
    iac_cfg.channels = NULL;

#ifdef HAVE_SCRIPTS
    p_conf_fsck_scripts(iac_cfg.scripts);
    iac_cfg.scripts = NULL;
#endif

    memset(line, 0, sizeof(line));

    while ( fgets(line, sizeof(line), fd) ) {

        rl_remove_eol(line);
        ti_trim(line);

        if (line[0] != '\n' && line[0] != '\r' && line[0] != '#')
        {

            char *id, *value;

            id = line;
            value = strchr(line, ' ');

            if ( value )
            {
                *value = '\0';
                value++;

                if ( strlen(id) > IAC_CONFIG_IDLEN )
                    id[IAC_CONFIG_IDLEN] = '\0';

                if ( strlen(value) > IAC_CONFIG_VALUELEN )
                    value[IAC_CONFIG_VALUELEN] = '\0';

                if ( !rl_stricmp(id, "link") ) {
                    /*
                     * link line
                     * <autoconnect> <mask> <hostname> <port> <password> [<options>]
                     */

                    rl_token_list_t *tl2 = rl_token_split(value, "     ");

                    if (tl2->rtl_ntokens >= 5) {
                        iac_link_line_t *ll;
                        long l;

                        if ( !(ll = (iac_link_line_t *)
                                malloc(sizeof(iac_link_line_t))) )
                            iac_log(IAC_ERR, "Out of memory\n");
                        memset(ll, 0, sizeof(iac_link_line_t));

                        l = strtol(rl_token_get_next(tl2), NULL, 10);

                        if (l != 0)
                            ll->flags |= IAC_AUTOCONNECT;

                        ll->mask = strdup(rl_token_get_next(tl2));
                        ll->host = strdup(rl_token_get_next(tl2));
                        ll->port = strtol(rl_token_get_next(tl2), NULL, 10);
                        ll->password = strdup(rl_token_get_next(tl2));

                        if ( tl2->rtl_ntokens > 5 )
                            ll->options = strdup(rl_token_get_next(tl2));

                        ll->next = iac_cfg.links;
                        iac_cfg.links = ll;
                    }

                    rl_token_del_token_list(tl2);

                } else if ( !rl_stricmp(id, "operator") ) {
                    /*
                     * operator <nick> <mask> <password>
                     */

                    rl_token_list_t *tl2 = rl_token_split(value, "  ");

                    if ( tl2->rtl_ntokens == 3 ) {

                        iac_operator_line_t *ol;

                        if ( !(ol = (iac_operator_line_t *)
                                malloc(sizeof(iac_operator_line_t))) )
                            iac_log(IAC_ERR, "Out of memory!\n");
                        memset(ol, 0, sizeof(iac_operator_line_t));

                        ol->nick = strdup(rl_token_get_next(tl2));
                        ol->mask = strdup(rl_token_get_next(tl2));
                        ol->password = strdup(rl_token_get_next(tl2));

                        ol->next = iac_cfg.operators;
                        iac_cfg.operators = ol;
                    }

                    rl_token_del_token_list(tl2);

                } else if ( !rl_stricmp(id, "block") ) {
                    /*
                     * block <mask> <reason>
                     */

                    rl_token_list_t *tl2 = rl_token_split(value, " ");

                    if ( tl2->rtl_ntokens == 2) {

                        iac_block_t *b;

                        if ( !(b = (iac_block_t *)
                                malloc(sizeof(iac_block_t))) )
                            iac_log(IAC_ERR, "Out of memory!\n");
                        memset(b, 0, sizeof(iac_block_t));

                        b->mask = strdup(rl_token_get_next(tl2));
                        b->reason = strdup(rl_token_get_next(tl2));

                        b->next = iac_cfg.blocked;
                        iac_cfg.blocked = b;

                        iac_log(IAC_DEBUG, "[   ] - New block line: %s -> %s\n",
                            b->mask, b->reason);
                    }

                    rl_token_del_token_list(tl2);
#ifdef HAVE_SCRIPTS
                } else if ( !rl_stricmp(id, "script") ) {

                    char *    nick;
                    char *    cmd;
                    char *    char_regex;

                    nick = value;

                    if ( ( cmd = strchr ( value, ' ' ) ) )
                    {
                        *cmd = '\0';
                        cmd++;

                        if ( ( char_regex = strchr ( cmd, ' ' ) ) )
                        {
                            iac_script_t *s;

                            *char_regex = '\0';
                            char_regex++;

                            if ( !(s = (iac_script_t *)
                                    calloc( 1, sizeof(iac_script_t) ) ) )
                                iac_log(IAC_ERR, "Out of memory!\n");

                            s->nick       = strdup( nick       );
                            s->cmd        = strdup( cmd        );
                            s->char_regex = strdup( char_regex );

                            s->next = iac_cfg.scripts;
                            iac_cfg.scripts = s;

                            iac_log ( IAC_DEBUG, "[   ] - New script line: [nick %s] " \
                                "[cmd %s] [char_regex %s]\n",
                                s->nick,
                                s->cmd,
                                s->char_regex);
                        }
                    }
#endif
                } else {
                    /*
                     * normal key=value pair
                     */
                    iac_confpair_t *cp;
                    unsigned int key;

                    iac_log(IAC_DEBUG, "[   ] - New config value: %s : %s\n",
                        (id) ? id : "(null)",
                        (value) ? value : "(null)");

                    if ( !(cp = (iac_confpair_t *)
                                malloc(sizeof(iac_confpair_t))))
                        iac_log(IAC_ERR, "Out of memory!\n");
                    memset(cp, 0, sizeof(iac_confpair_t));

                    cp->key = strdup(id);
                    cp->data = strdup(value);
                    
                    key = p_conf_hash(cp->key);

                    cp->next = p_config[key];
                    p_config[key] = cp;
                }
            }

        }

        memset(line, 0, sizeof(line));
    }
}

char *
iac_conf_get(const char *id)
{
    if (p_read && id) {
        unsigned int key = p_conf_hash(id);
        iac_confpair_t *cp;

        for (cp = p_config[key]; cp; cp = cp->next)
            if ( !strcmp(cp->key, id) )
                return cp->data;
    }

    return NULL;
}

iac_operator_line_t *
iac_conf_get_operline(const char *nick)
{
    iac_operator_line_t *ol;

    if (!iac_cfg.operators)
        return NULL;

    for (ol = iac_cfg.operators; ol; ol = ol->next)
        if ( !rl_stricmp(ol->nick, nick) )
            return ol;

    return NULL;
}

void
iac_conf_interpret_channel_list(char *path)
{
    FILE *fd = NULL;
    char *line = NULL;
    int len;
    static char *valid = "valid";

    fd = fopen(path, "r");
    if ( (fd = fopen(path, "r")) == NULL) {
      iac_log(IAC_WARN, "[WWW] - Unable to open channel_list file %s: %s\n",
          path, strerror(errno));
      return;
    }

    iac_cfg.channels = rl_hashtable_new(100, 37, RL_HTABLE_DONT_FREE_DATA);

    RL_MALLOC(line, char, IAC_CHANNAMELEN+2);

    while ( fgets(line, IAC_CHANNAMELEN+1, fd) ) {
      len = strlen(line);
      if ( line[len-1] != '\n' ) {
          iac_log(IAC_WARN, "[WWW] - Too long line in channel_list file "
            "ignored: %s\n", line);
          continue;
      }
      line[len-1] = '\0'; /* kill the newline */
      
      if ( line[0] == '&' || line[0] == '#' ||
           line[0] == '+' || line[0] == '!' ) {
          rl_hashtable_add(iac_cfg.channels, line, valid);
          iac_log(IAC_VERBOSE, "[   ] - added %s to the list of "
            "authorized channels\n", line);
      }
    }
    fclose(fd);
    RL_FREE(line);
}

void
iac_conf_interpret(void)
{
    char *s;
    long l;

    if (!p_config)
        return;

#define IAC_CFG_STR(dst, id) { \
    if ( (s = (char *) iac_conf_get(id)) ) \
        iac_safe_strncpy(dst, s, sizeof(dst)); }

#define IAC_CFG_INT(dst, id) { \
    if ( (s = (char *) iac_conf_get(id)) ) { \
        l = strtol(s, NULL, 10); \
        if (l != LONG_MIN && l < INT_MAX && l >= 0) \
            dst = (int) l; \
    } }

#define IAC_CFG_FLAG(id, mask) { \
    if ( (s = (char *) iac_conf_get(id)) ) { \
        l = strtol(s, NULL, 10); \
        if (l != 0) \
            iac_cfg.flags |= mask; \
    } }

    IAC_CFG_INT(iac_cfg.client_port, IAC_CONF_CLIENT_PORT);
    IAC_CFG_INT(iac_cfg.server_port, IAC_CONF_SERVER_PORT);
    IAC_CFG_INT(iac_cfg.numeric, IAC_CONF_SERVER_NUMERIC);

    IAC_CFG_FLAG(IAC_CONF_PARANOIA, IAC_PARANOIA);
    IAC_CFG_FLAG(IAC_CONF_LASTLOG, IAC_LASTLOG);
    IAC_CFG_FLAG(IAC_CONF_TIMESTAMPS, IAC_TIMESTAMPS);

    IAC_CFG_STR(iac_cfg.motdfile, IAC_CONF_MOTD);
    IAC_CFG_STR(iac_cfg.logprefix, IAC_CONF_LOG_PREFIX);
    IAC_CFG_STR(iac_cfg.info, IAC_CONF_SERVER_INFO);
    IAC_CFG_STR(iac_cfg.interface, IAC_CONF_INTERFACE);
    IAC_CFG_STR(iac_cfg.servername, IAC_CONF_SERVER_NAME);

    if ( ( s = (char *) iac_conf_get(IAC_CONF_CHANNEL_LIST)) ) {
      iac_conf_interpret_channel_list(s);
    }

#undef IAC_CFG_STR
#undef IAC_CFG_INT
#undef IAC_CFG_FLAG

}

Generated by  Doxygen 1.6.0   Back to index