/* Should we leave orphaned check here? -- dwr */
if (chmode_table[i].set_func != NULL &&
- chmode_table[i].set_func != chm_nosuch &&
chmode_table[i].set_func != chm_orphaned)
{
*ptr2++ = (char) i;
int c = (unsigned char)c_;
if (chmode_table[c].set_func != NULL &&
- chmode_table[c].set_func != chm_nosuch &&
chmode_table[c].set_func != chm_orphaned)
return 0;
- if (chmode_table[c].set_func == NULL || chmode_table[c].set_func == chm_nosuch)
+ if (chmode_table[c].set_func == NULL)
chmode_table[c].mode_type = find_cflag_slot();
if (chmode_table[c].mode_type == 0)
return 0;
return arg;
}
-/* chm_*()
- *
- * The handlers for each specific mode.
- */
-void
-chm_nosuch(struct Client *source_p, struct Channel *chptr,
- int alevel, const char *arg, int *errors, int dir, char c, long mode_type)
-{
- if(*errors & SM_ERR_UNKNOWN)
- return;
- *errors |= SM_ERR_UNKNOWN;
- sendto_one(source_p, form_str(ERR_UNKNOWNMODE), me.name, source_p->name, c);
-}
-
void
chm_simple(struct Client *source_p, struct Channel *chptr,
int alevel, const char *arg, int *errors, int dir, char c, long mode_type)
break;
default:
- sendto_realops_snomask(SNO_GENERAL, L_ALL, "chm_ban() called with unknown type!");
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "chm_ban() called with unknown type!");
return;
}
set_channel_mode(struct Client *client_p, struct Client *source_p,
struct Channel *chptr, struct membership *msptr, int parc, const char *parv[])
{
- static char modebuf[BUFSIZE];
+ static char modebuf[BUFSIZE * 2]; /* paranoid case: 2 canonical chars per input char */
static char parabuf[BUFSIZE];
char *mbuf;
char *pbuf;
static struct modeset modesets[MAXPARA];
struct modeset *ms = modesets, *mend;
+ char canon_op = '\0';
+
+ mbuf = modebuf;
for (ml = parv[0]; *ml != 0; ml++)
{
bool use_arg = dir == MODE_ADD ? cm->flags & CHM_ARG_SET :
dir == MODE_DEL ? cm->flags & CHM_ARG_DEL :
false;
- if (cm->set_func == NULL || cm->set_func == chm_nosuch)
+ if (cm->set_func == NULL)
{
sendto_one(source_p, form_str(ERR_UNKNOWNMODE), me.name, source_p->name, c);
return;
* does nothing for a query on a mode with no query. would it be
* good to send an error here?
*/
+ continue;
}
+ char op = effective_dir == MODE_ADD ? '+' :
+ effective_dir == MODE_DEL ? '-' :
+ '=';
+
+ if (op != canon_op)
+ *mbuf++ = canon_op = op;
+
+ *mbuf++ = c;
+
if (effective_dir != MODE_QUERY && access_dir == MODE_QUERY)
access_dir = effective_dir;
+ if (effective_dir == MODE_QUERY && cm->flags & CHM_OPS_QUERY)
+ access_dir = MODE_OP_QUERY;
ms->cm = cm;
ms->dir = effective_dir;
}
}
+ /* this will happen on something like MODE +-=++-.
+ * we'd have caught that with the if !mode_count
+ * later on, but this saves an override notice
+ */
+ if (ms == modesets)
+ return;
+
if (parn < parc)
{
/* XXX we could reject excess params here */
mend = ms;
- alevel = get_channel_access(source_p, chptr, msptr, access_dir, reconstruct_parv(parc, parv));
+ if (parn > 1)
+ {
+ strcpy(mbuf, " ");
+ rb_strlcat(modebuf, reconstruct_parv(parn - 1, parv + 1), sizeof modebuf);
+ }
+ else
+ {
+ *mbuf = '\0';
+ }
+ alevel = get_channel_access(source_p, chptr, msptr, access_dir, modebuf);
for (ms = modesets; ms < mend; ms++)
{
- ChannelModeFunc set_func = ms->cm->set_func;
- if (set_func == NULL)
- set_func = chm_nosuch;
+ ChannelModeFunc *set_func = ms->cm->set_func;
set_func(fakesource_p, chptr, alevel, ms->arg, &errors, ms->dir, ms->mode, ms->cm->mode_type);
}
/* bail out if we have nothing to do... */
- if(!mode_count)
+ if (!mode_count)
return;
- if(IsServer(source_p))
+ if (IsServer(source_p))
mlen = sprintf(modebuf, ":%s MODE %s ", fakesource_p->name, chptr->chname);
else
mlen = sprintf(modebuf, ":%s!%s@%s MODE %s ",