#ifdef LOCAL #define HOST "0.0.0.0" #define PORT "6970" #else #define HOST "ubq323.website" #define PORT "6667" #endif #define NICK "ffbm" #define USERNAME "ffbm" #define REALNAME ",flappy fly bird man?" #define CHANNEL "#a" #define PIPE "/run/apionet.pipe" #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include int hasjoined = 0; ssize_t sendall(int sockfd, void *buf, size_t len) { ssize_t total_sent = 0; ssize_t sent; do { if ((sent = send(sockfd, buf+total_sent, len-total_sent, 0)) == -1) { return -1; } total_sent += sent; } while (total_sent < len); total_sent = 0; do { if ((sent = write(0, buf+total_sent, len-total_sent)) == -1) { return -1; } total_sent += sent; } while (total_sent < len); return total_sent; } 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; } if ((sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) { perror("socket"); return -1; } if (connect(sockfd, res->ai_addr, res->ai_addrlen) != 0) { perror("connect"); return -1; } 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) { if (strncmp(start, "PING", 4) == 0) { start[1] = 'O'; sendall(sockfd, start, end-start); start[1] = 'I'; } char *str = strndup(start, end-start); printf("[%s]\n",str); free(str); } void irc_recv(int sockfd) { char recvbuf[1024]; ssize_t amt; if ((amt = recv(sockfd, recvbuf, 1024, 0)) == -1) { perror("recv"); exit(1); } char *start = &recvbuf[0]; char *cur; char *end = start+amt ; for (cur = start; cur < end; cur++) { if (*cur == '\r' && *(cur+1) == '\n') { irc_handle(sockfd, start, cur+2); start = cur + 2; cur = start; } } } int main(int argc, char *argv[]) { // this only works on linux, i think. // sorry int pipefd = open(PIPE, O_RDWR|O_NONBLOCK); if (pipefd == -1) { perror("(pipe) open"); return 1; } printf("bees\n"); int sockfd = irc_connect(); if (sockfd == -1) { return 1; } if (irc_handshake(sockfd) != 0) { perror("irc_handshake"); return 1; } // setup pollfds struct pollfd pollfds[2] = { { .fd = pipefd, .events = POLLIN, }, { .fd = sockfd, .events = POLLIN, }, }; printf("POLLIN %d POLLERR %d POLLHUP %d\n",POLLIN,POLLERR,POLLHUP); for (;;) { int r; if ((r = poll(pollfds, 2, -1)) == -1) { perror("poll"); return 1; } printf("poll %d\n",r); printf("sock %d pipe %d\n",pollfds[1].revents, pollfds[0].revents); 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) { // socket char buf[1]; // there is probably a better way of doing this // but if there is, i don't know what it is ssize_t h = recv(sockfd, buf, 1, MSG_PEEK); if (h<0) { perror("recv"); return -1; } else if (h == 0) { // eof ish puts("socket end"); break; } else { irc_recv(sockfd); } } if (pollfds[0].revents & POLLIN) { puts("pipe"); ssize_t amt; unsigned char buf[128]; if ((amt = read(pipefd, buf, 128)) == -1) { perror("(pipe) read"); return 1; } for (size_t i = 0; i < amt; i++) { if (buf[i] == '\r' || buf[i] == '\n' || buf[i] < ' ') { buf[i] = ' '; } } char msg[] = "PRIVMSG "CHANNEL" :"; if (sendall(sockfd, msg, sizeof msg-1) == -1) { perror("sendall"); exit(1); } if (sendall(sockfd, buf, amt) == -1) { perror("sendall"); exit(1); } if (sendall(sockfd, "\r\n", 2) == -1) { perror("sendall"); exit(1); } } } return 0; }