* Improve length checking logic in ChanServ.names command.
* Fix service trigger registration so that database is used in
preference to srvx.conf and compiled-in defaults.
* Allow service hostnames to be configured in srvx.conf and through
"service add"; document this and show an example of setting the
service description.
* Fix an uninitialized value bug in OpServ.join.
* Make OpServ.addtrust accept a count of 0.
* Remove untranslated messages from languages/de/modcmd.help (so that
new "service add" help is inherited).
git-archimport-id: srvx@srvx.net--2004-srvx/srvx--devo--1.3--patch-47
# arch-tag: automatic-ChangeLog--srvx@srvx.net--2004-srvx/srvx--devo--1.3
#
+2004-04-09 20:08:58 GMT Michael Poole <mdpoole@troilus.org> patch-47
+
+ Summary:
+ Fix service triggers; allow service hostname configuration; fix glitches
+ Revision:
+ srvx--devo--1.3--patch-47
+
+ * Improve length checking logic in ChanServ.names command.
+
+ * Fix service trigger registration so that database is used in
+ preference to srvx.conf and compiled-in defaults.
+
+ * Allow service hostnames to be configured in srvx.conf and through
+ "service add"; document this and show an example of setting the
+ service description.
+
+ * Fix an uninitialized value bug in OpServ.join.
+
+ * Make OpServ.addtrust accept a count of 0.
+
+ * Remove untranslated messages from languages/de/modcmd.help (so that
+ new "service add" help is inherited).
+
+ modified files:
+ ChangeLog languages/de/modcmd.help src/chanserv.c src/global.c
+ src/mod-helpserv.c src/modcmd.c src/modcmd.h src/modcmd.help
+ src/nickserv.c src/opserv.c src/opserv.help
+ src/proto-bahamut.c src/proto-p10.c src/proto.h
+ srvx.conf.example
+
+
2004-04-09 01:57:12 GMT adam <akl@gamesurge.net> patch-46
Summary:
-"bind" ("/msg $S BIND <service> <bindname> <command> [additional args..]",
- "Binds (adds) a command to an existing service. $bbindname$b is the name of the new command for the service. $bcommand$b may be one of:",
- " CommandName To refer to a command on the same service.",
- " ServiceNick.CommandName To refer to a command bound on a different service.",
- " *ModuleName.CommandName To bind a command directly from a module (note the asterisk before the module name).",
- " *ModuleName.* To bind all commands from the named module.",
- "For simplicity, you cannot bind to a command that is itself an alias. Certain commands will not bound with the last form; you must bind them by name.",
- "(A command binding is very similar to an alias, but only pays the speed penalty for alias expansion when there are additional arguments in the binding.)",
- "$uSee also:$u unbind");
-"commands" "${index}";
"god" ("/msg $C GOD [on|off]",
"Aktiviert und deaktiviert Security Override.");
"help" ("/msg $S HELP [Befehl]",
"Zeigt die Hilfe des angegebenen Befehls an.",
"Alle Hilfedateien benutzen die gleiche Syntax. Optionale Argumente werden mit [] und benötigte Argumente mit <> angegeben.",
"Um zu sehen, welche Befehle du mit $S verwenden kannst, benutze /msg $S help commands. Um Hilfe für einen speziellen Befehl zu bekommen, benutze /msg $S help <command>.");
-"readhelp" ("/msg $S READHELP <module>",
- "Re-reads the module's help file from disk.",
- "$uSee Also:$u help");
-"unbind" ("/msg $S UNBIND <service> <command>",
- "Unbinds a command from a service, so that it is no longer accessible.",
- "Some commands (such as $bauth$b and $bbind$b) will not let you unbind their last binding -- for obvious reasons.",
- "$uSee Also:$u bind");
-"timecmd" ("/msg $S TIMECMD <command and args>",
- "Reports how long it takes to run the specified command.");
"command" ("/msg $S COMMAND <Befehl>",
"Zeigt die Einschränkungen, wer den Befehl wie verwenden darf.");
-"modcmd" ("/msg $S MODCMD <command> [<option> <newval> ...]",
- "Displays options for the specified command, or changes the options and values listed. The command name may be prefixed with $bServiceNick.$b to specify another service's command (for example, $N.AUTH to refer to the auth command).",
- "Supported options are:",
- " FLAGS Comma-separated, +/- prefixed list of flags to add or remove.",
- " CHANNEL_ACCESS Minimum ChanServ access.",
- " OPER_ACCESS Minimum OpServ access.",
- " ACCOUNT_FLAGS Account flags to require or deny (for example, +R-S)",
- "See the $bmodcmd flags$b help entry for a list of supported flags.");
-"modcmd flags" ("The following flags are supported for commands:",
- " ACCEPTCHAN Treat a normal channel name (if specified) as the context for the command",
- " ACCEPTPLUSCHAN Accept modeless channel names as well as normal channel names",
- " AUTHED Require that the user be authed to use the command",
- " CHANNEL Require that an existing channel be given as the context",
- " CHANUSER Require that the user have $C access to the context",
- " DISABLED Command is disabled",
- " HELPING Require that the user have security override enabled",
- " IGNORE_CSUSPEND Allow a +REGCHAN command to work even if the channel is suspended",
- " JOINABLE Require that the user have $C access to the channel, be in the channel, or be network staff to use the command",
- " KEEPBOUND Do not let the last instance of the command be removed",
- " LOGHOSTMASK Log the user's ident, hostname and IP (as well as nick and account name)",
- " NOLOG Do not log the command at all",
- " NETWORKHELPER Allow network helpers to use the command",
- " OPER Allow opers to use the command",
- " QUALIFIED Require $b/msg Service@$s$b addressing when using the command",
- " REGCHAN Require a registered channel to be give as the context",
- " SUPPORTHELPER Allow support helpers to use the command",
- " TOY Command is a toy (cannot be invoked on a channel from outside the channel)",
- "Note: If any of SUPPORTHELPER, NETWORKHELPER, OPER, any of the specified flags is considered sufficient. For example, NETWORKHELPER and OPER both specified means both network helpers and opers can use the command.");
-"joiner" ("/msg $S JOINER [subcmd ...]",
- "Magically looks up subcommands and redirects to them. Use the command by itself to see what subcommands are known.");
-"stats modules" ("/msg $S STATS MODULES [modulename]",
- "With no module name argument, shows a list of loaded modules and brief statistics for each.",
- "When a module name is given, shows commands exported by that module.",
- "$uSee Also:$u stats services, command, modcmd, bind");
-"stats services" ("/msg $S STATS SERVICES [botnick]",
- "With no bot nick argument, shows a list of the service bots using the unified command framework, and brief statistics for each.",
- "When a bot nick is given, shows commands bound to that service.",
- "$uSee Also:$u stats modules, command, modcmd, bind, unbind");
-"showcommands" ("/msg $S SHOWCOMMANDS [opserv-access] [channel-access]",
- "Shows commands which you can execute (with their required access levels). If you give a numeric $O access level or text $C access name, it further restricts output to only show commands which can be executed by users with that access.",
- "$uSee Also:$u command");
-"helpfiles" ("/msg $S HELPFILES <service> [module list]",
- "With only a service nick, shows the helpfiles used by that service.",
- "With a list of modules, sets the order that the service will look up non-command help entries.",
- "$uSee Also:$u bind, unbind");
-"service add" ("/msg $S SERVICE ADD <nick> <description>",
- "Creates a new service bot.",
- "$uSee Also:$u service rename, service trigger, service remove");
-"service rename" ("/msg $S SERVICE RENAME <oldnick> <newnick>",
- "Renames a service bot. Currently does not support the default services.",
- "$uSee Also:$u service add, service trigger, service remove");
-"service trigger" ("/msg $S SERVICE TRIGGER <nick> [remove|<trigger>]",
- "Sets or clears the trigger character that the named service uses to identify in-channel messages directed at it.",
- "To remove a trigger, use the word $bremove$b (or $bnone$b) as the argument. Otherwise, the first letter of the argument will be used as the new trigger.",
- "If no argument is given, shows the current trigger for the service.",
- "$uSee Also:$u service add, service rename, service remove");
-"service remove" ("/msg $S SERVICE REMOVE <nick> [<quit reason>]",
- "Destroys a service. If a default service is named, it will be recreated when srvx restarts.",
- "$uSee Also:$u service add, service rename, service trigger");
"version" ("/msg $S version",
"Sendet dir Informationen über die Software und das Copyright.");
targData = GetTrueChannelAccess(channel->channel_info, targ->handle_info);
if(!targData)
continue;
- if(pos + strlen(targ->nick) + strlen(targ->handle_info->handle) + 6 > sizeof(buf))
+ if(pos + strlen(targ->nick) + strlen(targ->handle_info->handle) + 8 > sizeof(buf))
{
buf[pos] = 0;
reply("CSMSG_CHANNEL_NAMES", channel->name, buf);
dict_set_free_data(note_types, chanserv_deref_note_type);
if(nick)
{
- chanserv = AddService(nick, "Channel Services");
- service_register(chanserv, '!');
+ chanserv = AddService(nick, "Channel Services", NULL);
+ service_register(chanserv)->trigger = '!';
reg_chanmsg_func('\001', chanserv, chanserv_ctcp_check);
}
saxdb_register("ChanServ", chanserv_saxdb_read, chanserv_saxdb_write);
if(nick)
{
- global = AddService(nick, "Global Services");
- global_service = service_register(global, 0);
+ global = AddService(nick, "Global Services", NULL);
+ global_service = service_register(global);
}
saxdb_register("Global", global_saxdb_read, global_saxdb_write);
reg_exit_func(global_db_cleanup);
* it's a harmless default */
hs = calloc(1, sizeof(struct helpserv_bot));
- if (!(hs->helpserv = AddService(nick, helpserv_conf.description))) {
+ if (!(hs->helpserv = AddService(nick, helpserv_conf.description, NULL))) {
free(hs);
return NULL;
}
}
struct service *
-service_register(struct userNode *bot, char trigger) {
+service_register(struct userNode *bot) {
struct service *service;
if ((service = dict_find(services, bot->nick, NULL)))
return service;
module_list_init(&service->modules);
service->commands = dict_new();
service->bot = bot;
- service->trigger = trigger;
dict_set_free_data(service->commands, free_service_command);
dict_insert(services, service->bot->nick, service);
reg_privmsg_func(bot, modcmd_privmsg);
- if (trigger)
- reg_chanmsg_func(trigger, bot, modcmd_chanmsg);
return service;
}
}
static MODCMD_FUNC(cmd_service_add) {
- const char *nick, *desc;
+ const char *nick, *hostname, *desc;
struct userNode *bot;
nick = argv[1];
reply("MCMSG_BAD_SERVICE_NICK", nick);
return 0;
}
- desc = unsplit_string(argv+2, argc-2, NULL);
+ hostname = argv[2];
+ desc = unsplit_string(argv+3, argc-3, NULL);
bot = GetUserH(nick);
if (bot && IsService(bot)) {
reply("MCMSG_ALREADY_SERVICE", bot->nick);
return 0;
}
- bot = AddService(nick, desc);
- service_register(bot, '\0');
+ bot = AddService(nick, desc, hostname);
+ service_register(bot);
reply("MCMSG_NEW_SERVICE", bot->nick);
return 1;
}
saxdb_write_string(ctx, "trigger", buff);
}
saxdb_write_string(ctx, "description", service->bot->info);
+ saxdb_write_string(ctx, "hostname", service->bot->hostname);
if (service->privileged)
saxdb_write_string(ctx, "privileged", "1");
saxdb_end_record(ctx);
for (it = dict_first(db); it; it = iter_next(it)) {
struct record_data *rd;
- struct userNode *bot;
- const char *nick, *desc;
- char trigger;
+ struct service *svc;
+ const char *nick, *desc, *hostname;
rd = iter_data(it);
if (rd->type != RECDB_OBJECT) {
}
nick = database_get_data(rd->d.object, "nick", RECDB_QSTRING);
if (!nick)
- nick = iter_key(it);
- if (service_find(nick))
continue;
- desc = database_get_data(rd->d.object, "trigger", RECDB_QSTRING);
- trigger = desc ? desc[0] : '\0';
+ svc = service_find(nick);
desc = database_get_data(rd->d.object, "description", RECDB_QSTRING);
- if (desc)
- {
- struct service *svc;
- bot = AddService(nick, desc);
- svc = service_register(bot, trigger);
+ hostname = database_get_data(rd->d.object, "hostname", RECDB_QSTRING);
+ if (desc) {
+ if (!svc)
+ svc = service_register(AddService(nick, desc, hostname));
+ else if (hostname)
+ strcpy(svc->bot->hostname, hostname);
+ desc = database_get_data(rd->d.object, "trigger", RECDB_QSTRING);
+ if (desc)
+ svc->trigger = desc[0];
desc = database_get_data(rd->d.object, "privileged", RECDB_QSTRING);
if (desc && (true_string(desc) || enabled_string(desc)))
svc->privileged = 1;
modcmd_register(modcmd_module, "stats services", cmd_stats_services, 1, 0, "flags", "+oper", NULL);
modcmd_register(modcmd_module, "showcommands", cmd_showcommands, 1, 0, "flags", "+acceptchan", NULL);
modcmd_register(modcmd_module, "helpfiles", cmd_helpfiles, 2, 0, "template", "bind", NULL);
- modcmd_register(modcmd_module, "service add", cmd_service_add, 3, 0, "flags", "+oper", NULL);
+ modcmd_register(modcmd_module, "service add", cmd_service_add, 4, 0, "flags", "+oper", NULL);
modcmd_register(modcmd_module, "service rename", cmd_service_rename, 3, 0, "flags", "+oper", NULL);
modcmd_register(modcmd_module, "service trigger", cmd_service_trigger, 2, 0, "flags", "+oper", NULL);
modcmd_register(modcmd_module, "service privileged", cmd_service_privileged, 2, 0, "flags", "+oper", NULL);
void
modcmd_finalize(void) {
+ dict_iterator_t it;
+
/* Check databases. */
saxdb_register("modcmd", modcmd_saxdb_read, modcmd_saxdb_write);
create_default_binds();
if (!saxdb_present)
import_aliases_db();
+ /* Register services for their triggers. */
+ for (it = dict_first(services); it; it = iter_next(it)) {
+ struct service *svc = iter_data(it);
+ if (svc->trigger)
+ reg_chanmsg_func(svc->trigger, svc->bot, modcmd_chanmsg);
+ }
+
/* Resolve command rule-templates. */
while (pending_templates) {
struct pending_template *ptempl = pending_templates;
struct module *module_find(const char *name);
/* Register a command-using service. */
-struct service *service_register(struct userNode *bot, char trigger);
+struct service *service_register(struct userNode *bot);
/* Find a service by name. */
struct service *service_find(const char *name);
/* Bind one command to a service. */
"With only a service nick, shows the helpfiles used by that service.",
"With a list of modules, sets the order that the service will look up non-command help entries.",
"$uSee Also:$u bind, unbind");
-"service add" ("/msg $S SERVICE ADD <nick> <description>",
+"service add" ("/msg $S SERVICE ADD <nick> <hostname> <description>",
"Creates a new service bot.",
"$uSee Also:$u service rename, service trigger, service remove");
"service rename" ("/msg $S SERVICE RENAME <oldnick> <newnick>",
userList_init(&curr_helpers);
if (nick) {
- nickserv = AddService(nick, "Nick Services");
- nickserv_service = service_register(nickserv, 0);
+ nickserv = AddService(nick, "Nick Services", NULL);
+ nickserv_service = service_register(nickserv);
}
saxdb_register("NickServ", nickserv_saxdb_read, nickserv_saxdb_write);
reg_exit_func(nickserv_db_cleanup);
return 0;
} else {
struct mod_chanmode change;
- change.modes_set = change.modes_clear = 0;
+ mod_chanmode_init(&change);
change.argc = 1;
change.args[0].mode = MODE_CHANOP;
change.args[0].member = AddChannelUser(bot, channel);
}
count = strtoul(argv[2], &tmp, 10);
- if (!count || *tmp != '\0') {
+ if (*tmp != '\0') {
reply("OSMSG_BAD_NUMBER", argv[2]);
return 0;
}
{
OS_LOG = log_register_type("OpServ", "file:opserv.log");
if (nick)
- opserv = AddService(nick, "Oper Services");
+ opserv = AddService(nick, "Oper Services", NULL);
conf_register_reload(opserv_conf_read);
memset(level_strings, 0, sizeof(level_strings));
opserv_db_init();
saxdb_register("OpServ", opserv_saxdb_read, opserv_saxdb_write);
if (nick)
- service_register(opserv, '?');
+ service_register(opserv)->trigger = '?';
reg_exit_func(opserv_db_cleanup);
message_register_table(msgtab);
"ADDALERT" ("/msg $O ADDALERT <name> <reaction> <criteria>",
"Adds the specified alert to the $b$O$b alert list.",
"$uSee Also:$u delalert, alert reaction, trace criteria");
-"ADDTRUST" ("/msg $O ADDTRUST <ip> <number> <duration> <reason>",
+"ADDTRUST" ("/msg $O ADDTRUST <ip> <count> <duration> <reason>",
"Allows the specified IP address to have the specified amount of clones before being removed (rather than the usual limit).",
- "You may use 0 as the duration if you do not wish the trust to ever expire.",
+ "You may use 0 as the duration if you do not wish the trust to ever expire, and 0 as the count for unlimited connections.",
"$uSee Also:$u deltrust, stats trusted");
"ALERT REACTION" ("$bALERT REACTION$b",
"Valid alert actions (to be taken when an alert is hit) are:",
}
struct userNode *
-AddService(const char *nick, const char *desc) {
+AddService(const char *nick, const char *desc, const char *hostname) {
time_t timestamp = now;
struct userNode *old_user = GetUserH(nick);
struct in_addr ipaddr = { INADDR_LOOPBACK };
return old_user;
timestamp = old_user->timestamp - 1;
}
- return AddUser(self, nick, nick, self->name, "+oikr", desc, timestamp, ipaddr, 0);
+ if (!hostname)
+ hostname = self->name;
+ return AddUser(self, nick, nick, hostname, "+oikr", desc, timestamp, ipaddr, 0);
}
struct userNode *
}
struct userNode *
-AddService(const char *nick, const char *desc)
+AddService(const char *nick, const char *desc, const char *hostname)
{
char numeric[COMBO_NUMERIC_LEN+1];
int local_num = get_local_numeric();
log_module(MAIN_LOG, LOG_ERROR, "Unable to allocate numnick for service %s", nick);
return 0;
}
+ if (!hostname)
+ hostname = self->name;
make_numeric(self, local_num, numeric);
- return AddUser(self, nick, nick, self->name, "+oik", numeric, desc, now, "AAAAAA");
+ return AddUser(self, nick, nick, hostname, "+oik", numeric, desc, now, "AAAAAA");
}
struct userNode *
/* stuff originally from other headers that is really protocol-specific */
int IsChannelName(const char *name);
int is_valid_nick(const char *nick);
-struct userNode *AddService(const char *nick, const char *desc);
+struct userNode *AddService(const char *nick, const char *desc, const char *hostname);
struct userNode *AddClone(const char *nick, const char *ident, const char *hostname, const char *desc);
struct server* AddServer(struct server* uplink, const char *name, int hops, time_t boot, time_t link, const char *numeric, const char *description);
void DelServer(struct server* serv, int announce, const char *message);
"opserv" {
"nick" "OpServ";
+ // should use of this service be limited to global opers?
"privileged" "1";
+ // fullname for service
+ "description" "Oper Service Bot";
+ // hostname for service; only used if "description" is also set
+ "hostname" "dances-all-night-with.srvx.net";
// what channel should opserv send debug output to?
"debug_channel" "#opserv";
"debug_channel_modes" "+tinms";
"size" "200";
"drain-rate" "3";
};
- // character to make OpServ pay attention to you
- "trigger" "?";
};
"chanserv" {
"chan_expire_freq" "3d";
// How long is a channel unvisited (by masters or above) before it can be expired?
"chan_expire_delay" "30d";
- // character to make ChanServ pay attention to you
- "trigger" "!";
// what !set options should we show when user calls "!set" with no arguments?
"set_shows" ("DefaultTopic", "TopicMask", "Greeting", "UserGreeting", "Modes", "PubCmd", "InviteMe", "UserInfo", "GiveVoice", "GiveOps", "EnfOps", "EnfModes", "EnfTopic", "TopicSnarf", "Setters", "CtcpUser", "CtcpReaction", "Protect", "Toys", "DynLimit", "NoDelete");