+struct shun_extra {
+ struct userNode *user;
+ struct string_list *shuns;
+ struct userNode *bot;
+};
+
+static void
+strace_print_func(struct shun *shun, void *extra)
+{
+ struct shun_extra *xtra = extra;
+ char *when_text, set_text[20];
+ strftime(set_text, sizeof(set_text), "%Y-%m-%d", localtime(&shun->issued));
+ when_text = asctime(localtime(&shun->expires));
+ when_text[strlen(when_text)-1] = 0; /* strip lame \n */
+ send_message(xtra->user, xtra->bot, "OSMSG_STRACE_FORMAT", shun->target, set_text, shun->issuer, when_text, shun->reason);
+}
+
+static void
+strace_count_func(UNUSED_ARG(struct shun *shun), UNUSED_ARG(void *extra))
+{
+}
+
+static void
+strace_unshun_func(struct shun *shun, void *extra)
+{
+ struct shun_extra *xtra = extra;
+ string_list_append(xtra->shuns, strdup(shun->target));
+}
+
+static MODCMD_FUNC(cmd_strace)
+{
+ struct shun_discrim *discrim;
+ shun_search_func action;
+ unsigned int matches, nn;
+ struct shun_extra extra;
+ struct svccmd *subcmd;
+ char buf[MAXLEN];
+
+ if (!irccasecmp(argv[1], "print"))
+ action = strace_print_func;
+ else if (!irccasecmp(argv[1], "count"))
+ action = strace_count_func;
+ else if (!irccasecmp(argv[1], "unshun"))
+ action = strace_unshun_func;
+ else {
+ reply("OSMSG_BAD_ACTION", argv[1]);
+ return 0;
+ }
+ sprintf(buf, "%s %s", argv[0], argv[0]);
+ if ((subcmd = dict_find(opserv_service->commands, buf, NULL))
+ && !svccmd_can_invoke(user, opserv_service->bot, subcmd, channel, SVCCMD_NOISY)) {
+ return 0;
+ }
+
+ discrim = shun_discrim_create(user, cmd->parent->bot, argc-2, argv+2);
+ if (!discrim)
+ return 0;
+
+ if (action == strace_print_func)
+ reply("OSMSG_SHUN_SEARCH_RESULTS");
+ else if (action == strace_count_func)
+ discrim->limit = INT_MAX;
+
+ extra.user = user;
+ extra.shuns = alloc_string_list(4);
+ extra.bot = cmd->parent->bot;
+ matches = shun_discrim_search(discrim, action, &extra);
+
+ if (action == strace_unshun_func)
+ for (nn=0; nn<extra.shuns->used; nn++)
+ shun_remove(extra.shuns->list[nn], 1);
+ free_string_list(extra.shuns);
+
+ if (matches)
+ reply("MSG_MATCH_COUNT", matches);
+ else
+ reply("MSG_NO_MATCHES");
+ free(discrim->alt_target_mask);
+ free(discrim);
+ return 1;
+}
+