/* opserv.c - IRC Operator assistance service
* Copyright 2000-2004 srvx Development Team
*
- * This file is part of srvx.
+ * This file is part of x3.
*
* srvx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#define KEY_BLOCK_GLINE_DURATION "block_gline_duration"
#define KEY_ISSUER "issuer"
#define KEY_ISSUED "issued"
+#define KEY_ADMIN_LEVEL "admin_level"
#define IDENT_FORMAT "%s [%s@%s/%s]"
#define IDENT_DATA(user) user->nick, user->ident, user->hostname, inet_ntoa(user->ip)
#define OSMSG_GAG_REQUESTED "Gag requested by %s."
static const struct message_entry msgtab[] = {
+ { "OSMSG_BAR", "----------------------------------------" },
{ "OSMSG_USER_ACCESS_IS", "$b%s$b (account $b%s$b) has %d access." },
{ "OSMSG_LEVEL_TOO_LOW", "You lack sufficient access to use this command." },
{ "OSMSG_NEED_CHANNEL", "You must specify a channel for $b%s$b." },
{ "OSMSG_MAX_CLIENTS", "Max clients: %d at %s" },
{ "OSMSG_NETWORK_INFO", "Total users: %d (%d invisible, %d opers)" },
{ "OSMSG_RESERVED_LIST", "List of reserved nicks:" },
- { "OSMSG_TRUSTED_LIST", "List of trusted hosts:" },
- { "OSMSG_HOST_IS_TRUSTED", "%s (%s; set %s ago by %s; expires %s: %s)" },
+ { "OSMSG_TRUSTED_LIST", "$bTrusted Hosts$b" },
+ { "OSMSG_TRUSTED_LIST_HEADER", "IP Address Limit By Time" },
+ { "OSMSG_HOST_IS_TRUSTED", "%-15s %-5s %-10s set %s ago, expires %s" },
+ { "OSMSG_HOST_IS_TRUSTED_DESC", " Reason: %s" },
+ { "OSMSG_TRUSTED_LIST_BAR", "----------------------------------------" },
+ { "OSMSG_TRUSTED_LIST_END", "----------End of Trusted Hosts----------" },
{ "OSMSG_HOST_NOT_TRUSTED", "%s does not have a special trust." },
{ "OSMSG_UPTIME_STATS", "Uptime: %s (%u lines processed, CPU time %.2fu/%.2fs)" },
{ "OSMSG_LINE_DUMPED", "Raw line sent." },
{ "OSMSG_SETTIME_SUCCESS", "Set time for servers named like $b%s$b." },
{ "OSMSG_BAD_ACTION", "Unrecognized trace action $b%s$b." },
{ "OSMSG_USER_SEARCH_RESULTS", "The following users were found:" },
+ { "OSMSG_USER_SEARCH_HEADER", "Nick User@Host (Account)" },
+ { "OSMSG_USER_SEARCH_BAR", "-------------------------------------------" },
+ { "OSMSG_USER_SEARCH_COUNT", "There were %4u matches" },
+ { "OSMSG_USER_SEARCH_COUNT_BAR", "------------ Found %4u matches -----------" },
{ "OSMSG_CHANNEL_SEARCH_RESULTS", "The following channels were found:" },
{ "OSMSG_GLINE_SEARCH_RESULTS", "The following glines were found:" },
{ "OSMSG_LOG_SEARCH_RESULTS", "The following log entries were found:" },
{ "OSMSG_ADDED_ALERT", "Added alert named $b%s$b." },
{ "OSMSG_REMOVED_ALERT", "Removed alert named $b%s$b." },
{ "OSMSG_NO_SUCH_ALERT", "No alert named $b%s$b could be found." },
- { "OSMSG_ALERT_IS", "%s (by %s, reaction %s): %s" },
- { "OSMSG_ALERTS_LIST", "Current $O alerts:" },
+ { "OSMSG_ALERTS_LIST", "$bCurrent $O alerts$b" },
+ { "OSMSG_ALERTS_BAR", "----------------------------------------------" },
+ { "OSMSG_ALERTS_HEADER", "Name Action (by Oper)" },
+ { "OSMSG_ALERTS_DESC", " Criteria: %s" },
+ { "OSMSG_ALERT_IS", "$b%-20s$b %-6s (by %s)" },
+ { "OSMSG_ALERT_END", "----------------End of Alerts-----------------" },
{ "OSMSG_REHASH_COMPLETE", "Completed rehash of configuration database." },
{ "OSMSG_REHASH_FAILED", "Rehash of configuration database failed, previous configuration is intact." },
{ "OSMSG_REOPEN_COMPLETE", "Closed and reopened all log files." },
{ "OSMSG_SERVER_JUPED", "Added new jupe server %s." },
{ "OSMSG_SERVER_NOT_JUPE", "That server is not a juped server." },
{ "OSMSG_SERVER_UNJUPED", "Server jupe removed." },
+ /*
{ "OSMSG_WARN_ADDED", "Added channel activity warning for $b%s$b (%s)" },
{ "OSMSG_WARN_EXISTS", "Channel activity warning for $b%s$b already exists." },
{ "OSMSG_WARN_DELETED", "Removed channel activity warning for $b%s$b" },
{ "OSMSG_WARN_LISTSTART", "Channel activity warnings:" },
{ "OSMSG_WARN_LISTENTRY", "%s (%s)" },
{ "OSMSG_WARN_LISTEND", "End of activity warning list." },
+ */
{ "OSMSG_UPLINK_CONNECTING", "Establishing connection with %s (%s:%d)." },
{ "OSMSG_CURRENT_UPLINK", "$b%s$b is already the current uplink." },
{ "OSMSG_INVALID_UPLINK", "$b%s$b is not a valid uplink name." },
{ NULL, NULL }
};
-#define OPSERV_SYNTAX() svccmd_send_help(user, opserv, cmd)
+#define OPSERV_SYNTAX() svccmd_send_help_brief(user, opserv, cmd)
typedef int (*discrim_search_func)(struct userNode *match, void *extra);
struct userNode *opserv;
-static dict_t opserv_chan_warn; /* data is char* */
+/*static dict_t opserv_chan_warn; */ /* data is char* */
static dict_t opserv_reserved_nick_dict; /* data is struct userNode* */
static struct string_list *opserv_bad_words;
static dict_t opserv_exempt_channels; /* data is not used */
unsigned long purge_lock_delay;
unsigned long join_flood_moderate;
unsigned long join_flood_moderate_threshold;
+ unsigned long admin_level;
} opserv_conf;
struct trusted_host {
return 1;
}
+/* This command has been replaced by 'alert notice channel #foo' */
+/*
static MODCMD_FUNC(cmd_warn)
{
char *reason, *message;
reply("OSMSG_WARN_DELETED", argv[1]);
return 1;
}
+*/
static MODCMD_FUNC(cmd_clearbans)
{
change = mod_chanmode_alloc(channel->banlist.used);
for (ii=0; ii<channel->banlist.used; ii++) {
change->args[ii].mode = MODE_REMOVE | MODE_BAN;
- change->args[ii].u.hostmask = channel->banlist.list[ii]->ban;
+ change->args[ii].u.hostmask = strdup(channel->banlist.list[ii]->ban);
}
modcmd_chanmode_announce(change);
+ for (ii=0; ii<change->argc; ++ii)
+ free((char*)change->args[ii].u.hostmask);
mod_chanmode_free(change);
reply("OSMSG_CLEARBANS_DONE", channel->name);
return 1;
char buffer[400];
/* Show the bad word list.. */
+ /* TODO: convert nonprinting chars like bold to $b etc in a usable way */
for (ii=end=0; ii<opserv_bad_words->used; ii++) {
here_len = strlen(opserv_bad_words->list[ii]);
+ /* If the line is full output it & start again */
if ((end + here_len + 2) > sizeof(buffer)) {
buffer[end] = 0;
reply("OSMSG_BADWORD_LIST", buffer);
struct trusted_host *th;
char length[INTERVALLEN], issued[INTERVALLEN], limit[32];
+ reply("OSMSG_TRUSTED_LIST");
+ reply("OSMSG_TRUSTED_LIST_BAR");
+ reply("OSMSG_TRUSTED_LIST_HEADER");
+ reply("OSMSG_TRUSTED_LIST_BAR");
if (argc > 1) {
th = dict_find(opserv_trusted_hosts, argv[1], NULL);
if (th) {
if (th->expires)
intervalString(length, th->expires - now, user->handle_info);
if (th->limit)
- sprintf(limit, "limit %lu", th->limit);
+ sprintf(limit, "%lu", th->limit);
reply("OSMSG_HOST_IS_TRUSTED",
th->ipaddr,
- (th->limit ? limit : "no limit"),
- (th->issued ? issued : "some time"),
+ (th->limit ? limit : "none"),
(th->issuer ? th->issuer : "<unknown>"),
- (th->expires ? length : "never"),
- (th->reason ? th->reason : "<unknown>"));
+ (th->issued ? issued : "some time"),
+ (th->expires ? length : "never"));
+ reply("OSMSG_HOST_IS_TRUSTED_DESC", (th->reason ? th->reason : "<unknown>"));
} else {
reply("OSMSG_HOST_NOT_TRUSTED", argv[1]);
}
} else {
- reply("OSMSG_TRUSTED_LIST");
for (it = dict_first(opserv_trusted_hosts); it; it = iter_next(it)) {
th = iter_data(it);
if (th->issued)
if (th->expires)
intervalString(length, th->expires - now, user->handle_info);
if (th->limit)
- sprintf(limit, "limit %lu", th->limit);
+ sprintf(limit, "%lu", th->limit);
reply("OSMSG_HOST_IS_TRUSTED", iter_key(it),
- (th->limit ? limit : "no limit"),
- (th->issued ? issued : "some time"),
+ (th->limit ? limit : "none"),
(th->issuer ? th->issuer : "<unknown>"),
- (th->expires ? length : "never"),
- (th->reason ? th->reason : "<unknown>"));
+ (th->issued ? issued : "some time"),
+ (th->expires ? length : "never"));
+ reply("OSMSG_HOST_IS_TRUSTED_DESC", (th->reason ? th->reason : "<unknown>"));
}
}
+ reply("OSMSG_TRUSTED_LIST_END");
return 1;
}
const char *reaction;
reply("OSMSG_ALERTS_LIST");
+ reply("OSMSG_ALERTS_BAR");
+ reply("OSMSG_ALERTS_HEADER");
+ reply("OSMSG_ALERTS_BAR");
for (it = dict_first(opserv_user_alerts); it; it = iter_next(it)) {
alert = iter_data(it);
switch (alert->reaction) {
case REACT_GLINE: reaction = "gline"; break;
default: reaction = "<unknown>"; break;
}
- reply("OSMSG_ALERT_IS", iter_key(it), alert->owner, reaction, alert->text_discrim);
+ reply("OSMSG_ALERT_IS", iter_key(it), reaction, alert->owner);
+ reply("OSMSG_ALERTS_DESC", alert->text_discrim);
}
+ reply("OSMSG_ALERT_END");
return 1;
}
return 1;
}
+/*
static MODCMD_FUNC(cmd_stats_warn) {
dict_iterator_t it;
reply("OSMSG_WARN_LISTEND");
return 1;
}
+*/
+
+#if defined(WITH_MALLOC_X3)
+static MODCMD_FUNC(cmd_stats_memory) {
+ extern unsigned long alloc_count, alloc_size;
+ send_message_type(MSG_TYPE_NOXLATE, user, cmd->parent->bot,
+ "%u allocations totalling %u bytes.",
+ alloc_count, alloc_size);
+ return 1;
+}
+#elif defined(WITH_MALLOC_SLAB)
+static MODCMD_FUNC(cmd_stats_memory) {
+ extern unsigned long slab_alloc_count, slab_count, slab_alloc_size;
+ extern unsigned long big_alloc_count, big_alloc_size;
+ send_message_type(MSG_TYPE_NOXLATE, user, cmd->parent->bot,
+ "%u allocations in %u slabs totalling %u bytes.",
+ slab_alloc_count, slab_count, slab_alloc_size);
+/* send_message_type(MSG_TYPE_NOXLATE, user, cmd->parent->bot,
+ "%u big allocations totalling %u bytes.",
+ */
+ return 1;
+}
+#endif
static MODCMD_FUNC(cmd_dump)
{
- char linedup[MAXLEN], *original;
+ char linedup[MAXLEN], original[MAXLEN];
- original = unsplit_string(argv+1, argc-1, NULL);
+ unsplit_string(argv+1, argc-1, original);
safestrncpy(linedup, original, sizeof(linedup));
/* assume it's only valid IRC if we can parse it */
if (parse_line(linedup, 1)) {
static MODCMD_FUNC(cmd_raw)
{
- char linedup[MAXLEN], *original;
+ char linedup[MAXLEN], original[MAXLEN];
- original = unsplit_string(argv+1, argc-1, NULL);
+ unsplit_string(argv+1, argc-1, original);
safestrncpy(linedup, original, sizeof(linedup));
/* Try to parse the line before sending it; if it's too wrong,
* maybe it will core us instead of our uplink. */
opserv_bad_channel(const char *name)
{
unsigned int found;
+ int present;
- dict_find(opserv_exempt_channels, name, &found);
- if (found)
+ dict_find(opserv_exempt_channels, name, &present);
+ if (present)
return 0;
if (gline_find(name))
static void
opserv_channel_check(struct chanNode *newchan)
{
- char *warning;
+ /*char *warning; */
if (!newchan->join_policer.params) {
newchan->join_policer.last_req = now;
newchan->join_policer.params = opserv_conf.join_policer_params;
}
+ /*
if ((warning = dict_find(opserv_chan_warn, newchan->name, NULL))) {
char message[MAXLEN];
snprintf(message, sizeof(message), "Channel activity warning for channel %s: %s", newchan->name, warning);
global_message(MESSAGE_RECIPIENT_OPERS, message);
}
+ */
/* Wait until the join check to shut channels down. */
newchan->bad_channel = opserv_bad_channel(newchan->name);
alert->discrim->reason = strdup(name);
alert->reaction = reaction;
dict_insert(opserv_user_alerts, name_dup, alert);
- if (alert->discrim->channel)
+ /* Stick the alert into the appropriate additional alert dict(s).
+ * For channel alerts, we only use channels and min_channels;
+ * max_channels would have to be checked on /part, which we do not
+ * yet do, and which seems of questionable value.
+ */
+ if (alert->discrim->channel || alert->discrim->min_channels)
dict_insert(opserv_channel_alerts, name_dup, alert);
- else if (alert->discrim->mask_nick)
+ if (alert->discrim->mask_nick)
dict_insert(opserv_nick_based_alerts, name_dup, alert);
return alert;
}
+/*
static int
add_chan_warn(const char *key, void *data, UNUSED_ARG(void *extra))
{
struct record_data *rd = data;
char *reason = GET_RECORD_QSTRING(rd);
- /* i hope this can't happen */
+ * i hope this can't happen *
if (!reason)
reason = "No Reason";
dict_insert(opserv_chan_warn, strdup(key), strdup(reason));
return 0;
}
+*/
static int
add_user_alert(const char *key, void *data, UNUSED_ARG(void *extra))
dict_foreach(object, add_gag_helper, NULL);
if ((object = database_get_data(conf_db, KEY_ALERTS, RECDB_OBJECT)))
dict_foreach(object, add_user_alert, NULL);
+/*
if ((object = database_get_data(conf_db, KEY_WARN, RECDB_OBJECT)))
dict_foreach(object, add_chan_warn, NULL);
+*/
return 0;
}
saxdb_end_record(ctx);
}
/* channel warnings */
+ /*
if (dict_size(opserv_chan_warn)) {
saxdb_start_record(ctx, KEY_WARN, 0);
for (it = dict_first(opserv_chan_warn); it; it = iter_next(it)) {
}
saxdb_end_record(ctx);
}
+ */
/* alerts */
if (dict_size(opserv_user_alerts)) {
saxdb_start_record(ctx, KEY_ALERTS, 1);
{
struct discrim_and_source *das = extra;
if (match->handle_info) {
- send_message_type(4, das->source, opserv, "%s!%s@%s %s", match->nick, match->ident, match->hostname, match->handle_info->handle);
+ send_message_type(4, das->source, opserv, "%-15s\002 \002%10s\002@\002%s (%s)", match->nick, match->ident, match->hostname, match->handle_info->handle);
} else {
- send_message_type(4, das->source, opserv, "%s!%s@%s", match->nick, match->ident, match->hostname);
+ send_message_type(4, das->source, opserv, "%-15s\002 \002%10s\002@\002%s", match->nick, match->ident, match->hostname);
}
return 0;
}
return 0;
if (action == trace_print_func)
- reply("OSMSG_USER_SEARCH_RESULTS");
+ {
+ reply("OSMSG_USER_SEARCH_RESULTS");
+ reply("OSMSG_USER_SEARCH_BAR");
+ reply("OSMSG_USER_SEARCH_HEADER");
+ reply("OSMSG_USER_SEARCH_BAR");
+ }
else if (action == trace_count_func)
das.discrim->limit = INT_MAX;
else if ((action == trace_gline_func) && !das.discrim->duration)
dict_foreach(das.dict, opserv_show_hostinfo, &das);
if (matches)
- reply("MSG_MATCH_COUNT", matches);
+ {
+ if(action == trace_print_func)
+ reply("OSMSG_USER_SEARCH_COUNT_BAR", matches);
+ else
+ reply("OSMSG_USER_SEARCH_COUNT", matches);
+ }
else
- reply("MSG_NO_MATCHES");
+ reply("MSG_NO_MATCHES");
if (das.discrim->channel)
UnlockChannel(das.discrim->channel);
} else {
opserv_conf.staff_auth_channel = NULL;
}
+
+ str = database_get_data(conf_node, KEY_ADMIN_LEVEL, RECDB_QSTRING);
+ opserv_conf.admin_level = str ? strtoul(str, NULL, 0): 800;
+
str = database_get_data(conf_node, KEY_UNTRUSTED_MAX, RECDB_QSTRING);
opserv_conf.untrusted_max = str ? strtoul(str, NULL, 0) : 5;
str = database_get_data(conf_node, KEY_PURGE_LOCK_DELAY, RECDB_QSTRING);
dict_foreach(child, set_policer_param, pp);
}
+/* lame way to export opserv_conf value to nickserv.c ... */
+unsigned int
+opserv_conf_admin_level()
+{
+ return(opserv_conf.admin_level);
+}
+
static void
opserv_db_init(void) {
/* set up opserv_trusted_hosts dict */
opserv_trusted_hosts = dict_new();
dict_set_free_data(opserv_trusted_hosts, free_trusted_host);
/* set up opserv_chan_warn dict */
+
+/* alert trace notice channel #x replaces warnings
dict_delete(opserv_chan_warn);
opserv_chan_warn = dict_new();
dict_set_free_keys(opserv_chan_warn, free);
dict_set_free_data(opserv_chan_warn, free);
+*/
/* set up opserv_user_alerts */
dict_delete(opserv_channel_alerts);
opserv_channel_alerts = dict_new();
{
unsigned int nn;
- dict_delete(opserv_chan_warn);
+/* dict_delete(opserv_chan_warn); */
dict_delete(opserv_reserved_nick_dict);
free_string_list(opserv_bad_words);
dict_delete(opserv_exempt_channels);
opserv_define_func("STATS TRUSTED", cmd_stats_trusted, 0, 0, 0);
opserv_define_func("STATS UPLINK", cmd_stats_uplink, 0, 0, 0);
opserv_define_func("STATS UPTIME", cmd_stats_uptime, 0, 0, 0);
- opserv_define_func("STATS WARN", cmd_stats_warn, 0, 0, 0);
+/* opserv_define_func("STATS WARN", cmd_stats_warn, 0, 0, 0); */
+#if defined(WITH_MALLOC_X3) || defined(WITH_MALLOC_SLAB)
+ opserv_define_func("STATS MEMORY", cmd_stats_memory, 0, 0, 0);
+#endif
opserv_define_func("TRACE", cmd_trace, 100, 0, 3);
opserv_define_func("TRACE PRINT", NULL, 0, 0, 0);
opserv_define_func("TRACE COUNT", NULL, 0, 0, 0);
modcmd_register(opserv_module, "GTRACE UNGLINE", NULL, 0, 0, "template", "ungline", NULL);
opserv_define_func("UNJUPE", cmd_unjupe, 900, 0, 2);
opserv_define_func("UNRESERVE", cmd_unreserve, 800, 0, 2);
- opserv_define_func("UNWARN", cmd_unwarn, 800, 0, 0);
+/* opserv_define_func("UNWARN", cmd_unwarn, 800, 0, 0); */
opserv_define_func("VOICEALL", cmd_voiceall, 300, 2, 0);
- opserv_define_func("WARN", cmd_warn, 800, 0, 2);
+/* opserv_define_func("WARN", cmd_warn, 800, 0, 2); */
opserv_define_func("WHOIS", cmd_whois, 0, 0, 2);
opserv_reserved_nick_dict = dict_new();
reg_new_user_func(opserv_new_user_check);
reg_nick_change_func(opserv_alert_check_nick);
reg_del_user_func(opserv_user_cleanup);
- reg_new_channel_func(opserv_channel_check);
+ reg_new_channel_func(opserv_channel_check);
reg_del_channel_func(opserv_channel_delete);
reg_join_func(opserv_join_check);
reg_auth_func(opserv_staff_alert);