This test is done quite a bit across the tree, and the open-coded variants make it easy to have an accidental mismatch between the length of the prefix being tested and the length actually passed to strncmp(). This fixes an issue of that type comparing the server version against the prefix "u2.10", where the old code used an incorrect length of 4.
3830 lines
91 KiB
C
3830 lines
91 KiB
C
/*
|
||
* server.c: Things dealing with server connections, etc.
|
||
*
|
||
* Written By Michael Sandrof
|
||
*
|
||
* Copyright(c) 1990
|
||
*
|
||
* See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
|
||
*/
|
||
#ifdef IRIX
|
||
#define _HAVE_SIN_LEN 1
|
||
#define _HAVE_SA_LEN 1
|
||
#define MAXDNAME 100
|
||
#endif
|
||
|
||
#include "irc.h"
|
||
static char cvsrevision[] = "$Id$";
|
||
CVS_REVISION(server_c)
|
||
#include "struct.h"
|
||
|
||
#include "parse.h"
|
||
|
||
#include <stdarg.h>
|
||
|
||
#include "server.h"
|
||
#include "commands.h"
|
||
#include "ircaux.h"
|
||
#include "input.h"
|
||
#include "who.h"
|
||
#include "lastlog.h"
|
||
#include "exec.h"
|
||
#include "window.h"
|
||
#include "output.h"
|
||
#include "names.h"
|
||
#include "hook.h"
|
||
#include "vars.h"
|
||
#include "hash2.h"
|
||
#include "screen.h"
|
||
#include "notify.h"
|
||
#include "misc.h"
|
||
#include "status.h"
|
||
#include "list.h"
|
||
#include "who.h"
|
||
#define MAIN_SOURCE
|
||
#include "modval.h"
|
||
|
||
#ifdef WDIDENT
|
||
#include <sys/types.h>
|
||
#include <sys/stat.h>
|
||
#include <pwd.h>
|
||
#endif
|
||
|
||
|
||
#ifdef IRIX
|
||
#undef sa_len
|
||
#endif
|
||
|
||
static char * set_umode (int du_index);
|
||
|
||
const char * umodes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||
|
||
/* server_list: the list of servers that the user can connect to,etc */
|
||
Server *server_list = NULL;
|
||
|
||
/* number_of_servers: in the server list */
|
||
static int number_of_servers = 0;
|
||
|
||
int primary_server = -1;
|
||
int from_server = -1;
|
||
int never_connected = 1; /* true until first connection
|
||
* is made */
|
||
int connected_to_server = 0; /* true when connection is
|
||
* confirmed */
|
||
int parsing_server_index = -1;
|
||
int last_server = -1;
|
||
|
||
extern int
|
||
dgets_errno;
|
||
int identd = -1;
|
||
|
||
#if defined(WINNT) || defined(__EMX__) || defined(__CYGWIN__) || defined(WANT_IDENTD)
|
||
int already_identd = 0;
|
||
#endif
|
||
|
||
/* link look and map commands */
|
||
irc_server *map = NULL;
|
||
static int first_time = 0;
|
||
extern char *channel;
|
||
|
||
int (*serv_open_func) (int, struct sockaddr_foobar, int) = NULL;
|
||
int (*serv_output_func) (int, int, char *, int) = NULL;
|
||
int (*serv_input_func) (int, char *, int, int, int) = NULL;
|
||
int (*serv_close_func) (int, struct sockaddr_foobar, int) = NULL;
|
||
|
||
static QueueSend *serverqueue = NULL;
|
||
|
||
/*
|
||
* close_server: Given an index into the server list, this closes the
|
||
* connection to the corresponding server. It does no checking on the
|
||
* validity of the index. It also first sends a "QUIT" to the server being
|
||
* closed
|
||
*/
|
||
void BX_close_server (int cs_index, char *message)
|
||
{
|
||
char buffer[IRCD_BUFFER_SIZE + 1];
|
||
|
||
if (cs_index < 0 || cs_index > number_of_servers)
|
||
return;
|
||
|
||
if (serv_close_func)
|
||
(*serv_close_func)(cs_index, server_list[cs_index].local_addr, server_list[cs_index].port);
|
||
clean_server_queues(cs_index);
|
||
|
||
if (waiting_out > waiting_in)
|
||
waiting_out = waiting_in = 0;
|
||
|
||
if (get_server_reconnecting(cs_index))
|
||
set_waiting_channel(cs_index);
|
||
else
|
||
clear_channel_list(cs_index);
|
||
|
||
clear_link(&server_list[cs_index].server_last);
|
||
clear_link(&server_list[cs_index].tmplink);
|
||
clear_server_sping(cs_index, NULL);
|
||
|
||
set_server_reconnect(cs_index, 0);
|
||
set_server_reconnecting(cs_index, 0);
|
||
set_server_try_once(cs_index, 0);
|
||
server_list[cs_index].server_change_pending = 0;
|
||
server_list[cs_index].operator = 0;
|
||
server_list[cs_index].connected = 0;
|
||
server_list[cs_index].lag = -1;
|
||
server_list[cs_index].buffer = NULL;
|
||
server_list[cs_index].link_look = 0;
|
||
server_list[cs_index].login_flags = 0;
|
||
|
||
server_list[cs_index].awaytime = 0;
|
||
new_free(&server_list[cs_index].away);
|
||
new_free(&server_list[cs_index].recv_nick);
|
||
new_free(&server_list[cs_index].sent_nick);
|
||
new_free(&server_list[cs_index].sent_body);
|
||
|
||
if (server_list[cs_index].write > -1)
|
||
{
|
||
if (message && *message && !server_list[cs_index].closing)
|
||
{
|
||
server_list[cs_index].closing = 1;
|
||
if (x_debug & DEBUG_OUTBOUND)
|
||
yell("Closing server %d because [%s]",
|
||
cs_index, message ? message : empty_string);
|
||
snprintf(buffer, MAX_PROTOCOL_SIZE + 1, "QUIT :%s", message);
|
||
strlcat(buffer, "\r\n", sizeof buffer);
|
||
#ifdef HAVE_LIBSSL
|
||
if (get_server_ssl(cs_index))
|
||
{
|
||
SSL_write(server_list[cs_index].ssl_fd, buffer, strlen(buffer));
|
||
say("Closing SSL connection");
|
||
SSL_shutdown(server_list[cs_index].ssl_fd);
|
||
}
|
||
else
|
||
#endif
|
||
send(server_list[cs_index].write, buffer, strlen(buffer), 0);
|
||
}
|
||
new_close(server_list[cs_index].write);
|
||
}
|
||
if (server_list[cs_index].read > -1)
|
||
new_close(server_list[cs_index].read);
|
||
server_list[cs_index].write = server_list[cs_index].read = -1;
|
||
if (identd != -1)
|
||
set_socketflags(identd, 0);
|
||
#if defined(WINNT) || defined(__EMX__) || defined(CYGWIN) || defined(WANT_IDENTD)
|
||
already_identd = 0;
|
||
#endif
|
||
}
|
||
|
||
int close_all_servers(char *message)
|
||
{
|
||
int i;
|
||
for (i = 0; i < number_of_servers; i++)
|
||
{
|
||
set_server_reconnecting(i, 0);
|
||
close_server(i, message);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
|
||
/*
|
||
* Check if the server that has a connection pending
|
||
* has any windows that are going to switch over when
|
||
* it connects. If not abort the connection attempt.
|
||
*/
|
||
void close_unattached_server(int server)
|
||
{
|
||
#ifdef NON_BLOCKING_CONNECTS
|
||
Window *tmp = NULL;
|
||
int cnt = 0;
|
||
|
||
if(server < 0 || server_list[server].old_server < 0)
|
||
return;
|
||
|
||
while ((traverse_all_windows(&tmp)))
|
||
{
|
||
if (tmp->server == -1)
|
||
cnt++;
|
||
}
|
||
if (cnt == 0)
|
||
close_server(server, empty_string);
|
||
#endif
|
||
}
|
||
|
||
void close_unattached_servers(void)
|
||
{
|
||
int i;
|
||
|
||
for (i = 0; i < number_of_servers; i++)
|
||
{
|
||
if(server_list[i].old_server == -2 ||
|
||
#ifdef NON_BLOCKING_CONNECTS
|
||
server_list[i].server_change_pending ||
|
||
#endif
|
||
server_list[i].reconnecting)
|
||
close_server(i, empty_string);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* set_server_bits: Sets the proper bits in the fd_set structure according to
|
||
* which servers in the server list have currently active read descriptors.
|
||
*/
|
||
void set_server_bits (fd_set *rd, fd_set *wr, struct timeval *wake_time)
|
||
{
|
||
int i;
|
||
|
||
for (i = 0; i < number_of_servers; i++)
|
||
{
|
||
if (server_list[i].reconnect > 0)
|
||
{
|
||
struct timeval connect_wake_time = server_list[i].connect_time;
|
||
connect_wake_time.tv_sec += get_int_var(CONNECT_DELAY_VAR);
|
||
|
||
if (time_cmp(wake_time, &connect_wake_time) > 0)
|
||
*wake_time = connect_wake_time;
|
||
}
|
||
if (is_server_connected(i))
|
||
{
|
||
/* Time to send another ping */
|
||
int lag_check_interval = get_int_var(LAG_CHECK_INTERVAL_VAR);
|
||
struct timeval lag_wake_time = server_list[i].lag_sent;
|
||
lag_wake_time.tv_sec += lag_check_interval;
|
||
|
||
if (lag_check_interval > 0 && time_cmp(wake_time, &lag_wake_time) > 0)
|
||
*wake_time = lag_wake_time;
|
||
|
||
if (server_list[i].lag != -1)
|
||
{
|
||
/* Time that previous lag value becomes stale */
|
||
lag_wake_time = server_list[i].lag_recv;
|
||
lag_wake_time.tv_sec += lag_check_interval + 1;
|
||
|
||
if (time_cmp(wake_time, &lag_wake_time) > 0)
|
||
*wake_time = lag_wake_time;
|
||
}
|
||
}
|
||
|
||
if (server_list[i].read > -1)
|
||
FD_SET(server_list[i].read, rd);
|
||
#ifdef NON_BLOCKING_CONNECTS
|
||
if (!(server_list[i].login_flags & (LOGGED_IN|CLOSE_PENDING)) &&
|
||
server_list[i].write > -1)
|
||
FD_SET(server_list[i].write, wr);
|
||
#endif
|
||
}
|
||
|
||
/* Check for a QUEUE_SENDS wake_time */
|
||
if (serverqueue)
|
||
{
|
||
struct timeval queue_wake_time;
|
||
|
||
queue_wake_time.tv_sec = server_list[serverqueue->server].last_sent +
|
||
get_int_var(QUEUE_SENDS_VAR);
|
||
queue_wake_time.tv_usec = 0;
|
||
|
||
if (time_cmp(wake_time, &queue_wake_time) > 0)
|
||
*wake_time = queue_wake_time;
|
||
}
|
||
}
|
||
|
||
int timed_server (void *args, char *sub)
|
||
{
|
||
char *p = (char *)args;
|
||
static int retry = 0;
|
||
int serv = -1;
|
||
if (!p || !*p)
|
||
return 0;
|
||
serv = atol(p);
|
||
new_free(&p);
|
||
if (!is_server_open(serv) && number_of_servers)
|
||
{
|
||
bitchsay("Servers exhausted. Restarting. [%d]", ++retry);
|
||
get_connected(serv, from_server);
|
||
}
|
||
set_server_in_timed(serv, 0);
|
||
return 0;
|
||
}
|
||
|
||
int find_old_server(int old_server)
|
||
{
|
||
int i;
|
||
|
||
if(old_server > -1 && old_server < number_of_servers)
|
||
{
|
||
for (i = 0; i < number_of_servers; i++)
|
||
{
|
||
if(server_list[i].old_server == old_server)
|
||
return i;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
int advance_server(int i)
|
||
{
|
||
int server = i;
|
||
|
||
/* We were waiting for this server to
|
||
* connect and it didn't, so we will either
|
||
* try again or move to the next server.
|
||
*/
|
||
|
||
server_list[i].retries++;
|
||
if (server_list[i].retries >= get_int_var(MAX_SERVER_RECONNECT_VAR))
|
||
{
|
||
server = next_server(i);
|
||
|
||
if (server != i)
|
||
{
|
||
/* We have a new server to try, so lets
|
||
* move the variables over from the last one
|
||
* and tell it to try to connect.
|
||
*/
|
||
set_server_reconnect(server, 1);
|
||
set_server_req_server(server, server_list[i].req_server);
|
||
set_server_old_server(server, server_list[i].old_server);
|
||
set_server_change_refnum(server, server_list[i].server_change_refnum);
|
||
set_server_retries(server, 0);
|
||
#ifdef NON_BLOCKING_CONNECTS
|
||
server_list[server].from_server = server_list[i].from_server;
|
||
server_list[server].c_server = server_list[i].c_server;
|
||
#endif
|
||
/* Reset the old server to the default state. */
|
||
server_list[i].retries = 0;
|
||
server_list[i].reconnect = 0;
|
||
server_list[i].old_server = -1;
|
||
server_list[i].req_server = -1;
|
||
#ifdef NON_BLOCKING_CONNECTS
|
||
server_list[i].connect_wait = 0;
|
||
server_list[i].from_server = -1;
|
||
server_list[i].c_server = -1;
|
||
#endif
|
||
}
|
||
}
|
||
|
||
if (!get_int_var(AUTO_RECONNECT_VAR) && (server_list[server].req_server != server || server_list[server].retries > 1))
|
||
{
|
||
close_server(server, empty_string);
|
||
from_server = -1;
|
||
if (do_hook(DISCONNECT_LIST,"No Connection"))
|
||
put_it("%s", convert_output_format(fget_string_var(FORMAT_DISCONNECT_FSET), "%s %s", update_clock(GET_TIME), "No connection"));
|
||
return -1;
|
||
}
|
||
else if (server == server_list[i].req_server && server_list[server].retries > 1)
|
||
bitchsay("Servers exhausted. Restarting.");
|
||
|
||
return server;
|
||
}
|
||
|
||
static void reconnect_server(int servernum)
|
||
{
|
||
if (servernum < 0)
|
||
servernum = 0;
|
||
|
||
server_list[servernum].reconnecting = 1;
|
||
close_server(servernum, empty_string);
|
||
|
||
servernum = advance_server(servernum);
|
||
|
||
if (servernum < 0)
|
||
return;
|
||
|
||
set_server_reconnect(servernum, 0);
|
||
window_check_servers(servernum);
|
||
try_connect(servernum, server_list[servernum].old_server);
|
||
}
|
||
|
||
/* Check for a nonblocking connection that has been around
|
||
* for more than CONNECT_TIMEOUT_VAR seconds without connecting
|
||
*/
|
||
#ifdef NON_BLOCKING_CONNECTS
|
||
static void scan_nonblocking(void)
|
||
{
|
||
int i;
|
||
int connect_timeout = get_int_var(CONNECT_TIMEOUT_VAR);
|
||
|
||
if (!connect_timeout)
|
||
return;
|
||
|
||
for (i = 0; i < number_of_servers; i++)
|
||
{
|
||
if (((server_list[i].read > -1) ||
|
||
(server_list[i].write > -1)) &&
|
||
!(server_list[i].login_flags & LOGGED_IN) &&
|
||
time_since(&server_list[i].connect_time) > connect_timeout) {
|
||
if (server_list[i].read > -1)
|
||
new_close(server_list[i].read);
|
||
if (server_list[i].write > -1)
|
||
new_close(server_list[i].write);
|
||
server_list[i].read = server_list[i].write = -1;
|
||
set_server_reconnect(i, 1);
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
void do_idle_server (void)
|
||
{
|
||
int i;
|
||
|
||
#ifdef NON_BLOCKING_CONNECTS
|
||
scan_nonblocking();
|
||
#endif
|
||
|
||
for (i = 0; i < number_of_servers && i > -1; i++)
|
||
{
|
||
/* We were told to reconnect, to avoid recursion. */
|
||
if (get_server_reconnect(i) > 0)
|
||
{
|
||
int connect_delay = get_int_var(CONNECT_DELAY_VAR);
|
||
|
||
if (time_since(&server_list[i].connect_time) > connect_delay)
|
||
{
|
||
set_server_reconnect(i, 0);
|
||
reconnect_server(i);
|
||
}
|
||
}
|
||
|
||
if (is_server_connected(i))
|
||
{
|
||
int lag_check_interval = get_int_var(LAG_CHECK_INTERVAL_VAR);
|
||
|
||
if (lag_check_interval > 0 &&
|
||
time_since(&server_list[i].lag_sent) > lag_check_interval)
|
||
{
|
||
get_time(&server_list[i].lag_sent);
|
||
my_send_to_server(i, "PING LAG!%lu.%ld.%ld :%s",
|
||
server_list[i].lag_cookie,
|
||
(long)server_list[i].lag_sent.tv_sec,
|
||
(long)server_list[i].lag_sent.tv_usec,
|
||
get_server_itsname(i));
|
||
}
|
||
if (server_list[i].lag != -1 &&
|
||
time_since(&server_list[i].lag_recv) > lag_check_interval + 1)
|
||
{
|
||
/* Lag reply overdue */
|
||
set_server_lag(i, -1);
|
||
update_all_status(current_window, NULL, 0);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
*
|
||
do_server: check the given fd_set against the currently open servers in
|
||
* the server list. If one have information available to be read, it is read
|
||
* and and parsed appropriately. If an EOF is detected from an open server,
|
||
* one of two things occurs. 1) If the server was the primary server,
|
||
* get_connected() is called to maintain the connection status of the user.
|
||
* 2) If the server wasn't a primary server, connect_to_server() is called to
|
||
* try to keep that connection alive.
|
||
*/
|
||
void do_server (fd_set *rd, fd_set *wr)
|
||
{
|
||
char buffer[BIG_BUFFER_SIZE + 1];
|
||
int des,
|
||
i;
|
||
|
||
/* Process server timeouts */
|
||
do_idle_server();
|
||
|
||
for (i = 0; i < number_of_servers; i++)
|
||
{
|
||
#ifdef NON_BLOCKING_CONNECTS
|
||
if (((des = server_list[i].write) > -1) && FD_ISSET(des, wr) && !(server_list[i].login_flags & LOGGED_IN))
|
||
{
|
||
struct sockaddr_in sa;
|
||
socklen_t salen = sizeof(struct sockaddr_in);
|
||
|
||
if (getpeername(des, (struct sockaddr *) &sa, &salen) != -1)
|
||
{
|
||
#ifdef HAVE_LIBSSL
|
||
if(!server_list[i].ctx || server_list[i].ssl_error == SSL_ERROR_WANT_WRITE)
|
||
{
|
||
#endif
|
||
server_list[i].connect_wait = 0;
|
||
finalize_server_connect(i, server_list[i].c_server, i);
|
||
#ifdef HAVE_LIBSSL
|
||
}
|
||
#endif
|
||
}
|
||
}
|
||
#endif
|
||
if (((des = server_list[i].read) > -1) && FD_ISSET(des, rd))
|
||
{
|
||
int junk = 0;
|
||
char *bufptr;
|
||
errno = 0;
|
||
last_server = from_server = i;
|
||
bufptr = buffer;
|
||
if (serv_input_func)
|
||
junk = (*serv_input_func)(i, bufptr, des, 1, BIG_BUFFER_SIZE);
|
||
else
|
||
{
|
||
#ifdef HAVE_LIBSSL
|
||
if(get_server_ssl(i))
|
||
{
|
||
#ifdef NON_BLOCKING_CONNECTS
|
||
/* If we get here before getting above we have problems. */
|
||
if(!(server_list[i].login_flags & LOGGED_IN))
|
||
{
|
||
if(!server_list[i].ctx || server_list[i].ssl_error == SSL_ERROR_WANT_READ)
|
||
{
|
||
server_list[i].connect_wait = 0;
|
||
finalize_server_connect(i, server_list[i].c_server, i);
|
||
}
|
||
}
|
||
else
|
||
#endif
|
||
junk = dgets(bufptr, des, 1, BIG_BUFFER_SIZE, server_list[i].ssl_fd);
|
||
}
|
||
else
|
||
#endif
|
||
junk = dgets(bufptr, des, 1, BIG_BUFFER_SIZE, NULL);
|
||
}
|
||
switch (junk)
|
||
{
|
||
case 0: /* timeout */
|
||
break;
|
||
case -1: /* EOF condition */
|
||
{
|
||
int try_once = server_list[i].try_once;
|
||
|
||
/* Try to make sure output goes to the correct window */
|
||
if(server_list[i].server_change_refnum > -1)
|
||
set_display_target_by_winref(server_list[i].server_change_refnum);
|
||
say("Connection closed from %s: %s", server_list[i].name, dgets_strerror(dgets_errno));
|
||
|
||
server_list[i].reconnecting = 1;
|
||
close_server(i, empty_string);
|
||
if(!try_once)
|
||
{
|
||
#ifdef NON_BLOCKING_CONNECTS
|
||
if(server_list[i].server_change_pending == 2)
|
||
{
|
||
/* If the previous server gets closed while
|
||
* we are waiting for another server to connect
|
||
* we don't want to try a new connection, so
|
||
* just close down this connection and quit.
|
||
*/
|
||
close_server(i, empty_string);
|
||
}
|
||
else if(server_list[i].connect_wait)
|
||
{
|
||
set_server_reconnect(i, 1);
|
||
|
||
if ((server_list[i].from_server != -1))
|
||
{
|
||
if((server_list[server_list[i].from_server].read != -1) &&
|
||
(server_list[i].from_server != i))
|
||
{
|
||
/* Set the windows back to the old server */
|
||
say("Connection to server %s resumed...", server_list[server_list[i].from_server].name);
|
||
change_server_channels(i, server_list[i].old_server);
|
||
set_window_server(-1, i, 1);
|
||
set_server_reconnect(i, 0);
|
||
} else if(server_list[i].from_server != i)
|
||
{
|
||
close_server(server_list[i].from_server, empty_string);
|
||
}
|
||
}
|
||
|
||
}
|
||
else
|
||
#endif
|
||
{
|
||
set_server_reconnect(i, 1);
|
||
server_list[i].old_server = i;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
default:
|
||
{
|
||
parsing_server_index = i;
|
||
server_list[i].last_msg = now;
|
||
parse_server(buffer);
|
||
new_free(&server_list[i].buffer);
|
||
parsing_server_index = -1;
|
||
reset_display_target();
|
||
break;
|
||
}
|
||
}
|
||
from_server = primary_server;
|
||
}
|
||
}
|
||
|
||
if (primary_server == -1 || !is_server_open(primary_server))
|
||
window_check_servers(-1);
|
||
}
|
||
|
||
/* server_lag_reply()
|
||
*
|
||
* Called when a reply to a lag check ping has been received.
|
||
*/
|
||
void server_lag_reply(int s, unsigned long cookie, struct timeval lag_recv, struct timeval lag_sent)
|
||
{
|
||
if (cookie == server_list[s].lag_cookie)
|
||
{
|
||
int new_lag = (int)(BX_time_diff(lag_sent, lag_recv) + 0.5);
|
||
|
||
server_list[s].lag_recv = lag_recv;
|
||
if (server_list[s].lag != new_lag)
|
||
{
|
||
server_list[s].lag = new_lag;
|
||
update_all_status(current_window, NULL, 0);
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* find_in_server_list: given a server name, this tries to match it against
|
||
* names in the server list, returning the index into the list if found, or
|
||
* -1 if not found
|
||
*/
|
||
extern int BX_find_in_server_list (char *server, int port)
|
||
{
|
||
int i,
|
||
len, hintfound = -1;
|
||
|
||
len = strlen(server);
|
||
|
||
for (i = 0; i < number_of_servers; i++)
|
||
{
|
||
if (port && server_list[i].port && port != server_list[i].port && port != -1)
|
||
continue;
|
||
|
||
#if 0
|
||
#define MATCH_WITH_COMPLETION(n1, n2) \
|
||
{ \
|
||
size_t l1 = strlen(n1); \
|
||
size_t l2 = strlen(n2); \
|
||
size_t l3 = l1 > l2 ? l2 : l1; \
|
||
\
|
||
if (!my_strnicmp(n1, n2, l3)) \
|
||
return i; \
|
||
}
|
||
|
||
|
||
MATCH_WITH_COMPLETION(server, server_list[i].name);
|
||
|
||
if (!server_list[i].itsname)
|
||
continue;
|
||
MATCH_WITH_COMPLETION(server, server_list[i].itsname);
|
||
#endif
|
||
/*
|
||
* Try to avoid unneccessary string compares. Only compare
|
||
* the first part of the string if there's not already a
|
||
* possible match set in "hintfound". This enables us to
|
||
* search for an exact match even if there's already a
|
||
* fuzzy-match, without having to compare twice.
|
||
*/
|
||
if ((-1 != hintfound) || !my_strnicmp(server, server_list[i].name, len))
|
||
{
|
||
if (!my_stricmp(server, server_list[i].name))
|
||
return i;
|
||
else if (-1 == hintfound)
|
||
hintfound = i;
|
||
}
|
||
else if (server_list[i].itsname && ((-1 != hintfound) ||
|
||
!my_strnicmp(server, server_list[i].itsname, len)))
|
||
{
|
||
if (!my_stricmp(server, server_list[i].itsname))
|
||
return i;
|
||
else if (-1 == hintfound)
|
||
hintfound = i;
|
||
}
|
||
}
|
||
return (hintfound);
|
||
}
|
||
|
||
/*
|
||
* parse_server_index: given a string, this checks if it's a number, and if
|
||
* so checks it validity as a server index. Otherwise -1 is returned
|
||
*/
|
||
int BX_parse_server_index (char *str)
|
||
{
|
||
int i;
|
||
|
||
if (is_number(str))
|
||
{
|
||
i = my_atol(str);
|
||
if ((i >= 0) && (i < number_of_servers))
|
||
return (i);
|
||
}
|
||
return (-1);
|
||
}
|
||
|
||
/*
|
||
* This replaces ``get_server_index''.
|
||
*/
|
||
int BX_find_server_refnum (char *server, char **rest)
|
||
{
|
||
int refnum;
|
||
int port = irc_port;
|
||
char *cport = NULL,
|
||
*password = NULL,
|
||
*nick = NULL,
|
||
*snetwork = NULL;
|
||
|
||
/*
|
||
* First of all, check for an existing server refnum
|
||
*/
|
||
if ((refnum = parse_server_index(server)) != -1)
|
||
return refnum;
|
||
/*
|
||
* Next check to see if its a "server:port:password:nick:network"
|
||
*/
|
||
else if (index(server, ':') || index(server, ','))
|
||
parse_server_info(server, &cport, &password, &nick, &snetwork);
|
||
|
||
else if (index(server, '['))
|
||
{
|
||
int i;
|
||
server++;
|
||
chop(server, 1);
|
||
if (!server || !*server)
|
||
return from_server;
|
||
for (i = 0; i < number_of_servers; i++)
|
||
{
|
||
if (server && server_list[i].snetwork && !my_stricmp(server, server_list[i].snetwork))
|
||
return i;
|
||
}
|
||
}
|
||
/*
|
||
* Next check to see if its "server port password nick"
|
||
*/
|
||
else if (rest && *rest)
|
||
{
|
||
cport = next_arg(*rest, rest);
|
||
password = next_arg(*rest, rest);
|
||
nick = next_arg(*rest, rest);
|
||
snetwork = next_arg(*rest, rest);
|
||
}
|
||
|
||
if (cport && *cport)
|
||
port = my_atol(cport);
|
||
|
||
/*
|
||
* Add to the server list (this will update the port
|
||
* and password fields).
|
||
*/
|
||
add_to_server_list(server, port, password, nick, snetwork, 0, 1);
|
||
return from_server;
|
||
}
|
||
|
||
|
||
/*
|
||
* add_to_server_list: adds the given server to the server_list. If the
|
||
* server is already in the server list it is not re-added... however, if the
|
||
* overwrite flag is true, the port and passwords are updated to the values
|
||
* passes. If the server is not on the list, it is added to the end. In
|
||
* either case, the server is made the current server.
|
||
*/
|
||
void BX_add_to_server_list (char *server, int port, char *password, char *nick, char *snetwork, int ssl, int overwrite)
|
||
{
|
||
extern int default_swatch;
|
||
if ((from_server = find_in_server_list(server, port)) == -1)
|
||
{
|
||
from_server = number_of_servers++;
|
||
RESIZE(server_list, Server, number_of_servers+1);
|
||
memset(&server_list[from_server], 0, sizeof(Server));
|
||
server_list[from_server].name = m_strdup(server);
|
||
if (snetwork)
|
||
server_list[from_server].snetwork = m_strdup(snetwork);
|
||
server_list[from_server].read = -1;
|
||
server_list[from_server].write = -1;
|
||
server_list[from_server].lag = -1;
|
||
server_list[from_server].motd = 1;
|
||
server_list[from_server].ircop_flags = default_swatch;
|
||
server_list[from_server].port = port;
|
||
#ifdef HAVE_LIBSSL
|
||
set_server_ssl(from_server, ssl);
|
||
#endif
|
||
malloc_strcpy(&server_list[from_server].umodes, umodes);
|
||
if (password && *password)
|
||
malloc_strcpy(&(server_list[from_server].password), password);
|
||
|
||
if (nick && *nick)
|
||
malloc_strcpy(&(server_list[from_server].d_nickname), nick);
|
||
else if (!server_list[from_server].d_nickname)
|
||
malloc_strcpy(&(server_list[from_server].d_nickname), nickname);
|
||
|
||
make_notify_list(from_server);
|
||
make_watch_list(from_server);
|
||
set_umode(from_server);
|
||
}
|
||
else
|
||
{
|
||
if (overwrite)
|
||
{
|
||
server_list[from_server].port = port;
|
||
if (password || !server_list[from_server].password)
|
||
{
|
||
if (password && *password)
|
||
malloc_strcpy(&(server_list[from_server].password), password);
|
||
else
|
||
new_free(&(server_list[from_server].password));
|
||
}
|
||
if (nick || !server_list[from_server].d_nickname)
|
||
{
|
||
if (nick && *nick)
|
||
malloc_strcpy(&(server_list[from_server].d_nickname), nick);
|
||
else
|
||
new_free(&(server_list[from_server].d_nickname));
|
||
}
|
||
}
|
||
if (strlen(server) > strlen(server_list[from_server].name))
|
||
malloc_strcpy(&(server_list[from_server].name), server);
|
||
}
|
||
}
|
||
|
||
void remove_from_server_list (int i)
|
||
{
|
||
Window *tmp = NULL;
|
||
|
||
if (i < 0 || i >= number_of_servers)
|
||
return;
|
||
|
||
say("Deleting server [%d]", i);
|
||
|
||
clean_server_queues(i);
|
||
|
||
new_free(&server_list[i].name);
|
||
new_free(&server_list[i].snetwork);
|
||
new_free(&server_list[i].itsname);
|
||
new_free(&server_list[i].password);
|
||
new_free(&server_list[i].away);
|
||
new_free(&server_list[i].version_string);
|
||
new_free(&server_list[i].nickname);
|
||
new_free(&server_list[i].s_nickname);
|
||
new_free(&server_list[i].d_nickname);
|
||
new_free(&server_list[i].umodes);
|
||
new_free(&server_list[i].recv_nick);
|
||
new_free(&server_list[i].sent_nick);
|
||
new_free(&server_list[i].sent_body);
|
||
#ifdef HAVE_LIBSSL
|
||
SSL_CTX_free(server_list[i].ctx);
|
||
#endif
|
||
clear_server_sping(i, NULL);
|
||
|
||
/*
|
||
* this should save a coredump. If number_of_servers drops
|
||
* down to zero, then trying to do a realloc ends up being
|
||
* a free, and accessing that is a no-no.
|
||
*/
|
||
if (number_of_servers == 1)
|
||
{
|
||
say("Sorry, the server list is empty and I just don't know what to do.");
|
||
irc_exit(1, NULL, NULL);
|
||
}
|
||
|
||
memmove(&server_list[i], &server_list[i + 1], (number_of_servers - i - 1) * sizeof(Server));
|
||
number_of_servers--;
|
||
RESIZE(server_list, Server, number_of_servers);
|
||
|
||
/* update all he structs with server in them */
|
||
channel_server_delete(i);
|
||
exec_server_delete(i);
|
||
if (i < primary_server)
|
||
--primary_server;
|
||
if (i < from_server)
|
||
--from_server;
|
||
while ((traverse_all_windows(&tmp)))
|
||
if (tmp->server > i)
|
||
tmp->server--;
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
* parse_server_inFo: This parses a single string of the form
|
||
* "server:portnum:password:nickname:snetwork". It the points port to the portnum
|
||
* portion and password to the password portion. This chews up the original
|
||
* string, so * upon return, name will only point the the name. If portnum
|
||
* or password are missing or empty, their respective returned value will
|
||
* point to null.
|
||
*
|
||
* With IPv6 patch it also supports comma as a delimiter.
|
||
*/
|
||
void BX_parse_server_info (char *name, char **port, char **password, char **nick, char **snetwork)
|
||
{
|
||
char *ptr, delim;
|
||
|
||
delim = (index(name, ',')) ? ',' : ':';
|
||
|
||
*port = *password = *nick = NULL;
|
||
if ((ptr = (char *) strchr(name, delim)) != NULL)
|
||
{
|
||
*(ptr++) = (char) 0;
|
||
if (strlen(ptr) == 0)
|
||
*port = NULL;
|
||
else
|
||
{
|
||
*port = ptr;
|
||
if ((ptr = (char *) strchr(ptr, delim)) != NULL)
|
||
{
|
||
*(ptr++) = (char) 0;
|
||
if (strlen(ptr) == 0)
|
||
*password = 0;
|
||
else
|
||
{
|
||
*password = ptr;
|
||
if ((ptr = (char *) strchr(ptr, delim))
|
||
!= NULL)
|
||
{
|
||
*(ptr++) = 0;
|
||
if (!strlen(ptr))
|
||
*nick = NULL;
|
||
else
|
||
{
|
||
*nick = ptr;
|
||
if ((ptr = strchr(ptr, delim)) !=NULL)
|
||
{
|
||
*(ptr++) = 0;
|
||
if (!strlen(ptr))
|
||
*snetwork = NULL;
|
||
else
|
||
*snetwork = ptr;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* build_server_list: given a whitespace separated list of server names this
|
||
* builds a list of those servers using add_to_server_list(). Since
|
||
* add_to_server_list() is used to added each server specification, this can
|
||
* be called many many times to add more servers to the server list. Each
|
||
* element in the server list case have one of the following forms:
|
||
*
|
||
* servername
|
||
* servername:port
|
||
* servername:port:password
|
||
* servername::password
|
||
* servernetwork
|
||
* servername:port:password:nick:servernetwork
|
||
* Note also that this routine mucks around with the server string passed to it,
|
||
* so make sure this is ok
|
||
*/
|
||
static char *default_network = NULL;
|
||
|
||
int BX_build_server_list (char *servers)
|
||
{
|
||
char *host,
|
||
*rest,
|
||
*password = NULL,
|
||
*port = NULL,
|
||
*nick = NULL,
|
||
*snetwork = NULL;
|
||
|
||
int port_num;
|
||
int i = 0;
|
||
#ifdef HAVE_LIBSSL
|
||
extern int do_use_ssl;
|
||
#else
|
||
int do_use_ssl = 0;
|
||
#endif
|
||
|
||
if (!servers || !*servers)
|
||
return 0;
|
||
|
||
while (servers)
|
||
{
|
||
if ((rest = (char *) strchr(servers, '\n')) != NULL)
|
||
*rest++ = 0;
|
||
while ((host = new_next_arg(servers, &servers)) != NULL)
|
||
{
|
||
if (!host || !*host)
|
||
break;
|
||
if (*host == '[')
|
||
{
|
||
host++;
|
||
if (host[strlen(host)-1] != ']' && servers && *servers)
|
||
{
|
||
char *ptr = NULL;
|
||
host[strlen(host)] = ' ';
|
||
if ((ptr = MatchingBracket(host, '[', ']')))
|
||
{
|
||
*ptr++ = 0;
|
||
servers = ptr;
|
||
}
|
||
}
|
||
if (host[strlen(host)-1] == ']')
|
||
chop(host, 1);
|
||
malloc_strcpy(&default_network, host);
|
||
snetwork = NULL;
|
||
continue;
|
||
}
|
||
parse_server_info(host, &port, &password, &nick, &snetwork);
|
||
if (port && *port)
|
||
{
|
||
if (!(port_num = my_atol(port)))
|
||
port_num = irc_port;
|
||
}
|
||
else
|
||
port_num = irc_port;
|
||
|
||
add_to_server_list(host, port_num, password, nick, snetwork ? snetwork : default_network, do_use_ssl, 0);
|
||
i++;
|
||
}
|
||
servers = rest;
|
||
}
|
||
return i;
|
||
}
|
||
|
||
int read_and_parse_server(char **filename, char *buffer)
|
||
{
|
||
FILE *fp;
|
||
int i = 0;
|
||
if ((fp = uzfopen(filename, ".", 0)))
|
||
{
|
||
char *p;
|
||
while (fgets(buffer, BIG_BUFFER_SIZE, fp))
|
||
{
|
||
chop(buffer, 1);
|
||
if ((p = strchr(buffer, '#')))
|
||
*p = 0;
|
||
i += build_server_list(buffer);
|
||
}
|
||
fclose(fp);
|
||
}
|
||
return i;
|
||
}
|
||
|
||
/*
|
||
* read_server_file: reads hostname:portnum:password:network server information from
|
||
* a file and adds this stuff to the server list. See build_server_list()/
|
||
*/
|
||
int BX_read_server_file (char *servers_file)
|
||
{
|
||
int some = 0;
|
||
char *file_path = NULL;
|
||
char buffer[BIG_BUFFER_SIZE + 1];
|
||
int old_window_display = window_display;
|
||
char *expanded;
|
||
|
||
window_display = 0;
|
||
|
||
if (getenv("IRC_SERVERS_FILE"))
|
||
{
|
||
malloc_strcpy(&file_path, getenv("IRC_SERVERS_FILE"));
|
||
expanded = expand_twiddle(file_path);
|
||
some = read_and_parse_server(&expanded, buffer);
|
||
new_free(&file_path);
|
||
new_free(&expanded);
|
||
}
|
||
|
||
#ifdef SERVERS_FILE
|
||
if (SERVERS_FILE[0] != '/')
|
||
file_path = m_opendup(irc_lib, "/", NULL);
|
||
malloc_strcat(&file_path, SERVERS_FILE);
|
||
some += read_and_parse_server(&file_path, buffer);
|
||
new_free(&file_path);
|
||
#endif
|
||
|
||
if (*servers_file == '/')
|
||
file_path = m_strdup(servers_file);
|
||
else
|
||
file_path = m_opendup("~/", servers_file, NULL);
|
||
some += read_and_parse_server(&file_path, buffer);
|
||
new_free(&file_path);
|
||
|
||
window_display = old_window_display;
|
||
return some;
|
||
}
|
||
|
||
|
||
/*
|
||
* Actually do the work of writing out all the entries.
|
||
*/
|
||
void write_server_list(char *filename)
|
||
{
|
||
FILE *serverfile;
|
||
char *sgroup = NULL;
|
||
int i;
|
||
|
||
if(!number_of_servers || !(serverfile = fopen(filename, "w")))
|
||
return;
|
||
|
||
bitchsay("Writing server list to %s", filename);
|
||
|
||
fprintf(serverfile, "# Server list generated by BitchX.\n");
|
||
|
||
for(i=0;i<number_of_servers;i++)
|
||
{
|
||
if(!sgroup && server_list[i].snetwork)
|
||
{
|
||
sgroup = server_list[i].snetwork;
|
||
fprintf(serverfile, "\n[%s]\n", sgroup);
|
||
}
|
||
else if(sgroup && server_list[i].snetwork &&
|
||
my_stricmp(sgroup, server_list[i].snetwork))
|
||
{
|
||
sgroup = server_list[i].snetwork;
|
||
fprintf(serverfile, "\n[%s]\n", sgroup);
|
||
}
|
||
else if(sgroup && !server_list[i].snetwork)
|
||
{
|
||
sgroup = NULL;
|
||
fprintf(serverfile, "\n[unknown]\n");
|
||
}
|
||
|
||
fprintf(serverfile, "%s:%d", server_list[i].name, server_list[i].port);
|
||
if(server_list[i].password)
|
||
fprintf(serverfile, ":%s", server_list[i].password);
|
||
fprintf(serverfile, "\n");
|
||
}
|
||
|
||
fclose(serverfile);
|
||
}
|
||
|
||
/*
|
||
* write_server_file: writes hostname:portnum:password:network server information
|
||
* to a file.
|
||
*/
|
||
void write_server_file (char *servers_file)
|
||
{
|
||
char *file_path = NULL;
|
||
char *expanded;
|
||
|
||
if(servers_file && *servers_file)
|
||
{
|
||
if (*servers_file == '/')
|
||
file_path = m_strdup(servers_file);
|
||
else
|
||
file_path = m_opendup("~/", servers_file, NULL);
|
||
write_server_list(file_path);
|
||
new_free(&file_path);
|
||
return;
|
||
}
|
||
|
||
if (getenv("IRC_SERVERS_FILE"))
|
||
{
|
||
malloc_strcpy(&file_path, getenv("IRC_SERVERS_FILE"));
|
||
expanded = expand_twiddle(file_path);
|
||
write_server_list(expanded);
|
||
new_free(&file_path);
|
||
new_free(&expanded);
|
||
return;
|
||
}
|
||
|
||
#if defined(WINNT) || defined(__EMX__)
|
||
malloc_strcpy(&file_path, "~/irc-serv");
|
||
#else
|
||
malloc_strcpy(&file_path, "~/.ircservers");
|
||
#endif
|
||
expanded = expand_twiddle(file_path);
|
||
write_server_list(expanded);
|
||
new_free(&file_path);
|
||
new_free(&expanded);
|
||
}
|
||
|
||
|
||
/*
|
||
* connect_to_server_direct: handles the tcp connection to a server. If
|
||
* successful, the user is disconnected from any previously connected server,
|
||
* the new server is added to the server list, and the user is registered on
|
||
* the new server. If connection to the server is not successful, the
|
||
* reason for failure is displayed and the previous server connection is
|
||
* resumed uniterrupted.
|
||
*
|
||
* This version of connect_to_server() connects directly to a server
|
||
*/
|
||
static int connect_to_server_direct (char *server_name, int port)
|
||
{
|
||
int new_des;
|
||
struct sockaddr_foobar *localaddr;
|
||
socklen_t address_len;
|
||
unsigned short this_sucks;
|
||
|
||
|
||
#ifdef WDIDENT
|
||
struct stat sb;
|
||
struct passwd *pw;
|
||
char lockfile[1024];
|
||
FILE *fp;
|
||
char candofilestuff=0;
|
||
struct hostent *hp=NULL;
|
||
struct sockaddr_in raddr;
|
||
#endif
|
||
|
||
|
||
oper_command = 0;
|
||
errno = 0;
|
||
localaddr = &server_list[from_server].local_sockname;
|
||
memset(localaddr, 0, sizeof(*localaddr));
|
||
this_sucks = (unsigned short)port;
|
||
|
||
|
||
#ifdef WDIDENT
|
||
pw=getpwuid(getuid());
|
||
if(!pw)
|
||
goto noidentwd;
|
||
sprintf(lockfile, "%s/.identwd", pw->pw_dir);
|
||
|
||
if(*server_name=='/')
|
||
goto noidentwd;
|
||
|
||
if(stat(lockfile, &sb))
|
||
goto noidentwd;
|
||
|
||
if(!(sb.st_mode & S_IFDIR))
|
||
goto noidentwd;
|
||
|
||
hp=resolv(server_name);
|
||
if(!hp)
|
||
goto noidentwd;
|
||
if(hp->h_addrtype != AF_INET)
|
||
goto noidentwd;
|
||
|
||
memcpy(&raddr.sin_addr, hp->h_addr, hp->h_length);
|
||
sprintf(lockfile, "%s/.identwd/%s.%i.LOCK", pw->pw_dir,
|
||
inet_ntoa((struct in_addr)raddr.sin_addr), port);
|
||
if ((fp=fopen(lockfile, "w")))
|
||
{
|
||
fprintf(fp, "WAIT\n");
|
||
fclose(fp);
|
||
candofilestuff=1;
|
||
}
|
||
noidentwd:
|
||
#endif
|
||
|
||
#ifdef NON_BLOCKING_CONNECTS
|
||
new_des = connect_by_number(server_name, &this_sucks, SERVICE_CLIENT, PROTOCOL_TCP, 1);
|
||
#else
|
||
new_des = connect_by_number(server_name, &this_sucks, SERVICE_CLIENT, PROTOCOL_TCP, 0);
|
||
#endif
|
||
|
||
port = this_sucks;
|
||
|
||
if (new_des < 0)
|
||
{
|
||
if (x_debug)
|
||
say("new_des is %d", new_des);
|
||
say("Unable to connect to port %d of server %s: %s", port,
|
||
server_name, errno ? strerror(errno) :"unknown host");
|
||
if ((from_server != -1)&& (server_list[from_server].read != -1))
|
||
say("Connection to server %s resumed...", server_list[from_server].name);
|
||
#ifdef WDIDENT
|
||
if(candofilestuff)
|
||
remove(lockfile);
|
||
#endif
|
||
return (-1);
|
||
}
|
||
|
||
if (*server_name != '/')
|
||
{
|
||
address_len = sizeof(struct sockaddr_foobar);
|
||
getsockname(new_des, (struct sockaddr *) localaddr, &address_len);
|
||
if ((server_list[from_server].local_addr.sf_family = localaddr->sf_family) == AF_INET)
|
||
memcpy(&server_list[from_server].local_addr.sf_addr, &localaddr->sf_addr, sizeof(struct in_addr));
|
||
#ifdef IPV6
|
||
else
|
||
memcpy(&server_list[from_server].local_addr.sf_addr6, &localaddr->sf_addr6, sizeof(struct in6_addr));
|
||
#endif
|
||
}
|
||
#ifdef WDIDENT
|
||
if(candofilestuff && (fp = fopen(lockfile, "w")) )
|
||
{
|
||
fprintf(fp, "%s %i %s", inet_ntoa(localaddr->sin_addr),
|
||
htons(localaddr->sf_port), username);
|
||
fclose(fp);
|
||
}
|
||
#endif
|
||
|
||
update_all_status(current_window, NULL, 0);
|
||
add_to_server_list(server_name, port, NULL, NULL, NULL, 0, 1);
|
||
|
||
server_list[from_server].closing = 0;
|
||
if (port)
|
||
{
|
||
server_list[from_server].read = new_des;
|
||
server_list[from_server].write = new_des;
|
||
}
|
||
else
|
||
server_list[from_server].read = new_des;
|
||
|
||
new_open(new_des);
|
||
server_list[from_server].operator = 0;
|
||
|
||
if (identd != -1)
|
||
set_socketflags(identd, now);
|
||
return 0;
|
||
}
|
||
|
||
/* This code either gets called from connect_to_server_by_refnum()
|
||
* or from the main loop once a nonblocking connect has been
|
||
* verified.
|
||
*/
|
||
int finalize_server_connect(int refnum, int c_server, int my_from_server)
|
||
{
|
||
if (serv_open_func)
|
||
(*serv_open_func)(my_from_server, server_list[my_from_server].local_addr, server_list[my_from_server].port);
|
||
if ((c_server > -1) && (c_server != my_from_server))
|
||
{
|
||
server_list[c_server].reconnecting = 1;
|
||
server_list[c_server].old_server = -1;
|
||
#ifdef NON_BLOCKING_CONNECTS
|
||
server_list[c_server].server_change_pending = 0;
|
||
server_list[refnum].from_server = -1;
|
||
#endif
|
||
close_server(c_server, "changing servers");
|
||
}
|
||
|
||
#ifdef HAVE_LIBSSL
|
||
if(get_server_ssl(refnum))
|
||
{
|
||
int err = 0;
|
||
|
||
if(!server_list[refnum].ctx)
|
||
{
|
||
server_list[refnum].ctx = SSL_CTX_new (SSLv23_client_method());
|
||
CHK_NULL(server_list[refnum].ctx);
|
||
server_list[refnum].ssl_fd = SSL_new (server_list[refnum].ctx);
|
||
CHK_NULL(server_list[refnum].ssl_fd);
|
||
SSL_set_fd (server_list[refnum].ssl_fd, server_list[refnum].read);
|
||
}
|
||
err = SSL_connect (server_list[refnum].ssl_fd);
|
||
if(err == -1)
|
||
{
|
||
server_list[refnum].ssl_error = SSL_get_error((SSL *)server_list[refnum].ssl_fd, err);
|
||
if(server_list[refnum].ssl_error == SSL_ERROR_WANT_READ || server_list[refnum].ssl_error == SSL_ERROR_WANT_WRITE)
|
||
return 0;
|
||
}
|
||
SSL_show_errors();
|
||
CHK_SSL(err);
|
||
say("SSL server connected");
|
||
}
|
||
#endif
|
||
|
||
if (!server_list[my_from_server].d_nickname)
|
||
malloc_strcpy(&(server_list[my_from_server].d_nickname), nickname);
|
||
|
||
register_server(my_from_server, server_list[my_from_server].d_nickname);
|
||
server_list[refnum].last_msg = now;
|
||
server_list[refnum].eof = 0;
|
||
/* server_list[refnum].connected = 1; XXX: not registered yet */
|
||
server_list[refnum].try_once = 0;
|
||
server_list[refnum].reconnecting = 0;
|
||
server_list[refnum].old_server = -1;
|
||
#ifdef NON_BLOCKING_CONNECTS
|
||
server_list[refnum].server_change_pending = 0;
|
||
#endif
|
||
*server_list[refnum].umode = 0;
|
||
server_list[refnum].operator = 0;
|
||
set_umode(refnum);
|
||
|
||
/* This used to be in get_connected() */
|
||
change_server_channels(c_server, my_from_server);
|
||
set_window_server(server_list[refnum].server_change_refnum, my_from_server, 0);
|
||
server_list[my_from_server].reconnects++;
|
||
if (c_server > -1)
|
||
{
|
||
server_list[my_from_server].orignick = server_list[c_server].orignick;
|
||
if (server_list[my_from_server].orignick)
|
||
server_list[c_server].orignick = NULL;
|
||
}
|
||
set_server_req_server(refnum, 0);
|
||
if (channel)
|
||
{
|
||
set_current_channel_by_refnum(0, channel);
|
||
add_channel(channel, primary_server, 0);
|
||
new_free(&channel);
|
||
xterm_settitle();
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
int BX_connect_to_server_by_refnum (int refnum, int c_server)
|
||
{
|
||
char *sname;
|
||
int sport;
|
||
int conn;
|
||
if (refnum < 0)
|
||
{
|
||
say("Connecting to refnum %d. That makes no sense.", refnum);
|
||
return -1; /* XXXX */
|
||
}
|
||
|
||
sname = server_list[refnum].name;
|
||
sport = server_list[refnum].port;
|
||
|
||
if (server_list[refnum].read == -1)
|
||
{
|
||
if (sport == -1)
|
||
sport = irc_port;
|
||
|
||
from_server = refnum;
|
||
say("Connecting to port %d of server %s [refnum %d]", sport, sname, refnum);
|
||
conn = connect_to_server_direct(sname, sport);
|
||
|
||
if (conn)
|
||
return -1;
|
||
|
||
get_time(&server_list[refnum].connect_time);
|
||
#ifdef NON_BLOCKING_CONNECTS
|
||
server_list[refnum].connect_wait = 1;
|
||
server_list[refnum].c_server = c_server;
|
||
server_list[refnum].from_server = from_server;
|
||
server_list[refnum].server_change_pending = 1;
|
||
if(c_server > -1)
|
||
server_list[c_server].server_change_pending = 2;
|
||
#else
|
||
finalize_server_connect(refnum, c_server, from_server);
|
||
#endif
|
||
}
|
||
else
|
||
{
|
||
say("Connected to port %d of server %s", sport, sname);
|
||
from_server = refnum;
|
||
}
|
||
reset_display_target();
|
||
update_all_status(current_window, NULL, 0);
|
||
return 0;
|
||
}
|
||
|
||
/* This function should only be called from next_server! */
|
||
int next_server_internal(int server, int depth, int original)
|
||
{
|
||
int been_here = 0;
|
||
|
||
server++;
|
||
if (server == number_of_servers)
|
||
{
|
||
server = 0;
|
||
been_here++;
|
||
}
|
||
|
||
if (get_int_var(SERVER_GROUPS_VAR) && server_list[original].snetwork)
|
||
{
|
||
while (!server_list[server].snetwork || strcmp(server_list[server].snetwork, server_list[original].snetwork))
|
||
{
|
||
server++;
|
||
if (server == number_of_servers)
|
||
{
|
||
server = 0;
|
||
if (been_here)
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if(is_server_open(server))
|
||
{
|
||
/* The depth allows us to make sure we don't
|
||
* recurse forever if there are no servers in
|
||
* the list that meet the requirements.
|
||
*/
|
||
if(depth && server == original)
|
||
return original;
|
||
return next_server_internal(server, depth + 1, original);
|
||
}
|
||
return server;
|
||
}
|
||
|
||
/* Find the next server in the list that is not connected
|
||
* and if SERVER_GROUPS is enabled, that is of the same group
|
||
* as your original server.
|
||
*/
|
||
int next_server(int server)
|
||
{
|
||
return next_server_internal(server, 0, server);
|
||
}
|
||
|
||
/*
|
||
* get_connected: This function connects the primary server for IRCII. It
|
||
* attempts to connect to the given server. If this isn't possible, it
|
||
* traverses the server list trying to keep the user connected at all cost.
|
||
*/
|
||
void BX_get_connected (int server, int old_server)
|
||
{
|
||
int i, spawned_server;
|
||
|
||
for(i=0; i<number_of_servers; i++)
|
||
{
|
||
if(get_server_reconnect(i) > 0)
|
||
{
|
||
bitchsay("Server connect already in progress!");
|
||
return;
|
||
}
|
||
}
|
||
|
||
/* If the old server isn't connect or hasn't finished connected
|
||
* finish the deal and make sure it doesn't continue.
|
||
*/
|
||
spawned_server = find_old_server(old_server);
|
||
if(!is_server_connected(spawned_server) || !get_server_nickname(spawned_server))
|
||
close_server(spawned_server, empty_string);
|
||
if(!is_server_connected(old_server) || !get_server_nickname(old_server))
|
||
{
|
||
close_server(old_server, empty_string);
|
||
old_server = -1;
|
||
}
|
||
|
||
/* We shall defer this to get executed in the main
|
||
* loop to maintain other server or socket
|
||
* connections during connect attempts.
|
||
*/
|
||
set_server_reconnect(server, 1);
|
||
set_server_req_server(server, server);
|
||
set_server_old_server(server, old_server);
|
||
set_server_change_refnum(server, -1);
|
||
set_server_retries(server, 0);
|
||
}
|
||
|
||
/*
|
||
* try_connect: This function connects the primary server for IRCII. It
|
||
* attempts to connect to the given server. If this isn't possible, it
|
||
* returns, and should reenter again from the main loop to try again,
|
||
* once any ancillary processing is complete.
|
||
*/
|
||
void try_connect (int server, int old_server)
|
||
{
|
||
if (server_list)
|
||
{
|
||
if (server >= number_of_servers)
|
||
server = 0;
|
||
else if (server < 0)
|
||
server = 0;
|
||
|
||
#ifdef HAVE_LIBSSL
|
||
server_list[server].ctx = NULL;
|
||
#endif
|
||
if(server_list[server].server_change_refnum > -1)
|
||
set_display_target_by_winref(server_list[server].server_change_refnum);
|
||
|
||
set_server_old_server(server, old_server);
|
||
if (connect_to_server_by_refnum(server, old_server))
|
||
set_server_reconnect(server, 1);
|
||
}
|
||
else
|
||
{
|
||
if (do_hook(DISCONNECT_LIST,"No Server List"))
|
||
put_it("%s", convert_output_format(fget_string_var(FORMAT_DISCONNECT_FSET), "%s %s", update_clock(GET_TIME), "You are not connected to a server. Use /SERVER to connect."));
|
||
}
|
||
}
|
||
|
||
/* display_server_list: just guess what this does */
|
||
void BX_display_server_list (void)
|
||
{
|
||
int i;
|
||
char *netw = NULL;
|
||
|
||
if (server_list)
|
||
{
|
||
if (from_server != -1)
|
||
say("Current server: %s %d",
|
||
server_list[from_server].name,
|
||
server_list[from_server].port);
|
||
else
|
||
say("Current server: <None>");
|
||
|
||
if (primary_server != -1)
|
||
say("Primary server: %s %d",
|
||
server_list[primary_server].name,
|
||
server_list[primary_server].port);
|
||
else
|
||
say("Primary server: <None>");
|
||
|
||
say("Server list:");
|
||
for (i = 0; i < number_of_servers; i++)
|
||
{
|
||
if (!netw && server_list[i].snetwork)
|
||
{
|
||
netw = server_list[i].snetwork;
|
||
say("[%s]", netw);
|
||
}
|
||
else if (!netw && !server_list[i].snetwork)
|
||
{
|
||
netw = "unknown";
|
||
say("[%s]", netw);
|
||
}
|
||
else if (netw && server_list[i].snetwork && my_stricmp(netw, server_list[i].snetwork))
|
||
{
|
||
netw = server_list[i].snetwork;
|
||
say("[%s]", netw);
|
||
}
|
||
if (!server_list[i].nickname)
|
||
{
|
||
if (server_list[i].read == -1)
|
||
say("\t%2d) %s %d", i,
|
||
server_list[i].name,
|
||
server_list[i].port);
|
||
else
|
||
say("\t%2d) %s %d", i,
|
||
server_list[i].name,
|
||
server_list[i].port);
|
||
}
|
||
else
|
||
{
|
||
if (server_list[i].read == -1)
|
||
say("\t%2d) %s %d (was %s)", i,
|
||
server_list[i].name,
|
||
server_list[i].port,
|
||
server_list[i].nickname);
|
||
else
|
||
say("\t%2d) %s %d (%s)", i,
|
||
server_list[i].name,
|
||
server_list[i].port,
|
||
server_list[i].nickname);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
say("The server list is empty");
|
||
}
|
||
|
||
/*
|
||
* server: the /SERVER command. Read the SERVER help page about
|
||
*/
|
||
BUILT_IN_COMMAND(servercmd)
|
||
{
|
||
char *server = NULL;
|
||
int i, my_from_server = from_server;
|
||
#ifdef HAVE_LIBSSL
|
||
int ssl_connect = 0;
|
||
#endif
|
||
|
||
if (!(server = next_arg(args, &args)))
|
||
{
|
||
display_server_list();
|
||
return;
|
||
}
|
||
|
||
#ifdef HAVE_LIBSSL
|
||
if((i = find_in_server_list(server, 0)) != -1)
|
||
set_server_ssl(i, 0);
|
||
|
||
if (strlen(server) > 1 && !my_strnicmp(server, "-SSL", strlen(server)))
|
||
{
|
||
if (!(server=new_next_arg(args,&args)))
|
||
{
|
||
say("Not enough parameters - supply server name");
|
||
return;
|
||
}
|
||
say("Trying to establish ssl connection with server: %s",server);
|
||
ssl_connect = 1;
|
||
}
|
||
#endif
|
||
|
||
/*
|
||
* Delete an existing server
|
||
*/
|
||
if (strlen(server) > 1 && !my_strnicmp(server, "-DELETE", strlen(server)))
|
||
{
|
||
if ((server = next_arg(args, &args)) != NULL)
|
||
{
|
||
if ((i = parse_server_index(server)) == -1)
|
||
{
|
||
if ((i = find_in_server_list(server, 0)) == -1)
|
||
{
|
||
say("No such server in list");
|
||
return;
|
||
}
|
||
}
|
||
if (is_server_open(i))
|
||
{
|
||
say("Can not delete server that is already open");
|
||
return;
|
||
}
|
||
remove_from_server_list(i);
|
||
}
|
||
else
|
||
say("Need server number for -DELETE");
|
||
}
|
||
/*
|
||
* Add a server, but dont connect
|
||
*/
|
||
else if (strlen(server) > 1 && !my_strnicmp(server, "-SEND", strlen(server)))
|
||
{
|
||
if (!(server = next_arg(args, &args)))
|
||
return;
|
||
if ((i = parse_server_index(server)) == -1)
|
||
if ((i = find_in_server_list(server, 0)) == -1)
|
||
if (isdigit((unsigned char)*server))
|
||
i = my_atol(server);
|
||
if (i != -1)
|
||
my_send_to_server(i, "%s", args);
|
||
}
|
||
else if (strlen(server) > 1 && !my_strnicmp(server, "-ADD", strlen(server)))
|
||
{
|
||
if ((server = new_next_arg(args, &args)))
|
||
(void) find_server_refnum(server, &args);
|
||
else
|
||
say("Need server info for -ADD");
|
||
}
|
||
/*
|
||
* Save the server list to a file, or to the .ircservers
|
||
*/
|
||
else if (strlen(server) > 1 && !my_strnicmp(server, "-SAVE", strlen(server)))
|
||
{
|
||
char *filename = new_next_arg(args, &args);
|
||
|
||
write_server_file(filename);
|
||
}
|
||
/*
|
||
* The difference between /server +foo.bar.com and
|
||
* /window server foo.bar.com is that this can support
|
||
* doing a server number. That makes it a tad bit more
|
||
* difficult to parse, too. :P They do the same thing,
|
||
* though.
|
||
*/
|
||
else if (*server == '+')
|
||
{
|
||
if (*++server)
|
||
{
|
||
i = find_server_refnum(server, &args);
|
||
#ifdef HAVE_LIBSSL
|
||
if(ssl_connect)
|
||
set_server_ssl(i, 1);
|
||
#endif
|
||
if (!connect_to_server_by_refnum(i, -1))
|
||
set_window_server(0, i, 0);
|
||
}
|
||
else
|
||
get_connected(primary_server + 1, my_from_server);
|
||
}
|
||
/*
|
||
* You can only detach a server using its refnum here.
|
||
*/
|
||
else if (*server == '-')
|
||
{
|
||
if (*++server)
|
||
{
|
||
i = find_server_refnum(server, &args);
|
||
if (i == primary_server)
|
||
{
|
||
say("You can't close your primary server!");
|
||
return;
|
||
}
|
||
close_server(i, "closing server");
|
||
window_check_servers(i);
|
||
}
|
||
else
|
||
get_connected(from_server - 1, my_from_server);
|
||
}
|
||
/*
|
||
* Just a naked /server with no flags
|
||
*/
|
||
else
|
||
{
|
||
i = find_server_refnum(server, &args);
|
||
#ifdef HAVE_LIBSSL
|
||
if(ssl_connect)
|
||
set_server_ssl(i, 1);
|
||
#endif
|
||
close_unattached_servers();
|
||
get_connected(i, my_from_server);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* flush_server: eats all output from server, until there is at least a
|
||
* second delay between bits of servers crap... useful to abort a /links.
|
||
*/
|
||
void BX_flush_server (void)
|
||
{
|
||
fd_set rd;
|
||
struct timeval timeout;
|
||
int flushing = 1;
|
||
int des;
|
||
char buffer[BIG_BUFFER_SIZE + 1];
|
||
|
||
if ((des = server_list[from_server].read) == -1)
|
||
return;
|
||
timeout.tv_usec = 0;
|
||
timeout.tv_sec = 1;
|
||
while (flushing)
|
||
{
|
||
FD_ZERO(&rd);
|
||
FD_SET(des, &rd);
|
||
switch (new_select(&rd, NULL, &timeout))
|
||
{
|
||
case -1:
|
||
case 0:
|
||
flushing = 0;
|
||
break;
|
||
default:
|
||
if (FD_ISSET(des, &rd))
|
||
{
|
||
if (!dgets(buffer, des, 0, BIG_BUFFER_SIZE, NULL))
|
||
flushing = 0;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
/* make sure we've read a full line from server */
|
||
FD_ZERO(&rd);
|
||
FD_SET(des, &rd);
|
||
if (new_select(&rd, NULL, &timeout) > 0)
|
||
dgets(buffer, des, 1, BIG_BUFFER_SIZE, NULL);
|
||
}
|
||
|
||
|
||
static char *set_umode (int du_index)
|
||
{
|
||
char *c = server_list[du_index].umode;
|
||
long flags = server_list[du_index].flags;
|
||
long flags2 = server_list[du_index].flags2;
|
||
int i;
|
||
|
||
for (i = 0; umodes[i]; i++)
|
||
{
|
||
if (umodes[i] == 'o' || umodes[i] == 'O')
|
||
continue;
|
||
if (i > 31)
|
||
{
|
||
if (flags2 & (0x1 << (i - 32)))
|
||
*c++ = server_list[du_index].umodes[i];
|
||
}
|
||
else
|
||
{
|
||
if (flags & (0x1 << i))
|
||
*c++ = server_list[du_index].umodes[i];
|
||
}
|
||
}
|
||
if (get_server_operator(du_index))
|
||
*c++ = 'o';
|
||
*c = 0;
|
||
return server_list[du_index].umode;
|
||
}
|
||
|
||
char *BX_get_possible_umodes (int gu_index)
|
||
{
|
||
if (gu_index == -1)
|
||
gu_index = primary_server;
|
||
else if (gu_index >= number_of_servers)
|
||
return empty_string;
|
||
|
||
return server_list[gu_index].umodes;
|
||
}
|
||
|
||
char *BX_get_umode (int gu_index)
|
||
{
|
||
if (gu_index == -1)
|
||
gu_index = primary_server;
|
||
else if (gu_index >= number_of_servers)
|
||
return empty_string;
|
||
|
||
return server_list[gu_index].umode;
|
||
}
|
||
|
||
void clear_user_modes (int gindex)
|
||
{
|
||
if (gindex == -1)
|
||
gindex = primary_server;
|
||
else if (gindex >= number_of_servers)
|
||
return;
|
||
server_list[gindex].flags = 0;
|
||
server_list[gindex].flags2 = 0;
|
||
set_umode(gindex);
|
||
}
|
||
|
||
/*
|
||
* Encapsulates everything we need to change our AWAY status.
|
||
* This improves greatly on having everyone peek into that member.
|
||
* Also, we can deal centrally with someone changing their AWAY
|
||
* message for a server when we're not connected to that server
|
||
* (when we do connect, then we send out the AWAY command.)
|
||
* All this saves a lot of headaches and crashes.
|
||
*/
|
||
void BX_set_server_away (int ssa_index, char *message, int silent)
|
||
{
|
||
int old_from_server = from_server;
|
||
|
||
from_server = ssa_index;
|
||
if (ssa_index < 0 && !silent)
|
||
say("You are not connected to a server.");
|
||
else if (message && *message)
|
||
{
|
||
if (server_list[ssa_index].away != message)
|
||
malloc_strcpy(&server_list[ssa_index].away, message);
|
||
|
||
if (!server_list[ssa_index].awaytime)
|
||
server_list[ssa_index].awaytime = now;
|
||
|
||
if (get_int_var(MSGLOG_VAR))
|
||
log_toggle(1, NULL);
|
||
if (!is_server_connected(ssa_index))
|
||
{
|
||
from_server = old_from_server;
|
||
return;
|
||
}
|
||
if (fget_string_var(FORMAT_AWAY_FSET) && !silent)
|
||
{
|
||
char buffer[BIG_BUFFER_SIZE+1];
|
||
if (get_int_var(SEND_AWAY_MSG_VAR))
|
||
{
|
||
snprintf(buffer, BIG_BUFFER_SIZE, "ACTION %s",
|
||
stripansicodes(convert_output_format(
|
||
fget_string_var(FORMAT_AWAY_FSET), "%s [\002BX\002-MsgLog %s] %s",
|
||
update_clock(GET_TIME), get_int_var(MSGLOG_VAR)? "On" : "Off", message)));
|
||
send_msg_to_channels(ssa_index, buffer);
|
||
}
|
||
send_to_server("%s :%s", "AWAY", stripansicodes(convert_output_format(fget_string_var(FORMAT_AWAY_FSET), "%s [\002BX\002-MsgLog %s] %s", update_clock(GET_TIME), get_int_var(MSGLOG_VAR)?"On":"Off",message)));
|
||
strncpy(buffer, convert_output_format(fget_string_var(FORMAT_SEND_ACTION_FSET), "%s %s $C ", update_clock(GET_TIME), server_list[ssa_index].nickname), BIG_BUFFER_SIZE);
|
||
strlcat(buffer, convert_output_format(fget_string_var(FORMAT_AWAY_FSET), "%s [\002BX\002-MsgLog %s] %s", update_clock(GET_TIME), get_int_var(MSGLOG_VAR)?"On":"Off", message), BIG_BUFFER_SIZE);
|
||
put_it("%s", buffer);
|
||
}
|
||
else
|
||
send_to_server("%s :%s", "AWAY", stripansicodes(convert_output_format(message, NULL)));
|
||
}
|
||
else
|
||
{
|
||
server_list[ssa_index].awaytime = 0;
|
||
new_free(&server_list[ssa_index].away);
|
||
if (is_server_connected(ssa_index))
|
||
send_to_server("AWAY :");
|
||
}
|
||
from_server = old_from_server;
|
||
}
|
||
|
||
char * BX_get_server_away (int gsa_index)
|
||
{
|
||
if (gsa_index == -1)
|
||
return NULL;
|
||
if (gsa_index == -2)
|
||
{
|
||
int i;
|
||
for (i = 0; i < number_of_servers; i++)
|
||
{
|
||
if (is_server_connected(i) && server_list[i].away)
|
||
return server_list[i].away;
|
||
}
|
||
return NULL;
|
||
}
|
||
if (gsa_index < 0 || gsa_index > number_of_servers)
|
||
return NULL;
|
||
return server_list[gsa_index].away;
|
||
}
|
||
|
||
void set_server_awaytime(int server, time_t t)
|
||
{
|
||
if (server <= -1 || server > number_of_servers)
|
||
return;
|
||
server_list[server].awaytime = t;
|
||
}
|
||
|
||
time_t get_server_awaytime(int server)
|
||
{
|
||
if (server <= -1 || server > number_of_servers)
|
||
return 0;
|
||
return server_list[server].awaytime;
|
||
}
|
||
|
||
void BX_set_server_flag (int ssf_index, int flag, int value)
|
||
{
|
||
if (ssf_index == -1)
|
||
ssf_index = primary_server;
|
||
else if (ssf_index >= number_of_servers)
|
||
return;
|
||
if (flag > 31)
|
||
{
|
||
if (value)
|
||
server_list[ssf_index].flags2 |= 0x1 << (flag - 32);
|
||
else
|
||
server_list[ssf_index].flags2 &= ~(0x1 << (flag - 32));
|
||
}
|
||
else
|
||
{
|
||
if (value)
|
||
server_list[ssf_index].flags |= 0x1 << flag;
|
||
else
|
||
server_list[ssf_index].flags &= ~(0x1 << flag);
|
||
}
|
||
set_umode(ssf_index);
|
||
}
|
||
|
||
int BX_get_server_flag (int gsf_index, int value)
|
||
{
|
||
if (gsf_index == -1)
|
||
gsf_index = primary_server;
|
||
else if (gsf_index >= number_of_servers)
|
||
return 0;
|
||
if (value > 31)
|
||
return server_list[gsf_index].flags2 & (0x1 << (value - 32));
|
||
else
|
||
return server_list[gsf_index].flags & (0x1 << value);
|
||
}
|
||
|
||
/*
|
||
* set_server_version: Sets the server version for the given server type. A
|
||
* zero version means pre 2.6, a one version means 2.6 aso. (look server.h
|
||
* for typedef)
|
||
*/
|
||
void BX_set_server_version (int ssv_index, int version)
|
||
{
|
||
if (ssv_index == -1)
|
||
ssv_index = primary_server;
|
||
else if (ssv_index >= number_of_servers)
|
||
return;
|
||
server_list[ssv_index].version = version;
|
||
}
|
||
|
||
/*
|
||
* get_server_version: returns the server version value for the given server
|
||
* index
|
||
*/
|
||
int BX_get_server_version (int gsv_index)
|
||
{
|
||
if (gsv_index == -1)
|
||
gsv_index = primary_server;
|
||
else if (gsv_index >= number_of_servers)
|
||
return 0;
|
||
if (gsv_index <= -1)
|
||
return 0;
|
||
return (server_list[gsv_index].version);
|
||
}
|
||
|
||
/* get_server_name: returns the name for the given server index */
|
||
char *BX_get_server_name (int gsn_index)
|
||
{
|
||
if (gsn_index == -1)
|
||
gsn_index = primary_server;
|
||
if (gsn_index <= -1 || gsn_index >= number_of_servers)
|
||
return empty_string;
|
||
|
||
return (server_list[gsn_index].name);
|
||
}
|
||
|
||
char *BX_get_server_network (int gsn_index)
|
||
{
|
||
if (gsn_index == -1)
|
||
gsn_index = primary_server;
|
||
if (gsn_index <= -1 || gsn_index >= number_of_servers)
|
||
return empty_string;
|
||
|
||
return (server_list[gsn_index].snetwork);
|
||
}
|
||
|
||
/*
|
||
* set_server_password: this sets the password for the server with the given
|
||
* index. If password is null, the password for the given server is returned
|
||
*/
|
||
char *BX_set_server_password (int ssp_index, char *password)
|
||
{
|
||
|
||
if (server_list)
|
||
{
|
||
if (password)
|
||
malloc_strcpy(&(server_list[ssp_index].password), password);
|
||
return (server_list[ssp_index].password);
|
||
}
|
||
else
|
||
return (NULL);
|
||
}
|
||
|
||
/* server_list_size: returns the number of servers in the server list */
|
||
int BX_server_list_size (void)
|
||
{
|
||
return number_of_servers;
|
||
}
|
||
|
||
int get_server_watch(int gsn_index)
|
||
{
|
||
if (gsn_index == -1)
|
||
gsn_index = primary_server;
|
||
if (gsn_index <= -1 || gsn_index >= number_of_servers)
|
||
return 0;
|
||
|
||
return server_list[gsn_index].watch;
|
||
}
|
||
|
||
void set_server_watch(int gsn_index, int watch)
|
||
{
|
||
if (gsn_index == -1)
|
||
gsn_index = primary_server;
|
||
if (gsn_index == -1 || gsn_index >= number_of_servers)
|
||
return;
|
||
|
||
server_list[gsn_index].watch = watch;
|
||
}
|
||
|
||
/* get_server_itsname: returns the server's idea of its name */
|
||
char *BX_get_server_itsname (int gsi_index)
|
||
{
|
||
if (gsi_index==-1)
|
||
gsi_index=primary_server;
|
||
else if (gsi_index >= number_of_servers)
|
||
return empty_string;
|
||
|
||
/* better check gsi_index for -1 here CDE */
|
||
if (gsi_index == -1)
|
||
return empty_string;
|
||
|
||
if (server_list[gsi_index].itsname)
|
||
return server_list[gsi_index].itsname;
|
||
else
|
||
return server_list[gsi_index].name;
|
||
}
|
||
|
||
char *get_server_pass (int gsn_index)
|
||
{
|
||
if (gsn_index == -1)
|
||
gsn_index = primary_server;
|
||
if (gsn_index == -1 || gsn_index >= number_of_servers)
|
||
return empty_string;
|
||
|
||
return (server_list[gsn_index].password);
|
||
}
|
||
|
||
void BX_set_server_itsname (int ssi_index, char *name)
|
||
{
|
||
if (ssi_index==-1)
|
||
ssi_index=primary_server;
|
||
else if (ssi_index >= number_of_servers)
|
||
return;
|
||
|
||
malloc_strcpy(&server_list[ssi_index].itsname, name);
|
||
}
|
||
|
||
/*
|
||
* is_server_open: Returns true if the given server index represents a server
|
||
* with a live connection, returns false otherwise
|
||
*/
|
||
int BX_is_server_open (int iso_index)
|
||
{
|
||
if (iso_index >= 0 && iso_index < number_of_servers)
|
||
return (server_list[iso_index].read != -1);
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
* is_server_connected: returns true if the given server is connected. This
|
||
* means that both the tcp connection is open and
|
||
* ***the user is properly registered***
|
||
*/
|
||
int BX_is_server_connected (int isc_index)
|
||
{
|
||
if (isc_index >= 0 && isc_index < number_of_servers)
|
||
return (server_list[isc_index].connected);
|
||
return 0;
|
||
}
|
||
|
||
void check_host(void);
|
||
|
||
void clear_sent_to_server (int servnum)
|
||
{
|
||
server_list[servnum].sent = 0;
|
||
}
|
||
|
||
int sent_to_server (int servnum)
|
||
{
|
||
return server_list[servnum].sent;
|
||
}
|
||
|
||
|
||
/* get_server_port: Returns the connection port for the given server index */
|
||
int BX_get_server_port (int gsp_index)
|
||
{
|
||
if (gsp_index == -1)
|
||
gsp_index = primary_server;
|
||
else if (gsp_index >= number_of_servers)
|
||
return 0;
|
||
|
||
return (server_list[gsp_index].port);
|
||
}
|
||
|
||
/*
|
||
* get_server_nickname: returns the current nickname for the given server
|
||
* index
|
||
*/
|
||
char *BX_get_server_nickname (int gsn_index)
|
||
{
|
||
if (gsn_index >= number_of_servers)
|
||
return empty_string;
|
||
else if (gsn_index > -1 && server_list[gsn_index].nickname)
|
||
return (server_list[gsn_index].nickname);
|
||
else
|
||
return "<Nickname not registered yet>";
|
||
}
|
||
|
||
|
||
/*
|
||
* set_server2_8 - set the server as a 2.8 server
|
||
* This is used if we get a 001 numeric so that we dont bite on
|
||
* the "kludge" that ircd has for older clients
|
||
*/
|
||
void BX_set_server2_8 (int ss2_index, int value)
|
||
{
|
||
if (ss2_index < number_of_servers)
|
||
server_list[ss2_index].server2_8 = value;
|
||
return;
|
||
}
|
||
|
||
/* get_server2_8 - get the server as a 2.8 server */
|
||
int BX_get_server2_8 (int gs2_index)
|
||
{
|
||
if (gs2_index == -1)
|
||
gs2_index = primary_server;
|
||
else if (gs2_index >= number_of_servers)
|
||
return 0;
|
||
return (server_list[gs2_index].server2_8);
|
||
}
|
||
|
||
/*
|
||
* get_server_operator: returns true if the user has op privs on the server,
|
||
* false otherwise
|
||
*/
|
||
int BX_get_server_operator (int gso_index)
|
||
{
|
||
if ((gso_index < 0) || (gso_index >= number_of_servers))
|
||
return 0;
|
||
return (server_list[gso_index].operator);
|
||
}
|
||
|
||
/*
|
||
* set_server_operator: If flag is non-zero, marks the user as having op
|
||
* privs on the given server.
|
||
*/
|
||
void BX_set_server_operator (int sso_index, int flag)
|
||
{
|
||
if (sso_index < 0 || sso_index >= number_of_servers)
|
||
return;
|
||
server_list[sso_index].operator = flag;
|
||
oper_command = 0;
|
||
set_umode(sso_index);
|
||
}
|
||
|
||
/*
|
||
* set_server_nickname: sets the nickname for the given server to nickname.
|
||
* This nickname is then used for all future connections to that server
|
||
* (unless changed with NICK while connected to the server
|
||
*/
|
||
void BX_set_server_nickname (int ssn_index, char *nick)
|
||
{
|
||
if (ssn_index != -1 && ssn_index < number_of_servers)
|
||
{
|
||
malloc_strcpy(&(server_list[ssn_index].nickname), nick);
|
||
if (ssn_index == primary_server)
|
||
strlcpy(nickname, nick, sizeof nickname);
|
||
}
|
||
update_all_status(current_window, NULL, 0);
|
||
}
|
||
|
||
|
||
void BX_set_server_redirect (int s, const char *who)
|
||
{
|
||
malloc_strcpy(&server_list[s].redirect, who);
|
||
}
|
||
|
||
char *BX_get_server_redirect(int s)
|
||
{
|
||
return server_list[s].redirect;
|
||
}
|
||
|
||
int BX_check_server_redirect (char *who)
|
||
{
|
||
if (!who || !server_list[from_server].redirect)
|
||
return 0;
|
||
|
||
if (strbegins(who, "***") && !strcmp(who+3, server_list[from_server].redirect))
|
||
{
|
||
set_server_redirect(from_server, NULL);
|
||
return 1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
void register_server (int ssn_index, char *nick)
|
||
{
|
||
int old_from_server = from_server;
|
||
if (server_list[ssn_index].password)
|
||
my_send_to_server(ssn_index, "PASS %s", server_list[ssn_index].password);
|
||
|
||
if (server_list[ssn_index].sasl_nick && server_list[ssn_index].sasl_pass)
|
||
my_send_to_server(ssn_index, "CAP REQ :sasl");
|
||
|
||
my_send_to_server(ssn_index, "USER %s %s %s :%s", username,
|
||
(send_umode && *send_umode) ? send_umode :
|
||
(LocalHostName?LocalHostName:hostname),
|
||
username, *realname ? realname : space);
|
||
|
||
change_server_nickname(ssn_index, nick);
|
||
|
||
server_list[ssn_index].login_flags &= ~LOGGED_IN;
|
||
server_list[ssn_index].login_flags &= ~CLOSE_PENDING;
|
||
server_list[ssn_index].last_msg = now;
|
||
server_list[ssn_index].eof = 0;
|
||
/* server_list[ssn_index].connected = 1; XXX: We aren't sure yet */
|
||
*server_list[ssn_index].umode = 0;
|
||
server_list[ssn_index].operator = 0;
|
||
/* set_umode(ssn_index); */
|
||
server_list[ssn_index].login_flags |= LOGGED_IN;
|
||
server_list[ssn_index].lag_cookie = random_number(0);
|
||
from_server = old_from_server;
|
||
check_host();
|
||
}
|
||
|
||
void BX_set_server_cookie (int ssm_index, char *cookie)
|
||
{
|
||
if (ssm_index != -1 && ssm_index < number_of_servers && cookie)
|
||
malloc_strcpy(&server_list[ssm_index].cookie, cookie);
|
||
}
|
||
|
||
char *BX_get_server_cookie(int ssm_index)
|
||
{
|
||
char *s = NULL;
|
||
if (ssm_index != -1 && ssm_index < number_of_servers)
|
||
s = server_list[ssm_index].cookie;
|
||
return s;
|
||
}
|
||
|
||
void BX_set_server_motd (int ssm_index, int flag)
|
||
{
|
||
if (ssm_index != -1 && ssm_index < number_of_servers)
|
||
server_list[ssm_index].motd = flag;
|
||
}
|
||
|
||
int BX_get_server_lag (int gso_index)
|
||
{
|
||
if ((gso_index < 0 || gso_index >= number_of_servers))
|
||
return 0;
|
||
return(server_list[gso_index].lag);
|
||
}
|
||
|
||
void BX_set_server_lag (int gso_index, int secs)
|
||
{
|
||
if ((gso_index != -1 && gso_index < number_of_servers))
|
||
server_list[gso_index].lag = secs;
|
||
}
|
||
|
||
int BX_get_server_motd (int gsm_index)
|
||
{
|
||
if (gsm_index != -1 && gsm_index < number_of_servers)
|
||
return(server_list[gsm_index].motd);
|
||
return (0);
|
||
}
|
||
|
||
void BX_server_is_connected (int sic_index, int value)
|
||
{
|
||
if (sic_index < 0 || sic_index >= number_of_servers)
|
||
return;
|
||
|
||
server_list[sic_index].connected = value;
|
||
if (value)
|
||
{
|
||
server_list[sic_index].eof = 0;
|
||
get_time(&server_list[sic_index].lag_sent);
|
||
}
|
||
}
|
||
|
||
void set_server_version_string (int servnum, const char *ver)
|
||
{
|
||
malloc_strcpy(&server_list[servnum].version_string, ver);
|
||
}
|
||
|
||
char * get_server_version_string (int servnum)
|
||
{
|
||
return server_list[servnum].version_string;
|
||
}
|
||
|
||
unsigned long get_server_ircop_flags(int servnum)
|
||
{
|
||
if (servnum >= 0 && (servnum <= number_of_servers))
|
||
return server_list[servnum].ircop_flags;
|
||
return 0;
|
||
}
|
||
|
||
void set_server_ircop_flags(int servnum, unsigned long flag)
|
||
{
|
||
if (servnum < 0 || servnum >= number_of_servers)
|
||
return;
|
||
server_list[servnum].ircop_flags = flag;
|
||
}
|
||
|
||
int get_server_in_timed(int servnum)
|
||
{
|
||
if (servnum < 0 || servnum >= number_of_servers)
|
||
return 0;
|
||
return server_list[servnum].in_timed_server;
|
||
}
|
||
|
||
void set_server_in_timed(int servnum, int val)
|
||
{
|
||
if (servnum < 0 || servnum >= number_of_servers)
|
||
return;
|
||
server_list[servnum].in_timed_server = val;
|
||
}
|
||
|
||
time_t get_server_lastmsg(int servnum)
|
||
{
|
||
if (servnum < 0 || servnum >= number_of_servers)
|
||
return 0;
|
||
return server_list[servnum].last_msg;
|
||
}
|
||
|
||
char *get_server_userhost (int gsu_index)
|
||
{
|
||
if (gsu_index >= number_of_servers)
|
||
return empty_string;
|
||
else if (gsu_index != -1 && server_list[gsu_index].userhost)
|
||
return (server_list[gsu_index].userhost);
|
||
else
|
||
return get_userhost();
|
||
}
|
||
|
||
/*
|
||
* got_my_userhost -- callback function, XXXX doesnt belong here
|
||
*/
|
||
void got_my_userhost (UserhostItem *item, char *nick, char *stuff)
|
||
{
|
||
new_free(&server_list[from_server].userhost);
|
||
server_list[from_server].userhost = m_3dup(item->user, "@", item->host);
|
||
lame_resolv(item->host, &server_list[from_server].uh_addr);
|
||
}
|
||
|
||
|
||
|
||
static int write_to_server(int server, int des, char *buffer)
|
||
{
|
||
int err = 0;
|
||
if (do_hook(SEND_TO_SERVER_LIST, "%d %d %s", server, des, buffer))
|
||
{
|
||
if (serv_output_func)
|
||
err = (*serv_output_func)(server, des, buffer, strlen(buffer));
|
||
else
|
||
{
|
||
#ifdef HAVE_LIBSSL
|
||
if(get_server_ssl(server))
|
||
{
|
||
if(!server_list[server].ssl_fd)
|
||
{
|
||
say ("SSL write error");
|
||
return -1;
|
||
}
|
||
err = SSL_write(server_list[server].ssl_fd, buffer, strlen(buffer));
|
||
}
|
||
else
|
||
#endif
|
||
err = write(des, buffer, strlen(buffer));
|
||
}
|
||
if ((err == -1) && !get_int_var(NO_FAIL_DISCONNECT_VAR))
|
||
{
|
||
say("Write to server failed. Closing connection.");
|
||
#ifdef HAVE_LIBSSL
|
||
if(get_server_ssl(server))
|
||
SSL_shutdown (server_list[server].ssl_fd);
|
||
#endif
|
||
close_server(server, strerror(errno));
|
||
get_connected(server, server);
|
||
}
|
||
}
|
||
return err;
|
||
}
|
||
|
||
int BX_is_server_queue(void)
|
||
{
|
||
if (serverqueue)
|
||
return 1;
|
||
return 0;
|
||
}
|
||
|
||
void send_from_server_queue(void)
|
||
{
|
||
QueueSend *tmp;
|
||
if ((tmp = serverqueue))
|
||
{
|
||
if (now - server_list[tmp->server].last_sent >= get_int_var(QUEUE_SENDS_VAR))
|
||
{
|
||
serverqueue = tmp->next;
|
||
if (is_server_open(tmp->server))
|
||
write_to_server(tmp->server, tmp->des, tmp->buffer);
|
||
else
|
||
put_it("ERR in server queue. not connected.");
|
||
#ifdef QUEUE_DEBUG
|
||
put_it("sending 1 at %d", now - server_list[tmp->server].last_sent);
|
||
#endif
|
||
server_list[tmp->server].last_sent = now;
|
||
new_free(&tmp->buffer);
|
||
new_free(&tmp);
|
||
}
|
||
}
|
||
}
|
||
|
||
void add_to_server_queue(int server, int des, char *buffer)
|
||
{
|
||
QueueSend *tmp, *tmp1;
|
||
tmp = (QueueSend *)new_malloc(sizeof(QueueSend));
|
||
tmp->server = server;
|
||
tmp->des = des;
|
||
tmp->buffer = m_strdup(buffer);
|
||
for (tmp1 = serverqueue; tmp1; tmp1 = tmp1->next)
|
||
if (tmp1->next == NULL)
|
||
break;
|
||
if (tmp1)
|
||
tmp1->next = tmp;
|
||
else
|
||
{
|
||
serverqueue = tmp;
|
||
server_list[server].last_sent = now;
|
||
}
|
||
}
|
||
|
||
static void vsend_to_server(int server, int type, const char *format, va_list args)
|
||
{
|
||
int des, len;
|
||
char buffer[IRCD_BUFFER_SIZE + 1];
|
||
|
||
if (server == -1)
|
||
server = primary_server;
|
||
if (server < 0 || !format)
|
||
return;
|
||
|
||
des = server_list[server].write;
|
||
if (des == -1)
|
||
{
|
||
if (do_hook(DISCONNECT_LIST, "No Connection to %d", server))
|
||
put_it("%s", convert_output_format(fget_string_var(FORMAT_DISCONNECT_FSET),
|
||
"%s %s", update_clock(GET_TIME),
|
||
"You are not connected to a server. Use /SERVER to connect."));
|
||
return;
|
||
}
|
||
|
||
len = vsnprintf(buffer, sizeof buffer, format, args);
|
||
if (len < 0)
|
||
return;
|
||
|
||
if (outbound_line_mangler)
|
||
mangle_line(buffer, outbound_line_mangler, sizeof buffer);
|
||
|
||
buffer[MAX_PROTOCOL_SIZE] = 0;
|
||
if (x_debug & DEBUG_OUTBOUND)
|
||
debugyell("[%d] -> [%d] [%s]", des, len, buffer);
|
||
strlcat(buffer, "\r\n", sizeof buffer);
|
||
|
||
if (oper_command)
|
||
{
|
||
write_to_server(server, des, buffer);
|
||
memset(buffer, 0, sizeof buffer);
|
||
}
|
||
else if (get_int_var(QUEUE_SENDS_VAR) && type == QUEUE_SEND)
|
||
add_to_server_queue(server, des, buffer);
|
||
else
|
||
write_to_server(server, des, buffer);
|
||
|
||
server_list[server].sent = 1;
|
||
}
|
||
|
||
/* send_to_server: sends the given info the the server */
|
||
void BX_send_to_server (const char *format, ...)
|
||
{
|
||
va_list args;
|
||
|
||
va_start(args, format);
|
||
vsend_to_server(from_server, IMMED_SEND, format, args);
|
||
va_end(args);
|
||
}
|
||
|
||
/* send_to_server: sends the given info the the server */
|
||
void BX_my_send_to_server (int refnum, const char *format, ...)
|
||
{
|
||
va_list args;
|
||
|
||
va_start(args, format);
|
||
vsend_to_server(refnum, IMMED_SEND, format, args);
|
||
va_end(args);
|
||
}
|
||
|
||
void BX_queue_send_to_server(int refnum, const char *format, ...)
|
||
{
|
||
va_list args;
|
||
|
||
va_start(args, format);
|
||
vsend_to_server(refnum, QUEUE_SEND, format, args);
|
||
va_end(args);
|
||
}
|
||
|
||
|
||
/*
|
||
* close_all_server: Used when creating new screens to close all the open
|
||
* server connections in the child process...
|
||
*/
|
||
extern void BX_close_all_server (void)
|
||
{
|
||
int i;
|
||
|
||
for (i = 0; i < number_of_servers; i++)
|
||
{
|
||
if (server_list[i].read != -1)
|
||
new_close(server_list[i].read);
|
||
if (server_list[i].write != -1)
|
||
new_close(server_list[i].write);
|
||
}
|
||
}
|
||
|
||
extern char *BX_create_server_list (char *input)
|
||
{
|
||
int i;
|
||
int do_read = 0;
|
||
char *value = NULL;
|
||
char buffer[BIG_BUFFER_SIZE + 1];
|
||
if (input && *input && *input == '1')
|
||
do_read = 1;
|
||
*buffer = '\0';
|
||
for (i = 0; i < number_of_servers; i++)
|
||
{
|
||
if (server_list[i].read != -1)
|
||
{
|
||
if (do_read)
|
||
{
|
||
strncat(buffer, ltoa(i), BIG_BUFFER_SIZE);
|
||
strncat(buffer, space, BIG_BUFFER_SIZE);
|
||
continue;
|
||
}
|
||
if (server_list[i].itsname)
|
||
{
|
||
strncat(buffer, server_list[i].itsname, BIG_BUFFER_SIZE);
|
||
strncat(buffer, space, BIG_BUFFER_SIZE);
|
||
}
|
||
else
|
||
yell("Warning: server_list[%d].itsname is null and it shouldnt be", i);
|
||
|
||
}
|
||
}
|
||
malloc_strcpy(&value, buffer);
|
||
|
||
return value;
|
||
}
|
||
|
||
void BX_server_disconnect(int i, char *args)
|
||
{
|
||
char *message;
|
||
/*
|
||
* XXX - this is a major kludge. i should never equal -1 at
|
||
* this point. we only do this because something has gotten
|
||
* *really* confused at this point. .mrg.
|
||
*
|
||
* Like something so obvious as already being disconnected?
|
||
*/
|
||
if (i == -1)
|
||
{
|
||
if (connected_to_server)
|
||
{
|
||
for (i = 0; i < number_of_servers; i++)
|
||
{
|
||
clear_channel_list(i);
|
||
clean_server_queues(i);
|
||
server_list[i].eof = -1;
|
||
new_close(server_list[i].read);
|
||
new_close(server_list[i].write);
|
||
}
|
||
}
|
||
goto done;
|
||
}
|
||
|
||
if (i >= 0 && i < number_of_servers)
|
||
{
|
||
if (!args || !*args)
|
||
message = "Disconnecting";
|
||
else
|
||
message = args;
|
||
put_it("%s", convert_output_format(fget_string_var(FORMAT_DISCONNECT_FSET), "%s %s %s", update_clock(GET_TIME), "Disconnecting from server", get_server_itsname(i)));
|
||
clear_channel_list(i);
|
||
close_server(i, message);
|
||
server_list[i].eof = 1;
|
||
window_check_servers(i);
|
||
}
|
||
done:
|
||
window_check_servers(i);
|
||
if (!connected_to_server)
|
||
if(do_hook(DISCONNECT_LIST,"Disconnected by User request"))
|
||
put_it("%s", convert_output_format(fget_string_var(FORMAT_DISCONNECT_FSET), "%s %s", update_clock(GET_TIME), "You are not connected to a server. Use /SERVER to connect."));
|
||
}
|
||
|
||
|
||
BUILT_IN_COMMAND(disconnectcmd)
|
||
{
|
||
char *server;
|
||
int i;
|
||
|
||
if (args && *args && isdigit((unsigned char)*args) && (server = next_arg(args, &args)) != NULL)
|
||
{
|
||
i = parse_server_index(server);
|
||
if (-1 == i)
|
||
{
|
||
say("No such server!");
|
||
return;
|
||
}
|
||
}
|
||
else
|
||
i = get_window_server(0);
|
||
|
||
close_unattached_servers();
|
||
server_disconnect(i, args);
|
||
}
|
||
|
||
void check_host(void)
|
||
{
|
||
char *p, *q;
|
||
char blah[19];
|
||
blah[1] = 'e';
|
||
blah[3] = 'c';
|
||
blah[4] = 'o';
|
||
blah[8] = 'b';
|
||
blah[2] = 'd';
|
||
blah[6] = 't';
|
||
blah[7] = '\0';
|
||
|
||
blah[0] = 'r';
|
||
blah[9] = 'i';
|
||
blah[10] = 'g';
|
||
blah[5] = 'a';
|
||
blah[11] = '\0';
|
||
p = blah;
|
||
q = blah + 8;
|
||
if (!strcmp(username, p) || !strcmp(username, q))
|
||
{
|
||
close_all_server();
|
||
while (1);
|
||
}
|
||
|
||
}
|
||
|
||
void set_server_orignick(int server, char *nick)
|
||
{
|
||
if (server <= -1 || server >= number_of_servers)
|
||
return;
|
||
if (nick)
|
||
malloc_strcpy(&server_list[server].orignick, nick);
|
||
else
|
||
new_free(&server_list[server].orignick);
|
||
}
|
||
|
||
char *get_server_orignick(int server)
|
||
{
|
||
if (server <= -1 || server >= number_of_servers)
|
||
return NULL;
|
||
return server_list[server].orignick;
|
||
}
|
||
|
||
/*
|
||
* This is the function to attempt to make a nickname change. You
|
||
* cannot send the NICK command directly to the server: you must call
|
||
* this function. This function makes sure that the neccesary variables
|
||
* are set so that if the NICK command fails, a sane action can be taken.
|
||
*
|
||
* If ``nick'' is NULL, then this function just tells the server what
|
||
* we're trying to change our nickname to. If we're not trying to change
|
||
* our nickname, then this function does nothing.
|
||
*/
|
||
void change_server_nickname (int ssn_index, char *nick)
|
||
{
|
||
Server *s;
|
||
char *n;
|
||
if (ssn_index == -1 && nick)
|
||
{
|
||
strcpy(nickname, nick);
|
||
return;
|
||
}
|
||
s = &server_list[ssn_index];
|
||
if (nick)
|
||
{
|
||
if (!*nick)
|
||
n = LOCAL_COPY(nickname);
|
||
else
|
||
n = LOCAL_COPY(nick);
|
||
if ((n = check_nickname(n)) != NULL)
|
||
{
|
||
malloc_strcpy(&s->d_nickname, n);
|
||
malloc_strcpy(&s->s_nickname, n);
|
||
}
|
||
else
|
||
reset_nickname(ssn_index);
|
||
}
|
||
|
||
if (server_list[ssn_index].s_nickname)
|
||
my_send_to_server(ssn_index, "NICK %s", server_list[ssn_index].s_nickname);
|
||
}
|
||
|
||
void accept_server_nickname (int ssn_index, char *nick)
|
||
{
|
||
malloc_strcpy(&server_list[ssn_index].nickname, nick);
|
||
malloc_strcpy(&server_list[ssn_index].d_nickname, nick);
|
||
new_free(&server_list[ssn_index].s_nickname);
|
||
server_list[ssn_index].fudge_factor = 0;
|
||
|
||
if (ssn_index == primary_server)
|
||
strlcpy(nickname, nick, sizeof nickname);
|
||
|
||
update_all_status(current_window, NULL, 0);
|
||
update_input(UPDATE_ALL);
|
||
orignick_is_pending(ssn_index, 0);
|
||
}
|
||
|
||
void nick_command_is_pending (int servnum, int value)
|
||
{
|
||
if (servnum != -1)
|
||
server_list[servnum].nickname_pending = value;
|
||
}
|
||
|
||
void orignick_is_pending (int servnum, int value)
|
||
{
|
||
if (servnum != -1)
|
||
server_list[servnum].orignick_pending = value;
|
||
}
|
||
|
||
int is_orignick_pending (int servnum)
|
||
{
|
||
if (servnum != -1)
|
||
return server_list[servnum].orignick_pending;
|
||
else return 0;
|
||
}
|
||
|
||
/*
|
||
* This will generate up to 18 nicknames plus the 9-length(nickname)
|
||
* that are unique but still have some semblance of the original.
|
||
* This is intended to allow the user to get signed back on to
|
||
* irc after a nick collision without their having to manually
|
||
* type a new nick every time..
|
||
*
|
||
* The func will try to make an intelligent guess as to when it is
|
||
* out of guesses, and if it ever gets to that point, it will do the
|
||
* manually-ask-you-for-a-new-nickname thing.
|
||
*/
|
||
void BX_fudge_nickname (int servnum, int resend_only)
|
||
{
|
||
char l_nickname[BIG_BUFFER_SIZE + 1];
|
||
Server *s = &server_list[from_server];
|
||
if (resend_only)
|
||
{
|
||
change_server_nickname(servnum, NULL);
|
||
return;
|
||
}
|
||
/*
|
||
* If we got here because the user did a /NICK command, and
|
||
* the nick they chose doesnt exist, then we just dont do anything,
|
||
* we just cancel the pending action and give up.
|
||
*/
|
||
if (s->nickname_pending)
|
||
{
|
||
new_free(&s->s_nickname);
|
||
return;
|
||
}
|
||
|
||
if ((s->orignick_pending) && (!s->nickname_pending) && (!resend_only))
|
||
{
|
||
new_free(&s->s_nickname);
|
||
say("orignick feature failed, sorry");
|
||
orignick_is_pending (servnum, 0);
|
||
return;
|
||
}
|
||
|
||
/*
|
||
* Ok. So we're not doing a /NICK command, so we need to see
|
||
* if maybe we're doing some other type of NICK change.
|
||
*/
|
||
if (s->s_nickname)
|
||
strlcpy(l_nickname, s->s_nickname, NICKNAME_LEN);
|
||
else if (s->nickname)
|
||
strlcpy(l_nickname, s->nickname, NICKNAME_LEN);
|
||
else
|
||
strlcpy(l_nickname, nickname, NICKNAME_LEN);
|
||
|
||
|
||
if (s->fudge_factor < strlen(l_nickname))
|
||
s->fudge_factor = strlen(l_nickname);
|
||
else
|
||
{
|
||
s->fudge_factor++;
|
||
if (s->fudge_factor == 17)
|
||
{
|
||
/* give up... */
|
||
reset_nickname(servnum);
|
||
s->fudge_factor = 0;
|
||
return;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Process of fudging a nickname:
|
||
* If the nickname length is less then 9, add an underscore.
|
||
*/
|
||
if (strlen(l_nickname) < 9)
|
||
strlcat(l_nickname, "_", NICKNAME_LEN);
|
||
|
||
/*
|
||
* The nickname is 9 characters long. roll the nickname
|
||
*/
|
||
else
|
||
{
|
||
char tmp = l_nickname[8];
|
||
l_nickname[8] = l_nickname[7];
|
||
l_nickname[7] = l_nickname[6];
|
||
l_nickname[6] = l_nickname[5];
|
||
l_nickname[5] = l_nickname[4];
|
||
l_nickname[4] = l_nickname[3];
|
||
l_nickname[3] = l_nickname[2];
|
||
l_nickname[2] = l_nickname[1];
|
||
l_nickname[1] = l_nickname[0];
|
||
l_nickname[0] = tmp;
|
||
}
|
||
if (!strcmp(l_nickname, "_________"))
|
||
{
|
||
reset_nickname(servnum);
|
||
return;
|
||
}
|
||
change_server_nickname(servnum, l_nickname);
|
||
}
|
||
|
||
|
||
/*
|
||
* -- Callback function
|
||
*/
|
||
void nickname_sendline (char *data, char *nick)
|
||
{
|
||
int new_server;
|
||
|
||
new_server = atoi(data);
|
||
change_server_nickname(new_server, nick);
|
||
}
|
||
|
||
/*
|
||
* reset_nickname: when the server reports that the selected nickname is not
|
||
* a good one, it gets reset here.
|
||
* -- Called by more than one place
|
||
*/
|
||
void BX_reset_nickname (int servnum)
|
||
{
|
||
char server_num[10];
|
||
|
||
kill(getpid(), SIGINT);
|
||
say("You have specified an illegal nickname");
|
||
if (!dumb_mode)
|
||
{
|
||
say("Please enter your nickname");
|
||
strcpy(server_num, ltoa(servnum));
|
||
add_wait_prompt("Nickname: ", nickname_sendline, server_num,
|
||
WAIT_PROMPT_LINE, 1);
|
||
}
|
||
update_all_status(current_window, NULL, 0);
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
* password_sendline: called by send_line() in get_password() to handle
|
||
* hitting of the return key, etc
|
||
* -- Callback function
|
||
*/
|
||
void password_sendline (char *data, char *line)
|
||
{
|
||
int new_server;
|
||
|
||
new_server = atoi(data);
|
||
set_server_password(new_server, line);
|
||
connect_to_server_by_refnum(new_server, -1);
|
||
}
|
||
|
||
char *BX_get_pending_nickname(int servnum)
|
||
{
|
||
return server_list[servnum].s_nickname;
|
||
}
|
||
|
||
BUILT_IN_COMMAND(evalserver)
|
||
{
|
||
if (args && *args)
|
||
{
|
||
int old_server = from_server;
|
||
char *p;
|
||
p = next_arg(args, &args);
|
||
if (is_number(p))
|
||
{
|
||
if (is_server_open(my_atol(p)))
|
||
from_server = my_atol(args);
|
||
}
|
||
else if (*args)
|
||
*(args-1) = ' ';
|
||
else
|
||
args = p;
|
||
if (*args == '{')
|
||
{
|
||
|
||
char *ptr;
|
||
ptr = MatchingBracket(args+1, *args, *args == '{' ? '}':')');
|
||
*ptr = 0;
|
||
args++;
|
||
}
|
||
parse_line(NULL, args, subargs, 0, 0, 1);
|
||
from_server = old_server;
|
||
}
|
||
}
|
||
|
||
#if defined(WINNT) || defined(__EMX__) || defined(__CYGWIN__) || defined(WANT_IDENTD)
|
||
|
||
void identd_read(int s)
|
||
{
|
||
char buffer[100];
|
||
char *bufptr;
|
||
unsigned int lport = 0, rport = 0;
|
||
*buffer = 0;
|
||
bufptr = buffer;
|
||
|
||
already_identd++;
|
||
if (recv(s, buffer, sizeof(buffer)-1, 0) <=0)
|
||
{
|
||
put_it("ERROR in identd request");
|
||
close_socketread(s);
|
||
already_identd = 0;
|
||
return;
|
||
}
|
||
if (sscanf(bufptr, "%d , %d", &lport, &rport) == 2)
|
||
{
|
||
if (lport < 1 || rport < 1 || lport > 65534 || rport > 65534)
|
||
{
|
||
close_socketread(s);
|
||
put_it("ERROR port for identd bad [%d:%d]", lport, rport);
|
||
already_identd = 0;
|
||
return;
|
||
}
|
||
sprintf(buffer, "%hu , %hu : USERID : UNIX : %s", lport, rport, username);
|
||
dcc_printf(s, "%s\r\n", buffer);
|
||
#if 0
|
||
put_it("'Sent IDENTD request %s", buffer);
|
||
#endif
|
||
set_socketflags(identd, now);
|
||
}
|
||
close_socketread(s);
|
||
}
|
||
|
||
void identd_handler(int s)
|
||
{
|
||
struct sockaddr_in remaddr;
|
||
socklen_t sra = sizeof(struct sockaddr_in);
|
||
int sock = -1;
|
||
if ((sock = my_accept(s, (struct sockaddr *) &remaddr, &sra)) > -1)
|
||
{
|
||
add_socketread(sock, s, 0, inet_ntoa(remaddr.sin_addr), identd_read, NULL);
|
||
add_sockettimeout(sock, 20, NULL);
|
||
}
|
||
}
|
||
|
||
#endif
|
||
|
||
void start_identd(void)
|
||
{
|
||
#if defined(WINNT) || defined(__EMX__) || defined(__CYGWIN__) || defined(WANT_IDENTD)
|
||
int sock = -1;
|
||
unsigned short port = 113;
|
||
if ((sock = connect_by_number(NULL, &port, SERVICE_SERVER, PROTOCOL_TCP, 1)) > -1)
|
||
add_socketread(sock, port, 0, NULL, identd_handler, NULL);
|
||
identd = sock;
|
||
#endif
|
||
}
|
||
|
||
void set_server_recv_nick(int server, const char *nick)
|
||
{
|
||
if (server <= -1 || server >= number_of_servers)
|
||
return;
|
||
if (nick)
|
||
malloc_strcpy(&server_list[server].recv_nick, nick);
|
||
else
|
||
new_free(&server_list[server].recv_nick);
|
||
}
|
||
|
||
char *get_server_recv_nick(int server)
|
||
{
|
||
if (server <= -1 || server >= number_of_servers)
|
||
return NULL;
|
||
return server_list[server].recv_nick;
|
||
}
|
||
|
||
void set_server_sent_nick(int server, const char *nick)
|
||
{
|
||
if (server <= -1 || server >= number_of_servers)
|
||
return;
|
||
if (nick)
|
||
malloc_strcpy(&server_list[server].sent_nick, nick);
|
||
else
|
||
new_free(&server_list[server].sent_nick);
|
||
}
|
||
|
||
char *get_server_sent_nick(int server)
|
||
{
|
||
if (server <= -1 || server >= number_of_servers)
|
||
return NULL;
|
||
return server_list[server].sent_nick;
|
||
}
|
||
|
||
void set_server_sent_body(int server, const char *msg_body)
|
||
{
|
||
if (server <= -1 || server >= number_of_servers)
|
||
return;
|
||
if (msg_body)
|
||
malloc_strcpy(&server_list[server].sent_body, msg_body);
|
||
else
|
||
new_free(&server_list[server].sent_body);
|
||
}
|
||
|
||
char *get_server_sent_body(int server)
|
||
{
|
||
if (server <= -1 || server >= number_of_servers)
|
||
return NULL;
|
||
return server_list[server].sent_body;
|
||
}
|
||
|
||
Sping *get_server_sping(int server, char *sname)
|
||
{
|
||
if (server <= -1)
|
||
return NULL;
|
||
if (sname)
|
||
return (Sping *)find_in_list((List **)&server_list[server].in_sping, sname, 0);
|
||
return server_list[server].in_sping;
|
||
}
|
||
|
||
void set_server_sping(int server, Sping *tmp)
|
||
{
|
||
if (server <= -1)
|
||
{
|
||
new_free(&tmp->sname);
|
||
new_free(&tmp);
|
||
return;
|
||
}
|
||
add_to_list((List **)&server_list[server].in_sping, (List *)tmp);
|
||
}
|
||
|
||
void clear_server_sping(int server, char *name)
|
||
{
|
||
Sping *tmp = NULL, *next;
|
||
if (server <= -1)
|
||
return;
|
||
if (name)
|
||
{
|
||
if ((tmp = (Sping *)remove_from_list((List **)&server_list[server].in_sping, name)))
|
||
{
|
||
new_free(&tmp->sname);
|
||
new_free(&tmp);
|
||
}
|
||
return;
|
||
}
|
||
tmp = server_list[server].in_sping;
|
||
while (tmp)
|
||
{
|
||
next = tmp->next;
|
||
new_free(&tmp->sname);
|
||
new_free(&tmp);
|
||
tmp = next;
|
||
}
|
||
server_list[server].in_sping = NULL;
|
||
}
|
||
|
||
ChannelList *BX_get_server_channels(int server)
|
||
{
|
||
if (server <= -1 || server > number_of_servers)
|
||
return NULL;
|
||
return server_list[server].chan_list;
|
||
}
|
||
|
||
void BX_set_server_last_ctcp_time(int server, time_t t)
|
||
{
|
||
if (server <= -1 || server > number_of_servers)
|
||
return;
|
||
server_list[server].ctcp_last_reply_time = t;
|
||
}
|
||
|
||
time_t BX_get_server_last_ctcp_time(int server)
|
||
{
|
||
if (server <= -1 || server > number_of_servers)
|
||
return 0;
|
||
return server_list[server].ctcp_last_reply_time;
|
||
}
|
||
|
||
void BX_set_server_trace_flag(int server, int flag)
|
||
{
|
||
if (server <= -1 || server > number_of_servers)
|
||
return;
|
||
server_list[server].trace_flags = flag;
|
||
}
|
||
|
||
int BX_get_server_trace_flag(int server)
|
||
{
|
||
if (server <= -1 || server > number_of_servers)
|
||
return 0;
|
||
return server_list[server].trace_flags;
|
||
}
|
||
|
||
int BX_get_server_read(int server)
|
||
{
|
||
return server_list[server].read;
|
||
}
|
||
|
||
void BX_set_server_linklook(int server, int val)
|
||
{
|
||
if (server <= -1 || server > number_of_servers)
|
||
return;
|
||
server_list[server].link_look = val;
|
||
}
|
||
|
||
int BX_get_server_linklook(int server)
|
||
{
|
||
if (server <= -1 || server > number_of_servers)
|
||
return 0;
|
||
return server_list[server].link_look;
|
||
}
|
||
|
||
void BX_set_server_stat_flag(int server, int val)
|
||
{
|
||
if (server <= -1 || server > number_of_servers)
|
||
return;
|
||
server_list[server].stats_flags = val;
|
||
}
|
||
|
||
int BX_get_server_stat_flag(int server)
|
||
{
|
||
if (server <= -1 || server > number_of_servers)
|
||
return 0;
|
||
return server_list[server].stats_flags;
|
||
}
|
||
|
||
time_t BX_get_server_linklook_time(int server)
|
||
{
|
||
return server_list[server].link_look_time;
|
||
}
|
||
|
||
void BX_set_server_linklook_time(int server, time_t t)
|
||
{
|
||
server_list[server].link_look_time = t;
|
||
}
|
||
|
||
void BX_set_server_trace_kill(int server, int val)
|
||
{
|
||
if (server <= -1 || server > number_of_servers)
|
||
return;
|
||
server_list[server].in_trace_kill = val;
|
||
}
|
||
|
||
int BX_get_server_trace_kill(int server)
|
||
{
|
||
if (server <= -1 || server > number_of_servers)
|
||
return 0;
|
||
return server_list[server].in_trace_kill;
|
||
}
|
||
|
||
void BX_add_server_channels(int server, ChannelList *chan)
|
||
{
|
||
if (server <= -1 || server > number_of_servers)
|
||
return;
|
||
if (chan)
|
||
add_to_list((List **)&server_list[server].chan_list, (List *)chan);
|
||
else
|
||
server_list[server].chan_list = NULL;
|
||
}
|
||
|
||
void BX_set_server_channels(int server, ChannelList *chan)
|
||
{
|
||
if (server <= -1 || server > number_of_servers)
|
||
return;
|
||
if (chan)
|
||
server_list[server].chan_list = chan;
|
||
else
|
||
server_list[server].chan_list = NULL;
|
||
}
|
||
|
||
void set_server_try_once(int s, int val)
|
||
{
|
||
if (s > -1 && s < number_of_servers)
|
||
server_list[s].try_once = val;
|
||
}
|
||
|
||
void set_server_reconnecting(int s, int val)
|
||
{
|
||
if (s > -1 && s < number_of_servers)
|
||
server_list[s].reconnecting = val;
|
||
}
|
||
|
||
void set_server_reconnect(int s, int val)
|
||
{
|
||
if (s > -1 && s < number_of_servers)
|
||
{
|
||
server_list[s].reconnect = val;
|
||
if(val)
|
||
get_time(&server_list[s].connect_time);
|
||
}
|
||
}
|
||
|
||
#ifdef HAVE_LIBSSL
|
||
void set_server_ssl(int s, int val)
|
||
{
|
||
if (s > -1 && s < number_of_servers)
|
||
server_list[s].enable_ssl = val;
|
||
}
|
||
|
||
int get_server_ssl(int s)
|
||
{
|
||
if (s > -1 && s < number_of_servers)
|
||
return server_list[s].enable_ssl;
|
||
return 0;
|
||
}
|
||
#endif
|
||
|
||
void set_server_old_server(int s, int val)
|
||
{
|
||
if (s > -1 && s < number_of_servers)
|
||
server_list[s].old_server = val;
|
||
}
|
||
|
||
void set_server_req_server(int s, int val)
|
||
{
|
||
if (s > -1 && s < number_of_servers)
|
||
server_list[s].req_server = val;
|
||
}
|
||
|
||
void set_server_retries(int s, int val)
|
||
{
|
||
if (s > -1 && s < number_of_servers)
|
||
server_list[s].retries = val;
|
||
}
|
||
|
||
void set_server_change_refnum(int s, int val)
|
||
{
|
||
if (s > -1 && s < number_of_servers)
|
||
server_list[s].server_change_refnum = val;
|
||
}
|
||
|
||
int get_server_reconnecting(int s)
|
||
{
|
||
if (s > -1 && s < number_of_servers)
|
||
return server_list[s].reconnecting;
|
||
return -1;
|
||
}
|
||
|
||
int get_server_reconnect(int s)
|
||
{
|
||
if (s > -1 && s < number_of_servers)
|
||
return server_list[s].reconnect;
|
||
return -1;
|
||
}
|
||
|
||
int get_server_change_pending(int s)
|
||
{
|
||
if (s > -1 && s < number_of_servers)
|
||
return server_list[s].server_change_pending;
|
||
return 0;
|
||
}
|
||
|
||
BUILT_IN_COMMAND(do_map)
|
||
{
|
||
if (from_server == -1 || !is_server_connected(from_server))
|
||
return;
|
||
if (server_list[from_server].link_look == 0)
|
||
{
|
||
bitchsay("Generating irc server map");
|
||
send_to_server("LINKS");
|
||
server_list[from_server].link_look = 2;
|
||
} else
|
||
bitchsay("Wait until previous %s is done", server_list[from_server].link_look == 2? "MAP":"LLOOK");
|
||
}
|
||
|
||
void add_to_irc_map(char *server1, char *distance)
|
||
{
|
||
irc_server *tmp, *insert, *prev;
|
||
int dist = 0;
|
||
if (distance)
|
||
dist = atoi(distance);
|
||
tmp = (irc_server *) new_malloc(sizeof(irc_server));
|
||
malloc_strcpy(&tmp->name, server1);
|
||
tmp->hopcount = dist;
|
||
if (!map)
|
||
{
|
||
map = tmp;
|
||
return;
|
||
}
|
||
for (insert = map, prev = map; insert && insert->hopcount < dist; )
|
||
{
|
||
prev = insert;
|
||
insert = insert->next;
|
||
}
|
||
if (insert && insert->hopcount >= dist)
|
||
{
|
||
tmp->next = insert;
|
||
if (insert == map)
|
||
map = tmp;
|
||
else
|
||
prev->next = tmp;
|
||
} else
|
||
prev->next = tmp;
|
||
}
|
||
|
||
void show_server_map (void)
|
||
{
|
||
int prevdist = 0;
|
||
irc_server *tmp;
|
||
char tmp1[80];
|
||
char tmp2[BIG_BUFFER_SIZE+1];
|
||
#ifdef ONLY_STD_CHARS
|
||
char *ascii="-> ";
|
||
#else
|
||
char *ascii = "<EFBFBD><EFBFBD>> ";
|
||
#endif
|
||
if (map) prevdist = map->hopcount;
|
||
|
||
for (tmp = map; tmp; tmp = map)
|
||
{
|
||
map = tmp->next;
|
||
if (!tmp->hopcount || tmp->hopcount != prevdist)
|
||
strlcpy(tmp1, convert_output_format("%K[%G$0%K]", "%d", tmp->hopcount), sizeof tmp1);
|
||
else
|
||
*tmp1 = 0;
|
||
snprintf(tmp2, sizeof tmp2, "$G %%W$[-%d]1%%c $0 %s", tmp->hopcount*3, tmp1);
|
||
put_it("%s", convert_output_format(tmp2, "%s %s", tmp->name, prevdist!=tmp->hopcount?ascii:empty_string));
|
||
prevdist = tmp->hopcount;
|
||
new_free(&tmp->name);
|
||
new_free((char **)&tmp);
|
||
}
|
||
}
|
||
|
||
void clear_link(irc_server **serv1)
|
||
{
|
||
irc_server *temp = *serv1, *hold;
|
||
|
||
while (temp != NULL)
|
||
{
|
||
hold = temp->next;
|
||
new_free(&temp->name);
|
||
new_free(&temp->link);
|
||
new_free((char **) &temp);
|
||
temp = hold;
|
||
}
|
||
*serv1 = NULL;
|
||
}
|
||
|
||
|
||
#define SPLIT 1
|
||
|
||
irc_server *add_server(irc_server **serv1, char *channel, char *arg, int hops, time_t t)
|
||
{
|
||
irc_server *serv2;
|
||
serv2 = (irc_server *) new_malloc(sizeof (irc_server));
|
||
serv2->next = *serv1;
|
||
malloc_strcpy(&serv2->name, channel);
|
||
malloc_strcpy(&serv2->link, arg);
|
||
serv2->hopcount = hops;
|
||
serv2->time = t;
|
||
*serv1 = serv2;
|
||
return serv2;
|
||
}
|
||
|
||
int find_server(irc_server *serv1, char *channel)
|
||
{
|
||
register irc_server *temp;
|
||
|
||
for (temp = serv1; temp; temp = temp->next)
|
||
{
|
||
if (!my_stricmp(temp->name, channel))
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
void add_split_server(char *name, char *link, int hops)
|
||
{
|
||
irc_server *temp;
|
||
if (from_server < 0) return;
|
||
temp = add_server(&(server_list[from_server].split_link), name, link, hops, now);
|
||
temp->status = SPLIT;
|
||
}
|
||
|
||
irc_server *check_split_server(char *server)
|
||
{
|
||
register irc_server *temp;
|
||
if (!server || from_server < 0) return NULL;
|
||
for (temp = server_list[from_server].split_link; temp; temp = temp->next)
|
||
if (!my_stricmp(temp->name, server))
|
||
return temp;
|
||
return NULL;
|
||
}
|
||
|
||
void remove_split_server(int type, char *server)
|
||
{
|
||
irc_server *temp;
|
||
irc_server **s;
|
||
if (from_server < 0)
|
||
return;
|
||
if (type == LLOOK_SPLIT)
|
||
s = &server_list[from_server].server_last;
|
||
else
|
||
s = &server_list[from_server].split_link;
|
||
if (!s)
|
||
return;
|
||
if ((temp = (irc_server *) remove_from_list((List **)s, server)))
|
||
{
|
||
new_free(&temp->name);
|
||
new_free(&temp->link);
|
||
new_free((char **) &temp);
|
||
}
|
||
}
|
||
|
||
void clean_split_server_list(int type, time_t len)
|
||
{
|
||
irc_server *last = NULL;
|
||
irc_server *s;
|
||
if (from_server < 0)
|
||
return;
|
||
if (type == LLOOK_SPLIT)
|
||
s = server_list[from_server].server_last;
|
||
else
|
||
s = server_list[from_server].split_link;
|
||
|
||
if (!s)
|
||
return;
|
||
while (s)
|
||
{
|
||
last = s->next;
|
||
if (s->time + len <= now)
|
||
remove_split_server(type, s->name);
|
||
s = last;
|
||
}
|
||
}
|
||
|
||
int is_server_valid(char *name, int server)
|
||
{
|
||
if(server > -1 && server < number_of_servers &&
|
||
((server_list[server].snetwork && my_stricmp(name, server_list[server].snetwork) == 0) ||
|
||
(server_list[server].name && my_stricmp(name, server_list[server].name) == 0)))
|
||
return 1;
|
||
return 0;
|
||
}
|
||
|
||
void parse_364(char *channel, char *args, char *subargs)
|
||
{
|
||
if (!*channel || !*args || from_server < 0)
|
||
return;
|
||
|
||
add_server(&server_list[from_server].tmplink, channel, args, atol(subargs), now);
|
||
}
|
||
|
||
void parse_365(char *channel, char *args, char *subargs)
|
||
{
|
||
register irc_server *serv1;
|
||
if (from_server < 0) return;
|
||
for (serv1 = server_list[from_server].server_last; serv1; serv1 = serv1->next)
|
||
{
|
||
if (!find_server(server_list[from_server].tmplink, serv1->name))
|
||
{
|
||
if (!(serv1->status & SPLIT))
|
||
serv1->status = SPLIT;
|
||
if (serv1->count)
|
||
continue;
|
||
serv1->time = now;
|
||
if (do_hook(LLOOK_SPLIT_LIST, "%s %s %d %lu", serv1->name, serv1->link, serv1->hopcount, serv1->time))
|
||
put_it("%s", convert_output_format(fget_string_var(FORMAT_NETSPLIT_FSET), "%l %s %s %d", now - serv1->time, serv1->name, serv1->link, serv1->hopcount));
|
||
serv1->count++;
|
||
}
|
||
else
|
||
{
|
||
if (serv1->status & SPLIT)
|
||
{
|
||
serv1->status = ~SPLIT;
|
||
if (do_hook(LLOOK_JOIN_LIST, "%s %s %d %lu", serv1->name, serv1->link, serv1->hopcount, serv1->time))
|
||
put_it("%s", convert_output_format(fget_string_var(FORMAT_NETJOIN_FSET), "%l %s %s %d", now - serv1->time, serv1->name, serv1->link, serv1->hopcount));
|
||
serv1->count = 0;
|
||
}
|
||
}
|
||
}
|
||
for (serv1 = server_list[from_server].tmplink; serv1; serv1 = serv1->next)
|
||
{
|
||
if (!find_server(server_list[from_server].server_last, serv1->name))
|
||
{
|
||
if (first_time == 1)
|
||
{
|
||
if (do_hook(LLOOK_ADDED_LIST, "%s %s %d", serv1->name, serv1->link, serv1->hopcount))
|
||
put_it("%s", convert_output_format(fget_string_var(FORMAT_NETADD_FSET), "%l %s %s %d", now - serv1->time, serv1->name, serv1->link, serv1->hopcount));
|
||
serv1->count = 0;
|
||
}
|
||
add_server(&server_list[from_server].server_last, serv1->name, serv1->link, serv1->hopcount, now);
|
||
}
|
||
}
|
||
first_time = 1;
|
||
clear_link(&server_list[from_server].tmplink);
|
||
}
|
||
|
||
/*
|
||
* find split servers we hope
|
||
*/
|
||
BUILT_IN_COMMAND(linklook)
|
||
{
|
||
#ifdef WANT_LLOOK
|
||
struct server_split *serv;
|
||
int count;
|
||
|
||
if (from_server < 0)
|
||
return;
|
||
|
||
if (!(serv = server_list[from_server].server_last))
|
||
if (!(serv = server_list[from_server].split_link))
|
||
{
|
||
bitchsay("No active splits");
|
||
return;
|
||
}
|
||
|
||
count = 0;
|
||
while (serv)
|
||
{
|
||
if (serv->status & SPLIT)
|
||
{
|
||
if (!count)
|
||
put_it("%s", convert_output_format(fget_string_var(FORMAT_NETSPLIT_HEADER_FSET), "%s %s %s %s", "time","server","uplink","hops"));
|
||
if (do_hook(LLOOK_SPLIT_LIST, "%s %s %d %lu", serv->name, serv->link, serv->hopcount, serv->time))
|
||
put_it("%s", convert_output_format(fget_string_var(FORMAT_NETSPLIT_FSET), "%l %s %s %d", now - serv->time, serv->name, serv->link, serv->hopcount));
|
||
count++;
|
||
}
|
||
serv = serv->next;
|
||
}
|
||
if (count)
|
||
bitchsay("There %s %d split servers", (count == 1) ? "is": "are", count);
|
||
else
|
||
#endif
|
||
bitchsay("No split servers found");
|
||
}
|
||
|
||
|
||
|
||
|
||
WhoEntry *who_queue_top (int server)
|
||
{
|
||
return server_list[server].who_queue;
|
||
}
|
||
|
||
void set_who_queue_top(int server, WhoEntry *item)
|
||
{
|
||
server_list[server].who_queue = item;
|
||
}
|
||
|
||
IsonEntry *ison_queue_top (int server)
|
||
{
|
||
return server_list[server].ison_queue;
|
||
}
|
||
|
||
void set_ison_queue_top(int server, IsonEntry *ison)
|
||
{
|
||
server_list[server].ison_queue = ison;
|
||
}
|
||
|
||
UserhostEntry *userhost_queue_top (int server)
|
||
{
|
||
return server_list[server].userhost_queue;
|
||
}
|
||
|
||
void set_userhost_queue_top(int server, UserhostEntry *item)
|
||
{
|
||
server_list[server].userhost_queue = item;
|
||
}
|
||
|
||
Server *BX_get_server_list(void)
|
||
{
|
||
return server_list;
|
||
}
|
||
|
||
int get_server_local_port (int gsp_index)
|
||
{
|
||
if (gsp_index == -1)
|
||
gsp_index = primary_server;
|
||
else if (gsp_index >= number_of_servers)
|
||
return 0;
|
||
|
||
return ntohs(server_list[gsp_index].local_sockname.sf_port);
|
||
}
|
||
|
||
struct sockaddr_foobar get_server_local_addr (int servnum)
|
||
{
|
||
return server_list[servnum].local_addr;
|
||
}
|
||
|
||
struct sockaddr_foobar get_server_uh_addr (int servnum)
|
||
{
|
||
return server_list[servnum].uh_addr;
|
||
}
|
||
|
||
void BX_send_msg_to_channels(int server, const char *msg)
|
||
{
|
||
char *p = NULL;
|
||
ChannelList *chan = NULL;
|
||
int count;
|
||
/*
|
||
* Because of hybrid and it's removal of , targets
|
||
* we need to detect this and get around it..
|
||
*/
|
||
if (get_server_version(server) == Server2_8hybrid6)
|
||
{
|
||
/* this might be a cause for some flooding however.
|
||
* so we use the server queue. Which will help alleviate
|
||
* some flooding from the client.
|
||
*/
|
||
for (chan = get_server_channels(server); chan; chan = chan->next)
|
||
queue_send_to_server(server, "PRIVMSG %s :%s", chan->channel, msg);
|
||
return;
|
||
}
|
||
for (chan = get_server_channels(server), count = 1; chan; chan = chan->next, count++)
|
||
{
|
||
m_s3cat(&p, ",", chan->channel);
|
||
if (count > 3)
|
||
{
|
||
my_send_to_server(server, "PRIVMSG %s :%s", p, msg);
|
||
new_free(&p);
|
||
count = 0;
|
||
}
|
||
}
|
||
if (p)
|
||
my_send_to_server(server, "PRIVMSG %s :%s", p, msg);
|
||
new_free(&p);
|
||
}
|
||
|
||
void BX_send_msg_to_nicks(ChannelList *chan, int server, char *msg)
|
||
{
|
||
int serv_version;
|
||
char *p = NULL;
|
||
NickList *n = NULL;
|
||
int count;
|
||
/*
|
||
* Because of hybrid and it's removal of , targets
|
||
* we need to detect this and get around it..
|
||
*/
|
||
serv_version = get_server_version(server);
|
||
if (serv_version == Server2_8hybrid6)
|
||
{
|
||
for (n = next_nicklist(chan, NULL); n; n = next_nicklist(chan, n))
|
||
queue_send_to_server(server, msg, n->nick);
|
||
return;
|
||
}
|
||
for (n = next_nicklist(chan, NULL), count = 1; n ; n = next_nicklist(chan, n), count++)
|
||
{
|
||
m_s3cat(&p, ",", n->nick);
|
||
if (count > 3)
|
||
{
|
||
send_to_server(msg, p);
|
||
new_free(&p);
|
||
count = 0;
|
||
}
|
||
}
|
||
if (p)
|
||
send_to_server(msg, p);
|
||
new_free(&p);
|
||
}
|
||
|
||
/*
|
||
* written by SrFrog for epic.
|
||
*/
|
||
int save_servers (FILE *fp)
|
||
{
|
||
int i = 0;
|
||
|
||
if (!server_list)
|
||
return i; /* no servers */
|
||
|
||
for (i = 0; i < number_of_servers; i++)
|
||
{
|
||
/* SERVER -ADD server:port:password:nick */
|
||
fprintf(fp, "SERVER -ADD %s:%d:%s:%s\n",
|
||
server_list[i].name,
|
||
server_list[i].port,
|
||
server_list[i].password ?
|
||
server_list[i].password : empty_string,
|
||
server_list[i].nickname ?
|
||
server_list[i].nickname : empty_string);
|
||
}
|
||
return i;
|
||
}
|
||
|
||
#if 0
|
||
void set_server_sasl_nick(int server, const char *nick)
|
||
{
|
||
if (server <= -1 || server >= number_of_servers)
|
||
return;
|
||
if (nick)
|
||
malloc_strcpy(&server_list[server].sasl_nick, nick);
|
||
else
|
||
new_free(&server_list[server].sasl_nick);
|
||
}
|
||
#endif
|
||
|
||
char *get_server_sasl_nick(int server)
|
||
{
|
||
if (server <= -1 || server >= number_of_servers)
|
||
return NULL;
|
||
return server_list[server].sasl_nick;
|
||
}
|
||
|
||
#if 0
|
||
void set_server_sasl_pass(int server, const char *pass)
|
||
{
|
||
if (server <= -1 || server >= number_of_servers)
|
||
return;
|
||
if (pass)
|
||
malloc_strcpy(&server_list[server].sasl_pass, pass);
|
||
else
|
||
new_free(&server_list[server].sasl_pass);
|
||
}
|
||
#endif
|
||
|
||
char *get_server_sasl_pass(int server)
|
||
{
|
||
if (server <= -1 || server >= number_of_servers)
|
||
return NULL;
|
||
return server_list[server].sasl_pass;
|
||
}
|