commit de8dc859614b4fc9acffb96776b5c7eb854aaf76
parent bc4ddc6513f2a5e0f7a792f13318d0b7c90784f8
Author: hhvn <dev@hhvn.uk>
Date: Sun, 28 Nov 2021 21:44:15 +0000
commands.c handle.c hirc.h serv.c struct.h: schedule msgs to run on certain events
Diffstat:
5 files changed, 90 insertions(+), 3 deletions(-)
diff --git a/commands.c b/commands.c
@@ -89,15 +89,26 @@ command_quit(struct Server *server, char *str) {
static void
command_join(struct Server *server, char *str) {
+ char *chantypes, msg[512];
if (!str) {
ui_error("/join requires argument", NULL);
return;
}
- if (strchr(support_get(server, "CHANTYPES"), *str))
- ircprintf(server, "JOIN %s\r\n", str);
+ chantypes = support_get(server, "CHANTYPES");
+ if (strchr(chantypes, *str))
+ snprintf(msg, sizeof(msg), "JOIN %s\r\n", str);
else
- ircprintf(server, "JOIN #%s\r\n", str);
+ snprintf(msg, sizeof(msg), "JOIN %c%s\r\n", chantypes ? *chantypes : '#', str);
+
+ if (server->status == ConnStatus_connected)
+ ircprintf(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 */
handle_expect(server, Expect_join, str);
}
diff --git a/handle.c b/handle.c
@@ -483,6 +483,7 @@ handle(int rfd, struct Server *server) {
time_t timestamp;
char **params;
char *cmd;
+ char *schmsg;
char *msg;
char buf[511];
/* using a buffer size of 511:
@@ -521,6 +522,10 @@ handle(int rfd, struct Server *server) {
else
cmd = *(params);
+ /* Fire off any scheduled events for the current cmd */
+ while ((schmsg = schedule_pull(server, cmd)) != NULL)
+ ircprintf(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/hirc.h b/hirc.h
@@ -83,6 +83,8 @@ int serv_selected(struct Server *server);
void serv_disconnect(struct Server *server, int reconnect, char *msg);
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);
/* handle.c */
void handle(int rfd, struct Server *server);
diff --git a/serv.c b/serv.c
@@ -336,3 +336,64 @@ support_set(struct Server *server, char *key, char *value) {
p->next->key = key ? strdup(key) : NULL;
p->next->value = value ? strdup(value) : NULL;
}
+
+void
+schedule_push(struct Server *server, char *tmsg, char *msg) {
+ struct Schedule *p;
+
+ if (!server)
+ return;
+
+ if (!server->schedule) {
+ server->schedule = malloc(sizeof(struct Schedule));
+ server->schedule->prev = server->schedule->next = NULL;
+ server->schedule->tmsg = strdup(tmsg);
+ server->schedule->msg = strdup(msg);
+ return;
+ }
+
+ for (p = server->schedule; p && p->next; p = p->next);
+
+ p->next = malloc(sizeof(struct Schedule));
+ p->next->prev = p;
+ p->next->next = NULL;
+ p->next->tmsg = strdup(tmsg);
+ p->next->msg = strdup(msg);
+}
+
+char *
+schedule_pull(struct Server *server, char *tmsg) {
+ static char *ret = NULL;
+ struct Schedule *p;
+
+ if (!server || !tmsg)
+ return NULL;
+
+ for (p = server->schedule; p; p = p->next) {
+ if (strcmp(p->tmsg, tmsg) == 0) {
+ free(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 */
+ free(ret);
+ ret = p->msg;
+
+ if (p->prev) p->prev->next = p->next;
+ if (p->next) p->next->prev = p->prev;
+
+ if (!p->prev && !p->next)
+ server->schedule = NULL;
+
+ free(p);
+ return ret;
+ }
+ }
+
+ free(ret);
+ ret = NULL;
+ return NULL;
+}
diff --git a/struct.h b/struct.h
@@ -95,6 +95,13 @@ enum Expect {
Expect_last,
};
+struct Schedule {
+ struct Schedule *prev;
+ char *tmsg;
+ char *msg;
+ struct Schedule *next;
+};
+
struct Server {
struct Server *prev;
int wfd;
@@ -112,6 +119,7 @@ struct Server {
struct HistInfo *history;
struct Channel *channels;
struct Channel *privs;
+ struct Schedule *schedule;
int reconnect;
char *expect[Expect_last];
int connectfail; /* number of failed connections */