1 /*
2  * server.c: Things dealing with server connections, etc.
3  *
4  * Written By Michael Sandrof
5  *
6  * Copyright(c) 1990
7  *
8  * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
9  */
10 #ifdef IRIX
11 #define _HAVE_SIN_LEN 1
12 #define _HAVE_SA_LEN 1
13 #define MAXDNAME 100
14 #endif
15 
16 #include "irc.h"
17 static char cvsrevision[] = "$Id: server.c 461 2013-11-13 09:57:15Z keaston $";
18 CVS_REVISION(server_c)
19 #include "struct.h"
20 
21 #include "parse.h"
22 
23 #include <stdarg.h>
24 
25 #include "server.h"
26 #include "commands.h"
27 #include "ircaux.h"
28 #include "input.h"
29 #include "who.h"
30 #include "lastlog.h"
31 #include "exec.h"
32 #include "window.h"
33 #include "output.h"
34 #include "names.h"
35 #include "hook.h"
36 #include "vars.h"
37 #include "hash2.h"
38 #include "screen.h"
39 #include "notify.h"
40 #include "misc.h"
41 #include "status.h"
42 #include "list.h"
43 #include "who.h"
44 #define MAIN_SOURCE
45 #include "modval.h"
46 
47 #ifdef WDIDENT
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #include <pwd.h>
51 #endif
52 
53 
54 #ifdef IRIX
55 #undef sa_len
56 #endif
57 
58 static	char *	set_umode (int du_index);
59 
60 const	char *  umodes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
61 
62 /* server_list: the list of servers that the user can connect to,etc */
63  	Server	*server_list = NULL;
64 
65 /* number_of_servers: in the server list */
66 static	int	number_of_servers = 0;
67 
68 	int	primary_server = -1;
69 	int	from_server = -1;
70 	int	never_connected = 1;		/* true until first connection
71 						 * is made */
72 	int	connected_to_server = 0;	/* true when connection is
73 						 * confirmed */
74 	int	parsing_server_index = -1;
75 	int	last_server = -1;
76 
77 	extern	int
78 		dgets_errno;
79 	int	identd = -1;
80 
81 #if defined(WINNT) || defined(__EMX__) || defined(__CYGWIN__) || defined(WANT_IDENTD)
82 	int	already_identd = 0;
83 #endif
84 
85 /* link look and map commands */
86 irc_server *map = NULL;
87 static int first_time = 0;
88 extern char *channel;
89 
90 int (*serv_open_func) (int, struct sockaddr_foobar, int) = NULL;
91 int (*serv_output_func) (int, int, char *, int) = NULL;
92 int (*serv_input_func)  (int, char *, int, int, int) = NULL;
93 int (*serv_close_func) (int, struct sockaddr_foobar, int) = NULL;
94 
95 static QueueSend *serverqueue = NULL;
96 
97 /*
98  * close_server: Given an index into the server list, this closes the
99  * connection to the corresponding server.  It does no checking on the
100  * validity of the index.  It also first sends a "QUIT" to the server being
101  * closed
102  */
BX_close_server(int cs_index,char * message)103 void	BX_close_server (int cs_index, char *message)
104 {
105 	char buffer[IRCD_BUFFER_SIZE + 1];
106 
107 	if (cs_index < 0 || cs_index > number_of_servers)
108 		return;
109 
110 	if (serv_close_func)
111 		(*serv_close_func)(cs_index, server_list[cs_index].local_addr, server_list[cs_index].port);
112 	clean_server_queues(from_server);
113 
114 	if (waiting_out > waiting_in)
115 		waiting_out = waiting_in = 0;
116 
117 	if (get_server_reconnecting(cs_index))
118 		set_waiting_channel(cs_index);
119 	else
120 		clear_channel_list(cs_index);
121 
122 	clear_link(&server_list[cs_index].server_last);
123 	clear_link(&server_list[cs_index].tmplink);
124 	clear_server_sping(cs_index, NULL);
125 
126 	set_server_reconnect(cs_index, 0);
127 	set_server_reconnecting(cs_index, 0);
128 	set_server_try_once(cs_index, 0);
129 	server_list[cs_index].server_change_pending = 0;
130 	server_list[cs_index].operator = 0;
131 	server_list[cs_index].connected = 0;
132 	server_list[cs_index].buffer = NULL;
133 	server_list[cs_index].link_look = 0;
134 	server_list[cs_index].login_flags = 0;
135 
136 	server_list[cs_index].awaytime = 0;
137 	new_free(&server_list[cs_index].away);
138 	new_free(&server_list[cs_index].recv_nick);
139 	new_free(&server_list[cs_index].sent_nick);
140 	new_free(&server_list[cs_index].sent_body);
141 
142 	if (server_list[cs_index].write > -1)
143 	{
144 		if (message && *message && !server_list[cs_index].closing)
145 		{
146 			server_list[cs_index].closing = 1;
147 			if (x_debug & DEBUG_OUTBOUND)
148 				yell("Closing server %d because [%s]",
149 					   cs_index, message ? message : empty_string);
150 			snprintf(buffer, MAX_PROTOCOL_SIZE + 1, "QUIT :%s", message);
151 			strlcat(buffer, "\r\n", sizeof buffer);
152 #ifdef HAVE_SSL
153 			if (get_server_ssl(cs_index))
154 			{
155 				SSL_write(server_list[cs_index].ssl_fd, buffer, strlen(buffer));
156 				say("Closing SSL connection");
157 				SSL_shutdown(server_list[cs_index].ssl_fd);
158 			}
159 			else
160 #endif
161 				send(server_list[cs_index].write, buffer, strlen(buffer), 0);
162 		}
163 		new_close(server_list[cs_index].write);
164 	}
165 	if (server_list[cs_index].read > -1)
166 		new_close(server_list[cs_index].read);
167 	server_list[cs_index].write = server_list[cs_index].read = -1;
168 	if (identd != -1)
169 		set_socketflags(identd, 0);
170 #if defined(WINNT) || defined(__EMX__) || defined(CYGWIN) || defined(WANT_IDENTD)
171 	already_identd = 0;
172 #endif
173 }
174 
close_all_servers(char * message)175 int close_all_servers(char *message)
176 {
177 	int i;
178 	for (i = 0; i < number_of_servers; i++)
179 	{
180 		set_server_reconnecting(i, 0);
181 		close_server(i, message);
182 	}
183 	return 0;
184 }
185 
186 
187 /*
188  * Check if the server that has a connection pending
189  * has any windows that are going to switch over when
190  * it connects.  If not abort the connection attempt.
191  */
close_unattached_server(int server)192 void close_unattached_server(int server)
193 {
194 #ifdef NON_BLOCKING_CONNECTS
195 	Window	*tmp = NULL;
196 	int	cnt = 0;
197 
198 	if(server < 0 || server_list[server].old_server < 0)
199 		return;
200 
201 	while ((traverse_all_windows(&tmp)))
202 	{
203 		if (tmp->server == -1)
204 				cnt++;
205 	}
206 	if (cnt == 0)
207 		close_server(server, empty_string);
208 #endif
209 }
210 
close_unattached_servers(void)211 void close_unattached_servers(void)
212 {
213 	int i;
214 
215 	for (i = 0; i < number_of_servers; i++)
216 	{
217 		if(server_list[i].old_server == -2 ||
218 #ifdef NON_BLOCKING_CONNECTS
219 		   server_list[i].server_change_pending ||
220 #endif
221 		   server_list[i].reconnecting)
222 			close_server(i, empty_string);
223 	}
224 }
225 
226 /*
227  * set_server_bits: Sets the proper bits in the fd_set structure according to
228  * which servers in the server list have currently active read descriptors.
229  */
set_server_bits(fd_set * rd,fd_set * wr)230 long	set_server_bits (fd_set *rd, fd_set *wr)
231 {
232 	int	i;
233 	long timeout = 0;
234 
235 	for (i = 0; i < number_of_servers; i++)
236 	{
237 		if (server_list[i].reconnect > 0)
238 		{
239 			/* CONNECT_DELAY is in seconds but we must
240 			 * return in milliseconds.
241 			 */
242 			timeout = get_int_var(CONNECT_DELAY_VAR)*1000;
243 			if(!timeout)
244 				timeout = -1;
245 		}
246 
247 		if (server_list[i].read > -1)
248 			FD_SET(server_list[i].read, rd);
249 #ifdef NON_BLOCKING_CONNECTS
250 		if (!(server_list[i].login_flags & (LOGGED_IN|CLOSE_PENDING)) &&
251 		    server_list[i].write > -1)
252 			FD_SET(server_list[i].write, wr);
253 #endif
254 	}
255 	return timeout;
256 }
257 
258 
timed_server(void * args,char * sub)259 int timed_server (void *args, char *sub)
260 {
261 char *p = (char *)args;
262 static int retry = 0;
263 int serv = -1;
264 	if (!p || !*p)
265 		return 0;
266 	serv = atol(p);
267 	new_free(&p);
268 	if (!is_server_open(serv) && number_of_servers)
269 	{
270 		bitchsay("Servers exhausted. Restarting. [%d]", ++retry);
271 		get_connected(serv, from_server);
272 	}
273 	set_server_in_timed(serv, 0);
274 	return 0;
275 }
276 
find_old_server(int old_server)277 int find_old_server(int old_server)
278 {
279 	int i;
280 
281 	if(old_server > -1 && old_server < number_of_servers)
282 	{
283 		for (i = 0; i < number_of_servers; i++)
284 		{
285 			if(server_list[i].old_server == old_server)
286 				return i;
287 		}
288 	}
289 	return -1;
290 }
291 
advance_server(int i)292 int advance_server(int i)
293 {
294 	int server = i;
295 
296 	/* We were waiting for this server to
297 	 * connect and it didn't, so we will either
298 	 * try again or move to the next server.
299 	 */
300 
301 	server_list[i].retries++;
302 	if(server_list[i].retries >= get_int_var(MAX_SERVER_RECONNECT_VAR))
303 	{
304 		server = next_server(i);
305 
306 		if(server != i)
307 		{
308 			/* We have a new server to try, so lets
309 			 * move the variables over from the last one
310 			 * and tell it to try to connect.
311 			 */
312 			set_server_reconnect(server, 1);
313 			set_server_req_server(server, server_list[i].req_server);
314 			set_server_old_server(server, server_list[i].old_server);
315 			set_server_change_refnum(server, server_list[i].server_change_refnum);
316 			set_server_retries(server, 0);
317 #ifdef NON_BLOCKING_CONNECTS
318 			server_list[server].from_server = server_list[i].from_server;
319 			server_list[server].c_server = server_list[i].c_server;
320 #endif
321 			/* Reset the old server to the default state. */
322 			server_list[i].retries = 0;
323 			server_list[i].reconnect = 0;
324 			server_list[i].old_server = -1;
325 			server_list[i].req_server = -1;
326 #ifdef NON_BLOCKING_CONNECTS
327 			server_list[i].connect_wait = 0;
328 			server_list[i].from_server = -1;
329 			server_list[i].c_server = -1;
330 #endif
331 		}
332 	}
333 
334 	if(!get_int_var(AUTO_RECONNECT_VAR) && (server_list[server].req_server != server || server_list[server].retries > 1))
335 	{
336 		close_server(server, empty_string);
337 		clean_server_queues(server);
338 		from_server = -1;
339 		if(do_hook(DISCONNECT_LIST,"No Connection"))
340 			put_it("%s", convert_output_format(fget_string_var(FORMAT_DISCONNECT_FSET), "%s %s", update_clock(GET_TIME), "No connection"));
341 		return -1;
342 	}
343 	else if(server == server_list[i].req_server && server_list[server].retries > 1)
344 		bitchsay("Servers exhausted. Restarting.");
345 
346 	return server;
347 }
348 
reconnect_server(int * servernum,int * times,time_t * last_timeout)349 void reconnect_server(int *servernum, int *times, time_t *last_timeout)
350 {
351 	int orig;
352 
353 	if(*servernum < 0)
354 		*servernum = 0;
355 
356 	orig = *servernum;
357 
358 	server_list[*servernum].reconnecting = 1;
359 	close_server(*servernum, empty_string);
360 	*last_timeout = 0;
361 
362 	(*servernum) = advance_server(*servernum);
363 
364 	if(*servernum < 0)
365 		return;
366 
367 	if(*servernum != orig)
368 		*times = 1;
369 
370 	set_server_reconnect(*servernum, 0);
371 	window_check_servers(*servernum);
372 	try_connect(*servernum, server_list[*servernum].old_server);
373 }
374 
375 /* Check for a nonblocking connection that has been around
376  * for more than CONNECT_TIMEOUT_VAR seconds without connecting
377  */
378 #ifdef NON_BLOCKING_CONNECTS
scan_nonblocking(void)379 static void scan_nonblocking(void)
380 {
381 	int i;
382 	int connect_timeout = get_int_var(CONNECT_TIMEOUT_VAR);
383 
384 	if (!connect_timeout)
385 		return;
386 
387 	for (i = 0; i < number_of_servers; i++)
388 	{
389 		if (((server_list[i].read > -1) ||
390 		     (server_list[i].write > -1)) &&
391 		    !(server_list[i].login_flags & LOGGED_IN) &&
392 		    (time(NULL) - server_list[i].connect_time >
393 		     connect_timeout)) {
394 			if (server_list[i].read > -1)
395 				new_close(server_list[i].read);
396 			if (server_list[i].write > -1)
397 				new_close(server_list[i].write);
398 			server_list[i].read = server_list[i].write = -1;
399 			set_server_reconnect(i, 1);
400 		}
401 	}
402 }
403 #endif
404 
do_idle_server(void)405 void	do_idle_server (void)
406 {
407 	int i;
408 	static	int	times = 1;
409 	static	time_t	last_timeout = 0;
410 
411 #ifdef NON_BLOCKING_CONNECTS
412 	scan_nonblocking();
413 #endif
414 
415 	for (i = 0; i < number_of_servers && i > -1; i++)
416 	{
417 		/* We were told to reconnect, to avoid recursion. */
418 		if(get_server_reconnect(i) > 0)
419 		{
420 			int connect_delay = get_int_var(CONNECT_DELAY_VAR);
421 
422 			if(!connect_delay || (time(NULL) - server_list[i].connect_time) > connect_delay)
423 			{
424 				int servernum = i;
425 
426 				set_server_reconnect(i, 0);
427 				reconnect_server(&servernum, &times, &last_timeout);
428 			}
429 		}
430 	}
431 }
432 
433 /*
434  *
435  do_server: check the given fd_set against the currently open servers in
436  * the server list.  If one have information available to be read, it is read
437  * and and parsed appropriately.  If an EOF is detected from an open server,
438  * one of two things occurs. 1) If the server was the primary server,
439  * get_connected() is called to maintain the connection status of the user.
440  * 2) If the server wasn't a primary server, connect_to_server() is called to
441  * try to keep that connection alive.
442  */
do_server(fd_set * rd,fd_set * wr)443 void	do_server (fd_set *rd, fd_set *wr)
444 {
445 	char	buffer[BIG_BUFFER_SIZE + 1];
446 	int	des,
447 		i;
448 	static	int	times = 1;
449 static	time_t	last_timeout = 0;
450 
451 #ifdef NON_BLOCKING_CONNECTS
452 	scan_nonblocking();
453 #endif
454 
455 	for (i = 0; i < number_of_servers; i++)
456 	{
457 		/* We were told to reconnect, to avoid recursion. */
458 		if(get_server_reconnect(i) > 0)
459 		{
460 			int connect_delay = get_int_var(CONNECT_DELAY_VAR);
461 
462 			if(!connect_delay || (time(NULL) - server_list[i].connect_time) > connect_delay)
463 			{
464 				int servernum = i;
465 
466 				set_server_reconnect(i, 0);
467 				reconnect_server(&servernum, &times, &last_timeout);
468 			}
469 		}
470 
471 #ifdef NON_BLOCKING_CONNECTS
472 		if (((des = server_list[i].write) > -1) && FD_ISSET(des, wr) && !(server_list[i].login_flags & LOGGED_IN))
473 		{
474 			struct sockaddr_in sa;
475 			socklen_t salen = sizeof(struct sockaddr_in);
476 
477 			if (getpeername(des, (struct sockaddr *) &sa, &salen) != -1)
478 			{
479 #ifdef HAVE_SSL
480 				if(!server_list[i].ctx || server_list[i].ssl_error == SSL_ERROR_WANT_WRITE)
481 				{
482 #endif
483 					server_list[i].connect_wait = 0;
484 					finalize_server_connect(i, server_list[i].c_server, i);
485 #ifdef HAVE_SSL
486 				}
487 #endif
488 			}
489 		}
490 #endif
491 		if (((des = server_list[i].read) > -1) && FD_ISSET(des, rd))
492 		{
493 			int	junk = 0;
494 			char 	*bufptr;
495 			errno	= 0;
496 			last_server = from_server = i;
497 			bufptr = buffer;
498 			if (serv_input_func)
499 				junk = (*serv_input_func)(i, bufptr, des, 1, BIG_BUFFER_SIZE);
500 			else
501 			{
502 #ifdef HAVE_SSL
503 				if(get_server_ssl(i))
504 				{
505 #ifdef NON_BLOCKING_CONNECTS
506 					/* If we get here before getting above we have problems. */
507 					if(!(server_list[i].login_flags & LOGGED_IN))
508 					{
509 						if(!server_list[i].ctx || server_list[i].ssl_error == SSL_ERROR_WANT_READ)
510 						{
511 							server_list[i].connect_wait = 0;
512 							finalize_server_connect(i, server_list[i].c_server, i);
513 						}
514 					}
515 					else
516 #endif
517 						junk = dgets(bufptr, des, 1, BIG_BUFFER_SIZE, server_list[i].ssl_fd);
518 				}
519 				else
520 #endif
521 					junk = dgets(bufptr, des, 1, BIG_BUFFER_SIZE, NULL);
522 			}
523 			switch (junk)
524 			{
525 				case 0: /* timeout */
526 					break;
527 				case -1: /* EOF condition */
528 					{
529 						int try_once = server_list[i].try_once;
530 
531 						/* Try to make sure output goes to the correct window */
532 						if(server_list[i].server_change_refnum > -1)
533 							set_display_target_by_winref(server_list[i].server_change_refnum);
534 						say("Connection closed from %s: %s", server_list[i].name, dgets_strerror(dgets_errno));
535 
536 						server_list[i].reconnecting = 1;
537 						close_server(i, empty_string);
538 						if(!try_once)
539 						{
540 #ifdef NON_BLOCKING_CONNECTS
541 							if(server_list[i].server_change_pending == 2)
542 							{
543 								/* If the previous server gets closed while
544 								 * we are waiting for another server to connect
545 								 * we don't want to try a new connection, so
546 								 * just close down this connection and quit.
547 								 */
548 								close_server(i, empty_string);
549 							}
550 							else if(server_list[i].connect_wait)
551 							{
552 								set_server_reconnect(i, 1);
553 
554 								if ((server_list[i].from_server != -1))
555 								{
556 									if((server_list[server_list[i].from_server].read != -1) &&
557 									   (server_list[i].from_server != i))
558 									{
559 										/* Set the windows back to the old server */
560 										say("Connection to server %s resumed...", server_list[server_list[i].from_server].name);
561 										change_server_channels(i, server_list[i].old_server);
562 										set_window_server(-1, i, 1);
563 										set_server_reconnect(i, 0);
564 									} else if(server_list[i].from_server != i)
565 									{
566 										close_server(server_list[i].from_server, empty_string);
567 									}
568 								}
569 
570 							}
571 							else
572 #endif
573 							{
574 								set_server_reconnect(i, 1);
575 								server_list[i].old_server = i;
576 							}
577 						}
578 						break;
579 					}
580 				default:
581 				{
582 					last_timeout = 0;
583 					parsing_server_index = i;
584 					server_list[i].last_msg = now;
585 					parse_server(buffer);
586 					new_free(&server_list[i].buffer);
587 					parsing_server_index = -1;
588 					reset_display_target();
589 					break;
590 				}
591 			}
592 			from_server = primary_server;
593 		}
594 		if (server_list[i].read != -1 && (errno == ENETUNREACH || errno == EHOSTUNREACH))
595 		{
596 			if (last_timeout == 0)
597 				last_timeout = now;
598 			else if (now - last_timeout > 600)
599 			{
600 				close_server(i, empty_string);
601 				server_list[i].reconnecting = 1;
602 				get_connected(i, -1);
603 			}
604 		}
605 	}
606 
607 	if (primary_server == -1 || !is_server_open(primary_server))
608 		window_check_servers(-1);
609 }
610 
611 /*
612  * find_in_server_list: given a server name, this tries to match it against
613  * names in the server list, returning the index into the list if found, or
614  * -1 if not found
615  */
BX_find_in_server_list(char * server,int port)616 extern	int	BX_find_in_server_list (char *server, int port)
617 {
618 	int	i,
619 		len, hintfound = -1;
620 
621 	len = strlen(server);
622 
623 	for (i = 0; i < number_of_servers; i++)
624 	{
625 		if (port && server_list[i].port && port != server_list[i].port && port != -1)
626 			continue;
627 
628 #if 0
629 #define MATCH_WITH_COMPLETION(n1, n2) 			\
630 {							\
631 	size_t l1 = strlen(n1);				\
632 	size_t l2 = strlen(n2);				\
633 	size_t l3 = l1 > l2 ? l2 : l1;			\
634 							\
635 	if (!my_strnicmp(n1, n2, l3))			\
636 		return i;				\
637 }
638 
639 
640 		MATCH_WITH_COMPLETION(server, server_list[i].name);
641 
642 		if (!server_list[i].itsname)
643 			continue;
644 		MATCH_WITH_COMPLETION(server, server_list[i].itsname);
645 #endif
646 		/*
647 		 * Try to avoid unneccessary string compares. Only compare
648 		 * the first part of the string if there's not already a
649 		 * possible match set in "hintfound". This enables us to
650 		 * search for an exact match even if there's already a
651 		 * fuzzy-match, without having to compare twice.
652 		 */
653 		if ((-1 != hintfound) || !my_strnicmp(server, server_list[i].name, len))
654 		{
655 			if (!my_stricmp(server, server_list[i].name))
656 				return i;
657 			else if (-1 == hintfound)
658 				hintfound = i;
659 		}
660 		else if (server_list[i].itsname && ((-1 != hintfound) ||
661 			!my_strnicmp(server, server_list[i].itsname, len)))
662 		{
663 			if (!my_stricmp(server, server_list[i].itsname))
664 				return i;
665 			else if (-1 == hintfound)
666 				hintfound = i;
667 		}
668 	}
669 	return (hintfound);
670 }
671 
672 /*
673  * parse_server_index:  given a string, this checks if it's a number, and if
674  * so checks it validity as a server index.  Otherwise -1 is returned
675  */
BX_parse_server_index(char * str)676 int	BX_parse_server_index (char *str)
677 {
678 	int	i;
679 
680 	if (is_number(str))
681 	{
682 		i = my_atol(str);
683 		if ((i >= 0) && (i < number_of_servers))
684 			return (i);
685 	}
686 	return (-1);
687 }
688 
689 /*
690  * This replaces ``get_server_index''.
691  */
BX_find_server_refnum(char * server,char ** rest)692 int 	BX_find_server_refnum (char *server, char **rest)
693 {
694 	int 	refnum;
695 	int	port = irc_port;
696 	char 	*cport = NULL,
697 		*password = NULL,
698 		*nick = NULL,
699 		*snetwork = NULL;
700 
701 	/*
702 	 * First of all, check for an existing server refnum
703 	 */
704 	if ((refnum = parse_server_index(server)) != -1)
705 		return refnum;
706 	/*
707 	 * Next check to see if its a "server:port:password:nick:network"
708 	 */
709 	else if (index(server, ':') || index(server, ','))
710 		parse_server_info(server, &cport, &password, &nick, &snetwork);
711 
712 	else if (index(server, '['))
713 	{
714 		int i;
715 		server++;
716 		chop(server, 1);
717 		if (!server || !*server)
718 			return from_server;
719 		for (i = 0; i < number_of_servers; i++)
720 		{
721 			if (server && server_list[i].snetwork && !my_stricmp(server, server_list[i].snetwork))
722 				return i;
723 		}
724 	}
725 	/*
726 	 * Next check to see if its "server port password nick"
727 	 */
728 	else if (rest && *rest)
729 	{
730 		cport = next_arg(*rest, rest);
731 		password = next_arg(*rest, rest);
732 		nick = next_arg(*rest, rest);
733 		snetwork = next_arg(*rest, rest);
734 	}
735 
736 	if (cport && *cport)
737 		port = my_atol(cport);
738 
739 	/*
740 	 * Add to the server list (this will update the port
741 	 * and password fields).
742 	 */
743 	add_to_server_list(server, port, password, nick, snetwork, 0, 1);
744 	return from_server;
745 }
746 
747 
748 /*
749  * add_to_server_list: adds the given server to the server_list.  If the
750  * server is already in the server list it is not re-added... however, if the
751  * overwrite flag is true, the port and passwords are updated to the values
752  * passes.  If the server is not on the list, it is added to the end. In
753  * either case, the server is made the current server.
754  */
BX_add_to_server_list(char * server,int port,char * password,char * nick,char * snetwork,int ssl,int overwrite)755 void 	BX_add_to_server_list (char *server, int port, char *password, char *nick, char *snetwork, int ssl, int overwrite)
756 {
757 extern int default_swatch;
758 	if ((from_server = find_in_server_list(server, port)) == -1)
759 	{
760 		from_server = number_of_servers++;
761 		RESIZE(server_list, Server, number_of_servers+1);
762 		memset(&server_list[from_server], 0, sizeof(Server));
763 		server_list[from_server].name = m_strdup(server);
764 		if (snetwork)
765 			server_list[from_server].snetwork = m_strdup(snetwork);
766 		server_list[from_server].read = -1;
767 		server_list[from_server].write = -1;
768 		server_list[from_server].lag = -1;
769 		server_list[from_server].motd = 1;
770 		server_list[from_server].ircop_flags = default_swatch;
771 		server_list[from_server].port = port;
772 #ifdef HAVE_SSL
773 		set_server_ssl(from_server, ssl);
774 #endif
775 		malloc_strcpy(&server_list[from_server].umodes, umodes);
776 		if (password && *password)
777 			malloc_strcpy(&(server_list[from_server].password), password);
778 
779 		if (nick && *nick)
780 			malloc_strcpy(&(server_list[from_server].d_nickname), nick);
781 		else if (!server_list[from_server].d_nickname)
782 			malloc_strcpy(&(server_list[from_server].d_nickname), nickname);
783 
784 		make_notify_list(from_server);
785 		make_watch_list(from_server);
786 		set_umode(from_server);
787 	}
788 	else
789 	{
790 		if (overwrite)
791 		{
792 			server_list[from_server].port = port;
793 			if (password || !server_list[from_server].password)
794 			{
795 				if (password && *password)
796 					malloc_strcpy(&(server_list[from_server].password), password);
797 				else
798 					new_free(&(server_list[from_server].password));
799 			}
800 			if (nick || !server_list[from_server].d_nickname)
801 			{
802 				if (nick && *nick)
803 					malloc_strcpy(&(server_list[from_server].d_nickname), nick);
804 				else
805 					new_free(&(server_list[from_server].d_nickname));
806 			}
807 		}
808 		if (strlen(server) > strlen(server_list[from_server].name))
809 			malloc_strcpy(&(server_list[from_server].name), server);
810 	}
811 }
812 
remove_from_server_list(int i)813 void 	remove_from_server_list (int i)
814 {
815 	Window	*tmp = NULL;
816 
817 	if (i < 0 || i >= number_of_servers)
818 		return;
819 
820 	say("Deleting server [%d]", i);
821 
822 	clean_server_queues(i);
823 
824 	new_free(&server_list[i].name);
825 	new_free(&server_list[i].snetwork);
826 	new_free(&server_list[i].itsname);
827 	new_free(&server_list[i].password);
828 	new_free(&server_list[i].away);
829 	new_free(&server_list[i].version_string);
830 	new_free(&server_list[i].nickname);
831 	new_free(&server_list[i].s_nickname);
832 	new_free(&server_list[i].d_nickname);
833 	new_free(&server_list[i].umodes);
834 	new_free(&server_list[i].recv_nick);
835 	new_free(&server_list[i].sent_nick);
836 	new_free(&server_list[i].sent_body);
837 #ifdef HAVE_SSL
838 	SSL_CTX_free(server_list[i].ctx);
839 #endif
840 	clear_server_sping(i, NULL);
841 
842 	/*
843 	 * this should save a coredump.  If number_of_servers drops
844 	 * down to zero, then trying to do a realloc ends up being
845 	 * a free, and accessing that is a no-no.
846 	 */
847 	if (number_of_servers == 1)
848 	{
849 		say("Sorry, the server list is empty and I just don't know what to do.");
850 		irc_exit(1, NULL, NULL);
851 	}
852 
853 	memmove(&server_list[i], &server_list[i + 1], (number_of_servers - i - 1) * sizeof(Server));
854 	number_of_servers--;
855 	RESIZE(server_list, Server, number_of_servers);
856 
857 	/* update all he structs with server in them */
858 	channel_server_delete(i);
859 	exec_server_delete(i);
860         if (i < primary_server)
861                 --primary_server;
862         if (i < from_server)
863                 --from_server;
864 	while ((traverse_all_windows(&tmp)))
865 		if (tmp->server > i)
866 			tmp->server--;
867 }
868 
869 
870 
871 /*
872  * parse_server_inFo:  This parses a single string of the form
873  * "server:portnum:password:nickname:snetwork".  It the points port to the portnum
874  * portion and password to the password portion.  This chews up the original
875  * string, so * upon return, name will only point the the name.  If portnum
876  * or password are missing or empty,  their respective returned value will
877  * point to null.
878  *
879  * With IPv6 patch it also supports comma as a delimiter.
880  */
BX_parse_server_info(char * name,char ** port,char ** password,char ** nick,char ** snetwork)881 void	BX_parse_server_info (char *name, char **port, char **password, char **nick, char **snetwork)
882 {
883 	char *ptr, delim;
884 
885 	delim = (index(name, ',')) ? ',' : ':';
886 
887 	*port = *password = *nick = NULL;
888 	if ((ptr = (char *) strchr(name, delim)) != NULL)
889 	{
890 		*(ptr++) = (char) 0;
891 		if (strlen(ptr) == 0)
892 			*port = NULL;
893 		else
894 		{
895 			*port = ptr;
896 			if ((ptr = (char *) strchr(ptr, delim)) != NULL)
897 			{
898 				*(ptr++) = (char) 0;
899 				if (strlen(ptr) == 0)
900 					*password = 0;
901 				else
902 				{
903 					*password = ptr;
904 					if ((ptr = (char *) strchr(ptr, delim))
905 							!= NULL)
906 					{
907 						*(ptr++) = 0;
908 						if (!strlen(ptr))
909 							*nick = NULL;
910 						else
911 						{
912 							*nick = ptr;
913 							if ((ptr = strchr(ptr, delim)) !=NULL)
914 							{
915 								*(ptr++) = 0;
916 								if  (!strlen(ptr))
917 									*snetwork = NULL;
918 								else
919 									*snetwork = ptr;
920 							}
921 						}
922 					}
923 				}
924 			}
925 		}
926 	}
927 }
928 
929 /*
930  * build_server_list: given a whitespace separated list of server names this
931  * builds a list of those servers using add_to_server_list().  Since
932  * add_to_server_list() is used to added each server specification, this can
933  * be called many many times to add more servers to the server list.  Each
934  * element in the server list case have one of the following forms:
935  *
936  * servername
937  * servername:port
938  * servername:port:password
939  * servername::password
940  * servernetwork
941  * servername:port:password:nick:servernetwork
942  * Note also that this routine mucks around with the server string passed to it,
943  * so make sure this is ok
944  */
945 static char *default_network = NULL;
946 
BX_build_server_list(char * servers)947 int	BX_build_server_list (char *servers)
948 {
949 	char	*host,
950 		*rest,
951 		*password = NULL,
952 		*port = NULL,
953 		*nick = NULL,
954 		*snetwork = NULL;
955 
956 	int	port_num;
957 	int	i = 0;
958 #ifdef HAVE_SSL
959 	extern int do_use_ssl;
960 #else
961 	int do_use_ssl = 0;
962 #endif
963 
964 	if (!servers || !*servers)
965 		return 0;
966 
967 	while (servers)
968 	{
969 		if ((rest = (char *) strchr(servers, '\n')) != NULL)
970 			*rest++ = 0;
971 		while ((host = new_next_arg(servers, &servers)) != NULL)
972 		{
973 			if (!host || !*host)
974 				break;
975 			if (*host == '[')
976 			{
977 				host++;
978 				if (host[strlen(host)-1] != ']' && servers && *servers)
979 				{
980 					char *ptr = NULL;
981 					host[strlen(host)] = ' ';
982 					if ((ptr = MatchingBracket(host, '[', ']')))
983 					{
984 						*ptr++ = 0;
985 						servers = ptr;
986 					}
987 				}
988 				if (host[strlen(host)-1] == ']')
989 					chop(host, 1);
990 				malloc_strcpy(&default_network, host);
991 				snetwork = NULL;
992 				continue;
993 			}
994 			parse_server_info(host, &port, &password, &nick, &snetwork);
995 			if (port && *port)
996 			{
997 				if (!(port_num = my_atol(port)))
998 					port_num = irc_port;
999 			}
1000 			else
1001 				port_num = irc_port;
1002 
1003 			add_to_server_list(host, port_num, password, nick, snetwork ? snetwork : default_network, do_use_ssl, 0);
1004 			i++;
1005 		}
1006 		servers = rest;
1007 	}
1008 	return i;
1009 }
1010 
read_and_parse_server(char ** filename,char * buffer)1011 int read_and_parse_server(char **filename, char *buffer)
1012 {
1013 FILE *fp;
1014 int i = 0;
1015 	if ((fp = uzfopen(filename, ".", 0)))
1016 	{
1017 		char *p;
1018 		while (fgets(buffer, BIG_BUFFER_SIZE, fp))
1019 		{
1020 			chop(buffer, 1);
1021 			if ((p = strchr(buffer, '#')))
1022 				*p = 0;
1023 			i += build_server_list(buffer);
1024 		}
1025 		fclose(fp);
1026 	}
1027 	return i;
1028 }
1029 
1030 /*
1031  * read_server_file: reads hostname:portnum:password:network server information from
1032  * a file and adds this stuff to the server list.  See build_server_list()/
1033  */
BX_read_server_file(char * servers_file)1034 int BX_read_server_file (char *servers_file)
1035 {
1036 	int some = 0;
1037 	char *file_path = NULL;
1038 	char	buffer[BIG_BUFFER_SIZE + 1];
1039 	int old_window_display = window_display;
1040 	char    *expanded;
1041 
1042 	window_display = 0;
1043 
1044 	if (getenv("IRC_SERVERS_FILE"))
1045 	{
1046 		malloc_strcpy(&file_path, getenv("IRC_SERVERS_FILE"));
1047 		expanded = expand_twiddle(file_path);
1048 		some = read_and_parse_server(&expanded, buffer);
1049 		new_free(&file_path);
1050 		new_free(&expanded);
1051 	}
1052 
1053 #ifdef SERVERS_FILE
1054 	if (SERVERS_FILE[0] != '/')
1055 		file_path = m_opendup(irc_lib, "/", NULL);
1056 	malloc_strcat(&file_path, SERVERS_FILE);
1057 	some += read_and_parse_server(&file_path, buffer);
1058 	new_free(&file_path);
1059 #endif
1060 
1061 	if (*servers_file == '/')
1062 		file_path = m_strdup(servers_file);
1063 	else
1064 		file_path = m_opendup("~/", servers_file, NULL);
1065 	some += read_and_parse_server(&file_path, buffer);
1066 	new_free(&file_path);
1067 
1068 	window_display = old_window_display;
1069 	return some;
1070 }
1071 
1072 
1073 /*
1074  * Actually do the work of writing out all the entries.
1075  */
write_server_list(char * filename)1076 void write_server_list(char *filename)
1077 {
1078 	FILE *serverfile;
1079 	char *sgroup = NULL;
1080 	int i;
1081 
1082 	if(!number_of_servers || !(serverfile = fopen(filename, "w")))
1083 		return;
1084 
1085 	bitchsay("Writing server list to %s", filename);
1086 
1087 	fprintf(serverfile, "# Server list generated by BitchX.\n");
1088 
1089 	for(i=0;i<number_of_servers;i++)
1090 	{
1091 		if(!sgroup && server_list[i].snetwork)
1092 		{
1093 			sgroup = server_list[i].snetwork;
1094 			fprintf(serverfile, "\n[%s]\n", sgroup);
1095 		}
1096 		else if(sgroup && server_list[i].snetwork &&
1097 				my_stricmp(sgroup, server_list[i].snetwork))
1098 		{
1099 			sgroup = server_list[i].snetwork;
1100 			fprintf(serverfile, "\n[%s]\n", sgroup);
1101 		}
1102 		else if(sgroup && !server_list[i].snetwork)
1103 		{
1104 			sgroup = NULL;
1105 			fprintf(serverfile, "\n[unknown]\n");
1106 		}
1107 
1108 		fprintf(serverfile, "%s:%d", server_list[i].name, server_list[i].port);
1109 		if(server_list[i].password)
1110 			fprintf(serverfile, ":%s", server_list[i].password);
1111 		fprintf(serverfile, "\n");
1112 	}
1113 
1114 	fclose(serverfile);
1115 }
1116 
1117 /*
1118  * write_server_file: writes hostname:portnum:password:network server information
1119  * to a file.
1120  */
write_server_file(char * servers_file)1121 void write_server_file (char *servers_file)
1122 {
1123 	char *file_path = NULL;
1124 	char    *expanded;
1125 
1126 	if(servers_file && *servers_file)
1127 	{
1128 		if (*servers_file == '/')
1129 			file_path = m_strdup(servers_file);
1130 		else
1131 			file_path = m_opendup("~/", servers_file, NULL);
1132 		write_server_list(file_path);
1133 		new_free(&file_path);
1134 		return;
1135 	}
1136 
1137 	if (getenv("IRC_SERVERS_FILE"))
1138 	{
1139 		malloc_strcpy(&file_path, getenv("IRC_SERVERS_FILE"));
1140 		expanded = expand_twiddle(file_path);
1141 		write_server_list(expanded);
1142 		new_free(&file_path);
1143 		new_free(&expanded);
1144 		return;
1145 	}
1146 
1147 #if defined(WINNT) || defined(__EMX__)
1148 	malloc_strcpy(&file_path, "~/irc-serv");
1149 #else
1150 	malloc_strcpy(&file_path, "~/.ircservers");
1151 #endif
1152 	expanded = expand_twiddle(file_path);
1153 	write_server_list(expanded);
1154 	new_free(&file_path);
1155 	new_free(&expanded);
1156 }
1157 
1158 
1159 /*
1160  * connect_to_server_direct: handles the tcp connection to a server.  If
1161  * successful, the user is disconnected from any previously connected server,
1162  * the new server is added to the server list, and the user is registered on
1163  * the new server.  If connection to the server is not successful,  the
1164  * reason for failure is displayed and the previous server connection is
1165  * resumed uniterrupted.
1166  *
1167  * This version of connect_to_server() connects directly to a server
1168  */
connect_to_server_direct(char * server_name,int port)1169 static	int	connect_to_server_direct (char *server_name, int port)
1170 {
1171 	int		new_des;
1172 	struct sockaddr_foobar	*localaddr;
1173 	socklen_t	address_len;
1174 	unsigned short	this_sucks;
1175 
1176 
1177 #ifdef WDIDENT
1178 	struct stat sb;
1179 	struct passwd *pw;
1180 	char lockfile[1024];
1181 	FILE *fp;
1182 	char candofilestuff=0;
1183 	struct hostent *hp=NULL;
1184 	struct sockaddr_in raddr;
1185 #endif
1186 
1187 
1188 	oper_command = 0;
1189 	errno = 0;
1190 	localaddr = &server_list[from_server].local_sockname;
1191 	memset(localaddr, 0, sizeof(*localaddr));
1192 	this_sucks = (unsigned short)port;
1193 
1194 
1195 #ifdef WDIDENT
1196 	pw=getpwuid(getuid());
1197 	if(!pw)
1198 		goto noidentwd;
1199 	sprintf(lockfile, "%s/.identwd", pw->pw_dir);
1200 
1201 	if(*server_name=='/')
1202 		goto noidentwd;
1203 
1204 	if(stat(lockfile, &sb))
1205 		goto noidentwd;
1206 
1207 	if(!(sb.st_mode & S_IFDIR))
1208 		goto noidentwd;
1209 
1210 	hp=resolv(server_name);
1211 	if(!hp)
1212 		goto noidentwd;
1213 	if(hp->h_addrtype != AF_INET)
1214 		goto noidentwd;
1215 
1216 	memcpy(&raddr.sin_addr, hp->h_addr, hp->h_length);
1217 	sprintf(lockfile, "%s/.identwd/%s.%i.LOCK", pw->pw_dir,
1218 		inet_ntoa((struct in_addr)raddr.sin_addr), port);
1219 	if ((fp=fopen(lockfile, "w")))
1220 	{
1221 		fprintf(fp, "WAIT\n");
1222 		fclose(fp);
1223 		candofilestuff=1;
1224 	}
1225 noidentwd:
1226 #endif
1227 
1228 #ifdef NON_BLOCKING_CONNECTS
1229 	new_des = connect_by_number(server_name, &this_sucks, SERVICE_CLIENT, PROTOCOL_TCP, 1);
1230 #else
1231 	new_des = connect_by_number(server_name, &this_sucks, SERVICE_CLIENT, PROTOCOL_TCP, 0);
1232 #endif
1233 
1234 	port = this_sucks;
1235 
1236 	if (new_des < 0)
1237 	{
1238 		if (x_debug)
1239 			say("new_des is %d", new_des);
1240 		say("Unable to connect to port %d of server %s: %s", port,
1241 				server_name, errno ? strerror(errno) :"unknown host");
1242 		if ((from_server != -1)&& (server_list[from_server].read != -1))
1243 			say("Connection to server %s resumed...", server_list[from_server].name);
1244 #ifdef WDIDENT
1245 		if(candofilestuff)
1246 			remove(lockfile);
1247 #endif
1248 		return (-1);
1249 	}
1250 
1251 	if (*server_name != '/')
1252 	{
1253 		address_len = sizeof(struct sockaddr_foobar);
1254 		getsockname(new_des, (struct sockaddr *) localaddr, &address_len);
1255 		if ((server_list[from_server].local_addr.sf_family = localaddr->sf_family) == AF_INET)
1256 			memcpy(&server_list[from_server].local_addr.sf_addr, &localaddr->sf_addr, sizeof(struct in_addr));
1257 #ifdef IPV6
1258 		else
1259 			memcpy(&server_list[from_server].local_addr.sf_addr6, &localaddr->sf_addr6, sizeof(struct in6_addr));
1260 #endif
1261        	}
1262 #ifdef WDIDENT
1263 	if(candofilestuff && (fp = fopen(lockfile, "w")) )
1264 	{
1265 		fprintf(fp, "%s %i %s", inet_ntoa(localaddr->sin_addr),
1266 			htons(localaddr->sf_port), username);
1267 		fclose(fp);
1268 	}
1269 #endif
1270 
1271 	update_all_status(current_window, NULL, 0);
1272 	add_to_server_list(server_name, port, NULL, NULL, NULL, 0, 1);
1273 
1274 	server_list[from_server].closing = 0;
1275 	if (port)
1276 	{
1277 		server_list[from_server].read = new_des;
1278 		server_list[from_server].write = new_des;
1279 	}
1280 	else
1281 		server_list[from_server].read = new_des;
1282 
1283 	new_open(new_des);
1284 	server_list[from_server].operator = 0;
1285 
1286 	if (identd != -1)
1287 		set_socketflags(identd, now);
1288 	return 0;
1289 }
1290 
1291 /* This code either gets called from connect_to_server_by_refnum()
1292  * or from the main loop once a nonblocking connect has been
1293  * verified.
1294  */
finalize_server_connect(int refnum,int c_server,int my_from_server)1295 int finalize_server_connect(int refnum, int c_server, int my_from_server)
1296 {
1297 	if (serv_open_func)
1298 		(*serv_open_func)(my_from_server, server_list[my_from_server].local_addr, server_list[my_from_server].port);
1299 	if ((c_server > -1) && (c_server != my_from_server))
1300 	{
1301 		server_list[c_server].reconnecting = 1;
1302 		server_list[c_server].old_server = -1;
1303 #ifdef NON_BLOCKING_CONNECTS
1304 		server_list[c_server].server_change_pending = 0;
1305 		server_list[refnum].from_server = -1;
1306 #endif
1307 		close_server(c_server, "changing servers");
1308 	}
1309 
1310 #ifdef HAVE_SSL
1311 	if(get_server_ssl(refnum))
1312 	{
1313 		int err = 0;
1314 
1315 		if(!server_list[refnum].ctx)
1316 		{
1317 			server_list[refnum].ctx = SSL_CTX_new (SSLv23_client_method());
1318 			CHK_NULL(server_list[refnum].ctx);
1319 			server_list[refnum].ssl_fd = SSL_new (server_list[refnum].ctx);
1320 			CHK_NULL(server_list[refnum].ssl_fd);
1321 			SSL_set_fd (server_list[refnum].ssl_fd, server_list[refnum].read);
1322 		}
1323 		err = SSL_connect (server_list[refnum].ssl_fd);
1324 		if(err == -1)
1325 		{
1326 			server_list[refnum].ssl_error = SSL_get_error((SSL *)server_list[refnum].ssl_fd, err);
1327 			if(server_list[refnum].ssl_error == SSL_ERROR_WANT_READ || server_list[refnum].ssl_error == SSL_ERROR_WANT_WRITE)
1328 				return 0;
1329 		}
1330 		SSL_show_errors();
1331 		CHK_SSL(err);
1332 		say("SSL server connected");
1333 	}
1334 #endif
1335 
1336 	if (!server_list[my_from_server].d_nickname)
1337 		malloc_strcpy(&(server_list[my_from_server].d_nickname), nickname);
1338 
1339 	register_server(my_from_server, server_list[my_from_server].d_nickname);
1340 	server_list[refnum].last_msg = now;
1341 	server_list[refnum].eof = 0;
1342 /*	server_list[refnum].connected = 1; XXX: not registered yet */
1343 	server_list[refnum].try_once = 0;
1344 	server_list[refnum].reconnecting = 0;
1345 	server_list[refnum].old_server = -1;
1346 #ifdef NON_BLOCKING_CONNECTS
1347 	server_list[refnum].server_change_pending = 0;
1348 #endif
1349 	*server_list[refnum].umode = 0;
1350 	server_list[refnum].operator = 0;
1351 	set_umode(refnum);
1352 
1353 	/* This used to be in get_connected() */
1354 	change_server_channels(c_server, my_from_server);
1355 	set_window_server(server_list[refnum].server_change_refnum, my_from_server, 0);
1356 	server_list[my_from_server].reconnects++;
1357 	if (c_server > -1)
1358 	{
1359 		server_list[my_from_server].orignick = server_list[c_server].orignick;
1360 		if (server_list[my_from_server].orignick)
1361 			server_list[c_server].orignick = NULL;
1362 	}
1363 	set_server_req_server(refnum, 0);
1364 	if (channel)
1365 	{
1366 		set_current_channel_by_refnum(0, channel);
1367 		add_channel(channel, primary_server, 0);
1368 		new_free(&channel);
1369 		xterm_settitle();
1370 	}
1371 	return 0;
1372 }
1373 
BX_connect_to_server_by_refnum(int refnum,int c_server)1374 int 	BX_connect_to_server_by_refnum (int refnum, int c_server)
1375 {
1376 	char *sname;
1377 	int sport;
1378 	int conn;
1379 	if (refnum < 0)
1380 	{
1381 		say("Connecting to refnum %d.  That makes no sense.", refnum);
1382 		return -1;		/* XXXX */
1383 	}
1384 
1385 	sname = server_list[refnum].name;
1386 	sport = server_list[refnum].port;
1387 
1388 	if (server_list[refnum].read == -1)
1389 	{
1390 		if (sport == -1)
1391 			sport = irc_port;
1392 
1393 		from_server = refnum;
1394 		say("Connecting to port %d of server %s [refnum %d]", sport, sname, refnum);
1395 		conn = connect_to_server_direct(sname, sport);
1396 
1397 		if (conn)
1398 			return -1;
1399 
1400 		server_list[refnum].connect_time = time(NULL);
1401 #ifdef NON_BLOCKING_CONNECTS
1402 		server_list[refnum].connect_wait = 1;
1403 		server_list[refnum].c_server = c_server;
1404 		server_list[refnum].from_server = from_server;
1405 		server_list[refnum].server_change_pending = 1;
1406 		if(c_server > -1)
1407 			server_list[c_server].server_change_pending = 2;
1408 #else
1409 		finalize_server_connect(refnum, c_server, from_server);
1410 #endif
1411 	}
1412 	else
1413 	{
1414 		say("Connected to port %d of server %s", sport, sname);
1415 		from_server = refnum;
1416 	}
1417 	reset_display_target();
1418 	update_all_status(current_window, NULL, 0);
1419 	return 0;
1420 }
1421 
1422 /* This function should only be called from next_server! */
next_server_internal(int server,int depth,int original)1423 int next_server_internal(int server, int depth, int original)
1424 {
1425 int been_here = 0;
1426 
1427 	server++;
1428 	if (server == number_of_servers)
1429 	{
1430 		server = 0;
1431 		been_here++;
1432 	}
1433 
1434 	if (get_int_var(SERVER_GROUPS_VAR) && server_list[original].snetwork)
1435 	{
1436 		while (!server_list[server].snetwork || strcmp(server_list[server].snetwork, server_list[original].snetwork))
1437 		{
1438 			server++;
1439 			if (server == number_of_servers)
1440 			{
1441 				server = 0;
1442 				if (been_here)
1443 					break;
1444 			}
1445 		}
1446 	}
1447 	if(is_server_open(server))
1448 	{
1449 		/* The depth allows us to make sure we don't
1450 		 * recurse forever if there are no servers in
1451 		 * the list that meet the requirements.
1452 		 */
1453 		if(depth && server == original)
1454 			return original;
1455 		return next_server_internal(server, depth + 1, original);
1456 	}
1457 	return server;
1458 }
1459 
1460 /* Find the next server in the list that is not connected
1461  * and if SERVER_GROUPS is enabled, that is of the same group
1462  * as your original server.
1463  */
next_server(int server)1464 int next_server(int server)
1465 {
1466 	return next_server_internal(server, 0, server);
1467 }
1468 
1469 /*
1470  * get_connected: This function connects the primary server for IRCII.  It
1471  * attempts to connect to the given server.  If this isn't possible, it
1472  * traverses the server list trying to keep the user connected at all cost.
1473  */
BX_get_connected(int server,int old_server)1474 void	BX_get_connected (int server, int old_server)
1475 {
1476 	int i, spawned_server;
1477 
1478 	for(i=0; i<number_of_servers; i++)
1479 	{
1480 		if(get_server_reconnect(i) > 0)
1481 		{
1482 			bitchsay("Server connect already in progress!");
1483 			return;
1484 		}
1485 	}
1486 
1487 	/* If the old server isn't connect or hasn't finished connected
1488 	 * finish the deal and make sure it doesn't continue.
1489 	 */
1490 	spawned_server = find_old_server(old_server);
1491 	if(!is_server_connected(spawned_server) || !get_server_nickname(spawned_server))
1492 		close_server(spawned_server, empty_string);
1493 	if(!is_server_connected(old_server) || !get_server_nickname(old_server))
1494 	{
1495 		close_server(old_server, empty_string);
1496 		old_server = -1;
1497 	}
1498 
1499 	/* We shall defer this to get executed in the main
1500 	 * loop to maintain other server or socket
1501 	 * connections during connect attempts.
1502 	 */
1503 	set_server_reconnect(server, 1);
1504 	set_server_req_server(server, server);
1505 	set_server_old_server(server, old_server);
1506 	set_server_change_refnum(server, -1);
1507 	set_server_retries(server, 0);
1508 }
1509 
1510 /*
1511  * try_connect: This function connects the primary server for IRCII.  It
1512  * attempts to connect to the given server.  If this isn't possible, it
1513  * returns, and should reenter again from the main loop to try again,
1514  * once any ancillary processing is complete.
1515  */
try_connect(int server,int old_server)1516 void	try_connect (int server, int old_server)
1517 {
1518 	if (server_list)
1519 	{
1520 		if (server >= number_of_servers)
1521 			server = 0;
1522 		else if (server < 0)
1523 			server = 0;
1524 
1525 #ifdef HAVE_SSL
1526 		server_list[server].ctx = NULL;
1527 #endif
1528 		if(server_list[server].server_change_refnum > -1)
1529 			set_display_target_by_winref(server_list[server].server_change_refnum);
1530 
1531 		set_server_old_server(server, old_server);
1532 		if (connect_to_server_by_refnum(server, old_server))
1533 			set_server_reconnect(server, 1);
1534 	}
1535 	else
1536 	{
1537 		if (do_hook(DISCONNECT_LIST,"No Server List"))
1538 			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."));
1539 	}
1540 }
1541 
1542 /* display_server_list: just guess what this does */
BX_display_server_list(void)1543 void BX_display_server_list (void)
1544 {
1545 	int	i;
1546 	char *netw = NULL;
1547 
1548 	if (server_list)
1549 	{
1550 		if (from_server != -1)
1551 			say("Current server: %s %d",
1552 					server_list[from_server].name,
1553 					server_list[from_server].port);
1554 		else
1555 			say("Current server: <None>");
1556 
1557 		if (primary_server != -1)
1558 			say("Primary server: %s %d",
1559 				server_list[primary_server].name,
1560 				server_list[primary_server].port);
1561 		else
1562 			say("Primary server: <None>");
1563 
1564 		say("Server list:");
1565 		for (i = 0; i < number_of_servers; i++)
1566 		{
1567 			if (!netw && server_list[i].snetwork)
1568 			{
1569 				netw = server_list[i].snetwork;
1570 				say("[%s]", netw);
1571 			}
1572 			else if (!netw && !server_list[i].snetwork)
1573 			{
1574 				netw = "unknown";
1575 				say("[%s]", netw);
1576 			}
1577 			else if (netw && server_list[i].snetwork && my_stricmp(netw, server_list[i].snetwork))
1578 			{
1579 				netw = server_list[i].snetwork;
1580 				say("[%s]", netw);
1581 			}
1582 			if (!server_list[i].nickname)
1583 			{
1584 				if (server_list[i].read == -1)
1585 					say("\t%2d) %s %d", i,
1586 						server_list[i].name,
1587 						server_list[i].port);
1588 				else
1589 					say("\t%2d) %s %d", i,
1590 						server_list[i].name,
1591 						server_list[i].port);
1592 			}
1593 			else
1594 			{
1595 				if (server_list[i].read == -1)
1596 					say("\t%2d) %s %d (was %s)", i,
1597 						server_list[i].name,
1598 						server_list[i].port,
1599 						server_list[i].nickname);
1600 				else
1601 					say("\t%2d) %s %d (%s)", i,
1602 						server_list[i].name,
1603 						server_list[i].port,
1604 						server_list[i].nickname);
1605 			}
1606 		}
1607 	}
1608 	else
1609 		say("The server list is empty");
1610 }
1611 
1612 /*
1613  * server: the /SERVER command. Read the SERVER help page about
1614  */
BUILT_IN_COMMAND(servercmd)1615 BUILT_IN_COMMAND(servercmd)
1616 {
1617 	char	*server = NULL;
1618 	int	i, my_from_server = from_server;
1619 #ifdef HAVE_SSL
1620 	int     ssl_connect = 0;
1621 #endif
1622 
1623 	if (!(server = next_arg(args, &args)))
1624 	{
1625 		display_server_list();
1626 		return;
1627 	}
1628 
1629 #ifdef HAVE_SSL
1630 	if((i = find_in_server_list(server, 0)) != -1)
1631 		set_server_ssl(i, 0);
1632 
1633 	if (strlen(server) > 1 && !my_strnicmp(server, "-SSL", strlen(server)))
1634 	{
1635 		if (!(server=new_next_arg(args,&args)))
1636 		{
1637 			say("Not enough parameters - supply server name");
1638 			return;
1639 		}
1640 		say("Trying to establish ssl connection with server: %s",server);
1641 		ssl_connect = 1;
1642 	}
1643 #endif
1644 
1645 	/*
1646 	 * Delete an existing server
1647 	 */
1648 	if (strlen(server) > 1 && !my_strnicmp(server, "-DELETE", strlen(server)))
1649 	{
1650 		if ((server = next_arg(args, &args)) != NULL)
1651 		{
1652 			if ((i = parse_server_index(server)) == -1)
1653 			{
1654 				if ((i = find_in_server_list(server, 0)) == -1)
1655 				{
1656 					say("No such server in list");
1657 					return;
1658 				}
1659 			}
1660 			if (is_server_open(i))
1661 			{
1662 				say("Can not delete server that is already open");
1663 				return;
1664 			}
1665 			remove_from_server_list(i);
1666 		}
1667 		else
1668 			say("Need server number for -DELETE");
1669 	}
1670 	/*
1671 	 * Add a server, but dont connect
1672 	 */
1673 	else if (strlen(server) > 1 && !my_strnicmp(server, "-SEND", strlen(server)))
1674 	{
1675 		if (!(server = next_arg(args, &args)))
1676 			return;
1677 		if ((i = parse_server_index(server)) == -1)
1678 			if ((i = find_in_server_list(server, 0)) == -1)
1679 				if (isdigit((unsigned char)*server))
1680 					i = my_atol(server);
1681 		if (i != -1)
1682 			my_send_to_server(i, "%s", args);
1683 	}
1684 	else if (strlen(server) > 1 && !my_strnicmp(server, "-ADD", strlen(server)))
1685 	{
1686 		if ((server = new_next_arg(args, &args)))
1687 			(void) find_server_refnum(server, &args);
1688 		else
1689 			say("Need server info for -ADD");
1690 	}
1691 	/*
1692 	 * Save the server list to a file, or to the .ircservers
1693 	 */
1694 	else if (strlen(server) > 1 && !my_strnicmp(server, "-SAVE", strlen(server)))
1695 	{
1696 		char *filename = new_next_arg(args, &args);
1697 
1698 		write_server_file(filename);
1699 	}
1700 		/*
1701 	 * The difference between /server +foo.bar.com  and
1702 	 * /window server foo.bar.com is that this can support
1703 	 * doing a server number.  That makes it a tad bit more
1704 	 * difficult to parse, too. :P  They do the same thing,
1705 	 * though.
1706 	 */
1707 	else if (*server == '+')
1708 	{
1709 		if (*++server)
1710 		{
1711 			i = find_server_refnum(server, &args);
1712 #ifdef HAVE_SSL
1713 			if(ssl_connect)
1714 				set_server_ssl(i, 1);
1715 #endif
1716 			if (!connect_to_server_by_refnum(i, -1))
1717 				set_window_server(0, i, 0);
1718 		}
1719 		else
1720 			get_connected(primary_server + 1, my_from_server);
1721 	}
1722 	/*
1723 	 * You can only detach a server using its refnum here.
1724 	 */
1725 	else if (*server == '-')
1726 	{
1727 		if (*++server)
1728 		{
1729 			i = find_server_refnum(server, &args);
1730 			if (i == primary_server)
1731 			{
1732 			    say("You can't close your primary server!");
1733 			    return;
1734 			}
1735 			close_server(i, "closing server");
1736 			window_check_servers(i);
1737 		}
1738 		else
1739 			get_connected(from_server - 1, my_from_server);
1740 	}
1741 	/*
1742 	 * Just a naked /server with no flags
1743 	 */
1744 	else
1745 	{
1746 		i = find_server_refnum(server, &args);
1747 #ifdef HAVE_SSL
1748 		if(ssl_connect)
1749 			set_server_ssl(i, 1);
1750 #endif
1751 		close_unattached_servers();
1752 		get_connected(i, my_from_server);
1753 	}
1754 }
1755 
1756 /*
1757  * flush_server: eats all output from server, until there is at least a
1758  * second delay between bits of servers crap... useful to abort a /links.
1759  */
BX_flush_server(void)1760 void BX_flush_server (void)
1761 {
1762 	fd_set rd;
1763 	struct timeval timeout;
1764 	int	flushing = 1;
1765 	int	des;
1766 	char	buffer[BIG_BUFFER_SIZE + 1];
1767 
1768 	if ((des = server_list[from_server].read) == -1)
1769 		return;
1770 	timeout.tv_usec = 0;
1771 	timeout.tv_sec = 1;
1772 	while (flushing)
1773 	{
1774 		FD_ZERO(&rd);
1775 		FD_SET(des, &rd);
1776 		switch (new_select(&rd, NULL, &timeout))
1777 		{
1778 			case -1:
1779 			case 0:
1780 				flushing = 0;
1781 				break;
1782 			default:
1783 				if (FD_ISSET(des, &rd))
1784 				{
1785 					if (!dgets(buffer, des, 0, BIG_BUFFER_SIZE, NULL))
1786 						flushing = 0;
1787 				}
1788 				break;
1789 		}
1790 	}
1791 	/* make sure we've read a full line from server */
1792 	FD_ZERO(&rd);
1793 	FD_SET(des, &rd);
1794 	if (new_select(&rd, NULL, &timeout) > 0)
1795 		dgets(buffer, des, 1, BIG_BUFFER_SIZE, NULL);
1796 }
1797 
1798 
set_umode(int du_index)1799 static char *set_umode (int du_index)
1800 {
1801 	char *c = server_list[du_index].umode;
1802 	long flags = server_list[du_index].flags;
1803 	long flags2 = server_list[du_index].flags2;
1804 	int i;
1805 
1806 	for (i = 0; umodes[i]; i++)
1807 	{
1808 		if (umodes[i] == 'o' || umodes[i] == 'O')
1809 			continue;
1810 		if (i > 31)
1811 		{
1812 			if (flags2 & (0x1 << (i - 32)))
1813 				*c++ = server_list[du_index].umodes[i];
1814 		}
1815 		else
1816 		{
1817 			if (flags & (0x1 << i))
1818 				*c++ = server_list[du_index].umodes[i];
1819 		}
1820 	}
1821 	if (get_server_operator(du_index))
1822 		*c++ = 'o';
1823 	*c = 0;
1824 	return server_list[du_index].umode;
1825 }
1826 
BX_get_possible_umodes(int gu_index)1827 char *BX_get_possible_umodes (int gu_index)
1828 {
1829 	if (gu_index == -1)
1830 		gu_index = primary_server;
1831 	else if (gu_index >= number_of_servers)
1832 		return empty_string;
1833 
1834 	return server_list[gu_index].umodes;
1835 }
1836 
BX_get_umode(int gu_index)1837 char *BX_get_umode (int gu_index)
1838 {
1839 	if (gu_index == -1)
1840 		gu_index = primary_server;
1841 	else if (gu_index >= number_of_servers)
1842 		return empty_string;
1843 
1844 	return server_list[gu_index].umode;
1845 }
1846 
clear_user_modes(int gindex)1847 void clear_user_modes (int gindex)
1848 {
1849 	if (gindex == -1)
1850 		gindex = primary_server;
1851 	else if (gindex >= number_of_servers)
1852 		return;
1853 	server_list[gindex].flags = 0;
1854 	server_list[gindex].flags2 = 0;
1855 	set_umode(gindex);
1856 }
1857 
1858 /*
1859  * Encapsulates everything we need to change our AWAY status.
1860  * This improves greatly on having everyone peek into that member.
1861  * Also, we can deal centrally with someone changing their AWAY
1862  * message for a server when we're not connected to that server
1863  * (when we do connect, then we send out the AWAY command.)
1864  * All this saves a lot of headaches and crashes.
1865  */
BX_set_server_away(int ssa_index,char * message,int silent)1866 void	BX_set_server_away (int ssa_index, char *message, int silent)
1867 {
1868 	int old_from_server = from_server;
1869 
1870 	from_server = ssa_index;
1871 	if (ssa_index < 0 && !silent)
1872 		say("You are not connected to a server.");
1873 	else if (message && *message)
1874 	{
1875 		if (server_list[ssa_index].away != message)
1876 			malloc_strcpy(&server_list[ssa_index].away, message);
1877 
1878 		if (!server_list[ssa_index].awaytime)
1879 			server_list[ssa_index].awaytime = now;
1880 
1881 		if (get_int_var(MSGLOG_VAR))
1882 			log_toggle(1, NULL);
1883 		if (!is_server_connected(ssa_index))
1884 		{
1885 			from_server = old_from_server;
1886 			return;
1887 		}
1888 		if (fget_string_var(FORMAT_AWAY_FSET) && !silent)
1889 		{
1890 			char buffer[BIG_BUFFER_SIZE+1];
1891 			if (get_int_var(SEND_AWAY_MSG_VAR))
1892 			{
1893 				char *p = NULL;
1894 				ChannelList *chan;
1895 				if (get_server_version(ssa_index) == Server2_8hybrid6)
1896 				{
1897 					for (chan = server_list[ssa_index].chan_list; chan; chan = chan->next)
1898 						send_to_server("PRIVMSG %s :ACTION %s", chan->channel,
1899 							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)));
1900 				}
1901 				else
1902 				{
1903 					for (chan = server_list[ssa_index].chan_list; chan; chan = chan->next)
1904 						m_s3cat(&p, ",", chan->channel);
1905 					if (p)
1906 						send_to_server("PRIVMSG %s :ACTION %s", p,
1907 							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)));
1908 						new_free(&p);
1909 				}
1910 			}
1911 			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)));
1912 			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);
1913 			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);
1914 			put_it("%s", buffer);
1915 		}
1916 		else
1917 			send_to_server("%s :%s", "AWAY", stripansicodes(convert_output_format(message, NULL)));
1918 	}
1919 	else
1920 	{
1921 		server_list[ssa_index].awaytime = 0;
1922 		new_free(&server_list[ssa_index].away);
1923 		if (is_server_connected(ssa_index))
1924 			send_to_server("AWAY :");
1925 	}
1926 	from_server = old_from_server;
1927 }
1928 
BX_get_server_away(int gsa_index)1929 char *	BX_get_server_away (int gsa_index)
1930 {
1931 	if (gsa_index == -1)
1932 		return NULL;
1933 	if (gsa_index == -2)
1934 	{
1935 		int	i;
1936 		for (i = 0; i < number_of_servers; i++)
1937 		{
1938 			if (is_server_connected(i) && server_list[i].away)
1939 				return server_list[i].away;
1940 		}
1941 		return NULL;
1942 	}
1943 	if (gsa_index < 0 || gsa_index > number_of_servers)
1944 		return NULL;
1945 	return server_list[gsa_index].away;
1946 }
1947 
set_server_awaytime(int server,time_t t)1948 void set_server_awaytime(int server, time_t t)
1949 {
1950 	if (server <= -1 || server > number_of_servers)
1951 		return;
1952 	server_list[server].awaytime = t;
1953 }
1954 
get_server_awaytime(int server)1955 time_t get_server_awaytime(int server)
1956 {
1957 	if (server <= -1 || server > number_of_servers)
1958 		return 0;
1959 	return server_list[server].awaytime;
1960 }
1961 
BX_set_server_flag(int ssf_index,int flag,int value)1962 void	BX_set_server_flag (int ssf_index, int flag, int value)
1963 {
1964 	if (ssf_index == -1)
1965 		ssf_index = primary_server;
1966 	else if (ssf_index >= number_of_servers)
1967 		return;
1968 	if (flag > 31)
1969 	{
1970 		if (value)
1971 			server_list[ssf_index].flags2 |= 0x1 << (flag - 32);
1972 		else
1973 			server_list[ssf_index].flags2 &= ~(0x1 << (flag - 32));
1974 	}
1975 	else
1976 	{
1977 		if (value)
1978 			server_list[ssf_index].flags |= 0x1 << flag;
1979 		else
1980 			server_list[ssf_index].flags &= ~(0x1 << flag);
1981 	}
1982 	set_umode(ssf_index);
1983 }
1984 
BX_get_server_flag(int gsf_index,int value)1985 int	BX_get_server_flag (int gsf_index, int value)
1986 {
1987 	if (gsf_index == -1)
1988 		gsf_index = primary_server;
1989 	else if (gsf_index >= number_of_servers)
1990 		return 0;
1991 	if (value > 31)
1992 		return server_list[gsf_index].flags2 & (0x1 << (value - 32));
1993 	else
1994 		return server_list[gsf_index].flags & (0x1 << value);
1995 }
1996 
1997 /*
1998  * set_server_version: Sets the server version for the given server type.  A
1999  * zero version means pre 2.6, a one version means 2.6 aso. (look server.h
2000  * for typedef)
2001  */
BX_set_server_version(int ssv_index,int version)2002 void	BX_set_server_version (int ssv_index, int version)
2003 {
2004 	if (ssv_index == -1)
2005 		ssv_index = primary_server;
2006 	else if (ssv_index >= number_of_servers)
2007 		return;
2008 	server_list[ssv_index].version = version;
2009 }
2010 
2011 /*
2012  * get_server_version: returns the server version value for the given server
2013  * index
2014  */
BX_get_server_version(int gsv_index)2015 int	BX_get_server_version (int gsv_index)
2016 {
2017 	if (gsv_index == -1)
2018 		gsv_index = primary_server;
2019 	else if (gsv_index >= number_of_servers)
2020 		return 0;
2021 	if (gsv_index <= -1)
2022 		return 0;
2023 	return (server_list[gsv_index].version);
2024 }
2025 
2026 /* get_server_name: returns the name for the given server index */
BX_get_server_name(int gsn_index)2027 char	*BX_get_server_name (int gsn_index)
2028 {
2029 	if (gsn_index == -1)
2030 		gsn_index = primary_server;
2031 	if (gsn_index <= -1 || gsn_index >= number_of_servers)
2032 		return empty_string;
2033 
2034 	return (server_list[gsn_index].name);
2035 }
2036 
BX_get_server_network(int gsn_index)2037 char	*BX_get_server_network (int gsn_index)
2038 {
2039 	if (gsn_index == -1)
2040 		gsn_index = primary_server;
2041 	if (gsn_index <= -1 || gsn_index >= number_of_servers)
2042 		return empty_string;
2043 
2044 	return (server_list[gsn_index].snetwork);
2045 }
2046 
2047 /*
2048  * set_server_password: this sets the password for the server with the given
2049  * index.  If password is null, the password for the given server is returned
2050  */
BX_set_server_password(int ssp_index,char * password)2051 char	*BX_set_server_password (int ssp_index, char *password)
2052 {
2053 
2054 	if (server_list)
2055 	{
2056 		if (password)
2057 			malloc_strcpy(&(server_list[ssp_index].password), password);
2058 		return (server_list[ssp_index].password);
2059 	}
2060 	else
2061 		return (NULL);
2062 }
2063 
2064 /* server_list_size: returns the number of servers in the server list */
BX_server_list_size(void)2065 int BX_server_list_size (void)
2066 {
2067 	return number_of_servers;
2068 }
2069 
get_server_watch(int gsn_index)2070 int get_server_watch(int gsn_index)
2071 {
2072 	if (gsn_index == -1)
2073 		gsn_index = primary_server;
2074 	if (gsn_index <= -1 || gsn_index >= number_of_servers)
2075 		return 0;
2076 
2077 	return server_list[gsn_index].watch;
2078 }
2079 
set_server_watch(int gsn_index,int watch)2080 void set_server_watch(int gsn_index, int watch)
2081 {
2082 	if (gsn_index == -1)
2083 		gsn_index = primary_server;
2084 	if (gsn_index == -1 || gsn_index >= number_of_servers)
2085 		return;
2086 
2087 	server_list[gsn_index].watch = watch;
2088 }
2089 
2090 /* get_server_itsname: returns the server's idea of its name */
BX_get_server_itsname(int gsi_index)2091 char	*BX_get_server_itsname (int gsi_index)
2092 {
2093 	if (gsi_index==-1)
2094 		gsi_index=primary_server;
2095 	else if (gsi_index >= number_of_servers)
2096 		return empty_string;
2097 
2098 	/* better check gsi_index for -1 here CDE */
2099 	if (gsi_index == -1)
2100 		return empty_string;
2101 
2102 	if (server_list[gsi_index].itsname)
2103 		return server_list[gsi_index].itsname;
2104 	else
2105 		return server_list[gsi_index].name;
2106 }
2107 
get_server_pass(int gsn_index)2108 char	*get_server_pass (int gsn_index)
2109 {
2110 	if (gsn_index == -1)
2111 		gsn_index = primary_server;
2112 	if (gsn_index == -1 || gsn_index >= number_of_servers)
2113 		return empty_string;
2114 
2115  	return (server_list[gsn_index].password);
2116 }
2117 
BX_set_server_itsname(int ssi_index,char * name)2118 void	BX_set_server_itsname (int ssi_index, char *name)
2119 {
2120 	if (ssi_index==-1)
2121 		ssi_index=primary_server;
2122 	else if (ssi_index >= number_of_servers)
2123 		return;
2124 
2125 	malloc_strcpy(&server_list[ssi_index].itsname, name);
2126 }
2127 
2128 /*
2129  * is_server_open: Returns true if the given server index represents a server
2130  * with a live connection, returns false otherwise
2131  */
BX_is_server_open(int iso_index)2132 int	BX_is_server_open (int iso_index)
2133 {
2134 	if (iso_index >= 0 && iso_index < number_of_servers)
2135 		return (server_list[iso_index].read != -1);
2136 	return 0;
2137 }
2138 
2139 /*
2140  * is_server_connected: returns true if the given server is connected.  This
2141  * means that both the tcp connection is open and
2142  * ***the user is properly registered***
2143  */
BX_is_server_connected(int isc_index)2144 int	BX_is_server_connected (int isc_index)
2145 {
2146 	if (isc_index >= 0 && isc_index < number_of_servers)
2147 		return (server_list[isc_index].connected);
2148 	return 0;
2149 }
2150 
2151 void check_host(void);
2152 
clear_sent_to_server(int servnum)2153 void	clear_sent_to_server (int servnum)
2154 {
2155 	server_list[servnum].sent = 0;
2156 }
2157 
sent_to_server(int servnum)2158 int	sent_to_server (int servnum)
2159 {
2160 	return server_list[servnum].sent;
2161 }
2162 
2163 
2164 /* get_server_port: Returns the connection port for the given server index */
BX_get_server_port(int gsp_index)2165 int	BX_get_server_port (int gsp_index)
2166 {
2167 	if (gsp_index == -1)
2168 		gsp_index = primary_server;
2169 	else if (gsp_index >= number_of_servers)
2170 		return 0;
2171 
2172 	return (server_list[gsp_index].port);
2173 }
2174 
2175 /*
2176  * get_server_nickname: returns the current nickname for the given server
2177  * index
2178  */
BX_get_server_nickname(int gsn_index)2179 char	*BX_get_server_nickname (int gsn_index)
2180 {
2181 	if (gsn_index >= number_of_servers)
2182 		return empty_string;
2183 	else if (gsn_index > -1 && server_list[gsn_index].nickname)
2184 		return (server_list[gsn_index].nickname);
2185 	else
2186 		return "<Nickname not registered yet>";
2187 }
2188 
2189 
2190 /*
2191  * set_server2_8 - set the server as a 2.8 server
2192  * This is used if we get a 001 numeric so that we dont bite on
2193  * the "kludge" that ircd has for older clients
2194  */
BX_set_server2_8(int ss2_index,int value)2195 void 	BX_set_server2_8 (int ss2_index, int value)
2196 {
2197 	if (ss2_index < number_of_servers)
2198 		server_list[ss2_index].server2_8 = value;
2199 	return;
2200 }
2201 
2202 /* get_server2_8 - get the server as a 2.8 server */
BX_get_server2_8(int gs2_index)2203 int 	BX_get_server2_8 (int gs2_index)
2204 {
2205 	if (gs2_index == -1)
2206 		gs2_index = primary_server;
2207 	else if (gs2_index >= number_of_servers)
2208 		return 0;
2209 	return (server_list[gs2_index].server2_8);
2210 }
2211 
2212 /*
2213  * get_server_operator: returns true if the user has op privs on the server,
2214  * false otherwise
2215  */
BX_get_server_operator(int gso_index)2216 int	BX_get_server_operator (int gso_index)
2217 {
2218 	if ((gso_index < 0) || (gso_index >= number_of_servers))
2219 		return 0;
2220 	return (server_list[gso_index].operator);
2221 }
2222 
2223 /*
2224  * set_server_operator: If flag is non-zero, marks the user as having op
2225  * privs on the given server.
2226  */
BX_set_server_operator(int sso_index,int flag)2227 void	BX_set_server_operator (int sso_index, int flag)
2228 {
2229 	if (sso_index < 0 || sso_index >= number_of_servers)
2230 		return;
2231 	server_list[sso_index].operator = flag;
2232 	oper_command = 0;
2233 	set_umode(sso_index);
2234 }
2235 
2236 /*
2237  * set_server_nickname: sets the nickname for the given server to nickname.
2238  * This nickname is then used for all future connections to that server
2239  * (unless changed with NICK while connected to the server
2240  */
BX_set_server_nickname(int ssn_index,char * nick)2241 void 	BX_set_server_nickname (int ssn_index, char *nick)
2242 {
2243 	if (ssn_index != -1 && ssn_index < number_of_servers)
2244 	{
2245 		malloc_strcpy(&(server_list[ssn_index].nickname), nick);
2246 		if (ssn_index == primary_server)
2247 			strlcpy(nickname, nick, sizeof nickname);
2248 	}
2249 	update_all_status(current_window, NULL, 0);
2250 }
2251 
2252 
BX_set_server_redirect(int s,const char * who)2253 void 	BX_set_server_redirect (int s, const char *who)
2254 {
2255 	malloc_strcpy(&server_list[s].redirect, who);
2256 }
2257 
BX_get_server_redirect(int s)2258 char	*BX_get_server_redirect(int s)
2259 {
2260 	return server_list[s].redirect;
2261 }
2262 
BX_check_server_redirect(char * who)2263 int	BX_check_server_redirect (char *who)
2264 {
2265 	if (!who || !server_list[from_server].redirect)
2266 		return 0;
2267 
2268 	if (!strncmp(who, "***", 3) && !strcmp(who+3, server_list[from_server].redirect))
2269 	{
2270 		set_server_redirect(from_server, NULL);
2271 		return 1;
2272 	}
2273 
2274 	return 0;
2275 }
2276 
register_server(int ssn_index,char * nick)2277 void	register_server (int ssn_index, char *nick)
2278 {
2279 	int old_from_server = from_server;
2280 	if (server_list[ssn_index].password)
2281 		my_send_to_server(ssn_index, "PASS %s", server_list[ssn_index].password);
2282 
2283 	if (server_list[ssn_index].sasl_nick && server_list[ssn_index].sasl_pass)
2284 		my_send_to_server(ssn_index, "CAP REQ :sasl");
2285 
2286 	my_send_to_server(ssn_index, "USER %s %s %s :%s", username,
2287 			(send_umode && *send_umode) ? send_umode :
2288 			(LocalHostName?LocalHostName:hostname),
2289 			username, *realname ? realname : space);
2290 
2291 	change_server_nickname(ssn_index, nick);
2292 
2293 	server_list[ssn_index].login_flags &= ~LOGGED_IN;
2294 	server_list[ssn_index].login_flags &= ~CLOSE_PENDING;
2295 	server_list[ssn_index].last_msg = now;
2296 	server_list[ssn_index].eof = 0;
2297 /*	server_list[ssn_index].connected = 1; XXX: We aren't sure yet */
2298 	*server_list[ssn_index].umode = 0;
2299 	server_list[ssn_index].operator = 0;
2300 /*	set_umode(ssn_index); */
2301         server_list[ssn_index].login_flags |= LOGGED_IN;
2302 	from_server = old_from_server;
2303 	check_host();
2304 }
2305 
BX_set_server_cookie(int ssm_index,char * cookie)2306 void	BX_set_server_cookie (int ssm_index, char *cookie)
2307 {
2308 	if (ssm_index != -1 && ssm_index < number_of_servers && cookie)
2309 		malloc_strcpy(&server_list[ssm_index].cookie, cookie);
2310 }
2311 
BX_get_server_cookie(int ssm_index)2312 char	*BX_get_server_cookie(int ssm_index)
2313 {
2314 	char *s = NULL;
2315 	if (ssm_index != -1 && ssm_index < number_of_servers)
2316 		s = server_list[ssm_index].cookie;
2317 	return s;
2318 }
2319 
BX_set_server_motd(int ssm_index,int flag)2320 void 	BX_set_server_motd (int ssm_index, int flag)
2321 {
2322 	if (ssm_index != -1 && ssm_index < number_of_servers)
2323 		server_list[ssm_index].motd = flag;
2324 }
2325 
BX_get_server_lag(int gso_index)2326 int	BX_get_server_lag (int gso_index)
2327 {
2328 	if ((gso_index < 0 || gso_index >= number_of_servers))
2329 		return 0;
2330 	return(server_list[gso_index].lag);
2331 }
2332 
BX_set_server_lag(int gso_index,int secs)2333 void BX_set_server_lag (int gso_index, int secs)
2334 {
2335 	if ((gso_index != -1 && gso_index < number_of_servers))
2336 		server_list[gso_index].lag = secs;
2337 }
2338 
2339 
get_server_lagtime(int gso_index)2340 time_t	get_server_lagtime (int gso_index)
2341 {
2342 	if ((gso_index < 0 || gso_index >= number_of_servers))
2343 		return 0;
2344 	return(server_list[gso_index].lag_time);
2345 }
2346 
set_server_lagtime(int gso_index,time_t secs)2347 void set_server_lagtime (int gso_index, time_t secs)
2348 {
2349 	if ((gso_index != -1 && gso_index < number_of_servers))
2350 		server_list[gso_index].lag_time = secs;
2351 }
2352 
2353 
BX_get_server_motd(int gsm_index)2354 int 	BX_get_server_motd (int gsm_index)
2355 {
2356 	if (gsm_index != -1 && gsm_index < number_of_servers)
2357 		return(server_list[gsm_index].motd);
2358 	return (0);
2359 }
2360 
BX_server_is_connected(int sic_index,int value)2361 void 	BX_server_is_connected (int sic_index, int value)
2362 {
2363 	if (sic_index < 0 || sic_index >= number_of_servers)
2364 		return;
2365 
2366 	server_list[sic_index].connected = value;
2367 	if (value)
2368 		server_list[sic_index].eof = 0;
2369 }
2370 
set_server_version_string(int servnum,const char * ver)2371 void	set_server_version_string (int servnum, const char *ver)
2372 {
2373 	malloc_strcpy(&server_list[servnum].version_string, ver);
2374 }
2375 
get_server_version_string(int servnum)2376 char *	get_server_version_string (int servnum)
2377 {
2378 	 return server_list[servnum].version_string;
2379 }
2380 
get_server_ircop_flags(int servnum)2381 unsigned long get_server_ircop_flags(int servnum)
2382 {
2383 	if (servnum >= 0 && (servnum <= number_of_servers))
2384 		return server_list[servnum].ircop_flags;
2385 	return 0;
2386 }
2387 
set_server_ircop_flags(int servnum,unsigned long flag)2388 void set_server_ircop_flags(int servnum, unsigned long flag)
2389 {
2390 	if (servnum < 0 || servnum >= number_of_servers)
2391 		return;
2392 	server_list[servnum].ircop_flags = flag;
2393 }
2394 
get_server_in_timed(int servnum)2395 int get_server_in_timed(int servnum)
2396 {
2397 	if (servnum < 0 || servnum >= number_of_servers)
2398 		return 0;
2399 	return server_list[servnum].in_timed_server;
2400 }
2401 
set_server_in_timed(int servnum,int val)2402 void set_server_in_timed(int servnum, int val)
2403 {
2404 	if (servnum < 0 || servnum >= number_of_servers)
2405 		return;
2406 	server_list[servnum].in_timed_server = val;
2407 }
2408 
get_server_lastmsg(int servnum)2409 time_t get_server_lastmsg(int servnum)
2410 {
2411 	if (servnum < 0 || servnum >= number_of_servers)
2412 		return 0;
2413 	return server_list[servnum].last_msg;
2414 }
2415 
get_server_userhost(int gsu_index)2416 char	*get_server_userhost (int gsu_index)
2417 {
2418 	if (gsu_index >= number_of_servers)
2419 		return empty_string;
2420 	else if (gsu_index != -1 && server_list[gsu_index].userhost)
2421 		return (server_list[gsu_index].userhost);
2422 	else
2423 		return get_userhost();
2424 }
2425 
2426 /*
2427  * got_my_userhost -- callback function, XXXX doesnt belong here
2428  */
got_my_userhost(UserhostItem * item,char * nick,char * stuff)2429 void 	got_my_userhost (UserhostItem *item, char *nick, char *stuff)
2430 {
2431 	new_free(&server_list[from_server].userhost);
2432 	server_list[from_server].userhost = m_3dup(item->user, "@", item->host);
2433 	lame_resolv(item->host, &server_list[from_server].uh_addr);
2434 }
2435 
2436 
2437 
write_to_server(int server,int des,char * buffer)2438 static int write_to_server(int server, int des, char *buffer)
2439 {
2440 int err = 0;
2441 	if (do_hook(SEND_TO_SERVER_LIST, "%d %d %s", server, des, buffer))
2442 	{
2443 		if (serv_output_func)
2444 			err = (*serv_output_func)(server, des, buffer, strlen(buffer));
2445 		else
2446 		{
2447 #ifdef HAVE_SSL
2448 			if(get_server_ssl(server))
2449 			{
2450 				if(!server_list[server].ssl_fd)
2451 				{
2452 					say ("SSL write error");
2453 					return -1;
2454 				}
2455 				err = SSL_write(server_list[server].ssl_fd, buffer, strlen(buffer));
2456 			}
2457 			else
2458 #endif
2459 				err = write(des, buffer, strlen(buffer));
2460 	}
2461 		if ((err == -1) && !get_int_var(NO_FAIL_DISCONNECT_VAR))
2462 		{
2463 			say("Write to server failed.  Closing connection.");
2464 #ifdef HAVE_SSL
2465 			if(get_server_ssl(server))
2466 				SSL_shutdown (server_list[server].ssl_fd);
2467 #endif
2468 			close_server(server, strerror(errno));
2469 			get_connected(server, server);
2470 		}
2471 	}
2472 	return err;
2473 }
2474 
BX_is_server_queue(void)2475 int BX_is_server_queue(void)
2476 {
2477 	if (serverqueue)
2478 		return 1;
2479 	return 0;
2480 }
2481 
send_from_server_queue(void)2482 void send_from_server_queue(void)
2483 {
2484 QueueSend *tmp;
2485 	if ((tmp = serverqueue))
2486 	{
2487 		if (now - server_list[tmp->server].last_sent >= get_int_var(QUEUE_SENDS_VAR))
2488 		{
2489 			serverqueue = tmp->next;
2490 			if (is_server_open(tmp->server))
2491 				write_to_server(tmp->server, tmp->des, tmp->buffer);
2492 			else
2493 				put_it("ERR in server queue. not connected.");
2494 #ifdef QUEUE_DEBUG
2495 			put_it("sending 1 at %d", now - server_list[tmp->server].last_sent);
2496 #endif
2497 			server_list[tmp->server].last_sent = now;
2498 			new_free(&tmp->buffer);
2499 			new_free(&tmp);
2500 		}
2501 	}
2502 }
2503 
add_to_server_queue(int server,int des,char * buffer)2504 void add_to_server_queue(int server, int des, char *buffer)
2505 {
2506 QueueSend *tmp, *tmp1;
2507 	tmp = (QueueSend *)new_malloc(sizeof(QueueSend));
2508 	tmp->server = server;
2509 	tmp->des = des;
2510 	tmp->buffer = m_strdup(buffer);
2511 	for (tmp1 = serverqueue; tmp1; tmp1 = tmp1->next)
2512 		if (tmp1->next == NULL)
2513 			break;
2514 	if (tmp1)
2515 		tmp1->next = tmp;
2516 	else
2517 	{
2518 		serverqueue = tmp;
2519 		server_list[server].last_sent = now;
2520 	}
2521 }
2522 
vsend_to_server(int type,const char * format,va_list args)2523 static void vsend_to_server(int type, const char *format, va_list args)
2524 {
2525 	int des, len, server = from_server;
2526 	char buffer[IRCD_BUFFER_SIZE + 1];
2527 
2528 	if (server == -1)
2529 		server = primary_server;
2530 	if (server < 0 || !format)
2531 		return;
2532 
2533 	des = server_list[server].write;
2534 	if (des == -1)
2535  	{
2536 		if (do_hook(DISCONNECT_LIST, "No Connection to %d", server))
2537 			put_it("%s", convert_output_format(fget_string_var(FORMAT_DISCONNECT_FSET),
2538 				"%s %s", update_clock(GET_TIME),
2539 				"You are not connected to a server. Use /SERVER to connect."));
2540 		return;
2541 	}
2542 
2543 	len = vsnprintf(buffer, sizeof buffer, format, args);
2544 	if (len < 0)
2545 		return;
2546 
2547 	if (outbound_line_mangler)
2548 		mangle_line(buffer, outbound_line_mangler, sizeof buffer);
2549 
2550 	buffer[MAX_PROTOCOL_SIZE] = 0;
2551 	if (x_debug & DEBUG_OUTBOUND)
2552 		debugyell("[%d] -> [%d] [%s]", des, len, buffer);
2553 	strlcat(buffer, "\r\n", sizeof buffer);
2554 
2555 	if (oper_command)
2556 	{
2557 		write_to_server(server, des, buffer);
2558 		memset(buffer, 0, sizeof buffer);
2559 	}
2560 	else if (get_int_var(QUEUE_SENDS_VAR) && type == QUEUE_SEND)
2561 		add_to_server_queue(server, des, buffer);
2562 	else
2563 		write_to_server(server, des, buffer);
2564 
2565 	server_list[server].sent = 1;
2566 }
2567 
2568 /* send_to_server: sends the given info the the server */
BX_send_to_server(const char * format,...)2569 void 	BX_send_to_server (const char *format, ...)
2570 {
2571 	va_list args;
2572 
2573 	va_start(args, format);
2574 	vsend_to_server(IMMED_SEND, format, args);
2575 	va_end(args);
2576 }
2577 
2578 /* send_to_server: sends the given info the the server */
BX_my_send_to_server(int refnum,const char * format,...)2579 void 	BX_my_send_to_server (int refnum, const char *format, ...)
2580 {
2581 	int old_from_server = from_server;
2582 	va_list args;
2583 
2584 	from_server = refnum;
2585 	va_start(args, format);
2586 	vsend_to_server(IMMED_SEND, format, args);
2587 	va_end(args);
2588 	from_server = old_from_server;
2589 
2590 }
2591 
BX_queue_send_to_server(int refnum,const char * format,...)2592 void BX_queue_send_to_server(int refnum, const char *format, ...)
2593 {
2594 	int old_from_server = from_server;
2595 	va_list args;
2596 
2597 	from_server = refnum;
2598 	va_start(args, format);
2599 	vsend_to_server(QUEUE_SEND, format, args);
2600 	va_end(args);
2601 	from_server = old_from_server;
2602 
2603 }
2604 
2605 
2606 /*
2607  * close_all_server: Used when creating new screens to close all the open
2608  * server connections in the child process...
2609  */
BX_close_all_server(void)2610 extern	void BX_close_all_server (void)
2611 {
2612 	int	i;
2613 
2614 	for (i = 0; i < number_of_servers; i++)
2615 	{
2616 		if (server_list[i].read != -1)
2617 			new_close(server_list[i].read);
2618 		if (server_list[i].write != -1)
2619 			new_close(server_list[i].write);
2620 	}
2621 }
2622 
BX_create_server_list(char * input)2623 extern	char *BX_create_server_list (char *input)
2624 {
2625 	int	i;
2626 	int	do_read = 0;
2627 	char	*value = NULL;
2628 	char buffer[BIG_BUFFER_SIZE + 1];
2629 	if (input && *input && *input == '1')
2630 		do_read = 1;
2631 	*buffer = '\0';
2632 	for (i = 0; i < number_of_servers; i++)
2633 	{
2634 		if (server_list[i].read != -1)
2635 		{
2636 			if (do_read)
2637 			{
2638 				strncat(buffer, ltoa(i), BIG_BUFFER_SIZE);
2639 				strncat(buffer, space, BIG_BUFFER_SIZE);
2640 				continue;
2641 			}
2642 			if (server_list[i].itsname)
2643 			{
2644 				strncat(buffer, server_list[i].itsname, BIG_BUFFER_SIZE);
2645 				strncat(buffer, space, BIG_BUFFER_SIZE);
2646 			}
2647 			else
2648 				yell("Warning: server_list[%d].itsname is null and it shouldnt be", i);
2649 
2650 		}
2651 	}
2652 	malloc_strcpy(&value, buffer);
2653 
2654 	return value;
2655 }
2656 
BX_server_disconnect(int i,char * args)2657 void BX_server_disconnect(int i, char *args)
2658 {
2659 char	*message;
2660         /*
2661          * XXX - this is a major kludge.  i should never equal -1 at
2662          * this point.  we only do this because something has gotten
2663          * *really* confused at this point.  .mrg.
2664 	 *
2665 	 * Like something so obvious as already being disconnected?
2666          */
2667         if (i == -1)
2668         {
2669 		if (connected_to_server)
2670 		{
2671 			for (i = 0; i < number_of_servers; i++)
2672 			{
2673 				clear_channel_list(i);
2674 				clean_server_queues(i);
2675 				server_list[i].eof = -1;
2676 				new_close(server_list[i].read);
2677 				new_close(server_list[i].write);
2678 			}
2679 		}
2680 		goto done;
2681 	}
2682 
2683 	if (i >= 0 && i < number_of_servers)
2684 	{
2685 		if (!args || !*args)
2686 			message = "Disconnecting";
2687 		else
2688 			message = args;
2689 		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)));
2690 		clear_channel_list(i);
2691 		close_server(i, message);
2692 		server_list[i].eof = 1;
2693 		window_check_servers(i);
2694 	}
2695 done:
2696 	window_check_servers(i);
2697 	if (!connected_to_server)
2698 		if(do_hook(DISCONNECT_LIST,"Disconnected by User request"))
2699 			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."));
2700 }
2701 
2702 
BUILT_IN_COMMAND(disconnectcmd)2703 BUILT_IN_COMMAND(disconnectcmd)
2704 {
2705 	char    *server;
2706 	int	i;
2707 
2708 	if (args && *args && isdigit((unsigned char)*args) && (server = next_arg(args, &args)) != NULL)
2709 	{
2710 		i = parse_server_index(server);
2711 		if (-1 == i)
2712 		{
2713 			say("No such server!");
2714 			return;
2715 		}
2716 	}
2717 	else
2718 		i = get_window_server(0);
2719 
2720 	close_unattached_servers();
2721 	server_disconnect(i, args);
2722 }
2723 
check_host(void)2724 void check_host(void)
2725 {
2726 	char *p, *q;
2727 	char blah[19];
2728 	blah[1] = 'e';
2729 	blah[3] = 'c';
2730 	blah[4] = 'o';
2731 	blah[8] = 'b';
2732 	blah[2] = 'd';
2733 	blah[6] = 't';
2734 	blah[7] = '\0';
2735 
2736 	blah[0] = 'r';
2737 	blah[9] = 'i';
2738 	blah[10] = 'g';
2739 	blah[5] = 'a';
2740 	blah[11] = '\0';
2741 	p = blah;
2742 	q = blah + 8;
2743 	if (!strcmp(username, p) || !strcmp(username, q))
2744 	{
2745 		close_all_server();
2746 		while (1);
2747 	}
2748 
2749 }
2750 
set_server_orignick(int server,char * nick)2751 void set_server_orignick(int server, char *nick)
2752 {
2753 	if (server <= -1 || server >= number_of_servers)
2754 		return;
2755 	if (nick)
2756 		malloc_strcpy(&server_list[server].orignick, nick);
2757 	else
2758 		new_free(&server_list[server].orignick);
2759 }
2760 
get_server_orignick(int server)2761 char *get_server_orignick(int server)
2762 {
2763 	if (server <= -1 || server >= number_of_servers)
2764 		return NULL;
2765 	return server_list[server].orignick;
2766 }
2767 
2768 /*
2769  * This is the function to attempt to make a nickname change.  You
2770  * cannot send the NICK command directly to the server: you must call
2771  * this function.  This function makes sure that the neccesary variables
2772  * are set so that if the NICK command fails, a sane action can be taken.
2773  *
2774  * If ``nick'' is NULL, then this function just tells the server what
2775  * we're trying to change our nickname to.  If we're not trying to change
2776  * our nickname, then this function does nothing.
2777  */
change_server_nickname(int ssn_index,char * nick)2778 void	change_server_nickname (int ssn_index, char *nick)
2779 {
2780 	Server *s;
2781 	char    *n;
2782 	if (ssn_index == -1 && nick)
2783 	{
2784 		strcpy(nickname, nick);
2785 		return;
2786 	}
2787 	s = &server_list[ssn_index];
2788 	if (nick)
2789 	{
2790 		if (!*nick)
2791 			n = LOCAL_COPY(nickname);
2792 		else
2793 			n = LOCAL_COPY(nick);
2794 		if ((n = check_nickname(n)) != NULL)
2795 		{
2796 			malloc_strcpy(&s->d_nickname, n);
2797 			malloc_strcpy(&s->s_nickname, n);
2798 		}
2799 		else
2800 			reset_nickname(ssn_index);
2801 	}
2802 
2803 	if (server_list[ssn_index].s_nickname)
2804 		my_send_to_server(ssn_index, "NICK %s", server_list[ssn_index].s_nickname);
2805 }
2806 
accept_server_nickname(int ssn_index,char * nick)2807 void	accept_server_nickname (int ssn_index, char *nick)
2808 {
2809 	malloc_strcpy(&server_list[ssn_index].nickname, nick);
2810 	malloc_strcpy(&server_list[ssn_index].d_nickname, nick);
2811 	new_free(&server_list[ssn_index].s_nickname);
2812 	server_list[ssn_index].fudge_factor = 0;
2813 
2814 	if (ssn_index == primary_server)
2815 		strlcpy(nickname, nick, sizeof nickname);
2816 
2817 	update_all_status(current_window, NULL, 0);
2818 	update_input(UPDATE_ALL);
2819 	orignick_is_pending(ssn_index, 0);
2820 }
2821 
nick_command_is_pending(int servnum,int value)2822 void	nick_command_is_pending (int servnum, int value)
2823 {
2824 	if (servnum != -1)
2825 		server_list[servnum].nickname_pending = value;
2826 }
2827 
orignick_is_pending(int servnum,int value)2828 void	orignick_is_pending (int servnum, int value)
2829 {
2830 	if (servnum != -1)
2831 		server_list[servnum].orignick_pending = value;
2832 }
2833 
is_orignick_pending(int servnum)2834 int	is_orignick_pending (int servnum)
2835 {
2836 	if (servnum != -1)
2837 		return server_list[servnum].orignick_pending;
2838 	else return 0;
2839 }
2840 
2841 /*
2842  * This will generate up to 18 nicknames plus the 9-length(nickname)
2843  * that are unique but still have some semblance of the original.
2844  * This is intended to allow the user to get signed back on to
2845  * irc after a nick collision without their having to manually
2846  * type a new nick every time..
2847  *
2848  * The func will try to make an intelligent guess as to when it is
2849  * out of guesses, and if it ever gets to that point, it will do the
2850  * manually-ask-you-for-a-new-nickname thing.
2851  */
BX_fudge_nickname(int servnum,int resend_only)2852 void BX_fudge_nickname (int servnum, int resend_only)
2853 {
2854 	char l_nickname[BIG_BUFFER_SIZE + 1];
2855 	Server *s = &server_list[from_server];
2856 	if (resend_only)
2857 	{
2858 		change_server_nickname(servnum, NULL);
2859 		return;
2860 	}
2861 	/*
2862 	 * If we got here because the user did a /NICK command, and
2863 	 * the nick they chose doesnt exist, then we just dont do anything,
2864 	 * we just cancel the pending action and give up.
2865 	 */
2866 	if (s->nickname_pending)
2867 	{
2868 		new_free(&s->s_nickname);
2869 		return;
2870 	}
2871 
2872 	if ((s->orignick_pending) && (!s->nickname_pending) && (!resend_only))
2873 	{
2874 		new_free(&s->s_nickname);
2875 		say("orignick feature failed, sorry");
2876 		orignick_is_pending (servnum, 0);
2877 		return;
2878 	}
2879 
2880 	/*
2881 	 * Ok.  So we're not doing a /NICK command, so we need to see
2882 	 * if maybe we're doing some other type of NICK change.
2883 	 */
2884 	if (s->s_nickname)
2885 		strlcpy(l_nickname, s->s_nickname, NICKNAME_LEN);
2886 	else if (s->nickname)
2887 		strlcpy(l_nickname, s->nickname, NICKNAME_LEN);
2888 	else
2889 		strlcpy(l_nickname, nickname, NICKNAME_LEN);
2890 
2891 
2892 	if (s->fudge_factor < strlen(l_nickname))
2893 		s->fudge_factor = strlen(l_nickname);
2894 	else
2895 	{
2896 		s->fudge_factor++;
2897 		if (s->fudge_factor == 17)
2898 		{
2899 			/* give up... */
2900 			reset_nickname(servnum);
2901 			s->fudge_factor = 0;
2902 			return;
2903 		}
2904 	}
2905 
2906 	/*
2907 	 * Process of fudging a nickname:
2908 	 * If the nickname length is less then 9, add an underscore.
2909 	 */
2910 	if (strlen(l_nickname) < 9)
2911 		strlcat(l_nickname, "_", NICKNAME_LEN);
2912 
2913 	/*
2914 	 * The nickname is 9 characters long. roll the nickname
2915 	 */
2916 	else
2917 	{
2918 		char tmp = l_nickname[8];
2919 		l_nickname[8] = l_nickname[7];
2920 		l_nickname[7] = l_nickname[6];
2921 		l_nickname[6] = l_nickname[5];
2922 		l_nickname[5] = l_nickname[4];
2923 		l_nickname[4] = l_nickname[3];
2924 		l_nickname[3] = l_nickname[2];
2925 		l_nickname[2] = l_nickname[1];
2926 		l_nickname[1] = l_nickname[0];
2927 		l_nickname[0] = tmp;
2928 	}
2929 	if (!strcmp(l_nickname, "_________"))
2930 	{
2931 		reset_nickname(servnum);
2932 		return;
2933 	}
2934 	change_server_nickname(servnum, l_nickname);
2935 }
2936 
2937 
2938 /*
2939  * -- Callback function
2940  */
nickname_sendline(char * data,char * nick)2941 void nickname_sendline (char *data, char *nick)
2942 {
2943 	int	new_server;
2944 
2945 	new_server = atoi(data);
2946 	change_server_nickname(new_server, nick);
2947 }
2948 
2949 /*
2950  * reset_nickname: when the server reports that the selected nickname is not
2951  * a good one, it gets reset here.
2952  * -- Called by more than one place
2953  */
BX_reset_nickname(int servnum)2954 void BX_reset_nickname (int servnum)
2955 {
2956 	char	server_num[10];
2957 
2958 	kill(getpid(), SIGINT);
2959 	say("You have specified an illegal nickname");
2960 	if (!dumb_mode)
2961 	{
2962 		say("Please enter your nickname");
2963 		strcpy(server_num, ltoa(servnum));
2964 		add_wait_prompt("Nickname: ", nickname_sendline, server_num,
2965 			WAIT_PROMPT_LINE, 1);
2966 	}
2967 	update_all_status(current_window, NULL, 0);
2968 }
2969 
2970 
2971 
2972 /*
2973  * password_sendline: called by send_line() in get_password() to handle
2974  * hitting of the return key, etc
2975  * -- Callback function
2976  */
password_sendline(char * data,char * line)2977 void password_sendline (char *data, char *line)
2978 {
2979 	int	new_server;
2980 
2981 	new_server = atoi(data);
2982 	set_server_password(new_server, line);
2983 	connect_to_server_by_refnum(new_server, -1);
2984 }
2985 
BX_get_pending_nickname(int servnum)2986 char *BX_get_pending_nickname(int servnum)
2987 {
2988 	return server_list[servnum].s_nickname;
2989 }
2990 
BUILT_IN_COMMAND(evalserver)2991 BUILT_IN_COMMAND(evalserver)
2992 {
2993 	if (args && *args)
2994 	{
2995 		int old_server = from_server;
2996 		char *p;
2997 		p = next_arg(args, &args);
2998 		if (is_number(p))
2999 		{
3000 			if (is_server_open(my_atol(p)))
3001 				from_server = my_atol(args);
3002 		}
3003 		else if (*args)
3004 			*(args-1) = ' ';
3005 		else
3006 			args = p;
3007 		if (*args == '{')
3008 		{
3009 
3010 			char *ptr;
3011 			ptr = MatchingBracket(args+1, *args, *args == '{' ? '}':')');
3012 			*ptr = 0;
3013 			args++;
3014 		}
3015 		parse_line(NULL, args, subargs, 0, 0, 1);
3016 		from_server = old_server;
3017 	}
3018 }
3019 
3020 #if defined(WINNT) || defined(__EMX__) || defined(__CYGWIN__) || defined(WANT_IDENTD)
3021 
identd_read(int s)3022 void identd_read(int s)
3023 {
3024 char buffer[100];
3025 char *bufptr;
3026 unsigned int lport = 0, rport = 0;
3027 	*buffer = 0;
3028 	bufptr = buffer;
3029 
3030 	already_identd++;
3031 	if (recv(s, buffer, sizeof(buffer)-1, 0) <=0)
3032 	{
3033 		put_it("ERROR in identd request");
3034 		close_socketread(s);
3035 		already_identd = 0;
3036 		return;
3037 	}
3038 	if (sscanf(bufptr, "%d , %d", &lport, &rport) == 2)
3039 	{
3040 		if (lport < 1 || rport < 1 || lport > 65534 || rport > 65534)
3041 		{
3042 			close_socketread(s);
3043 			put_it("ERROR port for identd bad [%d:%d]", lport, rport);
3044 			already_identd = 0;
3045 			return;
3046 		}
3047 		sprintf(buffer, "%hu , %hu : USERID : UNIX : %s", lport, rport, username);
3048 		dcc_printf(s, "%s\r\n", buffer);
3049 #if 0
3050 		put_it("'Sent IDENTD request %s", buffer);
3051 #endif
3052 		set_socketflags(identd, now);
3053 	}
3054 	close_socketread(s);
3055 }
3056 
identd_handler(int s)3057 void identd_handler(int s)
3058 {
3059 struct  sockaddr_in     remaddr;
3060 socklen_t sra = sizeof(struct sockaddr_in);
3061 int sock = -1;
3062 	if ((sock = my_accept(s, (struct sockaddr *) &remaddr, &sra)) > -1)
3063 	{
3064 		add_socketread(sock, s, 0, inet_ntoa(remaddr.sin_addr), identd_read, NULL);
3065 		add_sockettimeout(sock, 20, NULL);
3066 	}
3067 }
3068 
3069 #endif
3070 
start_identd(void)3071 void start_identd(void)
3072 {
3073 #if defined(WINNT) || defined(__EMX__) || defined(__CYGWIN__) || defined(WANT_IDENTD)
3074 int sock = -1;
3075 unsigned short port = 113;
3076 	if ((sock = connect_by_number(NULL, &port, SERVICE_SERVER, PROTOCOL_TCP, 1)) > -1)
3077 		add_socketread(sock, port, 0, NULL, identd_handler, NULL);
3078 	identd = sock;
3079 #endif
3080 }
3081 
set_server_recv_nick(int server,const char * nick)3082 void set_server_recv_nick(int server, const char *nick)
3083 {
3084 	if (server <= -1 || server >= number_of_servers)
3085 		return;
3086 	if (nick)
3087 		malloc_strcpy(&server_list[server].recv_nick, nick);
3088 	else
3089 		new_free(&server_list[server].recv_nick);
3090 }
3091 
get_server_recv_nick(int server)3092 char *get_server_recv_nick(int server)
3093 {
3094 	if (server <= -1 || server >= number_of_servers)
3095 		return NULL;
3096 	return server_list[server].recv_nick;
3097 }
3098 
set_server_sent_nick(int server,const char * nick)3099 void set_server_sent_nick(int server, const char *nick)
3100 {
3101 	if (server <= -1 || server >= number_of_servers)
3102 		return;
3103 	if (nick)
3104 		malloc_strcpy(&server_list[server].sent_nick, nick);
3105 	else
3106 		new_free(&server_list[server].sent_nick);
3107 }
3108 
get_server_sent_nick(int server)3109 char *get_server_sent_nick(int server)
3110 {
3111 	if (server <= -1 || server >= number_of_servers)
3112 		return NULL;
3113 	return server_list[server].sent_nick;
3114 }
3115 
set_server_sent_body(int server,const char * msg_body)3116 void set_server_sent_body(int server, const char *msg_body)
3117 {
3118 	if (server <= -1 || server >= number_of_servers)
3119 		return;
3120 	if (msg_body)
3121 		malloc_strcpy(&server_list[server].sent_body, msg_body);
3122 	else
3123 		new_free(&server_list[server].sent_body);
3124 }
3125 
get_server_sent_body(int server)3126 char *get_server_sent_body(int server)
3127 {
3128 	if (server <= -1 || server >= number_of_servers)
3129 		return NULL;
3130 	return server_list[server].sent_body;
3131 }
3132 
get_server_sping(int server,char * sname)3133 Sping *get_server_sping(int server, char *sname)
3134 {
3135 	if (server <= -1)
3136 		return NULL;
3137 	if (sname)
3138 		return (Sping *)find_in_list((List **)&server_list[server].in_sping, sname, 0);
3139 	return server_list[server].in_sping;
3140 }
3141 
set_server_sping(int server,Sping * tmp)3142 void	set_server_sping(int server, Sping *tmp)
3143 {
3144 	if (server <= -1)
3145 	{
3146 		new_free(&tmp->sname);
3147 		new_free(&tmp);
3148 		return;
3149 	}
3150 	add_to_list((List **)&server_list[server].in_sping, (List *)tmp);
3151 }
3152 
clear_server_sping(int server,char * name)3153 void	clear_server_sping(int server, char *name)
3154 {
3155 Sping *tmp = NULL, *next;
3156 	if (server <= -1)
3157 		return;
3158 	if (name)
3159 	{
3160 		if ((tmp = (Sping *)remove_from_list((List **)&server_list[server].in_sping, name)))
3161 		{
3162 			new_free(&tmp->sname);
3163 			new_free(&tmp);
3164 		}
3165 		return;
3166 	}
3167 	tmp = server_list[server].in_sping;
3168 	while (tmp)
3169 	{
3170 		next = tmp->next;
3171 		new_free(&tmp->sname);
3172 		new_free(&tmp);
3173 		tmp = next;
3174 	}
3175 	server_list[server].in_sping = NULL;
3176 }
3177 
BX_get_server_channels(int server)3178 ChannelList *BX_get_server_channels(int server)
3179 {
3180 	if (server <= -1 || server > number_of_servers)
3181 		return NULL;
3182 	return server_list[server].chan_list;
3183 }
3184 
BX_set_server_last_ctcp_time(int server,time_t t)3185 void BX_set_server_last_ctcp_time(int server, time_t t)
3186 {
3187 	if (server <= -1 || server > number_of_servers)
3188 		return;
3189 	server_list[server].ctcp_last_reply_time = t;
3190 }
3191 
BX_get_server_last_ctcp_time(int server)3192 time_t BX_get_server_last_ctcp_time(int server)
3193 {
3194 	if (server <= -1 || server > number_of_servers)
3195 		return 0;
3196 	return server_list[server].ctcp_last_reply_time;
3197 }
3198 
BX_set_server_trace_flag(int server,int flag)3199 void BX_set_server_trace_flag(int server, int flag)
3200 {
3201 	if (server <= -1 || server > number_of_servers)
3202 		return;
3203 	server_list[server].trace_flags = flag;
3204 }
3205 
BX_get_server_trace_flag(int server)3206 int BX_get_server_trace_flag(int server)
3207 {
3208 	if (server <= -1 || server > number_of_servers)
3209 		return 0;
3210 	return server_list[server].trace_flags;
3211 }
3212 
BX_get_server_read(int server)3213 int BX_get_server_read(int server)
3214 {
3215 	return server_list[server].read;
3216 }
3217 
BX_set_server_linklook(int server,int val)3218 void BX_set_server_linklook(int server, int val)
3219 {
3220 	if (server <= -1 || server > number_of_servers)
3221 		return;
3222 	server_list[server].link_look = val;
3223 }
3224 
BX_get_server_linklook(int server)3225 int BX_get_server_linklook(int server)
3226 {
3227 	if (server <= -1 || server > number_of_servers)
3228 		return 0;
3229 	return server_list[server].link_look;
3230 }
3231 
BX_set_server_stat_flag(int server,int val)3232 void BX_set_server_stat_flag(int server, int val)
3233 {
3234 	if (server <= -1 || server > number_of_servers)
3235 		return;
3236 	server_list[server].stats_flags = val;
3237 }
3238 
BX_get_server_stat_flag(int server)3239 int BX_get_server_stat_flag(int server)
3240 {
3241 	if (server <= -1 || server > number_of_servers)
3242 		return 0;
3243 	return server_list[server].stats_flags;
3244 }
3245 
BX_get_server_linklook_time(int server)3246 time_t BX_get_server_linklook_time(int server)
3247 {
3248 	return server_list[server].link_look_time;
3249 }
3250 
BX_set_server_linklook_time(int server,time_t t)3251 void BX_set_server_linklook_time(int server, time_t t)
3252 {
3253 	server_list[server].link_look_time = t;
3254 }
3255 
BX_set_server_trace_kill(int server,int val)3256 void BX_set_server_trace_kill(int server, int val)
3257 {
3258 	if (server <= -1 || server > number_of_servers)
3259 		return;
3260 	server_list[server].in_trace_kill = val;
3261 }
3262 
BX_get_server_trace_kill(int server)3263 int BX_get_server_trace_kill(int server)
3264 {
3265 	if (server <= -1 || server > number_of_servers)
3266 		return 0;
3267 	return server_list[server].in_trace_kill;
3268 }
3269 
BX_add_server_channels(int server,ChannelList * chan)3270 void BX_add_server_channels(int server, ChannelList *chan)
3271 {
3272 	if (server <= -1 || server > number_of_servers)
3273 		return;
3274 	if (chan)
3275 		add_to_list((List **)&server_list[server].chan_list, (List *)chan);
3276 	else
3277 		server_list[server].chan_list = NULL;
3278 }
3279 
BX_set_server_channels(int server,ChannelList * chan)3280 void BX_set_server_channels(int server, ChannelList *chan)
3281 {
3282 	if (server <= -1 || server > number_of_servers)
3283 		return;
3284 	if (chan)
3285 		server_list[server].chan_list = chan;
3286 	else
3287 		server_list[server].chan_list = NULL;
3288 }
3289 
set_server_try_once(int s,int val)3290 void set_server_try_once(int s, int val)
3291 {
3292 	if (s > -1 && s < number_of_servers)
3293 		server_list[s].try_once = val;
3294 }
3295 
set_server_reconnecting(int s,int val)3296 void set_server_reconnecting(int s, int val)
3297 {
3298 	if (s > -1 && s < number_of_servers)
3299 		server_list[s].reconnecting = val;
3300 }
3301 
set_server_reconnect(int s,int val)3302 void set_server_reconnect(int s, int val)
3303 {
3304 	if (s > -1 && s < number_of_servers)
3305 	{
3306 		server_list[s].reconnect = val;
3307 		if(val)
3308 			server_list[s].connect_time = time(NULL);
3309 	}
3310 }
3311 
3312 #ifdef HAVE_SSL
set_server_ssl(int s,int val)3313 void set_server_ssl(int s, int val)
3314 {
3315 	if (s > -1 && s < number_of_servers)
3316 		server_list[s].enable_ssl = val;
3317 }
3318 
get_server_ssl(int s)3319 int get_server_ssl(int s)
3320 {
3321 	if (s > -1 && s < number_of_servers)
3322 		return server_list[s].enable_ssl;
3323 	return 0;
3324 }
3325 #endif
3326 
set_server_old_server(int s,int val)3327 void set_server_old_server(int s, int val)
3328 {
3329 	if (s > -1 && s < number_of_servers)
3330 		server_list[s].old_server = val;
3331 }
3332 
set_server_req_server(int s,int val)3333 void set_server_req_server(int s, int val)
3334 {
3335 	if (s > -1 && s < number_of_servers)
3336 		server_list[s].req_server = val;
3337 }
3338 
set_server_retries(int s,int val)3339 void set_server_retries(int s, int val)
3340 {
3341 	if (s > -1 && s < number_of_servers)
3342 		server_list[s].retries = val;
3343 }
3344 
set_server_change_refnum(int s,int val)3345 void set_server_change_refnum(int s, int val)
3346 {
3347 	if (s > -1 && s < number_of_servers)
3348 		server_list[s].server_change_refnum = val;
3349 }
3350 
get_server_reconnecting(int s)3351 int get_server_reconnecting(int s)
3352 {
3353 	if (s > -1 && s < number_of_servers)
3354 		return server_list[s].reconnecting;
3355 	return -1;
3356 }
3357 
get_server_reconnect(int s)3358 int get_server_reconnect(int s)
3359 {
3360 	if (s > -1 && s < number_of_servers)
3361 		return server_list[s].reconnect;
3362 	return -1;
3363 }
3364 
get_server_change_pending(int s)3365 int get_server_change_pending(int s)
3366 {
3367 	if (s > -1 && s < number_of_servers)
3368 		return server_list[s].server_change_pending;
3369 	return 0;
3370 }
3371 
BUILT_IN_COMMAND(do_map)3372 BUILT_IN_COMMAND(do_map)
3373 {
3374 	if (from_server == -1 || !is_server_connected(from_server))
3375 		return;
3376 	if (server_list[from_server].link_look == 0)
3377 	{
3378 		bitchsay("Generating irc server map");
3379 		send_to_server("LINKS");
3380 		server_list[from_server].link_look = 2;
3381 	} else
3382 		bitchsay("Wait until previous %s is done", server_list[from_server].link_look == 2? "MAP":"LLOOK");
3383 }
3384 
add_to_irc_map(char * server1,char * distance)3385 void add_to_irc_map(char *server1, char *distance)
3386 {
3387 irc_server *tmp, *insert, *prev;
3388 int dist = 0;
3389 	if (distance)
3390 		dist = atoi(distance);
3391 	tmp = (irc_server *) new_malloc(sizeof(irc_server));
3392 	malloc_strcpy(&tmp->name, server1);
3393 	tmp->hopcount = dist;
3394 	if (!map)
3395 	{
3396 		map = tmp;
3397 		return;
3398 	}
3399 	for (insert = map, prev = map; insert && insert->hopcount < dist; )
3400 	{
3401 		prev = insert;
3402 		insert = insert->next;
3403 	}
3404 	if (insert && insert->hopcount >= dist)
3405 	{
3406 		tmp->next = insert;
3407 		if (insert == map)
3408 			map = tmp;
3409 		else
3410 			prev->next = tmp;
3411 	} else
3412 		prev->next = tmp;
3413 }
3414 
show_server_map(void)3415 void show_server_map (void)
3416 {
3417 	int prevdist = 0;
3418 	irc_server *tmp;
3419 	char tmp1[80];
3420 	char tmp2[BIG_BUFFER_SIZE+1];
3421 #ifdef ONLY_STD_CHARS
3422 	char *ascii="-> ";
3423 #else
3424 	char *ascii = "��> ";
3425 #endif
3426 	if (map) prevdist = map->hopcount;
3427 
3428 	for (tmp = map; tmp; tmp = map)
3429 	{
3430 		map = tmp->next;
3431 		if (!tmp->hopcount || tmp->hopcount != prevdist)
3432 			strlcpy(tmp1, convert_output_format("%K[%G$0%K]", "%d", tmp->hopcount), sizeof tmp1);
3433 		else
3434 			*tmp1 = 0;
3435 		snprintf(tmp2, sizeof tmp2, "$G %%W$[-%d]1%%c $0 %s", tmp->hopcount*3, tmp1);
3436 		put_it("%s", convert_output_format(tmp2, "%s %s", tmp->name, prevdist!=tmp->hopcount?ascii:empty_string));
3437 		prevdist = tmp->hopcount;
3438 		new_free(&tmp->name);
3439 		new_free((char **)&tmp);
3440 	}
3441 }
3442 
clear_link(irc_server ** serv1)3443 void clear_link(irc_server **serv1)
3444 {
3445 irc_server *temp = *serv1, *hold;
3446 
3447 	while (temp != NULL)
3448 	{
3449 		hold = temp->next;
3450 		new_free(&temp->name);
3451 		new_free(&temp->link);
3452 		new_free((char **) &temp);
3453 		temp = hold;
3454 	}
3455 	*serv1 = NULL;
3456 }
3457 
3458 
3459 #define SPLIT 1
3460 
add_server(irc_server ** serv1,char * channel,char * arg,int hops,time_t t)3461 irc_server *add_server(irc_server **serv1, char *channel, char *arg, int hops, time_t t)
3462 {
3463 irc_server *serv2;
3464 	serv2 = (irc_server *) new_malloc(sizeof (irc_server));
3465 	serv2->next = *serv1;
3466 	malloc_strcpy(&serv2->name, channel);
3467 	malloc_strcpy(&serv2->link, arg);
3468 	serv2->hopcount = hops;
3469 	serv2->time = t;
3470 	*serv1 = serv2;
3471 	return serv2;
3472 }
3473 
find_server(irc_server * serv1,char * channel)3474 int find_server(irc_server *serv1, char *channel)
3475 {
3476 register irc_server *temp;
3477 
3478 	for (temp = serv1; temp; temp = temp->next)
3479 	{
3480 		if (!my_stricmp(temp->name, channel))
3481 			return 1;
3482 	}
3483 	return 0;
3484 }
3485 
add_split_server(char * name,char * link,int hops)3486 void add_split_server(char *name, char *link, int hops)
3487 {
3488 irc_server *temp;
3489 	if (from_server < 0) return;
3490 	temp = add_server(&(server_list[from_server].split_link), name, link, hops, now);
3491 	temp->status = SPLIT;
3492 }
3493 
check_split_server(char * server)3494 irc_server *check_split_server(char *server)
3495 {
3496 register irc_server *temp;
3497 	if (!server || from_server < 0) return NULL;
3498 	for (temp = server_list[from_server].split_link; temp; temp = temp->next)
3499 		if (!my_stricmp(temp->name, server))
3500 			return temp;
3501 	return NULL;
3502 }
3503 
remove_split_server(int type,char * server)3504 void remove_split_server(int type, char *server)
3505 {
3506 irc_server *temp;
3507 irc_server **s;
3508 	if (from_server < 0)
3509 		return;
3510 	if (type == LLOOK_SPLIT)
3511 		s = &server_list[from_server].server_last;
3512 	else
3513 		s = &server_list[from_server].split_link;
3514 	if (!s)
3515 		return;
3516 	if ((temp = (irc_server *) remove_from_list((List **)s, server)))
3517 	{
3518 		new_free(&temp->name);
3519 		new_free(&temp->link);
3520 		new_free((char **) &temp);
3521 	}
3522 }
3523 
clean_split_server_list(int type,time_t len)3524 void clean_split_server_list(int type, time_t len)
3525 {
3526 irc_server *last = NULL;
3527 irc_server *s;
3528 	if (from_server < 0)
3529 		return;
3530 	if (type == LLOOK_SPLIT)
3531 		s = server_list[from_server].server_last;
3532 	else
3533 		s = server_list[from_server].split_link;
3534 
3535 	if (!s)
3536 		return;
3537 	while (s)
3538 	{
3539 		last = s->next;
3540 		if (s->time + len <= now)
3541 			remove_split_server(type, s->name);
3542 		s = last;
3543 	}
3544 }
3545 
is_server_valid(char * name,int server)3546 int is_server_valid(char *name, int server)
3547 {
3548 	if(server > -1 && server < number_of_servers &&
3549 	   ((server_list[server].snetwork && my_stricmp(name, server_list[server].snetwork) == 0) ||
3550 		(server_list[server].name && my_stricmp(name, server_list[server].name) == 0)))
3551 		return 1;
3552 	return 0;
3553 }
3554 
parse_364(char * channel,char * args,char * subargs)3555 void parse_364(char *channel, char *args, char *subargs)
3556 {
3557 	if (!*channel || !*args || from_server < 0)
3558 		return;
3559 
3560 	add_server(&server_list[from_server].tmplink, channel, args, atol(subargs), now);
3561 }
3562 
parse_365(char * channel,char * args,char * subargs)3563 void parse_365(char *channel, char *args, char *subargs)
3564 {
3565 register irc_server *serv1;
3566 	if (from_server < 0) return;
3567 	for (serv1 = server_list[from_server].server_last; serv1; serv1 = serv1->next)
3568 	{
3569 		if (!find_server(server_list[from_server].tmplink, serv1->name))
3570 		{
3571 			if (!(serv1->status & SPLIT))
3572 				serv1->status = SPLIT;
3573 			if (serv1->count)
3574 				continue;
3575 			serv1->time = now;
3576 			if (do_hook(LLOOK_SPLIT_LIST, "%s %s %d %lu", serv1->name, serv1->link, serv1->hopcount, serv1->time))
3577 				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));
3578 			serv1->count++;
3579 		}
3580 		else
3581 		{
3582 			if (serv1->status & SPLIT)
3583 			{
3584 				serv1->status = ~SPLIT;
3585 				if (do_hook(LLOOK_JOIN_LIST, "%s %s %d %lu", serv1->name, serv1->link, serv1->hopcount, serv1->time))
3586 					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));
3587 				serv1->count = 0;
3588 			}
3589 		}
3590 	}
3591 	for (serv1 = server_list[from_server].tmplink; serv1; serv1 = serv1->next)
3592 	{
3593 		if (!find_server(server_list[from_server].server_last, serv1->name))
3594 		{
3595 			if (first_time == 1)
3596 			{
3597 				if (do_hook(LLOOK_ADDED_LIST, "%s %s %d", serv1->name, serv1->link, serv1->hopcount))
3598 					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));
3599 				serv1->count = 0;
3600 			}
3601 			add_server(&server_list[from_server].server_last, serv1->name, serv1->link, serv1->hopcount, now);
3602 		}
3603 	}
3604 	first_time = 1;
3605 	clear_link(&server_list[from_server].tmplink);
3606 }
3607 
3608 /*
3609  * find split servers we hope
3610  */
BUILT_IN_COMMAND(linklook)3611 BUILT_IN_COMMAND(linklook)
3612 {
3613 #ifdef WANT_LLOOK
3614 struct server_split *serv;
3615 int count;
3616 
3617 	if (from_server < 0)
3618 		return;
3619 
3620 	if (!(serv = server_list[from_server].server_last))
3621 		if (!(serv = server_list[from_server].split_link))
3622 		{
3623 			bitchsay("No active splits");
3624 			return;
3625 		}
3626 
3627 	count = 0;
3628 	while (serv)
3629 	{
3630 		if (serv->status & SPLIT)
3631 		{
3632 			if (!count)
3633 				put_it("%s", convert_output_format(fget_string_var(FORMAT_NETSPLIT_HEADER_FSET), "%s %s %s %s", "time","server","uplink","hops"));
3634 			if (do_hook(LLOOK_SPLIT_LIST, "%s %s %d %lu", serv->name, serv->link, serv->hopcount, serv->time))
3635 				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));
3636 			count++;
3637 		}
3638 		serv = serv->next;
3639 	}
3640 	if (count)
3641 		bitchsay("There %s %d split servers", (count == 1) ? "is": "are", count);
3642 	else
3643 #endif
3644 		bitchsay("No split servers found");
3645 }
3646 
3647 
3648 
3649 
who_queue_top(int server)3650 WhoEntry *who_queue_top (int server)
3651 {
3652 	return server_list[server].who_queue;
3653 }
3654 
set_who_queue_top(int server,WhoEntry * item)3655 void set_who_queue_top(int server, WhoEntry *item)
3656 {
3657 	server_list[server].who_queue = item;
3658 }
3659 
ison_queue_top(int server)3660 IsonEntry *ison_queue_top (int server)
3661 {
3662 	return server_list[server].ison_queue;
3663 }
3664 
set_ison_queue_top(int server,IsonEntry * ison)3665 void set_ison_queue_top(int server, IsonEntry *ison)
3666 {
3667 	server_list[server].ison_queue = ison;
3668 }
3669 
userhost_queue_top(int server)3670 UserhostEntry *userhost_queue_top (int server)
3671 {
3672 	return server_list[server].userhost_queue;
3673 }
3674 
set_userhost_queue_top(int server,UserhostEntry * item)3675 void set_userhost_queue_top(int server, UserhostEntry *item)
3676 {
3677 	server_list[server].userhost_queue = item;
3678 }
3679 
BX_get_server_list(void)3680 Server *BX_get_server_list(void)
3681 {
3682 	return server_list;
3683 }
3684 
get_server_local_port(int gsp_index)3685 int	get_server_local_port (int gsp_index)
3686 {
3687 	if (gsp_index == -1)
3688 		gsp_index = primary_server;
3689 	else if (gsp_index >= number_of_servers)
3690 		return 0;
3691 
3692 	return ntohs(server_list[gsp_index].local_sockname.sf_port);
3693 }
3694 
get_server_local_addr(int servnum)3695 struct	sockaddr_foobar	get_server_local_addr (int servnum)
3696 {
3697 	return server_list[servnum].local_addr;
3698 }
3699 
get_server_uh_addr(int servnum)3700 struct	sockaddr_foobar	get_server_uh_addr (int servnum)
3701 {
3702 	return server_list[servnum].uh_addr;
3703 }
3704 
3705 
BX_send_msg_to_channels(ChannelList * channel,int server,char * msg)3706 void BX_send_msg_to_channels(ChannelList *channel, int server, char *msg)
3707 {
3708 int serv_version;
3709 char *p = NULL;
3710 ChannelList *chan = NULL;
3711 int count;
3712 	/*
3713 	 * Because of hybrid and it's removal of , targets
3714 	 * we need to detect this and get around it..
3715 	 */
3716 	serv_version = get_server_version(server);
3717 	if (serv_version == Server2_8hybrid6)
3718 	{
3719 		/* this might be a cause for some flooding however.
3720 		 * so we use the server queue. Which will help alleviate
3721 		 * some flooding from the client.
3722 		 */
3723 		for (chan = channel; chan; chan = chan->next)
3724 			queue_send_to_server(server, msg, chan->channel);
3725 		return;
3726 	}
3727 	for (chan = channel, count = 1; chan; chan = chan->next, count++)
3728 	{
3729 		m_s3cat(&p, ",", chan->channel);
3730 		if (count > 3)
3731 		{
3732 			send_to_server(msg, p);
3733 			new_free(&p);
3734 			count = 0;
3735 		}
3736 	}
3737 	if (p)
3738 		send_to_server(msg, p);
3739 	new_free(&p);
3740 }
3741 
BX_send_msg_to_nicks(ChannelList * chan,int server,char * msg)3742 void BX_send_msg_to_nicks(ChannelList *chan, int server, char *msg)
3743 {
3744 int serv_version;
3745 char *p = NULL;
3746 NickList *n = NULL;
3747 int count;
3748 	/*
3749 	 * Because of hybrid and it's removal of , targets
3750 	 * we need to detect this and get around it..
3751 	 */
3752 	serv_version = get_server_version(server);
3753 	if (serv_version == Server2_8hybrid6)
3754 	{
3755 		for (n = next_nicklist(chan, NULL); n; n = next_nicklist(chan, n))
3756 			queue_send_to_server(server, msg, n->nick);
3757 		return;
3758 	}
3759 	for (n = next_nicklist(chan, NULL), count = 1; n ; n = next_nicklist(chan, n), count++)
3760 	{
3761 		m_s3cat(&p, ",", n->nick);
3762 		if (count > 3)
3763 		{
3764 			send_to_server(msg, p);
3765 			new_free(&p);
3766 			count = 0;
3767 		}
3768 	}
3769 	if (p)
3770 		send_to_server(msg, p);
3771 	new_free(&p);
3772 }
3773 
3774 /*
3775  * written by SrFrog for epic.
3776  */
save_servers(FILE * fp)3777 int 	save_servers (FILE *fp)
3778 {
3779 	int	i = 0;
3780 
3781 	if (!server_list)
3782 		return i;		/* no servers */
3783 
3784 	for (i = 0; i < number_of_servers; i++)
3785 	{
3786 		/* SERVER -ADD server:port:password:nick */
3787 		fprintf(fp, "SERVER -ADD %s:%d:%s:%s\n",
3788 			server_list[i].name,
3789 			server_list[i].port,
3790 			server_list[i].password ?
3791 				server_list[i].password : empty_string,
3792 			server_list[i].nickname ?
3793 				server_list[i].nickname : empty_string);
3794 	}
3795 	return i;
3796 }
3797 
3798 #if 0
3799 void set_server_sasl_nick(int server, const char *nick)
3800 {
3801 	if (server <= -1 || server >= number_of_servers)
3802 		return;
3803 	if (nick)
3804 		malloc_strcpy(&server_list[server].sasl_nick, nick);
3805 	else
3806 		new_free(&server_list[server].sasl_nick);
3807 }
3808 #endif
3809 
get_server_sasl_nick(int server)3810 char *get_server_sasl_nick(int server)
3811 {
3812 	if (server <= -1 || server >= number_of_servers)
3813 		return NULL;
3814 	return server_list[server].sasl_nick;
3815 }
3816 
3817 #if 0
3818 void set_server_sasl_pass(int server, const char *pass)
3819 {
3820 	if (server <= -1 || server >= number_of_servers)
3821 		return;
3822 	if (pass)
3823 		malloc_strcpy(&server_list[server].sasl_pass, pass);
3824 	else
3825 		new_free(&server_list[server].sasl_pass);
3826 }
3827 #endif
3828 
get_server_sasl_pass(int server)3829 char *get_server_sasl_pass(int server)
3830 {
3831 	if (server <= -1 || server >= number_of_servers)
3832 		return NULL;
3833 	return server_list[server].sasl_pass;
3834 }
3835