Initial commit

This commit is contained in:
Aaron Blakely 2015-03-24 05:12:35 -05:00
commit 3c586141c2
9 changed files with 345 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
xbot
build

19
Makefile Normal file
View File

@ -0,0 +1,19 @@
CC=gcc
CFLAGS=-c -lconfig -I./lib
BINFLAGS=-lconfig
SRC=./src
OBJ=./build
OBJECTS=$(OBJ)/*.o
EXEC=xbot
main:
@rm -rf build
@mkdir build
$(CC) $(CFLAGS) $(SRC)/main.c -o $(OBJ)/main.o
$(CC) $(CFLAGS) $(SRC)/irc.c -o $(OBJ)/irc.o
$(CC) $(CFLAGS) $(SRC)/util.c -o $(OBJ)/util.o
$(CC) -o $(EXEC) $(OBJECTS) $(BINFLAGS)
@echo "All Done!"
clean:
@rm -rf build $(EXEC)

1
README.md Normal file
View File

@ -0,0 +1 @@
# xbot

32
lib/irc.h Normal file
View File

@ -0,0 +1,32 @@
/*
* xbot: Just another IRC bot
*
* Written by Aaron Blakely <aaron@ephasic.org>
**/
#ifndef IRC_H
#define IRC_H
#include <stdio.h>
struct irc_conn
{
FILE *srv_fd;
char nick[32];
char *host;
char *port;
char *real_name;
// I/O Buffers
char out[4096];
char in[4096];
};
void irc_connect(struct irc_conn *bot);
void irc_auth(struct irc_conn *bot);
void irc_raw(struct irc_conn *bot, char *fmt, ...);
void irc_parse_raw(struct irc_conn *bot, char *raw);
#endif

15
lib/util.h Normal file
View File

@ -0,0 +1,15 @@
/*
* xbot: Just another IRC bot
*
* Written by Aaron Blakely <aaron@ephasic.org>
**/
#ifndef UTIL_H
#define UTIL_H
void eprint(char *fmt, ...);
void strlcpy(char *to, const char *from, int len);
char *skip(char *s, char c);
void trim(char *s);
#endif

128
src/irc.c Normal file
View File

@ -0,0 +1,128 @@
/*
* irc.c: IRC connection and parser
* xbot: Just another IRC bot
*
* Written by Aaron Blakely <aaron@ephasic.org>
**/
#include "irc.h"
#include "util.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
void irc_connect(struct irc_conn *bot)
{
int srv_fd;
struct addrinfo hints;
struct addrinfo *res, *r;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(bot->host, bot->port, &hints, &res) != 0)
{
eprint("Error: Cannot resolve hostname '%s':", bot->host);
}
for (r = res; r; r->ai_next)
{
if ((srv_fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol)) == -1)
{
continue;
}
if (connect(srv_fd, r->ai_addr, r->ai_addrlen) == 0)
{
break;
}
close(srv_fd);
}
freeaddrinfo(res);
if (!r)
{
eprint("Error: Cannot connect to host '%s'\n", bot->host);
}
bot->srv_fd = fdopen(srv_fd, "r+");
}
void irc_auth(struct irc_conn *bot)
{
irc_raw(bot, "NICK %s", bot->nick);
irc_raw(bot, "USER %s localhost %s :xbot (v0.1) - developed by @Dark_Aaron", bot->nick, bot->host);
fflush(bot->srv_fd);
}
void irc_raw(struct irc_conn *bot, char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vsnprintf(bot->out, sizeof bot->out, fmt, ap);
va_end(ap);
fprintf(bot->srv_fd, "%s\r\n", bot->out);
}
void irc_parse_raw(struct irc_conn *bot, char *raw)
{
char *user, *par, *text;
user = bot->host;
if (!raw || !*raw)
{
return;
}
if (raw[0] == ':')
{
user = raw + 1;
raw = skip(user, ' ');
if (raw[0] == '\0')
{
return;
}
skip(user, '!');
}
skip(raw, '\r');
par = skip(raw, ' ');
text = skip(par, ':');
trim(par);
if (!strcmp("PONG", raw))
{
return;
}
if (!strcmp("PRIVMSG", raw))
{
//handle_privmsg(user, par, text)
if (!strcmp("Dark_Aaron", user))
{
irc_raw(bot, "JOIN #bots");
}
}
else if (!strcmp("PING", raw))
{
irc_raw(bot, "PONG %s", text);
}
else
{
if (!strcmp("NICK", raw) && !strcmp(user, bot->nick))
{
strlcpy(bot->nick, text, sizeof bot->nick);
}
}
}

71
src/main.c Normal file
View File

@ -0,0 +1,71 @@
/*
* xbot: Just another IRC bot
*
* Written by Aaron Blakely <aaron@ephasic.org>
**/
#include <stdio.h>
#include <string.h>
#include <sys/select.h>
#include <libconfig.h>
#include "irc.h"
int main()
{
fd_set rd;
config_t cfg, *cf;
const config_setting_t *retries;
const char *base = NULL;
struct irc_conn bot;
// Init the config parser
cf = &cfg;
config_init(cf);
if (!config_read_file(cf, "xbot.cfg"))
{
printf("xbot.cfg:%d - %s\n",
config_error_line(cf),
config_error_text(cf));
config_destroy(cf);
return -1;
}
// Fill our bot struct with values from the config
if (config_lookup_string(cf, "bot.nick", &base))
strlcpy(bot.nick, base, sizeof bot.nick);
if (config_lookup_string(cf, "server.host", &base))
bot.host = (char *)base;
if (config_lookup_string(cf, "server.port", &base))
bot.port = (char *)base;
// Connect to the server
printf("Connecting to %s...\n", bot.host);
irc_connect(&bot);
irc_auth(&bot);
// Free the config before entering the main loop
config_destroy(cf);
for (;;)
{
FD_ZERO(&rd);
FD_SET(fileno(bot.srv_fd), &rd);
if (FD_ISSET(fileno(bot.srv_fd), &rd))
{
if (fgets(bot.in, sizeof bot.in, bot.srv_fd) == NULL)
{
eprint("xbot: remote host closed connection\n");
}
irc_parse_raw(&bot, bot.in);
}
}
return 0;
}

63
src/util.c Normal file
View File

@ -0,0 +1,63 @@
/*
* xbot: Just another IRC bot
*
* Written by Aaron Blakely <aaron@ephasic.org>
**/
#include <stdio.h>
#include <errno.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
void eprint(char *fmt, ...)
{
char bufout[4096];
va_list ap;
va_start(ap, fmt);
vsnprintf(bufout, sizeof bufout, fmt, ap);
va_end(ap);
fprintf(stderr, "%s", bufout);
if (fmt[0] && fmt[strlen(fmt) - 1] == ':')
{
fprintf(stderr, "%s\n", strerror(errno));
}
exit(1);
}
void strlcpy(char *to, const char *from, int len)
{
memccpy(to, from, '\0', len);
to[len-1] = '\0';
}
char *skip(char *s, char c)
{
while (*s != c && *s != '\0')
{
s++;
}
if (*s != '\0')
{
*s++ = '\0';
}
return s;
}
void trim(char *s)
{
char *e;
e = s + strlen(s) - 1;
while (isspace(*e) && e > s)
{
e--;
}
*(e + 1) = '\0';
}

13
xbot.cfg Normal file
View File

@ -0,0 +1,13 @@
# xbot configuration file
bot:
{
nick = "xbot";
user = "xbot";
};
server:
{
host = "irc.alphachat.net";
port = "6667";
};