Mercurial > irccd
view irccd/main.c @ 974:342fb90f2512
irccdctl: re-implement many of the plugin-* commands
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sun, 07 Feb 2021 14:36:28 +0100 |
parents | dfbdab8ea485 |
children | 8f8ce47aba8a |
line wrap: on
line source
/* * main.c -- irccd(1) main file * * 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. */ #include <config.h> #include <compat.h> #include <err.h> #include <errno.h> #include <poll.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <irccd/irccd.h> #include <irccd/log.h> #include <irccd/server.h> #include <irccd/transport.h> #include <irccd/util.h> #include <irccd/plugin.h> #include <irccd/rule.h> #include "dl-plugin.h" #include "js-plugin.h" #include "peer.h" struct pollables { struct pollfd *fds; size_t fdsz; size_t botsz; size_t localsz; }; static const char *config = IRCCD_SYSCONFDIR "/irccd.conf"; static struct peers peers = LIST_HEAD_INITIALIZER(); static int running = 1; /* conf.y */ void config_open(const char *); static void broadcast(const struct irc_event *ev) { char buf[IRC_BUF_LEN]; struct peer *p; if (!irc_event_str(ev, buf, sizeof (buf))) return; LIST_FOREACH(p, &peers, link) if (p->is_watching) peer_send(p, buf); } static inline size_t poll_count(void) { struct peer *p; size_t i = 1; LIST_FOREACH(p, &peers, link) ++i; return i; } static int run(int argc, char **argv) { (void)argc; if (strcmp(argv[0], "version") == 0) puts(IRCCD_VERSION); return 0; } static inline void init(void) { irc_bot_init(); irc_bot_plugin_loader_add(dl_plugin_loader_new()); #if defined(IRCCD_WITH_JS) irc_bot_plugin_loader_add(js_plugin_loader_new()); #endif } static void prepare(struct pollables *pb) { struct peer *p; struct pollfd *fd = pb->fds + pb->botsz; irc_bot_prepare(pb->fds); transport_prepare(fd++); LIST_FOREACH(p, &peers, link) peer_prepare(p, fd++); } static void flush(const struct pollables *pb) { struct peer *peer, *tmp; struct pollfd *fd = pb->fds + pb->botsz + 1; irc_bot_flush(pb->fds); LIST_FOREACH_SAFE(peer, &peers, link, tmp) { if (peer_flush(peer, fd++) < 0) { LIST_REMOVE(peer, link); peer_finish(peer); } } /* * Add a new client only now because we would iterate over a list * of pollfd that is smaller than the client list. */ if ((peer = transport_flush(pb->fds + pb->botsz))) LIST_INSERT_HEAD(&peers, peer, link); } static inline void load(void) { config_open(config); } static struct pollables pollables(void) { struct pollables pb = {0}; pb.botsz = irc_bot_poll_count(); pb.localsz = poll_count(); pb.fdsz = pb.botsz + pb.localsz; pb.fds = irc_util_calloc(pb.fdsz, sizeof (*pb.fds)); prepare(&pb); return pb; } static void loop(void) { struct pollables pb; struct irc_event ev; while (running) { pb = pollables(); if (poll(pb.fds, pb.fdsz, 1000) < 0 && errno != EINTR) err(1, "poll"); flush(&pb); while (irc_bot_dequeue(&ev)) { broadcast(&ev); irc_event_finish(&ev); } free(pb.fds); } } static inline void finish(void) { struct peer *peer, *tmp; LIST_FOREACH_SAFE(peer, &peers, link, tmp) peer_finish(peer); transport_finish(); irc_bot_finish(); } static void usage(void) { fprintf(stderr, "usage: %s [-c config]\n", getprogname()); exit(1); } int main(int argc, char **argv) { int ch; setprogname("irccd"); while ((ch = getopt(argc, argv, "c:")) != -1) { switch (ch) { case 'c': config = optarg; break; default: usage(); break; /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc > 0) return run(argc, argv); init(); load(); loop(); finish(); }