+ case MODE_EXEMPT:
+ /* If any existing exempt is a subset of the new exempt,
+ * silently remove it. The new exempt is not allowed
+ * to be more specific than an existing exempt.
+ */
+ for (jj=0; jj<channel->exemptlist.used; ++jj) {
+ if (match_ircglobs(change->args[ii].u.hostmask, channel->exemptlist.list[jj]->exempt)) {
+ exemptList_remove(&channel->exemptlist, channel->exemptlist.list[jj]);
+ free(channel->exemptlist.list[jj]);
+ jj--;
+ }
+ }
+ en = calloc(1, sizeof(*en));
+ safestrncpy(en->exempt, change->args[ii].u.hostmask, sizeof(en->exempt));
+ if (who)
+ safestrncpy(en->who, who->nick, sizeof(en->who));
+ else
+ safestrncpy(en->who, "<unknown>", sizeof(en->who));
+ en->set = now;
+ exemptList_append(&channel->exemptlist, en);
+ break;
+ case MODE_REMOVE|MODE_EXEMPT:
+ for (jj=0; jj<channel->exemptlist.used; ++jj) {
+ if (strcmp(channel->exemptlist.list[jj]->exempt, change->args[ii].u.hostmask))
+ continue;
+ free(channel->exemptlist.list[jj]);
+ exemptList_remove(&channel->exemptlist, channel->exemptlist.list[jj]);
+ break;
+ }
+ break;