diff options
-rw-r--r-- | Makefile | 12 | ||||
-rw-r--r-- | bee.c | 107 | ||||
-rw-r--r-- | conf.c | 11 | ||||
-rw-r--r-- | conf.h | 7 | ||||
-rw-r--r-- | irc.c | 18 | ||||
-rw-r--r-- | irc.h | 7 | ||||
-rw-r--r-- | unix.c | 51 | ||||
-rw-r--r-- | unix.h | 5 | ||||
-rw-r--r-- | util.c | 1 | ||||
-rw-r--r-- | util.h | 1 |
10 files changed, 128 insertions, 92 deletions
@@ -5,7 +5,7 @@ CC=cc debug=-g -DDEBUG -DLOCAL CFLAGS=$(MORE_CFLAGS) -Wall -Wpedantic -OBJS=bee.o irc.o util.o unix.o conf.o +OBJS=bee.o irc.o util.o unix.o all: apiobot apiobot: $(OBJS) @@ -19,12 +19,12 @@ local: .c.o: $(CC) $(CFLAGS) -c $< -o $@ -apiosend.o: apiosend.c -bee.o: bee.c irc.h unix.h -conf.o: conf.c conf.h +bee.o: bee.c irc.h unix.h conf.h debug.h irc.o: irc.c irc.h debug.h conf.h util.h -unix.o: unix.c unix.h conf.h -util.o: util.c util.h conf.h debug.h +thing.o: thing.c conf.h +unix.o: unix.c unix.h conf.h irc.h +util.o: util.c util.h debug.h conf.h + run: all ./apiobot @@ -1,59 +1,21 @@ #include "irc.h" #include "unix.h" +#include "conf.h" +#include "debug.h" #include <stdio.h> #include <poll.h> +#include <stdlib.h> -int -unix_handle(int fd, char chname[]) -{ - // PRIVMSG #{chname} :{message}<CR><LF> - // 123456789 12 3 4 - // 512 >= 13 + strlen(chname) + length of message - // chname can be max 16 bytes, so worst case - // 512 >= 13 + 16 + length of message - // 483 >= length of message - // 480 is slightly pessimistic but it's a rounder number. - // (one more byte for null terminator needed by snprintf) - unsigned char buf[481]; - - if (strlen(chname) > 16) { - fprintf(stderr,"channel name %s is longer than 16 bytes, ignoring\n",chname); +static int +socket_fname(char chname[], char out[], size_t lim) { + if (strlen(chname) > 16) return -1; + if (snprintf(out, lim, SOCKETDIR"/%s.sock", chname) >= lim) { return -1; } - - ssize_t amt; - if ((amt = recv(fd, buf, sizeof buf-1,0)) == -1) { - perror("recv"); - return -1; - } else if (amt == 0) { - fputs("unix eof\n",stderr); - return -1; - } else { - int i; - for (i=0;i<amt;i++) { - if (buf[i] < ' ') { - buf[i] = ' '; - } - } - buf[amt] = '\0'; - char msg[512]; - int s; - if ((s=snprintf(msg,512,"PRIVMSG #%s :%s\r\n",chname,buf)) > 512) { - fprintf(stderr,"irc message was somehow too long (this should never happen) (%d)/512\n",s); - return -1; - } - if (irc_sendall(msg, s) == -1) { - perror("sendall"); - return -1; - }; - - return 0; - } + return 0; } - - int main() { @@ -65,31 +27,40 @@ main() fputs("failure in unix_setup\n",stderr); return -1; } - struct pollfd pfs[2]; + // pfs[0] is the irc socket + // pfs[k>=1] is the unix socket that should send to channel g_chanlist[k-1] + struct pollfd *pfs = malloc((1 + g_nchannels) * sizeof(struct pollfd)); pfs[0].fd = g_ircsock; pfs[0].events = POLLIN; - pfs[1].fd = unixfd; - pfs[1].events = POLLIN; - for (;;) { - if (poll(pfs, 2, -1) == -1) { - perror("poll"); + char fname[100]; + for (int i = 0; i<g_nchannels; i++) { + // construct filename for listening socket + if (socket_fname(g_chanlist[i], fname, sizeof fname) == -1) { + fprintf(stderr,"failed to generate socket filename for channel %s\n",g_chanlist[i]); return 1; } - if (pfs[0].revents & POLLERR) { - fputs("irc socket error\n",stderr); - return 1; + int fd; + if ((fd = unix_setup(fname)) == -1) { + fputs("failure in unix_setup\n",stderr); + return -1; } - if (pfs[0].revents & POLLHUP) { - fputs("irc hup\n",stderr); + pfs[i+1].fd = fd; + pfs[i+1].events = POLLIN; + } + + for (;;) { + if (poll(pfs, g_nchannels+1, -1) == -1) { + perror("poll"); return 1; } - if (pfs[1].revents & POLLERR) { - fputs("unix sock err\n",stderr); + + // irc + if (pfs[0].revents & (POLLERR|POLLHUP)) { + fputs("irc socket error\n",stderr); return 1; } - if (pfs[0].revents & POLLIN) { int r = irc_recv(); if (r == -2) { @@ -102,12 +73,20 @@ main() return 1; } } - if (pfs[1].revents & POLLIN) { - int r = unix_handle(unixfd,"a"); - if (r==-1) { - fputs("exiting due to unix sock error\n",stderr); + + // unixes + for (int i = 0; i < g_nchannels; i++) { + struct pollfd *p = &pfs[i+1]; + if (p->revents & (POLLERR|POLLHUP)) { + fputs("unix socket error\n",stderr); return 1; } + if (p->revents & POLLIN) { + if (unix_handle(p->fd,g_chanlist[i]) == -1) { + fputs("unix_handle failure\n",stderr); + return 1; + } + } } } @@ -1,11 +0,0 @@ -#include "conf.h" - -#include <stddef.h> - -char *CHANNELS[] = { - "a", - "b", - "jonathan", - "secret-channel", - NULL, -}; @@ -4,12 +4,12 @@ #ifdef LOCAL #define HOST "0.0.0.0" #define PORT "6971" - #define SOCKETNAME "bees.sock" + #define SOCKETDIR "socks" #define SOCKETGROUP "cdrom" #else #define HOST "ubq323.website" #define PORT "6667" - #define SOCKETNAME "/srv/apiobot/bees.sock" + #define SOCKETDIR "socks" #define SOCKETGROUP "apionet" #endif @@ -18,8 +18,5 @@ #define USERNAME "apiobot" #define REALNAME "apiobot" -// defined in conf.c -extern char *CHANNELS[]; - #endif // conf_h_INCLUDED @@ -6,6 +6,16 @@ int g_ircsock = -1; +char *g_chanlist[] = { + "a", + "b", + "g", + "cg", + "secret-channel", +}; +const int g_nchannels = sizeof(g_chanlist)/sizeof(g_chanlist[0]); + + int irc_connect() { @@ -53,13 +63,13 @@ irc_handshake() #define E(x) do { if (x==-1) { perror("irc_sendall"); return -1; } } while(0) char msg1[] = "NICK "NICK"\r\nUSER "USERNAME" 0 * :"REALNAME"\r\n"; E(irc_sendall(msg1, sizeof msg1-1)); - for (int i = 0; CHANNELS[i] != NULL; i++) { - if (strlen(CHANNELS[i]) > 16) { - fprintf(stderr,"channel name too long (%s)\n",CHANNELS[i]); + for (int i = 0; i<g_nchannels; i++) { + if (strlen(g_chanlist[i]) > 16) { + fprintf(stderr,"channel name too long (%s)\n",g_chanlist[i]); return -1; } E(irc_sendall("JOIN #",6)); - E(irc_sendall(CHANNELS[i],strlen(CHANNELS[i]))); + E(irc_sendall(g_chanlist[i],strlen(g_chanlist[i]))); E(irc_sendall("\r\n",2)); } #undef E @@ -10,8 +10,15 @@ #define IRC_RECVBUF_SIZE 1024 +// fd of the irc connection socket extern int g_ircsock; +// list of channels to join +extern char *g_chanlist[]; +// length of the above +extern const int g_nchannels; + + // connects to the irc server, as defined in config.h // returns -1 on failure. int irc_connect(); @@ -1,6 +1,7 @@ #include "unix.h" #include "conf.h" +#include "irc.h" static int sock_perms(char fname[]) @@ -60,5 +61,53 @@ unix_setup(char filename[]) return sock; } - +// reads a message from the fd in question, and sends it to irc +int +unix_handle(int fd, char chname[]) +{ + // PRIVMSG #{chname} :{message}<CR><LF> + // 123456789 12 3 4 + // 512 >= 13 + strlen(chname) + length of message + // chname can be max 16 bytes, so worst case + // 512 >= 13 + 16 + length of message + // 483 >= length of message + // 480 is slightly pessimistic but it's a rounder number. + // (one more byte for null terminator needed by snprintf) + unsigned char buf[481]; + + if (strlen(chname) > 16) { + fprintf(stderr,"channel name %s is longer than 16 bytes, ignoring\n",chname); + return -1; + } + + ssize_t amt; + if ((amt = recv(fd, buf, sizeof buf-1,0)) == -1) { + perror("recv"); + return -1; + } else if (amt == 0) { + fputs("unix eof\n",stderr); + return -1; + } else { + int i; + for (i=0;i<amt;i++) { + if (buf[i] < ' ') { + buf[i] = ' '; + } + } + buf[amt] = '\0'; + char msg[512]; + int s; + if ((s=snprintf(msg,512,"PRIVMSG #%s :%s\r\n",chname,buf)) > 512) { + fprintf(stderr,"irc message was somehow too long (this should never happen) (%d)/512\n",s); + return -1; + } + if (irc_sendall(msg, s) == -1) { + perror("sendall"); + return -1; + }; + + return 0; + } +} + @@ -10,9 +10,14 @@ #include <stdio.h> + // takes filename, returns socket fd // or -1 on failure. int unix_setup(char sockname[]); +// reads a message from unix socket on fd, +// and sends it to irc on the channel chname. +int unix_handle(int fd, char chname[]); + #endif // unix_h_INCLUDED @@ -1,5 +1,6 @@ #include "util.h" #include "debug.h" +#include "conf.h" ssize_t sendall(int sockfd, char *buf, size_t len) { ssize_t total_sent = 0; @@ -4,7 +4,6 @@ #include <sys/types.h> #include <sys/socket.h> #include <stddef.h> -#include "conf.h" // repeatedly call send until all the data has been sent down // the socket. |