aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/kike.c72
1 files changed, 55 insertions, 17 deletions
diff --git a/src/kike.c b/src/kike.c
index 3435f6e..d3415e7 100644
--- a/src/kike.c
+++ b/src/kike.c
@@ -735,6 +735,26 @@ client_in_mask_list (const struct client *c, const struct str_vector *mask)
return result;
}
+static void
+irc_initiate_quit (struct server_context *ctx)
+{
+ print_status ("shutting down");
+
+ for (struct client *iter = ctx->clients; iter; iter = iter->next)
+ if (!iter->closing_link)
+ irc_close_link (iter, "Shutting down");
+
+ ssize_t i = poller_find_by_fd (&ctx->poller, ctx->listen_fd);
+ if (soft_assert (i != -1))
+ poller_remove_at_index (&ctx->poller, i);
+ if (ctx->listen_fd != -1)
+ xclose (ctx->listen_fd);
+ ctx->listen_fd = -1;
+
+ ctx->quitting = true;
+ irc_try_finish_quit (ctx);
+}
+
// --- Timers ------------------------------------------------------------------
static void
@@ -864,6 +884,7 @@ enum
IRC_ERR_BANNEDFROMCHAN = 474,
IRC_ERR_BADCHANNELKEY = 475,
IRC_ERR_BADCHANMASK = 476,
+ IRC_ERR_NOPRIVILEGES = 481,
IRC_ERR_CHANOPRIVSNEEDED = 482,
IRC_ERR_USERSDONTMATCH = 502
@@ -939,6 +960,7 @@ static const char *g_default_replies[] =
[IRC_ERR_BANNEDFROMCHAN] = "%s :Cannot join channel (+b)",
[IRC_ERR_BADCHANNELKEY] = "%s :Cannot join channel (+k)",
[IRC_ERR_BADCHANMASK] = "%s :Bad Channel Mask",
+ [IRC_ERR_NOPRIVILEGES] = ":Permission Denied- You're not an IRC operator",
[IRC_ERR_CHANOPRIVSNEEDED] = "%s :You're not channel operator",
[IRC_ERR_USERSDONTMATCH] = ":Cannot change mode for other users",
@@ -1958,6 +1980,34 @@ irc_handle_ison (const struct irc_message *msg, struct client *c)
str_free (&result);
}
+static void
+irc_handle_kill (const struct irc_message *msg, struct client *c)
+{
+ if (msg->params.len < 2)
+ RETURN_WITH_REPLY (c, IRC_ERR_NEEDMOREPARAMS, msg->command);
+ if (!(c->mode & IRC_USER_MODE_OPERATOR))
+ RETURN_WITH_REPLY (c, IRC_ERR_NOPRIVILEGES);
+
+ struct client *target;
+ if (!(target = str_map_find (&c->ctx->users, msg->params.vector[0])))
+ RETURN_WITH_REPLY (c, IRC_ERR_NOSUCHNICK, msg->params.vector[0]);
+ char *reason = xstrdup_printf ("Killed by %s: %s",
+ c->nickname, msg->params.vector[1]);
+ irc_close_link (target, reason);
+ free (reason);
+}
+
+static void
+irc_handle_die (const struct irc_message *msg, struct client *c)
+{
+ (void) msg;
+
+ if (!(c->mode & IRC_USER_MODE_OPERATOR))
+ RETURN_WITH_REPLY (c, IRC_ERR_NOPRIVILEGES);
+ if (!c->ctx->quitting)
+ irc_initiate_quit (c->ctx);
+}
+
// -----------------------------------------------------------------------------
struct irc_command
@@ -1972,6 +2022,7 @@ irc_register_handlers (struct server_context *ctx)
{
// TODO: add an index for IRC_ERR_NOSUCHSERVER validation?
// TODO: add a minimal parameter count?
+ // TODO: add a field for oper-only commands?
static const struct irc_command message_handlers[] =
{
{ "PASS", false, irc_handle_pass },
@@ -2002,6 +2053,9 @@ irc_register_handlers (struct server_context *ctx)
{ "WHO", true, irc_handle_who },
{ "WHOIS", true, irc_handle_whois },
{ "ISON", true, irc_handle_ison },
+
+ { "KILL", true, irc_handle_kill },
+ { "DIE", true, irc_handle_die },
};
for (size_t i = 0; i < N_ELEMENTS (message_handlers); i++)
@@ -2639,23 +2693,7 @@ on_signal_pipe_readable (const struct pollfd *fd, struct server_context *ctx)
(void) read (fd->fd, &dummy, 1);
if (g_termination_requested && !ctx->quitting)
- {
- print_status ("shutting down");
-
- for (struct client *iter = ctx->clients; iter; iter = iter->next)
- if (!iter->closing_link)
- irc_close_link (iter, "Shutting down");
-
- ssize_t i = poller_find_by_fd (&ctx->poller, ctx->listen_fd);
- if (soft_assert (i != -1))
- poller_remove_at_index (&ctx->poller, i);
- if (ctx->listen_fd != -1)
- xclose (ctx->listen_fd);
- ctx->listen_fd = -1;
-
- ctx->quitting = true;
- irc_try_finish_quit (ctx);
- }
+ irc_initiate_quit (ctx);
}
static void