From b44d5859e9dbca964d833742b08dbd3ecde318e1 Mon Sep 17 00:00:00 2001 From: Michael Poole Date: Mon, 10 May 2004 03:08:16 +0000 Subject: [PATCH] 2004-05-09 Michael Poole Forward port of Paul "Zoot" Chang's pseudo-command.patch and pseudo-support.patch. * doc/example.conf: Illustrate how to use the feature. * include/handlers.h (m_pseudo): Declare new handler function. * include/ircd_features.h (HIS_STATS_R): Add a feature to control user visibility of the pseudo-commands. * include/msg.h: Add flag and field for the extra information used to select a pseudo-command's target. * include/numeric.h (RPL_STATSRLINE, ERR_SERVICESDOWN): Add definitions. * include/parse.h (register_mapping, unregister_mapping): Declare. * include/s_conf.h (struct nick_host, struct s_map, GlobalServiceMapList): Define. * ircd/Makefile.in: Add m_pseudo.c to IRCD_SRC. Add generated files to "make depend" dependency list. Update dependencies. * ircd/ircd_features.c (HIS_STATS_R): Define feature type and default value. * ircd/ircd_lexer.l (pseudo, prepend): Recognize new tokens. * ircd/ircd_parser.y: Support "Pseudo" configuration blocks. * ircd/parse.c (msgtab): Add initializer for field "extra" to all commands. (msg_tree_insert, msg_tree_remove, register_mapping, unregister_mapping): New functions. (parse_client): Implement MFLG_EXTRA extra argument passing. * ircd/s_conf.c (GlobalServiceMapList): New variable. * ircd/s_err.c (RPL_STATRLINE, ERR_SERVICESDOWN): Add format strings for new numeric responses. * ircd/s_stats.c (stats_mapping): New function. (statsinfo): Add entry for /stats R and make old /stats r entry case-sensitive. git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@1037 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- ChangeLog | 48 ++++++++ doc/example.conf | 16 +++ include/handlers.h | 1 + include/ircd_features.h | 1 + include/msg.h | 3 + include/numeric.h | 3 +- include/parse.h | 4 + include/s_conf.h | 19 ++- ircd/Makefile.in | 39 +++--- ircd/ircd_features.c | 1 + ircd/ircd_lexer.l | 2 + ircd/ircd_parser.y | 65 +++++++++- ircd/parse.c | 257 ++++++++++++++++++++++++++++------------ ircd/s_conf.c | 1 + ircd/s_err.c | 4 +- ircd/s_stats.c | 24 +++- 16 files changed, 388 insertions(+), 100 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2495f24..680ce49 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,51 @@ +2004-05-09 Michael Poole + + Forward port of Paul "Zoot" Chang's pseudo-command.patch and + pseudo-support.patch. + + * doc/example.conf: Illustrate how to use the feature. + + * include/handlers.h (m_pseudo): Declare new handler function. + + * include/ircd_features.h (HIS_STATS_R): Add a feature to control + user visibility of the pseudo-commands. + + * include/msg.h: Add flag and field for the extra information used + to select a pseudo-command's target. + + * include/numeric.h (RPL_STATSRLINE, ERR_SERVICESDOWN): Add + definitions. + + * include/parse.h (register_mapping, unregister_mapping): Declare. + + * include/s_conf.h (struct nick_host, struct s_map, + GlobalServiceMapList): Define. + + * ircd/Makefile.in: Add m_pseudo.c to IRCD_SRC. Add generated + files to "make depend" dependency list. Update dependencies. + + * ircd/ircd_features.c (HIS_STATS_R): Define feature type and + default value. + + * ircd/ircd_lexer.l (pseudo, prepend): Recognize new tokens. + + * ircd/ircd_parser.y: Support "Pseudo" configuration blocks. + + * ircd/parse.c (msgtab): Add initializer for field "extra" to all + commands. + (msg_tree_insert, msg_tree_remove, register_mapping, + unregister_mapping): New functions. + (parse_client): Implement MFLG_EXTRA extra argument passing. + + * ircd/s_conf.c (GlobalServiceMapList): New variable. + + * ircd/s_err.c (RPL_STATRLINE, ERR_SERVICESDOWN): Add format + strings for new numeric responses. + + * ircd/s_stats.c (stats_mapping): New function. + (statsinfo): Add entry for /stats R and make old /stats r entry + case-sensitive. + 2004-05-09 Michael Poole * ircd/ircd_parser.y (parse_error): Convert to being a wrapper for diff --git a/doc/example.conf b/doc/example.conf index 8212254..904fd0e 100644 --- a/doc/example.conf +++ b/doc/example.conf @@ -664,6 +664,22 @@ Port { port = 7000; }; +# This is a server-implemented alias to send a message to a service. +# The string after Pseudo is the command name; the name entry inside +# is the service name, used for error messages. More than one nick +# entry can be provided; the last one listed has highest priority. +Pseudo "CHANSERV" { + name = "X"; + nick = "X@channels.undernet.org"; +}; + +# You can also prepend text before the user's message. +Pseudo "LOGIN" { + name = "X"; + prepend = "LOGIN "; + nick = "X@channels.undernet.org"; +}; + # [features] # IRC servers have a large number of options and features. Most of these # are set at compile time through the use of #define's--see "make config" diff --git a/include/handlers.h b/include/handlers.h index bbd483e..ca72913 100644 --- a/include/handlers.h +++ b/include/handlers.h @@ -118,6 +118,7 @@ extern int m_pong(struct Client*, struct Client*, int, char*[]); extern int m_private(struct Client*, struct Client*, int, char*[]); extern int m_privmsg(struct Client*, struct Client*, int, char*[]); extern int m_proto(struct Client*, struct Client*, int, char*[]); +extern int m_pseudo(struct Client*, struct Client*, int, char*[]); extern int m_quit(struct Client*, struct Client*, int, char*[]); extern int m_registered(struct Client*, struct Client*, int, char*[]); extern int m_silence(struct Client*, struct Client*, int, char*[]); diff --git a/include/ircd_features.h b/include/ircd_features.h index d9d3f06..e480b5b 100644 --- a/include/ircd_features.h +++ b/include/ircd_features.h @@ -148,6 +148,7 @@ enum Feature { FEAT_HIS_STATS_o, FEAT_HIS_STATS_p, FEAT_HIS_STATS_q, + FEAT_HIS_STATS_R, FEAT_HIS_STATS_r, FEAT_HIS_STATS_d, FEAT_HIS_STATS_e, diff --git a/include/msg.h b/include/msg.h index 9087926..207b0fb 100644 --- a/include/msg.h +++ b/include/msg.h @@ -362,6 +362,8 @@ struct Client; * clients. */ #define MFLG_IGNORE 0x04 /* silently ignore command from * unregistered clients */ +#define MFLG_EXTRA 0x08 /* Handler requests that mptr->extra + * be passed in parv[1] */ /* * Structures @@ -375,6 +377,7 @@ struct Message { to be used only on the average of once per 2 seconds -SRB */ unsigned int bytes; /* bytes received for this message */ + void *extra; /* extra pointer to be passed in parv[1] */ /* * cptr = Connected client ptr * sptr = Source client ptr diff --git a/include/numeric.h b/include/numeric.h index 72c5b51..05f62f5 100644 --- a/include/numeric.h +++ b/include/numeric.h @@ -172,6 +172,7 @@ extern const struct Numeric* get_error_numeric(int err); /* RPL_END_NOTIFY 274 aircd */ /* RPL_STATSDELTA 274 IRCnet extension */ #define RPL_STATSDLINE 275 /* Undernet extension */ +#define RPL_STATSRLINE 276 /* Undernet extension */ #define RPL_GLIST 280 /* Undernet extension */ #define RPL_ENDOFGLIST 281 /* Undernet extension */ @@ -351,7 +352,7 @@ extern const struct Numeric* get_error_numeric(int err); #define ERR_NICKTOOFAST 438 /* Undernet extension */ /* ERR_DEAD 438 IRCnet reserved for later use */ #define ERR_TARGETTOOFAST 439 /* Undernet extension */ -/* ERR_SERVICESDOWN 440 Dalnet,unreal */ +#define ERR_SERVICESDOWN 440 /* Dalnet,unreal,Undernet */ #define ERR_USERNOTINCHANNEL 441 #define ERR_NOTONCHANNEL 442 #define ERR_USERONCHANNEL 443 diff --git a/include/parse.h b/include/parse.h index 888d6de..75e3b0c 100644 --- a/include/parse.h +++ b/include/parse.h @@ -7,6 +7,7 @@ #define INCLUDED_parse_h struct Client; +struct s_map; /* * Prototypes @@ -16,4 +17,7 @@ extern int parse_client(struct Client *cptr, char *buffer, char *bufend); extern int parse_server(struct Client *cptr, char *buffer, char *bufend); extern void initmsgtree(void); +extern int register_mapping(struct s_map *map); +extern int unregister_mapping(struct s_map *map); + #endif /* INCLUDED_parse_h */ diff --git a/include/s_conf.h b/include/s_conf.h index 8823ce7..ff9a007 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -22,6 +22,7 @@ struct Client; struct SLink; struct TRecord; +struct Message; /* @@ -160,6 +161,21 @@ enum AuthorizationCheckResult { ACR_BAD_SOCKET }; +struct nick_host { + struct nick_host *next; + int nicklen; /* offset of @ part of server string */ + char nick[1]; /* start of nick@server string */ +}; + +struct s_map { + struct s_map *next; + struct Message *msg; + char *name; + char *command; + char *prepend; + struct nick_host *services; +}; + /* * GLOBALS @@ -170,7 +186,8 @@ extern struct tm motd_tm; extern struct MotdItem* motd; extern struct MotdItem* rmotd; extern struct TRecord* tdata; -extern struct qline* GlobalQuarantineList; +extern struct s_map* GlobalServiceMapList; +extern struct qline* GlobalQuarantineList; /* * Proto types diff --git a/ircd/Makefile.in b/ircd/Makefile.in index d10c9aa..713c7dc 100644 --- a/ircd/Makefile.in +++ b/ircd/Makefile.in @@ -153,6 +153,7 @@ IRCD_SRC = \ m_privmsg.c \ m_privs.c \ m_proto.c \ + m_pseudo.c \ m_quit.c \ m_rehash.c \ m_reset.c \ @@ -325,7 +326,7 @@ maintainer-clean: distclean # If I read this right, this will only work with gcc. Still, how many admins # are going to be doing "make depend"? -depend: +depend: ${DEP_SRC} chattr.tab.c @cd ${srcdir}; \ if [ -f Makefile.in.bak ]; then \ echo "make depend: First remove ircd/Makefile.in.bak"; \ @@ -354,7 +355,6 @@ depend: # @cd ../config; ${MAKE} config.h # DO NOT DELETE THIS LINE -- make depend depends on it. - IPcheck.o: IPcheck.c ../config.h ../include/IPcheck.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ @@ -692,7 +692,7 @@ m_kick.o: m_kick.c ../config.h ../include/channel.h \ ../include/hash.h ../include/ircd.h ../include/struct.h \ ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/send.h + ../include/numnicks.h ../include/send.h ../include/ircd_features.h m_kill.o: m_kill.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ @@ -786,7 +786,8 @@ m_opmode.o: m_opmode.c ../config.h ../include/client.h \ ../include/hash.h ../include/ircd.h ../include/struct.h \ ../include/ircd_features.h ../include/ircd_reply.h \ ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/send.h + ../include/numeric.h ../include/numnicks.h ../include/send.h \ + ../include/s_conf.h m_part.o: m_part.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \ ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ @@ -833,6 +834,14 @@ m_proto.o: m_proto.c ../config.h ../include/client.h \ ../include/numeric.h ../include/numnicks.h ../include/s_debug.h \ ../include/s_misc.h ../include/send.h ../include/supported.h \ ../include/channel.h ../include/version.h +m_pseudo.o: m_pseudo.c ../config.h ../include/client.h \ + ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ + ../include/ircd_relay.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h \ + ../include/ircd_snprintf.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/s_conf.h ../include/s_user.h m_quit.o: m_quit.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \ ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ @@ -1108,17 +1117,17 @@ s_bsd.o: s_bsd.c ../config.h ../include/s_bsd.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/IPcheck.h \ ../include/channel.h ../include/class.h ../include/hash.h \ - ../include/ircd_log.h ../include/ircd_features.h \ - ../include/ircd_osdep.h ../include/ircd_reply.h \ - ../include/ircd_snprintf.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/ircd.h ../include/struct.h \ - ../include/list.h ../include/listener.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/packet.h \ - ../include/parse.h ../include/querycmds.h ../include/res.h \ - ../include/s_auth.h ../include/s_conf.h ../include/s_debug.h \ - ../include/s_misc.h ../include/s_user.h ../include/send.h \ - ../include/support.h ../include/sys.h ../include/uping.h \ - ../include/version.h + ../include/ircd_alloc.h ../include/ircd_log.h \ + ../include/ircd_features.h ../include/ircd_osdep.h \ + ../include/ircd_reply.h ../include/ircd_snprintf.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/ircd.h \ + ../include/struct.h ../include/list.h ../include/listener.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/packet.h ../include/parse.h ../include/querycmds.h \ + ../include/res.h ../include/s_auth.h ../include/s_conf.h \ + ../include/s_debug.h ../include/s_misc.h ../include/s_user.h \ + ../include/send.h ../include/support.h ../include/sys.h \ + ../include/uping.h ../include/version.h s_conf.o: s_conf.c ../config.h ../include/s_conf.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/IPcheck.h \ diff --git a/ircd/ircd_features.c b/ircd/ircd_features.c index c128e8b..ff5abae 100644 --- a/ircd/ircd_features.c +++ b/ircd/ircd_features.c @@ -354,6 +354,7 @@ static struct FeatureDesc { F_B(HIS_STATS_o, 0, 1, 0), F_B(HIS_STATS_p, 0, 1, 0), F_B(HIS_STATS_q, 0, 1, 0), + F_B(HIS_STATS_R, 0, 1, 0), F_B(HIS_STATS_r, 0, 1, 0), F_B(HIS_STATS_d, 0, 1, 0), F_B(HIS_STATS_e, 0, 1, 0), diff --git a/ircd/ircd_lexer.l b/ircd/ircd_lexer.l index 35ecc04..774ed3d 100644 --- a/ircd/ircd_lexer.l +++ b/ircd/ircd_lexer.l @@ -149,5 +149,7 @@ unlimited_who_queries return TPRIV_UNLIMIT_QUERY; oper_status_display return TPRIV_DISPLAY; see_other_opers return TPRIV_SEE_OPERS; wide_glines return TPRIV_WIDE_GLINE; +pseudo return PSEUDO; +prepend return PREPEND; \n lineno++; . return yytext[0]; diff --git a/ircd/ircd_parser.y b/ircd/ircd_parser.y index f545c00..c79272f 100644 --- a/ircd/ircd_parser.y +++ b/ircd/ircd_parser.y @@ -63,7 +63,8 @@ extern struct DenyConf* denyConfList; extern struct CRuleConf* cruleConfList; extern struct ServerConf* serverConfList; - extern struct qline *GlobalQuarantineList; + extern struct s_map* GlobalServiceMapList; + extern struct qline* GlobalQuarantineList; int yylex(void); @@ -77,6 +78,7 @@ struct DenyConf *dconf; struct ServerConf *sconf; struct qline *qconf = NULL; + struct s_map *smap; static void parse_error(char *pattern,...) { static char error_buffer[1024]; @@ -150,6 +152,8 @@ static void parse_error(char *pattern,...) { %token IP %token FEATURES %token QUARANTINE +%token PSEUDO +%token PREPEND /* and now a lot of priviledges... */ %token TPRIV_CHAN_LIMIT TPRIV_MODE_LCHAN TPRIV_DEOP_LCHAN TPRIV_WALK_LCHAN %token TPRIV_KILL TPRIV_LOCAL_KILL TPRIV_REHASH TPRIV_RESTART TPRIV_DIE @@ -176,7 +180,7 @@ blocks: blocks block | block; block: adminblock | generalblock | classblock | connectblock | serverblock | operblock | portblock | jupeblock | clientblock | killblock | cruleblock | motdblock | featuresblock | quarantineblock | - error; + pseudoblock | error; /* The timespec, sizespec and expr was ripped straight from * ircd-hybrid-7. */ @@ -922,3 +926,60 @@ quarantineitems: CHANNEL NAME '=' QSTRING ';' { DupString(qconf->reason, yylval.text); }; + +pseudoblock: PSEUDO QSTRING '{' +{ + smap = MyCalloc(1, sizeof(struct s_map)); + DupString(smap->command, $2); +} +pseudoitems '}' ';' +{ + if (!smap->name || !smap->services) + { + log_write(LS_CONFIG, L_ERROR, 0, "pseudo commands need a service name and list of target nicks."); + return 0; + } + if (register_mapping(smap)) + { + smap->next = GlobalServiceMapList; + GlobalServiceMapList = smap; + } + else + { + struct nick_host *nh, *next; + for (nh = smap->services; nh; nh = next) + { + next = nh->next; + MyFree(nh); + } + MyFree(smap->name); + MyFree(smap->command); + MyFree(smap->prepend); + MyFree(smap); + } + smap = NULL; +}; + +pseudoitems: pseudoitem pseudoitems | pseudoitem; +pseudoitem: pseudoname | pseudoprepend | pseudonick | error; +pseudoname: NAME '=' QSTRING ';' +{ + DupString(smap->name, yylval.text); +}; +pseudoprepend: PREPEND '=' QSTRING ';' +{ + DupString(smap->prepend, yylval.text); +}; +pseudonick: NICK '=' QSTRING ';' +{ + char *sep = strchr(yylval.text, '@'); + + if (sep != NULL) { + size_t slen = strlen(yylval.text); + struct nick_host *nh = MyMalloc(sizeof(*nh) + slen); + memcpy(nh->nick, yylval.text, slen + 1); + nh->nicklen = sep - yylval.text; + nh->next = smap->services; + smap->services = nh; + } +}; diff --git a/ircd/parse.c b/ircd/parse.c index 59976ee..6add537 100644 --- a/ircd/parse.c +++ b/ircd/parse.c @@ -101,518 +101,518 @@ struct Message msgtab[] = { { MSG_PRIVATE, TOK_PRIVATE, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_privmsg, ms_privmsg, mo_privmsg, m_ignore } }, { MSG_NICK, TOK_NICK, - 0, MAXPARA, MFLG_SLOW | MFLG_UNREG, 0, + 0, MAXPARA, MFLG_SLOW | MFLG_UNREG, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_nick, m_nick, ms_nick, m_nick, m_ignore } }, { MSG_NOTICE, TOK_NOTICE, - 0, MAXPARA, MFLG_SLOW | MFLG_IGNORE, 0, + 0, MAXPARA, MFLG_SLOW | MFLG_IGNORE, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_ignore, m_notice, ms_notice, mo_notice, m_ignore } }, { MSG_WALLCHOPS, TOK_WALLCHOPS, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_wallchops, ms_wallchops, m_wallchops, m_ignore } }, { MSG_WALLVOICES, TOK_WALLVOICES, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_wallvoices, ms_wallvoices, m_wallvoices, m_ignore } }, { MSG_CPRIVMSG, TOK_CPRIVMSG, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_cprivmsg, m_ignore, m_cprivmsg, m_ignore } }, { MSG_CNOTICE, TOK_CNOTICE, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_cnotice, m_ignore, m_cnotice, m_ignore } }, { MSG_JOIN, TOK_JOIN, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_join, ms_join, m_join, m_ignore } }, { MSG_MODE, TOK_MODE, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_mode, ms_mode, m_mode, m_ignore } }, { MSG_BURST, TOK_BURST, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_ignore, m_ignore, ms_burst, m_ignore, m_ignore } }, { MSG_CREATE, TOK_CREATE, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_ignore, m_ignore, ms_create, m_ignore, m_ignore } }, { MSG_DESTRUCT, TOK_DESTRUCT, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_ignore, m_ignore, ms_destruct, m_ignore, m_ignore } }, { MSG_QUIT, TOK_QUIT, - 0, MAXPARA, MFLG_SLOW | MFLG_UNREG, 0, + 0, MAXPARA, MFLG_SLOW | MFLG_UNREG, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_quit, m_quit, ms_quit, m_quit, m_ignore } }, { MSG_PART, TOK_PART, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_part, ms_part, m_part, m_ignore } }, { MSG_TOPIC, TOK_TOPIC, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_topic, ms_topic, m_topic, m_ignore } }, { MSG_INVITE, TOK_INVITE, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_invite, ms_invite, m_invite, m_ignore } }, { MSG_KICK, TOK_KICK, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_kick, ms_kick, m_kick, m_ignore } }, { MSG_WALLOPS, TOK_WALLOPS, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_not_oper, ms_wallops, mo_wallops, m_ignore } }, { MSG_WALLUSERS, TOK_WALLUSERS, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_not_oper, ms_wallusers, mo_wallusers, m_ignore } }, { MSG_DESYNCH, TOK_DESYNCH, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_ignore, m_ignore, ms_desynch, m_ignore, m_ignore } }, { MSG_PING, TOK_PING, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_ping, ms_ping, mo_ping, m_ignore } }, { MSG_PONG, TOK_PONG, - 0, MAXPARA, MFLG_SLOW | MFLG_UNREG, 0, + 0, MAXPARA, MFLG_SLOW | MFLG_UNREG, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { mr_pong, m_pong, ms_pong, m_pong, m_ignore } }, { MSG_ERROR, TOK_ERROR, - 0, MAXPARA, MFLG_SLOW | MFLG_UNREG, 0, + 0, MAXPARA, MFLG_SLOW | MFLG_UNREG, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { mr_error, m_ignore, ms_error, m_ignore, m_ignore } }, { MSG_KILL, TOK_KILL, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_not_oper, ms_kill, mo_kill, m_ignore } }, { MSG_USER, TOK_USER, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_user, m_registered, m_ignore, m_registered, m_ignore } }, { MSG_AWAY, TOK_AWAY, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_away, ms_away, m_away, m_ignore } }, { MSG_ISON, TOK_ISON, - 0, 1, MFLG_SLOW, 0, + 0, 1, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_ison, m_ignore, m_ison, m_ignore } }, { MSG_SERVER, TOK_SERVER, - 0, MAXPARA, MFLG_SLOW | MFLG_UNREG, 0, + 0, MAXPARA, MFLG_SLOW | MFLG_UNREG, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { mr_server, m_registered, ms_server, m_registered, m_ignore } }, { MSG_SQUIT, TOK_SQUIT, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_not_oper, ms_squit, mo_squit, m_ignore } }, { MSG_WHOIS, TOK_WHOIS, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_whois, ms_whois, m_whois, m_ignore } }, { MSG_WHO, TOK_WHO, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_who, m_ignore, m_who, m_ignore } }, { MSG_WHOWAS, TOK_WHOWAS, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_whowas, m_whowas, m_whowas, m_ignore } }, { MSG_LIST, TOK_LIST, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_list, m_ignore, m_list, m_ignore } }, { MSG_NAMES, TOK_NAMES, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_names, ms_names, m_names, m_ignore } }, { MSG_USERHOST, TOK_USERHOST, - 0, 1, MFLG_SLOW, 0, + 0, 1, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_userhost, m_ignore, m_userhost, m_ignore } }, { MSG_USERIP, TOK_USERIP, - 0, 1, MFLG_SLOW, 0, + 0, 1, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_userip, m_ignore, m_userip, m_ignore } }, { MSG_TRACE, TOK_TRACE, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_trace, ms_trace, mo_trace, m_ignore } }, { MSG_PASS, TOK_PASS, - 0, MAXPARA, MFLG_SLOW | MFLG_UNREG, 0, + 0, MAXPARA, MFLG_SLOW | MFLG_UNREG, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { mr_pass, m_registered, m_ignore, m_registered, m_ignore } }, { MSG_LUSERS, TOK_LUSERS, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_lusers, ms_lusers, m_lusers, m_ignore } }, { MSG_TIME, TOK_TIME, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_time, m_time, m_time, m_ignore } }, { MSG_SETTIME, TOK_SETTIME, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_ignore, ms_settime, mo_settime, m_ignore } }, { MSG_RPING, TOK_RPING, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_not_oper, ms_rping, mo_rping, m_ignore } }, { MSG_RPONG, TOK_RPONG, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_ignore, ms_rpong, m_ignore, m_ignore } }, { MSG_OPER, TOK_OPER, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_oper, ms_oper, mo_oper, m_ignore } }, { MSG_CONNECT, TOK_CONNECT, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_not_oper, ms_connect, mo_connect, m_ignore } }, { MSG_MAP, TOK_MAP, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_map, m_ignore, m_map, m_ignore } }, { MSG_VERSION, TOK_VERSION, - 0, MAXPARA, MFLG_SLOW | MFLG_UNREG, 0, + 0, MAXPARA, MFLG_SLOW | MFLG_UNREG, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_version, m_version, ms_version, mo_version, m_ignore } }, { MSG_STATS, TOK_STATS, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_stats, m_stats, m_stats, m_ignore } }, { MSG_LINKS, TOK_LINKS, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_links, ms_links, m_links, m_ignore } }, { MSG_ADMIN, TOK_ADMIN, - 0, MAXPARA, MFLG_SLOW | MFLG_UNREG, 0, + 0, MAXPARA, MFLG_SLOW | MFLG_UNREG, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_admin, m_admin, ms_admin, mo_admin, m_ignore } }, { MSG_HELP, TOK_HELP, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_help, m_ignore, m_help, m_ignore } }, { MSG_INFO, TOK_INFO, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_info, ms_info, mo_info, m_ignore } }, { MSG_MOTD, TOK_MOTD, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_motd, m_motd, m_motd, m_ignore } }, { MSG_CLOSE, TOK_CLOSE, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_not_oper, m_ignore, mo_close, m_ignore } }, { MSG_SILENCE, TOK_SILENCE, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_silence, ms_silence, m_silence, m_ignore } }, { MSG_GLINE, TOK_GLINE, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_gline, ms_gline, mo_gline, m_ignore } }, { MSG_JUPE, TOK_JUPE, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_jupe, ms_jupe, mo_jupe, m_ignore } }, { MSG_OPMODE, TOK_OPMODE, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_not_oper, ms_opmode, mo_opmode, m_ignore } }, { MSG_CLEARMODE, TOK_CLEARMODE, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_not_oper, ms_clearmode, mo_clearmode, m_ignore } }, { MSG_UPING, TOK_UPING, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_not_oper, ms_uping, mo_uping, m_ignore } }, { MSG_END_OF_BURST, TOK_END_OF_BURST, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_ignore, m_ignore, ms_end_of_burst, m_ignore, m_ignore } }, { MSG_END_OF_BURST_ACK, TOK_END_OF_BURST_ACK, - 0, MAXPARA, 1, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_ignore, m_ignore, ms_end_of_burst_ack, m_ignore, m_ignore } }, { MSG_HASH, TOK_HASH, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_hash, m_hash, m_hash, m_ignore } }, { MSG_DNS, TOK_DNS, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_dns, m_dns, m_dns, m_ignore } }, { MSG_REHASH, TOK_REHASH, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_not_oper, m_ignore, mo_rehash, m_ignore } }, { MSG_RESTART, TOK_RESTART, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_not_oper, m_ignore, mo_restart, m_ignore } }, { MSG_DIE, TOK_DIE, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_not_oper, m_ignore, mo_die, m_ignore } }, { MSG_PROTO, TOK_PROTO, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_proto, m_proto, m_proto, m_proto, m_ignore } }, { MSG_SET, TOK_SET, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_not_oper, m_ignore, mo_set, m_ignore } }, { MSG_RESET, TOK_RESET, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_not_oper, m_ignore, mo_reset, m_ignore } }, { MSG_GET, TOK_GET, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_not_oper, m_ignore, mo_get, m_ignore } }, { MSG_PRIVS, TOK_PRIVS, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_unregistered, m_not_oper, m_ignore, mo_privs, m_ignore } }, { MSG_ACCOUNT, TOK_ACCOUNT, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_ignore, m_ignore, ms_account, m_ignore, m_ignore } }, { MSG_ASLL, TOK_ASLL, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_ignore, m_not_oper, ms_asll, mo_asll, m_ignore } }, @@ -625,7 +625,7 @@ struct Message msgtab[] = { { MSG_POST, TOK_POST, - 0, MAXPARA, MFLG_SLOW, 0, + 0, MAXPARA, MFLG_SLOW, 0, NULL, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ { m_quit, m_ignore, m_ignore, m_ignore, m_ignore } }, @@ -748,6 +748,104 @@ msg_tree_parse(char *cmd, struct MessageTree *root) return NULL; } +/* Inserts a single entry into a message tree; must use this function + when inserting messages at runtime. */ +static void msg_tree_insert(struct MessageTree *mtree, int pfxlen, + char *key, struct Message *mptr) +{ + struct MessageTree *child; + int c; + + if (!key[pfxlen]) + { + mtree->msg = mptr; + return; + } + c = key[pfxlen]; + child = mtree->pointers[c & (MAXPTRLEN-1)]; + if(!child) + { + child = (struct MessageTree *)MyCalloc(1, sizeof(struct MessageTree)); + mtree->pointers[c & (MAXPTRLEN-1)] = child; + } + msg_tree_insert(child, pfxlen+1, key, mptr); +} + +/* Removes an entry from the message tree; suitable for use at runtime. */ +static struct MessageTree *msg_tree_remove(struct MessageTree *root, char *key) +{ + int c; + + if (*key) + { + struct MessageTree *child = root->pointers[*key & (MAXPTRLEN-1)]; + if (msg_tree_remove(child, key + 1)) + return root; + root->pointers[*key & (MAXPTRLEN-1)] = NULL; + } + else + { + root->msg = NULL; + } + for (c = 0; c < MAXPTRLEN; ++c) + { + if (root->pointers[c]) + return root; + } + MyFree(root); + return NULL; +} + +/* Registers a service mapping to the pseudocommand handler. */ +int register_mapping(struct s_map *map) +{ + struct Message *msg; + + if (msg_tree_parse(map->command, &msg_tree)) + return 0; + + msg = (struct Message *)MyMalloc(sizeof(struct Message)); + msg->cmd = map->command; + msg->tok = map->command; + msg->count = 0; + msg->parameters = 2; + msg->flags = MFLG_SLOW | MFLG_EXTRA; + msg->bytes = 0; + msg->extra = map; + + msg->handlers[UNREGISTERED_HANDLER] = m_ignore; + msg->handlers[CLIENT_HANDLER] = m_pseudo; + msg->handlers[SERVER_HANDLER] = m_ignore; + msg->handlers[OPER_HANDLER] = m_pseudo; + msg->handlers[SERVICE_HANDLER] = m_ignore; + + /* Service mappings are only applicable to clients; insert the + pseudocommand into the command tree only. */ + msg_tree_insert(&msg_tree, 0, msg->cmd, msg); + map->msg = msg; + + return 1; +} + +/* Removes a service mapping. */ +int unregister_mapping(struct s_map *map) +{ + if (!msg_tree_parse(map->command, &msg_tree)) + { + /* This simply should never happen. */ + assert(0); + return 0; + } + + msg_tree_remove(&msg_tree, map->msg->cmd); + + map->msg->extra = NULL; + MyFree(map->msg); + map->msg = NULL; + + return 1; +} + /* * parse a buffer. * @@ -839,7 +937,14 @@ parse_client(struct Client *cptr, char *buffer, char *bufend) /* Note initially true: s==NULL || *(s-1) == '\0' !! */ - i = 0; + if (mptr->flags & MFLG_EXTRA) { + /* This is a horrid kludge to avoid changing the command handler + * argument list. */ + para[1] = (char*)mptr->extra; + i = 1; + } else { + i = 0; + } if (s) { if (paramcount > MAXPARA) diff --git a/ircd/s_conf.c b/ircd/s_conf.c index 64839a1..7733c9f 100644 --- a/ircd/s_conf.c +++ b/ircd/s_conf.c @@ -71,6 +71,7 @@ struct ConfItem *GlobalConfList = 0; int GlobalConfCount = 0; +struct s_map *GlobalServiceMapList = 0; struct qline *GlobalQuarantineList = 0; void yyparse(void); diff --git a/ircd/s_err.c b/ircd/s_err.c index d20f623..0c88681 100644 --- a/ircd/s_err.c +++ b/ircd/s_err.c @@ -584,7 +584,7 @@ static Numeric replyTable[] = { /* 275 */ { RPL_STATSDLINE, "%c %s %s", "275" }, /* 276 */ - { 0 }, + { RPL_STATSRLINE, "%-9s %-9s %-10s %s", "276" }, /* 277 */ { 0 }, /* 278 */ @@ -912,7 +912,7 @@ static Numeric replyTable[] = { /* 439 */ { ERR_TARGETTOOFAST, "%s :Target change too fast. Please wait %d seconds.", "439" }, /* 440 */ - { 0 }, + { ERR_SERVICESDOWN, "%s :Services are currently unavailable.", "440" }, /* 441 */ { ERR_USERNOTINCHANNEL, "%s %s :They aren't on that channel", "441" }, /* 442 */ diff --git a/ircd/s_stats.c b/ircd/s_stats.c index 886abda..34eb34a 100644 --- a/ircd/s_stats.c +++ b/ircd/s_stats.c @@ -318,9 +318,24 @@ stats_quarantine(struct Client* to, struct StatDesc* sd, int stat, char* param) if (param && match(param, qline->chname)) /* narrow search */ continue; send_reply(to, RPL_STATSQLINE, qline->chname, qline->reason); - } - } + } +} +static void +stats_mapping(struct Client *to, struct StatDesc* sd, int stat, char* param) +{ + struct s_map *map; + + send_reply(to, RPL_STATSRLINE, "Command", "Name", "Prepend", "Target"); + for (map = GlobalServiceMapList; map; map = map->next) { + struct nick_host *nh; + for (nh = map->services; nh; nh = nh->next) { + send_reply(to, RPL_STATSRLINE, map->command, map->name, + (map->prepend ? map->prepend : "*"), nh->nick); + } + } +} + static void stats_uptime(struct Client* to, struct StatDesc* sd, int stat, char* param) { @@ -453,8 +468,11 @@ struct StatDesc statsinfo[] = { { 'q', (STAT_FLAG_OPERONLY | STAT_FLAG_VARPARAM), FEAT_HIS_STATS_q, stats_quarantine, 0, "Quarantined channels list." }, + { 'R', (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_R, + stats_mapping, 0, + "Service mappings." }, #ifdef DEBUGMODE - { 'r', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_r, + { 'r', (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_r, send_usage, 0, "System resource usage (Debug only)." }, #endif -- 2.20.1