diff --git a/src/bip.c b/src/bip.c index 12e8c4c..f668610 100644 --- a/src/bip.c +++ b/src/bip.c @@ -2150,15 +2150,7 @@ int adm_bip(bip_t *bip, struct link_client *ic, struct line *line, int privmsg) " argument"); } #if 0 - TODO - } else if (strcasecmp(line->elemv[privmsg + 2], - "network") == 0) { - if (irc_line_count(line) == privmsg + 4) { - adm_info_network(ic, line->elemv[privmsg + 3]); - } else { - bip_notify(ic, "/BIP INFO network needs one " - "argument"); - } + TODO network info #endif } else { bip_notify(ic, "-- Invalid INFO request"); @@ -2193,8 +2185,8 @@ int adm_bip(bip_t *bip, struct link_client *ic, struct line *line, int privmsg) return OK_FORGET; } adm_follow_nick(ic, irc_line_elem(line, privmsg + 2)); - } else if (strcasecmp(line->elemv[privmsg + 1], - "IGNORE_FIRST_NICK") == 0) { + } else if (irc_line_elem_case_equals(line, privmsg + 1, + "IGNORE_FIRST_NICK")) { if (irc_line_count(line) != privmsg + 3) { bip_notify(ic, "-- IGNORE_FIRST_NICK " "command needs one argument"); diff --git a/src/connection.c b/src/connection.c index 7f75814..c95c7a6 100644 --- a/src/connection.c +++ b/src/connection.c @@ -347,6 +347,11 @@ void write_line_fast(connection_t *cn, char *line) } } +void write_lines(connection_t *cn, list_t *lines) +{ + list_append(cn->outgoing, lines); +} + void write_line(connection_t *cn, char *line) { list_add_last(cn->outgoing, bip_strdup(line)); diff --git a/src/connection.h b/src/connection.h index 9c98720..62d21ee 100644 --- a/src/connection.h +++ b/src/connection.h @@ -99,6 +99,7 @@ void connection_free(connection_t *cn); void connection_close(connection_t *cn); void write_line(connection_t *cn, char *line); +void write_lines(connection_t *cn, list_t *lines); void write_line_fast(connection_t *cn, char *line); list_t *read_lines(connection_t *cn, int *error); list_t *wait_event(list_t *cn_list, int *msec, int *nc); diff --git a/src/irc.c b/src/irc.c index 8a7df16..d88c63f 100644 --- a/src/irc.c +++ b/src/irc.c @@ -47,6 +47,7 @@ static int irc_367(struct link_server *server, struct line *l); static int irc_368(struct link_server *server, struct line *l); void irc_server_shutdown(struct link_server *s); static int origin_is_me(struct line *l, struct link_server *server); +static void ls_set_nick(struct link_server *ircs, char *nick); #ifdef HAVE_OIDENTD #define OIDENTD_FILENAME ".oidentd.conf" @@ -81,9 +82,9 @@ struct channel *channel_new(const char *name) return chan; } -char *nick_from_ircmask(char *mask) +char *nick_from_ircmask(const char *mask) { - char *nick = mask; + const char *nick = mask; char *ret; size_t len; @@ -219,11 +220,12 @@ static void irc_server_join(struct link_server *s) static void irc_server_connected(struct link_server *server) { int i; + LINK(server)->s_state = IRCS_CONNECTED; LINK(server)->s_conn_attempt = 0; - mylog(LOG_INFO, "Connected user %s to %s", LINK(server)->user->name, - LINK(server)->name); + mylog(LOG_INFO, "Connected to server %s for user %s", + LINK(server)->name, LINK(server)->user->name); irc_server_join(server); log_connected(LINK(server)->log); @@ -238,15 +240,16 @@ static void irc_server_connected(struct link_server *server) free(LINK(server)->cli_nick); LINK(server)->cli_nick = NULL; } + /* basic helper for nickserv and co */ list_iterator_t itocs; for (list_it_init(&LINK(server)->on_connect_send, &itocs); list_it_item(&itocs); list_it_next(&itocs)) { - ssize_t len = strlen(list_it_item(&itocs)) + 2; - char *str = bip_malloc(len + 1); - sprintf(str, "%s\r\n", (char *)list_it_item(&itocs)); - write_line(CONN(server), str); - free(str); + ssize_t len = strlen(list_it_item(&itocs)) + 2; + char *str = bip_malloc(len + 1); + sprintf(str, "%s\r\n", (char *)list_it_item(&itocs)); + write_line(CONN(server), str); + free(str); } if (LINK(server)->l_clientc == 0) { @@ -263,13 +266,33 @@ static void irc_server_connected(struct link_server *server) * Given the way irc nets disrespect the rfc, we completely forget * about this damn ircmask... :irc.iiens.net 352 pwet * ~a je.suis.t1r.net irc.iiens.net pwet H :0 d +-> nohar!~nohar@haruka.t1r.net */ static int irc_352(struct link_server *server, struct line *line) { (void)server; - if (!irc_line_include(line, 7)) + if (!irc_line_include(line, 6)) return ERR_PROTOCOL; +#if 0 + if (irc_line_elem_case_equals(line, 6, server->nick)) { + const char *nick = server->nick; + const char *iname = irc_line_elem(line, 3); + const char *ihost = irc_line_elem(line, 4); + char *ircmask = bip_malloc(strlen(nick) + strlen(iname) + + strlen(ihost) + 3); + strcpy(ircmask, nick); + strcat(ircmask, "!"); + strcat(ircmask, iname); + strcat(ircmask, "@"); + strcat(ircmask, ihost); + if (server->ircmask) + free(server->ircmask); + server->ircmask = ircmask; + } +#endif + +#if 0 if (!origin_is_me(line, server)) { struct channel *channel; struct nick *nick; @@ -283,6 +306,7 @@ static int irc_352(struct link_server *server, struct line *line) return OK_COPY_WHO; } +#endif return OK_COPY_WHO; } @@ -365,24 +389,24 @@ int irc_dispatch_server(bip_t *bip, struct link_server *server, if (LINK(server)->s_state != IRCS_CONNECTED) { size_t nicklen = strlen(server->nick); char *newnick = bip_malloc(nicklen + 2); + strcpy(newnick, server->nick); if (strlen(server->nick) < 9) { strcat(newnick, "`"); - } else if (newnick[7] != '`') { - if (newnick[8] != '`') { - newnick[8] = '`'; - newnick[9] = 0; - } else { - newnick[7] = '`'; - newnick[9] = 0; - } } else { - newnick[8] = rand() * ('z' - 'a') / RAND_MAX + - 'a'; + if (newnick[7] != '`') { + if (newnick[8] != '`') { + newnick[8] = '`'; + } else { + newnick[7] = '`'; + } + } else { + newnick[8] = rand() * + ('z' - 'a') / RAND_MAX + 'a'; + } newnick[9] = 0; } - free(server->nick); - server->nick = newnick; + ls_set_nick(server, newnick); WRITE_LINE1(CONN(server), NULL, "NICK", server->nick); ret = OK_FORGET; @@ -482,19 +506,21 @@ int irc_dispatch_server(bip_t *bip, struct link_server *server, /* send join and related stuff to client */ static void irc_send_join(struct link_client *ic, struct channel *chan) { - char *ircmask; /* fake an irc mask for rbot */ struct user *user; + char *ircmask; user = LINK(ic)->user; if (!user) fatal("irc_send_join: No user associated"); + /* user ircmask here for rbot */ ircmask = bip_malloc(strlen(LINK(ic)->l_server->nick) + - strlen("!bip@bip.bip.bip") + 1); + strlen(BIP_FAKEMASK) + 1); strcpy(ircmask, LINK(ic)->l_server->nick); - strcat(ircmask, "!bip@bip.bip.bip"); + strcat(ircmask, BIP_FAKEMASK); WRITE_LINE1(CONN(ic), ircmask, "JOIN", chan->name); free(ircmask); + if (chan->topic) WRITE_LINE3(CONN(ic), P_SERV, "332", LINK(ic)->l_server->nick, chan->name, chan->topic); @@ -517,38 +543,15 @@ static void irc_send_join(struct link_client *ic, struct channel *chan) WRITE_LINE3(CONN(ic), P_SERV, "366", LINK(ic)->l_server->nick, chan->name, "End of /NAMES list."); - /* XXX: could be more efficient */ - if (!user->backlog) { - mylog(LOG_DEBUG, "Backlog disabled for %s, not backlogging", - user->name); - } else if (log_has_backlog(LINK(ic)->log, chan->name)) { - char *line; - int skip = 0; - while ((line = - log_backread(LINK(ic)->log, chan->name, &skip))) { - if (!skip) - write_line(CONN(ic), line); - free(line); - } - WRITE_LINE2(CONN(ic), P_IRCMASK, "PRIVMSG", chan->name, - "End of backlog."); - } else { - mylog(LOG_DEBUG, "Nothing to backlog for %s/%s", - user->name, chan->name); - } } static void write_init_string(connection_t *c, struct line *line, char *nick) { - char *tmp; char *l; - tmp = (char *)irc_line_elem(line, 1); - line->elemv[1] = nick; - l = irc_line_to_string(line); + l = irc_line_to_string_to(line, nick); write_line(c, l); free(l); - line->elemv[1] = tmp; } static void bind_to_link(struct link *l, struct link_client *ic) @@ -654,18 +657,35 @@ static void irc_cli_make_join(struct link_client *ic) if (!hash_get(&LINK(ic)->chan_infos, chan->name)) irc_send_join(ic, chan); } - - /* backlog privates */ - char *str; - int skip = 0; - while ((str = log_backread(LINK(ic)->log, S_PRIVATES, &skip))) { - if (!skip) - write_line(CONN(ic), str); - free(str); - } } } +static void irc_cli_backlog(struct link_client *ic) +{ + struct user *user; + + user = LINK(ic)->user; + if (!user) + fatal("irc_send_join: No user associated"); + if (!user->backlog) { + mylog(LOG_DEBUG, "Backlog disabled for %s, not backlogging", + user->name); + return; + } + + list_t *backlogl; + char *bl; + + backlogl = log_backlogs(LINK(ic)->log); + while ((bl = list_remove_first(backlogl))) { + mylog(LOG_INFO, "backlogging: %s", bl); + write_lines(CONN(ic), + backlog_lines_from_last_mark(LINK(ic)->log, bl)); + free(bl); + } + list_free(backlogl); +} + static int irc_cli_startup(bip_t *bip, struct link_client *ic, struct line *line) { @@ -774,6 +794,7 @@ static int irc_cli_startup(bip_t *bip, struct link_client *ic, } irc_cli_make_join(ic); + irc_cli_backlog(ic); log_client_connected(LINK(ic)->log); free(init_nick); @@ -1559,17 +1580,20 @@ static int irc_mode(struct link_server *server, struct line *line) int add = 1; unsigned cur_arg = 0; struct nick *nick; + char **elemv; + int elemc; + if (!irc_line_include(line, 2)) return ERR_PROTOCOL; /* nick mode change */ if (irc_line_elem_equals(line, 1, server->nick)) { + irc_line_extract_args(line, 3, &elemv, &elemc); log_mode(LINK(server)->log, line->origin, irc_line_elem(line, 1), - irc_line_elem(line, 2), - (const const char **)(line->elemv + 3), - irc_line_count(line) - 3); + irc_line_elem(line, 2), elemv, elemc); + irc_line_free_args(elemv, elemc); irc_user_mode(server, line); return OK_COPY; } @@ -1582,10 +1606,11 @@ static int irc_mode(struct link_server *server, struct line *line) /* we can't get mode message for chans we're not on */ if (!channel) return ERR_PROTOCOL; + + irc_line_extract_args(line, 3, &elemv, &elemc); log_mode(LINK(server)->log, line->origin, irc_line_elem(line, 1), - irc_line_elem(line, 2), - (const const char **)(line->elemv + 3), - irc_line_count(line) - 3); + irc_line_elem(line, 2), elemv, elemc); + irc_line_free_args(elemv, elemc); /* * MODE -a+b.. #channel args @@ -1779,9 +1804,12 @@ static void irc_privmsg_check_ctcp(struct link_server *server, static int irc_privmsg(struct link_server *server, struct line *line) { - if (LINK(server)->s_state == IRCS_CONNECTED) - log_privmsg(LINK(server)->log, line->origin, irc_line_elem(line, 1), - irc_line_elem(line, 2)); + if (!irc_line_include(line, 2)) + return ERR_PROTOCOL; + if (LINK(server)->s_state == IRCS_CONNECTED) { + log_privmsg(LINK(server)->log, line->origin, + irc_line_elem(line, 1), irc_line_elem(line, 2)); + } irc_privmsg_check_ctcp(server, line); return OK_COPY; } @@ -1874,6 +1902,33 @@ static int irc_generic_quit(struct link_server *server, struct line *line) return OK_COPY; } +static void ls_set_nick(struct link_server *ircs, char *nick) +{ + if (ircs->nick) + free(ircs->nick); + ircs->nick = nick; +#if 0 + if (ircs->ircmask) { + char *eom = strchr(ircs->ircmask, '!'); + if (!eom) { + free(ircs->ircmask); + goto fake; + } + eom = bip_strdup(eom); + free(ircs->ircmask); + ircs->ircmask = bip_malloc(strlen(nick) + strlen(eom) + 1); + strcpy(ircs->ircmask, nick); + strcat(ircs->ircmask, eom); + free(eom); + return; + } +fake: + ircs->ircmask = bip_malloc(strlen(nick) + strlen(BIP_FAKEMASK) + 1); + strcpy(ircs->ircmask, nick); + strcat(ircs->ircmask, BIP_FAKEMASK); +#endif +} + static void irc_server_startup(struct link_server *ircs) { char *nick; @@ -1906,7 +1961,7 @@ static void irc_server_startup(struct link_server *ircs) nick = bip_strdup(LINK(ircs)->connect_nick); } - ircs->nick = nick; + ls_set_nick(ircs, nick); WRITE_LINE1(CONN(ircs), NULL, "NICK", ircs->nick); } @@ -1952,7 +2007,7 @@ void server_cleanup(struct link_server *server) for (hash_it_init(&server->channels, &hi); hash_it_item(&hi); hash_it_next(&hi)) channel_free(hash_it_item(&hi)); - hash_init(&server->channels, HASH_NOCASE); + hash_clean(&server->channels); if (CONN(server)) { connection_free(CONN(server)); diff --git a/src/irc.h b/src/irc.h index 11a7603..7c17d78 100644 --- a/src/irc.h +++ b/src/irc.h @@ -266,5 +266,8 @@ void irc_client_free(struct link_client *); struct link *irc_link_new(); void link_kill(bip_t *bip, struct link *); void unbind_from_link(struct link_client *ic); +char *nick_from_ircmask(const char *mask); +#define BIP_FAKEMASK "!bip@bip.bip.bip" + #endif diff --git a/src/line.c b/src/line.c index 0543057..beacd88 100644 --- a/src/line.c +++ b/src/line.c @@ -19,6 +19,11 @@ void irc_line_init(struct line *l) memset(l, 0, sizeof(struct line)); } +void _irc_line_deinit(struct line *l) +{ + free(l->elemv); +} + struct line *irc_line_new() { struct line *l; @@ -103,6 +108,19 @@ char *irc_line_to_string(struct line *l) return ret; } +char *irc_line_to_string_to(struct line *line, char *nick) +{ + char *tmp; + char *l; + + tmp = (char *)irc_line_elem(line, 1); + line->elemv[1] = nick; + l = irc_line_to_string(line); + line->elemv[1] = tmp; + + return l; +} + int irc_line_count(struct line *line) { return line->elemc; @@ -205,3 +223,30 @@ void irc_line_free(struct line *l) free(l->origin); free(l); } + +void irc_line_extract_args(struct line *line, int from, + char ***elemv, int *elemc) +{ + int i; + + *elemc = irc_line_count(line) - from; + if (*elemc == 0) { + *elemv = NULL; + return; + } + *elemv = bip_malloc(*elemc * sizeof(char *)); + for (i = 0; i < *elemc; i++) + *elemv[i] = bip_strdup(irc_line_elem(line, i + from)); +} + +void irc_line_free_args(char **elemv, int elemc) +{ + int i; + + if (elemc == 0) + return; + for (i = 0; i < elemc; i++) + free(elemv[i]); + free(elemv); +} + diff --git a/src/line.h b/src/line.h index 1f5f80c..c99f2f5 100644 --- a/src/line.h +++ b/src/line.h @@ -23,7 +23,7 @@ l.origin = org; \ _irc_line_append(&l, com); \ irc_line_write(&l, con); \ - free(l.elemv); \ + _irc_line_deinit(&l); \ } while(0) #define WRITE_LINE1(con, org, com, a) \ @@ -34,7 +34,7 @@ _irc_line_append(&l, com); \ _irc_line_append(&l, a); \ irc_line_write(&l, con); \ - free(l.elemv); \ + _irc_line_deinit(&l); \ } while(0) #define WRITE_LINE2(con, org, com, a1, a2) \ @@ -46,7 +46,7 @@ _irc_line_append(&l, a1); \ _irc_line_append(&l, a2); \ irc_line_write(&l, con); \ - free(l.elemv); \ + _irc_line_deinit(&l); \ } while(0) #define WRITE_LINE3(con, org, com, a1, a2, a3) \ @@ -59,7 +59,7 @@ _irc_line_append(&l, a2); \ _irc_line_append(&l, a3); \ irc_line_write(&l, con); \ - free(l.elemv); \ + _irc_line_deinit(&l); \ } while(0) #define WRITE_LINE4(con, org, com, a1, a2, a3, a4) \ @@ -73,7 +73,7 @@ _irc_line_append(&l, a3); \ _irc_line_append(&l, a4); \ irc_line_write(&l, con); \ - free(l.elemv); \ + _irc_line_deinit(&l); \ } while(0) struct line { @@ -84,11 +84,13 @@ struct line { }; void irc_line_init(struct line *l); +void _irc_line_deinit(struct line *l); struct line *irc_line_new(); void irc_line_write(struct line *l, connection_t *c); void irc_line_append(struct line *l, const char *s); struct line *irc_line(char *str); char *irc_line_to_string(struct line *l); +char *irc_line_to_string_to(struct line *line, char *nick); void irc_line_free(struct line *l); struct line *irc_line_dup(struct line *line); void _irc_line_append(struct line *l, const char *s); @@ -98,5 +100,8 @@ int irc_line_count(struct line *line); char *irc_line_pop(struct line *l); int irc_line_elem_equals(struct line *line, int elem, const char *cmp); int irc_line_elem_case_equals(struct line *line, int elem, const char *cmp); +void irc_line_extract_args(struct line *line, int from, + char ***elemv, int *elemc); +void irc_line_free_args(char **elemv, int elemc); #endif diff --git a/src/log.c b/src/log.c index adefae7..ebe5505 100644 --- a/src/log.c +++ b/src/log.c @@ -24,7 +24,6 @@ extern int conf_log; extern FILE *conf_global_log_file; -int log_set_backlog_offset(log_t *logdata, char *dest); static int _log_write(log_t *logdata, logfilegroup_t *lf, const char *d, const char *str); void logfile_free(logfile_t *lf); @@ -34,7 +33,6 @@ static char *_log_wrap(const char *dest, const char *line); #define LAMESTRING "!bip@bip.bip.bip PRIVMSG " #define PMSG_ARROW " \002->\002 " - int check_dir(char *filename, int is_fatal) { int err; @@ -119,13 +117,13 @@ void replace_var(char *str, char *var, char *value, unsigned int max) char *pos; unsigned int lenvar = strlen(var); unsigned int lenval = strlen(value); + while((pos = strstr(str, var))) { /* Make room */ - if (strlen(str) + (lenval - lenvar) >= max) + if (strlen(str) + lenval - lenvar >= max) return; - memmove(pos + lenval, pos + lenvar, - (strlen(pos + lenvar) + 1)*sizeof(char)); - memcpy(pos, value, lenval*sizeof(char)); + memmove(pos + lenval, pos + lenvar, strlen(pos + lenvar) + 1); + memcpy(pos, value, lenval); } } @@ -282,9 +280,6 @@ logfilegroup_t *log_find_file(log_t *logdata, const char *destination) struct tm *ltime; struct link *l; - if (!ischannel(*destination)) - destination = "privates"; - lfg = hash_get(&logdata->logfgs, destination); if (lfg && !conf_log) @@ -425,13 +420,13 @@ void log_nick(log_t *logdata, const char *ircmask, const char *channel, log_write(logdata, channel, logdata->buffer); } -static void _log_privmsg(log_t *logdata, const char *ircmask, int src, - const char *destination, const char *message) +static void do_log_privmsg(log_t *logdata, const char *storage, int src, + const char *from, const char *message) { char dir = '<'; - if (!ircmask) - ircmask = "Server message"; + if (!from) + from = "Server message"; if (src) dir = '>'; @@ -450,40 +445,34 @@ static void _log_privmsg(log_t *logdata, const char *ircmask, int src, return; msg = bip_strdup(real_message); *(msg + strlen(msg) - 1) = '\0'; - if (ischannel(*destination) || strchr(destination, '@')) { - snprintf(logdata->buffer, LOGLINE_MAXLEN, + snprintf(logdata->buffer, LOGLINE_MAXLEN, "%s %c * %s %s", timestamp(), dir, - ircmask, msg + 8); - } else { - snprintf(logdata->buffer, LOGLINE_MAXLEN, - "%s (%s) %c * %s %s", timestamp(), - destination, dir, ircmask, msg + 8); - } + from, msg + 8); free(msg); } else { - if (ischannel(*destination) || strchr(destination, '@')) { - snprintf(logdata->buffer, LOGLINE_MAXLEN, + snprintf(logdata->buffer, LOGLINE_MAXLEN, "%s %c %s: %s", timestamp(), dir, - ircmask, message); - } else { - snprintf(logdata->buffer, LOGLINE_MAXLEN, - "%s %c %s (%s): %s", timestamp(), - dir, ircmask, destination, message); - } + from, message); } - log_write(logdata, destination, logdata->buffer); + log_write(logdata, storage, logdata->buffer); } void log_privmsg(log_t *logdata, const char *ircmask, const char *destination, const char *message) { - _log_privmsg(logdata, ircmask, 0, destination, message); + if (!ischannel(*destination)) { + char *nick = nick_from_ircmask(ircmask); + do_log_privmsg(logdata, nick, 0, ircmask, message); + free(nick); + } else { + do_log_privmsg(logdata, destination, 0, ircmask, message); + } } void log_cli_privmsg(log_t *logdata, const char *ircmask, const char *destination, const char *message) { - _log_privmsg(logdata, ircmask, 1, destination, message); + do_log_privmsg(logdata, destination, 1, ircmask, message); } static void _log_notice(log_t *logdata, const char *ircmask, int src, @@ -560,7 +549,7 @@ void log_init_topic_time(log_t *logdata, const char *channel, const char *who, } void log_mode(log_t *logdata, const char *ircmask, const char *channel, - const char *modes, const const char **modargv, int modargc) + const char *modes, char **modargv, int modargc) { int i; char *tmpbuf = bip_malloc(LOGLINE_MAXLEN + 1); @@ -599,9 +588,14 @@ void log_disconnected(log_t *logdata) void log_ping_timeout(log_t *logdata) { + list_t *l = log_backlogs(logdata); + char *s; + snprintf(logdata->buffer, LOGLINE_MAXLEN, "%s -!- Ping timeout with server...", timestamp()); - log_write(logdata, "privates", logdata->buffer); + while ((s = list_remove_first(l))) + log_write(logdata, s, logdata->buffer); + list_free(l); log_disconnected(logdata); } @@ -697,7 +691,7 @@ void log_advance_backlogs(log_t* ld, logfilegroup_t *lfg) } } -int log_has_backlog(log_t *logdata, char *destination) +int log_has_backlog(log_t *logdata, const char *destination) { logfilegroup_t *lfg = hash_get(&logdata->logfgs, destination); @@ -824,7 +818,7 @@ char *log_beautify(log_t *logdata, const char *buf, const char *dest) lod = strlen(dest); } - if (out && strcmp(dest, "privates") == 0) { + if (out && !ischannel(*dest)) { const char *stmp; size_t ltmp; @@ -889,7 +883,7 @@ char *log_beautify(log_t *logdata, const char *buf, const char *dest) return ret; } -char *log_backread(log_t *logdata, char *destination, int *skip) +char *log_backread(log_t *logdata, const char *destination, int *skip) { char *buf; size_t pos = 0; @@ -1206,3 +1200,68 @@ void log_free(log_t *log) free(log); } +list_t *log_backlogs(log_t *log) +{ + return hash_keys(&log->logfgs); +} + +list_t *backlog_lines_from_last_mark(log_t *log, const char *bl) +{ + char *line; + int skip; + list_t *ret; + struct line l; + + ret = list_new(NULL); + + if (log_has_backlog(log, bl)) { + skip = 0; + while ((line = log_backread(log, bl, &skip))) { + if (!skip) + list_add_last(ret, line); + } + + if (ischannel(*bl)) { + /* clean this up */ + irc_line_init(&l); + l.origin = P_IRCMASK; + _irc_line_append(&l, "PRIVMSG"); + _irc_line_append(&l, bl); + _irc_line_append(&l, "End of backlog"); + list_add_last(ret, irc_line_to_string(&l)); + _irc_line_deinit(&l); + } + } + return ret; +} + +#if 0 + for (hash_it_init(&LINK(ic)->l_server->channels, &hi); + hash_it_item(&hi); hash_it_next(&hi)) { + struct channel *chan = (struct channel *)hash_it_item(&hi); + if (log_has_backlog(LINK(ic)->log, chan->name)) { + char *line; + int skip = 0; + while ((line = + log_backread(LINK(ic)->log, chan->name, &skip))) { + if (!skip) + write_line(CONN(ic), line); + free(line); + } + WRITE_LINE2(CONN(ic), P_IRCMASK, "PRIVMSG", chan->name, + "End of backlog."); + } else { + mylog(LOG_DEBUG, "Nothing to backlog for %s/%s", + user->name, chan->name); + } + } + + /* backlog privates */ + char *str; + int skip = 0; + while ((str = log_backread(LINK(ic)->log, S_PRIVATES, &skip))) { + if (!skip) + write_line(CONN(ic), str); + free(str); + } +#endif diff --git a/src/log.h b/src/log.h index 2a16a18..104103f 100644 --- a/src/log.h +++ b/src/log.h @@ -61,10 +61,8 @@ typedef struct log { struct user *user; } log_t; -void log_close_all(log_t *logdata); log_t *log_new(struct user *user, const char *network); void logdata_free(log_t *logdata); -int log_compare_files(logfile_t *f1, char *f2); void log_join(log_t *logdata, const char *ircmask, const char *channel); void log_part(log_t *logdata, const char *ircmask, const char *channel, @@ -85,7 +83,7 @@ void log_cli_notice(log_t *logdata, const char *ircmask, const char *channel, const char *message); void log_write(log_t *logdata, const char *str, const char *destination); void log_mode(log_t *logdata, const char *ircmask, const char *channel, - const char *modes, const const char **modargv, int modargc); + const char *modes, char **modargv, int modargc); void log_topic(log_t *logdata, const char *ircmask, const char *channel, const char *message); void log_init_topic(log_t *logdata, const char *channel, const char *message); @@ -96,12 +94,15 @@ void log_disconnected(log_t *logdata); void log_ping_timeout(log_t *logdata); void log_client_disconnected(log_t *logdata); void log_client_connected(log_t *logdata); -char *log_backread(log_t *logdata, char *destination, int *skip); -int log_has_backlog(log_t *logdata, char *destination); +char *log_backread(log_t *logdata, const char *destination, int *skip); +int log_has_backlog(log_t *logdata, const char *destination); void log_flush_all(void); void log_client_none_connected(log_t *logdata); void log_reset(logfilegroup_t *); -int check_dir(char *filename, int is_fatal); void log_reinit_all(log_t *logdata); void log_free(log_t *log); +int check_dir(char *filename, int is_fatal); + +list_t *log_backlogs(log_t *log); +list_t *backlog_lines_from_last_mark(log_t *log, const char *bl); #endif diff --git a/src/util.c b/src/util.c index 74a8264..9d99218 100644 --- a/src/util.c +++ b/src/util.c @@ -444,10 +444,17 @@ void list_free(list_t *t) void list_append(list_t *src, list_t *dest) { - list_iterator_t it; - - for (list_it_init(src, &it); list_it_item(&it); list_it_next(&it)) - list_add_last(dest, list_it_item(&it)); + if (dest->last == NULL) + return; + if (src->first == NULL) { + src->first = dest->first; + src->last = dest->last; + return; + } + dest->first->prev = src->last; + src->last->next = dest->first; + src->last = dest->last; + free(dest); } /* @@ -618,7 +625,7 @@ void *hash_it_item(hash_iterator_t *h) return hi->item; } -char *hash_it_key(hash_iterator_t *h) +const char *hash_it_key(hash_iterator_t *h) { struct hash_item *hi; hi = list_it_item(&h->lit); @@ -647,6 +654,19 @@ void hash_dump(hash_t *h) printf("%s => %p\n", hash_it_key(&it), hash_it_item(&it)); } +list_t *hash_keys(hash_t *hash) +{ + hash_iterator_t hi; + list_t *ret; + + ret = list_new(NULL); + + for (hash_it_init(hash, &hi); hash_it_item(&hi); hash_it_next(&hi)) + list_add_last(ret, bip_strdup(hash_it_key(&hi))); + + return ret; +} + char *bip_strmaydup(char *s) { if (!s) diff --git a/src/util.h b/src/util.h index 39a23fb..c947333 100644 --- a/src/util.h +++ b/src/util.h @@ -94,6 +94,7 @@ void *list_it_item(list_iterator_t *ti); void *list_it_remove(list_iterator_t *li); void list_free(list_t *t); void list_copy(list_t *src, list_t *dest); +/* dest must not be refed after wards */ void list_append(list_t *src, list_t *dest); int list_is_empty(list_t *l); @@ -109,8 +110,9 @@ int hash_is_empty(hash_t *h); void hash_it_init(hash_t *hash, hash_iterator_t *i); void hash_it_next(hash_iterator_t *hi); void *hash_it_item(hash_iterator_t *h); -char *hash_it_key(hash_iterator_t *h); +const char *hash_it_key(hash_iterator_t *h); void *hash_it_remove(hash_iterator_t *li); +list_t *hash_keys(hash_t *hash); int is_valid_nick(char *str); int is_valid_username(char *str);