Config load fixes.

- Leaks
- Better logging
- Handle historical configs
This commit is contained in:
Arnaud Cornet 2007-10-21 12:31:07 +02:00
parent 32e47b900c
commit 0abd8a386d
6 changed files with 125 additions and 103 deletions

195
src/bip.c
View File

@ -48,14 +48,15 @@ int conf_log = DEFAULT_LOG;
int conf_log_system = DEFAULT_LOG_SYSTEM; int conf_log_system = DEFAULT_LOG_SYSTEM;
int conf_log_sync_interval = DEFAULT_LOG_SYNC_INTERVAL; int conf_log_sync_interval = DEFAULT_LOG_SYNC_INTERVAL;
list_t *parse_conf(FILE *file); list_t *parse_conf(FILE *file, int *err);
static void conf_die(char *fmt, ...); static void conf_die(char *fmt, ...);
#ifdef HAVE_LIBSSL #ifdef HAVE_LIBSSL
int adm_trust(struct link_client *ic, struct line *line); int adm_trust(struct link_client *ic, struct line *line);
#endif #endif
static char *get_tuple_value(list_t *tuple_l, int lex); static char *get_tuple_pvalue(list_t *tuple_l, int lex);
void adm_reply(struct link_client *ic, char *str); void adm_reply(struct link_client *ic, char *str);
void adm_list_connections(struct link_client *ic, struct user *bu); void adm_list_connections(struct link_client *ic, struct user *bu);
void free_conf(list_t *l);
static void hash_binary(char *hex, unsigned char **password, unsigned int *seed) static void hash_binary(char *hex, unsigned char **password, unsigned int *seed)
{ {
@ -94,7 +95,7 @@ static int add_server(struct server *s, list_t *data)
while ((t = list_remove_first(data))) { while ((t = list_remove_first(data))) {
switch (t->type) { switch (t->type) {
case LEX_HOST: case LEX_HOST:
s->host = t->pdata; MOVE_STRING(s->host, t->pdata);
break; break;
case LEX_PORT: case LEX_PORT:
s->port = t->ndata; s->port = t->ndata;
@ -102,6 +103,9 @@ static int add_server(struct server *s, list_t *data)
default: default:
fatal("Config error in server block (%d)", t->type); fatal("Config error in server block (%d)", t->type);
} }
if (t->tuple_type == TUPLE_STR && t->pdata)
free(t->pdata);
free(t);
} }
if (!s->host) { if (!s->host) {
free(s); free(s);
@ -115,23 +119,12 @@ static int add_server(struct server *s, list_t *data)
extern list_t *root_list; extern list_t *root_list;
int yyparse(); int yyparse();
int conf_error;
char conf_errstr[ERRBUFSZ];
static void conf_start(void)
{
conf_error = 0;
}
static void conf_die(char *fmt, ...) static void conf_die(char *fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
_mylog(LOG_ERROR, fmt, ap);
vsnprintf(conf_errstr, ERRBUFSZ, fmt, ap);
conf_errstr[ERRBUFSZ - 1] = 0;
conf_error = 1;
va_end(ap); va_end(ap);
} }
@ -305,8 +298,9 @@ static int add_network(bip_t *bip, list_t *data)
struct tuple *t; struct tuple *t;
struct network *n; struct network *n;
int i; int i;
int r;
char *name = get_tuple_value(data, LEX_NAME); char *name = get_tuple_pvalue(data, LEX_NAME);
if (name == NULL) { if (name == NULL) {
conf_die("Network with no name"); conf_die("Network with no name");
@ -338,17 +332,22 @@ static int add_network(bip_t *bip, list_t *data)
n->serverv = realloc(n->serverv, (n->serverc + 1) n->serverv = realloc(n->serverv, (n->serverc + 1)
* sizeof(struct server)); * sizeof(struct server));
n->serverc++; n->serverc++;
add_server(&n->serverv[n->serverc - 1], t->pdata); memset(&n->serverv[n->serverc - 1], 0,
sizeof(struct server));
r = add_server(&n->serverv[n->serverc - 1], t->pdata);
if (!r) {
n->serverc--;
return 0;
}
free(t->pdata); free(t->pdata);
t->pdata = NULL; t->pdata = NULL;
break; break;
default: default:
conf_die("unknown keyword in network statement"); conf_die("unknown keyword in network statement");
if (t->type == TUPLE_STR) return 0;
free(t->pdata);
break; break;
} }
if (t->type == TUPLE_STR && t->pdata) if (t->tuple_type == TUPLE_STR && t->pdata)
free(t->pdata); free(t->pdata);
free(t); free(t);
} }
@ -360,7 +359,7 @@ static int add_connection(bip_t *bip, struct user *user, list_t *data)
struct tuple *t, *t2; struct tuple *t, *t2;
struct link *l; struct link *l;
struct chan_info *ci; struct chan_info *ci;
char *name = get_tuple_value(data, LEX_NAME); char *name = get_tuple_pvalue(data, LEX_NAME);
if (name == NULL) { if (name == NULL) {
conf_die("Connection with no name"); conf_die("Connection with no name");
@ -414,7 +413,7 @@ static int add_connection(bip_t *bip, struct user *user, list_t *data)
MOVE_STRING(l->vhost, t->pdata); MOVE_STRING(l->vhost, t->pdata);
break; break;
case LEX_CHANNEL: case LEX_CHANNEL:
name = get_tuple_value(t->pdata, LEX_NAME); name = get_tuple_pvalue(t->pdata, LEX_NAME);
if (name == NULL) { if (name == NULL) {
conf_die("Channel with no name"); conf_die("Channel with no name");
return 0; return 0;
@ -441,6 +440,9 @@ static int add_connection(bip_t *bip, struct user *user, list_t *data)
ci->backlog = t2->ndata; ci->backlog = t2->ndata;
break; break;
} }
if (t2->tuple_type == TUPLE_STR && t2->pdata)
free(t2->pdata);
free(t2);
} }
list_free(t->pdata); list_free(t->pdata);
break; break;
@ -458,6 +460,7 @@ static int add_connection(bip_t *bip, struct user *user, list_t *data)
break; break;
case LEX_ON_CONNECT_SEND: case LEX_ON_CONNECT_SEND:
list_add_last(&l->on_connect_send, t->pdata); list_add_last(&l->on_connect_send, t->pdata);
t->pdata = NULL;
break; break;
#ifdef HAVE_LIBSSL #ifdef HAVE_LIBSSL
case LEX_SSL_CHECK_MODE: case LEX_SSL_CHECK_MODE:
@ -470,10 +473,9 @@ static int add_connection(bip_t *bip, struct user *user, list_t *data)
#endif #endif
default: default:
conf_die("unknown keyword in connection statement"); conf_die("unknown keyword in connection statement");
if (t->type == TUPLE_STR) return 0;
free(t->pdata);
} }
if (t->type == TUPLE_STR && t->pdata) if (t->tuple_type == TUPLE_STR && t->pdata)
free(t->pdata); free(t->pdata);
free(t); free(t);
} }
@ -498,7 +500,7 @@ static int add_connection(bip_t *bip, struct user *user, list_t *data)
return 1; return 1;
} }
static char *get_tuple_value(list_t *tuple_l, int lex) static char *get_tuple_pvalue(list_t *tuple_l, int lex)
{ {
struct tuple *t; struct tuple *t;
list_iterator_t it; list_iterator_t it;
@ -511,13 +513,35 @@ static char *get_tuple_value(list_t *tuple_l, int lex)
return NULL; return NULL;
} }
static int add_user(bip_t *bip, list_t *data) static int get_tuple_nvalue(list_t *tuple_l, int lex)
{
struct tuple *t;
list_iterator_t it;
for (list_it_init(tuple_l, &it); (t = list_it_item(&it));
list_it_next(&it)) {
if (t->type == lex)
return t->ndata;
}
return -1;
}
struct historical_directives {
int always_backlog;
int backlog;
int bl_msg_only;
int backlog_lines;
int backlog_no_timestamp;
int blreset_on_talk;
};
static int add_user(bip_t *bip, list_t *data, struct historical_directives *hds)
{ {
int r; int r;
struct tuple *t; struct tuple *t;
struct user *u; struct user *u;
char *name = get_tuple_value(data, LEX_NAME); char *name = get_tuple_pvalue(data, LEX_NAME);
if (name == NULL) { if (name == NULL) {
conf_die("User with no name"); conf_die("User with no name");
@ -529,12 +553,6 @@ static int add_user(bip_t *bip, list_t *data)
hash_insert(&bip->users, name, u); hash_insert(&bip->users, name, u);
hash_init(&u->connections, HASH_NOCASE); hash_init(&u->connections, HASH_NOCASE);
u->admin = 0; u->admin = 0;
u->backlog = DEFAULT_BACKLOG;
u->always_backlog = DEFAULT_ALWAYS_BACKLOG;
u->bl_msg_only = DEFAULT_BL_MSG_ONLY;
u->backlog_lines = DEFAULT_BACKLOG_LINES;
u->backlog_no_timestamp = DEFAULT_BACKLOG_NO_TIMESTAMP;
u->blreset_on_talk = DEFAULT_BLRESET_ON_TALK;
} else { } else {
FREE(u->name); FREE(u->name);
FREE(u->password); FREE(u->password);
@ -546,6 +564,13 @@ static int add_user(bip_t *bip, list_t *data)
#endif #endif
} }
u->backlog = hds->backlog;
u->always_backlog = hds->always_backlog;
u->bl_msg_only = hds->bl_msg_only;
u->backlog_lines = hds->backlog_lines;
u->backlog_no_timestamp = hds->backlog_no_timestamp;
u->blreset_on_talk = hds->blreset_on_talk;
while ((t = list_remove_first(data))) { while ((t = list_remove_first(data))) {
switch (t->type) { switch (t->type) {
case LEX_NAME: case LEX_NAME:
@ -557,6 +582,7 @@ static int add_user(bip_t *bip, list_t *data)
case LEX_PASSWORD: case LEX_PASSWORD:
hash_binary(t->pdata, &u->password, &u->seed); hash_binary(t->pdata, &u->password, &u->seed);
free(t->pdata); free(t->pdata);
t->pdata = NULL;
break; break;
case LEX_DEFAULT_NICK: case LEX_DEFAULT_NICK:
MOVE_STRING(u->default_nick, t->pdata); MOVE_STRING(u->default_nick, t->pdata);
@ -585,10 +611,10 @@ static int add_user(bip_t *bip, list_t *data)
case LEX_BLRESET_ON_TALK: case LEX_BLRESET_ON_TALK:
u->blreset_on_talk = t->ndata; u->blreset_on_talk = t->ndata;
break; break;
case LEX_CONNECTION: case LEX_CONNECTION:
r = add_connection(bip, u, t->pdata); r = add_connection(bip, u, t->pdata);
free(t->pdata); free(t->pdata);
t->pdata = NULL;
if (!r) if (!r)
return 0; return 0;
break; break;
@ -599,16 +625,17 @@ static int add_user(bip_t *bip, list_t *data)
if (!strncmp(t->pdata, "ca", 2)) if (!strncmp(t->pdata, "ca", 2))
u->ssl_check_mode = SSL_CHECK_CA; u->ssl_check_mode = SSL_CHECK_CA;
free(t->pdata); free(t->pdata);
t->pdata = NULL;
break; break;
case LEX_SSL_CHECK_STORE: case LEX_SSL_CHECK_STORE:
u->ssl_check_store = t->pdata; MOVE_STRING(u->ssl_check_store, t->pdata);
break; break;
#endif #endif
default: default:
conf_die("Uknown keyword in user statement"); conf_die("Uknown keyword in user statement");
break; return 0;
} }
if (t->type == TUPLE_STR && t->pdata) if (t->tuple_type == TUPLE_STR && t->pdata)
free(t->pdata); free(t->pdata);
free(t); free(t);
} }
@ -653,7 +680,6 @@ static int validate_config(bip_t *bip)
link->name); link->name);
#endif #endif
//conf_die("user: ... net: ... can i has nick/user/rael");
r = 0; r = 0;
for (hash_it_init(&link->chan_infos, &cit); for (hash_it_init(&link->chan_infos, &cit);
@ -681,16 +707,34 @@ static int validate_config(bip_t *bip)
int fireup(bip_t *bip, FILE *conf) int fireup(bip_t *bip, FILE *conf)
{ {
int r;
struct tuple *t; struct tuple *t;
list_t *l; int err = 0;
struct historical_directives hds;
conf_start(); parse_conf(conf, &err);
if (err) {
l = parse_conf(conf); free_conf(root_list);
if (conf_error) root_list = NULL;
return 0; return 0;
}
while ((t = list_remove_first(l))) { #define SET_HV(d, n) do {\
int __gtv = get_tuple_nvalue(root_list, LEX_##n);\
if (__gtv != -1) \
d = __gtv;\
else\
d = DEFAULT_##n;\
} while(0);
SET_HV(hds.always_backlog, ALWAYS_BACKLOG);
SET_HV(hds.backlog, BACKLOG);
SET_HV(hds.bl_msg_only, BL_MSG_ONLY);
SET_HV(hds.backlog_lines, BACKLOG_LINES);
SET_HV(hds.backlog_no_timestamp, BACKLOG_NO_TIMESTAMP);
SET_HV(hds.blreset_on_talk, BLRESET_ON_TALK);
#undef SET_HV
while ((t = list_remove_first(root_list))) {
switch (t->type) { switch (t->type) {
case LEX_LOG_SYNC_INTERVAL: case LEX_LOG_SYNC_INTERVAL:
conf_log_sync_interval = t->ndata; conf_log_sync_interval = t->ndata;
@ -723,43 +767,22 @@ int fireup(bip_t *bip, FILE *conf)
MOVE_STRING(conf_pid_file, t->pdata); MOVE_STRING(conf_pid_file, t->pdata);
break; break;
case LEX_NETWORK: case LEX_NETWORK:
add_network(bip, t->pdata); r = add_network(bip, t->pdata);
list_free(t->pdata); list_free(t->pdata);
if (!r)
goto out_conf_error;
break; break;
case LEX_USER: case LEX_USER:
add_user(bip, t->pdata); r = add_user(bip, t->pdata, &hds);
list_free(t->pdata); list_free(t->pdata);
if (!r)
goto out_conf_error;
break; break;
#warning deprecated but we still need to support these
#if 0
case LEX_ALWAYS_BACKLOG:
conf_always_backlog = t->ndata;
break;
case LEX_BACKLOG:
conf_backlog = t->ndata;
break;
case LEX_BL_MSG_ONLY:
conf_bl_msg_only = t->ndata;
break;
case LEX_BACKLOG_LINES:
conf_backlog_lines = t->ndata;
break;
case LEX_BACKLOG_NO_TIMESTAMP:
conf_backlog_no_timestamp = t->ndata;
break;
case LEX_BLRESET_ON_TALK:
conf_blreset_on_talk = t->ndata;
break;
/* end of deprectated */
#endif
default: default:
conf_die("Config error in base config (%d)", t->type); conf_die("Config error in base config (%d)", t->type);
goto out_conf_error;
} }
if (t->type == TUPLE_STR && t->pdata) if (t->tuple_type == TUPLE_STR && t->pdata)
free(t->pdata); free(t->pdata);
free(t); free(t);
} }
@ -768,6 +791,11 @@ int fireup(bip_t *bip, FILE *conf)
validate_config(bip); validate_config(bip);
return 1; return 1;
out_conf_error:
free_conf(root_list);
root_list = NULL;
return 0;
} }
static void log_file_setup(void) static void log_file_setup(void)
@ -937,13 +965,10 @@ int main(int argc, char **argv)
fatal("%s config file not found", confpath); fatal("%s config file not found", confpath);
} }
r = fireup(&bip, conf); r = fireup(&bip, conf);
fclose(conf); fclose(conf);
if (!r) { if (!r)
fatal("%s", conf_errstr); fatal("Not starting: error in config file.");
exit(28);
}
if (!conf_biphome) { if (!conf_biphome) {
char *home = getenv("HOME"); char *home = getenv("HOME");
@ -1005,9 +1030,6 @@ int main(int argc, char **argv)
fatal("Could not create listening socket"); fatal("Could not create listening socket");
for (;;) { for (;;) {
if (conf_error)
mylog(LOG_ERROR, "conf error: %s", conf_errstr);
irc_main(&bip); irc_main(&bip);
sighup = 0; sighup = 0;
@ -1773,12 +1795,14 @@ void free_conf(list_t *l)
{ {
struct tuple *t; struct tuple *t;
list_iterator_t li; list_iterator_t li;
for (list_it_init(l, &li); (t = list_it_item(&li)); list_it_next(&li)) { for (list_it_init(l, &li); (t = list_it_item(&li)); list_it_next(&li)) {
switch (t->tuple_type) { switch (t->tuple_type) {
case TUPLE_STR: case TUPLE_STR:
free(t->pdata); /* no break, for the style */ printf("freeconf: %s\n", (char *)t->pdata);
free(t->pdata);
break;
case TUPLE_INT: case TUPLE_INT:
free(t);
break; break;
case TUPLE_LIST: case TUPLE_LIST:
free_conf(t->pdata); free_conf(t->pdata);
@ -1787,5 +1811,8 @@ void free_conf(list_t *l)
fatal("internal error free_conf"); fatal("internal error free_conf");
break; break;
} }
free(t);
} }
free(l);
} }

View File

@ -19,9 +19,7 @@
extern int yylex (void); extern int yylex (void);
extern char *yytext; extern char *yytext;
extern int linec; extern int linec;
extern int conf_error; int conf_error;
#define ERRBUFSZ 80
extern char conf_errstr[ERRBUFSZ];
int yywrap() int yywrap()
{ {
@ -30,9 +28,7 @@ int yywrap()
int yyerror() int yyerror()
{ {
snprintf(conf_errstr, ERRBUFSZ, "Parse error near %s, line %d\n", mylog(LOG_ERROR, "Parse error near %s, line %d\n", yytext, linec + 1);
yytext, linec + 1);
conf_errstr[ERRBUFSZ - 1] = 0;
conf_error = 1; conf_error = 1;
return 1; return 1;
} }

View File

@ -49,8 +49,6 @@ void oidentd_dump(list_t *connl);
void irc_client_free(struct link_client *cli); void irc_client_free(struct link_client *cli);
extern int conf_log_sync_interval; extern int conf_log_sync_interval;
extern int conf_error;
extern char conf_errstr[];
void write_user_list(connection_t *c, char *dest); void write_user_list(connection_t *c, char *dest);
@ -1556,7 +1554,7 @@ static int irc_mode(struct link_server *server, struct line *line)
log_mode(LINK(server)->log, line->origin, line->elemv[1], log_mode(LINK(server)->log, line->origin, line->elemv[1],
line->elemv[2], line->elemv + 3, line->elemc - 3); line->elemv[2], line->elemv + 3, line->elemc - 3);
/* /*
* MODE -a+b.. #channel args * MODE -a+b.. #channel args
* ^ ^ * ^ ^
* mode cur_arg * mode cur_arg

View File

@ -16,10 +16,10 @@
int linec = 0; int linec = 0;
#define YY_NO_UNPUT #define YY_NO_UNPUT
#include "util.h" #include "util.h"
extern int conf_error;
extern list_t *root_list; extern list_t *root_list;
void yyparse(void); void yyparse(void);
void free_conf(list_t*); void free_conf(list_t*);
extern int conf_error;
#if 0 #if 0
/* SPANK ME WITH A SHOVEL */ /* SPANK ME WITH A SHOVEL */
@ -30,15 +30,14 @@ void dummy_lex_FFS(void)
} }
#endif #endif
list_t *parse_conf(FILE *file) list_t *parse_conf(FILE *file, int *err)
{ {
YY_BUFFER_STATE in = yy_create_buffer(file, YY_BUF_SIZE); YY_BUFFER_STATE in = yy_create_buffer(file, YY_BUF_SIZE);
yy_switch_to_buffer(in); yy_switch_to_buffer(in);
conf_error = 0;
yyparse(); yyparse();
if (conf_error) { yy_delete_buffer(in);
free_conf(root_list); *err = conf_error;
return NULL;
}
return root_list; return root_list;
} }
%} %}
@ -112,6 +111,6 @@ list_t *parse_conf(FILE *file)
"{" { return LEX_LBRA; } "{" { return LEX_LBRA; }
"}" { return LEX_RBRA; } "}" { return LEX_RBRA; }
";" { return LEX_SEMICOLON; } ";" { return LEX_SEMICOLON; }
. { printf("Parse error line %d, unknown character '%s'\n", linec + 1, yytext); . { mylog(LOG_ERROR, "Parse error in config file line %d, unknown character '%s'\n", linec + 1, yytext);
return LEX_BUNCH; } return LEX_BUNCH; }
%% %%

View File

@ -118,6 +118,9 @@ void _mylog(int level, char *fmt, va_list ap)
{ {
char *prefix; char *prefix;
if (!conf_log_system)
return;
if (level > conf_log_level) if (level > conf_log_level)
return; return;
@ -157,9 +160,6 @@ void mylog(int level, char *fmt, ...)
{ {
va_list ap; va_list ap;
if (!conf_log_system)
return;
va_start(ap, fmt); va_start(ap, fmt);
_mylog(level, fmt, ap); _mylog(level, fmt, ap);
va_end(ap); va_end(ap);

View File

@ -15,6 +15,7 @@
#include <time.h> #include <time.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <stdarg.h>
/* Warning: must be in order, 0 = less output */ /* Warning: must be in order, 0 = less output */
#define LOG_STD -1 #define LOG_STD -1
@ -30,6 +31,7 @@
#define HASH_DEFAULT 0 #define HASH_DEFAULT 0
void mylog(int level, char *fmt, ...); void mylog(int level, char *fmt, ...);
void _mylog(int level, char *fmt, va_list ap);
void fatal(char *fmt, ...); void fatal(char *fmt, ...);
char *timestamp(void); char *timestamp(void);
struct list_item; struct list_item;