/* * Copyright (c) 2026 Nakidai Perumenei * * Permission to use, copy, modify, and 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 "ircd.h" #include #include #include #define ensure(cond, iffalse, doexit) if (!(cond)) { iffalse; if (doexit >= 0) return doexit; } static int nick(struct Message *msg, struct Peer *peer) { ensure(msg->params[0] && msg->params[0], writef( peer->fd, ":%s 431 %s :No nickname given", hostname, getnick(peer) ), 0); user_reg(peer, msg->params[0], NULL, NULL); return 0; } static int privmsg(struct Message *msg, struct Peer *peer) { size_t i; ensure(peer->type, writef( peer->fd, ":%s 451 %s :You have not registered", hostname, getnick(peer) ), 0); ensure(msg->params[0] && *msg->params[0], writef( peer->fd, ":%s 411 %s :No recipient given (PRIVMSG)", hostname, getnick(peer) ), 0); ensure(msg->params[1] && *msg->params[1], writef( peer->fd, ":%s 412 %s :No text to send", hostname, getnick(peer) ), 0); /* TODO: implement channels */ ensure(!strchr("!+#&", *msg->params[0]), writef( peer->fd, ":%s 421 %s :Channels are not supported yet", hostname, getnick(peer) ), 0); /* TODO: implement server-to-server communication */ for (i = 0; i < PEERS_MAX; ++i) if (peers[i].type == CLIENT && !strcmp(peers[i].nick, msg->params[0])) writef( peers[i].fd, ":%s!%s@%s PRIVMSG %s :%s", peer->nick, peer->user, peer->host, peer->nick, msg->params[1] ); return 0; } static int quit(struct Message *msg, struct Peer *peer) { return 1; } static int user(struct Message *msg, struct Peer *peer) { size_t i; ensure(!peer->type, writef( peer->fd, ":%s 462 %s :Unauthorized command (already registered)", hostname, getnick(peer) ), 0); for (i = 0; i < 4; ++i) ensure(msg->params[i] && *msg->params[i], writef( peer->fd, ":%s 461 %s %s :Not enough parameters", hostname, getnick(peer), msg->command ), 0); user_reg(peer, NULL, msg->params[0], msg->params[3]); return 0; } static int default_handler(struct Message *msg, struct Peer *peer) { ensure(peer->type, 0, 0); writef(peer->fd, ":%s 421 %s %s :Unknown command", hostname, getnick(peer), msg->command); return 0; } static struct Handler { const char *name; Handler *handler; } handlers[] = { { "nick", nick }, { "privmsg", privmsg }, { "quit", quit }, { "user", user }, }; Handler * find(const char *command) { struct Handler *l, *m, *r; int res; l = handlers; r = handlers + lengthof(handlers) - 1; while (l <= r) { m = l + (r - l) / 2; res = strcmp(command, m->name); if (res > 0) l = ++m; else if (res < 0) r = --m; else return m->handler; } return default_handler; }