kinda works

git-svn-id: file:///raid/svn-personal/irc-archiver/trunk@5 f310dea9-ad02-7e44-859a-30a050007fc7
This commit is contained in:
Nishi 2024-08-30 02:36:44 +00:00
parent 8081430179
commit 3800f7a403
6 changed files with 330 additions and 9 deletions

View File

@ -5,7 +5,7 @@ include $(PWD)/Platform/$(PLATFORM).mk
.PHONY: all clean
.SUFFIXES: .c .o
OBJS = main.o util.o bot.o
OBJS = main.o util.o bot.o ircfw.o
all: ircarc$(EXEC)

122
Bot/bot.c
View File

@ -2,16 +2,23 @@
#include "ia_bot.h"
#include "ia_util.h"
#include "ircfw.h"
#include <signal.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
int ia_sock;
struct sockaddr_in is_addr;
struct sockaddr_in ia_addr;
bool ia_do_log = false;
@ -21,32 +28,131 @@ void ia_log(const char* txt) {
}
extern char* host;
extern char* realname;
extern char* nickname;
extern char* username;
extern char* password;
extern char* channels[];
extern int port;
void ia_close(int sock) { close(sock); }
const char* ia_null(const char* str) {
if(str == NULL) return "(null)";
return str;
}
bool ia_is_number(const char* str) {
int i;
for(i = 0; str[i] != 0; i++) {
if(!('0' <= str[i] && str[i] <= '9')) return false;
}
return true;
}
bool loop = true;
void ia_bot_kill(int sig) {
ia_log("Shutdown");
ircfw_socket_send_cmd(ia_sock, NULL, "QUIT :Shutdown (Signal)");
exit(1);
}
void ia_bot_loop(void) {
if((ia_sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
ia_log("Socket creation failure");
return;
}
loop = true;
int yes = 1;
if(setsockopt(ia_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&yes, sizeof(yes)) < 0) {
ia_log("setsockopt failure");
ia_close(ia_sock);
return;
}
bzero((char*)&is_addr, sizeof(is_addr));
is_addr.sin_family = PF_INET;
is_addr.sin_addr.s_addr = inet_addr(host);
is_addr.sin_port = htons(port);
bzero((char*)&ia_addr, sizeof(ia_addr));
ia_addr.sin_family = PF_INET;
ia_addr.sin_addr.s_addr = inet_addr(host);
ia_addr.sin_port = htons(port);
if(connect(ia_sock, (struct sockaddr*)&ia_addr, sizeof(ia_addr)) < 0) {
ia_log("Connection failure");
close(ia_sock);
return 1;
ia_close(ia_sock);
return;
}
while(1) {
signal(SIGINT, ia_bot_kill);
signal(SIGTERM, ia_bot_kill);
char* construct = malloc(1025);
if(password != NULL && strlen(password) > 0) {
sprintf(construct, "PASS :%s", password);
ircfw_socket_send_cmd(ia_sock, NULL, construct);
}
sprintf(construct, "USER %s %s %s :%s", username, username, username, realname);
ircfw_socket_send_cmd(ia_sock, NULL, construct);
sprintf(construct, "NICK :%s", nickname);
ircfw_socket_send_cmd(ia_sock, NULL, construct);
bool is_in = false;
while(1) {
int st = ircfw_socket_read_cmd(ia_sock);
if(st != 0) {
ia_log("Bad response");
return;
}
if(strlen(ircfw_message.command) == 3 && ia_is_number(ircfw_message.command)) {
int res = atoi(ircfw_message.command);
if(!is_in && 400 <= res && res <= 599) {
ia_log("Bad response");
return;
} else if(400 <= res && res <= 599) {
sprintf(construct, "Ignored error: %d", res);
ia_log(construct);
continue;
}
if(res == 376) {
is_in = true;
ia_log("Login successful");
int i;
for(i = 0; channels[i] != NULL; i++) {
sprintf(construct, "JOIN :%s", channels[i]);
ircfw_socket_send_cmd(ia_sock, NULL, construct);
}
}
} else {
if(strcasecmp(ircfw_message.command, "PING") == 0) {
ia_log("Ping request");
sprintf(construct, "PONG :%s", ia_null(ircfw_message.prefix));
ircfw_socket_send_cmd(ia_sock, NULL, construct);
} else if(strcasecmp(ircfw_message.command, "PRIVMSG") == 0) {
char* prefix = ircfw_message.prefix;
char** params = ircfw_message.params;
if(prefix != NULL && params != NULL) {
char* nick = ia_strdup(prefix);
int i;
for(i = 0; nick[i] != 0; i++) {
if(nick[i] == '!') {
nick[i] = 0;
break;
}
}
free(nick);
}
}
}
}
ircfw_socket_send_cmd(ia_sock, NULL, "QUIT :Shutdown");
free(construct);
}

View File

@ -3,6 +3,8 @@
#ifndef __IA_BOT_H__
#define __IA_BOT_H__
void ia_log(const char* txt);
void is_close(int sock);
void ia_bot_loop(void);
#endif

165
Bot/ircfw.c Normal file
View File

@ -0,0 +1,165 @@
/* $Id$ */
#define IRCFW_SRC
#include "ircfw.h"
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
struct ircfw_message ircfw_message;
char* ircfw_strcat(const char* a, const char* b) {
char* str = malloc(strlen(a) + strlen(b) + 1);
memcpy(str, a, strlen(a));
memcpy(str + strlen(a), b, strlen(b));
str[strlen(a) + strlen(b)] = 0;
return str;
}
char* ircfw_strcat3(const char* a, const char* b, const char* c) {
char* tmp = ircfw_strcat(a, b);
char* str = ircfw_strcat(tmp, c);
free(tmp);
return str;
}
char* ircfw_strdup(const char* str) { return ircfw_strcat(str, ""); }
void ircfw_init(void) {
ircfw_message.prefix = NULL;
ircfw_message.params = NULL;
ircfw_message.command = NULL;
}
void ircfw_parse_params(const char* str) {
ircfw_message.params = malloc(sizeof(*ircfw_message.params));
ircfw_message.params[0] = NULL;
int i;
int incr = 0;
bool until_end = false;
char* dup = ircfw_strdup(str);
for(i = 0;; i++) {
if(dup[i] == 0 || (!until_end && dup[i] == ' ')) {
char oldc = dup[i];
dup[i] = 0;
char* param = ircfw_strdup(dup + incr);
char** old_params = ircfw_message.params;
int j;
for(j = 0; old_params[j] != NULL; j++)
;
ircfw_message.params = malloc(sizeof(*ircfw_message.params) * (2 + j));
for(j = 0; old_params[j] != NULL; j++) {
ircfw_message.params[j] = old_params[j];
}
ircfw_message.params[j] = param;
ircfw_message.params[j + 1] = NULL;
free(old_params);
incr = i + 1;
if(oldc == 0) break;
} else if(dup[i] == ':' && !until_end) {
until_end = true;
incr = i + 1;
}
}
free(dup);
}
int ircfw_socket_send_cmd(int sock, const char* name, const char* cmd) {
char* str = ircfw_strcat(cmd, "\r\n");
if(name != NULL) {
char* old = str;
char* tmp = ircfw_strcat3(":", name, " ");
str = ircfw_strcat(tmp, old);
free(old);
free(tmp);
}
int st = send(sock, str, strlen(str), 0);
free(str);
return st < 0 ? 1 : 0;
}
int ircfw_socket_read_cmd(int sock) {
char c[2];
c[1] = 0;
char* str = malloc(1);
str[0] = 0;
bool err = false;
bool end = false;
while(1) {
int s = recv(sock, c, 1, 0);
if(s <= 0) {
err = true;
break;
}
if(c[0] == '\n') {
end = true;
break;
} else if(c[0] != '\r') {
char* tmp = str;
str = ircfw_strcat(tmp, c);
free(tmp);
}
}
if(ircfw_message.prefix != NULL) free(ircfw_message.prefix);
if(ircfw_message.params != NULL) {
int i;
for(i = 0; ircfw_message.params[i] != NULL; i++) {
free(ircfw_message.params[i]);
}
free(ircfw_message.params);
}
if(ircfw_message.command != NULL) free(ircfw_message.command);
ircfw_message.prefix = NULL;
ircfw_message.params = NULL;
ircfw_message.command = NULL;
if(str[0] == ':') {
int i;
for(i = 0; str[i] != 0; i++) {
if(str[i] == ' ') {
str[i] = 0;
ircfw_message.prefix = ircfw_strdup(str + 1);
i++;
int start = i;
for(;; i++) {
if(str[i] == ' ' || str[i] == 0) {
char oldc = str[i];
str[i] = 0;
ircfw_message.command = ircfw_strdup(str + start);
if(oldc != 0) {
i++;
ircfw_parse_params(str + i);
}
break;
}
}
break;
}
}
} else {
int i;
for(i = 0; str[i] != 0; i++) {
if(str[i] == ' ' || str[i] == 0) {
char oldc = str[i];
str[i] = 0;
ircfw_message.command = ircfw_strdup(str);
if(oldc != 0) {
i++;
ircfw_parse_params(str + i);
}
break;
}
}
}
free(str);
return err ? 1 : 0;
}

20
Bot/ircfw.h Normal file
View File

@ -0,0 +1,20 @@
/* $Id$ */
#ifndef __IRCFW_H__
#define __IRCFW_H__
struct ircfw_message {
char* prefix;
char* command;
char** params;
};
void ircfw_init(void);
int ircfw_socket_send_cmd(int sock, const char* name, const char* cmd);
int ircfw_socket_read_cmd(int sock);
#ifndef IRCFW_SRC
extern struct ircfw_message ircfw_message;
#endif
#endif

View File

@ -14,9 +14,13 @@ extern bool ia_do_log;
char* host = NULL;
int port = 0;
char* nickname = NULL;
char* username = NULL;
char* realname = NULL;
char* password = NULL;
char* admin = NULL;
char* channels[128];
int chanincr;
int main(int argc, char** argv) {
const char* fn = "archiver.ini";
@ -51,6 +55,8 @@ int main(int argc, char** argv) {
int incr = 0;
channels[0] = NULL;
for(i = 0;; i++) {
if(buf[i] == 0 || buf[i] == '\n') {
char oldc = buf[i];
@ -72,12 +78,21 @@ int main(int argc, char** argv) {
} else if(strcmp(key, "username") == 0) {
if(username != NULL) free(username);
username = ia_strdup(value);
} else if(strcmp(key, "nickname") == 0) {
if(nickname != NULL) free(nickname);
nickname = ia_strdup(value);
} else if(strcmp(key, "password") == 0) {
if(password != NULL) free(password);
password = ia_strdup(value);
} else if(strcmp(key, "admin") == 0) {
if(admin != NULL) free(admin);
admin = ia_strdup(value);
} else if(strcmp(key, "realname") == 0) {
if(realname != NULL) free(realname);
realname = ia_strdup(value);
} else if(strcmp(key, "channel") == 0) {
channels[chanincr++] = ia_strdup(value);
channels[chanincr] = NULL;
}
break;
@ -101,6 +116,10 @@ int main(int argc, char** argv) {
fprintf(stderr, "Specify username\n");
st = 1;
}
if(nickname == NULL) {
fprintf(stderr, "Specify nickname\n");
st = 1;
}
if(password == NULL) {
fprintf(stderr, "Specify password\n");
st = 1;
@ -109,6 +128,10 @@ int main(int argc, char** argv) {
fprintf(stderr, "Specify admin\n");
st = 1;
}
if(realname == NULL) {
fprintf(stderr, "Specify realname\n");
st = 1;
}
if(st == 1) return st;
printf("Bot spawning a daemon\n");
@ -124,7 +147,12 @@ int main(int argc, char** argv) {
}
if(host != NULL) free(host);
if(realname != NULL) free(realname);
if(username != NULL) free(username);
if(nickname != NULL) free(nickname);
if(password != NULL) free(password);
if(admin != NULL) free(admin);
for(i = 0; channels[i] != NULL; i++) {
free(channels[i]);
}
}