Compare commits

...

10 Commits

20 changed files with 714 additions and 83 deletions

1
.gitignore vendored
View File

@ -7,6 +7,7 @@ mods/test
.cache
UpgradeLog*.XML
xbot.db
*.so
*.dll
*.lib

View File

@ -22,6 +22,8 @@ main:
$(CC) $(CFLAGS) $(SRC)/module.c -o $(OBJ)/module.o
$(CC) $(CFLAGS) $(SRC)/channel.c -o $(OBJ)/channel.o
$(CC) $(CFLAGS) $(SRC)/timers.c -o $(OBJ)/timers.o
$(CC) $(CFLAGS) $(SRC)/db.c -o $(OBJ)/db.o
$(CC) -o $(EXEC) $(OBJECTS) $(BINFLAGS)
@echo "All Done!"

View File

@ -4,5 +4,6 @@
#include "irc.h"
struct irc_conn read_config(struct irc_conn bot, char *file);
void run_autoload(struct irc_conn *bot);
#endif
#endif

52
lib/db.h Executable file
View File

@ -0,0 +1,52 @@
#ifndef DB_H
#define DB_H
#include "util.h"
#define DB_MAGIC 0xdeadbeef
#define DB_VER 0x10
enum db_type
{
DB_TYPE_CHAR,
DB_TYPE_INT,
DB_TYPE_FLOAT
};
struct db_hash
{
int key_len;
int value_len;
int type;
char *key;
void *value;
};
struct db_table
{
int db_magic;
int db_ver;
int count;
struct db_hash *hashes;
};
MY_API int db_write(struct db_table *db, char *fname);
MY_API struct db_table *db_read(char *fname);
MY_API int db_set_hash(struct db_table *db, char *key, void *value);
MY_API int db_set_hash_char(struct db_table *db, char *key, char *value);
MY_API int db_set_hash_int(struct db_table *db, char *key, int value);
MY_API int db_set_hash_float(struct db_table *db, char *key, float value);
MY_API int db_del_hash(struct db_table *db, char *key);
MY_API void *db_get_hash(struct db_table *db, char *key);
MY_API int db_get_hash_type(struct db_table *db, char *key);
MY_API char *db_get_hash_char(struct db_table *db, char *key);
MY_API int db_get_hash_int(struct db_table *db, char *key);
MY_API float db_get_hash_float(struct db_table *db, char *key);
#endif

View File

@ -9,6 +9,9 @@
#include <stdio.h>
#include "util.h"
#include "db.h"
#ifdef _WIN32
#include <winsock2.h>
#endif
@ -30,6 +33,9 @@ struct irc_conn
char port[5];
char real_name[512];
char db_file[256];
struct db_table *db;
// I/O Buffers
char *out;
char *in;
@ -37,16 +43,6 @@ struct irc_conn
typedef struct handler event_handler;
#ifdef _WIN32
#ifdef MY_DLL_EXPORTS
#define MY_API __declspec(dllexport)
#else
#define MY_API __declspec(dllimport)
#endif
#else
#define MY_API
#endif
void irc_connect(struct irc_conn *bot);
void irc_auth(struct irc_conn *bot);
@ -58,6 +54,7 @@ MY_API void irc_part(struct irc_conn *bot, char *channel, char *reason);
MY_API void irc_ban(struct irc_conn *bot, char *channel, char *nick);
MY_API void irc_kick(struct irc_conn *bot, char *channel, char *user, char *reason);
MY_API void irc_mode(struct irc_conn *bot, char *channel, char *mode);
MY_API void irc_ctcp(struct irc_conn *bot, char *to, char *fmt, ...);
void irc_parse_raw(struct irc_conn *bot, char *raw);

View File

@ -39,9 +39,12 @@ void load_module(struct irc_conn *bot, char *where, char *stype, char *file);
void unload_module(struct irc_conn *bot, char *where, char *file);
void list_modules(struct irc_conn *bot, char *where);
void set_bot(struct irc_conn *b);
void set_bot_db(struct db_table *db);
MY_API void register_module(char *name, char *author, char *version, char *description);
MY_API void unregister_module(char *name);
MY_API struct mods *get_mods();
MY_API struct irc_conn *get_bot();
MY_API struct db_table *get_bot_db();
#endif

View File

@ -12,17 +12,27 @@
#define false FALSE
#endif
#ifdef _WIN32
#ifdef MY_DLL_EXPORTS
#define MY_API __declspec(dllexport)
#else
#define MY_API __declspec(dllimport)
#endif
#else
#define MY_API
#endif
void eprint(char *fmt, ...);
#if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 38)) || defined(_WIN32)
void strlcpy(char *to, const char *from, int len);
MY_API void strlcpy(char *to, const char *from, int len);
#endif
#ifdef _WIN32
char *basename(char *path);
MY_API char *basename(char *path);
#endif
char *skip(char *s, char c);
void trim(char *s);
MY_API char *skip(char *s, char c);
MY_API void trim(char *s);
#endif

78
mods/lua/README.md Executable file
View File

@ -0,0 +1,78 @@
# API
## Events
### Event Types
- `PRIVMSG_SELF - user, host, message`
- `PRIVMSG_CHAN - user, host, channel, message`
- `JOIN - user, host, channel`
- `JOIN_MYSELF - channel`
- `PART - user, host, channel, reason`
- `PART_MYSELF - channel, reason`
- `QUIT - user, host, reason`
- `NICK - user, host, newnick`
- `NICK_MYSELF - newnick`
- `NICK_INUSE - newnick`
- `CTCP - user, host, to, message`
- `IRC_CONNECTED`
- `TICK`
### `add_handler(event, handler)`
Adds a handler for an event.
Example:
```lua
function msg(user, host, channel, message)
print(user .. " said: " .. message)
end
add_handler(PRIVMSG_CHAN, msg)
```
### `del_handler(event, handler)`
Removes a handler for an event.
Example:
```lua
del_handler(PRIVMSG_CHAN, msg)
```
## IRC Commands
### `raw(message)`
Sends a raw message to the server.
### `privmsg(to, message)`
Sends a message to a channel or user.
### `notice(to, message)`
Sends a notice to a channel or user.
### `join(channel)`
Joins a channel.
### `part(channel, reason)`
Leaves a channel.
### `kick(channel, user, reason)`
Kicks a user from a channel. Reason is optional.
### `mode(channel, mode, target)`
Sets a mode on a channel.
### `ctcp(to, message)`
Sends a CTCP message to a channel or user.

View File

@ -17,102 +17,102 @@
struct lua_interp lua;
struct irc_conn *instance;
char *scriptsfile = "./mods/lua/scripts";
int append_script(char *fname)
{
int i;
FILE *fp;
char *buf = (char *)malloc(sizeof(char *) * 500);
char *scriptlist = db_get_hash_char(get_bot_db(), "lua.scripts");
char *newlist = (char *)malloc(sizeof(char) * 500);
char *p = scriptlist;
// check if the file is already in the list
struct script_list list = get_scripts();
for (i = 0; i < list.count; i++)
if (scriptlist == NULL)
{
if (strcmp(list.scripts[i], fname) == 0)
{
free(buf);
return 0;
}
db_set_hash_char(get_bot_db(), "lua.scripts", fname);
db_write(get_bot_db(), instance->db_file);
return 0;
}
if ((fp = fopen(scriptsfile, "a")) == NULL)
{
free(buf);
return -1;
}
sprintf(newlist, "%s,%s", scriptlist, fname);
printf("newlist: %s\n", newlist);
sprintf(buf, "%s\n", fname);
fputs(buf, fp);
fclose(fp);
db_set_hash_char(get_bot_db(), "lua.scripts", newlist);
db_write(get_bot_db(), instance->db_file);
free(newlist);
free(buf);
return 0;
}
int remove_script(char *fname)
{
FILE *fp, *tmp;
char *buf = (char *)malloc(sizeof(char *) * 500);
char *tmpfile = "./mods/lua/scripts.tmp";
char *scriptlist = db_get_hash_char(get_bot_db(), "lua.scripts");
char *newlist = (char *)malloc(sizeof(char) * 500);
char *p = scriptlist;
char *q = newlist;
int len = strlen(fname);
int found = 0;
if ((fp = fopen(scriptsfile, "r")) == NULL)
if (scriptlist == NULL)
{
free(buf);
return -1;
return 0;
}
tmp = fopen(tmpfile, "w");
while (fgets(buf, 500, fp) != NULL)
while (*p != '\0')
{
if (strcmp(buf, fname) != 0)
if (strncmp(p, fname, len) == 0)
{
fputs(buf, tmp);
p = skip(p, ',');
found = 1;
continue;
}
*q = *p;
p++;
q++;
}
fclose(fp);
fclose(tmp);
if (found == 0)
{
return 0;
}
remove(scriptsfile);
rename(tmpfile, scriptsfile);
*q = '\0';
// remove trailing , if it exists
if (newlist[strlen(newlist) - 1] == ',')
{
newlist[strlen(newlist) - 1] = '\0';
}
db_set_hash_char(get_bot_db(), "lua.scripts", newlist);
db_write(get_bot_db(), instance->db_file);
free(newlist);
free(buf);
return 0;
}
struct script_list get_scripts()
{
FILE *fp;
char *buf = (char *)malloc(sizeof(char *) * 500);
struct script_list list;
char *scriptlist = db_get_hash_char(get_bot_db(), "lua.scripts");
struct script_list list = {0};
char *p = scriptlist;
int i = 0;
if ((fp = fopen(scriptsfile, "r")) == NULL)
if (scriptlist == NULL)
{
free(buf);
list.count = 0;
return list;
}
while (fgets(buf, 500, fp) != NULL)
while (*p != '\0')
{
list.scripts[i] = (char *)malloc(sizeof(char *) * 150);
strlcpy(list.scripts[i], buf, 150);
// remove newline
list.scripts[i][strlen(list.scripts[i]) - 1] = '\0';
list.scripts[i] = p;
p = skip(p, ',');
i++;
}
list.count = i;
free(buf);
return list;
}
@ -326,8 +326,10 @@ void mod_init()
{
int i;
char *buf = (char *)malloc(sizeof(char *) * 500);
struct script_list list = get_scripts();
struct script_list list = {0};
instance = get_bot();
list = get_scripts();
lua.scripts = calloc(512, sizeof(struct lua_script));
lua.events = calloc(1024, sizeof(struct lua_event));
@ -360,9 +362,54 @@ void mod_init()
{
printf("Loading %s\n", list.scripts[i]);
sprintf(buf, "!load %s", list.scripts[i]);
sprintf(buf, "./scripts/%s", list.scripts[i]);
strlcpy(lua.scripts[lua.script_count].fname, buf, 150);
lua_load_script(instance, "lua", "localhost", "-stdio-", buf);
if (luaL_loadfile(lua.L, buf) != LUA_OK)
{
printf("Error loading lua script: %s\n", lua_tostring(lua.L, -1));
continue;
}
// execute the script
if (lua_pcall(lua.L, 0, 0, 0) != LUA_OK)
{
printf("Error executing lua script: %s\n", lua_tostring(lua.L, -1));
continue;
}
// get a ref to unload function if it exists and store it with luaL_ref
lua_getglobal(lua.L, "unload");
if (lua_isfunction(lua.L, -1))
{
lua.scripts[lua.script_count].unload = luaL_ref(lua.L, LUA_REGISTRYINDEX);
printf("dbg: unload ref: %d\n", lua.scripts[lua.script_count].unload);
}
else
{
lua.scripts[lua.script_count].unload = -1;
printf("No unload() function in %s\n", list.scripts[i]);
}
// call the load function if it exists
lua_getglobal(lua.L, "load");
if (lua_isfunction(lua.L, -1))
{
if (lua_pcall(lua.L, 0, 0, 0) != LUA_OK)
{
printf("Error calling load() in %s: %s\n", buf, lua_tostring(lua.L, -1));
continue;
}
lua.script_count++;
printf("Loaded %s\n", list.scripts[i]);
}
else
{
printf("Error: No load() function in %s\n", buf);
}
}
printf("Lua module loaded\n");

View File

@ -63,6 +63,13 @@ void lua_fire_handlers(char *event, ...);
void lua_init_wrappers();
void raw_wrapper(lua_State *L);
void privmsg_wrapper(lua_State *L);
void notice_wrapper(lua_State *L);
void join_wrapper(lua_State *L);
void part_wrapper(lua_State *L);
void ban_wrapper(lua_State *L);
void kick_wrapper(lua_State *L);
void mode_wrapper(lua_State *L);
void ctcp_wrapper(lua_State *L);
// handlers.c
void lua_init_handlers();

View File

@ -3,3 +3,5 @@ cl /I "..\..\lib" /I "..\..\include\libconfig-1.7.3\lib" /I "..\..\include\lua5.
cl /I "..\..\lib" /I "..\..\include\libconfig-1.7.3\lib" /I "..\..\include\lua5.3\include" /c wrappers.c
cl /I "..\..\lib" /I "..\..\include\libconfig-1.7.3\lib" /I "..\..\include\lua5.3\include" /c lua.c
link /DLL /out:..\lua.dll events.obj handlers.obj wrappers.obj lua.obj ..\..\Debug\xbot.lib ..\..\include\libconfig.lib ..\..\include\lua5.3\lua53.lib
del *.obj

View File

@ -1,2 +1,2 @@
hello.lua
test.lua
hello.lua

View File

@ -4,6 +4,13 @@ void lua_init_wrappers()
{
lua_register(lua.L, "raw", raw_wrapper);
lua_register(lua.L, "privmsg", privmsg_wrapper);
lua_register(lua.L, "notice", notice_wrapper);
lua_register(lua.L, "join", join_wrapper);
lua_register(lua.L, "part", part_wrapper);
lua_register(lua.L, "ban", ban_wrapper);
lua_register(lua.L, "kick", kick_wrapper);
lua_register(lua.L, "mode", mode_wrapper);
lua_register(lua.L, "ctcp", ctcp_wrapper);
}
void raw_wrapper(lua_State *L)
@ -20,3 +27,70 @@ void privmsg_wrapper(lua_State *L)
irc_privmsg(instance, where, text);
}
void notice_wrapper(lua_State *L)
{
char *where = (char *)lua_tostring(L, 1);
char *text = (char *)lua_tostring(L, 2);
irc_notice(instance, where, text);
}
void join_wrapper(lua_State *L)
{
char *chan = (char *)lua_tostring(L, 1);
irc_join(instance, chan);
}
void part_wrapper(lua_State *L)
{
char *chan = (char *)lua_tostring(L, 1);
char *reason = (char *)lua_tostring(L, 2);
if (!reason)
{
reason = "";
}
irc_part(instance, chan, reason);
}
void ban_wrapper(lua_State *L)
{
char *chan = (char *)lua_tostring(L, 1);
char *user = (char *)lua_tostring(L, 2);
irc_ban(instance, chan, user);
}
void kick_wrapper(lua_State *L)
{
char *chan = (char *)lua_tostring(L, 1);
char *user = (char *)lua_tostring(L, 2);
char *reason = (char *)lua_tostring(L, 3);
if (!reason)
{
reason = "";
}
irc_kick(instance, chan, user, reason);
}
void mode_wrapper(lua_State *L)
{
char *chan = (char *)lua_tostring(L, 1);
char *mode = (char *)lua_tostring(L, 2);
irc_mode(instance, chan, mode);
}
void ctcp_wrapper(lua_State *L)
{
char *to = (char *)lua_tostring(L, 1);
char *msg = (char *)lua_tostring(L, 2);
va_list ap;
irc_ctcp(instance, to, msg);
}

View File

@ -41,6 +41,37 @@ struct irc_conn read_config(struct irc_conn bot, char *file)
if (config_lookup_string(cf, "bot.admin", &base))
strlcpy(bot.admin, base, sizeof bot.admin);
if (config_lookup_string(cf, "bot.db", &base))
strlcpy(bot.db_file, base, sizeof bot.db_file);
config_destroy(cf);
return bot;
}
void run_autoload(struct irc_conn *bot)
{
int count, n;
config_t cfg, *cf;
const config_setting_t *autoload;
const char *base = (const char*)malloc(sizeof(char) * 1024);
const char *mod = NULL;
char *modpath = (char *)malloc(sizeof(char) * 500);
cf = &cfg;
config_init(cf);
if (!config_read_file(cf, "xbot.cfg"))
{
printf("[xbot.cfg:%d] Configuration error: %s\n",
config_error_line(cf),
config_error_text(cf)
);
config_destroy(cf);
exit(-1);
}
autoload = config_lookup(cf, "mods.autoload");
count = config_setting_length(autoload);
@ -48,14 +79,12 @@ struct irc_conn read_config(struct irc_conn bot, char *file)
{
mod = config_setting_get_string_elem(autoload, n);
#ifdef _WIN32
sprintf(modpath, "./mods/%s.dll", mod);
sprintf(modpath, "./mods/%s.dll", mod);
#else
sprintf(modpath, "./mods/%s.so", mod);
#endif
load_module(&bot, "main", "runtime", modpath);
load_module(bot, "main", "runtime", modpath);
}
config_destroy(cf);
return bot;
}

283
src/db.c Executable file
View File

@ -0,0 +1,283 @@
#include "util.h"
#include "irc.h"
#include "db.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int db_write(struct db_table *db, char *fname)
{
FILE *fp;
int i;
char *fullpath;
if ((fp = fopen(fname, "wb")) == NULL)
{
return -1;
}
db->db_magic = DB_MAGIC;
db->db_ver = DB_VER;
// get the full path to the db file
#ifdef _WIN32
fullpath = _fullpath(NULL, fname, 0);
#else
fullpath = realpath(fname, NULL);
#endif
printf("Writing db to file: %s\n", fullpath);
// write the header
fwrite(db, sizeof(struct db_table), 1, fp);
// write the hashes
fwrite(db->hashes, sizeof(struct db_hash), db->count, fp);
// write the keys and values
for (i = 0; i < db->count; i++)
{
fwrite(db->hashes[i].key, sizeof(char), db->hashes[i].key_len, fp);
fwrite(db->hashes[i].value, sizeof(char), db->hashes[i].value_len, fp);
}
fclose(fp);
return 0;
}
struct db_table *db_read(char *fname)
{
FILE *fp;
struct db_table *db;
int tmp;
if ((fp = fopen(fname, "rb")) == NULL)
{
return NULL;
}
db = (struct db_table *)malloc(sizeof(struct db_table));
fread(db, sizeof(struct db_table), 1, fp);
// check the magic value
if (db->db_magic != DB_MAGIC)
{
printf("Error: %s incompatible or unknown db file format: Bad Magic\n", fname);
return NULL;
}
// check the version
if (db->db_ver != DB_VER)
{
printf("Error: %s incompatible or unknown db file format: Incompatible Version\n", fname);
return NULL;
}
tmp = db->count != 0 ? db->count : sizeof(struct db_hash);
db->hashes = (struct db_hash *)malloc(sizeof(struct db_hash) * tmp);
fread(db->hashes, sizeof(struct db_hash), db->count, fp);
// read the keys and values
for (tmp = 0; tmp < db->count; tmp++)
{
db->hashes[tmp].key = (char *)malloc(sizeof(char) * db->hashes[tmp].key_len);
db->hashes[tmp].value = (char *)malloc(sizeof(char) * db->hashes[tmp].value_len);
fread(db->hashes[tmp].key, sizeof(char), db->hashes[tmp].key_len, fp);
fread(db->hashes[tmp].value, sizeof(char), db->hashes[tmp].value_len, fp);
}
fclose(fp);
return db;
}
int db_set_hash(struct db_table *db, char *key, void *value)
{
int i;
// check if the key already exists and update it
for (i = 0; i < db->count; i++)
{
if (strcmp(db->hashes[i].key, key) == 0)
{
if (db->hashes[i].type == DB_TYPE_CHAR)
{
free(db->hashes[i].value);
}
db->hashes[i].value = value;
return 0;
}
}
db->hashes[db->count].key_len = strlen(key) + 1;
db->hashes[db->count].key = (char *)malloc(sizeof(char) * db->hashes[db->count].key_len);
memset(db->hashes[db->count].key, 0, sizeof(char) * db->hashes[db->count].key_len);
strlcpy(db->hashes[db->count].key, key, sizeof(char) * db->hashes[db->count].key_len);
db->hashes[db->count].value = value;
db->count++;
return 0;
}
int db_set_hash_char(struct db_table *db, char *key, char *value)
{
// check if the key already exists and update it
int i;
for (i = 0; i < db->count; i++)
{
if (strcmp(db->hashes[i].key, key) == 0)
{
if (db->hashes[i].type == DB_TYPE_CHAR)
{
free(db->hashes[i].value);
}
db->hashes[i].type = DB_TYPE_CHAR;
db->hashes[i].value_len = strlen(value) + 1;
db->hashes[i].value = (char *)malloc(sizeof(char) * db->hashes[i].value_len);
memset(db->hashes[i].value, 0, sizeof(char) * db->hashes[i].value_len);
strlcpy(db->hashes[i].value, value, sizeof(char) * db->hashes[i].value_len);
return 0;
}
}
db->hashes = (struct db_hash *)realloc(db->hashes, sizeof(struct db_hash) * (db->count + 1));
// zero out reallocated memory
memset(&db->hashes[db->count], 0, sizeof(struct db_hash));
db->hashes[db->count].type = DB_TYPE_CHAR;
db->hashes[db->count].value_len = strlen(value) + 1;
db->hashes[db->count].value = (char *)malloc(sizeof(char) * db->hashes[db->count].value_len);
memset(db->hashes[db->count].value, 0, sizeof(char) * db->hashes[db->count].value_len);
strlcpy(db->hashes[db->count].value, value, sizeof(char) * db->hashes[db->count].value_len);
return db_set_hash(db, key, db->hashes[db->count].value);
}
int db_set_hash_int(struct db_table *db, char *key, int value)
{
db->hashes = (struct db_hash *)realloc(db->hashes, sizeof(struct db_hash) * (db->count + 1));
// zero out reallocated memory
memset(&db->hashes[db->count], 0, sizeof(struct db_hash));
db->hashes[db->count].type = DB_TYPE_INT;
db->hashes[db->count].value_len = sizeof(int);
db->hashes[db->count].value = (int *)malloc(sizeof(int));
memcpy(db->hashes[db->count].value, &value, sizeof(int));
return db_set_hash(db, key, db->hashes[db->count].value);
}
int db_set_hash_float(struct db_table *db, char *key, float value)
{
db->hashes = (struct db_hash *)realloc(db->hashes, sizeof(struct db_hash) * (db->count + 1));
// zero out reallocated memory
memset(&db->hashes[db->count], 0, sizeof(struct db_hash));
db->hashes[db->count].type = DB_TYPE_FLOAT;
db->hashes[db->count].value_len = sizeof(float);
db->hashes[db->count].value = (float *)malloc(sizeof(float));
memcpy(db->hashes[db->count].value, &value, sizeof(float));
return db_set_hash(db, key, db->hashes[db->count].value);
}
int db_del_hash(struct db_table *db, char *key)
{
int i;
for (i = 0; i < db->count; i++)
{
if (strcmp(db->hashes[i].key, key) == 0)
{
free(db->hashes[i].key);
free(db->hashes[i].value);
memmove(&db->hashes[i], &db->hashes[i + 1], sizeof(struct db_hash) * (db->count - i));
db->count--;
return 0;
}
}
return -1;
}
void *db_get_hash(struct db_table *db, char *key)
{
int i;
for (i = 0; i < db->count; i++)
{
if (strcmp(db->hashes[i].key, key) == 0)
{
return db->hashes[i].value;
}
}
return NULL;
}
int db_get_hash_type(struct db_table *db, char *key)
{
int i;
for (i = 0; i < db->count; i++)
{
if (strcmp(db->hashes[i].key, key) == 0)
{
return db->hashes[i].type;
}
}
return -1;
}
char *db_get_hash_char(struct db_table *db, char *key)
{
return (char *)db_get_hash(db, key);
}
int db_get_hash_int(struct db_table *db, char *key)
{
int value;
memcpy(&value, db_get_hash(db, key), sizeof(int));
return value;
}
float db_get_hash_float(struct db_table *db, char *key)
{
float value;
memcpy(&value, db_get_hash(db, key), sizeof(float));
return value;
}

View File

@ -9,8 +9,10 @@
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include "config.h"
#include "irc.h"
#include "db.h"
#include "util.h"
#include "events.h"
#include "module.h"
@ -21,6 +23,7 @@
#include <winsock2.h>
#else
#include <sys/select.h>
#include <unistd.h>
#endif
static time_t trespond;
@ -43,13 +46,40 @@ int main()
last_ping.tv_sec = time(NULL);
set_bot(&bot);
init_events();
init_timers();
init_mods();
// Read the config
bot = read_config(bot, "xbot.cfg");
// check if the db exists, if not, create it
#ifdef _WIN32
if (access(bot.db_file, 0) == -1)
#else
if (access(bot.db_file, F_OK) == -1)
#endif
{
printf("Creating database file: %s\n", bot.db_file);
bot.db = (struct db_table *)malloc(sizeof(struct db_table));
memset(bot.db, 0, sizeof(struct db_table));
set_bot_db(bot.db);
bot.db->count = 0;
bot.db->hashes = NULL;
db_write(bot.db, bot.db_file);
}
else
{
printf("Reading database file: %s\n", bot.db_file);
bot.db = db_read(bot.db_file);
set_bot_db(bot.db);
}
// run autoload
run_autoload(&bot);
// Connect to the server
printf("Connecting to %s...\n", bot.host);

View File

@ -14,6 +14,7 @@
struct mods *mods;
struct irc_conn *instance;
struct db_table *dbinstance;
void init_mods()
{
@ -315,3 +316,13 @@ void set_bot(struct irc_conn *b)
{
instance = b;
}
void set_bot_db(struct db_table *db)
{
dbinstance = db;
}
MY_API struct db_table *get_bot_db()
{
return dbinstance;
}

View File

@ -11,7 +11,7 @@
#include <stdlib.h>
#include <ctype.h>
#include "irc.h"
#include "util.h"
void eprint(char *fmt, ...)
{
@ -30,7 +30,7 @@ void eprint(char *fmt, ...)
}
#if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 38)) || defined(_WIN32)
MY_API void strlcpy(char *to, const char *from, int len)
void strlcpy(char *to, const char *from, int len)
{
memccpy(to, from, '\0', len);
to[len-1] = '\0';
@ -38,14 +38,14 @@ MY_API void strlcpy(char *to, const char *from, int len)
#endif
#ifdef _WIN32
MY_API char *basename(char *path)
char *basename(char *path)
{
char *p = strrchr(path, '\\');
return p ? p + 1 : path;
}
#endif
MY_API char *skip(char *s, char c)
char *skip(char *s, char c)
{
while (*s != c && *s != '\0')
{

View File

@ -6,6 +6,8 @@ bot:
nick = "xbot";
user = "xbot";
admin = "ab3800";
db = "xbot.db";
};
server:

View File

@ -105,6 +105,7 @@
<ItemGroup>
<ClInclude Include="lib\channel.h" />
<ClInclude Include="lib\config.h" />
<ClInclude Include="lib\db.h" />
<ClInclude Include="lib\events.h" />
<ClInclude Include="lib\irc.h" />
<ClInclude Include="lib\module.h" />
@ -114,6 +115,7 @@
<ItemGroup>
<ClCompile Include="src\channel.c" />
<ClCompile Include="src\config.c" />
<ClCompile Include="src\db.c" />
<ClCompile Include="src\events.c" />
<ClCompile Include="src\irc.c" />
<ClCompile Include="src\main.c" />