[cvslog] [CVS] Module eggdrop1.6: Change committed

cvs at eggheads.org cvs at eggheads.org
Sat Nov 21 17:12:45 CST 2009


CVSROOT    : /usr/local/cvsroot
Module     : eggdrop1.6
Commit time: 2009-11-21 23:12:40 UTC
Committer  : Rumen Stoyanov <pseudo at egg6.net>

Modified files:
     doc/Changes1.6 doc/tcl-commands.doc doc/html/tcl-commands.html
     src/chan.h src/misc.c src/modules.c src/patch.h
     src/mod/channels.mod/channels.h src/mod/channels.mod/tclchan.c
     src/mod/irc.mod/chan.c src/mod/irc.mod/cmdsirc.c
     src/mod/irc.mod/irc.c src/mod/irc.mod/irc.h
     src/mod/irc.mod/mode.c src/mod/irc.mod/msgcmds.c
     src/mod/irc.mod/tclirc.c src/mod/irc.mod/help/msg/irc.help
     src/mod/server.mod/tclserv.c

Log message:

Modified reset_chan_info() to support independent reset of various information through flags. Updated tcl_resetchan() to make use of this.

Removed redundant TOPIC requests and optimized the channel join/reset code to ask for b/e/I modes in one message.

Added safety checks after some mode bind triggers to avoid accessing freed memory and not up-to-date flag records.

Added two new Tcl commands: resetchanidle and resetchanjoin.

Modified the channel reset logic to perform live updates on the member list without deleting and readding members. Channel mode changes with the bot as a target now trigger mode binds without initial blind delays during channel join/reset.
Fixes Bugzilla Bug # 385 "MODE - bug, when bot just joined the chan"
Found by: gernot at rockstarvienna.com / Patch by: pseudo

---------------------- diff included ----------------------
Index: eggdrop1.6/doc/Changes1.6
diff -u eggdrop1.6/doc/Changes1.6:1.46 eggdrop1.6/doc/Changes1.6:1.47
--- eggdrop1.6/doc/Changes1.6:1.46	Sun Nov 15 07:10:34 2009
+++ eggdrop1.6/doc/Changes1.6	Sat Nov 21 17:12:29 2009
@@ -1,4 +1,4 @@
-$Id: Changes1.6,v 1.46 2009/11/15 13:10:34 pseudo Exp $
+$Id: Changes1.6,v 1.47 2009/11/21 23:12:29 pseudo Exp $
 
 Eggdrop Changes (since version 1.6.0)
 
@@ -6,6 +6,20 @@
 
 1.6.20 (CVS):
 
+  - Modified reset_chan_info() to support independent reset of various
+    information through flags. Updated tcl_resetchan() to make use of this.
+  - Removed redundant TOPIC requests and optimized the channel join/reset code
+    to ask for b/e/I modes in one message.
+  - Added safety checks after some mode bind triggers to avoid accessing freed
+    memory and not up-to-date flag records.
+  - Added two new Tcl commands: resetchanidle and resetchanjoin.
+  - Modified the channel reset logic to perform live updates on the member list
+    without deleting and readding members. Channel mode changes with the bot as
+    a target now trigger mode binds without initial blind delays during channel
+    join/reset.
+    Fixes Bugzilla Bug # 385 "MODE - bug, when bot just joined the chan"
+    Found by: gernot at rockstarvienna.com / Patch by: pseudo
+
   - Modified build_flags() to not repeat global bot flags when both bot
     and chan flags are requested.
   - Fixed tcl_botattr() and tcl_chattr() to return only bot-specific or
Index: eggdrop1.6/doc/html/tcl-commands.html
diff -u eggdrop1.6/doc/html/tcl-commands.html:1.61 eggdrop1.6/doc/html/tcl-commands.html:1.62
--- eggdrop1.6/doc/html/tcl-commands.html:1.61	Sun Oct 25 09:19:05 2009
+++ eggdrop1.6/doc/html/tcl-commands.html	Sat Nov 21 17:12:30 2009
@@ -1,5 +1,5 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<!-- $Id: tcl-commands.html,v 1.61 2009/10/25 15:19:05 pseudo Exp $ -->
+<!-- $Id: tcl-commands.html,v 1.62 2009/11/21 23:12:30 pseudo Exp $ -->
 
 <html>
   <head>
@@ -1552,13 +1552,100 @@
           <p><strong>Module:</strong> irc</p>
         </dd>
 
-        <dt><strong><a name="cmd_resetchan"></a>resetchan &lt;channel&gt;</strong></dt>
+        <dt><strong><a name="cmd_resetchanidle"></a>resetchanidle [nick]
+        &lt;channel&gt;</strong></dt>
 
         <dd>
-          <p><strong>Description:</strong> </p>
+          <p><strong>Description:</strong> resets the channel idle time for
+          the given nick or for all nicks on the channel if no nick is
+          specified.</p>
 
-          <p><strong>Returns:</strong> rereads in the channel info from the
-          server</p>
+          <p><strong>Returns:</strong> nothing</p>
+
+          <p><strong>Module:</strong> irc</p>
+        </dd>
+
+        <dt><strong><a name="cmd_resetchanjoin"></a>resetchanjoin [nick]
+        &lt;channel&gt;</strong></dt>
+
+        <dd>
+          <p><strong>Description:</strong> resets the channel join time for
+          the given nick or for all nicks on the channel if no nick is
+          specified.</p>
+
+          <p><strong>Returns:</strong> nothing</p>
+
+          <p><strong>Module:</strong> irc</p>
+        </dd>
+
+        <dt><strong><a name="cmd_resetchan"></a>resetchan &lt;channel&gt;
+	[flags]</strong></dt>
+
+        <dd>
+          <p><strong>Description:</strong> rereads in the channel info from
+          the server. If flags are specified, only the required information
+          will be reset, according to the given flags. Available flags are:</p>
+          
+          <blockquote>
+          <table>
+          <tr valign="top">
+            <td>
+              <p><strong>b</strong></p>
+            </td>
+
+            <td>
+              <p>reset channel bans</p>
+            </td>
+          </tr>
+          <tr valign="top">
+            <td>
+              <p><strong>e</strong></p>
+            </td>
+
+            <td>
+              <p>reset channel exempts</p>
+            </td>
+          </tr>
+          <tr valign="top">
+            <td>
+              <p><strong>I</strong></p>
+            </td>
+
+            <td>
+              <p>reset channel invites</p>
+            </td>
+          </tr>
+          <tr valign="top">
+            <td>
+              <p><strong>m</strong></p>
+            </td>
+
+            <td>
+              <p>reset channel modes</p>
+            </td>
+          </tr>
+          <tr valign="top">
+            <td>
+              <p><strong>t</strong></p>
+            </td>
+
+            <td>
+              <p>refresh channel topic</p>
+            </td>
+          </tr>
+          <tr valign="top">
+            <td>
+              <p><strong>w</strong></p>
+            </td>
+
+            <td>
+              <p>refresh memberlist</p>
+            </td>
+          </tr>
+          </table>
+          </blockquote>
+
+          <p><strong>Returns:</strong> nothing </p>
 
           <p><strong>Module:</strong> irc</p>
         </dd>
Index: eggdrop1.6/doc/tcl-commands.doc
diff -u eggdrop1.6/doc/tcl-commands.doc:1.127 eggdrop1.6/doc/tcl-commands.doc:1.128
--- eggdrop1.6/doc/tcl-commands.doc:1.127	Sun Oct 25 09:19:05 2009
+++ eggdrop1.6/doc/tcl-commands.doc	Sat Nov 21 17:12:30 2009
@@ -1,4 +1,4 @@
-$Id: tcl-commands.doc,v 1.127 2009/10/25 15:19:05 pseudo Exp $
+$Id: tcl-commands.doc,v 1.128 2009/11/21 23:12:30 pseudo Exp $
 
 Eggdrop Tcl Commands
 Last revised: August 02, 2004
@@ -736,8 +736,28 @@
     Returns: nothing
     Module: irc
 
-  resetchan <channel>
-    Description: rereads in the channel info from the server
+  resetchanidle [nick] <channel>
+    Description: resets the channel idle time for the given nick or for all
+      nicks on the channel if no nick is specified.
+    Returns: nothing
+    Module: irc
+
+  resetchanjoin [nick] <channel>
+    Description: resets the channel join time for the given nick or for all
+      nicks on the channel if no nick is specified.
+    Returns: nothing
+    Module: irc
+
+  resetchan <channel> [flags]
+    Description: rereads in the channel info from the server. If flags are
+      specified, only the required information will be reset, according to
+      the given flags. Available flags:
+	b - reset channel bans
+	e - reset channel exempts
+	I - reset channel invites
+	m - refresh channel modes 
+	t - refresh channel topic
+	w - refresh memberlist
     Returns: nothing
     Module: irc
 
Index: eggdrop1.6/src/chan.h
diff -u eggdrop1.6/src/chan.h:1.48 eggdrop1.6/src/chan.h:1.49
--- eggdrop1.6/src/chan.h:1.48	Fri Oct 30 10:02:20 2009
+++ eggdrop1.6/src/chan.h	Sat Nov 21 17:12:30 2009
@@ -3,7 +3,7 @@
  *   stuff common to chan.c and mode.c
  *   users.h needs to be loaded too
  *
- * $Id: chan.h,v 1.48 2009/10/30 16:02:20 thommey Exp $
+ * $Id: chan.h,v 1.49 2009/11/21 23:12:30 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -73,6 +73,7 @@
 #define SENTHALFOP   0x04000 /* a mode +h was already sent out for this user */
 #define SENTDEHALFOP 0x08000 /* a mode -h was already sent out for this user */
 #define WASHALFOP    0x10000 /* was a halfop before a split                  */
+#define WHO_SYNCED   0x20000 /* who reply received for this member           */
 
 #define chan_hasvoice(x)     (x->flags & CHANVOICE)
 #define chan_hasop(x)        (x->flags & CHANOP)
@@ -90,6 +91,7 @@
 #define chan_wasop(x)        (x->flags & WASOP)
 #define chan_washalfop(x)    (x->flags & WASHALFOP)
 #define chan_stopcheck(x)    (x->flags & STOPCHECK)
+#define chan_whosynced(x)    (x->flags & WHO_SYNCED)
 
 /* Why duplicate this struct for exempts and invites only under another
  * name? <cybah>
Index: eggdrop1.6/src/misc.c
diff -u eggdrop1.6/src/misc.c:1.81 eggdrop1.6/src/misc.c:1.82
--- eggdrop1.6/src/misc.c:1.81	Mon Oct 12 08:10:32 2009
+++ eggdrop1.6/src/misc.c	Sat Nov 21 17:12:30 2009
@@ -7,7 +7,7 @@
  *   help system
  *   motd display and %var substitution
  *
- * $Id: misc.c,v 1.81 2009/10/12 14:10:32 thommey Exp $
+ * $Id: misc.c,v 1.82 2009/11/21 23:12:30 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -276,7 +276,7 @@
   register char *o, *r;
 
   if (!rest)
-    return *rest = "";
+    return "";
   o = *rest;
   while (*o == ' ')
     o++;
Index: eggdrop1.6/src/mod/channels.mod/channels.h
diff -u eggdrop1.6/src/mod/channels.mod/channels.h:1.29 eggdrop1.6/src/mod/channels.mod/channels.h:1.30
--- eggdrop1.6/src/mod/channels.mod/channels.h:1.29	Sat Feb 16 15:41:06 2008
+++ eggdrop1.6/src/mod/channels.mod/channels.h	Sat Nov 21 17:12:30 2009
@@ -1,7 +1,7 @@
 /*
  * channels.h -- part of channels.mod
  *
- * $Id: channels.h,v 1.29 2008/02/16 21:41:06 guppy Exp $
+ * $Id: channels.h,v 1.30 2009/11/21 23:12:30 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -33,6 +33,14 @@
 #define MASKREASON_MAX 307    /* Max length of ban/invite/exempt/etc reasons. */
 #define MASKREASON_LEN (MASKREASON_MAX + 1)
 
+/* Flags for reset_chan_info() */
+#define CHAN_RESETMODES   0x01
+#define CHAN_RESETWHO     0x02
+#define CHAN_RESETTOPIC   0x04
+#define CHAN_RESETBANS    0x08
+#define CHAN_RESETEXEMPTS 0x10
+#define CHAN_RESETINVITED 0x20
+#define CHAN_RESETALL     0x3F
 
 #ifdef MAKING_CHANNELS
 
Index: eggdrop1.6/src/mod/channels.mod/tclchan.c
diff -u eggdrop1.6/src/mod/channels.mod/tclchan.c:1.100 eggdrop1.6/src/mod/channels.mod/tclchan.c:1.101
--- eggdrop1.6/src/mod/channels.mod/tclchan.c:1.100	Thu May  7 16:01:41 2009
+++ eggdrop1.6/src/mod/channels.mod/tclchan.c	Sat Nov 21 17:12:30 2009
@@ -1,7 +1,7 @@
 /*
  * tclchan.c -- part of channels.mod
  *
- * $Id: tclchan.c,v 1.100 2009/05/07 22:01:41 tothwolf Exp $
+ * $Id: tclchan.c,v 1.101 2009/11/21 23:12:30 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -1794,27 +1794,35 @@
  */
 static void init_channel(struct chanset_t *chan, int reset)
 {
-  chan->channel.maxmembers = 0;
-  chan->channel.mode = 0;
-  chan->channel.members = 0;
+  int flags = reset ? reset : CHAN_RESETALL;
+
   if (!reset) {
     chan->channel.key = nmalloc(1);
     chan->channel.key[0] = 0;
+    chan->channel.members = 0;
+    chan->channel.member = nmalloc(sizeof(memberlist));
+    chan->channel.member->nick[0] = 0;
+    chan->channel.member->next = NULL;
+  }
+  if (flags & CHAN_RESETMODES) {
+    if (!reset)
+    chan->channel.mode = 0;
+    chan->channel.maxmembers = 0;
+  }
+  if (flags & CHAN_RESETBANS) {
+    chan->channel.ban = nmalloc(sizeof(masklist));
+    init_masklist(chan->channel.ban);
+  }
+  if (flags & CHAN_RESETEXEMPTS) {
+    chan->channel.exempt = nmalloc(sizeof(masklist));
+    init_masklist(chan->channel.exempt);
+  }
+  if (flags & CHAN_RESETINVITED) {
+    chan->channel.invite = nmalloc(sizeof(masklist));
+    init_masklist(chan->channel.invite);
   }
-
-  chan->channel.ban = nmalloc(sizeof(masklist));
-  init_masklist(chan->channel.ban);
-
-  chan->channel.exempt = nmalloc(sizeof(masklist));
-  init_masklist(chan->channel.exempt);
-
-  chan->channel.invite = nmalloc(sizeof(masklist));
-  init_masklist(chan->channel.invite);
-
-  chan->channel.member = nmalloc(sizeof(memberlist));
-  chan->channel.member->nick[0] = 0;
-  chan->channel.member->next = NULL;
-  chan->channel.topic = NULL;
+  if (flags & CHAN_RESETTOPIC)
+    chan->channel.topic = NULL;
 }
 
 static void clear_masklist(masklist *m)
@@ -1835,24 +1843,34 @@
  */
 static void clear_channel(struct chanset_t *chan, int reset)
 {
+  int flags = reset ? reset : CHAN_RESETALL;
   memberlist *m, *m1;
 
-  if (chan->channel.topic)
-    nfree(chan->channel.topic);
-  for (m = chan->channel.member; m; m = m1) {
-    m1 = m->next;
-    nfree(m);
+  if (flags & CHAN_RESETWHO) {
+    for (m = chan->channel.member; m; m = m1) {
+      m1 = m->next;
+      if (reset)
+         m->flags &= ~WHO_SYNCED;
+      else
+        nfree(m);
+    }
+  }
+  if (flags & CHAN_RESETBANS) {
+    clear_masklist(chan->channel.ban);
+    chan->channel.ban = NULL;
+  }
+  if (flags & CHAN_RESETEXEMPTS) {
+    clear_masklist(chan->channel.exempt);
+    chan->channel.exempt = NULL;
+  }
+  if (flags & CHAN_RESETINVITED) {
+    clear_masklist(chan->channel.invite);
+    chan->channel.invite = NULL;
   }
-
-  clear_masklist(chan->channel.ban);
-  chan->channel.ban = NULL;
-  clear_masklist(chan->channel.exempt);
-  chan->channel.exempt = NULL;
-  clear_masklist(chan->channel.invite);
-  chan->channel.invite = NULL;
-
+  if ((flags & CHAN_RESETTOPIC) && chan->channel.topic)
+    nfree(chan->channel.topic);
   if (reset)
-    init_channel(chan, 1);
+    init_channel(chan, reset);
 }
 
 /* Create new channel and parse commands.
Index: eggdrop1.6/src/mod/irc.mod/chan.c
diff -u eggdrop1.6/src/mod/irc.mod/chan.c:1.130 eggdrop1.6/src/mod/irc.mod/chan.c:1.131
--- eggdrop1.6/src/mod/irc.mod/chan.c:1.130	Thu Oct  1 09:02:14 2009
+++ eggdrop1.6/src/mod/irc.mod/chan.c	Sat Nov 21 17:12:30 2009
@@ -6,7 +6,7 @@
  *   user kickban, kick, op, deop
  *   idle kicking
  *
- * $Id: chan.c,v 1.130 2009/10/01 15:02:14 pseudo Exp $
+ * $Id: chan.c,v 1.131 2009/11/21 23:12:30 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -54,6 +54,25 @@
   return x;
 }
 
+/* Remove channel members for which no WHO reply was received */
+static inline void sync_members(struct chanset_t *chan)
+{
+  memberlist *m, *next, *prev;
+
+  for (m = chan->channel.member, prev = 0; m && m->nick[0]; m = next) {
+    next = m->next;
+    if (!chan_whosynced(m)) {
+      if (prev)
+        prev->next = next;
+      else
+        chan->channel.member = next;
+      nfree(m);
+      chan->channel.members--;
+    } else
+      prev = m;
+  }
+}
+
 /* Always pass the channel dname (display name) to this function <cybah>
  */
 static void update_idle(char *chname, char *nick)
@@ -876,10 +895,10 @@
   /* Most IRCDs nowadays require +h/+o for getting e/I lists,
    * so if we're still waiting for these, we'll request them here.
    * In case we got them on join, nothing will be done */
-  if ((chan->ircnet_status & CHAN_ASKED_EXEMPTS) && use_exempts == 1)
-    dprintf(DP_MODE, "MODE %s +e\n", chan->name);
-  if ((chan->ircnet_status & CHAN_ASKED_INVITED) && use_invites == 1)
-    dprintf(DP_MODE, "MODE %s +I\n", chan->name);
+  if (chan->ircnet_status & (CHAN_ASKED_EXEMPTS | CHAN_ASKED_INVITED)) {
+    chan->ircnet_status &= ~(CHAN_ASKED_EXEMPTS | CHAN_ASKED_INVITED);
+    reset_chan_info(chan, CHAN_RESETEXEMPTS | CHAN_RESETINVITED);
+  }
   if (dobans) {
     if (channel_nouserbans(chan) && !stop_reset)
       resetbans(chan);
@@ -1029,10 +1048,9 @@
   simple_sprintf(userhost, "%s!%s", nick, m->userhost);
   /* Combine n!u at h */
   m->user = NULL;               /* No handle match (yet) */
-  if (match_my_nick(nick)) {    /* Is it me? */
+  if (match_my_nick(nick))      /* Is it me? */
     strcpy(botuserhost, m->userhost);   /* Yes, save my own userhost */
-    m->joined = now;            /* set this to keep the whining masses happy */
-  }
+  m->flags |= WHO_SYNCED;
   if (strpbrk(flags, opchars) != NULL)
     m->flags |= (CHANOP | WASOP);
   else
@@ -1101,6 +1119,7 @@
   return 0;
 }
 
+
 /* got 315: end of who
  * <server> 315 <to> <chan> :End of /who
  */
@@ -1115,6 +1134,7 @@
   if (!chan || !channel_pending(chan)) /* Left channel before we got a 315? */
     return 0;
 
+  sync_members(chan);
   chan->status |= CHAN_ACTIVE;
   chan->status &= ~CHAN_PEND;
   if (!ismember(chan, botname)) {      /* Am I on the channel now?          */
@@ -1733,7 +1753,7 @@
              chan->dname);
       chan->status |= CHAN_ACTIVE;
       chan->status &= ~CHAN_PEND;
-      reset_chan_info(chan);
+      reset_chan_info(chan, CHAN_RESETALL);
     } else {
       m = ismember(chan, nick);
       if (m && m->split && !egg_strcasecmp(m->userhost, uhost)) {
@@ -1814,7 +1834,7 @@
           else
             putlog(LOG_JOIN | LOG_MISC, chan->dname, "%s joined %s.", nick,
                    chname);
-          reset_chan_info(chan);
+          reset_chan_info(chan, (CHAN_RESETALL & ~CHAN_RESETTOPIC));
         } else {
           struct chanuserrec *cr;
 
@@ -1966,7 +1986,7 @@
              chan->dname);
       chan->status |= CHAN_ACTIVE;
       chan->status &= ~CHAN_PEND;
-      reset_chan_info(chan);
+      reset_chan_info(chan, CHAN_RESETALL);
     }
     set_handle_laston(chan->dname, u, now);
     /* This must be directly above the killmember, in case we're doing anything
Index: eggdrop1.6/src/mod/irc.mod/cmdsirc.c
diff -u eggdrop1.6/src/mod/irc.mod/cmdsirc.c:1.62 eggdrop1.6/src/mod/irc.mod/cmdsirc.c:1.63
--- eggdrop1.6/src/mod/irc.mod/cmdsirc.c:1.62	Sat Feb 16 15:41:09 2008
+++ eggdrop1.6/src/mod/irc.mod/cmdsirc.c	Sat Nov 21 17:12:30 2009
@@ -2,7 +2,7 @@
  * chancmds.c -- part of irc.mod
  *   handles commands directly relating to channel interaction
  *
- * $Id: cmdsirc.c,v 1.62 2008/02/16 21:41:09 guppy Exp $
+ * $Id: cmdsirc.c,v 1.63 2009/11/21 23:12:30 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -1143,7 +1143,7 @@
       else {
         putlog(LOG_CMDS, "*", "#%s# reset %s", dcc[idx].nick, par);
         dprintf(idx, "Resetting channel info for %s...\n", chan->dname);
-        reset_chan_info(chan);
+        reset_chan_info(chan, CHAN_RESETALL);
       }
     }
   } else if (!(u->flags & USER_MASTER))
@@ -1153,7 +1153,7 @@
     dprintf(idx, "Resetting channel info for all channels...\n");
     for (chan = chanset; chan; chan = chan->next) {
       if (channel_active(chan))
-        reset_chan_info(chan);
+        reset_chan_info(chan, CHAN_RESETALL);
     }
   }
 }
Index: eggdrop1.6/src/mod/irc.mod/help/msg/irc.help
diff -u eggdrop1.6/src/mod/irc.mod/help/msg/irc.help:1.6 eggdrop1.6/src/mod/irc.mod/help/msg/irc.help:1.7
--- eggdrop1.6/src/mod/irc.mod/help/msg/irc.help:1.6	Thu Oct  1 08:38:04 2009
+++ eggdrop1.6/src/mod/irc.mod/help/msg/irc.help	Sat Nov 21 17:12:30 2009
@@ -26,7 +26,7 @@
 This lets the bot recognize you from a new address. You don't need to specify a handle if your handle is the same as your nickname on IRC.
 %{help=info}
 %b/MSG%b %B %bINFO%b <password> [channel] [info line]
-Whatever you set as your info line will be usually be displayed when you join a channel, as long as you haven't been there in the past three minutes. It's also shown when a %bWHO%b or %bWHOIS%b. You may set an info line specific to a channel. If no channel-specific info line exists for a channel, your global info line will be displayed.
+Whatever you set as your info line will be usually displayed when you join a channel, as long as you haven't been there in the past three minutes. It's also shown when a %bWHO%b or %bWHOIS%b. You may set an info line specific to a channel. If no channel-specific info line exists for a channel, your global info line will be displayed.
 %b/MSG%b %B %bINFO%b <password> [channel] %bNONE%b
 This erases your info line.
 %{help=invite}%{+l|l}
Index: eggdrop1.6/src/mod/irc.mod/irc.c
diff -u eggdrop1.6/src/mod/irc.mod/irc.c:1.114 eggdrop1.6/src/mod/irc.mod/irc.c:1.115
--- eggdrop1.6/src/mod/irc.mod/irc.c:1.114	Sat Oct 31 08:43:09 2009
+++ eggdrop1.6/src/mod/irc.mod/irc.c	Sat Nov 21 17:12:30 2009
@@ -2,7 +2,7 @@
  * irc.c -- part of irc.mod
  *   support for channels within the bot
  *
- * $Id: irc.c,v 1.114 2009/10/31 14:43:09 thommey Exp $
+ * $Id: irc.c,v 1.115 2009/11/21 23:12:30 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -410,10 +410,11 @@
   return 1;
 }
 
-/* Reset the channel information.
+/* Reset channel information.
  */
-static void reset_chan_info(struct chanset_t *chan)
+static void reset_chan_info(struct chanset_t *chan, int reset)
 {
+  char beI[4] = "\0";
   /* Leave the channel if we aren't supposed to be there */
   if (channel_inactive(chan)) {
     dprintf(DP_MODE, "PART %s\n", chan->name);
@@ -424,29 +425,39 @@
   if (channel_pending(chan))
     return;
 
-  nfree(chan->channel.key);
-  chan->channel.key = (char *) channel_malloc(1);
-  chan->channel.key[0] = 0;
-  clear_channel(chan, 1);
-  chan->status |= CHAN_PEND;
-  chan->status &= ~(CHAN_ACTIVE | CHAN_ASKEDMODES);
-  if (!(chan->status & CHAN_ASKEDBANS)) {
+  clear_channel(chan, reset);
+  if ((reset & CHAN_RESETBANS) && !(chan->status & CHAN_ASKEDBANS)) {
     chan->status |= CHAN_ASKEDBANS;
-    dprintf(DP_MODE, "MODE %s +b\n", chan->name);
+    strcat(beI, "b");
   }
-  if (!(chan->ircnet_status & CHAN_ASKED_EXEMPTS) && use_exempts == 1) {
+  if ((reset & CHAN_RESETEXEMPTS) &&
+      !(chan->ircnet_status & CHAN_ASKED_EXEMPTS) && (use_exempts == 1)) {
     chan->ircnet_status |= CHAN_ASKED_EXEMPTS;
-    dprintf(DP_MODE, "MODE %s +e\n", chan->name);
+    strcat(beI, "e");
   }
-  if (!(chan->ircnet_status & CHAN_ASKED_INVITED) && use_invites == 1) {
+  if ((reset & CHAN_RESETINVITED) &&
+      !(chan->ircnet_status & CHAN_ASKED_INVITED) && (use_invites == 1)) {
     chan->ircnet_status |= CHAN_ASKED_INVITED;
-    dprintf(DP_MODE, "MODE %s +I\n", chan->name);
+    strcat(beI, "I");
+  }
+  if (beI[0])
+    dprintf(DP_MODE, "MODE %s +%s\n", chan->name, beI);
+  if (reset & CHAN_RESETMODES) {
+    /* done here to keep expmem happy, as this is accounted in
+       irc.mod, not channels.mod where clear_channel() resides */
+    nfree(chan->channel.key);
+    chan->channel.key = (char *) channel_malloc (1);
+    chan->channel.key[0] = 0;
+    chan->status &= ~CHAN_ASKEDMODES;
+    dprintf(DP_MODE, "MODE %s\n", chan->name);
+  }
+  if (reset & CHAN_RESETWHO) {
+    chan->status |= CHAN_PEND;
+    chan->status &= ~CHAN_ACTIVE;
+    refresh_who_chan(chan->name);
   }
-  /* These 2 need to get out asap, so into the mode queue */
-  dprintf(DP_MODE, "MODE %s\n", chan->name);
-  refresh_who_chan(chan->name);
-  /* clear_channel nuked the data...so */
-  dprintf(DP_MODE, "TOPIC %s\n", chan->name);
+  if (reset & CHAN_RESETTOPIC)
+    dprintf(DP_MODE, "TOPIC %s\n", chan->name);
 }
 
 /* Leave the specified channel and notify registered Tcl procs. This
Index: eggdrop1.6/src/mod/irc.mod/irc.h
diff -u eggdrop1.6/src/mod/irc.mod/irc.h:1.32 eggdrop1.6/src/mod/irc.mod/irc.h:1.33
--- eggdrop1.6/src/mod/irc.mod/irc.h:1.32	Sat Oct 31 08:43:09 2009
+++ eggdrop1.6/src/mod/irc.mod/irc.h	Sat Nov 21 17:12:30 2009
@@ -1,7 +1,7 @@
 /*
  * irc.h -- part of irc.mod
  *
- * $Id: irc.h,v 1.32 2009/10/31 14:43:09 thommey Exp $
+ * $Id: irc.h,v 1.33 2009/11/21 23:12:30 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -35,6 +35,15 @@
 #define REVENGE_KICK 1          /* Kicked victim        */
 #define REVENGE_DEOP 2          /* Took op              */
 
+/* Flags for reset_chan_info() */
+#define CHAN_RESETMODES   0x01
+#define CHAN_RESETWHO     0x02
+#define CHAN_RESETTOPIC   0x04
+#define CHAN_RESETBANS    0x08
+#define CHAN_RESETEXEMPTS 0x10
+#define CHAN_RESETINVITED 0x20
+#define CHAN_RESETALL     0x3F
+
 #ifdef MAKING_IRC
 static void check_tcl_need(char *, char *);
 static void check_tcl_kick(char *, char *, struct userrec *, char *, char *, char *);
@@ -66,7 +75,7 @@
 #define resetinvites(chan)  resetmasks((chan), (chan)->channel.invite,       \
                                        (chan)->invites, global_invites, 'I')
 
-static void reset_chan_info(struct chanset_t *);
+static void reset_chan_info(struct chanset_t *, int);
 static void recheck_channel(struct chanset_t *, int);
 static void set_key(struct chanset_t *, char *);
 static void maybe_revenge(struct chanset_t *, char *, char *, int);
@@ -88,7 +97,6 @@
                                                 who)
 #define newinvite(chan, mask, who)      newmask((chan)->channel.invite, mask, \
                                                 who)
-
 #else
 /* 4 - 7 */
 #define H_splt (*(p_tcl_bind_list*)(irc_funcs[4]))
Index: eggdrop1.6/src/mod/irc.mod/mode.c
diff -u eggdrop1.6/src/mod/irc.mod/mode.c:1.86 eggdrop1.6/src/mod/irc.mod/mode.c:1.87
--- eggdrop1.6/src/mod/irc.mod/mode.c:1.86	Mon Jun 30 12:45:42 2008
+++ eggdrop1.6/src/mod/irc.mod/mode.c	Sat Nov 21 17:12:30 2009
@@ -4,7 +4,7 @@
  *   channel mode changes and the bot's reaction to them
  *   setting and getting the current wanted channel modes
  *
- * $Id: mode.c,v 1.86 2008/06/30 18:45:42 tothwolf Exp $
+ * $Id: mode.c,v 1.87 2009/11/21 23:12:30 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -40,6 +40,30 @@
 static struct flag_record user = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
 static struct flag_record victim = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
 
+/* This is called after a mode bind is processed. It will check if the
+ * channel still exists and will refresh the user and victim flag records,
+ * in case users were also modified.
+ */
+struct chanset_t *modebind_refresh(char *chname,
+                                   char *usrhost, struct flag_record *usr,
+                                   char *vcrhost, struct flag_record *vcr)
+{
+  struct userrec *u;
+  struct chanset_t *chan;
+  
+  if (!chname || !(chan = findchan(chname)))
+    return NULL;
+  if (usrhost) {
+    u = get_user_by_host(usrhost);
+    get_user_flagrec(u, usr, chan->dname);
+  }
+  if (vcrhost) {
+    u = get_user_by_host(vcrhost);
+    get_user_flagrec(u, vcr, chan->dname);
+  }
+  return chan;
+}
+
 static void flush_mode(struct chanset_t *chan, int pri)
 {
   char *p, out[512], post[512];
@@ -182,7 +206,7 @@
   memberlist *mx;
   char s[21];
 
-  /* Some IRCds do not allow halfops to set certian modes. The modes halfops
+  /* Some IRCds do not allow halfops to set certain modes. The modes halfops
    * are not allowed to set can be changed in chan.h. */
 #ifdef NO_HALFOP_CHANMODES
   if (!me_op(chan))
@@ -379,6 +403,7 @@
                    char *who, struct userrec *opu, struct flag_record *opper)
 {
   memberlist *m;
+  char ch[sizeof chan->name];
   char s[UHOSTLEN];
   struct userrec *u;
   int check_chan = 0, snm = chan->stopnethack_mode;
@@ -397,10 +422,11 @@
   if (!me_op(chan) && match_my_nick(who))
     check_chan = 1;
 
-  if (!m->user) {
-    simple_sprintf(s, "%s!%s", m->nick, m->userhost);
+  strcpy(ch, chan->name);
+  simple_sprintf(s, "%s!%s", m->nick, m->userhost);
+  if (!m->user)
     u = get_user_by_host(s);
-  } else
+  else
     u = m->user;
 
   get_user_flagrec(u, &victim, chan->dname);
@@ -409,6 +435,9 @@
    */
   m->flags |= CHANOP;
   check_tcl_mode(nick, from, opu, chan->dname, "+o", who);
+  if (!(chan = modebind_refresh(ch, from, opper, s, &victim)) ||
+      !(m = ismember(chan, who)))
+    return;
   /* Added new meaning of WASOP:
    * In mode binds it means: was the user an op before got (de)opped. A script
    * now can use [wasop nick chan] to check if user was op or wasnt.
@@ -472,6 +501,7 @@
 {
   memberlist *m;
   char s[UHOSTLEN];
+  char ch[sizeof chan->name];
   struct userrec *u;
   int check_chan = 0;
   int snm = chan->stopnethack_mode;
@@ -490,10 +520,11 @@
   if (!me_op(chan) && !me_halfop(chan) && match_my_nick(who))
     check_chan = 1;
 
-  if (!m->user) {
-    simple_sprintf(s, "%s!%s", m->nick, m->userhost);
+  strcpy(ch, chan->name);
+  simple_sprintf(s, "%s!%s", m->nick, m->userhost);
+  if (!m->user)
     u = get_user_by_host(s);
-  } else
+  else
     u = m->user;
 
   get_user_flagrec(u, &victim, chan->dname);
@@ -502,6 +533,9 @@
    */
   m->flags |= CHANHALFOP;
   check_tcl_mode(nick, from, opu, chan->dname, "+h", who);
+  if (!(chan = modebind_refresh(ch, from, opper, s, &victim)) ||
+      !(m = ismember(chan, who)))
+    return;
   m->flags &= ~SENTHALFOP;
 
   if (channel_pending(chan))
@@ -562,6 +596,7 @@
                      char *who, struct userrec *opu)
 {
   memberlist *m;
+  char ch[sizeof chan->name];
   char s[UHOSTLEN], s1[UHOSTLEN];
   struct userrec *u;
   int had_halfop;
@@ -576,6 +611,7 @@
     return;
   }
 
+  strcpy(ch, chan->name);
   simple_sprintf(s, "%s!%s", m->nick, m->userhost);
   simple_sprintf(s1, "%s!%s", nick, from);
   u = get_user_by_host(s);
@@ -587,6 +623,9 @@
    */
   m->flags &= ~(CHANOP | SENTDEOP | FAKEOP);
   check_tcl_mode(nick, from, opu, chan->dname, "-o", who);
+  if (!(chan = modebind_refresh(ch, from, &user, s, &victim)) ||
+      !(m = ismember(chan, who)))
+    return;
   m->flags &= ~WASOP;
 
   if (channel_pending(chan))
@@ -650,6 +689,7 @@
                          char *who, struct userrec *opu)
 {
   memberlist *m;
+  char ch[sizeof chan->name];
   char s[UHOSTLEN], s1[UHOSTLEN];
   struct userrec *u;
   int had_halfop;
@@ -664,6 +704,7 @@
     return;
   }
 
+  strcpy(ch, chan->name);
   simple_sprintf(s, "%s!%s", m->nick, m->userhost);
   simple_sprintf(s1, "%s!%s", nick, from);
   u = get_user_by_host(s);
@@ -675,6 +716,9 @@
    */
   m->flags &= ~(CHANHALFOP | SENTDEHALFOP | FAKEHALFOP);
   check_tcl_mode(nick, from, opu, chan->dname, "-h", who);
+  if (!(chan = modebind_refresh(ch, from, &user, s, &victim)) ||
+      !(m = ismember(chan, who)))
+    return;
   /* Check comments in got_op()  (drummer) */
   m->flags &= ~WASHALFOP;
 
@@ -711,15 +755,19 @@
   }
 }
 
-static void got_ban(struct chanset_t *chan, char *nick, char *from, char *who)
+static void got_ban(struct chanset_t *chan, char *nick, char *from, char *who,
+                    char *ch, struct userrec *u)
 {
   char me[UHOSTLEN], s[UHOSTLEN], s1[UHOSTLEN];
   memberlist *m;
-  struct userrec *u;
+  struct userrec *targ;
 
   egg_snprintf(me, sizeof me, "%s!%s", botname, botuserhost);
   egg_snprintf(s, sizeof s, "%s!%s", nick, from);
   newban(chan, who, s);
+  check_tcl_mode(nick, from, u, chan->dname, "+b", who);
+  if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
+    return;
 
   if (channel_pending(chan) || HALFOP_CANTDOMODE('b'))
     return;
@@ -738,9 +786,9 @@
     for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
       egg_snprintf(s1, sizeof s1, "%s!%s", m->nick, m->userhost);
       if (wild_match(who, s1)) {
-        u = get_user_by_host(s1);
-        if (u) {
-          get_user_flagrec(u, &victim, chan->dname);
+        targ = get_user_by_host(s1);
+        if (targ) {
+          get_user_flagrec(targ, &victim, chan->dname);
           if ((glob_friend(victim) || (glob_op(victim) && !chan_deop(victim)) ||
                chan_friend(victim) || chan_op(victim)) && !glob_master(user) &&
               !glob_bot(user) && !chan_master(user) && !isexempted(chan, s1)) {
@@ -776,7 +824,7 @@
 }
 
 static void got_unban(struct chanset_t *chan, char *nick, char *from,
-                      char *who, struct userrec *u)
+                      char *who, char *ch, struct userrec *u)
 {
   masklist *b, *old;
 
@@ -792,6 +840,9 @@
     nfree(b->who);
     nfree(b);
   }
+  check_tcl_mode(nick, from, u, chan->dname, "-b", who);
+  if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
+    return;
 
   if (channel_pending(chan))
     return;
@@ -806,12 +857,15 @@
 }
 
 static void got_exempt(struct chanset_t *chan, char *nick, char *from,
-                       char *who)
+                       char *who, char *ch, struct userrec *u)
 {
   char s[UHOSTLEN];
 
   simple_sprintf(s, "%s!%s", nick, from);
   newexempt(chan, who, s);
+  check_tcl_mode(nick, from, u, chan->dname, "+e", who);
+  if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
+    return;
 
   if (channel_pending(chan) || HALFOP_CANTDOMODE('e'))
     return;
@@ -832,7 +886,7 @@
 }
 
 static void got_unexempt(struct chanset_t *chan, char *nick, char *from,
-                         char *who, struct userrec *u)
+                         char *who, char *ch, struct userrec *u)
 {
   masklist *e = chan->channel.exempt, *old = NULL;
   masklist *b;
@@ -851,6 +905,9 @@
     nfree(e->who);
     nfree(e);
   }
+  check_tcl_mode(nick, from, u, chan->dname, "-e", who);
+  if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
+    return;
 
   if (channel_pending(chan))
     return;
@@ -877,12 +934,15 @@
 }
 
 static void got_invite(struct chanset_t *chan, char *nick, char *from,
-                       char *who)
+                       char *who, char *ch, struct userrec *u)
 {
   char s[UHOSTLEN];
 
   simple_sprintf(s, "%s!%s", nick, from);
   newinvite(chan, who, s);
+  check_tcl_mode(nick, from, u, chan->dname, "+I", who);
+  if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
+    return;
 
   if (channel_pending(chan) || HALFOP_CANTDOMODE('I'))
     return;
@@ -903,7 +963,7 @@
 }
 
 static void got_uninvite(struct chanset_t *chan, char *nick, char *from,
-                         char *who, struct userrec *u)
+                         char *who, char *ch, struct userrec *u)
 {
   masklist *inv = chan->channel.invite, *old = NULL;
 
@@ -920,6 +980,9 @@
     nfree(inv->who);
     nfree(inv);
   }
+  check_tcl_mode(nick, from, u, chan->dname, "-I", who);
+  if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
+    return;
 
   if (channel_pending(chan))
     return;
@@ -1092,6 +1155,9 @@
             reversing = 1;
           if (ms2[0] == '-') {
             check_tcl_mode(nick, from, u, chan->dname, ms2, "");
+            /* The Tcl proc might have modified/removed the chan or user */
+            if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
+              return 0;
             if (channel_active(chan)) {
               if (reversing && (chan->channel.maxmembers != 0)) {
                 simple_sprintf(s, "%d", chan->channel.maxmembers);
@@ -1111,6 +1177,9 @@
             chan->channel.maxmembers = atoi(op);
             check_tcl_mode(nick, from, u, chan->dname, ms2,
                            int_to_base10(chan->channel.maxmembers));
+            /* The Tcl proc might have modified/removed the chan or user */
+            if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
+              return 0;
             if (channel_pending(chan))
               break;
             if ((reversing && !(chan->mode_pls_prot & CHANLIMIT)) ||
@@ -1135,6 +1204,10 @@
           if (op == '\0') {
             break;
           }
+          check_tcl_mode(nick, from, u, chan->dname, ms2, op);
+          /* The Tcl proc might have modified/removed the chan or user */
+          if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
+            return 0;
           if (ms2[0] == '+') {
             set_key(chan, op);
             if (channel_active(chan))
@@ -1149,7 +1222,6 @@
             }
             set_key(chan, NULL);
           }
-          check_tcl_mode(nick, from, u, chan->dname, ms2, op);
           break;
         case 'o':
           op = newsplit(&msg);
@@ -1185,6 +1257,8 @@
               m->flags &= ~SENTVOICE;
               m->flags |= CHANVOICE;
               check_tcl_mode(nick, from, u, chan->dname, ms2, op);
+              if (!(chan = modebind_refresh(ch, from, &user, s, &victim)))
+                return 0;
               if (channel_active(chan) && !glob_master(user) &&
                   !chan_master(user) && !match_my_nick(nick)) {
                 if (chan_quiet(victim) ||
@@ -1197,6 +1271,8 @@
               m->flags &= ~SENTDEVOICE;
               m->flags &= ~CHANVOICE;
               check_tcl_mode(nick, from, u, chan->dname, ms2, op);
+              if (!(chan = modebind_refresh(ch, from, &user, s, &victim)))
+                return 0;
               if (channel_active(chan) && !glob_master(user) &&
                   !chan_master(user) && !match_my_nick(nick)) {
                 if ((channel_autovoice(chan) && !chan_quiet(victim) &&
@@ -1214,32 +1290,31 @@
           op = newsplit(&msg);
           fixcolon(op);
           if (ms2[0] == '+')
-            got_ban(chan, nick, from, op);
+            got_ban(chan, nick, from, op, ch, u);
           else
-            got_unban(chan, nick, from, op, u);
-          check_tcl_mode(nick, from, u, chan->dname, ms2, op);
+            got_unban(chan, nick, from, op, ch, u);
           break;
         case 'e':
           op = newsplit(&msg);
           fixcolon(op);
           if (ms2[0] == '+')
-            got_exempt(chan, nick, from, op);
+            got_exempt(chan, nick, from, op, ch, u);
           else
-            got_unexempt(chan, nick, from, op, u);
-          check_tcl_mode(nick, from, u, chan->dname, ms2, op);
+            got_unexempt(chan, nick, from, op, ch, u);
           break;
         case 'I':
           op = newsplit(&msg);
           fixcolon(op);
           if (ms2[0] == '+')
-            got_invite(chan, nick, from, op);
+            got_invite(chan, nick, from, op, ch, u);
           else
-            got_uninvite(chan, nick, from, op, u);
-          check_tcl_mode(nick, from, u, chan->dname, ms2, op);
+            got_uninvite(chan, nick, from, op, ch, u);
           break;
         }
         if (todo) {
           check_tcl_mode(nick, from, u, chan->dname, ms2, "");
+          if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
+            return 0;
           if (ms2[0] == '+')
             chan->channel.mode |= todo;
           else
Index: eggdrop1.6/src/mod/irc.mod/msgcmds.c
diff -u eggdrop1.6/src/mod/irc.mod/msgcmds.c:1.55 eggdrop1.6/src/mod/irc.mod/msgcmds.c:1.56
--- eggdrop1.6/src/mod/irc.mod/msgcmds.c:1.55	Fri Oct  2 05:16:59 2009
+++ eggdrop1.6/src/mod/irc.mod/msgcmds.c	Sat Nov 21 17:12:30 2009
@@ -2,7 +2,7 @@
  * msgcmds.c -- part of irc.mod
  *   all commands entered via /MSG
  *
- * $Id: msgcmds.c,v 1.55 2009/10/02 11:16:59 pseudo Exp $
+ * $Id: msgcmds.c,v 1.56 2009/11/21 23:12:30 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -1001,13 +1001,13 @@
     }
     putlog(LOG_CMDS, "*", "(%s!%s) !%s! RESET %s", nick, host, u->handle, par);
     dprintf(DP_HELP, "NOTICE %s :%s: %s\n", nick, par, IRC_RESETCHAN);
-    reset_chan_info(chan);
+    reset_chan_info(chan, CHAN_RESETALL);
     return 1;
   }
   putlog(LOG_CMDS, "*", "(%s!%s) !%s! RESET ALL", nick, host, u->handle);
   dprintf(DP_HELP, "NOTICE %s :%s\n", nick, IRC_RESETCHAN);
   for (chan = chanset; chan; chan = chan->next)
-    reset_chan_info(chan);
+    reset_chan_info(chan, CHAN_RESETALL);
   return 1;
 }
 
Index: eggdrop1.6/src/mod/irc.mod/tclirc.c
diff -u eggdrop1.6/src/mod/irc.mod/tclirc.c:1.55 eggdrop1.6/src/mod/irc.mod/tclirc.c:1.56
--- eggdrop1.6/src/mod/irc.mod/tclirc.c:1.55	Sat May 16 08:16:07 2009
+++ eggdrop1.6/src/mod/irc.mod/tclirc.c	Sat Nov 21 17:12:30 2009
@@ -1,7 +1,7 @@
 /*
  * tclirc.c -- part of irc.mod
  *
- * $Id: tclirc.c,v 1.55 2009/05/16 14:16:07 tothwolf Exp $
+ * $Id: tclirc.c,v 1.56 2009/11/21 23:12:30 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -750,18 +750,105 @@
   return TCL_OK;
 }
 
+static int tcl_resetchanidle STDVAR
+{
+  memberlist *m;
+  struct chanset_t *chan;
+  
+  BADARGS(2, 3, " ?nick? channel");
+  
+  chan = findchan_by_dname((argc == 2) ? argv[1] : argv[2]);
+  if (chan == NULL) {
+    Tcl_AppendResult(irp, "invalid channel ",
+                     (argc == 2) ? argv[1] : argv[2], NULL);
+    return TCL_ERROR;
+  }
+  
+  if (argc == 2)
+    for (m = chan->channel.member; m; m = m->next)
+      m->last = now;
+  else {
+    if (!(m = ismember(chan, argv[1]))) {
+      Tcl_AppendResult(irp, argv[1], " is not on ", argv[2], NULL);
+      return TCL_ERROR;
+    }
+    m->last = now;
+  }
+  return TCL_OK;
+}
+
+static int tcl_resetchanjoin STDVAR
+{
+  memberlist *m;
+  struct chanset_t *chan;
+  
+  BADARGS(2, 3, " ?nick? channel");
+  
+  chan = findchan_by_dname((argc == 2) ? argv[1] : argv[2]);
+  if (chan == NULL) {
+    Tcl_AppendResult(irp, "invalid channel ",
+                     (argc == 2) ? argv[1] : argv[2], NULL);
+    return TCL_ERROR;
+  }
+  
+  if (argc == 2)
+    for (m = chan->channel.member; m; m = m->next)
+      m->joined = now;
+  else {
+    if (!(m = ismember(chan, argv[1]))) {
+      Tcl_AppendResult(irp, argv[1], " is not on ", argv[2], NULL);
+      return TCL_ERROR;
+    }
+    m->joined = now;
+  }
+  return TCL_OK;
+}
+
 static int tcl_resetchan STDVAR
 {
+  char *c;
+  int flags = 0;
   struct chanset_t *chan;
 
-  BADARGS(2, 2, " channel");
+  BADARGS(2, 3, " channel ?flags?");
 
   chan = findchan_by_dname(argv[1]);
   if (chan == NULL) {
     Tcl_AppendResult(irp, "invalid channel ", argv[1], NULL);
     return TCL_ERROR;
   }
-  reset_chan_info(chan);
+
+  if (argc == 2) {
+    reset_chan_info(chan, CHAN_RESETALL);
+    return TCL_OK;
+  }
+  for (c = argv[2]; *c; c++) {
+    switch(*c) {
+    case 'w':
+      flags |= CHAN_RESETWHO;
+      break;
+    case 'm':
+      flags |= CHAN_RESETMODES;
+      break;
+    case 'b':
+      flags |= CHAN_RESETBANS;
+      break;
+    case 'e':
+      flags |= CHAN_RESETEXEMPTS;
+      break;
+    case 'I':
+      flags |= CHAN_RESETINVITED;
+      break;
+    case 't':
+      flags |= CHAN_RESETTOPIC;
+      break;
+    default:
+      Tcl_AppendResult(irp, "invalid reset flags: ", argv[2], NULL);
+      return TCL_ERROR;
+    }
+  }
+  if (flags)
+    reset_chan_info(chan, flags);
   return TCL_OK;
 }
 
@@ -941,6 +1028,8 @@
   {"resetbans",      tcl_resetbans},
   {"resetexempts",   tcl_resetexempts},
   {"resetinvites",   tcl_resetinvites},
+  {"resetchanidle",  tcl_resetchanidle},
+  {"resetchanjoin",  tcl_resetchanjoin},
   {"resetchan",      tcl_resetchan},
   {"topic",          tcl_topic},
   {"botonchan",      tcl_botonchan},
Index: eggdrop1.6/src/mod/server.mod/tclserv.c
diff -u eggdrop1.6/src/mod/server.mod/tclserv.c:1.23 eggdrop1.6/src/mod/server.mod/tclserv.c:1.24
--- eggdrop1.6/src/mod/server.mod/tclserv.c:1.23	Fri Oct  9 16:24:23 2009
+++ eggdrop1.6/src/mod/server.mod/tclserv.c	Sat Nov 21 17:12:30 2009
@@ -1,7 +1,7 @@
 /*
  * tclserv.c -- part of server.mod
  *
- * $Id: tclserv.c,v 1.23 2009/10/09 22:24:23 pseudo Exp $
+ * $Id: tclserv.c,v 1.24 2009/11/21 23:12:30 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -46,7 +46,7 @@
     return TCL_ERROR;
   }
   if (!serv) /* no server - no output */
-        return TCL_OK;
+    return TCL_OK;
 
   for (p = r = argv[1], q = buf; ; p++) {
     if (*p && *p != '\r' && *p != '\n')
Index: eggdrop1.6/src/modules.c
diff -u eggdrop1.6/src/modules.c:1.100 eggdrop1.6/src/modules.c:1.101
--- eggdrop1.6/src/modules.c:1.100	Thu May  7 16:01:41 2009
+++ eggdrop1.6/src/modules.c	Sat Nov 21 17:12:30 2009
@@ -4,7 +4,7 @@
  *
  * by Darrin Smith (beldin at light.iinet.net.au)
  *
- * $Id: modules.c,v 1.100 2009/05/07 22:01:41 tothwolf Exp $
+ * $Id: modules.c,v 1.101 2009/11/21 23:12:30 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -974,7 +974,7 @@
   n_free(ptr, x, line);
 }
 
-/* Hooks, various tables of functions to call on ceratin events
+/* Hooks, various tables of functions to call on certain events
  */
 void add_hook(int hook_num, Function func)
 {
Index: eggdrop1.6/src/patch.h
diff -u eggdrop1.6/src/patch.h:1.1220 eggdrop1.6/src/patch.h:1.1221
--- eggdrop1.6/src/patch.h:1.1220	Sun Nov 15 07:10:34 2009
+++ eggdrop1.6/src/patch.h	Sat Nov 21 17:12:30 2009
@@ -10,7 +10,7 @@
  * statement, leave the rest of the file alone, this allows better
  * overlapping patches.
  *
- * $Id: patch.h,v 1.1220 2009/11/15 13:10:34 pseudo Exp $
+ * $Id: patch.h,v 1.1221 2009/11/21 23:12:30 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -41,12 +41,12 @@
  *
  *
  */
-patch("1258232619");            /* current unixtime */
+patch("1258844438");            /* current unixtime */
 /*
  *
  *
  */
-patch("botattrfix");
+patch("pendingbinds");
 /*
  *
  *
----------------------- End of diff -----------------------


More information about the Changes mailing list