/***************************************************************************/ /** he_helpsys.c ****************** Author: GeniusDex ** Version: 1.1.2 **/ /***************************************************************************/ /* */ /* This module makes HelpServ a bit more usefull by adding the possibility */ /* to add your own help to HelpServ. It should allow you to use files and */ /* on-the-fly added sentences as helptexts to HelpServ. */ /* */ /* Configuration is below the version history. */ /* */ /***************************************************************************/ /***************************************************************************/ /** CHANGES ***************************************** VERSION HISTORY **/ /***************************************************************************/ /*** 1.1.2 ************************************************** 2004/05/13 ***/ /* -Changed the db loading code to be more crash-proof(tm) by some hints */ /* of codemastr */ /* -Removed a bogus notice on first load by hidin it if no db is found */ /* -Fixed a few compiler warnings */ /*** 1.1.1 ************************************************** 2003/11/13 ***/ /* -Added comments in the source to make it more readable */ /* -Removed a bogus function definition */ /* -Speeded up the adding of helpwords by adding them to the head of the */ /* linked list, instead of to the end */ /* -Fixed a segfault when mod_current_user was NULL */ /*** 1.1.0 ************************************************** 2003/11/10 ***/ /* -Added optional /msg HelpServ to look up helpwords */ /* -Fixed a segfault when using /msg HelpServ READ without params */ /* -Fixed all sorts of memleaks, as i didn't free() my sstrdup'd *char's */ /*** 1.0.2 ************************************************** 2003/11/03 ***/ /* -Changed database split codes to allow underlines */ /* -Changed ifs with only #defines to #ifs */ /*** 1.0.1 ************************************************** 2003/11/03 ***/ /* -Removed some debug output */ /* -Fixed possible bug on deleting a record */ /* -Added "DB" command */ /* -Added error notices when unable to load/save database on */ /* modload/modunload */ /*** 1.0.0 ************************************************** 2003/11/02 ***/ /* -Initial release */ /***************************************************************************/ /***************************************************************************/ /** CONFIGURATION ************************************* CONFIGURATION **/ /***************************************************************************/ /* HE_HS_DB_FILE ***********************************************************/ /************** */ /* Set this directive to the filename which should be used as the */ /* helpwords database. */ /***************************************************************************/ #define HE_HS_DB_FILE "helpwords.db" /***************************************************************************/ /* HE_HS_DIR ***************************************************************/ /************** */ /* Set this directive to the directory containing the optional help files. */ /* Please make sure the trailing slash is in place. */ /***************************************************************************/ #define HE_HS_DIR "helpserv/" /***************************************************************************/ /* HE_HS_ACCESS_IRC ********************************************************/ /********************* */ /* Set this directive to the minimum services oper level required to add */ /* help texts on the fly using IRC. */ /* */ /* Available oper levels are: */ /* OPER_OPER User is a Services Operator */ /* OPER_ADMIN User is a Services Admin */ /* OPER_ROOT User is a Services Root */ /***************************************************************************/ #define HE_HS_ACCESS_IRC OPER_ADMIN /***************************************************************************/ /* HE_HS_ACCESS_FILE *******************************************************/ /********************** */ /* Set this directive to the minimum services oper level required to add */ /* help texts from IRC whose contents are in a file on the disk. */ /* */ /* Available oper levels are: */ /* OPER_OPER User is a Services Operator */ /* OPER_ADMIN User is a Services Admin */ /* OPER_ROOT User is a Services Root */ /***************************************************************************/ #define HE_HS_ACCESS_FILE OPER_ROOT /***************************************************************************/ /* HE_HS_ACCESS_DEL ********************************************************/ /********************* */ /* Set this directive to the minimum services oper level required to */ /* delete help texts. */ /* */ /* Available oper levels are: */ /* OPER_OPER User is a Services Operator */ /* OPER_ADMIN User is a Services Admin */ /* OPER_ROOT User is a Services Root */ /***************************************************************************/ #define HE_HS_ACCESS_DEL OPER_ROOT /***************************************************************************/ /* HE_HS_ACCESS_DB *********************************************************/ /******************** */ /* Set this directive to the minimum services oper level required to */ /* get info on, load, or save the helpsys database. */ /* */ /* Available oper levels are: */ /* OPER_OPER User is a Services Operator */ /* OPER_ADMIN User is a Services Admin */ /* OPER_ROOT User is a Services Root */ /***************************************************************************/ #define HE_HS_ACCESS_DB OPER_ROOT /***************************************************************************/ /* HE_HS_USE_COMMANDS ******************************************************/ /*********************** */ /* Define this directive (#define HE_HS_USE_COMMANDS) to be able to use */ /* /msg HelpServ to look up a helpword. If you undefine this */ /* directive (#undef HE_HS_USE_COMMANDS) you can only use */ /* /msg HelpServ READ to look up helpwords. */ /***************************************************************************/ #define HE_HS_USE_COMMANDS /***************************************************************************/ /** END OF CONFIGURATION *************************** END OF CONFIGURATION **/ /****************** Don't change anything below this line ******************/ /***************************************************************************/ #include "module.h" #define AUTHOR "GeniusDex" #define VERSION "1.1.2" #define OPER_NOREG 0 #define OPER_USER 1 #define OPER_OPER 2 #define OPER_ADMIN 3 #define OPER_ROOT 4 #define SPLIT_RECORD 14 #define SPLIT_FIELD 15 #define IS_FILE 78 #define IS_VALUE 89 typedef struct HelpWord_ HelpWord; struct HelpWord_ { int id; char *helpword; char *file; char *value; HelpWord *prev; HelpWord *next; }; int hw_ll_max_id = 0; HelpWord *hw_ll_head = NULL; extern User *mod_current_user; int he_hs_add(User * u); int he_hs_addfile(User * u); int he_hs_del(User * u); int he_hs_find(User * u); int he_hs_read(User * u); int he_hs_db(User * u); #ifdef HE_HS_USE_COMMANDS int he_hs_privmsg(char *source, int ac, char **av); int he_hs_pmsg(User * u, char *buf); #endif int hw_ll_add(char *helpword, char *file, char *value); int hw_ll_del(HelpWord *hw_ll_cur); HelpWord *hw_ll_get(int id, char *helpword); HelpWord *hw_ll_find(HelpWord *hw_ll_start, char *mask); char *read_file(char *file); int save_hw_ll(void); int load_hw_ll(void); int hw_ll_save_callback(int argc, char **argv); void he_hs_helpserv_help(User * u); int he_hs_add_help(User * u); int he_hs_addfile_help(User * u); int he_hs_del_help(User * u); int he_hs_find_help(User * u); int he_hs_read_help(User * u); int he_hs_db_help(User * u); int AnopeInit(int argc, char **argv) { Command *c_add; Command *c_addfile; Command *c_del; Command *c_read; Command *c_find; Command *c_db; #ifdef HE_HS_USE_COMMANDS Message *m_privmsg; #endif int loadstate; /* Per function check rights and add the command/help */ #if (HE_HS_ACCESS_IRC == OPER_OPER) c_add = createCommand("add", he_hs_add, is_services_oper, -1, -1, -1, -1, -1); moduleAddOperHelp(c_add,he_hs_add_help); moduleAddAdminHelp(c_add,he_hs_add_help); moduleAddRootHelp(c_add,he_hs_add_help); #elif (HE_HS_ACCESS_IRC == OPER_ADMIN) c_add = createCommand("add", he_hs_add, is_services_admin, -1, -1, -1, -1, -1); moduleAddAdminHelp(c_add,he_hs_add_help); moduleAddRootHelp(c_add,he_hs_add_help); #elif (HE_HS_ACCESS_IRC == OPER_ROOT) c_add = createCommand("add", he_hs_add, is_services_root, -1, -1, -1, -1, -1); moduleAddRootHelp(c_add,he_hs_add_help); #else alog("he_helpsys.c: Unknown HE_HS_ACCESS_IRC"); return MOD_STOP; #endif #if (HE_HS_ACCESS_FILE == OPER_OPER) c_addfile = createCommand("addfile", he_hs_addfile, is_services_oper, -1, -1, -1, -1, -1); moduleAddOperHelp(c_addfile,he_hs_addfile_help); moduleAddAdminHelp(c_addfile,he_hs_addfile_help); moduleAddRootHelp(c_addfile,he_hs_addfile_help); #elif (HE_HS_ACCESS_FILE == OPER_ADMIN) c_addfile = createCommand("addfile", he_hs_addfile, is_services_admin, -1, -1, -1, -1, -1); moduleAddAdminHelp(c_addfile,he_hs_addfile_help); moduleAddRootHelp(c_addfile,he_hs_addfile_help); #elif (HE_HS_ACCESS_FILE == OPER_ROOT) c_addfile = createCommand("addfile", he_hs_addfile, is_services_root, -1, -1, -1, -1, -1); moduleAddRootHelp(c_addfile,he_hs_addfile_help); #else alog("he_helpsys.c: Unknown HE_HS_ACCESS_FILE"); return MOD_STOP; #endif #if (HE_HS_ACCESS_DEL == OPER_OPER) c_del = createCommand("del", he_hs_del, is_services_oper, -1, -1, -1, -1, -1); moduleAddOperHelp(c_del,he_hs_del_help); moduleAddAdminHelp(c_del,he_hs_del_help); moduleAddRootHelp(c_del,he_hs_del_help); #elif (HE_HS_ACCESS_DEL == OPER_ADMIN) c_del = createCommand("del", he_hs_del, is_services_admin, -1, -1, -1, -1, -1); moduleAddAdminHelp(c_del,he_hs_del_help); moduleAddRootHelp(c_del,he_hs_del_help); #elif (HE_HS_ACCESS_DEL == OPER_ROOT) c_del = createCommand("del", he_hs_del, is_services_root, -1, -1, -1, -1, -1); moduleAddRootHelp(c_del,he_hs_del_help); #else alog("he_helpsys.c: Unknown HE_HS_ACCESS_DEL"); return MOD_STOP; #endif #if (HE_HS_ACCESS_DB == OPER_OPER) c_db = createCommand("db", he_hs_db, is_services_oper, -1, -1, -1, -1, -1); moduleAddOperHelp(c_db,he_hs_db_help); moduleAddAdminHelp(c_db,he_hs_db_help); moduleAddRootHelp(c_db,he_hs_db_help); #elif (HE_HS_ACCESS_DB == OPER_ADMIN) c_db = createCommand("db", he_hs_db, is_services_admin, -1, -1, -1, -1, -1); moduleAddAdminHelp(c_db,he_hs_db_help); moduleAddRootHelp(c_db,he_hs_db_help); #elif (HE_HS_ACCESS_DB == OPER_ROOT) c_db = createCommand("db", he_hs_db, is_services_root, -1, -1, -1, -1, -1); moduleAddRootHelp(c_db,he_hs_db_help); #else alog("he_helpsys.c: Unknown HE_HS_ACCESS_DB"); return MOD_STOP; #endif c_find = createCommand("find", he_hs_find, NULL, -1, -1, -1, -1, -1); moduleAddHelp(c_find,he_hs_find_help); c_read = createCommand("read", he_hs_read, NULL, -1, -1, -1, -1, -1); moduleAddHelp(c_read,he_hs_read_help); moduleSetHelpHelp(he_hs_helpserv_help); /* Do your thing! */ alog("he_helpsys.c: Adding Commands add(%d) addfile(%d) del(%d) find(%d) read(%d) db(%d)", moduleAddCommand(HELPSERV, c_add, MOD_HEAD), moduleAddCommand(HELPSERV, c_addfile, MOD_HEAD), moduleAddCommand(HELPSERV, c_del, MOD_HEAD), moduleAddCommand(HELPSERV, c_find, MOD_HEAD), moduleAddCommand(HELPSERV, c_read, MOD_HEAD), moduleAddCommand(HELPSERV, c_db, MOD_HEAD)); /* For use with the helpword-commands i need a privmsg handler */ #ifdef HE_HS_USE_COMMANDS m_privmsg = createMessage("PRIVMSG", he_hs_privmsg); moduleAddMessage(m_privmsg, MOD_HEAD); #endif /* Add callback to save dbases */ moduleAddCallback("hw_ll_save_callback", time(NULL)+UpdateTimeout, hw_ll_save_callback, 0, NULL); alog("he_helpsys.c: Added Database Save Callback (%ds)", UpdateTimeout); /* My module! */ moduleAddAuthor(AUTHOR); moduleAddVersion(VERSION); /* Load dbases */ loadstate = load_hw_ll(); if (loadstate == 1) { alog("he_helpsys.c: Succesfully loaded database"); } else if (loadstate == 0) { alog("he_helpsys.c: Failed loading database"); if (mod_current_user) notice(s_HelpServ, mod_current_user->nick, "Failed loading HelpSys database. If it exists, please use \002/MSG %s DB LOAD\002 to try to load it again", s_HelpServ); } else if (loadstate == -1) { alog("he_helpsys.c: Unable to open database"); } else { alog("he_helpsys.c: load_hw_ll() returned an unknown value"); } return MOD_CONT; } void AnopeFini(void) { /* Save dbases */ if (!save_hw_ll()) notice(s_HelpServ, mod_current_user->nick, "Failed saving HelpSys database. Any recent changes have been lost"); /* Empty mem */ while (hw_ll_head != NULL) hw_ll_del(hw_ll_head); alog("he_helpsys.c unloaded"); } /* Core functions */ int he_hs_add(User * u) { /* Add a helpword */ char *helpword; char *value; helpword = strtok(NULL, " "); value = strtok(NULL, ""); if ((helpword == NULL) || (value == NULL)) return he_hs_add_help(u); if (hw_ll_get(0, helpword) == NULL) notice(s_HelpServ, u->nick, "Helpword \002%s\002 added as helpword #%d", helpword, hw_ll_add(helpword, NULL, value)); else notice(s_HelpServ, u->nick, "Helpword \002%s\002 already exists", helpword); return MOD_CONT; } int he_hs_addfile(User * u) { /* Add a helpword with contents from a file */ char *helpword; char *file; char *value; helpword = strtok(NULL, " "); file = strtok(NULL, " "); if ((helpword == NULL) || (file == NULL)) return he_hs_addfile_help(u); if (hw_ll_get(0, helpword) == NULL) { /* Add it! */ if ((value = read_file(file)) == NULL) { notice(s_HelpServ, u->nick, "Unable to read file \002%s\002 (%d)", file, errno); } else { notice(s_HelpServ, u->nick, "Helpword \002%s\002 added as helpword #%d", helpword, hw_ll_add(helpword, file, value)); } } else { notice(s_HelpServ, u->nick, "Helpword \002%s\002 already exists", helpword); } return MOD_CONT; } int he_hs_del(User * u) { /* Delete a helpword */ char *helpword; HelpWord *hw_ll_target; helpword = strtok(NULL, " "); if (helpword == NULL) return he_hs_del_help(u); /* See if it exists first though */ hw_ll_target = hw_ll_get(0, helpword); if (hw_ll_target == NULL) { notice(s_HelpServ, u->nick, "Helpword \002%s\002 not found", helpword); } else { /* Else we can delete! */ if (hw_ll_del(hw_ll_target)) notice(s_HelpServ, u->nick, "Helpword \002%s\002 deleted", helpword); else notice(s_HelpServ, u->nick, "Unable to delete helpword \002%s\002", helpword); } return MOD_CONT; } int he_hs_find(User * u) { /* Search for a helpword */ HelpWord *hw_ll_target; int results; char *mask; mask = strtok(NULL, " "); if (mask == NULL) return he_hs_find_help(u); hw_ll_target = hw_ll_find(hw_ll_head, mask);; /* Do the correct for loop, max of NSListMax results, blablabla */ for (results = 0; results < NSListMax; results++) { /* All results found! as hw_ll_find returns NULL when all are found */ if (hw_ll_target == NULL) { if (results == 0) { notice(s_HelpServ, u->nick, "No results found (search for \002%s\002)", mask); return MOD_CONT; } else { notice(s_HelpServ, u->nick, "All results displayed"); return MOD_CONT; } /* Another result! display it :P */ } else { if (results == 0) { notice(s_HelpServ, u->nick, "Results on helpword search for \002%s\002:", mask); notice(s_HelpServ, u->nick, " ID Helpword"); } notice(s_HelpServ, u->nick, " %-6d %s", hw_ll_target->id, hw_ll_target->helpword); } /* And search the next result... */ hw_ll_target = hw_ll_find(hw_ll_target->next, mask); } notice(s_HelpServ, u->nick, "There are more results than the %d shown. Please narrow down your search.", NSListMax); return MOD_CONT; } int he_hs_read(User * u) { /* Read out a helpword using the READ command */ HelpWord *hw_ll_target; char *helpword; char *line; char *value; helpword = strtok(NULL, " "); if (helpword == NULL) return he_hs_read_help(u); /* See if the helpword exists first, or we wouldn't have much to display */ hw_ll_target = hw_ll_get(0, helpword); if (hw_ll_target == NULL) { notice(s_HelpServ, u->nick, "Helpword \002%s\002 not found", helpword); } else { value = sstrdup(hw_ll_target->value); line = strtok(value, "\n"); if (stricmp(hw_ll_target->value, line) == 0) { notice(s_HelpServ, u->nick, "\002%s\002: %s", hw_ll_target->helpword, value); } else { notice(s_HelpServ, u->nick, "%s", line); while ((line = strtok(NULL, "\n"))) { notice(s_HelpServ, u->nick, "%s", line); } } /* Free willy! ermm, your allocated space i mean */ free(value); } return MOD_CONT; } int he_hs_db(User * u) { /* Database manipulation and stats */ char *action; FILE *fp; action = strtok(NULL, " "); if (!action) { /* Database stats is the chosen one */ notice(s_HelpServ, u->nick, "HelpSys Database Status:"); if ((fp = fopen(HE_HS_DB_FILE, "r")) == NULL) { notice(s_HelpServ, u->nick, " Able to read: NO"); } else { notice(s_HelpServ, u->nick, " Able to read: YES"); fclose(fp); } if ((fp = fopen(HE_HS_DB_FILE, "w")) == NULL) { notice(s_HelpServ, u->nick, " Able to write: NO"); } else { notice(s_HelpServ, u->nick, " Able to write: YES"); fclose(fp); } } else if (stricmp(action, "LOAD") == 0) { /* Load in the database */ if (load_hw_ll() == 1) notice(s_HelpServ, u->nick, "Succesfully loaded HelpSys database"); else notice(s_HelpServ, u->nick, "Failed loading HelpSys database"); } else if (stricmp(action, "SAVE") == 0) { /* Save the database! */ if (save_hw_ll()) notice(s_HelpServ, u->nick, "Succesfully saved HelpSys database"); else notice(s_HelpServ, u->nick, "Failed saving HelpSys database"); } else { /* We don't know how to use this function, show me the help! */ return he_hs_db_help(u); } return MOD_CONT; } #ifdef HE_HS_USE_COMMANDS /* Message functions */ int he_hs_privmsg(char *source, int ac, char **av) { /* Our own PRIVMSG handler! */ char *s; User *u; IgnoreData *ign; /* Sanity checks (args, user, non-chan message) */ if ((ac != 2) || (!(u = finduser(source))) || (*av[0] == '#')) return MOD_CONT; /* Ignore checks */ if (allow_ignore && !is_oper(u) && (ign = get_ignore(source)) && (ign->time > time(NULL))) return MOD_CONT; /* Server checks */ if ((s = strchr(av[0], '@'))) { *s++ = 0; if (stricmp(s, ServerName) != 0) return MOD_CONT; } /* See if it's for helpserv, if it is pass it to our second function :) */ if ((stricmp(av[0], s_HelpServ) == 0) || (s_HelpServAlias && (stricmp(av[0], s_HelpServAlias) == 0))) return he_hs_pmsg(u, sstrdup(av[1])); return MOD_CONT; } int he_hs_pmsg(User * u, char *buf) { /* And this function handles the contents of the PRIVMSG */ char *cmd; char *line; char *value; char *bkbr; char *bkbv; HelpWord *hw_ll_target; bkbr = NULL; bkbv = NULL; cmd = strtok_r(buf, " ", &bkbr); /* Let's see if i should pass it to the main handling loop */ if ((!cmd) || (stricmp(cmd, "\1PING") == 0) || (skeleton) || (findCommand(HELPSERV, cmd)) || (!(hw_ll_target = hw_ll_get(0,cmd)))) { free(buf); return MOD_CONT; } else { /* Naw, i'll handle it (a valid helpword, which is no helpserv command */ value = sstrdup(hw_ll_target->value); line = strtok_r(value, "\n", &bkbv); if (stricmp(hw_ll_target->value, line) == 0) { notice(s_HelpServ, u->nick, "\002%s\002: %s", hw_ll_target->helpword, value); } else { notice(s_HelpServ, u->nick, "%s", line); while ((line = strtok_r(NULL, "\n", &bkbv))) { notice(s_HelpServ, u->nick, "%s", line); } } free(buf); /* I dislike memleaks... */ return MOD_STOP; } } #endif /* Linked List functions */ int hw_ll_add(char *helpword, char *file, char *value) { /* Add a helpword to the linked list */ HelpWord *hw_ll_cur; int new_id; /* Allocate */ hw_ll_cur = smalloc(sizeof(HelpWord)); /* And fill with data */ new_id = ++hw_ll_max_id; hw_ll_cur->id = new_id; hw_ll_cur->helpword = sstrdup(helpword); hw_ll_cur->file = (file == NULL) ? NULL : sstrdup(file); hw_ll_cur->value = sstrdup(value); hw_ll_cur->prev = NULL; hw_ll_cur->next = hw_ll_head; /* Give it a place at the start of the linked list */ /* Adding it to the end consumes more CPU power */ hw_ll_head = hw_ll_cur; hw_ll_head->prev = hw_ll_cur; return new_id; } int hw_ll_del(HelpWord *hw_ll_cur) { /* Delete a helpword from the linked list */ /* First we update the linked list */ if (hw_ll_head == hw_ll_cur) hw_ll_head = hw_ll_cur->next; else hw_ll_cur->prev->next = hw_ll_cur->next; /* Then we free our allocated mem as memleaks suck badly */ if (hw_ll_cur->helpword) free(hw_ll_cur->helpword); if (hw_ll_cur->file) free(hw_ll_cur->file); if (hw_ll_cur->value) free(hw_ll_cur->value); free(hw_ll_cur); /* And it disappeared! Without a puff of smoke though, i'm not an effects man */ return 1; } HelpWord *hw_ll_get(int id, char *helpword) { /* Get a helpword from the list! */ HelpWord *hw_ll_cur; char loop = 1; /* Ofcourse this only works if we HAVE a linked list */ if (hw_ll_head == NULL) return NULL; hw_ll_cur = hw_ll_head; /* Now search for it... */ while (loop) { if ((hw_ll_cur->id == id) || (stricmp(hw_ll_cur->helpword,helpword) == 0)) { loop = 0; } else { hw_ll_cur = hw_ll_cur->next; if (hw_ll_cur == NULL) loop = 0; } } /* And return it */ return hw_ll_cur; } HelpWord *hw_ll_find(HelpWord *hw_ll_start, char *mask) { /* Lookup a helpword! */ int loop; HelpWord *hw_ll_cur; char *value; char *word; char *bkbf; /* See if we can start somewhere */ if (hw_ll_start == NULL) return NULL; loop = 1; hw_ll_cur = hw_ll_start; /* Main search loop! */ while (loop) { /* See if we have a match already */ if ((hw_ll_cur == NULL) || (stricmp(hw_ll_cur->helpword, mask) == 0)) { /* We do! or we arrived at the end. Anyways, return it */ loop = 0; } else { /* We don't at first, we might have a second chance! */ value = sstrdup(hw_ll_cur->value); word = strtok_r(value, " \n", &bkbf); if (stricmp(word, mask) == 0) { loop = 0; } else { while (word != NULL) { if (stricmp(word,mask) == 0) { /* Phew, our second chance gave us a mtch */ word = NULL; loop = 0; } else { word = strtok_r(NULL, " \n", &bkbf); } } } free(value); } if (loop) /* No match, loop for the next */ hw_ll_cur = hw_ll_cur->next; } return hw_ll_cur; } /* Disk functions */ char *read_file(char *file) { int malloc_size; char *path_file; char *contents; char *temp; char line[512]; FILE *fp; malloc_size = strlen(SERVICES_DIR) + strlen(HE_HS_DIR) + strlen(file) + 5; path_file = smalloc(malloc_size); strncpy(path_file, SERVICES_DIR, (strlen(SERVICES_DIR) + 1)); strcat(path_file, "/"); strncat(path_file, HE_HS_DIR, strlen(HE_HS_DIR)); strncat(path_file, file, strlen(file)); if ((fp = fopen(path_file, "r")) == NULL) { free(path_file); return NULL; } malloc_size = 1; contents = NULL; while (fgets((char *)&line, 512, fp)) { malloc_size += strlen(line); if (contents != NULL) { temp = contents; contents = smalloc(malloc_size); strncpy(contents, temp, malloc_size); strncat(contents, line, malloc_size); free(temp); } else { contents = smalloc(malloc_size); strncpy(contents, line, malloc_size); } } if (!feof(fp)) { fclose(fp); free(contents); free(path_file); return NULL; } fclose(fp); free(path_file); return contents; } int save_hw_ll(void) { HelpWord *hw_ll_cur; FILE *fp; if ((fp = fopen(HE_HS_DB_FILE, "w")) == NULL) return 0; hw_ll_cur = hw_ll_head; while (hw_ll_cur != NULL) { fprintf(fp, "%s%c", hw_ll_cur->helpword, SPLIT_FIELD); fprintf(fp, "%c%c", ((hw_ll_cur->file == NULL) ? IS_VALUE : IS_FILE), SPLIT_FIELD); fprintf(fp, "%s%c", ((hw_ll_cur->file == NULL) ? hw_ll_cur->value : hw_ll_cur->file), SPLIT_RECORD); hw_ll_cur = hw_ll_cur->next; } fclose(fp); return 1; } int load_hw_ll(void) { int malloc_size; char *contents; char *temp; char *record; char *helpword; char *file; char *value; char *bkbr; char *bkbf; char line[512]; char sep[3][2]; FILE *fp; if ((fp = fopen(HE_HS_DB_FILE, "r")) == NULL) { return -1; } malloc_size = 1; contents = NULL; while (fgets(line, 512, fp)) { malloc_size += strlen(line); if (contents != NULL) { temp = contents; contents = smalloc(malloc_size); strncpy(contents, temp, malloc_size); strncat(contents, line, malloc_size); free(temp); } else { contents = smalloc(malloc_size); strncpy(contents, line, malloc_size); } } if (!contents) { fclose(fp); return 0; } if (!feof(fp)) { free(contents); fclose(fp); return 0; } fclose(fp); sprintf(sep[0], "%c", SPLIT_RECORD); sprintf(sep[1], "%c", SPLIT_FIELD); sprintf(sep[2], "%c", IS_FILE); record = strtok_r(contents, sep[0], &bkbr); while (record) { if ((helpword = strtok_r(record, sep[1], &bkbf)) && (temp = strtok_r(NULL, sep[1], &bkbf)) && (value = strtok_r(NULL, sep[1], &bkbf))) { file = NULL; if (!stricmp(temp, sep[2])) { file = value; value = NULL; } if ((file != NULL) && ((value = read_file(file)) == NULL)) alog("Unable to read file \002%s\002 (%d)", file, errno); if (value != NULL) hw_ll_add(helpword, file, value); } record = strtok_r(NULL, sep[0], &bkbr); } return 1; } /* Callback functions */ int hw_ll_save_callback(int argc, char **argv) { /* Our database save callback. Add a new callback and save! */ moduleAddCallback("hw_ll_save_callback", time(NULL)+UpdateTimeout, hw_ll_save_callback, argc, argv); if (save_hw_ll()) return MOD_CONT; else return MOD_STOP; } /* HELP functions */ void he_hs_helpserv_help(User *u) { notice(s_HelpServ, u->nick, " READ Read the specified help item"); notice(s_HelpServ, u->nick, " FIND Search for a help item"); #if (HE_HS_ACCESS_IRC == OPER_OPER) if (is_services_oper(u)) notice(s_HelpServ, u->nick, " ADD Add a help item"); #elif (HE_HS_ACCESS_IRC == OPER_ADMIN) if (is_services_admin(u)) notice(s_HelpServ, u->nick, " ADD Add a help item"); #elif (HE_HS_ACCESS_IRC == OPER_ROOT) if (is_services_root(u)) notice(s_HelpServ, u->nick, " ADD Add a help item"); #endif #if (HE_HS_ACCESS_FILE == OPER_OPER) if (is_services_oper(u)) notice(s_HelpServ, u->nick, " ADDFILE Add a help item from a file"); #elif (HE_HS_ACCESS_FILE == OPER_ADMIN) if (is_services_admin(u)) notice(s_HelpServ, u->nick, " ADDFILE Add a help item from a file"); #elif (HE_HS_ACCESS_FILE == OPER_ROOT) if (is_services_root(u)) notice(s_HelpServ, u->nick, " ADDFILE Add a help item from a file"); #endif #if (HE_HS_ACCESS_DEL == OPER_OPER) if (is_services_oper(u)) notice(s_HelpServ, u->nick, " DEL Delete a help item"); #elif (HE_HS_ACCESS_DEL == OPER_ADMIN) if (is_services_admin(u)) notice(s_HelpServ, u->nick, " DEL Delete a help item"); #elif (HE_HS_ACCESS_DEL == OPER_ROOT) if (is_services_root(u)) notice(s_HelpServ, u->nick, " DEL Delete a help item"); #endif #if (HE_HS_ACCESS_DB == OPER_OPER) if (is_services_oper(u)) notice(s_HelpServ, u->nick, " DB Load/Save/Get info on HelpSys database"); #elif (HE_HS_ACCESS_DB == OPER_ADMIN) if (is_services_admin(u)) notice(s_HelpServ, u->nick, " DB Load/Save/Get info on HelpSys database"); #elif (HE_HS_ACCESS_DB == OPER_ROOT) if (is_services_root(u)) notice(s_HelpServ, u->nick, " DB Load/Save/Get info on HelpSys database"); #endif } int he_hs_add_help(User * u) { notice(s_HelpServ, u->nick, "Syntax: \002ADD \037helpword\037 \037value\037\002"); notice(s_HelpServ, u->nick, " "); notice(s_HelpServ, u->nick, "Allows you to add a \037helpword\037 to %s which will display", s_HelpServ); notice(s_HelpServ, u->nick, "\037value\037 when looked up."); return MOD_CONT; } int he_hs_addfile_help(User * u) { notice(s_HelpServ, u->nick, "Syntax: \002ADDFILE \037helpword\037 \037file\037\002"); notice(s_HelpServ, u->nick, " "); notice(s_HelpServ, u->nick, "Allows you to add a \037helpword\037 to %s which will display", s_HelpServ); notice(s_HelpServ, u->nick, "the contents of \037file\037 when looked up."); return MOD_CONT; } int he_hs_del_help(User * u) { notice(s_HelpServ, u->nick, "Syntax: \002DEL \037helpword\037\002"); notice(s_HelpServ, u->nick, " "); notice(s_HelpServ, u->nick, "Allows you to delete the given \037helpword\037 from the %s", s_HelpServ); notice(s_HelpServ, u->nick, "help list."); return MOD_CONT; } int he_hs_find_help(User * u) { notice(s_HelpServ, u->nick, "Syntax: \002FIND \037mask\037"); notice(s_HelpServ, u->nick, " "); notice(s_HelpServ, u->nick, "Searches the list of helpwords for a helpword containing the given"); notice(s_HelpServ, u->nick, "\037mask\037."); return MOD_CONT; } int he_hs_read_help(User * u) { notice(s_HelpServ, u->nick, "Syntax: \002READ \037helpword\037\002"); notice(s_HelpServ, u->nick, " "); notice(s_HelpServ, u->nick, "Displays the text associated with the given \037helpword\037."); return MOD_CONT; } int he_hs_db_help(User * u) { notice(s_HelpServ, u->nick, "Syntax: \002DB [LOAD|SAVE]\002"); notice(s_HelpServ, u->nick, " "); notice(s_HelpServ, u->nick, "Allows you to load, save, or get info the HelpSys database."); notice(s_HelpServ, u->nick, " "); notice(s_HelpServ, u->nick, "The \002DB LOAD\002 command tries to reload the database from"); notice(s_HelpServ, u->nick, "disk. Only use this in case of a failed load, or you will loose"); notice(s_HelpServ, u->nick, "any changes since the last save."); notice(s_HelpServ, u->nick, " "); notice(s_HelpServ, u->nick, "The \002DB SAVE\002 command tries to save the database to the"); notice(s_HelpServ, u->nick, "disk."); notice(s_HelpServ, u->nick, " "); notice(s_HelpServ, u->nick, "When called without paraments, the \002DB\002 command displays"); notice(s_HelpServ, u->nick, "information on the HelpSys database, namely if it's able to open"); notice(s_HelpServ, u->nick, "the file for reading and writing."); return MOD_CONT; } /* EOF */