Mercurial > irccd
changeset 958:533639ec5e9c
misc: use sys/queue.h
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 21 Jan 2021 23:15:20 +0100 |
parents | 3167c51f0c84 |
children | 0d6e2a89fee5 |
files | irccd/main.c irccdctl/main.c lib/CMakeLists.txt lib/irccd/channel.c lib/irccd/channel.h lib/irccd/irccd.c lib/irccd/irccd.h lib/irccd/jsapi-plugin.c lib/irccd/jsapi-server.c lib/irccd/limits.h lib/irccd/list.h lib/irccd/peer.c lib/irccd/peer.h lib/irccd/plugin.c lib/irccd/plugin.h lib/irccd/rule.c lib/irccd/rule.h lib/irccd/server.c lib/irccd/server.h lib/irccd/set.h lib/irccd/transport.c lib/irccd/transport.h tests/CMakeLists.txt tests/test-bot.c tests/test-channel.c tests/test-rule.c |
diffstat | 26 files changed, 676 insertions(+), 673 deletions(-) [+] |
line wrap: on
line diff
--- a/irccd/main.c Thu Jan 21 15:34:25 2021 +0100 +++ b/irccd/main.c Thu Jan 21 23:15:20 2021 +0100 @@ -34,31 +34,4 @@ (void)argc; (void)argv; - struct irc_server s = { - .name = "malikania", - .username = "circ", - .nickname = "circ", - .hostname = "malikania.fr", - .commandchar = "!", - .port = 6697, - .flags = IRC_SERVER_FLAGS_SSL | IRC_SERVER_FLAGS_JOIN_INVITE - }; - struct irc_plugin p = { - .name = "test" - }; - struct irc_rule r = { - .action = IRC_RULE_DROP - }; - - irc_rule_add(r.events, "onMe"); - - irc_log_set_verbose(true); - irc_bot_init(); - irc_bot_insert_rule(&r, 0); - irc_transport_bind("/tmp/irccd.sock"); - irc_server_join(&s, "#test", NULL); - irc_bot_add_server(irc_util_memdup(&s, sizeof (s))); - irc_js_plugin_open(&p, "/Users/markand/test.js"); - irc_bot_add_plugin(&p); - irc_bot_run(); }
--- a/irccdctl/main.c Thu Jan 21 15:34:25 2021 +0100 +++ b/irccdctl/main.c Thu Jan 21 23:15:20 2021 +0100 @@ -40,17 +40,17 @@ .sun_family = PF_LOCAL, .sun_path = "/tmp/irccd.sock" }; -static char in[IRC_BUF_MAX]; -static char out[IRC_BUF_MAX]; +static char in[IRC_BUF_LEN]; +static char out[IRC_BUF_LEN]; static char * poll(void) { - static char ret[IRC_BUF_MAX]; + static char ret[IRC_BUF_LEN]; char *nl; while (!(nl = strstr(in, "\n"))) { - char buf[IRC_BUF_MAX] = {0}; + char buf[IRC_BUF_LEN] = {0}; ssize_t nr; if ((nr = recv(sock, buf, sizeof (buf) - 1, 0)) <= 0) @@ -97,7 +97,7 @@ static void req(const char *fmt, ...) { - char buf[IRC_BUF_MAX]; + char buf[IRC_BUF_LEN]; va_list ap; va_start(ap, fmt); @@ -404,7 +404,7 @@ show_whois(char *line) { const char *args[6] = {0}; - char *p, *token; + //char *p, *token; if (irc_util_split(line, args, 6) >= 4) { printf("event: onWhois\n"); @@ -413,9 +413,7 @@ printf("username: %s\n", args[3]); printf("hostname: %s\n", args[4]); printf("username: %s\n", args[5]); - printf("channels: "); - - + //printf("channels: %s\n", args[6]); } }
--- a/lib/CMakeLists.txt Thu Jan 21 15:34:25 2021 +0100 +++ b/lib/CMakeLists.txt Thu Jan 21 23:15:20 2021 +0100 @@ -41,8 +41,6 @@ irccd/rule.h irccd/server.c irccd/server.h - irccd/set.h - irccd/list.h irccd/subst.c irccd/subst.h irccd/transport.c
--- a/lib/irccd/channel.c Thu Jan 21 15:34:25 2021 +0100 +++ b/lib/irccd/channel.c Thu Jan 21 23:15:20 2021 +0100 @@ -22,64 +22,76 @@ #include "channel.h" #include "util.h" -#include "set.h" + +static inline struct irc_channel_user * +find(const struct irc_channel *ch, const char *nickname) +{ + struct irc_channel_user *u; -static inline int -cmp(const struct irc_channel_user *u1, const struct irc_channel_user *u2) -{ - return strcmp(u1->nickname, u2->nickname); + LIST_FOREACH(u, &ch->users, link) + if (strcmp(u->nickname, nickname) == 0) + return u; + + return NULL; } -static inline struct irc_channel_user * -find(const struct irc_channel *ch, const char *nick) +struct irc_channel * +irc_channel_new(const char *name, const char *password, bool joined) { - struct irc_channel_user key = {0}; + assert(name); + + struct irc_channel *ch; + + ch = irc_util_calloc(1, sizeof (*ch)); + ch->joined = joined; - strlcpy(key.nickname, nick, sizeof (key.nickname)); + strlcpy(ch->name, name, sizeof (ch->name)); + strlcpy(ch->password, password ? password : "", sizeof (ch->password)); - return IRC_SET_FIND(ch->users, ch->usersz, &key, cmp); + LIST_INIT(&ch->users); + + return ch; } void -irc_channel_add(struct irc_channel *ch, const char *nick, char mode) +irc_channel_add(struct irc_channel *ch, const char *nickname, char mode, char symbol) { assert(ch); - assert(nick); + assert(nickname); - if (find(ch, nick)) + struct irc_channel_user *user; + + if (find(ch, nickname)) return; - struct irc_channel_user u = {0}; + user = irc_util_malloc(sizeof (*user)); + user->mode = mode; + user->symbol = symbol; + strlcpy(user->nickname, nickname, sizeof (user->nickname)); - strlcpy(u.nickname, nick, sizeof (u.nickname)); - u.mode = mode; - - IRC_SET_ALLOC_PUSH(&ch->users, &ch->usersz, &u, cmp); + LIST_INSERT_HEAD(&ch->users, user, link); } void -irc_channel_set_user_mode(struct irc_channel *ch, const char *nick, char mode) +irc_channel_update(struct irc_channel *ch, + const char *nickname, + const char *newnickname, + char mode, + char symbol) { assert(ch); - assert(nick); + assert(nickname); struct irc_channel_user *user; - if ((user = find(ch, nick))) - user->mode = mode; -} - -void -irc_channel_set_user_nick(struct irc_channel *ch, const char *nick, const char *newnick) -{ - assert(ch); - assert(nick); - assert(newnick); - - struct irc_channel_user *user; - - if ((user = find(ch, nick))) - strlcpy(user->nickname, newnick, sizeof (user->nickname)); + if ((user = find(ch, nickname))) { + if (newnickname) + strlcpy(user->nickname, newnickname, sizeof (user->nickname)); + if (mode != -1 && symbol != -1) { + user->mode = mode; + user->symbol = symbol; + } + } } void @@ -87,8 +99,11 @@ { assert(ch); - free(ch->users); - ch->users = 0; + struct irc_channel_user *user, *tmp; + + LIST_FOREACH_SAFE(user, &ch->users, link, tmp) + free(user); + LIST_INIT(&ch->users); } void @@ -100,7 +115,7 @@ struct irc_channel_user *user; if ((user = find(ch, nick))) - IRC_SET_ALLOC_REMOVE(&ch->users, &ch->usersz, user); + LIST_REMOVE(user, link); } void @@ -109,5 +124,5 @@ assert(ch); irc_channel_clear(ch); - memset(ch, 0, sizeof (*ch)); + free(ch); }
--- a/lib/irccd/channel.h Thu Jan 21 15:34:25 2021 +0100 +++ b/lib/irccd/channel.h Thu Jan 21 23:15:20 2021 +0100 @@ -19,32 +19,35 @@ #ifndef IRCCD_CHANNEL_H #define IRCCD_CHANNEL_H +#include <sys/queue.h> #include <stdbool.h> #include <stddef.h> #include "limits.h" struct irc_channel_user { - char nickname[IRC_NICKNAME_MAX]; + char nickname[IRC_NICKNAME_LEN]; char mode; + char symbol; + LIST_ENTRY(irc_channel_user) link; }; struct irc_channel { - char name[IRC_CHANNEL_MAX]; - char password[IRC_PASSWORD_MAX]; - struct irc_channel_user *users; - size_t usersz; + char name[IRC_CHANNEL_LEN]; + char password[IRC_PASSWORD_LEN]; bool joined; + LIST_HEAD(, irc_channel_user) users; + LIST_ENTRY(irc_channel) link; }; +struct irc_channel * +irc_channel_new(const char *, const char *, bool); + void -irc_channel_add(struct irc_channel *, const char *, char); +irc_channel_add(struct irc_channel *, const char *, char, char); void -irc_channel_set_user_mode(struct irc_channel *, const char *, char); - -void -irc_channel_set_user_nick(struct irc_channel *, const char *, const char *); +irc_channel_update(struct irc_channel *, const char *, const char *, char, char); void irc_channel_clear(struct irc_channel *);
--- a/lib/irccd/irccd.c Thu Jan 21 15:34:25 2021 +0100 +++ b/lib/irccd/irccd.c Thu Jan 21 23:15:20 2021 +0100 @@ -27,13 +27,11 @@ #include "event.h" #include "irccd.h" -#include "list.h" #include "log.h" #include "peer.h" #include "plugin.h" #include "rule.h" #include "server.h" -#include "set.h" #include "transport.h" #include "util.h" @@ -47,22 +45,15 @@ void *data; }; -struct irc irc; +struct irc irc = { + .servers = LIST_HEAD_INITIALIZER(), + .peers = LIST_HEAD_INITIALIZER(), + .plugins = LIST_HEAD_INITIALIZER(), + .rules = TAILQ_HEAD_INITIALIZER(irc.rules) +}; static int pipes[2]; -static int -cmp_plugin(const struct irc_plugin *p1, const struct irc_plugin *p2) -{ - return strcmp(p1->name, p2->name); -} - -static int -cmp_peer(const struct irc_peer *p1, const struct irc_peer *p2) -{ - return p1->fd - p2->fd; -} - static bool is_command(const struct irc_plugin *p, const struct irc_event *ev) { @@ -105,67 +96,80 @@ { switch (ev->type) { case IRC_EVENT_COMMAND: - return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name, + return irc_rule_matchlist(&irc.rules, ev->server->name, ev->message.channel, ev->message.origin, p->name, "onCommand"); case IRC_EVENT_CONNECT: - return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name, + return irc_rule_matchlist(&irc.rules, ev->server->name, NULL, NULL, p->name, "onConnect"); case IRC_EVENT_DISCONNECT: - return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name, + return irc_rule_matchlist(&irc.rules, ev->server->name, NULL, NULL, p->name, "onDisconnect"); case IRC_EVENT_INVITE: - return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name, + return irc_rule_matchlist(&irc.rules, ev->server->name, ev->invite.channel, ev->invite.origin, p->name, "onInvite"); case IRC_EVENT_JOIN: - return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name, + return irc_rule_matchlist(&irc.rules, ev->server->name, ev->join.channel, ev->join.origin, p->name, "onJoin"); case IRC_EVENT_KICK: - return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name, + return irc_rule_matchlist(&irc.rules, ev->server->name, ev->kick.channel, ev->kick.origin, p->name, "onKick"); break; case IRC_EVENT_ME: - return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name, + return irc_rule_matchlist(&irc.rules, ev->server->name, ev->message.channel, ev->message.origin, p->name, "onMe"); case IRC_EVENT_MESSAGE: - return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name, + return irc_rule_matchlist(&irc.rules, ev->server->name, ev->message.channel, ev->message.origin, p->name, "onMessage"); case IRC_EVENT_MODE: - return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name, + return irc_rule_matchlist(&irc.rules, ev->server->name, ev->mode.channel, ev->mode.origin, p->name, "onMode"); case IRC_EVENT_NAMES: - return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name, + return irc_rule_matchlist(&irc.rules, ev->server->name, ev->names.channel, NULL, p->name, "onNames"); case IRC_EVENT_NICK: - return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name, + return irc_rule_matchlist(&irc.rules, ev->server->name, NULL, ev->nick.origin, p->name, "onNick"); case IRC_EVENT_NOTICE: - return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name, + return irc_rule_matchlist(&irc.rules, ev->server->name, ev->notice.channel, ev->notice.origin, p->name, "onNotice"); case IRC_EVENT_PART: - return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name, + return irc_rule_matchlist(&irc.rules, ev->server->name, ev->part.channel, ev->part.origin, p->name, "onPart"); case IRC_EVENT_TOPIC: - return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name, + return irc_rule_matchlist(&irc.rules, ev->server->name, ev->topic.channel, ev->topic.origin, p->name, "onTopic"); case IRC_EVENT_WHOIS: - return irc_rule_matchlist(irc.rules, irc.rulesz, ev->server->name, + return irc_rule_matchlist(&irc.rules, ev->server->name, NULL, NULL, p->name, "onWhois"); default: return true; } } +static inline size_t +pollable(void) +{ + const struct irc_server *s; + const struct irc_peer *p; + size_t i = 2; /* pipe + transport. */ + + LIST_FOREACH(s, &irc.servers, link) + ++i; + LIST_FOREACH(p, &irc.peers, link) + ++i; + + return i; +} + static struct pkg prepare(void) { + struct irc_peer *p; + struct irc_server *s; struct pkg pkg = {0}; size_t i = 0; - pkg.fdsz += 1; /* pipe */ - pkg.fdsz += 1; /* transport fd */ - pkg.fdsz += irc.serversz; /* servers */ - pkg.fdsz += irc.peersz; /* transport peers */ - + pkg.fdsz = pollable(); pkg.fds = irc_util_calloc(pkg.fdsz, sizeof (*pkg.fds)); /* pipe */ @@ -175,9 +179,9 @@ /* transport */ irc_transport_prepare(&pkg.fds[i++]); - for (size_t p = 0; p < irc.peersz; ++p) - irc_peer_prepare(&irc.peers[p], &pkg.fds[i++]); - for (struct irc_server *s = irc.servers; s; s = s->next) + LIST_FOREACH(p, &irc.peers, link) + irc_peer_prepare(p, &pkg.fds[i++]); + LIST_FOREACH(s, &irc.servers, link) irc_server_prepare(s, &pkg.fds[i++]); return pkg; @@ -186,20 +190,21 @@ static inline void broadcast(const struct irc_event *ev) { - char buf[IRC_MESSAGE_MAX]; + char buf[IRC_BUF_LEN]; + struct irc_peer *p; if (!irc_event_str(ev, buf, sizeof (buf))) return; - for (size_t i = 0; i < irc.peersz; ++i) - if (irc.peers[i].is_watching) - irc_peer_send(&irc.peers[i], buf); + LIST_FOREACH(p, &irc.peers, link) + if (p->is_watching) + irc_peer_send(p, buf); } static void invoke(struct irc_event *ev) { - struct irc_plugin *plgcmd = NULL; + struct irc_plugin *p, *tmp, *plgcmd = NULL; /* * Invoke for every plugin the event verbatim. Then, the event may match @@ -215,11 +220,11 @@ * onMessage for hangman and logger but onCommand for ask. As such call * hangman and logger first and modify event before ask. */ - for (size_t i = 0; i < irc.pluginsz; ++i) { - if (is_command(&irc.plugins[i], ev)) - plgcmd = &irc.plugins[i]; - else if (invokable(&irc.plugins[i], ev)) - irc_plugin_handle(&irc.plugins[i], ev); + LIST_FOREACH_SAFE(p, &irc.plugins, link, tmp) { + if (is_command(p, ev)) + plgcmd = p; + else if (invokable(p, ev)) + irc_plugin_handle(p, ev); } if (plgcmd && invokable(plgcmd, ev)) @@ -244,7 +249,7 @@ process(struct pkg *pkg) { struct irc_server *s; - struct irc_peer peer; + struct irc_peer *p, *ptmp; struct irc_event ev; if (poll(pkg->fds, pkg->fdsz, 1000) < 0 && errno != EINTR) @@ -258,20 +263,19 @@ for (size_t i = 0; i < pkg->fdsz; ++i) { pipe_flush(&pkg->fds[i]); - IRC_LIST_FOREACH(irc.servers, s) + LIST_FOREACH(s, &irc.servers, link) irc_server_flush(s, &pkg->fds[i]); /* Accept new transport client. */ - if (irc_transport_flush(&pkg->fds[i], &peer)) - IRC_SET_ALLOC_PUSH(&irc.peers, &irc.peersz, &peer, cmp_peer); + if ((p = irc_transport_flush(&pkg->fds[i]))) + LIST_INSERT_HEAD(&irc.peers, p, link); /* Flush clients. */ - for (size_t p = 0; p < irc.peersz; ) { - if (!irc_peer_flush(&irc.peers[p], &pkg->fds[i])) { - irc_peer_finish(&irc.peers[p]); - IRC_SET_ALLOC_REMOVE(&irc.peers, &irc.peersz, &irc.peers[p]); - } else - ++p; + LIST_FOREACH_SAFE(p, &irc.peers, link, ptmp) { + if (!irc_peer_flush(p, &pkg->fds[i])) { + irc_peer_finish(p); + LIST_REMOVE(p, link); + } } } @@ -279,7 +283,7 @@ * For every server, poll any kind of new event and pass them to the * plugin unless the rules explicitly disallow us to do so. */ - IRC_LIST_FOREACH(irc.servers, s) { + LIST_FOREACH(s, &irc.servers, link) { while (irc_server_poll(s, &ev)) { broadcast(&ev); invoke(&ev); @@ -294,6 +298,18 @@ free(pkg->fds); } +static inline size_t +rulescount(void) +{ + const struct irc_rule *r; + size_t total = 0; + + TAILQ_FOREACH(r, &irc.rules, link) + total++; + + return total; +} + void irc_bot_init(void) { @@ -304,24 +320,22 @@ } void -irc_bot_add_server(struct irc_server *s) +irc_bot_server_add(struct irc_server *s) { assert(s); irc_server_incref(s); irc_server_connect(s); - IRC_LIST_ADD(irc.servers, s); - - irc.serversz++; + LIST_INSERT_HEAD(&irc.servers, s, link); } struct irc_server * -irc_bot_find_server(const char *name) +irc_bot_server_find(const char *name) { struct irc_server *s; - for (s = irc.servers; s; s = s->next) + LIST_FOREACH(s, &irc.servers, link) if (strcmp(s->name, name) == 0) return s; @@ -329,11 +343,11 @@ } void -irc_bot_remove_server(const char *name) +irc_bot_server_remove(const char *name) { struct irc_server *s; - if (!(s = irc_bot_find_server(name))) + if (!(s = irc_bot_server_find(name))) return; irc_server_disconnect(s); @@ -344,43 +358,43 @@ .server = s }); - IRC_LIST_REMOVE(irc.servers, s); - + LIST_REMOVE(s, link); irc_server_decref(s); - irc.serversz--; } void -irc_bot_clear_servers(void) +irc_bot_server_clear(void) { - struct irc_server *s, *next; + struct irc_server *s, *tmp; - IRC_LIST_FOREACH_SAFE(irc.servers, s, next) - irc_bot_remove_server(s->name); + LIST_FOREACH_SAFE(s, &irc.servers, link, tmp) + irc_bot_server_remove(s->name); } void -irc_bot_add_plugin(const struct irc_plugin *p) +irc_bot_add_plugin(struct irc_plugin *p) { assert(p); - IRC_SET_ALLOC_PUSH(&irc.plugins, &irc.pluginsz, p, cmp_plugin); + LIST_INSERT_HEAD(&irc.plugins, p, link); irc_log_info("plugin %s: %s", p->name, p->description); irc_log_info("plugin %s: version %s, from %s (%s license)", p->name, p->version, p->author, p->license); - irc_plugin_load(&irc.plugins[irc.pluginsz - 1]); + irc_plugin_load(p); } struct irc_plugin * irc_bot_find_plugin(const char *name) { - struct irc_plugin key = {0}; + struct irc_plugin *p; - strlcpy(key.name, name, sizeof (key.name)); + LIST_FOREACH(p, &irc.plugins, link) + if (strcmp(p->name, name) == 0) + return p; - return IRC_SET_FIND(irc.plugins, irc.pluginsz, &key, cmp_plugin); + return NULL; } void @@ -394,37 +408,49 @@ irc_plugin_unload(p); irc_plugin_finish(p); - IRC_SET_ALLOC_REMOVE(&irc.plugins, &irc.pluginsz, p); + LIST_REMOVE(p, link); } -bool -irc_bot_insert_rule(const struct irc_rule *rule, size_t i) +void +irc_bot_rule_insert(struct irc_rule *rule, size_t index) { assert(rule); - if (irc.rulesz >= IRC_RULE_MAX) { - errno = ENOMEM; - return false; - } + if (index == 0) + TAILQ_INSERT_HEAD(&irc.rules, rule, link); + else if (index >= rulescount()) + TAILQ_INSERT_TAIL(&irc.rules, rule, link); + else { + struct irc_rule *pos = TAILQ_FIRST(&irc.rules); - if (i >= irc.rulesz) - i = irc.rulesz; + for (size_t i = 0; i < index; ++i) + pos = TAILQ_NEXT(pos, link); - memmove(&irc.rules[i + 1], &irc.rules[i], sizeof (*irc.rules) * (irc.rulesz++ - i)); - memcpy(&irc.rules[i], rule, sizeof (*rule)); - - return true; + TAILQ_INSERT_AFTER(&irc.rules, pos, rule, link); + } } void -irc_bot_remove_rule(size_t i) +irc_bot_rule_remove(size_t index) { - assert(i < irc.rulesz); + assert(index < rulescount()); + + struct irc_rule *pos = TAILQ_FIRST(&irc.rules); + + for (size_t i = 0; i < index; ++i) + pos = TAILQ_NEXT(pos, link); - if (i + 1 >= irc.rulesz) - irc.rulesz--; - else - memmove(&irc.rules[i], &irc.rules[i + 1], sizeof (*irc.rules) * (irc.rulesz-- - i)); + TAILQ_REMOVE(&irc.rules, pos, link); +} + +void +irc_bot_rule_clear(void) +{ + struct irc_rule *r, *tmp; + + TAILQ_FOREACH_SAFE(r, &irc.rules, link, tmp) + irc_rule_finish(r); + TAILQ_INIT(&irc.rules); } void
--- a/lib/irccd/irccd.h Thu Jan 21 15:34:25 2021 +0100 +++ b/lib/irccd/irccd.h Thu Jan 21 23:15:20 2021 +0100 @@ -19,57 +19,52 @@ #ifndef IRCCD_H #define IRCCD_H -#include <stdbool.h> -#include <stddef.h> - -#include "rule.h" +#include <sys/queue.h> -#define IRC_BOT_RULE_MAX 256 - -struct irc_server; -struct irc_plugin; -struct irc_peer; +#include "peer.h" +#include "plugin.h" +#include "rule.h" +#include "server.h" extern struct irc { - struct irc_peer *peers; - size_t peersz; - struct irc_plugin *plugins; - size_t pluginsz; - struct irc_server *servers; - size_t serversz; - struct irc_rule rules[IRC_BOT_RULE_MAX]; - size_t rulesz; + struct irc_server_list servers; + struct irc_peer_list peers; + struct irc_plugin_list plugins; + struct irc_rule_list rules; } irc; void irc_bot_init(void); void -irc_bot_add_server(struct irc_server *); +irc_bot_server_add(struct irc_server *); struct irc_server * -irc_bot_find_server(const char *); +irc_bot_server_find(const char *); void -irc_bot_remove_server(const char *); +irc_bot_server_remove(const char *); void -irc_bot_clear_servers(void); +irc_bot_server_clear(void); void -irc_bot_add_plugin(const struct irc_plugin *); +irc_bot_plugin_add(struct irc_plugin *); struct irc_plugin * -irc_bot_find_plugin(const char *); +irc_bot_plugin_find(const char *); void -irc_bot_remove_plugin(const char *); - -bool -irc_bot_insert_rule(const struct irc_rule *, size_t); +irc_bot_plugin_remove(const char *); void -irc_bot_remove_rule(size_t); +irc_bot_rule_insert(struct irc_rule *, size_t); + +void +irc_bot_rule_remove(size_t); + +void +irc_bot_rule_clear(void); void irc_bot_post(void (*)(void *), void *);
--- a/lib/irccd/jsapi-plugin.c Thu Jan 21 15:34:25 2021 +0100 +++ b/lib/irccd/jsapi-plugin.c Thu Jan 21 23:15:20 2021 +0100 @@ -134,7 +134,7 @@ find(duk_context *ctx) { const char *name = duk_require_string(ctx, 0); - struct irc_plugin *plg = irc_bot_find_plugin(name); + struct irc_plugin *plg = irc_bot_plugin_find(name); if (!plg) duk_error(ctx, DUK_ERR_REFERENCE_ERROR, "plugin %s not found", name); @@ -171,10 +171,13 @@ static duk_ret_t Plugin_list(duk_context *ctx) { + size_t i = 0; + struct irc_plugin *p; + duk_push_array(ctx); - for (size_t i = 0; i < irc.pluginsz; ++i) { - duk_push_string(ctx, irc.plugins[i].name); + LIST_FOREACH(p, &irc.plugins, link) { + duk_push_string(ctx, p->name); duk_put_prop_index(ctx, -2, i++); } @@ -201,7 +204,7 @@ Plugin_unload(duk_context *ctx) { /* Use find so it can raise ReferenceError if not found. */ - irc_bot_remove_plugin(find(ctx)->name); + irc_bot_plugin_remove(find(ctx)->name); return 0; }
--- a/lib/irccd/jsapi-server.c Thu Jan 21 15:34:25 2021 +0100 +++ b/lib/irccd/jsapi-server.c Thu Jan 21 23:15:20 2021 +0100 @@ -23,7 +23,6 @@ #include "channel.h" #include "irccd.h" #include "jsapi-server.h" -#include "list.h" #include "server.h" #include "util.h" @@ -138,6 +137,9 @@ Server_prototype_info(duk_context *ctx) { const struct irc_server *s = self(ctx); + const struct irc_channel *c; + const struct irc_channel_user *u; + size_t ci = 0, ui = 0; duk_push_object(ctx); duk_push_string(ctx, s->name); @@ -159,28 +161,28 @@ duk_push_array(ctx); - for (size_t c = 0; c < s->channelsz; ++c) { + LIST_FOREACH(c, &s->channels, link) { duk_push_object(ctx); - duk_push_string(ctx, s->channels[c].name); + duk_push_string(ctx, c->name); duk_put_prop_string(ctx, -2, "name"); - duk_push_boolean(ctx, s->channels[c].joined); + duk_push_boolean(ctx, c->joined); duk_put_prop_string(ctx, -2, "joined"); duk_push_array(ctx); - for (size_t n = 0; n < s->channels[c].usersz; ++n) { + LIST_FOREACH(u, &c->users, link) { duk_push_object(ctx); - duk_push_string(ctx, s->channels[c].users[n].nickname); + duk_push_string(ctx, u->nickname); duk_put_prop_string(ctx, -2, "nickname"); - if (s->channels[c].users[n].mode) - duk_push_sprintf(ctx, "%c", s->channels[c].users[n].mode); + if (u->mode) + duk_push_sprintf(ctx, "%c", u->mode); else duk_push_null(ctx); duk_put_prop_string(ctx, -2, "mode"); - duk_put_prop_index(ctx, -2, n); + duk_put_prop_index(ctx, -2, ui++); } duk_put_prop_string(ctx, -2, "users"); - duk_put_prop_index(ctx, -2, c); + duk_put_prop_index(ctx, -2, ci++); } duk_put_prop_string(ctx, -2, "channels"); @@ -484,9 +486,7 @@ static duk_ret_t Server_add(duk_context *ctx) { - struct irc_server *sv = require(ctx, 0); - - irc_bot_add_server(sv); + irc_bot_server_add(require(ctx, 0)); return 0; } @@ -495,7 +495,7 @@ Server_find(duk_context *ctx) { const char *name = duk_require_string(ctx, 0); - struct irc_server *s = irc_bot_find_server(name); + struct irc_server *s = irc_bot_server_find(name); if (!s) return 0; @@ -512,7 +512,7 @@ duk_push_object(ctx); - IRC_LIST_FOREACH(irc.servers, s) { + LIST_FOREACH(s, &irc.servers, link) { irc_jsapi_server_push(ctx, s); duk_put_prop_string(ctx, -2, s->name); } @@ -523,7 +523,7 @@ static duk_ret_t Server_remove(duk_context *ctx) { - irc_bot_remove_server(duk_require_string(ctx, 0)); + irc_bot_server_remove(duk_require_string(ctx, 0)); return 0; }
--- a/lib/irccd/limits.h Thu Jan 21 15:34:25 2021 +0100 +++ b/lib/irccd/limits.h Thu Jan 21 23:15:20 2021 +0100 @@ -19,27 +19,24 @@ #ifndef IRCCD_LIMITS_H #define IRCCD_LIMITS_H -/* - * Those were IRC limits but not strictly following RFC 1459 because lots of - * servers allow higher limits. - */ -#define IRC_NICKNAME_MAX 32 -#define IRC_USERNAME_MAX 32 -#define IRC_REALNAME_MAX 64 -#define IRC_CHANNEL_MAX 64 -#define IRC_PASSWORD_MAX 64 -#define IRC_CTCPVERSION_MAX 128 -#define IRC_USERMODES_MAX 16 - -#define IRC_MESSAGE_MAX 512 -#define IRC_ARGS_MAX 32 +/* Server limits. */ +#define IRC_NICKNAME_LEN 32 /* Nickname. */ +#define IRC_USERNAME_LEN 32 /* User name. */ +#define IRC_REALNAME_LEN 64 /* Real name. */ +#define IRC_CHANNEL_LEN 64 /* Channel name. */ +#define IRC_PASSWORD_LEN 64 /* Password length. */ +#define IRC_CTCPVERSION_LEN 64 /* Custom CTCP version answer. */ +#define IRC_USERMODES_LEN 8 /* Number of modes (e.g. ohv). */ +#define IRC_CMDCHAR_LEN 4 /* Prefix for plugin commands (e.g. !). */ /* Network limits. */ -#define IRC_HOST_MAX 32 -#define IRC_BUF_MAX 128000 +#define IRC_HOST_LEN 64 /* Hostname length.. */ +#define IRC_BUF_LEN 128000 /* Network buffer input/output. */ -/* Types limits. */ -#define IRC_NAME_MAX 16 -#define IRC_COMMANDCHAR_MAX 8 +/* Generic limits. */ +#define IRC_ID_LEN 16 /* Plugin/server identifiers. */ + +/* Rule limits. */ +#define IRC_RULE_LEN 1024 /* Space-separated list of values. */ #endif /* !IRCCD_LIMITS_H */
--- a/lib/irccd/list.h Thu Jan 21 15:34:25 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/* - * list.h -- generic macros to manipulate linked lists - * - * Copyright (c) 2013-2021 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef IRCCD_LIST_H -#define IRCCD_LIST_H - -#define IRC_LIST_ADD(h, o) \ -do { \ - if ((h)) \ - (h)->prev = (o); \ - (o)->next = (h); \ - (h) = (o); \ -} while (0) - -#define IRC_LIST_REMOVE(h, o) \ -do { \ - if ((o)->prev) \ - (o)->prev->next = (o)->next; \ - if ((o)->next) \ - (o)->next->prev = (o)->prev; \ - if ((o) == (h)) \ - (h) = (o)->next; \ - (o)->next = (o)->prev = NULL; \ -} while (0) - -#define IRC_LIST_FOREACH(h, s) \ - for ((s) = (h); (s); (s) = (s)->next) - -#define IRC_LIST_FOREACH_SAFE(h, s, tmp) \ - for ((s) = (h); s && ((tmp) = (s)->next, 1); (s) = (tmp)) - -#endif /* IRCCD_LIST_H */
--- a/lib/irccd/peer.c Thu Jan 21 15:34:25 2021 +0100 +++ b/lib/irccd/peer.c Thu Jan 21 23:15:20 2021 +0100 @@ -67,7 +67,7 @@ { struct irc_server *s; - if (!(s = irc_bot_find_server(id))) { + if (!(s = irc_bot_server_find(id))) { irc_peer_send(p, "server %s not found", id); return NULL; } @@ -98,8 +98,7 @@ irc_server_disconnect(s); } else - for (struct irc_server *s = irc.servers; s; s = s->next) - irc_server_disconnect(s); + irc_bot_server_clear(); return ok(p); } @@ -246,16 +245,25 @@ { (void)line; - char out[IRC_BUF_MAX] = "OK "; + struct irc_server *s; + FILE *fp; + char *out; + size_t outsz; + + fp = open_memstream(&out, &outsz); - for (struct irc_server *s = irc.servers; s; s = s->next) { - if (strlcat(out, s->name, sizeof (out)) >= sizeof (out)) - return EMSGSIZE; - if (s->next && strlcat(out, " ", sizeof (out)) >= sizeof (out)) - return EMSGSIZE; + fprintf(fp, "OK "); + + LIST_FOREACH(s, &irc.servers, link) { + fprintf(fp, "%s", s->name); + + if (LIST_NEXT(s, link)) + fputc(' ', fp); } + fclose(fp); irc_peer_send(p, out); + free(out); return 0; } @@ -411,13 +419,24 @@ return true; } +struct irc_peer * +irc_peer_new(int fd) +{ + struct irc_peer *p; + + p = irc_util_calloc(1, sizeof (*p)); + p->fd = fd; + + return p; +} + bool irc_peer_send(struct irc_peer *p, const char *fmt, ...) { assert(p); assert(fmt); - char buf[IRC_BUF_MAX]; + char buf[IRC_BUF_LEN]; va_list ap; size_t len, avail, required; @@ -474,5 +493,5 @@ assert(p); close(p->fd); - memset(p, 0, sizeof (*p)); + free(p); }
--- a/lib/irccd/peer.h Thu Jan 21 15:34:25 2021 +0100 +++ b/lib/irccd/peer.h Thu Jan 21 23:15:20 2021 +0100 @@ -19,6 +19,7 @@ #ifndef IRCCD_PEER_H #define IRCCD_PEER_H +#include <sys/queue.h> #include <stdbool.h> #include "limits.h" @@ -28,10 +29,16 @@ struct irc_peer { int fd; bool is_watching; - char in[IRC_BUF_MAX]; - char out[IRC_BUF_MAX]; + char in[IRC_BUF_LEN]; + char out[IRC_BUF_LEN]; + LIST_ENTRY(irc_peer) link; }; +LIST_HEAD(irc_peer_list, irc_peer); + +struct irc_peer * +irc_peer_new(int); + bool irc_peer_send(struct irc_peer *, const char *, ...);
--- a/lib/irccd/plugin.c Thu Jan 21 15:34:25 2021 +0100 +++ b/lib/irccd/plugin.c Thu Jan 21 23:15:20 2021 +0100 @@ -17,8 +17,7 @@ */ #include <assert.h> -#include <stddef.h> -#include <string.h> +#include <stdlib.h> #include "plugin.h" @@ -169,5 +168,5 @@ if (plg->finish) plg->finish(plg); - memset(plg, 0, sizeof (*plg)); + free(plg); }
--- a/lib/irccd/plugin.h Thu Jan 21 15:34:25 2021 +0100 +++ b/lib/irccd/plugin.h Thu Jan 21 23:15:20 2021 +0100 @@ -19,6 +19,7 @@ #ifndef IRCCD_PLUGIN_H #define IRCCD_PLUGIN_H +#include <sys/queue.h> #include <stdbool.h> #include "limits.h" @@ -26,7 +27,7 @@ struct irc_event; struct irc_plugin { - char name[IRC_NAME_MAX]; + char name[IRC_ID_LEN]; const char *license; const char *version; const char *author; @@ -51,8 +52,12 @@ void (*handle)(struct irc_plugin *, const struct irc_event *); void (*finish)(struct irc_plugin *); + + LIST_ENTRY(irc_plugin) link; }; +LIST_HEAD(irc_plugin_list, irc_plugin); + void irc_plugin_set_template(struct irc_plugin *, const char *, const char *);
--- a/lib/irccd/rule.c Thu Jan 21 15:34:25 2021 +0100 +++ b/lib/irccd/rule.c Thu Jan 21 23:15:20 2021 +0100 @@ -20,24 +20,25 @@ #include <ctype.h> #include <errno.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <strings.h> #include "rule.h" #include "util.h" -static void +static inline void lower(char *dst, const char *src) { while (*src) *dst++ = tolower(*src++); } -static inline char * +static char * find(const char *str, const char *value) { - char strlower[IRC_RULE_MAX] = {0}; - char valuelower[IRC_RULE_MAX] = {0}; + char strlower[IRC_RULE_LEN] = {0}; + char valuelower[IRC_RULE_LEN] = {0}; char *p; lower(strlower, str); @@ -49,7 +50,7 @@ return NULL; } -static inline bool +static bool match(const char *str, const char *value) { size_t len; @@ -75,6 +76,17 @@ return strncasecmp(p, value, len) == 0; } +struct irc_rule * +irc_rule_new(enum irc_rule_action action) +{ + struct irc_rule *r; + + r = irc_util_calloc(1, sizeof (*r)); + r->action = action; + + return r; +} + bool irc_rule_add(char *str, const char *value) { @@ -86,7 +98,7 @@ slen = strlen(str); vlen = strlen(value); - if (vlen + 1 >= IRC_RULE_MAX - slen) { + if (vlen + 1 >= IRC_RULE_LEN - slen) { errno = ENOMEM; return false; } @@ -109,7 +121,7 @@ vlen = strlen(value) + 1; /* includes ':' */ assert(pos[vlen - 1] == ':'); - memmove(&pos[0], &pos[vlen], IRC_RULE_MAX - (&pos[vlen] - str)); + memmove(&pos[0], &pos[vlen], IRC_RULE_LEN - (&pos[vlen] - str)); } bool @@ -128,8 +140,7 @@ } bool -irc_rule_matchlist(const struct irc_rule *rules, - size_t rulesz, +irc_rule_matchlist(const struct irc_rule_list *rules, const char *server, const char *channel, const char *origin, @@ -137,10 +148,11 @@ const char *event) { bool result = true; + struct irc_rule *r; - for (size_t i = 0; i < rulesz; ++i) - if (irc_rule_match(&rules[i], server, channel, origin, plugin, event)) - result = rules[i].action == IRC_RULE_ACCEPT; + TAILQ_FOREACH(r, rules, link) + if (irc_rule_match(r, server, channel, origin, plugin, event)) + result = r->action == IRC_RULE_ACCEPT; return result; } @@ -150,5 +162,5 @@ { assert(rule); - memset(rule, 0, sizeof (*rule)); + free(rule); }
--- a/lib/irccd/rule.h Thu Jan 21 15:34:25 2021 +0100 +++ b/lib/irccd/rule.h Thu Jan 21 23:15:20 2021 +0100 @@ -19,10 +19,11 @@ #ifndef IRCCD_RULE_H #define IRCCD_RULE_H +#include <sys/queue.h> #include <stdbool.h> #include <stddef.h> -#define IRC_RULE_MAX 1024 +#include "limits.h" enum irc_rule_action { IRC_RULE_ACCEPT, @@ -31,13 +32,19 @@ struct irc_rule { enum irc_rule_action action; - char servers[IRC_RULE_MAX]; - char channels[IRC_RULE_MAX]; - char origins[IRC_RULE_MAX]; - char plugins[IRC_RULE_MAX]; - char events[IRC_RULE_MAX]; + char servers[IRC_RULE_LEN]; + char channels[IRC_RULE_LEN]; + char origins[IRC_RULE_LEN]; + char plugins[IRC_RULE_LEN]; + char events[IRC_RULE_LEN]; + TAILQ_ENTRY(irc_rule) link; }; +TAILQ_HEAD(irc_rule_list, irc_rule); + +struct irc_rule * +irc_rule_new(enum irc_rule_action); + bool irc_rule_add(char *, const char *); @@ -53,8 +60,7 @@ const char *); bool -irc_rule_matchlist(const struct irc_rule *, - size_t, +irc_rule_matchlist(const struct irc_rule_list *, const char *, const char *, const char *,
--- a/lib/irccd/server.c Thu Jan 21 15:34:25 2021 +0100 +++ b/lib/irccd/server.c Thu Jan 21 23:15:20 2021 +0100 @@ -40,20 +40,19 @@ #include "event.h" #include "log.h" #include "server.h" -#include "set.h" #include "util.h" struct origin { - char nickname[IRC_NICKNAME_MAX]; - char username[IRC_USERNAME_MAX]; - char host[IRC_HOST_MAX]; + char nickname[IRC_NICKNAME_LEN]; + char username[IRC_USERNAME_LEN]; + char host[IRC_HOST_LEN]; }; struct message { char *prefix; char *cmd; - char *args[IRC_ARGS_MAX]; - char buf[IRC_MESSAGE_MAX]; + char *args[32]; + char buf[512]; }; static inline void @@ -88,7 +87,7 @@ scan(&ptr, &msg->cmd); /* command */ /* And finally arguments. */ - for (a = 0; *ptr && a < IRC_ARGS_MAX; ++a) { + for (a = 0; *ptr && a < IRC_UTIL_SIZE(msg->args); ++a) { if (*ptr == ':') { msg->args[a] = ptr + 1; ptr = strchr(ptr, '\0'); @@ -96,7 +95,7 @@ scan(&ptr, &msg->args[a]); } - if (a >= IRC_ARGS_MAX) + if (a >= IRC_UTIL_SIZE(msg->args)) return errno = EMSGSIZE, false; if (msg->cmd == NULL) return errno = EBADMSG, false; @@ -120,12 +119,6 @@ return strncmp(s->nickname, nick, strlen(s->nickname)) == 0; } -static int -cmp_channel(const struct irc_channel *c1, const struct irc_channel *c2) -{ - return strcmp(c1->name, c2->name); -} - #if 0 static const struct origin * @@ -149,46 +142,48 @@ static void add_nick(const struct irc_server *s, struct irc_channel *ch, const char *nick) { - char mode = 0; + char mode = 0, symbol = 0; for (size_t i = 0; i < IRC_UTIL_SIZE(s->prefixes); ++i) { if (nick[0] == s->prefixes[i].token) { mode = s->prefixes[i].mode; + symbol = s->prefixes[i].token; ++nick; break; } } - irc_channel_add(ch, nick, mode); + irc_channel_add(ch, nick, mode, symbol); } static struct irc_channel * add_channel(struct irc_server *s, const char *name, const char *password, bool joined) { - struct irc_channel chnew = {0}, *ch; + struct irc_channel *ch; if ((ch = irc_server_find(s, name))) { ch->joined = joined; return ch; } - strlcpy(chnew.name, name, sizeof (chnew.name)); + ch = irc_util_calloc(1, sizeof (*ch)); + ch->joined = joined; + strlcpy(ch->name, name, sizeof (ch->name)); if (password) - strlcpy(chnew.password, password, sizeof (chnew.password)); - - chnew.joined = joined; + strlcpy(ch->password, password, sizeof (ch->password)); - IRC_SET_ALLOC_PUSH(&s->channels, &s->channelsz, &chnew, cmp_channel); + LIST_INIT(&ch->users); + LIST_INSERT_HEAD(&s->channels, ch, link); - return irc_server_find(s, name); + return ch; } static void -remove_channel(struct irc_server *s, struct irc_channel *ch) +remove_channel(struct irc_channel *ch) { - irc_channel_clear(ch); - IRC_SET_ALLOC_REMOVE(&s->channels, &s->channelsz, ch); + irc_channel_finish(ch); + LIST_REMOVE(ch, link); } bool @@ -248,11 +243,13 @@ { (void)msg; + struct irc_channel *ch; + s->state = IRC_SERVER_STATE_CONNECTED; /* Now join all channels that were requested. */ - for (size_t i = 0; i < s->channelsz; ++i) - irc_server_join(s, s->channels[i].name, s->channels[i].password); + LIST_FOREACH(ch, &s->channels, link) + irc_server_join(s, ch->name, ch->password); ev->type = IRC_EVENT_CONNECT; } @@ -354,7 +351,7 @@ ch = add_channel(s, ev->part.channel, NULL, true); if (is_self(s, ev->part.origin) == 0) - remove_channel(s, ch); + remove_channel(ch); else irc_channel_remove(ch, ev->part.origin); } @@ -452,8 +449,9 @@ (void)msg; FILE *fp; + size_t length; const struct irc_channel *ch; - size_t length; + const struct irc_channel_user *u; ev->type = IRC_EVENT_NAMES; ev->names.channel = strdup(msg->args[1]); @@ -462,15 +460,13 @@ ch = irc_server_find(s, ev->names.channel); fp = open_memstream(&ev->names.names, &length); - for (size_t i = 0; i < ch->usersz; ++i) { - const struct irc_channel_user *u = &ch->users[i]; - + LIST_FOREACH(u, &ch->users, link) { if (u->mode) fprintf(fp, "%c", sym(s, u->mode)); fprintf(fp, "%s", u->nickname); - if (i + 1 < ch->usersz) + if (LIST_NEXT(u, link)) fputc(' ', fp); } @@ -481,6 +477,7 @@ handle_whoisuser(struct irc_server *s, struct irc_event *ev, struct message *msg) { (void)s; + (void)ev; (void)msg; s->bufwhois.nickname = strdup(msg->args[1]); @@ -581,6 +578,8 @@ static void clear(struct irc_server *s) { + struct irc_channel *ch, *tmp; + s->state = IRC_SERVER_STATE_DISCONNECTED; if (s->fd != 0) { @@ -604,6 +603,12 @@ s->ctx = NULL; } #endif + + LIST_FOREACH_SAFE(ch, &s->channels, link, tmp) { + irc_channel_finish(ch); + free(ch); + } + LIST_INIT(&s->channels); } static bool @@ -945,6 +950,36 @@ }, }; +struct irc_server * +irc_server_new(const char *name, + const char *nickname, + const char *username, + const char *realname, + const char *hostname, + unsigned int port) +{ + assert(name); + assert(nickname); + assert(username); + assert(realname); + assert(hostname); + + struct irc_server *s; + + s = irc_util_calloc(1, sizeof (*s)); + s->port = port; + + strlcpy(s->name, name, sizeof (s->name)); + strlcpy(s->nickname, nickname, sizeof (s->nickname)); + strlcpy(s->username, username, sizeof (s->username)); + strlcpy(s->realname, realname, sizeof (s->realname)); + strlcpy(s->hostname, hostname, sizeof (s->hostname)); + + LIST_INIT(&s->channels); + + return s; +} + void irc_server_connect(struct irc_server *s) { @@ -1017,11 +1052,13 @@ assert(s); assert(name); - struct irc_channel key = {0}; + struct irc_channel *ch; - strlcpy(key.name, name, sizeof (key.name)); + LIST_FOREACH(ch, &s->channels, link) + if (strcmp(ch->name, name) == 0) + return ch; - return IRC_SET_FIND(s->channels, s->channelsz, &key, cmp_channel); + return NULL; } bool @@ -1030,7 +1067,7 @@ assert(s); assert(fmt); - char buf[IRC_BUF_MAX]; + char buf[IRC_BUF_LEN]; va_list ap; size_t len, avail, required; @@ -1251,8 +1288,6 @@ if (--s->refc == 0) { clear(s); - //free(s->whois.channels); - free(s->channels); free(s); } }
--- a/lib/irccd/server.h Thu Jan 21 15:34:25 2021 +0100 +++ b/lib/irccd/server.h Thu Jan 21 23:15:20 2021 +0100 @@ -19,6 +19,7 @@ #ifndef IRCCD_SERVER_H #define IRCCD_SERVER_H +#include <sys/queue.h> #include <stdbool.h> #include <stddef.h> @@ -75,31 +76,29 @@ struct irc_server { /* Connection settings. */ - char name[IRC_NAME_MAX]; - char hostname[IRC_HOST_MAX]; - char password[IRC_PASSWORD_MAX]; + char name[IRC_ID_LEN]; + char hostname[IRC_HOST_LEN]; + char password[IRC_PASSWORD_LEN]; unsigned short port; enum irc_server_flags flags; /* Plugin prefix. */ - char commandchar[IRC_COMMANDCHAR_MAX]; + char commandchar[IRC_CMDCHAR_LEN]; /* IRC identity. */ - char nickname[IRC_NICKNAME_MAX]; - char username[IRC_USERNAME_MAX]; - char realname[IRC_REALNAME_MAX]; - char ctcpversion[IRC_CTCPVERSION_MAX]; + char nickname[IRC_NICKNAME_LEN]; + char username[IRC_USERNAME_LEN]; + char realname[IRC_REALNAME_LEN]; + char ctcpversion[IRC_CTCPVERSION_LEN]; - /* Joined channels. */ - struct irc_channel *channels; - size_t channelsz; + LIST_HEAD(, irc_channel) channels; /* Network connectivity. */ int fd; struct addrinfo *ai; struct addrinfo *aip; - char in[IRC_BUF_MAX]; - char out[IRC_BUF_MAX]; + char in[IRC_BUF_LEN]; + char out[IRC_BUF_LEN]; enum irc_server_state state; /* OpenSSL support. */ @@ -113,14 +112,24 @@ /* Reference count. */ size_t refc; - struct irc_server *next; - struct irc_server *prev; /* IRC server settings. */ char chantypes[8]; struct irc_server_prefix prefixes[16]; + + LIST_ENTRY(irc_server) link; }; +LIST_HEAD(irc_server_list, irc_server); + +struct irc_server * +irc_server_new(const char *, + const char *, + const char *, + const char *, + const char *, + unsigned int); + void irc_server_connect(struct irc_server *);
--- a/lib/irccd/set.h Thu Jan 21 15:34:25 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/* - * set.h -- generic macros to insert/remove in sorted arrays - * - * Copyright (c) 2013-2021 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef IRCCD_SET_H -#define IRCCD_SET_H - -#include <string.h> -#include <stdlib.h> - -#include "util.h" - -typedef int (*irc_set_cmp)(const void *, const void *); - -#define IRC_SET_FIND(a, asz, o, f) \ - bsearch(o, a, asz, sizeof (*(o)), (irc_set_cmp)f) - -#define IRC_SET_ALLOC_PUSH(a, asz, o, f) \ -do { \ - *(a) = irc_util_reallocarray(*(a), ++(*(asz)), sizeof (*(o))); \ - memcpy(*(a) + ((*asz) - 1), o, sizeof (*o)); \ - qsort(*(a), *(asz), sizeof (*o), (irc_set_cmp)f); \ -} while (0) - -#define IRC_SET_ALLOC_REMOVE(a, asz, o) \ -do { \ - if (--(*(asz)) == 0) { \ - free(*(a)); \ - *(a) = NULL; \ - } else { \ - memmove(o, o + 1, sizeof (*(o)) * (*(asz) - ((o) - *(a)))); \ - *(a) = irc_util_reallocarray(*(a), *(asz), sizeof (*(o))); \ - } \ -} while (0) - -#define IRC_SET_PUSH(a, asz, o, f) \ -do { \ - memcpy(a + (*(asz))++, o, sizeof (*o)); \ - qsort(a, *(asz), sizeof (*o), (irc_set_cmp)f); \ -} while (0) - -#define IRC_SET_REMOVE(a, asz, o) \ -do { \ - if (--(*asz) != 0) \ - memmove(o, o + 1, sizeof (*(o)) * (*(asz) - ((o) - (a)))); \ -} while (0) - -#endif /* !IRCCD_SET_H */
--- a/lib/irccd/transport.c Thu Jan 21 15:34:25 2021 +0100 +++ b/lib/irccd/transport.c Thu Jan 21 23:15:20 2021 +0100 @@ -31,6 +31,7 @@ #include "log.h" #include "transport.h" #include "peer.h" +#include "util.h" static struct sockaddr_un addr; static int fd = -1; @@ -85,27 +86,29 @@ pfd->events = POLLIN; } -bool -irc_transport_flush(const struct pollfd *pfd, struct irc_peer *peer) +struct irc_peer * +irc_transport_flush(const struct pollfd *pfd) { assert(pfd); - assert(peer); + + struct irc_peer *peer; + int newfd; if (fd < 0 || pfd->fd != fd || !(pfd->revents & POLLIN)) - return false; - - memset(peer, 0, sizeof (*peer)); + return NULL; - if ((peer->fd = accept(fd, NULL, NULL)) < 0) { + if ((newfd = accept(fd, NULL, NULL)) < 0) { irc_log_warn("transport: %s", strerror(errno)); - return false; + return NULL; } + peer = irc_peer_new(newfd); + irc_log_info("transport: new client connected"); irc_peer_send(peer, "IRCCD %d.%d.%d", IRCCD_VERSION_MAJOR, IRCCD_VERSION_MINOR, IRCCD_VERSION_PATCH); - return true; + return peer; } void
--- a/lib/irccd/transport.h Thu Jan 21 15:34:25 2021 +0100 +++ b/lib/irccd/transport.h Thu Jan 21 23:15:20 2021 +0100 @@ -33,8 +33,8 @@ void irc_transport_prepare(struct pollfd *); -bool -irc_transport_flush(const struct pollfd *, struct irc_peer *); +struct irc_peer * +irc_transport_flush(const struct pollfd *); void irc_transport_finish(void);
--- a/tests/CMakeLists.txt Thu Jan 21 15:34:25 2021 +0100 +++ b/tests/CMakeLists.txt Thu Jan 21 23:15:20 2021 +0100 @@ -22,7 +22,7 @@ TESTS test-bot test-channel - test-event + #test-event #test-dl-plugin test-log test-rule
--- a/tests/test-bot.c Thu Jan 21 15:34:25 2021 +0100 +++ b/tests/test-bot.c Thu Jan 21 23:15:20 2021 +0100 @@ -25,66 +25,52 @@ #include <irccd/server.h> #include <irccd/util.h> -static struct irc_server * -server_new(const char *name) -{ - struct irc_server *s; - - s = irc_util_calloc(1, sizeof (*s)); - strlcpy(s->name, name, sizeof (s->name)); - - return s; -} - static void clean(void *udata) { (void)udata; - irc_bot_clear_servers(); + irc_bot_server_clear(); } GREATEST_TEST servers_add(void) { - struct irc_server *s1, *s2, *s3; + struct irc_server *s, *s1, *s2, *s3; - s1 = server_new("malikania"); - s2 = server_new("freenode"); - s3 = server_new("oftc"); + s1 = irc_server_new("malikania", "x", "x", "x", "localhost", 6667); + s2 = irc_server_new("freenode", "x", "x", "x", "localhost", 6667); + s3 = irc_server_new("oftc", "x", "x", "x", "localhost", 6667); /* irc.servers -> s1 */ - irc_bot_add_server(s1); - GREATEST_ASSERT_EQ(1, irc.serversz); - GREATEST_ASSERT_EQ(1, s1->refc); - GREATEST_ASSERT_EQ(s1, irc.servers); - GREATEST_ASSERT_EQ(NULL, s1->prev); - GREATEST_ASSERT_EQ(NULL, s1->next); + irc_bot_server_add(s1); + s = LIST_FIRST(&irc.servers); + GREATEST_ASSERT_EQ(1, s->refc); + GREATEST_ASSERT_EQ(s, s1); + s = LIST_NEXT(s, link); + GREATEST_ASSERT(!s); /* irc.servers -> s2 -> s1 */ - irc_bot_add_server(s2); - GREATEST_ASSERT_EQ(2, irc.serversz); - GREATEST_ASSERT_EQ(1, s1->refc); - GREATEST_ASSERT_EQ(1, s2->refc); - GREATEST_ASSERT_EQ(s2, irc.servers); - GREATEST_ASSERT_EQ(s1, s2->next); - GREATEST_ASSERT_EQ(NULL, s2->prev); - GREATEST_ASSERT_EQ(NULL, s1->next); - GREATEST_ASSERT_EQ(s2, s1->prev); + irc_bot_server_add(s2); + s = LIST_FIRST(&irc.servers); + GREATEST_ASSERT_EQ(1, s->refc); + GREATEST_ASSERT_EQ(s, s2); + s = LIST_NEXT(s, link); + GREATEST_ASSERT_EQ(s, s1); + s = LIST_NEXT(s, link); + GREATEST_ASSERT(!s); /* irc.servers -> s3 -> s2 -> s1 */ - irc_bot_add_server(s3); - GREATEST_ASSERT_EQ(3, irc.serversz); - GREATEST_ASSERT_EQ(1, s1->refc); - GREATEST_ASSERT_EQ(1, s2->refc); - GREATEST_ASSERT_EQ(1, s3->refc); - GREATEST_ASSERT_EQ(s3, irc.servers); - GREATEST_ASSERT_EQ(s2, s3->next); - GREATEST_ASSERT_EQ(NULL, s3->prev); - GREATEST_ASSERT_EQ(s1, s2->next); - GREATEST_ASSERT_EQ(s3, s2->prev); - GREATEST_ASSERT_EQ(NULL, s1->next); - GREATEST_ASSERT_EQ(s2, s1->prev); + irc_bot_server_add(s3); + s = LIST_FIRST(&irc.servers); + GREATEST_ASSERT_EQ(1, s->refc); + GREATEST_ASSERT_EQ(s, s3); + s = LIST_NEXT(s, link); + GREATEST_ASSERT_EQ(s, s2); + s = LIST_NEXT(s, link); + GREATEST_ASSERT_EQ(s, s1); + s = LIST_NEXT(s, link); + GREATEST_ASSERT(!s); GREATEST_PASS(); } @@ -92,11 +78,11 @@ GREATEST_TEST servers_remove(void) { - struct irc_server *s1, *s2, *s3; + struct irc_server *s, *s1, *s2, *s3; - s1 = server_new("1"); - s2 = server_new("2"); - s3 = server_new("3"); + s1 = irc_server_new("1", "x", "x", "x", "localhost", 6667); + s2 = irc_server_new("2", "x", "x", "x", "localhost", 6667); + s3 = irc_server_new("3", "x", "x", "x", "localhost", 6667); /* Protect deletion from irc_bot_remove_server. */ irc_server_incref(s1); @@ -104,46 +90,42 @@ irc_server_incref(s3); /* irc.servers -> s3 -> s2 -> s1 */ - irc_bot_add_server(s1); - irc_bot_add_server(s2); - irc_bot_add_server(s3); + irc_bot_server_add(s1); + irc_bot_server_add(s2); + irc_bot_server_add(s3); /* irc.servers -> s3 -> [s2] -> s1 */ /* irc.servers -> s3 -> s1 */ - irc_bot_remove_server(s2->name); - GREATEST_ASSERT_EQ(2, irc.serversz); + irc_bot_server_remove(s2->name); GREATEST_ASSERT_EQ(2, s1->refc); GREATEST_ASSERT_EQ(1, s2->refc); GREATEST_ASSERT_EQ(2, s3->refc); - GREATEST_ASSERT_EQ(NULL, s2->next); - GREATEST_ASSERT_EQ(NULL, s2->prev); - GREATEST_ASSERT_EQ(s1, s3->next); - GREATEST_ASSERT_EQ(NULL, s3->prev); - GREATEST_ASSERT_EQ(NULL, s1->next); - GREATEST_ASSERT_EQ(s3, s1->prev); + s = LIST_FIRST(&irc.servers); + GREATEST_ASSERT_EQ(s, s3); + s = LIST_NEXT(s, link); + GREATEST_ASSERT_EQ(s, s1); + s = LIST_NEXT(s, link); + GREATEST_ASSERT(!s); /* irc.servers -> s3 -> [s1] */ /* irc.servers -> s3 */ - irc_bot_remove_server(s1->name); - GREATEST_ASSERT_EQ(1, irc.serversz); + irc_bot_server_remove(s1->name); GREATEST_ASSERT_EQ(1, s1->refc); GREATEST_ASSERT_EQ(1, s2->refc); GREATEST_ASSERT_EQ(2, s3->refc); - GREATEST_ASSERT_EQ(NULL, s1->next); - GREATEST_ASSERT_EQ(NULL, s1->prev); - GREATEST_ASSERT_EQ(NULL, s3->next); - GREATEST_ASSERT_EQ(NULL, s3->prev); + s = LIST_FIRST(&irc.servers); + GREATEST_ASSERT_EQ(s, s3); + s = LIST_NEXT(s, link); + GREATEST_ASSERT(!s); /* irc.servers -> [s3] */ /* irc.servers -> NULL */ - irc_bot_remove_server(s3->name); - GREATEST_ASSERT_EQ(0, irc.serversz); - GREATEST_ASSERT_EQ(NULL, irc.servers); + irc_bot_server_remove(s3->name); GREATEST_ASSERT_EQ(1, s1->refc); GREATEST_ASSERT_EQ(1, s2->refc); GREATEST_ASSERT_EQ(1, s3->refc); - GREATEST_ASSERT_EQ(NULL, s3->next); - GREATEST_ASSERT_EQ(NULL, s3->prev); + s = LIST_FIRST(&irc.servers); + GREATEST_ASSERT(!s); irc_server_decref(s1); irc_server_decref(s2); @@ -157,31 +139,24 @@ { struct irc_server *s1, *s2, *s3; - s1 = server_new("1"); - s2 = server_new("2"); - s3 = server_new("3"); + s1 = irc_server_new("1", "x", "x", "x", "localhost", 6667); + s2 = irc_server_new("2", "x", "x", "x", "localhost", 6667); + s3 = irc_server_new("3", "x", "x", "x", "localhost", 6667); /* Protect deletion from irc_bot_remove_server. */ irc_server_incref(s1); irc_server_incref(s2); irc_server_incref(s3); - irc_bot_add_server(s1); - irc_bot_add_server(s2); - irc_bot_add_server(s3); - irc_bot_clear_servers(); + irc_bot_server_add(s1); + irc_bot_server_add(s2); + irc_bot_server_add(s3); + irc_bot_server_clear(); - GREATEST_ASSERT_EQ(0, irc.serversz); - GREATEST_ASSERT_EQ(NULL, irc.servers); GREATEST_ASSERT_EQ(1, s1->refc); - GREATEST_ASSERT_EQ(NULL, s1->next); - GREATEST_ASSERT_EQ(NULL, s1->prev); GREATEST_ASSERT_EQ(1, s2->refc); - GREATEST_ASSERT_EQ(NULL, s2->next); - GREATEST_ASSERT_EQ(NULL, s2->prev); GREATEST_ASSERT_EQ(1, s3->refc); - GREATEST_ASSERT_EQ(NULL, s3->next); - GREATEST_ASSERT_EQ(NULL, s3->prev); + GREATEST_ASSERT(!LIST_FIRST(&irc.servers)); GREATEST_PASS(); }
--- a/tests/test-channel.c Thu Jan 21 15:34:25 2021 +0100 +++ b/tests/test-channel.c Thu Jan 21 23:15:20 2021 +0100 @@ -24,33 +24,51 @@ GREATEST_TEST basics_add(void) { - struct irc_channel ch = {0}; + struct irc_channel *ch; + struct irc_channel_user *user; + + ch = irc_channel_new("#test", NULL, true); + GREATEST_ASSERT_STR_EQ("#test", ch->name); + GREATEST_ASSERT_STR_EQ("", ch->password); + GREATEST_ASSERT(ch->joined); - irc_channel_add(&ch, "markand", '@'); - GREATEST_ASSERT_EQ(ch.usersz, 1U); - GREATEST_ASSERT_EQ(ch.users[0].mode, '@'); - GREATEST_ASSERT_STR_EQ(ch.users[0].nickname, "markand"); + irc_channel_add(ch, "markand", 'o', '@'); + user = LIST_FIRST(&ch->users); + GREATEST_ASSERT_EQ('o', user->mode); + GREATEST_ASSERT_EQ('@', user->symbol); + GREATEST_ASSERT_STR_EQ("markand", user->nickname); - irc_channel_add(&ch, "markand", '@'); - GREATEST_ASSERT_EQ(ch.usersz, 1U); - GREATEST_ASSERT_EQ(ch.users[0].mode, '@'); - GREATEST_ASSERT_STR_EQ(ch.users[0].nickname, "markand"); + irc_channel_add(ch, "markand", '+', '@'); + user = LIST_FIRST(&ch->users); + GREATEST_ASSERT_EQ('o', user->mode); + GREATEST_ASSERT_EQ('@', user->symbol); + GREATEST_ASSERT_STR_EQ("markand", user->nickname); - irc_channel_add(&ch, "jean", 0); - GREATEST_ASSERT_EQ(ch.usersz, 2U); - GREATEST_ASSERT_EQ(ch.users[0].mode, 0); - GREATEST_ASSERT_STR_EQ(ch.users[0].nickname, "jean"); - GREATEST_ASSERT_EQ(ch.users[1].mode, '@'); - GREATEST_ASSERT_STR_EQ(ch.users[1].nickname, "markand"); + irc_channel_add(ch, "jean", 'h', '+'); + user = LIST_FIRST(&ch->users); + GREATEST_ASSERT_EQ('h', user->mode); + GREATEST_ASSERT_EQ('+', user->symbol); + GREATEST_ASSERT_STR_EQ("jean", user->nickname); + user = LIST_NEXT(user, link); + GREATEST_ASSERT_EQ('o', user->mode); + GREATEST_ASSERT_EQ('@', user->symbol); + GREATEST_ASSERT_STR_EQ("markand", user->nickname); - irc_channel_add(&ch, "zoe", 0); - GREATEST_ASSERT_EQ(ch.usersz, 3U); - GREATEST_ASSERT_EQ(ch.users[0].mode, 0); - GREATEST_ASSERT_STR_EQ(ch.users[0].nickname, "jean"); - GREATEST_ASSERT_EQ(ch.users[1].mode, '@'); - GREATEST_ASSERT_STR_EQ(ch.users[1].nickname, "markand"); - GREATEST_ASSERT_EQ(ch.users[2].mode, 0); - GREATEST_ASSERT_STR_EQ(ch.users[2].nickname, "zoe"); + irc_channel_add(ch, "zoe", 0, 0); + user = LIST_FIRST(&ch->users); + GREATEST_ASSERT_EQ(0, user->mode); + GREATEST_ASSERT_EQ(0, user->symbol); + GREATEST_ASSERT_STR_EQ("zoe", user->nickname); + user = LIST_NEXT(user, link); + GREATEST_ASSERT_EQ('h', user->mode); + GREATEST_ASSERT_EQ('+', user->symbol); + GREATEST_ASSERT_STR_EQ("jean", user->nickname); + user = LIST_NEXT(user, link); + GREATEST_ASSERT_EQ('o', user->mode); + GREATEST_ASSERT_EQ('@', user->symbol); + GREATEST_ASSERT_STR_EQ("markand", user->nickname); + + irc_channel_finish(ch); GREATEST_PASS(); } @@ -58,58 +76,65 @@ GREATEST_TEST basics_remove(void) { - struct irc_channel ch = {0}; + struct irc_channel *ch; + struct irc_channel_user *user; - irc_channel_add(&ch, "markand", '@'); - irc_channel_add(&ch, "jean", 0); - irc_channel_add(&ch, "zoe", 0); + ch = irc_channel_new("#test", NULL, true); + + irc_channel_add(ch, "markand", 'o', '@'); + irc_channel_add(ch, "jean", 0, 0); + irc_channel_add(ch, "zoe", 0, 0); - irc_channel_remove(&ch, "jean"); - GREATEST_ASSERT_EQ(ch.usersz, 2U); - GREATEST_ASSERT_EQ(ch.users[0].mode, '@'); - GREATEST_ASSERT_STR_EQ(ch.users[0].nickname, "markand"); - GREATEST_ASSERT_EQ(ch.users[1].mode, 0); - GREATEST_ASSERT_STR_EQ(ch.users[1].nickname, "zoe"); + irc_channel_remove(ch, "jean"); + user = LIST_FIRST(&ch->users); + GREATEST_ASSERT_EQ(0, user->mode); + GREATEST_ASSERT_EQ(0, user->symbol); + GREATEST_ASSERT_STR_EQ("zoe", user->nickname); + user = LIST_NEXT(user, link); + GREATEST_ASSERT_EQ('o', user->mode); + GREATEST_ASSERT_EQ('@', user->symbol); + GREATEST_ASSERT_STR_EQ("markand", user->nickname); - irc_channel_remove(&ch, "zoe"); - GREATEST_ASSERT_EQ(ch.usersz, 1U); - GREATEST_ASSERT_EQ(ch.users[0].mode, '@'); - GREATEST_ASSERT_STR_EQ(ch.users[0].nickname, "markand"); + irc_channel_remove(ch, "zoe"); + user = LIST_FIRST(&ch->users); + GREATEST_ASSERT_EQ('o', user->mode); + GREATEST_ASSERT_EQ('@', user->symbol); + GREATEST_ASSERT_STR_EQ("markand", user->nickname); - irc_channel_remove(&ch, "markand"); - GREATEST_ASSERT_EQ(ch.usersz, 0U); - GREATEST_ASSERT(!ch.users); + irc_channel_remove(ch, "markand"); + GREATEST_ASSERT(!LIST_FIRST(&ch->users)); + + irc_channel_finish(ch); GREATEST_PASS(); } GREATEST_TEST -basics_set_mode(void) +basics_update(void) { - struct irc_channel ch = {0}; + struct irc_channel *ch; + struct irc_channel_user *user; - irc_channel_add(&ch, "jean", '@'); - irc_channel_set_user_mode(&ch, "jean", '+'); - irc_channel_set_user_mode(&ch, "nobody", '+'); + ch = irc_channel_new("#test", NULL, true); - GREATEST_ASSERT_EQ(ch.usersz, 1); - GREATEST_ASSERT_EQ(ch.users[0].mode, '+'); - GREATEST_ASSERT_STR_EQ(ch.users[0].nickname, "jean"); - GREATEST_PASS(); -} + irc_channel_add(ch, "markand", 'o', '@'); + irc_channel_add(ch, "jean", 0, 0); + irc_channel_add(ch, "zoe", 0, 0); + + irc_channel_update(ch, "zoe", NULL, 'o', '@'); + user = LIST_FIRST(&ch->users); + GREATEST_ASSERT_EQ('o', user->mode); + GREATEST_ASSERT_EQ('@', user->symbol); + GREATEST_ASSERT_STR_EQ("zoe", user->nickname); -GREATEST_TEST -basics_set_nick(void) -{ - struct irc_channel ch = {0}; + irc_channel_update(ch, "zoe", "eoz", -1, -1); + user = LIST_FIRST(&ch->users); + GREATEST_ASSERT_EQ('o', user->mode); + GREATEST_ASSERT_EQ('@', user->symbol); + GREATEST_ASSERT_STR_EQ("eoz", user->nickname); - irc_channel_add(&ch, "jean", '@'); - irc_channel_set_user_nick(&ch, "jean", "francis"); - irc_channel_set_user_nick(&ch, "nobody", "francis"); + irc_channel_finish(ch); - GREATEST_ASSERT_EQ(ch.usersz, 1); - GREATEST_ASSERT_EQ(ch.users[0].mode, '@'); - GREATEST_ASSERT_STR_EQ(ch.users[0].nickname, "francis"); GREATEST_PASS(); } @@ -117,8 +142,7 @@ { GREATEST_RUN_TEST(basics_add); GREATEST_RUN_TEST(basics_remove); - GREATEST_RUN_TEST(basics_set_mode); - GREATEST_RUN_TEST(basics_set_nick); + GREATEST_RUN_TEST(basics_update); } GREATEST_MAIN_DEFS();
--- a/tests/test-rule.c Thu Jan 21 15:34:25 2021 +0100 +++ b/tests/test-rule.c Thu Jan 21 23:15:20 2021 +0100 @@ -27,50 +27,61 @@ { (void)udata; - memset(&irc, 0, sizeof (irc)); + irc_bot_rule_clear(); } GREATEST_TEST basics_insert(void) { - struct irc_rule r1 = {0}, r2 = {0}; + struct irc_rule *r, *r1, *r2; - irc_rule_add(r1.servers, "s1"); - irc_rule_add(r2.servers, "s2"); + r1 = irc_rule_new(IRC_RULE_DROP); + r2 = irc_rule_new(IRC_RULE_DROP); + + irc_rule_add(r1->servers, "s1"); + irc_rule_add(r2->servers, "s2"); - irc_bot_insert_rule(&r1, 0); - irc_bot_insert_rule(&r2, 0); + irc_bot_rule_insert(r1, 0); + irc_bot_rule_insert(r2, 0); - GREATEST_ASSERT_EQ(2U, irc.rulesz); - GREATEST_ASSERT(memcmp(&irc.rules[0], &r2, sizeof (r2)) == 0); - GREATEST_ASSERT(memcmp(&irc.rules[1], &r1, sizeof (r1)) == 0); + r = TAILQ_FIRST(&irc.rules); + GREATEST_ASSERT_EQ(r2, r); + r = TAILQ_NEXT(r, link); + GREATEST_ASSERT_EQ(r1, r); + GREATEST_PASS(); } GREATEST_TEST basics_remove(void) { - struct irc_rule r1 = {0}, r2 = {0}, r3 = {0}; + struct irc_rule *r, *r1, *r2, *r3; - irc_rule_add(r1.servers, "s1"); - irc_rule_add(r2.servers, "s2"); - irc_rule_add(r3.servers, "s3"); + r1 = irc_rule_new(IRC_RULE_DROP); + r2 = irc_rule_new(IRC_RULE_DROP); + r3 = irc_rule_new(IRC_RULE_DROP); - irc_bot_insert_rule(&r1, -1); - irc_bot_insert_rule(&r2, -1); - irc_bot_insert_rule(&r3, -1); - irc_bot_remove_rule(1); + irc_rule_add(r1->servers, "s1"); + irc_rule_add(r2->servers, "s2"); + irc_rule_add(r3->servers, "s3"); - GREATEST_ASSERT_EQ(2U, irc.rulesz); - GREATEST_ASSERT(memcmp(&irc.rules[0], &r1, sizeof (r1)) == 0); - GREATEST_ASSERT(memcmp(&irc.rules[1], &r3, sizeof (r3)) == 0); + irc_bot_rule_insert(r1, -1); + irc_bot_rule_insert(r2, -1); + irc_bot_rule_insert(r3, -1); + irc_bot_rule_remove(1); - irc_bot_remove_rule(1); - GREATEST_ASSERT_EQ(1U, irc.rulesz); - GREATEST_ASSERT(memcmp(&irc.rules[0], &r1, sizeof (r1)) == 0); + r = TAILQ_FIRST(&irc.rules); + GREATEST_ASSERT_EQ(r1, r); + r = TAILQ_NEXT(r, link); + GREATEST_ASSERT_EQ(r3, r); - irc_bot_remove_rule(0); - GREATEST_ASSERT_EQ(0U, irc.rulesz); + irc_bot_rule_remove(1); + r = TAILQ_FIRST(&irc.rules); + GREATEST_ASSERT_EQ(r1, r); + + irc_bot_rule_remove(0); + r = TAILQ_FIRST(&irc.rules); + GREATEST_ASSERT(!r); GREATEST_PASS(); } @@ -121,38 +132,37 @@ { (void)udata; - struct irc_rule r1 = {0}, r2 = {0}, r31 = {0}, r32 = {0}; + struct irc_rule *r1, *r2, *r31, *r32; - /* Deinit irccd first. */ - memset(&irc, 0, sizeof (irc)); + irc_bot_rule_clear(); /* #1 */ - r1.action = IRC_RULE_DROP; - irc_rule_add(r1.channels, "#staff"); - irc_rule_add(r1.events, "onCommand"); - irc_bot_insert_rule(&r1, -1); + r1 = irc_rule_new(IRC_RULE_DROP); + irc_rule_add(r1->channels, "#staff"); + irc_rule_add(r1->events, "onCommand"); + irc_bot_rule_insert(r1, -1); /* #2 */ - r2.action = IRC_RULE_ACCEPT; - irc_rule_add(r2.servers, "unsafe"); - irc_rule_add(r2.channels, "#staff"); - irc_rule_add(r2.events, "onCommand"); - irc_bot_insert_rule(&r2, -1); + r2 = irc_rule_new(IRC_RULE_ACCEPT); + irc_rule_add(r2->servers, "unsafe"); + irc_rule_add(r2->channels, "#staff"); + irc_rule_add(r2->events, "onCommand"); + irc_bot_rule_insert(r2, -1); /* #3-1 */ - r31.action = IRC_RULE_DROP; - irc_rule_add(r31.plugins, "game"); - irc_bot_insert_rule(&r31, -1); + r31 = irc_rule_new(IRC_RULE_DROP); + irc_rule_add(r31->plugins, "game"); + irc_bot_rule_insert(r31, -1); /* #3-2 */ - r32.action = IRC_RULE_ACCEPT; - irc_rule_add(r32.servers, "malikania"); - irc_rule_add(r32.servers, "localhost"); - irc_rule_add(r32.channels, "#games"); - irc_rule_add(r32.plugins, "game"); - irc_rule_add(r32.events, "onCommand"); - irc_rule_add(r32.events, "onMessage"); - irc_bot_insert_rule(&r32, -1); + r32 = irc_rule_new(IRC_RULE_ACCEPT); + irc_rule_add(r32->servers, "malikania"); + irc_rule_add(r32->servers, "localhost"); + irc_rule_add(r32->channels, "#games"); + irc_rule_add(r32->plugins, "game"); + irc_rule_add(r32->events, "onCommand"); + irc_rule_add(r32->events, "onMessage"); + irc_bot_rule_insert(r32, -1); }; GREATEST_TEST @@ -239,19 +249,19 @@ solve_match7(void) { /* Allowed */ - GREATEST_ASSERT(irc_rule_matchlist(irc.rules, irc.rulesz, "malikania", "#staff", "", "a", "onMessage")); + GREATEST_ASSERT(irc_rule_matchlist(&irc.rules, "malikania", "#staff", "", "a", "onMessage")); /* Allowed */ - GREATEST_ASSERT(irc_rule_matchlist(irc.rules, irc.rulesz, "freenode", "#staff", "", "b", "onTopic")); + GREATEST_ASSERT(irc_rule_matchlist(&irc.rules, "freenode", "#staff", "", "b", "onTopic")); /* Not allowed */ - GREATEST_ASSERT(!irc_rule_matchlist(irc.rules, irc.rulesz, "malikania", "#staff", "", "", "onCommand")); + GREATEST_ASSERT(!irc_rule_matchlist(&irc.rules, "malikania", "#staff", "", "", "onCommand")); /* Not allowed */ - GREATEST_ASSERT(!irc_rule_matchlist(irc.rules, irc.rulesz, "freenode", "#staff", "", "c", "onCommand")); + GREATEST_ASSERT(!irc_rule_matchlist(&irc.rules, "freenode", "#staff", "", "c", "onCommand")); /* Allowed */ - GREATEST_ASSERT(irc_rule_matchlist(irc.rules, irc.rulesz, "unsafe", "#staff", "", "c", "onCommand")); + GREATEST_ASSERT(irc_rule_matchlist(&irc.rules, "unsafe", "#staff", "", "c", "onCommand")); GREATEST_PASS(); } @@ -260,29 +270,29 @@ solve_match8(void) { /* Allowed */ - GREATEST_ASSERT(irc_rule_matchlist(irc.rules, irc.rulesz, "malikania", "#games", "", "game", "onMessage")); + GREATEST_ASSERT(irc_rule_matchlist(&irc.rules, "malikania", "#games", "", "game", "onMessage")); /* Allowed */ - GREATEST_ASSERT(irc_rule_matchlist(irc.rules, irc.rulesz, "localhost", "#games", "", "game", "onMessage")); + GREATEST_ASSERT(irc_rule_matchlist(&irc.rules, "localhost", "#games", "", "game", "onMessage")); /* Allowed */ - GREATEST_ASSERT(irc_rule_matchlist(irc.rules, irc.rulesz, "malikania", "#games", "", "game", "onCommand")); + GREATEST_ASSERT(irc_rule_matchlist(&irc.rules, "malikania", "#games", "", "game", "onCommand")); /* Not allowed */ - GREATEST_ASSERT(!irc_rule_matchlist(irc.rules, irc.rulesz, "malikania", "#games", "", "game", "onQuery")); + GREATEST_ASSERT(!irc_rule_matchlist(&irc.rules, "malikania", "#games", "", "game", "onQuery")); /* Not allowed */ - GREATEST_ASSERT(!irc_rule_matchlist(irc.rules, irc.rulesz, "freenode", "#no", "", "game", "onMessage")); + GREATEST_ASSERT(!irc_rule_matchlist(&irc.rules, "freenode", "#no", "", "game", "onMessage")); /* Not allowed */ - GREATEST_ASSERT(!irc_rule_matchlist(irc.rules, irc.rulesz, "malikania", "#test", "", "game", "onMessage")); + GREATEST_ASSERT(!irc_rule_matchlist(&irc.rules, "malikania", "#test", "", "game", "onMessage")); GREATEST_PASS(); } GREATEST_TEST solve_match9(void) { - GREATEST_ASSERT(!irc_rule_matchlist(irc.rules, irc.rulesz, "MALIKANIA", "#STAFF", "", "SYSTEM", "onCommand")); + GREATEST_ASSERT(!irc_rule_matchlist(&irc.rules, "MALIKANIA", "#STAFF", "", "SYSTEM", "onCommand")); GREATEST_PASS(); }