Move /BIP to bip_strcat{,f}_fit memccpy wrapper

instead of snprintf.
This commit is contained in:
Loïc Gomez 2022-01-06 13:43:18 +01:00 committed by Pierre-Louis Bonicoli
parent 399a104d1e
commit 34b3c4b0c3
Signed by: pilou
GPG Key ID: 06914C4A5EDAA6DD
3 changed files with 312 additions and 152 deletions

380
src/bip.c
View File

@ -1178,12 +1178,14 @@ void check_rlimits()
#define RET_STR_LEN 256 #define RET_STR_LEN 256
#define LINE_SIZE_LIM 70 #define LINE_SIZE_LIM 70
void adm_print_connection(struct link_client *ic, struct link *lnk, void adm_print_connection(struct link_client *ic, struct link *lnk,
struct bipuser *bu) struct bipuser *bu)
{ {
hash_iterator_t lit; hash_iterator_t lit;
char buf[RET_STR_LEN + 1]; char buf[LINE_SIZE_LIM + 1];
int t_written = 0; char *bufpos = buf;
size_t remaining = LINE_SIZE_LIM;
if (!bu) if (!bu)
bu = lnk->user; bu = lnk->user;
@ -1194,136 +1196,195 @@ void adm_print_connection(struct link_client *ic, struct link *lnk,
(lnk->connect_nick ? lnk->connect_nick : bu->default_nick), (lnk->connect_nick ? lnk->connect_nick : bu->default_nick),
(lnk->username ? lnk->username : bu->default_username)); (lnk->username ? lnk->username : bu->default_username));
t_written = snprintf(buf, RET_STR_LEN, " Options:"); bufpos = bip_strcat_fit(&remaining, bufpos, " Options:");
if (t_written >= RET_STR_LEN) // This should not happen, unless LINE_SIZE_LIM is too low
goto noroom; if (!bufpos)
goto limittoolow;
if (lnk->follow_nick) { if (lnk->follow_nick) {
t_written += snprintf(buf + t_written, bufpos = bip_strcat_fit(&remaining, bufpos, " follow_nick");
RET_STR_LEN - t_written, " follow_nick"); if (!bufpos) {
if (t_written >= RET_STR_LEN) buf[LINE_SIZE_LIM] = 0;
goto noroom; bip_notify(ic, "%s", buf);
remaining = LINE_SIZE_LIM;
bufpos = bip_strcat_fit(&remaining, bufpos, " follow_nick");
if (!bufpos)
goto limittoolow;
}
} }
if (lnk->ignore_first_nick) { if (lnk->ignore_first_nick) {
t_written += snprintf(buf + t_written, bufpos = bip_strcat_fit(&remaining, bufpos, " ignore_first_nick");
RET_STR_LEN - t_written, " ignore_first_nick"); if (!bufpos) {
if (t_written >= RET_STR_LEN) buf[LINE_SIZE_LIM] = 0;
goto noroom; bip_notify(ic, "%s", buf);
remaining = LINE_SIZE_LIM;
bufpos = bip_strcat_fit(&remaining, bufpos, " ignore_first_nick");
if (!bufpos)
goto limittoolow;
}
} }
if (lnk->away_nick) { if (lnk->away_nick) {
t_written += snprintf(buf + t_written, bufpos = bip_strcatf_fit(&remaining, bufpos, " away_nick=%s", lnk->away_nick);
RET_STR_LEN - t_written, " away_nick=%s", if (!bufpos) {
lnk->away_nick); buf[LINE_SIZE_LIM] = 0;
if (t_written >= RET_STR_LEN) bip_notify(ic, "%s", buf);
goto noroom; remaining = LINE_SIZE_LIM;
bufpos = bip_strcatf_fit(&remaining, bufpos, " away_nick=%s", lnk->away_nick);
if (!bufpos)
goto limittoolow;
}
} }
if (lnk->no_client_away_msg) { if (lnk->no_client_away_msg) {
t_written += snprintf(buf + t_written, bufpos = bip_strcatf_fit(&remaining, bufpos, " no_client_away_msg=%s", lnk->no_client_away_msg);
RET_STR_LEN - t_written, " no_client_away_msg=%s", if (!bufpos) {
lnk->no_client_away_msg); buf[LINE_SIZE_LIM] = 0;
if (t_written >= RET_STR_LEN) bip_notify(ic, "%s", buf);
goto noroom; remaining = LINE_SIZE_LIM;
bufpos = bip_strcatf_fit(&remaining, bufpos, " no_client_away_msg=%s", lnk->no_client_away_msg);
if (!bufpos)
goto limittoolow;
}
} }
if (lnk->vhost) { if (lnk->vhost) {
t_written += snprintf(buf + t_written, bufpos = bip_strcatf_fit(&remaining, bufpos, " vhost=%s", lnk->vhost);
RET_STR_LEN - t_written, " vhost=%s", if (!bufpos) {
lnk->vhost); buf[LINE_SIZE_LIM] = 0;
if (t_written >= RET_STR_LEN) bip_notify(ic, "%s", buf);
goto noroom; remaining = LINE_SIZE_LIM;
bufpos = bip_strcatf_fit(&remaining, bufpos, " vhost=%s", lnk->vhost);
if (!bufpos)
goto limittoolow;
}
} }
if (lnk->bind_port) { if (lnk->bind_port) {
t_written += snprintf(buf + t_written, bufpos = bip_strcatf_fit(&remaining, bufpos, " bind_port=%s", lnk->bind_port);
RET_STR_LEN - t_written, " bind_port=%u", if (!bufpos) {
lnk->bind_port); buf[LINE_SIZE_LIM] = 0;
if (t_written >= RET_STR_LEN) bip_notify(ic, "%s", buf);
goto noroom; remaining = LINE_SIZE_LIM;
bufpos = bip_strcatf_fit(&remaining, bufpos, " bind_port=%s", lnk->bind_port);
if (!bufpos)
goto limittoolow;
}
} }
noroom: /* that means the line is larger that RET_STR_LEN. We're not likely to buf[LINE_SIZE_LIM] = 0;
even read such a long line */
buf[RET_STR_LEN] = 0;
bip_notify(ic, "%s", buf); bip_notify(ic, "%s", buf);
remaining = LINE_SIZE_LIM;
bufpos = buf;
list_iterator_t itocs;
for (list_it_init(&lnk->on_connect_send, &itocs);
list_it_item(&itocs); ) {
bufpos = bip_strcatf_fit(&remaining, bufpos, "%s",
(char *)list_it_item(&itocs));
if (!bufpos) {
// if oversized, print and reset
buf[LINE_SIZE_LIM] = 0;
bip_notify(ic, "%s", buf);
remaining = LINE_SIZE_LIM;
bufpos = buf;
continue;
} else {
// if ok, go to next item
list_it_next(&itocs);
}
}
buf[LINE_SIZE_LIM] = 0;
bip_notify(ic, "%s", buf);
remaining = LINE_SIZE_LIM;
bufpos = buf;
// TODO: on_connect_send
// TODO : check channels struct // TODO : check channels struct
t_written = snprintf(buf, RET_STR_LEN, " Channels (* with key, ` no backlog)"); bufpos = bip_strcat_fit(&remaining, bufpos, " Channels (* with key, ` no backlog)");
if (t_written >= RET_STR_LEN) if (!bufpos)
goto noroomchan; goto limittoolow;
for (hash_it_init(&lnk->chan_infos, &lit); hash_it_item(&lit); for (hash_it_init(&lnk->chan_infos, &lit); hash_it_item(&lit);
hash_it_next(&lit)) { hash_it_next(&lit)) {
struct chan_info *ch = hash_it_item(&lit); struct chan_info *ch = hash_it_item(&lit);
t_written += snprintf(buf + t_written, RET_STR_LEN - t_written, " %s%s%s", bufpos = bip_strcatf_fit(&remaining, bufpos, "%s%s%s",
ch->name, (ch->key ? "*" : ""), ch->name, (ch->key ? "*" : ""),
(ch->backlog ? "" : "`")); (ch->backlog ? "" : "`"));
if (t_written > LINE_SIZE_LIM) { if (!bufpos) {
buf[RET_STR_LEN] = 0; buf[LINE_SIZE_LIM] = 0;
bip_notify(ic, "%s", buf); bip_notify(ic, "%s", buf);
t_written = 0; remaining = LINE_SIZE_LIM;
bufpos = buf;
} }
} }
noroomchan:
buf[RET_STR_LEN] = 0;
bip_notify(ic, "%s", buf);
t_written = snprintf(buf, RET_STR_LEN, " Status: "); buf[LINE_SIZE_LIM] = 0;
if (t_written >= RET_STR_LEN) bip_notify(ic, "%s", buf);
goto noroomstatus; remaining = LINE_SIZE_LIM;
bufpos = buf;
bufpos = bip_strcat_fit(&remaining, bufpos, " Status: ");
if (!bufpos)
goto limittoolow;
switch (lnk->s_state) { switch (lnk->s_state) {
case IRCS_NONE: case IRCS_NONE:
t_written += snprintf(buf + t_written, RET_STR_LEN - t_written, bufpos = bip_strcat_fit(&remaining, bufpos, "not started");
"not started"); if (!bufpos)
if (t_written >= RET_STR_LEN) goto limittoolow;
goto noroomstatus;
break; break;
case IRCS_CONNECTING: case IRCS_CONNECTING:
t_written += snprintf(buf + t_written, RET_STR_LEN - t_written, bufpos = bip_strcatf_fit(&remaining, bufpos,
"connecting... attempts: %d, last: %s", "connecting... attempts: %d, last: %s",
lnk->s_conn_attempt, lnk->s_conn_attempt,
hrtime(lnk->last_connection_attempt)); hrtime(lnk->last_connection_attempt));
if (t_written >= RET_STR_LEN) if (!bufpos)
goto noroomstatus; goto noroomstatus;
break; break;
case IRCS_CONNECTED: case IRCS_CONNECTED:
t_written += snprintf(buf + t_written, RET_STR_LEN - t_written, bufpos = bip_strcat_fit(&remaining, bufpos, "connected !");
"connected !"); if (!bufpos)
if (t_written >= RET_STR_LEN) goto limittoolow;
goto noroomstatus;
break; break;
case IRCS_WAS_CONNECTED: case IRCS_WAS_CONNECTED:
t_written += snprintf(buf + t_written, RET_STR_LEN - t_written, bufpos = bip_strcatf_fit(&remaining, bufpos,
"disconnected, attempts: %d, last: %s", "disconnected, attempts: %d, last: %s",
lnk->s_conn_attempt, lnk->s_conn_attempt,
hrtime(lnk->last_connection_attempt)); hrtime(lnk->last_connection_attempt));
if (t_written >= RET_STR_LEN) if (!bufpos)
goto noroomstatus; goto noroomstatus;
break; break;
case IRCS_RECONNECTING: case IRCS_RECONNECTING:
t_written += snprintf(buf + t_written, RET_STR_LEN - t_written, bufpos = bip_strcatf_fit(&remaining, bufpos,
"reconnecting... attempts: %d, last: %s", "reconnecting... attempts: %d, last: %s",
lnk->s_conn_attempt, lnk->s_conn_attempt,
hrtime(lnk->last_connection_attempt)); hrtime(lnk->last_connection_attempt));
if (t_written >= RET_STR_LEN) if (!bufpos)
goto noroomstatus; goto noroomstatus;
break; break;
case IRCS_TIMER_WAIT: case IRCS_TIMER_WAIT:
t_written += snprintf(buf + t_written, RET_STR_LEN - t_written, bufpos = bip_strcatf_fit(&remaining, bufpos,
"waiting to reconnect, attempts: %d, last: %s", "waiting to reconnect, attempts: %d, last: %s",
lnk->s_conn_attempt, lnk->s_conn_attempt,
hrtime(lnk->last_connection_attempt)); hrtime(lnk->last_connection_attempt));
if (t_written >= RET_STR_LEN) if (!bufpos)
goto noroomstatus; goto noroomstatus;
break; break;
default: default:
t_written += snprintf(buf + t_written, RET_STR_LEN - t_written, bufpos = bip_strcat_fit(&remaining, bufpos, "unknown");
"unknown"); if (!bufpos)
if (t_written >= RET_STR_LEN) goto limittoolow;
goto noroomstatus;
break; break;
// s_conn_attempt recon_timer last_connection_attempt // s_conn_attempt recon_timer last_connection_attempt
} }
noroomstatus: buf[LINE_SIZE_LIM] = 0;
buf[RET_STR_LEN] = 0;
bip_notify(ic, "%s", buf); bip_notify(ic, "%s", buf);
return;
noroomstatus:
buf[LINE_SIZE_LIM] = 0;
bip_notify(ic, "%stoo long to print", buf);
return;
limittoolow:
bip_notify(ic, "cannot print connection, LINE_SIZE_LIM(%d) "
"is too low (please recompile)", LINE_SIZE_LIM);
return;
} }
void adm_list_all_links(struct link_client *ic) void adm_list_all_links(struct link_client *ic)
@ -1359,8 +1420,6 @@ void adm_list_all_connections(struct link_client *ic)
void adm_info_user(struct link_client *ic, const char *name) void adm_info_user(struct link_client *ic, const char *name)
{ {
struct bipuser *u; struct bipuser *u;
char buf[RET_STR_LEN + 1];
int t_written = 0;
bip_notify(ic, "-- User '%s' info", name); bip_notify(ic, "-- User '%s' info", name);
u = hash_get(&_bip->users, name); u = hash_get(&_bip->users, name);
@ -1369,20 +1428,7 @@ void adm_info_user(struct link_client *ic, const char *name)
return; return;
} }
t_written += snprintf(buf + t_written, RET_STR_LEN - t_written, bip_notify(ic, "user: %s%s", u->name, (u->admin ? ", is bip admin" : ""));
"user: %s", u->name);
if (t_written >= RET_STR_LEN)
goto noroom;
if (u->admin) {
t_written += snprintf(buf + t_written, RET_STR_LEN - t_written,
", is bip admin");
if (t_written >= RET_STR_LEN)
goto noroom;
}
noroom:
buf[RET_STR_LEN] = 0;
bip_notify(ic, "%s", buf);
#ifdef HAVE_LIBSSL #ifdef HAVE_LIBSSL
if (u->ssl_check_store) { if (u->ssl_check_store) {
@ -1421,48 +1467,64 @@ void adm_list_users(struct link_client *ic)
{ {
hash_iterator_t it; hash_iterator_t it;
hash_iterator_t lit; hash_iterator_t lit;
char buf[RET_STR_LEN + 1]; char buf[LINE_SIZE_LIM + 1];
size_t remaining = LINE_SIZE_LIM;
bip_notify(ic, "-- User list"); bip_notify(ic, "-- User list");
for (hash_it_init(&_bip->users, &it); hash_it_item(&it); for (hash_it_init(&_bip->users, &it); hash_it_item(&it);
hash_it_next(&it)) { hash_it_next(&it)) {
struct bipuser *u = hash_it_item(&it); struct bipuser *u = hash_it_item(&it);
int first = 1; int first = 1;
int t_written = 0; char *bufpos = buf;
buf[RET_STR_LEN] = 0; bufpos = bip_strcatf_fit(&remaining, bufpos, "* %s%s:", u->name,
t_written += snprintf(buf, RET_STR_LEN, "* %s%s:", u->name,
(u->admin ? "(admin)": "")); (u->admin ? "(admin)": ""));
if (t_written >= RET_STR_LEN) // this should not happen or LINE_SIZE_LIM is really low...
goto noroom; if (!bufpos)
for (hash_it_init(&u->connections, &lit); hash_it_item(&lit); goto limittoolow;
hash_it_next(&lit)) { for (hash_it_init(&u->connections, &lit); hash_it_item(&lit); ) {
struct link *lnk = hash_it_item(&lit); struct link *lnk = hash_it_item(&lit);
if (first) { if (first) {
first = 0; first = 0;
} else { } else {
t_written += snprintf(buf + t_written, bufpos = bip_strcat_fit(&remaining, bufpos, ",");
RET_STR_LEN - t_written, ","); // if this is too long for a comma, print and prefix with spaces
if (t_written >= RET_STR_LEN) if (!bufpos) {
goto noroom; buf[LINE_SIZE_LIM] = 0;
bip_notify(ic, "%s", buf);
remaining = LINE_SIZE_LIM;
bufpos = bip_strcat_fit(&remaining, buf, " ");;
// this should not happen or LINE_SIZE_LIM is really low...
if (!bufpos)
goto limittoolow;
}
} }
t_written += snprintf(buf + t_written, bufpos = bip_strcatf_fit(&remaining, bufpos, " %s", lnk->name);
RET_STR_LEN - t_written, if (!bufpos) {
" %s", lnk->name); // if this is too long, print and reset
if (t_written >= RET_STR_LEN) buf[LINE_SIZE_LIM] = 0;
goto noroom;
if (t_written > LINE_SIZE_LIM) {
buf[RET_STR_LEN] = 0;
bip_notify(ic, "%s", buf); bip_notify(ic, "%s", buf);
t_written = 0; remaining = LINE_SIZE_LIM;
bufpos = bip_strcat_fit(&remaining, buf, " ");;
// this should not happen or LINE_SIZE_LIM is really low...
if (!bufpos)
goto limittoolow;
} else {
// if all good, go to next entry
hash_it_next(&lit);
} }
} }
noroom: buf[LINE_SIZE_LIM] = 0;
buf[RET_STR_LEN] = 0;
bip_notify(ic, "%s", buf); bip_notify(ic, "%s", buf);
remaining = LINE_SIZE_LIM;
bufpos = buf;
} }
bip_notify(ic, "-- End of User list"); bip_notify(ic, "-- End of User list");
return;
limittoolow:
bip_notify(ic, "cannot print users, LINE_SIZE_LIM(%d) "
"is too low (please recompile)", LINE_SIZE_LIM);
} }
void adm_list_networks(struct link_client *ic) void adm_list_networks(struct link_client *ic)
@ -1474,38 +1536,53 @@ void adm_list_networks(struct link_client *ic)
for (hash_it_init(&_bip->networks, &it); hash_it_item(&it); for (hash_it_init(&_bip->networks, &it); hash_it_item(&it);
hash_it_next(&it)) { hash_it_next(&it)) {
struct network *n = hash_it_item(&it); struct network *n = hash_it_item(&it);
int t_written = 0;
int i; int i;
char *bufpos = buf;
size_t remaining = RET_STR_LEN;
buf[RET_STR_LEN] = 0;
#ifdef HAVE_LIBSSL #ifdef HAVE_LIBSSL
if (n->ssl) { if (n->ssl) {
t_written += snprintf(buf, RET_STR_LEN, "- %s*:", bufpos = bip_strcatf_fit(&remaining, bufpos, "- %s*:",
n->name); n->name);
if (t_written >= RET_STR_LEN)
goto noroom;
} else { } else {
#endif #endif
t_written += snprintf(buf, RET_STR_LEN, "- %s:", n->name); bufpos = bip_strcatf_fit(&remaining, bufpos, "- %s:",
if (t_written >= RET_STR_LEN) n->name);
goto noroom;
#ifdef HAVE_LIBSSL #ifdef HAVE_LIBSSL
} }
#endif #endif
for (i = 0; i < n->serverc; i++) { // if we've reached max length, print name and reset
// honestly, this should not happen, but for the sake of cleanliness...
if (!bufpos) {
#ifdef HAVE_LIBSSL
if (n->ssl) {
bip_notify(ic, "- %s*:", n->name);
} else {
#endif
bip_notify(ic, "- %s:", n->name);
#ifdef HAVE_LIBSSL
}
#endif
bufpos = buf;
remaining = RET_STR_LEN;
}
for (i = 0; i < n->serverc; ) {
struct server *serv = i+n->serverv; struct server *serv = i+n->serverv;
t_written += snprintf(buf + t_written, RET_STR_LEN bufpos = bip_strcatf_fit(&remaining, bufpos, " %s:%d",
- t_written, " %s:%d", serv->host, serv->host, serv->port);
serv->port); if (!bufpos) {
if (t_written >= RET_STR_LEN) // if line is too long, print and reset
goto noroom;
if (t_written > LINE_SIZE_LIM) {
buf[RET_STR_LEN] = 0; buf[RET_STR_LEN] = 0;
bip_notify(ic, "%s", buf); bip_notify(ic, "%s", buf);
t_written = 0; remaining = RET_STR_LEN;
bufpos = buf;
i--;
} else {
// if ok, go to next server
i++;
} }
} }
noroom:
buf[RET_STR_LEN] = 0; buf[RET_STR_LEN] = 0;
bip_notify(ic, "%s", buf); bip_notify(ic, "%s", buf);
} }
@ -1751,8 +1828,9 @@ void set_on_connect_send(struct link_client *ic, char *val)
void adm_on_connect_send(struct link_client *ic, struct line *line, void adm_on_connect_send(struct link_client *ic, struct line *line,
unsigned int privmsg) unsigned int privmsg)
{ {
size_t remaining = ON_CONNECT_MAX_STRSIZE;
char buf[ON_CONNECT_MAX_STRSIZE]; char buf[ON_CONNECT_MAX_STRSIZE];
int t_written = 0; char *bufpos = buf;
int i; int i;
if (!line) { if (!line) {
@ -1760,30 +1838,32 @@ void adm_on_connect_send(struct link_client *ic, struct line *line,
return; return;
} }
if (irc_line_includes(line, 2)) if (!irc_line_includes(line, 2)) {
mylog(LOG_DEBUG, "[%s] not enough parameters on /BIP on_connect_send",
LINK(ic)->user->name);
return; return;
}
for (i = privmsg + 2; i < irc_line_count(line); i++) { for (i = privmsg + 2; i < irc_line_count(line); i++) {
if (t_written) { mylog(LOG_DEBUG, "[%s] processing item %d, remaining %ld, %s",
t_written += snprintf(buf, LINK(ic)->user->name, i, remaining, buf);
ON_CONNECT_MAX_STRSIZE - 1 - t_written, if ((unsigned int)i > privmsg + 2)
" %s", irc_line_elem(line, i)); bufpos = bip_strcatf_fit(&remaining, bufpos, " %s",
if (t_written >= ON_CONNECT_MAX_STRSIZE) irc_line_elem(line, i));
goto noroom; else
} else { bufpos = bip_strcat_fit(&remaining, bufpos,
t_written = snprintf(buf, ON_CONNECT_MAX_STRSIZE - 1, (char *)irc_line_elem(line, i));
"%s", irc_line_elem(line, i)); mylog(LOG_DEBUG, "[%s] processed item %d, remaining %ld, %s",
if (t_written >= ON_CONNECT_MAX_STRSIZE) LINK(ic)->user->name, i, remaining, buf);
goto noroom; if (!bufpos) {
bip_notify(ic, "on connect send string too big, not changing.");
return;
} }
} }
ok:
buf[ON_CONNECT_MAX_STRSIZE - 1] = 0; buf[ON_CONNECT_MAX_STRSIZE - 1] = 0;
set_on_connect_send(ic, buf); set_on_connect_send(ic, buf);
return; return;
noroom:
bip_notify(ic, "on connect send string too big, truncated");
goto ok;
} }
void adm_away_nick(struct link_client *ic, const char *val) void adm_away_nick(struct link_client *ic, const char *val)
@ -1958,7 +2038,7 @@ int adm_bip(bip_t *bip, struct link_client *ic, struct line *line, int privmsg)
mylog(LOG_INFO, "/BIP %s from %s", irc_line_elem(line, privmsg + 1), mylog(LOG_INFO, "/BIP %s from %s", irc_line_elem(line, privmsg + 1),
LINK(ic)->user->name); LINK(ic)->user->name);
if (strcasecmp(irc_line_elem(line, privmsg + 1), "RELOAD") == 0) { if (irc_line_elem_case_equals(line, privmsg + 1, "RELOAD")) {
if (!admin) { if (!admin) {
bip_notify(ic, "-- You're not allowed to reload bip"); bip_notify(ic, "-- You're not allowed to reload bip");
return OK_FORGET; return OK_FORGET;
@ -1966,7 +2046,7 @@ int adm_bip(bip_t *bip, struct link_client *ic, struct line *line, int privmsg)
bip_notify(ic, "-- Reloading bip..."); bip_notify(ic, "-- Reloading bip...");
bip->reloading_client = ic; bip->reloading_client = ic;
sighup = 1; sighup = 1;
} else if (strcasecmp(irc_line_elem(line, privmsg + 1), "LIST") == 0) { } else if (irc_line_elem_case_equals(line, privmsg + 1, "LIST")) {
if (irc_line_count(line) != privmsg + 3) { if (irc_line_count(line) != privmsg + 3) {
bip_notify(ic, "-- LIST command needs one argument"); bip_notify(ic, "-- LIST command needs one argument");
return OK_FORGET; return OK_FORGET;
@ -1990,10 +2070,10 @@ int adm_bip(bip_t *bip, struct link_client *ic, struct line *line, int privmsg)
} else { } else {
bip_notify(ic, "-- Invalid LIST request"); bip_notify(ic, "-- Invalid LIST request");
} }
} else if (strcasecmp(irc_line_elem(line, privmsg + 1), "INFO") == 0) { } else if (irc_line_elem_case_equals(line, privmsg + 1, "INFO")) {
if (!irc_line_includes(line, privmsg + 2)) { if (!irc_line_includes(line, privmsg + 3)) {
bip_notify(ic, "-- INFO command needs at least one " bip_notify(ic, "-- INFO command needs at least two "
"argument"); "arguments");
return OK_FORGET; return OK_FORGET;
} }

View File

@ -2,7 +2,8 @@
* $Id: util.c,v 1.60 2005/04/12 19:34:35 nohar Exp $ * $Id: util.c,v 1.60 2005/04/12 19:34:35 nohar Exp $
* *
* This file is part of the bip project * This file is part of the bip project
* Copyright (C) 2004 2005 Arnaud Cornet and Loïc Gomez * Copyright (C) 2004,2005 Arnaud Cornet
* Copyright (C) 2004,2005,2022 Loïc Gomez
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -81,6 +82,82 @@ char *bip_strdup(const char *str)
return r; return r;
} }
char *bip_strcat_fit(size_t *remaining, char *str, const char *str2)
{
char *res;
if (!remaining || !str || !str2) {
mylog(LOG_DEBUGVERB, "bip_strcat_fit: got NULL pointer");
return NULL;
}
res = memccpy(str, str2, '\0', *remaining);
if (!res) {
mylog(LOG_DEBUGTOOMUCH, "bip_strcat_fit: memccpy() failed, remaining %lu",
*remaining);
return NULL;
}
res--;
if (res < str) {
mylog(LOG_DEBUG, "bip_strcat_fit: memccpy res < str");
return NULL;
}
(*remaining) -= (size_t)(res - str);
return res;
}
#define STRCATF_BUF_MAXLEN 1024
char *bip_strcatf_fit(size_t *remaining, char *str, const char *fmt, ...)
{
va_list ap;
char str2[STRCATF_BUF_MAXLEN + 1];
int written;
char *res = NULL;
if (!remaining || !str || !fmt) {
mylog(LOG_DEBUGVERB, "bip_strcatf_fit: NULL pointer");
return NULL;
}
if (*remaining > STRCATF_BUF_MAXLEN) {
mylog(LOG_ERROR, "bip_strcatf_fit: remaining "
"is over STRCATF_BUF_MAXLEN");
}
va_start(ap, fmt);
str2[*remaining] = '\0';
written = vsnprintf(str2, *remaining, fmt, ap);
if (written < 0) {
mylog(LOG_ERROR, "bip_strcatf_fit: vsnprintf failed with: %s",
strerror(errno));
return NULL;
}
if ((unsigned)written >= *remaining) {
mylog(LOG_DEBUGVERB, "bip_strcatf_fit,vsnprintf: no space left");
goto end;
}
res = memccpy(str, str2, '\0', *remaining);
if (!res) {
mylog(LOG_DEBUGTOOMUCH, "bip_strcatf_fit: memccpy() failed, "
"remaining %lu", *remaining);
goto end;
}
if (res < str) {
mylog(LOG_DEBUG, "bip_strcatf_fit: memccpy res < str");
goto end;
}
res--;
(*remaining) -= (size_t)(res - str);
end:
va_end(ap);
return res;
}
/* /*
* <nick> ::= <letter> { <letter> | <number> | <special> } * <nick> ::= <letter> { <letter> | <number> | <special> }
* <special> ::= '-' | '[' | ']' | '\' | '`' | '^' | '{' | '}' * <special> ::= '-' | '[' | ']' | '\' | '`' | '^' | '{' | '}'

View File

@ -2,7 +2,8 @@
* $Id: util.h,v 1.35 2005/04/12 19:34:35 nohar Exp $ * $Id: util.h,v 1.35 2005/04/12 19:34:35 nohar Exp $
* *
* This file is part of the bip project * This file is part of the bip project
* Copyright (C) 2004 2005 Arnaud Cornet and Loïc Gomez * Copyright (C) 2004,2005 Arnaud Cornet
* Copyright (C) 2004,2005,2022 Loïc Gomez
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -175,6 +176,8 @@ void *bip_malloc(size_t size);
void *bip_calloc(size_t nmemb, size_t size); void *bip_calloc(size_t nmemb, size_t size);
void *bip_realloc(void *ptr, size_t size); void *bip_realloc(void *ptr, size_t size);
char *bip_strdup(const char *str); char *bip_strdup(const char *str);
char *bip_strcat_fit(size_t *remaining, char *str, const char *str2);
char *bip_strcatf_fit(size_t *remaining, char *str, const char *str2, ...);
#define array_each(a, idx, ptr) for ((idx) = 0; \ #define array_each(a, idx, ptr) for ((idx) = 0; \
(idx) < (a)->elemc && (((ptr) = array_get((a), (idx))) || 1); \ (idx) < (a)->elemc && (((ptr) = array_get((a), (idx))) || 1); \
(idx)++) (idx)++)