From a25dbc52fdfa59df0fc23394b6d2649c642d1b35 Mon Sep 17 00:00:00 2001 From: 8nlight <8nlight@disroot.org> Date: Tue, 1 Aug 2023 22:40:45 +0300 Subject: [PATCH] =?UTF-8?q?=D0=97=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D1=84=D0=B0=D0=B9=D0=BB=D1=8B=20=D0=B2=20=C2=AB?= =?UTF-8?q?C=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- C/Makefile | 5 ++ C/irc.c | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++++ C/irc.h | 37 +++++++++++++ C/main.c | 51 ++++++++++++++++++ 4 files changed, 246 insertions(+) create mode 100644 C/Makefile create mode 100644 C/irc.c create mode 100644 C/irc.h create mode 100644 C/main.c diff --git a/C/Makefile b/C/Makefile new file mode 100644 index 0000000..33f2730 --- /dev/null +++ b/C/Makefile @@ -0,0 +1,5 @@ +all: + cc *.c -omain -O0 -g3 + +clean: + rm main diff --git a/C/irc.c b/C/irc.c new file mode 100644 index 0000000..afc4dc0 --- /dev/null +++ b/C/irc.c @@ -0,0 +1,153 @@ +#include "irc.h" + +unsigned int IRCC_connect(IRCC_client *irc, const char *ip, const unsigned int port){ + struct hostent *ghbn = gethostbyname(ip); + if (!ghbn) + return IRCC_ERROR; + + struct sockaddr_in client_str; + memset(&client_str, 0, sizeof(client_str)); + client_str.sin_family = AF_INET; + client_str.sin_port = htons(port); + client_str.sin_addr.s_addr = inet_addr(inet_ntoa(*(struct in_addr *)ghbn->h_addr)); + + irc->socket = socket(AF_INET, SOCK_STREAM, 0); + if (irc->socket < 0) + return IRCC_ERROR; + + int status = connect(irc->socket, (struct sockaddr *)&client_str, sizeof(client_str)); + if (status == -1) + return IRCC_ERROR; + + return IRCC_SUCCESS; +} + +unsigned int IRCC_register(IRCC_client *irc, const char *nickname){ + size_t size = strlen("USER \r\n 0 0 ") + strlen(nickname) + strlen(nickname); + char *tmp = (char *)malloc(size + 1); + if (tmp == NULL){ + fprintf(stderr, "malloc returned NULL (IRCC_register)\n"); + exit(1); + } + + sleep(2); + snprintf(tmp, size, "USER %s 0 0 %s\r\n", nickname, nickname); + send(irc->socket, tmp, strlen(tmp), 0); + + snprintf(tmp, size, "NICK %s\r\n", nickname); + send(irc->socket, tmp, strlen(tmp), 0); + + free(tmp); + return IRCC_SUCCESS; +} + +void IRCC_parse(char *tmp, IRCC_client *irc){ + if (tmp != NULL){ + //Message + if (strstr(tmp, ":") != NULL) + irc->msg = strstr(tmp, ":"); + + //Channel + if (strstr(tmp, "#") != NULL){ + irc->channel = strstr(tmp, "#"); + irc->channel[strcspn(irc->channel, " ")] = '\0'; + } + + //Nickname + irc->raw[strcspn(irc->raw, "!")] = '\0'; + irc->nick = irc->raw + 1; + } +} + +unsigned int IRCC_recv(IRCC_client *irc){ + memset(irc->raw, '\0', irc->size); + irc->channel = NULL; + irc->msg = NULL; + irc->nick = NULL; + + int msg_size = recv(irc->socket, irc->raw, irc->size, 0); + if (msg_size == 0 || msg_size == -1) + return IRCC_DISCONNECTED; + + else if (!strncmp(irc->raw, "PING", 4)){ + *(strchr(irc->raw, 'I')) = 'O'; + send(irc->socket, irc->raw, strlen(irc->raw), 0); + return IRCC_PING; + } + + else { + //puts(irc->raw); + irc->raw[strcspn(irc->raw, "\r\n")] = '\0'; + + if (strstr(irc->raw, "PRIVMSG ")){ + IRCC_parse(strstr(irc->raw, "PRIVMSG "), irc); + return IRCC_PRIVMSG; + } + + else if (strstr(irc->raw, "NICK ")){ + IRCC_parse(strstr(irc->raw, "NICK "), irc); + return IRCC_NICK; + } + + else if (strstr(irc->raw, "JOIN ")){ + IRCC_parse(strstr(irc->raw, "JOIN "), irc); + return IRCC_JOIN; + } + + else if (strstr(irc->raw, "PART ") || strstr(irc->raw, "QUIT ")){ + IRCC_parse(strstr(irc->raw, "PART "), irc); + IRCC_parse(strstr(irc->raw, "QUIT "), irc); + return IRCC_PART; + } + } + + return IRCC_SUCCESS; +} + +void IRCC_send(IRCC_client *irc, char *msg, char *channel){ + size_t size = strlen("PRIVMSG :\r\n") + strlen(channel) + strlen(msg); + + char *tmp = (char *)malloc(size + 1); + if (tmp == NULL){ + fprintf(stderr, "malloc returned NULL (IRCC_send)\n"); + exit(1); + } + + snprintf(tmp, size, "PRIVMSG %s :%s\r\n", channel, msg); + send(irc->socket, tmp, strlen(tmp), 0); + + memset(tmp, 0, size); + free(tmp); +} + +unsigned int IRCC_init(IRCC_client *irc, size_t size){ + if (size <= 200){ + fprintf(stderr, "Low buffer size (IRCC_init)\n"); + return IRCC_ERROR; + } + + irc->raw = (char *)malloc(size + 1); + if (irc->raw == NULL){ + fprintf(stderr, "malloc returned NULL (IRCC_init)\n"); + exit(1); + } + + irc->msg = NULL; + irc->nick = NULL; + irc->channel = NULL; + + irc->size = size; + return IRCC_SUCCESS; +} + +void IRCC_close(IRCC_client *irc){ + close(irc->socket); + + free(irc->raw); + irc->raw = NULL; + irc->msg = NULL; + irc->nick = NULL; + irc->channel = NULL; + + irc->size = 0; +} diff --git a/C/irc.h b/C/irc.h new file mode 100644 index 0000000..44cd5a5 --- /dev/null +++ b/C/irc.h @@ -0,0 +1,37 @@ +#ifndef IRC_LINUX +#define IRC_LINUX + +#include +#include +#include +#include +#include +#include +#include +#include +#define IRCC_NICK 8 +#define IRCC_PRIVMSG 7 +#define IRCC_JOIN 6 +#define IRCC_PART 5 +#define IRCC_PING 4 + +#define IRCC_DISCONNECTED 2 +#define IRCC_ERROR 1 +#define IRCC_SUCCESS 0 + +typedef struct { + int socket; + size_t size; + char *raw; + char *msg; + char *channel; + char *nick; +} IRCC_client; + +unsigned int IRCC_connect(IRCC_client *irc, const char *ip, const unsigned int port); +unsigned int IRCC_register(IRCC_client *irc, const char *nickname); +unsigned int IRCC_recv(IRCC_client *irc); +void IRCC_send(IRCC_client *irc, char *msg, char *channel); +unsigned int IRCC_init(IRCC_client *irc, size_t size); +void IRCC_close(IRCC_client *irc); +#endif diff --git a/C/main.c b/C/main.c new file mode 100644 index 0000000..2c695e4 --- /dev/null +++ b/C/main.c @@ -0,0 +1,51 @@ +#include "irc.h" +#define IF_NULL(client) (client.msg != NULL || client.nick != NULL || client.channel != NULL) + +IRCC_client client; + +void die(char *msg){ + puts(msg); + IRCC_close(&client); + exit(1); +} + +int main(void){ + IRCC_init(&client, 250); + int status = IRCC_connect(&client, "irc.libera.chat", 6667); + if (status == IRCC_ERROR) + die("Conn refused"); + + IRCC_register(&client, "bot"); + sleep(5); + send(client.socket, "JOIN #channel\r\n", strlen("JOIN #channel\r\n"), 0); + + while (1){ + unsigned int irc_status = IRCC_recv(&client); + if (irc_status == IRCC_DISCONNECTED) + die("Disconnected"); + + if (IF_NULL(client)) { + client.msg++; + switch (irc_status) { + case IRCC_PRIVMSG: + printf("%s %s %s\n", client.channel, client.nick, client.msg); + break; + + case IRCC_NICK: + printf("%s is know as %s", client.nick, client.msg); + break; + + case IRCC_JOIN: + printf("< %s\n", client.nick); + break; + + case IRCC_PART: + printf("> %s\n", client.nick); + break; + + default: + break; + } + } + } +}