kinda works
git-svn-id: file:///raid/svn-personal/irc-archiver/trunk@5 f310dea9-ad02-7e44-859a-30a050007fc7
This commit is contained in:
parent
8081430179
commit
3800f7a403
|
@ -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
122
Bot/bot.c
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
165
Bot/ircfw.c
Normal 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
20
Bot/ircfw.h
Normal 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
|
28
Bot/main.c
28
Bot/main.c
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user