From 35589a562473e6eab83933e498fbecf5540431d6 Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Sat, 4 Aug 2018 17:54:46 -0400 Subject: Rename client to irc --- Makefile | 2 +- chat.c | 4 +- chat.h | 8 ++-- client.c | 129 --------------------------------------------------------------- handle.c | 6 +-- input.c | 10 ++--- irc.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 144 insertions(+), 144 deletions(-) delete mode 100644 client.c create mode 100644 irc.c diff --git a/Makefile b/Makefile index d707ee3..26c70a1 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CFLAGS += -Wall -Wextra -Wpedantic CFLAGS += -I/usr/local/include LDFLAGS += -L/usr/local/lib LDLIBS = -lcursesw -ltls -OBJS = chat.o client.o handle.o input.o ui.o +OBJS = chat.o handle.o input.o irc.o ui.o all: tags chat diff --git a/chat.c b/chat.c index ab0d4d7..f52bc3a 100644 --- a/chat.c +++ b/chat.c @@ -71,7 +71,7 @@ int main(int argc, char *argv[]) { uiChat("Traveling..."); uiDraw(); - int sock = clientConnect(host, port, webPass); + int sock = ircConnect(host, port, webPass); free(host); struct pollfd fds[2] = { @@ -87,7 +87,7 @@ int main(int argc, char *argv[]) { } if (fds[0].revents) uiRead(); - if (fds[1].revents) clientRead(); + if (fds[1].revents) ircRead(); uiDraw(); } } diff --git a/chat.h b/chat.h index 4c1cff4..04e3c6b 100644 --- a/chat.h +++ b/chat.h @@ -28,12 +28,12 @@ struct { char *chan; } chat; -int clientConnect(const char *host, const char *port, const char *webPass); -void clientRead(void); -void clientWrite(const char *ptr, size_t len); +int ircConnect(const char *host, const char *port, const char *webPass); +void ircRead(void); +void ircWrite(const char *ptr, size_t len); __attribute__((format(printf, 1, 2))) -void clientFmt(const char *format, ...); +void ircFmt(const char *format, ...); void uiInit(void); void uiHide(void); diff --git a/client.c b/client.c deleted file mode 100644 index 64f14cf..0000000 --- a/client.c +++ /dev/null @@ -1,129 +0,0 @@ -/* Copyright (C) 2018 Curtis McEnroe - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "chat.h" - -static struct tls *client; - -static void webirc(const char *pass) { - const char *ssh = getenv("SSH_CLIENT"); - if (!ssh) return; - int len = strlen(ssh); - const char *sp = strchr(ssh, ' '); - if (sp) len = sp - ssh; - clientFmt( - "WEBIRC %s %s %.*s %.*s\r\n", - pass, chat.user, len, ssh, len, ssh - ); -} - -int clientConnect(const char *host, const char *port, const char *webPass) { - int error; - - struct tls_config *config = tls_config_new(); - error = tls_config_set_ciphers(config, "compat"); - if (error) errx(EX_SOFTWARE, "tls_config: %s", tls_config_error(config)); - - client = tls_client(); - if (!client) errx(EX_SOFTWARE, "tls_client"); - - error = tls_configure(client, config); - if (error) errx(EX_SOFTWARE, "tls_configure"); - tls_config_free(config); - - struct addrinfo *ai; - struct addrinfo hints = { - .ai_family = AF_UNSPEC, - .ai_socktype = SOCK_STREAM, - .ai_protocol = IPPROTO_TCP, - }; - error = getaddrinfo(host, port, &hints, &ai); - if (error) errx(EX_NOHOST, "getaddrinfo: %s", gai_strerror(error)); - - int sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (sock < 0) err(EX_OSERR, "socket"); - - error = connect(sock, ai->ai_addr, ai->ai_addrlen); - if (error) err(EX_UNAVAILABLE, "connect"); - freeaddrinfo(ai); - - error = tls_connect_socket(client, sock, host); - if (error) err(EX_PROTOCOL, "tls_connect"); - - if (webPass) webirc(webPass); - clientFmt("NICK %s\r\n", chat.nick); - clientFmt("USER %s 0 * :%s\r\n", chat.user, chat.nick); - - return sock; -} - -void clientWrite(const char *ptr, size_t len) { - while (len) { - ssize_t ret = tls_write(client, ptr, len); - if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) continue; - if (ret < 0) errx(EX_IOERR, "tls_write: %s", tls_error(client)); - ptr += ret; - len -= ret; - } -} - -void clientFmt(const char *format, ...) { - char *buf; - va_list ap; - va_start(ap, format); - int len = vasprintf(&buf, format, ap); - va_end(ap); - if (!buf) err(EX_OSERR, "vasprintf"); - if (chat.verbose) uiFmt("<<< %.*s", len - 2, buf); - clientWrite(buf, len); - free(buf); -} - -void clientRead(void) { - static char buf[4096]; - static size_t len; - - ssize_t read = tls_read(client, &buf[len], sizeof(buf) - len); - if (read < 0) errx(EX_IOERR, "tls_read: %s", tls_error(client)); - if (!read) { - uiHide(); - exit(EX_OK); - } - len += read; - - char *crlf, *line = buf; - while ((crlf = strnstr(line, "\r\n", &buf[len] - line))) { - crlf[0] = '\0'; - if (chat.verbose) uiFmt(">>> %s", line); - handle(line); - line = &crlf[2]; - } - - len -= line - buf; - memmove(buf, line, len); -} diff --git a/handle.c b/handle.c index ba3cb00..7bbf3e7 100644 --- a/handle.c +++ b/handle.c @@ -50,7 +50,7 @@ static char *shift(char **params) { static void handlePing(char *prefix, char *params) { (void)prefix; - clientFmt("PONG %s\r\n", params); + ircFmt("PONG %s\r\n", params); } static void handle432(char *prefix, char *params) { @@ -70,7 +70,7 @@ static void handle001(char *prefix, char *params) { free(chat.nick); chat.nick = strdup(nick); } - clientFmt("JOIN %s\r\n", chat.chan); + ircFmt("JOIN %s\r\n", chat.chan); } static void handleJoin(char *prefix, char *params) { @@ -149,7 +149,7 @@ static void handle366(char *prefix, char *params) { (void)prefix; shift(¶ms); char *chan = shift(¶ms); - clientFmt("WHO %s\r\n", chan); + ircFmt("WHO %s\r\n", chan); } static char whoBuf[4096]; diff --git a/input.c b/input.c index 12f214e..53957ec 100644 --- a/input.c +++ b/input.c @@ -44,7 +44,7 @@ static void privmsg(bool action, const wchar_t *mesg) { (action ? "\1ACTION " : ""), mesg, (action ? "\1" : "") ); if (!line) err(EX_OSERR, "asprintf"); - clientFmt("%s\r\n", &line[send]); + ircFmt("%s\r\n", &line[send]); handle(line); free(line); } @@ -58,7 +58,7 @@ static void inputMe(wchar_t *params) { static void inputNick(wchar_t *params) { wchar_t *nick = wcssep(¶ms, L" "); if (nick) { - clientFmt("NICK %ls\r\n", nick); + ircFmt("NICK %ls\r\n", nick); } else { uiChat("/nick requires a name"); } @@ -66,14 +66,14 @@ static void inputNick(wchar_t *params) { static void inputWho(wchar_t *params) { (void)params; - clientFmt("WHO %s\r\n", chat.chan); + ircFmt("WHO %s\r\n", chat.chan); } static void inputQuit(wchar_t *params) { if (params) { - clientFmt("QUIT :%ls\r\n", params); + ircFmt("QUIT :%ls\r\n", params); } else { - clientFmt("QUIT :Goodbye\r\n"); + ircFmt("QUIT :Goodbye\r\n"); } } diff --git a/irc.c b/irc.c new file mode 100644 index 0000000..02a9f64 --- /dev/null +++ b/irc.c @@ -0,0 +1,129 @@ +/* Copyright (C) 2018 Curtis McEnroe + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chat.h" + +static struct tls *client; + +static void webirc(const char *pass) { + const char *ssh = getenv("SSH_CLIENT"); + if (!ssh) return; + int len = strlen(ssh); + const char *sp = strchr(ssh, ' '); + if (sp) len = sp - ssh; + ircFmt( + "WEBIRC %s %s %.*s %.*s\r\n", + pass, chat.user, len, ssh, len, ssh + ); +} + +int ircConnect(const char *host, const char *port, const char *webPass) { + int error; + + struct tls_config *config = tls_config_new(); + error = tls_config_set_ciphers(config, "compat"); + if (error) errx(EX_SOFTWARE, "tls_config: %s", tls_config_error(config)); + + client = tls_client(); + if (!client) errx(EX_SOFTWARE, "tls_client"); + + error = tls_configure(client, config); + if (error) errx(EX_SOFTWARE, "tls_configure"); + tls_config_free(config); + + struct addrinfo *ai; + struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + .ai_protocol = IPPROTO_TCP, + }; + error = getaddrinfo(host, port, &hints, &ai); + if (error) errx(EX_NOHOST, "getaddrinfo: %s", gai_strerror(error)); + + int sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (sock < 0) err(EX_OSERR, "socket"); + + error = connect(sock, ai->ai_addr, ai->ai_addrlen); + if (error) err(EX_UNAVAILABLE, "connect"); + freeaddrinfo(ai); + + error = tls_connect_socket(client, sock, host); + if (error) err(EX_PROTOCOL, "tls_connect"); + + if (webPass) webirc(webPass); + ircFmt("NICK %s\r\n", chat.nick); + ircFmt("USER %s 0 * :%s\r\n", chat.user, chat.nick); + + return sock; +} + +void ircWrite(const char *ptr, size_t len) { + while (len) { + ssize_t ret = tls_write(client, ptr, len); + if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) continue; + if (ret < 0) errx(EX_IOERR, "tls_write: %s", tls_error(client)); + ptr += ret; + len -= ret; + } +} + +void ircFmt(const char *format, ...) { + char *buf; + va_list ap; + va_start(ap, format); + int len = vasprintf(&buf, format, ap); + va_end(ap); + if (!buf) err(EX_OSERR, "vasprintf"); + if (chat.verbose) uiFmt("<<< %.*s", len - 2, buf); + ircWrite(buf, len); + free(buf); +} + +static char buf[4096]; +static size_t len; + +void ircRead(void) { + ssize_t read = tls_read(client, &buf[len], sizeof(buf) - len); + if (read < 0) errx(EX_IOERR, "tls_read: %s", tls_error(client)); + if (!read) { + uiHide(); + exit(EX_OK); + } + len += read; + + char *crlf, *line = buf; + while ((crlf = strnstr(line, "\r\n", &buf[len] - line))) { + crlf[0] = '\0'; + if (chat.verbose) uiFmt(">>> %s", line); + handle(line); + line = &crlf[2]; + } + + len -= line - buf; + memmove(buf, line, len); +} -- cgit 1.4.1