summaryrefslogtreecommitdiffstats
path: root/src/irc/core/servers-idle.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/irc/core/servers-idle.c')
-rw-r--r--src/irc/core/servers-idle.c264
1 files changed, 264 insertions, 0 deletions
diff --git a/src/irc/core/servers-idle.c b/src/irc/core/servers-idle.c
new file mode 100644
index 0000000..93c8f05
--- /dev/null
+++ b/src/irc/core/servers-idle.c
@@ -0,0 +1,264 @@
+/*
+ server-idle.c : irssi
+
+ Copyright (C) 1999-2000 Timo Sirainen
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "module.h"
+#include <irssi/src/core/signals.h>
+
+#include <irssi/src/irc/core/irc-servers.h>
+#include <irssi/src/irc/core/servers-idle.h>
+#include <irssi/src/irc/core/servers-redirect.h>
+
+typedef struct {
+ char *cmd;
+ char *arg;
+ int tag;
+
+ char *redirect_cmd;
+ int count;
+ int remote;
+ char *failure_signal;
+ GSList *redirects;
+} SERVER_IDLE_REC;
+
+static int idle_tag, idlepos;
+
+/* Add new idle command to queue */
+static SERVER_IDLE_REC *
+server_idle_create(const char *cmd, const char *redirect_cmd, int count,
+ const char *arg, int remote, const char *failure_signal,
+ va_list va)
+{
+ SERVER_IDLE_REC *rec;
+ const char *event, *signal;
+
+ g_return_val_if_fail(cmd != NULL, FALSE);
+
+ rec = g_new0(SERVER_IDLE_REC, 1);
+ rec->cmd = g_strdup(cmd);
+ rec->arg = g_strdup(arg);
+ rec->tag = ++idlepos;
+
+ rec->redirect_cmd = g_strdup(redirect_cmd);
+ rec->count = count;
+ rec->remote = remote;
+ rec->failure_signal = g_strdup(failure_signal);
+
+ while ((event = va_arg(va, const char *)) != NULL) {
+ signal = va_arg(va, const char *);
+ if (signal == NULL) {
+ g_warning("server_idle_create(%s): "
+ "signal not specified for event",
+ redirect_cmd);
+ break;
+ }
+
+ rec->redirects =
+ g_slist_append(rec->redirects, g_strdup(event));
+ rec->redirects =
+ g_slist_append(rec->redirects, g_strdup(signal));
+ }
+
+ return rec;
+}
+
+static SERVER_IDLE_REC *server_idle_find_rec(IRC_SERVER_REC *server, int tag)
+{
+ GSList *tmp;
+
+ g_return_val_if_fail(server != NULL, FALSE);
+
+ for (tmp = server->idles; tmp != NULL; tmp = tmp->next) {
+ SERVER_IDLE_REC *rec = tmp->data;
+
+ if (rec->tag == tag)
+ return rec;
+ }
+
+ return NULL;
+}
+
+/* Add new idle command to queue */
+int server_idle_add_redir(IRC_SERVER_REC *server, const char *cmd,
+ const char *redirect_cmd, int count, const char *arg,
+ int remote, const char *failure_signal, ...)
+{
+ va_list va;
+ SERVER_IDLE_REC *rec;
+
+ g_return_val_if_fail(server != NULL, -1);
+
+ va_start(va, failure_signal);
+ rec = server_idle_create(cmd, redirect_cmd, count, arg, remote,
+ failure_signal, va);
+ server->idles = g_slist_append(server->idles, rec);
+ va_end(va);
+
+ return rec->tag;
+}
+
+/* Add new idle command to first of queue */
+int server_idle_add_first_redir(IRC_SERVER_REC *server, const char *cmd,
+ const char *redirect_cmd, int count,
+ const char *arg, int remote,
+ const char *failure_signal, ...)
+{
+ va_list va;
+ SERVER_IDLE_REC *rec;
+
+ g_return_val_if_fail(server != NULL, -1);
+
+ va_start(va, failure_signal);
+ rec = server_idle_create(cmd, redirect_cmd, count, arg, remote,
+ failure_signal, va);
+ server->idles = g_slist_prepend(server->idles, rec);
+ va_end(va);
+
+ return rec->tag;
+}
+
+/* Add new idle command to specified position of queue */
+int server_idle_insert_redir(IRC_SERVER_REC *server, const char *cmd, int tag,
+ const char *redirect_cmd, int count,
+ const char *arg, int remote,
+ const char *failure_signal, ...)
+{
+ va_list va;
+ SERVER_IDLE_REC *rec;
+ int pos;
+
+ g_return_val_if_fail(server != NULL, -1);
+
+ va_start(va, failure_signal);
+
+ /* find the position of tag in idle list */
+ rec = server_idle_find_rec(server, tag);
+ pos = g_slist_index(server->idles, rec);
+
+ rec = server_idle_create(cmd, redirect_cmd, count, arg, remote,
+ failure_signal, va);
+ server->idles = pos < 0 ?
+ g_slist_append(server->idles, rec) :
+ g_slist_insert(server->idles, rec, pos);
+ va_end(va);
+
+ return rec->tag;
+}
+
+static void server_idle_destroy(IRC_SERVER_REC *server, SERVER_IDLE_REC *rec)
+{
+ g_return_if_fail(server != NULL);
+
+ server->idles = g_slist_remove(server->idles, rec);
+
+ g_slist_foreach(rec->redirects, (GFunc) g_free, NULL);
+ g_slist_free(rec->redirects);
+
+ g_free_not_null(rec->arg);
+ g_free_not_null(rec->redirect_cmd);
+ g_free_not_null(rec->failure_signal);
+ g_free(rec->cmd);
+ g_free(rec);
+}
+
+/* Check if record is still in queue */
+int server_idle_find(IRC_SERVER_REC *server, int tag)
+{
+ return server_idle_find_rec(server, tag) != NULL;
+}
+
+/* Remove record from idle queue */
+int server_idle_remove(IRC_SERVER_REC *server, int tag)
+{
+ SERVER_IDLE_REC *rec;
+
+ g_return_val_if_fail(server != NULL, FALSE);
+
+ rec = server_idle_find_rec(server, tag);
+ if (rec == NULL)
+ return FALSE;
+
+ server_idle_destroy(server, rec);
+ return TRUE;
+}
+
+/* Execute next idle command */
+static void server_idle_next(IRC_SERVER_REC *server)
+{
+ SERVER_IDLE_REC *rec;
+
+ g_return_if_fail(server != NULL);
+
+ if (server->idles == NULL)
+ return;
+ rec = server->idles->data;
+
+ /* Send command */
+ if (rec->redirect_cmd != NULL) {
+ server_redirect_event_list(server, rec->redirect_cmd,
+ rec->count, rec->arg,
+ rec->remote, rec->failure_signal,
+ rec->redirects);
+ }
+ irc_send_cmd(server, rec->cmd);
+
+ server_idle_destroy(server, rec);
+}
+
+static void sig_disconnected(IRC_SERVER_REC *server)
+{
+ g_return_if_fail(server != NULL);
+
+ if (!IS_IRC_SERVER(server))
+ return;
+
+ while (server->idles != NULL)
+ server_idle_destroy(server, server->idles->data);
+}
+
+static int sig_idle_timeout(void)
+{
+ GSList *tmp;
+
+ /* Scan through every server */
+ for (tmp = servers; tmp != NULL; tmp = tmp->next) {
+ IRC_SERVER_REC *rec = tmp->data;
+
+ if (IS_IRC_SERVER(rec) &&
+ rec->idles != NULL && rec->cmdcount == 0) {
+ /* We're idling and we have idle commands to run! */
+ server_idle_next(rec);
+ }
+ }
+ return 1;
+}
+
+void servers_idle_init(void)
+{
+ idlepos = 0;
+ idle_tag = g_timeout_add(1000, (GSourceFunc) sig_idle_timeout, NULL);
+
+ signal_add("server disconnected", (SIGNAL_FUNC) sig_disconnected);
+}
+
+void servers_idle_deinit(void)
+{
+ g_source_remove(idle_tag);
+ signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected);
+}