X-Git-Url: https://jfr.im/git/irc/evilnet/x3.git/blobdiff_plain/ff3b058ac51e9caf5cf1fd310b8a401a97a85582..8ebec7fcaf44fc444596c6bc1df9e71bb45cb2d1:/src/mod-helpserv.c diff --git a/src/mod-helpserv.c b/src/mod-helpserv.c index 121700a..23d0e7e 100644 --- a/src/mod-helpserv.c +++ b/src/mod-helpserv.c @@ -245,7 +245,7 @@ static const struct message_entry msgtab[] = { { "HSMSG_PAGE_HELPER_GONE_2", "Request ID#%lu from $b%s$b (Not authed) $bhas been unassigned$b, as its helper, %s has %s." }, { "HSMSG_PAGE_HELPER_GONE_3", "Request ID#%lu from an offline user (Account %s) $bhas been unassigned$b, as its helper, %s has %s." }, { "HSMSG_PAGE_HELPER_GONE_4", "Request ID#%lu from an offline user (No account) $bhas been unassigned$b, as its helper, %s has %s." }, - { "HSMSG_PAGE_WHINE_HEADER", "$b%u unhandled request(s)$b waiting at least $b%s$b (%u total)" }, + { "HSMSG_PAGE_WHINE_HEADER", "$b%u unhandled request(s)$b waiting at least $b%s$b (%u unhandled, %u total)" }, { "HSMSG_PAGE_IDLE_HEADER", "$b%u users$b in %s $bidle at least %s$b:" }, { "HSMSG_PAGE_EMPTYALERT", "$b%s has no helpers present (%u unhandled request(s))$b" }, { "HSMSG_PAGE_ONLYTRIALALERT", "$b%s has no full helpers present (%d trial(s) present; %u unhandled request(s))$b" }, @@ -527,7 +527,7 @@ struct helpserv_bot { enum notification_type notify; /* This is a default; it can be changed on a per-request basis */ - enum persistence_type persist_types[PERSIST_T_COUNT]; + enum persistence_length persist_types[PERSIST_T_COUNT]; dict_t users; /* indexed by handle */ @@ -613,16 +613,16 @@ void STRUCTNAME##_free(void *data) {\ } DECLARE_LIST(helpserv_botlist, struct helpserv_bot *); -DEFINE_LIST(helpserv_botlist, struct helpserv_bot *); -DEFINE_LIST_ALLOC(helpserv_botlist); +DEFINE_LIST(helpserv_botlist, struct helpserv_bot *) +DEFINE_LIST_ALLOC(helpserv_botlist) DECLARE_LIST(helpserv_reqlist, struct helpserv_request *); -DEFINE_LIST(helpserv_reqlist, struct helpserv_request *); -DEFINE_LIST_ALLOC(helpserv_reqlist); +DEFINE_LIST(helpserv_reqlist, struct helpserv_request *) +DEFINE_LIST_ALLOC(helpserv_reqlist) DECLARE_LIST(helpserv_userlist, struct helpserv_user *); -DEFINE_LIST(helpserv_userlist, struct helpserv_user *); -DEFINE_LIST_ALLOC(helpserv_userlist); +DEFINE_LIST(helpserv_userlist, struct helpserv_user *) +DEFINE_LIST_ALLOC(helpserv_userlist) struct helpfile *helpserv_helpfile; static struct module *helpserv_module; @@ -655,31 +655,37 @@ static HELPSERV_FUNC(cmd_help); return 0; } /* For messages going to users being helped */ -#define helpserv_msguser(target, format...) send_message_type((from_opserv ? 0 : hs->privmsg_only), (target), (from_opserv ? opserv : hs->helpserv) , ## format) -#define helpserv_user_reply(format...) send_message_type(req->hs->privmsg_only, req->user, req->hs->helpserv , ## format) +#if defined(GCC_VARMACROS) +# define helpserv_msguser(target, ARGS...) send_message_type((from_opserv ? 0 : hs->privmsg_only), (target), (fromopserv ? opserv : hs->helpserv), ARGS) +# define helpserv_user_reply(ARGS...) send_message_type(req->hs->privmsg_only, req->user, req->hs->helpserv, ARGS) /* For messages going to helpers */ -#define helpserv_notice(target, format...) send_message((target), (from_opserv ? opserv : hs->helpserv) , ## format) -#define helpserv_notify(helper, format...) do { struct userNode *_target; for (_target = (helper)->handle->users; _target; _target = _target->next_authed) { \ - send_message(_target, (helper)->hs->helpserv, ## format); \ +# define helpserv_notice(target, ARGS...) send_message((target), (from_opserv ? opserv : hs->helpserv), ARGS) +# define helpserv_notify(helper, ARGS...) do { struct userNode *_target; for (_target = (helper)->handle->users; _target; _target = _target->next_authed) { \ + send_message(_target, (helper)->hs->helpserv, ARGS); \ } } while (0) +# define helpserv_page(TYPE, ARGS...) do { \ + int msg_type=0; struct chanNode *target=helpserv_get_page_type(hs, (TYPE), &msg_type); \ + if (target) send_target_message(msg_type, target->name, hs->helpserv, ARGS); \ + } while (0) +#elif defined(C99_VARMACROS) +# define helpserv_msguser(target, ...) send_message_type((from_opserv ? 0 : hs->privmsg_only), (target), (from_opserv ? opserv : hs->helpserv), __VA_ARGS__) +# define helpserv_user_reply(...) send_message_type(req->hs->privmsg_only, req->user, req->hs->helpserv, __VA_ARGS__) +/* For messages going to helpers */ +# define helpserv_notice(target, ...) send_message((target), (from_opserv ? opserv : hs->helpserv), __VA_ARGS__) +# define helpserv_notify(helper, ...) do { struct userNode *_target; for (_target = (helper)->handle->users; _target; _target = _target->next_authed) { \ + send_message(_target, (helper)->hs->helpserv, __VA_ARGS__); \ + } } while (0) +# define helpserv_page(TYPE, ...) do { \ + int msg_type=0; struct chanNode *target=helpserv_get_page_type(hs, (TYPE), &msg_type); \ + if (target) send_target_message(msg_type, target->name, hs->helpserv, __VA_ARGS__); \ + } while (0) +#endif #define helpserv_message(hs, target, id) do { if ((hs)->messages[id]) { \ if (from_opserv) \ send_message_type(4, (target), opserv, "%s", (hs)->messages[id]); \ else \ send_message_type(4 | hs->privmsg_only, (target), hs->helpserv, "%s", (hs)->messages[id]); \ } } while (0) -#define helpserv_page(TYPE, FORMAT...) do { \ - struct chanNode *target=NULL; int msg_type=0; \ - target = hs->page_targets[TYPE]; \ - switch (hs->page_types[TYPE]) { \ - case PAGE_NOTICE: msg_type = 0; break; \ - case PAGE_PRIVMSG: msg_type = 1; break; \ - case PAGE_ONOTICE: msg_type = 2; break; \ - default: log_module(HS_LOG, LOG_ERROR, "helpserv_page() called but %s has an invalid page type %d.", hs->helpserv->nick, TYPE); \ - case PAGE_NONE: target = NULL; break; \ - } \ - if (target) send_target_message(msg_type, target->name, hs->helpserv, ## FORMAT); \ - } while (0) #define helpserv_get_handle_info(user, text) smart_get_handle_info((from_opserv ? opserv : hs->helpserv) , (user), (text)) struct helpserv_cmd { @@ -728,10 +734,10 @@ static void helpserv_log_request(struct helpserv_request *req, const char *reaso assert(req != NULL); assert(reason != NULL); - if (!(ctx = saxdb_open_context(reqlog_f))) + if (!reqlog_f || !(ctx = saxdb_open_context(reqlog_f))) return; sprintf(key, "%s-" FMT_TIME_T "-%lu", req->hs->helpserv->nick, req->opened, req->id); - if ((res = setjmp(ctx->jbuf)) != 0) { + if ((res = setjmp(*saxdb_jmp_buf(ctx))) != 0) { log_module(HS_LOG, LOG_ERROR, "Unable to log helpserv request: %s.", strerror(res)); } else { saxdb_start_record(ctx, key, 1); @@ -752,11 +758,31 @@ static void helpserv_log_request(struct helpserv_request *req, const char *reaso saxdb_write_string(ctx, KEY_REQUEST_CLOSEREASON, reason); saxdb_write_string_list(ctx, KEY_REQUEST_TEXT, req->text); saxdb_end_record(ctx); - saxdb_close_context(ctx); - fflush(reqlog_f); + saxdb_close_context(ctx, 0); } } +static struct chanNode *helpserv_get_page_type(struct helpserv_bot *hs, enum page_source type, int *msg_type) +{ + switch (hs->page_types[type]) { + case PAGE_NOTICE: + *msg_type = 0; + break; + case PAGE_PRIVMSG: + *msg_type = 1; + break; + case PAGE_ONOTICE: + *msg_type = 2; + break; + default: + log_module(HS_LOG, LOG_ERROR, "helpserv_page() called but %s has an invalid page type %d.", hs->helpserv->nick, type); + /* and fall through */ + case PAGE_NONE: + return NULL; + } + return hs->page_targets[type]; +} + /* Searches for a request by number, nick, or account (num|nick|*account). * As there can potentially be >1 match, it takes a reqlist. The return * value is the "best" request found (explained in the comment block below). @@ -853,7 +879,7 @@ static struct helpserv_request * smart_get_request(struct helpserv_bot *hs, stru static struct helpserv_request * create_request(struct userNode *user, struct helpserv_bot *hs, int from_join) { struct helpserv_request *req = calloc(1, sizeof(struct helpserv_request)); - char lbuf[3][MAX_LINE_SIZE], unh[INTERVALLEN], abuf[1][MAX_LINE_SIZE]; + char lbuf[3][MAX_LINE_SIZE], req_id[INTERVALLEN], abuf[1][MAX_LINE_SIZE]; struct helpserv_reqlist *reqlist, *hand_reqlist; struct helpserv_user *hs_user; struct userNode *target, *next_un = NULL; @@ -864,8 +890,8 @@ static struct helpserv_request * create_request(struct userNode *user, struct he assert(req); req->id = ++hs->last_requestid; - sprintf(unh, "%lu", req->id); - dict_insert(hs->requests, strdup(unh), req); + sprintf(req_id, "%lu", req->id); + dict_insert(hs->requests, strdup(req_id), req); if (hs->id_wrap) { unsigned long i; @@ -960,12 +986,12 @@ static struct helpserv_request * create_request(struct userNode *user, struct he } if (req != hs->unhandled) { - intervalString(unh, now - hs->unhandled->opened, user->handle_info); + intervalString(req_id, now - hs->unhandled->opened, user->handle_info); fmt = user_find_message(user, "HSMSG_REQ_UNHANDLED_TIME"); - sprintf(lbuf[1], fmt, unh); + sprintf(lbuf[1], fmt, req_id); } else { fmt = user_find_message(user, "HSMSG_REQ_NO_UNHANDLED"); - sprintf(lbuf[1], fmt); + sprintf(lbuf[1], "%s", fmt); } if (hs->alert_new) { @@ -988,18 +1014,17 @@ static struct helpserv_request * create_request(struct userNode *user, struct he break; case PERSIST_QUIT: fmt = user_find_message(user, "HSMSG_REQ_PERSIST_QUIT"); - sprintf(lbuf[2], fmt); + sprintf(lbuf[2], "%s", fmt); break; default: log_module(HS_LOG, LOG_ERROR, "%s has an invalid req_persist.", hs->helpserv->nick); case PERSIST_CLOSE: if (user->handle_info) { fmt = user_find_message(user, "HSMSG_REQ_PERSIST_HANDLE"); - sprintf(lbuf[2], fmt); } else { fmt = user_find_message(user, "HSMSG_REQ_PERSIST_QUIT"); - sprintf(lbuf[2], fmt); } + sprintf(lbuf[2], "%s", fmt); break; } helpserv_message(hs, user, MSGTYPE_REQ_OPENED); @@ -1176,8 +1201,8 @@ static void helpserv_botmsg(struct userNode *user, struct userNode *target, cons struct helpserv_cmd *cmd; struct helpserv_user *hs_user = NULL; char *argv[MAXNUMPARAMS]; - int argc, argv_shift; char tmpline[MAXLEN]; + int argc, argv_shift; const int from_opserv = 0; /* for helpserv_notice */ /* Ignore things consisting of empty lines or from ourselves */ @@ -1189,12 +1214,10 @@ static void helpserv_botmsg(struct userNode *user, struct userNode *target, cons /* XXX: For some unknown reason we are shifting +1 on the array and ignoring argv[0]; to avoid someone rightly assuming argv[0] * was the first argument later on and addressing random memory, were going to make argv[0] null. This whole thing is pretty unacceptable and needs fixed, though.*/ - - + argv[0] = NULL; argv_shift = 1; safestrncpy(tmpline, text, sizeof(tmpline)); argc = split_line(tmpline, false, ArrayLength(argv)-argv_shift, argv+argv_shift); - if (!argc) return; @@ -1448,7 +1471,7 @@ static void helpserv_del_user(struct helpserv_bot *hs, struct helpserv_user *hs_ } static int cmd_add_user(struct helpserv_bot *hs, int from_opserv, struct userNode *user, enum helpserv_level level, int argc, char *argv[]) { - struct helpserv_user *actor, *new_user; + struct helpserv_user *actor; struct handle_info *handle; REQUIRE_PARMS(2); @@ -1476,7 +1499,7 @@ static int cmd_add_user(struct helpserv_bot *hs, int from_opserv, struct userNod return 0; } - new_user = helpserv_add_user(hs, handle, level); + helpserv_add_user(hs, handle, level); helpserv_notice(user, "HSMSG_ADDED_USER", helpserv_level2str(level), handle->handle); return 1; @@ -2665,7 +2688,7 @@ static void run_whine_interval(void *data) { tbl.contents[i][3] = strdup(unh_time); } - helpserv_page(PGSRC_ALERT, "HSMSG_PAGE_WHINE_HEADER", reqlist.used, strwhinedelay, queuesize); + helpserv_page(PGSRC_ALERT, "HSMSG_PAGE_WHINE_HEADER", reqlist.used, strwhinedelay, queuesize, dict_size(hs->requests)); table_send(hs->helpserv, hs->page_targets[PGSRC_ALERT]->name, 0, page_type_funcs[hs->page_types[PGSRC_ALERT]], tbl); for (i=1; i <= reqlist.used; i++) { @@ -2673,7 +2696,7 @@ static void run_whine_interval(void *data) { free((char *)tbl.contents[i][3]); } #else - helpserv_page(PGSRC_ALERT, "HSMSG_PAGE_WHINE_HEADER", reqlist.used, strwhinedelay, queuesize); + helpserv_page(PGSRC_ALERT, "HSMSG_PAGE_WHINE_HEADER", reqlist.used, strwhinedelay, queuesize, dict_size(hs->requests)); #endif } @@ -4094,10 +4117,10 @@ static void helpserv_conf_read(void) { } static struct helpserv_cmd * -helpserv_define_func(const char *name, helpserv_func_t *func, enum helpserv_level access, long flags) { +helpserv_define_func(const char *name, helpserv_func_t *func, enum helpserv_level level, long flags) { struct helpserv_cmd *cmd = calloc(1, sizeof(struct helpserv_cmd)); - cmd->access = access; + cmd->access = level; cmd->weight = 1.0; cmd->func = func; cmd->flags = flags; @@ -4107,7 +4130,7 @@ helpserv_define_func(const char *name, helpserv_func_t *func, enum helpserv_leve } /* Drop requests that persist until part when a user leaves the chan */ -static void handle_part(struct modeNode *mn, UNUSED_ARG(const char *reason)) { +static void handle_part(struct modeNode *mn, UNUSED_ARG(const char *reason), UNUSED_ARG(void *extra)) { struct helpserv_botlist *botlist; struct helpserv_userlist *userlist; const int from_opserv = 0; /* for helpserv_notice */ @@ -4166,9 +4189,9 @@ static void handle_part(struct modeNode *mn, UNUSED_ARG(const char *reason)) { if ((hs->persist_types[PERSIST_T_HELPER] == PERSIST_PART) && (req->helper == hs_user)) { - char reason[CHANNELLEN + 8]; - sprintf(reason, "parted %s", mn->channel->name); - helpserv_page_helper_gone(hs, req, reason); + char our_reason[CHANNELLEN + 8]; + sprintf(our_reason, "parted %s", mn->channel->name); + helpserv_page_helper_gone(hs, req, our_reason); } } @@ -4203,7 +4226,7 @@ static void handle_part(struct modeNode *mn, UNUSED_ARG(const char *reason)) { * * Unassign requests where req->helper persists until the helper parts or * quits. */ -static void handle_quit(struct userNode *user, UNUSED_ARG(struct userNode *killer), UNUSED_ARG(const char *why)) { +static void handle_quit(struct userNode *user, UNUSED_ARG(struct userNode *killer), UNUSED_ARG(const char *why), UNUSED_ARG(void *extra)) { struct helpserv_reqlist *reqlist; struct helpserv_userlist *userlist; unsigned int i, n; @@ -4351,7 +4374,7 @@ static void associate_requests_bychan(struct chanNode *chan, struct userNode *us /* Greet users upon joining a helpserv channel (if greeting is set) and set * req->user to the user joining for all requests owned by the user's handle * (if any) with a req->user == NULL */ -static int handle_join(struct modeNode *mNode) { +static int handle_join(struct modeNode *mNode, UNUSED_ARG(void *extra)) { struct userNode *user = mNode->user; struct chanNode *chan = mNode->channel; struct helpserv_botlist *botlist; @@ -4422,7 +4445,7 @@ static int handle_join(struct modeNode *mNode) { } /* Update helpserv_reqs_bynick_dict upon nick change */ -static void handle_nickchange(struct userNode *user, const char *old_nick) { +static void handle_nickchange(struct userNode *user, const char *old_nick, UNUSED_ARG(void *extra)) { struct helpserv_reqlist *reqlist; unsigned int i; @@ -4442,7 +4465,7 @@ static void handle_nickchange(struct userNode *user, const char *old_nick) { } /* Also update helpserv_reqs_byhand_dict upon handle rename */ -static void handle_nickserv_rename(struct handle_info *handle, const char *old_handle) { +static void handle_nickserv_rename(struct handle_info *handle, const char *old_handle, UNUSED_ARG(void *extra)) { struct helpserv_reqlist *reqlist; struct helpserv_userlist *userlist; unsigned int i; @@ -4495,7 +4518,7 @@ static void handle_nickserv_rename(struct handle_info *handle, const char *old_h * have req->user set). * - In either of the above cases, if a user is on a bot's userlist and has * requests assigned to them, it will give them a list. */ -static void handle_nickserv_auth(struct userNode *user, struct handle_info *old_handle) { +static void handle_nickserv_auth(struct userNode *user, struct handle_info *old_handle, UNUSED_ARG(void* extra)) { struct helpserv_reqlist *reqlist, *dellist=NULL, *hand_reqlist, *oldhand_reqlist; struct helpserv_userlist *userlist; unsigned int i, j; @@ -4662,7 +4685,7 @@ static void handle_nickserv_auth(struct userNode *user, struct handle_info *old_ * * Also, remove the user from all bots that it has access in. * helpserv_del_user() will take care of unassigning the requests. */ -static void handle_nickserv_unreg(struct userNode *user, struct handle_info *handle) { +static void handle_nickserv_unreg(struct userNode *user, struct handle_info *handle, UNUSED_ARG(void *extra)) { struct helpserv_reqlist *hand_reqlist; struct helpserv_userlist *userlist; unsigned int i, n; @@ -4745,7 +4768,7 @@ static void handle_nickserv_unreg(struct userNode *user, struct handle_info *han dict_remove(helpserv_reqs_byhand_dict, handle->handle); } -static void handle_nickserv_merge(struct userNode *user, struct handle_info *handle_to, struct handle_info *handle_from) { +static void handle_nickserv_merge(struct userNode *user, struct handle_info *handle_to, struct handle_info *handle_from, UNUSED_ARG(void *extra)) { struct helpserv_reqlist *reqlist_from, *reqlist_to; unsigned int i; @@ -4777,7 +4800,7 @@ static void handle_nickserv_merge(struct userNode *user, struct handle_info *han } } -static void handle_nickserv_allowauth(struct userNode *user, struct userNode *target, struct handle_info *handle) { +static void handle_nickserv_allowauth(struct userNode *user, struct userNode *target, struct handle_info *handle, UNUSED_ARG(void *extra)) { struct helpserv_reqlist *reqlist; unsigned int i; @@ -4796,7 +4819,7 @@ static void handle_nickserv_allowauth(struct userNode *user, struct userNode *ta } } -static void handle_nickserv_failpw(struct userNode *user, struct handle_info *handle) { +static void handle_nickserv_failpw(struct userNode *user, struct handle_info *handle, UNUSED_ARG(void *extra)) { struct helpserv_reqlist *reqlist; unsigned int i; @@ -4874,10 +4897,10 @@ helpserv_define_option(const char *name, helpserv_option_func_t *func) { dict_insert(helpserv_option_dict, name, func); } -static void helpserv_db_cleanup(void) { +static void helpserv_db_cleanup(UNUSED_ARG(void *extra)) { shutting_down=1; - unreg_part_func(handle_part); - unreg_del_user_func(handle_quit); + unreg_part_func(handle_part, NULL); + unreg_del_user_func(handle_quit, NULL); close_helpfile(helpserv_helpfile); dict_delete(helpserv_func_dict); dict_delete(helpserv_option_dict); @@ -4995,19 +5018,19 @@ int helpserv_init() { } timeq_add(helpserv_next_stats(now), helpserv_timed_run_stats, NULL); - reg_join_func(handle_join); - reg_part_func(handle_part); /* also deals with kick */ - reg_nick_change_func(handle_nickchange); - reg_del_user_func(handle_quit); + reg_join_func(handle_join, NULL); + reg_part_func(handle_part, NULL); /* also deals with kick */ + reg_nick_change_func(handle_nickchange, NULL); + reg_del_user_func(handle_quit, NULL); - reg_auth_func(handle_nickserv_auth); - reg_handle_rename_func(handle_nickserv_rename); - reg_unreg_func(handle_nickserv_unreg); - reg_allowauth_func(handle_nickserv_allowauth); - reg_failpw_func(handle_nickserv_failpw); - reg_handle_merge_func(handle_nickserv_merge); + reg_auth_func(handle_nickserv_auth, NULL); + reg_handle_rename_func(handle_nickserv_rename, NULL); + reg_unreg_func(handle_nickserv_unreg, NULL); + reg_allowauth_func(handle_nickserv_allowauth, NULL); + reg_failpw_func(handle_nickserv_failpw, NULL); + reg_handle_merge_func(handle_nickserv_merge, NULL); - reg_exit_func(helpserv_db_cleanup); + reg_exit_func(helpserv_db_cleanup, NULL); helpserv_module = module_register("helpserv", HS_LOG, HELPSERV_HELPFILE_NAME, helpserv_expand_variable); modcmd_register(helpserv_module, "helpserv", cmd_helpserv, 1, MODCMD_REQUIRE_AUTHED|MODCMD_NO_LOG|MODCMD_NO_DEFAULT_BIND, "level", "800", NULL);