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

Diff Legend

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