/*
* ----------------------------------------------------------------
* Night Light IRC Proxy - Client Parser Functions
* ----------------------------------------------------------------
* Copyright (C) 1997-2007 Jonas Kvinge <jonas@night-light.net>
* All rights reserved.
*
* 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 2 of the License, 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Last modified by:
* Jonas Kvinge (25.11.2007)
*
*/
#define CLIENT_PARSER_C
#define NEED_SYS_TYPES_H 1 /* Extra types */
#define NEED_SYS_PARAM_H 1 /* Some systems need this */
#define NEED_LIMITS_H 0 /* Kernel limits */
#define NEED_STDARG_H 1 /* va_list, etc */
#define NEED_ERRNO_H 1 /* errno */
#define NEED_CTYPE_H 1 /* isdigit(), etc */
#define NEED_NETINET_IN_H 1 /* in_addr, sockaddr_in, etc */
#define NEED_ARPA_INET_H 0 /* inet_ntoa(), inet_aton(), etc */
#define NEED_STDIO_H 1 /* Standard C UNIX functions */
#define NEED_STDLIB_H 1 /* malloc(), exit(), atoi(), etc */
#define NEED_TIME_H 1 /* time(), etc */
#define NEED_SYSCTL_H 0 /* sysctl(), etc */
#define NEED_SYS_STAT_H 0 /* chmod(), mkdir(), etc */
#define NEED_SYS_UIO_H 0 /* iovec, etc */
#define NEED_FCNTL_H 1 /* open(), creat(), fcntl(), etc */
#define NEED_SYS_IOCTL_H 0 /* ioctl(), etc */
#define NEED_SYS_FILIO_H 0 /* Solaris need this for ioctl(), etc */
#define NEED_UNISTD_H 1 /* Unix standard functions */
#define NEED_STRING_H 1 /* C string functions */
#define NEED_SIGNAL_H 0 /* Signal functions */
#define NEED_SYS_SOCKET_H 0 /* Socket functions */
#define NEED_NETDB_H 0 /* Network database functions */
#define NEED_ARPA_NAMESER_H 0 /* Nameserver definitions */
#define NEED_GETUSERPW_HEADERS 0 /* Functions to retrive system passwords */
#define NEED_ARES 1 /* Functions needed for ares */
#define NEED_SSL 1 /* Needed for SSL support */
#include "includes.h"
#include "irc.h"
#include "conf.h"
#if MEMDEBUG
#include "memlist.h"
#endif
#include "access_conf.h"
#include "conn_conf.h"
#include "listen.h"
#include "client.h"
#include "client_connection.h"
#include "client_parser.h"
#include "client_auth.h"
#include "client_handle.h"
#include "client_notice.h"
#include "conn.h"
#include "conn_connection.h"
#include "conn_sendq.h"
#include "chan.h"
#include "chan_user.h"
/* VARIABLES - JONAS (31.07.2001) */
#if MEMDEBUG
extern unsigned long int Leaks;
extern unsigned long int LeaksSize;
#endif
#if ARES
extern ares_channel Ares_Channel;
#endif
extern struct Conf_Struct ConfS;
extern struct Conn_Struct *Conn_Head;
/* CLIENT_PARSE FUNCTION - JONAS (18.07.2001) */
void client_parse(struct Client_Struct *ClientS) {
char *BufferPT = NULL;
char *LinePT = NULL;
unsigned long int Count = 0;
unsigned long int Len = 0;
char *TempPT = NULL;
BufferPT = ClientS->RecvBuffer;
for (Count = 1 ; BufferPT != NULL ; Count++) {
TempPT = strchr(BufferPT, '\n');
if (TempPT == NULL) {
if (Count == 1) { return; }
Len = strlen(BufferPT) + 1;
memmove(ClientS->RecvBuffer, BufferPT, Len);
TempPT = realloc(ClientS->RecvBuffer, Len);
if (TempPT == NULL) {
client_close(ClientS, "Memory allocation failure: [%d] %s", errno, strerror(errno));
return;
}
ClientS->RecvBuffer = TempPT;
return;
}
LinePT = strtok(BufferPT, "\n");
BufferPT = strtok(NULL, "\0");
if (LinePT == NULL) { continue; }
Len = strlen(LinePT);
if (LinePT[Len-1] == '\r') { LinePT[Len-1] = '\0'; }
client_parse_message(ClientS, LinePT);
if (ClientS->RecvBuffer == NULL) { return; }
}
FREE(ClientS->RecvBuffer);
}
/* CLIENT_PARSE_MESSAGE FUNCTION - JONAS (17.07.2001) */
void client_parse_message(struct Client_Struct *ClientS, char *MessagePT) {
char *PrefixPT = NULL;
char *LinePT = NULL;
char *CommandPT = NULL;
char **ParamsPT = NULL;
char **TempPT = NULL;
unsigned short int Index = 0;
unsigned short int Params = 0;
time_t Duration = 0;
Duration = (NOW - ClientS->LineTime);
if (Duration >= ConfS.ClientLineFloodTTL) { ClientS->Lines = 0; }
++ClientS->Lines;
if (ClientS->Lines >= ConfS.ClientMaxLines) {
client_close(ClientS, ACCESS_CONF_USERFLOOD);
access_conf_adddeny(ClientS->HostName, ACCESS_CONF_USERFLOOD);
return;
}
ClientS->LineTime = NOW;
while (MessagePT[0] == ' ') { MessagePT++; }
if (MessagePT[0] == '\0') { return; }
if (MessagePT[0] == ':') {
MessagePT++;
PrefixPT = MessagePT;
MessagePT = strchr(MessagePT, ' ');
if (MessagePT == NULL) { return; }
MessagePT[0] = '\0';
MessagePT++;
while (MessagePT[0] == ' ') { MessagePT++; }
if (MessagePT[0] == '\0') { return; }
}
else {
if (ClientS->User == NULL) { PrefixPT = "*"; }
else { PrefixPT = ClientS->User; }
}
LinePT = strdup(MessagePT);
if (LinePT == NULL) {
client_close(ClientS, "Memory allocation failure: [%d] %s", errno, strerror(errno));
return;
}
CommandPT = MessagePT;
MessagePT = strchr(MessagePT, ' ');
if (MessagePT != NULL) {
MessagePT[0] = '\0';
MessagePT++;
while (MessagePT[0] == ' ') { MessagePT++; }
if (MessagePT[0] == '\0') {
free(LinePT);
return;
}
FOREVERLOOP {
if (MessagePT[0] == ':') {
MessagePT++;
++Params;
TempPT = realloc(ParamsPT, (sizeof(char *) * Params));
if (TempPT == NULL) {
client_close(ClientS, "Memory allocation failure: [%d] %s", errno, strerror(errno));
free(ParamsPT);
free(LinePT);
return;
}
ParamsPT = TempPT;
ParamsPT[Index] = MessagePT;
break;
}
else {
++Params;
TempPT = realloc(ParamsPT, (sizeof(char *) * Params));
if (TempPT == NULL) {
client_close(ClientS, "Memory allocation failure: [%d] %s", errno, strerror(errno));
free(ParamsPT);
free(LinePT);
return;
}
ParamsPT = TempPT;
ParamsPT[Index] = MessagePT;
++Index;
MessagePT = strchr(MessagePT, ' ');
if (MessagePT == NULL) { break; }
MessagePT[0] = '\0';
MessagePT++;
while (MessagePT[0] == ' ') { MessagePT++; }
if (MessagePT[0] == '\0') { break; }
}
}
}
strupper(CommandPT);
client_parse_command(ClientS, LinePT, CommandPT, ParamsPT, Params);
free(LinePT);
free(ParamsPT);
}
/* CLIENT_PARSE_COMMAND FUNCTION - JONAS (17.07.2001) */
void client_parse_command(struct Client_Struct *ClientS, char *LinePT, char *CommandPT, char **ParamsPT, const unsigned short int Params) {
if (!Client_IsVerified(ClientS)) {
if (strcasecmp(CommandPT, "PASS") == FALSE) {
if (Params < 1) { client_notice(ClientS, "%s :Not enough parameters.", CommandPT); return; }
ClientS->Pass = strrealloc(ClientS->Pass, ParamsPT[0]);
#if 0
client_notice(ClientS, "Got password.");
#endif
}
else if (strcasecmp(CommandPT, "NICK") == FALSE) {
if (Params < 1) { client_notice(ClientS, "%s :Not enough parameters.", CommandPT); return; }
ClientS->Nick = strrealloc(ClientS->Nick, ParamsPT[0]);
#if 0
client_notice(ClientS, "Got nickname.");
#endif
if (ClientS->Pass == NULL) { client_notice(ClientS, "You need to send the PASS command!"); }
}
else if (strcasecmp(CommandPT, "USER") == FALSE) {
if (Params < 4) { client_notice(ClientS, "%s :Not enough parameters.", CommandPT); return; }
ClientS->User = strrealloc(ClientS->User, ParamsPT[0]);
#if 0
client_notice(ClientS, "Got username.");
#endif
if (ClientS->Pass == NULL) { client_notice(ClientS, "You need to send the PASS command!"); }
}
else { client_addsend(ClientS, ":%s 451 * :You have not registered.", IRCP_USER_HOST(ClientS)); }
if ((ClientS->User != NULL) && (ClientS->Pass != NULL)) {
struct Conn_Struct *ConnS = NULL;
assert(geteuid() != 0);
client_authcheck(ClientS->User, ClientS->Pass);
assert(geteuid() != 0);
if (aerrno != AESUCCESS) {
client_close(ClientS, "USER / PASS is incorrect.");
return;
}
sysprint(BITMASK_MAIN, "Client %s (%s) sucessfully authenticated as \"%s\".", ClientS->HostName, ClientS->HostIPS, ClientS->User);
client_noticeallbutone(ClientS, "Client %s (%s) authenticated as \"%s\".", ClientS->HostName, ClientS->HostIPS, ClientS->User);
Client_SetVerified(ClientS);
client_welcome(ClientS);
for (ConnS = Conn_Head ; ConnS != NULL ; ConnS = ConnS->Next) {
if ((strcmp(ClientS->User, ConnS->User) == FALSE) && (Conn_IsAttached(ConnS))) { client_attach(ClientS, ConnS); break; }
}
return;
}
return;
}
if (strcasecmp(CommandPT, "PCONNLIST") == FALSE) {
struct Conn_Struct *ConnS = NULL;
struct ConnServer_Struct *ConnServer = NULL;
unsigned short int Count = 0;
for (ConnS = Conn_Head ; ConnS != NULL ; ConnS = ConnS->Next) {
if (strcmp(ConnS->User, ClientS->User) != FALSE) { continue; }
++Count;
client_notice(ClientS, "\2Connection: %s Host: %s\2", ConnS->Name, ConnS->Host);
if (Host_IsResolving(ConnS->ResolveFlags)) { client_notice(ClientS, "--- Status: Resolving local hostname %s to IP-address.", ConnS->HostName); }
else if (Host_IsResolving(ConnS->ServerResolveFlags)) { client_notice(ClientS, "--- Status: Resolving server nostname %s to IP-address.", ConnS->ServerHostName); }
else if (Conn_IsConnecting(ConnS)) { client_notice(ClientS, "--- Status: Connecting to %s(%s):%ld.", ConnS->ServerHostName, ConnS->ServerHostIPS, ConnS->ServerPortH); }
else if (Conn_IsWelcome(ConnS)) { client_notice(ClientS, "--- Status: Connected to %s(%s):%ld \"%s\".", ConnS->ServerHostName, ConnS->ServerHostIPS, ConnS->ServerPortH, ConnS->ServerName); }
else if (Conn_IsConnected(ConnS)) { client_notice(ClientS, "--- Status: Socket connected to %s(%s):%ld.", ConnS->ServerHostName, ConnS->ServerHostIPS, ConnS->ServerPortH); }
else { client_notice(ClientS, "--- Status: Disconnected."); }
if (ConnS->Server_Head == NULL) { client_notice(ClientS, "--- No servers!"); }
else {
for (ConnServer = ConnS->Server_Head ; ConnServer != NULL ; ConnServer = ConnServer->Next) {
client_notice(ClientS, "--- Server: %s Port: %ld", ConnServer->Host, ConnServer->Port);
}
}
}
if (Count == 0) {
client_notice(ClientS, "You have no connections.");
}
return;
}
else if (strcasecmp(CommandPT, "PCONNECT") == FALSE) {
struct Conn_Struct *ConnS = NULL;
if (Params < 1) {
if (ClientS->ConnS == NULL) { client_notice(ClientS, "Usage: PCONNECT <Connection name> [Connection server]."); return; }
ConnS = ClientS->ConnS;
}
else { ConnS = conn_get(ParamsPT[0]); }
if (ConnS == NULL) { client_notice(ClientS, "No such connection, use /PCONNLIST to list your connections."); return; }
if (strcmp(ConnS->User, ClientS->User) != FALSE) { client_notice(ClientS, "Permission denied, You're not the owner of connection %s.", ConnS->Name); return; }
if (Params >= 2) {
for (ConnS->ConnServerTry = ConnS->Server_Head ; ConnS->ConnServerTry != NULL ; ConnS->ConnServerTry = ConnS->ConnServerTry->Next) {
if (strwm(ParamsPT[1], ConnS->ConnServerTry->Host) == TRUE) { break; }
}
if (ConnS->ConnServerTry == NULL) { client_notice(ClientS, "No such server for that connection."); return; }
}
if (Host_IsResolving(ConnS->ResolveFlags)) {
if (ConnS->ConnServerTry == NULL) { client_notice(ClientS, "Connection %s: Resolving local hostname %s to IP-address.", ConnS->Name, ConnS->HostName); return; }
#if HAVE_ARES_CANCELQUERY
ares_cancelquery(Ares_Channel, ConnS);
#endif
return;
}
else if (Host_IsResolving(ConnS->ServerResolveFlags)) {
if (ConnS->ConnServerTry == NULL) { client_notice(ClientS, "Connection %s: Resolving server hostname %s to IP-address.", ConnS->Name, ConnS->ServerHostName); return; }
#if HAVE_ARES_CANCELQUERY
ares_cancelquery(Ares_Channel, ConnS);
#endif
return;
}
else if (Conn_IsConnecting(ConnS)) {
if (ConnS->ConnServerTry == NULL) { client_notice(ClientS, "%s: Connecting to %s(%s):%ld.", ConnS->Name, ConnS->ServerHostName, ConnS->ServerHostIPS, ConnS->ServerPortH); return; }
conn_disconnect(ConnS, "Connection %s: Connection attempt to %s(%s):%ld cancelled by user %s(%s).", ConnS->Name, ConnS->ServerHostName, ConnS->ServerHostIPS, ConnS->ServerPortH, ClientS->HostName, ClientS->HostIPS);
return;
}
else if (Conn_IsWelcome(ConnS)) {
if ((ConnS->ConnServerTry == NULL) || (strcasecmp(ConnS->ServerHostName, ConnS->ConnServerTry->Host) == FALSE)) { client_notice(ClientS, "Connection %s: Already connected to %s, use PQUIT to quit.", ConnS->Name, ConnS->ServerHostName); return; }
conn_quit(ConnS, "Changing server to %s.", ConnS->ConnServerTry->Host);
return;
}
else if (Conn_IsConnected(ConnS)) {
if (ConnS->ConnServerTry == NULL) { client_notice(ClientS, "Connection %s: Socket connected to %s(%s):%ld.", ConnS->Name, ConnS->ServerHostName, ConnS->ServerHostIPS, ConnS->ServerPortH); return; }
conn_disconnect(ConnS, "Connection %s attempt to %s(%s):%ld cancelled by user %s(%s).", ConnS->Name, ConnS->ServerHostName, ConnS->ServerHostIPS, ConnS->ServerPortH, ClientS->HostName, ClientS->HostIPS);
return;
}
#if SSL_SUPPORT
conn_connect(ConnS);
#else
if (!ConnConf_IsSSL(ConnS)) { conn_connect(ConnS); }
else { client_notice(ClientS, "Connection %s: SSL is enabled for this connection, but %s is compiled without SSL support.", ConnS->Name, PACKAGE); }
#endif
return;
}
else if (strcasecmp(CommandPT, "PQUIT") == FALSE) {
struct Conn_Struct *ConnS = NULL;
if (Params >= 1) {
ConnS = conn_get(ParamsPT[0]);
if (ConnS == NULL) { client_notice(ClientS, "No such connection, eventually use /PCONNLIST to list your connections."); return; }
}
else {
ConnS = ClientS->ConnS;
if (ConnS == NULL) { client_notice(ClientS, "Usage: PQUIT <Connection name>"); return; }
}
if (strcmp(ConnS->User, ClientS->User) != FALSE) { client_notice(ClientS, "Permission denied, You're not the owner of connection %s.", ConnS->Name); return; }
if (Conn_IsConnect(ConnS)) {
if (Conn_IsWelcome(ConnS)) {
if (Conn_IsSentQuit(ConnS)) { conn_disconnect(ConnS, "Connection %s to server %s aborted by user %s (%s[%s]).", ConnS->Name, ConnS->ServerHostName, ClientS->User, ClientS->HostName, ClientS->HostIPS); return; }
else { conn_quit(ConnS, "%s (%s[%s]) requested QUIT.", ClientS->User, ClientS->HostName, ClientS->HostIPS); }
}
else { conn_disconnect(ConnS, "Connection %s to server %s aborted by user %s (%s[%s]).", ConnS->Name, ConnS->ServerHostName, ClientS->User, ClientS->HostName, ClientS->HostIPS); return; }
}
else { client_notice(ClientS, "Connection %s is not connected.", ConnS->Name); return; }
return;
}
else if ((strcasecmp(CommandPT, "PATTACH") == FALSE) || (strcasecmp(CommandPT, "PRESUME") == FALSE)) {
struct Conn_Struct *ConnS = NULL;
if (ClientS->ConnS != NULL) { client_notice(ClientS, "You are already attached on connection %s.", ClientS->ConnS->Name); return; }
if (Params < 1) { client_notice(ClientS, "Usage: PATTACH <Connection name>"); return; }
ConnS = conn_get(ParamsPT[0]);
if (ConnS == NULL) { client_notice(ClientS, "No such connection."); return; }
if (strcmp(ConnS->User, ClientS->User) != FALSE) { client_notice(ClientS, "Permission denied, You're not the owner of connection %s.", ConnS->Name); return; }
client_attach(ClientS, ConnS);
}
else if (strcasecmp(CommandPT, "PDETACH") == FALSE) {
if (ClientS->ConnS == NULL) { client_notice(ClientS, "You have no attached connection."); return; }
Conn_ClearAttached(ClientS->ConnS);
client_detach(ClientS);
}
else if (strcasecmp(CommandPT, "QUIT") == FALSE) {
client_close(ClientS, "Client sent QUIT.");
}
else if (strcasecmp(CommandPT, "PING") == FALSE) {
if (Params < 1) { client_notice(ClientS, "%s :Not enough parameters.", CommandPT); return; }
client_addsend(ClientS, ":%s PONG %s :%s", HOSTNAME, IRCP_USER_HOST(ClientS), ParamsPT[0]);
/* client_addsend(ClientS, "PONG :%s", ParamsPT[0]); */
}
else if (strcasecmp(CommandPT, "PONG") == FALSE) {
Client_ClearSentPing(ClientS);
}
else if (strcasecmp(CommandPT, "QUOTE") == FALSE) {
char *DumbPT = NULL;
if (ClientS->ConnS == NULL) { client_notice(ClientS, "QUOTE: No attached connection."); return; }
if (!Conn_IsConnected(ClientS->ConnS)) { client_notice(ClientS, "Connection %s not established.", ClientS->ConnS->Name); return; }
DumbPT = strchr(LinePT, ' ');
DumbPT++;
conn_addsendq(ClientS->ConnS, "%s", DumbPT);
}
else if (strcasecmp(CommandPT, "READLOG") == FALSE) {
FILE *FilePT = NULL;
struct Conn_Struct *ConnS = NULL;
unsigned long int Count = 0;
if (Params >= 1) {
ConnS = conn_get(ParamsPT[0]);
if (ConnS == NULL) { client_notice(ClientS, "No such connection, eventually use /PCONNLIST to list your connections."); return; }
}
else {
ConnS = ClientS->ConnS;
if (ConnS == NULL) { client_notice(ClientS, "Usage: READLOG <Connection name>"); return; }
}
if (strcmp(ConnS->User, ClientS->User) != FALSE) { client_notice(ClientS, "Permission denied, You're not the owner of connection %s.", ConnS->Name); return; }
if (ConnS->FileName == NULL) { client_notice(ClientS, "Logfile missing for connection %s.", ConnS->Name); return; }
#if !WIN32
if (Conn_IsLogHomeDir(ConnS)) { sysseteuidbyuser(ConnS->User); }
#endif
FilePT = fopen(ConnS->FileName, "r");
if (FilePT == NULL) {
sysprint(BITMASK_ERROR, "Unable to open %s for reading: [%d] %s", ConnS->FileName, errno, strerror(errno));
client_notice(ClientS, "Unable to open %s for reading: [%d] %s", ConnS->FileName, errno, strerror(errno));
#if !WIN32
if (Conn_IsLogHomeDir(ConnS)) { sysseteuidnormal(); }
#endif
return;
}
FOREVERLOOP {
char Line[LINELEN+1] = "";
char *DumbPT = NULL;
memset(&Line, 0, LINELEN+1);
DumbPT = fgets(Line, LINELEN, FilePT);
if (DumbPT == NULL) { break; }
Count++;
client_addsend(ClientS, ":%s PRIVMSG %s :%s", IRCP_USER_HOST(ClientS), IRCP_USER_NICK(ClientS), Line);
}
if (Count == 0) { client_notice(ClientS, "Logfile for %s is empty.", ConnS->Name); }
fclose(FilePT);
#if !WIN32
if (Conn_IsLogHomeDir(ConnS)) { sysseteuidnormal(); }
#endif
}
else if (strcasecmp(CommandPT, "ERASELOG") == FALSE) {
FILE *FilePT = NULL;
struct Conn_Struct *ConnS = NULL;
unsigned long int Count = 0;
if (Params >= 1) {
ConnS = conn_get(ParamsPT[0]);
if (ConnS == NULL) { client_notice(ClientS, "No such connection, eventually use /PCONNLIST to list your connections."); return; }
}
else {
ConnS = ClientS->ConnS;
if (ConnS == NULL) { client_notice(ClientS, "Usage: ERASELOG <Connection name>"); return; }
}
if (strcmp(ConnS->User, ClientS->User) != FALSE) { client_notice(ClientS, "Permission denied, You're not the owner of connection %s.", ConnS->Name); return; }
if (ConnS->FileName == NULL) { client_notice(ClientS, "Logfile missing for connection %s.", ConnS->Name); return; }
#if !WIN32
if (Conn_IsLogHomeDir(ConnS)) { sysseteuidbyuser(ConnS->User); }
#endif
FilePT = fopen(ConnS->FileName, "r");
if (FilePT == NULL) {
sysprint(BITMASK_ERROR, "Unable to open %s for reading: [%d] %s", ConnS->FileName, errno, strerror(errno));
client_notice(ClientS, "Unable to open %s for reading: [%d] %s", ConnS->FileName, errno, strerror(errno));
#if !WIN32
if (Conn_IsLogHomeDir(ConnS)) { sysseteuidnormal(); }
#endif
return;
}
FOREVERLOOP {
char Line[LINELEN+1] = "";
char *DumbPT = NULL;
memset(&Line, 0, LINELEN+1);
DumbPT = fgets(Line, LINELEN, FilePT);
if (DumbPT == NULL) { break; }
Count++;
}
fclose(FilePT);
if (Count == 0) {
client_notice(ClientS, "Logfile for %s is empty.", ConnS->Name);
#if !WIN32
if (Conn_IsLogHomeDir(ConnS)) { sysseteuidnormal(); }
#endif
return;
}
FilePT = fopen(ConnS->FileName, "w+");
if (FilePT == NULL) {
sysprint(BITMASK_ERROR, "Unable to open %s for writing: [%d] %s", ConnS->FileName, errno, strerror(errno));
client_notice(ClientS, "Unable to open %s for writing: [%d] %s", ConnS->FileName, errno, strerror(errno));
#if !WIN32
if (Conn_IsLogHomeDir(ConnS)) { sysseteuidnormal(); }
#endif
return;
}
fclose(FilePT);
#if !WIN32
if (Conn_IsLogHomeDir(ConnS)) { sysseteuidnormal(); }
#endif
client_notice(ClientS, "Logfile for %s erased.", ConnS->Name);
}
#if MEMDEBUG
else if (strcasecmp(CommandPT, "MEMLEAKS") == FALSE) {
client_notice(ClientS, "Calculating memory leaks...");
mem_leaks();
if (Leaks > 1 ) {
client_notice(ClientS, "Memory leaks: %ld size: %ld", Leaks, LeaksSize);
client_notice(ClientS, "!!! MEMORY LEAKS FOUND --- LOOK IN THE ERROR LOG !!!");
}
else { client_notice(ClientS, "No memory leaks found! IGNORE 1 FAKE MEMLEAK IN client_io.c!"); }
}
#endif
else {
if (ClientS->ConnS == NULL) { client_notice(ClientS, "No attached connection, use PATTACH to attach first."); }
else {
if (Conn_IsConnect(ClientS->ConnS)) {
if (Conn_IsWelcome(ClientS->ConnS)) {
if ((!strcasecmp(CommandPT, "WHO")) && (Params >= 1)) {
struct Chan_Struct *ChanS;
struct Who_Struct *WhoS;
ChanS = chan_get(ClientS->ConnS, ParamsPT[0]);
if (ChanS != NULL) {
WhoS = malloc(sizeof(struct Who_Struct));
if (WhoS != NULL) {
memset(WhoS, 0, sizeof(struct Who_Struct));
WhoS->PrevForClient = NULL;
WhoS->NextForClient = ClientS->Who_Head;
if (WhoS->NextForClient != NULL) { WhoS->NextForClient->PrevForClient = WhoS; }
ClientS->Who_Head = WhoS;
WhoS->NextForChan = ChanS->Who_Head;
ChanS->Who_Head = WhoS;
WhoS->ClientS = ClientS;
}
}
}
}
conn_addsendq(ClientS->ConnS, "%s", LinePT);
}
else { client_notice(ClientS, "Attached connection not established."); }
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1