degesch: reply to some CTCPs

This commit is contained in:
Přemysl Eric Janouch 2015-04-27 01:36:33 +02:00
parent 5ad6d7cfbc
commit 2f6974c7ca
1 changed files with 59 additions and 8 deletions

View File

@ -48,6 +48,7 @@
#include <langinfo.h>
#include <locale.h>
#include <pwd.h>
#include <sys/utsname.h>
#include <curses.h>
#include <term.h>
@ -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 <recipient>: <whatever>
// 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;
}