This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Undernet IRC Server Source Code.".

The branch, pclient has been created
        at  1c128471f5f275fe2c0b181e25df59f8a54797b8 (commit)

- Log -----------------------------------------------------------------
commit 1c128471f5f275fe2c0b181e25df59f8a54797b8
Author: Michael Poole <[email protected]>
Date:   Wed Jan 25 22:45:47 2012 -0500

    Add missing #include lines for m_{un,}zombie.c.
    
    This is necessary to get the declaration for {un,}zombie_client().

diff --git a/ircd/m_unzombie.c b/ircd/m_unzombie.c
index 12e0550..32adefa 100644
--- a/ircd/m_unzombie.c
+++ b/ircd/m_unzombie.c
@@ -32,6 +32,7 @@
 #include "msg.h"
 #include "numnicks.h"
 #include "s_debug.h"
+#include "s_misc.h"
 #include "s_user.h"
 #include "send.h"
 
diff --git a/ircd/m_zombie.c b/ircd/m_zombie.c
index 3fe4c98..cd4b26d 100644
--- a/ircd/m_zombie.c
+++ b/ircd/m_zombie.c
@@ -32,6 +32,7 @@
 #include "msg.h"
 #include "numnicks.h"
 #include "s_debug.h"
+#include "s_misc.h"
 #include "s_user.h"
 #include "send.h"
 
commit 9412dbaac7863c35650ba7862da88a5df9a61896
Author: Jan Krüger <[email protected]>
Date:   Tue May 10 03:54:50 2011 +0200

    Test code for zombie feature
    
    Not for production use.
    
    Use /quit ZOMBIE to zombiefy your current client.
    
    Use /quit UNZOMBIE to attempt to reattach to a client with nick 'jast'.

diff --git a/ircd/m_quit.c b/ircd/m_quit.c
index 9ccc361..8b4db6a 100644
--- a/ircd/m_quit.c
+++ b/ircd/m_quit.c
@@ -90,6 +90,8 @@
 #include "s_misc.h"
 #include "ircd_reply.h"
 
+#include "hash.h"
+
 /* #include <assert.h> -- Now using assert in ircd_log.h */
 #include <string.h>
 
@@ -105,6 +107,18 @@ int m_quit(struct Client* cptr, struct Client* sptr, int 
parc, char* parv[])
   assert(0 != sptr);
   assert(cptr == sptr);
 
+  if (!strcmp(parv[parc - 1], "ZOMBIE")) {
+    zombie_client(&me, &me, sptr);
+    return 0;
+  }
+  if (!strcmp(parv[parc - 1], "UNZOMBIE")) {
+    struct Client *victim = FindUser("jast");
+    if (victim) {
+      unzombie_client(&me, &me, sptr, victim);
+      return 0;
+    }
+  }
+
   if (cli_user(sptr)) {
     struct Membership* chan;
     for (chan = cli_user(sptr)->channel; chan; chan = chan->next_channel) {
commit dfec9980b8826328f7d3fee4fa0e0d8c732483cd
Author: Jan Krüger <[email protected]>
Date:   Tue May 10 22:29:34 2011 +0200

    Implement initial support for zombie mode
    
    This allows users to regain their status on the network after a ping
    timeout. When a user pings out, the client structure is marked as a
    zombie (FLAG_NOTCONN). Now the user has 15 minutes to reattach to that
    client structure, using a separate Login on Connect feature.
    
    When a user turns into a zombie, a ZO token is sent across the network;
    the zombie status is reported in net bursts as the +Z umode.
    
    > YY ZO YYXXX
    
    When a user re-attaches, he regains all previous state information
    (except oper privileges which are cleared), but retains his current
    numnick.
    
    > ZZ ZU ZZQQQ YYXXX
    
    Here, ZZQQQ takes over all the state information of YYXXX.
    
    Zombie mode is designed to be completely transparent to other users in
    the sense that the user's disappearance should not be noticeable. The
    current implementation silently drops all messages addressed to the
    zombie in order to achieve this.

diff --git a/include/client.h b/include/client.h
index 26f0481..b37a64c 100644
--- a/include/client.h
+++ b/include/client.h
@@ -166,6 +166,7 @@ enum Flag
     FLAG_DEBUG,                     /**< send global debug/anti-hack info */
     FLAG_ACCOUNT,                   /**< account name has been set */
     FLAG_HIDDENHOST,                /**< user's host is hidden */
+    FLAG_NOTCONN,                   /**< nobody is connected to this client */
     FLAG_LAST_FLAG,                 /**< number of flags */
     FLAG_LOCAL_UMODES = FLAG_LOCOP, /**< First local mode flag */
     FLAG_GLOBAL_UMODES = FLAG_OPER  /**< First global mode flag */
@@ -579,6 +580,8 @@ struct Client {
 #define IsAccount(x)            HasFlag(x, FLAG_ACCOUNT)
 /** Return non-zero if the client has set mode +x (hidden host). */
 #define IsHiddenHost(x)         HasFlag(x, FLAG_HIDDENHOST)
+/** Return non-zero if nobody is connected to this client structure */
+#define IsNotConn(x)            HasFlag(x, FLAG_NOTCONN)
 /** Return non-zero if the client has an active PING request. */
 #define IsPingSent(x)           HasFlag(x, FLAG_PINGSENT)
 
@@ -625,6 +628,8 @@ struct Client {
 #define SetAccount(x)           SetFlag(x, FLAG_ACCOUNT)
 /** Mark a client as having mode +x (hidden host). */
 #define SetHiddenHost(x)        SetFlag(x, FLAG_HIDDENHOST)
+/** Mark a client as not having anyone connected to it */
+#define SetNotConn(x)           SetFlag(x, FLAG_NOTCONN)
 /** Mark a client as having a pending PING. */
 #define SetPingSent(x)          SetFlag(x, FLAG_PINGSENT)
 
@@ -658,6 +663,8 @@ struct Client {
 #define ClearServNotice(x)      ClrFlag(x, FLAG_SERVNOTICE)
 /** Remove mode +x (hidden host) from the client. */
 #define ClearHiddenHost(x)      ClrFlag(x, FLAG_HIDDENHOST)
+/** Mark client as having someone connected to it */
+#define ClearNotConn(x)         ClrFlag(x, FLAG_NOTCONN)
 /** Clear the client's pending PING flag. */
 #define ClearPingSent(x)        ClrFlag(x, FLAG_PINGSENT)
 /** Clear the client's HUB flag. */
diff --git a/include/handlers.h b/include/handlers.h
index 1b96ee2..fc0f230 100644
--- a/include/handlers.h
+++ b/include/handlers.h
@@ -219,6 +219,7 @@ extern int ms_squit(struct Client*, struct Client*, int, 
char*[]);
 extern int ms_stats(struct Client*, struct Client*, int, char*[]);
 extern int ms_topic(struct Client*, struct Client*, int, char*[]);
 extern int ms_trace(struct Client*, struct Client*, int, char*[]);
+extern int ms_unzombie(struct Client*, struct Client*, int, char*[]);
 extern int ms_uping(struct Client*, struct Client*, int, char*[]);
 extern int ms_version(struct Client*, struct Client*, int, char*[]);
 extern int ms_wallchops(struct Client*, struct Client*, int, char*[]);
@@ -228,6 +229,7 @@ extern int ms_wallvoices(struct Client*, struct Client*, 
int, char*[]);
 extern int ms_whois(struct Client*, struct Client*, int, char*[]);
 extern int ms_xquery(struct Client*, struct Client*, int, char*[]);
 extern int ms_xreply(struct Client*, struct Client*, int, char*[]);
+extern int ms_zombie(struct Client*, struct Client*, int, char*[]);
 
 #endif /* INCLUDED_handlers_h */
 
diff --git a/include/msg.h b/include/msg.h
index 18b5ba3..35e5893 100644
--- a/include/msg.h
+++ b/include/msg.h
@@ -336,6 +336,14 @@ struct Client;
 #define TOK_ACCOUNT            "AC"
 #define CMD_ACCOUNT            MSG_ACCOUNT, TOK_ACCOUNT
 
+#define MSG_ZOMBIE             "ZOMBIE"        /* ZOMB */
+#define TOK_ZOMBIE             "ZO"
+#define CMD_ZOMBIE             MSG_ZOMBIE, TOK_ZOMBIE
+
+#define MSG_UNZOMBIE           "UNZOMBIE"      /* UZMB */
+#define TOK_UNZOMBIE           "ZU"
+#define CMD_UNZOMBIE           MSG_UNZOMBIE, TOK_UNZOMBIE
+
 #define MSG_ASLL               "ASLL"          /* ASLL */
 #define TOK_ASLL               "LL"
 #define CMD_ASLL               MSG_ASLL, TOK_ASLL
diff --git a/include/s_bsd.h b/include/s_bsd.h
index 8b2231d..41bbd53 100644
--- a/include/s_bsd.h
+++ b/include/s_bsd.h
@@ -63,6 +63,8 @@ extern unsigned int deliver_it(struct Client *cptr, struct 
MsgQ *buf);
 extern int connect_server(struct ConfItem* aconf, struct Client* by);
 extern int  net_close_unregistered_connections(struct Client* source);
 extern void close_connection(struct Client *cptr);
+extern void connection_switch_to_client(struct Client *source,
+                                       struct Client *target);
 extern void add_connection(struct Listener* listener, int fd);
 extern int  read_message(time_t delay);
 extern void init_server_identity(void);
diff --git a/include/s_misc.h b/include/s_misc.h
index 1fb82b0..fd11b8a 100644
--- a/include/s_misc.h
+++ b/include/s_misc.h
@@ -76,6 +76,10 @@ struct ServerStatistics {
 
 extern int check_registered(struct Client *sptr);
 extern int check_registered_user(struct Client *sptr);
+extern void zombie_client(struct Client *cptr, struct Client *killer,
+                        struct Client *victim);
+extern void unzombie_client(struct Client *cptr, struct Client *sptr,
+                           struct Client *acptr, struct Client *victim);
 extern int exit_client(struct Client *cptr, struct Client *bcptr,
     struct Client *sptr, const char *comment);
 extern char *myctime(time_t value);
diff --git a/include/s_user.h b/include/s_user.h
index 63ed134..185e984 100644
--- a/include/s_user.h
+++ b/include/s_user.h
@@ -74,6 +74,8 @@ extern int set_nick_name(struct Client* cptr, struct Client* 
sptr,
                          const char* nick, int parc, char* parv[]);
 extern void send_umode_out(struct Client* cptr, struct Client* sptr,
                           struct Flags* old, int prop);
+extern void send_umode(struct Client *cptr, struct Client *sptr, struct Flags 
*old,
+                       int sendset);
 extern int whisper(struct Client* source, const char* nick,
                    const char* channel, const char* text, int is_notice);
 extern void send_user_info(struct Client* to, char* names, int rpl,
diff --git a/ircd/Makefile.in b/ircd/Makefile.in
index 01b69ca..dfd01c5 100644
--- a/ircd/Makefile.in
+++ b/ircd/Makefile.in
@@ -174,6 +174,7 @@ IRCD_SRC = \
        m_time.c \
        m_topic.c \
        m_trace.c \
+       m_unzombie.c \
        m_uping.c \
        m_user.c \
        m_userhost.c \
@@ -188,6 +189,7 @@ IRCD_SRC = \
        m_whowas.c \
        m_xquery.c \
        m_xreply.c \
+       m_zombie.c \
        match.c \
        memdebug.c \
        motd.c \
diff --git a/ircd/ircd.c b/ircd/ircd.c
index 7048e7d..c296795 100644
--- a/ircd/ircd.c
+++ b/ircd/ircd.c
@@ -339,6 +339,18 @@ static void check_pings(struct Event* ev) {
     if (!cptr)
       continue;
      
+    /* We don't need to check zombies here */
+    if (IsNotConn(cptr)) {
+      assert(IsUser(cptr));
+      /* for now: reap after fixed time (15 minutes) */
+      if ((CurrentTime - cli_user(cptr)->last) >= 900) {
+        SetFlag(cptr, FLAG_DEADSOCKET);
+        /* this will be used as exit message */
+        ircd_strncpy(cli_info(cptr), "Ping timeout", REALLEN);
+      } else
+        continue;
+    }
+
     assert(&me != cptr);  /* I should never be in the local client array! */
    
 
@@ -419,6 +431,14 @@ static void check_pings(struct Event* ev) {
         sendto_opmask_butone(0, SNO_OLDSNO,
                              "No response from %s, closing link",
                              cli_name(cptr));
+      /*
+       * Keep client structure around when a user pings out, so that they can
+       * reconnect to it later
+       */
+      if (IsUser(cptr) && IsAccount(cptr)) {
+        zombie_client(&me, &me, cptr);
+        continue;
+      }
       exit_client_msg(cptr, cptr, &me, "Ping timeout");
       continue;
     }
diff --git a/ircd/m_unzombie.c b/ircd/m_unzombie.c
new file mode 100644
index 0000000..12e0550
--- /dev/null
+++ b/ircd/m_unzombie.c
@@ -0,0 +1,80 @@
+/*
+ * IRC - Internet Relay Chat, ircd/m_unzombie.c
+ * Copyright (C) 2011 Jan Krueger <[email protected]>
+ *
+ * See file AUTHORS in IRC package for additional names of
+ * the programmers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+
+#include "config.h"
+
+#include "client.h"
+#include "ircd.h"
+#include "ircd_log.h"
+#include "ircd_reply.h"
+#include "ircd_string.h"
+#include "msg.h"
+#include "numnicks.h"
+#include "s_debug.h"
+#include "s_user.h"
+#include "send.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/** Handle an UNZOMBIE message from a server connection.
+ *
+ * \a parv has the following elements:
+ * \li \a parv[1] is the numnick of the client attaching to the zombie
+ * \li \a parv[2] is the numnick of the zombie
+ *
+ * See @ref m_functions for discussion of the arguments.
+ * @param[in] cptr Client that sent us the message.
+ * @param[in] sptr Original source of message.
+ * @param[in] parc Number of arguments.
+ * @param[in] parv Argument vector.
+ */
+int ms_unzombie(struct Client* cptr, struct Client* sptr, int parc,
+              char* parv[])
+{
+  struct Client *acptr;
+  struct Client *victim;
+
+  if (parc < 3)
+    return need_more_params(sptr, "UNZOMBIE");
+
+  if (!IsServer(sptr))
+    return protocol_violation(cptr, "UNZOMBIE from non-server %s",
+                             cli_name(sptr));
+
+  if (!(acptr = findNUser(parv[1])))
+    return 0; /* If this is colliding with a QUIT, let the QUIT win */
+
+  if (!(victim = findNUser(parv[2])))
+    /* TODO send error */
+    ;
+
+  if (!IsNotConn(victim))
+    return protocol_violation(cptr, "UNZOMBIE trying to attach to non-zombie 
%s",
+                             cli_name(victim));
+  assert(IsAccount(victim));
+
+  unzombie_client(cptr, sptr, acptr, victim);
+  return 0;
+}
diff --git a/ircd/m_zombie.c b/ircd/m_zombie.c
new file mode 100644
index 0000000..3fe4c98
--- /dev/null
+++ b/ircd/m_zombie.c
@@ -0,0 +1,73 @@
+/*
+ * IRC - Internet Relay Chat, ircd/m_zombie.c
+ * Copyright (C) 2011 Jan Krueger <[email protected]>
+ *
+ * See file AUTHORS in IRC package for additional names of
+ * the programmers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+
+#include "config.h"
+
+#include "client.h"
+#include "ircd.h"
+#include "ircd_log.h"
+#include "ircd_reply.h"
+#include "ircd_string.h"
+#include "msg.h"
+#include "numnicks.h"
+#include "s_debug.h"
+#include "s_user.h"
+#include "send.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/** Handle a ZOMBIE message from a server connection.
+ *
+ * \a parv has the following elements:
+ * \li \a parv[1] is the numnick of the client to act on
+ *
+ * See @ref m_functions for discussion of the arguments.
+ * @param[in] cptr Client that sent us the message.
+ * @param[in] sptr Original source of message.
+ * @param[in] parc Number of arguments.
+ * @param[in] parv Argument vector.
+ */
+int ms_zombie(struct Client* cptr, struct Client* sptr, int parc,
+              char* parv[])
+{
+  struct Client *acptr;
+
+  if (parc < 2)
+    return need_more_params(sptr, "ZOMBIE");
+
+  if (!IsServer(sptr))
+    return protocol_violation(cptr, "ZOMBIE from non-server %s",
+                             cli_name(sptr));
+
+  if (!(acptr = findNUser(parv[1])))
+    return 0; /* Ignore for a user that QUIT; probably crossed (however 
unlikely) */
+
+  if (!IsAccount(acptr))
+    return protocol_violation(cptr, "ZOMBIE for user without account (%s)",
+                             cli_name(acptr));
+
+  zombie_client(cptr, sptr, acptr);
+  return 0;
+}
diff --git a/ircd/parse.c b/ircd/parse.c
index b79ebb8..2cb1ffc 100644
--- a/ircd/parse.c
+++ b/ircd/parse.c
@@ -611,6 +611,20 @@ struct Message msgtab[] = {
     { m_ignore, m_ignore, ms_account, m_ignore, m_ignore }
   },
   {
+    MSG_ZOMBIE,
+    TOK_ZOMBIE,
+    0, MAXPARA, MFLG_SLOW, 0, NULL,
+    /* UNREG, CLIENT, SERVER, OPER, SERVICE */
+    { m_ignore, m_ignore, ms_zombie, m_ignore, m_ignore }
+  },
+  {
+    MSG_UNZOMBIE,
+    TOK_UNZOMBIE,
+    0, MAXPARA, MFLG_SLOW, 0, NULL,
+    /* UNREG, CLIENT, SERVER, OPER, SERVICE */
+    { m_ignore, m_ignore, ms_unzombie, m_ignore, m_ignore }
+  },
+  {
     MSG_ASLL,
     TOK_ASLL,
     0, MAXPARA, MFLG_SLOW, 0, NULL,
diff --git a/ircd/s_bsd.c b/ircd/s_bsd.c
index 7e3205a..ca5ca9d 100644
--- a/ircd/s_bsd.c
+++ b/ircd/s_bsd.c
@@ -431,6 +431,34 @@ void close_connection(struct Client *cptr)
   }
 }
 
+/**
+ * Switches a client's connection over to a different, zombied client.
+ *
+ * @param source client to attach to zombied client
+ * @param target zombied client
+ */
+void connection_switch_to_client(struct Client *source, struct Client *target)
+{
+  assert(IsNotConn(target));
+  assert(MyConnect(source));
+  assert(-1 < cli_fd(source));
+  cli_connect(target) = cli_connect(source);
+  /* conveniently, this makes it much easier to get rid of source later on */
+  cli_from(target) = target;
+  LocalClientArray[cli_fd(source)] = target;
+
+  /* make main loop remove source soonish */
+  SetFlag(source, FLAG_DEADSOCKET);
+
+  /* need to copy over data from old client */
+  cli_user(target)->server = cli_user(source)->server;
+  strcpy(cli_yxx(target), cli_yxx(source));
+  cli_hopcount(target) = cli_hopcount(source);
+  cli_ip(target) = cli_ip(source);
+  strcpy(cli_username(target), cli_username(source));
+  strcpy(cli_user(target)->realhost, cli_user(source)->realhost);
+}
+
 /** Close all unregistered connections.
  * @param source Oper who requested the close.
  * @return Number of closed connections.
diff --git a/ircd/s_misc.c b/ircd/s_misc.c
index b5324fa..8b5ddca 100644
--- a/ircd/s_misc.c
+++ b/ircd/s_misc.c
@@ -319,6 +319,91 @@ static void exit_downlinks(struct Client *cptr, struct 
Client *sptr, char *comme
   }
 }
 
+/**
+ * Marks a local client as disconnected, and close its link if it is a local 
client.
+ *
+ * @param cptr server that notified us
+ * @param killer origin of decision to zombie \a victim
+ * @param victim zombied client
+ */
+void zombie_client(struct Client *cptr, struct Client *killer, struct Client 
*victim)
+{
+  assert(IsServer(cptr) || IsMe(cptr));
+  assert(IsServer(killer) || IsMe(killer));
+  assert(IsUser(victim));
+
+  /*
+   * Stop a running /LIST clean
+   */
+  if (MyUser(victim) && cli_listing(victim)) {
+    MyFree(cli_listing(victim));
+    cli_listing(victim) = NULL;
+  }
+
+  if (MyConnect(victim))
+    close_connection(victim);
+  /* need this so that main loop doesn't exit the client */
+  ClrFlag(victim, FLAG_DEADSOCKET);
+
+  SetNotConn(victim);
+  sendcmdto_serv_butone(killer, CMD_ZOMBIE, cptr, "%C", victim);
+}
+
+/**
+ * Attaches a client to a zombied client, removing the superfluous client in 
the process.
+ *
+ * @param cptr server that notified us
+ * @param sptr origin server of unzombie operation
+ * @param acptr client that is attaching to \a victim
+ * @param victim zombied client that someone is attaching to
+ */
+void unzombie_client(struct Client *cptr, struct Client *sptr, struct Client 
*acptr, struct Client *victim)
+{
+  assert(IsServer(cptr) || IsMe(cptr));
+  assert(IsServer(sptr) || IsMe(sptr));
+  assert(IsUser(acptr));
+  assert(IsNotConn(victim));
+
+  if (MyConnect(acptr))
+    connection_switch_to_client(acptr, victim);
+
+  ClearOper(victim);
+  ClearNotConn(victim);
+
+  if (MyConnect(victim)) {
+    /* inform client about "new" modes */
+    struct Flags setflags = cli_flags(acptr);
+    struct Membership *chan;
+    sendcmdto_one(acptr, CMD_NICK, victim, "%C", victim);
+    send_umode(victim, victim, &setflags, ALL_UMODES);
+
+    /*
+     * mark current client as zombie on all channels so that it does not show
+     * up in the memberships we'll resend below
+     */
+    for (chan = cli_user(acptr)->channel; chan; chan = chan->next_channel) {
+      SetZombie(chan);
+    }
+
+    /* resend channel memberships */
+    for (chan = cli_user(victim)->channel; chan; chan = chan->next_channel) {
+      struct Channel *chptr = chan->channel;
+      /* pretty unlikely to happen but let's handle this anyway */
+      if (IsZombie(chan))
+        continue;
+      sendcmdto_one(victim, CMD_JOIN, victim, ":%H", chptr);
+      if (chptr->topic[0]) {
+        send_reply(victim, RPL_TOPIC, chptr->chname, chptr->topic);
+        send_reply(victim, RPL_TOPICWHOTIME, chptr->chname, chptr->topic_nick,
+                  chptr->topic_time);
+      }
+      do_names(victim, chptr, NAMES_ALL|NAMES_EON); /* send /names list */
+    }
+  }
+
+  sendcmdto_serv_butone(sptr, CMD_UNZOMBIE, cptr, "%C %C", acptr, victim);
+}
+
 /* exit_client, rewritten 25-9-94 by Run */
 /**
  * Exits a client of *any* type (user, server, etc)
diff --git a/ircd/s_user.c b/ircd/s_user.c
index a19691d..7880291 100644
--- a/ircd/s_user.c
+++ b/ircd/s_user.c
@@ -499,7 +499,8 @@ static const struct UserMode {
   { FLAG_CHSERV,      'k' },
   { FLAG_DEBUG,       'g' },
   { FLAG_ACCOUNT,     'r' },
-  { FLAG_HIDDENHOST,  'x' }
+  { FLAG_HIDDENHOST,  'x' },
+  { FLAG_NOTCONN,     'Z' }
 };
 
 /** Length of #userModeList. */
@@ -1084,6 +1085,12 @@ int set_user_mode(struct Client *cptr, struct Client 
*sptr, int parc,
        }
        /* There is no -r */
        break;
+      case 'Z':
+       if (what == MODE_ADD)
+         SetNotConn(sptr);
+       else
+         ClearNotConn(sptr);
+       break;
       default:
         send_reply(sptr, ERR_UMODEUNKNOWNFLAG, *m);
         break;
@@ -1102,6 +1109,8 @@ int set_user_mode(struct Client *cptr, struct Client 
*sptr, int parc,
       ClearLocOp(sptr);
     if (!FlagHas(&setflags, FLAG_ACCOUNT) && IsAccount(sptr))
       ClrFlag(sptr, FLAG_ACCOUNT);
+    if (!FlagHas(&setflags, FLAG_NOTCONN) && IsNotConn(sptr))
+      ClrFlag(sptr, FLAG_NOTCONN);
     /*
      * new umode; servers can set it, local users cannot;
      * prevents users from /kick'ing or /mode -o'ing
diff --git a/ircd/send.c b/ircd/send.c
index 1afbaec..faa88c3 100644
--- a/ircd/send.c
+++ b/ircd/send.c
@@ -106,7 +106,7 @@ static void dead_link(struct Client *to, char *notice)
 static int can_send(struct Client* to)
 {
   assert(0 != to);
-  return (IsDead(to) || IsMe(to) || -1 == cli_fd(to)) ? 0 : 1;
+  return (IsDead(to) || IsMe(to) || IsNotConn(to) || -1 == cli_fd(to)) ? 0 : 1;
 }
 
 /** Close the connection with the highest sendq.
-----------------------------------------------------------------------


hooks/post-receive
-- 
Undernet IRC Server Source Code.
_______________________________________________
Patches mailing list
[email protected]
http://undernet.sbg.org/mailman/listinfo/patches

Reply via email to