Initial commit
This commit is contained in:
commit
3c586141c2
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
xbot
|
||||
build
|
||||
|
19
Makefile
Normal file
19
Makefile
Normal 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)
|
32
lib/irc.h
Normal file
32
lib/irc.h
Normal 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
15
lib/util.h
Normal 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
128
src/irc.c
Normal 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
71
src/main.c
Normal 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
63
src/util.c
Normal 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';
|
||||
}
|
Loading…
Reference in New Issue
Block a user