Compare commits

...

10 Commits

Author SHA1 Message Date
Kevin Easton
eaf6456854 Improve efficiency of m_3cat() algorithm
Use exact memcpy() instead of repeated strcat().
2019-12-28 17:30:01 +11:00
Kevin Easton
4f63d48929 Remove duplicate global definitions
This fixes compiling with gcc-10.

Reported by ixz.
2019-12-28 17:20:30 +11:00
Kevin Easton
9fe7de361e Minor fixes and improvements to channel_stats()
Show total channel memory use for /CHANST -ALL (previously it just showed the size of a single channel struct).

Fix stray cyan-coloured [ for /CHANST -ALL.

Fix display of "Channel created" and "in memory", which were displayed the wrong way around.
2019-08-27 16:29:40 +10:00
Kevin Easton
960e2d8087 Reformat and simplify channel_stats() and make_channel() 2019-08-27 15:36:29 +10:00
Kevin Easton
ddfbec0b4b Remove queueing of wildcard CSETs and fix use-after-free with queued CSETs
A queued CSET is one that is set before the matching channel is joined.  The CSetList is allocated and linked to
the cset_queue list.

The use-after-free bug was caused because the CSetList wasn't removed from the cset_queue after it was attached
to a joined channel.  If the channel is parted, it eventually ages out of the Whowas-Chan-List and the CSetList
is freed, but there is now a dangling pointer to it in the cset_queue.  This is fixed by removing the CSetList
from the cset_queue when it is attached to a channel, so the net result of /CSET #chan ; /JOIN #chan is the same
as doing the reverse.

Queued wildcard CSETs never worked properly - the queued CSET with the wildcard name would end up attached to any
subsequent matching channel that was joined.  Channel names with wildcards in them are legal anyway, so the best
medium-term solution (pending a full redesign of the whole CSET command) is to just enforce that queued CSETs are
always literal channel names, not wildcards.
2019-08-03 01:09:21 +10:00
Kevin Easton
f714e3e951 Combine cset_variable_case1() and cset_variable_casedef() into cset_variable_range()
There's no point having two functions that two essentially the same thing.  Also implement
cset_variable_noargs() as a call to cset_variable_range().
2019-07-18 14:17:04 +10:00
Kevin Easton
e0ad103153 Simplify cset_variable_casedef()
This should make no functional change.
2019-07-17 16:29:53 +10:00
Kevin Easton
43ace65cb3 Simplifications to cset_variable()
Remove some unnecessary variables and reorder the code slightly. This should have no functional change.
2019-07-13 01:14:15 +10:00
Kevin Easton
e347375cb3 Very minor simplification/cleanup of is_channel() 2019-07-08 17:34:08 +10:00
Kevin Easton
b9803e69d1 Avoid reading an uninitialized byte in dgets()
This was caused by an off-by-one error in the case when a line exceeded the buffer size provided to
dgets().  Found with valgrind.
2019-06-27 17:37:35 +10:00
11 changed files with 208 additions and 328 deletions

View File

@@ -1,5 +1,11 @@
[Changes 1.2.2] [Changes 1.2.2]
* Remove duplicate global definitions to fix compiling with gcc 10.
Reported by ixz. (caf)
* Remove queueing of wildcard CSETs and fix use-after-free with queued
CSETs. (caf)
* Bump MAXPARA (maximum protocol message arguments) to 20 as per EPIC5. (caf) * Bump MAXPARA (maximum protocol message arguments) to 20 as per EPIC5. (caf)
* Correctly handle a last argument prefixed with : for any protocol message, * Correctly handle a last argument prefixed with : for any protocol message,

View File

@@ -321,7 +321,7 @@ extern int cpu_saver;
extern struct sockaddr_foobar local_ip_address; extern struct sockaddr_foobar local_ip_address;
int BX_is_channel (char *); int BX_is_channel (const char *);
void BX_irc_exit (int, char *, char *, ...); void BX_irc_exit (int, char *, char *, ...);
void BX_beep_em (int); void BX_beep_em (int);
void got_initial_version (char *); void got_initial_version (char *);

View File

@@ -404,7 +404,7 @@ extern Function_ptr *global;
#define add_completion_type (*(int (*)(char *, int , enum completion ))global[ADD_COMPLETION_TYPE]) #define add_completion_type (*(int (*)(char *, int , enum completion ))global[ADD_COMPLETION_TYPE])
/* names.c */ /* names.c */
#define is_channel (*(int (*)(char *))global[IS_CHANNEL]) #define is_channel (*(int (*)(const char *))global[IS_CHANNEL])
#define make_channel (*(char *(*)(char *))global[MAKE_CHANNEL]) #define make_channel (*(char *(*)(char *))global[MAKE_CHANNEL])
#define is_chanop (*(int (*)(char *, char *))global[IS_CHANOP]) #define is_chanop (*(int (*)(char *, char *))global[IS_CHANOP])
#define is_halfop (*(int (*)(char *, char *))global[IS_HALFOP]) #define is_halfop (*(int (*)(char *, char *))global[IS_HALFOP])

View File

@@ -118,7 +118,6 @@ extern int doing_notice;
static void oper_password_received (char *, char *); static void oper_password_received (char *, char *);
int no_hook_notify = 0;
int load_depth = -1; int load_depth = -1;
extern char cx_function[]; extern char cx_function[];

View File

@@ -325,156 +325,58 @@ static void set_cset_var_value(CSetList *tmp, int var_index, char *value)
CSetList *check_cset_queue(char *channel, int add) CSetList *check_cset_queue(char *channel, int add)
{ {
CSetList *c = NULL; CSetList *c = (CSetList *)find_in_list((List **)&cset_queue, channel, 0);
int found = 0;
if (!strchr(channel, '*') && !(c = (CSetList *)find_in_list((List **)&cset_queue, channel, 0))) if (!c && add)
{ {
if (!add)
{
for (c = cset_queue; c; c = c->next)
if (!my_stricmp(c->channel, channel) || wild_match(c->channel, channel))
return c;
return NULL;
}
c = create_csets_for_channel(channel); c = create_csets_for_channel(channel);
add_to_list((List **)&cset_queue, (List *)c); add_to_list((List **)&cset_queue, (List *)c);
found++;
} }
if (c)
return c; return c;
if (add && !found)
{
for (c = cset_queue; c; c = c->next)
if (!my_stricmp(c->channel, channel))
return c;
c = create_csets_for_channel(channel);
c->next = cset_queue;
cset_queue = c;
return c;
}
return NULL;
} }
static inline void cset_variable_case1(char *channel, int var_index, char *args) static inline void cset_variable_range(char *channel, int cnt, int var_index, char *args)
{
ChannelList *chan = NULL;
int tmp = 0;
int count = 0;
/*
* implement a queue for channels that don't exist... later...
* go home if user doesn't have any channels.
*/
if (current_window->server != -1)
{
for (chan = get_server_channels(current_window->server); chan; chan = chan->next)
{
tmp = var_index;
if (wild_match(channel, chan->channel))
{
set_cset_var_value(chan->csets, tmp, args);
count++;
}
}
}
/* no channel match. lets check the queue */
/* if (!count)*/
{
CSetList *c = NULL;
if (!count)
check_cset_queue(channel, 1);
for (c = cset_queue; c; c = c->next)
{
tmp = var_index;
if (!my_stricmp(channel, c->channel) || wild_match(channel, c->channel))
{
set_cset_var_value(c, tmp, args);
count++;
}
}
if (!count)
say("CSET_VARIABLE: No match in cset queue for %s", channel);
}
}
static inline void cset_variable_casedef(char *channel, int cnt, int var_index, char *args)
{ {
ChannelList *chan = NULL; ChannelList *chan = NULL;
int tmp, tmp2; CSetList *c = NULL;
int i;
int count = 0; int count = 0;
if (current_window->server != -1) if (current_window->server != -1)
{ {
for (chan = get_server_channels(current_window->server); chan; chan = chan->next) for (chan = get_server_channels(current_window->server); chan; chan = chan->next)
{ {
tmp = var_index;
tmp2 = cnt;
if (wild_match(channel, chan->channel)) if (wild_match(channel, chan->channel))
{ {
for (tmp2 += tmp; tmp < tmp2; tmp++) for (i = var_index; i < var_index + cnt; i++)
set_cset_var_value(chan->csets, tmp, empty_string); set_cset_var_value(chan->csets, i, args);
count++; count++;
} }
} }
} }
/* if (!count) */
{
CSetList *c = NULL;
if (!count)
check_cset_queue(channel, 1);
for (c = cset_queue; c; c = c->next)
{
tmp = var_index;
tmp2 = cnt;
if (!my_stricmp(channel, c->channel) || wild_match(channel, c->channel))
{
for (tmp2 +=tmp; tmp < tmp2; tmp++)
set_cset_var_value(c, tmp, empty_string);
count++;
}
}
if (!count)
say("CSET_VARIABLE: No match in cset queue for %s", channel);
return;
}
if (!count)
check_cset_queue(channel, 1);
for (c = cset_queue; c; c = c->next)
{
if (!my_stricmp(channel, c->channel) || wild_match(channel, c->channel))
{
for (i = var_index; i < var_index + cnt; i++)
{
set_cset_var_value(c, i, args);
count++;
}
}
}
if (!count)
say("CSET_VARIABLE: No match in cset queue for %s", channel);
} }
static inline void cset_variable_noargs(char *channel) static inline void cset_variable_noargs(char *channel)
{ {
int var_index = 0; /* Show the current value of every cset */
ChannelList *chan = NULL; cset_variable_range(channel, NUMBER_OF_CSETS, 0, "");
int count = 0;
if (current_window->server != -1)
{
for (chan = get_server_channels(current_window->server); chan; chan = chan->next)
{
if (wild_match(channel, chan->channel))
{
for (var_index = 0; var_index < NUMBER_OF_CSETS; var_index++)
set_cset_var_value(chan->csets, var_index, empty_string);
count++;
}
}
}
/* if (!count) */
{
CSetList *c = NULL;
if (!count)
check_cset_queue(channel, 1);
for (c = cset_queue; c; c = c->next)
{
if (!wild_match(channel, c->channel))
continue;
for (var_index = 0; var_index < NUMBER_OF_CSETS; var_index++)
set_cset_var_value(c, var_index, empty_string);
count++;
}
if (!count)
say("CSET_VARIABLE: No match in cset queue for %s", channel ? channel : empty_string);
return;
}
} }
char *set_cset(char *var, ChannelList *chan, char *value) char *set_cset(char *var, ChannelList *chan, char *value)
@@ -567,50 +469,46 @@ int var_index, cnt = 0;
BUILT_IN_COMMAND(cset_variable) BUILT_IN_COMMAND(cset_variable)
{ {
char *var, *channel = NULL; char *var, *channel = NULL;
int no_args = 1, cnt, var_index, hook = 1; int cnt, var_index;
if (from_server != -1 && current_window->server != -1) if (args && *args && (is_channel(args) || *args == '*'))
{
if (args && *args && (is_channel(args) || *args == '*'))
channel = next_arg(args, &args);
else
channel = get_current_channel_by_refnum(0);
}
else if (args && *args && (is_channel(args) || *args == '*'))
channel = next_arg(args, &args); channel = next_arg(args, &args);
else
channel = get_current_channel_by_refnum(0);
if (!channel) if (!channel)
return; return;
if ((var = next_arg(args, &args)) != NULL) var = next_arg(args, &args);
if (!var)
{ {
if (*var == '-')
{
var++;
args = NULL;
}
var_index = find_cset_variable(cset_array, var, &cnt);
if (hook)
{
switch (cnt)
{
case 0:
say("No such variable \"%s\"", var);
return;
case 1:
cset_variable_case1(channel, var_index, args);
return;
default:
say("%s is ambiguous", var);
cset_variable_casedef(channel, cnt, var_index, args);
return;
}
}
}
if (no_args)
cset_variable_noargs(channel); cset_variable_noargs(channel);
return;
}
if (*var == '-')
{
var++;
args = NULL;
}
var_index = find_cset_variable(cset_array, var, &cnt);
if (cnt == 0)
{
say("No such variable \"%s\"", var);
return;
}
if (cnt > 1)
{
say("Variable \"%s\" is ambiguous", var);
args = "";
}
cset_variable_range(channel, cnt, var_index, args);
} }
CSetList *create_csets_for_channel(char *channel) CSetList *create_csets_for_channel(char *channel)
@@ -624,14 +522,9 @@ CSetList *create_csets_for_channel(char *channel)
ircpanic("Variable [%d] (%s) is out of order.", i, cset_array[i].name); ircpanic("Variable [%d] (%s) is out of order.", i, cset_array[i].name);
#endif #endif
if (check_cset_queue(channel, 0)) if ((tmp = (CSetList *)remove_from_list((List **)&cset_queue, channel)))
{ return tmp;
if ((tmp = (CSetList *)find_in_list((List **)&cset_queue, channel, 0)))
return tmp;
for (tmp = cset_queue; tmp; tmp = tmp->next)
if (!my_stricmp(tmp->channel, channel) || wild_match(tmp->channel, channel))
return tmp;
}
tmp = (CSetList *) new_malloc(sizeof(CSetList)); tmp = (CSetList *) new_malloc(sizeof(CSetList));
/* use default settings. */ /* use default settings. */
tmp->set_aop = get_int_var(AOP_VAR); tmp->set_aop = get_int_var(AOP_VAR);

View File

@@ -274,27 +274,27 @@ char *BX_m_s3cat_s (char **one, const char *maybe, const char *ifthere)
char *BX_m_3cat(char **one, const char *two, const char *three) char *BX_m_3cat(char **one, const char *two, const char *three)
{ {
int len = 0; size_t one_len = 0, two_len = 0, three_len = 0;
char *str; char *str;
if (*one) if (*one)
len = strlen(*one); one_len = strlen(*one);
if (two) if (two)
len += strlen(two); two_len = strlen(two);
if (three) if (three)
len += strlen(three); three_len = strlen(three);
len += 1;
str = (char *)new_malloc(len); str = new_malloc(one_len + two_len + three_len + 1);
if (*one) if (*one)
strcpy(str, *one); memcpy(str, *one, one_len);
if (two) if (two)
strcat(str, two); memcpy(str + one_len, two, two_len);
if (three) if (three)
strcat(str, three); memcpy(str + one_len + two_len, three, three_len);
str[one_len + two_len + three_len] = 0;
new_free(one); new_free(one);
return ((*one = str)); return (*one = str);
} }
/* upper() /* upper()

View File

@@ -482,62 +482,43 @@ int count = 0;
BUILT_IN_COMMAND(channel_stats) BUILT_IN_COMMAND(channel_stats)
{ {
ChannelList *new = NULL; ChannelList *new = NULL;
char *channel = NULL; char *channel = NULL;
WhowasChanList *new1 = NULL; int numircops = 0;
int numircops = 0; int usershere = 0;
int usershere = 0; int usersaway = 0;
int usersaway = 0; int chanops = 0;
int chanops = 0; int chanunop = 0;
int chanunop = 0; char *ircops = NULL;
char *ircops = NULL; int server = -1;
int server = -1; int max_hops = 0;
int max_hops = 0; NickList *l;
unsigned long nick_mem = 0;
NickList *l; unsigned long ban_mem = 0;
unsigned long nick_mem = 0, BanList *b;
ban_mem = 0;
BanList *b;
if (args && *args) if (args && *args)
{ {
channel = next_arg(args, &args); channel = next_arg(args, &args);
if (my_strnicmp(channel, "-ALL", strlen(channel)))
if (!my_strnicmp(channel, "-ALL", strlen(channel)))
{ {
if (!(channel = make_channel(channel))) /* Accumulate stats from all joined channels on server */
return;
if (!(new = prepare_command(&server, channel, PC_SILENT)))
if ((channel && !(new1 = check_whowas_chan_buffer(channel, -1, 0))))
return;
}
else
{
int stats_ops= 0, stats_dops = 0, stats_bans = 0, stats_unbans = 0; int stats_ops= 0, stats_dops = 0, stats_bans = 0, stats_unbans = 0;
int stats_topics = 0, stats_kicks = 0, stats_pubs = 0, stats_parts = 0; int stats_topics = 0, stats_kicks = 0, stats_pubs = 0, stats_parts = 0;
int stats_signoffs = 0, stats_joins = 0; int stats_signoffs = 0, stats_joins = 0;
int total_nicks = 0, max_nicks = 0, total_bans = 0, max_bans = 0; int total_nicks = 0, max_nicks = 0, total_bans = 0, max_bans = 0;
int stats_sops = 0, stats_sdops = 0, stats_sbans = 0, stats_sunbans = 0; int stats_sops = 0, stats_sdops = 0, stats_sbans = 0, stats_sunbans = 0;
NickList *l;
BanList *b;
unsigned long chan_mem = 0; unsigned long chan_mem = 0;
channel = NULL;
channel = NULL;
if (from_server != -1) if (from_server != -1)
{ {
for (new = get_server_channels(from_server); new; new = new->next) for (new = get_server_channels(from_server); new; new = new->next)
{ {
if (!channel) m_s3cat(&channel, ",", new->channel);
malloc_strcpy(&channel, new->channel);
else
{
malloc_strcat(&channel, ",");
malloc_strcat(&channel, new->channel);
}
for (l = next_nicklist(new, NULL); l; l = next_nicklist(new, l)) for (l = next_nicklist(new, NULL); l; l = next_nicklist(new, l))
{ {
if (nick_isaway(l)) if (nick_isaway(l))
@@ -583,106 +564,112 @@ BanList *b;
stats_sunbans += new->stats_sunbans; stats_sunbans += new->stats_sunbans;
} }
} }
if (!ircops)
malloc_strcat(&ircops, empty_string); if (do_hook(CHANNEL_STATS_LIST,
if (do_hook(CHANNEL_STATS_LIST, "%s %s %s %lu %lu %lu %lu %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %d %s", "%s %s %s %lu %lu %lu %lu %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %d %s",
channel, empty_string, empty_string, channel, empty_string, empty_string,
nick_mem+chan_mem+ban_mem, nick_mem, nick_mem + chan_mem + ban_mem, nick_mem,
(unsigned long)sizeof(ChannelList),ban_mem, chan_mem, ban_mem,
stats_ops, stats_dops, stats_bans, stats_unbans, stats_ops, stats_dops, stats_bans, stats_unbans,
stats_topics, stats_kicks, stats_pubs, stats_parts, stats_topics, stats_kicks, stats_pubs, stats_parts,
stats_signoffs, stats_joins, total_bans, max_bans, stats_signoffs, stats_joins, total_bans, max_bans,
stats_sops, stats_sdops,stats_sbans, stats_sunbans, stats_sops, stats_sdops, stats_sbans, stats_sunbans,
usershere, usersaway, chanops, chanunop,total_nicks,max_nicks, usershere, usersaway, chanops, chanunop, total_nicks, max_nicks,
numircops, max_hops, ircops)) numircops, max_hops, ircops ? ircops : ""))
{ {
put_it("%s", convert_output_format("$G %CInformation for channels %K: %W$0", "%s", channel)); put_it("%s", convert_output_format("$G %CInformation for channels %K: %W$0", "%s", channel));
put_it("%s", convert_output_format(" MEM usage%K:%w Total%K:%w %c$0 bytes %K[%cNicks $1 b Chan $2 b Bans $3 b%K]", "%d %d %d %d", (int)(nick_mem+chan_mem+ban_mem), (int)nick_mem, (int)sizeof(ChannelList), (int)ban_mem)); put_it("%s", convert_output_format(" MEM usage%K:%w Total%K:%w %c$0 bytes %K[%cNicks $1 b Chan $2 b Bans $3 b%K]", "%d %d %d %d", (int)(nick_mem + chan_mem + ban_mem), (int)nick_mem, (int)chan_mem, (int)ban_mem));
put_it("%s", convert_output_format("Ops %K[%W$[-5]0%K]%w De-Ops %K[%W$[-5]1%K]%w Bans %K[%W$[-5]2%K]%w Unbans %K[%W$[-5]3%K]%w", "%u %u %u %u", stats_ops, stats_dops, stats_bans, stats_unbans)); put_it("%s", convert_output_format("Ops %K[%W$[-5]0%K]%w De-Ops %K[%W$[-5]1%K]%w Bans %K[%W$[-5]2%K]%w Unbans %K[%W$[-5]3%K]%w", "%u %u %u %u", stats_ops, stats_dops, stats_bans, stats_unbans));
put_it("%s", convert_output_format("Topics %K[%W$[-5]0%K]%w Kicks %K[%W$[-5]1%K]%w Publics %K[%W$[-5]2%K]%w Parts %K[%W$[-5]3%K]%w", "%u %u %u %u", stats_topics, stats_kicks, stats_pubs, stats_parts)); put_it("%s", convert_output_format("Topics %K[%W$[-5]0%K]%w Kicks %K[%W$[-5]1%K]%w Publics %K[%W$[-5]2%K]%w Parts %K[%W$[-5]3%K]%w", "%u %u %u %u", stats_topics, stats_kicks, stats_pubs, stats_parts));
put_it("%s", convert_output_format("Signoffs %C[%W$[-5]0%K]%w Joins %K[%W$[-5]1%K]%w TotalBans %K[%W$[-5]2%K]%w MaxBans %K[%W$[-5]3%K]%w", "%u %u %u %u", stats_signoffs, stats_joins, total_bans, max_bans)); put_it("%s", convert_output_format("Signoffs %K[%W$[-5]0%K]%w Joins %K[%W$[-5]1%K]%w TotalBans %K[%W$[-5]2%K]%w MaxBans %K[%W$[-5]3%K]%w", "%u %u %u %u", stats_signoffs, stats_joins, total_bans, max_bans));
put_it("%s", convert_output_format("ServOps %K[%W$[-5]0%K]%w ServDeop %K[%W$[-5]1%K]%w ServBans %K[%W$[-5]2%K]%w ServUB %K[%W$[-5]3%K]%w", "%u %u %u %u", stats_sops, stats_sdops,stats_sbans, stats_sunbans)); put_it("%s", convert_output_format("ServOps %K[%W$[-5]0%K]%w ServDeop %K[%W$[-5]1%K]%w ServBans %K[%W$[-5]2%K]%w ServUB %K[%W$[-5]3%K]%w", "%u %u %u %u", stats_sops, stats_sdops,stats_sbans, stats_sunbans));
put_it("%s", convert_output_format("Users Here %K[%W$[-5]0%K]%w Users Away %K[%W$[-5]1%K]%w Opped %K[%W$[-5]2%K]%w Unopped %K[%W$[-5]3%K]%w", "%u %u %u %u", usershere, usersaway, chanops, chanunop)); put_it("%s", convert_output_format("Users Here %K[%W$[-5]0%K]%w Users Away %K[%W$[-5]1%K]%w Opped %K[%W$[-5]2%K]%w Unopped %K[%W$[-5]3%K]%w", "%u %u %u %u", usershere, usersaway, chanops, chanunop));
put_it("%s", convert_output_format("TotalNicks %K[%W$[-5]0%K]%w MaxNicks %K[%W$[-5]1%K]%w ServerHops %K[%W$[-5]2%K]%w", "%d %d %d", total_nicks,max_nicks, max_hops)); put_it("%s", convert_output_format("TotalNicks %K[%W$[-5]0%K]%w MaxNicks %K[%W$[-5]1%K]%w ServerHops %K[%W$[-5]2%K]%w", "%d %d %d", total_nicks,max_nicks, max_hops));
put_it("%s", convert_output_format("IRCops %K[%W$[3]0%K]%w$1-", "%d %s", numircops, ircops)); put_it("%s", convert_output_format("IRCops %K[%W$[3]0%K]%w$1-", "%d %s", numircops, ircops ? ircops : ""));
} }
new_free(&ircops); new_free(&ircops);
new_free(&channel); new_free(&channel);
return; return;
} }
} }
else
{
if (!(new = prepare_command(&server, channel, PC_SILENT)))
if ((channel && !(new1 = check_whowas_chan_buffer(channel, -1, 0))))
return;
}
if (!new && new1) channel = make_channel(channel);
new = new1->channellist; new = prepare_command(&server, channel, PC_SILENT);
if (!new) if (!new)
{ {
bitchsay("Try joining a channel first"); if (channel)
return;
}
if (new)
{
for (l = next_nicklist(new, NULL); l; l = next_nicklist(new, l))
{ {
nick_mem += sizeof(NickList); WhowasChanList *whowas_chan = check_whowas_chan_buffer(channel, -1, 0);
if (nick_isaway(l))
usersaway++; if (!whowas_chan)
else
usershere++;
if (nick_isircop(l))
{ {
numircops++; bitchsay("No stats available for %s", channel);
malloc_strcat(&ircops, " ("); return;
malloc_strcat(&ircops, l->nick);
malloc_strcat(&ircops, ")");
} }
if (nick_isop(l))
chanops++; new = whowas_chan->channellist;
else }
chanunop++; else
if (l->serverhops > max_hops) {
max_hops = l->serverhops; bitchsay("Try joining a channel first");
return;
} }
for (b = new->bans; b; b = b->next)
ban_mem += sizeof(BanList);
} }
if (!ircops)
malloc_strcat(&ircops, empty_string); for (l = next_nicklist(new, NULL); l; l = next_nicklist(new, l))
if (do_hook(CHANNEL_STATS_LIST, "%s %s %s %ld %ld %ld %ld %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %d %s",
new->channel, my_ctime(new->channel_create.tv_sec), convert_time(now-new->join_time.tv_sec),
nick_mem+sizeof(ChannelList)+ban_mem, nick_mem,
(unsigned long)sizeof(ChannelList),ban_mem,
new->stats_ops, new->stats_dops, new->stats_bans, new->stats_unbans,
new->stats_topics, new->stats_kicks, new->stats_pubs, new->stats_parts,
new->stats_signoffs, new->stats_joins, new->totalbans, new->maxbans,
new->stats_sops, new->stats_sdops,new->stats_sbans, new->stats_sunbans,
usershere, usersaway, chanops, chanunop,new->totalnicks,new->maxnicks,
numircops, max_hops, ircops))
{ {
put_it("%s", convert_output_format("$G %CInformation for channel %K: %W$0", "%s", new->channel)); nick_mem += sizeof(NickList);
put_it("%s", convert_output_format("$G %CChannel created %K: %W$0 $1 $2 $3%n in memory %W$4-", "%s %s", convert_time(now-new->channel_create.tv_sec), my_ctime(new->join_time.tv_sec))); if (nick_isaway(l))
usersaway++;
else
usershere++;
if (nick_isircop(l))
{
numircops++;
malloc_strcat(&ircops, " (");
malloc_strcat(&ircops, l->nick);
malloc_strcat(&ircops, ")");
}
if (nick_isop(l))
chanops++;
else
chanunop++;
if (l->serverhops > max_hops)
max_hops = l->serverhops;
}
for (b = new->bans; b; b = b->next)
ban_mem += sizeof(BanList);
put_it("%s", convert_output_format(" MEM usage%K:%w Total%K:%w %c$0 bytes %K[%cNicks $1 b Chan $2 b Bans $3 b%K]", "%d %d %d %d", (int)(nick_mem+sizeof(ChannelList)+ban_mem), (int)nick_mem, (int)sizeof(ChannelList), (int)ban_mem)); if (do_hook(CHANNEL_STATS_LIST,
put_it("%s", convert_output_format("Ops %K[%W$[-5]0%K]%w De-Ops %K[%W$[-5]1%K]%w Bans %K[%W$[-5]2%K]%w Unbans %K[%W$[-5]3%K]%w", "%u %u %u %u", new->stats_ops, new->stats_dops, new->stats_bans, new->stats_unbans)); "%s %s %s %ld %ld %ld %ld %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %d %s",
put_it("%s", convert_output_format("Topics %K[%W$[-5]0%K]%w Kicks %K[%W$[-5]1%K]%w Publics %K[%W$[-5]2%K]%w Parts %K[%W$[-5]3%K]%w", "%u %u %u %u", new->stats_topics, new->stats_kicks, new->stats_pubs, new->stats_parts)); new->channel, my_ctime(new->channel_create.tv_sec), convert_time(time_since(&new->join_time)),
put_it("%s", convert_output_format("Signoffs %K[%W$[-5]0%K]%w Joins %K[%W$[-5]1%K]%w TotalBans %K[%W$[-5]2%K]%w MaxBans %K[%W$[-5]3%K]%w", "%u %u %u %u", new->stats_signoffs, new->stats_joins, new->totalbans, new->maxbans)); nick_mem+sizeof(ChannelList)+ban_mem, nick_mem,
put_it("%s", convert_output_format("ServOps %K[%W$[-5]0%K]%w ServDeop %K[%W$[-5]1%K]%w ServBans %K[%W$[-5]2%K]%w ServUB %K[%W$[-5]3%K]%w", "%u %u %u %u", new->stats_sops, new->stats_sdops,new->stats_sbans, new->stats_sunbans)); (unsigned long)sizeof(ChannelList),ban_mem,
put_it("%s", convert_output_format("Users Here %K[%W$[-5]0%K]%w Users Away %K[%W$[-5]1%K]%w Opped %K[%W$[-5]2%K]%w Unopped %K[%W$[-5]3%K]%w", "%u %u %u %u", usershere, usersaway, chanops, chanunop)); new->stats_ops, new->stats_dops, new->stats_bans, new->stats_unbans,
put_it("%s", convert_output_format("TotalNicks %K[%W$[-5]0%K]%w MaxNicks %K[%W$[-5]1%K]%w ServerHops %K[%W$[-5]2%K]%w", "%d %d %d", new->totalnicks,new->maxnicks, max_hops)); new->stats_topics, new->stats_kicks, new->stats_pubs, new->stats_parts,
put_it("%s", convert_output_format("IRCops %K[%W$[3]0%K]%w$1-", "%d %s", numircops, ircops)); new->stats_signoffs, new->stats_joins, new->totalbans, new->maxbans,
new->stats_sops, new->stats_sdops,new->stats_sbans, new->stats_sunbans,
usershere, usersaway, chanops, chanunop,new->totalnicks,new->maxnicks,
numircops, max_hops, ircops ? ircops : ""))
{
put_it("%s", convert_output_format("$G %CInformation for channel %K: %W$0", "%s", new->channel));
put_it("%s", convert_output_format("$G %CChannel created %K: %W$4-%n in memory %W$0 $1 $2 $3", "%s %s", convert_time(time_since(&new->join_time)), my_ctime(new->channel_create.tv_sec)));
put_it("%s", convert_output_format(" MEM usage%K:%w Total%K:%w %c$0 bytes %K[%cNicks $1 b Chan $2 b Bans $3 b%K]", "%d %d %d %d", (int)(nick_mem+sizeof(ChannelList)+ban_mem), (int)nick_mem, (int)sizeof(ChannelList), (int)ban_mem));
put_it("%s", convert_output_format("Ops %K[%W$[-5]0%K]%w De-Ops %K[%W$[-5]1%K]%w Bans %K[%W$[-5]2%K]%w Unbans %K[%W$[-5]3%K]%w", "%u %u %u %u", new->stats_ops, new->stats_dops, new->stats_bans, new->stats_unbans));
put_it("%s", convert_output_format("Topics %K[%W$[-5]0%K]%w Kicks %K[%W$[-5]1%K]%w Publics %K[%W$[-5]2%K]%w Parts %K[%W$[-5]3%K]%w", "%u %u %u %u", new->stats_topics, new->stats_kicks, new->stats_pubs, new->stats_parts));
put_it("%s", convert_output_format("Signoffs %K[%W$[-5]0%K]%w Joins %K[%W$[-5]1%K]%w TotalBans %K[%W$[-5]2%K]%w MaxBans %K[%W$[-5]3%K]%w", "%u %u %u %u", new->stats_signoffs, new->stats_joins, new->totalbans, new->maxbans));
put_it("%s", convert_output_format("ServOps %K[%W$[-5]0%K]%w ServDeop %K[%W$[-5]1%K]%w ServBans %K[%W$[-5]2%K]%w ServUB %K[%W$[-5]3%K]%w", "%u %u %u %u", new->stats_sops, new->stats_sdops,new->stats_sbans, new->stats_sunbans));
put_it("%s", convert_output_format("Users Here %K[%W$[-5]0%K]%w Users Away %K[%W$[-5]1%K]%w Opped %K[%W$[-5]2%K]%w Unopped %K[%W$[-5]3%K]%w", "%u %u %u %u", usershere, usersaway, chanops, chanunop));
put_it("%s", convert_output_format("TotalNicks %K[%W$[-5]0%K]%w MaxNicks %K[%W$[-5]1%K]%w ServerHops %K[%W$[-5]2%K]%w", "%d %d %d", new->totalnicks,new->maxnicks, max_hops));
put_it("%s", convert_output_format("IRCops %K[%W$[3]0%K]%w$1-", "%d %s", numircops, ircops ? ircops : ""));
put_it("%s", convert_output_format(" %CThere is %R$0%C limit and limit checking is %R$1-", "%s %s", new->limit ? ltoa(new->limit): "no", new->tog_limit?"Enabled":"Disabled")); put_it("%s", convert_output_format(" %CThere is %R$0%C limit and limit checking is %R$1-", "%s %s", new->limit ? ltoa(new->limit): "no", new->tog_limit?"Enabled":"Disabled"));
put_it("%s", convert_output_format(" %CIdle user check is %K[%R$0-%K]", "%s", new->check_idle?"Enabled":"Disabled")); put_it("%s", convert_output_format(" %CIdle user check is %K[%R$0-%K]", "%s", new->check_idle?"Enabled":"Disabled"));
/*put_it("%s", convert_output_format("$G End of channel stats for $0", "%s", new->channel));*/ /*put_it("%s", convert_output_format("$G End of channel stats for $0", "%s", new->channel));*/
/* wtf is do_scan in the channel struct */ /* wtf is do_scan in the channel struct */
} }
new_free(&ircops); new_free(&ircops);
} }
void update_stats(int what, NickList *nick, ChannelList *chan, int splitter) void update_stats(int what, NickList *nick, ChannelList *chan, int splitter)
@@ -4676,14 +4663,15 @@ ChannelList *chan = NULL;
char *BX_make_channel (char *chan) char *BX_make_channel (char *chan)
{ {
static char buffer[IRCD_BUFFER_SIZE+1]; static char buffer[IRCD_BUFFER_SIZE+1];
*buffer = 0;
if (!chan) if (!chan)
return NULL; return NULL;
if (*chan != '#' && *chan != '&' && *chan != '+' && *chan != '!') if (*chan != '#' && *chan != '&' && *chan != '+' && *chan != '!')
snprintf(buffer, IRCD_BUFFER_SIZE-2, "#%s", chan); snprintf(buffer, sizeof buffer, "#%s", chan);
else else
strlcpy(buffer, chan, sizeof buffer); strlcpy(buffer, chan, sizeof buffer);
return buffer; return buffer;
} }

View File

@@ -77,7 +77,7 @@ extern int BX_read_sockets();
extern int identd; extern int identd;
extern int doing_notice; extern int doing_notice;
int (*serv_open_func) (int, unsigned long, int); extern int (*serv_open_func) (int, unsigned long, int);
extern int (*serv_output_func) (int, int, char *, int); extern int (*serv_output_func) (int, int, char *, int);
extern int (*serv_input_func) (int, char *, int, int, int); extern int (*serv_input_func) (int, char *, int, int, int);
extern int (*serv_close_func) (int, unsigned long, int); extern int (*serv_close_func) (int, unsigned long, int);

View File

@@ -349,19 +349,16 @@ int BX_dgets (char *str, int des, int buffer, int buffersize, void *ssl_fd)
/* /*
* Slurp up the data that is available into 'str'. * Slurp up the data that is available into 'str'.
*/ */
while (ioe->read_pos < ioe->write_pos) while (ioe->read_pos < ioe->write_pos && cnt < (buffersize - 1))
{ {
if (((str[cnt] = ioe->buffer[ioe->read_pos++])) == '\n') if ((str[cnt++] = ioe->buffer[ioe->read_pos++]) == '\n')
break;
cnt++;
if (cnt >= buffersize-1)
break; break;
} }
/* /*
* Terminate it * Terminate it
*/ */
str[cnt + 1] = 0; str[cnt] = 0;
/* /*
* If we end in a newline, then all is well. * If we end in a newline, then all is well.
@@ -369,8 +366,8 @@ int BX_dgets (char *str, int des, int buffer, int buffersize, void *ssl_fd)
* The caller then would need to do a strlen() to get * The caller then would need to do a strlen() to get
* the amount of data. * the amount of data.
*/ */
if (str[cnt] == '\n') if (cnt > 0 && str[cnt - 1] == '\n')
return cnt; return cnt - 1;
else else
return 0; return 0;
} }

View File

@@ -66,7 +66,6 @@ void show_server_map (void);
int stats_k_grep (char **); int stats_k_grep (char **);
void who_handlekill (char *, char *, char *); void who_handlekill (char *, char *, char *);
void handle_tracekill (int, char *, char *, char *); void handle_tracekill (int, char *, char *, char *);
int no_hook_notify;
extern AJoinList *ajoin_list; extern AJoinList *ajoin_list;
void remove_from_server_list (int); void remove_from_server_list (int);

View File

@@ -285,15 +285,13 @@ int annoy_kicks(int list_type, char *to, char *from, char *ptr, NickList *nick)
* begins with MULTI_CHANNEL and has no '*', or STRING_CHANNEL, then its a * begins with MULTI_CHANNEL and has no '*', or STRING_CHANNEL, then its a
* channel * channel
*/ */
int BX_is_channel(char *to) int BX_is_channel(const char *to)
{ {
if (!to || !*to) return to &&
return 0; (*to == MULTI_CHANNEL ||
*to == STRING_CHANNEL ||
return ( (to) && ((*to == MULTI_CHANNEL) *to == ID_CHANNEL ||
|| (*to == STRING_CHANNEL) *to == LOCAL_CHANNEL);
|| (*to == ID_CHANNEL)
|| (*to == LOCAL_CHANNEL)));
} }