1
0
mirror of https://github.com/irssi/irssi.git synced 2025-02-02 15:08:01 -05:00
irssi/src/irc/core/server-setup.c
Timo Sirainen c7fbd670e6 /server -add messed up everything when modifying existing servers.
Now it also changes only the specified settings in the server instead of
replacing it entirely.

only the settings you change changed parts


git-svn-id: http://svn.irssi.org/repos/irssi/trunk@266 dbcabf3a-b0e7-0310-adc4-f8d773084564
2000-06-01 18:04:34 +00:00

392 lines
11 KiB
C

/*
server-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 "common-setup.h"
#include "irc-server.h"
#include "server-setup.h"
#include "ircnet-setup.h"
GSList *setupservers; /* list of irc servers */
int source_host_ok; /* Use source_host_ip .. */
IPADDR *source_host_ip; /* Resolved address */
static void get_source_host_ip(void)
{
IPADDR ip;
/* FIXME: This will block! */
if (!source_host_ok) {
source_host_ok = *settings_get_str("hostname") != '\0' &&
net_gethostbyname(settings_get_str("hostname"), &ip) == 0;
if (source_host_ok) {
source_host_ip = g_new(IPADDR, 1);
memcpy(source_host_ip, &ip, sizeof(IPADDR));
}
}
}
/* Create server connection record. `address' is required, rest can be NULL */
static IRC_SERVER_CONNECT_REC *
create_addr_conn(const char *address, int port, const char *password,
const char *nick)
{
IRC_SERVER_CONNECT_REC *conn;
SETUP_SERVER_REC *sserver;
IRCNET_REC *ircnet;
g_return_val_if_fail(address != NULL, NULL);
conn = g_new0(IRC_SERVER_CONNECT_REC, 1);
conn->address = g_strdup(address);
conn->port = port > 0 ? port : 6667;
if (password && *password) conn->password = g_strdup(password);
if (nick && *nick) conn->nick = g_strdup(nick);
if (!conn->nick) conn->nick = g_strdup(settings_get_str("default_nick"));
conn->alternate_nick = g_strdup(settings_get_str("alternate_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_ircproxy")) {
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));
}
/* fill the information from setup */
sserver = server_setup_find(address, -1);
if (sserver == NULL) return conn;
if (sserver->own_ip != NULL) {
/* use already resolved IP */
if (conn->own_ip == NULL)
conn->own_ip = g_new(IPADDR, 1);
memcpy(conn->own_ip, sserver->own_ip, sizeof(IPADDR));
} else if (sserver->own_host != NULL) {
/* resolve the IP and use it */
IPADDR ip;
if (net_gethostbyname(sserver->own_host, &ip) == 0) {
if (conn->own_ip == NULL)
conn->own_ip = g_new(IPADDR, 1);
memcpy(conn->own_ip, &ip, sizeof(IPADDR));
sserver->own_ip = g_new(IPADDR, 1);
memcpy(sserver->own_ip, &ip, sizeof(IPADDR));
}
}
sserver->last_connect = time(NULL);
if (sserver->ircnet) conn->ircnet = g_strdup(sserver->ircnet);
if (sserver->password && !conn->password)
conn->password = g_strdup(sserver->password);
if (sserver->cmd_queue_speed > 0)
conn->cmd_queue_speed = sserver->cmd_queue_speed;
if (sserver->max_cmds_at_once > 0)
conn->max_cmds_at_once = sserver->max_cmds_at_once;
/* fill the rest from IRC network settings */
ircnet = sserver->ircnet == NULL ? NULL : ircnet_find(sserver->ircnet);
if (ircnet == NULL) return conn;
if (ircnet->nick && !(nick && *nick)) {
g_free(conn->nick);
conn->nick = g_strdup(ircnet->nick);;
}
if (ircnet->username) {
g_free(conn->username);
conn->username = g_strdup(ircnet->username);;
}
if (ircnet->realname) {
g_free(conn->realname);
conn->realname = g_strdup(ircnet->realname);;
}
if (ircnet->max_kicks > 0) conn->max_kicks = ircnet->max_kicks;
if (ircnet->max_msgs > 0) conn->max_msgs = ircnet->max_msgs;
if (ircnet->max_modes > 0) conn->max_modes = ircnet->max_modes;
if (ircnet->max_whois > 0) conn->max_whois = ircnet->max_whois;
return conn;
}
/* Create server connection record. `dest' is required, rest can be NULL.
`dest' is either a server address or irc network */
IRC_SERVER_CONNECT_REC *
irc_server_create_conn(const char *dest, int port, const char *password, const char *nick)
{
GSList *tmp;
time_t now;
int n;
g_return_val_if_fail(dest != NULL, NULL);
/* check if `dest' is IRC network */
if (ircnet_find(dest) == NULL)
return create_addr_conn(dest, port, password, nick);
/* first try to find a server that hasn't had any connection failures
for the past half an hour. If that isn't found, try any server. */
now = time(NULL);
for (n = 0; n < 2; n++) {
for (tmp = setupservers; tmp != NULL; tmp = tmp->next) {
SETUP_SERVER_REC *rec = tmp->data;
if (rec->ircnet == NULL || g_strcasecmp(rec->ircnet, dest) != 0)
continue;
if (n == 1 || !rec->last_failed || rec->last_connect < now-FAILED_RECONNECT_WAIT)
return create_addr_conn(rec->address, port, password, nick);
}
}
return NULL;
}
/* Find matching server from setup. Set port to -1 if you don't care about it */
SETUP_SERVER_REC *server_setup_find(const char *address, int port)
{
GSList *tmp;
g_return_val_if_fail(address != NULL, NULL);
for (tmp = setupservers; tmp != NULL; tmp = tmp->next) {
SETUP_SERVER_REC *rec = tmp->data;
if (g_strcasecmp(rec->address, address) == 0 &&
(port == -1 || rec->port == port)) return rec;
}
return NULL;
}
static void init_userinfo(void)
{
const char *set, *default_nick, *user_name;
char *str;
/* check if nick/username/realname wasn't read from setup.. */
set = settings_get_str("real_name");
if (set == NULL || *set == '\0') {
str = g_getenv("IRCNAME");
iconfig_set_str("settings", "real_name",
str != NULL ? str : g_get_real_name());
}
/* username */
user_name = settings_get_str("user_name");
if (user_name == NULL || *user_name == '\0') {
str = g_getenv("IRCUSER");
iconfig_set_str("settings", "user_name",
str != NULL ? str : g_get_user_name());
user_name = settings_get_str("user_name");
}
/* nick */
default_nick = settings_get_str("default_nick");
if (default_nick == NULL || *default_nick == '\0') {
str = g_getenv("IRCNICK");
iconfig_set_str("settings", "default_nick",
str != NULL ? str : user_name);
default_nick = settings_get_str("default_nick");
}
/* alternate nick */
set = settings_get_str("alternate_nick");
if (set == NULL || *set == '\0') {
if (strlen(default_nick) < 9)
str = g_strconcat(default_nick, "_", NULL);
else {
str = g_strdup(default_nick);
str[strlen(str)-1] = '_';
}
iconfig_set_str("settings", "alternate_nick", str);
g_free(str);
}
/* host name */
set = settings_get_str("hostname");
if (set == NULL || *set == '\0') {
str = g_getenv("IRCHOST");
if (str != NULL)
iconfig_set_str("settings", "hostname", str);
}
}
void setupserver_config_add(SETUP_SERVER_REC *rec)
{
CONFIG_NODE *node;
node = iconfig_node_traverse("(servers", TRUE);
node = config_node_section(node, NULL, NODE_TYPE_BLOCK);
iconfig_node_set_str(node, "address", rec->address);
iconfig_node_set_str(node, "ircnet", rec->ircnet);
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);
if (rec->max_cmds_at_once > 0)
config_node_set_int(node, "cmds_max_at_once", rec->max_cmds_at_once);
if (rec->cmd_queue_speed > 0)
config_node_set_int(node, "cmd_queue_speed", rec->cmd_queue_speed);
}
void setupserver_config_remove(SETUP_SERVER_REC *rec)
{
CONFIG_NODE *node;
node = iconfig_node_traverse("servers", FALSE);
if (node != NULL) iconfig_node_list_remove(node, g_slist_index(setupservers, rec));
}
static void setupserver_destroy(SETUP_SERVER_REC *rec)
{
setupservers = g_slist_remove(setupservers, rec);
g_free_not_null(rec->own_host);
g_free_not_null(rec->own_ip);
g_free(rec->ircnet);
g_free(rec->address);
g_free_not_null(rec->password);
g_free(rec);
}
void server_setup_add(SETUP_SERVER_REC *rec)
{
if (g_slist_find(setupservers, rec) != NULL) {
setupserver_config_remove(rec);
setupservers = g_slist_remove(setupservers, rec);
}
setupservers = g_slist_append(setupservers, rec);
setupserver_config_add(rec);
}
void server_setup_remove(SETUP_SERVER_REC *rec)
{
setupserver_config_remove(rec);
setupserver_destroy(rec);
}
static SETUP_SERVER_REC *setupserver_add_node(CONFIG_NODE *node)
{
SETUP_SERVER_REC *rec;
char *server;
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(server, port) != NULL) {
/* already exists - don't let it get there twice or
server reconnects will screw up! */
return NULL;
}
rec = g_new0(SETUP_SERVER_REC, 1);
rec->ircnet = g_strdup(config_node_get_str(node, "ircnet", NULL));
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->max_cmds_at_once = config_node_get_int(node, "cmds_max_at_once", 0);
rec->cmd_queue_speed = config_node_get_int(node, "cmd_queue_speed", 0);
rec->own_host = g_strdup(config_node_get_str(node, "own_host", 0));
setupservers = g_slist_append(setupservers, rec);
return rec;
}
static void read_servers(void)
{
CONFIG_NODE *node;
GSList *tmp;
while (setupservers != NULL)
setupserver_destroy(setupservers->data);
/* Read servers */
node = iconfig_node_traverse("servers", FALSE);
if (node != NULL) {
for (tmp = node->value; tmp != NULL; tmp = tmp->next)
setupserver_add_node(tmp->data);
}
}
void servers_setup_init(void)
{
source_host_ok = FALSE;
source_host_ip = NULL;
settings_add_int("server", "server_reconnect_time", 300);
settings_add_str("server", "hostname", "");
settings_add_bool("server", "skip_motd", FALSE);
settings_add_str("server", "default_nick", NULL);
settings_add_str("server", "alternate_nick", NULL);
settings_add_str("server", "user_name", NULL);
settings_add_str("server", "real_name", NULL);
settings_add_bool("ircproxy", "use_ircproxy", FALSE);
settings_add_str("ircproxy", "proxy_address", "");
settings_add_int("ircproxy", "proxy_port", 6667);
settings_add_str("ircproxy", "proxy_string", "CONNECT %s %d");
init_userinfo();
read_servers();
signal_add("setup reread", (SIGNAL_FUNC) read_servers);
}
void servers_setup_deinit(void)
{
while (setupservers != NULL)
setupserver_destroy(setupservers->data);
signal_remove("setup reread", (SIGNAL_FUNC) read_servers);
}