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:
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;
};