diff options
Diffstat (limited to 'thing.c')
-rw-r--r-- | thing.c | 327 |
1 files changed, 0 insertions, 327 deletions
diff --git a/thing.c b/thing.c deleted file mode 100644 index 3f84948..0000000 --- a/thing.c +++ /dev/null @@ -1,327 +0,0 @@ -#include "conf.h" - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <grp.h> -#include <errno.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <poll.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <netdb.h> -#include <arpa/inet.h> -#include <netinet/in.h> - - -int irc_connect() { - struct addrinfo hints; - int status, sockfd; - struct addrinfo *res; - - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - - // assuming the first one is valid because it normally is - - if ((status = getaddrinfo(HOST, PORT, &hints, &res)) != 0) { - fprintf(stderr, "getaddrinfo fail: %s\n", gai_strerror(status)); - return -1; - } - - struct addrinfo *cur; - for (cur = res; cur != NULL; cur = cur->ai_next) { - if ((sockfd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol)) == -1) { - perror("socket"); - continue; - } - if (connect(sockfd, cur->ai_addr, cur->ai_addrlen) != 0) { - perror("connect"); - continue; - } - goto success; - } - return -1; - success: - return sockfd; -} - -int irc_handshake(int sockfd) { - char msg[] = "NICK "NICK"\r\nUSER "USERNAME" 0 * :"REALNAME"\r\nJOIN "CHANNEL"\r\n"; - if (sendall(sockfd, msg, sizeof msg-1) == -1) { - return -1; - } - return 0; -} - -void irc_handle(int sockfd, char *start, char *end) { - DP("irc_handle..."); -#ifdef DEBUG - char *the = strndup(start,end-start); - printf("HANDLE [%s]\n",the); - free(the); -#endif - - if (strncmp(start, "PING", 4) == 0) { - start[1] = 'O'; - sendall(sockfd, start, end-start); - start[1] = 'I'; - return; - } - - char *msg = start; - size_t msglen = end-start; - if (msglen > 512) { - fprintf(stderr,"message longer than 512 bytes, this is bad probably\n"); - return; - } - - // this is quite bad - // i should change it one day - - char msg_source[512]; - msg_source[0] = '\0'; - - char msg_command[512]; - msg_command[0] = '\0'; - - char msg_params[16][512]; - for (int i = 0; i < 16; i++) - msg_params[i][0] = '\0'; - - int i = 0; - if (msg[0] == ':') { - for (i = 1; i < msglen && msg[i] != ' ' && msg[i] != '\r' && msg[i] != '\n'; i++) - msg_source[i-1] = msg[i]; - msg_source[i-1] = '\0'; - i++; - } - int j; - for (j=0; i < msglen && msg[i] != ' ' && msg[i] != '\r' && msg[i] != '\n'; i++, j++) - msg_command[j] = msg[i]; - msg_command[j] = '\0'; - i++; - - for (int px = 0; px < 16; px++) { - if (i >= msglen) break; - if (msg[i] == ':') { - memcpy(msg_params[px],&msg[i+1],msglen-i-2); - msg_params[px][msglen-i-1] = '\0'; - break; - } - for (j = 0; i < msglen && msg[i] != ' ' && msg[i] != '\r' && msg[i] != '\n'; i++, j++) - msg_params[px][j] = msg[i]; - msg_params[px][j] = '\0'; - i++; - } -#ifdef DEBUG - printf("source [%s]\n",msg_source); - printf("command [%s]\n",msg_command); - printf("params: "); - for (int px = 0; px < 16; px++) - printf("%d:[%s] ",px,msg_params[px]); - printf("\n"); -#endif - - - -} - -#define IRC_RECVBUF_SIZE 1024 -char irc_recvbuf[IRC_RECVBUF_SIZE]; -const char *irc_recvbuf_end = &irc_recvbuf[IRC_RECVBUF_SIZE]; -char *irc_recvbuf_cur = &irc_recvbuf[0]; - -void irc_recv(int sockfd) { - DP("irc_recv..."); - - - ssize_t s = recv(sockfd, irc_recvbuf_cur, irc_recvbuf_end-irc_recvbuf_cur, 0); - - if (s == 0) { - fputs("socket eof\n",stderr); - exit(3); // todo: reconnecting properly - } - - if (s == -1) { - perror("recv"); - exit(1); - } -#ifdef DEBUG - char *the = strndup(irc_recvbuf_cur,s); - printf("RECV %ld [%s]\n",s,the); - free(the); -#endif - char *buf_last = irc_recvbuf_cur+s; - - char *cur; - char *start = irc_recvbuf; - for (cur = irc_recvbuf; cur < buf_last; cur++) { - if (*cur=='\r' && *(cur+1) == '\n') { - irc_handle(sockfd, start, cur+2); - start = cur+2; - cur++; - } - } - - if (start == buf_last) { - // all done - irc_recvbuf_cur = irc_recvbuf; - } else { - size_t remainder_len = buf_last-start; - // if we are to support ircv3 message tags then this should be - // quite a lot bigger, but i don't care about that - // (buffer would have to be bigger too, at least 16384 i think) - if (remainder_len > 512) { - fputs("message longer than 512 bytes! this indicates a broken server\n",stderr); - exit(2); - } - memmove(irc_recvbuf,start,remainder_len); - irc_recvbuf_cur = irc_recvbuf+remainder_len; - } -} - - - -int unix_setup() { - unlink(SOCKETNAME); - - int sock = socket(AF_UNIX, SOCK_DGRAM, 0); - if (sock == -1) { - perror("(unix) socket"); - return -1; - } - - struct sockaddr_un name; - memset(&name, 0, sizeof name); - name.sun_family = AF_UNIX; - strncpy(name.sun_path, SOCKETNAME, (sizeof name.sun_path)-1); - if (bind(sock, (const struct sockaddr*)&name, sizeof name) == -1) { - perror("(unix) bind"); - return -1; - } - - // set group and permissions on socket - long buflen = sysconf(_SC_GETGR_R_SIZE_MAX); - buflen = (buflen == -1) ? 1024 : buflen; - char *buf = malloc(buflen); - struct group grp; - struct group *res; - errno = 0; - // get group gid from name - getgrnam_r(SOCKETGROUP,&grp,buf,buflen,&res); - if (res == NULL) { - if (errno != 0) - perror("getgrnam_r"); - else - fprintf(stderr,"group %s does not exist",SOCKETGROUP); - free(buf); - return -1; - } - free(buf); - - // set socket's group - if (chown(SOCKETNAME,-1,grp.gr_gid) == -1) { - perror("chown"); - return -1; - } - - struct stat sb; - if (stat(SOCKETNAME,&sb) == -1) { - perror("stat"); - return -1; - } - if (chmod(SOCKETNAME,sb.st_mode|S_IWGRP) == -1) { - perror("chmod"); - return -1; - } - - - return sock; -} - - - -int main(int argc, char *argv[]) { - - int ircsock = irc_connect(); - if (ircsock == -1) { - return 1; - } - if (irc_handshake(ircsock) != 0) { - perror("irc_handshake"); - return 1; - } - - int unixsock = unix_setup(); - if (unixsock == -1) - return 1; - - struct pollfd pollfds[2] = { - { - .fd = unixsock, - .events = POLLIN, - }, - { - .fd = ircsock, - .events = POLLIN, - }, - }; -#ifdef DEBUG - printf("POLLIN %d POLLERR %d POLLHUP %d\n",POLLIN,POLLERR,POLLHUP); -#endif - - for (;;) { - int r; - if ((r = poll(pollfds, 2, -1)) == -1) { - perror("poll"); - return 1; - } -#ifdef DEBUG - printf("sock %d unix %d\n",pollfds[1].revents, pollfds[0].revents); -#endif - - - if (pollfds[1].revents & POLLHUP) { - // socket closed, probably - puts("socket hup"); - break; - } - if (pollfds[1].revents & POLLERR) { - // socket error - puts("socket err"); - break; - } - if (pollfds[1].revents & POLLIN) { - DP("socket..."); - // socket - irc_recv(ircsock); - } - if (pollfds[0].revents & POLLIN) { - unsigned char buf[128]; - ssize_t amt; - if ((amt = recv(unixsock,buf,sizeof buf,0)) == -1) { - perror("(unix) read"); - return 1; - } - for (size_t i = 0; i < amt; i++) - if (buf[i] == '\r' || buf[i] == '\n' || buf[i] == '\0') - buf[i] = ' '; - char msg[] = "PRIVMSG "CHANNEL" :"; - - if (sendall(ircsock, msg, sizeof msg-1) == -1) { perror("sendall"); return 1; } - if (sendall(ircsock, buf, amt) == -1) { perror("sendall"); return 1; } - if (sendall(ircsock, "\r\n", 2) == -1) { perror("sendall"); return 1; } - - } - } - - - - - return 0; -} |