/* OperServ functions.
*
* (C) 2003-2009 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*
* Based on the original code of Epona by Lara.
* Based on the original code of Services by Andy Church.
*
* $Id$
*
*/
#include "services.h"
#include "pseudo.h"
/*************************************************************************/
/* List of Services administrators */
SList servadmins;
/* List of Services operators */
SList servopers;
/* AKILL, SGLINE, SQLINE and SZLINE lists */
SList akills, sglines, sqlines, szlines;
/*************************************************************************/
static int compare_adminlist_entries(SList * slist, void *item1,
void *item2);
static int compare_operlist_entries(SList * slist, void *item1,
void *item2);
static void free_adminlist_entry(SList * slist, void *item);
static void free_operlist_entry(SList * slist, void *item);
static int is_akill_entry_equal(SList * slist, void *item1, void *item2);
static void free_akill_entry(SList * slist, void *item);
static int is_sgline_entry_equal(SList * slist, void *item1, void *item2);
static void free_sgline_entry(SList * slist, void *item);
static int is_sqline_entry_equal(SList * slist, void *item1, void *item2);
static void free_sqline_entry(SList * slist, void *item);
static int is_szline_entry_equal(SList * slist, void *item1, void *item2);
static void free_szline_entry(SList * slist, void *item);
time_t DefContimer;
int DefConModesSet = 0;
char *defconReverseModes(const char *modes);
uint32 DefConModesOn; /* Modes to be enabled during DefCon */
uint32 DefConModesOff; /* Modes to be disabled during DefCon */
ChannelInfo DefConModesCI; /* ChannelInfo containg params for locked modes
* during DefCon; I would've done this nicer if i
* could, but all damn mode functions require a
* ChannelInfo struct! --gdex
*/
void moduleAddOperServCmds();
/*************************************************************************/
/* Options for the lists */
SListOpts akopts = { 0, NULL, &is_akill_entry_equal, &free_akill_entry };
SListOpts saopts = { SLISTF_SORT, &compare_adminlist_entries, NULL,
&free_adminlist_entry
};
SListOpts sgopts = { 0, NULL, &is_sgline_entry_equal, &free_sgline_entry };
SListOpts soopts =
{ SLISTF_SORT, &compare_operlist_entries, NULL, &free_operlist_entry };
SListOpts sqopts =
{ SLISTF_SORT, NULL, &is_sqline_entry_equal, &free_sqline_entry };
SListOpts szopts = { 0, NULL, &is_szline_entry_equal, &free_szline_entry };
/*************************************************************************/
/* *INDENT-OFF* */
void moduleAddOperServCmds() {
ModuleManager::LoadModuleList(OperServCoreNumber, OperServCoreModules);
}
/* *INDENT-ON* */
/*************************************************************************/
/*************************************************************************/
/* OperServ initialization. */
void os_init()
{
moduleAddOperServCmds();
/* Initialization of the lists */
slist_init(&servadmins);
servadmins.opts = &saopts;
slist_init(&servopers);
servopers.opts = &soopts;
slist_init(&akills);
akills.opts = &akopts;
if (ircd->sgline) {
slist_init(&sglines);
sglines.opts = &sgopts;
}
if (ircd->sqline) {
slist_init(&sqlines);
sqlines.opts = &sqopts;
}
if (ircd->szline) {
slist_init(&szlines);
szlines.opts = &szopts;
}
}
/*************************************************************************/
/* Main OperServ routine. */
void operserv(User * u, char *buf)
{
const char *cmd;
const char *s;
alog("%s: %s: %s", s_OperServ, u->nick, buf);
cmd = strtok(buf, " ");
if (!cmd) {
return;
} else if (stricmp(cmd, "\1PING") == 0) {
if (!(s = strtok(NULL, ""))) {
s = "";
}
ircdproto->SendCTCP(findbot(s_OperServ), u->nick, "PING %s", s);
} else {
mod_run_cmd(s_OperServ, u, OPERSERV, cmd);
}
}
/*************************************************************************/
/**************************** Privilege checks ***************************/
/*************************************************************************/
/* Load OperServ data. */
#define SAFE(x) do { \
if ((x) < 0) { \
if (!forceload) \
fatal("Read error on %s", OperDBName); \
failed = 1; \
break; \
} \
} while (0)
void load_os_dbase()
{
dbFILE *f;
int16 i, ver;
uint16 tmp16;
uint32 tmp32;
int failed = 0;
if (!(f = open_db(s_OperServ, OperDBName, "r", OPER_VERSION)))
return;
ver = get_file_version(f);
if (ver != 13)
{
close_db(f);
fatal("Read error on %s", ChanDBName);
return;
}
SAFE(read_int32(&maxusercnt, f));
SAFE(read_int32(&tmp32, f));
maxusertime = tmp32;
Akill *ak;
read_int16(&tmp16, f);
slist_setcapacity(&akills, tmp16);
for (i = 0; i < akills.capacity; i++) {
ak = new Akill;
SAFE(read_string(&ak->user, f));
SAFE(read_string(&ak->host, f));
SAFE(read_string(&ak->by, f));
SAFE(read_string(&ak->reason, f));
SAFE(read_int32(&tmp32, f));
ak->seton = tmp32;
SAFE(read_int32(&tmp32, f));
ak->expires = tmp32;
slist_add(&akills, ak);
}
SXLine *sx;
read_int16(&tmp16, f);
slist_setcapacity(&sglines, tmp16);
for (i = 0; i < sglines.capacity; i++) {
sx = new SXLine;
SAFE(read_string(&sx->mask, f));
SAFE(read_string(&sx->by, f));
SAFE(read_string(&sx->reason, f));
SAFE(read_int32(&tmp32, f));
sx->seton = tmp32;
SAFE(read_int32(&tmp32, f));
sx->expires = tmp32;
slist_add(&sglines, sx);
}
read_int16(&tmp16, f);
slist_setcapacity(&sqlines, tmp16);
for (i = 0; i < sqlines.capacity; i++) {
sx = new SXLine;
SAFE(read_string(&sx->mask, f));
SAFE(read_string(&sx->by, f));
SAFE(read_string(&sx->reason, f));
SAFE(read_int32(&tmp32, f));
sx->seton = tmp32;
SAFE(read_int32(&tmp32, f));
sx->expires = tmp32;
slist_add(&sqlines, sx);
}
read_int16(&tmp16, f);
slist_setcapacity(&szlines, tmp16);
for (i = 0; i < szlines.capacity; i++) {
sx = new SXLine;
SAFE(read_string(&sx->mask, f));
SAFE(read_string(&sx->by, f));
SAFE(read_string(&sx->reason, f));
SAFE(read_int32(&tmp32, f));
sx->seton = tmp32;
SAFE(read_int32(&tmp32, f));
sx->expires = tmp32;
slist_add(&szlines, sx);
}
close_db(f);
}
#undef SAFE
/*************************************************************************/
/* Save OperServ data. */
#define SAFE(x) do { \
if ((x) < 0) { \
restore_db(f); \
log_perror("Write error on %s", OperDBName); \
if (time(NULL) - lastwarn > WarningTimeout) { \
ircdproto->SendGlobops(NULL, "Write error on %s: %s", OperDBName, \
strerror(errno)); \
lastwarn = time(NULL); \
} \
return; \
} \
} while (0)
void save_os_dbase()
{
int i;
dbFILE *f;
static time_t lastwarn = 0;
Akill *ak;
SXLine *sx;
if (!(f = open_db(s_OperServ, OperDBName, "w", OPER_VERSION)))
return;
SAFE(write_int32(maxusercnt, f));
SAFE(write_int32(maxusertime, f));
SAFE(write_int16(akills.count, f));
for (i = 0; i < akills.count; i++) {
ak = static_cast<Akill *>(akills.list[i]);
SAFE(write_string(ak->user, f));
SAFE(write_string(ak->host, f));
SAFE(write_string(ak->by, f));
SAFE(write_string(ak->reason, f));
SAFE(write_int32(ak->seton, f));
SAFE(write_int32(ak->expires, f));
}
SAFE(write_int16(sglines.count, f));
for (i = 0; i < sglines.count; i++) {
sx = static_cast<SXLine *>(sglines.list[i]);
SAFE(write_string(sx->mask, f));
SAFE(write_string(sx->by, f));
SAFE(write_string(sx->reason, f));
SAFE(write_int32(sx->seton, f));
SAFE(write_int32(sx->expires, f));
}
SAFE(write_int16(sqlines.count, f));
for (i = 0; i < sqlines.count; i++) {
sx = static_cast<SXLine *>(sqlines.list[i]);
SAFE(write_string(sx->mask, f));
SAFE(write_string(sx->by, f));
SAFE(write_string(sx->reason, f));
SAFE(write_int32(sx->seton, f));
SAFE(write_int32(sx->expires, f));
}
SAFE(write_int16(szlines.count, f));
for (i = 0; i < szlines.count; i++) {
sx = static_cast<SXLine *>(szlines.list[i]);
SAFE(write_string(sx->mask, f));
SAFE(write_string(sx->by, f));
SAFE(write_string(sx->reason, f));
SAFE(write_int32(sx->seton, f));
SAFE(write_int32(sx->expires, f));
}
close_db(f);
}
#undef SAFE
/*************************************************************************/
/* Removes the nick structure from OperServ lists. */
void os_remove_nick(NickCore * nc)
{
slist_remove(&servadmins, nc);
slist_remove(&servopers, nc);
}
/*
|