0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-25 16:22:35 +01:00

ircd: Namespace and partially modernize ircd::cache.

This commit is contained in:
Jason Volk 2016-08-13 16:42:12 -07:00
parent 31328e4759
commit 90c9fe686e
9 changed files with 326 additions and 275 deletions

View file

@ -1,5 +1,6 @@
/**
* Copyright (C) 2016 Charybdis development team
* Copyright (C) 2016 Jason Volk <jason@zemos.net>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -21,47 +22,48 @@
#pragma once
#define HAVE_IRCD_CACHE_H
#define HELP_MAX 100
#define CACHEFILELEN 30
/* two servernames, a gecos, three spaces, ":1", '\0' */
#define LINKSLINELEN (HOSTLEN + HOSTLEN + REALLEN + 6)
#define HELP_USER 0x001
#define HELP_OPER 0x002
#ifdef __cplusplus
namespace ircd {
namespace ircd {
namespace cache {
struct cachefile
constexpr auto CACHEFILELEN = 30;
constexpr auto LINKSLINELEN = HOSTLEN + HOSTLEN + REALLEN + 6; // 2 servernames, 1 gecos, 3 spaces, ":1", '\0'
struct file;
uint flags(const file &file);
const std::string &name(const file &file);
const std::vector<std::string> &contents(const file &file);
using dict = std::map<std::string, std::shared_ptr<file>, case_insensitive_less>;
namespace motd
{
cachefile(const char *filename, const char *shortname, int flags) {
cache(filename, shortname, flags);
}
extern char user_motd_changed[MAX_DATE_STRING];
cachefile() {};
extern file user;
extern file oper;
std::string name;
std::vector<std::string> contents;
int flags;
void send_user(Client *);
void send_oper(Client *);
void cache(const char *filename, const char *shortname, int flags);
};
void cache_user();
void cache_oper();
}
void init_cache(void);
void cache_links(void *unused);
namespace help
{
constexpr auto MAX = 100;
constexpr auto USER = 0x01;
constexpr auto OPER = 0x02;
void load_help(void);
extern dict user;
extern dict oper;
void send_user_motd(struct Client *);
void send_oper_motd(struct Client *);
void cache_user_motd(void);
void load();
}
extern struct cachefile user_motd;
extern struct cachefile oper_motd;
extern char user_motd_changed[MAX_DATE_STRING];
extern std::map<std::string, std::shared_ptr<cachefile>, case_insensitive_less> help_dict_oper;
extern std::map<std::string, std::shared_ptr<cachefile>, case_insensitive_less> help_dict_user;
void init();
} // namespace cache
} // namespace ircd
#endif // __cplusplus

View file

@ -75,7 +75,7 @@ extern "C" {
//#include <RB_INC_UNORDERED_MAP
//#include <RB_INC_DEQUE
#include <RB_INC_SSTREAM
//#include <RB_INC_FSTREAM
#include <RB_INC_FSTREAM
#include <RB_INC_IOSTREAM
#include <RB_INC_CSTDIO
#endif

View file

@ -4,6 +4,8 @@
*
* Copyright (C) 2003 Lee Hardy <lee@leeh.co.uk>
* Copyright (C) 2003-2005 ircd-ratbox development team
* Copyright (C) 2016 Charybdis development team
* Copyright (C) 2016 Jason Volk <jason@zemos.net>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@ -30,9 +32,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <map>
#include <vector>
#include <ircd/stdinc.h>
#include <ircd/s_conf.h>
#include <ircd/client.h>
@ -41,14 +40,33 @@
#include <ircd/numeric.h>
#include <ircd/send.h>
namespace ircd {
namespace cache = ircd::cache;
using namespace cache;
struct cachefile user_motd {};
struct cachefile oper_motd {};
char user_motd_changed[MAX_DATE_STRING];
static size_t untabify(char *dest, const char *src, size_t destlen);
struct cache::file
{
std::string filename;
std::string shortname;
std::ifstream stream;
int flags;
std::vector<std::string> contents;
file(const char *const &filename, const char *const &shortname, const int &flags);
file() = default;
file &operator=(file &&) noexcept;
};
file motd::user;
file motd::oper;
dict help::oper;
dict help::user;
char motd::user_motd_changed[MAX_DATE_STRING];
std::map<std::string, std::shared_ptr<cachefile>, case_insensitive_less> help_dict_oper;
std::map<std::string, std::shared_ptr<cachefile>, case_insensitive_less> help_dict_user;
/* init_cache()
*
@ -57,12 +75,215 @@ std::map<std::string, std::shared_ptr<cachefile>, case_insensitive_less> help_di
* side effects - inits the file/line cache blockheaps, loads motds
*/
void
init_cache(void)
cache::init()
{
user_motd_changed[0] = '\0';
motd::user = file(fs::paths[IRCD_PATH_IRCD_MOTD], "ircd.motd", 0);
motd::oper = file(fs::paths[IRCD_PATH_IRCD_OMOTD], "opers.motd", 0);
}
user_motd.cache(fs::paths[IRCD_PATH_IRCD_MOTD], "ircd.motd", 0);
oper_motd.cache(fs::paths[IRCD_PATH_IRCD_OMOTD], "opers.motd", 0);
/* load_help()
*
* inputs -
* outputs -
* side effects - old help cache deleted
* - contents of help directories are loaded.
*/
void
cache::help::load()
{
oper.clear();
user.clear();
DIR *dir(opendir(fs::paths[IRCD_PATH_OPERHELP]));
if (!dir)
return;
struct dirent *ldirent(nullptr);
while ((ldirent = readdir(dir)) != nullptr)
{
const auto &d_name(ldirent->d_name);
if (d_name[0] == '.')
continue;
char filename[PATH_MAX];
snprintf(filename, sizeof(filename), "%s%c%s", fs::paths[IRCD_PATH_OPERHELP], RB_PATH_SEPARATOR, d_name);
oper.emplace(d_name, std::make_shared<file>(filename, d_name, OPER));
}
closedir(dir);
dir = opendir(fs::paths[IRCD_PATH_USERHELP]);
if (dir == nullptr)
return;
while ((ldirent = readdir(dir)) != nullptr)
{
const auto &d_name(ldirent->d_name);
if (d_name[0] == '.')
continue;
char filename[PATH_MAX];
snprintf(filename, sizeof(filename), "%s%c%s", fs::paths[IRCD_PATH_USERHELP], RB_PATH_SEPARATOR, d_name);
#if defined(S_ISLNK) && defined(HAVE_LSTAT)
struct stat sb;
if (lstat(filename, &sb) < 0)
continue;
/* ok, if its a symlink, we work on the presumption if an
* oper help exists of that name, its a symlink to that --fl
*/
if (S_ISLNK(sb.st_mode))
{
const auto it(oper.find(d_name));
if (it != end(oper))
{
auto &file(it->second);
file->flags |= USER;
continue;
}
}
#endif
user.emplace(d_name, std::make_shared<file>(filename, d_name, USER));
}
closedir(dir);
}
void
cache::motd::cache_user(void)
{
struct stat sb;
if (stat(fs::paths[IRCD_PATH_IRCD_MOTD], &sb) == 0)
{
struct tm *const local_tm(localtime(&sb.st_mtime));
if (local_tm != nullptr)
{
snprintf(user_motd_changed, sizeof(user_motd_changed),
"%d/%d/%d %d:%d",
local_tm->tm_mday, local_tm->tm_mon + 1,
1900 + local_tm->tm_year, local_tm->tm_hour,
local_tm->tm_min);
}
}
user = file(fs::paths[IRCD_PATH_IRCD_MOTD], "ircd.motd", 0);
}
void
cache::motd::cache_oper(void)
{
oper = cache::file(fs::paths[IRCD_PATH_IRCD_OMOTD], "opers.motd", 0);
}
/* send_user_motd()
*
* inputs - client to send motd to
* outputs - client is sent motd if exists, else ERR_NOMOTD
* side effects -
*/
void
cache::motd::send_user(Client *source_p)
{
const char *const myname(get_id(&me, source_p));
const char *const nick(get_id(source_p, source_p));
if (user.contents.empty())
{
sendto_one(source_p, form_str(ERR_NOMOTD), myname, nick);
return;
}
sendto_one(source_p, form_str(RPL_MOTDSTART), myname, nick, me.name);
for (const auto &it : user.contents)
sendto_one(source_p, form_str(RPL_MOTD), myname, nick, it.c_str());
sendto_one(source_p, form_str(RPL_ENDOFMOTD), myname, nick);
}
/* send_oper_motd()
*
* inputs - client to send motd to
* outputs - client is sent oper motd if exists
* side effects -
*/
void
cache::motd::send_oper(Client *source_p)
{
if (oper.contents.empty())
return;
sendto_one(source_p, form_str(RPL_OMOTDSTART), me.name, source_p->name);
for (const auto &it : motd::oper.contents)
sendto_one(source_p, form_str(RPL_OMOTD), me.name, source_p->name, it.c_str());
sendto_one(source_p, form_str(RPL_ENDOFOMOTD), me.name, source_p->name);
}
/* ircd::cache::file::file()
*
* inputs - file to cache, files "shortname", flags to set
* outputs - none
* side effects - cachefile.contents is populated with the lines from the file
*/
file::file(const char *const &filename,
const char *const &shortname,
const int &flags)
:filename(filename)
,shortname(shortname)
,stream(filename)
,flags(flags)
,contents([this]
{
std::vector<std::string> contents;
while (stream.good())
{
char line[BUFSIZE], *p;
stream.getline(line, sizeof(line));
if ((p = strpbrk(line, "\r\n")) != nullptr)
*p = '\0';
char untabline[BUFSIZE];
untabify(untabline, line, sizeof(untabline));
contents.emplace_back(untabline);
}
stream.close();
return contents;
}())
{
}
file &file::operator=(file &&other)
noexcept
{
filename = std::move(other.filename);
shortname = std::move(other.shortname);
flags = std::move(other.flags);
contents = std::move(other.contents);
return *this;
}
uint
cache::flags(const file &file)
{
return file.flags;
}
const std::string &
cache::name(const file &file)
{
return file.shortname;
}
const std::vector<std::string> &
cache::contents(const file &file)
{
return file.contents;
}
/*
@ -93,195 +314,3 @@ untabify(char *dest, const char *src, size_t destlen)
*d = '\0';
return x;
}
/* cachefile::cache()
*
* inputs - file to cache, files "shortname", flags to set
* outputs - none
* side effects - cachefile.contents is populated with the lines from the file
*/
void
cachefile::cache(const char *filename, const char *shortname, int flags_)
{
FILE *in;
char line[BUFSIZE];
char *p;
if((in = fopen(filename, "r")) == NULL)
return;
contents.clear();
name = shortname;
flags = flags_;
/* cache the file... */
while(fgets(line, sizeof(line), in) != NULL)
{
char untabline[BUFSIZE];
if((p = strpbrk(line, "\r\n")) != NULL)
*p = '\0';
untabify(untabline, line, sizeof(untabline));
contents.push_back(untabline);
}
fclose(in);
}
/* load_help()
*
* inputs -
* outputs -
* side effects - old help cache deleted
* - contents of help directories are loaded.
*/
void
load_help(void)
{
DIR *helpfile_dir = NULL;
struct dirent *ldirent= NULL;
char filename[PATH_MAX];
#if defined(S_ISLNK) && defined(HAVE_LSTAT)
struct stat sb;
#endif
void *elem;
help_dict_oper.clear();
help_dict_user.clear();
helpfile_dir = opendir(fs::paths[IRCD_PATH_OPERHELP]);
if(helpfile_dir == NULL)
return;
while((ldirent = readdir(helpfile_dir)) != NULL)
{
if(ldirent->d_name[0] == '.')
continue;
snprintf(filename, sizeof(filename), "%s%c%s", fs::paths[IRCD_PATH_OPERHELP], RB_PATH_SEPARATOR, ldirent->d_name);
help_dict_oper[ldirent->d_name] = std::make_shared<cachefile>(filename, ldirent->d_name, HELP_OPER);
}
closedir(helpfile_dir);
helpfile_dir = opendir(fs::paths[IRCD_PATH_USERHELP]);
if(helpfile_dir == NULL)
return;
while((ldirent = readdir(helpfile_dir)) != NULL)
{
if(ldirent->d_name[0] == '.')
continue;
snprintf(filename, sizeof(filename), "%s%c%s", fs::paths[IRCD_PATH_USERHELP], RB_PATH_SEPARATOR, ldirent->d_name);
#if defined(S_ISLNK) && defined(HAVE_LSTAT)
if(lstat(filename, &sb) < 0)
continue;
/* ok, if its a symlink, we work on the presumption if an
* oper help exists of that name, its a symlink to that --fl
*/
if(S_ISLNK(sb.st_mode))
{
std::shared_ptr<cachefile> cacheptr = help_dict_oper[ldirent->d_name];
if(cacheptr != NULL)
{
cacheptr->flags |= HELP_USER;
continue;
}
}
#endif
help_dict_user[ldirent->d_name] = std::make_shared<cachefile>(filename, ldirent->d_name, HELP_USER);
}
closedir(helpfile_dir);
}
/* send_user_motd()
*
* inputs - client to send motd to
* outputs - client is sent motd if exists, else ERR_NOMOTD
* side effects -
*/
void
send_user_motd(struct Client *source_p)
{
rb_dlink_node *ptr;
const char *myname = get_id(&me, source_p);
const char *nick = get_id(source_p, source_p);
if (user_motd.contents.size() == 0)
{
sendto_one(source_p, form_str(ERR_NOMOTD), myname, nick);
return;
}
sendto_one(source_p, form_str(RPL_MOTDSTART), myname, nick, me.name);
for (auto it = user_motd.contents.begin(); it != user_motd.contents.end(); it++)
{
sendto_one(source_p, form_str(RPL_MOTD), myname, nick, it->c_str());
}
sendto_one(source_p, form_str(RPL_ENDOFMOTD), myname, nick);
}
void
cache_user_motd(void)
{
struct stat sb;
struct tm *local_tm;
if(stat(fs::paths[IRCD_PATH_IRCD_MOTD], &sb) == 0)
{
local_tm = localtime(&sb.st_mtime);
if(local_tm != NULL)
{
snprintf(user_motd_changed, sizeof(user_motd_changed),
"%d/%d/%d %d:%d",
local_tm->tm_mday, local_tm->tm_mon + 1,
1900 + local_tm->tm_year, local_tm->tm_hour,
local_tm->tm_min);
}
}
user_motd.cache(fs::paths[IRCD_PATH_IRCD_MOTD], "ircd.motd", 0);
}
/* send_oper_motd()
*
* inputs - client to send motd to
* outputs - client is sent oper motd if exists
* side effects -
*/
void
send_oper_motd(struct Client *source_p)
{
struct cacheline *lineptr;
rb_dlink_node *ptr;
if (oper_motd.contents.size() == 0)
return;
sendto_one(source_p, form_str(RPL_OMOTDSTART),
me.name, source_p->name);
for (auto it = oper_motd.contents.begin(); it != oper_motd.contents.end(); it++)
{
sendto_one(source_p, form_str(RPL_OMOTD),
me.name, source_p->name, it->c_str());
}
sendto_one(source_p, form_str(RPL_ENDOFOMOTD),
me.name, source_p->name);
}
} // namespace ircd

View file

@ -303,7 +303,7 @@ check_rehash(void *unused)
{
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Got signal SIGUSR1, reloading ircd motd file");
cache_user_motd();
cache::motd::cache_user();
doremotd = false;
}
}
@ -674,7 +674,7 @@ charybdis_main(int argc, char * const argv[])
initclass();
whowas_init();
init_reject();
init_cache();
cache::init();
init_monitor();
chmode_init();
@ -759,7 +759,7 @@ charybdis_main(int argc, char * const argv[])
check_class();
write_pidfile(pidFileName);
load_help();
cache::help::load();
open_logfiles();
configure_authd();

View file

@ -1351,7 +1351,7 @@ user_welcome(struct Client *source_p)
if(ConfigFileEntry.short_motd)
{
sendto_one_notice(source_p, ":*** Notice -- motd was last changed at %s", user_motd_changed);
sendto_one_notice(source_p, ":*** Notice -- motd was last changed at %s", cache::motd::user_motd_changed);
sendto_one_notice(source_p, ":*** Notice -- Please read the motd if you haven't read it");
sendto_one(source_p, form_str(RPL_MOTDSTART),
@ -1363,7 +1363,7 @@ user_welcome(struct Client *source_p)
sendto_one(source_p, form_str(RPL_ENDOFMOTD), me.name, source_p->name);
}
else
send_user_motd(source_p);
cache::motd::send_user(source_p);
}
/* oper_up()
@ -1438,7 +1438,7 @@ oper_up(struct Client *source_p, struct oper_conf *oper_p)
sendto_one(source_p, form_str(RPL_YOUREOPER), me.name, source_p->name);
sendto_one_notice(source_p, ":*** Oper privilege set is %s", oper_p->privset->name);
sendto_one_notice(source_p, ":*** Oper privs are %s", oper_p->privset->privs);
send_oper_motd(source_p);
cache::motd::send_oper(source_p);
}
/*

View file

@ -64,7 +64,9 @@ DECLARE_MODULE_AV2(help, NULL, NULL, help_clist, NULL, NULL, NULL, NULL, help_de
static void
m_help(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
dohelp(source_p, HELP_USER, parc > 1 ? parv[1] : NULL);
using namespace ircd::cache::help;
dohelp(source_p, USER, parc > 1 ? parv[1] : NULL);
}
/*
@ -73,7 +75,9 @@ m_help(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
static void
mo_help(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
dohelp(source_p, HELP_OPER, parc > 1 ? parv[1] : NULL);
using namespace ircd::cache::help;
dohelp(source_p, OPER, parc > 1 ? parv[1] : NULL);
}
/*
@ -83,41 +87,57 @@ mo_help(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
static void
mo_uhelp(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
dohelp(source_p, HELP_USER, parc > 1 ? parv[1] : NULL);
using namespace ircd::cache::help;
dohelp(source_p, USER, parc > 1 ? parv[1] : NULL);
}
static void
dohelp(struct Client *source_p, int flags, const char *topic)
dohelp(Client *const source_p,
int type,
const char *topic)
try
{
static const char ntopic[] = "index";
std::shared_ptr<cachefile> hptr;
int linecnt = 0;
namespace help = cache::help;
if(EmptyString(topic))
static const char *const ntopic("index");
if (EmptyString(topic))
topic = ntopic;
hptr = flags & HELP_OPER ? help_dict_oper[topic] : help_dict_user[topic];
if(hptr == NULL || !(hptr->flags & flags))
std::shared_ptr<cache::file> file
{
sendto_one(source_p, form_str(ERR_HELPNOTFOUND),
me.name, source_p->name, topic);
return;
}
type & help::OPER? help::oper.at(topic):
type & help::USER? help::user.at(topic):
nullptr
};
for (auto it = hptr->contents.begin(); it != hptr->contents.end(); it++, linecnt++)
{
if (!linecnt)
{
sendto_one(source_p, form_str(RPL_HELPSTART),
me.name, source_p->name, topic, it->c_str());
continue;
}
if (!file || !(flags(*file) & type))
throw std::out_of_range(ntopic);
auto it(begin(contents(*file)));
if (it != end(contents(*file)))
sendto_one(source_p, form_str(RPL_HELPSTART),
me.name,
source_p->name,
topic,
it->c_str());
for (++it; it != end(contents(*file)); ++it)
sendto_one(source_p, form_str(RPL_HELPTXT),
me.name, source_p->name, topic, it->c_str());
}
me.name,
source_p->name,
topic,
it->c_str());
sendto_one(source_p, form_str(RPL_ENDOFHELP),
me.name, source_p->name, topic);
me.name,
source_p->name,
topic);
}
catch(const std::out_of_range &e)
{
sendto_one(source_p, form_str(ERR_HELPNOTFOUND),
me.name,
source_p->name,
topic?: e.what());
}

View file

@ -85,7 +85,7 @@ m_motd(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
return;
motd_spy(source_p);
send_user_motd(source_p);
cache::motd::send_user(source_p);
}
/*
@ -99,7 +99,7 @@ mo_motd(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
return;
motd_spy(source_p);
send_user_motd(source_p);
cache::motd::send_user(source_p);
}
/* motd_spy()

View file

@ -73,7 +73,7 @@ m_oper(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
if(IsOper(source_p))
{
sendto_one(source_p, form_str(RPL_YOUREOPER), me.name, source_p->name);
send_oper_motd(source_p);
cache::motd::send_oper(source_p);
return;
}

View file

@ -105,7 +105,7 @@ rehash_motd(struct Client *source_p)
if (!MyConnect(source_p))
remote_rehash_oper_p = source_p;
cache_user_motd();
cache::motd::cache_user();
}
static void
@ -117,7 +117,7 @@ rehash_omotd(struct Client *source_p)
if (!MyConnect(source_p))
remote_rehash_oper_p = source_p;
oper_motd.cache(fs::paths[IRCD_PATH_IRCD_OMOTD], "opers.motd", 0);
cache::motd::cache_oper();
}
static void
@ -258,7 +258,7 @@ rehash_help(struct Client *source_p)
get_oper_name(source_p));
if (!MyConnect(source_p))
remote_rehash_oper_p = source_p;
load_help();
cache::help::load();
}
static void