forked from PsychoticNinja/irssi
git-svn-id: http://svn.irssi.org/repos/irssi/trunk@4490 dbcabf3a-b0e7-0310-adc4-f8d773084564
265 lines
6.3 KiB
C
265 lines
6.3 KiB
C
/*
|
|
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 "signals.h"
|
|
|
|
#include "irc-servers.h"
|
|
#include "servers-idle.h"
|
|
#include "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);
|
|
}
|