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

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

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

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

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

Diff Legend

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