From 2f6974c7caa98ce36dc593325484504aa45f558d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Mon, 27 Apr 2015 01:36:33 +0200 Subject: [PATCH] degesch: reply to some CTCPs --- degesch.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 8 deletions(-) diff --git a/degesch.c b/degesch.c index 0dee7ac..05b22ba 100644 --- a/degesch.c +++ b/degesch.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -125,6 +126,12 @@ toupper_ascii (int c) return false; \ BLOCK_END +// A few other debugging shorthands +#define LOG_FUNC_FAILURE(name, desc) \ + print_debug ("%s: %s: %s", __func__, (name), (desc)) +#define LOG_LIBC_FAILURE(name) \ + print_debug ("%s: %s: %s", __func__, (name), strerror (errno)) + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // We need a few reference countable objects with support @@ -1841,14 +1848,14 @@ irc_send (struct app_context *ctx, const char *format, ...) // TODO: call SSL_get_error() to detect if a clean shutdown has occured if (SSL_write (ctx->ssl, str.str, str.len) != (int) str.len) { - print_debug ("%s: %s: %s", __func__, "SSL_write", + LOG_FUNC_FAILURE ("SSL_write", ERR_error_string (ERR_get_error (), NULL)); result = false; } } else if (write (ctx->irc_fd, str.str, str.len) != (ssize_t) str.len) { - print_debug ("%s: %s: %s", __func__, "write", strerror (errno)); + LOG_LIBC_FAILURE ("write"); result = false; } @@ -2017,7 +2024,7 @@ irc_establish_connection (struct app_context *ctx, err = getnameinfo (gai_iter->ai_addr, gai_iter->ai_addrlen, buf, sizeof buf, NULL, 0, NI_NUMERICHOST); if (err) - print_debug ("%s: %s", "getnameinfo", gai_strerror (err)); + LOG_FUNC_FAILURE ("getnameinfo", gai_strerror (err)); else real_host = buf; @@ -2636,21 +2643,65 @@ irc_handle_ping (struct app_context *ctx, const struct irc_message *msg) irc_send (ctx, "PONG"); } +static char * +ctime_now (char buf[26]) +{ + struct tm tm_; + time_t now = time (NULL); + if (!asctime_r (localtime_r (&now, &tm_), buf)) + return NULL; + + // Annoying thing + *strchr (buf, '\n') = '\0'; + return buf; +} + static void irc_handle_ctcp_request (struct app_context *ctx, const struct irc_message *msg, struct ctcp_chunk *chunk) { char *nickname = irc_cut_nickname (msg->prefix); char *nickname_utf8 = irc_to_utf8 (ctx, nickname); - free (nickname); char *tag_utf8 = irc_to_utf8 (ctx, chunk->tag.str); buffer_send_status (ctx, ctx->server_buffer, "CTCP requested by %s: %s", nickname_utf8, tag_utf8); - // TODO: reply to other CTCPs; - // see http://www.irchelp.org/irchelp/rfc/ctcpspec.html + const char *target = msg->params.vector[0]; + const char *recipient = nickname; + if (irc_is_channel (ctx, target)) + recipient = target; + // TODO: log a "CTCP reply to : + // Probably abstract the irc_send call to something like + // irc_send_ctcp_reply (ctx, recipient, fmt, ...) + + if (!strcmp (chunk->tag.str, "CLIENTINFO")) + irc_send (ctx, "NOTICE %s :\x01" "CLIENTINFO %s %s %s %s\x01", + recipient, "PING", "VERSION", "TIME", "CLIENTINFO"); + else if (!strcmp (chunk->tag.str, "PING")) + irc_send (ctx, "NOTICE %s :\x01" "PING %s\x01", + recipient, chunk->text.str); + else if (!strcmp (chunk->tag.str, "VERSION")) + { + struct utsname info; + if (uname (&info)) + LOG_LIBC_FAILURE ("uname"); + else + irc_send (ctx, "NOTICE %s :\x01" "VERSION %s %s on %s %s\x01", + recipient, PROGRAM_NAME, PROGRAM_VERSION, + info.sysname, info.machine); + } + else if (!strcmp (chunk->tag.str, "TIME")) + { + char buf[26]; + if (!ctime_now (buf)) + LOG_LIBC_FAILURE ("asctime_r"); + else + irc_send (ctx, "NOTICE %s :\x01" "TIME %s\x01", recipient, buf); + } + + free (nickname); free (nickname_utf8); free (tag_utf8); } @@ -3718,7 +3769,7 @@ start: case XSSL_ERROR_TRY_AGAIN: goto start; default: - print_debug ("%s: %s: %s", __func__, "SSL_read", error_info); + LOG_FUNC_FAILURE ("SSL_read", error_info); return IRC_READ_ERROR; } } @@ -3744,7 +3795,7 @@ start: if (errno == EINTR) goto start; - print_debug ("%s: %s: %s", __func__, "recv", strerror (errno)); + LOG_LIBC_FAILURE ("recv"); return IRC_READ_ERROR; }