Author: Kev <klmitch@mit.edu>
authorKevin L. Mitchell <klmitch@mit.edu>
Tue, 28 Mar 2000 02:40:30 +0000 (02:40 +0000)
committerKevin L. Mitchell <klmitch@mit.edu>
Tue, 28 Mar 2000 02:40:30 +0000 (02:40 +0000)
Log message:

Various misc. bug fixes, feature additions for modebuf_* for anticipated
future use; /clearmode should now be fully functional.

git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@88 c9e4aea6-c8fd-4c43-8297-357d70d61c8c

ChangeLog
include/channel.h
ircd/channel.c
ircd/m_clearmode.c

index 804098b99f78d9e233c0a3ca59b8be2810f66813..448e9881382078850604f796346e54db22b5d840 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,24 @@
 2000-03-27  Kevin L. Mitchell  <klmitch@emc.com>
 
+       * ircd/m_clearmode.c (do_clearmode): only mark the modes the
+       channel actually has in effect for deletion
+
+       * ircd/channel.c: added explanatory comments to all added
+       functions; made flushing take place at the correct place even if
+       the MODEBUF_DEST_DEOP flag is set; rewrote build_string() helper
+       to bash some stupid bugs; made modebuf_flush() return if ModeBuf
+       is empty, fixed the apparent source, removed some bogus string
+       termination code, properly terminate the mode strings, add support
+       for HACK2 and HACK3, made limit strings not be sent if the limit
+       is being removed, changed where '+' and '-' come from in sent
+       strings, added support for DEOP flag, set up bouncing code for
+       HACK2
+
+       * ircd/Makefile.in: ran make depend
+
+       * include/channel.h: added new defines for future functionality,
+       made modebuf_flush() return int so I can use tail recursion
+
        * ircd/m_clearmode.c: add msg.h to includes; other misc cleanups
        to make it all compile
 
 #
 # ChangeLog for ircu2.10.11
 #
-# $Id: ChangeLog,v 1.33 2000-03-28 00:52:14 bleep Exp $
+# $Id: ChangeLog,v 1.34 2000-03-28 02:40:30 kev Exp $
 #
 # Insert new changes at beginning of the change list.
 #
index a75b5766c93856a052138028fc3a841436beefc2..5f7fa24e66c7fba3fe239a6dfb7cf5e195998010 100644 (file)
@@ -253,9 +253,12 @@ struct ModeBuf {
 
 #define MODEBUF_DEST_CHANNEL   0x01    /* Mode is flushed to channel */
 #define MODEBUF_DEST_SERVER    0x02    /* Mode is flushed to server */
-#define MODEBUF_DEST_OPMODE    0x40    /* Send server mode as OPMODE */
-#define MODEBUF_DEST_HACK4     0x80    /* Send a HACK(4) notice and, on
-                                          server sends, use a TS of 0 */
+
+#define MODEBUF_DEST_OPMODE    0x08    /* Send server mode as OPMODE */
+#define MODEBUF_DEST_DEOP      0x10    /* Deop the offender */
+#define MODEBUF_DEST_HACK2     0x20    /* Send a HACK(2) notice, reverse */
+#define MODEBUF_DEST_HACK3     0x40    /* Send a HACK(3) notice, TS == 0 */
+#define MODEBUF_DEST_HACK4     0x80    /* Send a HACK(4) notice, TS == 0 */
 
 #define MB_TYPE(mb, i)         ((mb)->mb_modeargs[(i)].mbm_type)
 #define MB_UINT(mb, i)         ((mb)->mb_modeargs[(i)].mbm_arg.mbma_uint)
@@ -328,6 +331,6 @@ extern void modebuf_mode_string(struct ModeBuf *mbuf, unsigned int mode,
                                char *string);
 extern void modebuf_mode_client(struct ModeBuf *mbuf, unsigned int mode,
                                struct Client *client);
-extern void modebuf_flush(struct ModeBuf *mbuf);
+extern int modebuf_flush(struct ModeBuf *mbuf);
 
 #endif /* INCLUDED_channel_h */
index 06ceff78ad046dd7cdc6d3905c155c3c1f9dd6fb..cdad174aef610bb299aafb86eb700a4f5b8225cb 100644 (file)
@@ -2659,6 +2659,10 @@ void send_hack_notice(struct Client *cptr, struct Client *sptr, int parc,
   }
 }
 
+/*
+ * This routine just initializes a ModeBuf structure with the information
+ * needed and the options given.
+ */
 void
 modebuf_init(struct ModeBuf *mbuf, struct Client *source,
             struct Client *connect, struct Channel *chan, unsigned int dest)
@@ -2678,12 +2682,17 @@ modebuf_init(struct ModeBuf *mbuf, struct Client *source,
   mbuf->mb_dest = dest;
   mbuf->mb_count = 0;
 
+  /* clear each mode-with-parameter slot */
   for (i = 0; i < MAXMODEPARAMS; i++) {
     MB_TYPE(mbuf, i) = 0;
     MB_UINT(mbuf, i) = 0;
   }
 }
 
+/*
+ * This routine simply adds modes to be added or deleted; do a binary OR
+ * with either MODE_ADD or MODE_DEL
+ */
 void
 modebuf_mode(struct ModeBuf *mbuf, unsigned int mode)
 {
@@ -2702,6 +2711,11 @@ modebuf_mode(struct ModeBuf *mbuf, unsigned int mode)
   }
 }
 
+/*
+ * This routine adds a mode to be added or deleted that takes a unsigned
+ * int parameter; mode may *only* be the relevant mode flag ORed with one
+ * of MODE_ADD or MODE_DEL
+ */
 void
 modebuf_mode_uint(struct ModeBuf *mbuf, unsigned int mode, unsigned int uint)
 {
@@ -2711,10 +2725,17 @@ modebuf_mode_uint(struct ModeBuf *mbuf, unsigned int mode, unsigned int uint)
   MB_TYPE(mbuf, mbuf->mb_count) = mode;
   MB_UINT(mbuf, mbuf->mb_count) = uint;
 
-  if (++mbuf->mb_count >= 6)
+  /* when we've reached the maximal count, flush the buffer */
+  if (++mbuf->mb_count >=
+      (MAXMODEPARAMS - (mbuf->mb_dest & MODEBUF_DEST_DEOP ? 1 : 0)))
     modebuf_flush(mbuf);
 }
 
+/*
+ * This routine adds a mode to be added or deleted that takes a string
+ * parameter; mode may *only* be the relevant mode flag ORed with one of
+ * MODE_ADD or MODE_DEL
+ */
 void
 modebuf_mode_string(struct ModeBuf *mbuf, unsigned int mode, char *string)
 {
@@ -2724,10 +2745,17 @@ modebuf_mode_string(struct ModeBuf *mbuf, unsigned int mode, char *string)
   MB_TYPE(mbuf, mbuf->mb_count) = mode;
   MB_STRING(mbuf, mbuf->mb_count) = string;
 
-  if (++mbuf->mb_count >= 6)
+  /* when we've reached the maximal count, flush the buffer */
+  if (++mbuf->mb_count >=
+      (MAXMODEPARAMS - (mbuf->mb_dest & MODEBUF_DEST_DEOP ? 1 : 0)))
     modebuf_flush(mbuf);
 }
 
+/*
+ * This routine adds a mode to be added or deleted that takes a client
+ * parameter; mode may *only* be the relevant mode flag ORed with one of
+ * MODE_ADD or MODE_DEL
+ */
 void
 modebuf_mode_client(struct ModeBuf *mbuf, unsigned int mode,
                    struct Client *client)
@@ -2738,26 +2766,40 @@ modebuf_mode_client(struct ModeBuf *mbuf, unsigned int mode,
   MB_TYPE(mbuf, mbuf->mb_count) = mode;
   MB_CLIENT(mbuf, mbuf->mb_count) = client;
 
-  if (++mbuf->mb_count >= 6)
+  /* when we've reached the maximal count, flush the buffer */
+  if (++mbuf->mb_count >=
+      (MAXMODEPARAMS - (mbuf->mb_dest & MODEBUF_DEST_DEOP ? 1 : 0)))
     modebuf_flush(mbuf);
 }
 
+/*
+ * This helper function builds an argument string in strptr, consisting
+ * of the original string, a space, and str1 and str2 concatenated (if,
+ * of course, str2 is not NULL)
+ */
 static void
 build_string(char *strptr, int *strptr_i, char *str1, char *str2)
 {
   strptr[(*strptr_i)++] = ' ';
 
-  while ((strptr[(*strptr_i)++] = *(str1++)))
-    ; /* very simple strcat */
+  while (*str1)
+    strptr[(*strptr_i)++] = *(str1++);
 
   if (str2)
-    while ((strptr[(*strptr_i)++] = *(str2++)))
-      ; /* for the two-argument form--used for numeric nicks */
+    while (*str2)
+      strptr[(*strptr_i)++] = *(str2++);
+
+  strptr[(*strptr_i)] = '\0';
 }
 
-void
+/*
+ * This is the workhorse of our ModeBuf suite; this actually generates the
+ * output MODE commands, HACK notices, or whatever.  It's pretty complicated.
+ */
+int
 modebuf_flush(struct ModeBuf *mbuf)
 {
+  /* we only need the flags that don't take args right now */
   static int flags[] = {
 /*  MODE_CHANOP,       'o', */
 /*  MODE_VOICE,                'v', */
@@ -2775,31 +2817,39 @@ modebuf_flush(struct ModeBuf *mbuf)
   int i;
   int *flag_p;
 
-  struct Client *app_source;
+  struct Client *app_source; /* where the MODE appears to come from */
 
-  char addbuf[20] = "+";
-  int addbuf_i = 1;
-  char rembuf[20] = "-";
-  int rembuf_i = 1;
-  char *bufptr;
+  char addbuf[20]; /* accumulates +psmtin, etc. */
+  int addbuf_i = 0;
+  char rembuf[20]; /* accumulates -psmtin, etc. */
+  int rembuf_i = 0;
+  char *bufptr; /* we make use of indirection to simplify the code */
   int *bufptr_i;
 
-  char addstr[MODEBUFLEN];
+  char addstr[MODEBUFLEN]; /* accumulates MODE parameters to add */
   int addstr_i;
-  char remstr[MODEBUFLEN];
+  char remstr[MODEBUFLEN]; /* accumulates MODE parameters to remove */
   int remstr_i;
-  char *strptr;
+  char *strptr; /* more indirection to simplify the code */
   int *strptr_i;
 
-  char limitbuf[10];
+  char limitbuf[10]; /* convert limits to strings */
+
+  unsigned int limitdel = MODE_LIMIT;
 
   assert(0 != mbuf);
 
+  /* If the ModeBuf is empty, we have nothing to do */
+  if (mbuf->mb_add == 0 && mbuf->mb_rem == 0 && mbuf->mb_count == 0)
+    return 0;
+
+  /* Ok, if we were given the OPMODE flag, hide the source if its a user */
   if (mbuf->mb_dest & MODEBUF_DEST_OPMODE && !IsServer(mbuf->mb_source))
-    app_source = mbuf->mb_source->from;
+    app_source = mbuf->mb_source->user->server;
   else
     app_source = mbuf->mb_source;
 
+  /* Calculate the simple flags */
   for (flag_p = flags; flag_p[0]; flag_p += 2) {
     if (*flag_p & mbuf->mb_add)
       addbuf[addbuf_i++] = flag_p[1];
@@ -2807,21 +2857,9 @@ modebuf_flush(struct ModeBuf *mbuf)
       rembuf[rembuf_i++] = flag_p[1];
   }
 
-  if (addbuf_i == 1 && rembuf_i == 1)
-    return;
-
-  if (addbuf_i == 1)
-    addbuf[0] = '\0';
-  else
-    addbuf[addbuf_i] = '\0';
-
-  if (rembuf_i == 1)
-    rembuf[0] = '\0';
-  else
-    rembuf[rembuf_i] = '\0';
-
+  /* Now go through the modes with arguments... */
   for (i = 0; i < mbuf->mb_count; i++) {
-    if (MB_TYPE(mbuf, i) & MODE_ADD) {
+    if (MB_TYPE(mbuf, i) & MODE_ADD) { /* adding or removing? */
       bufptr = addbuf;
       bufptr_i = &addbuf_i;
     } else {
@@ -2840,18 +2878,26 @@ modebuf_flush(struct ModeBuf *mbuf)
     else if (MB_TYPE(mbuf, i) & MODE_LIMIT) {
       bufptr[(*bufptr_i)++] = 'l';
 
+      /* if it's a limit, we also format the number */
       sprintf_irc(limitbuf, "%d", MB_UINT(mbuf, i));
     }
   }
 
-  if (mbuf->mb_dest & (MODEBUF_DEST_CHANNEL | MODEBUF_DEST_HACK4)) {
+  /* terminate the mode strings */
+  addbuf[addbuf_i] = '\0';
+  rembuf[rembuf_i] = '\0';
+
+  /* If we're building a user visible MODE or HACK... */
+  if (mbuf->mb_dest & (MODEBUF_DEST_CHANNEL | MODEBUF_DEST_HACK2 |
+                      MODEBUF_DEST_HACK3   | MODEBUF_DEST_HACK4)) {
+    /* Set up the parameter strings */
     addstr[0] = '\0';
     addstr_i = 0;
     remstr[0] = '\0';
     remstr_i = 0;
 
     for (i = 0; i < mbuf->mb_count; i++) {
-      if (MB_TYPE(mbuf, i) & MODE_ADD) {
+      if (MB_TYPE(mbuf, i) & MODE_ADD) { /* adding or removing? */
        strptr = addstr;
        strptr_i = &addstr_i;
       } else {
@@ -2859,34 +2905,67 @@ modebuf_flush(struct ModeBuf *mbuf)
        strptr_i = &remstr_i;
       }
 
+      /* deal with clients... */
       if (MB_TYPE(mbuf, i) & (MODE_CHANOP | MODE_VOICE))
        build_string(strptr, strptr_i, MB_CLIENT(mbuf, i)->name, 0);
+
+      /* deal with strings... */
       else if (MB_TYPE(mbuf, i) & (MODE_KEY | MODE_BAN))
        build_string(strptr, strptr_i, MB_STRING(mbuf, i), 0);
-      else if (MB_TYPE(mbuf, i) & MODE_LIMIT)
+
+      /*
+       * deal with limit; note we cannot include the limit parameter if we're
+       * removing it
+       */
+      else if ((MB_TYPE(mbuf, i) & (MODE_ADD | MODE_LIMIT)) ==
+              (MODE_ADD | MODE_LIMIT))
        build_string(strptr, strptr_i, limitbuf, 0);
     }
 
+    /* send the messages off to their destination */
     if (mbuf->mb_dest & MODEBUF_DEST_CHANNEL)
       sendto_channel_butserv(mbuf->mb_channel, app_source,
-                            ":%s MODE %s %s%s%s%s", app_source->name,
-                            mbuf->mb_channel->chname, addbuf, rembuf, addstr,
+                            ":%s MODE %s %s%s%s%s%s%s", app_source->name,
+                            mbuf->mb_channel->chname, addbuf_i ? "+" : "",
+                            addbuf, rembuf_i ? "-" : "", rembuf, addstr,
                             remstr);
-    if (mbuf->mb_dest & MODEBUF_DEST_HACK4)
-      sendto_op_mask(SNO_HACK4, "HACK(4): %s MODE %s %s%s%s%s [" TIME_T_FMT
+
+    if (mbuf->mb_dest & MODEBUF_DEST_HACK2)
+      sendto_op_mask(SNO_HACK2, "HACK(2): %s MODE %s %s%s%s%s%s%s [" TIME_T_FMT
                     "]", app_source->name, mbuf->mb_channel->chname,
-                    addbuf, rembuf, addstr, remstr,
+                    addbuf_i ? "+" : "", addbuf, rembuf_i ? "-" : "", rembuf,
+                    addstr, remstr, mbuf->mb_channel->creationtime);
+
+    if (mbuf->mb_dest & MODEBUF_DEST_HACK3)
+      sendto_op_mask(SNO_HACK3, "BOUNCE or HACK(3): %s MODE %s %s%s%s%s%s%s ["
+                    TIME_T_FMT "]", app_source->name,
+                    mbuf->mb_channel->chname, addbuf_i ? "+" : "", addbuf,
+                    rembuf_i ? "-" : "", rembuf, addstr, remstr,
                     mbuf->mb_channel->creationtime);
+
+    if (mbuf->mb_dest & MODEBUF_DEST_HACK4)
+      sendto_op_mask(SNO_HACK4, "HACK(4): %s MODE %s %s%s%s%s%s%s [" TIME_T_FMT
+                    "]", app_source->name, mbuf->mb_channel->chname,
+                    addbuf_i ? "+" : "", addbuf, rembuf_i ? "-" : "", rembuf,
+                    addstr, remstr, mbuf->mb_channel->creationtime);
   }
 
+  /* Now are we supposed to propagate to other servers? */
   if (mbuf->mb_dest & MODEBUF_DEST_SERVER) {
+    /* set up parameter string */
     addstr[0] = '\0';
     addstr_i = 0;
     remstr[0] = '\0';
     remstr_i = 0;
 
+    /*
+     * limit is supressed if we're removing it; we have to figure out which
+     * direction is the direction for it to be removed, though...
+     */
+    limitdel |= (mbuf->mb_dest & MODEBUF_DEST_HACK2) ? MODE_DEL : MODE_ADD;
+
     for (i = 0; i < mbuf->mb_count; i++) {
-      if (MB_TYPE(mbuf, i) & MODE_ADD) {
+      if (MB_TYPE(mbuf, i) & MODE_ADD) { /* adding or removing? */
        strptr = addstr;
        strptr_i = &addstr_i;
       } else {
@@ -2894,46 +2973,93 @@ modebuf_flush(struct ModeBuf *mbuf)
        strptr_i = &remstr_i;
       }
 
+      /* deal with modes that take clients */
       if (MB_TYPE(mbuf, i) & (MODE_CHANOP | MODE_VOICE))
        build_string(strptr, strptr_i, NumNick(MB_CLIENT(mbuf, i)));
+
+      /* deal with modes that take strings */
       else if (MB_TYPE(mbuf, i) & (MODE_KEY | MODE_BAN))
        build_string(strptr, strptr_i, MB_STRING(mbuf, i), 0);
-      else if (MB_TYPE(mbuf, i) & MODE_LIMIT)
+
+      /*
+       * deal with the limit.  Logic here is complicated; if HACK2 is set,
+       * we're bouncing the mode, so sense is reversed, and we have to
+       * include the original limit if it looks like it's being removed
+       */
+      else if ((MB_TYPE(mbuf, i) & limitdel) == limitdel)
        build_string(strptr, strptr_i, limitbuf, 0);
     }
 
+    /* we were told to deop the source */
+    if (mbuf->mb_dest & MODEBUF_DEST_DEOP) {
+      addbuf[addbuf_i++] = 'o'; /* remember, sense is reversed */
+      addbuf[addbuf_i] = '\0'; /* terminate the string... */
+      build_string(addstr, &addstr_i, NumNick(mbuf->mb_source)); /* add user */
+
+      /* mark that we've done this, so we don't do it again */
+      mbuf->mb_dest &= ~MODEBUF_DEST_DEOP;
+    }
+
     if (mbuf->mb_dest & MODEBUF_DEST_OPMODE) {
+      /* If OPMODE was set, we're propagating the mode as an OPMODE message */
       if (IsServer(mbuf->mb_source))
-       sendto_serv_butone(mbuf->mb_connect, "%s " TOK_OPMODE " %s %s%s%s%s",
-                          NumServ(mbuf->mb_source), mbuf->mb_channel->chname,
-                          addbuf, rembuf, addstr, remstr);
+       sendto_serv_butone(mbuf->mb_connect, "%s " TOK_OPMODE
+                          " %s %s%s%s%s%s%s", NumServ(mbuf->mb_source),
+                          mbuf->mb_channel->chname, addbuf_i ? "+" : "",
+                          addbuf, rembuf_i ? "-" : "", rembuf, addstr,
+                          remstr);
       else
-       sendto_serv_butone(mbuf->mb_connect, "%s%s " TOK_OPMODE " %s %s%s%s%s",
-                          NumNick(mbuf->mb_source), mbuf->mb_channel->chname,
-                          addbuf, rembuf, addstr, remstr);
+       sendto_serv_butone(mbuf->mb_connect, "%s%s " TOK_OPMODE
+                          " %s %s%s%s%s%s%s", NumNick(mbuf->mb_source),
+                          mbuf->mb_channel->chname, addbuf_i ? "+" : "",
+                          addbuf, rembuf_i ? "-" : "", rembuf, addstr,
+                          remstr);
+    } else if (mbuf->mb_dest & MODEBUF_DEST_HACK2) {
+      /*
+       * If HACK2 was set, we're bouncing; we send the MODE back to the
+       * connection we got it from with the senses reversed and a TS of 0;
+       * origin is us
+       */
+      sendto_one(mbuf->mb_connect, "%s " TOK_MODE " %s %s%s%s%s%s%s "
+                TIME_T_FMT, NumServ(&me), mbuf->mb_channel->chname,
+                rembuf_i ? "+" : "", rembuf, addbuf_i ? "-" : "", addbuf,
+                remstr, addstr, 0);
     } else {
+      /*
+       * We're propagating a normal MODE command to the rest of the network;
+       * we send the actual channel TS unless this is a HACK3 or a HACK4
+       */
       if (IsServer(mbuf->mb_source))
-       sendto_serv_butone(mbuf->mb_connect, "%s " TOK_MODE " %s %s%s%s%s "
+       sendto_serv_butone(mbuf->mb_connect, "%s " TOK_MODE " %s %s%s%s%s%s%s "
                           TIME_T_FMT, NumServ(mbuf->mb_source),
-                          mbuf->mb_channel->chname, addbuf, rembuf, addstr,
-                          remstr, (mbuf->mb_dest & MODEBUF_DEST_HACK4) ? 0 :
+                          mbuf->mb_channel->chname, addbuf_i ? "+" : "",
+                          addbuf, rembuf_i ? "-" : "", rembuf, addstr,
+                          remstr, (mbuf->mb_dest & (MODEBUF_DEST_HACK3 |
+                                                    MODEBUF_DEST_HACK4)) ? 0 :
                           mbuf->mb_channel->creationtime);
       else
-       sendto_serv_butone(mbuf->mb_connect, "%s%s " TOK_MODE " %s %s%s%s%s "
-                          TIME_T_FMT, NumNick(mbuf->mb_source),
-                          mbuf->mb_channel->chname, addbuf, rembuf, addstr,
-                          remstr, (mbuf->mb_dest & MODEBUF_DEST_HACK4) ? 0 :
+       sendto_serv_butone(mbuf->mb_connect, "%s%s " TOK_MODE
+                          " %s %s%s%s%s%s%s " TIME_T_FMT,
+                          NumNick(mbuf->mb_source), mbuf->mb_channel->chname,
+                          addbuf_i ? "+" : "", addbuf, rembuf_i ? "-" : "",
+                          rembuf, addstr, remstr,
+                          (mbuf->mb_dest & (MODEBUF_DEST_HACK3 |
+                                            MODEBUF_DEST_HACK4)) ? 0 :
                           mbuf->mb_channel->creationtime);
     }
   }
 
+  /* We've drained the ModeBuf... */
   mbuf->mb_add = 0;
   mbuf->mb_rem = 0;
   mbuf->mb_count = 0;
 
+  /* reinitialize the mode-with-arg slots */
   for (i = 0; i < MAXMODEPARAMS; i++) {
     MB_TYPE(mbuf, i) = 0;
     MB_UINT(mbuf, i) = 0;
   }
+
+  return 0;
 }
 
index 53cbc12c21f234ff8806cadd040be71421f2ef81..2004494c446c5df0152b676bd7ad846a8cb02666 100644 (file)
@@ -156,7 +156,7 @@ do_clearmode(struct Client *cptr, struct Client *sptr, struct Channel *chptr,
                MODEBUF_DEST_OPMODE  | /* Treat it like an OPMODE */
                MODEBUF_DEST_HACK4));  /* Generate a HACK(4) notice */
 
-  modebuf_mode(&mbuf, MODE_DEL | del_mode); /* Mark modes for deletion */
+  modebuf_mode(&mbuf, MODE_DEL | (del_mode & chptr->mode.mode));
   chptr->mode.mode &= ~del_mode; /* and of course actually delete them */
 
   /* If we're removing invite, remove all the invites */