hirc

IRC client
Log | Files | Refs

commit c4464d8f4b577f76771979bbdab006bbb2a67af2
parent 1c4d5d61f72ffa322a7e321aa5434a430a1990d4
Author: hhvn <dev@hhvn.uk>
Date:   Sun, 15 May 2022 15:54:05 +0100

serv_write can do both send/schedule (replaces schedule_push)

Diffstat:
Msrc/commands.c | 89+++++++++++++++++++++++++++++++++----------------------------------------------
Msrc/handle.c | 17++++++++---------
Msrc/hirc.h | 6+++---
Msrc/main.c | 2+-
Msrc/serv.c | 74++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/struct.h | 7++++++-
6 files changed, 89 insertions(+), 106 deletions(-)

diff --git a/src/commands.c b/src/commands.c @@ -87,9 +87,9 @@ command_away) { if (all) { for (sp = servers; sp; sp = sp->next) - serv_write(sp, format, str); + serv_write(sp, Sched_connected, format, str); } else if (server) { - serv_write(server, format, str); + serv_write(server, Sched_connected, format, str); } else { ui_error("-one specified, but no server selected", NULL); } @@ -112,7 +112,7 @@ command_msg) { else chan = chan_get(&server->queries, target, -1); - serv_write(server, "PRIVMSG %s :%s\r\n", target, message); + serv_write(server, Sched_connected, "PRIVMSG %s :%s\r\n", target, message); if (chan) { hist_format(chan->history, Activity_self, HIST_SHOW|HIST_LOG|HIST_SELF, "PRIVMSG %s :%s", target, message); @@ -136,7 +136,7 @@ command_notice) { else chan = chan_get(&server->queries, target, -1); - serv_write(server, "NOTICE %s :%s\r\n", target, message); + serv_write(server, Sched_connected, "NOTICE %s :%s\r\n", target, message); if (chan) { hist_format(chan->history, Activity_self, HIST_SHOW|HIST_LOG|HIST_SELF, "NOTICE %s :%s", target, message); @@ -148,7 +148,7 @@ command_me) { if (!str) str = ""; - serv_write(server, "PRIVMSG %s :%cACTION %s%c\r\n", channel->name, 1, str, 1); + serv_write(server, Sched_connected, "PRIVMSG %s :%cACTION %s%c\r\n", channel->name, 1, str, 1); hist_format(channel->history, Activity_self, HIST_SHOW|HIST_LOG|HIST_SELF, "PRIVMSG %s :%cACTION %s%c", channel->name, 1, str, 1); } @@ -176,7 +176,7 @@ command_ctcp) { /* XXX: if we CTCP a channel, responses should go to that channel. * This requires more than just expect_set, so might never be * implemented. */ - serv_write(server, "PRIVMSG %s :%c%s%c\r\n", target, 1, ctcp, 1); + serv_write(server, Sched_connected, "PRIVMSG %s :%c%s%c\r\n", target, 1, ctcp, 1); if (chan) { hist_format(channel->history, Activity_self, HIST_SHOW|HIST_LOG|HIST_SELF, "PRIVMSG %s :%c%s%c", @@ -230,17 +230,7 @@ command_join) { else snprintf(msg, sizeof(msg), "JOIN %c%s\r\n", '#', str); - if (server->status == ConnStatus_connected) - serv_write(server, "%s", msg); - else - schedule_push(server, "376" /* RPL_ENDOFMOTD */, msg); - - /* Perhaps we should update expect from schedule? - * That'd make more sense if different stuff gets - * scheduled for events that happen at different times - * - * Actually, I think that would be a bad idea if schedule gets opened - * up to the user. Don't want automatic events triggering ui changes. */ + serv_write(server, Sched_connected, "%s", msg); expect_set(server, Expect_join, str); } @@ -267,7 +257,7 @@ command_part) { snprintf(msg, sizeof(msg), "PART %s :%s\r\n", chan, reason ? reason : config_gets("def.partmessage")); - serv_write(server, "%s", msg); + serv_write(server, Sched_connected, "%s", msg); expect_set(server, Expect_part, chan); } @@ -314,9 +304,9 @@ command_kick) { } if (reason) - serv_write(server, "KICK %s %s :%s\r\n", chan, nick, reason); + serv_write(server, Sched_connected, "KICK %s %s :%s\r\n", chan, nick, reason); else - serv_write(server, "KICK %s %s\r\n", chan, nick); + serv_write(server, Sched_connected, "KICK %s %s\r\n", chan, nick); } COMMAND( @@ -345,10 +335,10 @@ command_mode) { if (modes) { if (chan == channel->name) expect_set(server, Expect_nosuchnick, chan); - serv_write(server, "MODE %s %s\r\n", chan, modes); + serv_write(server, Sched_connected, "MODE %s %s\r\n", chan, modes); } else { expect_set(server, Expect_channelmodeis, chan); - serv_write(server, "MODE %s\r\n", chan); + serv_write(server, Sched_connected, "MODE %s\r\n", chan); } } @@ -364,7 +354,7 @@ command_nick) { return; } - serv_write(server, "NICK %s\r\n", str); + serv_write(server, Sched_now, "NICK %s\r\n", str); expect_set(server, Expect_nicknameinuse, str); } @@ -375,7 +365,7 @@ command_list) { return; } - serv_write(server, "LIST\r\n", str); + serv_write(server, Sched_connected, "LIST\r\n", str); } COMMAND( @@ -394,9 +384,9 @@ command_whois) { } if (tserver) - serv_write(server, "WHOIS %s :%s\r\n", tserver, nick); + serv_write(server, Sched_connected, "WHOIS %s :%s\r\n", tserver, nick); else - serv_write(server, "WHOIS %s\r\n", nick); + serv_write(server, Sched_connected, "WHOIS %s\r\n", nick); } COMMAND( @@ -404,7 +394,7 @@ command_who) { if (!str) str = "*"; /* wildcard */ - serv_write(server, "WHO %s\r\n", str); + serv_write(server, Sched_connected, "WHO %s\r\n", str); } COMMAND( @@ -420,11 +410,11 @@ command_whowas) { } if (tserver) - serv_write(server, "WHOWAS %s %s :%s\r\n", nick, count, tserver); + serv_write(server, Sched_connected, "WHOWAS %s %s :%s\r\n", nick, count, tserver); else if (count) - serv_write(server, "WHOWAS %s %s\r\n", nick, count); + serv_write(server, Sched_connected, "WHOWAS %s %s\r\n", nick, count); else - serv_write(server, "WHOWAS %s 5\r\n", nick); + serv_write(server, Sched_connected, "WHOWAS %s 5\r\n", nick); } COMMAND( @@ -434,7 +424,7 @@ command_ping) { return; } - serv_write(server, "PING :%s\r\n", str); + serv_write(server, Sched_now, "PING :%s\r\n", str); expect_set(server, Expect_pong, str); } @@ -447,12 +437,7 @@ command_quote) { return; } - if (server->status == ConnStatus_connected) { - serv_write(server, "%s\r\n", str); - } else { - snprintf(msg, sizeof(msg), "%s\r\n", str); - schedule_push(server, "376" /* RPL_ENDOFMOTD */, msg); - } + serv_write(server, Sched_connected, "%s\r\n", str); } COMMAND( @@ -856,7 +841,7 @@ command_names) { return; } - serv_write(server, "NAMES %s\r\n", chan); + serv_write(server, Sched_connected, "NAMES %s\r\n", chan); expect_set(server, Expect_names, chan); } @@ -902,14 +887,14 @@ command_topic) { command_toomany("topic"); return; } - serv_write(server, "TOPIC %s :\r\n", chan); + serv_write(server, Sched_connected, "TOPIC %s :\r\n", chan); return; } if (!topic) { - serv_write(server, "TOPIC %s\r\n", chan); + serv_write(server, Sched_connected, "TOPIC %s\r\n", chan); expect_set(server, Expect_topic, chan); - } else serv_write(server, "TOPIC %s :%s\r\n", chan, topic); + } else serv_write(server, Sched_connected, "TOPIC %s :%s\r\n", chan, topic); } COMMAND( @@ -931,7 +916,7 @@ command_oper) { user = server->self->nick; } - serv_write(server, "OPER %s %s\r\n", user, pass); + serv_write(server, Sched_connected, "OPER %s %s\r\n", user, pass); } static void @@ -939,7 +924,7 @@ command_send0(struct Server *server, char *cmd, char *cmdname, char *str) { if (str) command_toomany(cmdname); else - serv_write(server, "%s\r\n", cmd); + serv_write(server, Sched_connected, "%s\r\n", cmd); } COMMAND( @@ -957,9 +942,9 @@ command_send1(struct Server *server, char *cmd, char *cmdname, char *str) { if (str && strchr(str, ' ')) command_toomany(cmdname); else if (str) - serv_write(server, "%s %s\r\n", cmd, str); + serv_write(server, Sched_connected, "%s %s\r\n", cmd, str); else - serv_write(server, "%s\r\n", cmd); + serv_write(server, Sched_connected, "%s\r\n", cmd); } COMMAND( @@ -977,9 +962,9 @@ command_send2(struct Server *server, char *cmd, char *cmdname, char *str) { if (str && strchr(str, ' ') != strrchr(str, ' ')) command_toomany(cmdname); else if (str) - serv_write(server, "%s %s\r\n", cmd, str); + serv_write(server, Sched_connected, "%s %s\r\n", cmd, str); else - serv_write(server, "%s\r\n", cmd); + serv_write(server, Sched_connected, "%s\r\n", cmd); } COMMAND( @@ -1004,7 +989,7 @@ command_kill) { nick = strtok_r(str, " ", &reason); if (!reason) reason = config_gets("def.killmessage"); - serv_write(server, "KILL %s :%s\r\n", nick, reason); + serv_write(server, Sched_connected, "KILL %s :%s\r\n", nick, reason); } COMMAND( @@ -1578,7 +1563,7 @@ command_close) { if (chp) { if (serv_ischannel(sp, chp->name) && !chp->old) { - serv_write(sp, "PART %s\r\n", chp->name); + serv_write(sp, Sched_connected, "PART %s\r\n", chp->name); chan_remove(&sp->channels, chp->name); } else { chan_remove(&sp->queries, chp->name); @@ -1803,7 +1788,7 @@ modelset(char *cmd, struct Server *server, struct Channel *channel, i++; *(modes + i + 1) = '\0'; - serv_write(server, "MODE %s %s %s\r\n", channel->name, modes, args); + serv_write(server, Sched_connected, "MODE %s %s %s\r\n", channel->name, modes, args); args = p; } @@ -1897,7 +1882,7 @@ command_invite) { if (!chan) chan = channel->name; - serv_write(server, "INVITE %s %s\r\n", nick, chan); + serv_write(server, Sched_connected, "INVITE %s %s\r\n", nick, chan); } int @@ -2051,7 +2036,7 @@ command_eval(struct Server *server, char *str) { if (selected.channel && selected.server) { // TODO: message splitting snprintf(msg, sizeof(msg), "PRIVMSG %s :%s", selected.channel->name, s); - serv_write(selected.server, "%s\r\n", msg); + serv_write(selected.server, Sched_connected, "%s\r\n", msg); hist_format(selected.channel->history, Activity_self, HIST_SHOW|HIST_LOG|HIST_SELF, "%s", msg); } else { ui_error("channel not selected, message ignored", NULL); diff --git a/src/handle.c b/src/handle.c @@ -28,7 +28,7 @@ HANDLER( handle_PING) { assert_warn(param_len(msg->params) >= 2,); - serv_write(server, "PONG :%s\r\n", *(msg->params+1)); + serv_write(server, Sched_now, "PONG :%s\r\n", *(msg->params+1)); } HANDLER( @@ -199,9 +199,9 @@ handle_MODE) { expect_set(server, Expect_nosuchnick, NULL); hist_addp(server->history, msg, Activity_status, HIST_LOG); hist_addp(chan->history, msg, Activity_status, HIST_DFL); - serv_write(server, "MODE %s\r\n", chan->name); /* Get full mode via RPL_CHANNELMODEIS - * instead of concatenating manually */ - serv_write(server, "NAMES %s\r\n", chan->name); /* Also get updated priviledges */ + serv_write(server, Sched_now, "MODE %s\r\n", chan->name); /* Get full mode via RPL_CHANNELMODEIS + * instead of concatenating manually */ + serv_write(server, Sched_now, "NAMES %s\r\n", chan->name); /* Also get updated priviledges */ } else { hist_addp(server->history, msg, Activity_status, HIST_DFL); } @@ -423,7 +423,7 @@ handle_ERR_NICKNAMEINUSE) { nick_free(server->self); server->self = nnick; server->self->self = 1; - serv_write(server, "NICK %s\r\n", nick); + serv_write(server, Sched_now, "NICK %s\r\n", nick); } else { expect_set(server, Expect_nicknameinuse, NULL); } @@ -553,8 +553,10 @@ handle_RPL_TOPICWHOTIME) { HANDLER( handle_RPL_WELCOME) { if (server->status != ConnStatus_connected) { + /* XXX: unify this with RPL_ENDOFMOTD */ server->status = ConnStatus_connected; serv_auto_send(server); + schedule_send(server, Sched_connected); } hist_addp(server->history, msg, Activity_status, HIST_DFL); windows[Win_buflist].refresh = 1; @@ -585,6 +587,7 @@ handle_RPL_ENDOFMOTD) { if (server->status != ConnStatus_connected) { server->status = ConnStatus_connected; serv_auto_send(server); + schedule_send(server, Sched_connected); } hist_addp(server->history, msg, Activity_status, HIST_DFL); windows[Win_buflist].refresh = 1; @@ -616,10 +619,6 @@ handle(struct Server *server, char *msg) { else cmd = *(params); - /* Fire off any scheduled events for the current cmd */ - while ((schmsg = schedule_pull(server, cmd)) != NULL) - serv_write(server, "%s", schmsg); - for (i=0; cmd && handlers[i].cmd; i++) { if (strcmp(handlers[i].cmd, cmd) == 0) { if (handlers[i].func) { diff --git a/src/hirc.h b/src/hirc.h @@ -122,7 +122,7 @@ void hist_purgeopt(struct HistInfo *histinfo, enum HistOpt options); void serv_free(struct Server *server); void serv_connect(struct Server *server); void serv_read(struct Server *sp); -int serv_write(struct Server *server, char *format, ...); +int serv_write(struct Server *server, enum Sched when, char *format, ...); struct Server * serv_create(char *name, char *host, char *port, char *nick, char *username, char *realname, char *password, int tls, int tls_verify); void serv_update(struct Server *sp, char *nick, char *username, @@ -142,8 +142,8 @@ void serv_auto_send(struct Server *server); int serv_auto_haschannel(struct Server *server, char *chan); char * support_get(struct Server *server, char *key); void support_set(struct Server *server, char *key, char *value); -void schedule_push(struct Server *server, char *tmsg, char *msg); -char * schedule_pull(struct Server *server, char *tmsg); +void schedule(struct Server *server, enum Sched when, char *msg); +void schedule_send(struct Server *server, enum Sched when); void expect_set(struct Server *server, enum Expect cmd, char *about); char * expect_get(struct Server *server, enum Expect cmd); diff --git a/src/main.c b/src/main.c @@ -140,7 +140,7 @@ main(int argc, char *argv[]) { serv_read(sp); } else if (!sp->pingsent && sp->lastrecv && (time(NULL) - sp->lastrecv) >= pinginact) { /* haven't heard from server in pinginact seconds, sending a ping */ - serv_write(sp, "PING :ground control to Major Tom\r\n"); + serv_write(sp, Sched_now, "PING :ground control to Major Tom\r\n"); sp->pingsent = time(NULL); } else if (sp->pingsent && (time(NULL) - sp->pingsent) >= pinginact) { /* haven't gotten a response in pinginact seconds since diff --git a/src/serv.c b/src/serv.c @@ -69,7 +69,6 @@ serv_free(struct Server *server) { if (eprev) ep = eprev->next; while (eprev) { - pfree(&eprev->tmsg); pfree(&eprev->msg); pfree(&eprev); eprev = ep; @@ -344,9 +343,9 @@ serv_connect(struct Server *server) { server->connectfail = 0; if (server->password) - serv_write(server, "PASS %s\r\n", server->password); - serv_write(server, "NICK %s\r\n", server->self->nick); - serv_write(server, "USER %s * * :%s\r\n", + serv_write(server, Sched_now, "PASS %s\r\n", server->password); + serv_write(server, Sched_now, "NICK %s\r\n", server->self->nick); + serv_write(server, Sched_now, "USER %s * * :%s\r\n", server->username ? server->username : server->self->nick, server->realname ? server->realname : server->self->nick); @@ -442,22 +441,32 @@ serv_read(struct Server *sp) { } int -serv_write(struct Server *server, char *format, ...) { +serv_write(struct Server *server, enum Sched when, char *format, ...) { char msg[512]; va_list ap; int ret; - if (!server || server->status == ConnStatus_notconnected) { - ui_error("Not connected to server '%s'", server ? server->name : ""); - return -1; - } + assert_warn(server && server->status != ConnStatus_notconnected, -1); va_start(ap, format); - if (vsnprintf(msg, sizeof(msg), format, ap) < 0) { - va_end(ap); - return -1; + ret = vsnprintf(msg, sizeof(msg), format, ap); + va_end(ap); + + assert_warn(ret >= 0, -1); + + if (when != Sched_now) { + switch (when) { + case Sched_connected: + if (server->status == ConnStatus_connected) + goto write; + break; + } + schedule(server, when, msg); + return 0; } +write: + #ifdef TLS if (server->tls) do { @@ -476,7 +485,6 @@ serv_write(struct Server *server, char *format, ...) { ui_error("Not connected to server '%s'", server->name); } - va_end(ap); return ret; } @@ -521,7 +529,7 @@ serv_disconnect(struct Server *server, int reconnect, char *msg) { int ret; if (msg) - serv_write(server, "QUIT :%s\r\n", msg); + serv_write(server, Sched_now, "QUIT :%s\r\n", msg); #ifdef TLS if (server->tls) { if (server->tls_ctx) { @@ -684,16 +692,16 @@ serv_auto_haschannel(struct Server *server, char *chan) { } void -schedule_push(struct Server *server, char *tmsg, char *msg) { +schedule(struct Server *server, enum Sched when, char *msg) { struct Schedule *p; - assert_warn(server,); + assert_warn(server && msg,); if (!server->schedule) { server->schedule = emalloc(sizeof(struct Schedule)); server->schedule->prev = server->schedule->next = NULL; - server->schedule->tmsg = strdup(tmsg); - server->schedule->msg = strdup(msg); + server->schedule->when = when; + server->schedule->msg = estrdup(msg); return; } @@ -702,29 +710,19 @@ schedule_push(struct Server *server, char *tmsg, char *msg) { p->next = emalloc(sizeof(struct Schedule)); p->next->prev = p; p->next->next = NULL; - p->next->tmsg = strdup(tmsg); - p->next->msg = strdup(msg); + p->next->when = when; + p->next->msg = estrdup(msg); } -char * -schedule_pull(struct Server *server, char *tmsg) { - static char *ret = NULL; +void +schedule_send(struct Server *server, enum Sched when) { struct Schedule *p; - assert_warn(server && tmsg, NULL); + assert_warn(server, NULL); for (p = server->schedule; p; p = p->next) { - if (strcmp(p->tmsg, tmsg) == 0) { - pfree(&p->tmsg); - - /* Don't free p->msg, instead save it to - * a static pointer that we free the next - * time schedule_pull is invoked. Since - * schedule_pull will probably be used in - * while loops until it equals NULL, this - * will likely be set free quite quickly */ - pfree(&ret); - ret = p->msg; + if (p->when == when) { + serv_write(server, Sched_now, "%s", p->msg); if (p->prev) p->prev->next = p->next; if (p->next) p->next->prev = p->prev; @@ -732,14 +730,10 @@ schedule_pull(struct Server *server, char *tmsg) { if (!p->prev) server->schedule = p->next; + pfree(&p->msg); pfree(&p); - return ret; } } - - pfree(&ret); - ret = NULL; - return NULL; } void diff --git a/src/struct.h b/src/struct.h @@ -155,9 +155,14 @@ enum Expect { Expect_last, }; +enum Sched { + Sched_now, + Sched_connected, /* when 001, or end of motd is received */ +}; + struct Schedule { struct Schedule *prev; - char *tmsg; + enum Sched when; char *msg; struct Schedule *next; };