ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/channel_mode.c
(Generate patch)

Comparing:
ircd-hybrid/src/channel_mode.c (file contents), Revision 30 by adx, Sun Oct 2 20:03:27 2005 UTC vs.
ircd-hybrid/trunk/src/channel_mode.c (file contents), Revision 3685 by michael, Thu May 29 15:59:17 2014 UTC

# Line 1 | Line 1
1   /*
2 < *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 < *  channel_mode.c: Controls modes on channels.
2 > *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (C) 2005 by the past and present ircd coders, and others.
4 > *  Copyright (c) 1997-2014 ircd-hybrid development team
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 18 | Line 17
17   *  along with this program; if not, write to the Free Software
18   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
19   *  USA
20 < *
21 < *  $Id: channel_mode.c,v 7.165 2005/09/18 12:43:45 michael Exp $
20 > */
21 >
22 > /*! \file channel_mode.c
23 > * \brief Controls modes on channels.
24 > * \version $Id$
25   */
26  
27   #include "stdinc.h"
28 < #include "tools.h"
28 > #include "list.h"
29   #include "channel.h"
30   #include "channel_mode.h"
31   #include "client.h"
32 < #include "common.h"
33 < #include "hash.h"
32 > #include "conf.h"
33 > #include "hostmask.h"
34   #include "irc_string.h"
33 – #include "sprintf_irc.h"
35   #include "ircd.h"
35 – #include "list.h"
36   #include "numeric.h"
37 < #include "s_serv.h"             /* captab */
38 < #include "s_user.h"
37 > #include "server.h"
38   #include "send.h"
40 – #include "whowas.h"
41 – #include "s_conf.h"             /* ConfigFileEntry, ConfigChannel */
42 – #include "event.h"
39   #include "memory.h"
40 < #include "balloc.h"
41 < #include "s_log.h"
46 <
47 < /* some small utility functions */
48 < static char *check_string(char *);
49 < static char *fix_key(char *);
50 < static char *fix_key_old(char *);
51 < static void chm_nosuch(struct Client *, struct Client *,
52 <                       struct Channel *, int, int *, char **, int *, int,
53 <                       int, char, void *, const char *);
54 < static void chm_simple(struct Client *, struct Client *, struct Channel *,
55 <                       int, int *, char **, int *, int, int, char, void *,
56 <                       const char *);
57 < static void chm_limit(struct Client *, struct Client *, struct Channel *,
58 <                      int, int *, char **, int *, int, int, char, void *,
59 <                      const char *);
60 < static void chm_key(struct Client *, struct Client *, struct Channel *,
61 <                    int, int *, char **, int *, int, int, char, void *,
62 <                    const char *);
63 < static void chm_op(struct Client *, struct Client *, struct Channel *, int,
64 <                   int *, char **, int *, int, int, char, void *,
65 <                   const char *);
66 < #ifdef HALFOPS
67 < static void chm_hop(struct Client *, struct Client *, struct Channel *, int,
68 <                   int *, char **, int *, int, int, char, void *,
69 <                   const char *);
70 < #endif
71 < static void chm_voice(struct Client *, struct Client *, struct Channel *,
72 <                      int, int *, char **, int *, int, int, char, void *,
73 <                      const char *);
74 < static void chm_ban(struct Client *, struct Client *, struct Channel *, int,
75 <                    int *, char **, int *, int, int, char, void *,
76 <                    const char *);
77 < static void chm_except(struct Client *, struct Client *, struct Channel *,
78 <                       int, int *, char **, int *, int, int, char, void *,
79 <                       const char *);
80 < static void chm_invex(struct Client *, struct Client *, struct Channel *,
81 <                      int, int *, char **, int *, int, int, char, void *,
82 <                      const char *);
83 < static void send_cap_mode_changes(struct Client *, struct Client *,
84 <                                  struct Channel *, int, int);
85 < static void send_mode_changes(struct Client *, struct Client *,
86 <                              struct Channel *, char *);
40 > #include "mempool.h"
41 > #include "parse.h"
42  
43   /* 10 is a magic number in hybrid 6 NFI where it comes from -db */
44 < #define BAN_FUDGE       10
90 < #define NCHCAPS         (sizeof(channel_capabs)/sizeof(int))
91 < #define NCHCAP_COMBOS   (1 << NCHCAPS)
44 > #define BAN_FUDGE       10
45  
46 + static char nuh_mask[MAXPARA][IRCD_BUFSIZE];
47   /* some buffers for rebuilding channel/nick lists with ,'s */
48   static char modebuf[IRCD_BUFSIZE];
49   static char parabuf[MODEBUFLEN];
50   static struct ChModeChange mode_changes[IRCD_BUFSIZE];
51 < static int mode_count;
52 < static int mode_limit;          /* number of modes set other than simple */
53 < static int simple_modes_mask;   /* bit mask of simple modes already set */
54 < static int channel_capabs[] = { CAP_EX, CAP_IE, CAP_TS6 };
55 < static struct ChCapCombo chcap_combos[NCHCAP_COMBOS];
56 < extern BlockHeap *ban_heap;
51 > static unsigned int mode_count;
52 > static unsigned int mode_limit;  /* number of modes set other than simple */
53 > static unsigned int simple_modes_mask;  /* bit mask of simple modes already set */
54 > extern mp_pool_t *ban_pool;
55 >
56 > const struct mode_letter chan_modes[] =
57 > {
58 >  { MODE_NOCTRL,     'c' },
59 >  { MODE_INVITEONLY, 'i' },
60 >  { MODE_MODERATED,  'm' },
61 >  { MODE_NOPRIVMSGS, 'n' },
62 >  { MODE_PRIVATE,    'p' },
63 >  { MODE_REGISTERED, 'r' },
64 >  { MODE_SECRET,     's' },
65 >  { MODE_TOPICLIMIT, 't' },
66 >  { MODE_MODREG,     'M' },
67 >  { MODE_OPERONLY,   'O' },
68 >  { MODE_REGONLY,    'R' },
69 >  { MODE_SSLONLY,    'S' },
70 >  { 0, '\0' }
71 > };
72  
73  
105 – /* XXX check_string is propably not longer required in add_id and del_id */
74   /* check_string()
75   *
76   * inputs       - string to check
# Line 118 | Line 86 | check_string(char *s)
86    char *str = s;
87    static char star[] = "*";
88  
89 <  if (EmptyString(s))
90 <    return (star);
89 >  if (EmptyString(str))
90 >    return star;
91  
92    for (; *s; ++s)
93    {
# Line 130 | Line 98 | check_string(char *s)
98      }
99    }
100  
101 <  return (str);
101 >  return EmptyString(str) ? star : str;
102   }
103  
104   /*
105   * Ban functions to work with mode +b/e/d/I
106   */
107 < /* add the specified ID to the channel..
108 < *   -is 8/9/00
107 > /* add the specified ID to the channel.
108 > *   -is 8/9/00
109   */
110  
111   int
112 < add_id(struct Client *client_p, struct Channel *chptr, char *banid, int type)
112 > add_id(struct Client *client_p, struct Channel *chptr, char *banid, unsigned int type)
113   {
114 <  dlink_list *list;
115 <  dlink_node *ban;
116 <  size_t len = 0;
149 <  struct Ban *actualBan;
114 >  dlink_list *list = NULL;
115 >  dlink_node *ban = NULL;
116 >  struct Ban *ban_p = NULL;
117    unsigned int num_mask;
118 <  char *name = NULL, *user = NULL, *host = NULL;
118 >  size_t len = 0;
119 >  char name[NICKLEN + 1] = "";
120 >  char user[USERLEN + 1] = "";
121 >  char host[HOSTLEN + 1] = "";
122 >  struct split_nuh_item nuh;
123  
124 <  /* dont let local clients overflow the b/e/I lists */
124 >  /* Don't let local clients overflow the b/e/I lists */
125    if (MyClient(client_p))
126    {
127      num_mask = dlink_list_length(&chptr->banlist) +
# Line 159 | Line 130 | add_id(struct Client *client_p, struct C
130  
131      if (num_mask >= ConfigChannel.max_bans)
132      {
133 <      sendto_one(client_p, form_str(ERR_BANLISTFULL),
163 <                 me.name, client_p->name, chptr->chname, banid);
133 >      sendto_one_numeric(client_p, &me, ERR_BANLISTFULL, chptr->chname, banid);
134        return 0;
135      }
136  
137      collapse(banid);
138    }
139  
140 <  split_nuh(check_string(banid), &name, &user, &host);
140 >  nuh.nuhmask  = check_string(banid);
141 >  nuh.nickptr  = name;
142 >  nuh.userptr  = user;
143 >  nuh.hostptr  = host;
144 >
145 >  nuh.nicksize = sizeof(name);
146 >  nuh.usersize = sizeof(user);
147 >  nuh.hostsize = sizeof(host);
148 >
149 >  split_nuh(&nuh);
150  
151    /*
152 <   * Assemble a n!u@h and print it back to banid for sending
152 >   * Re-assemble a new n!u@h and print it back to banid for sending
153     * the mode to the channel.
154     */
155 <  len = ircsprintf(banid, "%s!%s@%s", name, user, host);
155 >  len = sprintf(banid, "%s!%s@%s", name, user, host);
156  
157    switch (type)
158    {
# Line 195 | Line 174 | add_id(struct Client *client_p, struct C
174  
175    DLINK_FOREACH(ban, list->head)
176    {
177 <    actualBan = ban->data;
178 <    if (!irccmp(actualBan->name, name) &&
179 <        !irccmp(actualBan->username, user) &&
180 <        !irccmp(actualBan->host, host))
181 <    {
203 <      MyFree(name);
204 <      MyFree(user);
205 <      MyFree(host);
177 >    ban_p = ban->data;
178 >
179 >    if (!irccmp(ban_p->name, name) &&
180 >        !irccmp(ban_p->user, user) &&
181 >        !irccmp(ban_p->host, host))
182        return 0;
207 –    }
183    }
184  
185 <  actualBan = BlockHeapAlloc(ban_heap);
186 <  actualBan->when = CurrentTime;
187 <  actualBan->name = name;
188 <  actualBan->username = user;
189 <  actualBan->host = host;
190 <  actualBan->len = len-2; /* -2 for @ and ! */
185 >  ban_p = mp_pool_get(ban_pool);
186 >  memset(ban_p, 0, sizeof(*ban_p));
187 >  ban_p->name = xstrdup(name);
188 >  ban_p->user = xstrdup(user);
189 >  ban_p->host = xstrdup(host);
190 >  ban_p->when = CurrentTime;
191 >  ban_p->len = len - 2;  /* -2 for @ and ! */
192 >  ban_p->type = parse_netmask(host, &ban_p->addr, &ban_p->bits);
193  
194    if (IsClient(client_p))
195    {
196 <    actualBan->who =
197 <      MyMalloc(strlen(client_p->name) +
198 <               strlen(client_p->username) +
199 <               strlen(client_p->host) + 3);
200 <    ircsprintf(actualBan->who, "%s!%s@%s",
224 <               client_p->name, client_p->username, client_p->host);
196 >    ban_p->who = MyCalloc(strlen(client_p->name) +
197 >                          strlen(client_p->username) +
198 >                          strlen(client_p->host) + 3);
199 >    sprintf(ban_p->who, "%s!%s@%s", client_p->name,
200 >            client_p->username, client_p->host);
201    }
202 +  else if (IsHidden(client_p) || (IsServer(client_p) && ConfigServerHide.hide_servers))
203 +    ban_p->who = xstrdup(me.name);
204    else
205 <    DupString(actualBan->who, client_p->name);
205 >    ban_p->who = xstrdup(client_p->name);
206  
207 <  dlinkAdd(actualBan, &actualBan->node, list);
207 >  dlinkAdd(ban_p, &ban_p->node, list);
208  
209    return 1;
210   }
# Line 239 | Line 217 | add_id(struct Client *client_p, struct C
217   * side effects -
218   */
219   static int
220 < del_id(struct Channel *chptr, char *banid, int type)
220 > del_id(struct Channel *chptr, char *banid, unsigned int type)
221   {
222 <  dlink_list *list;
223 <  dlink_node *ban;
224 <  struct Ban *banptr;
225 <  char *name = NULL, *user = NULL, *host = NULL;
222 >  dlink_list *list = NULL;
223 >  dlink_node *ban = NULL;
224 >  char name[NICKLEN + 1] = "";
225 >  char user[USERLEN + 1] = "";
226 >  char host[HOSTLEN + 1] = "";
227 >  struct split_nuh_item nuh;
228 >
229 >  assert(banid);
230 >
231 >  nuh.nuhmask  = check_string(banid);
232 >  nuh.nickptr  = name;
233 >  nuh.userptr  = user;
234 >  nuh.hostptr  = host;
235 >
236 >  nuh.nicksize = sizeof(name);
237 >  nuh.usersize = sizeof(user);
238 >  nuh.hostsize = sizeof(host);
239  
240 <  if (banid == NULL)
250 <    return 0;
251 <
252 <  split_nuh(check_string(banid), &name, &user, &host);
240 >  split_nuh(&nuh);
241  
242    /*
243 <   * Assemble a n!u@h and print it back to banid for sending
243 >   * Re-assemble a new n!u@h and print it back to banid for sending
244     * the mode to the channel.
245     */
246 <  ircsprintf(banid, "%s!%s@%s", name, user, host);
246 >  sprintf(banid, "%s!%s@%s", name, user, host);
247  
248    switch (type)
249    {
# Line 271 | Line 259 | del_id(struct Channel *chptr, char *bani
259        list = &chptr->invexlist;
260        break;
261      default:
262 <      sendto_realops_flags(UMODE_ALL, L_ALL,
263 <                           "del_id() called with unknown ban type %d!", type);
276 <      MyFree(name);
277 <      MyFree(user);
278 <      MyFree(host);
279 <      return(0);
262 >      assert(0);
263 >      return 0;
264    }
265  
266    DLINK_FOREACH(ban, list->head)
267    {
268 <    banptr = ban->data;
268 >    struct Ban *banptr = ban->data;
269  
270      if (!irccmp(name, banptr->name) &&
271 <        !irccmp(user, banptr->username) &&
272 <        !irccmp(host, banptr->host))
271 >        !irccmp(user, banptr->user) &&
272 >        !irccmp(host, banptr->host))
273      {
274        remove_ban(banptr, list);
291 –      MyFree(name);
292 –      MyFree(user);
293 –      MyFree(host);
275        return 1;
276      }
277    }
278  
298 –  MyFree(name);
299 –  MyFree(user);
300 –  MyFree(host);
279    return 0;
280   }
281  
304 – static const struct mode_letter
305 – {
306 –  const unsigned int mode;
307 –  const unsigned char letter;
308 – } flags[] = {
309 –  { MODE_INVITEONLY, 'i' },
310 –  { MODE_MODERATED,  'm' },
311 –  { MODE_NOPRIVMSGS, 'n' },
312 –  { MODE_PRIVATE,    'p' },
313 –  { MODE_SECRET,     's' },
314 –  { MODE_TOPICLIMIT, 't' },
315 –  { 0, '\0' }
316 – };
317 –
282   /* channel_modes()
283   *
284   * inputs       - pointer to channel
# Line 329 | Line 293 | void
293   channel_modes(struct Channel *chptr, struct Client *client_p,
294                char *mbuf, char *pbuf)
295   {
296 <  int i;
296 >  const struct mode_letter *tab = chan_modes;
297  
298    *mbuf++ = '+';
299    *pbuf = '\0';
300  
301 <  for (i = 0; flags[i].mode; ++i)
302 <    if (chptr->mode.mode & flags[i].mode)
303 <      *mbuf++ = flags[i].letter;
301 >  for (; tab->mode; ++tab)
302 >    if (chptr->mode.mode & tab->mode)
303 >      *mbuf++ = tab->letter;
304  
305    if (chptr->mode.limit)
306    {
307      *mbuf++ = 'l';
308  
309 <    if (IsMember(client_p, chptr) || IsServer(client_p))
310 <      pbuf += ircsprintf(pbuf, "%d ", chptr->mode.limit);
309 >    if (IsServer(client_p) || HasFlag(client_p, FLAGS_SERVICE) || IsMember(client_p, chptr))
310 >      pbuf += sprintf(pbuf, "%d", chptr->mode.limit);
311    }
312  
313    if (chptr->mode.key[0])
314    {
315      *mbuf++ = 'k';
316  
317 <    if (*pbuf || IsMember(client_p, chptr) || IsServer(client_p))
318 <      ircsprintf(pbuf, "%s ", chptr->mode.key);
317 >    if (IsServer(client_p) || HasFlag(client_p, FLAGS_SERVICE) || IsMember(client_p, chptr))
318 >      sprintf(pbuf, *pbuf ? " %s" : "%s", chptr->mode.key);
319    }
320  
321    *mbuf = '\0';
322   }
323  
324   /* fix_key()
325 < *
325 > *
326   * inputs       - pointer to key to clean up
327   * output       - pointer to cleaned up key
328   * side effects - input string is modified
# Line 370 | Line 334 | fix_key(char *arg)
334   {
335    unsigned char *s, *t, c;
336  
337 <  for (s = t = (unsigned char *)arg; (c = *s); s++)
337 >  for (s = t = (unsigned char *)arg; (c = *s); ++s)
338    {
339      c &= 0x7f;
340 +
341      if (c != ':' && c > ' ' && c != ',')
342        *t++ = c;
343    }
344  
345    *t = '\0';
346 <  return(arg);
346 >  return arg;
347   }
348  
349   /* fix_key_old()
350 < *
350 > *
351   * inputs       - pointer to key to clean up
352   * output       - pointer to cleaned up key
353 < * side effects - input string is modifed
353 > * side effects - input string is modifed
354   *
355   * Here we attempt to be compatible with older non-hybrid servers.
356   * We can't back down from the ':' issue however.  --Rodder
# Line 395 | Line 360 | fix_key_old(char *arg)
360   {
361    unsigned char *s, *t, c;
362  
363 <  for (s = t = (unsigned char *)arg; (c = *s); s++)
363 >  for (s = t = (unsigned char *)arg; (c = *s); ++s)
364    {
365      c &= 0x7f;
366 <    if ((c != 0x0a) && (c != ':') && (c != 0x0d) && (c != ','))
366 >
367 >    if ((c != 0x0a) && (c != ':') &&
368 >        (c != 0x0d) && (c != ','))
369        *t++ = c;
370    }
371  
372    *t = '\0';
373 <  return(arg);
373 >  return arg;
374   }
375  
376 < /* bitmasks for various error returns that set_channel_mode should only return
377 < * once per call  -orabidoo
378 < */
379 <
413 < #define SM_ERR_NOTS         0x00000001 /* No TS on channel  */
414 < #define SM_ERR_NOOPS        0x00000002 /* No chan ops       */
415 < #define SM_ERR_UNKNOWN      0x00000004
416 < #define SM_ERR_RPL_B        0x00000008
417 < #define SM_ERR_RPL_E        0x00000010
418 < #define SM_ERR_NOTONCHANNEL 0x00000020 /* Not on channel    */
419 < #define SM_ERR_RPL_I        0x00000040
420 <
421 < /* Now lets do some stuff to keep track of what combinations of
422 < * servers exist...
423 < * Note that the number of combinations doubles each time you add
424 < * something to this list. Each one is only quick if no servers use that
425 < * combination, but if the numbers get too high here MODE will get too
426 < * slow. I suggest if you get more than 7 here, you consider getting rid
427 < * of some and merging or something. If it wasn't for irc+cs we would
428 < * probably not even need to bother about most of these, but unfortunately
429 < * we do. -A1kmm
430 < */
431 <
432 < /* void init_chcap_usage_counts(void)
433 < *
434 < * Inputs       - none
435 < * Output       - none
436 < * Side-effects - Initialises the usage counts to zero. Fills in the
437 < *                chcap_yes and chcap_no combination tables.
376 > /*
377 > * inputs       - pointer to channel
378 > * output       - none
379 > * side effects - clear ban cache
380   */
381   void
382 < init_chcap_usage_counts(void)
382 > clear_ban_cache(struct Channel *chptr)
383   {
384 <  unsigned long m, c, y, n;
443 <
444 <  memset(chcap_combos, 0, sizeof(chcap_combos));
384 >  dlink_node *ptr = NULL;
385  
386 <  /* For every possible combination */
447 <  for (m = 0; m < NCHCAP_COMBOS; m++)
386 >  DLINK_FOREACH(ptr, chptr->members.head)
387    {
388 <    /* Check each capab */
389 <    for (c = y = n = 0; c < NCHCAPS; c++)
390 <    {
391 <      if ((m & (1 << c)) == 0)
453 <        n |= channel_capabs[c];
454 <      else
455 <        y |= channel_capabs[c];
456 <    }
457 <    chcap_combos[m].cap_yes = y;
458 <    chcap_combos[m].cap_no  = n;
388 >    struct Membership *ms = ptr->data;
389 >
390 >    if (MyConnect(ms->client_p))
391 >      ms->flags &= ~(CHFL_BAN_SILENCED|CHFL_BAN_CHECKED);
392    }
393   }
394  
462 – /* void set_chcap_usage_counts(struct Client *serv_p)
463 – * Input: serv_p; The client whose capabs to register.
464 – * Output: none
465 – * Side-effects: Increments the usage counts for the correct capab
466 – *               combination.
467 – */
395   void
396 < set_chcap_usage_counts(struct Client *serv_p)
396 > clear_ban_cache_client(struct Client *client_p)
397   {
398 <  int n;
398 >  dlink_node *ptr = NULL;
399  
400 <  for (n = 0; n < NCHCAP_COMBOS; n++)
400 >  DLINK_FOREACH(ptr, client_p->channel.head)
401    {
402 <    if (((serv_p->localClient->caps & chcap_combos[n].cap_yes) ==
403 <         chcap_combos[n].cap_yes) &&
477 <        ((serv_p->localClient->caps & chcap_combos[n].cap_no) == 0))
478 <    {
479 <      chcap_combos[n].count++;
480 <      return;
481 <    }
402 >    struct Membership *ms = ptr->data;
403 >    ms->flags &= ~(CHFL_BAN_SILENCED|CHFL_BAN_CHECKED);
404    }
483 –
484 –  /* This should be impossible -A1kmm. */
485 –  assert(0);
405   }
406  
407 < /* void set_chcap_usage_counts(struct Client *serv_p)
408 < *
409 < * Inputs       - serv_p; The client whose capabs to register.
491 < * Output       - none
492 < * Side-effects - Decrements the usage counts for the correct capab
493 < *                combination.
407 > /*
408 > * Bitmasks for various error returns that set_channel_mode should only return
409 > * once per call  -orabidoo
410   */
411 < void
496 < unset_chcap_usage_counts(struct Client *serv_p)
411 > enum
412   {
413 <  int n;
414 <
415 <  for (n = 0; n < NCHCAP_COMBOS; n++)
416 <  {
417 <    if ((serv_p->localClient->caps & chcap_combos[n].cap_yes) ==
418 <        chcap_combos[n].cap_yes &&
419 <        (serv_p->localClient->caps & chcap_combos[n].cap_no) == 0)
420 <    {
421 <      /* Hopefully capabs can't change dynamically or anything... */
507 <      assert(chcap_combos[n].count > 0);
508 <      chcap_combos[n].count--;
509 <      return;
510 <    }
511 <  }
512 <
513 <  /* This should be impossible -A1kmm. */
514 <  assert(0);
515 < }
413 >  SM_ERR_NOOPS        = 1 << 0,  /* No chan ops */
414 >  SM_ERR_UNKNOWN      = 1 << 1,
415 >  SM_ERR_RPL_B        = 1 << 2,
416 >  SM_ERR_RPL_E        = 1 << 3,
417 >  SM_ERR_RPL_I        = 1 << 4,
418 >  SM_ERR_NOTONCHANNEL = 1 << 5,  /* Client is not on channel */
419 >  SM_ERR_NOTOPER      = 1 << 6,
420 >  SM_ERR_ONLYSERVER   = 1 << 7
421 > };
422  
423   /* Mode functions handle mode changes for a particular mode... */
424   static void
425 < chm_nosuch(struct Client *client_p, struct Client *source_p,
426 <           struct Channel *chptr, int parc, int *parn,
521 <           char **parv, int *errors, int alev, int dir, char c, void *d,
522 <           const char *chname)
425 > chm_nosuch(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
426 >           char **parv, int *errors, int alev, int dir, char c, unsigned int d)
427   {
428    if (*errors & SM_ERR_UNKNOWN)
429      return;
430  
431    *errors |= SM_ERR_UNKNOWN;
432 <  sendto_one(source_p, form_str(ERR_UNKNOWNMODE), me.name,
529 <             source_p->name, c);
432 >  sendto_one_numeric(source_p, &me, ERR_UNKNOWNMODE, c);
433   }
434  
435   static void
436 < chm_simple(struct Client *client_p, struct Client *source_p, struct Channel *chptr,
437 <           int parc, int *parn, char **parv, int *errors, int alev, int dir,
535 <           char c, void *d, const char *chname)
436 > chm_simple(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
437 >           char **parv, int *errors, int alev, int dir, char c, unsigned int d)
438   {
537 –  long mode_type;
538 –
539 –  mode_type = (long)d;
540 –
439    if ((alev < CHACCESS_HALFOP) ||
440 <      ((mode_type == MODE_PRIVATE) && (alev < CHACCESS_CHANOP)))
440 >      ((d == MODE_PRIVATE) && (alev < CHACCESS_CHANOP)))
441    {
442      if (!(*errors & SM_ERR_NOOPS))
443 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
444 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
445 <                 me.name, source_p->name, chname);
443 >      sendto_one_numeric(source_p, &me,
444 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
445 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
446      *errors |= SM_ERR_NOOPS;
447      return;
448    }
449  
450    /* If have already dealt with this simple mode, ignore it */
451 <  if (simple_modes_mask & mode_type)
451 >  if (simple_modes_mask & d)
452 >    return;
453 >
454 >  simple_modes_mask |= d;
455 >
456 >  /* setting + */
457 >  /* Apparently, (though no one has ever told the hybrid group directly)
458 >   * admins don't like redundant mode checking. ok. It would have been nice
459 >   * if you had have told us directly. I've left the original code snippets
460 >   * in place.
461 >   *
462 >   * -Dianora
463 >   */
464 >  if (dir == MODE_ADD) /* && !(chptr->mode.mode & d)) */
465 >  {
466 >    chptr->mode.mode |= d;
467 >
468 >    mode_changes[mode_count].letter = c;
469 >    mode_changes[mode_count].dir = MODE_ADD;
470 >    mode_changes[mode_count].id = NULL;
471 >    mode_changes[mode_count].mems = ALL_MEMBERS;
472 >    mode_changes[mode_count++].arg = NULL;
473 >  }
474 >  else if (dir == MODE_DEL) /* && (chptr->mode.mode & d)) */
475 >  {
476 >    /* setting - */
477 >
478 >    chptr->mode.mode &= ~d;
479 >
480 >    mode_changes[mode_count].letter = c;
481 >    mode_changes[mode_count].dir = MODE_DEL;
482 >    mode_changes[mode_count].mems = ALL_MEMBERS;
483 >    mode_changes[mode_count].id = NULL;
484 >    mode_changes[mode_count++].arg = NULL;
485 >  }
486 > }
487 >
488 > static void
489 > chm_registered(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
490 >               char **parv, int *errors, int alev, int dir, char c, unsigned int d)
491 > {
492 >  if (!IsServer(source_p) && !HasFlag(source_p, FLAGS_SERVICE))
493 >  {
494 >    if (!(*errors & SM_ERR_ONLYSERVER))
495 >      sendto_one_numeric(source_p, &me,
496 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
497 >                         ERR_ONLYSERVERSCANCHANGE, chptr->chname);
498 >    *errors |= SM_ERR_ONLYSERVER;
499 >    return;
500 >  }
501 >
502 >  /* If have already dealt with this simple mode, ignore it */
503 >  if (simple_modes_mask & d)
504      return;
505  
506 <  simple_modes_mask |= mode_type;
506 >  simple_modes_mask |= d;
507  
508    /* setting + */
509 <  /* Apparently, (though no one has ever told the hybrid group directly)
510 <   * admins don't like redundant mode checking. ok. It would have been nice
511 <   * if you had have told us directly. I've left the original code snippets
512 <   * in place.
513 <   *
514 <   * -Dianora
515 <   */
516 <  if ((dir == MODE_ADD)) /* && !(chptr->mode.mode & mode_type)) */
509 >  /* Apparently, (though no one has ever told the hybrid group directly)
510 >   * admins don't like redundant mode checking. ok. It would have been nice
511 >   * if you had have told us directly. I've left the original code snippets
512 >   * in place.
513 >   *
514 >   * -Dianora
515 >   */
516 >  if (dir == MODE_ADD) /* && !(chptr->mode.mode & d)) */
517 >  {
518 >    chptr->mode.mode |= d;
519 >
520 >    mode_changes[mode_count].letter = c;
521 >    mode_changes[mode_count].dir = MODE_ADD;
522 >    mode_changes[mode_count].id = NULL;
523 >    mode_changes[mode_count].mems = ALL_MEMBERS;
524 >    mode_changes[mode_count++].arg = NULL;
525 >  }
526 >  else if (dir == MODE_DEL) /* && (chptr->mode.mode & d)) */
527 >  {
528 >    /* setting - */
529 >
530 >    chptr->mode.mode &= ~d;
531 >
532 >    mode_changes[mode_count].letter = c;
533 >    mode_changes[mode_count].dir = MODE_DEL;
534 >    mode_changes[mode_count].mems = ALL_MEMBERS;
535 >    mode_changes[mode_count].id = NULL;
536 >    mode_changes[mode_count++].arg = NULL;
537 >  }
538 > }
539 >
540 > static void
541 > chm_operonly(struct Client *source_p, struct Channel *chptr,
542 >             int parc, int *parn, char **parv, int *errors, int alev, int dir,
543 >             char c, unsigned int d)
544 > {
545 >  if ((alev < CHACCESS_HALFOP) || ((d == MODE_PRIVATE) && (alev < CHACCESS_CHANOP)))
546 >  {
547 >    if (!(*errors & SM_ERR_NOOPS))
548 >      sendto_one_numeric(source_p, &me,
549 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
550 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
551 >
552 >    *errors |= SM_ERR_NOOPS;
553 >    return;
554 >  }
555 >
556 >  if (MyClient(source_p) && !HasUMode(source_p, UMODE_OPER))
557 >  {
558 >    if (!(*errors & SM_ERR_NOTOPER))
559 >      sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
560 >
561 >    *errors |= SM_ERR_NOTOPER;
562 >    return;
563 >  }
564 >
565 >  /* If have already dealt with this simple mode, ignore it */
566 >  if (simple_modes_mask & d)
567 >    return;
568 >
569 >  simple_modes_mask |= d;
570 >
571 >  if (dir == MODE_ADD) /* && !(chptr->mode.mode & d)) */
572    {
573 <    chptr->mode.mode |= mode_type;
573 >    chptr->mode.mode |= d;
574  
575      mode_changes[mode_count].letter = c;
576      mode_changes[mode_count].dir = MODE_ADD;
572 –    mode_changes[mode_count].caps = 0;
573 –    mode_changes[mode_count].nocaps = 0;
577      mode_changes[mode_count].id = NULL;
578      mode_changes[mode_count].mems = ALL_MEMBERS;
579      mode_changes[mode_count++].arg = NULL;
580    }
581 <  else if ((dir == MODE_DEL)) /* && (chptr->mode.mode & mode_type)) */
581 >  else if (dir == MODE_DEL) /* && (chptr->mode.mode & d)) */
582    {
583      /* setting - */
584  
585 <    chptr->mode.mode &= ~mode_type;
585 >    chptr->mode.mode &= ~d;
586  
587      mode_changes[mode_count].letter = c;
588      mode_changes[mode_count].dir = MODE_DEL;
586 –    mode_changes[mode_count].caps = 0;
587 –    mode_changes[mode_count].nocaps = 0;
589      mode_changes[mode_count].mems = ALL_MEMBERS;
590      mode_changes[mode_count].id = NULL;
591      mode_changes[mode_count++].arg = NULL;
# Line 592 | Line 593 | chm_simple(struct Client *client_p, stru
593   }
594  
595   static void
596 < chm_ban(struct Client *client_p, struct Client *source_p,
597 <        struct Channel *chptr, int parc, int *parn,
597 <        char **parv, int *errors, int alev, int dir, char c, void *d,
598 <        const char *chname)
596 > chm_ban(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
597 >        char **parv, int *errors, int alev, int dir, char c, unsigned int d)
598   {
599    char *mask = NULL;
600  
# Line 611 | Line 610 | chm_ban(struct Client *client_p, struct
610      DLINK_FOREACH(ptr, chptr->banlist.head)
611      {
612        const struct Ban *banptr = ptr->data;
613 <      sendto_one(client_p, form_str(RPL_BANLIST),
614 <                 me.name, client_p->name, chname,
615 <                 banptr->name, banptr->username, banptr->host,
617 <                 banptr->who, banptr->when);
613 >      sendto_one_numeric(source_p, &me, RPL_BANLIST, chptr->chname,
614 >                         banptr->name, banptr->user, banptr->host,
615 >                         banptr->who, banptr->when);
616      }
617  
618 <    sendto_one(source_p, form_str(RPL_ENDOFBANLIST), me.name,
621 <               source_p->name, chname);
618 >    sendto_one_numeric(source_p, &me, RPL_ENDOFBANLIST, chptr->chname);
619      return;
620    }
621  
622    if (alev < CHACCESS_HALFOP)
623    {
624      if (!(*errors & SM_ERR_NOOPS))
625 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
626 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
627 <                 me.name, source_p->name, chname);
625 >      sendto_one_numeric(source_p, &me,
626 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
627 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
628      *errors |= SM_ERR_NOOPS;
629      return;
630    }
# Line 635 | Line 632 | chm_ban(struct Client *client_p, struct
632    if (MyClient(source_p) && (++mode_limit > MAXMODEPARAMS))
633      return;
634  
635 <  mask = parv[(*parn)++];
636 <  
637 <  if (IsServer(client_p))
635 >  mask = nuh_mask[*parn];
636 >  memcpy(mask, parv[*parn], sizeof(nuh_mask[*parn]));
637 >  ++*parn;
638 >
639 >  if (!MyConnect(source_p))
640      if (strchr(mask, ' '))
641        return;
642  
# Line 648 | Line 647 | chm_ban(struct Client *client_p, struct
647          return;
648        break;
649      case MODE_DEL:
651 – /* XXX grrrrrrr */
652 – #ifdef NO_BAN_COOKIE
650        if (!del_id(chptr, mask, CHFL_BAN))
651          return;
655 – #else
656 –     /* XXX this hack allows /mode * +o-b nick ban.cookie
657 –      * I'd like to see this hack go away in the future.
658 –      */
659 –      del_id(chptr, mask, CHFL_BAN);
660 – #endif
652        break;
653      default:
654        assert(0);
# Line 665 | Line 656 | chm_ban(struct Client *client_p, struct
656  
657    mode_changes[mode_count].letter = c;
658    mode_changes[mode_count].dir = dir;
668 –  mode_changes[mode_count].caps = 0;
669 –  mode_changes[mode_count].nocaps = 0;
659    mode_changes[mode_count].mems = ALL_MEMBERS;
660    mode_changes[mode_count].id = NULL;
661    mode_changes[mode_count++].arg = mask;
662   }
663  
664   static void
665 < chm_except(struct Client *client_p, struct Client *source_p,
666 <           struct Channel *chptr, int parc, int *parn,
678 <           char **parv, int *errors, int alev, int dir, char c, void *d,
679 <           const char *chname)
665 > chm_except(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
666 >           char **parv, int *errors, int alev, int dir, char c, unsigned int d)
667   {
668    char *mask = NULL;
669  
683 –  /* if we have +e disabled, allow local clients to do anything but
684 –   * set the mode.  This prevents the abuse of +e when just a few
685 –   * servers support it. --fl
686 –   */
687 –  if (!ConfigChannel.use_except && MyClient(source_p) &&
688 –      ((dir == MODE_ADD) && (parc > *parn)))
689 –  {
690 –    if (*errors & SM_ERR_RPL_E)
691 –      return;
692 –
693 –    *errors |= SM_ERR_RPL_E;
694 –    return;
695 –  }
696 –
670    if (alev < CHACCESS_HALFOP)
671    {
672      if (!(*errors & SM_ERR_NOOPS))
673 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
674 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
675 <                 me.name, source_p->name, chname);
673 >      sendto_one_numeric(source_p, &me,
674 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
675 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
676      *errors |= SM_ERR_NOOPS;
677      return;
678    }
# Line 716 | Line 689 | chm_except(struct Client *client_p, stru
689      DLINK_FOREACH(ptr, chptr->exceptlist.head)
690      {
691        const struct Ban *banptr = ptr->data;
692 <      sendto_one(client_p, form_str(RPL_EXCEPTLIST),
693 <                 me.name, client_p->name, chname,
694 <                 banptr->name, banptr->username, banptr->host,
695 <                 banptr->who, banptr->when);
692 >
693 >      sendto_one_numeric(source_p, &me, RPL_EXCEPTLIST, chptr->chname,
694 >                         banptr->name, banptr->user, banptr->host,
695 >                         banptr->who, banptr->when);
696      }
697  
698 <    sendto_one(source_p, form_str(RPL_ENDOFEXCEPTLIST), me.name,
726 <               source_p->name, chname);
698 >    sendto_one_numeric(source_p, &me, RPL_ENDOFEXCEPTLIST, chptr->chname);
699      return;
700    }
701  
702    if (MyClient(source_p) && (++mode_limit > MAXMODEPARAMS))
703      return;
704  
705 <  mask = parv[(*parn)++];
705 >  mask = nuh_mask[*parn];
706 >  memcpy(mask, parv[*parn], sizeof(nuh_mask[*parn]));
707 >  ++*parn;
708  
709 <  if (IsServer(client_p))
709 >  if (!MyConnect(source_p))
710      if (strchr(mask, ' '))
711        return;
712  
# Line 752 | Line 726 | chm_except(struct Client *client_p, stru
726  
727    mode_changes[mode_count].letter = c;
728    mode_changes[mode_count].dir = dir;
729 <  mode_changes[mode_count].caps = CAP_EX;
756 <  mode_changes[mode_count].nocaps = 0;
757 <
758 <  if (ConfigChannel.use_except)
759 <    mode_changes[mode_count].mems = ONLY_CHANOPS;
760 <  else
761 <    mode_changes[mode_count].mems = ONLY_SERVERS;
762 <
729 >  mode_changes[mode_count].mems = ONLY_CHANOPS;
730    mode_changes[mode_count].id = NULL;
731    mode_changes[mode_count++].arg = mask;
732   }
733  
734   static void
735 < chm_invex(struct Client *client_p, struct Client *source_p,
736 <          struct Channel *chptr, int parc, int *parn,
770 <          char **parv, int *errors, int alev, int dir, char c, void *d,
771 <          const char *chname)
735 > chm_invex(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
736 >          char **parv, int *errors, int alev, int dir, char c, unsigned int d)
737   {
738    char *mask = NULL;
739  
775 –  /* if we have +I disabled, allow local clients to do anything but
776 –   * set the mode.  This prevents the abuse of +I when just a few
777 –   * servers support it --fl
778 –   */
779 –  if (!ConfigChannel.use_invex && MyClient(source_p) &&
780 –      (dir == MODE_ADD) && (parc > *parn))
781 –  {
782 –    if (*errors & SM_ERR_RPL_I)
783 –      return;
784 –    
785 –    *errors |= SM_ERR_RPL_I;
786 –    return;
787 –  }
788 –
740    if (alev < CHACCESS_HALFOP)
741    {
742      if (!(*errors & SM_ERR_NOOPS))
743 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
744 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
745 <                 me.name, source_p->name, chname);
743 >      sendto_one_numeric(source_p, &me,
744 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
745 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
746      *errors |= SM_ERR_NOOPS;
747      return;
748    }
# Line 808 | Line 759 | chm_invex(struct Client *client_p, struc
759      DLINK_FOREACH(ptr, chptr->invexlist.head)
760      {
761        const struct Ban *banptr = ptr->data;
762 <      sendto_one(client_p, form_str(RPL_INVITELIST), me.name,
763 <                 client_p->name, chname,
764 <                 banptr->name, banptr->username, banptr->host,
765 <                 banptr->who, banptr->when);
762 >
763 >      sendto_one_numeric(source_p, &me, RPL_INVITELIST, chptr->chname,
764 >                         banptr->name, banptr->user, banptr->host,
765 >                         banptr->who, banptr->when);
766      }
767  
768 <    sendto_one(source_p, form_str(RPL_ENDOFINVITELIST), me.name,
818 <               source_p->name, chname);
768 >    sendto_one_numeric(source_p, &me, RPL_ENDOFINVITELIST, chptr->chname);
769      return;
770    }
771  
772    if (MyClient(source_p) && (++mode_limit > MAXMODEPARAMS))
773      return;
774  
775 <  mask = parv[(*parn)++];
775 >  mask = nuh_mask[*parn];
776 >  memcpy(mask, parv[*parn], sizeof(nuh_mask[*parn]));
777 >  ++*parn;
778  
779 <  if (IsServer(client_p))
779 >  if (!MyConnect(source_p))
780      if (strchr(mask, ' '))
781        return;
782  
# Line 844 | Line 796 | chm_invex(struct Client *client_p, struc
796  
797    mode_changes[mode_count].letter = c;
798    mode_changes[mode_count].dir = dir;
799 <  mode_changes[mode_count].caps = CAP_IE;
848 <  mode_changes[mode_count].nocaps = 0;
849 <
850 <  if (ConfigChannel.use_invex)
851 <    mode_changes[mode_count].mems = ONLY_CHANOPS;
852 <  else
853 <    mode_changes[mode_count].mems = ONLY_SERVERS;
854 <
799 >  mode_changes[mode_count].mems = ONLY_CHANOPS;
800    mode_changes[mode_count].id = NULL;
801    mode_changes[mode_count++].arg = mask;
802   }
803  
859 – /*
860 – * inputs       - pointer to channel
861 – * output       - none
862 – * side effects - clear ban cache
863 – */
864 – void
865 – clear_ban_cache(struct Channel *chptr)
866 – {
867 –  dlink_node *ptr = NULL;
868 –
869 –  DLINK_FOREACH(ptr, chptr->locmembers.head)
870 –  {
871 –    struct Membership *ms = ptr->data;
872 –    ms->flags &= ~(CHFL_BAN_SILENCED|CHFL_BAN_CHECKED);
873 –  }
874 – }
875 –
804   static void
805 < chm_op(struct Client *client_p, struct Client *source_p,
806 <       struct Channel *chptr, int parc, int *parn,
879 <       char **parv, int *errors, int alev, int dir, char c, void *d,
880 <       const char *chname)
805 > chm_voice(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
806 >          char **parv, int *errors, int alev, int dir, char c, unsigned int d)
807   {
808 <  char *opnick;
883 <  struct Client *targ_p;
808 >  struct Client *target_p;
809    struct Membership *member;
810  
811 <  if (alev < CHACCESS_CHANOP)
811 >  if (alev < CHACCESS_HALFOP)
812    {
813      if (!(*errors & SM_ERR_NOOPS))
814 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
815 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
816 <                 me.name, source_p->name, chname);
814 >      sendto_one_numeric(source_p, &me,
815 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
816 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
817      *errors |= SM_ERR_NOOPS;
818      return;
819    }
820  
821 <  if ((dir == MODE_QUERY) || (parc <= *parn))
821 >  if (dir == MODE_QUERY || parc <= *parn)
822      return;
823  
824 <  opnick = parv[(*parn)++];
900 <
901 <  if ((targ_p = find_chasing(client_p, source_p, opnick, NULL)) == NULL)
902 <    return;
903 <  if (!IsClient(targ_p))
824 >  if ((target_p = find_chasing(source_p, parv[(*parn)++])) == NULL)
825      return;
826  
827 <  if ((member = find_channel_link(targ_p, chptr)) == NULL)
827 >  if ((member = find_channel_link(target_p, chptr)) == NULL)
828    {
829      if (!(*errors & SM_ERR_NOTONCHANNEL))
830 <      sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL),
910 <                 me.name, source_p->name, opnick, chname);
830 >      sendto_one_numeric(source_p, &me, ERR_USERNOTINCHANNEL, target_p->name, chptr->chname);
831      *errors |= SM_ERR_NOTONCHANNEL;
832      return;
833    }
# Line 916 | Line 836 | chm_op(struct Client *client_p, struct C
836      return;
837  
838    /* no redundant mode changes */
839 <  if (dir == MODE_ADD &&  has_member_flags(member, CHFL_CHANOP))
839 >  if (dir == MODE_ADD &&  has_member_flags(member, CHFL_VOICE))
840      return;
841 <  if (dir == MODE_DEL && !has_member_flags(member, CHFL_CHANOP))
841 >  if (dir == MODE_DEL && !has_member_flags(member, CHFL_VOICE))
842      return;
843  
844 <  mode_changes[mode_count].letter = 'o';
844 >  mode_changes[mode_count].letter = 'v';
845    mode_changes[mode_count].dir = dir;
926 –  mode_changes[mode_count].caps = 0;
927 –  mode_changes[mode_count].nocaps = 0;
846    mode_changes[mode_count].mems = ALL_MEMBERS;
847 <  mode_changes[mode_count].id = targ_p->id;
848 <  mode_changes[mode_count].arg = targ_p->name;
849 <  mode_changes[mode_count++].client = targ_p;
847 >  mode_changes[mode_count].id = target_p->id;
848 >  mode_changes[mode_count].arg = target_p->name;
849 >  mode_changes[mode_count++].client = target_p;
850  
851    if (dir == MODE_ADD)
852 <  {
935 <    AddMemberFlag(member, CHFL_CHANOP);
936 <    DelMemberFlag(member, CHFL_DEOPPED);
937 <  }
852 >    AddMemberFlag(member, CHFL_VOICE);
853    else
854 <    DelMemberFlag(member, CHFL_CHANOP);
854 >    DelMemberFlag(member, CHFL_VOICE);
855   }
856  
857   #ifdef HALFOPS
858   static void
859 < chm_hop(struct Client *client_p, struct Client *source_p,
860 <       struct Channel *chptr, int parc, int *parn,
946 <       char **parv, int *errors, int alev, int dir, char c, void *d,
947 <       const char *chname)
859 > chm_hop(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
860 >        char **parv, int *errors, int alev, int dir, char c, unsigned int d)
861   {
862 <  char *opnick;
950 <  struct Client *targ_p;
862 >  struct Client *target_p;
863    struct Membership *member;
864  
865    /* *sigh* - dont allow halfops to set +/-h, they could fully control a
# Line 967 | Line 879 | chm_hop(struct Client *client_p, struct
879        ((chptr->mode.mode & MODE_PRIVATE) ? CHACCESS_CHANOP : CHACCESS_HALFOP))
880    {
881      if (!(*errors & SM_ERR_NOOPS))
882 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
883 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
884 <                 me.name, source_p->name, chname);
882 >      sendto_one_numeric(source_p, &me,
883 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
884 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
885      *errors |= SM_ERR_NOOPS;
886      return;
887    }
888  
889 <  if ((dir == MODE_QUERY) || (parc <= *parn))
889 >  if (dir == MODE_QUERY || parc <= *parn)
890      return;
891  
892 <  opnick = parv[(*parn)++];
981 <
982 <  if ((targ_p = find_chasing(client_p, source_p, opnick, NULL)) == NULL)
983 <    return;
984 <  if (!IsClient(targ_p))
892 >  if ((target_p = find_chasing(source_p, parv[(*parn)++])) == NULL)
893      return;
894  
895 <  if ((member = find_channel_link(targ_p, chptr)) == NULL)
895 >  if ((member = find_channel_link(target_p, chptr)) == NULL)
896    {
897      if (!(*errors & SM_ERR_NOTONCHANNEL))
898 <      sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL),
991 <                 me.name, source_p->name, opnick, chname);
898 >      sendto_one_numeric(source_p, &me, ERR_USERNOTINCHANNEL, target_p->name, chptr->chname);
899      *errors |= SM_ERR_NOTONCHANNEL;
900      return;
901    }
# Line 1004 | Line 911 | chm_hop(struct Client *client_p, struct
911  
912    mode_changes[mode_count].letter = 'h';
913    mode_changes[mode_count].dir = dir;
1007 –  mode_changes[mode_count].caps = 0;
1008 –  mode_changes[mode_count].nocaps = 0;
914    mode_changes[mode_count].mems = ALL_MEMBERS;
915 <  mode_changes[mode_count].id = targ_p->id;
916 <  mode_changes[mode_count].arg = targ_p->name;
917 <  mode_changes[mode_count++].client = targ_p;
915 >  mode_changes[mode_count].id = target_p->id;
916 >  mode_changes[mode_count].arg = target_p->name;
917 >  mode_changes[mode_count++].client = target_p;
918  
919    if (dir == MODE_ADD)
920    {
# Line 1022 | Line 927 | chm_hop(struct Client *client_p, struct
927   #endif
928  
929   static void
930 < chm_voice(struct Client *client_p, struct Client *source_p,
931 <          struct Channel *chptr, int parc, int *parn,
1027 <          char **parv, int *errors, int alev, int dir, char c, void *d,
1028 <          const char *chname)
930 > chm_op(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
931 >       char **parv, int *errors, int alev, int dir, char c, unsigned int d)
932   {
933 <  char *opnick;
1031 <  struct Client *targ_p;
933 >  struct Client *target_p;
934    struct Membership *member;
935  
936 <  if (alev < CHACCESS_HALFOP)
936 >  if (alev < CHACCESS_CHANOP)
937    {
938      if (!(*errors & SM_ERR_NOOPS))
939 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
940 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
941 <                 me.name, source_p->name, chname);
939 >      sendto_one_numeric(source_p, &me,
940 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
941 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
942      *errors |= SM_ERR_NOOPS;
943      return;
944    }
945  
946 <  if ((dir == MODE_QUERY) || parc <= *parn)
946 >  if (dir == MODE_QUERY || parc <= *parn)
947      return;
948  
949 <  opnick = parv[(*parn)++];
1048 <
1049 <  if ((targ_p = find_chasing(client_p, source_p, opnick, NULL)) == NULL)
1050 <    return;
1051 <  if (!IsClient(targ_p))
949 >  if ((target_p = find_chasing(source_p, parv[(*parn)++])) == NULL)
950      return;
951  
952 <  if ((member = find_channel_link(targ_p, chptr)) == NULL)
952 >  if ((member = find_channel_link(target_p, chptr)) == NULL)
953    {
954      if (!(*errors & SM_ERR_NOTONCHANNEL))
955 <      sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL),
1058 <                 me.name, source_p->name, opnick, chname);
955 >      sendto_one_numeric(source_p, &me, ERR_USERNOTINCHANNEL, target_p->name, chptr->chname);
956      *errors |= SM_ERR_NOTONCHANNEL;
957      return;
958    }
# Line 1064 | Line 961 | chm_voice(struct Client *client_p, struc
961      return;
962  
963    /* no redundant mode changes */
964 <  if (dir == MODE_ADD &&  has_member_flags(member, CHFL_VOICE))
964 >  if (dir == MODE_ADD &&  has_member_flags(member, CHFL_CHANOP))
965      return;
966 <  if (dir == MODE_DEL && !has_member_flags(member, CHFL_VOICE))
966 >  if (dir == MODE_DEL && !has_member_flags(member, CHFL_CHANOP))
967      return;
968  
969 <  mode_changes[mode_count].letter = 'v';
969 >  mode_changes[mode_count].letter = 'o';
970    mode_changes[mode_count].dir = dir;
1074 –  mode_changes[mode_count].caps = 0;
1075 –  mode_changes[mode_count].nocaps = 0;
971    mode_changes[mode_count].mems = ALL_MEMBERS;
972 <  mode_changes[mode_count].id = targ_p->id;
973 <  mode_changes[mode_count].arg = targ_p->name;
974 <  mode_changes[mode_count++].client = targ_p;
972 >  mode_changes[mode_count].id = target_p->id;
973 >  mode_changes[mode_count].arg = target_p->name;
974 >  mode_changes[mode_count++].client = target_p;
975  
976    if (dir == MODE_ADD)
977 <    AddMemberFlag(member, CHFL_VOICE);
977 >  {
978 >    AddMemberFlag(member, CHFL_CHANOP);
979 >    DelMemberFlag(member, CHFL_DEOPPED);
980 >  }
981    else
982 <    DelMemberFlag(member, CHFL_VOICE);
982 >    DelMemberFlag(member, CHFL_CHANOP);
983   }
984  
985   static void
986 < chm_limit(struct Client *client_p, struct Client *source_p,
987 <          struct Channel *chptr, int parc, int *parn,
1090 <          char **parv, int *errors, int alev, int dir, char c, void *d,
1091 <          const char *chname)
986 > chm_limit(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
987 >          char **parv, int *errors, int alev, int dir, char c, unsigned int d)
988   {
989 <  int i, limit;
1094 <  char *lstr;
989 >  int limit = 0;
990  
991    if (alev < CHACCESS_HALFOP)
992    {
993      if (!(*errors & SM_ERR_NOOPS))
994 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
995 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
996 <                 me.name, source_p->name, chname);
994 >      sendto_one_numeric(source_p, &me,
995 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
996 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
997      *errors |= SM_ERR_NOOPS;
998      return;
999    }
# Line 1106 | Line 1001 | chm_limit(struct Client *client_p, struc
1001    if (dir == MODE_QUERY)
1002      return;
1003  
1004 <  if ((dir == MODE_ADD) && parc > *parn)
1004 >  if (dir == MODE_ADD && parc > *parn)
1005    {
1006 <    lstr = parv[(*parn)++];
1006 >    char *lstr = parv[(*parn)++];
1007  
1008 <    if ((limit = atoi(lstr)) <= 0)
1008 >    if (EmptyString(lstr) || (limit = atoi(lstr)) <= 0)
1009        return;
1010  
1011 <    ircsprintf(lstr, "%d", limit);
1011 >    sprintf(lstr, "%d", limit);
1012  
1013 <    /* if somebody sets MODE #channel +ll 1 2, accept latter --fl */
1014 <    for (i = 0; i < mode_count; i++)
1120 <    {
1013 >    /* If somebody sets MODE #channel +ll 1 2, accept latter --fl */
1014 >    for (unsigned int i = 0; i < mode_count; ++i)
1015        if (mode_changes[i].letter == c && mode_changes[i].dir == MODE_ADD)
1016          mode_changes[i].letter = 0;
1123 –    }
1017  
1018      mode_changes[mode_count].letter = c;
1019      mode_changes[mode_count].dir = MODE_ADD;
1127 –    mode_changes[mode_count].caps = 0;
1128 –    mode_changes[mode_count].nocaps = 0;
1020      mode_changes[mode_count].mems = ALL_MEMBERS;
1021      mode_changes[mode_count].id = NULL;
1022      mode_changes[mode_count++].arg = lstr;
# Line 1141 | Line 1032 | chm_limit(struct Client *client_p, struc
1032  
1033      mode_changes[mode_count].letter = c;
1034      mode_changes[mode_count].dir = MODE_DEL;
1144 –    mode_changes[mode_count].caps = 0;
1145 –    mode_changes[mode_count].nocaps = 0;
1035      mode_changes[mode_count].mems = ALL_MEMBERS;
1036      mode_changes[mode_count].id = NULL;
1037      mode_changes[mode_count++].arg = NULL;
# Line 1150 | Line 1039 | chm_limit(struct Client *client_p, struc
1039   }
1040  
1041   static void
1042 < chm_key(struct Client *client_p, struct Client *source_p,
1043 <        struct Channel *chptr, int parc, int *parn,
1155 <        char **parv, int *errors, int alev, int dir, char c, void *d,
1156 <        const char *chname)
1042 > chm_key(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
1043 >        char **parv, int *errors, int alev, int dir, char c, unsigned int d)
1044   {
1158 –  int i;
1159 –  char *key;
1160 –
1045    if (alev < CHACCESS_HALFOP)
1046    {
1047      if (!(*errors & SM_ERR_NOOPS))
1048 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
1049 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
1050 <                 me.name, source_p->name, chname);
1048 >      sendto_one_numeric(source_p, &me,
1049 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
1050 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
1051      *errors |= SM_ERR_NOOPS;
1052      return;
1053    }
# Line 1171 | Line 1055 | chm_key(struct Client *client_p, struct
1055    if (dir == MODE_QUERY)
1056      return;
1057  
1058 <  if ((dir == MODE_ADD) && parc > *parn)
1058 >  if (dir == MODE_ADD && parc > *parn)
1059    {
1060 <    key = parv[(*parn)++];
1060 >    char *key = parv[(*parn)++];
1061  
1062      if (MyClient(source_p))
1063        fix_key(key);
1064      else
1065        fix_key_old(key);
1066  
1067 <    if (*key == '\0')
1067 >    if (EmptyString(key))
1068        return;
1069  
1070      assert(key[0] != ' ');
1071      strlcpy(chptr->mode.key, key, sizeof(chptr->mode.key));
1072  
1073 <    /* if somebody does MODE #channel +kk a b, accept latter --fl */
1074 <    for (i = 0; i < mode_count; i++)
1191 <    {
1073 >    /* If somebody does MODE #channel +kk a b, accept latter --fl */
1074 >    for (unsigned int i = 0; i < mode_count; ++i)
1075        if (mode_changes[i].letter == c && mode_changes[i].dir == MODE_ADD)
1076          mode_changes[i].letter = 0;
1194 –    }
1077  
1078      mode_changes[mode_count].letter = c;
1079      mode_changes[mode_count].dir = MODE_ADD;
1198 –    mode_changes[mode_count].caps = 0;
1199 –    mode_changes[mode_count].nocaps = 0;
1080      mode_changes[mode_count].mems = ALL_MEMBERS;
1081      mode_changes[mode_count].id = NULL;
1082      mode_changes[mode_count++].arg = chptr->mode.key;
# Line 1213 | Line 1093 | chm_key(struct Client *client_p, struct
1093  
1094      mode_changes[mode_count].letter = c;
1095      mode_changes[mode_count].dir = MODE_DEL;
1216 –    mode_changes[mode_count].caps = 0;
1217 –    mode_changes[mode_count].nocaps = 0;
1096      mode_changes[mode_count].mems = ALL_MEMBERS;
1097      mode_changes[mode_count].id = NULL;
1098      mode_changes[mode_count++].arg = "*";
# Line 1223 | Line 1101 | chm_key(struct Client *client_p, struct
1101  
1102   struct ChannelMode
1103   {
1104 <  void (*func) (struct Client *client_p, struct Client *source_p,
1105 <                struct Channel *chptr, int parc, int *parn, char **parv,
1106 <                int *errors, int alev, int dir, char c, void *d,
1107 <                const char *chname);
1230 <  void *d;
1104 >  void (*func)(struct Client *,
1105 >               struct Channel *, int, int *, char **,
1106 >               int *, int, int, char, unsigned int);
1107 >  unsigned int d;
1108   };
1109  
1110 < /* *INDENT-OFF* */
1234 < static struct ChannelMode ModeTable[255] =
1110 > static struct ChannelMode ModeTable[256] =
1111   {
1112 <  {chm_nosuch, NULL},
1113 <  {chm_nosuch, NULL},                             /* A */
1114 <  {chm_nosuch, NULL},                             /* B */
1115 <  {chm_nosuch, NULL},                             /* C */
1116 <  {chm_nosuch, NULL},                             /* D */
1117 <  {chm_nosuch, NULL},                             /* E */
1118 <  {chm_nosuch, NULL},                             /* F */
1119 <  {chm_nosuch, NULL},                             /* G */
1120 <  {chm_nosuch, NULL},                             /* H */
1121 <  {chm_invex, NULL},                              /* I */
1122 <  {chm_nosuch, NULL},                             /* J */
1123 <  {chm_nosuch, NULL},                             /* K */
1124 <  {chm_nosuch, NULL},                             /* L */
1125 <  {chm_nosuch, NULL},                             /* M */
1126 <  {chm_nosuch, NULL},                             /* N */
1127 <  {chm_nosuch, NULL},                             /* O */
1128 <  {chm_nosuch, NULL},                             /* P */
1129 <  {chm_nosuch, NULL},                             /* Q */
1130 <  {chm_nosuch, NULL},                             /* R */
1131 <  {chm_nosuch, NULL},                             /* S */
1132 <  {chm_nosuch, NULL},                             /* T */
1133 <  {chm_nosuch, NULL},                             /* U */
1134 <  {chm_nosuch, NULL},                             /* V */
1135 <  {chm_nosuch, NULL},                             /* W */
1136 <  {chm_nosuch, NULL},                             /* X */
1137 <  {chm_nosuch, NULL},                             /* Y */
1138 <  {chm_nosuch, NULL},                             /* Z */
1139 <  {chm_nosuch, NULL},
1140 <  {chm_nosuch, NULL},
1141 <  {chm_nosuch, NULL},
1142 <  {chm_nosuch, NULL},
1143 <  {chm_nosuch, NULL},
1144 <  {chm_nosuch, NULL},
1145 <  {chm_nosuch, NULL},                             /* a */
1146 <  {chm_ban, NULL},                                /* b */
1147 <  {chm_nosuch, NULL},                             /* c */
1148 <  {chm_nosuch, NULL},                             /* d */
1149 <  {chm_except, NULL},                             /* e */
1150 <  {chm_nosuch, NULL},                             /* f */
1151 <  {chm_nosuch, NULL},                             /* g */
1112 >  { chm_nosuch,  0 },                   /* 0x00 */
1113 >  { chm_nosuch,  0 },                   /* 0x01 */
1114 >  { chm_nosuch,  0 },                   /* 0x02 */
1115 >  { chm_nosuch,  0 },                   /* 0x03 */
1116 >  { chm_nosuch,  0 },                   /* 0x04 */
1117 >  { chm_nosuch,  0 },                   /* 0x05 */
1118 >  { chm_nosuch,  0 },                   /* 0x06 */
1119 >  { chm_nosuch,  0 },                   /* 0x07 */
1120 >  { chm_nosuch,  0 },                   /* 0x08 */
1121 >  { chm_nosuch,  0 },                   /* 0x09 */
1122 >  { chm_nosuch,  0 },                   /* 0x0a */
1123 >  { chm_nosuch,  0 },                   /* 0x0b */
1124 >  { chm_nosuch,  0 },                   /* 0x0c */
1125 >  { chm_nosuch,  0 },                   /* 0x0d */
1126 >  { chm_nosuch,  0 },                   /* 0x0e */
1127 >  { chm_nosuch,  0 },                   /* 0x0f */
1128 >  { chm_nosuch,  0 },                   /* 0x10 */
1129 >  { chm_nosuch,  0 },                   /* 0x11 */
1130 >  { chm_nosuch,  0 },                   /* 0x12 */
1131 >  { chm_nosuch,  0 },                   /* 0x13 */
1132 >  { chm_nosuch,  0 },                   /* 0x14 */
1133 >  { chm_nosuch,  0 },                   /* 0x15 */
1134 >  { chm_nosuch,  0 },                   /* 0x16 */
1135 >  { chm_nosuch,  0 },                   /* 0x17 */
1136 >  { chm_nosuch,  0 },                   /* 0x18 */
1137 >  { chm_nosuch,  0 },                   /* 0x19 */
1138 >  { chm_nosuch,  0 },                   /* 0x1a */
1139 >  { chm_nosuch,  0 },                   /* 0x1b */
1140 >  { chm_nosuch,  0 },                   /* 0x1c */
1141 >  { chm_nosuch,  0 },                   /* 0x1d */
1142 >  { chm_nosuch,  0 },                   /* 0x1e */
1143 >  { chm_nosuch,  0 },                   /* 0x1f */
1144 >  { chm_nosuch,  0 },                   /* 0x20 */
1145 >  { chm_nosuch,  0 },                   /* 0x21 */
1146 >  { chm_nosuch,  0 },                   /* 0x22 */
1147 >  { chm_nosuch,  0 },                   /* 0x23 */
1148 >  { chm_nosuch,  0 },                   /* 0x24 */
1149 >  { chm_nosuch,  0 },                   /* 0x25 */
1150 >  { chm_nosuch,  0 },                   /* 0x26 */
1151 >  { chm_nosuch,  0 },                   /* 0x27 */
1152 >  { chm_nosuch,  0 },                   /* 0x28 */
1153 >  { chm_nosuch,  0 },                   /* 0x29 */
1154 >  { chm_nosuch,  0 },                   /* 0x2a */
1155 >  { chm_nosuch,  0 },                   /* 0x2b */
1156 >  { chm_nosuch,  0 },                   /* 0x2c */
1157 >  { chm_nosuch,  0 },                   /* 0x2d */
1158 >  { chm_nosuch,  0 },                   /* 0x2e */
1159 >  { chm_nosuch,  0 },                   /* 0x2f */
1160 >  { chm_nosuch,  0 },                   /* 0x30 */
1161 >  { chm_nosuch,  0 },                   /* 0x31 */
1162 >  { chm_nosuch,  0 },                   /* 0x32 */
1163 >  { chm_nosuch,  0 },                   /* 0x33 */
1164 >  { chm_nosuch,  0 },                   /* 0x34 */
1165 >  { chm_nosuch,  0 },                   /* 0x35 */
1166 >  { chm_nosuch,  0 },                   /* 0x36 */
1167 >  { chm_nosuch,  0 },                   /* 0x37 */
1168 >  { chm_nosuch,  0 },                   /* 0x38 */
1169 >  { chm_nosuch,  0 },                   /* 0x39 */
1170 >  { chm_nosuch,  0 },                   /* 0x3a */
1171 >  { chm_nosuch,  0 },                   /* 0x3b */
1172 >  { chm_nosuch,  0 },                   /* 0x3c */
1173 >  { chm_nosuch,  0 },                   /* 0x3d */
1174 >  { chm_nosuch,  0 },                   /* 0x3e */
1175 >  { chm_nosuch,  0 },                   /* 0x3f */
1176 >  { chm_nosuch,  0 },                   /* @ */
1177 >  { chm_nosuch,  0 },                   /* A */
1178 >  { chm_nosuch,  0 },                   /* B */
1179 >  { chm_nosuch,  0 },                   /* C */
1180 >  { chm_nosuch,  0 },                   /* D */
1181 >  { chm_nosuch,  0 },                   /* E */
1182 >  { chm_nosuch,  0 },                   /* F */
1183 >  { chm_nosuch,  0 },                   /* G */
1184 >  { chm_nosuch,  0 },                   /* H */
1185 >  { chm_invex,   0 },                   /* I */
1186 >  { chm_nosuch,  0 },                   /* J */
1187 >  { chm_nosuch,  0 },                   /* K */
1188 >  { chm_nosuch,  0 },                   /* L */
1189 >  { chm_simple, MODE_MODREG},           /* M */
1190 >  { chm_nosuch,  0 },                   /* N */
1191 >  { chm_operonly, MODE_OPERONLY},       /* O */
1192 >  { chm_nosuch,  0 },                   /* P */
1193 >  { chm_nosuch,  0 },                   /* Q */
1194 >  { chm_simple, MODE_REGONLY},          /* R */
1195 >  { chm_simple, MODE_SSLONLY},          /* S */
1196 >  { chm_nosuch,  0 },                   /* T */
1197 >  { chm_nosuch,  0 },                   /* U */
1198 >  { chm_nosuch,  0 },                   /* V */
1199 >  { chm_nosuch,  0 },                   /* W */
1200 >  { chm_nosuch,  0 },                   /* X */
1201 >  { chm_nosuch,  0 },                   /* Y */
1202 >  { chm_nosuch,  0 },                   /* Z */
1203 >  { chm_nosuch,  0 },
1204 >  { chm_nosuch,  0 },
1205 >  { chm_nosuch,  0 },
1206 >  { chm_nosuch,  0 },
1207 >  { chm_nosuch,  0 },
1208 >  { chm_nosuch,  0 },
1209 >  { chm_nosuch,  0 },                   /* a */
1210 >  { chm_ban,     0 },                   /* b */
1211 >  { chm_simple, MODE_NOCTRL},           /* c */
1212 >  { chm_nosuch,  0 },                   /* d */
1213 >  { chm_except,  0 },                   /* e */
1214 >  { chm_nosuch,  0 },                   /* f */
1215 >  { chm_nosuch,  0 },                   /* g */
1216   #ifdef HALFOPS
1217 <  {chm_hop, NULL},                                /* h */
1217 >  { chm_hop,     0 },                   /* h */
1218   #else
1219 <  {chm_nosuch, NULL},                             /* h */
1219 >  { chm_nosuch,  0 },                   /* h */
1220   #endif
1221 <  {chm_simple, (void *) MODE_INVITEONLY},         /* i */
1222 <  {chm_nosuch, NULL},                             /* j */
1223 <  {chm_key, NULL},                                /* k */
1224 <  {chm_limit, NULL},                              /* l */
1225 <  {chm_simple, (void *) MODE_MODERATED},          /* m */
1226 <  {chm_simple, (void *) MODE_NOPRIVMSGS},         /* n */
1227 <  {chm_op, NULL},                                 /* o */
1228 <  {chm_simple, (void *) MODE_PRIVATE},            /* p */
1229 <  {chm_nosuch, NULL},                             /* q */
1230 <  {chm_nosuch, NULL},                             /* r */
1231 <  {chm_simple, (void *) MODE_SECRET},             /* s */
1232 <  {chm_simple, (void *) MODE_TOPICLIMIT},         /* t */
1233 <  {chm_nosuch, NULL},                             /* u */
1234 <  {chm_voice, NULL},                              /* v */
1235 <  {chm_nosuch, NULL},                             /* w */
1236 <  {chm_nosuch, NULL},                             /* x */
1237 <  {chm_nosuch, NULL},                             /* y */
1238 <  {chm_nosuch, NULL},                             /* z */
1221 >  { chm_simple,     MODE_INVITEONLY },  /* i */
1222 >  { chm_nosuch,     0               },  /* j */
1223 >  { chm_key,        0               },  /* k */
1224 >  { chm_limit,      0               },  /* l */
1225 >  { chm_simple,     MODE_MODERATED  },  /* m */
1226 >  { chm_simple,     MODE_NOPRIVMSGS },  /* n */
1227 >  { chm_op,         0               },  /* o */
1228 >  { chm_simple,     MODE_PRIVATE    },  /* p */
1229 >  { chm_nosuch,     0               },  /* q */
1230 >  { chm_registered, MODE_REGISTERED },  /* r */
1231 >  { chm_simple,     MODE_SECRET     },  /* s */
1232 >  { chm_simple,     MODE_TOPICLIMIT },  /* t */
1233 >  { chm_nosuch,     0               },  /* u */
1234 >  { chm_voice,      0               },  /* v */
1235 >  { chm_nosuch,     0               },  /* w */
1236 >  { chm_nosuch,     0               },  /* x */
1237 >  { chm_nosuch,     0               },  /* y */
1238 >  { chm_nosuch,     0               },  /* z */
1239 >  { chm_nosuch,  0 },                   /* 0x7b */
1240 >  { chm_nosuch,  0 },                   /* 0x7c */
1241 >  { chm_nosuch,  0 },                   /* 0x7d */
1242 >  { chm_nosuch,  0 },                   /* 0x7e */
1243 >  { chm_nosuch,  0 },                   /* 0x7f */
1244 >  { chm_nosuch,  0 },                   /* 0x80 */
1245 >  { chm_nosuch,  0 },                   /* 0x81 */
1246 >  { chm_nosuch,  0 },                   /* 0x82 */
1247 >  { chm_nosuch,  0 },                   /* 0x83 */
1248 >  { chm_nosuch,  0 },                   /* 0x84 */
1249 >  { chm_nosuch,  0 },                   /* 0x85 */
1250 >  { chm_nosuch,  0 },                   /* 0x86 */
1251 >  { chm_nosuch,  0 },                   /* 0x87 */
1252 >  { chm_nosuch,  0 },                   /* 0x88 */
1253 >  { chm_nosuch,  0 },                   /* 0x89 */
1254 >  { chm_nosuch,  0 },                   /* 0x8a */
1255 >  { chm_nosuch,  0 },                   /* 0x8b */
1256 >  { chm_nosuch,  0 },                   /* 0x8c */
1257 >  { chm_nosuch,  0 },                   /* 0x8d */
1258 >  { chm_nosuch,  0 },                   /* 0x8e */
1259 >  { chm_nosuch,  0 },                   /* 0x8f */
1260 >  { chm_nosuch,  0 },                   /* 0x90 */
1261 >  { chm_nosuch,  0 },                   /* 0x91 */
1262 >  { chm_nosuch,  0 },                   /* 0x92 */
1263 >  { chm_nosuch,  0 },                   /* 0x93 */
1264 >  { chm_nosuch,  0 },                   /* 0x94 */
1265 >  { chm_nosuch,  0 },                   /* 0x95 */
1266 >  { chm_nosuch,  0 },                   /* 0x96 */
1267 >  { chm_nosuch,  0 },                   /* 0x97 */
1268 >  { chm_nosuch,  0 },                   /* 0x98 */
1269 >  { chm_nosuch,  0 },                   /* 0x99 */
1270 >  { chm_nosuch,  0 },                   /* 0x9a */
1271 >  { chm_nosuch,  0 },                   /* 0x9b */
1272 >  { chm_nosuch,  0 },                   /* 0x9c */
1273 >  { chm_nosuch,  0 },                   /* 0x9d */
1274 >  { chm_nosuch,  0 },                   /* 0x9e */
1275 >  { chm_nosuch,  0 },                   /* 0x9f */
1276 >  { chm_nosuch,  0 },                   /* 0xa0 */
1277 >  { chm_nosuch,  0 },                   /* 0xa1 */
1278 >  { chm_nosuch,  0 },                   /* 0xa2 */
1279 >  { chm_nosuch,  0 },                   /* 0xa3 */
1280 >  { chm_nosuch,  0 },                   /* 0xa4 */
1281 >  { chm_nosuch,  0 },                   /* 0xa5 */
1282 >  { chm_nosuch,  0 },                   /* 0xa6 */
1283 >  { chm_nosuch,  0 },                   /* 0xa7 */
1284 >  { chm_nosuch,  0 },                   /* 0xa8 */
1285 >  { chm_nosuch,  0 },                   /* 0xa9 */
1286 >  { chm_nosuch,  0 },                   /* 0xaa */
1287 >  { chm_nosuch,  0 },                   /* 0xab */
1288 >  { chm_nosuch,  0 },                   /* 0xac */
1289 >  { chm_nosuch,  0 },                   /* 0xad */
1290 >  { chm_nosuch,  0 },                   /* 0xae */
1291 >  { chm_nosuch,  0 },                   /* 0xaf */
1292 >  { chm_nosuch,  0 },                   /* 0xb0 */
1293 >  { chm_nosuch,  0 },                   /* 0xb1 */
1294 >  { chm_nosuch,  0 },                   /* 0xb2 */
1295 >  { chm_nosuch,  0 },                   /* 0xb3 */
1296 >  { chm_nosuch,  0 },                   /* 0xb4 */
1297 >  { chm_nosuch,  0 },                   /* 0xb5 */
1298 >  { chm_nosuch,  0 },                   /* 0xb6 */
1299 >  { chm_nosuch,  0 },                   /* 0xb7 */
1300 >  { chm_nosuch,  0 },                   /* 0xb8 */
1301 >  { chm_nosuch,  0 },                   /* 0xb9 */
1302 >  { chm_nosuch,  0 },                   /* 0xba */
1303 >  { chm_nosuch,  0 },                   /* 0xbb */
1304 >  { chm_nosuch,  0 },                   /* 0xbc */
1305 >  { chm_nosuch,  0 },                   /* 0xbd */
1306 >  { chm_nosuch,  0 },                   /* 0xbe */
1307 >  { chm_nosuch,  0 },                   /* 0xbf */
1308 >  { chm_nosuch,  0 },                   /* 0xc0 */
1309 >  { chm_nosuch,  0 },                   /* 0xc1 */
1310 >  { chm_nosuch,  0 },                   /* 0xc2 */
1311 >  { chm_nosuch,  0 },                   /* 0xc3 */
1312 >  { chm_nosuch,  0 },                   /* 0xc4 */
1313 >  { chm_nosuch,  0 },                   /* 0xc5 */
1314 >  { chm_nosuch,  0 },                   /* 0xc6 */
1315 >  { chm_nosuch,  0 },                   /* 0xc7 */
1316 >  { chm_nosuch,  0 },                   /* 0xc8 */
1317 >  { chm_nosuch,  0 },                   /* 0xc9 */
1318 >  { chm_nosuch,  0 },                   /* 0xca */
1319 >  { chm_nosuch,  0 },                   /* 0xcb */
1320 >  { chm_nosuch,  0 },                   /* 0xcc */
1321 >  { chm_nosuch,  0 },                   /* 0xcd */
1322 >  { chm_nosuch,  0 },                   /* 0xce */
1323 >  { chm_nosuch,  0 },                   /* 0xcf */
1324 >  { chm_nosuch,  0 },                   /* 0xd0 */
1325 >  { chm_nosuch,  0 },                   /* 0xd1 */
1326 >  { chm_nosuch,  0 },                   /* 0xd2 */
1327 >  { chm_nosuch,  0 },                   /* 0xd3 */
1328 >  { chm_nosuch,  0 },                   /* 0xd4 */
1329 >  { chm_nosuch,  0 },                   /* 0xd5 */
1330 >  { chm_nosuch,  0 },                   /* 0xd6 */
1331 >  { chm_nosuch,  0 },                   /* 0xd7 */
1332 >  { chm_nosuch,  0 },                   /* 0xd8 */
1333 >  { chm_nosuch,  0 },                   /* 0xd9 */
1334 >  { chm_nosuch,  0 },                   /* 0xda */
1335 >  { chm_nosuch,  0 },                   /* 0xdb */
1336 >  { chm_nosuch,  0 },                   /* 0xdc */
1337 >  { chm_nosuch,  0 },                   /* 0xdd */
1338 >  { chm_nosuch,  0 },                   /* 0xde */
1339 >  { chm_nosuch,  0 },                   /* 0xdf */
1340 >  { chm_nosuch,  0 },                   /* 0xe0 */
1341 >  { chm_nosuch,  0 },                   /* 0xe1 */
1342 >  { chm_nosuch,  0 },                   /* 0xe2 */
1343 >  { chm_nosuch,  0 },                   /* 0xe3 */
1344 >  { chm_nosuch,  0 },                   /* 0xe4 */
1345 >  { chm_nosuch,  0 },                   /* 0xe5 */
1346 >  { chm_nosuch,  0 },                   /* 0xe6 */
1347 >  { chm_nosuch,  0 },                   /* 0xe7 */
1348 >  { chm_nosuch,  0 },                   /* 0xe8 */
1349 >  { chm_nosuch,  0 },                   /* 0xe9 */
1350 >  { chm_nosuch,  0 },                   /* 0xea */
1351 >  { chm_nosuch,  0 },                   /* 0xeb */
1352 >  { chm_nosuch,  0 },                   /* 0xec */
1353 >  { chm_nosuch,  0 },                   /* 0xed */
1354 >  { chm_nosuch,  0 },                   /* 0xee */
1355 >  { chm_nosuch,  0 },                   /* 0xef */
1356 >  { chm_nosuch,  0 },                   /* 0xf0 */
1357 >  { chm_nosuch,  0 },                   /* 0xf1 */
1358 >  { chm_nosuch,  0 },                   /* 0xf2 */
1359 >  { chm_nosuch,  0 },                   /* 0xf3 */
1360 >  { chm_nosuch,  0 },                   /* 0xf4 */
1361 >  { chm_nosuch,  0 },                   /* 0xf5 */
1362 >  { chm_nosuch,  0 },                   /* 0xf6 */
1363 >  { chm_nosuch,  0 },                   /* 0xf7 */
1364 >  { chm_nosuch,  0 },                   /* 0xf8 */
1365 >  { chm_nosuch,  0 },                   /* 0xf9 */
1366 >  { chm_nosuch,  0 },                   /* 0xfa */
1367 >  { chm_nosuch,  0 },                   /* 0xfb */
1368 >  { chm_nosuch,  0 },                   /* 0xfc */
1369 >  { chm_nosuch,  0 },                   /* 0xfd */
1370 >  { chm_nosuch,  0 },                   /* 0xfe */
1371 >  { chm_nosuch,  0 },                   /* 0xff */
1372   };
1300 – /* *INDENT-ON* */
1373  
1374   /* get_channel_access()
1375   *
# Line 1308 | Line 1380 | static struct ChannelMode ModeTable[255]
1380   * side effects - NONE
1381   */
1382   static int
1383 < get_channel_access(struct Client *source_p, struct Membership *member)
1383 > get_channel_access(const struct Client *source_p,
1384 >                   const struct Membership *member)
1385   {
1386    /* Let hacked servers in for now... */
1387    if (!MyClient(source_p))
1388      return CHACCESS_CHANOP;
1389  
1390 <  if (member == NULL)
1390 >  if (!member)
1391      return CHACCESS_NOTONCHAN;
1392  
1393 <  /* just to be sure.. */
1393 >  /* Just to be sure.. */
1394    assert(source_p == member->client_p);
1395  
1396    if (has_member_flags(member, CHFL_CHANOP))
# Line 1331 | Line 1404 | get_channel_access(struct Client *source
1404    return CHACCESS_PEON;
1405   }
1406  
1407 < /* void send_cap_mode_changes(struct Client *client_p,
1408 < *                        struct Client *source_p,
1336 < *                        struct Channel *chptr, int cap, int nocap)
1337 < * Input: The client sending(client_p), the source client(source_p),
1407 > /* send_mode_changes_server()
1408 > * Input: the source client(source_p),
1409   *        the channel to send mode changes for(chptr)
1410   * Output: None.
1411 < * Side-effects: Sends the appropriate mode changes to capable servers.
1341 < *
1342 < * send_cap_mode_changes() will loop the server list itself, because
1343 < * at this point in time we have 4 capabs for channels, CAP_IE, CAP_EX,
1344 < * and a server could support any number of these..
1345 < * so we make the modebufs per server, tailoring them to each servers
1346 < * specific demand.  Its not very pretty, but its one of the few realistic
1347 < * ways to handle having this many capabs for channel modes.. --fl_
1411 > * Side-effects: Sends the appropriate mode changes to servers.
1412   *
1349 – * Reverted back to my original design, except that we now keep a count
1350 – * of the number of servers which each combination as an optimisation, so
1351 – * the capabs combinations which are not needed are not worked out. -A1kmm
1413   */
1353 – /* rewritten to ensure parabuf < MODEBUFLEN -db */
1354 –
1414   static void
1415 < send_cap_mode_changes(struct Client *client_p, struct Client *source_p,
1357 <                      struct Channel *chptr, int cap, int nocap)
1415 > send_mode_changes_server(struct Client *source_p, struct Channel *chptr)
1416   {
1417 <  int i, mbl, pbl, arglen, nc, mc;
1418 <  int len;
1361 <  const char *arg = NULL;
1362 <  char *parptr;
1417 >  int mbl = 0, pbl = 0, arglen = 0, nc = 0, mc = 0;
1418 >  int len = 0;
1419    int dir = MODE_QUERY;
1420 <
1421 <  mc = 0;
1366 <  nc = 0;
1367 <  pbl = 0;
1420 >  const char *arg = NULL;
1421 >  char *parptr = NULL;
1422  
1423    parabuf[0] = '\0';
1424    parptr = parabuf;
1425  
1426 <  if ((cap & CAP_TS6) && source_p->id[0] != '\0')
1427 <    mbl = ircsprintf(modebuf, ":%s TMODE %lu %s ", source_p->id,
1374 <                     (unsigned long)chptr->channelts, chptr->chname);
1375 <  else
1376 <    mbl = ircsprintf(modebuf, ":%s MODE %s ", source_p->name,
1377 <                     chptr->chname);
1426 >  mbl = snprintf(modebuf, sizeof(modebuf), ":%s TMODE %lu %s ", source_p->id,
1427 >                 (unsigned long)chptr->channelts, chptr->chname);
1428  
1429 <  /* loop the list of - modes we have */
1430 <  for (i = 0; i < mode_count; i++)
1429 >  /* Loop the list of modes we have */
1430 >  for (unsigned i = 0; i < mode_count; ++i)
1431    {
1432 <    /* if they dont support the cap we need, or they do support a cap they
1383 <     * cant have, then dont add it to the modebuf.. that way they wont see
1384 <     * the mode
1385 <     */
1386 <    if ((mode_changes[i].letter == 0) ||
1387 <        ((cap & mode_changes[i].caps) != mode_changes[i].caps)
1388 <        || ((nocap & mode_changes[i].nocaps) != mode_changes[i].nocaps))
1432 >    if (mode_changes[i].letter == 0)
1433        continue;
1434  
1435 <    arg = "";
1392 <
1393 <    if ((cap & CAP_TS6) && mode_changes[i].id)
1435 >    if (mode_changes[i].id)
1436        arg = mode_changes[i].id;
1437 <    if (*arg == '\0')
1437 >    else
1438        arg = mode_changes[i].arg;
1439  
1440 <    /* if we're creeping past the buf size, we need to send it and make
1399 <     * another line for the other modes
1400 <     * XXX - this could give away server topology with uids being
1401 <     * different lengths, but not much we can do, except possibly break
1402 <     * them as if they were the longest of the nick or uid at all times,
1403 <     * which even then won't work as we don't always know the uid -A1kmm.
1404 <     */
1405 <    if (arg != NULL)
1440 >    if (arg)
1441        arglen = strlen(arg);
1442      else
1443        arglen = 0;
1444  
1445 +    /*
1446 +     * If we're creeping past the buf size, we need to send it and make
1447 +     * another line for the other modes
1448 +     */
1449      if ((mc == MAXMODEPARAMS) ||
1450          ((arglen + mbl + pbl + 2) > IRCD_BUFSIZE) ||
1451          (pbl + arglen + BAN_FUDGE) >= MODEBUFLEN)
1452      {
1453 <      if (nc != 0)
1454 <        sendto_server(client_p, source_p, chptr, cap, nocap,
1455 <                      LL_ICHAN | LL_ICLIENT, "%s %s",
1417 <                      modebuf, parabuf);
1453 >      if (nc)
1454 >        sendto_server(source_p, NOCAPS, NOCAPS, "%s %s", modebuf, parabuf);
1455 >
1456        nc = 0;
1457        mc = 0;
1458  
1459 <      if ((cap & CAP_TS6) && source_p->id[0] != '\0')
1460 <        mbl = ircsprintf(modebuf, ":%s MODE %s ", source_p->id,
1423 <                         chptr->chname);
1424 <      else
1425 <        mbl = ircsprintf(modebuf, ":%s MODE %s ", source_p->name,
1426 <                         chptr->chname);
1459 >      mbl = snprintf(modebuf, sizeof(modebuf), ":%s TMODE %lu %s ", source_p->id,
1460 >                     (unsigned long)chptr->channelts, chptr->chname);
1461  
1462        pbl = 0;
1463        parabuf[0] = '\0';
# Line 1441 | Line 1475 | send_cap_mode_changes(struct Client *cli
1475      modebuf[mbl] = '\0';
1476      nc++;
1477  
1478 <    if (arg != NULL)
1478 >    if (arg)
1479      {
1480 <      len = ircsprintf(parptr, "%s ", arg);
1480 >      len = sprintf(parptr, "%s ", arg);
1481        pbl += len;
1482        parptr += len;
1483        mc++;
# Line 1451 | Line 1485 | send_cap_mode_changes(struct Client *cli
1485    }
1486  
1487    if (pbl && parabuf[pbl - 1] == ' ')
1488 <    parabuf[pbl - 1] = 0;
1488 >    parabuf[pbl - 1] = '\0';
1489  
1490 <  if (nc != 0)
1491 <    sendto_server(client_p, source_p, chptr, cap, nocap,
1458 <                  LL_ICLIENT, "%s %s", modebuf, parabuf);
1490 >  if (nc)
1491 >    sendto_server(source_p, NOCAPS, NOCAPS, "%s %s", modebuf, parabuf);
1492   }
1493  
1494   /* void send_mode_changes(struct Client *client_p,
# Line 1470 | Line 1503 | send_cap_mode_changes(struct Client *cli
1503   */
1504   /* ensure parabuf < MODEBUFLEN -db */
1505   static void
1506 < send_mode_changes(struct Client *client_p, struct Client *source_p,
1474 <                  struct Channel *chptr, char *chname)
1506 > send_mode_changes(struct Client *source_p, struct Channel *chptr)
1507   {
1508 <  int i, mbl, pbl, arglen, nc, mc;
1509 <  int len;
1478 <  const char *arg = NULL;
1479 <  char *parptr;
1508 >  int mbl = 0, pbl = 0, arglen = 0, nc = 0, mc = 0;
1509 >  int len = 0;
1510    int dir = MODE_QUERY;
1511 +  const char *arg = NULL;
1512 +  char *parptr = NULL;
1513  
1514 <  /* bail out if we have nothing to do... */
1514 >  /* Bail out if we have nothing to do... */
1515    if (!mode_count)
1516      return;
1517  
1518    if (IsServer(source_p))
1519 <    mbl = ircsprintf(modebuf, ":%s MODE %s ", (IsHidden(source_p) ||
1520 <                     ConfigServerHide.hide_servers) ?
1521 <                     me.name : source_p->name, chname);
1519 >    mbl = snprintf(modebuf, sizeof(modebuf), ":%s MODE %s ", (IsHidden(source_p) ||
1520 >                   ConfigServerHide.hide_servers) ?
1521 >                   me.name : source_p->name, chptr->chname);
1522    else
1523 <    mbl = ircsprintf(modebuf, ":%s!%s@%s MODE %s ", source_p->name,
1524 <                     source_p->username, source_p->host, chname);
1493 <
1494 <  mc = 0;
1495 <  nc = 0;
1496 <  pbl = 0;
1523 >    mbl = snprintf(modebuf, sizeof(modebuf), ":%s!%s@%s MODE %s ", source_p->name,
1524 >                   source_p->username, source_p->host, chptr->chname);
1525  
1526    parabuf[0] = '\0';
1527    parptr = parabuf;
1528  
1529 <  for (i = 0; i < mode_count; i++)
1529 >  for (unsigned int i = 0; i < mode_count; ++i)
1530    {
1531      if (mode_changes[i].letter == 0 ||
1532          mode_changes[i].mems == NON_CHANOPS ||
# Line 1506 | Line 1534 | send_mode_changes(struct Client *client_
1534        continue;
1535  
1536      arg = mode_changes[i].arg;
1537 <    if (arg != NULL)
1537 >    if (arg)
1538        arglen = strlen(arg);
1539      else
1540        arglen = 0;
1541  
1542 <    if ((mc == MAXMODEPARAMS)  ||
1542 >    if ((mc == MAXMODEPARAMS)  ||
1543          ((arglen + mbl + pbl + 2) > IRCD_BUFSIZE) ||
1544 <        ((arglen + pbl + BAN_FUDGE) >= MODEBUFLEN))
1544 >        ((arglen + pbl + BAN_FUDGE) >= MODEBUFLEN))
1545      {
1546        if (mbl && modebuf[mbl - 1] == '-')
1547          modebuf[mbl - 1] = '\0';
1548  
1549 <      if (nc != 0)
1550 <        sendto_channel_local(ALL_MEMBERS, NO, chptr, "%s %s", modebuf, parabuf);
1549 >      if (nc)
1550 >        sendto_channel_local(ALL_MEMBERS, 0, chptr, "%s %s", modebuf, parabuf);
1551  
1552        nc = 0;
1553        mc = 0;
1554  
1555        if (IsServer(source_p))
1556 <        mbl = ircsprintf(modebuf, ":%s MODE %s ", me.name, chname);
1556 >        mbl = snprintf(modebuf, sizeof(modebuf), ":%s MODE %s ", (IsHidden(source_p) ||
1557 >                       ConfigServerHide.hide_servers) ?
1558 >                       me.name : source_p->name, chptr->chname);
1559        else
1560 <        mbl = ircsprintf(modebuf, ":%s!%s@%s MODE %s ", source_p->name,
1561 <                         source_p->username, source_p->host, chname);
1560 >        mbl = snprintf(modebuf, sizeof(modebuf), ":%s!%s@%s MODE %s ", source_p->name,
1561 >                       source_p->username, source_p->host, chptr->chname);
1562  
1563        pbl = 0;
1564        parabuf[0] = '\0';
# Line 1546 | Line 1576 | send_mode_changes(struct Client *client_
1576      modebuf[mbl] = '\0';
1577      nc++;
1578  
1579 <    if (arg != NULL)
1579 >    if (arg)
1580      {
1581 <      len = ircsprintf(parptr, "%s ", arg);
1581 >      len = sprintf(parptr, "%s ", arg);
1582        pbl += len;
1583        parptr += len;
1584        mc++;
# Line 1556 | Line 1586 | send_mode_changes(struct Client *client_
1586    }
1587  
1588    if (pbl && parabuf[pbl - 1] == ' ')
1589 <    parabuf[pbl - 1] = 0;
1589 >    parabuf[pbl - 1] = '\0';
1590  
1591 <  if (nc != 0)
1592 <    sendto_channel_local(ALL_MEMBERS, NO, chptr, "%s %s", modebuf, parabuf);
1591 >  if (nc)
1592 >    sendto_channel_local(ALL_MEMBERS, 0, chptr, "%s %s", modebuf, parabuf);
1593  
1594 <  nc = 0;
1595 <  mc = 0;
1594 >  send_mode_changes_server(source_p, chptr);
1595 > }
1596  
1597 <  /* Now send to servers... */
1598 <  for (i = 0; i < NCHCAP_COMBOS; i++)
1569 <    if (chcap_combos[i].count != 0)
1570 <      send_cap_mode_changes(client_p, source_p, chptr,
1571 <                            chcap_combos[i].cap_yes,
1572 <                            chcap_combos[i].cap_no);
1573 < }
1574 <
1575 < /* void set_channel_mode(struct Client *client_p, struct Client *source_p,
1576 < *               struct Channel *chptr, int parc, char **parv,
1577 < *               char *chname)
1578 < * Input: The client we received this from, the client this originated
1597 > /*
1598 > * Input: The the client this originated
1599   *        from, the channel, the parameter count starting at the modes,
1600   *        the parameters, the channel name.
1601   * Output: None.
# Line 1584 | Line 1604 | send_mode_changes(struct Client *client_
1604   *               clients.
1605   */
1606   void
1607 < set_channel_mode(struct Client *client_p, struct Client *source_p, struct Channel *chptr,
1608 <                 struct Membership *member, int parc, char *parv[], char *chname)
1607 > set_channel_mode(struct Client *source_p, struct Channel *chptr,
1608 >                 struct Membership *member, int parc, char *parv[])
1609   {
1610    int dir = MODE_ADD;
1611    int parn = 1;
1612 <  int alevel, errors = 0;
1593 <  char *ml = parv[0], c;
1594 <  int table_position;
1612 >  int alevel = 0, errors = 0;
1613  
1614    mode_count = 0;
1615    mode_limit = 0;
# Line 1599 | Line 1617 | set_channel_mode(struct Client *client_p
1617  
1618    alevel = get_channel_access(source_p, member);
1619  
1620 <  for (; (c = *ml) != '\0'; ml++)
1620 >  for (const char *ml = parv[0]; *ml; ++ml)
1621    {
1622 < #if 0
1605 <    if(mode_count > 20)
1606 <      break;
1607 < #endif
1608 <    switch (c)
1622 >    switch (*ml)
1623      {
1624        case '+':
1625          dir = MODE_ADD;
# Line 1617 | Line 1631 | set_channel_mode(struct Client *client_p
1631          dir = MODE_QUERY;
1632          break;
1633        default:
1634 <        if (c < 'A' || c > 'z')
1635 <          table_position = 0;
1636 <        else
1637 <          table_position = c - 'A' + 1;
1638 <        ModeTable[table_position].func(client_p, source_p, chptr,
1625 <                                       parc, &parn,
1626 <                                       parv, &errors, alevel, dir, c,
1627 <                                       ModeTable[table_position].d,
1628 <                                       chname);
1634 >      {
1635 >        struct ChannelMode *tptr = &ModeTable[(unsigned char)*ml];
1636 >
1637 >        tptr->func(source_p, chptr, parc, &parn, parv,
1638 >                   &errors, alevel, dir, *ml, tptr->d);
1639          break;
1640 +      }
1641      }
1642    }
1643  
1644 <  send_mode_changes(client_p, source_p, chptr, chname);
1644 >  send_mode_changes(source_p, chptr);
1645   }

Comparing:
ircd-hybrid/src/channel_mode.c (property svn:keywords), Revision 30 by adx, Sun Oct 2 20:03:27 2005 UTC vs.
ircd-hybrid/trunk/src/channel_mode.c (property svn:keywords), Revision 3685 by michael, Thu May 29 15:59:17 2014 UTC

# Line 1 | Line 1
1 < "Id Revision"
1 > Id Revision

Diff Legend

– Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)