diff --git a/lib/config.h b/lib/config.h index 5b682a1..e21bbfc 100755 --- a/lib/config.h +++ b/lib/config.h @@ -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 \ No newline at end of file +#endif diff --git a/lib/db.h b/lib/db.h index 3aecbf1..ca686af 100755 --- a/lib/db.h +++ b/lib/db.h @@ -7,7 +7,8 @@ enum db_type { DB_TYPE_CHAR, - DB_TYPE_INT + DB_TYPE_INT, + DB_TYPE_FLOAT }; struct db_hash @@ -29,17 +30,21 @@ struct db_table struct db_hash *hashes; }; -int write_db(struct db_table *db, char *fname); -struct db_table *read_db(char *fname); +int db_write(struct db_table *db, char *fname); +struct db_table *db_read(char *fname); -int db_add_hash(struct db_table *db, char *key, void *value); -int db_add_hash_char(struct db_table *db, char *key, char *value); -int db_add_hash_int(struct db_table *db, char *key, int value); +int db_set_hash(struct db_table *db, char *key, void *value); +int db_set_hash_char(struct db_table *db, char *key, char *value); +int db_set_hash_int(struct db_table *db, char *key, int value); +int db_set_hash_float(struct db_table *db, char *key, float value); int db_del_hash(struct db_table *db, char *key); -void *get_hash(struct db_table *db, char *key); -char *get_hash_char(struct db_table *db, char *key); -int get_hash_int(struct db_table *db, char *key); +void *db_get_hash(struct db_table *db, char *key); +int db_get_hash_type(struct db_table *db, char *key); + +char *db_get_hash_char(struct db_table *db, char *key); +int db_get_hash_int(struct db_table *db, char *key); +float db_get_hash_float(struct db_table *db, char *key); #endif diff --git a/lib/module.h b/lib/module.h index cf6efce..1da0d40 100755 --- a/lib/module.h +++ b/lib/module.h @@ -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 diff --git a/mods/lua/lua.c b/mods/lua/lua.c index 4faeb86..a8039fb 100755 --- a/mods/lua/lua.c +++ b/mods/lua/lua.c @@ -17,102 +17,106 @@ 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"); + printf("dbug: scriptlist: %s\n", scriptlist); + + // dbug: scriptlist: hello.lua,test.lua,youtube.lua + + 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 +330,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 +366,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"); diff --git a/scripts/t1.lua b/scripts/t1.lua new file mode 100755 index 0000000..e69de29 diff --git a/src/config.c b/src/config.c index 22698cc..f8b953a 100755 --- a/src/config.c +++ b/src/config.c @@ -44,6 +44,34 @@ struct irc_conn read_config(struct irc_conn bot, char *file) 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); @@ -51,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; } diff --git a/src/db.c b/src/db.c index 0c3eeaf..cebfcb0 100755 --- a/src/db.c +++ b/src/db.c @@ -6,7 +6,7 @@ #include #include -int write_db(struct db_table *db, char *fname) +int db_write(struct db_table *db, char *fname) { FILE *fp; int i; @@ -37,7 +37,7 @@ int write_db(struct db_table *db, char *fname) return 0; } -struct db_table *read_db(char *fname) +struct db_table *db_read(char *fname) { FILE *fp; struct db_table *db; @@ -89,15 +89,23 @@ struct db_table *read_db(char *fname) return db; } -int db_add_hash(struct db_table *db, char *key, void *value) +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) { - return -1; + if (db->hashes[i].type == DB_TYPE_CHAR) + { + free(db->hashes[i].value); + } + + db->hashes[i].value = value; + + return 0; } } @@ -115,8 +123,33 @@ int db_add_hash(struct db_table *db, char *key, void *value) return 0; } -int db_add_hash_char(struct db_table *db, char *key, char *value) + +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 @@ -130,10 +163,10 @@ int db_add_hash_char(struct db_table *db, char *key, char *value) strlcpy(db->hashes[db->count].value, value, sizeof(char) * db->hashes[db->count].value_len); - return db_add_hash(db, key, db->hashes[db->count].value); + return db_set_hash(db, key, db->hashes[db->count].value); } -int db_add_hash_int(struct db_table *db, char *key, int 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)); @@ -146,7 +179,23 @@ int db_add_hash_int(struct db_table *db, char *key, int value) memcpy(db->hashes[db->count].value, &value, sizeof(int)); - return db_add_hash(db, key, db->hashes[db->count].value); + 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) @@ -169,7 +218,7 @@ int db_del_hash(struct db_table *db, char *key) return -1; } -void *get_hash(struct db_table *db, char *key) +void *db_get_hash(struct db_table *db, char *key) { int i; @@ -184,16 +233,40 @@ void *get_hash(struct db_table *db, char *key) return NULL; } -char *get_hash_char(struct db_table *db, char *key) +int db_get_hash_type(struct db_table *db, char *key) { - return (char *)get_hash(db, 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; } -int get_hash_int(struct db_table *db, char *key) +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, get_hash(db, key), sizeof(int)); + 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; } diff --git a/src/main.c b/src/main.c index ba166b2..95b9a4f 100755 --- a/src/main.c +++ b/src/main.c @@ -46,30 +46,37 @@ 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 if (access(bot.db_file, F_OK) == -1) { - printf("Creating db\n"); + 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; - write_db(bot.db, bot.db_file); + db_write(bot.db, bot.db_file); } else { - bot.db = read_db(bot.db_file); + 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); diff --git a/src/module.c b/src/module.c index 0696ec6..3c0e315 100755 --- a/src/module.c +++ b/src/module.c @@ -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; +} diff --git a/test_db.c b/test_db.c index df2d54a..3dc4f3f 100755 --- a/test_db.c +++ b/test_db.c @@ -27,8 +27,9 @@ int main() // write some data if db is empty if (db->count == 0) { - db_add_hash_char(db, "lua.scripts", "hello.lua,test.lua,youtube.lua"); - db_add_hash_int(db, "lua.scriptcount", 2); + db_set_hash_char(db, "lua.scripts", "hello.lua,test.lua,youtube.lua"); + db_set_hash_int(db, "lua.scriptcount", 2); + db_set_hash_float(db, "lua.version", 5.1); write_db(db, FNAME); return 0; @@ -40,7 +41,11 @@ int main() { printf("Key: %s, Value: %d\n", db->hashes[i].key, get_hash_int(db, db->hashes[i].key)); } - else + else if (db->hashes[i].type == DB_TYPE_FLOAT) + { + printf("Key: %s, Value: %f\n", db->hashes[i].key, get_hash_float(db, db->hashes[i].key)); + } + else if (db->hashes[i].type == DB_TYPE_CHAR) { printf("Key: %s, Value: %s\n", db->hashes[i].key, get_hash_char(db, db->hashes[i].key)); } diff --git a/testdb b/testdb index 5a58f5a..479996c 100755 Binary files a/testdb and b/testdb differ diff --git a/xbot.db b/xbot.db old mode 100644 new mode 100755 index 7c75e0d..973d318 Binary files a/xbot.db and b/xbot.db differ