+ /* Exhaustively search account DNRs. */
+ for(it = dict_first(handle_dnrs); it; it = next)
+ {
+ next = iter_next(it);
+ dnr = iter_data(it);
+ if(dnr_search_matches(dnr, discrim) && (count++ < discrim->limit) && dsf(dnr, data))
+ break;
+ }
+
+ /* Do the same for channel DNRs. */
+ for(it = dict_first(plain_dnrs); it; it = next)
+ {
+ next = iter_next(it);
+ dnr = iter_data(it);
+ if(dnr_search_matches(dnr, discrim) && (count++ < discrim->limit) && dsf(dnr, data))
+ break;
+ }
+
+ /* Do the same for wildcarded channel DNRs. */
+ for(it = dict_first(mask_dnrs); it; it = next)
+ {
+ next = iter_next(it);
+ dnr = iter_data(it);
+ if(dnr_search_matches(dnr, discrim) && (count++ < discrim->limit) && dsf(dnr, data))
+ break;
+ }
+ }
+ return count;
+}
+
+static int
+dnr_remove_func(struct do_not_register *match, void *extra)
+{
+ struct userNode *user;
+ char *chan_name;
+
+ chan_name = alloca(strlen(match->chan_name) + 1);
+ strcpy(chan_name, match->chan_name);
+ user = extra;
+ if(((chan_name[0] == '*') && dict_remove(handle_dnrs, chan_name+1))
+ || dict_remove(plain_dnrs, chan_name)
+ || dict_remove(mask_dnrs, chan_name))
+ {
+ send_message(user, chanserv, "CSMSG_DNR_REMOVED", chan_name);
+ }
+ return 0;
+}
+
+static int
+dnr_count_func(struct do_not_register *match, void *extra)
+{
+ return 0; (void)match; (void)extra;
+}
+
+static MODCMD_FUNC(cmd_dnrsearch)
+{
+ struct dnr_search *discrim;
+ dnr_search_func action;
+ struct svccmd *subcmd;
+ unsigned int matches;
+ char buf[MAXLEN];
+
+ sprintf(buf, "dnrsearch %s", argv[1]);
+ subcmd = dict_find(cmd->parent->commands, buf, NULL);
+ if(!subcmd)
+ {
+ reply("CSMSG_DNR_BAD_ACTION", argv[1]);
+ return 0;
+ }
+ if(!svccmd_can_invoke(user, cmd->parent->bot, subcmd, channel, SVCCMD_NOISY))
+ return 0;
+ if(!irccasecmp(argv[1], "print"))
+ action = dnr_print_func;
+ else if(!irccasecmp(argv[1], "remove"))
+ action = dnr_remove_func;
+ else if(!irccasecmp(argv[1], "count"))
+ action = dnr_count_func;
+ else
+ {
+ reply("CSMSG_DNR_BAD_ACTION", argv[1]);