mirror of
https://github.com/irssi/irssi.git
synced 2026-08-11 12:53:42 +02:00
Lots of moving stuff around - hopefully I didn't break too much :)
git-svn-id: http://svn.irssi.org/repos/irssi/trunk@632 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
parent
3d124da13b
commit
e395e87ded
160 changed files with 3954 additions and 2959 deletions
|
|
@ -1,4 +1,4 @@
|
|||
noinst_LTLIBRARIES = libcore.la
|
||||
noinst_LIBRARIES = libcore.a
|
||||
|
||||
INCLUDES = \
|
||||
$(GLIB_CFLAGS) \
|
||||
|
|
@ -13,13 +13,17 @@ else
|
|||
memdebug_src=
|
||||
endif
|
||||
|
||||
libcore_la_SOURCES = \
|
||||
libcore_a_SOURCES = \
|
||||
args.c \
|
||||
channels.c \
|
||||
channels-setup.c \
|
||||
commands.c \
|
||||
chatnets.c \
|
||||
core.c \
|
||||
levels.c \
|
||||
line-split.c \
|
||||
log.c \
|
||||
masks.c \
|
||||
$(memdebug_src) \
|
||||
misc.c \
|
||||
modules.c \
|
||||
|
|
@ -27,21 +31,38 @@ libcore_la_SOURCES = \
|
|||
net-nonblock.c \
|
||||
net-sendbuffer.c \
|
||||
network.c \
|
||||
nicklist.c \
|
||||
pidwait.c \
|
||||
queries.c \
|
||||
rawlog.c \
|
||||
server.c \
|
||||
server-redirect.c \
|
||||
servers.c \
|
||||
servers-reconnect.c \
|
||||
servers-redirect.c \
|
||||
servers-setup.c \
|
||||
settings.c \
|
||||
signals.c \
|
||||
special-vars.c
|
||||
|
||||
structure_headers = \
|
||||
chatnet-rec.h \
|
||||
channel-rec.h \
|
||||
query-rec.h \
|
||||
server-rec.h \
|
||||
server-setup-rec.h \
|
||||
server-connect-rec.h \
|
||||
window-item-rec.h
|
||||
|
||||
noinst_HEADERS = \
|
||||
args.h \
|
||||
channels.h \
|
||||
channels-setup.h \
|
||||
commands.h \
|
||||
chatnets.h \
|
||||
core.h \
|
||||
levels.h \
|
||||
line-split.h \
|
||||
log.h \
|
||||
masks.h \
|
||||
memdebug.h \
|
||||
misc.h \
|
||||
module.h \
|
||||
|
|
@ -51,13 +72,19 @@ noinst_HEADERS = \
|
|||
net-nonblock.h \
|
||||
net-sendbuffer.h \
|
||||
network.h \
|
||||
nicklist.h \
|
||||
pidwait.h \
|
||||
queries.h \
|
||||
rawlog.h \
|
||||
server.h \
|
||||
server-redirect.h \
|
||||
servers.h \
|
||||
servers-reconnect.h \
|
||||
servers-redirect.h \
|
||||
servers-setup.h \
|
||||
settings.h \
|
||||
signals.h \
|
||||
special-vars.h
|
||||
special-vars.h \
|
||||
window-item-def.h \
|
||||
$(structure_headers)
|
||||
|
||||
EXTRA_DIST = \
|
||||
memdebug.c
|
||||
|
|
|
|||
21
src/core/channel-rec.h
Normal file
21
src/core/channel-rec.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/* CHANNEL_REC definition, used for inheritance */
|
||||
|
||||
#include "window-item-rec.h"
|
||||
|
||||
char *topic;
|
||||
GHashTable *nicks; /* list of nicks */
|
||||
|
||||
int no_modes:1; /* channel doesn't support modes */
|
||||
char *mode;
|
||||
int limit; /* user limit */
|
||||
char *key; /* password key */
|
||||
|
||||
int chanop:1; /* You're a channel operator */
|
||||
int names_got:1; /* Received /NAMES list */
|
||||
int wholist:1; /* WHO list got */
|
||||
int synced:1; /* Channel synced - all queries done */
|
||||
|
||||
int joined:1; /* Have we even received JOIN event for this channel? */
|
||||
int left:1; /* You just left the channel */
|
||||
int kicked:1; /* You just got kicked */
|
||||
int destroying:1;
|
||||
170
src/core/channels-setup.c
Normal file
170
src/core/channels-setup.c
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
channels-setup.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "signals.h"
|
||||
#include "lib-config/iconfig.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include "channels.h"
|
||||
#include "channels-setup.h"
|
||||
#include "servers-setup.h"
|
||||
|
||||
GSList *setupchannels;
|
||||
|
||||
static CHANNEL_SETUP_REC *channel_setup_read(CONFIG_NODE *node)
|
||||
{
|
||||
CHANNEL_SETUP_REC *rec;
|
||||
char *channel, *password, *botmasks, *autosendcmd;
|
||||
|
||||
g_return_val_if_fail(node != NULL, NULL);
|
||||
|
||||
channel = config_node_get_str(node, "name", NULL);
|
||||
if (channel == NULL) {
|
||||
/* missing information.. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
password = config_node_get_str(node, "password", NULL);
|
||||
botmasks = config_node_get_str(node, "botmasks", NULL);
|
||||
autosendcmd = config_node_get_str(node, "autosendcmd", NULL);
|
||||
|
||||
rec = g_new(CHANNEL_SETUP_REC, 1);
|
||||
rec->autojoin = config_node_get_bool(node, "autojoin", FALSE);
|
||||
rec->name = g_strdup(channel);
|
||||
rec->chatnet = g_strdup(config_node_get_str(node, "chatnet", NULL));
|
||||
rec->password = (password == NULL || *password == '\0') ? NULL : g_strdup(password);
|
||||
rec->botmasks = (botmasks == NULL || *botmasks == '\0') ? NULL : g_strdup(botmasks);
|
||||
rec->autosendcmd = (autosendcmd == NULL || *autosendcmd == '\0') ? NULL : g_strdup(autosendcmd);
|
||||
|
||||
setupchannels = g_slist_append(setupchannels, rec);
|
||||
signal_emit("channel setup created", 2, rec, node);
|
||||
return rec;
|
||||
}
|
||||
|
||||
static void channel_setup_save(CHANNEL_SETUP_REC *channel)
|
||||
{
|
||||
CONFIG_NODE *parentnode, *node;
|
||||
int index;
|
||||
|
||||
index = g_slist_index(setupchannels, channel);
|
||||
|
||||
parentnode = iconfig_node_traverse("(channels", TRUE);
|
||||
node = config_node_index(parentnode, index);
|
||||
if (node == NULL)
|
||||
node = config_node_section(parentnode, NULL, NODE_TYPE_BLOCK);
|
||||
|
||||
iconfig_node_clear(node);
|
||||
iconfig_node_set_str(node, "name", channel->name);
|
||||
iconfig_node_set_str(node, "chatnet", channel->chatnet);
|
||||
if (channel->autojoin)
|
||||
config_node_set_bool(node, "autojoin", TRUE);
|
||||
iconfig_node_set_str(node, "password", channel->password);
|
||||
iconfig_node_set_str(node, "botmasks", channel->botmasks);
|
||||
iconfig_node_set_str(node, "autosendcmd", channel->autosendcmd);
|
||||
}
|
||||
|
||||
static void channel_config_remove(CHANNEL_SETUP_REC *channel)
|
||||
{
|
||||
CONFIG_NODE *node;
|
||||
|
||||
node = iconfig_node_traverse("channels", FALSE);
|
||||
if (node != NULL) iconfig_node_list_remove(node, g_slist_index(setupchannels, channel));
|
||||
}
|
||||
|
||||
void channels_setup_create(CHANNEL_SETUP_REC *channel)
|
||||
{
|
||||
if (g_slist_find(setupchannels, channel) == NULL)
|
||||
setupchannels = g_slist_append(setupchannels, channel);
|
||||
channel_setup_save(channel);
|
||||
|
||||
signal_emit("channel setup created", 1, channel);
|
||||
}
|
||||
|
||||
static void channels_setup_destroy_rec(CHANNEL_SETUP_REC *channel)
|
||||
{
|
||||
g_return_if_fail(channel != NULL);
|
||||
|
||||
setupchannels = g_slist_remove(setupchannels, channel);
|
||||
signal_emit("channel setup destroyed", 1, channel);
|
||||
|
||||
g_free(channel->name);
|
||||
g_free(channel->chatnet);
|
||||
g_free_not_null(channel->password);
|
||||
g_free_not_null(channel->botmasks);
|
||||
g_free_not_null(channel->autosendcmd);
|
||||
g_free(channel);
|
||||
}
|
||||
|
||||
void channels_setup_destroy(CHANNEL_SETUP_REC *channel)
|
||||
{
|
||||
channel_config_remove(channel);
|
||||
channels_setup_destroy_rec(channel);
|
||||
}
|
||||
|
||||
CHANNEL_SETUP_REC *channels_setup_find(const char *channel, const char *chatnet)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
g_return_val_if_fail(channel != NULL, NULL);
|
||||
|
||||
for (tmp = setupchannels; tmp != NULL; tmp = tmp->next) {
|
||||
CHANNEL_SETUP_REC *rec = tmp->data;
|
||||
|
||||
if (g_strcasecmp(rec->name, channel) == 0 &&
|
||||
channel_chatnet_match(rec->chatnet, chatnet))
|
||||
return rec;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void channels_read_config(void)
|
||||
{
|
||||
CONFIG_NODE *node;
|
||||
GSList *tmp;
|
||||
|
||||
while (setupchannels != NULL)
|
||||
channels_setup_destroy_rec(setupchannels->data);
|
||||
|
||||
/* Read channels */
|
||||
node = iconfig_node_traverse("channels", FALSE);
|
||||
if (node != NULL) {
|
||||
for (tmp = node->value; tmp != NULL; tmp = tmp->next)
|
||||
channel_setup_read(tmp->data);
|
||||
}
|
||||
}
|
||||
|
||||
void channels_setup_init(void)
|
||||
{
|
||||
source_host_ok = FALSE;
|
||||
|
||||
signal_add("setup reread", (SIGNAL_FUNC) channels_read_config);
|
||||
signal_add("irssi init read settings", (SIGNAL_FUNC) channels_read_config);
|
||||
}
|
||||
|
||||
void channels_setup_deinit(void)
|
||||
{
|
||||
while (setupchannels != NULL)
|
||||
channels_setup_destroy(setupchannels->data);
|
||||
|
||||
signal_remove("setup reread", (SIGNAL_FUNC) channels_read_config);
|
||||
signal_remove("irssi init read settings", (SIGNAL_FUNC) channels_read_config);
|
||||
}
|
||||
33
src/core/channels-setup.h
Normal file
33
src/core/channels-setup.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef __CHANNELS_SETUP_H
|
||||
#define __CHANNELS_SETUP_H
|
||||
|
||||
#include "modules.h"
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
char *chatnet;
|
||||
char *password;
|
||||
|
||||
char *botmasks;
|
||||
char *autosendcmd;
|
||||
|
||||
int autojoin:1;
|
||||
GHashTable *module_data;
|
||||
} CHANNEL_SETUP_REC;
|
||||
|
||||
extern GSList *setupchannels;
|
||||
|
||||
void channels_setup_init(void);
|
||||
void channels_setup_deinit(void);
|
||||
|
||||
void channels_setup_create(CHANNEL_SETUP_REC *channel);
|
||||
void channels_setup_destroy(CHANNEL_SETUP_REC *channel);
|
||||
|
||||
CHANNEL_SETUP_REC *channels_setup_find(const char *channel,
|
||||
const char *chatnet);
|
||||
|
||||
#define channel_chatnet_match(rec, chatnet) \
|
||||
((rec) == NULL || (rec)[0] == '\0' || \
|
||||
((chatnet) != NULL && g_strcasecmp(rec, chatnet) == 0))
|
||||
|
||||
#endif
|
||||
116
src/core/channels.c
Normal file
116
src/core/channels.c
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
channel.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "signals.h"
|
||||
#include "misc.h"
|
||||
|
||||
#include "channels.h"
|
||||
|
||||
typedef CHANNEL_REC *(*CHANNEL_FIND_FUNC)(SERVER_REC *, const char *);
|
||||
|
||||
GSList *channels; /* List of all channels */
|
||||
|
||||
void channel_init(CHANNEL_REC *channel, int automatic)
|
||||
{
|
||||
g_return_if_fail(channel != NULL);
|
||||
g_return_if_fail(channel->name != NULL);
|
||||
|
||||
channels = g_slist_append(channels, channel);
|
||||
if (channel->server != NULL) {
|
||||
channel->server->channels =
|
||||
g_slist_append(channel->server->channels, channel);
|
||||
}
|
||||
|
||||
MODULE_DATA_INIT(channel);
|
||||
channel->type = module_get_uniq_id("CHANNEL", 0);
|
||||
channel->mode = g_strdup("");
|
||||
channel->createtime = time(NULL);
|
||||
|
||||
signal_emit("channel created", 2, channel, GINT_TO_POINTER(automatic));
|
||||
}
|
||||
|
||||
void channel_destroy(CHANNEL_REC *channel)
|
||||
{
|
||||
g_return_if_fail(IS_CHANNEL(channel));
|
||||
|
||||
if (channel->destroying) return;
|
||||
channel->destroying = TRUE;
|
||||
|
||||
channels = g_slist_remove(channels, channel);
|
||||
if (channel->server != NULL)
|
||||
channel->server->channels = g_slist_remove(channel->server->channels, channel);
|
||||
signal_emit("channel destroyed", 1, channel);
|
||||
|
||||
MODULE_DATA_DEINIT(channel);
|
||||
g_free_not_null(channel->topic);
|
||||
g_free_not_null(channel->key);
|
||||
g_free(channel->name);
|
||||
g_free(channel);
|
||||
}
|
||||
|
||||
static CHANNEL_REC *channel_find_server(SERVER_REC *server,
|
||||
const char *name)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
g_return_val_if_fail(IS_SERVER(server), NULL);
|
||||
|
||||
if (server->channel_find_func != NULL) {
|
||||
/* use the server specific channel find function */
|
||||
CHANNEL_FIND_FUNC channel_find_func;
|
||||
channel_find_func =
|
||||
(CHANNEL_FIND_FUNC) server->channel_find_func;
|
||||
return channel_find_func(server, name);
|
||||
}
|
||||
|
||||
for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
|
||||
CHANNEL_REC *rec = tmp->data;
|
||||
|
||||
if (rec->chat_type == server->channel_type &&
|
||||
g_strcasecmp(name, rec->name) == 0)
|
||||
return rec;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CHANNEL_REC *channel_find(SERVER_REC *server, const char *name)
|
||||
{
|
||||
g_return_val_if_fail(server == NULL || IS_SERVER(server), NULL);
|
||||
g_return_val_if_fail(name != NULL, NULL);
|
||||
|
||||
if (server != NULL)
|
||||
return channel_find_server(server, name);
|
||||
|
||||
/* find from any server */
|
||||
return gslist_foreach_find(servers,
|
||||
(FOREACH_FIND_FUNC) channel_find_server,
|
||||
(void *) name);
|
||||
}
|
||||
|
||||
void channels_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void channels_deinit(void)
|
||||
{
|
||||
module_uniq_destroy("CHANNEL");
|
||||
}
|
||||
31
src/core/channels.h
Normal file
31
src/core/channels.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef __CHANNELS_H
|
||||
#define __CHANNELS_H
|
||||
|
||||
#include "servers.h"
|
||||
|
||||
#define IS_CHANNEL(channel) \
|
||||
((channel) != NULL && \
|
||||
module_find_id("CHANNEL", ((CHANNEL_REC *) (channel))->type) != -1)
|
||||
|
||||
/* Returns CHANNEL_REC if it's channel, NULL if it isn't. */
|
||||
#define CHANNEL(channel) \
|
||||
(IS_CHANNEL(channel) ? (CHANNEL_REC *) (channel) : NULL)
|
||||
|
||||
#define STRUCT_SERVER_REC SERVER_REC
|
||||
typedef struct {
|
||||
#include "channel-rec.h"
|
||||
} CHANNEL_REC;
|
||||
|
||||
extern GSList *channels;
|
||||
|
||||
void channels_init(void);
|
||||
void channels_deinit(void);
|
||||
|
||||
/* Create new channel record */
|
||||
void channel_init(CHANNEL_REC *channel, int automatic);
|
||||
void channel_destroy(CHANNEL_REC *channel);
|
||||
|
||||
/* find channel by name, if `server' is NULL, search from all servers */
|
||||
CHANNEL_REC *channel_find(SERVER_REC *server, const char *name);
|
||||
|
||||
#endif
|
||||
12
src/core/chatnet-rec.h
Normal file
12
src/core/chatnet-rec.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
int type; /* should always be "CHATNET" */
|
||||
int chat_type;
|
||||
|
||||
char *name;
|
||||
|
||||
char *nick;
|
||||
char *username;
|
||||
char *realname;
|
||||
|
||||
char *own_host; /* address to use when connecting this server */
|
||||
char *autosendcmd; /* command to send after connecting to this ircnet */
|
||||
IPADDR *own_ip; /* resolved own_address if not NULL */
|
||||
148
src/core/chatnets.c
Normal file
148
src/core/chatnets.c
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
chatnets.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "network.h"
|
||||
#include "signals.h"
|
||||
#include "special-vars.h"
|
||||
#include "lib-config/iconfig.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include "chatnets.h"
|
||||
#include "servers.h"
|
||||
|
||||
GSList *chatnets; /* list of available chat networks */
|
||||
|
||||
void chatnet_read(CHATNET_REC *chatnet, void *nodep)
|
||||
{
|
||||
CONFIG_NODE *node = nodep;
|
||||
|
||||
g_return_if_fail(chatnet != NULL);
|
||||
g_return_if_fail(node != NULL);
|
||||
g_return_if_fail(node->key != NULL);
|
||||
|
||||
chatnet->type = module_get_uniq_id("CHATNET", 0);
|
||||
chatnet->name = g_strdup(node->key);
|
||||
chatnet->nick = g_strdup(config_node_get_str(node, "nick", NULL));
|
||||
chatnet->username = g_strdup(config_node_get_str(node, "username", NULL));
|
||||
chatnet->realname = g_strdup(config_node_get_str(node, "realname", NULL));
|
||||
chatnet->own_host = g_strdup(config_node_get_str(node, "host", NULL));
|
||||
chatnet->autosendcmd = g_strdup(config_node_get_str(node, "autosendcmd", NULL));
|
||||
|
||||
chatnets = g_slist_append(chatnets, chatnet);
|
||||
}
|
||||
|
||||
void *chatnet_save(CHATNET_REC *chatnet, void *parentnode)
|
||||
{
|
||||
CONFIG_NODE *node = parentnode;
|
||||
|
||||
g_return_val_if_fail(parentnode != NULL, NULL);
|
||||
g_return_val_if_fail(IS_CHATNET(chatnet), NULL);
|
||||
|
||||
node = config_node_section(node, chatnet->name, NODE_TYPE_BLOCK);
|
||||
iconfig_node_clear(node);
|
||||
|
||||
iconfig_node_set_str(node, "nick", chatnet->nick);
|
||||
iconfig_node_set_str(node, "username", chatnet->username);
|
||||
iconfig_node_set_str(node, "realname", chatnet->realname);
|
||||
iconfig_node_set_str(node, "host", chatnet->own_host);
|
||||
iconfig_node_set_str(node, "autosendcmd", chatnet->autosendcmd);
|
||||
return node;
|
||||
}
|
||||
|
||||
void chatnet_create(CHATNET_REC *chatnet)
|
||||
{
|
||||
g_return_if_fail(chatnet != NULL);
|
||||
|
||||
chatnet->type = module_get_uniq_id("CHATNET", 0);
|
||||
if (g_slist_find(chatnets, chatnet) == NULL)
|
||||
chatnets = g_slist_append(chatnets, chatnet);
|
||||
|
||||
signal_emit("chatnet created", 1, chatnet);
|
||||
}
|
||||
|
||||
void chatnet_remove(CHATNET_REC *chatnet)
|
||||
{
|
||||
g_return_if_fail(IS_CHATNET(chatnet));
|
||||
|
||||
signal_emit("chatnet removed", 1, chatnet);
|
||||
chatnet_destroy(chatnet);
|
||||
}
|
||||
|
||||
void chatnet_destroy(CHATNET_REC *chatnet)
|
||||
{
|
||||
g_return_if_fail(IS_CHATNET(chatnet));
|
||||
|
||||
chatnets = g_slist_remove(chatnets, chatnet);
|
||||
signal_emit("chatnet destroyed", 1, chatnet);
|
||||
|
||||
g_free(chatnet->name);
|
||||
g_free_not_null(chatnet->nick);
|
||||
g_free_not_null(chatnet->username);
|
||||
g_free_not_null(chatnet->realname);
|
||||
g_free_not_null(chatnet->own_host);
|
||||
g_free_not_null(chatnet->autosendcmd);
|
||||
g_free(chatnet);
|
||||
}
|
||||
|
||||
/* Find the irc network by name */
|
||||
CHATNET_REC *chatnet_find(const char *name)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
g_return_val_if_fail(name != NULL, NULL);
|
||||
|
||||
for (tmp = chatnets; tmp != NULL; tmp = tmp->next) {
|
||||
CHATNET_REC *rec = tmp->data;
|
||||
|
||||
if (g_strcasecmp(rec->name, name) == 0)
|
||||
return rec;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void sig_connected(SERVER_REC *server)
|
||||
{
|
||||
CHATNET_REC *rec;
|
||||
|
||||
g_return_if_fail(IS_SERVER(server));
|
||||
|
||||
if (server->connrec->chatnet == NULL)
|
||||
return;
|
||||
|
||||
rec = chatnet_find(server->connrec->chatnet);
|
||||
if (rec != NULL && rec->autosendcmd)
|
||||
eval_special_string(rec->autosendcmd, "", server, NULL);
|
||||
}
|
||||
|
||||
void chatnets_init(void)
|
||||
{
|
||||
signal_add("event connected", (SIGNAL_FUNC) sig_connected);
|
||||
}
|
||||
|
||||
void chatnets_deinit(void)
|
||||
{
|
||||
while (chatnets != NULL)
|
||||
chatnet_destroy(chatnets->data);
|
||||
|
||||
signal_remove("event connected", (SIGNAL_FUNC) sig_connected);
|
||||
module_uniq_destroy("CHATNET");
|
||||
}
|
||||
37
src/core/chatnets.h
Normal file
37
src/core/chatnets.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef __CHATNETS_H
|
||||
#define __CHATNETS_H
|
||||
|
||||
#include "modules.h"
|
||||
|
||||
#define IS_CHATNET(chatnet) \
|
||||
((chatnet) != NULL && \
|
||||
module_find_id("CHATNET", (chatnet)->type) != -1)
|
||||
|
||||
/* Returns CHATNET_REC if it's chatnet, NULL if it isn't. */
|
||||
#define CHATNET(chatnet) \
|
||||
(IS_CHATNET(chatnet) ? (CHATNET_REC *) (chatnet) : NULL)
|
||||
|
||||
typedef struct {
|
||||
#include "chatnet-rec.h"
|
||||
} CHATNET_REC;
|
||||
|
||||
extern GSList *chatnets; /* list of available chat networks */
|
||||
|
||||
/* read/save to configuration file */
|
||||
void chatnet_read(CHATNET_REC *chatnet, void *node);
|
||||
void *chatnet_save(CHATNET_REC *chatnet, void *parentnode);
|
||||
|
||||
/* add the chatnet to chat networks list */
|
||||
void chatnet_create(CHATNET_REC *chatnet);
|
||||
/* remove the chatnet from chat networks list */
|
||||
void chatnet_remove(CHATNET_REC *chatnet);
|
||||
/* destroy the chatnet structure. doesn't remove from config file */
|
||||
void chatnet_destroy(CHATNET_REC *chatnet);
|
||||
|
||||
/* Find the irc network by name */
|
||||
CHATNET_REC *chatnet_find(const char *name);
|
||||
|
||||
void chatnets_init(void);
|
||||
void chatnets_deinit(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -19,12 +19,11 @@
|
|||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules.h"
|
||||
#include "signals.h"
|
||||
#include "commands.h"
|
||||
#include "misc.h"
|
||||
#include "server.h"
|
||||
#include "server-redirect.h"
|
||||
#include "servers.h"
|
||||
#include "servers-redirect.h"
|
||||
#include "special-vars.h"
|
||||
|
||||
#include "lib-config/iconfig.h"
|
||||
|
|
@ -617,6 +616,8 @@ static void parse_command(const char *command, int expand_aliases,
|
|||
const char *alias, *newcmd;
|
||||
char *cmd, *orig, *args, *oldcmd;
|
||||
|
||||
g_return_if_fail(command != NULL);
|
||||
|
||||
cmd = orig = g_strconcat("command ", command, NULL);
|
||||
args = strchr(cmd+8, ' ');
|
||||
if (args != NULL) *args++ = '\0'; else args = "";
|
||||
|
|
@ -643,7 +644,7 @@ static void parse_command(const char *command, int expand_aliases,
|
|||
|
||||
cmd = g_strconcat("command ", newcmd, NULL);
|
||||
if (server != NULL)
|
||||
server_redirect_default((SERVER_REC *) server, cmd);
|
||||
server_redirect_default(SERVER(server), cmd);
|
||||
|
||||
g_strdown(cmd);
|
||||
oldcmd = current_command;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
core.c : irssi
|
||||
|
||||
Copyright (C) 1999 Timo Sirainen
|
||||
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
|
||||
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
#include "module.h"
|
||||
|
||||
#include "modules.h"
|
||||
#include "pidwait.h"
|
||||
|
||||
#include "net-disconnect.h"
|
||||
|
|
@ -28,12 +27,17 @@
|
|||
#include "signals.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include "server.h"
|
||||
#include "servers.h"
|
||||
#include "chatnets.h"
|
||||
#include "commands.h"
|
||||
#include "log.h"
|
||||
#include "rawlog.h"
|
||||
#include "special-vars.h"
|
||||
|
||||
#include "channels.h"
|
||||
#include "queries.h"
|
||||
#include "nicklist.h"
|
||||
|
||||
int irssi_gui;
|
||||
|
||||
void core_init(void)
|
||||
|
|
@ -47,18 +51,28 @@ void core_init(void)
|
|||
settings_init();
|
||||
commands_init();
|
||||
|
||||
chatnets_init();
|
||||
servers_init();
|
||||
log_init();
|
||||
rawlog_init();
|
||||
special_vars_init();
|
||||
|
||||
channels_init();
|
||||
queries_init();
|
||||
nicklist_init();
|
||||
}
|
||||
|
||||
void core_deinit(void)
|
||||
{
|
||||
nicklist_deinit();
|
||||
queries_deinit();
|
||||
channels_deinit();
|
||||
|
||||
special_vars_deinit();
|
||||
rawlog_deinit();
|
||||
log_deinit();
|
||||
servers_deinit();
|
||||
chatnets_deinit();
|
||||
|
||||
commands_deinit();
|
||||
settings_deinit();
|
||||
|
|
|
|||
137
src/core/masks.c
Normal file
137
src/core/masks.c
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
masks.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "network.h"
|
||||
#include "misc.h"
|
||||
|
||||
#include "servers.h"
|
||||
|
||||
typedef int (*MASK_MATCH_FUNC) (const char *, const char *);
|
||||
|
||||
/* Returns TRUE if mask contains '!' ie. address should be checked too.
|
||||
Also checks if mask contained any wildcards. */
|
||||
static int check_address(const char *mask, int *wildcards)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = FALSE;
|
||||
while (*mask != '\0') {
|
||||
if (*mask == '!') {
|
||||
if (*wildcards) return TRUE;
|
||||
ret = TRUE;
|
||||
}
|
||||
|
||||
if (*mask == '?' || *mask == '*') {
|
||||
*wildcards = TRUE;
|
||||
if (ret) return TRUE;
|
||||
}
|
||||
mask++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int check_mask(SERVER_REC *server, const char *mask,
|
||||
const char *str, int wildcards)
|
||||
{
|
||||
MASK_MATCH_FUNC mask_match_func;
|
||||
|
||||
if (server != NULL && server->mask_match_func != NULL) {
|
||||
/* use server specified mask match function */
|
||||
mask_match_func = (MASK_MATCH_FUNC)server->mask_match_func;
|
||||
return mask_match_func(mask, str);
|
||||
}
|
||||
|
||||
return wildcards ? match_wildcards(mask, str) :
|
||||
g_strcasecmp(mask, str) == 0;
|
||||
}
|
||||
|
||||
int mask_match(SERVER_REC *server, const char *mask,
|
||||
const char *nick, const char *user, const char *host)
|
||||
{
|
||||
char *str;
|
||||
int ret, wildcards;
|
||||
|
||||
g_return_val_if_fail(server == NULL || IS_SERVER(server), FALSE);
|
||||
g_return_val_if_fail(mask != NULL && nick != NULL &&
|
||||
nick != NULL && host != NULL, FALSE);
|
||||
|
||||
str = !check_address(mask, &wildcards) ? (char *) nick :
|
||||
g_strdup_printf("%s!%s@%s", nick, user, host);
|
||||
ret = check_mask(server, mask, str, wildcards);
|
||||
if (str != nick) g_free(str);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mask_match_address(SERVER_REC *server, const char *mask,
|
||||
const char *nick, const char *address)
|
||||
{
|
||||
char *str;
|
||||
int ret, wildcards;
|
||||
|
||||
g_return_val_if_fail(server == NULL || IS_SERVER(server), FALSE);
|
||||
g_return_val_if_fail(mask != NULL && nick != NULL, FALSE);
|
||||
if (address == NULL) address = "";
|
||||
|
||||
str = !check_address(mask, &wildcards) ? (char *) nick :
|
||||
g_strdup_printf("%s!%s", nick, address);
|
||||
ret = check_mask(server, mask, str, wildcards);
|
||||
if (str != nick) g_free(str);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int masks_match(SERVER_REC *server, const char *masks,
|
||||
const char *nick, const char *address)
|
||||
{
|
||||
MASK_MATCH_FUNC mask_match_func;
|
||||
char **list, **tmp, *mask;
|
||||
int found;
|
||||
|
||||
g_return_val_if_fail(server == NULL || IS_SERVER(server), FALSE);
|
||||
g_return_val_if_fail(masks != NULL &&
|
||||
nick != NULL && address != NULL, FALSE);
|
||||
|
||||
mask_match_func = server != NULL && server->mask_match_func != NULL ?
|
||||
(MASK_MATCH_FUNC) server->mask_match_func :
|
||||
(MASK_MATCH_FUNC) match_wildcards;
|
||||
|
||||
found = FALSE;
|
||||
mask = g_strdup_printf("%s!%s", nick, address);
|
||||
list = g_strsplit(masks, " ", -1);
|
||||
for (tmp = list; *tmp != NULL; tmp++) {
|
||||
if (strchr(*tmp, '!') == NULL &&
|
||||
g_strcasecmp(*tmp, nick) == 0) {
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mask_match_func(*tmp, mask)) {
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_strfreev(list);
|
||||
g_free(mask);
|
||||
|
||||
return found;
|
||||
}
|
||||
13
src/core/masks.h
Normal file
13
src/core/masks.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef __MASKS_H
|
||||
#define __MASKS_H
|
||||
|
||||
#include "servers.h"
|
||||
|
||||
int mask_match(SERVER_REC *server, const char *mask,
|
||||
const char *nick, const char *user, const char *host);
|
||||
int mask_match_address(SERVER_REC *server, const char *mask,
|
||||
const char *nick, const char *address);
|
||||
int masks_match(SERVER_REC *server, const char *masks,
|
||||
const char *nick, const char *address);
|
||||
|
||||
#endif
|
||||
|
|
@ -38,7 +38,7 @@ typedef struct {
|
|||
static GHashTable *data = NULL, *preallocs = NULL;
|
||||
static const char *comment = "";
|
||||
|
||||
static void add_flow_checks(guchar *p, unsigned long size)
|
||||
static void add_flow_checks(char *p, unsigned long size)
|
||||
{
|
||||
#ifdef ENABLE_BUFFER_CHECKS
|
||||
int n;
|
||||
|
|
@ -75,7 +75,7 @@ static void mem_check(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void data_add(void *p, int size, const char *file, int line)
|
||||
static void data_add(char *p, int size, const char *file, int line)
|
||||
{
|
||||
MEM_REC *rec;
|
||||
|
||||
|
|
@ -106,7 +106,19 @@ static void data_add(void *p, int size, const char *file, int line)
|
|||
mem_check();
|
||||
}
|
||||
|
||||
static void *data_remove(void *p, const char *file, int line)
|
||||
static void data_clear(char *p)
|
||||
{
|
||||
MEM_REC *rec;
|
||||
|
||||
if (g_hash_table_lookup(preallocs, p) != NULL)
|
||||
p += BUFFER_CHECK_SIZE;
|
||||
|
||||
rec = g_hash_table_lookup(data, p);
|
||||
if (rec != NULL && rec->size > 0)
|
||||
memset(p, 'F', rec->size);
|
||||
}
|
||||
|
||||
static void *data_remove(char *p, const char *file, int line)
|
||||
{
|
||||
MEM_REC *rec;
|
||||
|
||||
|
|
@ -132,34 +144,34 @@ static void *data_remove(void *p, const char *file, int line)
|
|||
|
||||
void *ig_malloc(int size, const char *file, int line)
|
||||
{
|
||||
void *p;
|
||||
char *p;
|
||||
|
||||
size += BUFFER_CHECK_SIZE*2;
|
||||
p = g_malloc(size);
|
||||
data_add(p, size, file, line);
|
||||
return p+BUFFER_CHECK_SIZE;
|
||||
return (void *) (p+BUFFER_CHECK_SIZE);
|
||||
}
|
||||
|
||||
void *ig_malloc0(int size, const char *file, int line)
|
||||
{
|
||||
void *p;
|
||||
char *p;
|
||||
|
||||
size += BUFFER_CHECK_SIZE*2;
|
||||
p = g_malloc0(size);
|
||||
data_add(p, size, file, line);
|
||||
return p+BUFFER_CHECK_SIZE;
|
||||
return (void *) (p+BUFFER_CHECK_SIZE);
|
||||
}
|
||||
|
||||
void *ig_realloc(void *mem, unsigned long size, const char *file, int line)
|
||||
{
|
||||
void *p;
|
||||
char *p, *oldmem = mem;
|
||||
|
||||
size += BUFFER_CHECK_SIZE*2;
|
||||
mem -= BUFFER_CHECK_SIZE;
|
||||
data_remove(mem, file, line);
|
||||
p = g_realloc(mem, size);
|
||||
oldmem -= BUFFER_CHECK_SIZE;
|
||||
data_remove(oldmem, file, line);
|
||||
p = g_realloc(oldmem, size);
|
||||
data_add(p, size, file, line);
|
||||
return p+BUFFER_CHECK_SIZE;
|
||||
return (void *) (p+BUFFER_CHECK_SIZE);
|
||||
}
|
||||
|
||||
char *ig_strdup(const char *str, const char *file, int line)
|
||||
|
|
@ -252,11 +264,14 @@ char *ig_strdup_vprintf(const char *file, int line, const char *format, va_list
|
|||
|
||||
void ig_free(void *p)
|
||||
{
|
||||
if (p == NULL) g_error("ig_free() : trying to free NULL");
|
||||
char *cp = p;
|
||||
|
||||
p -= BUFFER_CHECK_SIZE;
|
||||
p = data_remove(p, "??", 0);
|
||||
if (p != NULL) g_free(p);
|
||||
if (cp == NULL) g_error("ig_free() : trying to free NULL");
|
||||
|
||||
cp -= BUFFER_CHECK_SIZE;
|
||||
data_clear(cp);
|
||||
cp = data_remove(cp, "??", 0);
|
||||
if (cp != NULL) g_free(cp);
|
||||
}
|
||||
|
||||
GString *ig_string_new(const char *file, int line, const char *str)
|
||||
|
|
@ -264,13 +279,13 @@ GString *ig_string_new(const char *file, int line, const char *str)
|
|||
GString *ret;
|
||||
|
||||
ret = g_string_new(str);
|
||||
data_add(ret, INT_MIN, file, line);
|
||||
data_add((void *) ret, INT_MIN, file, line);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ig_string_free(const char *file, int line, GString *str, gboolean freeit)
|
||||
{
|
||||
data_remove(str, file, line);
|
||||
data_remove((void *) str, file, line);
|
||||
if (!freeit)
|
||||
data_add(str->str, INT_MIN, file, line);
|
||||
|
||||
|
|
@ -304,7 +319,7 @@ void ig_profile_line(void *key, MEM_REC *rec)
|
|||
strcmp(rec->file, "ig_strdup_vprintf") == 0 ||
|
||||
strcmp(rec->file, "ig_strconcat") == 0 ||
|
||||
strcmp(rec->file, "ig_string_free (free = FALSE)") == 0))
|
||||
data = rec->p + BUFFER_CHECK_SIZE;
|
||||
data = (char *) rec->p + BUFFER_CHECK_SIZE;
|
||||
else
|
||||
data = rec->comment;
|
||||
fprintf(stderr, "%s:%d %d bytes (%s)\n", rec->file, rec->line, rec->size, data);
|
||||
|
|
|
|||
|
|
@ -196,12 +196,12 @@ GSList *gslist_find_icase_string(GSList *list, const char *key)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void *gslist_foreach_find(GSList *list, FOREACH_FIND_FUNC func, void *data)
|
||||
void *gslist_foreach_find(GSList *list, FOREACH_FIND_FUNC func, const void *data)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
while (list != NULL) {
|
||||
ret = func(list->data, data);
|
||||
ret = func(list->data, (void *) data);
|
||||
if (ret != NULL) return ret;
|
||||
|
||||
list = list->next;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ GSList *gslist_find_icase_string(GSList *list, const char *key);
|
|||
GList *glist_find_string(GList *list, const char *key);
|
||||
GList *glist_find_icase_string(GList *list, const char *key);
|
||||
|
||||
void *gslist_foreach_find(GSList *list, FOREACH_FIND_FUNC func, void *data);
|
||||
void *gslist_foreach_find(GSList *list, FOREACH_FIND_FUNC func, const void *data);
|
||||
|
||||
/* `list' contains pointer to structure with a char* to string. */
|
||||
char *gslistptr_to_string(GSList *list, int offset, const char *delimiter);
|
||||
|
|
|
|||
|
|
@ -324,6 +324,11 @@ void module_unload(MODULE_REC *module)
|
|||
g_free(module);
|
||||
}
|
||||
|
||||
static void uniq_get_modules(char *key, void *value, GSList **list)
|
||||
{
|
||||
*list = g_slist_append(*list, key);
|
||||
}
|
||||
|
||||
void modules_init(void)
|
||||
{
|
||||
modules = NULL;
|
||||
|
|
@ -342,11 +347,19 @@ void modules_init(void)
|
|||
|
||||
void modules_deinit(void)
|
||||
{
|
||||
g_hash_table_foreach(idlookup, (GHFunc) module_uniq_destroy, NULL);
|
||||
g_hash_table_destroy(idlookup);
|
||||
g_hash_table_destroy(uniqids);
|
||||
GSList *list;
|
||||
|
||||
g_hash_table_foreach(stridlookup, (GHFunc) module_uniq_destroy, NULL);
|
||||
list = NULL;
|
||||
g_hash_table_foreach(idlookup, (GHFunc) uniq_get_modules, &list);
|
||||
g_hash_table_foreach(stridlookup, (GHFunc) uniq_get_modules, &list);
|
||||
|
||||
while (list != NULL) {
|
||||
module_uniq_destroy(list->data);
|
||||
list = g_slist_remove(list, list->data);
|
||||
}
|
||||
|
||||
g_hash_table_destroy(idlookup);
|
||||
g_hash_table_destroy(stridlookup);
|
||||
g_hash_table_destroy(uniqids);
|
||||
g_hash_table_destroy(uniqstrids);
|
||||
}
|
||||
|
|
|
|||
268
src/core/nicklist.c
Normal file
268
src/core/nicklist.c
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
/*
|
||||
nicklist.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "signals.h"
|
||||
#include "misc.h"
|
||||
|
||||
#include "nicklist.h"
|
||||
#include "masks.h"
|
||||
|
||||
/* Add new nick to list */
|
||||
NICK_REC *nicklist_insert(CHANNEL_REC *channel, const char *nick,
|
||||
int op, int voice, int send_massjoin)
|
||||
{
|
||||
NICK_REC *rec;
|
||||
|
||||
g_return_val_if_fail(IS_CHANNEL(channel), NULL);
|
||||
g_return_val_if_fail(nick != NULL, NULL);
|
||||
|
||||
rec = g_new0(NICK_REC, 1);
|
||||
|
||||
if (op) rec->op = TRUE;
|
||||
if (voice) rec->voice = TRUE;
|
||||
|
||||
rec->send_massjoin = send_massjoin;
|
||||
rec->nick = g_strdup(nick);
|
||||
rec->host = NULL;
|
||||
|
||||
g_hash_table_insert(channel->nicks, rec->nick, rec);
|
||||
signal_emit("nicklist new", 2, channel, rec);
|
||||
return rec;
|
||||
}
|
||||
|
||||
static void nicklist_destroy(CHANNEL_REC *channel, NICK_REC *nick)
|
||||
{
|
||||
signal_emit("nicklist remove", 2, channel, nick);
|
||||
|
||||
g_free(nick->nick);
|
||||
g_free_not_null(nick->realname);
|
||||
g_free_not_null(nick->host);
|
||||
g_free(nick);
|
||||
}
|
||||
|
||||
/* remove nick from list */
|
||||
void nicklist_remove(CHANNEL_REC *channel, NICK_REC *nick)
|
||||
{
|
||||
g_return_if_fail(IS_CHANNEL(channel));
|
||||
g_return_if_fail(nick != NULL);
|
||||
|
||||
g_hash_table_remove(channel->nicks, nick->nick);
|
||||
nicklist_destroy(channel, nick);
|
||||
}
|
||||
|
||||
static NICK_REC *nicklist_find_wildcards(CHANNEL_REC *channel,
|
||||
const char *mask)
|
||||
{
|
||||
GSList *nicks, *tmp;
|
||||
NICK_REC *nick;
|
||||
|
||||
nicks = nicklist_getnicks(channel);
|
||||
nick = NULL;
|
||||
for (tmp = nicks; tmp != NULL; tmp = tmp->next) {
|
||||
nick = tmp->data;
|
||||
|
||||
if (mask_match_address(channel->server, mask,
|
||||
nick->nick, nick->host))
|
||||
break;
|
||||
}
|
||||
g_slist_free(nicks);
|
||||
return tmp == NULL ? NULL : nick;
|
||||
}
|
||||
|
||||
GSList *nicklist_find_multiple(CHANNEL_REC *channel, const char *mask)
|
||||
{
|
||||
GSList *nicks, *tmp, *next;
|
||||
|
||||
g_return_val_if_fail(IS_CHANNEL(channel), NULL);
|
||||
g_return_val_if_fail(mask != NULL, NULL);
|
||||
|
||||
nicks = nicklist_getnicks(channel);
|
||||
for (tmp = nicks; tmp != NULL; tmp = next) {
|
||||
NICK_REC *nick = tmp->data;
|
||||
|
||||
next = tmp->next;
|
||||
if (!mask_match_address(channel->server, mask,
|
||||
nick->nick, nick->host))
|
||||
nicks = g_slist_remove(nicks, tmp->data);
|
||||
}
|
||||
|
||||
return nicks;
|
||||
}
|
||||
|
||||
/* Find nick record from list */
|
||||
NICK_REC *nicklist_find(CHANNEL_REC *channel, const char *mask)
|
||||
{
|
||||
NICK_REC *nickrec;
|
||||
char *nick, *host;
|
||||
|
||||
g_return_val_if_fail(IS_CHANNEL(channel), NULL);
|
||||
g_return_val_if_fail(mask != NULL, NULL);
|
||||
|
||||
nick = g_strdup(mask);
|
||||
host = strchr(nick, '!');
|
||||
if (host != NULL) *host++ = '\0';
|
||||
|
||||
if (strchr(nick, '*') || strchr(nick, '?')) {
|
||||
g_free(nick);
|
||||
return nicklist_find_wildcards(channel, mask);
|
||||
}
|
||||
|
||||
nickrec = g_hash_table_lookup(channel->nicks, nick);
|
||||
|
||||
if (nickrec != NULL && host != NULL &&
|
||||
(nickrec->host == NULL || !match_wildcards(host, nickrec->host))) {
|
||||
/* hosts didn't match */
|
||||
nickrec = NULL;
|
||||
}
|
||||
g_free(nick);
|
||||
return nickrec;
|
||||
}
|
||||
|
||||
static void get_nicks_hash(gpointer key, NICK_REC *rec, GSList **list)
|
||||
{
|
||||
*list = g_slist_append(*list, rec);
|
||||
}
|
||||
|
||||
/* Get list of nicks */
|
||||
GSList *nicklist_getnicks(CHANNEL_REC *channel)
|
||||
{
|
||||
GSList *list;
|
||||
|
||||
g_return_val_if_fail(IS_CHANNEL(channel), NULL);
|
||||
|
||||
list = NULL;
|
||||
g_hash_table_foreach(channel->nicks, (GHFunc) get_nicks_hash, &list);
|
||||
return list;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
CHANNEL_REC *channel;
|
||||
const char *nick;
|
||||
GSList *list;
|
||||
} NICKLIST_GET_SAME_REC;
|
||||
|
||||
static void get_nicks_same_hash(gpointer key, NICK_REC *nick,
|
||||
NICKLIST_GET_SAME_REC *rec)
|
||||
{
|
||||
if (g_strcasecmp(nick->nick, rec->nick) == 0) {
|
||||
rec->list = g_slist_append(rec->list, rec->channel);
|
||||
rec->list = g_slist_append(rec->list, nick);
|
||||
}
|
||||
}
|
||||
|
||||
GSList *nicklist_get_same(SERVER_REC *server, const char *nick)
|
||||
{
|
||||
NICKLIST_GET_SAME_REC rec;
|
||||
GSList *tmp;
|
||||
|
||||
g_return_val_if_fail(IS_SERVER(server), NULL);
|
||||
|
||||
rec.nick = nick;
|
||||
rec.list = NULL;
|
||||
for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
|
||||
rec.channel = tmp->data;
|
||||
g_hash_table_foreach(rec.channel->nicks,
|
||||
(GHFunc) get_nicks_same_hash, &rec);
|
||||
}
|
||||
return rec.list;
|
||||
}
|
||||
|
||||
/* nick record comparision for sort functions */
|
||||
int nicklist_compare(NICK_REC *p1, NICK_REC *p2)
|
||||
{
|
||||
if (p1 == NULL) return -1;
|
||||
if (p2 == NULL) return 1;
|
||||
|
||||
if (p1->op && !p2->op) return -1;
|
||||
if (!p1->op && p2->op) return 1;
|
||||
|
||||
if (!p1->op) {
|
||||
if (p1->voice && !p2->voice) return -1;
|
||||
if (!p1->voice && p2->voice) return 1;
|
||||
}
|
||||
|
||||
return g_strcasecmp(p1->nick, p2->nick);
|
||||
}
|
||||
|
||||
void nicklist_update_flags(SERVER_REC *server, const char *nick,
|
||||
int gone, int serverop)
|
||||
{
|
||||
GSList *nicks, *tmp;
|
||||
CHANNEL_REC *channel;
|
||||
NICK_REC *rec;
|
||||
|
||||
g_return_if_fail(IS_SERVER(server));
|
||||
g_return_if_fail(nick != NULL);
|
||||
|
||||
nicks = nicklist_get_same(server, nick);
|
||||
for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) {
|
||||
channel = tmp->data;
|
||||
rec = tmp->next->data;
|
||||
|
||||
rec->last_check = time(NULL);
|
||||
|
||||
if (gone != -1 && rec->gone != gone) {
|
||||
rec->gone = gone;
|
||||
signal_emit("nick gone changed", 2, channel, rec);
|
||||
}
|
||||
|
||||
if (serverop != -1 && rec->serverop != serverop) {
|
||||
rec->serverop = serverop;
|
||||
signal_emit("nick serverop changed", 2, channel, rec);
|
||||
}
|
||||
}
|
||||
g_slist_free(nicks);
|
||||
}
|
||||
|
||||
static void sig_channel_created(CHANNEL_REC *channel)
|
||||
{
|
||||
g_return_if_fail(IS_CHANNEL(channel));
|
||||
|
||||
channel->nicks = g_hash_table_new((GHashFunc) g_istr_hash,
|
||||
(GCompareFunc) g_istr_equal);
|
||||
}
|
||||
|
||||
static void nicklist_remove_hash(gpointer key, NICK_REC *nick,
|
||||
CHANNEL_REC *channel)
|
||||
{
|
||||
nicklist_destroy(channel, nick);
|
||||
}
|
||||
|
||||
static void sig_channel_destroyed(CHANNEL_REC *channel)
|
||||
{
|
||||
g_return_if_fail(IS_CHANNEL(channel));
|
||||
|
||||
g_hash_table_foreach(channel->nicks,
|
||||
(GHFunc) nicklist_remove_hash, channel);
|
||||
g_hash_table_destroy(channel->nicks);
|
||||
}
|
||||
|
||||
void nicklist_init(void)
|
||||
{
|
||||
signal_add_first("channel created", (SIGNAL_FUNC) sig_channel_created);
|
||||
signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
|
||||
}
|
||||
|
||||
void nicklist_deinit(void)
|
||||
{
|
||||
signal_remove("channel created", (SIGNAL_FUNC) sig_channel_created);
|
||||
signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
|
||||
}
|
||||
50
src/core/nicklist.h
Normal file
50
src/core/nicklist.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#ifndef __NICKLIST_H
|
||||
#define __NICKLIST_H
|
||||
|
||||
#include "servers.h"
|
||||
#include "channels.h"
|
||||
|
||||
typedef struct {
|
||||
time_t last_check; /* last time gone was checked */
|
||||
|
||||
char *nick;
|
||||
char *host;
|
||||
char *realname;
|
||||
int hops;
|
||||
|
||||
/* status in server */
|
||||
int gone:1;
|
||||
int serverop:1;
|
||||
|
||||
/* status in channel */
|
||||
int send_massjoin:1; /* Waiting to be sent in massjoin signal */
|
||||
int op:1;
|
||||
int halfop:1;
|
||||
int voice:1;
|
||||
} NICK_REC;
|
||||
|
||||
/* Add new nick to list */
|
||||
NICK_REC *nicklist_insert(CHANNEL_REC *channel, const char *nick,
|
||||
int op, int voice, int send_massjoin);
|
||||
/* remove nick from list */
|
||||
void nicklist_remove(CHANNEL_REC *channel, NICK_REC *nick);
|
||||
/* Find nick record from list */
|
||||
NICK_REC *nicklist_find(CHANNEL_REC *channel, const char *mask);
|
||||
/* Get list of nicks that match the mask */
|
||||
GSList *nicklist_find_multiple(CHANNEL_REC *channel, const char *mask);
|
||||
/* Get list of nicks */
|
||||
GSList *nicklist_getnicks(CHANNEL_REC *channel);
|
||||
/* Get all the nick records of `nick'. Returns channel, nick, channel, ... */
|
||||
GSList *nicklist_get_same(SERVER_REC *server, const char *nick);
|
||||
|
||||
/* Update specified nick's status in server. */
|
||||
void nicklist_update_flags(SERVER_REC *server, const char *nick,
|
||||
int gone, int ircop);
|
||||
|
||||
/* Nick record comparision for sort functions */
|
||||
int nicklist_compare(NICK_REC *p1, NICK_REC *p2);
|
||||
|
||||
void nicklist_init(void);
|
||||
void nicklist_deinit(void);
|
||||
|
||||
#endif
|
||||
124
src/core/queries.c
Normal file
124
src/core/queries.c
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
queries.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "signals.h"
|
||||
#include "misc.h"
|
||||
|
||||
#include "queries.h"
|
||||
|
||||
GSList *queries;
|
||||
|
||||
typedef QUERY_REC *(*QUERY_FIND_FUNC)(SERVER_REC *, const char *);
|
||||
|
||||
void query_init(QUERY_REC *query, int automatic)
|
||||
{
|
||||
g_return_if_fail(query != NULL);
|
||||
g_return_if_fail(query->name != NULL);
|
||||
|
||||
queries = g_slist_append(queries, query);
|
||||
if (query->server != NULL) {
|
||||
query->server->queries =
|
||||
g_slist_append(query->server->queries, query);
|
||||
}
|
||||
|
||||
MODULE_DATA_INIT(query);
|
||||
query->type = module_get_uniq_id("QUERY", 0);
|
||||
if (query->server != NULL)
|
||||
query->server_tag = g_strdup(query->server->tag);
|
||||
|
||||
signal_emit("query created", 2, query, GINT_TO_POINTER(automatic));
|
||||
}
|
||||
|
||||
void query_destroy(QUERY_REC *query)
|
||||
{
|
||||
g_return_if_fail(IS_QUERY(query));
|
||||
|
||||
if (query->destroying) return;
|
||||
query->destroying = TRUE;
|
||||
|
||||
queries = g_slist_remove(queries, query);
|
||||
if (query->server != NULL) {
|
||||
query->server->queries =
|
||||
g_slist_remove(query->server->queries, query);
|
||||
}
|
||||
signal_emit("query destroyed", 1, query);
|
||||
|
||||
MODULE_DATA_DEINIT(query);
|
||||
g_free_not_null(query->address);
|
||||
g_free(query->name);
|
||||
g_free(query->server_tag);
|
||||
g_free(query);
|
||||
}
|
||||
|
||||
static QUERY_REC *query_find_server(SERVER_REC *server, const char *nick)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
g_return_val_if_fail(IS_SERVER(server), NULL);
|
||||
|
||||
if (server->query_find_func != NULL) {
|
||||
/* use the server specific query find function */
|
||||
QUERY_FIND_FUNC query_find_func;
|
||||
query_find_func = (QUERY_FIND_FUNC) server->query_find_func;
|
||||
return query_find_func(server, nick);
|
||||
}
|
||||
|
||||
for (tmp = server->queries; tmp != NULL; tmp = tmp->next) {
|
||||
QUERY_REC *rec = tmp->data;
|
||||
|
||||
if (rec->chat_type == server->query_type &&
|
||||
g_strcasecmp(nick, rec->name) == 0)
|
||||
return rec;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
QUERY_REC *query_find(SERVER_REC *server, const char *nick)
|
||||
{
|
||||
g_return_val_if_fail(server == NULL || IS_SERVER(server), NULL);
|
||||
g_return_val_if_fail(nick != NULL, NULL);
|
||||
|
||||
if (server != NULL)
|
||||
return query_find_server(server, nick);
|
||||
|
||||
/* find from any server */
|
||||
return gslist_foreach_find(servers,
|
||||
(FOREACH_FIND_FUNC) query_find_server,
|
||||
(void *) nick);
|
||||
}
|
||||
|
||||
void query_change_server(QUERY_REC *query, SERVER_REC *server)
|
||||
{
|
||||
g_return_if_fail(IS_QUERY(query));
|
||||
|
||||
query->server = server;
|
||||
signal_emit("query server changed", 2, query, server);
|
||||
}
|
||||
|
||||
void queries_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void queries_deinit(void)
|
||||
{
|
||||
module_uniq_destroy("QUERY");
|
||||
}
|
||||
32
src/core/queries.h
Normal file
32
src/core/queries.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef __QUERIES_H
|
||||
#define __QUERIES_H
|
||||
|
||||
#include "servers.h"
|
||||
|
||||
#define IS_QUERY(query) \
|
||||
((query) != NULL && \
|
||||
module_find_id("QUERY", ((QUERY_REC *) (query))->type) != -1)
|
||||
|
||||
/* Returns QUERY_REC if it's query, NULL if it isn't. */
|
||||
#define QUERY(query) \
|
||||
(IS_QUERY(query) ? (QUERY_REC *) (query) : NULL)
|
||||
|
||||
#define STRUCT_SERVER_REC SERVER_REC
|
||||
typedef struct {
|
||||
#include "query-rec.h"
|
||||
} QUERY_REC;
|
||||
|
||||
extern GSList *queries;
|
||||
|
||||
void query_init(QUERY_REC *query, int automatic);
|
||||
void query_destroy(QUERY_REC *query);
|
||||
|
||||
/* Find query by name, if `server' is NULL, search from all servers */
|
||||
QUERY_REC *query_find(SERVER_REC *server, const char *nick);
|
||||
|
||||
void query_change_server(QUERY_REC *query, SERVER_REC *server);
|
||||
|
||||
void queries_init(void);
|
||||
void queries_deinit(void);
|
||||
|
||||
#endif
|
||||
9
src/core/query-rec.h
Normal file
9
src/core/query-rec.h
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
/* QUERY_REC definition, used for inheritance */
|
||||
|
||||
#include "window-item-rec.h"
|
||||
|
||||
char *address;
|
||||
char *server_tag;
|
||||
int unwanted:1; /* TRUE if the other side closed or
|
||||
some error occured (DCC chats!) */
|
||||
int destroying:1;
|
||||
26
src/core/server-connect-rec.h
Normal file
26
src/core/server-connect-rec.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/* SERVER_CONNECT_REC definition, used for inheritance */
|
||||
|
||||
int type;
|
||||
int chat_type;
|
||||
|
||||
/* if we're connecting via proxy, or just NULLs */
|
||||
char *proxy;
|
||||
int proxy_port;
|
||||
char *proxy_string;
|
||||
|
||||
char *address;
|
||||
int port;
|
||||
char *chatnet;
|
||||
|
||||
IPADDR *own_ip;
|
||||
|
||||
char *password;
|
||||
char *nick;
|
||||
char *username;
|
||||
char *realname;
|
||||
|
||||
/* when reconnecting, the old server status */
|
||||
int reconnection:1; /* we're trying to reconnect */
|
||||
char *channels;
|
||||
char *away_reason;
|
||||
char *usermode;
|
||||
50
src/core/server-rec.h
Normal file
50
src/core/server-rec.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/* SERVER_REC definition, used for inheritance */
|
||||
|
||||
int type; /* should always be "SERVER" */
|
||||
int chat_type;
|
||||
|
||||
STRUCT_SERVER_CONNECT_REC *connrec;
|
||||
time_t connect_time; /* connection time */
|
||||
time_t real_connect_time; /* time when server replied that we really are connected */
|
||||
|
||||
char *tag; /* tag name for addressing server */
|
||||
char *nick; /* current nick */
|
||||
|
||||
int connected:1; /* connected to server */
|
||||
int connection_lost:1; /* Connection lost unintentionally */
|
||||
|
||||
void *handle; /* NET_SENDBUF_REC socket */
|
||||
int readtag; /* input tag */
|
||||
|
||||
/* for net_connect_nonblock() */
|
||||
int connect_pipe[2];
|
||||
int connect_tag;
|
||||
int connect_pid;
|
||||
|
||||
/* For deciding if event should be handled internally */
|
||||
GHashTable *eventtable; /* "event xxx" : GSList* of REDIRECT_RECs */
|
||||
GHashTable *eventgrouptable; /* event group : GSList* of REDIRECT_RECs */
|
||||
GHashTable *cmdtable; /* "command xxx" : REDIRECT_CMD_REC* */
|
||||
|
||||
void *rawlog;
|
||||
void *buffer; /* receive buffer */
|
||||
GHashTable *module_data;
|
||||
|
||||
char *version; /* server version */
|
||||
char *away_reason;
|
||||
int server_operator:1;
|
||||
int usermode_away:1;
|
||||
int banned:1; /* not allowed to connect to this server */
|
||||
|
||||
GSList *channels;
|
||||
GSList *queries;
|
||||
|
||||
/* support for multiple server types */
|
||||
void *channel_find_func;
|
||||
void *query_find_func;
|
||||
int channel_type;
|
||||
int query_type;
|
||||
|
||||
void *mask_match_func;
|
||||
|
||||
#undef STRUCT_SERVER_CONNECT_REC
|
||||
19
src/core/server-setup-rec.h
Normal file
19
src/core/server-setup-rec.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
int type;
|
||||
int chat_type;
|
||||
|
||||
char *chatnet;
|
||||
|
||||
char *address;
|
||||
int port;
|
||||
char *password;
|
||||
|
||||
char *own_host; /* address to use when connecting this server */
|
||||
IPADDR *own_ip; /* resolved own_address if not NULL */
|
||||
|
||||
time_t last_connect; /* to avoid reconnecting too fast.. */
|
||||
|
||||
int autoconnect:1;
|
||||
int last_failed:1; /* if last connection attempt failed */
|
||||
int banned:1; /* if we're banned from this server */
|
||||
|
||||
GHashTable *module_data;
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
#ifndef __SERVER_H
|
||||
#define __SERVER_H
|
||||
|
||||
#ifndef __NETWORK_H
|
||||
typedef struct _ipaddr IPADDR;
|
||||
#endif
|
||||
|
||||
/* all strings should be either NULL or dynamically allocated */
|
||||
/* address and nick are mandatory, rest are optional */
|
||||
typedef struct {
|
||||
/* if we're connecting via proxy, or just NULLs */
|
||||
char *proxy;
|
||||
int proxy_port;
|
||||
char *proxy_string;
|
||||
|
||||
char *address;
|
||||
int port;
|
||||
char *ircnet;
|
||||
|
||||
IPADDR *own_ip;
|
||||
|
||||
char *password;
|
||||
char *nick;
|
||||
char *username;
|
||||
char *realname;
|
||||
|
||||
/* when reconnecting, the old server status */
|
||||
int reconnection:1; /* we're trying to reconnect */
|
||||
char *channels;
|
||||
char *away_reason;
|
||||
char *usermode;
|
||||
} SERVER_CONNECT_REC;
|
||||
|
||||
typedef struct {
|
||||
int type; /* server type */
|
||||
|
||||
SERVER_CONNECT_REC *connrec;
|
||||
time_t connect_time; /* connection time */
|
||||
time_t real_connect_time; /* time when server replied that we really are connected */
|
||||
|
||||
char *tag; /* tag name for addressing server */
|
||||
char *nick; /* current nick */
|
||||
|
||||
int connected:1; /* connected to server */
|
||||
int connection_lost:1; /* Connection lost unintentionally */
|
||||
|
||||
void *handle; /* NET_SENDBUF_REC socket */
|
||||
int readtag; /* input tag */
|
||||
|
||||
/* for net_connect_nonblock() */
|
||||
int connect_pipe[2];
|
||||
int connect_tag;
|
||||
int connect_pid;
|
||||
|
||||
/* For deciding if event should be handled internally */
|
||||
GHashTable *eventtable; /* "event xxx" : GSList* of REDIRECT_RECs */
|
||||
GHashTable *eventgrouptable; /* event group : GSList* of REDIRECT_RECs */
|
||||
GHashTable *cmdtable; /* "command xxx" : REDIRECT_CMD_REC* */
|
||||
|
||||
void *rawlog;
|
||||
void *buffer; /* receive buffer */
|
||||
GHashTable *module_data;
|
||||
|
||||
char *version; /* server version */
|
||||
char *away_reason;
|
||||
int usermode_away:1;
|
||||
int banned:1; /* not allowed to connect to this server */
|
||||
} SERVER_REC;
|
||||
|
||||
extern GSList *servers, *lookup_servers;
|
||||
|
||||
/* Connect to server */
|
||||
int server_connect(SERVER_REC *server);
|
||||
/* Disconnect from server */
|
||||
void server_disconnect(SERVER_REC *server);
|
||||
|
||||
SERVER_REC *server_find_tag(const char *tag);
|
||||
SERVER_REC *server_find_ircnet(const char *ircnet);
|
||||
|
||||
void servers_init(void);
|
||||
void servers_deinit(void);
|
||||
|
||||
#endif
|
||||
356
src/core/servers-reconnect.c
Normal file
356
src/core/servers-reconnect.c
Normal file
|
|
@ -0,0 +1,356 @@
|
|||
/*
|
||||
servers-reconnect.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "commands.h"
|
||||
#include "network.h"
|
||||
#include "signals.h"
|
||||
|
||||
#include "servers-setup.h"
|
||||
#include "servers-reconnect.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
GSList *reconnects;
|
||||
static int last_reconnect_tag;
|
||||
static int reconnect_timeout_tag;
|
||||
static int reconnect_time;
|
||||
|
||||
static void server_reconnect_add(SERVER_CONNECT_REC *conn,
|
||||
time_t next_connect)
|
||||
{
|
||||
RECONNECT_REC *rec;
|
||||
|
||||
g_return_if_fail(IS_SERVER_CONNECT(conn));
|
||||
|
||||
rec = g_new(RECONNECT_REC, 1);
|
||||
rec->tag = ++last_reconnect_tag;
|
||||
rec->conn = conn;
|
||||
rec->next_connect = next_connect;
|
||||
|
||||
reconnects = g_slist_append(reconnects, rec);
|
||||
}
|
||||
|
||||
static void server_reconnect_destroy(RECONNECT_REC *rec, int free_conn)
|
||||
{
|
||||
g_return_if_fail(rec != NULL);
|
||||
|
||||
reconnects = g_slist_remove(reconnects, rec);
|
||||
|
||||
signal_emit("server reconnect remove", 1, rec);
|
||||
if (free_conn) server_connect_free(rec->conn);
|
||||
g_free(rec);
|
||||
|
||||
if (reconnects == NULL)
|
||||
last_reconnect_tag = 0;
|
||||
}
|
||||
|
||||
static int server_reconnect_timeout(void)
|
||||
{
|
||||
SERVER_CONNECT_REC *conn;
|
||||
GSList *list, *tmp;
|
||||
time_t now;
|
||||
|
||||
/* If server_connect() removes the next reconnection in queue,
|
||||
we're screwed. I don't think this should happen anymore, but just
|
||||
to be sure we don't crash, do this safely. */
|
||||
list = g_slist_copy(reconnects);
|
||||
now = time(NULL);
|
||||
for (tmp = list; tmp != NULL; tmp = tmp->next) {
|
||||
RECONNECT_REC *rec = tmp->data;
|
||||
|
||||
if (g_slist_find(reconnects, rec) == NULL)
|
||||
continue;
|
||||
|
||||
if (rec->next_connect <= now) {
|
||||
conn = rec->conn;
|
||||
server_reconnect_destroy(rec, FALSE);
|
||||
server_connect(conn);
|
||||
}
|
||||
}
|
||||
|
||||
g_slist_free(list);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void sserver_connect(SERVER_SETUP_REC *rec, SERVER_CONNECT_REC *conn)
|
||||
{
|
||||
conn->address = g_strdup(rec->address);
|
||||
conn->port = rec->port;
|
||||
|
||||
server_setup_fill_reconn(conn, rec);
|
||||
if (rec->last_connect > time(NULL)-reconnect_time) {
|
||||
/* can't reconnect this fast, wait.. */
|
||||
server_reconnect_add(conn, rec->last_connect+reconnect_time);
|
||||
} else {
|
||||
/* connect to server.. */
|
||||
server_connect(conn);
|
||||
}
|
||||
}
|
||||
|
||||
static SERVER_CONNECT_REC *
|
||||
server_connect_copy_skeleton(SERVER_CONNECT_REC *src)
|
||||
{
|
||||
SERVER_CONNECT_REC *dest;
|
||||
|
||||
dest = NULL;
|
||||
signal_emit("server connect copy", 2, &dest, src);
|
||||
g_return_val_if_fail(dest != NULL, NULL);
|
||||
|
||||
dest->proxy = g_strdup(src->proxy);
|
||||
dest->proxy_port = src->proxy_port;
|
||||
dest->proxy_string = g_strdup(src->proxy_string);
|
||||
|
||||
dest->chatnet = g_strdup(src->chatnet);
|
||||
dest->nick = g_strdup(src->nick);
|
||||
dest->username = g_strdup(src->username);
|
||||
dest->realname = g_strdup(src->realname);
|
||||
|
||||
if (src->own_ip != NULL) {
|
||||
dest->own_ip = g_new(IPADDR, 1);
|
||||
memcpy(dest->own_ip, src->own_ip, sizeof(IPADDR));
|
||||
}
|
||||
|
||||
dest->channels = g_strdup(src->channels);
|
||||
dest->away_reason = g_strdup(src->away_reason);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
#define server_should_reconnect(server) \
|
||||
((server)->connection_lost && \
|
||||
((server)->connrec->chatnet != NULL || !(server)->banned))
|
||||
|
||||
static void sig_reconnect(SERVER_REC *server)
|
||||
{
|
||||
SERVER_CONNECT_REC *conn;
|
||||
SERVER_SETUP_REC *sserver;
|
||||
GSList *tmp;
|
||||
int found, through;
|
||||
time_t now;
|
||||
|
||||
g_return_if_fail(IS_SERVER(server));
|
||||
|
||||
if (reconnect_time == -1 || !server_should_reconnect(server))
|
||||
return;
|
||||
|
||||
conn = server_connect_copy_skeleton(server->connrec);
|
||||
|
||||
/* save the server status */
|
||||
if (server->connected) {
|
||||
conn->reconnection = TRUE;
|
||||
|
||||
g_free_not_null(conn->away_reason);
|
||||
conn->away_reason = !server->usermode_away ? NULL :
|
||||
g_strdup(server->away_reason);
|
||||
|
||||
signal_emit("server reconnect save status", 2, conn, server);
|
||||
}
|
||||
|
||||
sserver = server_setup_find(server->connrec->address,
|
||||
server->connrec->port);
|
||||
|
||||
if (sserver != NULL) {
|
||||
/* save the last connection time/status */
|
||||
sserver->last_connect = server->connect_time == 0 ?
|
||||
time(NULL) : server->connect_time;
|
||||
sserver->last_failed = !server->connected;
|
||||
if (server->banned) sserver->banned = TRUE;
|
||||
}
|
||||
|
||||
if (sserver == NULL || conn->chatnet == NULL) {
|
||||
/* not in any chatnet, just reconnect back to same server */
|
||||
conn->address = g_strdup(server->connrec->address);
|
||||
conn->port = server->connrec->port;
|
||||
conn->password = server->connrec->password == NULL ? NULL :
|
||||
g_strdup(server->connrec->password);
|
||||
|
||||
if (server->connect_time != 0 &&
|
||||
time(NULL)-server->connect_time > reconnect_time) {
|
||||
/* there's been enough time since last connection,
|
||||
reconnect back immediately */
|
||||
server_connect(conn);
|
||||
} else {
|
||||
/* reconnect later.. */
|
||||
server_reconnect_add(conn, (server->connect_time == 0 ? time(NULL) :
|
||||
server->connect_time) + reconnect_time);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* always try to first connect to the first on the list where we
|
||||
haven't got unsuccessful connection attempts for the last half
|
||||
an hour. */
|
||||
|
||||
now = time(NULL);
|
||||
for (tmp = setupservers; tmp != NULL; tmp = tmp->next) {
|
||||
SERVER_SETUP_REC *rec = tmp->data;
|
||||
|
||||
if (rec->chatnet != NULL && g_strcasecmp(conn->chatnet, rec->chatnet) == 0 &&
|
||||
!rec->banned && (!rec->last_connect || !rec->last_failed ||
|
||||
rec->last_connect < now-FAILED_RECONNECT_WAIT)) {
|
||||
sserver_connect(rec, conn);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* just try the next server in list */
|
||||
found = through = FALSE;
|
||||
for (tmp = setupservers; tmp != NULL; ) {
|
||||
SERVER_SETUP_REC *rec = tmp->data;
|
||||
|
||||
if (!found && g_strcasecmp(rec->address, server->connrec->address) == 0 &&
|
||||
server->connrec->port == rec->port)
|
||||
found = TRUE;
|
||||
else if (found && !rec->banned && rec->chatnet != NULL &&
|
||||
g_strcasecmp(conn->chatnet, rec->chatnet) == 0) {
|
||||
sserver_connect(rec, conn);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tmp->next != NULL) {
|
||||
tmp = tmp->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (through) {
|
||||
/* shouldn't happen unless there's no servers in
|
||||
this chatnet in setup.. */
|
||||
server_connect_free(conn);
|
||||
break;
|
||||
}
|
||||
|
||||
tmp = setupservers;
|
||||
found = through = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove all servers from reconnect list */
|
||||
/* SYNTAX: RMRECONNS */
|
||||
static void cmd_rmreconns(void)
|
||||
{
|
||||
while (reconnects != NULL)
|
||||
server_reconnect_destroy(reconnects->data, TRUE);
|
||||
}
|
||||
|
||||
static RECONNECT_REC *reconnect_find_tag(int tag)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
for (tmp = reconnects; tmp != NULL; tmp = tmp->next) {
|
||||
RECONNECT_REC *rec = tmp->data;
|
||||
|
||||
if (rec->tag == tag)
|
||||
return rec;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Try to reconnect immediately */
|
||||
/* SYNTAX: RECONNECT <tag> */
|
||||
static void cmd_reconnect(const char *data, SERVER_REC *server)
|
||||
{
|
||||
SERVER_CONNECT_REC *conn;
|
||||
RECONNECT_REC *rec;
|
||||
char *str;
|
||||
int tag;
|
||||
|
||||
if (*data == '\0') {
|
||||
/* reconnect back to same server */
|
||||
if (server == NULL) cmd_return_error(CMDERR_NOT_CONNECTED);
|
||||
str = g_strdup_printf("%s %d %s %s", server->connrec->address,
|
||||
server->connrec->port, server->connrec->password,
|
||||
server->connrec->nick);
|
||||
signal_emit("command server", 2, str, server);
|
||||
g_free(str);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_strncasecmp(data, "RECON-", 6) == 0)
|
||||
data += 6;
|
||||
|
||||
tag = atoi(data);
|
||||
rec = tag <= 0 ? NULL : reconnect_find_tag(tag);
|
||||
|
||||
if (rec == NULL)
|
||||
signal_emit("server reconnect not found", 1, data);
|
||||
else {
|
||||
conn = rec->conn;
|
||||
server_reconnect_destroy(rec, FALSE);
|
||||
server_connect(conn);
|
||||
}
|
||||
}
|
||||
|
||||
static void cmd_disconnect(const char *data, SERVER_REC *server)
|
||||
{
|
||||
RECONNECT_REC *rec;
|
||||
int tag;
|
||||
|
||||
if (g_strncasecmp(data, "RECON-", 6) != 0)
|
||||
return; /* handle only reconnection removing */
|
||||
|
||||
rec = sscanf(data+6, "%d", &tag) == 1 && tag > 0 ?
|
||||
reconnect_find_tag(tag) : NULL;
|
||||
|
||||
if (rec == NULL)
|
||||
signal_emit("server reconnect not found", 1, data);
|
||||
else
|
||||
server_reconnect_destroy(rec, TRUE);
|
||||
signal_stop();
|
||||
}
|
||||
|
||||
static void read_settings(void)
|
||||
{
|
||||
reconnect_time = settings_get_int("server_reconnect_time");
|
||||
}
|
||||
|
||||
void servers_reconnect_init(void)
|
||||
{
|
||||
settings_add_int("server", "server_reconnect_time", 300);
|
||||
|
||||
reconnects = NULL;
|
||||
last_reconnect_tag = 0;
|
||||
|
||||
reconnect_timeout_tag = g_timeout_add(1000, (GSourceFunc) server_reconnect_timeout, NULL);
|
||||
read_settings();
|
||||
|
||||
signal_add("server connect failed", (SIGNAL_FUNC) sig_reconnect);
|
||||
signal_add("server disconnected", (SIGNAL_FUNC) sig_reconnect);
|
||||
command_bind("rmreconns", NULL, (SIGNAL_FUNC) cmd_rmreconns);
|
||||
command_bind("reconnect", NULL, (SIGNAL_FUNC) cmd_reconnect);
|
||||
command_bind_first("disconnect", NULL, (SIGNAL_FUNC) cmd_disconnect);
|
||||
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
|
||||
}
|
||||
|
||||
void servers_reconnect_deinit(void)
|
||||
{
|
||||
g_source_remove(reconnect_timeout_tag);
|
||||
|
||||
while (reconnects != NULL)
|
||||
server_reconnect_destroy(reconnects->data, TRUE);
|
||||
|
||||
signal_remove("server connect failed", (SIGNAL_FUNC) sig_reconnect);
|
||||
signal_remove("server disconnected", (SIGNAL_FUNC) sig_reconnect);
|
||||
command_unbind("rmreconns", (SIGNAL_FUNC) cmd_rmreconns);
|
||||
command_unbind("reconnect", (SIGNAL_FUNC) cmd_reconnect);
|
||||
command_unbind("disconnect", (SIGNAL_FUNC) cmd_disconnect);
|
||||
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
|
||||
}
|
||||
20
src/core/servers-reconnect.h
Normal file
20
src/core/servers-reconnect.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef __SERVER_RECONNECT_H
|
||||
#define __SERVER_RECONNECT_H
|
||||
|
||||
/* wait for half an hour before trying to reconnect to host where last
|
||||
connection failed */
|
||||
#define FAILED_RECONNECT_WAIT (60*30)
|
||||
|
||||
typedef struct {
|
||||
int tag;
|
||||
time_t next_connect;
|
||||
|
||||
SERVER_CONNECT_REC *conn;
|
||||
} RECONNECT_REC;
|
||||
|
||||
extern GSList *reconnects;
|
||||
|
||||
void servers_reconnect_init(void);
|
||||
void servers_reconnect_deinit(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -22,8 +22,8 @@
|
|||
#include "signals.h"
|
||||
#include "misc.h"
|
||||
|
||||
#include "server.h"
|
||||
#include "server-redirect.h"
|
||||
#include "servers.h"
|
||||
#include "servers-redirect.h"
|
||||
|
||||
static int redirect_group;
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ static void server_cmdtable_destroy(char *key, REDIRECT_CMD_REC *value)
|
|||
|
||||
static void sig_disconnected(SERVER_REC *server)
|
||||
{
|
||||
g_return_if_fail(server != NULL);
|
||||
g_return_if_fail(IS_SERVER(server));
|
||||
|
||||
if (server->eventtable != NULL) {
|
||||
g_hash_table_foreach(server->eventtable,
|
||||
|
|
@ -84,7 +84,7 @@ void server_redirect_initv(SERVER_REC *server, const char *command,
|
|||
{
|
||||
REDIRECT_CMD_REC *rec;
|
||||
|
||||
g_return_if_fail(server != NULL);
|
||||
g_return_if_fail(IS_SERVER(server));
|
||||
g_return_if_fail(command != NULL);
|
||||
g_return_if_fail(last > 0);
|
||||
|
||||
|
|
@ -125,7 +125,7 @@ int server_redirect_single_event(SERVER_REC *server, const char *arg,
|
|||
GSList *list, *grouplist;
|
||||
char *origkey;
|
||||
|
||||
g_return_val_if_fail(server != NULL, 0);
|
||||
g_return_val_if_fail(IS_SERVER(server), 0);
|
||||
g_return_val_if_fail(event != NULL, 0);
|
||||
g_return_val_if_fail(signal != NULL, 0);
|
||||
g_return_val_if_fail(arg != NULL || argpos == -1, 0);
|
||||
|
|
@ -171,7 +171,7 @@ void server_redirect_event(SERVER_REC *server, const char *arg, int last, ...)
|
|||
char *event, *signal;
|
||||
int argpos, group;
|
||||
|
||||
g_return_if_fail(server != NULL);
|
||||
g_return_if_fail(IS_SERVER(server));
|
||||
|
||||
va_start(args, last);
|
||||
|
||||
|
|
@ -197,7 +197,7 @@ void server_redirect_default(SERVER_REC *server, const char *command)
|
|||
char *event, *origkey;
|
||||
int last;
|
||||
|
||||
g_return_if_fail(server != NULL);
|
||||
g_return_if_fail(IS_SERVER(server));
|
||||
g_return_if_fail(command != NULL);
|
||||
|
||||
if (server->cmdtable == NULL)
|
||||
|
|
@ -245,7 +245,7 @@ void server_redirect_remove_next(SERVER_REC *server, const char *event,
|
|||
char *origkey;
|
||||
int group;
|
||||
|
||||
g_return_if_fail(server != NULL);
|
||||
g_return_if_fail(IS_SERVER(server));
|
||||
g_return_if_fail(event != NULL);
|
||||
|
||||
if (!g_hash_table_lookup_extended(server->eventtable, event,
|
||||
|
|
@ -321,6 +321,9 @@ GSList *server_redirect_getqueue(SERVER_REC *server, const char *event,
|
|||
char **arglist;
|
||||
int found;
|
||||
|
||||
g_return_val_if_fail(IS_SERVER(server), NULL);
|
||||
g_return_val_if_fail(event != NULL, NULL);
|
||||
|
||||
list = g_hash_table_lookup(server->eventtable, event);
|
||||
|
||||
for (; list != NULL; list = list->next) {
|
||||
|
|
@ -328,7 +331,7 @@ GSList *server_redirect_getqueue(SERVER_REC *server, const char *event,
|
|||
if (rec->argpos == -1)
|
||||
break;
|
||||
|
||||
if (rec->arg == NULL)
|
||||
if (rec->arg == NULL || args == NULL)
|
||||
continue;
|
||||
|
||||
/* we need to check that the argument is right.. */
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __SERVER_REDIRECT_H
|
||||
#define __SERVER_REDIRECT_H
|
||||
#ifndef __SERVERS_REDIRECT_H
|
||||
#define __SERVERS_REDIRECT_H
|
||||
|
||||
#include "server.h"
|
||||
#include "servers.h"
|
||||
|
||||
typedef struct {
|
||||
int last; /* number of "last" events at the start of the events list */
|
||||
456
src/core/servers-setup.c
Normal file
456
src/core/servers-setup.c
Normal file
|
|
@ -0,0 +1,456 @@
|
|||
/*
|
||||
servers-setup.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "signals.h"
|
||||
#include "network.h"
|
||||
#include "lib-config/iconfig.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include "servers.h"
|
||||
#include "servers-setup.h"
|
||||
#include "chatnets.h"
|
||||
|
||||
GSList *setupservers;
|
||||
|
||||
int source_host_ok; /* Use source_host_ip .. */
|
||||
IPADDR *source_host_ip; /* Resolved address */
|
||||
|
||||
static void get_source_host_ip(void)
|
||||
{
|
||||
IPADDR ip;
|
||||
|
||||
if (source_host_ok)
|
||||
return;
|
||||
|
||||
/* FIXME: This will block! */
|
||||
source_host_ok = *settings_get_str("hostname") != '\0' &&
|
||||
net_gethostbyname(settings_get_str("hostname"), &ip) == 0;
|
||||
if (source_host_ok) {
|
||||
if (source_host_ip == NULL)
|
||||
source_host_ip = g_new(IPADDR, 1);
|
||||
memcpy(source_host_ip, &ip, sizeof(IPADDR));
|
||||
}
|
||||
}
|
||||
|
||||
static void conn_set_ip(SERVER_CONNECT_REC *conn,
|
||||
IPADDR **own_ip, const char *own_host)
|
||||
{
|
||||
IPADDR ip;
|
||||
|
||||
if (*own_ip != NULL) {
|
||||
/* use already resolved IP */
|
||||
if (conn->own_ip == NULL)
|
||||
conn->own_ip = g_new(IPADDR, 1);
|
||||
memcpy(conn->own_ip, *own_ip, sizeof(IPADDR));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* resolve the IP and use it */
|
||||
if (net_gethostbyname(own_host, &ip) == 0) {
|
||||
if (conn->own_ip == NULL)
|
||||
conn->own_ip = g_new(IPADDR, 1);
|
||||
memcpy(conn->own_ip, &ip, sizeof(IPADDR));
|
||||
|
||||
*own_ip = g_new(IPADDR, 1);
|
||||
memcpy(*own_ip, &ip, sizeof(IPADDR));
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill information to connection from server setup record */
|
||||
void server_setup_fill_reconn(SERVER_CONNECT_REC *conn,
|
||||
SERVER_SETUP_REC *sserver)
|
||||
{
|
||||
g_return_if_fail(IS_SERVER_CONNECT(conn));
|
||||
g_return_if_fail(IS_SERVER_SETUP(sserver));
|
||||
|
||||
if (sserver->own_host != NULL)
|
||||
conn_set_ip(conn, &sserver->own_ip, sserver->own_host);
|
||||
|
||||
if (sserver->chatnet != NULL && conn->chatnet == NULL)
|
||||
conn->chatnet = g_strdup(sserver->chatnet);
|
||||
|
||||
if (sserver->password != NULL && conn->password == NULL)
|
||||
conn->password = g_strdup(sserver->password);
|
||||
|
||||
signal_emit("server setup fill reconn", 2, conn, sserver);
|
||||
}
|
||||
|
||||
static void server_setup_fill(SERVER_CONNECT_REC *conn,
|
||||
const char *address, int port)
|
||||
{
|
||||
g_return_if_fail(conn != NULL);
|
||||
g_return_if_fail(address != NULL);
|
||||
|
||||
conn->type = module_get_uniq_id("SERVER CONNECT", 0);
|
||||
|
||||
conn->address = g_strdup(address);
|
||||
conn->port = port > 0 ? port : 6667;
|
||||
|
||||
if (!conn->nick) conn->nick = g_strdup(settings_get_str("default_nick"));
|
||||
conn->username = g_strdup(settings_get_str("user_name"));
|
||||
conn->realname = g_strdup(settings_get_str("real_name"));
|
||||
|
||||
/* proxy settings */
|
||||
if (settings_get_bool("use_proxy")) {
|
||||
conn->proxy = g_strdup(settings_get_str("proxy_address"));
|
||||
conn->proxy_port = settings_get_int("proxy_port");
|
||||
conn->proxy_string = g_strdup(settings_get_str("proxy_string"));
|
||||
}
|
||||
|
||||
/* source IP */
|
||||
get_source_host_ip();
|
||||
if (source_host_ok) {
|
||||
conn->own_ip = g_new(IPADDR, 1);
|
||||
memcpy(conn->own_ip, source_host_ip, sizeof(IPADDR));
|
||||
}
|
||||
}
|
||||
|
||||
static void server_setup_fill_server(SERVER_CONNECT_REC *conn,
|
||||
SERVER_SETUP_REC *sserver)
|
||||
{
|
||||
g_return_if_fail(IS_SERVER_CONNECT(conn));
|
||||
g_return_if_fail(IS_SERVER_SETUP(sserver));
|
||||
|
||||
sserver->last_connect = time(NULL);
|
||||
|
||||
if (sserver->port > 0) conn->port = sserver->port;
|
||||
server_setup_fill_reconn(conn, sserver);
|
||||
|
||||
signal_emit("server setup fill server", 2, conn, sserver);
|
||||
}
|
||||
|
||||
static void server_setup_fill_chatnet(SERVER_CONNECT_REC *conn,
|
||||
CHATNET_REC *chatnet)
|
||||
{
|
||||
g_return_if_fail(IS_SERVER_CONNECT(conn));
|
||||
g_return_if_fail(IS_CHATNET(chatnet));
|
||||
|
||||
if (chatnet->nick) {
|
||||
g_free(conn->nick);
|
||||
conn->nick = g_strdup(chatnet->nick);;
|
||||
}
|
||||
if (chatnet->username) {
|
||||
g_free(conn->username);
|
||||
conn->username = g_strdup(chatnet->username);;
|
||||
}
|
||||
if (chatnet->realname) {
|
||||
g_free(conn->realname);
|
||||
conn->realname = g_strdup(chatnet->realname);;
|
||||
}
|
||||
if (chatnet->own_host != NULL)
|
||||
conn_set_ip(conn, &chatnet->own_ip, chatnet->own_host);
|
||||
|
||||
signal_emit("server setup fill chatnet", 2, conn, chatnet);
|
||||
}
|
||||
|
||||
static SERVER_CONNECT_REC *
|
||||
create_addr_conn(const char *address, int port,
|
||||
const char *password, const char *nick)
|
||||
{
|
||||
SERVER_CONNECT_REC *conn;
|
||||
SERVER_SETUP_REC *sserver;
|
||||
CHATNET_REC *chatnet;
|
||||
|
||||
g_return_val_if_fail(address != NULL, NULL);
|
||||
|
||||
sserver = server_setup_find(address, port);
|
||||
chatnet = sserver->chatnet == NULL ? NULL :
|
||||
chatnet_find(sserver->chatnet);
|
||||
conn = NULL;
|
||||
signal_emit("server setup connect", 2, &conn, chatnet);
|
||||
if (conn == NULL) {
|
||||
/* no chat protocol wanted this server? */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* fill in the defaults */
|
||||
server_setup_fill(conn, address, port);
|
||||
|
||||
/* fill the rest from chat network settings */
|
||||
if (chatnet != NULL)
|
||||
server_setup_fill_chatnet(conn, chatnet);
|
||||
|
||||
/* fill the information from setup */
|
||||
if (sserver != NULL)
|
||||
server_setup_fill_server(conn, sserver);
|
||||
|
||||
/* nick / password given in command line overrides all settings */
|
||||
if (password && *password) {
|
||||
g_free_not_null(conn->password);
|
||||
conn->password = g_strdup(password);
|
||||
}
|
||||
if (nick && *nick) {
|
||||
g_free_not_null(conn->nick);
|
||||
conn->nick = g_strdup(nick);
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
/* Connect to server where last connect succeeded (or we haven't tried to
|
||||
connect yet). If there's no such server, connect to server where we
|
||||
haven't connected for the longest time */
|
||||
static SERVER_CONNECT_REC *
|
||||
create_chatnet_conn(const char *dest, int port,
|
||||
const char *password, const char *nick)
|
||||
{
|
||||
SERVER_SETUP_REC *bestrec;
|
||||
GSList *tmp;
|
||||
time_t now, besttime;
|
||||
|
||||
now = time(NULL);
|
||||
bestrec = NULL; besttime = now;
|
||||
for (tmp = setupservers; tmp != NULL; tmp = tmp->next) {
|
||||
SERVER_SETUP_REC *rec = tmp->data;
|
||||
|
||||
if (rec->chatnet == NULL ||
|
||||
g_strcasecmp(rec->chatnet, dest) != 0)
|
||||
continue;
|
||||
|
||||
if (!rec->last_failed) {
|
||||
bestrec = rec;
|
||||
break;
|
||||
}
|
||||
|
||||
if (bestrec == NULL || besttime > rec->last_connect) {
|
||||
bestrec = rec;
|
||||
besttime = rec->last_connect;
|
||||
}
|
||||
}
|
||||
|
||||
return bestrec == NULL ? NULL :
|
||||
create_addr_conn(bestrec->address, 0, NULL, nick);
|
||||
}
|
||||
|
||||
/* Create server connection record. `dest' is required, rest can be NULL.
|
||||
`dest' is either a server address or chat network */
|
||||
SERVER_CONNECT_REC *
|
||||
server_create_conn(const char *dest, int port,
|
||||
const char *password, const char *nick)
|
||||
{
|
||||
SERVER_CONNECT_REC *rec;
|
||||
|
||||
g_return_val_if_fail(dest != NULL, NULL);
|
||||
|
||||
if (chatnet_find(dest)) {
|
||||
rec = create_chatnet_conn(dest, port, password, nick);
|
||||
if (rec != NULL)
|
||||
return rec;
|
||||
}
|
||||
|
||||
return create_addr_conn(dest, port, password, nick);
|
||||
}
|
||||
|
||||
/* Find matching server from setup. Try to find record with a same port,
|
||||
but fallback to any server with the same address. */
|
||||
SERVER_SETUP_REC *server_setup_find(const char *address, int port)
|
||||
{
|
||||
SERVER_SETUP_REC *server;
|
||||
GSList *tmp;
|
||||
|
||||
g_return_val_if_fail(address != NULL, NULL);
|
||||
|
||||
server = NULL;
|
||||
for (tmp = setupservers; tmp != NULL; tmp = tmp->next) {
|
||||
SERVER_SETUP_REC *rec = tmp->data;
|
||||
|
||||
if (g_strcasecmp(rec->address, address) == 0) {
|
||||
server = rec;
|
||||
if (rec->port == port)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
/* Find matching server from setup. Ports must match or NULL is returned. */
|
||||
SERVER_SETUP_REC *server_setup_find_port(const char *address, int port)
|
||||
{
|
||||
SERVER_SETUP_REC *rec;
|
||||
|
||||
rec = server_setup_find(address, port);
|
||||
return rec == NULL || rec->port != port ? NULL : rec;
|
||||
}
|
||||
|
||||
static SERVER_SETUP_REC *server_setup_read(CONFIG_NODE *node)
|
||||
{
|
||||
SERVER_SETUP_REC *rec;
|
||||
char *server, *chatnet;
|
||||
int port;
|
||||
|
||||
g_return_val_if_fail(node != NULL, NULL);
|
||||
|
||||
server = config_node_get_str(node, "address", NULL);
|
||||
if (server == NULL)
|
||||
return NULL;
|
||||
|
||||
port = config_node_get_int(node, "port", 6667);
|
||||
if (server_setup_find_port(server, port) != NULL) {
|
||||
/* already exists - don't let it get there twice or
|
||||
server reconnects will screw up! */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rec = NULL;
|
||||
chatnet = config_node_get_str(node, "chatnet", NULL);
|
||||
signal_emit("server setup read", 3, &rec, node,
|
||||
chatnet == NULL ? NULL : chatnet_find(chatnet));
|
||||
if (rec == NULL) {
|
||||
/* no chat protocol wanted this server? */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rec->type = module_get_uniq_id("SERVER SETUP", 0);
|
||||
rec->chatnet = g_strdup(chatnet);
|
||||
rec->address = g_strdup(server);
|
||||
rec->password = g_strdup(config_node_get_str(node, "password", NULL));
|
||||
rec->port = port;
|
||||
rec->autoconnect = config_node_get_bool(node, "autoconnect", FALSE);
|
||||
rec->own_host = g_strdup(config_node_get_str(node, "own_host", 0));
|
||||
|
||||
setupservers = g_slist_append(setupservers, rec);
|
||||
return rec;
|
||||
}
|
||||
|
||||
static void server_setup_save(SERVER_SETUP_REC *rec)
|
||||
{
|
||||
CONFIG_NODE *parentnode, *node;
|
||||
int index;
|
||||
|
||||
index = g_slist_index(setupservers, rec);
|
||||
|
||||
parentnode = iconfig_node_traverse("(servers", TRUE);
|
||||
node = config_node_index(parentnode, index);
|
||||
if (node == NULL)
|
||||
node = config_node_section(parentnode, NULL, NODE_TYPE_BLOCK);
|
||||
|
||||
iconfig_node_clear(node);
|
||||
iconfig_node_set_str(node, "address", rec->address);
|
||||
iconfig_node_set_str(node, "chatnet", rec->chatnet);
|
||||
|
||||
config_node_set_int(node, "port", rec->port);
|
||||
iconfig_node_set_str(node, "password", rec->password);
|
||||
iconfig_node_set_str(node, "own_host", rec->own_host);
|
||||
|
||||
if (rec->autoconnect)
|
||||
config_node_set_bool(node, "autoconnect", TRUE);
|
||||
|
||||
signal_emit("server setup saved", 2, rec, node);
|
||||
}
|
||||
|
||||
static void server_setup_remove_config(SERVER_SETUP_REC *rec)
|
||||
{
|
||||
CONFIG_NODE *node;
|
||||
int index;
|
||||
|
||||
node = iconfig_node_traverse("servers", FALSE);
|
||||
if (node != NULL) {
|
||||
index = g_slist_index(setupservers, rec);
|
||||
iconfig_node_list_remove(node, index);
|
||||
}
|
||||
}
|
||||
|
||||
static void server_setup_destroy(SERVER_SETUP_REC *rec)
|
||||
{
|
||||
setupservers = g_slist_remove(setupservers, rec);
|
||||
signal_emit("server setup destroyed", 1, rec);
|
||||
|
||||
g_free_not_null(rec->own_host);
|
||||
g_free_not_null(rec->own_ip);
|
||||
g_free_not_null(rec->chatnet);
|
||||
g_free(rec->address);
|
||||
g_free_not_null(rec->password);
|
||||
g_free(rec);
|
||||
}
|
||||
|
||||
void server_setup_add(SERVER_SETUP_REC *rec)
|
||||
{
|
||||
if (g_slist_find(setupservers, rec) == NULL)
|
||||
setupservers = g_slist_append(setupservers, rec);
|
||||
server_setup_save(rec);
|
||||
}
|
||||
|
||||
void server_setup_remove(SERVER_SETUP_REC *rec)
|
||||
{
|
||||
server_setup_remove_config(rec);
|
||||
server_setup_destroy(rec);
|
||||
}
|
||||
|
||||
static void read_servers(void)
|
||||
{
|
||||
CONFIG_NODE *node;
|
||||
GSList *tmp;
|
||||
|
||||
while (setupservers != NULL)
|
||||
server_setup_destroy(setupservers->data);
|
||||
|
||||
/* Read servers */
|
||||
node = iconfig_node_traverse("servers", FALSE);
|
||||
if (node != NULL) {
|
||||
for (tmp = node->value; tmp != NULL; tmp = tmp->next)
|
||||
server_setup_read(tmp->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void read_settings(void)
|
||||
{
|
||||
g_free_and_null(source_host_ip);
|
||||
|
||||
source_host_ok = FALSE;
|
||||
get_source_host_ip();
|
||||
}
|
||||
|
||||
void servers_setup_init(void)
|
||||
{
|
||||
settings_add_str("server", "hostname", "");
|
||||
|
||||
settings_add_str("server", "default_nick", NULL);
|
||||
settings_add_str("server", "user_name", NULL);
|
||||
settings_add_str("server", "real_name", NULL);
|
||||
|
||||
settings_add_bool("proxy", "use_proxy", FALSE);
|
||||
settings_add_str("proxy", "proxy_address", "");
|
||||
settings_add_int("proxy", "proxy_port", 6667);
|
||||
settings_add_str("proxy", "proxy_string", "CONNECT %s %d");
|
||||
|
||||
source_host_ip = NULL;
|
||||
read_settings();
|
||||
|
||||
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
|
||||
signal_add("setup reread", (SIGNAL_FUNC) read_servers);
|
||||
signal_add("irssi init read settings", (SIGNAL_FUNC) read_servers);
|
||||
}
|
||||
|
||||
void servers_setup_deinit(void)
|
||||
{
|
||||
g_free_not_null(source_host_ip);
|
||||
|
||||
while (setupservers != NULL)
|
||||
server_setup_destroy(setupservers->data);
|
||||
|
||||
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
|
||||
signal_remove("setup reread", (SIGNAL_FUNC) read_servers);
|
||||
signal_remove("irssi init read settings", (SIGNAL_FUNC) read_servers);
|
||||
|
||||
module_uniq_destroy("SERVER SETUP");
|
||||
}
|
||||
46
src/core/servers-setup.h
Normal file
46
src/core/servers-setup.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
#ifndef __SERVERS_SETUP_H
|
||||
#define __SERVERS_SETUP_H
|
||||
|
||||
#include "servers.h"
|
||||
|
||||
#define IS_SERVER_SETUP(server) \
|
||||
((server) != NULL && \
|
||||
module_find_id("SERVER SETUP", (server)->type) != -1)
|
||||
|
||||
#define SERVER_SETUP(server) \
|
||||
(IS_SERVER_SETUP(server) ? (SERVER_SETUP_REC *) (server) : NULL)
|
||||
|
||||
/* servers */
|
||||
typedef struct {
|
||||
#include "server-setup-rec.h"
|
||||
} SERVER_SETUP_REC;
|
||||
|
||||
extern GSList *setupservers;
|
||||
|
||||
extern IPADDR *source_host_ip; /* Resolved address */
|
||||
extern int source_host_ok; /* Use source_host_ip .. */
|
||||
|
||||
/* Fill reconnection specific information to connection
|
||||
from server setup record */
|
||||
void server_setup_fill_reconn(SERVER_CONNECT_REC *conn,
|
||||
SERVER_SETUP_REC *sserver);
|
||||
|
||||
/* Create server connection record. `dest' is required, rest can be NULL.
|
||||
`dest' is either a server address or chat network */
|
||||
SERVER_CONNECT_REC *
|
||||
server_create_conn(const char *dest, int port,
|
||||
const char *password, const char *nick);
|
||||
|
||||
/* Find matching server from setup. Try to find record with a same port,
|
||||
but fallback to any server with the same address. */
|
||||
SERVER_SETUP_REC *server_setup_find(const char *address, int port);
|
||||
/* Find matching server from setup. Ports must match or NULL is returned. */
|
||||
SERVER_SETUP_REC *server_setup_find_port(const char *address, int port);
|
||||
|
||||
void server_setup_add(SERVER_SETUP_REC *rec);
|
||||
void server_setup_remove(SERVER_SETUP_REC *rec);
|
||||
|
||||
void servers_setup_init(void);
|
||||
void servers_setup_deinit(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -19,24 +19,26 @@
|
|||
*/
|
||||
|
||||
#include "module.h"
|
||||
|
||||
#include "modules.h"
|
||||
#include "signals.h"
|
||||
#include "line-split.h"
|
||||
#include "net-nonblock.h"
|
||||
#include "net-sendbuffer.h"
|
||||
#include "rawlog.h"
|
||||
#include "misc.h"
|
||||
#include "server.h"
|
||||
#include "server-redirect.h"
|
||||
#include "rawlog.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include "servers.h"
|
||||
#include "servers-redirect.h"
|
||||
#include "servers-setup.h"
|
||||
#include "channels.h"
|
||||
#include "queries.h"
|
||||
|
||||
GSList *servers, *lookup_servers;
|
||||
|
||||
/* connection to server failed */
|
||||
static void server_cant_connect(SERVER_REC *server, const char *msg)
|
||||
{
|
||||
g_return_if_fail(server != NULL);
|
||||
g_return_if_fail(IS_SERVER(server));
|
||||
|
||||
lookup_servers = g_slist_remove(lookup_servers, server);
|
||||
|
||||
|
|
@ -52,6 +54,7 @@ static void server_cant_connect(SERVER_REC *server, const char *msg)
|
|||
}
|
||||
|
||||
MODULE_DATA_DEINIT(server);
|
||||
server_connect_free(server->connrec);
|
||||
g_free_not_null(server->nick);
|
||||
g_free(server->tag);
|
||||
g_free(server);
|
||||
|
|
@ -62,6 +65,8 @@ static char *server_create_address_tag(const char *address)
|
|||
{
|
||||
const char *start, *end;
|
||||
|
||||
g_return_val_if_fail(address != NULL, NULL);
|
||||
|
||||
/* try to generate a reasonable server tag */
|
||||
if (strchr(address, '.') == NULL) {
|
||||
start = end = NULL;
|
||||
|
|
@ -91,7 +96,9 @@ static char *server_create_tag(SERVER_CONNECT_REC *conn)
|
|||
char *tag;
|
||||
int num;
|
||||
|
||||
tag = conn->ircnet != NULL ? g_strdup(conn->ircnet) :
|
||||
g_return_val_if_fail(IS_SERVER_CONNECT(conn), NULL);
|
||||
|
||||
tag = conn->chatnet != NULL ? g_strdup(conn->chatnet) :
|
||||
server_create_address_tag(conn->address);
|
||||
|
||||
/* then just append numbers after tag until unused is found.. */
|
||||
|
|
@ -109,6 +116,8 @@ static void server_connect_callback_init(SERVER_REC *server, int handle)
|
|||
{
|
||||
int error;
|
||||
|
||||
g_return_if_fail(IS_SERVER(server));
|
||||
|
||||
error = net_geterror(handle);
|
||||
if (error != 0) {
|
||||
server->connection_lost = TRUE;
|
||||
|
|
@ -122,8 +131,12 @@ static void server_connect_callback_init(SERVER_REC *server, int handle)
|
|||
server->connect_tag = -1;
|
||||
server->connect_time = time(NULL);
|
||||
server->rawlog = rawlog_create();
|
||||
servers = g_slist_append(servers, server);
|
||||
|
||||
server->eventtable = g_hash_table_new((GHashFunc) g_istr_hash, (GCompareFunc) g_istr_equal);
|
||||
server->eventgrouptable = g_hash_table_new((GHashFunc) g_direct_hash, (GCompareFunc) g_direct_equal);
|
||||
server->cmdtable = g_hash_table_new((GHashFunc) g_istr_hash, (GCompareFunc) g_istr_equal);
|
||||
|
||||
servers = g_slist_append(servers, server);
|
||||
signal_emit("server connected", 1, server);
|
||||
}
|
||||
|
||||
|
|
@ -134,6 +147,8 @@ static void server_connect_callback_readpipe(SERVER_REC *server)
|
|||
const char *errormsg;
|
||||
int handle;
|
||||
|
||||
g_return_if_fail(IS_SERVER(server));
|
||||
|
||||
g_source_remove(server->connect_tag);
|
||||
server->connect_tag = -1;
|
||||
|
||||
|
|
@ -182,13 +197,14 @@ static void server_connect_callback_readpipe(SERVER_REC *server)
|
|||
signal_emit("server connecting", 2, server, &iprec.ip);
|
||||
}
|
||||
|
||||
int server_connect(SERVER_REC *server)
|
||||
int server_start_connect(SERVER_REC *server)
|
||||
{
|
||||
const char *connect_address;
|
||||
|
||||
g_return_val_if_fail(server != NULL, FALSE);
|
||||
|
||||
MODULE_DATA_INIT(server);
|
||||
server->type = module_get_uniq_id("SERVER", 0);
|
||||
|
||||
if (pipe(server->connect_pipe) != 0) {
|
||||
g_warning("server_connect(): pipe() failed.");
|
||||
|
|
@ -213,9 +229,48 @@ int server_connect(SERVER_REC *server)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* Connect to server */
|
||||
SERVER_REC *server_connect(SERVER_CONNECT_REC *conn)
|
||||
{
|
||||
SERVER_REC *server;
|
||||
|
||||
g_return_val_if_fail(IS_SERVER_CONNECT(conn), NULL);
|
||||
|
||||
server = NULL;
|
||||
signal_emit("server connect", 2, &server, conn);
|
||||
return server;
|
||||
}
|
||||
|
||||
static int server_remove_channels(SERVER_REC *server)
|
||||
{
|
||||
GSList *tmp;
|
||||
int found;
|
||||
|
||||
g_return_val_if_fail(server != NULL, FALSE);
|
||||
|
||||
found = FALSE;
|
||||
for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
|
||||
CHANNEL_REC *channel = tmp->data;
|
||||
|
||||
channel->server = NULL;
|
||||
channel_destroy(channel);
|
||||
found = TRUE;
|
||||
}
|
||||
|
||||
for (tmp = server->queries; tmp != NULL; tmp = tmp->next)
|
||||
query_change_server(tmp->data, NULL);
|
||||
|
||||
g_slist_free(server->channels);
|
||||
g_slist_free(server->queries);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
void server_disconnect(SERVER_REC *server)
|
||||
{
|
||||
g_return_if_fail(server != NULL);
|
||||
int chans;
|
||||
|
||||
g_return_if_fail(IS_SERVER(server));
|
||||
|
||||
if (server->connect_tag != -1) {
|
||||
/* still connecting to server.. */
|
||||
|
|
@ -229,12 +284,27 @@ void server_disconnect(SERVER_REC *server)
|
|||
|
||||
signal_emit("server disconnected", 1, server);
|
||||
|
||||
if (server->handle != NULL)
|
||||
net_sendbuffer_destroy(server->handle, TRUE);
|
||||
/* close all channels */
|
||||
chans = server_remove_channels(server);
|
||||
|
||||
if (server->handle != NULL) {
|
||||
if (!chans || server->connection_lost)
|
||||
net_sendbuffer_destroy(server->handle, TRUE);
|
||||
else {
|
||||
/* we were on some channels, try to let the server
|
||||
disconnect so that our quit message is guaranteed
|
||||
to get displayed */
|
||||
net_disconnect_later(net_sendbuffer_handle(server->handle));
|
||||
net_sendbuffer_destroy(server->handle, FALSE);
|
||||
}
|
||||
server->handle = NULL;
|
||||
}
|
||||
|
||||
if (server->readtag > 0)
|
||||
g_source_remove(server->readtag);
|
||||
|
||||
MODULE_DATA_DEINIT(server);
|
||||
server_connect_free(server->connrec);
|
||||
rawlog_destroy(server->rawlog);
|
||||
line_split_free(server->buffer);
|
||||
g_free_not_null(server->version);
|
||||
|
|
@ -268,29 +338,54 @@ SERVER_REC *server_find_tag(const char *tag)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
SERVER_REC *server_find_ircnet(const char *ircnet)
|
||||
SERVER_REC *server_find_chatnet(const char *chatnet)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
g_return_val_if_fail(ircnet != NULL, NULL);
|
||||
if (*ircnet == '\0') return NULL;
|
||||
g_return_val_if_fail(chatnet != NULL, NULL);
|
||||
if (*chatnet == '\0') return NULL;
|
||||
|
||||
for (tmp = servers; tmp != NULL; tmp = tmp->next) {
|
||||
SERVER_REC *server = tmp->data;
|
||||
|
||||
if (server->connrec->ircnet != NULL &&
|
||||
g_strcasecmp(server->connrec->ircnet, ircnet) == 0)
|
||||
if (server->connrec->chatnet != NULL &&
|
||||
g_strcasecmp(server->connrec->chatnet, chatnet) == 0)
|
||||
return server;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void server_connect_free(SERVER_CONNECT_REC *conn)
|
||||
{
|
||||
g_return_if_fail(IS_SERVER_CONNECT(conn));
|
||||
|
||||
signal_emit("server connect free", 1, conn);
|
||||
g_free_not_null(conn->proxy);
|
||||
g_free_not_null(conn->proxy_string);
|
||||
|
||||
g_free_not_null(conn->address);
|
||||
g_free_not_null(conn->chatnet);
|
||||
|
||||
g_free_not_null(conn->own_ip);
|
||||
|
||||
g_free_not_null(conn->password);
|
||||
g_free_not_null(conn->nick);
|
||||
g_free_not_null(conn->username);
|
||||
g_free_not_null(conn->realname);
|
||||
|
||||
g_free_not_null(conn->channels);
|
||||
g_free_not_null(conn->away_reason);
|
||||
g_free_not_null(conn->usermode);
|
||||
g_free(conn);
|
||||
}
|
||||
|
||||
void servers_init(void)
|
||||
{
|
||||
lookup_servers = servers = NULL;
|
||||
|
||||
servers_redirect_init();
|
||||
servers_setup_init();
|
||||
}
|
||||
|
||||
void servers_deinit(void)
|
||||
|
|
@ -300,5 +395,9 @@ void servers_deinit(void)
|
|||
while (lookup_servers != NULL)
|
||||
server_cant_connect(lookup_servers->data, NULL);
|
||||
|
||||
servers_setup_deinit();
|
||||
servers_redirect_deinit();
|
||||
|
||||
module_uniq_destroy("SERVER");
|
||||
module_uniq_destroy("SERVER CONNECT");
|
||||
}
|
||||
52
src/core/servers.h
Normal file
52
src/core/servers.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#ifndef __SERVERS_H
|
||||
#define __SERVERS_H
|
||||
|
||||
#include "modules.h"
|
||||
|
||||
#ifndef __NETWORK_H
|
||||
typedef struct _ipaddr IPADDR;
|
||||
#endif
|
||||
|
||||
#define IS_SERVER(server) \
|
||||
((server) != NULL && module_find_id("SERVER", (server)->type) != -1)
|
||||
|
||||
#define IS_SERVER_CONNECT(conn) \
|
||||
((conn) != NULL && \
|
||||
module_find_id("SERVER CONNECT", (conn)->type) != -1)
|
||||
|
||||
/* Returns SERVER_REC if it's server, NULL if it isn't. */
|
||||
#define SERVER(server) \
|
||||
(IS_SERVER(server) ? (SERVER_REC *) (server) : NULL)
|
||||
|
||||
/* Returns SERVER_CONNECT_REC if it's server connection, NULL if it isn't. */
|
||||
#define SERVER_CONNECT(conn) \
|
||||
(IS_SERVER_CONNECT(conn) ? (SERVER_CONNECT_REC *) (conn) : NULL)
|
||||
|
||||
/* all strings should be either NULL or dynamically allocated */
|
||||
/* address and nick are mandatory, rest are optional */
|
||||
typedef struct {
|
||||
#include "server-connect-rec.h"
|
||||
} SERVER_CONNECT_REC;
|
||||
|
||||
#define STRUCT_SERVER_CONNECT_REC SERVER_CONNECT_REC
|
||||
typedef struct {
|
||||
#include "server-rec.h"
|
||||
} SERVER_REC;
|
||||
|
||||
extern GSList *servers, *lookup_servers;
|
||||
|
||||
void servers_init(void);
|
||||
void servers_deinit(void);
|
||||
|
||||
/* Connect to server */
|
||||
SERVER_REC *server_connect(SERVER_CONNECT_REC *conn);
|
||||
/* Disconnect from server */
|
||||
void server_disconnect(SERVER_REC *server);
|
||||
|
||||
SERVER_REC *server_find_tag(const char *tag);
|
||||
SERVER_REC *server_find_chatnet(const char *chatnet);
|
||||
|
||||
int server_start_connect(SERVER_REC *server);
|
||||
void server_connect_free(SERVER_CONNECT_REC *conn);
|
||||
|
||||
#endif
|
||||
|
|
@ -32,6 +32,7 @@ typedef struct {
|
|||
#define iconfig_node_set_str(a, b, c) config_node_set_str(mainconfig, a, b, c)
|
||||
#define iconfig_node_list_remove(a, b) config_node_list_remove(mainconfig, a, b)
|
||||
#define iconfig_node_remove(a, b) config_node_remove(mainconfig, a, b)
|
||||
#define iconfig_node_clear(a) config_node_clear(mainconfig, a)
|
||||
|
||||
extern CONFIG_REC *mainconfig;
|
||||
|
||||
|
|
|
|||
|
|
@ -310,7 +310,8 @@ void signal_stop_by_name(const char *signal)
|
|||
|
||||
static void signal_remove_module(void *signal, SIGNAL_REC *rec, const char *module)
|
||||
{
|
||||
int signal_id, list, index;
|
||||
unsigned int index;
|
||||
int signal_id, list;
|
||||
|
||||
signal_id = GPOINTER_TO_INT(signal);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,10 @@
|
|||
#include "misc.h"
|
||||
#include "irssi-version.h"
|
||||
|
||||
#include "channels.h"
|
||||
#include "queries.h"
|
||||
#include "window-item-def.h"
|
||||
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#define ALIGN_RIGHT 0x01
|
||||
|
|
@ -99,7 +103,7 @@ static char *get_internal_setting(const char *key, int type, int *free_ret)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static char *get_long_variable_value(const char *key, void *server,
|
||||
static char *get_long_variable_value(const char *key, SERVER_REC *server,
|
||||
void *item, int *free_ret)
|
||||
{
|
||||
EXPANDO_FUNC func;
|
||||
|
|
@ -126,7 +130,7 @@ static char *get_long_variable_value(const char *key, void *server,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static char *get_long_variable(char **cmd, void *server,
|
||||
static char *get_long_variable(char **cmd, SERVER_REC *server,
|
||||
void *item, int *free_ret)
|
||||
{
|
||||
char *start, *var, *ret;
|
||||
|
|
@ -142,7 +146,7 @@ static char *get_long_variable(char **cmd, void *server,
|
|||
}
|
||||
|
||||
/* return the value of the variable found from `cmd' */
|
||||
static char *get_variable(char **cmd, void *server, void *item,
|
||||
static char *get_variable(char **cmd, SERVER_REC *server, void *item,
|
||||
char **arglist, int *free_ret, int *arg_used)
|
||||
{
|
||||
if (isdigit(**cmd) || **cmd == '*' || **cmd == '-' || **cmd == '~') {
|
||||
|
|
@ -183,7 +187,7 @@ static char *get_history(char **cmd, void *item, int *free_ret)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static char *get_special_value(char **cmd, void *server, void *item,
|
||||
static char *get_special_value(char **cmd, SERVER_REC *server, void *item,
|
||||
char **arglist, int *free_ret, int *arg_used)
|
||||
{
|
||||
char command, *value, *p;
|
||||
|
|
@ -313,7 +317,7 @@ static char *get_alignment(const char *text, int align, int flags, char pad)
|
|||
|
||||
/* Parse and expand text after '$' character. return value has to be
|
||||
g_free()'d if `free_ret' is TRUE. */
|
||||
char *parse_special(char **cmd, void *server, void *item,
|
||||
char *parse_special(char **cmd, SERVER_REC *server, void *item,
|
||||
char **arglist, int *free_ret, int *arg_used)
|
||||
{
|
||||
static char **nested_orig_cmd = NULL; /* FIXME: KLUDGE! */
|
||||
|
|
@ -405,7 +409,7 @@ char *parse_special(char **cmd, void *server, void *item,
|
|||
}
|
||||
|
||||
/* parse the whole string. $ and \ chars are replaced */
|
||||
char *parse_special_string(const char *cmd, void *server, void *item,
|
||||
char *parse_special_string(const char *cmd, SERVER_REC *server, void *item,
|
||||
const char *data, int *arg_used)
|
||||
{
|
||||
char code, **arglist, *ret;
|
||||
|
|
@ -466,7 +470,7 @@ char *parse_special_string(const char *cmd, void *server, void *item,
|
|||
|
||||
/* execute the commands in string - commands can be split with ';' */
|
||||
void eval_special_string(const char *cmd, const char *data,
|
||||
void *server, void *item)
|
||||
SERVER_REC *server, void *item)
|
||||
{
|
||||
const char *cmdchars;
|
||||
char *orig, *str, *start, *ret;
|
||||
|
|
@ -556,40 +560,101 @@ void special_history_func_set(SPECIAL_HISTORY_FUNC func)
|
|||
history_func = func;
|
||||
}
|
||||
|
||||
/* text of your AWAY message, if any */
|
||||
static char *expando_awaymsg(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
return server == NULL ? "" : server->away_reason;
|
||||
}
|
||||
|
||||
/* current channel */
|
||||
static char *expando_channel(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
return !IS_CHANNEL(item) ? NULL : CHANNEL(item)->name;
|
||||
}
|
||||
|
||||
/* time client was started, $time() format */
|
||||
static char *expando_clientstarted(void *server, void *item, int *free_ret)
|
||||
static char *expando_clientstarted(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
*free_ret = TRUE;
|
||||
return g_strdup_printf("%ld", (long) client_start_time);
|
||||
}
|
||||
|
||||
/* client version text string */
|
||||
static char *expando_version(void *server, void *item, int *free_ret)
|
||||
static char *expando_version(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
return IRSSI_VERSION;
|
||||
}
|
||||
|
||||
/* current value of CMDCHARS */
|
||||
static char *expando_cmdchars(void *server, void *item, int *free_ret)
|
||||
static char *expando_cmdchars(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
return (char *) settings_get_str("cmdchars");
|
||||
}
|
||||
|
||||
/* modes of current channel, if any */
|
||||
static char *expando_chanmode(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
return !IS_CHANNEL(item) ? NULL : CHANNEL(item)->mode;
|
||||
}
|
||||
|
||||
/* current nickname */
|
||||
static char *expando_nick(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
return server == NULL ? "" : server->nick;
|
||||
}
|
||||
|
||||
/* value of STATUS_OPER if you are an irc operator */
|
||||
static char *expando_statusoper(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
return server == NULL || !server->server_operator ? "" :
|
||||
(char *) settings_get_str("STATUS_OPER");
|
||||
}
|
||||
|
||||
/* if you are a channel operator in $C, expands to a '@' */
|
||||
static char *expando_chanop(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
return IS_CHANNEL(item) && CHANNEL(item)->chanop ? "@" : "";
|
||||
}
|
||||
|
||||
/* nickname of whomever you are QUERYing */
|
||||
static char *expando_query(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
return !IS_QUERY(item) ? "" : QUERY(item)->name;
|
||||
}
|
||||
|
||||
/* version of current server */
|
||||
static char *expando_serverversion(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
return server == NULL ? "" : server->version;
|
||||
}
|
||||
|
||||
/* target of current input (channel or QUERY nickname) */
|
||||
static char *expando_target(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
return ((WI_ITEM_REC *) item)->name;
|
||||
}
|
||||
|
||||
/* client release date (numeric version string) */
|
||||
static char *expando_releasedate(void *server, void *item, int *free_ret)
|
||||
static char *expando_releasedate(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
return IRSSI_VERSION_DATE;
|
||||
}
|
||||
|
||||
/* current working directory */
|
||||
static char *expando_workdir(void *server, void *item, int *free_ret)
|
||||
static char *expando_workdir(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
*free_ret = TRUE;
|
||||
return g_get_current_dir();
|
||||
}
|
||||
|
||||
/* value of REALNAME */
|
||||
static char *expando_realname(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
return server == NULL ? "" : server->connrec->realname;
|
||||
}
|
||||
|
||||
/* time of day (hh:mm) */
|
||||
static char *expando_time(void *server, void *item, int *free_ret)
|
||||
static char *expando_time(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
struct tm *tm;
|
||||
|
|
@ -600,13 +665,13 @@ static char *expando_time(void *server, void *item, int *free_ret)
|
|||
}
|
||||
|
||||
/* a literal '$' */
|
||||
static char *expando_dollar(void *server, void *item, int *free_ret)
|
||||
static char *expando_dollar(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
return "$";
|
||||
}
|
||||
|
||||
/* system name */
|
||||
static char *expando_sysname(void *server, void *item, int *free_ret)
|
||||
static char *expando_sysname(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
struct utsname un;
|
||||
|
||||
|
|
@ -619,7 +684,7 @@ static char *expando_sysname(void *server, void *item, int *free_ret)
|
|||
}
|
||||
|
||||
/* system release */
|
||||
static char *expando_sysrelease(void *server, void *item, int *free_ret)
|
||||
static char *expando_sysrelease(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
struct utsname un;
|
||||
|
||||
|
|
@ -631,8 +696,22 @@ static char *expando_sysrelease(void *server, void *item, int *free_ret)
|
|||
|
||||
}
|
||||
|
||||
/* Server tag */
|
||||
static char *expando_servertag(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
return server == NULL ? "" : server->tag;
|
||||
}
|
||||
|
||||
/* Server chatnet */
|
||||
static char *expando_chatnet(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
return server == NULL ? "" : server->connrec->chatnet;
|
||||
}
|
||||
|
||||
void special_vars_init(void)
|
||||
{
|
||||
settings_add_str("misc", "STATUS_OPER", "*");
|
||||
|
||||
client_start_time = time(NULL);
|
||||
|
||||
memset(char_expandos, 0, sizeof(char_expandos));
|
||||
|
|
@ -640,22 +719,36 @@ void special_vars_init(void)
|
|||
(GCompareFunc) g_str_equal);
|
||||
history_func = NULL;
|
||||
|
||||
char_expandos['A'] = expando_awaymsg;
|
||||
char_expandos['C'] = expando_channel;
|
||||
char_expandos['F'] = expando_clientstarted;
|
||||
char_expandos['J'] = expando_version;
|
||||
char_expandos['K'] = expando_cmdchars;
|
||||
char_expandos['M'] = expando_chanmode;
|
||||
char_expandos['N'] = expando_nick;
|
||||
char_expandos['O'] = expando_statusoper;
|
||||
char_expandos['P'] = expando_chanop;
|
||||
char_expandos['Q'] = expando_query;
|
||||
char_expandos['R'] = expando_serverversion;
|
||||
char_expandos['T'] = expando_target;
|
||||
char_expandos['V'] = expando_releasedate;
|
||||
char_expandos['W'] = expando_workdir;
|
||||
char_expandos['Y'] = expando_realname;
|
||||
char_expandos['Z'] = expando_time;
|
||||
char_expandos['$'] = expando_dollar;
|
||||
|
||||
expando_create("sysname", expando_sysname);
|
||||
expando_create("sysrelease", expando_sysrelease);
|
||||
expando_create("tag", expando_servertag);
|
||||
expando_create("chatnet", expando_chatnet);
|
||||
}
|
||||
|
||||
void special_vars_deinit(void)
|
||||
{
|
||||
expando_destroy("sysname", expando_sysname);
|
||||
expando_destroy("sysrelease", expando_sysrelease);
|
||||
expando_destroy("tag", expando_servertag);
|
||||
expando_destroy("chatnet", expando_chatnet);
|
||||
|
||||
g_hash_table_destroy(expandos);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,25 @@
|
|||
#ifndef __SPECIAL_VARS_H
|
||||
#define __SPECIAL_VARS_H
|
||||
|
||||
typedef char* (*EXPANDO_FUNC) (void *server, void *item, int *free_ret);
|
||||
typedef char* (*SPECIAL_HISTORY_FUNC) (const char *text, void *item, int *free_ret);
|
||||
#include "servers.h"
|
||||
|
||||
typedef char* (*EXPANDO_FUNC)
|
||||
(SERVER_REC *server, void *item, int *free_ret);
|
||||
typedef char* (*SPECIAL_HISTORY_FUNC)
|
||||
(const char *text, void *item, int *free_ret);
|
||||
|
||||
/* Parse and expand text after '$' character. return value has to be
|
||||
g_free()'d if `free_ret' is TRUE. */
|
||||
char *parse_special(char **cmd, void *server, void *item, char **arglist, int *free_ret, int *arg_used);
|
||||
char *parse_special(char **cmd, SERVER_REC *server, void *item,
|
||||
char **arglist, int *free_ret, int *arg_used);
|
||||
|
||||
/* parse the whole string. $ and \ chars are replaced */
|
||||
char *parse_special_string(const char *cmd, void *server, void *item, const char *data, int *arg_used);
|
||||
char *parse_special_string(const char *cmd, SERVER_REC *server, void *item,
|
||||
const char *data, int *arg_used);
|
||||
|
||||
/* execute the commands in string - commands can be split with ';' */
|
||||
void eval_special_string(const char *cmd, const char *data, void *server, void *item);
|
||||
void eval_special_string(const char *cmd, const char *data,
|
||||
SERVER_REC *server, void *item);
|
||||
|
||||
/* Create expando - overrides any existing ones. */
|
||||
void expando_create(const char *key, EXPANDO_FUNC func);
|
||||
|
|
|
|||
9
src/core/window-item-def.h
Normal file
9
src/core/window-item-def.h
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef __WINDOW_ITEM_DEF_H
|
||||
#define __WINDOW_ITEM_DEF_H
|
||||
|
||||
#define STRUCT_SERVER_REC SERVER_REC
|
||||
typedef struct {
|
||||
#include "window-item-rec.h"
|
||||
} WI_ITEM_REC;
|
||||
|
||||
#endif
|
||||
14
src/core/window-item-rec.h
Normal file
14
src/core/window-item-rec.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/* WI_ITEM_REC definition, used for inheritance */
|
||||
|
||||
int type; /* window item type - channel/query/.. */
|
||||
int chat_type; /* chat server type - irc/silc/.. */
|
||||
GHashTable *module_data;
|
||||
|
||||
STRUCT_SERVER_REC *server;
|
||||
char *name;
|
||||
|
||||
time_t createtime;
|
||||
int new_data;
|
||||
int last_color; /* if NEWDATA_HILIGHT is set, color number could be specified here */
|
||||
|
||||
#undef STRUCT_SERVER_REC
|
||||
Loading…
Add table
Add a link
Reference in a new issue