This repository has been archived on 2025-02-12. You can view files and clone it, but cannot push or open issues or pull requests.
NeoStats/ircd.c

2070 lines
46 KiB
C

/* NeoStats - IRC Statistical Services
** Copyright (c) 1999-2004 Adam Rutter, Justin Hammond
** http://www.neostats.net/
**
** Portions Copyright (c) 2000-2001 ^Enigma^
**
** Portions Copyright (c) 1999 Johnathan George net@lite.net
**
** 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
** USA
**
** NeoStats CVS Identification
** $Id$
*/
#include <setjmp.h>
#include "stats.h"
#include "ircd.h"
#include "dl.h"
#include "sock.h"
#include "log.h"
#include "users.h"
#include "chans.h"
#include "services.h"
#include "server.h"
#include "bans.h"
#include "dns.h"
ircd_server ircd_srv;
static char ircd_buf[BUFSIZE];
static char UmodeStringBuf[64];
#ifdef GOTUSERSMODES
static char SmodeStringBuf[64];
#endif
long services_bot_umode= 0;
/* Fully split buffer */
static char privmsgbuffer[BUFSIZE];
/* Temp flag for backward compatibility in new splitbuf system */
static int SkipModuleFunction = 0;
static int signon_newbot (const char *nick, const char *user, const char *host, const char *realname, long Umode);
#ifdef IRCU
int scmode_op (const char *who, const char *chan, const char *mode, const char *bot);
#endif
/** @brief init_ircd
*
* ircd initialisation
*
* @return
*/
void
init_ircd ()
{
#ifdef IRCU
/* Temp: force tokens for IRCU */
ircd_srv.token = 1;
#endif
services_bot_umode = UmodeStringToMask(services_bot_modes, 0);
};
/** @brief UmodeMaskToString
*
* Translate a mode mask to the string equivalent
*
* @return
*/
char*
UmodeMaskToString(const long Umode)
{
int i, j;
UmodeStringBuf[0] = '+';
j = 1;
for (i = 0; i < ircd_umodecount; i++) {
if (Umode & user_umodes[i].umode) {
UmodeStringBuf[j] = user_umodes[i].mode;
j++;
}
}
UmodeStringBuf[j] = '\0';
return(UmodeStringBuf);
}
/** @brief UmodeStringToMask
*
* Translate a mode string to the mask equivalent
*
* @return
*/
long
UmodeStringToMask(const char* UmodeString, long Umode)
{
int i;
int add = 0;
char tmpmode;
/* Walk through mode string and convert to umode */
tmpmode = *(UmodeString);
while (tmpmode) {
switch (tmpmode) {
case '+':
add = 1;
break;
case '-':
add = 0;
break;
default:
for (i = 0; i < ircd_umodecount; i++) {
if (user_umodes[i].mode == tmpmode) {
if (add) {
Umode |= user_umodes[i].umode;
break;
} else {
Umode &= ~user_umodes[i].umode;
break;
}
}
}
}
tmpmode = *UmodeString++;
}
return(Umode);
}
#ifdef GOTUSERSMODES
/** @brief SmodeMaskToString
*
* Translate a smode mask to the string equivalent
*
* @return
*/
char*
SmodeMaskToString(const long Smode)
{
int i, j;
SmodeStringBuf[0] = '+';
j = 1;
for (i = 0; i < ircd_smodecount; i++) {
if (Smode & user_smodes[i].umode) {
SmodeStringBuf[j] = user_smodes[i].mode;
j++;
}
}
SmodeStringBuf[j] = '\0';
return(SmodeStringBuf);
}
/** @brief SmodeStringToMask
*
* Translate a smode string to the mask equivalent
*
* @return
*/
long
SmodeStringToMask(const char* SmodeString, long Smode)
{
int i;
int add = 0;
char tmpmode;
/* Walk through mode string and convert to smode */
tmpmode = *(SmodeString);
while (tmpmode) {
switch (tmpmode) {
case '+':
add = 1;
break;
case '-':
add = 0;
break;
default:
for (i = 0; i < ircd_smodecount; i++) {
if (user_smodes[i].mode == tmpmode) {
if (add) {
Smode |= user_smodes[i].umode;
break;
} else {
Smode &= ~user_smodes[i].umode;
break;
}
}
}
}
tmpmode = *SmodeString++;
}
return(Smode);
}
#endif
/** @brief join_bot_to_chan
*
*
*
* @return NS_SUCCESS if suceeds, NS_FAILURE if not
*/
int
join_bot_to_chan (const char *who, const char *chan, unsigned long chflag)
{
char savemod[SEGV_INMODULE_BUFSIZE];
strlcpy(savemod, segv_inmodule, SEGV_INMODULE_BUFSIZE);
#ifdef GOTSJOIN
ssjoin_cmd(who, chan, chflag);
#else
sjoin_cmd(who, chan);
if(chflag == CMODE_CHANOP || chflag == CMODE_CHANADMIN)
#if defined(IRCU)
scmode_op(who, chan, "+o", who);
#else
schmode_cmd(who, chan, "+o", who);
#endif
#endif
SET_SEGV_INMODULE(savemod);
return NS_SUCCESS;
}
/** @brief signon_newbot
*
* work in progress to replace ircd specific routines
* needs sjoin fix to complete
*
* @return NS_SUCCESS if suceeds, NS_FAILURE if not
*/
int
signon_newbot (const char *nick, const char *user, const char *host, const char *realname, long Umode)
{
snewnick_cmd (nick, user, host, realname, Umode);
if ((me.allbots > 0) || (Umode & services_bot_umode)) {
#ifdef GOTSJOIN
ssjoin_cmd (nick, me.chan, CMODE_CHANADMIN);
#else
sjoin_cmd (nick, me.chan);
#if defined(IRCU)
scmode_op(nick, me.chan, "+o", nick);
#else
schmode_cmd(nick, me.chan, "+o", nick);
#endif
#endif
}
return NS_SUCCESS;
}
/** @brief init_bot
*
*
*
* @return NS_SUCCESS if suceeds, NS_FAILURE if not
*/
int
init_bot (char *nick, char *user, char *host, char *realname, const char *modes, char *mod_name)
{
User *u;
long Umode;
SET_SEGV_LOCATION();
u = finduser (nick);
if (u) {
nlog (LOG_WARNING, LOG_CORE, "Attempting to Login with a Nickname that already Exists: %s", nick);
return NS_FAILURE;
}
if(!add_mod_user (nick, mod_name)) {
nlog (LOG_WARNING, LOG_CORE, "add_mod_user failed for module %s bot %s", mod_name, nick);
return NS_FAILURE;
}
Umode = UmodeStringToMask(modes, 0);
signon_newbot (nick, user, host, realname, Umode);
/* restore segv_inmodule from SIGNON */
SET_SEGV_INMODULE(mod_name);
return NS_SUCCESS;
}
/** @brief init_mod_bot
*
* replacement for init_bot - work in progress
*
* @return NS_SUCCESS if suceeds, NS_FAILURE if not
*/
ModUser * init_mod_bot (char * nick, char * user, char * host, char * realname,
const char *modes, unsigned int flags, bot_cmd *bot_cmd_list,
bot_setting *bot_setting_list, char * mod_name)
{
ModUser * bot_ptr;
User *u;
long Umode;
SET_SEGV_LOCATION();
u = finduser (nick);
if (u) {
nlog (LOG_WARNING, LOG_CORE, "Attempting to Login with a Nickname that already Exists: %s", nick);
return NULL;
}
bot_ptr = add_mod_user (nick, mod_name);
if(!bot_ptr) {
nlog (LOG_WARNING, LOG_CORE, "add_mod_user failed for module %s bot %s", mod_name, nick);
return NULL;
}
Umode = UmodeStringToMask(modes, 0);
signon_newbot (nick, user, host, realname, Umode);
#ifdef UMODE_DEAF
if(flags&BOT_FLAG_DEAF) {
sumode_cmd (nick, nick, UMODE_DEAF);
}
#endif
/* restore segv_inmodule from SIGNON */
SET_SEGV_INMODULE(mod_name);
bot_ptr->flags = flags;
add_bot_cmd_list(bot_ptr, bot_cmd_list);
if (bot_setting_list != NULL) {
bot_ptr->bot_settings = bot_setting_list;
/* Default SET to ROOT only */
bot_ptr->set_ulevel = NS_ULEVEL_ROOT;
/* Now calculate minimum defined user level */
while(bot_setting_list->option != NULL) {
if(bot_setting_list->ulevel < bot_ptr->set_ulevel)
bot_ptr->set_ulevel = bot_setting_list->ulevel;
bot_setting_list++;
}
} else {
bot_ptr->bot_settings = NULL;
bot_ptr->set_ulevel = NS_ULEVEL_ROOT;
}
return bot_ptr;
}
/** @brief del_bot
*
*
*
* @return NS_SUCCESS if suceeds, NS_FAILURE if not
*/
int
del_bot (char *nick, char *reason)
{
User *u;
SET_SEGV_LOCATION();
u = finduser (nick);
if (!u) {
nlog (LOG_WARNING, LOG_CORE, "Attempting to Logoff with a Nickname that does not Exists: %s", nick);
return NS_FAILURE;
}
nlog (LOG_DEBUG1, LOG_CORE, "Deleting bot %s for %s", nick, reason);
//XXXX TODO: need to free the channel list hash. We dont according to valgrind
squit_cmd (nick, reason);
del_mod_user (nick);
return NS_SUCCESS;
}
/** @brief CloakBotHost
*
* Create a hidden hostmask for the bot
* Currently only Unreal support via UMODE auto cloaking
* but function created for future use and propogation to
* external modules to avoid a future joint release.
*
* @return NS_SUCCESS if suceeds, NS_FAILURE if not
*/
int
CloakHost (ModUser *bot_ptr)
{
#ifdef GOTUMODECLOAKING
sumode_cmd (bot_ptr->nick, bot_ptr->nick, UMODE_HIDE);
return NS_SUCCESS;
#else
return NS_FAILURE;
#endif
}
/** @brief split_buf
* Taken from Epona - Thanks!
* Split a buffer into arguments and store the arguments in an
* argument vector pointed to by argv (which will be malloc'd
* as necessary); return the argument count. If colon_special
* is non-zero, then treat a parameter with a leading ':' as
* the last parameter of the line, per the IRC RFC. Destroys
* the buffer by side effect.
*
* @return
*/
#ifndef IRCD_SPLITBUF
int
splitbuf (char *buf, char ***argv, int colon_special)
{
int argvsize = 8;
int argc;
char *s;
int colcount = 0;
SET_SEGV_LOCATION();
*argv = calloc (sizeof (char *) * argvsize, 1);
argc = 0;
/*if (*buf == ':')
buf++;*/
while (*buf) {
if (argc == argvsize) {
argvsize += 8;
*argv = realloc (*argv, sizeof (char *) * argvsize);
}
if ((*buf == ':') && (colcount < 1)) {
buf++;
colcount++;
if(colon_special) {
(*argv)[argc++] = buf;
break;
}
}
s = strpbrk (buf, " ");
if (s) {
*s++ = 0;
while (isspace (*s))
s++;
} else {
s = buf + strnlen (buf, BUFSIZE);
}
if (*buf == 0) {
buf++;
}
(*argv)[argc++] = buf;
buf = s;
}
return argc;
}
#endif
int
split_buf (char *buf, char ***argv, int colon_special)
{
int argvsize = 8;
int argc;
char *s;
int colcount = 0;
SET_SEGV_LOCATION();
*argv = calloc (sizeof (char *) * argvsize, 1);
argc = 0;
if (*buf == ':')
buf++;
while (*buf) {
if (argc == argvsize) {
argvsize += 8;
*argv = realloc (*argv, sizeof (char *) * argvsize);
}
if ((*buf == ':') && (colcount < 1)) {
buf++;
colcount++;
}
s = strpbrk (buf, " ");
if (s) {
*s++ = 0;
while (isspace (*s))
s++;
} else {
s = buf + strnlen (buf, BUFSIZE);
}
if (*buf == 0) {
buf++;
}
(*argv)[argc++] = buf;
buf = s;
}
return argc;
}
/** @brief joinbuf
*
*
*
* @return
*/
char *
joinbuf (char **av, int ac, int from)
{
int i;
char *buf;
buf = malloc (BUFSIZE);
/* from is zero based while ac has base of 1.
* Therefore we need to check >= before trying to perform
* the join.
* The current (null) string we return may not be needed
* so should be removed once all joinbuf calls are checked.
* Maybe we should just return NULL if we fail and let
* the caller handle that case.
*/
if(from >= ac) {
nlog (LOG_DEBUG1, LOG_CORE, "joinbuf: from (%d) >= ac (%d)", from, ac);
strlcpy (buf, "(null)", BUFSIZE);
}
else {
strlcpy (buf, av[from], BUFSIZE);
for (i = from + 1; i < ac; i++) {
strlcat (buf, " ", BUFSIZE);
strlcat (buf, av[i], BUFSIZE);
}
}
return (char *) buf;
}
/** @brief process privmsg
*
*
*
* @return none
*/
void
m_notice (char* origin, char **av, int ac, int cmdptr)
{
int i;
int splitargc;
char **splitargv;
int argc;
char **argv;
SET_SEGV_LOCATION();
if( av[0] == NULL) {
nlog (LOG_DEBUG1, LOG_CORE, "m_notice: dropping unknown privmsg from %s, to %s : %s", origin, av[0], av[ac-1]);
return;
}
#if 0
if( ircstrcasecmp(av[0], "AUTH")) {
nlog (LOG_DEBUG1, LOG_CORE, "m_notice: dropping server notice from %s, to %s : %s", origin, av[0], av[ac-1]);
return;
}
#endif
nlog (LOG_DEBUG1, LOG_CORE, "m_notice: from %s, to %s : %s", origin, av[0], av[ac-1]);
strlcpy (privmsgbuffer, av[ac-1], BUFSIZE);
splitargc = split_buf (av[ac-1], &splitargv, 0);
argc = 0;
AddStringToList (&argv, av[0], &argc);
for( i = 0 ; i < splitargc ; i++ ) {
AddStringToList (&argv, splitargv[i], &argc);
}
ModuleFunction (cmdptr, MSG_NOTICE, origin, argv, argc);
free (argv);
argc = 0;
AddStringToList (&argv, origin, &argc);
AddStringToList (&argv, av[0], &argc);
AddStringToList (&argv, privmsgbuffer, &argc);
if(av[0][0] == '#') {
ModuleEvent (EVENT_CNOTICE, argv, argc);
} else {
ModuleEvent (EVENT_NOTICE, argv, argc);
}
free (argv);
SkipModuleFunction = 1;
}
/** @brief process privmsg
*
*
*
* @return none
*/
void
m_private (char* origin, char **av, int ac, int cmdptr)
{
int i;
int ret = NS_SUCCESS;
int splitargc;
char **splitargv;
int argc;
char **argv;
char target[64];
SET_SEGV_LOCATION();
if( av[0] == NULL) {
nlog (LOG_DEBUG1, LOG_CORE, "m_private: dropping unknown privmsg from %s, to %s : %s", origin, av[0], av[ac-1]);
return;
}
nlog (LOG_DEBUG1, LOG_CORE, "m_private: from %s, to %s : %s", origin, av[0], av[ac-1]);
/* its a privmsg, now lets see who too... */
if (strstr (av[0], "!")) {
strlcpy (target, av[0], 64);
av[0] = strtok (target, "!");
} else if (strstr (av[0], "@")) {
strlcpy (target, av[0], 64);
av[0] = strtok (target, "@");
}
strlcpy (privmsgbuffer, av[ac-1], BUFSIZE);
splitargc = split_buf (av[ac-1], &splitargv, 0);
argc = 0;
AddStringToList (&argv, av[0], &argc);
for( i = 0 ; i < splitargc ; i++ ) {
AddStringToList (&argv, splitargv[i], &argc);
}
if(av[0][0] == '#') {
bot_chan_message (origin, argv, argc);
/* we need this to fool the check below */
ret = NS_FAILURE;
} else {
ret = bot_message (origin, argv, argc);
}
free (argv);
free (splitargv);
if(ret == NS_FAILURE) {
argc = 0;
AddStringToList (&argv, origin, &argc);
AddStringToList (&argv, av[0], &argc);
AddStringToList (&argv, privmsgbuffer, &argc);
if(av[0][0] == '#') {
ModuleEvent (EVENT_CPRIVATE, argv, argc);
} else {
ModuleEvent (EVENT_PRIVATE, argv, argc);
}
free (argv);
}
return;
}
/** @brief process ircd commands
*
*
*
* @return none
*/
#ifdef IRCU
void
#else
static void
#endif
process_ircd_cmd (int cmdptr, char *cmd, char* origin, char **av, int ac)
{
int i;
SET_SEGV_LOCATION();
for (i = 0; i < ircd_cmdcount; i++) {
if (!strcmp (cmd_list[i].name, cmd)
#ifdef GOTTOKENSUPPORT
||(ircd_srv.token && cmd_list[i].token && !strcmp (cmd_list[i].token, cmd))
#endif
) {
if(cmd_list[i].function) {
nlog (LOG_DEBUG3, LOG_CORE, "process_ircd_cmd: running command %s", cmd_list[i].name);
cmd_list[i].function (origin, av, ac, cmdptr);
} else {
nlog (LOG_DEBUG3, LOG_CORE, "process_ircd_cmd: ignoring command %s", cmd);
}
cmd_list[i].usage++;
break;
}
}
#if 0
if(i >= ircd_cmdcount) {
nlog (LOG_INFO, LOG_CORE, "No support for %s", cmd);
}
#endif
/* Send to modules */
if(!SkipModuleFunction) {
ModuleFunction (cmdptr, cmd, origin, av, ac);
}
SkipModuleFunction = 0;
}
/** @brief parse
*
*
*
* @return none
*/
#ifndef IRCD_PARSE
void
parse (char *line)
{
char origin[64], cmd[64], *coreLine;
int cmdptr = 0;
int ac;
char **av;
SET_SEGV_LOCATION();
strip (line);
strlcpy (recbuf, line, BUFSIZE);
if (!(*line))
return;
nlog (LOG_DEBUG1, LOG_CORE, "--------------------------BEGIN PARSE---------------------------");
nlog (LOG_DEBUG1, LOG_CORE, "R: %s", line);
if (*line == ':') {
coreLine = strpbrk (line, " ");
if (!coreLine)
return;
*coreLine = 0;
while (isspace (*++coreLine));
strlcpy (origin, line + 1, sizeof (origin));
memmove (line, coreLine, strnlen (coreLine, BUFSIZE) + 1);
cmdptr = 1;
} else {
cmdptr = 0;
*origin = 0;
}
if (!*line)
return;
coreLine = strpbrk (line, " ");
if (coreLine) {
*coreLine = 0;
while (isspace (*++coreLine));
} else {
coreLine = line + strlen (line);
}
strlcpy (cmd, line, sizeof (cmd));
nlog (LOG_DEBUG1, LOG_CORE, "origin: %s", origin);
nlog (LOG_DEBUG1, LOG_CORE, "cmd : %s", cmd);
nlog (LOG_DEBUG1, LOG_CORE, "args : %s", coreLine);
ac = splitbuf (coreLine, &av, 1);
process_ircd_cmd (cmdptr, cmd, origin, av, ac);
nlog (LOG_DEBUG1, LOG_CORE, "---------------------------END PARSE----------------------------");
free (av);
}
#endif
/** @brief init_services_bot
*
*
*
* @return none
*/
int
init_services_bot (void)
{
char **av;
int ac = 0;
long Umode;
SET_SEGV_LOCATION();
if (finduser (s_Services)) {
/* nick already exists on the network */
strlcat (s_Services, "1", MAXNICK);
}
ircsnprintf (me.realname, MAXREALNAME, "/msg %s \2HELP\2", s_Services);
Umode = UmodeStringToMask(services_bot_modes, 0);
signon_newbot (s_Services, me.user, me.host, me.realname, Umode);
#ifdef UMODE_DEAF
sumode_cmd (s_Services, s_Services, UMODE_DEAF);
#endif
me.onchan = 1;
AddStringToList (&av, me.uplink, &ac);
ModuleEvent (EVENT_ONLINE, av, ac);
free (av);
return NS_SUCCESS;
}
/** @brief do_ping
*
*
*
* @return none
*/
void
do_ping (const char* origin, const char* destination)
{
send_pong (origin);
#ifdef MSG_BURST
if (ircd_srv.burst) {
send_ping (me.name, origin, origin);
}
#endif
}
/** @brief do_pong
*
*
*
* @return none
*/
void
do_pong (const char* origin, const char* destination)
{
Server *s;
char **av;
int ac = 0;
s = findserver (origin);
if (s) {
s->ping = me.now - ping.last_sent;
if (ping.ulag > 1)
s->ping -= (float) ping.ulag;
if (!strcmp (me.s->name, s->name))
ping.ulag = me.s->ping;
AddStringToList (&av, s->name, &ac);
ModuleEvent (EVENT_PONG, av, ac);
free (av);
} else {
nlog (LOG_NOTICE, LOG_CORE, "Received PONG from unknown server: %s", origin);
}
}
/** @brief flood
*
*
*
* @return
*/
int
flood (User * u)
{
time_t current = me.now;
if (!u) {
nlog (LOG_WARNING, LOG_CORE, "flood: can't find user");
return 0;
}
if (UserLevel (u) >= NS_ULEVEL_OPER) /* locop or higher */
return 0;
if (current - u->t_flood > 10) {
u->t_flood = me.now;
u->flood = 0;
return 0;
}
if (u->flood >= 5) {
nlog (LOG_NORMAL, LOG_CORE, "FLOODING: %s!%s@%s", u->nick, u->username, u->hostname);
ssvskill_cmd (u->nick, "%s!%s (Flooding Services.)", me.host, s_Services);
return 1;
} else {
u->flood++;
}
return 0;
}
/** @brief Display NeoStats version info
*
*
*
* @return
*/
void
do_version (const char* nick, const char *remoteserver)
{
SET_SEGV_LOCATION();
numeric (RPL_VERSION, nick, "%s :%s -> %s %s", me.versionfull, me.name, version_date, version_time);
ModulesVersion (nick, remoteserver);
}
/** @brief Display our MOTD Message of the Day from the external neostats.motd file
*
*
*
* @return
*/
void
do_motd (const char* nick, const char *remoteserver)
{
FILE *fp;
char buf[BUFSIZE];
SET_SEGV_LOCATION();
fp = fopen (MOTD_FILENAME, "r");
if(!fp) {
numeric (ERR_NOMOTD, nick, "MOTD File is missing");
} else {
numeric (RPL_MOTDSTART, nick, ":- %s Message of the Day -", me.name);
numeric (RPL_MOTD, nick, ":- %s. Copyright (c) 1999 - 2004 The NeoStats Group", me.versionfull);
numeric (RPL_MOTD, nick, ":-");
if (fp) {
while (fgets (buf, sizeof (buf), fp)) {
buf[strnlen (buf, BUFSIZE) - 1] = 0;
numeric (RPL_MOTD, nick, ":- %s", buf);
}
fclose (fp);
} else {
numeric (RPL_MOTD, nick, ":- MOTD file Missing");
}
numeric (RPL_ENDOFMOTD, nick, ":End of MOTD command.");
}
}
/** @brief Display the ADMIN Message from the external stats.admin file
*
*
*
* @return
*/
void
do_admin (const char* nick, const char *remoteserver)
{
FILE *fp;
char buf[BUFSIZE];
SET_SEGV_LOCATION();
fp = fopen (ADMIN_FILENAME, "r");
if(!fp) {
numeric (ERR_NOADMININFO, nick, "%s :No administrative info available", me.name);
} else {
numeric (RPL_ADMINME, nick, ":%s :Administrative info", me.name);
numeric (RPL_ADMINME, nick, ":%s. Copyright (c) 1999 - 2004 The NeoStats Group", me.versionfull);
if (fp) {
while (fgets (buf, sizeof (buf), fp)) {
buf[strnlen (buf, BUFSIZE) - 1] = 0;
numeric (RPL_ADMINLOC1, nick, ":- %s", buf);
}
fclose (fp);
}
numeric (RPL_ADMINLOC2, nick, "End of /ADMIN command.");
}
}
/** @brief
*
*
*
* @return
*/
void
do_credits (const char* nick, const char *remoteserver)
{
SET_SEGV_LOCATION();
numeric (RPL_VERSION, nick, ":- NeoStats %s Credits ", me.versionfull);
numeric (RPL_VERSION, nick, ":- Now Maintained by Shmad (shmad@neostats.net) and ^Enigma^ (enigma@neostats.net)");
numeric (RPL_VERSION, nick, ":- For Support, you can find ^Enigma^ or Shmad at");
numeric (RPL_VERSION, nick, ":- irc.irc-chat.net #NeoStats");
numeric (RPL_VERSION, nick, ":- Thanks to:");
numeric (RPL_VERSION, nick, ":- Enigma for being part of the dev team");
numeric (RPL_VERSION, nick, ":- Stskeeps for writing the best IRCD ever!");
numeric (RPL_VERSION, nick, ":- chrisv@b0rked.dhs.org for the Code for Dynamically Loading Modules (Hurrican IRCD)");
numeric (RPL_VERSION, nick, ":- monkeyIRCD for the Module Segv Catching code");
numeric (RPL_VERSION, nick, ":- the Users of Global-irc.net and Dreaming.org for being our Guinea Pigs!");
numeric (RPL_VERSION, nick, ":- Andy For Ideas");
numeric (RPL_VERSION, nick, ":- HeadBang for BetaTesting, and Ideas, And Hassling us for Beta Copies");
numeric (RPL_VERSION, nick, ":- sre and Jacob for development systems and access");
numeric (RPL_VERSION, nick, ":- Error51 for Translating our FAQ and README files");
numeric (RPL_VERSION, nick, ":- users and opers of irc.irc-chat.net/org for putting up with our constant coding crashes!");
numeric (RPL_VERSION, nick, ":- Eggy for proving to use our code still had bugs when we thought it didn't (and all the bug reports!)");
numeric (RPL_VERSION, nick, ":- Hwy - Helping us even though he also has a similar project, and providing solaris porting tips :)");
numeric (RPL_VERSION, nick, ":- M - Updating lots of Doco and code and providing lots of great feedback");
numeric (RPL_VERSION, nick, ":- J Michael Jones - Giving us Patches to support QuantumIRCd");
numeric (RPL_VERSION, nick, ":- Blud - Giving us patches for Mystic IRCd");
numeric (RPL_VERSION, nick, ":- herrohr - Giving us patches for Liquid IRCd support");
numeric (RPL_VERSION, nick, ":- OvErRiTe - Giving us patches for Viagra IRCd support");
numeric (RPL_VERSION, nick, ":- Reed Loden - Contributions to IRCu support");
}
/** @brief
*
*
*
* @return
*/
void
do_stats (const char* nick, const char *what)
{
time_t tmp;
time_t tmp2;
int i;
#ifdef EXTAUTH
int dl;
int (*listauth) (User * u);
#endif
User *u;
SET_SEGV_LOCATION();
u = finduser (nick);
if (!u) {
nlog (LOG_WARNING, LOG_CORE, "do_stats: message from unknown user %s", nick);
return;
}
if (!ircstrcasecmp (what, "u")) {
/* server uptime - Shmad */
int uptime = me.now - me.t_start;
numeric (RPL_STATSUPTIME, u->nick, "Statistical Server up %d days, %d:%02d:%02d", uptime / 86400, (uptime / 3600) % 24, (uptime / 60) % 60, uptime % 60);
} else if (!ircstrcasecmp (what, "c")) {
/* Connections */
numeric (RPL_STATSNLINE, u->nick, "N *@%s * * %d 50", me.uplink, me.port);
numeric (RPL_STATSCLINE, u->nick, "C *@%s * * %d 50", me.uplink, me.port);
} else if (!ircstrcasecmp (what, "o")) {
/* Operators */
#ifdef EXTAUTH
dl = get_dl_handle ("extauth");
if (dl > 0) {
listauth = ns_dlsym ((int *) dl, "__list_auth");
if (listauth)
(*listauth) (u);
} else
#endif
numeric (RPL_STATSOLINE, u->nick, "Operators think they are God, but you and I know they are not!");
} else if (!ircstrcasecmp (what, "l")) {
/* Port Lists */
tmp = me.now - me.lastmsg;
tmp2 = me.now - me.t_start;
numeric (RPL_STATSLINKINFO, u->nick, "l SendQ SendM SendBytes RcveM RcveBytes Open_Since CPU :IDLE");
numeric (RPL_STATSLLINE, u->nick, "%s 0 %d %d %d %d %d 0 :%d", me.uplink, (int)me.SendM, (int)me.SendBytes, (int)me.RcveM, (int)me.RcveBytes, (int)tmp2, (int)tmp);
} else if (!ircstrcasecmp (what, "M")) {
for (i = 0; i < ircd_cmdcount; i++) {
if (cmd_list[i].usage > 0)
numeric (RPL_STATSCOMMANDS, u->nick, "Command %s Usage %d", cmd_list[i].name, cmd_list[i].usage);
}
} else if (!ircstrcasecmp(what, "Z")) {
if (UserLevel(u) >= NS_ULEVEL_ADMIN) {
do_dns_stats_Z(u);
}
}
numeric (RPL_ENDOFSTATS, u->nick, "%s :End of /STATS report", what);
chanalert (s_Services, "%s Requested Stats %s", u->nick, what);
};
void
do_protocol (char *origin, char **argv, int argc)
{
int i;
ircd_srv.unkline = 0;
for (i = 0; i < argc; i++) {
#ifdef GOTTOKENSUPPORT
if (!ircstrcasecmp ("TOKEN", argv[i])) {
ircd_srv.token = 1;
}
#endif
#ifdef GOTCLIENTSUPPORT
if (!ircstrcasecmp ("CLIENT", argv[i])) {
me.client = 1;
}
#endif
#if defined(HYBRID7)
if (!ircstrcasecmp ("UNKLN", argv[i])) {
ircd_srv.unkline = 1;
}
#endif
#ifdef GOTNOQUITSUPPORT
if (!ircstrcasecmp ("NOQUIT", argv[i])) {
ircd_srv.noquit = 1;
}
#endif
#ifdef UNREAL32
if (!ircstrcasecmp ("NICKIP", argv[i])) {
ircd_srv.nickip = 1;
}
#endif
}
}
void
privmsg_list (char *to, char *from, const char **text)
{
while (*text) {
if (**text)
prefmsg (to, from, (char*)*text);
else
prefmsg (to, from, " ");
text++;
}
}
void
chanalert (char *from, char *fmt, ...)
{
va_list ap;
if (!me.onchan)
return;
va_start (ap, fmt);
ircvsnprintf (ircd_buf, BUFSIZE, fmt, ap);
va_end (ap);
send_privmsg (from, me.chan, ircd_buf);
}
void
prefmsg (char *to, const char *from, char *fmt, ...)
{
va_list ap;
if (findbot (to)) {
chanalert (s_Services, "Message From our Bot(%s) to Our Bot(%s), Dropping Message", from, to);
return;
}
va_start (ap, fmt);
ircvsnprintf (ircd_buf, BUFSIZE, fmt, ap);
va_end (ap);
if (me.want_privmsg) {
send_privmsg (from, to, ircd_buf);
} else {
send_notice (from, to, ircd_buf);
}
}
void
privmsg (char *to, const char *from, char *fmt, ...)
{
va_list ap;
if (findbot (to)) {
chanalert (s_Services, "Message From our Bot(%s) to Our Bot(%s), Dropping Message", from, to);
return;
}
va_start (ap, fmt);
ircvsnprintf (ircd_buf, BUFSIZE, fmt, ap);
va_end (ap);
send_privmsg (from, to, ircd_buf);
}
void
notice (char *to, const char *from, char *fmt, ...)
{
va_list ap;
if (findbot (to)) {
chanalert (s_Services, "Message From our Bot(%s) to Our Bot(%s), Dropping Message", from, to);
return;
}
va_start (ap, fmt);
ircvsnprintf (ircd_buf, BUFSIZE, fmt, ap);
va_end (ap);
send_notice (from, to, ircd_buf);
}
void
globops (char *from, char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
ircvsnprintf (ircd_buf, BUFSIZE, fmt, ap);
va_end (ap);
if (me.onchan) {
send_globops(from, ircd_buf);
} else {
nlog (LOG_NORMAL, LOG_CORE, ircd_buf);
}
}
int
wallops (const char *from, const char *msg, ...)
{
va_list ap;
va_start (ap, msg);
ircvsnprintf (ircd_buf, BUFSIZE, msg, ap);
va_end (ap);
send_wallops ((char*)from, (char*)ircd_buf);
return NS_SUCCESS;
}
int
numeric (const int numeric, const char *target, const char *data, ...)
{
va_list ap;
va_start (ap, data);
ircvsnprintf (ircd_buf, BUFSIZE, data, ap);
va_end (ap);
send_numeric (me.name, numeric, target, ircd_buf);
return NS_SUCCESS;
}
void
unsupported_cmd(const char* cmd)
{
chanalert (s_Services, "Warning, %s tried to %s which is not supported", ((segvinmodule[0] != 0)? segvinmodule : ""), cmd);
nlog (LOG_NOTICE, LOG_CORE, "Warning, %s tried to %s, which is not supported", ((segvinmodule[0] != 0)? segvinmodule : ""), cmd);
}
int
sumode_cmd (const char *who, const char *target, long mode)
{
char* newmode;
newmode = UmodeMaskToString(mode);
send_umode (who, target, newmode);
UserMode (target, newmode);
return NS_SUCCESS;
}
int
spart_cmd (const char *who, const char *chan)
{
send_part(who, chan);
part_chan (finduser (who), (char *) chan, NULL);
return NS_SUCCESS;
}
int
snick_cmd (const char *oldnick, const char *newnick)
{
UserNick (oldnick, newnick, NULL);
send_nickchange (oldnick, newnick, me.now);
return NS_SUCCESS;
}
#ifdef IRCU
int
scmode_op (const char *who, const char *chan, const char *mode, const char *bot)
{
char **av;
int ac;
send_cmode (me.name, who, chan, mode, nicktobase64 (bot), me.now);
ircsnprintf (ircd_buf, BUFSIZE, "%s %s %s", chan, mode, bot);
ac = split_buf (ircd_buf, &av, 0);
ChanMode (me.name, av, ac);
free (av);
return NS_SUCCESS;
}
#endif
int
schmode_cmd (const char *who, const char *chan, const char *mode, const char *args)
{
char **av;
int ac;
send_cmode (me.name, who, chan, mode, args, me.now);
ircsnprintf (ircd_buf, BUFSIZE, "%s %s %s", chan, mode, args);
ac = split_buf (ircd_buf, &av, 0);
ChanMode (me.name, av, ac);
free (av);
return NS_SUCCESS;
}
int
squit_cmd (const char *who, const char *quitmsg)
{
send_quit (who, quitmsg);
do_quit (who, quitmsg);
return NS_SUCCESS;
}
int
skill_cmd (const char *from, const char *target, const char *reason, ...)
{
va_list ap;
va_start (ap, reason);
ircvsnprintf (ircd_buf, BUFSIZE, reason, ap);
va_end (ap);
send_kill (from, target, ircd_buf);
do_quit (target, ircd_buf);
return NS_SUCCESS;
}
int
ssvskill_cmd (const char *target, const char *reason, ...)
{
va_list ap;
va_start (ap, reason);
ircvsnprintf (ircd_buf, BUFSIZE, reason, ap);
va_end (ap);
#ifdef GOTSVSKILL
send_svskill (me.name, target, ircd_buf);
#else
send_kill (me.name, target, ircd_buf);
do_quit (target, ircd_buf);
#endif
return NS_SUCCESS;
}
#ifdef GOTSVSTIME
int
ssvstime_cmd (const time_t ts)
{
send_svstime(me.name, (unsigned long)ts);
nlog (LOG_NOTICE, LOG_CORE, "ssvstime_cmd: synching server times to %lu", ts);
return NS_SUCCESS;
}
#endif
int
skick_cmd (const char *who, const char *chan, const char *target, const char *reason)
{
send_kick (who, chan, target, reason);
part_chan (finduser (target), (char *) chan, reason[0] != 0 ? (char *)reason : NULL);
return NS_SUCCESS;
}
int
sinvite_cmd (const char *from, const char *to, const char *chan)
{
send_invite(from, to, chan);
return NS_SUCCESS;
}
int
ssvsmode_cmd (const char *target, const char *modes)
{
#ifdef GOTSVSMODE
User *u;
u = finduser (target);
if (!u) {
nlog (LOG_WARNING, LOG_CORE, "ssvsmode_cmd: can't find user %s", target);
return 0;
}
send_svsmode(me.name, target, modes);
UserMode (target, modes);
#else
unsupported_cmd("SVSMODE");
#endif
return NS_SUCCESS;
}
int
ssvshost_cmd (const char *who, const char *vhost)
{
#ifdef GOTSVSHOST
User *u;
u = finduser (who);
if (!u) {
nlog (LOG_WARNING, LOG_CORE, "ssvshost_cmd: can't find user %s", who);
return 0;
}
strlcpy (u->vhost, vhost, MAXHOST);
send_svshost(me.name, who, vhost);
#else
unsupported_cmd("SVSHOST");
#endif
return NS_SUCCESS;
}
int
ssvsjoin_cmd (const char *target, const char *chan)
{
#ifdef GOTSVSJOIN
send_svsjoin (me.name, target, chan);
#else
unsupported_cmd("SVSJOIN");
#endif
return NS_SUCCESS;
}
int
ssvspart_cmd (const char *target, const char *chan)
{
#ifdef GOTSVSPART
send_svspart (me.name, target, chan);
#else
unsupported_cmd("SVSPART");
#endif
return NS_SUCCESS;
}
int
sswhois_cmd (const char *target, const char *swhois)
{
#ifdef GOTSWHOIS
send_swhois (me.name, target, swhois);
#else
unsupported_cmd("SWHOIS");
#endif
return NS_SUCCESS;
}
int
ssvsnick_cmd (const char *target, const char *newnick)
{
#ifdef GOTSVSNICK
send_svsnick (me.name, target, newnick, me.now);
#else
notice (s_Services, "Warning Module %s tried to SVSNICK, which is not supported", segvinmodule);
nlog (LOG_NOTICE, LOG_CORE, "Warning. Module %s tried to SVSNICK, which is not supported", segvinmodule);
#endif
return NS_SUCCESS;
}
int
ssmo_cmd (const char *from, const char *umodetarget, const char *msg)
{
#ifdef GOTSMO
send_smo (from, umodetarget, msg);
#else
unsupported_cmd("SMO");
#endif
return NS_SUCCESS;
}
int
sakill_cmd (const char *host, const char *ident, const char *setby, const int length, const char *reason, ...)
{
va_list ap;
va_start (ap, reason);
ircvsnprintf (ircd_buf, BUFSIZE, reason, ap);
va_end (ap);
send_akill(me.name, host, ident, setby, length, ircd_buf, me.now);
return NS_SUCCESS;
}
int
srakill_cmd (const char *host, const char *ident)
{
send_rakill (me.name, host, ident);
return NS_SUCCESS;
}
int
ssjoin_cmd (const char *who, const char *chan, unsigned long chflag)
{
char flag;
char mode;
char **av;
int ac;
time_t ts;
Chans *c;
c = findchan ((char *) chan);
if (!c) {
ts = me.now;
} else {
ts = c->tstime;
}
switch (chflag) {
#ifdef CMODE_FL_CHANOP
case CMODE_CHANOP:
flag = CMODE_FL_CHANOP;
mode= CMODE_CH_CHANOP;
break;
#endif
#ifdef CMODE_FL_VOICE
case CMODE_VOICE:
flag = CMODE_FL_VOICE;
mode= CMODE_CH_VOICE;
break;
#endif
#ifdef CMODE_FL_CHANOWNER
case CMODE_CHANOWNER:
flag = CMODE_FL_CHANOWNER;
mode= CMODE_CH_CHANOWNER;
break;
#endif
#ifdef CMODE_FL_CHANPROT
case CMODE_CHANPROT:
flag = CMODE_FL_CHANPROT;
mode= CMODE_CH_CHANPROT;
break;
#endif
#ifdef CMODE_FL_VIP
case CMODE_VIP:
flag = CMODE_FL_VIP;
mode= CMODE_CH_VIP;
break;
#endif
#ifdef CMODE_FL_HALFOP
case CMODE_HALFOP:
flag = CMODE_FL_HALFOP;
mode= CMODE_CH_HALFOP;
break;
#endif
#ifdef CMODE_FL_UOP
case CMODE_UOP:
flag = CMODE_FL_UOP;
mode= CMODE_CH_UOP;
break;
#endif
#ifndef FAKE_CMODE_CHANADMIN
#ifdef CMODE_FL_CHANADMIN
case CMODE_CHANADMIN:
flag = CMODE_FL_CHANADMIN;
mode= CMODE_CH_CHANADMIN;
break;
#endif
#endif
#ifdef CMODE_SILENCE
case CMODE_FL_SILENCE:
flag = CMODE_FL_SILENCE;
mode= CMODE_CH_SILENCE;
break;
#endif
default:
flag = ' ';
mode= '\0';
}
if (mode == 0) {
ircsnprintf (ircd_buf, BUFSIZE, "%s", who);
} else {
ircsnprintf (ircd_buf, BUFSIZE, "%c%s", flag, who);
}
send_sjoin (me.name, ircd_buf, chan, (unsigned long)ts);
join_chan (who, chan);
ircsnprintf (ircd_buf, BUFSIZE, "%s +%c %s", chan, mode, who);
ac = split_buf (ircd_buf, &av, 0);
ChanMode (me.name, av, ac);
free (av);
return NS_SUCCESS;
}
int
sjoin_cmd (const char *who, const char *chan)
{
send_join (me.name, who, chan, me.now);
join_chan (who, chan);
return NS_SUCCESS;
}
int
sping_cmd (const char *from, const char *reply, const char *to)
{
send_ping (from, reply, to);
return NS_SUCCESS;
}
int
spong_cmd (const char *reply)
{
send_pong (reply);
return NS_SUCCESS;
}
int
sserver_cmd (const char *name, const int numeric, const char *infoline)
{
send_server (me.name, name, numeric, infoline);
return NS_SUCCESS;
}
int
ssquit_cmd (const char *server, const char *quitmsg)
{
send_squit (server, quitmsg);
return NS_SUCCESS;
}
int
snewnick_cmd (const char *nick, const char *ident, const char *host, const char *realname, long mode)
{
char* newmode;
newmode = UmodeMaskToString(mode);
AddUser (nick, ident, host, realname, me.name, NULL, NULL, NULL);
send_nick (nick, (unsigned long)me.now, newmode, ident, host, me.name, realname);
#if defined(ULTIMATE3) || defined(BAHAMUT) || defined(HYBRID7) || defined(IRCU) || defined(NEOIRCD) || defined(QUANTUM) || defined(LIQUID)
UserMode (nick, newmode);
#else
sumode_cmd (nick, nick, mode);
#endif
return NS_SUCCESS;
}
/* SJOIN <TS> #<channel> <modes> :[@][+]<nick_1> ... [@][+]<nick_n> */
void
do_sjoin (char* tstime, char* channame, char *modes, char *sjoinnick, char **argv, int argc)
{
char nick[MAXNICK];
char* nicklist;
int modeexists;
long mode = 0;
int ok = 1, i, j = 3;
ModesParm *m;
Chans *c;
lnode_t *mn = NULL;
char **param;
int paramcnt = 0;
int paramidx = 0;
if (*modes == '#') {
join_chan (sjoinnick, modes);
return;
}
paramcnt = split_buf(argv[argc-1], &param, 0);
while (paramcnt > paramidx) {
nicklist = param[paramidx];
#ifdef UNREAL
/* Unreal passes +b(&) and +e(") via SJ3 so skip them for now */
if(*nicklist == '&' || *nicklist == '"') {
nlog (LOG_DEBUG1, LOG_CORE, "Skipping %s", nicklist);
paramidx++;
continue;
}
#endif
mode = 0;
while (ok == 1) {
for (i = 0; i < ircd_cmodecount; i++) {
if (chan_modes[i].sjoin != 0) {
if (*nicklist == chan_modes[i].sjoin) {
mode |= chan_modes[i].mode;
nicklist++;
i = -1;
}
} else {
/* sjoin's should be at the top of the list */
ok = 0;
strlcpy (nick, nicklist, MAXNICK);
break;
}
}
}
join_chan (nick, channame);
ChanUserMode (channame, nick, 1, mode);
paramidx++;
ok = 1;
}
c = findchan (channame);
if(c) {
/* update the TS time */
SetChanTS (c, atoi (tstime));
if (*modes == '+') {
while (*modes) {
for (i = 0; i < ircd_cmodecount; i++) {
if (*modes == chan_modes[i].flag) {
if (chan_modes[i].parameters) {
mn = list_first (c->modeparms);
modeexists = 0;
while (mn) {
m = lnode_get (mn);
/* mode limit and mode key replace current values */
if ((m->mode == CMODE_LIMIT) && (chan_modes[i].mode == CMODE_LIMIT)) {
strlcpy (m->param, argv[j], PARAMSIZE);
j++;
modeexists = 1;
break;
} else if ((m->mode == CMODE_KEY) && (chan_modes[i].mode == CMODE_KEY)) {
strlcpy (m->param, argv[j], PARAMSIZE);
j++;
modeexists = 1;
break;
} else if (((int *) m->mode == (int *) chan_modes[i].mode) && !ircstrcasecmp (m->param, argv[j])) {
nlog (LOG_INFO, LOG_CORE, "ChanMode: Mode %c (%s) already exists, not adding again", chan_modes[i].flag, argv[j]);
j++;
modeexists = 1;
break;
}
mn = list_next (c->modeparms, mn);
}
if (modeexists != 1) {
m = smalloc (sizeof (ModesParm));
m->mode = chan_modes[i].mode;
strlcpy (m->param, argv[j], PARAMSIZE);
mn = lnode_create (m);
if (list_isfull (c->modeparms)) {
nlog (LOG_CRITICAL, LOG_CORE, "ChanMode: modelist is full adding to channel %s", c->name);
do_exit (NS_EXIT_ERROR, "List full - see log file");
} else {
list_append (c->modeparms, mn);
}
j++;
}
} else {
c->modes |= chan_modes[i].mode;
}
}
}
modes++;
}
}
}
free(param);
}
#ifdef MSG_NETINFO
void
do_netinfo(const char* maxglobalcnt, const char* tsendsync, const char* prot, const char* cloak, const char* netname)
{
ircd_srv.maxglobalcnt = atoi (maxglobalcnt);
ircd_srv.tsendsync = atoi (tsendsync);
ircd_srv.uprot = atoi (prot);
strlcpy (ircd_srv.cloak, cloak, CLOAKKEYLEN);
strlcpy (me.netname, netname, MAXPASS);
send_netinfo (me.name, ircd_srv.uprot, ircd_srv.cloak, me.netname, me.now);
init_services_bot ();
globops (me.name, "Link with Network \2Complete!\2");
ModuleEvent (EVENT_NETINFO, NULL, 0);
me.synced = 1;
}
#endif
#ifdef MSG_SNETINFO
void
do_snetinfo(const char* maxglobalcnt, const char* tsendsync, const char* prot, const char* cloak, const char* netname)
{
ircd_srv.uprot = atoi (prot);
strlcpy (ircd_srv.cloak, cloak, CLOAKKEYLEN);
strlcpy (me.netname, netname, MAXPASS);
send_snetinfo (me.name, ircd_srv.uprot, ircd_srv.cloak, me.netname, me.now);
init_services_bot ();
globops (me.name, "Link with Network \2Complete!\2");
ModuleEvent (EVENT_NETINFO, NULL, 0);
me.synced = 1;
}
#endif
void
do_join (const char* nick, const char* chanlist, const char* keys)
{
char *s, *t;
t = (char*)chanlist;
while (*(s = t)) {
t = s + strcspn (s, ",");
if (*t)
*t++ = 0;
join_chan (nick, s);
}
}
void
do_part (const char* nick, const char* chan, const char* reason)
{
part_chan (finduser (nick), chan, reason);
}
void
do_nick (const char *nick, const char *hopcount, const char* TS,
const char *user, const char *host, const char *server,
const char *ip, const char *servicestamp, const char *modes,
const char *vhost, const char *realname, const char *numeric
#ifdef GOTUSERSMODES
, const char *smodes
#endif
)
{
AddUser (nick, user, host, realname, server, ip, TS, numeric);
if(modes) {
UserMode (nick, modes);
}
if(vhost) {
SetUserVhost(nick, vhost);
}
#ifdef GOTUSERSMODES
if(smodes) {
UserSMode (nick, smodes);
}
#endif
}
void
do_client (const char *nick, const char *arg1, const char *TS,
const char *modes, const char *smodes,
const char *user, const char *host, const char *vhost,
const char *server, const char *arg9,
const char *ip, const char *realname)
{
AddUser (nick, user, host, realname, server, ip, TS, NULL);
if(modes) {
UserMode (nick, modes);
}
if(vhost) {
SetUserVhost(nick, vhost);
}
#ifdef GOTUSERSMODES
if(smodes) {
UserSMode (nick, smodes);
}
#endif
}
void
do_kill (const char *nick, const char *reason)
{
DelUser (nick, 1, reason);
}
void
do_quit (const char *nick, const char *quitmsg)
{
DelUser (nick, 0, quitmsg);
}
void
do_squit(const char *name, const char* reason)
{
DelServer (name, reason);
}
void
do_kick (const char *kickby, const char *chan, const char *kicked, const char *kickreason)
{
kick_chan (kickby, chan, kicked, kickreason);
}
#ifdef MSG_SVINFO
void
do_svinfo (void)
{
send_svinfo (TS_CURRENT, TS_MIN, (unsigned long)me.now);
}
#endif
#ifdef MSG_VCTRL
void
do_vctrl (const char* uprot, const char* nicklen, const char* modex, const char* gc, const char* netname)
{
ircd_srv.uprot = atoi(uprot);
ircd_srv.nicklen = atoi(nicklen);
ircd_srv.modex = atoi(modex);
ircd_srv.gc = atoi(gc);
strlcpy (me.netname, netname, MAXPASS);
send_vctrl (ircd_srv.uprot, ircd_srv.nicklen, ircd_srv.modex, ircd_srv.gc, me.netname);
}
#endif
#ifdef GOTUSERSMODES
void
do_smode (const char* nick, const char* modes)
{
UserSMode (nick, modes);
}
#endif
void
do_mode_user (const char* nick, const char* modes)
{
UserMode (nick, modes);
}
void
do_svsmode_user (const char* nick, const char* modes, const char* ts)
{
char modebuf[MODESIZE];
if (ts && isdigit(*ts)) {
const char* pModes;
char* pNewModes;
SetUserServicesTS (nick, ts);
/* If only setting TS, we do not need further mode processing */
if(strcasecmp(modes, "+d") == 0) {
nlog (LOG_DEBUG3, LOG_CORE, "dropping modes since this is a services TS %s", modes);
return;
}
/* We need to strip the d from the mode string */
pNewModes = modebuf;
pModes = modes;
while(*pModes) {
if(*pModes != 'd') {
*pNewModes = *pModes;
}
pModes++;
pNewModes++;
}
/* NULL terminate */
*pNewModes = 0;
UserMode (nick, modebuf);
} else {
UserMode (nick, modes);
}
}
void
do_mode_channel (char *origin, char **argv, int argc)
{
ChanMode (origin, argv, argc);
}
void
do_away (const char* nick, const char *reason)
{
UserAway (nick, reason);
}
void
do_vhost (const char* nick, const char *vhost)
{
SetUserVhost(nick, vhost);
}
void
do_nickchange (const char * oldnick, const char *newnick, const char * ts)
{
UserNick (oldnick, newnick, ts);
}
void
do_topic (const char* chan, const char *owner, const char* ts, const char *topic)
{
ChanTopic (chan, owner, ts, topic);
}
void
do_server (const char *name, const char *uplink, const char* hops, const char *numeric, const char *infoline, int srv)
{
if(srv == 0) {
if (uplink == NULL || *uplink == 0) {
me.s = AddServer (name, me.name, hops, numeric, infoline);
} else {
me.s = AddServer (name, uplink, hops, numeric, infoline);
}
} else {
AddServer (name, uplink, hops, numeric, infoline);
}
}
#ifndef IRCU
#ifdef MSG_BURST
void
do_burst (char *origin, char **argv, int argc)
{
if (argc > 0) {
if (ircd_srv.burst == 1) {
send_burst (0);
ircd_srv.burst = 0;
me.synced = 1;
init_services_bot ();
}
} else {
ircd_srv.burst = 1;
}
}
#endif
#endif
#ifdef MSG_SWHOIS
void
do_swhois (char *who, char *swhois)
{
User* u;
u = finduser(who);
if(u) {
strlcpy(u->swhois, swhois, MAXHOST);
}
}
#endif
#ifdef MSG_TKL
void
do_tkl(const char *add, const char *type, const char *user, const char *host, const char *setby, const char *tsexpire, const char *tsset, const char *reason)
{
char mask[MAXHOST];
ircsnprintf(mask, MAXHOST, "%s@%s", user, host);
if(add[0] == '+') {
AddBan(type, user, host, mask, reason, setby, tsset, tsexpire);
} else {
DelBan(type, user, host, mask, reason, setby, tsset, tsexpire);
}
}
#endif
#ifdef MSG_EOS
void
do_eos (const char *name)
{
Server *s;
s = findserver (name);
if(s) {
SynchServer(s);
nlog (LOG_DEBUG1, LOG_CORE, "do_eos: server %s is now synched", name);
} else {
nlog (LOG_WARNING, LOG_CORE, "do_eos: server %s not found", name);
}
}
#endif
void
send_cmd (char *fmt, ...)
{
va_list ap;
char buf[BUFSIZE];
int buflen;
va_start (ap, fmt);
ircvsnprintf (buf, BUFSIZE, fmt, ap);
va_end (ap);
nlog (LOG_DEBUG2, LOG_CORE, "SENT: %s", buf);
if(strnlen (buf, BUFSIZE) < BUFSIZE - 2) {
strlcat (buf, "\n", BUFSIZE);
} else {
buf[BUFSIZE - 1] = 0;
buf[BUFSIZE - 2] = '\n';
}
buflen = strnlen (buf, BUFSIZE);
sts (buf, buflen);
}
#ifdef BASE64SERVERNAME
void
setserverbase64 (const char *name, const char* num)
{
Server *s;
s = findserver(name);
if(s) {
nlog (LOG_DEBUG1, LOG_CORE, "setserverbase64: setting %s to %s", name, num);
strlcpy(s->name64, num, 6);
} else {
nlog (LOG_DEBUG1, LOG_CORE, "setserverbase64: cannot find %s for %s", name, num);
}
}
char*
servertobase64 (const char* name)
{
Server *s;
nlog (LOG_DEBUG1, LOG_CORE, "servertobase64: scanning for %s", name);
s = findserver(name);
if(s) {
return s->name64;
} else {
nlog (LOG_DEBUG1, LOG_CORE, "servertobase64: cannot find %s", name);
}
return NULL;
}
char*
base64toserver (const char* num)
{
Server *s;
nlog (LOG_DEBUG1, LOG_CORE, "base64toserver: scanning for %s", num);
s = findserverbase64(num);
if(s) {
return s->name;
} else {
nlog (LOG_DEBUG1, LOG_CORE, "base64toserver: cannot find %s", num);
}
return NULL;
}
#endif
#ifdef BASE64NICKNAME
void
setnickbase64 (const char *nick, const char* num)
{
User *u;
u = finduser(nick);
if(u) {
nlog (LOG_DEBUG1, LOG_CORE, "setnickbase64: setting %s to %s", nick, num);
strlcpy(u->nick64, num, B64SIZE);
} else {
nlog (LOG_DEBUG1, LOG_CORE, "setnickbase64: cannot find %s for %s", nick, num);
}
}
char*
nicktobase64 (const char* nick)
{
User *u;
nlog (LOG_DEBUG1, LOG_CORE, "nicktobase64: scanning for %s", nick);
u = finduser(nick);
if(u) {
return u->nick64;
} else {
nlog (LOG_DEBUG1, LOG_CORE, "nicktobase64: cannot find %s", nick);
}
return NULL;
}
char*
base64tonick (const char* num)
{
User *u;
nlog (LOG_DEBUG1, LOG_CORE, "base64tonick: scanning for %s", num);
u = finduserbase64(num);
if(u) {
return u->nick;
} else {
nlog (LOG_DEBUG1, LOG_CORE, "base64tonick: cannot find %s", num);
}
return NULL;
}
#endif