summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/modules.h18
-rw-r--r--src/inspircd.cpp36
-rw-r--r--src/modules.cpp28
3 files changed, 69 insertions, 13 deletions
diff --git a/include/modules.h b/include/modules.h
index a040757f6..34549b6c2 100644
--- a/include/modules.h
+++ b/include/modules.h
@@ -96,6 +96,8 @@ typedef std::deque<userrec*> chanuserlist;
// *********************************************************************************************
+#define FD_MAGIC_NUMBER -42
+
extern void createcommand(char* cmd, handlerfunc f, char flags, int minparams, char* source);
extern void server_mode(char **parameters, int pcnt, userrec *user);
@@ -667,6 +669,22 @@ class Server : public classbase
*/
virtual chanuserlist GetUsers(chanrec* chan);
+ /** Remove a user's connection to the irc server, but leave their client in existence in the
+ * user hash. When you call this function, the user's file descriptor will be replaced with the
+ * value of FD_MAGIC_NUMBER and their old file descriptor will be closed. This idle client will
+ * remain until it is restored with a valid file descriptor, or is removed from IRC by an operator
+ * After this call, the pointer to user will be invalid.
+ */
+ virtual bool UserToPseudo(userrec* user,std::string message);
+
+ /** This user takes one user, and switches their file descriptor with another user, so that one user
+ * "becomes" the other. The user in 'alive' is booted off the server with the given message. The user
+ * referred to by 'zombie' should have previously been locked with Server::ZombifyUser, otherwise
+ * stale sockets and file descriptor leaks can occur. After this call, the pointer to alive will be
+ * invalid, and the pointer to zombie will be equivalent in effect to the old pointer to alive.
+ */
+ virtual bool PseudoToUser(userrec* alive,userrec* zombie,std::string message);
+
};
#define CONF_NOT_A_NUMBER 0x000010
diff --git a/src/inspircd.cpp b/src/inspircd.cpp
index 6ec5631a7..e5150a566 100644
--- a/src/inspircd.cpp
+++ b/src/inspircd.cpp
@@ -544,6 +544,8 @@ void ReadConfig(bool bail, userrec* user)
void Write(int sock,char *text, ...)
{
+ if (sock == FD_MAGIC_NUMBER)
+ return;
if (!text)
{
log(DEFAULT,"*** BUG *** Write was given an invalid parameter");
@@ -568,6 +570,8 @@ void Write(int sock,char *text, ...)
void WriteServ(int sock, char* text, ...)
{
+ if (sock == FD_MAGIC_NUMBER)
+ return;
if (!text)
{
log(DEFAULT,"*** BUG *** WriteServ was given an invalid parameter");
@@ -591,6 +595,8 @@ void WriteServ(int sock, char* text, ...)
void WriteFrom(int sock, userrec *user,char* text, ...)
{
+ if (sock == FD_MAGIC_NUMBER)
+ return;
if ((!text) || (!user))
{
log(DEFAULT,"*** BUG *** WriteFrom was given an invalid parameter");
@@ -619,6 +625,8 @@ void WriteTo(userrec *source, userrec *dest,char *data, ...)
log(DEFAULT,"*** BUG *** WriteTo was given an invalid parameter");
return;
}
+ if (dest->fd == FD_MAGIC_NUMBER)
+ return;
char textbuffer[MAXBUF],tb[MAXBUF];
va_list argsPtr;
va_start (argsPtr, data);
@@ -656,7 +664,8 @@ void WriteChannel(chanrec* Ptr, userrec* user, char* text, ...)
{
if (has_channel(i->second,Ptr))
{
- WriteTo(user,i->second,"%s",textbuffer);
+ if (i->second->fd != FD_MAGIC_NUMBER)
+ WriteTo(user,i->second,"%s",textbuffer);
}
}
}
@@ -681,7 +690,7 @@ void WriteChannelLocal(chanrec* Ptr, userrec* user, char* text, ...)
{
if (has_channel(i->second,Ptr))
{
- if (i->second->fd != -1)
+ if ((i->second->fd != -1) && (i->second->fd != FD_MAGIC_NUMBER))
{
if (!user)
{
@@ -713,7 +722,7 @@ void WriteChannelWithServ(char* ServerName, chanrec* Ptr, userrec* user, char* t
{
if (i->second)
{
- if (has_channel(i->second,Ptr))
+ if ((has_channel(i->second,Ptr)) && (i->second->fd != FD_MAGIC_NUMBER))
{
WriteServ(i->second->fd,"%s",textbuffer);
}
@@ -742,7 +751,7 @@ void ChanExceptSender(chanrec* Ptr, userrec* user, char* text, ...)
{
if (i->second)
{
- if (has_channel(i->second,Ptr) && (user != i->second))
+ if ((has_channel(i->second,Ptr)) && (user != i->second) && (i->second->fd != FD_MAGIC_NUMBER))
{
WriteTo(user,i->second,"%s",textbuffer);
}
@@ -798,7 +807,7 @@ void WriteCommon(userrec *u, char* text, ...)
{
if (i->second)
{
- if (common_channels(u,i->second) && (i->second != u))
+ if ((common_channels(u,i->second) && (i->second != u)) && (i->second->fd != FD_MAGIC_NUMBER))
{
WriteFrom(i->second->fd,u,"%s",textbuffer);
}
@@ -856,7 +865,7 @@ void WriteOpers(char* text, ...)
for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
{
- if (i->second)
+ if ((i->second) && (i->second->fd != FD_MAGIC_NUMBER))
{
if (strchr(i->second->modes,'o'))
{
@@ -1059,7 +1068,7 @@ void WriteMode(const char* modes, int flags, const char* text, ...)
for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
{
- if (i->second)
+ if ((i->second) && (i->second->fd != FD_MAGIC_NUMBER))
{
bool send_to_user = false;
@@ -1114,7 +1123,7 @@ void WriteWallOps(userrec *source, bool local_only, char* text, ...)
for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
{
- if (i->second)
+ if ((i->second) && (i->second->fd != FD_MAGIC_NUMBER))
{
if (strchr(i->second->modes,'w'))
{
@@ -3765,10 +3774,11 @@ int InspIRCd(void)
{
for( int n = 0; n < fd_reap.size(); n++)
{
- //Blocking(fd_reap[n]);
- close(fd_reap[n]);
- shutdown (fd_reap[n],2);
- //NonBlocking(fd_reap[n]);
+ if ((fd_reap[n] > -1))
+ {
+ close(fd_reap[n]);
+ shutdown (fd_reap[n],2);
+ }
}
}
fd_reap.clear();
@@ -3935,7 +3945,7 @@ int InspIRCd(void)
#endif
result = EAGAIN;
- if ((count2a->second->fd != -1) && (FD_ISSET (count2a->second->fd, &sfd)))
+ if ((count2a->second->fd != FD_MAGIC_NUMBER) && (count2a->second->fd != -1) && (FD_ISSET (count2a->second->fd, &sfd)))
{
memset(data, 0, 10240);
result = read(count2a->second->fd, data, 10240);
diff --git a/src/modules.cpp b/src/modules.cpp
index 324ab375c..2b4314dee 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -576,6 +576,34 @@ int Server::CountUsers(chanrec* c)
}
+bool Server::UserToPseudo(userrec* user,std::string message)
+{
+ unsigned int old_fd = user->fd;
+ user->fd = FD_MAGIC_NUMBER;
+ Write(old_fd,"ERROR :Closing link (%s@%s) [%s]",user->ident,user->host,message.c_str());
+ close(old_fd);
+ shutdown (old_fd,2);
+}
+
+bool Server::PseudoToUser(userrec* alive,userrec* zombie,std::string message)
+{
+ zombie->fd = alive->fd;
+ alive->fd = FD_MAGIC_NUMBER;
+ Write(zombie->fd,"NICK %s",zombie->nick);
+ kill_link(alive,message.c_str());
+ for (int i = 0; i != MAXCHANS; i++)
+ {
+ if (zombie->chans[i].channel != NULL)
+ {
+ if (zombie->chans[i].channel->name)
+ {
+ Write(zombie->fd,"JOIN %s",zombie->chans[i].channel->name);
+ }
+ }
+ }
+
+}
+
ConfigReader::ConfigReader()
{
this->cache = new std::stringstream(std::stringstream::in | std::stringstream::out);